blob: b1e6e42b5a4ab2df0bc2fbd8835778c90209cae6 [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
1580TEST_P(
1581 ASTImporterTestBase,
1582 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
1583{
1584 Decl *ToTU = getToTuDecl(
1585 R"(
1586 template <typename T>
1587 struct B;
1588
1589 template <>
1590 struct B<int> {};
1591
1592 template <>
1593 struct B<int>;
1594 )",
1595 Lang_CXX);
1596 // We should have only one definition.
1597 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1598 [](const ClassTemplateSpecializationDecl *T) {
1599 return T->isThisDeclarationADefinition();
1600 })
1601 .match(ToTU, classTemplateSpecializationDecl()));
1602
1603 Decl *FromTU = getTuDecl(
1604 R"(
1605 template <typename T>
1606 struct B;
1607
1608 template <>
1609 struct B<int> {};
1610 )",
1611 Lang_CXX, "input1.cc");
1612 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1613 FromTU, classTemplateSpecializationDecl(hasName("B")));
1614
1615 Import(FromD, Lang_CXX);
1616
1617 // We should have only one definition.
1618 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1619 [](const ClassTemplateSpecializationDecl *T) {
1620 return T->isThisDeclarationADefinition();
1621 })
1622 .match(ToTU, classTemplateSpecializationDecl()));
1623}
1624
Peter Szecsidedda6f2018-03-30 22:03:29 +00001625struct ImportFunctions : ASTImporterTestBase {};
1626
1627TEST_P(ImportFunctions,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001628 DefinitionShouldBeImportedAsDefintionWhenThereIsAPrototype) {
1629 Decl *FromTU = getTuDecl("void f(); void f() {}", Lang_CXX);
1630 auto Pattern = functionDecl(hasName("f"));
1631 FunctionDecl *FromD = // Definition
1632 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1633
1634 Decl *ImportedD = Import(FromD, Lang_CXX);
1635 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1636
Gabor Marton5254e642018-06-27 13:32:50 +00001637 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001638 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1639}
1640
1641TEST_P(ImportFunctions, DefinitionShouldBeImportedAsADefinition) {
1642 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX);
1643 auto Pattern = functionDecl(hasName("f"));
1644 FunctionDecl *FromD =
1645 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1646
1647 Decl *ImportedD = Import(FromD, Lang_CXX);
1648 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1649
1650 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
1651 EXPECT_TRUE(cast<FunctionDecl>(ImportedD)->doesThisDeclarationHaveABody());
1652}
1653
Gabor Marton5254e642018-06-27 13:32:50 +00001654TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001655 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1656 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001657 auto *From =
1658 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00001659
Gabor Marton5254e642018-06-27 13:32:50 +00001660 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001661 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1662
Gabor Marton5254e642018-06-27 13:32:50 +00001663 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1664 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1665 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1666 EXPECT_TRUE(ImportedD == To0);
1667 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1668 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1669 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001670}
1671
1672TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1673 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1674 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001675 auto *From =
1676 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00001677
Gabor Marton5254e642018-06-27 13:32:50 +00001678 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001679 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1680
Gabor Marton5254e642018-06-27 13:32:50 +00001681 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1682 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1683 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1684 EXPECT_TRUE(ImportedD == To1);
1685 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1686 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1687 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001688}
1689
1690TEST_P(ImportFunctions, ImportPrototypes) {
1691 auto Pattern = functionDecl(hasName("f"));
1692
1693 Decl *ImportedD;
1694 {
1695 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001696 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001697
1698 ImportedD = Import(FromD, Lang_CXX);
1699 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001700 {
1701 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001702 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1703 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001704 }
1705
Gabor Marton5254e642018-06-27 13:32:50 +00001706 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1707
1708 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1709 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1710 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1711 EXPECT_TRUE(ImportedD == To0);
1712 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1713 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1714 EXPECT_EQ(To1->getPreviousDecl(), To0);
1715}
1716
1717TEST_P(ImportFunctions, ImportDefinitions) {
1718 auto Pattern = functionDecl(hasName("f"));
1719
1720 Decl *ImportedD;
1721 {
1722 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
1723 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1724 ImportedD = Import(FromD, Lang_CXX);
1725 }
1726 {
1727 Decl *FromTU = getTuDecl("void f(){};", Lang_CXX, "input1.cc");
1728 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1729 Import(FromD, Lang_CXX);
1730 }
1731
1732 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1733
Peter Szecsidedda6f2018-03-30 22:03:29 +00001734 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Gabor Marton5254e642018-06-27 13:32:50 +00001735 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1736 EXPECT_TRUE(ImportedD == To0);
1737 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00001738}
1739
1740TEST_P(ImportFunctions, ImportDefinitionThenPrototype) {
1741 auto Pattern = functionDecl(hasName("f"));
1742
1743 Decl *ImportedD;
1744 {
1745 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001746 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001747 ImportedD = Import(FromD, Lang_CXX);
1748 }
Peter Szecsidedda6f2018-03-30 22:03:29 +00001749 {
1750 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001751 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1752 Import(FromD, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001753 }
1754
1755 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00001756
1757 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1758 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1759 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1760 EXPECT_TRUE(ImportedD == To0);
1761 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
1762 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
1763 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001764}
1765
1766TEST_P(ImportFunctions, ImportPrototypeThenDefinition) {
1767 auto Pattern = functionDecl(hasName("f"));
1768
1769 {
1770 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
1771 FunctionDecl *FromD =
1772 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1773
1774 Import(FromD, Lang_CXX);
1775 }
1776 {
1777 Decl *FromTU = getTuDecl("void f(){}", Lang_CXX, "input1.cc");
1778 FunctionDecl *FromD =
1779 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1780 Import(FromD, Lang_CXX);
1781 }
1782
1783 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1784 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1785 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00001786 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
Peter Szecsidedda6f2018-03-30 22:03:29 +00001787 FunctionDecl *DefinitionD =
1788 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1789 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
1790 EXPECT_EQ(DefinitionD->getPreviousDecl(), ProtoD);
1791}
1792
Gabor Marton5254e642018-06-27 13:32:50 +00001793TEST_P(ImportFunctions, ImportPrototypeThenProtoAndDefinition) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001794 auto Pattern = functionDecl(hasName("f"));
1795
1796 {
1797 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input0.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001798 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001799 Import(FromD, Lang_CXX);
1800 }
1801 {
1802 Decl *FromTU = getTuDecl("void f(); void f(){}", Lang_CXX, "input1.cc");
Gabor Marton5254e642018-06-27 13:32:50 +00001803 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001804 Import(FromD, Lang_CXX);
1805 }
1806
1807 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
Gabor Marton5254e642018-06-27 13:32:50 +00001808
1809 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 3u);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001810 FunctionDecl *ProtoD = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
Gabor Marton5254e642018-06-27 13:32:50 +00001811 EXPECT_FALSE(ProtoD->doesThisDeclarationHaveABody());
1812
Peter Szecsidedda6f2018-03-30 22:03:29 +00001813 FunctionDecl *DefinitionD =
1814 LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1815 EXPECT_TRUE(DefinitionD->doesThisDeclarationHaveABody());
Gabor Marton5254e642018-06-27 13:32:50 +00001816
1817 EXPECT_TRUE(DefinitionD->getPreviousDecl());
1818 EXPECT_FALSE(DefinitionD->getPreviousDecl()->doesThisDeclarationHaveABody());
1819 EXPECT_EQ(DefinitionD->getPreviousDecl()->getPreviousDecl(), ProtoD);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001820}
1821
1822TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
1823 auto Code =
1824 R"(
1825 struct B { virtual void f(); };
1826 void B::f() {}
1827 struct D : B { void f(); };
1828 )";
1829 auto Pattern =
1830 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
1831 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1832 CXXMethodDecl *Proto =
1833 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1834
1835 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
1836 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1837 EXPECT_EQ(To->size_overridden_methods(), 1u);
1838}
1839
1840TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
1841 auto Code =
1842 R"(
1843 struct B { virtual void f(); };
1844 void B::f() {}
1845 )";
1846 auto Pattern =
1847 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1848 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1849 CXXMethodDecl *Proto =
1850 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1851 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1852
1853 ASSERT_TRUE(Proto->isVirtual());
1854 ASSERT_TRUE(Def->isVirtual());
1855 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1856 EXPECT_TRUE(To->isVirtual());
1857}
1858
Gabor Marton5254e642018-06-27 13:32:50 +00001859TEST_P(ImportFunctions,
1860 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
1861 Decl *ToTU = getToTuDecl(
1862 R"(
1863 void f() {}
1864 void f();
1865 )",
1866 Lang_CXX);
1867 ASSERT_EQ(1u,
1868 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
1869 return FD->doesThisDeclarationHaveABody();
1870 }).match(ToTU, functionDecl()));
1871
1872 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
1873 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1874
1875 Import(FromD, Lang_CXX);
1876
1877 EXPECT_EQ(1u,
1878 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
1879 return FD->doesThisDeclarationHaveABody();
1880 }).match(ToTU, functionDecl()));
1881}
1882
1883struct ImportFriendFunctions : ImportFunctions {};
1884
1885TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
1886 auto Pattern = functionDecl(hasName("f"));
1887
1888 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
1889 "void f();",
1890 Lang_CXX,
1891 "input0.cc");
1892 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1893
1894 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
1895 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1896 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1897 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
1898 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1899 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
1900 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
1901}
1902
1903TEST_P(ImportFriendFunctions,
1904 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
1905 auto Pattern = functionDecl(hasName("f"));
1906
1907 Decl *FromTU = getTuDecl("void f();"
1908 "struct X { friend void f(); };",
1909 Lang_CXX, "input0.cc");
1910 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1911
1912 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
1913 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1914 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1915 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
1916 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1917 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
1918 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
1919}
1920
1921TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
1922 auto Pattern = functionDecl(hasName("f"));
1923
1924 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
1925 "void f();",
1926 Lang_CXX,
1927 "input0.cc");
1928 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1929
1930 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
1931 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1932 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1933 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
1934 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1935 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
1936 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
1937}
1938
1939TEST_P(ImportFriendFunctions,
1940 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
1941 auto Pattern = functionDecl(hasName("f"));
1942
1943 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
1944 "void f(){}",
1945 Lang_CXX, "input0.cc");
1946 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1947
1948 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
1949 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1950 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1951 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
1952 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1953 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
1954 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
1955}
1956
1957// This test is disabled, because ATM we create a redundant FunctionDecl. We
1958// start the import with the definition of `f` then we continue with the import
1959// of the type of `f` which involves `X`. During the import of `X` we start
1960// again the import of the definition of `f` and then finally we create the
1961// node. But then in the first frame of `VisitFunctionDecl` we create a node
1962// again since we do not check if such a node exists yet or not. This is being
1963// fixed in a separate patch: https://reviews.llvm.org/D47632
1964// FIXME enable this test once the above patch is approved.
1965TEST_P(ImportFriendFunctions,
1966 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
1967 auto Pattern = functionDecl(hasName("f"));
1968
1969 Decl *FromTU = getTuDecl(
1970 R"(
1971 class X;
1972 void f(X *x){}
1973 class X{
1974 friend void f(X *x);
1975 };
1976 )",
1977 Lang_CXX, "input0.cc");
1978 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
1979
1980 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
1981 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1982 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1983 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
1984 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
1985 .match(ToTU, friendDecl())
1986 ->getFriendDecl());
1987 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
1988 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
1989 // The parameters must refer the same type
1990 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
1991 (*ImportedD->param_begin())->getOriginalType());
1992}
1993
1994// This test is disabled, because ATM we create a redundant FunctionDecl. We
1995// start the import with the definition of `f` then we continue with the import
1996// of the type of `f` which involves `X`. During the import of `X` we start
1997// again the import of the definition of `f` and then finally we create the
1998// node. But then in the first frame of `VisitFunctionDecl` we create a node
1999// again since we do not check if such a node exists yet or not. This is being
2000// fixed in a separate patch: https://reviews.llvm.org/D47632
2001// FIXME enable this test once the above patch is approved.
2002TEST_P(ImportFriendFunctions,
2003 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
2004 auto Pattern = functionDecl(hasName("f"));
2005
2006 Decl *FromTU = getTuDecl(
2007 R"(
2008 class X;
2009 void f(X *x){}
2010 class X{
2011 friend void f(X *x);
2012 };
2013 )",
2014 Lang_CXX, "input0.cc");
2015 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2016
2017 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2018 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2019 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2020 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2021 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2022 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2023
2024 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2025 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2026 // The parameters must refer the same type
2027 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2028 (*ImportedD->param_begin())->getOriginalType());
2029}
2030
2031TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2032 auto Pattern = functionDecl(hasName("f"));
2033
2034 FunctionDecl *ImportedD;
2035 {
2036 Decl *FromTU =
2037 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2038 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2039 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2040 }
2041 FunctionDecl *ImportedD1;
2042 {
2043 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2044 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2045 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2046 }
2047
2048 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2049 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2050 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2051 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2052 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2053}
2054
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002055AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2056 InnerMatcher) {
2057 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2058 return InnerMatcher.matches(*Typedef, Finder, Builder);
2059 return false;
2060}
2061
Gabor Marton19f4f392018-06-25 13:04:37 +00002062TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002063 CodeFiles Samples{{"main.c",
2064 {"void foo();"
2065 "void moo();"
2066 "int main() { foo(); moo(); }",
2067 Lang_C}},
2068
2069 {"foo.c",
2070 {"typedef enum { THING_VALUE } thing_t;"
2071 "void conflict(thing_t type);"
2072 "void foo() { (void)THING_VALUE; }"
2073 "void conflict(thing_t type) {}",
2074 Lang_C}},
2075
2076 {"moo.c",
2077 {"typedef enum { THING_VALUE } thing_t;"
2078 "void conflict(thing_t type);"
2079 "void moo() { conflict(THING_VALUE); }",
2080 Lang_C}}};
2081
2082 auto VerificationMatcher =
2083 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2084 hasTypedefForAnonDecl(hasName("thing_t")));
2085
2086 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2087 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2088
2089 testImportSequence(
2090 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2091 // Just check that there is only one enum decl in the result AST.
2092 "main.c", enumDecl(), VerificationMatcher);
2093
2094 // For different import order, result should be the same.
2095 testImportSequence(
2096 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2097 // Check that there is only one enum decl in the result AST.
2098 "main.c", enumDecl(), VerificationMatcher);
2099}
2100
Peter Szecsice7f3182018-05-07 12:08:27 +00002101const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2102 dependentScopeDeclRefExpr;
2103
Gabor Marton19f4f392018-06-25 13:04:37 +00002104TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002105 MatchVerifier<Decl> Verifier;
2106 testImport("template <typename T> struct S { static T foo; };"
2107 "template <typename T> void declToImport() {"
2108 " (void) S<T>::foo;"
2109 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002110 "void instantiate() { declToImport<int>(); }"
2111 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002112 Lang_CXX11, "", Lang_CXX11, Verifier,
2113 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2114 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2115
2116 testImport("template <typename T> struct S {"
2117 "template<typename S> static void foo(){};"
2118 "};"
2119 "template <typename T> void declToImport() {"
2120 " S<T>::template foo<T>();"
2121 "}"
2122 "void instantiate() { declToImport<int>(); }",
2123 Lang_CXX11, "", Lang_CXX11, Verifier,
2124 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2125 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2126}
2127
2128const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2129 dependentNameType;
2130
Gabor Marton19f4f392018-06-25 13:04:37 +00002131TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002132 MatchVerifier<Decl> Verifier;
2133 testImport("template <typename T> struct declToImport {"
2134 " typedef typename T::type dependent_name;"
2135 "};",
2136 Lang_CXX11, "", Lang_CXX11, Verifier,
2137 classTemplateDecl(has(
2138 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2139}
2140
2141const internal::VariadicDynCastAllOfMatcher<Expr, UnresolvedMemberExpr>
2142 unresolvedMemberExpr;
2143
Gabor Marton19f4f392018-06-25 13:04:37 +00002144TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002145 MatchVerifier<Decl> Verifier;
2146 testImport("struct S { template <typename T> void mem(); };"
2147 "template <typename U> void declToImport() {"
2148 " S s;"
2149 " s.mem<U>();"
2150 "}"
2151 "void instantiate() { declToImport<int>(); }",
2152 Lang_CXX11, "", Lang_CXX11, Verifier,
2153 functionTemplateDecl(has(functionDecl(has(
2154 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2155}
2156
Gabor Marton61d862a2018-05-18 09:08:47 +00002157struct DeclContextTest : ASTImporterTestBase {};
2158
2159TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
2160 Decl *TU = getTuDecl(
2161 R"(
2162 namespace NS {
2163
2164 template <typename T>
2165 struct S {};
2166 template struct S<int>;
2167
2168 inline namespace INS {
2169 template <typename T>
2170 struct S {};
2171 template struct S<int>;
2172 }
2173
2174 }
2175 )", Lang_CXX11, "input0.cc");
2176 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
2177 TU, namespaceDecl());
2178 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
2179 TU, classTemplateSpecializationDecl());
2180 ASSERT_TRUE(NS->containsDecl(Spec));
2181
2182 NS->removeDecl(Spec);
2183 EXPECT_FALSE(NS->containsDecl(Spec));
2184}
2185
Gabor Marton5254e642018-06-27 13:32:50 +00002186struct ImportFunctionTemplateSpecializations : ASTImporterTestBase {};
2187
2188TEST_P(ImportFunctionTemplateSpecializations,
2189 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
2190
2191 Decl *FromTU = getTuDecl(
2192 R"(
2193 template<class T>
2194 int f() { return 0; }
2195 void foo() { f<int>(); }
2196 )",
2197 Lang_CXX, "input0.cc");
2198
2199 // Check that the function template instantiation is NOT the child of the TU.
2200 auto Pattern = translationUnitDecl(
2201 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
2202 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2203
2204 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
2205 FromTU, functionDecl(hasName("foo")));
2206 ASSERT_TRUE(Import(Foo, Lang_CXX));
2207
2208 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2209 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2210}
2211
2212TEST_P(ImportFunctionTemplateSpecializations,
2213 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
2214
2215 Decl *FromTU = getTuDecl(
2216 R"(
2217 template<class T>
2218 int f() { return 0; }
2219 template int f<int>();
2220 )",
2221 Lang_CXX, "input0.cc");
2222
2223 // Check that the function template instantiation is NOT the child of the TU.
2224 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
2225 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
2226 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2227
2228 ASSERT_TRUE(
2229 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
2230
2231 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2232 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2233}
2234
2235TEST_P(ImportFunctionTemplateSpecializations,
2236 TUshouldContainFunctionTemplateSpecialization) {
2237
2238 Decl *FromTU = getTuDecl(
2239 R"(
2240 template<class T>
2241 int f() { return 0; }
2242 template <> int f<int>() { return 4; }
2243 )",
2244 Lang_CXX, "input0.cc");
2245
2246 // Check that the function template specialization is the child of the TU.
2247 auto Specialization =
2248 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2249 auto Pattern = translationUnitDecl(has(Specialization));
2250 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
2251
2252 ASSERT_TRUE(
2253 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
2254
2255 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2256 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
2257}
2258
2259TEST_P(ImportFunctionTemplateSpecializations,
2260 FunctionTemplateSpecializationRedeclChain) {
2261
2262 Decl *FromTU = getTuDecl(
2263 R"(
2264 template<class T>
2265 int f() { return 0; }
2266 template <> int f<int>() { return 4; }
2267 )",
2268 Lang_CXX, "input0.cc");
2269
2270 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
2271 hasParent(translationUnitDecl()));
2272 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
2273 {
2274 auto *TU = FromTU;
2275 auto *SpecD = FromSpecD;
2276 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2277 TU, functionTemplateDecl());
2278 auto *FirstSpecD = *(TemplateD->spec_begin());
2279 ASSERT_EQ(SpecD, FirstSpecD);
2280 ASSERT_TRUE(SpecD->getPreviousDecl());
2281 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
2282 ->doesThisDeclarationHaveABody());
2283 }
2284
2285 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
2286
2287 {
2288 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
2289 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
2290 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2291 TU, functionTemplateDecl());
2292 auto *FirstSpecD = *(TemplateD->spec_begin());
2293 EXPECT_EQ(SpecD, FirstSpecD);
2294 ASSERT_TRUE(SpecD->getPreviousDecl());
2295 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
2296 ->doesThisDeclarationHaveABody());
2297 }
2298}
2299
2300TEST_P(ImportFunctionTemplateSpecializations,
2301 MatchNumberOfFunctionTemplateSpecializations) {
2302
2303 Decl *FromTU = getTuDecl(
2304 R"(
2305 template <typename T> constexpr int f() { return 0; }
2306 template <> constexpr int f<int>() { return 4; }
2307 void foo() {
2308 static_assert(f<char>() == 0, "");
2309 static_assert(f<int>() == 4, "");
2310 }
2311 )",
2312 Lang_CXX11, "input0.cc");
2313 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2314 FromTU, functionDecl(hasName("foo")));
2315
2316 Import(FromD, Lang_CXX11);
2317 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2318 EXPECT_EQ(
2319 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
2320 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
2321}
2322
2323TEST_P(ImportFunctionTemplateSpecializations,
2324 ImportPrototypes) {
2325 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2326 auto Code =
2327 R"(
2328 // Proto of the primary template.
2329 template <class T>
2330 void f();
2331 // Proto of the specialization.
2332 template <>
2333 void f<int>();
2334 )";
2335
2336 Decl *ImportedD;
2337 {
2338 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2339 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2340
2341 ImportedD = Import(FromD, Lang_CXX);
2342 }
2343 {
2344 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
2345 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2346 Import(FromD, Lang_CXX);
2347 }
2348
2349 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2350
2351 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2352 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2353 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2354 EXPECT_TRUE(ImportedD == To0);
2355 EXPECT_TRUE(ImportedD != To1);
2356 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2357 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2358 // Check that they are part of the same redecl chain.
2359 EXPECT_EQ(To1->getCanonicalDecl(), To0->getCanonicalDecl());
2360}
2361
2362TEST_P(ImportFunctionTemplateSpecializations, ImportDefinitions) {
2363 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2364 auto Code =
2365 R"(
2366 // Proto of the primary template.
2367 template <class T>
2368 void f();
2369 // Specialization and definition.
2370 template <>
2371 void f<int>() {}
2372 )";
2373
2374 Decl *ImportedD;
2375 {
2376 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2377 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2378 ImportedD = Import(FromD, Lang_CXX);
2379 }
2380 {
2381 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input1.cc");
2382 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2383 Import(FromD, Lang_CXX);
2384 }
2385
2386 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2387
2388 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
2389 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2390 EXPECT_TRUE(ImportedD == To0);
2391 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2392
2393 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
2394 ToTU, functionTemplateDecl());
2395 auto *FirstSpecD = *(TemplateD->spec_begin());
2396 EXPECT_EQ(FirstSpecD->getCanonicalDecl(), To0->getCanonicalDecl());
2397}
2398
2399TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenPrototype) {
2400 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2401 auto Code =
2402 R"(
2403 // Proto of the primary template.
2404 template <class T>
2405 void f();
2406 // Specialization proto.
2407 template <>
2408 void f<int>();
2409 // Specialization proto.
2410 template <>
2411 void f<int>();
2412 )";
2413
2414 Decl *ImportedD;
2415 {
2416 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2417 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2418 ImportedD = Import(FromD, Lang_CXX);
2419 }
2420
2421 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2422
2423 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2424 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2425 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2426 EXPECT_TRUE(ImportedD == To0);
2427 EXPECT_TRUE(ImportedD != To1);
2428 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2429 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2430 EXPECT_EQ(To1->getPreviousDecl(), To0);
2431}
2432
2433TEST_P(ImportFunctionTemplateSpecializations, PrototypeThenDefinition) {
2434 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2435 auto Code =
2436 R"(
2437 // Proto of the primary template.
2438 template <class T>
2439 void f();
2440 // Specialization proto.
2441 template <>
2442 void f<int>();
2443 // Specialization definition.
2444 template <>
2445 void f<int>() {}
2446 )";
2447
2448 Decl *ImportedD;
2449 {
2450 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2451 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2452 ImportedD = Import(FromD, Lang_CXX);
2453 }
2454
2455 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2456
2457 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2458 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2459 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2460 EXPECT_TRUE(ImportedD == To0);
2461 EXPECT_TRUE(ImportedD != To1);
2462 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2463 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2464 EXPECT_EQ(To1->getPreviousDecl(), To0);
2465}
2466
2467TEST_P(ImportFunctionTemplateSpecializations, DefinitionThenPrototype) {
2468 auto Pattern = functionDecl(hasName("f"), isExplicitTemplateSpecialization());
2469 auto Code =
2470 R"(
2471 // Proto of the primary template.
2472 template <class T>
2473 void f();
2474 // Specialization definition.
2475 template <>
2476 void f<int>() {}
2477 // Specialization proto.
2478 template <>
2479 void f<int>();
2480 )";
2481
2482 Decl *ImportedD;
2483 {
2484 Decl *FromTU = getTuDecl(Code, Lang_CXX, "input0.cc");
2485 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2486 ImportedD = Import(FromD, Lang_CXX);
2487 }
2488
2489 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2490
2491 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2492 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2493 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2494 EXPECT_TRUE(ImportedD == To0);
2495 EXPECT_TRUE(ImportedD != To1);
2496 EXPECT_TRUE(To0->doesThisDeclarationHaveABody());
2497 EXPECT_FALSE(To1->doesThisDeclarationHaveABody());
2498 EXPECT_EQ(To1->getPreviousDecl(), To0);
2499}
2500
Gabor Marton19f4f392018-06-25 13:04:37 +00002501INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
2502 ::testing::Values(ArgVector()), );
2503
Gabor Marton5254e642018-06-27 13:32:50 +00002504INSTANTIATE_TEST_CASE_P(
2505 ParameterizedTests, CanonicalRedeclChain,
2506 ::testing::Values(ArgVector()),);
2507
Gabor Marton19f4f392018-06-25 13:04:37 +00002508auto DefaultTestValuesForRunOptions = ::testing::Values(
2509 ArgVector(),
2510 ArgVector{"-fdelayed-template-parsing"},
2511 ArgVector{"-fms-compatibility"},
2512 ArgVector{"-fdelayed-template-parsing", "-fms-compatibility"});
2513
2514INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
2515 DefaultTestValuesForRunOptions, );
2516
2517INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
2518 DefaultTestValuesForRunOptions, );
2519
2520INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
2521 DefaultTestValuesForRunOptions, );
2522
2523INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterTestBase,
2524 DefaultTestValuesForRunOptions, );
2525
2526INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
2527 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00002528
Gabor Marton5254e642018-06-27 13:32:50 +00002529INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
2530 DefaultTestValuesForRunOptions, );
2531
2532INSTANTIATE_TEST_CASE_P(ParameterizedTests,
2533 ImportFunctionTemplateSpecializations,
2534 DefaultTestValuesForRunOptions, );
2535
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00002536} // end namespace ast_matchers
2537} // end namespace clang