blob: c81b4b338b7bf8f22587b216277129f3abee044f [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"
Gabor Marton1f667532018-05-24 08:41:07 +000022#include "Language.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000023#include "gtest/gtest.h"
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000024#include "llvm/ADT/StringMap.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000025
26namespace clang {
27namespace ast_matchers {
28
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000029using internal::Matcher;
30using internal::BindableMatcher;
31using llvm::StringMap;
32
Peter Szecsidedda6f2018-03-30 22:03:29 +000033// Creates a virtual file and assigns that to the context of given AST. If the
34// file already exists then the file will not be created again as a duplicate.
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000035static void
36createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
37 std::unique_ptr<llvm::MemoryBuffer> &&Buffer) {
Peter Szecsidedda6f2018-03-30 22:03:29 +000038 assert(ToAST);
39 ASTContext &ToCtx = ToAST->getASTContext();
40 auto *OFS = static_cast<vfs::OverlayFileSystem *>(
41 ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
42 auto *MFS =
43 static_cast<vfs::InMemoryFileSystem *>(OFS->overlays_begin()->get());
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000044 MFS->addFile(FileName, 0, std::move(Buffer));
Peter Szecsidedda6f2018-03-30 22:03:29 +000045}
46
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000047static void createVirtualFileIfNeeded(ASTUnit *ToAST, StringRef FileName,
48 StringRef Code) {
49 return createVirtualFileIfNeeded(ToAST, FileName,
50 llvm::MemoryBuffer::getMemBuffer(Code));
51}
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000052
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000053template <typename NodeType>
54NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer,
55 NodeType Node) {
56 ASTContext &ToCtx = To->getASTContext();
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000057
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000058 // Add 'From' file to virtual file system so importer can 'find' it
59 // while importing SourceLocations. It is safe to add same file multiple
60 // times - it just isn't replaced.
61 StringRef FromFileName = From->getMainFileName();
62 createVirtualFileIfNeeded(To, FromFileName,
63 From->getBufferForFile(FromFileName));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000064
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000065 auto Imported = Importer.Import(Node);
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000066
67 // This should dump source locations and assert if some source locations
Aleksei Sidorine45ab562017-12-21 17:41:06 +000068 // were not imported.
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000069 SmallString<1024> ImportChecker;
70 llvm::raw_svector_ostream ToNothing(ImportChecker);
71 ToCtx.getTranslationUnitDecl()->print(ToNothing);
72
Gabor Horvath480892b2017-10-18 09:25:18 +000073 // This traverses the AST to catch certain bugs like poorly or not
74 // implemented subtrees.
75 Imported->dump(ToNothing);
76
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000077 return Imported;
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000078}
79
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000080const StringRef DeclToImportID = "declToImport";
81const StringRef DeclToVerifyID = "declToVerify";
82
83template <typename NodeType>
84testing::AssertionResult
85testImport(const std::string &FromCode, const ArgVector &FromArgs,
86 const std::string &ToCode, const ArgVector &ToArgs,
87 MatchVerifier<NodeType> &Verifier,
88 const BindableMatcher<NodeType> &SearchMatcher,
89 const BindableMatcher<NodeType> &VerificationMatcher) {
90 const char *const InputFileName = "input.cc";
91 const char *const OutputFileName = "output.cc";
92
93 std::unique_ptr<ASTUnit>
94 FromAST = tooling::buildASTFromCodeWithArgs(
95 FromCode, FromArgs, InputFileName),
96 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
97
98 ASTContext &FromCtx = FromAST->getASTContext(),
99 &ToCtx = ToAST->getASTContext();
100
Adam Baloghe4192a82018-06-15 06:45:39 +0000101 FromAST->enableSourceFileDiagnostics();
102 ToAST->enableSourceFileDiagnostics();
103
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000104 ASTImporter Importer(ToCtx, ToAST->getFileManager(),
105 FromCtx, FromAST->getFileManager(), false);
106
107 auto FoundNodes = match(SearchMatcher, FromCtx);
108 if (FoundNodes.size() != 1)
109 return testing::AssertionFailure()
110 << "Multiple potential nodes were found!";
111
112 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
113 if (!ToImport)
114 return testing::AssertionFailure() << "Node type mismatch!";
115
116 // Sanity check: the node being imported should match in the same way as
117 // the result node.
118 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
119 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
120
121 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
122 if (!Imported)
123 return testing::AssertionFailure() << "Import failed, nullptr returned!";
124
125 return Verifier.match(Imported, WrapperMatcher);
126}
127
128template <typename NodeType>
129testing::AssertionResult
130testImport(const std::string &FromCode, const ArgVector &FromArgs,
131 const std::string &ToCode, const ArgVector &ToArgs,
132 MatchVerifier<NodeType> &Verifier,
133 const BindableMatcher<NodeType> &VerificationMatcher) {
134 return testImport(
135 FromCode, FromArgs, ToCode, ToArgs, Verifier,
136 translationUnitDecl(
137 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
138 VerificationMatcher);
139}
140
141/// Test how AST node named "declToImport" located in the translation unit
142/// of "FromCode" virtual file is imported to "ToCode" virtual file.
143/// The verification is done by running AMatcher over the imported node.
144template <typename NodeType, typename MatcherType>
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000145void testImport(const std::string &FromCode, Language FromLang,
146 const std::string &ToCode, Language ToLang,
147 MatchVerifier<NodeType> &Verifier,
148 const MatcherType &AMatcher) {
149 auto RunOptsFrom = getRunOptionsForLanguage(FromLang);
150 auto RunOptsTo = getRunOptionsForLanguage(ToLang);
151 for (const auto &FromArgs : RunOptsFrom)
152 for (const auto &ToArgs : RunOptsTo)
153 EXPECT_TRUE(testImport(FromCode, FromArgs, ToCode, ToArgs,
154 Verifier, AMatcher));
155}
156
Peter Szecsidedda6f2018-03-30 22:03:29 +0000157// This class provides generic methods to write tests which can check internal
158// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
159// this fixture makes it possible to import from several "From" contexts.
160class ASTImporterTestBase : public ::testing::TestWithParam<ArgVector> {
161
162 const char *const InputFileName = "input.cc";
163 const char *const OutputFileName = "output.cc";
164
165 // Buffer for the To context, must live in the test scope.
166 std::string ToCode;
167
168 struct TU {
169 // Buffer for the context, must live in the test scope.
Aleksei Sidorin54d6af52018-05-14 16:12:31 +0000170 std::string Code;
171 std::string FileName;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000172 std::unique_ptr<ASTUnit> Unit;
173 TranslationUnitDecl *TUDecl = nullptr;
174 TU(StringRef Code, StringRef FileName, ArgVector Args)
175 : Code(Code), FileName(FileName),
176 Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
177 this->FileName)),
Adam Baloghe4192a82018-06-15 06:45:39 +0000178 TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
179 Unit->enableSourceFileDiagnostics();
180 }
Peter Szecsidedda6f2018-03-30 22:03:29 +0000181 };
182
183 // We may have several From contexts and related translation units. In each
184 // AST, the buffers for the source are handled via references and are set
185 // during the creation of the AST. These references must point to a valid
186 // buffer until the AST is alive. Thus, we must use a list in order to avoid
187 // moving of the stored objects because that would mean breaking the
188 // references in the AST. By using a vector a move could happen when the
189 // vector is expanding, with the list we won't have these issues.
190 std::list<TU> FromTUs;
191
192public:
193 // We may have several From context but only one To context.
194 std::unique_ptr<ASTUnit> ToAST;
195
196 // Returns the argument vector used for a specific language, this set
197 // can be tweaked by the test parameters.
198 ArgVector getArgVectorForLanguage(Language Lang) {
199 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
200 ArgVector ExtraArgs = GetParam();
201 for (const auto& Arg : ExtraArgs) {
202 Args.push_back(Arg);
203 }
204 return Args;
205 }
206
207 // Creates an AST both for the From and To source code and imports the Decl
208 // of the identifier into the To context.
209 // Must not be called more than once within the same test.
210 std::tuple<Decl *, Decl *>
211 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
212 Language ToLang, StringRef Identifier = DeclToImportID) {
213 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
214 ToArgs = getArgVectorForLanguage(ToLang);
215
216 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
217 TU &FromTU = FromTUs.back();
218
219 ToCode = ToSrcCode;
220 assert(!ToAST);
221 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
Adam Baloghe4192a82018-06-15 06:45:39 +0000222 ToAST->enableSourceFileDiagnostics();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000223
224 ASTContext &FromCtx = FromTU.Unit->getASTContext(),
225 &ToCtx = ToAST->getASTContext();
226
227 createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
228
229 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
230 FromTU.Unit->getFileManager(), false);
231
232 IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
233 assert(ImportedII && "Declaration with the given identifier "
234 "should be specified in test!");
235 DeclarationName ImportDeclName(ImportedII);
236 SmallVector<NamedDecl *, 4> FoundDecls;
237 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
238 FoundDecls);
239
240 assert(FoundDecls.size() == 1);
241
242 Decl *Imported = Importer.Import(FoundDecls.front());
243 assert(Imported);
244 return std::make_tuple(*FoundDecls.begin(), Imported);
245 }
246
Gabor Marton9581c332018-05-23 13:53:36 +0000247 // Creates a TU decl for the given source code which can be used as a From
248 // context. May be called several times in a given test (with different file
249 // name).
Peter Szecsidedda6f2018-03-30 22:03:29 +0000250 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
251 StringRef FileName = "input.cc") {
252 assert(
253 std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) {
254 return E.FileName == FileName;
255 }) == FromTUs.end());
256
257 ArgVector Args = getArgVectorForLanguage(Lang);
258 FromTUs.emplace_back(SrcCode, FileName, Args);
259 TU &Tu = FromTUs.back();
260
261 return Tu.TUDecl;
262 }
263
Gabor Marton9581c332018-05-23 13:53:36 +0000264 // Creates the To context with the given source code and returns the TU decl.
265 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
266 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
267 ToCode = ToSrcCode;
268 assert(!ToAST);
269 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
Adam Baloghe4192a82018-06-15 06:45:39 +0000270 ToAST->enableSourceFileDiagnostics();
Gabor Marton9581c332018-05-23 13:53:36 +0000271
272 return ToAST->getASTContext().getTranslationUnitDecl();
273 }
274
Peter Szecsidedda6f2018-03-30 22:03:29 +0000275 // Import the given Decl into the ToCtx.
276 // May be called several times in a given test.
277 // The different instances of the param From may have different ASTContext.
278 Decl *Import(Decl *From, Language ToLang) {
279 if (!ToAST) {
280 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
281 // Build the AST from an empty file.
282 ToAST =
283 tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
Adam Baloghe4192a82018-06-15 06:45:39 +0000284 ToAST->enableSourceFileDiagnostics();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000285 }
286
287 // Create a virtual file in the To Ctx which corresponds to the file from
288 // which we want to import the `From` Decl. Without this source locations
289 // will be invalid in the ToCtx.
290 auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) {
291 return E.TUDecl == From->getTranslationUnitDecl();
292 });
293 assert(It != FromTUs.end());
294 createVirtualFileIfNeeded(ToAST.get(), It->FileName, It->Code);
295
296 ASTContext &FromCtx = From->getASTContext(),
297 &ToCtx = ToAST->getASTContext();
298 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
299 FromCtx.getSourceManager().getFileManager(), false);
300 return Importer.Import(From);
301 }
302
303 ~ASTImporterTestBase() {
304 if (!::testing::Test::HasFailure()) return;
305
306 for (auto &Tu : FromTUs) {
307 assert(Tu.Unit);
308 llvm::errs() << "FromAST:\n";
309 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
310 llvm::errs() << "\n";
311 }
312 if (ToAST) {
313 llvm::errs() << "ToAST:\n";
314 ToAST->getASTContext().getTranslationUnitDecl()->dump();
315 }
316 }
317};
318
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000319
320struct ImportAction {
321 StringRef FromFilename;
322 StringRef ToFilename;
323 // FIXME: Generalize this to support other node kinds.
324 BindableMatcher<Decl> ImportPredicate;
325
326 ImportAction(StringRef FromFilename, StringRef ToFilename,
327 DeclarationMatcher ImportPredicate)
328 : FromFilename(FromFilename), ToFilename(ToFilename),
329 ImportPredicate(ImportPredicate) {}
330
331 ImportAction(StringRef FromFilename, StringRef ToFilename,
332 const std::string &DeclName)
333 : FromFilename(FromFilename), ToFilename(ToFilename),
334 ImportPredicate(namedDecl(hasName(DeclName))) {}
335};
336
337using SingleASTUnitForAllOpts = std::vector<std::unique_ptr<ASTUnit>>;
338using AllASTUnitsForAllOpts = StringMap<SingleASTUnitForAllOpts>;
339
340struct CodeEntry {
341 std::string CodeSample;
342 Language Lang;
343
344 /// Builds N copies of ASTUnits for each potential compile options set
345 /// for further import actions. N is equal to size of this option set.
346 SingleASTUnitForAllOpts createASTUnits(StringRef FileName) const {
347 auto RunOpts = getRunOptionsForLanguage(Lang);
348 size_t NumOpts = RunOpts.size();
349 SingleASTUnitForAllOpts ResultASTs(NumOpts);
350 for (size_t CompileOpt = 0; CompileOpt < NumOpts; ++CompileOpt) {
351 auto AST = tooling::buildASTFromCodeWithArgs(
352 CodeSample, RunOpts[CompileOpt], FileName);
353 EXPECT_TRUE(AST.get());
354 ResultASTs[CompileOpt] = std::move(AST);
355 }
356 return ResultASTs;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000357 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000358};
359
360using CodeFiles = StringMap<CodeEntry>;
361
362/// Test an arbitrary sequence of imports for a set of given in-memory files.
363/// The verification is done by running VerificationMatcher against a specified
364/// AST node inside of one of given files.
365/// \param CodeSamples Map whose key is the file name and the value is the file
366/// content.
367/// \param ImportActions Sequence of imports. Each import in sequence
368/// specifies "from file" and "to file" and a matcher that is used for
369/// searching a declaration for import in "from file".
370/// \param FileForFinalCheck Name of virtual file for which the final check is
371/// applied.
372/// \param FinalSelectPredicate Matcher that specifies the AST node in the
373/// FileForFinalCheck for which the verification will be done.
374/// \param VerificationMatcher Matcher that will be used for verification after
375/// all imports in sequence are done.
376void testImportSequence(const CodeFiles &CodeSamples,
377 const std::vector<ImportAction> &ImportActions,
378 StringRef FileForFinalCheck,
379 BindableMatcher<Decl> FinalSelectPredicate,
380 BindableMatcher<Decl> VerificationMatcher) {
381 AllASTUnitsForAllOpts AllASTUnits;
382 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
383 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
384
385 auto GenASTsIfNeeded = [&AllASTUnits, &CodeSamples](StringRef Filename) {
386 if (!AllASTUnits.count(Filename)) {
387 auto Found = CodeSamples.find(Filename);
388 assert(Found != CodeSamples.end() && "Wrong file for import!");
389 AllASTUnits[Filename] = Found->getValue().createASTUnits(Filename);
390 }
391 };
392
393 size_t NumCompileOpts = 0;
394 for (const ImportAction &Action : ImportActions) {
395 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
396 GenASTsIfNeeded(FromFile);
397 GenASTsIfNeeded(ToFile);
398 NumCompileOpts = AllASTUnits[FromFile].size();
399
400 for (size_t CompileOpt = 0; CompileOpt < NumCompileOpts; ++CompileOpt) {
401 ASTUnit *From = AllASTUnits[FromFile][CompileOpt].get();
402 ASTUnit *To = AllASTUnits[ToFile][CompileOpt].get();
403
404 // Create a new importer if needed.
405 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
406 if (!ImporterRef)
407 ImporterRef.reset(new ASTImporter(
408 To->getASTContext(), To->getFileManager(), From->getASTContext(),
409 From->getFileManager(), false));
410
411 // Find the declaration and import it.
412 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
413 From->getASTContext());
414 EXPECT_TRUE(FoundDecl.size() == 1);
415 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
416 auto Imported = importNode(From, To, *ImporterRef, ToImport);
417 EXPECT_TRUE(Imported);
418 }
419 }
420
421 // NOTE: We don't do cross-option import check here due to fast growth of
422 // potential option sets.
423 for (size_t CompileOpt = 0; CompileOpt < NumCompileOpts; ++CompileOpt) {
424 // Find the declaration and import it.
425 auto FoundDecl =
426 match(FinalSelectPredicate.bind(DeclToVerifyID),
427 AllASTUnits[FileForFinalCheck][CompileOpt]->getASTContext());
428 EXPECT_TRUE(FoundDecl.size() == 1);
429 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
430 MatchVerifier<Decl> Verifier;
431 EXPECT_TRUE(Verifier.match(ToVerify,
432 BindableMatcher<Decl>(VerificationMatcher)));
433 }
Peter Szecsidedda6f2018-03-30 22:03:29 +0000434}
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000435
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000436TEST(ImportExpr, ImportStringLiteral) {
437 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000438 testImport("void declToImport() { \"foo\"; }",
439 Lang_CXX, "", Lang_CXX, Verifier,
440 functionDecl(
441 hasBody(
442 compoundStmt(
443 has(
444 stringLiteral(
445 hasType(
446 asString("const char [4]"))))))));
447 testImport("void declToImport() { L\"foo\"; }",
448 Lang_CXX, "", Lang_CXX, Verifier,
449 functionDecl(
450 hasBody(
451 compoundStmt(
452 has(
453 stringLiteral(
454 hasType(
455 asString("const wchar_t [4]"))))))));
456 testImport("void declToImport() { \"foo\" \"bar\"; }",
457 Lang_CXX, "", Lang_CXX, Verifier,
458 functionDecl(
459 hasBody(
460 compoundStmt(
461 has(
462 stringLiteral(
463 hasType(
464 asString("const char [7]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000465}
466
467TEST(ImportExpr, ImportGNUNullExpr) {
468 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000469 testImport("void declToImport() { __null; }",
470 Lang_CXX, "", Lang_CXX, Verifier,
471 functionDecl(
472 hasBody(
473 compoundStmt(
474 has(
475 gnuNullExpr(
476 hasType(isInteger())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000477}
478
479TEST(ImportExpr, ImportCXXNullPtrLiteralExpr) {
480 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000481 testImport("void declToImport() { nullptr; }",
482 Lang_CXX11, "", Lang_CXX11, Verifier,
483 functionDecl(
484 hasBody(
485 compoundStmt(
486 has(
487 cxxNullPtrLiteralExpr())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000488}
489
490
491TEST(ImportExpr, ImportFloatinglLiteralExpr) {
492 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000493 testImport("void declToImport() { 1.0; }",
494 Lang_C, "", Lang_C, Verifier,
495 functionDecl(
496 hasBody(
497 compoundStmt(
498 has(
499 floatLiteral(
500 equals(1.0),
501 hasType(asString("double"))))))));
502 testImport("void declToImport() { 1.0e-5f; }",
503 Lang_C, "", Lang_C, Verifier,
504 functionDecl(
505 hasBody(
506 compoundStmt(
507 has(
508 floatLiteral(
509 equals(1.0e-5f),
510 hasType(asString("float"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000511}
512
513TEST(ImportExpr, ImportCompoundLiteralExpr) {
514 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000515 testImport("void declToImport() {"
516 " struct s { int x; long y; unsigned z; }; "
517 " (struct s){ 42, 0L, 1U }; }",
518 Lang_CXX, "", Lang_CXX, Verifier,
519 functionDecl(
520 hasBody(
521 compoundStmt(
522 has(
523 compoundLiteralExpr(
524 hasType(asString("struct s")),
525 has(initListExpr(
526 hasType(asString("struct s")),
527 has(integerLiteral(
528 equals(42), hasType(asString("int")))),
529 has(integerLiteral(
530 equals(0), hasType(asString("long")))),
531 has(integerLiteral(
532 equals(1),
533 hasType(asString("unsigned int"))))
534 ))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000535}
536
537TEST(ImportExpr, ImportCXXThisExpr) {
538 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000539 testImport("class declToImport { void f() { this; } };",
540 Lang_CXX, "", Lang_CXX, Verifier,
541 cxxRecordDecl(
542 hasMethod(
543 hasBody(
544 compoundStmt(
545 has(
546 cxxThisExpr(
547 hasType(
548 asString("class declToImport *")))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000549}
550
551TEST(ImportExpr, ImportAtomicExpr) {
552 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000553 testImport("void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
554 Lang_C, "", Lang_C, Verifier,
555 functionDecl(hasBody(compoundStmt(has(atomicExpr(
556 has(ignoringParenImpCasts(
557 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
558 hasType(asString("int *"))))),
559 has(integerLiteral(equals(1), hasType(asString("int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000560}
561
562TEST(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
563 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000564 testImport(
565 "void declToImport() { loop: goto loop; &&loop; }", Lang_C, "", Lang_C,
566 Verifier,
567 functionDecl(hasBody(compoundStmt(
568 has(labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
569 has(addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000570}
571
572AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
573 internal::Matcher<NamedDecl>, InnerMatcher) {
574 const NamedDecl *Template = Node.getTemplatedDecl();
575 return Template && InnerMatcher.matches(*Template, Finder, Builder);
576}
577
578TEST(ImportExpr, ImportParenListExpr) {
579 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000580 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000581 "template<typename T> class dummy { void f() { dummy X(*this); } };"
582 "typedef dummy<int> declToImport;"
583 "template class dummy<int>;",
584 Lang_CXX, "", Lang_CXX, Verifier,
585 typedefDecl(hasType(templateSpecializationType(
586 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
587 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
588 hasName("f"),
589 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
590 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
591 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000592 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000593}
594
Gabor Horvath480892b2017-10-18 09:25:18 +0000595TEST(ImportExpr, ImportSwitch) {
596 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000597 testImport("void declToImport() { int b; switch (b) { case 1: break; } }",
598 Lang_C, "", Lang_C, Verifier,
599 functionDecl(hasBody(compoundStmt(
600 has(switchStmt(has(compoundStmt(has(caseStmt())))))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000601}
602
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000603TEST(ImportExpr, ImportStmtExpr) {
604 MatchVerifier<Decl> Verifier;
605 // NOTE: has() ignores implicit casts, using hasDescendant() to match it
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000606 testImport(
607 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
608 Lang_C, "", Lang_C, Verifier,
609 functionDecl(
610 hasBody(
611 compoundStmt(
612 has(
613 declStmt(
614 hasSingleDecl(
615 varDecl(
616 hasName("C"),
617 hasType(asString("int")),
618 hasInitializer(
619 stmtExpr(
620 hasAnySubstatement(
621 declStmt(
622 hasSingleDecl(
623 varDecl(
624 hasName("X"),
625 hasType(asString("int")),
626 hasInitializer(
627 integerLiteral(equals(4))))))),
628 hasDescendant(
629 implicitCastExpr()
630 )))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000631}
632
633TEST(ImportExpr, ImportConditionalOperator) {
634 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000635 testImport(
636 "void declToImport() { true ? 1 : -5; }",
637 Lang_CXX, "", Lang_CXX, Verifier,
638 functionDecl(
639 hasBody(
640 compoundStmt(
641 has(
642 conditionalOperator(
643 hasCondition(cxxBoolLiteral(equals(true))),
644 hasTrueExpression(integerLiteral(equals(1))),
645 hasFalseExpression(
646 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))
647 )))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000648}
649
650TEST(ImportExpr, ImportBinaryConditionalOperator) {
651 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000652 testImport(
653 "void declToImport() { 1 ?: -5; }", Lang_CXX, "", Lang_CXX, Verifier,
654 functionDecl(
655 hasBody(
656 compoundStmt(
657 has(
658 binaryConditionalOperator(
659 hasCondition(
660 implicitCastExpr(
661 hasSourceExpression(
662 opaqueValueExpr(
663 hasSourceExpression(integerLiteral(equals(1))))),
664 hasType(booleanType()))),
665 hasTrueExpression(
666 opaqueValueExpr(hasSourceExpression(
667 integerLiteral(equals(1))))),
668 hasFalseExpression(
669 unaryOperator(hasOperatorName("-"),
670 hasUnaryOperand(integerLiteral(equals(5)))))
671 ))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000672}
673
674TEST(ImportExpr, ImportDesignatedInitExpr) {
675 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000676 testImport("void declToImport() {"
677 " struct point { double x; double y; };"
678 " struct point ptarray[10] = "
679 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
680 Lang_C, "", Lang_C, Verifier,
681 functionDecl(
682 hasBody(
683 compoundStmt(
684 has(
685 declStmt(
686 hasSingleDecl(
687 varDecl(
688 hasInitializer(
689 initListExpr(
690 hasSyntacticForm(
691 initListExpr(
692 has(
693 designatedInitExpr(
694 designatorCountIs(2),
695 has(floatLiteral(
696 equals(1.0))),
697 has(integerLiteral(
698 equals(2))))),
699 has(
700 designatedInitExpr(
701 designatorCountIs(2),
702 has(floatLiteral(
703 equals(2.0))),
704 has(integerLiteral(
705 equals(2))))),
706 has(
707 designatedInitExpr(
708 designatorCountIs(2),
709 has(floatLiteral(
710 equals(1.0))),
711 has(integerLiteral(
712 equals(0)))))
713 ))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000714}
715
716
717TEST(ImportExpr, ImportPredefinedExpr) {
718 MatchVerifier<Decl> Verifier;
719 // __func__ expands as StringLiteral("declToImport")
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000720 testImport("void declToImport() { __func__; }",
721 Lang_CXX, "", Lang_CXX, Verifier,
722 functionDecl(
723 hasBody(
724 compoundStmt(
725 has(
726 predefinedExpr(
727 hasType(
728 asString("const char [13]")),
729 has(
730 stringLiteral(
731 hasType(
732 asString("const char [13]"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000733}
734
735TEST(ImportExpr, ImportInitListExpr) {
736 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000737 testImport(
738 "void declToImport() {"
739 " struct point { double x; double y; };"
740 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
741 " [0].x = 1.0 }; }",
742 Lang_CXX, "", Lang_CXX, Verifier,
743 functionDecl(
744 hasBody(
745 compoundStmt(
746 has(
747 declStmt(
748 hasSingleDecl(
749 varDecl(
750 hasInitializer(
751 initListExpr(
752 has(
753 cxxConstructExpr(
754 requiresZeroInitialization())),
755 has(
756 initListExpr(
757 hasType(asString("struct point")),
758 has(floatLiteral(equals(1.0))),
759 has(implicitValueInitExpr(
760 hasType(asString("double")))))),
761 has(
762 initListExpr(
763 hasType(asString("struct point")),
764 has(floatLiteral(equals(2.0))),
765 has(floatLiteral(equals(1.0)))))
766 ))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000767}
768
769
Aleksei Sidorina693b372016-09-28 10:16:56 +0000770const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
771
772TEST(ImportExpr, ImportVAArgExpr) {
773 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000774 testImport("void declToImport(__builtin_va_list list, ...) {"
775 " (void)__builtin_va_arg(list, int); }",
776 Lang_CXX, "", Lang_CXX, Verifier,
777 functionDecl(
778 hasBody(
779 compoundStmt(
780 has(
781 cStyleCastExpr(
782 hasSourceExpression(
783 vaArgExpr())))))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000784}
785
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000786TEST(ImportExpr, CXXTemporaryObjectExpr) {
787 MatchVerifier<Decl> Verifier;
788 testImport("struct C {};"
789 "void declToImport() { C c = C(); }",
790 Lang_CXX, "", Lang_CXX, Verifier,
791 functionDecl(hasBody(compoundStmt(has(
792 declStmt(has(varDecl(has(exprWithCleanups(has(cxxConstructExpr(
793 has(materializeTemporaryExpr(has(implicitCastExpr(
794 has(cxxTemporaryObjectExpr())))))))))))))))));
795}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000796
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000797TEST(ImportType, ImportAtomicType) {
798 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000799 testImport("void declToImport() { typedef _Atomic(int) a_int; }",
800 Lang_CXX11, "", Lang_CXX11, Verifier,
801 functionDecl(
802 hasBody(
803 compoundStmt(
804 has(
805 declStmt(
806 has(
807 typedefDecl(
808 has(atomicType())))))))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000809}
810
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000811TEST(ImportDecl, ImportFunctionTemplateDecl) {
812 MatchVerifier<Decl> Verifier;
813 testImport("template <typename T> void declToImport() { };", Lang_CXX, "",
814 Lang_CXX, Verifier, functionTemplateDecl());
815}
816
817const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
818 cxxDependentScopeMemberExpr;
819
820TEST(ImportExpr, ImportCXXDependentScopeMemberExpr) {
821 MatchVerifier<Decl> Verifier;
822 testImport("template <typename T> struct C { T t; };"
823 "template <typename T> void declToImport() {"
824 " C<T> d;"
825 " d.t;"
826 "}"
827 "void instantiate() { declToImport<int>(); }",
828 Lang_CXX, "", Lang_CXX, Verifier,
829 functionTemplateDecl(has(functionDecl(
830 has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
831 testImport("template <typename T> struct C { T t; };"
832 "template <typename T> void declToImport() {"
833 " C<T> d;"
834 " (&d)->t;"
835 "}"
836 "void instantiate() { declToImport<int>(); }",
837 Lang_CXX, "", Lang_CXX, Verifier,
838 functionTemplateDecl(has(functionDecl(
839 has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
840}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000841
Gabor Horvath7a91c082017-11-14 11:30:38 +0000842TEST(ImportType, ImportTypeAliasTemplate) {
843 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000844 testImport(
845 "template <int K>"
846 "struct dummy { static const int i = K; };"
847 "template <int K> using dummy2 = dummy<K>;"
848 "int declToImport() { return dummy2<3>::i; }",
849 Lang_CXX11, "", Lang_CXX11, Verifier,
850 functionDecl(
851 hasBody(compoundStmt(
852 has(returnStmt(has(implicitCastExpr(has(declRefExpr()))))))),
853 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
854}
855
856const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
857 varTemplateSpecializationDecl;
858
859TEST(ImportDecl, ImportVarTemplate) {
860 MatchVerifier<Decl> Verifier;
861 testImport(
862 "template <typename T>"
863 "T pi = T(3.1415926535897932385L);"
864 "void declToImport() { pi<int>; }",
865 Lang_CXX11, "", Lang_CXX11, Verifier,
866 functionDecl(
867 hasBody(has(declRefExpr(to(varTemplateSpecializationDecl())))),
868 unless(hasAncestor(translationUnitDecl(has(varDecl(
869 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000870}
871
Gabor Horvath7a91c082017-11-14 11:30:38 +0000872TEST(ImportType, ImportPackExpansion) {
873 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000874 testImport("template <typename... Args>"
875 "struct dummy {"
876 " dummy(Args... args) {}"
877 " static const int i = 4;"
878 "};"
879 "int declToImport() { return dummy<int>::i; }",
880 Lang_CXX11, "", Lang_CXX11, Verifier,
881 functionDecl(
882 hasBody(
883 compoundStmt(
884 has(
885 returnStmt(
886 has(
887 implicitCastExpr(
888 has(
889 declRefExpr())))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000890}
891
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000892const internal::VariadicDynCastAllOfMatcher<Type,
893 DependentTemplateSpecializationType>
894 dependentTemplateSpecializationType;
895
896TEST(ImportType, ImportDependentTemplateSpecialization) {
897 MatchVerifier<Decl> Verifier;
898 testImport("template<typename T>"
899 "struct A;"
900 "template<typename T>"
901 "struct declToImport {"
902 " typename A<T>::template B<T> a;"
903 "};",
904 Lang_CXX, "", Lang_CXX, Verifier,
905 classTemplateDecl(has(cxxRecordDecl(has(
906 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
907}
908
909const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
910 sizeOfPackExpr;
911
912TEST(ImportExpr, ImportSizeOfPackExpr) {
913 MatchVerifier<Decl> Verifier;
914 testImport("template <typename... Ts>"
915 "void declToImport() {"
916 " const int i = sizeof...(Ts);"
917 "};"
918 "void g() { declToImport<int>(); }",
919 Lang_CXX11, "", Lang_CXX11, Verifier,
920 functionTemplateDecl(has(functionDecl(
921 hasBody(compoundStmt(has(declStmt(has(varDecl(hasInitializer(
922 implicitCastExpr(has(sizeOfPackExpr())))))))))))));
923 testImport(
924 "template <typename... Ts>"
925 "using X = int[sizeof...(Ts)];"
926 "template <typename... Us>"
927 "struct Y {"
928 " X<Us..., int, double, int, Us...> f;"
929 "};"
930 "Y<float, int> declToImport;",
931 Lang_CXX11, "", Lang_CXX11, Verifier,
932 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
933 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
934}
935
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000936/// \brief Matches __builtin_types_compatible_p:
937/// GNU extension to check equivalent types
938/// Given
939/// \code
940/// __builtin_types_compatible_p(int, int)
941/// \endcode
942// will generate TypeTraitExpr <...> 'int'
943const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
944
945TEST(ImportExpr, ImportTypeTraitExpr) {
946 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000947 testImport("void declToImport() { "
948 " __builtin_types_compatible_p(int, int);"
949 "}",
950 Lang_C, "", Lang_C, Verifier,
951 functionDecl(
952 hasBody(
953 compoundStmt(
954 has(
955 typeTraitExpr(hasType(asString("int"))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000956}
957
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000958const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
959
960TEST(ImportExpr, ImportCXXTypeidExpr) {
961 MatchVerifier<Decl> Verifier;
962 testImport(
963 "namespace std { class type_info {}; }"
964 "void declToImport() {"
965 " int x;"
966 " auto a = typeid(int); auto b = typeid(x);"
967 "}",
968 Lang_CXX11, "", Lang_CXX11, Verifier,
969 functionDecl(
970 hasDescendant(varDecl(
971 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
972 hasDescendant(varDecl(
973 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
974}
975
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000976TEST(ImportExpr, ImportTypeTraitExprValDep) {
977 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000978 testImport("template<typename T> struct declToImport {"
979 " void m() { __is_pod(T); }"
980 "};"
981 "void f() { declToImport<int>().m(); }",
982 Lang_CXX11, "", Lang_CXX11, Verifier,
983 classTemplateDecl(
984 has(
985 cxxRecordDecl(
986 has(
987 functionDecl(
988 hasBody(
989 compoundStmt(
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000990 has(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000991 typeTraitExpr(
992 hasType(booleanType())
993 ))))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000994}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000995
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000996const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
997 cxxPseudoDestructorExpr;
998
999TEST(ImportExpr, ImportCXXPseudoDestructorExpr) {
1000 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001001 testImport("typedef int T;"
1002 "void declToImport(int *p) {"
1003 " T t;"
1004 " p->T::~T();"
1005 "}",
1006 Lang_CXX, "", Lang_CXX, Verifier,
1007 functionDecl(has(compoundStmt(has(
1008 callExpr(has(cxxPseudoDestructorExpr())))))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001009}
1010
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001011TEST(ImportDecl, ImportUsingDecl) {
1012 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001013 testImport("namespace foo { int bar; }"
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001014 "void declToImport() { using foo::bar; }",
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001015 Lang_CXX, "", Lang_CXX, Verifier,
1016 functionDecl(
1017 has(
1018 compoundStmt(
1019 has(
1020 declStmt(
1021 has(
1022 usingDecl())))))));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001023}
1024
1025/// \brief Matches shadow declarations introduced into a scope by a
1026/// (resolved) using declaration.
1027///
1028/// Given
1029/// \code
1030/// namespace n { int f; }
1031/// namespace declToImport { using n::f; }
1032/// \endcode
1033/// usingShadowDecl()
1034/// matches \code f \endcode
1035const internal::VariadicDynCastAllOfMatcher<Decl,
1036 UsingShadowDecl> usingShadowDecl;
1037
1038TEST(ImportDecl, ImportUsingShadowDecl) {
1039 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001040 testImport("namespace foo { int bar; }"
1041 "namespace declToImport { using foo::bar; }",
1042 Lang_CXX, "", Lang_CXX, Verifier,
1043 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001044}
1045
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001046TEST(ImportExpr, ImportUnresolvedLookupExpr) {
1047 MatchVerifier<Decl> Verifier;
1048 testImport("template<typename T> int foo();"
1049 "template <typename T> void declToImport() {"
1050 " ::foo<T>;"
1051 " ::template foo<T>;"
1052 "}"
1053 "void instantiate() { declToImport<int>(); }",
1054 Lang_CXX, "", Lang_CXX, Verifier,
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001055 functionTemplateDecl(has(functionDecl(
1056 has(compoundStmt(has(unresolvedLookupExpr())))))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001057}
1058
1059TEST(ImportExpr, ImportCXXUnresolvedConstructExpr) {
1060 MatchVerifier<Decl> Verifier;
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001061 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001062 "template <typename T> void declToImport() {"
1063 " C<T> d;"
1064 " d.t = T();"
1065 "}"
1066 "void instantiate() { declToImport<int>(); }",
1067 Lang_CXX, "", Lang_CXX, Verifier,
1068 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
1069 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001070 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001071 "template <typename T> void declToImport() {"
1072 " C<T> d;"
1073 " (&d)->t = T();"
1074 "}"
1075 "void instantiate() { declToImport<int>(); }",
1076 Lang_CXX, "", Lang_CXX, Verifier,
1077 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
1078 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
1079}
1080
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001081/// Check that function "declToImport()" (which is the templated function
1082/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1083/// Same for class template declarations.
1084TEST(ImportDecl, ImportTemplatedDeclForTemplate) {
1085 MatchVerifier<Decl> Verifier;
1086 testImport("template <typename T> void declToImport() { T a = 1; }"
1087 "void instantiate() { declToImport<int>(); }",
1088 Lang_CXX, "", Lang_CXX, Verifier,
1089 functionTemplateDecl(hasAncestor(translationUnitDecl(
1090 unless(has(functionDecl(hasName("declToImport"))))))));
1091 testImport("template <typename T> struct declToImport { T t; };"
1092 "void instantiate() { declToImport<int>(); }",
1093 Lang_CXX, "", Lang_CXX, Verifier,
1094 classTemplateDecl(hasAncestor(translationUnitDecl(
1095 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
1096}
1097
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001098TEST(ImportExpr, CXXOperatorCallExpr) {
1099 MatchVerifier<Decl> Verifier;
1100 testImport("class declToImport {"
1101 " void f() { *this = declToImport(); }"
1102 "};",
1103 Lang_CXX, "", Lang_CXX, Verifier,
1104 cxxRecordDecl(has(cxxMethodDecl(hasBody(compoundStmt(
1105 has(exprWithCleanups(has(cxxOperatorCallExpr())))))))));
1106}
1107
1108TEST(ImportExpr, DependentSizedArrayType) {
1109 MatchVerifier<Decl> Verifier;
1110 testImport("template<typename T, int Size> class declToImport {"
1111 " T data[Size];"
1112 "};",
1113 Lang_CXX, "", Lang_CXX, Verifier,
1114 classTemplateDecl(has(cxxRecordDecl(
1115 has(fieldDecl(hasType(dependentSizedArrayType())))))));
1116}
1117
Gabor Martona0df7a92018-05-30 09:19:26 +00001118TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
1119 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1120 auto From =
1121 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1122 ASSERT_TRUE(From);
1123 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1124 ASSERT_TRUE(To);
1125 Decl *ToTemplated = To->getTemplatedDecl();
1126 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1127 EXPECT_TRUE(ToTemplated1);
1128 EXPECT_EQ(ToTemplated1, ToTemplated);
1129}
1130
1131TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
1132 auto Code =
1133 R"(
1134 namespace x {
1135 template<class X> struct S1{};
1136 template<class X> struct S2{};
1137 template<class X> struct S3{};
1138 }
1139 )";
1140 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1141 auto FromNs =
1142 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1143 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1144 ASSERT_TRUE(ToNs);
1145 auto From =
1146 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1147 classTemplateDecl(
1148 hasName("S2")));
1149 auto To =
1150 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1151 classTemplateDecl(
1152 hasName("S2")));
1153 ASSERT_TRUE(From);
1154 ASSERT_TRUE(To);
1155 auto ToTemplated = To->getTemplatedDecl();
1156 auto ToTemplated1 =
1157 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1158 EXPECT_TRUE(ToTemplated1);
1159 ASSERT_EQ(ToTemplated1, ToTemplated);
1160}
1161
Peter Szecsidedda6f2018-03-30 22:03:29 +00001162TEST_P(ASTImporterTestBase, DISABLED_ImportFunctionWithBackReferringParameter) {
1163 Decl *From, *To;
1164 std::tie(From, To) = getImportedDecl(
1165 R"(
1166 template <typename T> struct X {};
1167
1168 void declToImport(int y, X<int> &x) {}
1169
1170 template <> struct X<int> {
1171 void g() {
1172 X<int> x;
1173 declToImport(0, x);
1174 }
1175 };
1176 )",
1177 Lang_CXX, "", Lang_CXX);
1178
1179 MatchVerifier<Decl> Verifier;
1180 auto Matcher = functionDecl(hasName("declToImport"),
1181 parameterCountIs(2),
1182 hasParameter(0, hasName("y")),
1183 hasParameter(1, hasName("x")),
1184 hasParameter(1, hasType(asString("X<int> &"))));
1185 ASSERT_TRUE(Verifier.match(From, Matcher));
1186 EXPECT_TRUE(Verifier.match(To, Matcher));
1187}
1188
1189TEST_P(ASTImporterTestBase,
1190 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1191 Decl *From, *To;
1192 std::tie(From, To) =
1193 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1194 "void instantiate() { declToImport<int>(); }",
1195 Lang_CXX, "", Lang_CXX);
1196
1197 auto Check = [](Decl *D) -> bool {
1198 auto TU = D->getTranslationUnitDecl();
1199 for (auto Child : TU->decls()) {
1200 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1201 if (FD->getNameAsString() == "declToImport") {
1202 GTEST_NONFATAL_FAILURE_(
1203 "TU should not contain any FunctionDecl with name declToImport");
1204 return false;
1205 }
1206 }
1207 }
1208 return true;
1209 };
1210
1211 ASSERT_TRUE(Check(From));
1212 EXPECT_TRUE(Check(To));
1213}
1214
1215TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
1216 Decl *From, *To;
1217 std::tie(From, To) =
1218 getImportedDecl("template <typename T> struct declToImport { T t; };"
1219 "void instantiate() { declToImport<int>(); }",
1220 Lang_CXX, "", Lang_CXX);
1221
1222 auto Check = [](Decl *D) -> bool {
1223 auto TU = D->getTranslationUnitDecl();
1224 for (auto Child : TU->decls()) {
1225 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1226 if (RD->getNameAsString() == "declToImport") {
1227 GTEST_NONFATAL_FAILURE_(
1228 "TU should not contain any CXXRecordDecl with name declToImport");
1229 return false;
1230 }
1231 }
1232 }
1233 return true;
1234 };
1235
1236 ASSERT_TRUE(Check(From));
1237 EXPECT_TRUE(Check(To));
1238}
1239
1240TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
1241 Decl *From, *To;
1242 std::tie(From, To) =
1243 getImportedDecl(
1244 "template <typename T> struct X {};"
1245 "template <typename T> using declToImport = X<T>;"
1246 "void instantiate() { declToImport<int> a; }",
1247 Lang_CXX11, "", Lang_CXX11);
1248
1249 auto Check = [](Decl *D) -> bool {
1250 auto TU = D->getTranslationUnitDecl();
1251 for (auto Child : TU->decls()) {
1252 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1253 if (AD->getNameAsString() == "declToImport") {
1254 GTEST_NONFATAL_FAILURE_(
1255 "TU should not contain any TypeAliasDecl with name declToImport");
1256 return false;
1257 }
1258 }
1259 }
1260 return true;
1261 };
1262
1263 ASSERT_TRUE(Check(From));
1264 EXPECT_TRUE(Check(To));
1265}
1266
1267TEST_P(
1268 ASTImporterTestBase,
Gabor Martonb14056b2018-05-25 11:21:24 +00001269 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001270
1271 Decl *From, *To;
1272 std::tie(From, To) = getImportedDecl(
1273 R"(
1274 template<class T>
1275 class Base {};
1276 class declToImport : public Base<declToImport> {};
1277 )",
1278 Lang_CXX, "", Lang_CXX);
1279
1280 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1281 auto Pattern =
1282 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1283 ASSERT_TRUE(
1284 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1285 EXPECT_TRUE(
1286 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1287
1288 // Check that the ClassTemplateSpecializationDecl is the child of the
1289 // ClassTemplateDecl.
1290 Pattern = translationUnitDecl(has(classTemplateDecl(
1291 hasName("Base"), has(classTemplateSpecializationDecl()))));
1292 ASSERT_TRUE(
1293 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1294 EXPECT_TRUE(
1295 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1296}
1297
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001298AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1299 size_t Index = 0;
1300 for (FieldDecl *Field : Node.fields()) {
1301 if (Index == Order.size())
1302 return false;
1303 if (Field->getName() != Order[Index])
1304 return false;
1305 ++Index;
1306 }
1307 return Index == Order.size();
1308}
1309
Peter Szecsidedda6f2018-03-30 22:03:29 +00001310TEST_P(ASTImporterTestBase,
1311 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1312 Decl *From, *To;
1313 std::tie(From, To) = getImportedDecl(
1314 R"(
1315 namespace NS {
1316 template<class T>
1317 class X {};
1318 template class X<int>;
1319 }
1320 )",
1321 Lang_CXX, "", Lang_CXX, "NS");
1322
1323 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1324 // ClassTemplateDecl.
1325 auto Pattern = namespaceDecl(has(classTemplateDecl(
1326 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1327 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1328 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1329
1330 // Check that the ClassTemplateSpecializationDecl is the child of the
1331 // NamespaceDecl.
1332 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1333 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1334 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1335}
1336
1337TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1338 Decl *From, *To;
1339 std::tie(From, To) =
1340 getImportedDecl(
1341 "struct declToImport { int a; int b; };",
1342 Lang_CXX11, "", Lang_CXX11);
1343
1344 MatchVerifier<Decl> Verifier;
1345 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1346 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1347}
1348
1349TEST_P(ASTImporterTestBase,
1350 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1351 Decl *From, *To;
1352 std::tie(From, To) = getImportedDecl(
1353 // The original recursive algorithm of ASTImporter first imports 'c' then
1354 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1355 R"s(
1356 struct declToImport {
1357 int a = c + b;
1358 int b = 1;
1359 int c = 2;
1360 };
1361 )s",
1362 Lang_CXX11, "", Lang_CXX11);
1363
1364 MatchVerifier<Decl> Verifier;
1365 ASSERT_TRUE(
1366 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1367 EXPECT_TRUE(
1368 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1369}
1370
Gabor Martonde8bf262018-05-17 09:46:07 +00001371TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001372 Decl *From, *To;
1373 std::tie(From, To) = getImportedDecl(
1374 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001375 struct declToImport {
1376 };
1377 )",
1378 Lang_CXX, "", Lang_CXX);
1379
1380 MatchVerifier<Decl> Verifier;
1381 // Match the implicit Decl.
1382 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1383 ASSERT_TRUE(Verifier.match(From, Matcher));
1384 EXPECT_TRUE(Verifier.match(To, Matcher));
1385}
1386
1387TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1388 Decl *From, *To;
1389 std::tie(From, To) = getImportedDecl(
1390 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001391 template <typename U>
1392 struct declToImport {
1393 };
1394 )",
1395 Lang_CXX, "", Lang_CXX);
1396
1397 MatchVerifier<Decl> Verifier;
1398 // Match the implicit Decl.
1399 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1400 ASSERT_TRUE(Verifier.match(From, Matcher));
1401 EXPECT_TRUE(Verifier.match(To, Matcher));
1402}
1403
1404TEST_P(
1405 ASTImporterTestBase,
Gabor Martona3af5672018-05-23 14:24:02 +00001406 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001407 Decl *From, *To;
1408 std::tie(From, To) = getImportedDecl(
1409 R"(
1410 template<class T>
1411 class Base {};
1412 class declToImport : public Base<declToImport> {};
1413 )",
1414 Lang_CXX, "", Lang_CXX);
1415
1416 auto hasImplicitClass = has(cxxRecordDecl());
1417 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1418 hasName("Base"),
1419 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1420 ASSERT_TRUE(
1421 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1422 EXPECT_TRUE(
1423 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1424}
1425
1426TEST_P(ASTImporterTestBase, IDNSOrdinary) {
1427 Decl *From, *To;
1428 std::tie(From, To) =
1429 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1430
1431 MatchVerifier<Decl> Verifier;
1432 auto Matcher = functionDecl();
1433 ASSERT_TRUE(Verifier.match(From, Matcher));
1434 EXPECT_TRUE(Verifier.match(To, Matcher));
1435 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1436}
1437
Gabor Marton2ae9da32018-05-18 15:46:18 +00001438TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001439 Decl *FromTU = getTuDecl(
1440 R"(
1441 struct X {};
1442 void operator<<(int, X);
1443 )",
1444 Lang_CXX);
1445 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1446 const Decl *To = Import(From, Lang_CXX);
1447 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1448}
1449
1450TEST_P(ASTImporterTestBase,
1451 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1452 Decl *From, *To;
1453 std::tie(From, To) = getImportedDecl(
1454 R"(
1455 template<class T>
1456 class Base { int a; };
1457 class declToImport : Base<declToImport> {};
1458 )",
1459 Lang_CXX, "", Lang_CXX);
1460
1461 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1462 hasName("Base"),
1463 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1464 ASSERT_TRUE(
1465 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1466 EXPECT_TRUE(
1467 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1468}
1469
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001470TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
1471 {
1472 Decl *FromTU = getTuDecl(
1473 R"(
1474 template <typename T>
1475 struct B;
1476 )",
1477 Lang_CXX, "input0.cc");
1478 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1479 FromTU, classTemplateDecl(hasName("B")));
1480
1481 Import(FromD, Lang_CXX);
1482 }
1483
1484 {
1485 Decl *FromTU = getTuDecl(
1486 R"(
1487 template <typename T>
1488 struct B {
1489 void f();
1490 };
1491 )",
1492 Lang_CXX, "input1.cc");
1493 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1494 FromTU, functionDecl(hasName("f")));
1495 Import(FromD, Lang_CXX);
1496 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1497 FromTU, classTemplateDecl(hasName("B")));
1498 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1499 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1500 }
1501}
1502
Gabor Marton9581c332018-05-23 13:53:36 +00001503TEST_P(ASTImporterTestBase,
1504 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1505 Decl *ToTU = getToTuDecl(
1506 R"(
1507 template <typename T>
1508 struct B {
1509 void f();
1510 };
1511
1512 template <typename T>
1513 struct B;
1514 )",
1515 Lang_CXX);
1516 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1517 [](const ClassTemplateDecl *T) {
1518 return T->isThisDeclarationADefinition();
1519 })
1520 .match(ToTU, classTemplateDecl()));
1521
1522 Decl *FromTU = getTuDecl(
1523 R"(
1524 template <typename T>
1525 struct B {
1526 void f();
1527 };
1528 )",
1529 Lang_CXX, "input1.cc");
1530 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1531 FromTU, classTemplateDecl(hasName("B")));
1532
1533 Import(FromD, Lang_CXX);
1534
1535 // We should have only one definition.
1536 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1537 [](const ClassTemplateDecl *T) {
1538 return T->isThisDeclarationADefinition();
1539 })
1540 .match(ToTU, classTemplateDecl()));
1541}
1542
1543TEST_P(ASTImporterTestBase,
1544 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1545 Decl *ToTU = getToTuDecl(
1546 R"(
1547 struct B {
1548 void f();
1549 };
1550
1551 struct B;
1552 )",
1553 Lang_CXX);
1554 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001555 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001556
1557 Decl *FromTU = getTuDecl(
1558 R"(
1559 struct B {
1560 void f();
1561 };
1562 )",
1563 Lang_CXX, "input1.cc");
1564 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1565 FromTU, cxxRecordDecl(hasName("B")));
1566
1567 Import(FromD, Lang_CXX);
1568
1569 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001570 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001571}
1572
1573TEST_P(
1574 ASTImporterTestBase,
1575 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
1576{
1577 Decl *ToTU = getToTuDecl(
1578 R"(
1579 template <typename T>
1580 struct B;
1581
1582 template <>
1583 struct B<int> {};
1584
1585 template <>
1586 struct B<int>;
1587 )",
1588 Lang_CXX);
1589 // We should have only one definition.
1590 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1591 [](const ClassTemplateSpecializationDecl *T) {
1592 return T->isThisDeclarationADefinition();
1593 })
1594 .match(ToTU, classTemplateSpecializationDecl()));
1595
1596 Decl *FromTU = getTuDecl(
1597 R"(
1598 template <typename T>
1599 struct B;
1600
1601 template <>
1602 struct B<int> {};
1603 )",
1604 Lang_CXX, "input1.cc");
1605 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1606 FromTU, classTemplateSpecializationDecl(hasName("B")));
1607
1608 Import(FromD, Lang_CXX);
1609
1610 // We should have only one definition.
1611 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1612 [](const ClassTemplateSpecializationDecl *T) {
1613 return T->isThisDeclarationADefinition();
1614 })
1615 .match(ToTU, classTemplateSpecializationDecl()));
1616}
1617
Peter Szecsidedda6f2018-03-30 22:03:29 +00001618INSTANTIATE_TEST_CASE_P(
1619 ParameterizedTests, ASTImporterTestBase,
1620 ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),);
1621
1622struct ImportFunctions : ASTImporterTestBase {};
1623
1624TEST_P(ImportFunctions,
1625 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
1626 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
1627 auto Pattern = functionDecl(hasName("f"));
1628 FunctionDecl *FromD =
1629 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1630
1631 Decl *ImportedD = Import(FromD, Lang_CXX);
1632 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1633
1634 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1635 EXPECT_TRUE(!cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1636}
1637
1638TEST_P(ImportFunctions,
1639 PrototypeShouldBeImportedAsDefintionWhenThereIsADefinition) {
1640 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1641 auto Pattern = functionDecl(hasName("f"));
1642 FunctionDecl *FromD = // Prototype
1643 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1644
1645 Decl *ImportedD = Import(FromD, Lang_CXX);
1646 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1647
1648 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1649 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1650}
1651
1652TEST_P(ImportFunctions,
1653 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1654 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1655 auto Pattern = functionDecl(hasName("f"));
1656 FunctionDecl *FromD = // Definition
1657 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1658
1659 Decl *ImportedD = Import(FromD, Lang_CXX);
1660 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1661
1662 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1663 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1664}
1665
1666TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1667 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1668 auto Pattern = functionDecl(hasName("f"));
1669 FunctionDecl *FromD =
1670 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1671
1672 Decl *ImportedD = Import(FromD, Lang_CXX);
1673 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1674
1675 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1676 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1677}
1678
1679TEST_P(ImportFunctions, DISABLED_ImportPrototypeOfRecursiveFunction) {
1680 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1681 auto Pattern = functionDecl(hasName("f"));
1682 FunctionDecl *PrototypeFD =
1683 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1684
1685 Decl *ImportedD = Import(PrototypeFD, Lang_CXX);
1686 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1687
1688 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1689 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1690}
1691
1692TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1693 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1694 auto Pattern = functionDecl(hasName("f"));
1695 FunctionDecl *DefinitionFD =
1696 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1697
1698 Decl *ImportedD = Import(DefinitionFD, Lang_CXX);
1699 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1700
1701 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1702 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1703}
1704
1705TEST_P(ImportFunctions, ImportPrototypes) {
1706 auto Pattern = functionDecl(hasName("f"));
1707
1708 Decl *ImportedD;
1709 {
1710 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1711 FunctionDecl *FromD =
1712 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1713
1714 ImportedD = Import(FromD, Lang_CXX);
1715 }
1716 Decl *ImportedD1;
1717 {
1718 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
1719 FunctionDecl *FromD =
1720 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1721 ImportedD1 = Import(FromD, Lang_CXX);
1722 }
1723
1724 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1725 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1726 EXPECT_EQ(ImportedD, ImportedD1);
1727 EXPECT_TRUE(!cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1728}
1729
1730TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
1731 auto Pattern = functionDecl(hasName("f"));
1732
1733 Decl *ImportedD;
1734 {
1735 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
1736 FunctionDecl *FromD =
1737 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1738
1739 ImportedD = Import(FromD, Lang_CXX);
1740 }
1741 Decl *ImportedD1;
1742 {
1743 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
1744 FunctionDecl *FromD =
1745 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1746 ImportedD1 = Import(FromD, Lang_CXX);
1747 }
1748
1749 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1750 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1751 EXPECT_EQ(ImportedD, ImportedD1);
1752 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1753}
1754
1755TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
1756 auto Pattern = functionDecl(hasName("f"));
1757
1758 {
1759 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1760 FunctionDecl *FromD =
1761 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1762
1763 Import(FromD, Lang_CXX);
1764 }
1765 {
1766 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
1767 FunctionDecl *FromD =
1768 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1769 Import(FromD, Lang_CXX);
1770 }
1771
1772 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1773 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1774 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1775 EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody());
1776 FunctionDecl *DefinitionD =
1777 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1778 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
1779 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
1780}
1781
1782TEST_P(ImportFunctions, DISABLED_ImportPrototypeThenProtoAndDefinition) {
1783 auto Pattern = functionDecl(hasName("f"));
1784
1785 {
1786 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1787 FunctionDecl *FromD =
1788 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1789
1790 Import(FromD, Lang_CXX);
1791 }
1792 {
1793 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
1794 FunctionDecl *FromD =
1795 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1796 Import(FromD, Lang_CXX);
1797 }
1798
1799 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1800 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1801 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1802 EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody());
1803 FunctionDecl *DefinitionD =
1804 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1805 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
1806 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
1807}
1808
1809TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
1810 auto Code =
1811 R"(
1812 struct B { virtual void f(); };
1813 void B::f() {}
1814 struct D : B { void f(); };
1815 )";
1816 auto Pattern =
1817 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
1818 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1819 CXXMethodDecl *Proto =
1820 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1821
1822 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
1823 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1824 EXPECT_EQ(To->size_overridden_methods(), 1u);
1825}
1826
1827TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
1828 auto Code =
1829 R"(
1830 struct B { virtual void f(); };
1831 void B::f() {}
1832 )";
1833 auto Pattern =
1834 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1835 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1836 CXXMethodDecl *Proto =
1837 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1838 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1839
1840 ASSERT_TRUE(Proto->isVirtual());
1841 ASSERT_TRUE(Def->isVirtual());
1842 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1843 EXPECT_TRUE(To->isVirtual());
1844}
1845
1846INSTANTIATE_TEST_CASE_P(
1847 ParameterizedTests, ImportFunctions,
1848 ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),);
1849
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001850AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
1851 InnerMatcher) {
1852 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
1853 return InnerMatcher.matches(*Typedef, Finder, Builder);
1854 return false;
1855}
1856
1857TEST(ImportDecl, ImportEnumSequential) {
1858 CodeFiles Samples{{"main.c",
1859 {"void foo();"
1860 "void moo();"
1861 "int main() { foo(); moo(); }",
1862 Lang_C}},
1863
1864 {"foo.c",
1865 {"typedef enum { THING_VALUE } thing_t;"
1866 "void conflict(thing_t type);"
1867 "void foo() { (void)THING_VALUE; }"
1868 "void conflict(thing_t type) {}",
1869 Lang_C}},
1870
1871 {"moo.c",
1872 {"typedef enum { THING_VALUE } thing_t;"
1873 "void conflict(thing_t type);"
1874 "void moo() { conflict(THING_VALUE); }",
1875 Lang_C}}};
1876
1877 auto VerificationMatcher =
1878 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
1879 hasTypedefForAnonDecl(hasName("thing_t")));
1880
1881 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
1882 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
1883
1884 testImportSequence(
1885 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
1886 // Just check that there is only one enum decl in the result AST.
1887 "main.c", enumDecl(), VerificationMatcher);
1888
1889 // For different import order, result should be the same.
1890 testImportSequence(
1891 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
1892 // Check that there is only one enum decl in the result AST.
1893 "main.c", enumDecl(), VerificationMatcher);
1894}
1895
Peter Szecsice7f3182018-05-07 12:08:27 +00001896const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
1897 dependentScopeDeclRefExpr;
1898
1899TEST(ImportExpr, DependentScopeDeclRefExpr) {
1900 MatchVerifier<Decl> Verifier;
1901 testImport("template <typename T> struct S { static T foo; };"
1902 "template <typename T> void declToImport() {"
1903 " (void) S<T>::foo;"
1904 "}"
1905 "void instantiate() { declToImport<int>(); }",
1906 Lang_CXX11, "", Lang_CXX11, Verifier,
1907 functionTemplateDecl(has(functionDecl(has(compoundStmt(
1908 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
1909
1910 testImport("template <typename T> struct S {"
1911 "template<typename S> static void foo(){};"
1912 "};"
1913 "template <typename T> void declToImport() {"
1914 " S<T>::template foo<T>();"
1915 "}"
1916 "void instantiate() { declToImport<int>(); }",
1917 Lang_CXX11, "", Lang_CXX11, Verifier,
1918 functionTemplateDecl(has(functionDecl(has(compoundStmt(
1919 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
1920}
1921
1922const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
1923 dependentNameType;
1924
1925TEST(ImportExpr, DependentNameType) {
1926 MatchVerifier<Decl> Verifier;
1927 testImport("template <typename T> struct declToImport {"
1928 " typedef typename T::type dependent_name;"
1929 "};",
1930 Lang_CXX11, "", Lang_CXX11, Verifier,
1931 classTemplateDecl(has(
1932 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
1933}
1934
1935const internal::VariadicDynCastAllOfMatcher<Expr, UnresolvedMemberExpr>
1936 unresolvedMemberExpr;
1937
1938TEST(ImportExpr, UnresolvedMemberExpr) {
1939 MatchVerifier<Decl> Verifier;
1940 testImport("struct S { template <typename T> void mem(); };"
1941 "template <typename U> void declToImport() {"
1942 " S s;"
1943 " s.mem<U>();"
1944 "}"
1945 "void instantiate() { declToImport<int>(); }",
1946 Lang_CXX11, "", Lang_CXX11, Verifier,
1947 functionTemplateDecl(has(functionDecl(has(
1948 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
1949}
1950
Gabor Marton61d862a2018-05-18 09:08:47 +00001951struct DeclContextTest : ASTImporterTestBase {};
1952
1953TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
1954 Decl *TU = getTuDecl(
1955 R"(
1956 namespace NS {
1957
1958 template <typename T>
1959 struct S {};
1960 template struct S<int>;
1961
1962 inline namespace INS {
1963 template <typename T>
1964 struct S {};
1965 template struct S<int>;
1966 }
1967
1968 }
1969 )", Lang_CXX11, "input0.cc");
1970 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
1971 TU, namespaceDecl());
1972 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1973 TU, classTemplateSpecializationDecl());
1974 ASSERT_TRUE(NS->containsDecl(Spec));
1975
1976 NS->removeDecl(Spec);
1977 EXPECT_FALSE(NS->containsDecl(Spec));
1978}
1979
1980INSTANTIATE_TEST_CASE_P(
1981 ParameterizedTests, DeclContextTest,
1982 ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),);
1983
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00001984} // end namespace ast_matchers
1985} // end namespace clang