blob: 69611a46247f66f756c698eb2f90e55524c793de [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"
Gabor Marton5254e642018-06-27 13:32:50 +000023#include "gmock/gmock.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 +000053const StringRef DeclToImportID = "declToImport";
54const StringRef DeclToVerifyID = "declToVerify";
55
Gabor Marton19f4f392018-06-25 13:04:37 +000056// Common base for the different families of ASTImporter tests that are
57// parameterized on the compiler options which may result a different AST. E.g.
58// -fms-compatibility or -fdelayed-template-parsing.
59struct ParameterizedTestsFixture : ::testing::TestWithParam<ArgVector> {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000060
Gabor Marton19f4f392018-06-25 13:04:37 +000061 // Returns the argument vector used for a specific language option, this set
62 // can be tweaked by the test parameters.
63 ArgVector getArgVectorForLanguage(Language Lang) const {
64 ArgVector Args = getBasicRunOptionsForLanguage(Lang);
65 ArgVector ExtraArgs = GetParam();
66 for (const auto &Arg : ExtraArgs) {
67 Args.push_back(Arg);
68 }
69 return Args;
70 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000071
Gabor Marton19f4f392018-06-25 13:04:37 +000072};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000073
Gabor Marton19f4f392018-06-25 13:04:37 +000074// Base class for those tests which use the family of `testImport` functions.
75class TestImportBase : public ParameterizedTestsFixture {
Adam Baloghe4192a82018-06-15 06:45:39 +000076
Gabor Marton19f4f392018-06-25 13:04:37 +000077 template <typename NodeType>
78 NodeType importNode(ASTUnit *From, ASTUnit *To, ASTImporter &Importer,
79 NodeType Node) {
80 ASTContext &ToCtx = To->getASTContext();
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000081
Gabor Marton19f4f392018-06-25 13:04:37 +000082 // Add 'From' file to virtual file system so importer can 'find' it
83 // while importing SourceLocations. It is safe to add same file multiple
84 // times - it just isn't replaced.
85 StringRef FromFileName = From->getMainFileName();
86 createVirtualFileIfNeeded(To, FromFileName,
87 From->getBufferForFile(FromFileName));
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000088
Gabor Marton19f4f392018-06-25 13:04:37 +000089 auto Imported = Importer.Import(Node);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000090
Gabor Marton19f4f392018-06-25 13:04:37 +000091 // This should dump source locations and assert if some source locations
92 // were not imported.
93 SmallString<1024> ImportChecker;
94 llvm::raw_svector_ostream ToNothing(ImportChecker);
95 ToCtx.getTranslationUnitDecl()->print(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000096
Gabor Marton19f4f392018-06-25 13:04:37 +000097 // This traverses the AST to catch certain bugs like poorly or not
98 // implemented subtrees.
99 Imported->dump(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000100
Gabor Marton19f4f392018-06-25 13:04:37 +0000101 return Imported;
102 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000103
Gabor Marton19f4f392018-06-25 13:04:37 +0000104 template <typename NodeType>
105 testing::AssertionResult
106 testImport(const std::string &FromCode, const ArgVector &FromArgs,
107 const std::string &ToCode, const ArgVector &ToArgs,
108 MatchVerifier<NodeType> &Verifier,
109 const BindableMatcher<NodeType> &SearchMatcher,
110 const BindableMatcher<NodeType> &VerificationMatcher) {
111 const char *const InputFileName = "input.cc";
112 const char *const OutputFileName = "output.cc";
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000113
Gabor Marton19f4f392018-06-25 13:04:37 +0000114 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
115 FromCode, FromArgs, InputFileName),
116 ToAST = tooling::buildASTFromCodeWithArgs(
117 ToCode, ToArgs, OutputFileName);
118
119 ASTContext &FromCtx = FromAST->getASTContext(),
120 &ToCtx = ToAST->getASTContext();
121
122 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
123 FromAST->getFileManager(), false);
124
125 auto FoundNodes = match(SearchMatcher, FromCtx);
126 if (FoundNodes.size() != 1)
127 return testing::AssertionFailure()
128 << "Multiple potential nodes were found!";
129
130 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
131 if (!ToImport)
132 return testing::AssertionFailure() << "Node type mismatch!";
133
134 // Sanity check: the node being imported should match in the same way as
135 // the result node.
136 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
137 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
138
139 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
140 if (!Imported)
141 return testing::AssertionFailure() << "Import failed, nullptr returned!";
142
143 return Verifier.match(Imported, WrapperMatcher);
144 }
145
146 template <typename NodeType>
147 testing::AssertionResult
148 testImport(const std::string &FromCode, const ArgVector &FromArgs,
149 const std::string &ToCode, const ArgVector &ToArgs,
150 MatchVerifier<NodeType> &Verifier,
151 const BindableMatcher<NodeType> &VerificationMatcher) {
152 return testImport(
153 FromCode, FromArgs, ToCode, ToArgs, Verifier,
154 translationUnitDecl(
155 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
156 VerificationMatcher);
157 }
158
159public:
160
161 /// Test how AST node named "declToImport" located in the translation unit
162 /// of "FromCode" virtual file is imported to "ToCode" virtual file.
163 /// The verification is done by running AMatcher over the imported node.
164 template <typename NodeType, typename MatcherType>
165 void testImport(const std::string &FromCode, Language FromLang,
166 const std::string &ToCode, Language ToLang,
167 MatchVerifier<NodeType> &Verifier,
168 const MatcherType &AMatcher) {
169 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
170 ToArgs = getArgVectorForLanguage(ToLang);
171 EXPECT_TRUE(
172 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
173 }
174
175 struct ImportAction {
176 StringRef FromFilename;
177 StringRef ToFilename;
178 // FIXME: Generalize this to support other node kinds.
179 BindableMatcher<Decl> ImportPredicate;
180
181 ImportAction(StringRef FromFilename, StringRef ToFilename,
182 DeclarationMatcher ImportPredicate)
183 : FromFilename(FromFilename), ToFilename(ToFilename),
184 ImportPredicate(ImportPredicate) {}
185
186 ImportAction(StringRef FromFilename, StringRef ToFilename,
187 const std::string &DeclName)
188 : FromFilename(FromFilename), ToFilename(ToFilename),
189 ImportPredicate(namedDecl(hasName(DeclName))) {}
190 };
191
192 using SingleASTUnit = std::unique_ptr<ASTUnit>;
193 using AllASTUnits = StringMap<SingleASTUnit>;
194
195 struct CodeEntry {
196 std::string CodeSample;
197 Language Lang;
198 };
199
200 using CodeFiles = StringMap<CodeEntry>;
201
202 /// Builds an ASTUnit for one potential compile options set.
203 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
204 ArgVector Args = getArgVectorForLanguage(CE.Lang);
205 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
206 EXPECT_TRUE(AST.get());
207 return AST;
208 }
209
210 /// Test an arbitrary sequence of imports for a set of given in-memory files.
211 /// The verification is done by running VerificationMatcher against a
212 /// specified AST node inside of one of given files.
213 /// \param CodeSamples Map whose key is the file name and the value is the
214 /// file content.
215 /// \param ImportActions Sequence of imports. Each import in sequence
216 /// specifies "from file" and "to file" and a matcher that is used for
217 /// searching a declaration for import in "from file".
218 /// \param FileForFinalCheck Name of virtual file for which the final check is
219 /// applied.
220 /// \param FinalSelectPredicate Matcher that specifies the AST node in the
221 /// FileForFinalCheck for which the verification will be done.
222 /// \param VerificationMatcher Matcher that will be used for verification
223 /// after all imports in sequence are done.
224 void testImportSequence(const CodeFiles &CodeSamples,
225 const std::vector<ImportAction> &ImportActions,
226 StringRef FileForFinalCheck,
227 BindableMatcher<Decl> FinalSelectPredicate,
228 BindableMatcher<Decl> VerificationMatcher) {
229 AllASTUnits AllASTs;
230 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
231 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
232
233 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
234 if (!AllASTs.count(Filename)) {
235 auto Found = CodeSamples.find(Filename);
236 assert(Found != CodeSamples.end() && "Wrong file for import!");
237 AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
238 }
239 };
240
241 for (const ImportAction &Action : ImportActions) {
242 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
243 GenASTsIfNeeded(FromFile);
244 GenASTsIfNeeded(ToFile);
245
246 ASTUnit *From = AllASTs[FromFile].get();
247 ASTUnit *To = AllASTs[ToFile].get();
248
249 // Create a new importer if needed.
250 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
251 if (!ImporterRef)
252 ImporterRef.reset(new ASTImporter(
253 To->getASTContext(), To->getFileManager(), From->getASTContext(),
254 From->getFileManager(), false));
255
256 // Find the declaration and import it.
257 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
258 From->getASTContext());
259 EXPECT_TRUE(FoundDecl.size() == 1);
260 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
261 auto Imported = importNode(From, To, *ImporterRef, ToImport);
262 EXPECT_TRUE(Imported);
263 }
264
265 // Find the declaration and import it.
266 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
267 AllASTs[FileForFinalCheck]->getASTContext());
268 EXPECT_TRUE(FoundDecl.size() == 1);
269 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
270 MatchVerifier<Decl> Verifier;
271 EXPECT_TRUE(
272 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
273 }
274};
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000275
Peter Szecsidedda6f2018-03-30 22:03:29 +0000276// This class provides generic methods to write tests which can check internal
277// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
278// this fixture makes it possible to import from several "From" contexts.
Gabor Marton19f4f392018-06-25 13:04:37 +0000279class ASTImporterTestBase : public ParameterizedTestsFixture {
Peter Szecsidedda6f2018-03-30 22:03:29 +0000280
281 const char *const InputFileName = "input.cc";
282 const char *const OutputFileName = "output.cc";
283
284 // Buffer for the To context, must live in the test scope.
285 std::string ToCode;
286
287 struct TU {
288 // Buffer for the context, must live in the test scope.
Aleksei Sidorin54d6af52018-05-14 16:12:31 +0000289 std::string Code;
290 std::string FileName;
Peter Szecsidedda6f2018-03-30 22:03:29 +0000291 std::unique_ptr<ASTUnit> Unit;
292 TranslationUnitDecl *TUDecl = nullptr;
293 TU(StringRef Code, StringRef FileName, ArgVector Args)
294 : Code(Code), FileName(FileName),
295 Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args,
296 this->FileName)),
Adam Baloghe4192a82018-06-15 06:45:39 +0000297 TUDecl(Unit->getASTContext().getTranslationUnitDecl()) {
298 Unit->enableSourceFileDiagnostics();
299 }
Peter Szecsidedda6f2018-03-30 22:03:29 +0000300 };
301
302 // We may have several From contexts and related translation units. In each
303 // AST, the buffers for the source are handled via references and are set
304 // during the creation of the AST. These references must point to a valid
305 // buffer until the AST is alive. Thus, we must use a list in order to avoid
306 // moving of the stored objects because that would mean breaking the
307 // references in the AST. By using a vector a move could happen when the
308 // vector is expanding, with the list we won't have these issues.
309 std::list<TU> FromTUs;
310
311public:
312 // We may have several From context but only one To context.
313 std::unique_ptr<ASTUnit> ToAST;
314
Peter Szecsidedda6f2018-03-30 22:03:29 +0000315 // Creates an AST both for the From and To source code and imports the Decl
316 // of the identifier into the To context.
317 // Must not be called more than once within the same test.
318 std::tuple<Decl *, Decl *>
319 getImportedDecl(StringRef FromSrcCode, Language FromLang, StringRef ToSrcCode,
320 Language ToLang, StringRef Identifier = DeclToImportID) {
321 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
322 ToArgs = getArgVectorForLanguage(ToLang);
323
324 FromTUs.emplace_back(FromSrcCode, InputFileName, FromArgs);
325 TU &FromTU = FromTUs.back();
326
327 ToCode = ToSrcCode;
328 assert(!ToAST);
329 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
Adam Baloghe4192a82018-06-15 06:45:39 +0000330 ToAST->enableSourceFileDiagnostics();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000331
332 ASTContext &FromCtx = FromTU.Unit->getASTContext(),
333 &ToCtx = ToAST->getASTContext();
334
335 createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code);
336
337 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
338 FromTU.Unit->getFileManager(), false);
339
340 IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier);
341 assert(ImportedII && "Declaration with the given identifier "
342 "should be specified in test!");
343 DeclarationName ImportDeclName(ImportedII);
344 SmallVector<NamedDecl *, 4> FoundDecls;
345 FromCtx.getTranslationUnitDecl()->localUncachedLookup(ImportDeclName,
346 FoundDecls);
347
348 assert(FoundDecls.size() == 1);
349
350 Decl *Imported = Importer.Import(FoundDecls.front());
351 assert(Imported);
352 return std::make_tuple(*FoundDecls.begin(), Imported);
353 }
354
Gabor Marton9581c332018-05-23 13:53:36 +0000355 // Creates a TU decl for the given source code which can be used as a From
356 // context. May be called several times in a given test (with different file
357 // name).
Peter Szecsidedda6f2018-03-30 22:03:29 +0000358 TranslationUnitDecl *getTuDecl(StringRef SrcCode, Language Lang,
359 StringRef FileName = "input.cc") {
360 assert(
361 std::find_if(FromTUs.begin(), FromTUs.end(), [FileName](const TU &E) {
362 return E.FileName == FileName;
363 }) == FromTUs.end());
364
365 ArgVector Args = getArgVectorForLanguage(Lang);
366 FromTUs.emplace_back(SrcCode, FileName, Args);
367 TU &Tu = FromTUs.back();
368
369 return Tu.TUDecl;
370 }
371
Gabor Marton9581c332018-05-23 13:53:36 +0000372 // Creates the To context with the given source code and returns the TU decl.
373 TranslationUnitDecl *getToTuDecl(StringRef ToSrcCode, Language ToLang) {
374 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
375 ToCode = ToSrcCode;
376 assert(!ToAST);
377 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
Adam Baloghe4192a82018-06-15 06:45:39 +0000378 ToAST->enableSourceFileDiagnostics();
Gabor Marton9581c332018-05-23 13:53:36 +0000379
380 return ToAST->getASTContext().getTranslationUnitDecl();
381 }
382
Peter Szecsidedda6f2018-03-30 22:03:29 +0000383 // Import the given Decl into the ToCtx.
384 // May be called several times in a given test.
385 // The different instances of the param From may have different ASTContext.
386 Decl *Import(Decl *From, Language ToLang) {
387 if (!ToAST) {
388 ArgVector ToArgs = getArgVectorForLanguage(ToLang);
389 // Build the AST from an empty file.
390 ToAST =
391 tooling::buildASTFromCodeWithArgs(/*Code=*/"", ToArgs, "empty.cc");
Adam Baloghe4192a82018-06-15 06:45:39 +0000392 ToAST->enableSourceFileDiagnostics();
Peter Szecsidedda6f2018-03-30 22:03:29 +0000393 }
394
395 // Create a virtual file in the To Ctx which corresponds to the file from
396 // which we want to import the `From` Decl. Without this source locations
397 // will be invalid in the ToCtx.
398 auto It = std::find_if(FromTUs.begin(), FromTUs.end(), [From](const TU &E) {
399 return E.TUDecl == From->getTranslationUnitDecl();
400 });
401 assert(It != FromTUs.end());
402 createVirtualFileIfNeeded(ToAST.get(), It->FileName, It->Code);
403
404 ASTContext &FromCtx = From->getASTContext(),
405 &ToCtx = ToAST->getASTContext();
406 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
407 FromCtx.getSourceManager().getFileManager(), false);
408 return Importer.Import(From);
409 }
410
411 ~ASTImporterTestBase() {
412 if (!::testing::Test::HasFailure()) return;
413
414 for (auto &Tu : FromTUs) {
415 assert(Tu.Unit);
416 llvm::errs() << "FromAST:\n";
417 Tu.Unit->getASTContext().getTranslationUnitDecl()->dump();
418 llvm::errs() << "\n";
419 }
420 if (ToAST) {
421 llvm::errs() << "ToAST:\n";
422 ToAST->getASTContext().getTranslationUnitDecl()->dump();
423 }
424 }
425};
426
Gabor Marton19f4f392018-06-25 13:04:37 +0000427struct ImportExpr : TestImportBase {};
428struct ImportType : TestImportBase {};
429struct ImportDecl : TestImportBase {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000430
Gabor Marton5254e642018-06-27 13:32:50 +0000431struct CanonicalRedeclChain : ASTImporterTestBase {};
432
433TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
434 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
435 auto Pattern = functionDecl(hasName("f"));
436 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
437
438 auto Redecls = getCanonicalForwardRedeclChain(D0);
439 ASSERT_EQ(Redecls.size(), 1u);
440 EXPECT_EQ(D0, Redecls[0]);
441}
442
443TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
444 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
445 auto Pattern = functionDecl(hasName("f"));
446 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
447 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
448 FunctionDecl *D1 = D2->getPreviousDecl();
449
450 auto Redecls = getCanonicalForwardRedeclChain(D0);
451 ASSERT_EQ(Redecls.size(), 3u);
452 EXPECT_EQ(D0, Redecls[0]);
453 EXPECT_EQ(D1, Redecls[1]);
454 EXPECT_EQ(D2, Redecls[2]);
455}
456
457TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
458 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
459 auto Pattern = functionDecl(hasName("f"));
460 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
461 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
462 FunctionDecl *D1 = D2->getPreviousDecl();
463
464 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
465 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
466 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
467
468 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
469 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
470}
471
472
Gabor Marton19f4f392018-06-25 13:04:37 +0000473TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000474 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000475 testImport("void declToImport() { \"foo\"; }",
476 Lang_CXX, "", Lang_CXX, Verifier,
477 functionDecl(
478 hasBody(
479 compoundStmt(
480 has(
481 stringLiteral(
482 hasType(
483 asString("const char [4]"))))))));
484 testImport("void declToImport() { L\"foo\"; }",
485 Lang_CXX, "", Lang_CXX, Verifier,
486 functionDecl(
487 hasBody(
488 compoundStmt(
489 has(
490 stringLiteral(
491 hasType(
492 asString("const wchar_t [4]"))))))));
493 testImport("void declToImport() { \"foo\" \"bar\"; }",
494 Lang_CXX, "", Lang_CXX, Verifier,
495 functionDecl(
496 hasBody(
497 compoundStmt(
498 has(
499 stringLiteral(
500 hasType(
501 asString("const char [7]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000502}
503
Gabor Marton19f4f392018-06-25 13:04:37 +0000504TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000505 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000506 testImport("void declToImport() { __null; }",
507 Lang_CXX, "", Lang_CXX, Verifier,
508 functionDecl(
509 hasBody(
510 compoundStmt(
511 has(
512 gnuNullExpr(
513 hasType(isInteger())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000514}
515
Gabor Marton19f4f392018-06-25 13:04:37 +0000516TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000517 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000518 testImport("void declToImport() { nullptr; }",
519 Lang_CXX11, "", Lang_CXX11, Verifier,
520 functionDecl(
521 hasBody(
522 compoundStmt(
523 has(
524 cxxNullPtrLiteralExpr())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000525}
526
527
Gabor Marton19f4f392018-06-25 13:04:37 +0000528TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000529 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000530 testImport("void declToImport() { 1.0; }",
531 Lang_C, "", Lang_C, Verifier,
532 functionDecl(
533 hasBody(
534 compoundStmt(
535 has(
536 floatLiteral(
537 equals(1.0),
538 hasType(asString("double"))))))));
539 testImport("void declToImport() { 1.0e-5f; }",
540 Lang_C, "", Lang_C, Verifier,
541 functionDecl(
542 hasBody(
543 compoundStmt(
544 has(
545 floatLiteral(
546 equals(1.0e-5f),
547 hasType(asString("float"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000548}
549
Gabor Marton19f4f392018-06-25 13:04:37 +0000550TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000551 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000552 testImport("void declToImport() {"
553 " struct s { int x; long y; unsigned z; }; "
554 " (struct s){ 42, 0L, 1U }; }",
555 Lang_CXX, "", Lang_CXX, Verifier,
556 functionDecl(
557 hasBody(
558 compoundStmt(
559 has(
560 compoundLiteralExpr(
561 hasType(asString("struct s")),
562 has(initListExpr(
563 hasType(asString("struct s")),
564 has(integerLiteral(
565 equals(42), hasType(asString("int")))),
566 has(integerLiteral(
567 equals(0), hasType(asString("long")))),
568 has(integerLiteral(
569 equals(1),
570 hasType(asString("unsigned int"))))
571 ))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000572}
573
Gabor Marton19f4f392018-06-25 13:04:37 +0000574TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000575 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000576 testImport("class declToImport { void f() { this; } };",
577 Lang_CXX, "", Lang_CXX, Verifier,
578 cxxRecordDecl(
579 hasMethod(
580 hasBody(
581 compoundStmt(
582 has(
583 cxxThisExpr(
584 hasType(
585 asString("class declToImport *")))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000586}
587
Gabor Marton19f4f392018-06-25 13:04:37 +0000588TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000589 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000590 testImport("void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
591 Lang_C, "", Lang_C, Verifier,
592 functionDecl(hasBody(compoundStmt(has(atomicExpr(
593 has(ignoringParenImpCasts(
594 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
595 hasType(asString("int *"))))),
596 has(integerLiteral(equals(1), hasType(asString("int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000597}
598
Gabor Marton19f4f392018-06-25 13:04:37 +0000599TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000600 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000601 testImport(
602 "void declToImport() { loop: goto loop; &&loop; }", Lang_C, "", Lang_C,
603 Verifier,
604 functionDecl(hasBody(compoundStmt(
605 has(labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
606 has(addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000607}
608
609AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
610 internal::Matcher<NamedDecl>, InnerMatcher) {
611 const NamedDecl *Template = Node.getTemplatedDecl();
612 return Template && InnerMatcher.matches(*Template, Finder, Builder);
613}
614
Gabor Marton19f4f392018-06-25 13:04:37 +0000615TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000616 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000617 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000618 "template<typename T> class dummy { void f() { dummy X(*this); } };"
619 "typedef dummy<int> declToImport;"
620 "template class dummy<int>;",
621 Lang_CXX, "", Lang_CXX, Verifier,
622 typedefDecl(hasType(templateSpecializationType(
623 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
624 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
625 hasName("f"),
626 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
627 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
628 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000629 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000630}
631
Gabor Marton19f4f392018-06-25 13:04:37 +0000632TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000633 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000634 testImport("void declToImport() { int b; switch (b) { case 1: break; } }",
635 Lang_C, "", Lang_C, Verifier,
636 functionDecl(hasBody(compoundStmt(
637 has(switchStmt(has(compoundStmt(has(caseStmt())))))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000638}
639
Gabor Marton19f4f392018-06-25 13:04:37 +0000640TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000641 MatchVerifier<Decl> Verifier;
642 // NOTE: has() ignores implicit casts, using hasDescendant() to match it
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000643 testImport(
644 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
645 Lang_C, "", Lang_C, Verifier,
646 functionDecl(
647 hasBody(
648 compoundStmt(
649 has(
650 declStmt(
651 hasSingleDecl(
652 varDecl(
653 hasName("C"),
654 hasType(asString("int")),
655 hasInitializer(
656 stmtExpr(
657 hasAnySubstatement(
658 declStmt(
659 hasSingleDecl(
660 varDecl(
661 hasName("X"),
662 hasType(asString("int")),
663 hasInitializer(
664 integerLiteral(equals(4))))))),
665 hasDescendant(
666 implicitCastExpr()
667 )))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000668}
669
Gabor Marton19f4f392018-06-25 13:04:37 +0000670TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000671 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000672 testImport(
673 "void declToImport() { true ? 1 : -5; }",
674 Lang_CXX, "", Lang_CXX, Verifier,
675 functionDecl(
676 hasBody(
677 compoundStmt(
678 has(
679 conditionalOperator(
680 hasCondition(cxxBoolLiteral(equals(true))),
681 hasTrueExpression(integerLiteral(equals(1))),
682 hasFalseExpression(
683 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))
684 )))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000685}
686
Gabor Marton19f4f392018-06-25 13:04:37 +0000687TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000688 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000689 testImport(
690 "void declToImport() { 1 ?: -5; }", Lang_CXX, "", Lang_CXX, Verifier,
691 functionDecl(
692 hasBody(
693 compoundStmt(
694 has(
695 binaryConditionalOperator(
696 hasCondition(
697 implicitCastExpr(
698 hasSourceExpression(
699 opaqueValueExpr(
700 hasSourceExpression(integerLiteral(equals(1))))),
701 hasType(booleanType()))),
702 hasTrueExpression(
703 opaqueValueExpr(hasSourceExpression(
704 integerLiteral(equals(1))))),
705 hasFalseExpression(
706 unaryOperator(hasOperatorName("-"),
707 hasUnaryOperand(integerLiteral(equals(5)))))
708 ))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000709}
710
Gabor Marton19f4f392018-06-25 13:04:37 +0000711TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000712 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000713 testImport("void declToImport() {"
714 " struct point { double x; double y; };"
715 " struct point ptarray[10] = "
716 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
717 Lang_C, "", Lang_C, Verifier,
718 functionDecl(
719 hasBody(
720 compoundStmt(
721 has(
722 declStmt(
723 hasSingleDecl(
724 varDecl(
725 hasInitializer(
726 initListExpr(
727 hasSyntacticForm(
728 initListExpr(
729 has(
730 designatedInitExpr(
731 designatorCountIs(2),
732 has(floatLiteral(
733 equals(1.0))),
734 has(integerLiteral(
735 equals(2))))),
736 has(
737 designatedInitExpr(
738 designatorCountIs(2),
739 has(floatLiteral(
740 equals(2.0))),
741 has(integerLiteral(
742 equals(2))))),
743 has(
744 designatedInitExpr(
745 designatorCountIs(2),
746 has(floatLiteral(
747 equals(1.0))),
748 has(integerLiteral(
749 equals(0)))))
750 ))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000751}
752
753
Gabor Marton19f4f392018-06-25 13:04:37 +0000754TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000755 MatchVerifier<Decl> Verifier;
756 // __func__ expands as StringLiteral("declToImport")
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000757 testImport("void declToImport() { __func__; }",
758 Lang_CXX, "", Lang_CXX, Verifier,
759 functionDecl(
760 hasBody(
761 compoundStmt(
762 has(
763 predefinedExpr(
764 hasType(
765 asString("const char [13]")),
766 has(
767 stringLiteral(
768 hasType(
769 asString("const char [13]"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000770}
771
Gabor Marton19f4f392018-06-25 13:04:37 +0000772TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000773 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000774 testImport(
775 "void declToImport() {"
776 " struct point { double x; double y; };"
777 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
778 " [0].x = 1.0 }; }",
779 Lang_CXX, "", Lang_CXX, Verifier,
780 functionDecl(
781 hasBody(
782 compoundStmt(
783 has(
784 declStmt(
785 hasSingleDecl(
786 varDecl(
787 hasInitializer(
788 initListExpr(
789 has(
790 cxxConstructExpr(
791 requiresZeroInitialization())),
792 has(
793 initListExpr(
794 hasType(asString("struct point")),
795 has(floatLiteral(equals(1.0))),
796 has(implicitValueInitExpr(
797 hasType(asString("double")))))),
798 has(
799 initListExpr(
800 hasType(asString("struct point")),
801 has(floatLiteral(equals(2.0))),
802 has(floatLiteral(equals(1.0)))))
803 ))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000804}
805
806
Aleksei Sidorina693b372016-09-28 10:16:56 +0000807const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
808
Gabor Marton19f4f392018-06-25 13:04:37 +0000809TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000810 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000811 testImport("void declToImport(__builtin_va_list list, ...) {"
812 " (void)__builtin_va_arg(list, int); }",
813 Lang_CXX, "", Lang_CXX, Verifier,
814 functionDecl(
815 hasBody(
816 compoundStmt(
817 has(
818 cStyleCastExpr(
819 hasSourceExpression(
820 vaArgExpr())))))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000821}
822
Gabor Marton19f4f392018-06-25 13:04:37 +0000823TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000824 MatchVerifier<Decl> Verifier;
825 testImport("struct C {};"
826 "void declToImport() { C c = C(); }",
827 Lang_CXX, "", Lang_CXX, Verifier,
828 functionDecl(hasBody(compoundStmt(has(
829 declStmt(has(varDecl(has(exprWithCleanups(has(cxxConstructExpr(
830 has(materializeTemporaryExpr(has(implicitCastExpr(
831 has(cxxTemporaryObjectExpr())))))))))))))))));
832}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000833
Gabor Marton19f4f392018-06-25 13:04:37 +0000834TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000835 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000836 testImport("void declToImport() { typedef _Atomic(int) a_int; }",
837 Lang_CXX11, "", Lang_CXX11, Verifier,
838 functionDecl(
839 hasBody(
840 compoundStmt(
841 has(
842 declStmt(
843 has(
844 typedefDecl(
845 has(atomicType())))))))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000846}
847
Gabor Marton19f4f392018-06-25 13:04:37 +0000848TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000849 MatchVerifier<Decl> Verifier;
850 testImport("template <typename T> void declToImport() { };", Lang_CXX, "",
851 Lang_CXX, Verifier, functionTemplateDecl());
852}
853
854const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
855 cxxDependentScopeMemberExpr;
856
Gabor Marton19f4f392018-06-25 13:04:37 +0000857TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000858 MatchVerifier<Decl> Verifier;
859 testImport("template <typename T> struct C { T t; };"
860 "template <typename T> void declToImport() {"
861 " C<T> d;"
862 " d.t;"
863 "}"
864 "void instantiate() { declToImport<int>(); }",
865 Lang_CXX, "", Lang_CXX, Verifier,
866 functionTemplateDecl(has(functionDecl(
867 has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
868 testImport("template <typename T> struct C { T t; };"
869 "template <typename T> void declToImport() {"
870 " C<T> d;"
871 " (&d)->t;"
872 "}"
873 "void instantiate() { declToImport<int>(); }",
874 Lang_CXX, "", Lang_CXX, Verifier,
875 functionTemplateDecl(has(functionDecl(
876 has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
877}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000878
Gabor Marton19f4f392018-06-25 13:04:37 +0000879TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000880 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000881 testImport(
882 "template <int K>"
883 "struct dummy { static const int i = K; };"
884 "template <int K> using dummy2 = dummy<K>;"
885 "int declToImport() { return dummy2<3>::i; }",
886 Lang_CXX11, "", Lang_CXX11, Verifier,
887 functionDecl(
888 hasBody(compoundStmt(
889 has(returnStmt(has(implicitCastExpr(has(declRefExpr()))))))),
890 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
891}
892
893const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
894 varTemplateSpecializationDecl;
895
Gabor Marton19f4f392018-06-25 13:04:37 +0000896TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000897 MatchVerifier<Decl> Verifier;
898 testImport(
899 "template <typename T>"
900 "T pi = T(3.1415926535897932385L);"
901 "void declToImport() { pi<int>; }",
902 Lang_CXX11, "", Lang_CXX11, Verifier,
903 functionDecl(
904 hasBody(has(declRefExpr(to(varTemplateSpecializationDecl())))),
905 unless(hasAncestor(translationUnitDecl(has(varDecl(
906 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000907}
908
Gabor Marton19f4f392018-06-25 13:04:37 +0000909TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000910 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000911 testImport("template <typename... Args>"
912 "struct dummy {"
913 " dummy(Args... args) {}"
914 " static const int i = 4;"
915 "};"
916 "int declToImport() { return dummy<int>::i; }",
917 Lang_CXX11, "", Lang_CXX11, Verifier,
918 functionDecl(
919 hasBody(
920 compoundStmt(
921 has(
922 returnStmt(
923 has(
924 implicitCastExpr(
925 has(
926 declRefExpr())))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000927}
928
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000929const internal::VariadicDynCastAllOfMatcher<Type,
930 DependentTemplateSpecializationType>
931 dependentTemplateSpecializationType;
932
Gabor Marton19f4f392018-06-25 13:04:37 +0000933TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000934 MatchVerifier<Decl> Verifier;
935 testImport("template<typename T>"
936 "struct A;"
937 "template<typename T>"
938 "struct declToImport {"
939 " typename A<T>::template B<T> a;"
940 "};",
941 Lang_CXX, "", Lang_CXX, Verifier,
942 classTemplateDecl(has(cxxRecordDecl(has(
943 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
944}
945
946const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
947 sizeOfPackExpr;
948
Gabor Marton19f4f392018-06-25 13:04:37 +0000949TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000950 MatchVerifier<Decl> Verifier;
951 testImport("template <typename... Ts>"
952 "void declToImport() {"
953 " const int i = sizeof...(Ts);"
954 "};"
955 "void g() { declToImport<int>(); }",
956 Lang_CXX11, "", Lang_CXX11, Verifier,
957 functionTemplateDecl(has(functionDecl(
958 hasBody(compoundStmt(has(declStmt(has(varDecl(hasInitializer(
959 implicitCastExpr(has(sizeOfPackExpr())))))))))))));
960 testImport(
961 "template <typename... Ts>"
962 "using X = int[sizeof...(Ts)];"
963 "template <typename... Us>"
964 "struct Y {"
965 " X<Us..., int, double, int, Us...> f;"
966 "};"
967 "Y<float, int> declToImport;",
968 Lang_CXX11, "", Lang_CXX11, Verifier,
969 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
970 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
971}
972
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000973/// \brief Matches __builtin_types_compatible_p:
974/// GNU extension to check equivalent types
975/// Given
976/// \code
977/// __builtin_types_compatible_p(int, int)
978/// \endcode
979// will generate TypeTraitExpr <...> 'int'
980const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
981
Gabor Marton19f4f392018-06-25 13:04:37 +0000982TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000983 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000984 testImport("void declToImport() { "
985 " __builtin_types_compatible_p(int, int);"
986 "}",
987 Lang_C, "", Lang_C, Verifier,
988 functionDecl(
989 hasBody(
990 compoundStmt(
991 has(
992 typeTraitExpr(hasType(asString("int"))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000993}
994
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000995const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
996
Gabor Marton19f4f392018-06-25 13:04:37 +0000997TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000998 MatchVerifier<Decl> Verifier;
999 testImport(
1000 "namespace std { class type_info {}; }"
1001 "void declToImport() {"
1002 " int x;"
1003 " auto a = typeid(int); auto b = typeid(x);"
1004 "}",
1005 Lang_CXX11, "", Lang_CXX11, Verifier,
1006 functionDecl(
1007 hasDescendant(varDecl(
1008 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
1009 hasDescendant(varDecl(
1010 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
1011}
1012
Gabor Marton19f4f392018-06-25 13:04:37 +00001013TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001014 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001015 testImport("template<typename T> struct declToImport {"
1016 " void m() { __is_pod(T); }"
1017 "};"
1018 "void f() { declToImport<int>().m(); }",
1019 Lang_CXX11, "", Lang_CXX11, Verifier,
1020 classTemplateDecl(
1021 has(
1022 cxxRecordDecl(
1023 has(
1024 functionDecl(
1025 hasBody(
1026 compoundStmt(
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001027 has(
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001028 typeTraitExpr(
1029 hasType(booleanType())
1030 ))))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +00001031}
Gabor Horvath7a91c082017-11-14 11:30:38 +00001032
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001033const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1034 cxxPseudoDestructorExpr;
1035
Gabor Marton19f4f392018-06-25 13:04:37 +00001036TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001037 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001038 testImport("typedef int T;"
1039 "void declToImport(int *p) {"
1040 " T t;"
1041 " p->T::~T();"
1042 "}",
1043 Lang_CXX, "", Lang_CXX, Verifier,
1044 functionDecl(has(compoundStmt(has(
1045 callExpr(has(cxxPseudoDestructorExpr())))))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001046}
1047
Gabor Marton19f4f392018-06-25 13:04:37 +00001048TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001049 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001050 testImport("namespace foo { int bar; }"
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001051 "void declToImport() { using foo::bar; }",
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001052 Lang_CXX, "", Lang_CXX, Verifier,
1053 functionDecl(
1054 has(
1055 compoundStmt(
1056 has(
1057 declStmt(
1058 has(
1059 usingDecl())))))));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001060}
1061
1062/// \brief Matches shadow declarations introduced into a scope by a
1063/// (resolved) using declaration.
1064///
1065/// Given
1066/// \code
1067/// namespace n { int f; }
1068/// namespace declToImport { using n::f; }
1069/// \endcode
1070/// usingShadowDecl()
1071/// matches \code f \endcode
1072const internal::VariadicDynCastAllOfMatcher<Decl,
1073 UsingShadowDecl> usingShadowDecl;
1074
Gabor Marton19f4f392018-06-25 13:04:37 +00001075TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001076 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +00001077 testImport("namespace foo { int bar; }"
1078 "namespace declToImport { using foo::bar; }",
1079 Lang_CXX, "", Lang_CXX, Verifier,
1080 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001081}
1082
Gabor Marton19f4f392018-06-25 13:04:37 +00001083TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001084 MatchVerifier<Decl> Verifier;
1085 testImport("template<typename T> int foo();"
1086 "template <typename T> void declToImport() {"
1087 " ::foo<T>;"
1088 " ::template foo<T>;"
1089 "}"
1090 "void instantiate() { declToImport<int>(); }",
1091 Lang_CXX, "", Lang_CXX, Verifier,
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001092 functionTemplateDecl(has(functionDecl(
1093 has(compoundStmt(has(unresolvedLookupExpr())))))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001094}
1095
Gabor Marton19f4f392018-06-25 13:04:37 +00001096TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001097 MatchVerifier<Decl> Verifier;
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001098 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001099 "template <typename T> void declToImport() {"
1100 " C<T> d;"
1101 " d.t = T();"
1102 "}"
1103 "void instantiate() { declToImport<int>(); }",
1104 Lang_CXX, "", Lang_CXX, Verifier,
1105 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
1106 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001107 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001108 "template <typename T> void declToImport() {"
1109 " C<T> d;"
1110 " (&d)->t = T();"
1111 "}"
1112 "void instantiate() { declToImport<int>(); }",
1113 Lang_CXX, "", Lang_CXX, Verifier,
1114 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
1115 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
1116}
1117
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001118/// Check that function "declToImport()" (which is the templated function
1119/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1120/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001121TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001122 MatchVerifier<Decl> Verifier;
1123 testImport("template <typename T> void declToImport() { T a = 1; }"
1124 "void instantiate() { declToImport<int>(); }",
1125 Lang_CXX, "", Lang_CXX, Verifier,
1126 functionTemplateDecl(hasAncestor(translationUnitDecl(
1127 unless(has(functionDecl(hasName("declToImport"))))))));
1128 testImport("template <typename T> struct declToImport { T t; };"
1129 "void instantiate() { declToImport<int>(); }",
1130 Lang_CXX, "", Lang_CXX, Verifier,
1131 classTemplateDecl(hasAncestor(translationUnitDecl(
1132 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
1133}
1134
Gabor Marton19f4f392018-06-25 13:04:37 +00001135TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001136 MatchVerifier<Decl> Verifier;
1137 auto Code =
1138 R"s(
1139 struct declToImport {
1140 template <typename T0> struct X;
1141 template <typename T0> struct X<T0 *> {};
1142 };
1143 )s";
1144 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1145 recordDecl(has(classTemplateDecl()),
1146 has(classTemplateSpecializationDecl())));
1147}
1148
Gabor Marton19f4f392018-06-25 13:04:37 +00001149TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001150 MatchVerifier<Decl> Verifier;
1151 testImport("class declToImport {"
1152 " void f() { *this = declToImport(); }"
1153 "};",
1154 Lang_CXX, "", Lang_CXX, Verifier,
1155 cxxRecordDecl(has(cxxMethodDecl(hasBody(compoundStmt(
1156 has(exprWithCleanups(has(cxxOperatorCallExpr())))))))));
1157}
1158
Gabor Marton19f4f392018-06-25 13:04:37 +00001159TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001160 MatchVerifier<Decl> Verifier;
1161 testImport("template<typename T, int Size> class declToImport {"
1162 " T data[Size];"
1163 "};",
1164 Lang_CXX, "", Lang_CXX, Verifier,
1165 classTemplateDecl(has(cxxRecordDecl(
1166 has(fieldDecl(hasType(dependentSizedArrayType())))))));
1167}
1168
Gabor Martona0df7a92018-05-30 09:19:26 +00001169TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
1170 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1171 auto From =
1172 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1173 ASSERT_TRUE(From);
1174 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1175 ASSERT_TRUE(To);
1176 Decl *ToTemplated = To->getTemplatedDecl();
1177 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1178 EXPECT_TRUE(ToTemplated1);
1179 EXPECT_EQ(ToTemplated1, ToTemplated);
1180}
1181
Gabor Marton6578a4a2018-06-25 11:38:43 +00001182TEST_P(ASTImporterTestBase,
1183 DISABLED_ImportOfTemplatedDeclOfFunctionTemplateDecl) {
1184 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1185 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1186 FromTU, functionTemplateDecl());
1187 ASSERT_TRUE(From);
1188 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1189 ASSERT_TRUE(To);
1190 Decl *ToTemplated = To->getTemplatedDecl();
1191 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1192 EXPECT_TRUE(ToTemplated1);
1193 EXPECT_EQ(ToTemplated1, ToTemplated);
1194}
1195
1196TEST_P(ASTImporterTestBase,
1197 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1198 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1199 auto FromFT =
1200 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1201 ASSERT_TRUE(FromFT);
1202
1203 auto ToTemplated =
1204 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1205 EXPECT_TRUE(ToTemplated);
1206 auto ToTU = ToTemplated->getTranslationUnitDecl();
1207 auto ToFT =
1208 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1209 EXPECT_TRUE(ToFT);
1210}
1211
1212TEST_P(ASTImporterTestBase,
1213 DISABLED_ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
1214 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1215 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1216 FromTU, functionTemplateDecl());
1217 ASSERT_TRUE(FromFT);
1218
1219 auto ToTemplated =
1220 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1221 EXPECT_TRUE(ToTemplated);
1222 auto ToTU = ToTemplated->getTranslationUnitDecl();
1223 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1224 ToTU, functionTemplateDecl());
1225 EXPECT_TRUE(ToFT);
1226}
1227
Gabor Martona0df7a92018-05-30 09:19:26 +00001228TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
1229 auto Code =
1230 R"(
1231 namespace x {
1232 template<class X> struct S1{};
1233 template<class X> struct S2{};
1234 template<class X> struct S3{};
1235 }
1236 )";
1237 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1238 auto FromNs =
1239 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1240 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1241 ASSERT_TRUE(ToNs);
1242 auto From =
1243 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1244 classTemplateDecl(
1245 hasName("S2")));
1246 auto To =
1247 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1248 classTemplateDecl(
1249 hasName("S2")));
1250 ASSERT_TRUE(From);
1251 ASSERT_TRUE(To);
1252 auto ToTemplated = To->getTemplatedDecl();
1253 auto ToTemplated1 =
1254 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1255 EXPECT_TRUE(ToTemplated1);
1256 ASSERT_EQ(ToTemplated1, ToTemplated);
1257}
1258
Peter Szecsidedda6f2018-03-30 22:03:29 +00001259TEST_P(ASTImporterTestBase, DISABLED_ImportFunctionWithBackReferringParameter) {
1260 Decl *From, *To;
1261 std::tie(From, To) = getImportedDecl(
1262 R"(
1263 template <typename T> struct X {};
1264
1265 void declToImport(int y, X<int> &x) {}
1266
1267 template <> struct X<int> {
1268 void g() {
1269 X<int> x;
1270 declToImport(0, x);
1271 }
1272 };
1273 )",
1274 Lang_CXX, "", Lang_CXX);
1275
1276 MatchVerifier<Decl> Verifier;
1277 auto Matcher = functionDecl(hasName("declToImport"),
1278 parameterCountIs(2),
1279 hasParameter(0, hasName("y")),
1280 hasParameter(1, hasName("x")),
1281 hasParameter(1, hasType(asString("X<int> &"))));
1282 ASSERT_TRUE(Verifier.match(From, Matcher));
1283 EXPECT_TRUE(Verifier.match(To, Matcher));
1284}
1285
1286TEST_P(ASTImporterTestBase,
1287 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1288 Decl *From, *To;
1289 std::tie(From, To) =
1290 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1291 "void instantiate() { declToImport<int>(); }",
1292 Lang_CXX, "", Lang_CXX);
1293
1294 auto Check = [](Decl *D) -> bool {
1295 auto TU = D->getTranslationUnitDecl();
1296 for (auto Child : TU->decls()) {
1297 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1298 if (FD->getNameAsString() == "declToImport") {
1299 GTEST_NONFATAL_FAILURE_(
1300 "TU should not contain any FunctionDecl with name declToImport");
1301 return false;
1302 }
1303 }
1304 }
1305 return true;
1306 };
1307
1308 ASSERT_TRUE(Check(From));
1309 EXPECT_TRUE(Check(To));
1310}
1311
1312TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
1313 Decl *From, *To;
1314 std::tie(From, To) =
1315 getImportedDecl("template <typename T> struct declToImport { T t; };"
1316 "void instantiate() { declToImport<int>(); }",
1317 Lang_CXX, "", Lang_CXX);
1318
1319 auto Check = [](Decl *D) -> bool {
1320 auto TU = D->getTranslationUnitDecl();
1321 for (auto Child : TU->decls()) {
1322 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1323 if (RD->getNameAsString() == "declToImport") {
1324 GTEST_NONFATAL_FAILURE_(
1325 "TU should not contain any CXXRecordDecl with name declToImport");
1326 return false;
1327 }
1328 }
1329 }
1330 return true;
1331 };
1332
1333 ASSERT_TRUE(Check(From));
1334 EXPECT_TRUE(Check(To));
1335}
1336
1337TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
1338 Decl *From, *To;
1339 std::tie(From, To) =
1340 getImportedDecl(
1341 "template <typename T> struct X {};"
1342 "template <typename T> using declToImport = X<T>;"
1343 "void instantiate() { declToImport<int> a; }",
1344 Lang_CXX11, "", Lang_CXX11);
1345
1346 auto Check = [](Decl *D) -> bool {
1347 auto TU = D->getTranslationUnitDecl();
1348 for (auto Child : TU->decls()) {
1349 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1350 if (AD->getNameAsString() == "declToImport") {
1351 GTEST_NONFATAL_FAILURE_(
1352 "TU should not contain any TypeAliasDecl with name declToImport");
1353 return false;
1354 }
1355 }
1356 }
1357 return true;
1358 };
1359
1360 ASSERT_TRUE(Check(From));
1361 EXPECT_TRUE(Check(To));
1362}
1363
1364TEST_P(
1365 ASTImporterTestBase,
Gabor Martonb14056b2018-05-25 11:21:24 +00001366 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001367
1368 Decl *From, *To;
1369 std::tie(From, To) = getImportedDecl(
1370 R"(
1371 template<class T>
1372 class Base {};
1373 class declToImport : public Base<declToImport> {};
1374 )",
1375 Lang_CXX, "", Lang_CXX);
1376
1377 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1378 auto Pattern =
1379 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1380 ASSERT_TRUE(
1381 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1382 EXPECT_TRUE(
1383 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1384
1385 // Check that the ClassTemplateSpecializationDecl is the child of the
1386 // ClassTemplateDecl.
1387 Pattern = translationUnitDecl(has(classTemplateDecl(
1388 hasName("Base"), has(classTemplateSpecializationDecl()))));
1389 ASSERT_TRUE(
1390 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1391 EXPECT_TRUE(
1392 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1393}
1394
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001395AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1396 size_t Index = 0;
1397 for (FieldDecl *Field : Node.fields()) {
1398 if (Index == Order.size())
1399 return false;
1400 if (Field->getName() != Order[Index])
1401 return false;
1402 ++Index;
1403 }
1404 return Index == Order.size();
1405}
1406
Peter Szecsidedda6f2018-03-30 22:03:29 +00001407TEST_P(ASTImporterTestBase,
1408 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1409 Decl *From, *To;
1410 std::tie(From, To) = getImportedDecl(
1411 R"(
1412 namespace NS {
1413 template<class T>
1414 class X {};
1415 template class X<int>;
1416 }
1417 )",
1418 Lang_CXX, "", Lang_CXX, "NS");
1419
1420 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1421 // ClassTemplateDecl.
1422 auto Pattern = namespaceDecl(has(classTemplateDecl(
1423 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1424 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1425 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1426
1427 // Check that the ClassTemplateSpecializationDecl is the child of the
1428 // NamespaceDecl.
1429 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1430 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1431 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1432}
1433
1434TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1435 Decl *From, *To;
1436 std::tie(From, To) =
1437 getImportedDecl(
1438 "struct declToImport { int a; int b; };",
1439 Lang_CXX11, "", Lang_CXX11);
1440
1441 MatchVerifier<Decl> Verifier;
1442 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1443 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1444}
1445
1446TEST_P(ASTImporterTestBase,
1447 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1448 Decl *From, *To;
1449 std::tie(From, To) = getImportedDecl(
1450 // The original recursive algorithm of ASTImporter first imports 'c' then
1451 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1452 R"s(
1453 struct declToImport {
1454 int a = c + b;
1455 int b = 1;
1456 int c = 2;
1457 };
1458 )s",
1459 Lang_CXX11, "", Lang_CXX11);
1460
1461 MatchVerifier<Decl> Verifier;
1462 ASSERT_TRUE(
1463 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1464 EXPECT_TRUE(
1465 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1466}
1467
Gabor Martonde8bf262018-05-17 09:46:07 +00001468TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001469 Decl *From, *To;
1470 std::tie(From, To) = getImportedDecl(
1471 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001472 struct declToImport {
1473 };
1474 )",
1475 Lang_CXX, "", Lang_CXX);
1476
1477 MatchVerifier<Decl> Verifier;
1478 // Match the implicit Decl.
1479 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1480 ASSERT_TRUE(Verifier.match(From, Matcher));
1481 EXPECT_TRUE(Verifier.match(To, Matcher));
1482}
1483
1484TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1485 Decl *From, *To;
1486 std::tie(From, To) = getImportedDecl(
1487 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001488 template <typename U>
1489 struct declToImport {
1490 };
1491 )",
1492 Lang_CXX, "", Lang_CXX);
1493
1494 MatchVerifier<Decl> Verifier;
1495 // Match the implicit Decl.
1496 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1497 ASSERT_TRUE(Verifier.match(From, Matcher));
1498 EXPECT_TRUE(Verifier.match(To, Matcher));
1499}
1500
1501TEST_P(
1502 ASTImporterTestBase,
Gabor Martona3af5672018-05-23 14:24:02 +00001503 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001504 Decl *From, *To;
1505 std::tie(From, To) = getImportedDecl(
1506 R"(
1507 template<class T>
1508 class Base {};
1509 class declToImport : public Base<declToImport> {};
1510 )",
1511 Lang_CXX, "", Lang_CXX);
1512
1513 auto hasImplicitClass = has(cxxRecordDecl());
1514 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1515 hasName("Base"),
1516 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1517 ASSERT_TRUE(
1518 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1519 EXPECT_TRUE(
1520 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1521}
1522
1523TEST_P(ASTImporterTestBase, IDNSOrdinary) {
1524 Decl *From, *To;
1525 std::tie(From, To) =
1526 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1527
1528 MatchVerifier<Decl> Verifier;
1529 auto Matcher = functionDecl();
1530 ASSERT_TRUE(Verifier.match(From, Matcher));
1531 EXPECT_TRUE(Verifier.match(To, Matcher));
1532 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1533}
1534
Gabor Marton2ae9da32018-05-18 15:46:18 +00001535TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001536 Decl *FromTU = getTuDecl(
1537 R"(
1538 struct X {};
1539 void operator<<(int, X);
1540 )",
1541 Lang_CXX);
1542 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1543 const Decl *To = Import(From, Lang_CXX);
1544 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1545}
1546
1547TEST_P(ASTImporterTestBase,
1548 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1549 Decl *From, *To;
1550 std::tie(From, To) = getImportedDecl(
1551 R"(
1552 template<class T>
1553 class Base { int a; };
1554 class declToImport : Base<declToImport> {};
1555 )",
1556 Lang_CXX, "", Lang_CXX);
1557
1558 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1559 hasName("Base"),
1560 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1561 ASSERT_TRUE(
1562 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1563 EXPECT_TRUE(
1564 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1565}
1566
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001567TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
1568 {
1569 Decl *FromTU = getTuDecl(
1570 R"(
1571 template <typename T>
1572 struct B;
1573 )",
1574 Lang_CXX, "input0.cc");
1575 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1576 FromTU, classTemplateDecl(hasName("B")));
1577
1578 Import(FromD, Lang_CXX);
1579 }
1580
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 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1591 FromTU, functionDecl(hasName("f")));
1592 Import(FromD, Lang_CXX);
1593 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1594 FromTU, classTemplateDecl(hasName("B")));
1595 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1596 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1597 }
1598}
1599
Gabor Marton9581c332018-05-23 13:53:36 +00001600TEST_P(ASTImporterTestBase,
1601 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1602 Decl *ToTU = getToTuDecl(
1603 R"(
1604 template <typename T>
1605 struct B {
1606 void f();
1607 };
1608
1609 template <typename T>
1610 struct B;
1611 )",
1612 Lang_CXX);
1613 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1614 [](const ClassTemplateDecl *T) {
1615 return T->isThisDeclarationADefinition();
1616 })
1617 .match(ToTU, classTemplateDecl()));
1618
1619 Decl *FromTU = getTuDecl(
1620 R"(
1621 template <typename T>
1622 struct B {
1623 void f();
1624 };
1625 )",
1626 Lang_CXX, "input1.cc");
1627 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1628 FromTU, classTemplateDecl(hasName("B")));
1629
1630 Import(FromD, Lang_CXX);
1631
1632 // We should have only one definition.
1633 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1634 [](const ClassTemplateDecl *T) {
1635 return T->isThisDeclarationADefinition();
1636 })
1637 .match(ToTU, classTemplateDecl()));
1638}
1639
1640TEST_P(ASTImporterTestBase,
1641 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1642 Decl *ToTU = getToTuDecl(
1643 R"(
1644 struct B {
1645 void f();
1646 };
1647
1648 struct B;
1649 )",
1650 Lang_CXX);
1651 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001652 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001653
1654 Decl *FromTU = getTuDecl(
1655 R"(
1656 struct B {
1657 void f();
1658 };
1659 )",
1660 Lang_CXX, "input1.cc");
1661 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1662 FromTU, cxxRecordDecl(hasName("B")));
1663
1664 Import(FromD, Lang_CXX);
1665
1666 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001667 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001668}
1669
1670TEST_P(
1671 ASTImporterTestBase,
1672 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
1673{
1674 Decl *ToTU = getToTuDecl(
1675 R"(
1676 template <typename T>
1677 struct B;
1678
1679 template <>
1680 struct B<int> {};
1681
1682 template <>
1683 struct B<int>;
1684 )",
1685 Lang_CXX);
1686 // We should have only one definition.
1687 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1688 [](const ClassTemplateSpecializationDecl *T) {
1689 return T->isThisDeclarationADefinition();
1690 })
1691 .match(ToTU, classTemplateSpecializationDecl()));
1692
1693 Decl *FromTU = getTuDecl(
1694 R"(
1695 template <typename T>
1696 struct B;
1697
1698 template <>
1699 struct B<int> {};
1700 )",
1701 Lang_CXX, "input1.cc");
1702 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1703 FromTU, classTemplateSpecializationDecl(hasName("B")));
1704
1705 Import(FromD, Lang_CXX);
1706
1707 // We should have only one definition.
1708 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1709 [](const ClassTemplateSpecializationDecl *T) {
1710 return T->isThisDeclarationADefinition();
1711 })
1712 .match(ToTU, classTemplateSpecializationDecl()));
1713}
1714
Peter Szecsidedda6f2018-03-30 22:03:29 +00001715struct ImportFunctions : ASTImporterTestBase {};
1716
1717TEST_P(ImportFunctions,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001718 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1719 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1720 auto Pattern = functionDecl(hasName("f"));
1721 FunctionDecl *FromD = // Definition
1722 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1723
1724 Decl *ImportedD = Import(FromD, Lang_CXX);
1725 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1726
Gabor Marton5254e642018-06-27 13:32:50 +00001727 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001728 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1729}
1730
1731TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1732 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1733 auto Pattern = functionDecl(hasName("f"));
1734 FunctionDecl *FromD =
1735 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1736
1737 Decl *ImportedD = Import(FromD, Lang_CXX);
1738 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1739
1740 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1741 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1742}
1743
Gabor Marton5254e642018-06-27 13:32:50 +00001744TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001745 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1746 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001747 auto *From =
1748 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00001749
Gabor Marton5254e642018-06-27 13:32:50 +00001750 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001751 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1752
Gabor Marton5254e642018-06-27 13:32:50 +00001753 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1754 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1755 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1756 EXPECT_TRUE(ImportedD == To0);
1757 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1758 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1759 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001760}
1761
1762TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1763 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1764 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001765 auto *From =
1766 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00001767
Gabor Marton5254e642018-06-27 13:32:50 +00001768 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001769 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1770
Gabor Marton5254e642018-06-27 13:32:50 +00001771 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1772 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1773 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1774 EXPECT_TRUE(ImportedD == To1);
1775 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1776 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1777 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001778}
1779
1780TEST_P(ImportFunctions, ImportPrototypes) {
1781 auto Pattern = functionDecl(hasName("f"));
1782
1783 Decl *ImportedD;
1784 {
1785 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001786 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001787
1788 ImportedD = Import(FromD, Lang_CXX);
1789 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001790 {
1791 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001792 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1793 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001794 }
1795
Gabor Marton5254e642018-06-27 13:32:50 +00001796 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1797
1798 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1799 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1800 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1801 EXPECT_TRUE(ImportedD == To0);
1802 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1803 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1804 EXPECT_EQ(To1->getPreviousDecl(), To0);
1805}
1806
1807TEST_P(ImportFunctions, ImportDefinitions) {
1808 auto Pattern = functionDecl(hasName("f"));
1809
1810 Decl *ImportedD;
1811 {
1812 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
1813 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1814 ImportedD = Import(FromD, Lang_CXX);
1815 }
1816 {
1817 Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");
1818 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1819 Import(FromD, Lang_CXX);
1820 }
1821
1822 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1823
Peter Szecsidedda6f2018-03-30 22:03:29 +00001824 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Gabor Marton5254e642018-06-27 13:32:50 +00001825 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1826 EXPECT_TRUE(ImportedD == To0);
1827 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00001828}
1829
1830TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
1831 auto Pattern = functionDecl(hasName("f"));
1832
1833 Decl *ImportedD;
1834 {
1835 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001836 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001837 ImportedD = Import(FromD, Lang_CXX);
1838 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001839 {
1840 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001841 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1842 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001843 }
1844
1845 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00001846
1847 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1848 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1849 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1850 EXPECT_TRUE(ImportedD == To0);
1851 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
1852 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1853 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001854}
1855
1856TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
1857 auto Pattern = functionDecl(hasName("f"));
1858
1859 {
1860 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1861 FunctionDecl *FromD =
1862 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1863
1864 Import(FromD, Lang_CXX);
1865 }
1866 {
1867 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
1868 FunctionDecl *FromD =
1869 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1870 Import(FromD, Lang_CXX);
1871 }
1872
1873 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1874 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1875 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00001876 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00001877 FunctionDecl *DefinitionD =
1878 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1879 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
1880 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
1881}
1882
Gabor Marton5254e642018-06-27 13:32:50 +00001883TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001884 auto Pattern = functionDecl(hasName("f"));
1885
1886 {
1887 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001888 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001889 Import(FromD, Lang_CXX);
1890 }
1891 {
1892 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001893 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001894 Import(FromD, Lang_CXX);
1895 }
1896
1897 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00001898
1899 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001900 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00001901 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
1902
Peter Szecsidedda6f2018-03-30 22:03:29 +00001903 FunctionDecl *DefinitionD =
1904 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1905 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
Gabor Marton5254e642018-06-27 13:32:50 +00001906
1907 EXPECT_TRUE(DefinitionD->getPreviousDecl());
1908 EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());
1909 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001910}
1911
1912TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
1913 auto Code =
1914 R"(
1915 struct B { virtual void f(); };
1916 void B::f() {}
1917 struct D : B { void f(); };
1918 )";
1919 auto Pattern =
1920 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
1921 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1922 CXXMethodDecl *Proto =
1923 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1924
1925 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
1926 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1927 EXPECT_EQ(To->size_overridden_methods(), 1u);
1928}
1929
1930TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
1931 auto Code =
1932 R"(
1933 struct B { virtual void f(); };
1934 void B::f() {}
1935 )";
1936 auto Pattern =
1937 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1938 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1939 CXXMethodDecl *Proto =
1940 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1941 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1942
1943 ASSERT_TRUE(Proto->isVirtual());
1944 ASSERT_TRUE(Def->isVirtual());
1945 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1946 EXPECT_TRUE(To->isVirtual());
1947}
1948
Gabor Marton5254e642018-06-27 13:32:50 +00001949TEST_P(ImportFunctions,
1950 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
1951 Decl *ToTU = getToTuDecl(
1952 R"(
1953 void f() {}
1954 void f();
1955 )",
1956 Lang_CXX);
1957 ASSERT_EQ(1u,
1958 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
1959 return FD->doesThisDeclarationHaveABody();
1960 }).match(ToTU, functionDecl()));
1961
1962 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
1963 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1964
1965 Import(FromD, Lang_CXX);
1966
1967 EXPECT_EQ(1u,
1968 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
1969 return FD->doesThisDeclarationHaveABody();
1970 }).match(ToTU, functionDecl()));
1971}
1972
1973struct ImportFriendFunctions : ImportFunctions {};
1974
1975TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
1976 auto Pattern = functionDecl(hasName("f"));
1977
1978 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
1979 "void f();",
1980 Lang_CXX,
1981 "input0.cc");
1982 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1983
1984 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
1985 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1986 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1987 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
1988 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1989 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
1990 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
1991}
1992
1993TEST_P(ImportFriendFunctions,
1994 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
1995 auto Pattern = functionDecl(hasName("f"));
1996
1997 Decl *FromTU = getTuDecl("void f();"
1998 "struct X { friend void f(); };",
1999 Lang_CXX, "input0.cc");
2000 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2001
2002 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2003 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2004 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2005 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2006 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2007 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2008 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2009}
2010
2011TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2012 auto Pattern = functionDecl(hasName("f"));
2013
2014 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2015 "void f();",
2016 Lang_CXX,
2017 "input0.cc");
2018 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2019
2020 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2021 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2022 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2023 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2024 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2025 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2026 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2027}
2028
2029TEST_P(ImportFriendFunctions,
2030 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2031 auto Pattern = functionDecl(hasName("f"));
2032
2033 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2034 "void f(){}",
2035 Lang_CXX, "input0.cc");
2036 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2037
2038 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2039 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2040 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2041 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2042 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2043 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2044 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2045}
2046
2047// This test is disabled, because ATM we create a redundant FunctionDecl. We
2048// start the import with the definition of `f` then we continue with the import
2049// of the type of `f` which involves `X`. During the import of `X` we start
2050// again the import of the definition of `f` and then finally we create the
2051// node. But then in the first frame of `VisitFunctionDecl` we create a node
2052// again since we do not check if such a node exists yet or not. This is being
2053// fixed in a separate patch: https://reviews.llvm.org/D47632
2054// FIXME enable this test once the above patch is approved.
2055TEST_P(ImportFriendFunctions,
2056 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2057 auto Pattern = functionDecl(hasName("f"));
2058
2059 Decl *FromTU = getTuDecl(
2060 R"(
2061 class X;
2062 void f(X *x){}
2063 class X{
2064 friend void f(X *x);
2065 };
2066 )",
2067 Lang_CXX, "input0.cc");
2068 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2069
2070 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2071 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2072 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2073 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2074 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2075 .match(ToTU, friendDecl())
2076 ->getFriendDecl());
2077 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2078 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2079 // The parameters must refer the same type
2080 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2081 (*ImportedD->param_begin())->getOriginalType());
2082}
2083
2084// This test is disabled, because ATM we create a redundant FunctionDecl. We
2085// start the import with the definition of `f` then we continue with the import
2086// of the type of `f` which involves `X`. During the import of `X` we start
2087// again the import of the definition of `f` and then finally we create the
2088// node. But then in the first frame of `VisitFunctionDecl` we create a node
2089// again since we do not check if such a node exists yet or not. This is being
2090// fixed in a separate patch: https://reviews.llvm.org/D47632
2091// FIXME enable this test once the above patch is approved.
2092TEST_P(ImportFriendFunctions,
2093 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
2094 auto Pattern = functionDecl(hasName("f"));
2095
2096 Decl *FromTU = getTuDecl(
2097 R"(
2098 class X;
2099 void f(X *x){}
2100 class X{
2101 friend void f(X *x);
2102 };
2103 )",
2104 Lang_CXX, "input0.cc");
2105 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2106
2107 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2108 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2109 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2110 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2111 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2112 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2113
2114 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2115 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2116 // The parameters must refer the same type
2117 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2118 (*ImportedD->param_begin())->getOriginalType());
2119}
2120
2121TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2122 auto Pattern = functionDecl(hasName("f"));
2123
2124 FunctionDecl *ImportedD;
2125 {
2126 Decl *FromTU =
2127 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2128 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2129 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2130 }
2131 FunctionDecl *ImportedD1;
2132 {
2133 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2134 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2135 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2136 }
2137
2138 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2139 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2140 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2141 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2142 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2143}
2144
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002145AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2146 InnerMatcher) {
2147 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2148 return InnerMatcher.matches(*Typedef, Finder, Builder);
2149 return false;
2150}
2151
Gabor Marton19f4f392018-06-25 13:04:37 +00002152TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002153 CodeFiles Samples{{"main.c",
2154 {"void foo();"
2155 "void moo();"
2156 "int main() { foo(); moo(); }",
2157 Lang_C}},
2158
2159 {"foo.c",
2160 {"typedef enum { THING_VALUE } thing_t;"
2161 "void conflict(thing_t type);"
2162 "void foo() { (void)THING_VALUE; }"
2163 "void conflict(thing_t type) {}",
2164 Lang_C}},
2165
2166 {"moo.c",
2167 {"typedef enum { THING_VALUE } thing_t;"
2168 "void conflict(thing_t type);"
2169 "void moo() { conflict(THING_VALUE); }",
2170 Lang_C}}};
2171
2172 auto VerificationMatcher =
2173 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2174 hasTypedefForAnonDecl(hasName("thing_t")));
2175
2176 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2177 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2178
2179 testImportSequence(
2180 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2181 // Just check that there is only one enum decl in the result AST.
2182 "main.c", enumDecl(), VerificationMatcher);
2183
2184 // For different import order, result should be the same.
2185 testImportSequence(
2186 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2187 // Check that there is only one enum decl in the result AST.
2188 "main.c", enumDecl(), VerificationMatcher);
2189}
2190
Peter Szecsice7f3182018-05-07 12:08:27 +00002191const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2192 dependentScopeDeclRefExpr;
2193
Gabor Marton19f4f392018-06-25 13:04:37 +00002194TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002195 MatchVerifier<Decl> Verifier;
2196 testImport("template <typename T> struct S { static T foo; };"
2197 "template <typename T> void declToImport() {"
2198 " (void) S<T>::foo;"
2199 "}"
2200 "void instantiate() { declToImport<int>(); }",
2201 Lang_CXX11, "", Lang_CXX11, Verifier,
2202 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2203 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2204
2205 testImport("template <typename T> struct S {"
2206 "template<typename S> static void foo(){};"
2207 "};"
2208 "template <typename T> void declToImport() {"
2209 " S<T>::template foo<T>();"
2210 "}"
2211 "void instantiate() { declToImport<int>(); }",
2212 Lang_CXX11, "", Lang_CXX11, Verifier,
2213 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2214 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2215}
2216
2217const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2218 dependentNameType;
2219
Gabor Marton19f4f392018-06-25 13:04:37 +00002220TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002221 MatchVerifier<Decl> Verifier;
2222 testImport("template <typename T> struct declToImport {"
2223 " typedef typename T::type dependent_name;"
2224 "};",
2225 Lang_CXX11, "", Lang_CXX11, Verifier,
2226 classTemplateDecl(has(
2227 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2228}
2229
2230const internal::VariadicDynCastAllOfMatcher<Expr, UnresolvedMemberExpr>
2231 unresolvedMemberExpr;
2232
Gabor Marton19f4f392018-06-25 13:04:37 +00002233TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002234 MatchVerifier<Decl> Verifier;
2235 testImport("struct S { template <typename T> void mem(); };"
2236 "template <typename U> void declToImport() {"
2237 " S s;"
2238 " s.mem<U>();"
2239 "}"
2240 "void instantiate() { declToImport<int>(); }",
2241 Lang_CXX11, "", Lang_CXX11, Verifier,
2242 functionTemplateDecl(has(functionDecl(has(
2243 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2244}
2245
Gabor Marton61d862a2018-05-18 09:08:47 +00002246struct DeclContextTest : ASTImporterTestBase {};
2247
2248TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
2249 Decl *TU = getTuDecl(
2250 R"(
2251 namespace NS {
2252
2253 template <typename T>
2254 struct S {};
2255 template struct S<int>;
2256
2257 inline namespace INS {
2258 template <typename T>
2259 struct S {};
2260 template struct S<int>;
2261 }
2262
2263 }
2264 )", Lang_CXX11, "input0.cc");
2265 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
2266 TU, namespaceDecl());
2267 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
2268 TU, classTemplateSpecializationDecl());
2269 ASSERT_TRUE(NS->containsDecl(Spec));
2270
2271 NS->removeDecl(Spec);
2272 EXPECT_FALSE(NS->containsDecl(Spec));
2273}
2274
Gabor Marton5254e642018-06-27 13:32:50 +00002275struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
2276
2277TEST_P(ImportFunctionTemplateSpecializations,
2278 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
2279
2280 Decl *FromTU = getTuDecl(
2281 R"(
2282 template<class T>
2283 int f() { return 0; }
2284 void foo() { f<int>(); }
2285 )",
2286 Lang_CXX, "input0.cc");
2287
2288 // Check that the function template instantiation is NOT the child of the TU.
2289 auto Pattern = translationUnitDecl(
2290 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
2291 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2292
2293 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
2294 FromTU, functionDecl(hasName("foo")));
2295 ASSERT_TRUE(Import(Foo, Lang_CXX));
2296
2297 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2298 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2299}
2300
2301TEST_P(ImportFunctionTemplateSpecializations,
2302 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
2303
2304 Decl *FromTU = getTuDecl(
2305 R"(
2306 template<class T>
2307 int f() { return 0; }
2308 template int f<int>();
2309 )",
2310 Lang_CXX, "input0.cc");
2311
2312 // Check that the function template instantiation is NOT the child of the TU.
2313 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
2314 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
2315 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2316
2317 ASSERT_TRUE(
2318 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
2319
2320 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2321 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2322}
2323
2324TEST_P(ImportFunctionTemplateSpecializations,
2325 TUshouldContainFunctionTemplateSpecialization) {
2326
2327 Decl *FromTU = getTuDecl(
2328 R"(
2329 template<class T>
2330 int f() { return 0; }
2331 template <> int f<int>() { return 4; }
2332 )",
2333 Lang_CXX, "input0.cc");
2334
2335 // Check that the function template specialization is the child of the TU.
2336 auto Specialization =
2337 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2338 auto Pattern = translationUnitDecl(has(Specialization));
2339 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2340
2341 ASSERT_TRUE(
2342 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
2343
2344 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2345 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2346}
2347
2348TEST_P(ImportFunctionTemplateSpecializations,
2349 FunctionTemplateSpecializationRedeclChain) {
2350
2351 Decl *FromTU = getTuDecl(
2352 R"(
2353 template<class T>
2354 int f() { return 0; }
2355 template <> int f<int>() { return 4; }
2356 )",
2357 Lang_CXX, "input0.cc");
2358
2359 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
2360 hasParent(translationUnitDecl()));
2361 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
2362 {
2363 auto *TU = FromTU;
2364 auto *SpecD = FromSpecD;
2365 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2366 TU, functionTemplateDecl());
2367 auto *FirstSpecD = *(TemplateD->spec_begin());
2368 ASSERT_EQ(SpecD, FirstSpecD);
2369 ASSERT_TRUE(SpecD->getPreviousDecl());
2370 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
2371 ->doesThisDeclarationHaveABody());
2372 }
2373
2374 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
2375
2376 {
2377 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
2378 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
2379 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2380 TU, functionTemplateDecl());
2381 auto *FirstSpecD = *(TemplateD->spec_begin());
2382 EXPECT_EQ(SpecD, FirstSpecD);
2383 ASSERT_TRUE(SpecD->getPreviousDecl());
2384 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
2385 ->doesThisDeclarationHaveABody());
2386 }
2387}
2388
2389TEST_P(ImportFunctionTemplateSpecializations,
2390 MatchNumberOfFunctionTemplateSpecializations) {
2391
2392 Decl *FromTU = getTuDecl(
2393 R"(
2394 template <typename T> constexpr int f() { return 0; }
2395 template <> constexpr int f<int>() { return 4; }
2396 void foo() {
2397 static_assert(f<char>() == 0, "");
2398 static_assert(f<int>() == 4, "");
2399 }
2400 )",
2401 Lang_CXX11, "input0.cc");
2402 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2403 FromTU, functionDecl(hasName("foo")));
2404
2405 Import(FromD, Lang_CXX11);
2406 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2407 EXPECT_EQ(
2408 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
2409 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
2410}
2411
2412TEST_P(ImportFunctionTemplateSpecializations,
2413 ImportPrototypes) {
2414 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2415 auto Code =
2416 R"(
2417 // Proto of the primary template.
2418 template <class T>
2419 void f();
2420 // Proto of the specialization.
2421 template <>
2422 void f<int>();
2423 )";
2424
2425 Decl *ImportedD;
2426 {
2427 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2428 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2429
2430 ImportedD = Import(FromD, Lang_CXX);
2431 }
2432 {
2433 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
2434 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2435 Import(FromD, Lang_CXX);
2436 }
2437
2438 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2439
2440 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2441 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2442 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2443 EXPECT_TRUE(ImportedD == To0);
2444 EXPECT_TRUE(ImportedD != To1);
2445 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2446 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2447 // Check that they are part of the same redecl chain.
2448 EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
2449}
2450
2451TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
2452 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2453 auto Code =
2454 R"(
2455 // Proto of the primary template.
2456 template <class T>
2457 void f();
2458 // Specialization and definition.
2459 template <>
2460 void f<int>() {}
2461 )";
2462
2463 Decl *ImportedD;
2464 {
2465 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2466 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2467 ImportedD = Import(FromD, Lang_CXX);
2468 }
2469 {
2470 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
2471 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2472 Import(FromD, Lang_CXX);
2473 }
2474
2475 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2476
2477 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
2478 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2479 EXPECT_TRUE(ImportedD == To0);
2480 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2481
2482 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2483 ToTU, functionTemplateDecl());
2484 auto *FirstSpecD = *(TemplateD->spec_begin());
2485 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
2486}
2487
2488TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
2489 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2490 auto Code =
2491 R"(
2492 // Proto of the primary template.
2493 template <class T>
2494 void f();
2495 // Specialization proto.
2496 template <>
2497 void f<int>();
2498 // Specialization proto.
2499 template <>
2500 void f<int>();
2501 )";
2502
2503 Decl *ImportedD;
2504 {
2505 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2506 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2507 ImportedD = Import(FromD, Lang_CXX);
2508 }
2509
2510 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2511
2512 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2513 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2514 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2515 EXPECT_TRUE(ImportedD == To0);
2516 EXPECT_TRUE(ImportedD != To1);
2517 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2518 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2519 EXPECT_EQ(To1->getPreviousDecl(), To0);
2520}
2521
2522TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
2523 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2524 auto Code =
2525 R"(
2526 // Proto of the primary template.
2527 template <class T>
2528 void f();
2529 // Specialization proto.
2530 template <>
2531 void f<int>();
2532 // Specialization definition.
2533 template <>
2534 void f<int>() {}
2535 )";
2536
2537 Decl *ImportedD;
2538 {
2539 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2540 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2541 ImportedD = Import(FromD, Lang_CXX);
2542 }
2543
2544 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2545
2546 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2547 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2548 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2549 EXPECT_TRUE(ImportedD == To0);
2550 EXPECT_TRUE(ImportedD != To1);
2551 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2552 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2553 EXPECT_EQ(To1->getPreviousDecl(), To0);
2554}
2555
2556TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
2557 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2558 auto Code =
2559 R"(
2560 // Proto of the primary template.
2561 template <class T>
2562 void f();
2563 // Specialization definition.
2564 template <>
2565 void f<int>() {}
2566 // Specialization proto.
2567 template <>
2568 void f<int>();
2569 )";
2570
2571 Decl *ImportedD;
2572 {
2573 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2574 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2575 ImportedD = Import(FromD, Lang_CXX);
2576 }
2577
2578 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2579
2580 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2581 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2582 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2583 EXPECT_TRUE(ImportedD == To0);
2584 EXPECT_TRUE(ImportedD != To1);
2585 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2586 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2587 EXPECT_EQ(To1->getPreviousDecl(), To0);
2588}
2589
Gabor Marton19f4f392018-06-25 13:04:37 +00002590INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
2591 ::testing::Values(ArgVector()), );
2592
Gabor Marton5254e642018-06-27 13:32:50 +00002593INSTANTIATE_TEST_CASE_P(
2594 ParameterizedTests, CanonicalRedeclChain,
2595 ::testing::Values(ArgVector()),);
2596
Gabor Marton19f4f392018-06-25 13:04:37 +00002597auto DefaultTestValuesForRunOptions = ::testing::Values(
2598 ArgVector(),
2599 ArgVector{"-fdelayed-template-parsing"},
2600 ArgVector{"-fms-compatibility"},
2601 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
2602
2603INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
2604 DefaultTestValuesForRunOptions, );
2605
2606INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
2607 DefaultTestValuesForRunOptions, );
2608
2609INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
2610 DefaultTestValuesForRunOptions, );
2611
2612INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
2613 DefaultTestValuesForRunOptions, );
2614
2615INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
2616 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00002617
Gabor Marton5254e642018-06-27 13:32:50 +00002618INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
2619 DefaultTestValuesForRunOptions, );
2620
2621INSTANTIATE_TEST_CASE_P(ParameterizedTests,
2622 ImportFunctionTemplateSpecializations,
2623 DefaultTestValuesForRunOptions, );
2624
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00002625} // end namespace ast_matchers
2626} // end namespace clang