blob: ca024b17d3cd0a129253b2088e1a8a069c3a351d [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"
Peter Szecsidedda6f2018-03-30 22:03:29 +000020
21#include "DeclMatcher.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000022#include "gtest/gtest.h"
23
24namespace clang {
25namespace ast_matchers {
26
Aleksei Sidorine45ab562017-12-21 17:41:06 +000027typedef std::vector<std::string> ArgVector;
28typedef std::vector<ArgVector> RunOptions;
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000029
Aleksei Sidorine45ab562017-12-21 17:41:06 +000030static bool isCXX(Language Lang) {
31 return Lang == Lang_CXX || Lang == Lang_CXX11;
32}
33
Peter Szecsidedda6f2018-03-30 22:03:29 +000034static ArgVector getBasicRunOptionsForLanguage(Language Lang) {
Aleksei Sidorine45ab562017-12-21 17:41:06 +000035 ArgVector BasicArgs;
36 // Test with basic arguments.
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000037 switch (Lang) {
38 case Lang_C:
Aleksei Sidorine45ab562017-12-21 17:41:06 +000039 BasicArgs = {"-x", "c", "-std=c99"};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000040 break;
41 case Lang_C89:
Aleksei Sidorine45ab562017-12-21 17:41:06 +000042 BasicArgs = {"-x", "c", "-std=c89"};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000043 break;
44 case Lang_CXX:
Gabor Horvathd2c562d2018-01-27 16:38:56 +000045 BasicArgs = {"-std=c++98", "-frtti"};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000046 break;
47 case Lang_CXX11:
Gabor Horvathd2c562d2018-01-27 16:38:56 +000048 BasicArgs = {"-std=c++11", "-frtti"};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000049 break;
50 case Lang_OpenCL:
51 case Lang_OBJCXX:
Aleksei Sidorine45ab562017-12-21 17:41:06 +000052 llvm_unreachable("Not implemented yet!");
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000053 }
Peter Szecsidedda6f2018-03-30 22:03:29 +000054 return BasicArgs;
55}
56
57static RunOptions getRunOptionsForLanguage(Language Lang) {
58 ArgVector BasicArgs = getBasicRunOptionsForLanguage(Lang);
Aleksei Sidorine45ab562017-12-21 17:41:06 +000059
60 // For C++, test with "-fdelayed-template-parsing" enabled to handle MSVC
61 // default behaviour.
62 if (isCXX(Lang)) {
63 ArgVector ArgsForDelayedTemplateParse = BasicArgs;
64 ArgsForDelayedTemplateParse.emplace_back("-fdelayed-template-parsing");
65 return {BasicArgs, ArgsForDelayedTemplateParse};
66 }
67
68 return {BasicArgs};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000069}
70
Peter Szecsidedda6f2018-03-30 22:03:29 +000071// Creates a virtual file and assigns that to the context of given AST. If the
72// file already exists then the file will not be created again as a duplicate.
73static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
74 const std::string &Code) {
75 assert(ToAST);
76 ASTContext &ToCtx = ToAST->getASTContext();
77 auto *OFS = static_cast<vfs::OverlayFileSystem *>(
78 ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
79 auto *MFS =
80 static_cast<vfs::InMemoryFileSystem *>(OFS->overlays_begin()->get());
81 MFS->addFile(FileName, 0, llvm::MemoryBuffer::getMemBuffer(Code.c_str()));
82}
83
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000084template<typename NodeType, typename MatcherType>
85testing::AssertionResult
Aleksei Sidorine45ab562017-12-21 17:41:06 +000086testImport(const std::string &FromCode, const ArgVector &FromArgs,
87 const std::string &ToCode, const ArgVector &ToArgs,
88 MatchVerifier<NodeType> &Verifier, const MatcherType &AMatcher) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000089 const char *const InputFileName = "input.cc";
90 const char *const OutputFileName = "output.cc";
91
92 std::unique_ptr<ASTUnit>
93 FromAST = tooling::buildASTFromCodeWithArgs(
94 FromCode, FromArgs, InputFileName),
95 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
96
97 ASTContext &FromCtx = FromAST->getASTContext(),
98 &ToCtx = ToAST->getASTContext();
99
100 // Add input.cc to virtual file system so importer can 'find' it
101 // while importing SourceLocations.
Peter Szecsidedda6f2018-03-30 22:03:29 +0000102 createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromCode);
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000103
104 ASTImporter Importer(ToCtx, ToAST->getFileManager(),
105 FromCtx, FromAST->getFileManager(), false);
106
107 IdentifierInfo *ImportedII = &FromCtx.Idents.get("declToImport");
108 assert(ImportedII && "Declaration with 'declToImport' name"
109 "should be specified in test!");
110 DeclarationName ImportDeclName(ImportedII);
111 SmallVector<NamedDecl *, 4> FoundDecls;
112 FromCtx.getTranslationUnitDecl()->localUncachedLookup(
113 ImportDeclName, FoundDecls);
114
115 if (FoundDecls.size() != 1)
116 return testing::AssertionFailure() << "Multiple declarations were found!";
117
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000118 // Sanity check: the node being imported should match in the same way as
119 // the result node.
120 EXPECT_TRUE(Verifier.match(FoundDecls.front(), AMatcher));
121
122 auto Imported = Importer.Import(FoundDecls.front());
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000123 if (!Imported)
124 return testing::AssertionFailure() << "Import failed, nullptr returned!";
125
126 // This should dump source locations and assert if some source locations
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000127 // were not imported.
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000128 SmallString<1024> ImportChecker;
129 llvm::raw_svector_ostream ToNothing(ImportChecker);
130 ToCtx.getTranslationUnitDecl()->print(ToNothing);
131
Gabor Horvath480892b2017-10-18 09:25:18 +0000132 // This traverses the AST to catch certain bugs like poorly or not
133 // implemented subtrees.
134 Imported->dump(ToNothing);
135
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000136 return Verifier.match(Imported, AMatcher);
137}
138
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000139template<typename NodeType, typename MatcherType>
140void testImport(const std::string &FromCode, Language FromLang,
141 const std::string &ToCode, Language ToLang,
142 MatchVerifier<NodeType> &Verifier,
143 const MatcherType &AMatcher) {
144 auto RunOptsFrom = getRunOptionsForLanguage(FromLang);
145 auto RunOptsTo = getRunOptionsForLanguage(ToLang);
146 for (const auto &FromArgs : RunOptsFrom)
147 for (const auto &ToArgs : RunOptsTo)
148 EXPECT_TRUE(testImport(FromCode, FromArgs, ToCode, ToArgs,
149 Verifier, AMatcher));
150}
151
Peter Szecsidedda6f2018-03-30 22:03:29 +0000152const StringRef DeclToImportID = "declToImport";
153
154// This class provides generic methods to write tests which can check internal
155// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
156// this fixture makes it possible to import from several "From" contexts.
157class ASTImporterTestBase : public ::testing::TestWithParam<ArgVector> {
158
159 const char *const InputFileName = "input.cc";
160 const char *const OutputFileName = "output.cc";
161
162 // Buffer for the To context, must live in the test scope.
163 std::string ToCode;
164
165 struct TU {
166 // Buffer for the context, must live in the test scope.
167 std::string Code;
168 std::string FileName;
169 std::unique_ptr<ASTUnit> Unit;
170 TranslationUnitDecl *TUDecl = nullptr;
171 TU(StringRef Code, StringRef FileName, ArgVector Args)
172 : Code(Code), FileName(FileName),
173 Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
174 this->FileName)),
175 TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {}
176 };
177
178 // We may have several From contexts and related translation units. In each
179 // AST, the buffers for the source are handled via references and are set
180 // during the creation of the AST. These references must point to a valid
181 // buffer until the AST is alive. Thus, we must use a list in order to avoid
182 // moving of the stored objects because that would mean breaking the
183 // references in the AST. By using a vector a move could happen when the
184 // vector is expanding, with the list we won't have these issues.
185 std::list<TU> FromTUs;
186
187public:
188 // We may have several From context but only one To context.
189 std::unique_ptr<ASTUnit> ToAST;
190
191 // Returns the argument vector used for a specific language, this set
192 // can be tweaked by the test parameters.
193 ArgVector getArgVectorForLanguage(Language Lang) {
194 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
195 ArgVector ExtraArgs = GetParam();
196 for (const auto& Arg : ExtraArgs) {
197 Args.push_back(Arg);
198 }
199 return Args;
200 }
201
202 // Creates an AST both for the From and To source code and imports the Decl
203 // of the identifier into the To context.
204 // Must not be called more than once within the same test.
205 std::tuple<Decl *, Decl *>
206 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
207 Language ToLang, StringRef Identifier = DeclToImportID) {
208 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
209 ToArgs = getArgVectorForLanguage(ToLang);
210
211 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
212 TU &FromTU = FromTUs.back();
213
214 ToCode = ToSrcCode;
215 assert(!ToAST);
216 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
217
218 ASTContext &FromCtx = FromTU.Unit->getASTContext(),
219 &ToCtx = ToAST->getASTContext();
220
221 createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
222
223 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
224 FromTU.Unit->getFileManager(), false);
225
226 IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
227 assert(ImportedII && "Declaration with the given identifier "
228 "should be specified in test!");
229 DeclarationName ImportDeclName(ImportedII);
230 SmallVector<NamedDecl *, 4> FoundDecls;
231 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
232 FoundDecls);
233
234 assert(FoundDecls.size() == 1);
235
236 Decl *Imported = Importer.Import(FoundDecls.front());
237 assert(Imported);
238 return std::make_tuple(*FoundDecls.begin(), Imported);
239 }
240
241 // Creates a TU decl for the given source code.
242 // May be called several times in a given test.
243 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
244 StringRef FileName = "input.cc") {
245 assert(
246 std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) {
247 return E.FileName == FileName;
248 }) == FromTUs.end());
249
250 ArgVector Args = getArgVectorForLanguage(Lang);
251 FromTUs.emplace_back(SrcCode, FileName, Args);
252 TU &Tu = FromTUs.back();
253
254 return Tu.TUDecl;
255 }
256
257 // Import the given Decl into the ToCtx.
258 // May be called several times in a given test.
259 // The different instances of the param From may have different ASTContext.
260 Decl *Import(Decl *From, Language ToLang) {
261 if (!ToAST) {
262 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
263 // Build the AST from an empty file.
264 ToAST =
265 tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
266 }
267
268 // Create a virtual file in the To Ctx which corresponds to the file from
269 // which we want to import the `From` Decl. Without this source locations
270 // will be invalid in the ToCtx.
271 auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) {
272 return E.TUDecl == From->getTranslationUnitDecl();
273 });
274 assert(It != FromTUs.end());
275 createVirtualFileIfNeeded(ToAST.get(), It->FileName, It->Code);
276
277 ASTContext &FromCtx = From->getASTContext(),
278 &ToCtx = ToAST->getASTContext();
279 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
280 FromCtx.getSourceManager().getFileManager(), false);
281 return Importer.Import(From);
282 }
283
284 ~ASTImporterTestBase() {
285 if (!::testing::Test::HasFailure()) return;
286
287 for (auto &Tu : FromTUs) {
288 assert(Tu.Unit);
289 llvm::errs() << "FromAST:\n";
290 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
291 llvm::errs() << "\n";
292 }
293 if (ToAST) {
294 llvm::errs() << "ToAST:\n";
295 ToAST->getASTContext().getTranslationUnitDecl()->dump();
296 }
297 }
298};
299
300AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
301 size_t Index = 0;
302 for (FieldDecl *Field : Node.fields()) {
303 if (Index == Order.size())
304 return false;
305 if (Field->getName() != Order[Index])
306 return false;
307 ++Index;
308 }
309 return Index == Order.size();
310}
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000311
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000312TEST(ImportExpr, ImportStringLiteral) {
313 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000314 testImport("void declToImport() { \"foo\"; }",
315 Lang_CXX, "", Lang_CXX, Verifier,
316 functionDecl(
317 hasBody(
318 compoundStmt(
319 has(
320 stringLiteral(
321 hasType(
322 asString("const char [4]"))))))));
323 testImport("void declToImport() { L\"foo\"; }",
324 Lang_CXX, "", Lang_CXX, Verifier,
325 functionDecl(
326 hasBody(
327 compoundStmt(
328 has(
329 stringLiteral(
330 hasType(
331 asString("const wchar_t [4]"))))))));
332 testImport("void declToImport() { \"foo\" \"bar\"; }",
333 Lang_CXX, "", Lang_CXX, Verifier,
334 functionDecl(
335 hasBody(
336 compoundStmt(
337 has(
338 stringLiteral(
339 hasType(
340 asString("const char [7]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000341}
342
343TEST(ImportExpr, ImportGNUNullExpr) {
344 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000345 testImport("void declToImport() { __null; }",
346 Lang_CXX, "", Lang_CXX, Verifier,
347 functionDecl(
348 hasBody(
349 compoundStmt(
350 has(
351 gnuNullExpr(
352 hasType(isInteger())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000353}
354
355TEST(ImportExpr, ImportCXXNullPtrLiteralExpr) {
356 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000357 testImport("void declToImport() { nullptr; }",
358 Lang_CXX11, "", Lang_CXX11, Verifier,
359 functionDecl(
360 hasBody(
361 compoundStmt(
362 has(
363 cxxNullPtrLiteralExpr())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000364}
365
366
367TEST(ImportExpr, ImportFloatinglLiteralExpr) {
368 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000369 testImport("void declToImport() { 1.0; }",
370 Lang_C, "", Lang_C, Verifier,
371 functionDecl(
372 hasBody(
373 compoundStmt(
374 has(
375 floatLiteral(
376 equals(1.0),
377 hasType(asString("double"))))))));
378 testImport("void declToImport() { 1.0e-5f; }",
379 Lang_C, "", Lang_C, Verifier,
380 functionDecl(
381 hasBody(
382 compoundStmt(
383 has(
384 floatLiteral(
385 equals(1.0e-5f),
386 hasType(asString("float"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000387}
388
389TEST(ImportExpr, ImportCompoundLiteralExpr) {
390 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000391 testImport("void declToImport() {"
392 " struct s { int x; long y; unsigned z; }; "
393 " (struct s){ 42, 0L, 1U }; }",
394 Lang_CXX, "", Lang_CXX, Verifier,
395 functionDecl(
396 hasBody(
397 compoundStmt(
398 has(
399 compoundLiteralExpr(
400 hasType(asString("struct s")),
401 has(initListExpr(
402 hasType(asString("struct s")),
403 has(integerLiteral(
404 equals(42), hasType(asString("int")))),
405 has(integerLiteral(
406 equals(0), hasType(asString("long")))),
407 has(integerLiteral(
408 equals(1),
409 hasType(asString("unsigned int"))))
410 ))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000411}
412
413TEST(ImportExpr, ImportCXXThisExpr) {
414 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000415 testImport("class declToImport { void f() { this; } };",
416 Lang_CXX, "", Lang_CXX, Verifier,
417 cxxRecordDecl(
418 hasMethod(
419 hasBody(
420 compoundStmt(
421 has(
422 cxxThisExpr(
423 hasType(
424 asString("class declToImport *")))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000425}
426
427TEST(ImportExpr, ImportAtomicExpr) {
428 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000429 testImport("void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
430 Lang_C, "", Lang_C, Verifier,
431 functionDecl(hasBody(compoundStmt(has(atomicExpr(
432 has(ignoringParenImpCasts(
433 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
434 hasType(asString("int *"))))),
435 has(integerLiteral(equals(1), hasType(asString("int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000436}
437
438TEST(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
439 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000440 testImport(
441 "void declToImport() { loop: goto loop; &&loop; }", Lang_C, "", Lang_C,
442 Verifier,
443 functionDecl(hasBody(compoundStmt(
444 has(labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
445 has(addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000446}
447
448AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
449 internal::Matcher<NamedDecl>, InnerMatcher) {
450 const NamedDecl *Template = Node.getTemplatedDecl();
451 return Template && InnerMatcher.matches(*Template, Finder, Builder);
452}
453
454TEST(ImportExpr, ImportParenListExpr) {
455 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000456 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000457 "template<typename T> class dummy { void f() { dummy X(*this); } };"
458 "typedef dummy<int> declToImport;"
459 "template class dummy<int>;",
460 Lang_CXX, "", Lang_CXX, Verifier,
461 typedefDecl(hasType(templateSpecializationType(
462 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
463 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
464 hasName("f"),
465 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
466 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
467 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000468 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000469}
470
Gabor Horvath480892b2017-10-18 09:25:18 +0000471TEST(ImportExpr, ImportSwitch) {
472 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000473 testImport("void declToImport() { int b; switch (b) { case 1: break; } }",
474 Lang_C, "", Lang_C, Verifier,
475 functionDecl(hasBody(compoundStmt(
476 has(switchStmt(has(compoundStmt(has(caseStmt())))))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000477}
478
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000479TEST(ImportExpr, ImportStmtExpr) {
480 MatchVerifier<Decl> Verifier;
481 // NOTE: has() ignores implicit casts, using hasDescendant() to match it
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000482 testImport(
483 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
484 Lang_C, "", Lang_C, Verifier,
485 functionDecl(
486 hasBody(
487 compoundStmt(
488 has(
489 declStmt(
490 hasSingleDecl(
491 varDecl(
492 hasName("C"),
493 hasType(asString("int")),
494 hasInitializer(
495 stmtExpr(
496 hasAnySubstatement(
497 declStmt(
498 hasSingleDecl(
499 varDecl(
500 hasName("X"),
501 hasType(asString("int")),
502 hasInitializer(
503 integerLiteral(equals(4))))))),
504 hasDescendant(
505 implicitCastExpr()
506 )))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000507}
508
509TEST(ImportExpr, ImportConditionalOperator) {
510 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000511 testImport(
512 "void declToImport() { true ? 1 : -5; }",
513 Lang_CXX, "", Lang_CXX, Verifier,
514 functionDecl(
515 hasBody(
516 compoundStmt(
517 has(
518 conditionalOperator(
519 hasCondition(cxxBoolLiteral(equals(true))),
520 hasTrueExpression(integerLiteral(equals(1))),
521 hasFalseExpression(
522 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))
523 )))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000524}
525
526TEST(ImportExpr, ImportBinaryConditionalOperator) {
527 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000528 testImport(
529 "void declToImport() { 1 ?: -5; }", Lang_CXX, "", Lang_CXX, Verifier,
530 functionDecl(
531 hasBody(
532 compoundStmt(
533 has(
534 binaryConditionalOperator(
535 hasCondition(
536 implicitCastExpr(
537 hasSourceExpression(
538 opaqueValueExpr(
539 hasSourceExpression(integerLiteral(equals(1))))),
540 hasType(booleanType()))),
541 hasTrueExpression(
542 opaqueValueExpr(hasSourceExpression(
543 integerLiteral(equals(1))))),
544 hasFalseExpression(
545 unaryOperator(hasOperatorName("-"),
546 hasUnaryOperand(integerLiteral(equals(5)))))
547 ))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000548}
549
550TEST(ImportExpr, ImportDesignatedInitExpr) {
551 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000552 testImport("void declToImport() {"
553 " struct point { double x; double y; };"
554 " struct point ptarray[10] = "
555 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
556 Lang_C, "", Lang_C, Verifier,
557 functionDecl(
558 hasBody(
559 compoundStmt(
560 has(
561 declStmt(
562 hasSingleDecl(
563 varDecl(
564 hasInitializer(
565 initListExpr(
566 hasSyntacticForm(
567 initListExpr(
568 has(
569 designatedInitExpr(
570 designatorCountIs(2),
571 has(floatLiteral(
572 equals(1.0))),
573 has(integerLiteral(
574 equals(2))))),
575 has(
576 designatedInitExpr(
577 designatorCountIs(2),
578 has(floatLiteral(
579 equals(2.0))),
580 has(integerLiteral(
581 equals(2))))),
582 has(
583 designatedInitExpr(
584 designatorCountIs(2),
585 has(floatLiteral(
586 equals(1.0))),
587 has(integerLiteral(
588 equals(0)))))
589 ))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000590}
591
592
593TEST(ImportExpr, ImportPredefinedExpr) {
594 MatchVerifier<Decl> Verifier;
595 // __func__ expands as StringLiteral("declToImport")
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000596 testImport("void declToImport() { __func__; }",
597 Lang_CXX, "", Lang_CXX, Verifier,
598 functionDecl(
599 hasBody(
600 compoundStmt(
601 has(
602 predefinedExpr(
603 hasType(
604 asString("const char [13]")),
605 has(
606 stringLiteral(
607 hasType(
608 asString("const char [13]"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000609}
610
611TEST(ImportExpr, ImportInitListExpr) {
612 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000613 testImport(
614 "void declToImport() {"
615 " struct point { double x; double y; };"
616 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
617 " [0].x = 1.0 }; }",
618 Lang_CXX, "", Lang_CXX, Verifier,
619 functionDecl(
620 hasBody(
621 compoundStmt(
622 has(
623 declStmt(
624 hasSingleDecl(
625 varDecl(
626 hasInitializer(
627 initListExpr(
628 has(
629 cxxConstructExpr(
630 requiresZeroInitialization())),
631 has(
632 initListExpr(
633 hasType(asString("struct point")),
634 has(floatLiteral(equals(1.0))),
635 has(implicitValueInitExpr(
636 hasType(asString("double")))))),
637 has(
638 initListExpr(
639 hasType(asString("struct point")),
640 has(floatLiteral(equals(2.0))),
641 has(floatLiteral(equals(1.0)))))
642 ))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000643}
644
645
Aleksei Sidorina693b372016-09-28 10:16:56 +0000646const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
647
648TEST(ImportExpr, ImportVAArgExpr) {
649 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000650 testImport("void declToImport(__builtin_va_list list, ...) {"
651 " (void)__builtin_va_arg(list, int); }",
652 Lang_CXX, "", Lang_CXX, Verifier,
653 functionDecl(
654 hasBody(
655 compoundStmt(
656 has(
657 cStyleCastExpr(
658 hasSourceExpression(
659 vaArgExpr())))))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000660}
661
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000662TEST(ImportExpr, CXXTemporaryObjectExpr) {
663 MatchVerifier<Decl> Verifier;
664 testImport("struct C {};"
665 "void declToImport() { C c = C(); }",
666 Lang_CXX, "", Lang_CXX, Verifier,
667 functionDecl(hasBody(compoundStmt(has(
668 declStmt(has(varDecl(has(exprWithCleanups(has(cxxConstructExpr(
669 has(materializeTemporaryExpr(has(implicitCastExpr(
670 has(cxxTemporaryObjectExpr())))))))))))))))));
671}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000672
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000673TEST(ImportType, ImportAtomicType) {
674 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000675 testImport("void declToImport() { typedef _Atomic(int) a_int; }",
676 Lang_CXX11, "", Lang_CXX11, Verifier,
677 functionDecl(
678 hasBody(
679 compoundStmt(
680 has(
681 declStmt(
682 has(
683 typedefDecl(
684 has(atomicType())))))))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000685}
686
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000687TEST(ImportDecl, ImportFunctionTemplateDecl) {
688 MatchVerifier<Decl> Verifier;
689 testImport("template <typename T> void declToImport() { };", Lang_CXX, "",
690 Lang_CXX, Verifier, functionTemplateDecl());
691}
692
693const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
694 cxxDependentScopeMemberExpr;
695
696TEST(ImportExpr, ImportCXXDependentScopeMemberExpr) {
697 MatchVerifier<Decl> Verifier;
698 testImport("template <typename T> struct C { T t; };"
699 "template <typename T> void declToImport() {"
700 " C<T> d;"
701 " d.t;"
702 "}"
703 "void instantiate() { declToImport<int>(); }",
704 Lang_CXX, "", Lang_CXX, Verifier,
705 functionTemplateDecl(has(functionDecl(
706 has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
707 testImport("template <typename T> struct C { T t; };"
708 "template <typename T> void declToImport() {"
709 " C<T> d;"
710 " (&d)->t;"
711 "}"
712 "void instantiate() { declToImport<int>(); }",
713 Lang_CXX, "", Lang_CXX, Verifier,
714 functionTemplateDecl(has(functionDecl(
715 has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
716}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000717
Gabor Horvath7a91c082017-11-14 11:30:38 +0000718TEST(ImportType, ImportTypeAliasTemplate) {
719 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000720 testImport(
721 "template <int K>"
722 "struct dummy { static const int i = K; };"
723 "template <int K> using dummy2 = dummy<K>;"
724 "int declToImport() { return dummy2<3>::i; }",
725 Lang_CXX11, "", Lang_CXX11, Verifier,
726 functionDecl(
727 hasBody(compoundStmt(
728 has(returnStmt(has(implicitCastExpr(has(declRefExpr()))))))),
729 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
730}
731
732const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
733 varTemplateSpecializationDecl;
734
735TEST(ImportDecl, ImportVarTemplate) {
736 MatchVerifier<Decl> Verifier;
737 testImport(
738 "template <typename T>"
739 "T pi = T(3.1415926535897932385L);"
740 "void declToImport() { pi<int>; }",
741 Lang_CXX11, "", Lang_CXX11, Verifier,
742 functionDecl(
743 hasBody(has(declRefExpr(to(varTemplateSpecializationDecl())))),
744 unless(hasAncestor(translationUnitDecl(has(varDecl(
745 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000746}
747
Gabor Horvath7a91c082017-11-14 11:30:38 +0000748TEST(ImportType, ImportPackExpansion) {
749 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000750 testImport("template <typename... Args>"
751 "struct dummy {"
752 " dummy(Args... args) {}"
753 " static const int i = 4;"
754 "};"
755 "int declToImport() { return dummy<int>::i; }",
756 Lang_CXX11, "", Lang_CXX11, Verifier,
757 functionDecl(
758 hasBody(
759 compoundStmt(
760 has(
761 returnStmt(
762 has(
763 implicitCastExpr(
764 has(
765 declRefExpr())))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000766}
767
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000768const internal::VariadicDynCastAllOfMatcher<Type,
769 DependentTemplateSpecializationType>
770 dependentTemplateSpecializationType;
771
772TEST(ImportType, ImportDependentTemplateSpecialization) {
773 MatchVerifier<Decl> Verifier;
774 testImport("template<typename T>"
775 "struct A;"
776 "template<typename T>"
777 "struct declToImport {"
778 " typename A<T>::template B<T> a;"
779 "};",
780 Lang_CXX, "", Lang_CXX, Verifier,
781 classTemplateDecl(has(cxxRecordDecl(has(
782 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
783}
784
785const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
786 sizeOfPackExpr;
787
788TEST(ImportExpr, ImportSizeOfPackExpr) {
789 MatchVerifier<Decl> Verifier;
790 testImport("template <typename... Ts>"
791 "void declToImport() {"
792 " const int i = sizeof...(Ts);"
793 "};"
794 "void g() { declToImport<int>(); }",
795 Lang_CXX11, "", Lang_CXX11, Verifier,
796 functionTemplateDecl(has(functionDecl(
797 hasBody(compoundStmt(has(declStmt(has(varDecl(hasInitializer(
798 implicitCastExpr(has(sizeOfPackExpr())))))))))))));
799 testImport(
800 "template <typename... Ts>"
801 "using X = int[sizeof...(Ts)];"
802 "template <typename... Us>"
803 "struct Y {"
804 " X<Us..., int, double, int, Us...> f;"
805 "};"
806 "Y<float, int> declToImport;",
807 Lang_CXX11, "", Lang_CXX11, Verifier,
808 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
809 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
810}
811
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000812/// \brief Matches __builtin_types_compatible_p:
813/// GNU extension to check equivalent types
814/// Given
815/// \code
816/// __builtin_types_compatible_p(int, int)
817/// \endcode
818// will generate TypeTraitExpr <...> 'int'
819const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
820
821TEST(ImportExpr, ImportTypeTraitExpr) {
822 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000823 testImport("void declToImport() { "
824 " __builtin_types_compatible_p(int, int);"
825 "}",
826 Lang_C, "", Lang_C, Verifier,
827 functionDecl(
828 hasBody(
829 compoundStmt(
830 has(
831 typeTraitExpr(hasType(asString("int"))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000832}
833
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000834const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
835
836TEST(ImportExpr, ImportCXXTypeidExpr) {
837 MatchVerifier<Decl> Verifier;
838 testImport(
839 "namespace std { class type_info {}; }"
840 "void declToImport() {"
841 " int x;"
842 " auto a = typeid(int); auto b = typeid(x);"
843 "}",
844 Lang_CXX11, "", Lang_CXX11, Verifier,
845 functionDecl(
846 hasDescendant(varDecl(
847 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
848 hasDescendant(varDecl(
849 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
850}
851
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000852TEST(ImportExpr, ImportTypeTraitExprValDep) {
853 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000854 testImport("template<typename T> struct declToImport {"
855 " void m() { __is_pod(T); }"
856 "};"
857 "void f() { declToImport<int>().m(); }",
858 Lang_CXX11, "", Lang_CXX11, Verifier,
859 classTemplateDecl(
860 has(
861 cxxRecordDecl(
862 has(
863 functionDecl(
864 hasBody(
865 compoundStmt(
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000866 has(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000867 typeTraitExpr(
868 hasType(booleanType())
869 ))))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000870}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000871
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000872const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
873 cxxPseudoDestructorExpr;
874
875TEST(ImportExpr, ImportCXXPseudoDestructorExpr) {
876 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000877 testImport("typedef int T;"
878 "void declToImport(int *p) {"
879 " T t;"
880 " p->T::~T();"
881 "}",
882 Lang_CXX, "", Lang_CXX, Verifier,
883 functionDecl(has(compoundStmt(has(
884 callExpr(has(cxxPseudoDestructorExpr())))))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000885}
886
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000887TEST(ImportDecl, ImportUsingDecl) {
888 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000889 testImport("namespace foo { int bar; }"
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000890 "void declToImport() { using foo::bar; }",
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000891 Lang_CXX, "", Lang_CXX, Verifier,
892 functionDecl(
893 has(
894 compoundStmt(
895 has(
896 declStmt(
897 has(
898 usingDecl())))))));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000899}
900
901/// \brief Matches shadow declarations introduced into a scope by a
902/// (resolved) using declaration.
903///
904/// Given
905/// \code
906/// namespace n { int f; }
907/// namespace declToImport { using n::f; }
908/// \endcode
909/// usingShadowDecl()
910/// matches \code f \endcode
911const internal::VariadicDynCastAllOfMatcher<Decl,
912 UsingShadowDecl> usingShadowDecl;
913
914TEST(ImportDecl, ImportUsingShadowDecl) {
915 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000916 testImport("namespace foo { int bar; }"
917 "namespace declToImport { using foo::bar; }",
918 Lang_CXX, "", Lang_CXX, Verifier,
919 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000920}
921
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000922TEST(ImportExpr, ImportUnresolvedLookupExpr) {
923 MatchVerifier<Decl> Verifier;
924 testImport("template<typename T> int foo();"
925 "template <typename T> void declToImport() {"
926 " ::foo<T>;"
927 " ::template foo<T>;"
928 "}"
929 "void instantiate() { declToImport<int>(); }",
930 Lang_CXX, "", Lang_CXX, Verifier,
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000931 functionTemplateDecl(has(functionDecl(
932 has(compoundStmt(has(unresolvedLookupExpr())))))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000933}
934
935TEST(ImportExpr, ImportCXXUnresolvedConstructExpr) {
936 MatchVerifier<Decl> Verifier;
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000937 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000938 "template <typename T> void declToImport() {"
939 " C<T> d;"
940 " d.t = T();"
941 "}"
942 "void instantiate() { declToImport<int>(); }",
943 Lang_CXX, "", Lang_CXX, Verifier,
944 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
945 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000946 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000947 "template <typename T> void declToImport() {"
948 " C<T> d;"
949 " (&d)->t = T();"
950 "}"
951 "void instantiate() { declToImport<int>(); }",
952 Lang_CXX, "", Lang_CXX, Verifier,
953 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
954 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
955}
956
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000957/// Check that function "declToImport()" (which is the templated function
958/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
959/// Same for class template declarations.
960TEST(ImportDecl, ImportTemplatedDeclForTemplate) {
961 MatchVerifier<Decl> Verifier;
962 testImport("template <typename T> void declToImport() { T a = 1; }"
963 "void instantiate() { declToImport<int>(); }",
964 Lang_CXX, "", Lang_CXX, Verifier,
965 functionTemplateDecl(hasAncestor(translationUnitDecl(
966 unless(has(functionDecl(hasName("declToImport"))))))));
967 testImport("template <typename T> struct declToImport { T t; };"
968 "void instantiate() { declToImport<int>(); }",
969 Lang_CXX, "", Lang_CXX, Verifier,
970 classTemplateDecl(hasAncestor(translationUnitDecl(
971 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
972}
973
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000974TEST(ImportExpr, CXXOperatorCallExpr) {
975 MatchVerifier<Decl> Verifier;
976 testImport("class declToImport {"
977 " void f() { *this = declToImport(); }"
978 "};",
979 Lang_CXX, "", Lang_CXX, Verifier,
980 cxxRecordDecl(has(cxxMethodDecl(hasBody(compoundStmt(
981 has(exprWithCleanups(has(cxxOperatorCallExpr())))))))));
982}
983
984TEST(ImportExpr, DependentSizedArrayType) {
985 MatchVerifier<Decl> Verifier;
986 testImport("template<typename T, int Size> class declToImport {"
987 " T data[Size];"
988 "};",
989 Lang_CXX, "", Lang_CXX, Verifier,
990 classTemplateDecl(has(cxxRecordDecl(
991 has(fieldDecl(hasType(dependentSizedArrayType())))))));
992}
993
Peter Szecsidedda6f2018-03-30 22:03:29 +0000994TEST_P(ASTImporterTestBase, DISABLED_ImportFunctionWithBackReferringParameter) {
995 Decl *From, *To;
996 std::tie(From, To) = getImportedDecl(
997 R"(
998 template <typename T> struct X {};
999
1000 void declToImport(int y, X<int> &x) {}
1001
1002 template <> struct X<int> {
1003 void g() {
1004 X<int> x;
1005 declToImport(0, x);
1006 }
1007 };
1008 )",
1009 Lang_CXX, "", Lang_CXX);
1010
1011 MatchVerifier<Decl> Verifier;
1012 auto Matcher = functionDecl(hasName("declToImport"),
1013 parameterCountIs(2),
1014 hasParameter(0, hasName("y")),
1015 hasParameter(1, hasName("x")),
1016 hasParameter(1, hasType(asString("X<int> &"))));
1017 ASSERT_TRUE(Verifier.match(From, Matcher));
1018 EXPECT_TRUE(Verifier.match(To, Matcher));
1019}
1020
1021TEST_P(ASTImporterTestBase,
1022 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1023 Decl *From, *To;
1024 std::tie(From, To) =
1025 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1026 "void instantiate() { declToImport<int>(); }",
1027 Lang_CXX, "", Lang_CXX);
1028
1029 auto Check = [](Decl *D) -> bool {
1030 auto TU = D->getTranslationUnitDecl();
1031 for (auto Child : TU->decls()) {
1032 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1033 if (FD->getNameAsString() == "declToImport") {
1034 GTEST_NONFATAL_FAILURE_(
1035 "TU should not contain any FunctionDecl with name declToImport");
1036 return false;
1037 }
1038 }
1039 }
1040 return true;
1041 };
1042
1043 ASSERT_TRUE(Check(From));
1044 EXPECT_TRUE(Check(To));
1045}
1046
1047TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
1048 Decl *From, *To;
1049 std::tie(From, To) =
1050 getImportedDecl("template <typename T> struct declToImport { T t; };"
1051 "void instantiate() { declToImport<int>(); }",
1052 Lang_CXX, "", Lang_CXX);
1053
1054 auto Check = [](Decl *D) -> bool {
1055 auto TU = D->getTranslationUnitDecl();
1056 for (auto Child : TU->decls()) {
1057 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1058 if (RD->getNameAsString() == "declToImport") {
1059 GTEST_NONFATAL_FAILURE_(
1060 "TU should not contain any CXXRecordDecl with name declToImport");
1061 return false;
1062 }
1063 }
1064 }
1065 return true;
1066 };
1067
1068 ASSERT_TRUE(Check(From));
1069 EXPECT_TRUE(Check(To));
1070}
1071
1072TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
1073 Decl *From, *To;
1074 std::tie(From, To) =
1075 getImportedDecl(
1076 "template <typename T> struct X {};"
1077 "template <typename T> using declToImport = X<T>;"
1078 "void instantiate() { declToImport<int> a; }",
1079 Lang_CXX11, "", Lang_CXX11);
1080
1081 auto Check = [](Decl *D) -> bool {
1082 auto TU = D->getTranslationUnitDecl();
1083 for (auto Child : TU->decls()) {
1084 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1085 if (AD->getNameAsString() == "declToImport") {
1086 GTEST_NONFATAL_FAILURE_(
1087 "TU should not contain any TypeAliasDecl with name declToImport");
1088 return false;
1089 }
1090 }
1091 }
1092 return true;
1093 };
1094
1095 ASSERT_TRUE(Check(From));
1096 EXPECT_TRUE(Check(To));
1097}
1098
1099TEST_P(
1100 ASTImporterTestBase,
1101 DISABLED_TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
1102
1103 Decl *From, *To;
1104 std::tie(From, To) = getImportedDecl(
1105 R"(
1106 template<class T>
1107 class Base {};
1108 class declToImport : public Base<declToImport> {};
1109 )",
1110 Lang_CXX, "", Lang_CXX);
1111
1112 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1113 auto Pattern =
1114 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1115 ASSERT_TRUE(
1116 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1117 EXPECT_TRUE(
1118 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1119
1120 // Check that the ClassTemplateSpecializationDecl is the child of the
1121 // ClassTemplateDecl.
1122 Pattern = translationUnitDecl(has(classTemplateDecl(
1123 hasName("Base"), has(classTemplateSpecializationDecl()))));
1124 ASSERT_TRUE(
1125 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1126 EXPECT_TRUE(
1127 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1128}
1129
1130TEST_P(ASTImporterTestBase,
1131 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1132 Decl *From, *To;
1133 std::tie(From, To) = getImportedDecl(
1134 R"(
1135 namespace NS {
1136 template<class T>
1137 class X {};
1138 template class X<int>;
1139 }
1140 )",
1141 Lang_CXX, "", Lang_CXX, "NS");
1142
1143 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1144 // ClassTemplateDecl.
1145 auto Pattern = namespaceDecl(has(classTemplateDecl(
1146 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1147 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1148 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1149
1150 // Check that the ClassTemplateSpecializationDecl is the child of the
1151 // NamespaceDecl.
1152 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1153 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1154 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1155}
1156
1157TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1158 Decl *From, *To;
1159 std::tie(From, To) =
1160 getImportedDecl(
1161 "struct declToImport { int a; int b; };",
1162 Lang_CXX11, "", Lang_CXX11);
1163
1164 MatchVerifier<Decl> Verifier;
1165 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1166 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1167}
1168
1169TEST_P(ASTImporterTestBase,
1170 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1171 Decl *From, *To;
1172 std::tie(From, To) = getImportedDecl(
1173 // The original recursive algorithm of ASTImporter first imports 'c' then
1174 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1175 R"s(
1176 struct declToImport {
1177 int a = c + b;
1178 int b = 1;
1179 int c = 2;
1180 };
1181 )s",
1182 Lang_CXX11, "", Lang_CXX11);
1183
1184 MatchVerifier<Decl> Verifier;
1185 ASSERT_TRUE(
1186 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1187 EXPECT_TRUE(
1188 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1189}
1190
1191TEST_P(ASTImporterTestBase, DISABLED_ShouldImportImplicitCXXRecordDecl) {
1192 Decl *From, *To;
1193 std::tie(From, To) = getImportedDecl(
1194 R"(
1195 template <typename U>
1196 struct declToImport {
1197 };
1198 )",
1199 Lang_CXX, "", Lang_CXX);
1200
1201 MatchVerifier<Decl> Verifier;
1202 // Match the implicit Decl.
1203 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1204 ASSERT_TRUE(Verifier.match(From, Matcher));
1205 EXPECT_TRUE(Verifier.match(To, Matcher));
1206}
1207
1208TEST_P(
1209 ASTImporterTestBase,
1210 DISABLED_ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
1211 Decl *From, *To;
1212 std::tie(From, To) = getImportedDecl(
1213 R"(
1214 template<class T>
1215 class Base {};
1216 class declToImport : public Base<declToImport> {};
1217 )",
1218 Lang_CXX, "", Lang_CXX);
1219
1220 auto hasImplicitClass = has(cxxRecordDecl());
1221 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1222 hasName("Base"),
1223 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1224 ASSERT_TRUE(
1225 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1226 EXPECT_TRUE(
1227 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1228}
1229
1230TEST_P(ASTImporterTestBase, IDNSOrdinary) {
1231 Decl *From, *To;
1232 std::tie(From, To) =
1233 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1234
1235 MatchVerifier<Decl> Verifier;
1236 auto Matcher = functionDecl();
1237 ASSERT_TRUE(Verifier.match(From, Matcher));
1238 EXPECT_TRUE(Verifier.match(To, Matcher));
1239 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1240}
1241
1242TEST_P(ASTImporterTestBase, DISABLED_IDNSOfNonmemberOperator) {
1243 Decl *FromTU = getTuDecl(
1244 R"(
1245 struct X {};
1246 void operator<<(int, X);
1247 )",
1248 Lang_CXX);
1249 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1250 const Decl *To = Import(From, Lang_CXX);
1251 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1252}
1253
1254TEST_P(ASTImporterTestBase,
1255 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1256 Decl *From, *To;
1257 std::tie(From, To) = getImportedDecl(
1258 R"(
1259 template<class T>
1260 class Base { int a; };
1261 class declToImport : Base<declToImport> {};
1262 )",
1263 Lang_CXX, "", Lang_CXX);
1264
1265 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1266 hasName("Base"),
1267 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1268 ASSERT_TRUE(
1269 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1270 EXPECT_TRUE(
1271 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1272}
1273
1274INSTANTIATE_TEST_CASE_P(
1275 ParameterizedTests, ASTImporterTestBase,
1276 ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),);
1277
1278struct ImportFunctions : ASTImporterTestBase {};
1279
1280TEST_P(ImportFunctions,
1281 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
1282 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
1283 auto Pattern = functionDecl(hasName("f"));
1284 FunctionDecl *FromD =
1285 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1286
1287 Decl *ImportedD = Import(FromD, Lang_CXX);
1288 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1289
1290 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1291 EXPECT_TRUE(!cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1292}
1293
1294TEST_P(ImportFunctions,
1295 PrototypeShouldBeImportedAsDefintionWhenThereIsADefinition) {
1296 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1297 auto Pattern = functionDecl(hasName("f"));
1298 FunctionDecl *FromD = // Prototype
1299 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1300
1301 Decl *ImportedD = Import(FromD, Lang_CXX);
1302 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1303
1304 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1305 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1306}
1307
1308TEST_P(ImportFunctions,
1309 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1310 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1311 auto Pattern = functionDecl(hasName("f"));
1312 FunctionDecl *FromD = // Definition
1313 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1314
1315 Decl *ImportedD = Import(FromD, Lang_CXX);
1316 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1317
1318 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1319 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1320}
1321
1322TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1323 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1324 auto Pattern = functionDecl(hasName("f"));
1325 FunctionDecl *FromD =
1326 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1327
1328 Decl *ImportedD = Import(FromD, Lang_CXX);
1329 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1330
1331 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1332 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1333}
1334
1335TEST_P(ImportFunctions, DISABLED_ImportPrototypeOfRecursiveFunction) {
1336 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1337 auto Pattern = functionDecl(hasName("f"));
1338 FunctionDecl *PrototypeFD =
1339 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1340
1341 Decl *ImportedD = Import(PrototypeFD, Lang_CXX);
1342 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1343
1344 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1345 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1346}
1347
1348TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1349 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1350 auto Pattern = functionDecl(hasName("f"));
1351 FunctionDecl *DefinitionFD =
1352 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1353
1354 Decl *ImportedD = Import(DefinitionFD, Lang_CXX);
1355 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1356
1357 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1358 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1359}
1360
1361TEST_P(ImportFunctions, ImportPrototypes) {
1362 auto Pattern = functionDecl(hasName("f"));
1363
1364 Decl *ImportedD;
1365 {
1366 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1367 FunctionDecl *FromD =
1368 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1369
1370 ImportedD = Import(FromD, Lang_CXX);
1371 }
1372 Decl *ImportedD1;
1373 {
1374 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
1375 FunctionDecl *FromD =
1376 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1377 ImportedD1 = Import(FromD, Lang_CXX);
1378 }
1379
1380 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1381 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1382 EXPECT_EQ(ImportedD, ImportedD1);
1383 EXPECT_TRUE(!cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1384}
1385
1386TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
1387 auto Pattern = functionDecl(hasName("f"));
1388
1389 Decl *ImportedD;
1390 {
1391 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
1392 FunctionDecl *FromD =
1393 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1394
1395 ImportedD = Import(FromD, Lang_CXX);
1396 }
1397 Decl *ImportedD1;
1398 {
1399 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
1400 FunctionDecl *FromD =
1401 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1402 ImportedD1 = Import(FromD, Lang_CXX);
1403 }
1404
1405 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1406 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1407 EXPECT_EQ(ImportedD, ImportedD1);
1408 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1409}
1410
1411TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
1412 auto Pattern = functionDecl(hasName("f"));
1413
1414 {
1415 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1416 FunctionDecl *FromD =
1417 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1418
1419 Import(FromD, Lang_CXX);
1420 }
1421 {
1422 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
1423 FunctionDecl *FromD =
1424 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1425 Import(FromD, Lang_CXX);
1426 }
1427
1428 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1429 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1430 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1431 EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody());
1432 FunctionDecl *DefinitionD =
1433 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1434 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
1435 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
1436}
1437
1438TEST_P(ImportFunctions, DISABLED_ImportPrototypeThenProtoAndDefinition) {
1439 auto Pattern = functionDecl(hasName("f"));
1440
1441 {
1442 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1443 FunctionDecl *FromD =
1444 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1445
1446 Import(FromD, Lang_CXX);
1447 }
1448 {
1449 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
1450 FunctionDecl *FromD =
1451 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1452 Import(FromD, Lang_CXX);
1453 }
1454
1455 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1456 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1457 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1458 EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody());
1459 FunctionDecl *DefinitionD =
1460 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1461 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
1462 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
1463}
1464
1465TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
1466 auto Code =
1467 R"(
1468 struct B { virtual void f(); };
1469 void B::f() {}
1470 struct D : B { void f(); };
1471 )";
1472 auto Pattern =
1473 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
1474 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1475 CXXMethodDecl *Proto =
1476 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1477
1478 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
1479 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1480 EXPECT_EQ(To->size_overridden_methods(), 1u);
1481}
1482
1483TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
1484 auto Code =
1485 R"(
1486 struct B { virtual void f(); };
1487 void B::f() {}
1488 )";
1489 auto Pattern =
1490 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1491 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1492 CXXMethodDecl *Proto =
1493 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1494 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1495
1496 ASSERT_TRUE(Proto->isVirtual());
1497 ASSERT_TRUE(Def->isVirtual());
1498 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1499 EXPECT_TRUE(To->isVirtual());
1500}
1501
1502INSTANTIATE_TEST_CASE_P(
1503 ParameterizedTests, ImportFunctions,
1504 ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),);
1505
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00001506} // end namespace ast_matchers
1507} // end namespace clang