blob: 50f7285a39015e06dcf7be92b37bcad13d958efb [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
Balazs Keri21f938c2018-07-02 14:14:07 +0000277// attributes of AST nodes like getPreviousDecl(), isVirtual(), etc. Also,
Peter Szecsidedda6f2018-03-30 22:03:29 +0000278// 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;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000475 testImport(
476 "void declToImport() { (void)\"foo\"; }",
477 Lang_CXX, "", Lang_CXX, Verifier,
478 functionDecl(hasDescendant(
479 stringLiteral(hasType(asString("const char [4]"))))));
480 testImport(
481 "void declToImport() { (void)L\"foo\"; }",
482 Lang_CXX, "", Lang_CXX, Verifier,
483 functionDecl(hasDescendant(
484 stringLiteral(hasType(asString("const wchar_t [4]"))))));
485 testImport(
486 "void declToImport() { (void) \"foo\" \"bar\"; }",
487 Lang_CXX, "", Lang_CXX, Verifier,
488 functionDecl(hasDescendant(
489 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000490}
491
Gabor Marton19f4f392018-06-25 13:04:37 +0000492TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000493 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000494 testImport(
495 "void declToImport() { (void)__null; }",
496 Lang_CXX, "", Lang_CXX, Verifier,
497 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000498}
499
Gabor Marton19f4f392018-06-25 13:04:37 +0000500TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000501 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000502 testImport(
503 "void declToImport() { (void)nullptr; }",
504 Lang_CXX11, "", Lang_CXX11, Verifier,
505 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000506}
507
508
Gabor Marton19f4f392018-06-25 13:04:37 +0000509TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000510 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000511 testImport(
512 "void declToImport() { (void)1.0; }",
513 Lang_C, "", Lang_C, Verifier,
514 functionDecl(hasDescendant(
515 floatLiteral(equals(1.0), hasType(asString("double"))))));
516 testImport(
517 "void declToImport() { (void)1.0e-5f; }",
518 Lang_C, "", Lang_C, Verifier,
519 functionDecl(hasDescendant(
520 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000521}
522
Gabor Marton19f4f392018-06-25 13:04:37 +0000523TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000524 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000525 testImport(
526 "void declToImport() {"
527 " struct s { int x; long y; unsigned z; }; "
528 " (void)(struct s){ 42, 0L, 1U }; }",
529 Lang_CXX, "", Lang_CXX, Verifier,
530 functionDecl(hasDescendant(
531 compoundLiteralExpr(
532 hasType(asString("struct s")),
533 has(initListExpr(
534 hasType(asString("struct s")),
535 has(integerLiteral(
536 equals(42), hasType(asString("int")))),
537 has(integerLiteral(
538 equals(0), hasType(asString("long")))),
539 has(integerLiteral(
540 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000541}
542
Gabor Marton19f4f392018-06-25 13:04:37 +0000543TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000544 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000545 testImport(
546 "class declToImport { void f() { (void)this; } };",
547 Lang_CXX, "", Lang_CXX, Verifier,
548 cxxRecordDecl(
549 hasMethod(
550 hasDescendant(
551 cxxThisExpr(
552 hasType(
553 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000554}
555
Gabor Marton19f4f392018-06-25 13:04:37 +0000556TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000557 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000558 testImport(
559 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
560 Lang_C, "", Lang_C, Verifier,
561 functionDecl(hasDescendant(
562 atomicExpr(
563 has(ignoringParenImpCasts(
564 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
565 hasType(asString("int *"))))),
566 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000567}
568
Gabor Marton19f4f392018-06-25 13:04:37 +0000569TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000570 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000571 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000572 "void declToImport() { loop: goto loop; (void)&&loop; }",
573 Lang_C, "", Lang_C, Verifier,
574 functionDecl(
575 hasDescendant(
576 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
577 hasDescendant(
578 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000579}
580
581AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
582 internal::Matcher<NamedDecl>, InnerMatcher) {
583 const NamedDecl *Template = Node.getTemplatedDecl();
584 return Template && InnerMatcher.matches(*Template, Finder, Builder);
585}
586
Gabor Marton19f4f392018-06-25 13:04:37 +0000587TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000588 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000589 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000590 "template<typename T> class dummy { void f() { dummy X(*this); } };"
591 "typedef dummy<int> declToImport;"
592 "template class dummy<int>;",
593 Lang_CXX, "", Lang_CXX, Verifier,
594 typedefDecl(hasType(templateSpecializationType(
595 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
596 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
597 hasName("f"),
598 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
599 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
600 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000601 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000602}
603
Gabor Marton19f4f392018-06-25 13:04:37 +0000604TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000605 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000606 testImport(
607 "void declToImport() { int b; switch (b) { case 1: break; } }",
608 Lang_C, "", Lang_C, Verifier,
609 functionDecl(hasDescendant(
610 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000611}
612
Gabor Marton19f4f392018-06-25 13:04:37 +0000613TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000614 MatchVerifier<Decl> Verifier;
615 // NOTE: has() ignores implicit casts, using hasDescendant() to match it
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000616 testImport(
617 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
618 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000619 functionDecl(hasDescendant(
620 varDecl(
621 hasName("C"),
622 hasType(asString("int")),
623 hasInitializer(
624 stmtExpr(
625 hasAnySubstatement(declStmt(hasSingleDecl(
626 varDecl(
627 hasName("X"),
628 hasType(asString("int")),
629 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000630 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000631 hasDescendant(
632 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000633}
634
Gabor Marton19f4f392018-06-25 13:04:37 +0000635TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000636 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000637 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000638 "void declToImport() { (void)(true ? 1 : -5); }",
639 Lang_CXX, "", Lang_CXX, Verifier,
640 functionDecl(hasDescendant(
641 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000642 hasCondition(cxxBoolLiteral(equals(true))),
643 hasTrueExpression(integerLiteral(equals(1))),
644 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000645 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
646 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000647}
648
Gabor Marton19f4f392018-06-25 13:04:37 +0000649TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000650 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000651 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000652 "void declToImport() { (void)(1 ?: -5); }",
653 Lang_CXX, "", Lang_CXX, Verifier,
654 functionDecl(hasDescendant(
655 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000656 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000657 implicitCastExpr(
658 hasSourceExpression(opaqueValueExpr(
659 hasSourceExpression(integerLiteral(equals(1))))),
660 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000661 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000662 opaqueValueExpr(
663 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000664 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000665 unaryOperator(
666 hasOperatorName("-"),
667 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000668}
669
Gabor Marton19f4f392018-06-25 13:04:37 +0000670TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000671 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000672 testImport(
673 "void declToImport() {"
674 " struct point { double x; double y; };"
675 " struct point ptarray[10] = "
676 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
677 Lang_C, "", Lang_C, Verifier,
678 functionDecl(hasDescendant(
679 initListExpr(
680 has(designatedInitExpr(
681 designatorCountIs(2),
682 has(floatLiteral(equals(1.0))),
683 has(integerLiteral(equals(2))))),
684 has(designatedInitExpr(
685 designatorCountIs(2),
686 has(floatLiteral(equals(2.0))),
687 has(integerLiteral(equals(2))))),
688 has(designatedInitExpr(
689 designatorCountIs(2),
690 has(floatLiteral(equals(1.0))),
691 has(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000692}
693
694
Gabor Marton19f4f392018-06-25 13:04:37 +0000695TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000696 MatchVerifier<Decl> Verifier;
697 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000698 testImport(
699 "void declToImport() { (void)__func__; }",
700 Lang_CXX, "", Lang_CXX, Verifier,
701 functionDecl(hasDescendant(
702 predefinedExpr(
703 hasType(
704 asString("const char [13]")),
705 has(stringLiteral(hasType(
706 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000707}
708
Gabor Marton19f4f392018-06-25 13:04:37 +0000709TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000710 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000711 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000712 "void declToImport() {"
713 " struct point { double x; double y; };"
714 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
715 " [0].x = 1.0 }; }",
716 Lang_CXX, "", Lang_CXX, Verifier,
717 functionDecl(hasDescendant(
718 initListExpr(
719 has(
720 cxxConstructExpr(
721 requiresZeroInitialization())),
722 has(
723 initListExpr(
724 hasType(asString("struct point")),
725 has(floatLiteral(equals(1.0))),
726 has(implicitValueInitExpr(
727 hasType(asString("double")))))),
728 has(
729 initListExpr(
730 hasType(asString("struct point")),
731 has(floatLiteral(equals(2.0))),
732 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000733}
734
735
Aleksei Sidorina693b372016-09-28 10:16:56 +0000736const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
737
Gabor Marton19f4f392018-06-25 13:04:37 +0000738TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000739 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000740 testImport(
741 "void declToImport(__builtin_va_list list, ...) {"
742 " (void)__builtin_va_arg(list, int); }",
743 Lang_CXX, "", Lang_CXX, Verifier,
744 functionDecl(hasDescendant(
745 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000746}
747
Gabor Marton19f4f392018-06-25 13:04:37 +0000748TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000749 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000750 testImport(
751 "struct C {};"
752 "void declToImport() { C c = C(); }",
753 Lang_CXX, "", Lang_CXX, Verifier,
754 functionDecl(hasDescendant(
755 exprWithCleanups(has(cxxConstructExpr(
756 has(materializeTemporaryExpr(has(implicitCastExpr(
757 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000758}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000759
Gabor Marton19f4f392018-06-25 13:04:37 +0000760TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000761 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000762 testImport(
763 "void declToImport() { typedef _Atomic(int) a_int; }",
764 Lang_CXX11, "", Lang_CXX11, Verifier,
765 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000766}
767
Gabor Marton19f4f392018-06-25 13:04:37 +0000768TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000769 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000770 testImport(
771 "template <typename T> void declToImport() { };",
772 Lang_CXX, "", Lang_CXX, Verifier,
773 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000774}
775
776const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
777 cxxDependentScopeMemberExpr;
778
Gabor Marton19f4f392018-06-25 13:04:37 +0000779TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000780 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000781 testImport(
782 "template <typename T> struct C { T t; };"
783 "template <typename T> void declToImport() {"
784 " C<T> d;"
785 " (void)d.t;"
786 "}"
787 "void instantiate() { declToImport<int>(); }",
788 Lang_CXX, "", Lang_CXX, Verifier,
789 functionTemplateDecl(hasDescendant(
790 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
791 testImport(
792 "template <typename T> struct C { T t; };"
793 "template <typename T> void declToImport() {"
794 " C<T> d;"
795 " (void)(&d)->t;"
796 "}"
797 "void instantiate() { declToImport<int>(); }",
798 Lang_CXX, "", Lang_CXX, Verifier,
799 functionTemplateDecl(hasDescendant(
800 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000801}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000802
Gabor Marton19f4f392018-06-25 13:04:37 +0000803TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000804 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000805 testImport(
806 "template <int K>"
807 "struct dummy { static const int i = K; };"
808 "template <int K> using dummy2 = dummy<K>;"
809 "int declToImport() { return dummy2<3>::i; }",
810 Lang_CXX11, "", Lang_CXX11, Verifier,
811 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000812 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000813 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
814}
815
816const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
817 varTemplateSpecializationDecl;
818
Gabor Marton19f4f392018-06-25 13:04:37 +0000819TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000820 MatchVerifier<Decl> Verifier;
821 testImport(
822 "template <typename T>"
823 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000824 "void declToImport() { (void)pi<int>; }",
825 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000826 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000827 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000828 unless(hasAncestor(translationUnitDecl(has(varDecl(
829 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000830}
831
Gabor Marton19f4f392018-06-25 13:04:37 +0000832TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000833 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000834 testImport(
835 "template <typename... Args>"
836 "struct dummy {"
837 " dummy(Args... args) {}"
838 " static const int i = 4;"
839 "};"
840 "int declToImport() { return dummy<int>::i; }",
841 Lang_CXX11, "", Lang_CXX11, Verifier,
842 functionDecl(hasDescendant(
843 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000844}
845
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000846const internal::VariadicDynCastAllOfMatcher<Type,
847 DependentTemplateSpecializationType>
848 dependentTemplateSpecializationType;
849
Gabor Marton19f4f392018-06-25 13:04:37 +0000850TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000851 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000852 testImport(
853 "template<typename T>"
854 "struct A;"
855 "template<typename T>"
856 "struct declToImport {"
857 " typename A<T>::template B<T> a;"
858 "};",
859 Lang_CXX, "", Lang_CXX, Verifier,
860 classTemplateDecl(has(cxxRecordDecl(has(
861 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000862}
863
864const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
865 sizeOfPackExpr;
866
Gabor Marton19f4f392018-06-25 13:04:37 +0000867TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000868 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000869 testImport(
870 "template <typename... Ts>"
871 "void declToImport() {"
872 " const int i = sizeof...(Ts);"
873 "};"
874 "void g() { declToImport<int>(); }",
875 Lang_CXX11, "", Lang_CXX11, Verifier,
876 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000877 testImport(
878 "template <typename... Ts>"
879 "using X = int[sizeof...(Ts)];"
880 "template <typename... Us>"
881 "struct Y {"
882 " X<Us..., int, double, int, Us...> f;"
883 "};"
884 "Y<float, int> declToImport;",
885 Lang_CXX11, "", Lang_CXX11, Verifier,
886 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
887 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
888}
889
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000890/// \brief Matches __builtin_types_compatible_p:
891/// GNU extension to check equivalent types
892/// Given
893/// \code
894/// __builtin_types_compatible_p(int, int)
895/// \endcode
896// will generate TypeTraitExpr <...> 'int'
897const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
898
Gabor Marton19f4f392018-06-25 13:04:37 +0000899TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000900 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000901 testImport(
902 "void declToImport() { "
903 " (void)__builtin_types_compatible_p(int, int);"
904 "}",
905 Lang_C, "", Lang_C, Verifier,
906 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000907}
908
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000909const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
910
Gabor Marton19f4f392018-06-25 13:04:37 +0000911TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000912 MatchVerifier<Decl> Verifier;
913 testImport(
914 "namespace std { class type_info {}; }"
915 "void declToImport() {"
916 " int x;"
917 " auto a = typeid(int); auto b = typeid(x);"
918 "}",
919 Lang_CXX11, "", Lang_CXX11, Verifier,
920 functionDecl(
921 hasDescendant(varDecl(
922 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
923 hasDescendant(varDecl(
924 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
925}
926
Gabor Marton19f4f392018-06-25 13:04:37 +0000927TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000928 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000929 testImport(
930 "template<typename T> struct declToImport {"
931 " void m() { (void)__is_pod(T); }"
932 "};"
933 "void f() { declToImport<int>().m(); }",
934 Lang_CXX11, "", Lang_CXX11, Verifier,
935 classTemplateDecl(has(cxxRecordDecl(has(
936 functionDecl(hasDescendant(
937 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000938}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000939
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000940const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
941 cxxPseudoDestructorExpr;
942
Gabor Marton19f4f392018-06-25 13:04:37 +0000943TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000944 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000945 testImport(
946 "typedef int T;"
947 "void declToImport(int *p) {"
948 " T t;"
949 " p->T::~T();"
950 "}",
951 Lang_CXX, "", Lang_CXX, Verifier,
952 functionDecl(hasDescendant(
953 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000954}
955
Gabor Marton19f4f392018-06-25 13:04:37 +0000956TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000957 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000958 testImport(
959 "namespace foo { int bar; }"
960 "void declToImport() { using foo::bar; }",
961 Lang_CXX, "", Lang_CXX, Verifier,
962 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000963}
964
965/// \brief Matches shadow declarations introduced into a scope by a
966/// (resolved) using declaration.
967///
968/// Given
969/// \code
970/// namespace n { int f; }
971/// namespace declToImport { using n::f; }
972/// \endcode
973/// usingShadowDecl()
974/// matches \code f \endcode
975const internal::VariadicDynCastAllOfMatcher<Decl,
976 UsingShadowDecl> usingShadowDecl;
977
Gabor Marton19f4f392018-06-25 13:04:37 +0000978TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000979 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000980 testImport(
981 "namespace foo { int bar; }"
982 "namespace declToImport { using foo::bar; }",
983 Lang_CXX, "", Lang_CXX, Verifier,
984 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000985}
986
Gabor Marton19f4f392018-06-25 13:04:37 +0000987TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000988 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000989 testImport(
990 "template<typename T> int foo();"
991 "template <typename T> void declToImport() {"
992 " (void)::foo<T>;"
993 " (void)::template foo<T>;"
994 "}"
995 "void instantiate() { declToImport<int>(); }",
996 Lang_CXX, "", Lang_CXX, Verifier,
997 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000998}
999
Gabor Marton19f4f392018-06-25 13:04:37 +00001000TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001001 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001002 testImport(
1003 "template <typename T> struct C { T t; };"
1004 "template <typename T> void declToImport() {"
1005 " C<T> d;"
1006 " d.t = T();"
1007 "}"
1008 "void instantiate() { declToImport<int>(); }",
1009 Lang_CXX, "", Lang_CXX, Verifier,
1010 functionTemplateDecl(hasDescendant(
1011 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1012 testImport(
1013 "template <typename T> struct C { T t; };"
1014 "template <typename T> void declToImport() {"
1015 " C<T> d;"
1016 " (&d)->t = T();"
1017 "}"
1018 "void instantiate() { declToImport<int>(); }",
1019 Lang_CXX, "", Lang_CXX, Verifier,
1020 functionTemplateDecl(hasDescendant(
1021 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001022}
1023
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001024/// Check that function "declToImport()" (which is the templated function
1025/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1026/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001027TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001028 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001029 testImport(
1030 "template <typename T> void declToImport() { T a = 1; }"
1031 "void instantiate() { declToImport<int>(); }",
1032 Lang_CXX, "", Lang_CXX, Verifier,
1033 functionTemplateDecl(hasAncestor(translationUnitDecl(
1034 unless(has(functionDecl(hasName("declToImport"))))))));
1035 testImport(
1036 "template <typename T> struct declToImport { T t; };"
1037 "void instantiate() { declToImport<int>(); }",
1038 Lang_CXX, "", Lang_CXX, Verifier,
1039 classTemplateDecl(hasAncestor(translationUnitDecl(
1040 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001041}
1042
Gabor Marton19f4f392018-06-25 13:04:37 +00001043TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001044 MatchVerifier<Decl> Verifier;
1045 auto Code =
1046 R"s(
1047 struct declToImport {
1048 template <typename T0> struct X;
1049 template <typename T0> struct X<T0 *> {};
1050 };
1051 )s";
1052 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1053 recordDecl(has(classTemplateDecl()),
1054 has(classTemplateSpecializationDecl())));
1055}
1056
Gabor Marton19f4f392018-06-25 13:04:37 +00001057TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001058 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001059 testImport(
1060 "class declToImport {"
1061 " void f() { *this = declToImport(); }"
1062 "};",
1063 Lang_CXX, "", Lang_CXX, Verifier,
1064 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1065 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001066}
1067
Gabor Marton19f4f392018-06-25 13:04:37 +00001068TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001069 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001070 testImport(
1071 "template<typename T, int Size> class declToImport {"
1072 " T data[Size];"
1073 "};",
1074 Lang_CXX, "", Lang_CXX, Verifier,
1075 classTemplateDecl(has(cxxRecordDecl(
1076 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001077}
1078
Gabor Martona0df7a92018-05-30 09:19:26 +00001079TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfClassTemplateDecl) {
1080 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1081 auto From =
1082 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1083 ASSERT_TRUE(From);
1084 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1085 ASSERT_TRUE(To);
1086 Decl *ToTemplated = To->getTemplatedDecl();
1087 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1088 EXPECT_TRUE(ToTemplated1);
1089 EXPECT_EQ(ToTemplated1, ToTemplated);
1090}
1091
Gabor Marton6578a4a2018-06-25 11:38:43 +00001092TEST_P(ASTImporterTestBase,
1093 DISABLED_ImportOfTemplatedDeclOfFunctionTemplateDecl) {
1094 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1095 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1096 FromTU, functionTemplateDecl());
1097 ASSERT_TRUE(From);
1098 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1099 ASSERT_TRUE(To);
1100 Decl *ToTemplated = To->getTemplatedDecl();
1101 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1102 EXPECT_TRUE(ToTemplated1);
1103 EXPECT_EQ(ToTemplated1, ToTemplated);
1104}
1105
1106TEST_P(ASTImporterTestBase,
1107 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1108 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1109 auto FromFT =
1110 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1111 ASSERT_TRUE(FromFT);
1112
1113 auto ToTemplated =
1114 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1115 EXPECT_TRUE(ToTemplated);
1116 auto ToTU = ToTemplated->getTranslationUnitDecl();
1117 auto ToFT =
1118 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1119 EXPECT_TRUE(ToFT);
1120}
1121
1122TEST_P(ASTImporterTestBase,
1123 DISABLED_ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
1124 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1125 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1126 FromTU, functionTemplateDecl());
1127 ASSERT_TRUE(FromFT);
1128
1129 auto ToTemplated =
1130 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1131 EXPECT_TRUE(ToTemplated);
1132 auto ToTU = ToTemplated->getTranslationUnitDecl();
1133 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1134 ToTU, functionTemplateDecl());
1135 EXPECT_TRUE(ToFT);
1136}
1137
Gabor Martona0df7a92018-05-30 09:19:26 +00001138TEST_P(ASTImporterTestBase, ImportCorrectTemplatedDecl) {
1139 auto Code =
1140 R"(
1141 namespace x {
1142 template<class X> struct S1{};
1143 template<class X> struct S2{};
1144 template<class X> struct S3{};
1145 }
1146 )";
1147 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1148 auto FromNs =
1149 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1150 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1151 ASSERT_TRUE(ToNs);
1152 auto From =
1153 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1154 classTemplateDecl(
1155 hasName("S2")));
1156 auto To =
1157 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1158 classTemplateDecl(
1159 hasName("S2")));
1160 ASSERT_TRUE(From);
1161 ASSERT_TRUE(To);
1162 auto ToTemplated = To->getTemplatedDecl();
1163 auto ToTemplated1 =
1164 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1165 EXPECT_TRUE(ToTemplated1);
1166 ASSERT_EQ(ToTemplated1, ToTemplated);
1167}
1168
Peter Szecsidedda6f2018-03-30 22:03:29 +00001169TEST_P(ASTImporterTestBase, DISABLED_ImportFunctionWithBackReferringParameter) {
1170 Decl *From, *To;
1171 std::tie(From, To) = getImportedDecl(
1172 R"(
1173 template <typename T> struct X {};
1174
1175 void declToImport(int y, X<int> &x) {}
1176
1177 template <> struct X<int> {
1178 void g() {
1179 X<int> x;
1180 declToImport(0, x);
1181 }
1182 };
1183 )",
1184 Lang_CXX, "", Lang_CXX);
1185
1186 MatchVerifier<Decl> Verifier;
1187 auto Matcher = functionDecl(hasName("declToImport"),
1188 parameterCountIs(2),
1189 hasParameter(0, hasName("y")),
1190 hasParameter(1, hasName("x")),
1191 hasParameter(1, hasType(asString("X<int> &"))));
1192 ASSERT_TRUE(Verifier.match(From, Matcher));
1193 EXPECT_TRUE(Verifier.match(To, Matcher));
1194}
1195
1196TEST_P(ASTImporterTestBase,
1197 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1198 Decl *From, *To;
1199 std::tie(From, To) =
1200 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1201 "void instantiate() { declToImport<int>(); }",
1202 Lang_CXX, "", Lang_CXX);
1203
1204 auto Check = [](Decl *D) -> bool {
1205 auto TU = D->getTranslationUnitDecl();
1206 for (auto Child : TU->decls()) {
1207 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1208 if (FD->getNameAsString() == "declToImport") {
1209 GTEST_NONFATAL_FAILURE_(
1210 "TU should not contain any FunctionDecl with name declToImport");
1211 return false;
1212 }
1213 }
1214 }
1215 return true;
1216 };
1217
1218 ASSERT_TRUE(Check(From));
1219 EXPECT_TRUE(Check(To));
1220}
1221
1222TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfClassTemplates) {
1223 Decl *From, *To;
1224 std::tie(From, To) =
1225 getImportedDecl("template <typename T> struct declToImport { T t; };"
1226 "void instantiate() { declToImport<int>(); }",
1227 Lang_CXX, "", Lang_CXX);
1228
1229 auto Check = [](Decl *D) -> bool {
1230 auto TU = D->getTranslationUnitDecl();
1231 for (auto Child : TU->decls()) {
1232 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1233 if (RD->getNameAsString() == "declToImport") {
1234 GTEST_NONFATAL_FAILURE_(
1235 "TU should not contain any CXXRecordDecl with name declToImport");
1236 return false;
1237 }
1238 }
1239 }
1240 return true;
1241 };
1242
1243 ASSERT_TRUE(Check(From));
1244 EXPECT_TRUE(Check(To));
1245}
1246
1247TEST_P(ASTImporterTestBase, TUshouldNotContainTemplatedDeclOfTypeAlias) {
1248 Decl *From, *To;
1249 std::tie(From, To) =
1250 getImportedDecl(
1251 "template <typename T> struct X {};"
1252 "template <typename T> using declToImport = X<T>;"
1253 "void instantiate() { declToImport<int> a; }",
1254 Lang_CXX11, "", Lang_CXX11);
1255
1256 auto Check = [](Decl *D) -> bool {
1257 auto TU = D->getTranslationUnitDecl();
1258 for (auto Child : TU->decls()) {
1259 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1260 if (AD->getNameAsString() == "declToImport") {
1261 GTEST_NONFATAL_FAILURE_(
1262 "TU should not contain any TypeAliasDecl with name declToImport");
1263 return false;
1264 }
1265 }
1266 }
1267 return true;
1268 };
1269
1270 ASSERT_TRUE(Check(From));
1271 EXPECT_TRUE(Check(To));
1272}
1273
1274TEST_P(
1275 ASTImporterTestBase,
Gabor Martonb14056b2018-05-25 11:21:24 +00001276 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001277
1278 Decl *From, *To;
1279 std::tie(From, To) = getImportedDecl(
1280 R"(
1281 template<class T>
1282 class Base {};
1283 class declToImport : public Base<declToImport> {};
1284 )",
1285 Lang_CXX, "", Lang_CXX);
1286
1287 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1288 auto Pattern =
1289 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1290 ASSERT_TRUE(
1291 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1292 EXPECT_TRUE(
1293 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1294
1295 // Check that the ClassTemplateSpecializationDecl is the child of the
1296 // ClassTemplateDecl.
1297 Pattern = translationUnitDecl(has(classTemplateDecl(
1298 hasName("Base"), has(classTemplateSpecializationDecl()))));
1299 ASSERT_TRUE(
1300 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1301 EXPECT_TRUE(
1302 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1303}
1304
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001305AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1306 size_t Index = 0;
1307 for (FieldDecl *Field : Node.fields()) {
1308 if (Index == Order.size())
1309 return false;
1310 if (Field->getName() != Order[Index])
1311 return false;
1312 ++Index;
1313 }
1314 return Index == Order.size();
1315}
1316
Peter Szecsidedda6f2018-03-30 22:03:29 +00001317TEST_P(ASTImporterTestBase,
1318 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1319 Decl *From, *To;
1320 std::tie(From, To) = getImportedDecl(
1321 R"(
1322 namespace NS {
1323 template<class T>
1324 class X {};
1325 template class X<int>;
1326 }
1327 )",
1328 Lang_CXX, "", Lang_CXX, "NS");
1329
1330 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1331 // ClassTemplateDecl.
1332 auto Pattern = namespaceDecl(has(classTemplateDecl(
1333 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1334 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1335 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1336
1337 // Check that the ClassTemplateSpecializationDecl is the child of the
1338 // NamespaceDecl.
1339 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1340 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1341 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1342}
1343
1344TEST_P(ASTImporterTestBase, CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1345 Decl *From, *To;
1346 std::tie(From, To) =
1347 getImportedDecl(
1348 "struct declToImport { int a; int b; };",
1349 Lang_CXX11, "", Lang_CXX11);
1350
1351 MatchVerifier<Decl> Verifier;
1352 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1353 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1354}
1355
1356TEST_P(ASTImporterTestBase,
1357 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1358 Decl *From, *To;
1359 std::tie(From, To) = getImportedDecl(
1360 // The original recursive algorithm of ASTImporter first imports 'c' then
1361 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1362 R"s(
1363 struct declToImport {
1364 int a = c + b;
1365 int b = 1;
1366 int c = 2;
1367 };
1368 )s",
1369 Lang_CXX11, "", Lang_CXX11);
1370
1371 MatchVerifier<Decl> Verifier;
1372 ASSERT_TRUE(
1373 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1374 EXPECT_TRUE(
1375 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1376}
1377
Gabor Martonde8bf262018-05-17 09:46:07 +00001378TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001379 Decl *From, *To;
1380 std::tie(From, To) = getImportedDecl(
1381 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001382 struct declToImport {
1383 };
1384 )",
1385 Lang_CXX, "", Lang_CXX);
1386
1387 MatchVerifier<Decl> Verifier;
1388 // Match the implicit Decl.
1389 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1390 ASSERT_TRUE(Verifier.match(From, Matcher));
1391 EXPECT_TRUE(Verifier.match(To, Matcher));
1392}
1393
1394TEST_P(ASTImporterTestBase, ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1395 Decl *From, *To;
1396 std::tie(From, To) = getImportedDecl(
1397 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001398 template <typename U>
1399 struct declToImport {
1400 };
1401 )",
1402 Lang_CXX, "", Lang_CXX);
1403
1404 MatchVerifier<Decl> Verifier;
1405 // Match the implicit Decl.
1406 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1407 ASSERT_TRUE(Verifier.match(From, Matcher));
1408 EXPECT_TRUE(Verifier.match(To, Matcher));
1409}
1410
1411TEST_P(
1412 ASTImporterTestBase,
Gabor Martona3af5672018-05-23 14:24:02 +00001413 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001414 Decl *From, *To;
1415 std::tie(From, To) = getImportedDecl(
1416 R"(
1417 template<class T>
1418 class Base {};
1419 class declToImport : public Base<declToImport> {};
1420 )",
1421 Lang_CXX, "", Lang_CXX);
1422
1423 auto hasImplicitClass = has(cxxRecordDecl());
1424 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1425 hasName("Base"),
1426 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1427 ASSERT_TRUE(
1428 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1429 EXPECT_TRUE(
1430 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1431}
1432
1433TEST_P(ASTImporterTestBase, IDNSOrdinary) {
1434 Decl *From, *To;
1435 std::tie(From, To) =
1436 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1437
1438 MatchVerifier<Decl> Verifier;
1439 auto Matcher = functionDecl();
1440 ASSERT_TRUE(Verifier.match(From, Matcher));
1441 EXPECT_TRUE(Verifier.match(To, Matcher));
1442 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1443}
1444
Gabor Marton2ae9da32018-05-18 15:46:18 +00001445TEST_P(ASTImporterTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001446 Decl *FromTU = getTuDecl(
1447 R"(
1448 struct X {};
1449 void operator<<(int, X);
1450 )",
1451 Lang_CXX);
1452 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1453 const Decl *To = Import(From, Lang_CXX);
1454 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1455}
1456
1457TEST_P(ASTImporterTestBase,
1458 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1459 Decl *From, *To;
1460 std::tie(From, To) = getImportedDecl(
1461 R"(
1462 template<class T>
1463 class Base { int a; };
1464 class declToImport : Base<declToImport> {};
1465 )",
1466 Lang_CXX, "", Lang_CXX);
1467
1468 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1469 hasName("Base"),
1470 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1471 ASSERT_TRUE(
1472 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1473 EXPECT_TRUE(
1474 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1475}
1476
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001477TEST_P(ASTImporterTestBase, ImportDefinitionOfClassTemplateAfterFwdDecl) {
1478 {
1479 Decl *FromTU = getTuDecl(
1480 R"(
1481 template <typename T>
1482 struct B;
1483 )",
1484 Lang_CXX, "input0.cc");
1485 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1486 FromTU, classTemplateDecl(hasName("B")));
1487
1488 Import(FromD, Lang_CXX);
1489 }
1490
1491 {
1492 Decl *FromTU = getTuDecl(
1493 R"(
1494 template <typename T>
1495 struct B {
1496 void f();
1497 };
1498 )",
1499 Lang_CXX, "input1.cc");
1500 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1501 FromTU, functionDecl(hasName("f")));
1502 Import(FromD, Lang_CXX);
1503 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1504 FromTU, classTemplateDecl(hasName("B")));
1505 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1506 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1507 }
1508}
1509
Gabor Marton9581c332018-05-23 13:53:36 +00001510TEST_P(ASTImporterTestBase,
1511 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1512 Decl *ToTU = getToTuDecl(
1513 R"(
1514 template <typename T>
1515 struct B {
1516 void f();
1517 };
1518
1519 template <typename T>
1520 struct B;
1521 )",
1522 Lang_CXX);
1523 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1524 [](const ClassTemplateDecl *T) {
1525 return T->isThisDeclarationADefinition();
1526 })
1527 .match(ToTU, classTemplateDecl()));
1528
1529 Decl *FromTU = getTuDecl(
1530 R"(
1531 template <typename T>
1532 struct B {
1533 void f();
1534 };
1535 )",
1536 Lang_CXX, "input1.cc");
1537 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1538 FromTU, classTemplateDecl(hasName("B")));
1539
1540 Import(FromD, Lang_CXX);
1541
1542 // We should have only one definition.
1543 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1544 [](const ClassTemplateDecl *T) {
1545 return T->isThisDeclarationADefinition();
1546 })
1547 .match(ToTU, classTemplateDecl()));
1548}
1549
1550TEST_P(ASTImporterTestBase,
1551 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1552 Decl *ToTU = getToTuDecl(
1553 R"(
1554 struct B {
1555 void f();
1556 };
1557
1558 struct B;
1559 )",
1560 Lang_CXX);
1561 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001562 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001563
1564 Decl *FromTU = getTuDecl(
1565 R"(
1566 struct B {
1567 void f();
1568 };
1569 )",
1570 Lang_CXX, "input1.cc");
1571 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1572 FromTU, cxxRecordDecl(hasName("B")));
1573
1574 Import(FromD, Lang_CXX);
1575
1576 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001577 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001578}
1579
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001580static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1581 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1582 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1583 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1584 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1585}
1586static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1587 SourceManager &SM1, SourceManager &SM2) {
1588 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1589 FullSourceLoc{ Range2.getBegin(), SM2 });
1590 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1591 FullSourceLoc{ Range2.getEnd(), SM2 });
1592}
1593TEST_P(ASTImporterTestBase, ImportSourceLocs) {
1594 Decl *FromTU = getTuDecl(
1595 R"(
1596 #define MFOO(arg) arg = arg + 1
1597
1598 void foo() {
1599 int a = 5;
1600 MFOO(a);
1601 }
1602 )",
1603 Lang_CXX);
1604 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1605 auto ToD = Import(FromD, Lang_CXX);
1606
1607 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1608 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1609 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1610 auto FromRHS =
1611 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1612
1613 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1614 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1615 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1616 FromSM);
1617 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1618 FromSM);
1619 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1620 FromSM);
1621}
1622
Rafael Stahla0010472018-07-09 08:40:17 +00001623TEST_P(ASTImporterTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001624 Decl *FromTU = getTuDecl(
1625 R"(
1626 #define FUNC_INT void declToImport
1627 #define FUNC FUNC_INT
1628 FUNC(int a);
1629 )",
1630 Lang_CXX);
1631 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1632 auto ToD = Import(FromD, Lang_CXX);
1633
1634 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1635 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1636 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1637 FromSM);
1638}
1639
Gabor Marton9581c332018-05-23 13:53:36 +00001640TEST_P(
1641 ASTImporterTestBase,
1642 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
1643{
1644 Decl *ToTU = getToTuDecl(
1645 R"(
1646 template <typename T>
1647 struct B;
1648
1649 template <>
1650 struct B<int> {};
1651
1652 template <>
1653 struct B<int>;
1654 )",
1655 Lang_CXX);
1656 // We should have only one definition.
1657 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1658 [](const ClassTemplateSpecializationDecl *T) {
1659 return T->isThisDeclarationADefinition();
1660 })
1661 .match(ToTU, classTemplateSpecializationDecl()));
1662
1663 Decl *FromTU = getTuDecl(
1664 R"(
1665 template <typename T>
1666 struct B;
1667
1668 template <>
1669 struct B<int> {};
1670 )",
1671 Lang_CXX, "input1.cc");
1672 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1673 FromTU, classTemplateSpecializationDecl(hasName("B")));
1674
1675 Import(FromD, Lang_CXX);
1676
1677 // We should have only one definition.
1678 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1679 [](const ClassTemplateSpecializationDecl *T) {
1680 return T->isThisDeclarationADefinition();
1681 })
1682 .match(ToTU, classTemplateSpecializationDecl()));
1683}
1684
Gabor Marton0bebf952018-07-05 09:51:13 +00001685TEST_P(ASTImporterTestBase, ObjectsWithUnnamedStructType) {
1686 Decl *FromTU = getTuDecl(
1687 R"(
1688 struct { int a; int b; } object0 = { 2, 3 };
1689 struct { int x; int y; int z; } object1;
1690 )",
1691 Lang_CXX, "input0.cc");
1692
1693 auto getRecordDecl = [](VarDecl *VD) {
1694 auto *ET = cast<ElaboratedType>(VD->getType().getTypePtr());
1695 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
1696 };
1697
1698 auto *Obj0 =
1699 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1700 auto *From0 = getRecordDecl(Obj0);
1701 auto *Obj1 =
1702 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1703 auto *From1 = getRecordDecl(Obj1);
1704
1705 auto *To0 = Import(From0, Lang_CXX);
1706 auto *To1 = Import(From1, Lang_CXX);
1707
1708 EXPECT_TRUE(To0);
1709 EXPECT_TRUE(To1);
1710 EXPECT_NE(To0, To1);
1711 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1712}
1713
Peter Szecsidedda6f2018-03-30 22:03:29 +00001714struct ImportFunctions : ASTImporterTestBase {};
1715
1716TEST_P(ImportFunctions,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001717 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1718 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1719 auto Pattern = functionDecl(hasName("f"));
1720 FunctionDecl *FromD = // Definition
1721 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1722
1723 Decl *ImportedD = Import(FromD, Lang_CXX);
1724 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1725
Gabor Marton5254e642018-06-27 13:32:50 +00001726 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001727 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1728}
1729
1730TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1731 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1732 auto Pattern = functionDecl(hasName("f"));
1733 FunctionDecl *FromD =
1734 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1735
1736 Decl *ImportedD = Import(FromD, Lang_CXX);
1737 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1738
1739 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1740 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1741}
1742
Gabor Marton5254e642018-06-27 13:32:50 +00001743TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001744 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1745 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001746 auto *From =
1747 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00001748
Gabor Marton5254e642018-06-27 13:32:50 +00001749 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001750 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1751
Gabor Marton5254e642018-06-27 13:32:50 +00001752 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1753 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1754 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1755 EXPECT_TRUE(ImportedD == To0);
1756 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1757 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1758 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001759}
1760
1761TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1762 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1763 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001764 auto *From =
1765 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00001766
Gabor Marton5254e642018-06-27 13:32:50 +00001767 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001768 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1769
Gabor Marton5254e642018-06-27 13:32:50 +00001770 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1771 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1772 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1773 EXPECT_TRUE(ImportedD == To1);
1774 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1775 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1776 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001777}
1778
1779TEST_P(ImportFunctions, ImportPrototypes) {
1780 auto Pattern = functionDecl(hasName("f"));
1781
1782 Decl *ImportedD;
1783 {
1784 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001785 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001786
1787 ImportedD = Import(FromD, Lang_CXX);
1788 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001789 {
1790 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001791 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1792 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001793 }
1794
Gabor Marton5254e642018-06-27 13:32:50 +00001795 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1796
1797 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1798 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1799 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1800 EXPECT_TRUE(ImportedD == To0);
1801 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1802 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1803 EXPECT_EQ(To1->getPreviousDecl(), To0);
1804}
1805
1806TEST_P(ImportFunctions, ImportDefinitions) {
1807 auto Pattern = functionDecl(hasName("f"));
1808
1809 Decl *ImportedD;
1810 {
1811 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
1812 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1813 ImportedD = Import(FromD, Lang_CXX);
1814 }
1815 {
1816 Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");
1817 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1818 Import(FromD, Lang_CXX);
1819 }
1820
1821 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1822
Peter Szecsidedda6f2018-03-30 22:03:29 +00001823 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Gabor Marton5254e642018-06-27 13:32:50 +00001824 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1825 EXPECT_TRUE(ImportedD == To0);
1826 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00001827}
1828
1829TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
1830 auto Pattern = functionDecl(hasName("f"));
1831
1832 Decl *ImportedD;
1833 {
1834 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001835 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001836 ImportedD = Import(FromD, Lang_CXX);
1837 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001838 {
1839 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001840 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1841 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001842 }
1843
1844 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00001845
1846 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1847 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1848 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1849 EXPECT_TRUE(ImportedD == To0);
1850 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
1851 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1852 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001853}
1854
1855TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
1856 auto Pattern = functionDecl(hasName("f"));
1857
1858 {
1859 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1860 FunctionDecl *FromD =
1861 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1862
1863 Import(FromD, Lang_CXX);
1864 }
1865 {
1866 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
1867 FunctionDecl *FromD =
1868 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1869 Import(FromD, Lang_CXX);
1870 }
1871
1872 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1873 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1874 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00001875 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00001876 FunctionDecl *DefinitionD =
1877 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1878 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
1879 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
1880}
1881
Gabor Marton5254e642018-06-27 13:32:50 +00001882TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001883 auto Pattern = functionDecl(hasName("f"));
1884
1885 {
1886 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001887 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001888 Import(FromD, Lang_CXX);
1889 }
1890 {
1891 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001892 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001893 Import(FromD, Lang_CXX);
1894 }
1895
1896 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00001897
1898 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001899 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00001900 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
1901
Peter Szecsidedda6f2018-03-30 22:03:29 +00001902 FunctionDecl *DefinitionD =
1903 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1904 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
Gabor Marton5254e642018-06-27 13:32:50 +00001905
1906 EXPECT_TRUE(DefinitionD->getPreviousDecl());
1907 EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());
1908 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001909}
1910
1911TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
1912 auto Code =
1913 R"(
1914 struct B { virtual void f(); };
1915 void B::f() {}
1916 struct D : B { void f(); };
1917 )";
1918 auto Pattern =
1919 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
1920 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1921 CXXMethodDecl *Proto =
1922 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1923
1924 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
1925 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1926 EXPECT_EQ(To->size_overridden_methods(), 1u);
1927}
1928
1929TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
1930 auto Code =
1931 R"(
1932 struct B { virtual void f(); };
1933 void B::f() {}
1934 )";
1935 auto Pattern =
1936 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1937 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1938 CXXMethodDecl *Proto =
1939 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1940 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1941
1942 ASSERT_TRUE(Proto->isVirtual());
1943 ASSERT_TRUE(Def->isVirtual());
1944 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1945 EXPECT_TRUE(To->isVirtual());
1946}
1947
Gabor Marton5254e642018-06-27 13:32:50 +00001948TEST_P(ImportFunctions,
1949 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
1950 Decl *ToTU = getToTuDecl(
1951 R"(
1952 void f() {}
1953 void f();
1954 )",
1955 Lang_CXX);
1956 ASSERT_EQ(1u,
1957 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
1958 return FD->doesThisDeclarationHaveABody();
1959 }).match(ToTU, functionDecl()));
1960
1961 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
1962 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1963
1964 Import(FromD, Lang_CXX);
1965
1966 EXPECT_EQ(1u,
1967 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
1968 return FD->doesThisDeclarationHaveABody();
1969 }).match(ToTU, functionDecl()));
1970}
1971
1972struct ImportFriendFunctions : ImportFunctions {};
1973
1974TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
1975 auto Pattern = functionDecl(hasName("f"));
1976
1977 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
1978 "void f();",
1979 Lang_CXX,
1980 "input0.cc");
1981 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1982
1983 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
1984 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1985 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1986 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
1987 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1988 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
1989 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
1990}
1991
1992TEST_P(ImportFriendFunctions,
1993 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
1994 auto Pattern = functionDecl(hasName("f"));
1995
1996 Decl *FromTU = getTuDecl("void f();"
1997 "struct X { friend void f(); };",
1998 Lang_CXX, "input0.cc");
1999 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2000
2001 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2002 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2003 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2004 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2005 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2006 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2007 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2008}
2009
2010TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2011 auto Pattern = functionDecl(hasName("f"));
2012
2013 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2014 "void f();",
2015 Lang_CXX,
2016 "input0.cc");
2017 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2018
2019 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2020 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2021 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2022 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2023 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2024 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2025 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2026}
2027
2028TEST_P(ImportFriendFunctions,
2029 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2030 auto Pattern = functionDecl(hasName("f"));
2031
2032 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2033 "void f(){}",
2034 Lang_CXX, "input0.cc");
2035 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2036
2037 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2038 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2039 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2040 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2041 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2042 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2043 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2044}
2045
2046// This test is disabled, because ATM we create a redundant FunctionDecl. We
2047// start the import with the definition of `f` then we continue with the import
2048// of the type of `f` which involves `X`. During the import of `X` we start
2049// again the import of the definition of `f` and then finally we create the
2050// node. But then in the first frame of `VisitFunctionDecl` we create a node
2051// again since we do not check if such a node exists yet or not. This is being
2052// fixed in a separate patch: https://reviews.llvm.org/D47632
2053// FIXME enable this test once the above patch is approved.
2054TEST_P(ImportFriendFunctions,
2055 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2056 auto Pattern = functionDecl(hasName("f"));
2057
2058 Decl *FromTU = getTuDecl(
2059 R"(
2060 class X;
2061 void f(X *x){}
2062 class X{
2063 friend void f(X *x);
2064 };
2065 )",
2066 Lang_CXX, "input0.cc");
2067 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2068
2069 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2070 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2071 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2072 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2073 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2074 .match(ToTU, friendDecl())
2075 ->getFriendDecl());
2076 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2077 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2078 // The parameters must refer the same type
2079 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2080 (*ImportedD->param_begin())->getOriginalType());
2081}
2082
2083// This test is disabled, because ATM we create a redundant FunctionDecl. We
2084// start the import with the definition of `f` then we continue with the import
2085// of the type of `f` which involves `X`. During the import of `X` we start
2086// again the import of the definition of `f` and then finally we create the
2087// node. But then in the first frame of `VisitFunctionDecl` we create a node
2088// again since we do not check if such a node exists yet or not. This is being
2089// fixed in a separate patch: https://reviews.llvm.org/D47632
2090// FIXME enable this test once the above patch is approved.
2091TEST_P(ImportFriendFunctions,
2092 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
2093 auto Pattern = functionDecl(hasName("f"));
2094
2095 Decl *FromTU = getTuDecl(
2096 R"(
2097 class X;
2098 void f(X *x){}
2099 class X{
2100 friend void f(X *x);
2101 };
2102 )",
2103 Lang_CXX, "input0.cc");
2104 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2105
2106 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2107 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2108 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2109 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2110 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2111 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2112
2113 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2114 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2115 // The parameters must refer the same type
2116 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2117 (*ImportedD->param_begin())->getOriginalType());
2118}
2119
2120TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2121 auto Pattern = functionDecl(hasName("f"));
2122
2123 FunctionDecl *ImportedD;
2124 {
2125 Decl *FromTU =
2126 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2127 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2128 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2129 }
2130 FunctionDecl *ImportedD1;
2131 {
2132 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2133 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2134 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2135 }
2136
2137 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2138 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2139 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2140 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2141 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2142}
2143
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002144AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2145 InnerMatcher) {
2146 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2147 return InnerMatcher.matches(*Typedef, Finder, Builder);
2148 return false;
2149}
2150
Gabor Marton19f4f392018-06-25 13:04:37 +00002151TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002152 CodeFiles Samples{{"main.c",
2153 {"void foo();"
2154 "void moo();"
2155 "int main() { foo(); moo(); }",
2156 Lang_C}},
2157
2158 {"foo.c",
2159 {"typedef enum { THING_VALUE } thing_t;"
2160 "void conflict(thing_t type);"
2161 "void foo() { (void)THING_VALUE; }"
2162 "void conflict(thing_t type) {}",
2163 Lang_C}},
2164
2165 {"moo.c",
2166 {"typedef enum { THING_VALUE } thing_t;"
2167 "void conflict(thing_t type);"
2168 "void moo() { conflict(THING_VALUE); }",
2169 Lang_C}}};
2170
2171 auto VerificationMatcher =
2172 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2173 hasTypedefForAnonDecl(hasName("thing_t")));
2174
2175 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2176 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2177
2178 testImportSequence(
2179 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2180 // Just check that there is only one enum decl in the result AST.
2181 "main.c", enumDecl(), VerificationMatcher);
2182
2183 // For different import order, result should be the same.
2184 testImportSequence(
2185 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2186 // Check that there is only one enum decl in the result AST.
2187 "main.c", enumDecl(), VerificationMatcher);
2188}
2189
Peter Szecsice7f3182018-05-07 12:08:27 +00002190const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2191 dependentScopeDeclRefExpr;
2192
Gabor Marton19f4f392018-06-25 13:04:37 +00002193TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002194 MatchVerifier<Decl> Verifier;
2195 testImport("template <typename T> struct S { static T foo; };"
2196 "template <typename T> void declToImport() {"
2197 " (void) S<T>::foo;"
2198 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002199 "void instantiate() { declToImport<int>(); }"
2200 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002201 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
Balazs Keric7797c42018-07-11 09:37:24 +00002246TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) {
2247 Decl *ToR1;
2248 {
2249 Decl *FromTU = getTuDecl(
2250 "struct A { };", Lang_CXX, "input0.cc");
2251 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2252 FromTU, cxxRecordDecl(hasName("A")));
2253
2254 ToR1 = Import(FromR, Lang_CXX);
2255 }
2256
2257 Decl *ToR2;
2258 {
2259 Decl *FromTU = getTuDecl(
2260 "struct A { };", Lang_CXX, "input1.cc");
2261 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2262 FromTU, cxxRecordDecl(hasName("A")));
2263
2264 ToR2 = Import(FromR, Lang_CXX);
2265 }
2266
2267 EXPECT_EQ(ToR1, ToR2);
2268}
2269
2270TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) {
2271 Decl *ToR1;
2272 {
2273 Decl *FromTU = getTuDecl(
2274 "struct A { int x; };", Lang_CXX, "input0.cc");
2275 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2276 FromTU, cxxRecordDecl(hasName("A")));
2277 ToR1 = Import(FromR, Lang_CXX);
2278 }
2279 Decl *ToR2;
2280 {
2281 Decl *FromTU = getTuDecl(
2282 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2283 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2284 FromTU, cxxRecordDecl(hasName("A")));
2285 ToR2 = Import(FromR, Lang_CXX);
2286 }
2287 EXPECT_NE(ToR1, ToR2);
2288}
2289
2290TEST_P(ASTImporterTestBase, ImportOfEquivalentField) {
2291 Decl *ToF1;
2292 {
2293 Decl *FromTU = getTuDecl(
2294 "struct A { int x; };", Lang_CXX, "input0.cc");
2295 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2296 FromTU, fieldDecl(hasName("x")));
2297 ToF1 = Import(FromF, Lang_CXX);
2298 }
2299 Decl *ToF2;
2300 {
2301 Decl *FromTU = getTuDecl(
2302 "struct A { int x; };", Lang_CXX, "input1.cc");
2303 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2304 FromTU, fieldDecl(hasName("x")));
2305 ToF2 = Import(FromF, Lang_CXX);
2306 }
2307 EXPECT_EQ(ToF1, ToF2);
2308}
2309
2310TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) {
2311 Decl *ToF1;
2312 {
2313 Decl *FromTU = getTuDecl(
2314 "struct A { int x; };", Lang_CXX, "input0.cc");
2315 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2316 FromTU, fieldDecl(hasName("x")));
2317 ToF1 = Import(FromF, Lang_CXX);
2318 }
2319 Decl *ToF2;
2320 {
2321 Decl *FromTU = getTuDecl(
2322 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2323 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2324 FromTU, fieldDecl(hasName("x")));
2325 ToF2 = Import(FromF, Lang_CXX);
2326 }
2327 EXPECT_NE(ToF1, ToF2);
2328}
2329
2330TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) {
2331 Decl *ToM1;
2332 {
2333 Decl *FromTU = getTuDecl(
2334 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
2335 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2336 FromTU, functionDecl(hasName("x"), isDefinition()));
2337 ToM1 = Import(FromM, Lang_CXX);
2338 }
2339 Decl *ToM2;
2340 {
2341 Decl *FromTU = getTuDecl(
2342 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
2343 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2344 FromTU, functionDecl(hasName("x"), isDefinition()));
2345 ToM2 = Import(FromM, Lang_CXX);
2346 }
2347 EXPECT_EQ(ToM1, ToM2);
2348}
2349
2350TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) {
2351 Decl *ToM1;
2352 {
2353 Decl *FromTU = getTuDecl(
2354 "struct A { void x(); }; void A::x() { }",
2355 Lang_CXX, "input0.cc");
2356 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2357 FromTU, functionDecl(hasName("x"), isDefinition()));
2358 ToM1 = Import(FromM, Lang_CXX);
2359 }
2360 Decl *ToM2;
2361 {
2362 Decl *FromTU = getTuDecl(
2363 "struct A { void x() const; }; void A::x() const { }",
2364 Lang_CXX, "input1.cc");
2365 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2366 FromTU, functionDecl(hasName("x"), isDefinition()));
2367 ToM2 = Import(FromM, Lang_CXX);
2368 }
2369 EXPECT_NE(ToM1, ToM2);
2370}
2371
Gabor Marton61d862a2018-05-18 09:08:47 +00002372struct DeclContextTest : ASTImporterTestBase {};
2373
2374TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
2375 Decl *TU = getTuDecl(
2376 R"(
2377 namespace NS {
2378
2379 template <typename T>
2380 struct S {};
2381 template struct S<int>;
2382
2383 inline namespace INS {
2384 template <typename T>
2385 struct S {};
2386 template struct S<int>;
2387 }
2388
2389 }
2390 )", Lang_CXX11, "input0.cc");
2391 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
2392 TU, namespaceDecl());
2393 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
2394 TU, classTemplateSpecializationDecl());
2395 ASSERT_TRUE(NS->containsDecl(Spec));
2396
2397 NS->removeDecl(Spec);
2398 EXPECT_FALSE(NS->containsDecl(Spec));
2399}
2400
Gabor Marton5254e642018-06-27 13:32:50 +00002401struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
2402
2403TEST_P(ImportFunctionTemplateSpecializations,
2404 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
2405
2406 Decl *FromTU = getTuDecl(
2407 R"(
2408 template<class T>
2409 int f() { return 0; }
2410 void foo() { f<int>(); }
2411 )",
2412 Lang_CXX, "input0.cc");
2413
2414 // Check that the function template instantiation is NOT the child of the TU.
2415 auto Pattern = translationUnitDecl(
2416 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
2417 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2418
2419 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
2420 FromTU, functionDecl(hasName("foo")));
2421 ASSERT_TRUE(Import(Foo, Lang_CXX));
2422
2423 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2424 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2425}
2426
2427TEST_P(ImportFunctionTemplateSpecializations,
2428 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
2429
2430 Decl *FromTU = getTuDecl(
2431 R"(
2432 template<class T>
2433 int f() { return 0; }
2434 template int f<int>();
2435 )",
2436 Lang_CXX, "input0.cc");
2437
2438 // Check that the function template instantiation is NOT the child of the TU.
2439 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
2440 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
2441 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2442
2443 ASSERT_TRUE(
2444 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
2445
2446 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2447 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2448}
2449
2450TEST_P(ImportFunctionTemplateSpecializations,
2451 TUshouldContainFunctionTemplateSpecialization) {
2452
2453 Decl *FromTU = getTuDecl(
2454 R"(
2455 template<class T>
2456 int f() { return 0; }
2457 template <> int f<int>() { return 4; }
2458 )",
2459 Lang_CXX, "input0.cc");
2460
2461 // Check that the function template specialization is the child of the TU.
2462 auto Specialization =
2463 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2464 auto Pattern = translationUnitDecl(has(Specialization));
2465 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2466
2467 ASSERT_TRUE(
2468 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
2469
2470 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2471 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2472}
2473
2474TEST_P(ImportFunctionTemplateSpecializations,
2475 FunctionTemplateSpecializationRedeclChain) {
2476
2477 Decl *FromTU = getTuDecl(
2478 R"(
2479 template<class T>
2480 int f() { return 0; }
2481 template <> int f<int>() { return 4; }
2482 )",
2483 Lang_CXX, "input0.cc");
2484
2485 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
2486 hasParent(translationUnitDecl()));
2487 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
2488 {
2489 auto *TU = FromTU;
2490 auto *SpecD = FromSpecD;
2491 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2492 TU, functionTemplateDecl());
2493 auto *FirstSpecD = *(TemplateD->spec_begin());
2494 ASSERT_EQ(SpecD, FirstSpecD);
2495 ASSERT_TRUE(SpecD->getPreviousDecl());
2496 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
2497 ->doesThisDeclarationHaveABody());
2498 }
2499
2500 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
2501
2502 {
2503 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
2504 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
2505 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2506 TU, functionTemplateDecl());
2507 auto *FirstSpecD = *(TemplateD->spec_begin());
2508 EXPECT_EQ(SpecD, FirstSpecD);
2509 ASSERT_TRUE(SpecD->getPreviousDecl());
2510 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
2511 ->doesThisDeclarationHaveABody());
2512 }
2513}
2514
2515TEST_P(ImportFunctionTemplateSpecializations,
2516 MatchNumberOfFunctionTemplateSpecializations) {
2517
2518 Decl *FromTU = getTuDecl(
2519 R"(
2520 template <typename T> constexpr int f() { return 0; }
2521 template <> constexpr int f<int>() { return 4; }
2522 void foo() {
2523 static_assert(f<char>() == 0, "");
2524 static_assert(f<int>() == 4, "");
2525 }
2526 )",
2527 Lang_CXX11, "input0.cc");
2528 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2529 FromTU, functionDecl(hasName("foo")));
2530
2531 Import(FromD, Lang_CXX11);
2532 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2533 EXPECT_EQ(
2534 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
2535 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
2536}
2537
2538TEST_P(ImportFunctionTemplateSpecializations,
2539 ImportPrototypes) {
2540 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2541 auto Code =
2542 R"(
2543 // Proto of the primary template.
2544 template <class T>
2545 void f();
2546 // Proto of the specialization.
2547 template <>
2548 void f<int>();
2549 )";
2550
2551 Decl *ImportedD;
2552 {
2553 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2554 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2555
2556 ImportedD = Import(FromD, Lang_CXX);
2557 }
2558 {
2559 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
2560 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2561 Import(FromD, Lang_CXX);
2562 }
2563
2564 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2565
2566 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2567 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2568 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2569 EXPECT_TRUE(ImportedD == To0);
2570 EXPECT_TRUE(ImportedD != To1);
2571 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2572 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2573 // Check that they are part of the same redecl chain.
2574 EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
2575}
2576
2577TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
2578 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2579 auto Code =
2580 R"(
2581 // Proto of the primary template.
2582 template <class T>
2583 void f();
2584 // Specialization and definition.
2585 template <>
2586 void f<int>() {}
2587 )";
2588
2589 Decl *ImportedD;
2590 {
2591 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2592 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2593 ImportedD = Import(FromD, Lang_CXX);
2594 }
2595 {
2596 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
2597 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2598 Import(FromD, Lang_CXX);
2599 }
2600
2601 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2602
2603 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
2604 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2605 EXPECT_TRUE(ImportedD == To0);
2606 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2607
2608 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2609 ToTU, functionTemplateDecl());
2610 auto *FirstSpecD = *(TemplateD->spec_begin());
2611 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
2612}
2613
2614TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
2615 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2616 auto Code =
2617 R"(
2618 // Proto of the primary template.
2619 template <class T>
2620 void f();
2621 // Specialization proto.
2622 template <>
2623 void f<int>();
2624 // Specialization proto.
2625 template <>
2626 void f<int>();
2627 )";
2628
2629 Decl *ImportedD;
2630 {
2631 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2632 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2633 ImportedD = Import(FromD, Lang_CXX);
2634 }
2635
2636 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2637
2638 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2639 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2640 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2641 EXPECT_TRUE(ImportedD == To0);
2642 EXPECT_TRUE(ImportedD != To1);
2643 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2644 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2645 EXPECT_EQ(To1->getPreviousDecl(), To0);
2646}
2647
2648TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
2649 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2650 auto Code =
2651 R"(
2652 // Proto of the primary template.
2653 template <class T>
2654 void f();
2655 // Specialization proto.
2656 template <>
2657 void f<int>();
2658 // Specialization definition.
2659 template <>
2660 void f<int>() {}
2661 )";
2662
2663 Decl *ImportedD;
2664 {
2665 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2666 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2667 ImportedD = Import(FromD, Lang_CXX);
2668 }
2669
2670 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2671
2672 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2673 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2674 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2675 EXPECT_TRUE(ImportedD == To0);
2676 EXPECT_TRUE(ImportedD != To1);
2677 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2678 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2679 EXPECT_EQ(To1->getPreviousDecl(), To0);
2680}
2681
2682TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
2683 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2684 auto Code =
2685 R"(
2686 // Proto of the primary template.
2687 template <class T>
2688 void f();
2689 // Specialization definition.
2690 template <>
2691 void f<int>() {}
2692 // Specialization proto.
2693 template <>
2694 void f<int>();
2695 )";
2696
2697 Decl *ImportedD;
2698 {
2699 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2700 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2701 ImportedD = Import(FromD, Lang_CXX);
2702 }
2703
2704 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2705
2706 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2707 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2708 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2709 EXPECT_TRUE(ImportedD == To0);
2710 EXPECT_TRUE(ImportedD != To1);
2711 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2712 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2713 EXPECT_EQ(To1->getPreviousDecl(), To0);
2714}
2715
Gabor Marton19f4f392018-06-25 13:04:37 +00002716INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
2717 ::testing::Values(ArgVector()), );
2718
Gabor Marton5254e642018-06-27 13:32:50 +00002719INSTANTIATE_TEST_CASE_P(
2720 ParameterizedTests, CanonicalRedeclChain,
2721 ::testing::Values(ArgVector()),);
2722
Gabor Marton19f4f392018-06-25 13:04:37 +00002723auto DefaultTestValuesForRunOptions = ::testing::Values(
2724 ArgVector(),
2725 ArgVector{"-fdelayed-template-parsing"},
2726 ArgVector{"-fms-compatibility"},
2727 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
2728
2729INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
2730 DefaultTestValuesForRunOptions, );
2731
2732INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
2733 DefaultTestValuesForRunOptions, );
2734
2735INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
2736 DefaultTestValuesForRunOptions, );
2737
2738INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
2739 DefaultTestValuesForRunOptions, );
2740
2741INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
2742 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00002743
Gabor Marton5254e642018-06-27 13:32:50 +00002744INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
2745 DefaultTestValuesForRunOptions, );
2746
2747INSTANTIATE_TEST_CASE_P(ParameterizedTests,
2748 ImportFunctionTemplateSpecializations,
2749 DefaultTestValuesForRunOptions, );
2750
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00002751} // end namespace ast_matchers
2752} // end namespace clang