blob: 1cdae8066f81c3ac3defcd6557b0b1e09357d006 [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 Marton6578a4a2018-06-25 11:38:43 +00001098TEST(ImportDecl, ImportClassTemplatePartialSpecialization) {
1099 MatchVerifier<Decl> Verifier;
1100 auto Code =
1101 R"s(
1102 struct declToImport {
1103 template <typename T0> struct X;
1104 template <typename T0> struct X<T0 *> {};
1105 };
1106 )s";
1107 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1108 recordDecl(has(classTemplateDecl()),
1109 has(classTemplateSpecializationDecl())));
1110}
1111
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001112TEST(ImportExpr, CXXOperatorCallExpr) {
1113 MatchVerifier<Decl> Verifier;
1114 testImport("class declToImport {"
1115 " void f() { *this = declToImport(); }"
1116 "};",
1117 Lang_CXX, "", Lang_CXX, Verifier,
1118 cxxRecordDecl(has(cxxMethodDecl(hasBody(compoundStmt(
1119 has(exprWithCleanups(has(cxxOperatorCallExpr())))))))));
1120}
1121
1122TEST(ImportExpr, DependentSizedArrayType) {
1123 MatchVerifier<Decl> Verifier;
1124 testImport("template<typename T, int Size> class declToImport {"
1125 " T data[Size];"
1126 "};",
1127 Lang_CXX, "", Lang_CXX, Verifier,
1128 classTemplateDecl(has(cxxRecordDecl(
1129 has(fieldDecl(hasType(dependentSizedArrayType())))))));
1130}
1131
Gabor Martona0df7a92018-05-30 09:19:26 +00001132TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
1133 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1134 auto From =
1135 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1136 ASSERT_TRUE(From);
1137 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1138 ASSERT_TRUE(To);
1139 Decl *ToTemplated = To->getTemplatedDecl();
1140 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1141 EXPECT_TRUE(ToTemplated1);
1142 EXPECT_EQ(ToTemplated1, ToTemplated);
1143}
1144
Gabor Marton6578a4a2018-06-25 11:38:43 +00001145TEST_P(ASTImporterTestBase,
1146 DISABLED_ImportOfTemplatedDeclOfFunctionTemplateDecl) {
1147 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1148 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1149 FromTU, functionTemplateDecl());
1150 ASSERT_TRUE(From);
1151 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1152 ASSERT_TRUE(To);
1153 Decl *ToTemplated = To->getTemplatedDecl();
1154 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1155 EXPECT_TRUE(ToTemplated1);
1156 EXPECT_EQ(ToTemplated1, ToTemplated);
1157}
1158
1159TEST_P(ASTImporterTestBase,
1160 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1161 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1162 auto FromFT =
1163 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1164 ASSERT_TRUE(FromFT);
1165
1166 auto ToTemplated =
1167 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1168 EXPECT_TRUE(ToTemplated);
1169 auto ToTU = ToTemplated->getTranslationUnitDecl();
1170 auto ToFT =
1171 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1172 EXPECT_TRUE(ToFT);
1173}
1174
1175TEST_P(ASTImporterTestBase,
1176 DISABLED_ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
1177 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1178 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1179 FromTU, functionTemplateDecl());
1180 ASSERT_TRUE(FromFT);
1181
1182 auto ToTemplated =
1183 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1184 EXPECT_TRUE(ToTemplated);
1185 auto ToTU = ToTemplated->getTranslationUnitDecl();
1186 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1187 ToTU, functionTemplateDecl());
1188 EXPECT_TRUE(ToFT);
1189}
1190
Gabor Martona0df7a92018-05-30 09:19:26 +00001191TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
1192 auto Code =
1193 R"(
1194 namespace x {
1195 template<class X> struct S1{};
1196 template<class X> struct S2{};
1197 template<class X> struct S3{};
1198 }
1199 )";
1200 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1201 auto FromNs =
1202 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1203 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1204 ASSERT_TRUE(ToNs);
1205 auto From =
1206 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1207 classTemplateDecl(
1208 hasName("S2")));
1209 auto To =
1210 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1211 classTemplateDecl(
1212 hasName("S2")));
1213 ASSERT_TRUE(From);
1214 ASSERT_TRUE(To);
1215 auto ToTemplated = To->getTemplatedDecl();
1216 auto ToTemplated1 =
1217 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1218 EXPECT_TRUE(ToTemplated1);
1219 ASSERT_EQ(ToTemplated1, ToTemplated);
1220}
1221
Peter Szecsidedda6f2018-03-30 22:03:29 +00001222TEST_P(ASTImporterTestBase, DISABLED_ImportFunctionWithBackReferringParameter) {
1223 Decl *From, *To;
1224 std::tie(From, To) = getImportedDecl(
1225 R"(
1226 template <typename T> struct X {};
1227
1228 void declToImport(int y, X<int> &x) {}
1229
1230 template <> struct X<int> {
1231 void g() {
1232 X<int> x;
1233 declToImport(0, x);
1234 }
1235 };
1236 )",
1237 Lang_CXX, "", Lang_CXX);
1238
1239 MatchVerifier<Decl> Verifier;
1240 auto Matcher = functionDecl(hasName("declToImport"),
1241 parameterCountIs(2),
1242 hasParameter(0, hasName("y")),
1243 hasParameter(1, hasName("x")),
1244 hasParameter(1, hasType(asString("X<int> &"))));
1245 ASSERT_TRUE(Verifier.match(From, Matcher));
1246 EXPECT_TRUE(Verifier.match(To, Matcher));
1247}
1248
1249TEST_P(ASTImporterTestBase,
1250 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1251 Decl *From, *To;
1252 std::tie(From, To) =
1253 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1254 "void instantiate() { declToImport<int>(); }",
1255 Lang_CXX, "", Lang_CXX);
1256
1257 auto Check = [](Decl *D) -> bool {
1258 auto TU = D->getTranslationUnitDecl();
1259 for (auto Child : TU->decls()) {
1260 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1261 if (FD->getNameAsString() == "declToImport") {
1262 GTEST_NONFATAL_FAILURE_(
1263 "TU should not contain any FunctionDecl with name declToImport");
1264 return false;
1265 }
1266 }
1267 }
1268 return true;
1269 };
1270
1271 ASSERT_TRUE(Check(From));
1272 EXPECT_TRUE(Check(To));
1273}
1274
1275TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
1276 Decl *From, *To;
1277 std::tie(From, To) =
1278 getImportedDecl("template <typename T> struct declToImport { T t; };"
1279 "void instantiate() { declToImport<int>(); }",
1280 Lang_CXX, "", Lang_CXX);
1281
1282 auto Check = [](Decl *D) -> bool {
1283 auto TU = D->getTranslationUnitDecl();
1284 for (auto Child : TU->decls()) {
1285 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1286 if (RD->getNameAsString() == "declToImport") {
1287 GTEST_NONFATAL_FAILURE_(
1288 "TU should not contain any CXXRecordDecl with name declToImport");
1289 return false;
1290 }
1291 }
1292 }
1293 return true;
1294 };
1295
1296 ASSERT_TRUE(Check(From));
1297 EXPECT_TRUE(Check(To));
1298}
1299
1300TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
1301 Decl *From, *To;
1302 std::tie(From, To) =
1303 getImportedDecl(
1304 "template <typename T> struct X {};"
1305 "template <typename T> using declToImport = X<T>;"
1306 "void instantiate() { declToImport<int> a; }",
1307 Lang_CXX11, "", Lang_CXX11);
1308
1309 auto Check = [](Decl *D) -> bool {
1310 auto TU = D->getTranslationUnitDecl();
1311 for (auto Child : TU->decls()) {
1312 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1313 if (AD->getNameAsString() == "declToImport") {
1314 GTEST_NONFATAL_FAILURE_(
1315 "TU should not contain any TypeAliasDecl with name declToImport");
1316 return false;
1317 }
1318 }
1319 }
1320 return true;
1321 };
1322
1323 ASSERT_TRUE(Check(From));
1324 EXPECT_TRUE(Check(To));
1325}
1326
1327TEST_P(
1328 ASTImporterTestBase,
Gabor Martonb14056b2018-05-25 11:21:24 +00001329 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001330
1331 Decl *From, *To;
1332 std::tie(From, To) = getImportedDecl(
1333 R"(
1334 template<class T>
1335 class Base {};
1336 class declToImport : public Base<declToImport> {};
1337 )",
1338 Lang_CXX, "", Lang_CXX);
1339
1340 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1341 auto Pattern =
1342 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1343 ASSERT_TRUE(
1344 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1345 EXPECT_TRUE(
1346 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1347
1348 // Check that the ClassTemplateSpecializationDecl is the child of the
1349 // ClassTemplateDecl.
1350 Pattern = translationUnitDecl(has(classTemplateDecl(
1351 hasName("Base"), has(classTemplateSpecializationDecl()))));
1352 ASSERT_TRUE(
1353 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1354 EXPECT_TRUE(
1355 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1356}
1357
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001358AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1359 size_t Index = 0;
1360 for (FieldDecl *Field : Node.fields()) {
1361 if (Index == Order.size())
1362 return false;
1363 if (Field->getName() != Order[Index])
1364 return false;
1365 ++Index;
1366 }
1367 return Index == Order.size();
1368}
1369
Peter Szecsidedda6f2018-03-30 22:03:29 +00001370TEST_P(ASTImporterTestBase,
1371 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1372 Decl *From, *To;
1373 std::tie(From, To) = getImportedDecl(
1374 R"(
1375 namespace NS {
1376 template<class T>
1377 class X {};
1378 template class X<int>;
1379 }
1380 )",
1381 Lang_CXX, "", Lang_CXX, "NS");
1382
1383 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1384 // ClassTemplateDecl.
1385 auto Pattern = namespaceDecl(has(classTemplateDecl(
1386 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1387 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1388 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1389
1390 // Check that the ClassTemplateSpecializationDecl is the child of the
1391 // NamespaceDecl.
1392 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1393 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1394 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1395}
1396
1397TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1398 Decl *From, *To;
1399 std::tie(From, To) =
1400 getImportedDecl(
1401 "struct declToImport { int a; int b; };",
1402 Lang_CXX11, "", Lang_CXX11);
1403
1404 MatchVerifier<Decl> Verifier;
1405 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1406 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1407}
1408
1409TEST_P(ASTImporterTestBase,
1410 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1411 Decl *From, *To;
1412 std::tie(From, To) = getImportedDecl(
1413 // The original recursive algorithm of ASTImporter first imports 'c' then
1414 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1415 R"s(
1416 struct declToImport {
1417 int a = c + b;
1418 int b = 1;
1419 int c = 2;
1420 };
1421 )s",
1422 Lang_CXX11, "", Lang_CXX11);
1423
1424 MatchVerifier<Decl> Verifier;
1425 ASSERT_TRUE(
1426 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1427 EXPECT_TRUE(
1428 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1429}
1430
Gabor Martonde8bf262018-05-17 09:46:07 +00001431TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001432 Decl *From, *To;
1433 std::tie(From, To) = getImportedDecl(
1434 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001435 struct declToImport {
1436 };
1437 )",
1438 Lang_CXX, "", Lang_CXX);
1439
1440 MatchVerifier<Decl> Verifier;
1441 // Match the implicit Decl.
1442 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1443 ASSERT_TRUE(Verifier.match(From, Matcher));
1444 EXPECT_TRUE(Verifier.match(To, Matcher));
1445}
1446
1447TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1448 Decl *From, *To;
1449 std::tie(From, To) = getImportedDecl(
1450 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001451 template <typename U>
1452 struct declToImport {
1453 };
1454 )",
1455 Lang_CXX, "", Lang_CXX);
1456
1457 MatchVerifier<Decl> Verifier;
1458 // Match the implicit Decl.
1459 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1460 ASSERT_TRUE(Verifier.match(From, Matcher));
1461 EXPECT_TRUE(Verifier.match(To, Matcher));
1462}
1463
1464TEST_P(
1465 ASTImporterTestBase,
Gabor Martona3af5672018-05-23 14:24:02 +00001466 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001467 Decl *From, *To;
1468 std::tie(From, To) = getImportedDecl(
1469 R"(
1470 template<class T>
1471 class Base {};
1472 class declToImport : public Base<declToImport> {};
1473 )",
1474 Lang_CXX, "", Lang_CXX);
1475
1476 auto hasImplicitClass = has(cxxRecordDecl());
1477 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1478 hasName("Base"),
1479 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1480 ASSERT_TRUE(
1481 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1482 EXPECT_TRUE(
1483 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1484}
1485
1486TEST_P(ASTImporterTestBase, IDNSOrdinary) {
1487 Decl *From, *To;
1488 std::tie(From, To) =
1489 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1490
1491 MatchVerifier<Decl> Verifier;
1492 auto Matcher = functionDecl();
1493 ASSERT_TRUE(Verifier.match(From, Matcher));
1494 EXPECT_TRUE(Verifier.match(To, Matcher));
1495 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1496}
1497
Gabor Marton2ae9da32018-05-18 15:46:18 +00001498TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001499 Decl *FromTU = getTuDecl(
1500 R"(
1501 struct X {};
1502 void operator<<(int, X);
1503 )",
1504 Lang_CXX);
1505 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1506 const Decl *To = Import(From, Lang_CXX);
1507 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1508}
1509
1510TEST_P(ASTImporterTestBase,
1511 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1512 Decl *From, *To;
1513 std::tie(From, To) = getImportedDecl(
1514 R"(
1515 template<class T>
1516 class Base { int a; };
1517 class declToImport : Base<declToImport> {};
1518 )",
1519 Lang_CXX, "", Lang_CXX);
1520
1521 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1522 hasName("Base"),
1523 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1524 ASSERT_TRUE(
1525 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1526 EXPECT_TRUE(
1527 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1528}
1529
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001530TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
1531 {
1532 Decl *FromTU = getTuDecl(
1533 R"(
1534 template <typename T>
1535 struct B;
1536 )",
1537 Lang_CXX, "input0.cc");
1538 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1539 FromTU, classTemplateDecl(hasName("B")));
1540
1541 Import(FromD, Lang_CXX);
1542 }
1543
1544 {
1545 Decl *FromTU = getTuDecl(
1546 R"(
1547 template <typename T>
1548 struct B {
1549 void f();
1550 };
1551 )",
1552 Lang_CXX, "input1.cc");
1553 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1554 FromTU, functionDecl(hasName("f")));
1555 Import(FromD, Lang_CXX);
1556 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1557 FromTU, classTemplateDecl(hasName("B")));
1558 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1559 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1560 }
1561}
1562
Gabor Marton9581c332018-05-23 13:53:36 +00001563TEST_P(ASTImporterTestBase,
1564 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1565 Decl *ToTU = getToTuDecl(
1566 R"(
1567 template <typename T>
1568 struct B {
1569 void f();
1570 };
1571
1572 template <typename T>
1573 struct B;
1574 )",
1575 Lang_CXX);
1576 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1577 [](const ClassTemplateDecl *T) {
1578 return T->isThisDeclarationADefinition();
1579 })
1580 .match(ToTU, classTemplateDecl()));
1581
1582 Decl *FromTU = getTuDecl(
1583 R"(
1584 template <typename T>
1585 struct B {
1586 void f();
1587 };
1588 )",
1589 Lang_CXX, "input1.cc");
1590 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1591 FromTU, classTemplateDecl(hasName("B")));
1592
1593 Import(FromD, Lang_CXX);
1594
1595 // We should have only one definition.
1596 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1597 [](const ClassTemplateDecl *T) {
1598 return T->isThisDeclarationADefinition();
1599 })
1600 .match(ToTU, classTemplateDecl()));
1601}
1602
1603TEST_P(ASTImporterTestBase,
1604 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1605 Decl *ToTU = getToTuDecl(
1606 R"(
1607 struct B {
1608 void f();
1609 };
1610
1611 struct B;
1612 )",
1613 Lang_CXX);
1614 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001615 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001616
1617 Decl *FromTU = getTuDecl(
1618 R"(
1619 struct B {
1620 void f();
1621 };
1622 )",
1623 Lang_CXX, "input1.cc");
1624 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1625 FromTU, cxxRecordDecl(hasName("B")));
1626
1627 Import(FromD, Lang_CXX);
1628
1629 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001630 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001631}
1632
1633TEST_P(
1634 ASTImporterTestBase,
1635 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
1636{
1637 Decl *ToTU = getToTuDecl(
1638 R"(
1639 template <typename T>
1640 struct B;
1641
1642 template <>
1643 struct B<int> {};
1644
1645 template <>
1646 struct B<int>;
1647 )",
1648 Lang_CXX);
1649 // We should have only one definition.
1650 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1651 [](const ClassTemplateSpecializationDecl *T) {
1652 return T->isThisDeclarationADefinition();
1653 })
1654 .match(ToTU, classTemplateSpecializationDecl()));
1655
1656 Decl *FromTU = getTuDecl(
1657 R"(
1658 template <typename T>
1659 struct B;
1660
1661 template <>
1662 struct B<int> {};
1663 )",
1664 Lang_CXX, "input1.cc");
1665 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1666 FromTU, classTemplateSpecializationDecl(hasName("B")));
1667
1668 Import(FromD, Lang_CXX);
1669
1670 // We should have only one definition.
1671 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1672 [](const ClassTemplateSpecializationDecl *T) {
1673 return T->isThisDeclarationADefinition();
1674 })
1675 .match(ToTU, classTemplateSpecializationDecl()));
1676}
1677
Peter Szecsidedda6f2018-03-30 22:03:29 +00001678INSTANTIATE_TEST_CASE_P(
1679 ParameterizedTests, ASTImporterTestBase,
1680 ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),);
1681
1682struct ImportFunctions : ASTImporterTestBase {};
1683
1684TEST_P(ImportFunctions,
1685 PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) {
1686 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
1687 auto Pattern = functionDecl(hasName("f"));
1688 FunctionDecl *FromD =
1689 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1690
1691 Decl *ImportedD = Import(FromD, Lang_CXX);
1692 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1693
1694 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1695 EXPECT_TRUE(!cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1696}
1697
1698TEST_P(ImportFunctions,
1699 PrototypeShouldBeImportedAsDefintionWhenThereIsADefinition) {
1700 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1701 auto Pattern = functionDecl(hasName("f"));
1702 FunctionDecl *FromD = // Prototype
1703 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1704
1705 Decl *ImportedD = Import(FromD, Lang_CXX);
1706 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1707
1708 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1709 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1710}
1711
1712TEST_P(ImportFunctions,
1713 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1714 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1715 auto Pattern = functionDecl(hasName("f"));
1716 FunctionDecl *FromD = // Definition
1717 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1718
1719 Decl *ImportedD = Import(FromD, Lang_CXX);
1720 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1721
1722 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1723 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1724}
1725
1726TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1727 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1728 auto Pattern = functionDecl(hasName("f"));
1729 FunctionDecl *FromD =
1730 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1731
1732 Decl *ImportedD = Import(FromD, Lang_CXX);
1733 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1734
1735 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1736 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1737}
1738
1739TEST_P(ImportFunctions, DISABLED_ImportPrototypeOfRecursiveFunction) {
1740 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1741 auto Pattern = functionDecl(hasName("f"));
1742 FunctionDecl *PrototypeFD =
1743 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1744
1745 Decl *ImportedD = Import(PrototypeFD, Lang_CXX);
1746 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1747
1748 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1749 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1750}
1751
1752TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1753 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1754 auto Pattern = functionDecl(hasName("f"));
1755 FunctionDecl *DefinitionFD =
1756 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1757
1758 Decl *ImportedD = Import(DefinitionFD, Lang_CXX);
1759 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1760
1761 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1762 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1763}
1764
1765TEST_P(ImportFunctions, ImportPrototypes) {
1766 auto Pattern = functionDecl(hasName("f"));
1767
1768 Decl *ImportedD;
1769 {
1770 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1771 FunctionDecl *FromD =
1772 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1773
1774 ImportedD = Import(FromD, Lang_CXX);
1775 }
1776 Decl *ImportedD1;
1777 {
1778 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
1779 FunctionDecl *FromD =
1780 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1781 ImportedD1 = Import(FromD, Lang_CXX);
1782 }
1783
1784 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1785 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1786 EXPECT_EQ(ImportedD, ImportedD1);
1787 EXPECT_TRUE(!cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1788}
1789
1790TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
1791 auto Pattern = functionDecl(hasName("f"));
1792
1793 Decl *ImportedD;
1794 {
1795 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
1796 FunctionDecl *FromD =
1797 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1798
1799 ImportedD = Import(FromD, Lang_CXX);
1800 }
1801 Decl *ImportedD1;
1802 {
1803 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
1804 FunctionDecl *FromD =
1805 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1806 ImportedD1 = Import(FromD, Lang_CXX);
1807 }
1808
1809 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1810 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1811 EXPECT_EQ(ImportedD, ImportedD1);
1812 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1813}
1814
1815TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
1816 auto Pattern = functionDecl(hasName("f"));
1817
1818 {
1819 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1820 FunctionDecl *FromD =
1821 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1822
1823 Import(FromD, Lang_CXX);
1824 }
1825 {
1826 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
1827 FunctionDecl *FromD =
1828 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1829 Import(FromD, Lang_CXX);
1830 }
1831
1832 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1833 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1834 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1835 EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody());
1836 FunctionDecl *DefinitionD =
1837 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1838 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
1839 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
1840}
1841
1842TEST_P(ImportFunctions, DISABLED_ImportPrototypeThenProtoAndDefinition) {
1843 auto Pattern = functionDecl(hasName("f"));
1844
1845 {
1846 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1847 FunctionDecl *FromD =
1848 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1849
1850 Import(FromD, Lang_CXX);
1851 }
1852 {
1853 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
1854 FunctionDecl *FromD =
1855 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1856 Import(FromD, Lang_CXX);
1857 }
1858
1859 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1860 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1861 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1862 EXPECT_TRUE(!ProtoD->doesThisDeclarationHaveABody());
1863 FunctionDecl *DefinitionD =
1864 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1865 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
1866 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
1867}
1868
1869TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
1870 auto Code =
1871 R"(
1872 struct B { virtual void f(); };
1873 void B::f() {}
1874 struct D : B { void f(); };
1875 )";
1876 auto Pattern =
1877 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
1878 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1879 CXXMethodDecl *Proto =
1880 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1881
1882 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
1883 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1884 EXPECT_EQ(To->size_overridden_methods(), 1u);
1885}
1886
1887TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
1888 auto Code =
1889 R"(
1890 struct B { virtual void f(); };
1891 void B::f() {}
1892 )";
1893 auto Pattern =
1894 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1895 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1896 CXXMethodDecl *Proto =
1897 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1898 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1899
1900 ASSERT_TRUE(Proto->isVirtual());
1901 ASSERT_TRUE(Def->isVirtual());
1902 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1903 EXPECT_TRUE(To->isVirtual());
1904}
1905
1906INSTANTIATE_TEST_CASE_P(
1907 ParameterizedTests, ImportFunctions,
1908 ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),);
1909
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001910AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
1911 InnerMatcher) {
1912 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
1913 return InnerMatcher.matches(*Typedef, Finder, Builder);
1914 return false;
1915}
1916
1917TEST(ImportDecl, ImportEnumSequential) {
1918 CodeFiles Samples{{"main.c",
1919 {"void foo();"
1920 "void moo();"
1921 "int main() { foo(); moo(); }",
1922 Lang_C}},
1923
1924 {"foo.c",
1925 {"typedef enum { THING_VALUE } thing_t;"
1926 "void conflict(thing_t type);"
1927 "void foo() { (void)THING_VALUE; }"
1928 "void conflict(thing_t type) {}",
1929 Lang_C}},
1930
1931 {"moo.c",
1932 {"typedef enum { THING_VALUE } thing_t;"
1933 "void conflict(thing_t type);"
1934 "void moo() { conflict(THING_VALUE); }",
1935 Lang_C}}};
1936
1937 auto VerificationMatcher =
1938 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
1939 hasTypedefForAnonDecl(hasName("thing_t")));
1940
1941 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
1942 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
1943
1944 testImportSequence(
1945 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
1946 // Just check that there is only one enum decl in the result AST.
1947 "main.c", enumDecl(), VerificationMatcher);
1948
1949 // For different import order, result should be the same.
1950 testImportSequence(
1951 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
1952 // Check that there is only one enum decl in the result AST.
1953 "main.c", enumDecl(), VerificationMatcher);
1954}
1955
Peter Szecsice7f3182018-05-07 12:08:27 +00001956const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
1957 dependentScopeDeclRefExpr;
1958
1959TEST(ImportExpr, DependentScopeDeclRefExpr) {
1960 MatchVerifier<Decl> Verifier;
1961 testImport("template <typename T> struct S { static T foo; };"
1962 "template <typename T> void declToImport() {"
1963 " (void) S<T>::foo;"
1964 "}"
1965 "void instantiate() { declToImport<int>(); }",
1966 Lang_CXX11, "", Lang_CXX11, Verifier,
1967 functionTemplateDecl(has(functionDecl(has(compoundStmt(
1968 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
1969
1970 testImport("template <typename T> struct S {"
1971 "template<typename S> static void foo(){};"
1972 "};"
1973 "template <typename T> void declToImport() {"
1974 " S<T>::template foo<T>();"
1975 "}"
1976 "void instantiate() { declToImport<int>(); }",
1977 Lang_CXX11, "", Lang_CXX11, Verifier,
1978 functionTemplateDecl(has(functionDecl(has(compoundStmt(
1979 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
1980}
1981
1982const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
1983 dependentNameType;
1984
1985TEST(ImportExpr, DependentNameType) {
1986 MatchVerifier<Decl> Verifier;
1987 testImport("template <typename T> struct declToImport {"
1988 " typedef typename T::type dependent_name;"
1989 "};",
1990 Lang_CXX11, "", Lang_CXX11, Verifier,
1991 classTemplateDecl(has(
1992 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
1993}
1994
1995const internal::VariadicDynCastAllOfMatcher<Expr, UnresolvedMemberExpr>
1996 unresolvedMemberExpr;
1997
1998TEST(ImportExpr, UnresolvedMemberExpr) {
1999 MatchVerifier<Decl> Verifier;
2000 testImport("struct S { template <typename T> void mem(); };"
2001 "template <typename U> void declToImport() {"
2002 " S s;"
2003 " s.mem<U>();"
2004 "}"
2005 "void instantiate() { declToImport<int>(); }",
2006 Lang_CXX11, "", Lang_CXX11, Verifier,
2007 functionTemplateDecl(has(functionDecl(has(
2008 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2009}
2010
Gabor Marton61d862a2018-05-18 09:08:47 +00002011struct DeclContextTest : ASTImporterTestBase {};
2012
2013TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
2014 Decl *TU = getTuDecl(
2015 R"(
2016 namespace NS {
2017
2018 template <typename T>
2019 struct S {};
2020 template struct S<int>;
2021
2022 inline namespace INS {
2023 template <typename T>
2024 struct S {};
2025 template struct S<int>;
2026 }
2027
2028 }
2029 )", Lang_CXX11, "input0.cc");
2030 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
2031 TU, namespaceDecl());
2032 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
2033 TU, classTemplateSpecializationDecl());
2034 ASSERT_TRUE(NS->containsDecl(Spec));
2035
2036 NS->removeDecl(Spec);
2037 EXPECT_FALSE(NS->containsDecl(Spec));
2038}
2039
2040INSTANTIATE_TEST_CASE_P(
2041 ParameterizedTests, DeclContextTest,
2042 ::testing::Values(ArgVector(), ArgVector{"-fdelayed-template-parsing"}),);
2043
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00002044} // end namespace ast_matchers
2045} // end namespace clang