blob: 277d16fa3b3b5711d938a48adcf7189673682a6f [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
487
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000488TEST(ImportType, ImportAtomicType) {
489 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000490 testImport("void declToImport() { typedef _Atomic(int) a_int; }",
491 Lang_CXX11, "", Lang_CXX11, Verifier,
492 functionDecl(
493 hasBody(
494 compoundStmt(
495 has(
496 declStmt(
497 has(
498 typedefDecl(
499 has(atomicType())))))))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000500}
501
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000502TEST(ImportDecl, ImportFunctionTemplateDecl) {
503 MatchVerifier<Decl> Verifier;
504 testImport("template <typename T> void declToImport() { };", Lang_CXX, "",
505 Lang_CXX, Verifier, functionTemplateDecl());
506}
507
508const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
509 cxxDependentScopeMemberExpr;
510
511TEST(ImportExpr, ImportCXXDependentScopeMemberExpr) {
512 MatchVerifier<Decl> Verifier;
513 testImport("template <typename T> struct C { T t; };"
514 "template <typename T> void declToImport() {"
515 " C<T> d;"
516 " d.t;"
517 "}"
518 "void instantiate() { declToImport<int>(); }",
519 Lang_CXX, "", Lang_CXX, Verifier,
520 functionTemplateDecl(has(functionDecl(
521 has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
522 testImport("template <typename T> struct C { T t; };"
523 "template <typename T> void declToImport() {"
524 " C<T> d;"
525 " (&d)->t;"
526 "}"
527 "void instantiate() { declToImport<int>(); }",
528 Lang_CXX, "", Lang_CXX, Verifier,
529 functionTemplateDecl(has(functionDecl(
530 has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
531}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000532
Gabor Horvath7a91c082017-11-14 11:30:38 +0000533TEST(ImportType, ImportTypeAliasTemplate) {
534 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000535 testImport("template <int K>"
536 "struct dummy { static const int i = K; };"
537 "template <int K> using dummy2 = dummy<K>;"
538 "int declToImport() { return dummy2<3>::i; }",
539 Lang_CXX11, "", Lang_CXX11, Verifier,
540 functionDecl(
541 hasBody(
542 compoundStmt(
543 has(
544 returnStmt(
545 has(
546 implicitCastExpr(
547 has(
548 declRefExpr())))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000549}
550
Gabor Horvath7a91c082017-11-14 11:30:38 +0000551TEST(ImportType, ImportPackExpansion) {
552 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000553 testImport("template <typename... Args>"
554 "struct dummy {"
555 " dummy(Args... args) {}"
556 " static const int i = 4;"
557 "};"
558 "int declToImport() { return dummy<int>::i; }",
559 Lang_CXX11, "", Lang_CXX11, Verifier,
560 functionDecl(
561 hasBody(
562 compoundStmt(
563 has(
564 returnStmt(
565 has(
566 implicitCastExpr(
567 has(
568 declRefExpr())))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000569}
570
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000571/// \brief Matches __builtin_types_compatible_p:
572/// GNU extension to check equivalent types
573/// Given
574/// \code
575/// __builtin_types_compatible_p(int, int)
576/// \endcode
577// will generate TypeTraitExpr <...> 'int'
578const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
579
580TEST(ImportExpr, ImportTypeTraitExpr) {
581 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000582 testImport("void declToImport() { "
583 " __builtin_types_compatible_p(int, int);"
584 "}",
585 Lang_C, "", Lang_C, Verifier,
586 functionDecl(
587 hasBody(
588 compoundStmt(
589 has(
590 typeTraitExpr(hasType(asString("int"))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000591}
592
593TEST(ImportExpr, ImportTypeTraitExprValDep) {
594 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000595 testImport("template<typename T> struct declToImport {"
596 " void m() { __is_pod(T); }"
597 "};"
598 "void f() { declToImport<int>().m(); }",
599 Lang_CXX11, "", Lang_CXX11, Verifier,
600 classTemplateDecl(
601 has(
602 cxxRecordDecl(
603 has(
604 functionDecl(
605 hasBody(
606 compoundStmt(
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000607 has(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000608 typeTraitExpr(
609 hasType(booleanType())
610 ))))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000611}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000612
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000613const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
614 cxxPseudoDestructorExpr;
615
616TEST(ImportExpr, ImportCXXPseudoDestructorExpr) {
617 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000618 testImport("typedef int T;"
619 "void declToImport(int *p) {"
620 " T t;"
621 " p->T::~T();"
622 "}",
623 Lang_CXX, "", Lang_CXX, Verifier,
624 functionDecl(has(compoundStmt(has(
625 callExpr(has(cxxPseudoDestructorExpr())))))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000626}
627
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000628TEST(ImportDecl, ImportUsingDecl) {
629 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000630 testImport("namespace foo { int bar; }"
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000631 "void declToImport() { using foo::bar; }",
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000632 Lang_CXX, "", Lang_CXX, Verifier,
633 functionDecl(
634 has(
635 compoundStmt(
636 has(
637 declStmt(
638 has(
639 usingDecl())))))));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000640}
641
642/// \brief Matches shadow declarations introduced into a scope by a
643/// (resolved) using declaration.
644///
645/// Given
646/// \code
647/// namespace n { int f; }
648/// namespace declToImport { using n::f; }
649/// \endcode
650/// usingShadowDecl()
651/// matches \code f \endcode
652const internal::VariadicDynCastAllOfMatcher<Decl,
653 UsingShadowDecl> usingShadowDecl;
654
655TEST(ImportDecl, ImportUsingShadowDecl) {
656 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000657 testImport("namespace foo { int bar; }"
658 "namespace declToImport { using foo::bar; }",
659 Lang_CXX, "", Lang_CXX, Verifier,
660 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000661}
662
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000663TEST(ImportExpr, ImportUnresolvedLookupExpr) {
664 MatchVerifier<Decl> Verifier;
665 testImport("template<typename T> int foo();"
666 "template <typename T> void declToImport() {"
667 " ::foo<T>;"
668 " ::template foo<T>;"
669 "}"
670 "void instantiate() { declToImport<int>(); }",
671 Lang_CXX, "", Lang_CXX, Verifier,
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000672 functionTemplateDecl(has(functionDecl(
673 has(compoundStmt(has(unresolvedLookupExpr())))))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000674}
675
676TEST(ImportExpr, ImportCXXUnresolvedConstructExpr) {
677 MatchVerifier<Decl> Verifier;
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000678 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000679 "template <typename T> void declToImport() {"
680 " C<T> d;"
681 " d.t = T();"
682 "}"
683 "void instantiate() { declToImport<int>(); }",
684 Lang_CXX, "", Lang_CXX, Verifier,
685 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
686 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000687 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000688 "template <typename T> void declToImport() {"
689 " C<T> d;"
690 " (&d)->t = T();"
691 "}"
692 "void instantiate() { declToImport<int>(); }",
693 Lang_CXX, "", Lang_CXX, Verifier,
694 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
695 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
696}
697
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000698/// Check that function "declToImport()" (which is the templated function
699/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
700/// Same for class template declarations.
701TEST(ImportDecl, ImportTemplatedDeclForTemplate) {
702 MatchVerifier<Decl> Verifier;
703 testImport("template <typename T> void declToImport() { T a = 1; }"
704 "void instantiate() { declToImport<int>(); }",
705 Lang_CXX, "", Lang_CXX, Verifier,
706 functionTemplateDecl(hasAncestor(translationUnitDecl(
707 unless(has(functionDecl(hasName("declToImport"))))))));
708 testImport("template <typename T> struct declToImport { T t; };"
709 "void instantiate() { declToImport<int>(); }",
710 Lang_CXX, "", Lang_CXX, Verifier,
711 classTemplateDecl(hasAncestor(translationUnitDecl(
712 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
713}
714
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000715} // end namespace ast_matchers
716} // end namespace clang