blob: ba2feff5fca673aca5b782161e8b100fc53da704 [file] [log] [blame]
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00001//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00006//
7//===----------------------------------------------------------------------===//
8//
9// Tests for the correct import of AST nodes from one AST context to another.
10//
11//===----------------------------------------------------------------------===//
12
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000013#include "llvm/ADT/StringMap.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000014
Gabor Marton3c72fe12019-05-13 10:06:25 +000015#include "clang/AST/DeclContextInternals.h"
16
17#include "ASTImporterFixtures.h"
18#include "MatchVerifier.h"
19
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000020namespace clang {
21namespace ast_matchers {
22
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000023using internal::Matcher;
24using internal::BindableMatcher;
25using llvm::StringMap;
26
Gabor Marton19f4f392018-06-25 13:04:37 +000027// Base class for those tests which use the family of `testImport` functions.
Gabor Marton0b57ccb2019-02-07 16:52:48 +000028class TestImportBase : public CompilerOptionSpecificTest,
29 public ::testing::WithParamInterface<ArgVector> {
Adam Baloghe4192a82018-06-15 06:45:39 +000030
Gabor Marton19f4f392018-06-25 13:04:37 +000031 template <typename NodeType>
Balazs Keria1f6b102019-04-08 13:59:15 +000032 llvm::Expected<NodeType> importNode(ASTUnit *From, ASTUnit *To,
33 ASTImporter &Importer, NodeType Node) {
Gabor Marton19f4f392018-06-25 13:04:37 +000034 ASTContext &ToCtx = To->getASTContext();
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000035
Gabor Marton19f4f392018-06-25 13:04:37 +000036 // Add 'From' file to virtual file system so importer can 'find' it
37 // while importing SourceLocations. It is safe to add same file multiple
38 // times - it just isn't replaced.
39 StringRef FromFileName = From->getMainFileName();
40 createVirtualFileIfNeeded(To, FromFileName,
41 From->getBufferForFile(FromFileName));
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000042
Gabor Marton5ac6d492019-05-15 10:29:48 +000043 auto Imported = Importer.Import(Node);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000044
Balazs Keria1f6b102019-04-08 13:59:15 +000045 if (Imported) {
46 // This should dump source locations and assert if some source locations
47 // were not imported.
48 SmallString<1024> ImportChecker;
49 llvm::raw_svector_ostream ToNothing(ImportChecker);
50 ToCtx.getTranslationUnitDecl()->print(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000051
Balazs Keria1f6b102019-04-08 13:59:15 +000052 // This traverses the AST to catch certain bugs like poorly or not
53 // implemented subtrees.
54 (*Imported)->dump(ToNothing);
55 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000056
Gabor Marton19f4f392018-06-25 13:04:37 +000057 return Imported;
58 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000059
Gabor Marton19f4f392018-06-25 13:04:37 +000060 template <typename NodeType>
61 testing::AssertionResult
62 testImport(const std::string &FromCode, const ArgVector &FromArgs,
63 const std::string &ToCode, const ArgVector &ToArgs,
64 MatchVerifier<NodeType> &Verifier,
65 const BindableMatcher<NodeType> &SearchMatcher,
66 const BindableMatcher<NodeType> &VerificationMatcher) {
67 const char *const InputFileName = "input.cc";
68 const char *const OutputFileName = "output.cc";
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000069
Gabor Marton19f4f392018-06-25 13:04:37 +000070 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
71 FromCode, FromArgs, InputFileName),
72 ToAST = tooling::buildASTFromCodeWithArgs(
73 ToCode, ToArgs, OutputFileName);
74
75 ASTContext &FromCtx = FromAST->getASTContext(),
76 &ToCtx = ToAST->getASTContext();
77
78 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
79 FromAST->getFileManager(), false);
80
81 auto FoundNodes = match(SearchMatcher, FromCtx);
82 if (FoundNodes.size() != 1)
83 return testing::AssertionFailure()
84 << "Multiple potential nodes were found!";
85
86 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
87 if (!ToImport)
88 return testing::AssertionFailure() << "Node type mismatch!";
89
90 // Sanity check: the node being imported should match in the same way as
91 // the result node.
92 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
93 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
94
95 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
Balazs Keria1f6b102019-04-08 13:59:15 +000096 if (!Imported) {
97 std::string ErrorText;
98 handleAllErrors(
99 Imported.takeError(),
100 [&ErrorText](const ImportError &Err) { ErrorText = Err.message(); });
101 return testing::AssertionFailure()
102 << "Import failed, error: \"" << ErrorText << "\"!";
103 }
Gabor Marton19f4f392018-06-25 13:04:37 +0000104
Balazs Keria1f6b102019-04-08 13:59:15 +0000105 return Verifier.match(*Imported, WrapperMatcher);
Gabor Marton19f4f392018-06-25 13:04:37 +0000106 }
107
108 template <typename NodeType>
109 testing::AssertionResult
110 testImport(const std::string &FromCode, const ArgVector &FromArgs,
111 const std::string &ToCode, const ArgVector &ToArgs,
112 MatchVerifier<NodeType> &Verifier,
113 const BindableMatcher<NodeType> &VerificationMatcher) {
114 return testImport(
115 FromCode, FromArgs, ToCode, ToArgs, Verifier,
116 translationUnitDecl(
117 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
118 VerificationMatcher);
119 }
120
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000121protected:
122 ArgVector getExtraArgs() const override { return GetParam(); }
123
Gabor Marton19f4f392018-06-25 13:04:37 +0000124public:
125
126 /// Test how AST node named "declToImport" located in the translation unit
127 /// of "FromCode" virtual file is imported to "ToCode" virtual file.
128 /// The verification is done by running AMatcher over the imported node.
129 template <typename NodeType, typename MatcherType>
130 void testImport(const std::string &FromCode, Language FromLang,
131 const std::string &ToCode, Language ToLang,
132 MatchVerifier<NodeType> &Verifier,
133 const MatcherType &AMatcher) {
134 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
135 ToArgs = getArgVectorForLanguage(ToLang);
136 EXPECT_TRUE(
137 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
138 }
139
140 struct ImportAction {
141 StringRef FromFilename;
142 StringRef ToFilename;
143 // FIXME: Generalize this to support other node kinds.
144 BindableMatcher<Decl> ImportPredicate;
145
146 ImportAction(StringRef FromFilename, StringRef ToFilename,
147 DeclarationMatcher ImportPredicate)
148 : FromFilename(FromFilename), ToFilename(ToFilename),
149 ImportPredicate(ImportPredicate) {}
150
151 ImportAction(StringRef FromFilename, StringRef ToFilename,
152 const std::string &DeclName)
153 : FromFilename(FromFilename), ToFilename(ToFilename),
154 ImportPredicate(namedDecl(hasName(DeclName))) {}
155 };
156
157 using SingleASTUnit = std::unique_ptr<ASTUnit>;
158 using AllASTUnits = StringMap<SingleASTUnit>;
159
160 struct CodeEntry {
161 std::string CodeSample;
162 Language Lang;
163 };
164
165 using CodeFiles = StringMap<CodeEntry>;
166
167 /// Builds an ASTUnit for one potential compile options set.
168 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
169 ArgVector Args = getArgVectorForLanguage(CE.Lang);
170 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
171 EXPECT_TRUE(AST.get());
172 return AST;
173 }
174
175 /// Test an arbitrary sequence of imports for a set of given in-memory files.
176 /// The verification is done by running VerificationMatcher against a
177 /// specified AST node inside of one of given files.
178 /// \param CodeSamples Map whose key is the file name and the value is the
179 /// file content.
180 /// \param ImportActions Sequence of imports. Each import in sequence
181 /// specifies "from file" and "to file" and a matcher that is used for
182 /// searching a declaration for import in "from file".
183 /// \param FileForFinalCheck Name of virtual file for which the final check is
184 /// applied.
185 /// \param FinalSelectPredicate Matcher that specifies the AST node in the
186 /// FileForFinalCheck for which the verification will be done.
187 /// \param VerificationMatcher Matcher that will be used for verification
188 /// after all imports in sequence are done.
189 void testImportSequence(const CodeFiles &CodeSamples,
190 const std::vector<ImportAction> &ImportActions,
191 StringRef FileForFinalCheck,
192 BindableMatcher<Decl> FinalSelectPredicate,
193 BindableMatcher<Decl> VerificationMatcher) {
194 AllASTUnits AllASTs;
195 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
196 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
197
198 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
199 if (!AllASTs.count(Filename)) {
200 auto Found = CodeSamples.find(Filename);
201 assert(Found != CodeSamples.end() && "Wrong file for import!");
202 AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
203 }
204 };
205
206 for (const ImportAction &Action : ImportActions) {
207 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
208 GenASTsIfNeeded(FromFile);
209 GenASTsIfNeeded(ToFile);
210
211 ASTUnit *From = AllASTs[FromFile].get();
212 ASTUnit *To = AllASTs[ToFile].get();
213
214 // Create a new importer if needed.
215 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
216 if (!ImporterRef)
217 ImporterRef.reset(new ASTImporter(
218 To->getASTContext(), To->getFileManager(), From->getASTContext(),
219 From->getFileManager(), false));
220
221 // Find the declaration and import it.
222 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
223 From->getASTContext());
224 EXPECT_TRUE(FoundDecl.size() == 1);
225 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
226 auto Imported = importNode(From, To, *ImporterRef, ToImport);
Balazs Keria1f6b102019-04-08 13:59:15 +0000227 EXPECT_TRUE(static_cast<bool>(Imported));
228 if (!Imported)
229 llvm::consumeError(Imported.takeError());
Gabor Marton19f4f392018-06-25 13:04:37 +0000230 }
231
232 // Find the declaration and import it.
233 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
234 AllASTs[FileForFinalCheck]->getASTContext());
235 EXPECT_TRUE(FoundDecl.size() == 1);
236 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
237 MatchVerifier<Decl> Verifier;
238 EXPECT_TRUE(
239 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
240 }
241};
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000242
Gabor Martonf086fa82018-07-17 12:06:36 +0000243template <typename T> RecordDecl *getRecordDecl(T *D) {
244 auto *ET = cast<ElaboratedType>(D->getType().getTypePtr());
245 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
Nico Weberb980b5c2018-07-17 14:20:02 +0000246}
Gabor Martonf086fa82018-07-17 12:06:36 +0000247
Gabor Marton19f4f392018-06-25 13:04:37 +0000248struct ImportExpr : TestImportBase {};
249struct ImportType : TestImportBase {};
250struct ImportDecl : TestImportBase {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000251
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000252struct CanonicalRedeclChain : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +0000253
254TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
255 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
256 auto Pattern = functionDecl(hasName("f"));
257 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
258
259 auto Redecls = getCanonicalForwardRedeclChain(D0);
260 ASSERT_EQ(Redecls.size(), 1u);
261 EXPECT_EQ(D0, Redecls[0]);
262}
263
264TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
265 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
266 auto Pattern = functionDecl(hasName("f"));
267 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
268 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
269 FunctionDecl *D1 = D2->getPreviousDecl();
270
271 auto Redecls = getCanonicalForwardRedeclChain(D0);
272 ASSERT_EQ(Redecls.size(), 3u);
273 EXPECT_EQ(D0, Redecls[0]);
274 EXPECT_EQ(D1, Redecls[1]);
275 EXPECT_EQ(D2, Redecls[2]);
276}
277
278TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
279 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
280 auto Pattern = functionDecl(hasName("f"));
281 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
282 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
283 FunctionDecl *D1 = D2->getPreviousDecl();
284
285 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
286 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
287 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
288
289 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
290 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
291}
292
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000293namespace {
294struct RedirectingImporter : public ASTImporter {
295 using ASTImporter::ASTImporter;
296
297protected:
298 llvm::Expected<Decl *> ImportImpl(Decl *FromD) override {
299 auto *ND = dyn_cast<NamedDecl>(FromD);
300 if (!ND || ND->getName() != "shouldNotBeImported")
301 return ASTImporter::ImportImpl(FromD);
302 for (Decl *D : getToContext().getTranslationUnitDecl()->decls()) {
303 if (auto *ND = dyn_cast<NamedDecl>(D))
304 if (ND->getName() == "realDecl") {
305 RegisterImportedDecl(FromD, ND);
306 return ND;
307 }
308 }
309 return ASTImporter::ImportImpl(FromD);
310 }
311};
312
313} // namespace
314
315struct RedirectingImporterTest : ASTImporterOptionSpecificTestBase {
316 RedirectingImporterTest() {
317 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
318 ASTContext &FromContext, FileManager &FromFileManager,
Gabor Marton2afbfb62019-07-01 15:37:07 +0000319 bool MinimalImport,
320 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000321 return new RedirectingImporter(ToContext, ToFileManager, FromContext,
322 FromFileManager, MinimalImport,
Gabor Marton2afbfb62019-07-01 15:37:07 +0000323 SharedState);
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000324 };
325 }
326};
327
328// Test that an ASTImporter subclass can intercept an import call.
329TEST_P(RedirectingImporterTest, InterceptImport) {
330 Decl *From, *To;
331 std::tie(From, To) =
332 getImportedDecl("class shouldNotBeImported {};", Lang_CXX,
333 "class realDecl {};", Lang_CXX, "shouldNotBeImported");
334 auto *Imported = cast<CXXRecordDecl>(To);
335 EXPECT_EQ(Imported->getQualifiedNameAsString(), "realDecl");
336
337 // Make sure our importer prevented the importing of the decl.
338 auto *ToTU = Imported->getTranslationUnitDecl();
339 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
340 unsigned count =
341 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
342 EXPECT_EQ(0U, count);
343}
344
345// Test that when we indirectly import a declaration the custom ASTImporter
346// is still intercepting the import.
347TEST_P(RedirectingImporterTest, InterceptIndirectImport) {
348 Decl *From, *To;
349 std::tie(From, To) =
350 getImportedDecl("class shouldNotBeImported {};"
351 "class F { shouldNotBeImported f; };",
352 Lang_CXX, "class realDecl {};", Lang_CXX, "F");
353
354 // Make sure our ASTImporter prevented the importing of the decl.
355 auto *ToTU = To->getTranslationUnitDecl();
356 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
357 unsigned count =
358 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
359 EXPECT_EQ(0U, count);
360}
361
Gabor Marton1ad4b992019-07-01 14:19:53 +0000362struct ImportPath : ASTImporterOptionSpecificTestBase {
363 Decl *FromTU;
364 FunctionDecl *D0, *D1, *D2;
365 ImportPath() {
366 FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
367 auto Pattern = functionDecl(hasName("f"));
368 D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
369 D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
370 D1 = D2->getPreviousDecl();
371 }
372};
373
374TEST_P(ImportPath, Push) {
375 ASTImporter::ImportPathTy path;
376 path.push(D0);
377 EXPECT_FALSE(path.hasCycleAtBack());
378}
379
380TEST_P(ImportPath, SmallCycle) {
381 ASTImporter::ImportPathTy path;
382 path.push(D0);
383 path.push(D0);
384 EXPECT_TRUE(path.hasCycleAtBack());
385 path.pop();
386 EXPECT_FALSE(path.hasCycleAtBack());
387 path.push(D0);
388 EXPECT_TRUE(path.hasCycleAtBack());
389}
390
391TEST_P(ImportPath, GetSmallCycle) {
392 ASTImporter::ImportPathTy path;
393 path.push(D0);
394 path.push(D0);
395 EXPECT_TRUE(path.hasCycleAtBack());
396 std::array<Decl* ,2> Res;
397 int i = 0;
398 for (Decl *Di : path.getCycleAtBack()) {
399 Res[i++] = Di;
400 }
401 ASSERT_EQ(i, 2);
402 EXPECT_EQ(Res[0], D0);
403 EXPECT_EQ(Res[1], D0);
404}
405
406TEST_P(ImportPath, GetCycle) {
407 ASTImporter::ImportPathTy path;
408 path.push(D0);
409 path.push(D1);
410 path.push(D2);
411 path.push(D0);
412 EXPECT_TRUE(path.hasCycleAtBack());
413 std::array<Decl* ,4> Res;
414 int i = 0;
415 for (Decl *Di : path.getCycleAtBack()) {
416 Res[i++] = Di;
417 }
418 ASSERT_EQ(i, 4);
419 EXPECT_EQ(Res[0], D0);
420 EXPECT_EQ(Res[1], D2);
421 EXPECT_EQ(Res[2], D1);
422 EXPECT_EQ(Res[3], D0);
423}
424
425TEST_P(ImportPath, CycleAfterCycle) {
426 ASTImporter::ImportPathTy path;
427 path.push(D0);
428 path.push(D1);
429 path.push(D0);
430 path.push(D1);
431 path.push(D2);
432 path.push(D0);
433 EXPECT_TRUE(path.hasCycleAtBack());
434 std::array<Decl* ,4> Res;
435 int i = 0;
436 for (Decl *Di : path.getCycleAtBack()) {
437 Res[i++] = Di;
438 }
439 ASSERT_EQ(i, 4);
440 EXPECT_EQ(Res[0], D0);
441 EXPECT_EQ(Res[1], D2);
442 EXPECT_EQ(Res[2], D1);
443 EXPECT_EQ(Res[3], D0);
444
445 path.pop();
446 path.pop();
447 path.pop();
448 EXPECT_TRUE(path.hasCycleAtBack());
449 i = 0;
450 for (Decl *Di : path.getCycleAtBack()) {
451 Res[i++] = Di;
452 }
453 ASSERT_EQ(i, 3);
454 EXPECT_EQ(Res[0], D0);
455 EXPECT_EQ(Res[1], D1);
456 EXPECT_EQ(Res[2], D0);
457
458 path.pop();
459 EXPECT_FALSE(path.hasCycleAtBack());
460}
461
Gabor Marton19f4f392018-06-25 13:04:37 +0000462TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000463 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000464 testImport(
465 "void declToImport() { (void)\"foo\"; }",
466 Lang_CXX, "", Lang_CXX, Verifier,
467 functionDecl(hasDescendant(
468 stringLiteral(hasType(asString("const char [4]"))))));
469 testImport(
470 "void declToImport() { (void)L\"foo\"; }",
471 Lang_CXX, "", Lang_CXX, Verifier,
472 functionDecl(hasDescendant(
473 stringLiteral(hasType(asString("const wchar_t [4]"))))));
474 testImport(
475 "void declToImport() { (void) \"foo\" \"bar\"; }",
476 Lang_CXX, "", Lang_CXX, Verifier,
477 functionDecl(hasDescendant(
478 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000479}
480
Tom Roeder521f0042019-02-26 19:26:41 +0000481TEST_P(ImportExpr, ImportChooseExpr) {
482 MatchVerifier<Decl> Verifier;
483
484 // This case tests C code that is not condition-dependent and has a true
485 // condition.
486 testImport(
487 "void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }",
488 Lang_C, "", Lang_C, Verifier,
489 functionDecl(hasDescendant(chooseExpr())));
490}
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 Martonbf7f18b2018-08-09 12:18:07 +0000523TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
524 MatchVerifier<Decl> Verifier;
525 testImport(
526 "void declToImport() { (void)1.0i; }",
527 Lang_CXX14, "", Lang_CXX14, Verifier,
528 functionDecl(hasDescendant(imaginaryLiteral())));
529}
530
Gabor Marton19f4f392018-06-25 13:04:37 +0000531TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000532 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000533 testImport(
534 "void declToImport() {"
535 " struct s { int x; long y; unsigned z; }; "
536 " (void)(struct s){ 42, 0L, 1U }; }",
537 Lang_CXX, "", Lang_CXX, Verifier,
538 functionDecl(hasDescendant(
539 compoundLiteralExpr(
540 hasType(asString("struct s")),
541 has(initListExpr(
542 hasType(asString("struct s")),
543 has(integerLiteral(
544 equals(42), hasType(asString("int")))),
545 has(integerLiteral(
546 equals(0), hasType(asString("long")))),
547 has(integerLiteral(
548 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000549}
550
Gabor Marton19f4f392018-06-25 13:04:37 +0000551TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000552 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000553 testImport(
554 "class declToImport { void f() { (void)this; } };",
555 Lang_CXX, "", Lang_CXX, Verifier,
556 cxxRecordDecl(
557 hasMethod(
558 hasDescendant(
559 cxxThisExpr(
560 hasType(
561 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000562}
563
Gabor Marton19f4f392018-06-25 13:04:37 +0000564TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000565 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000566 testImport(
567 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
568 Lang_C, "", Lang_C, Verifier,
569 functionDecl(hasDescendant(
570 atomicExpr(
571 has(ignoringParenImpCasts(
572 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
573 hasType(asString("int *"))))),
574 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000575}
576
Gabor Marton19f4f392018-06-25 13:04:37 +0000577TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000578 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000579 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000580 "void declToImport() { loop: goto loop; (void)&&loop; }",
581 Lang_C, "", Lang_C, Verifier,
582 functionDecl(
583 hasDescendant(
584 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
585 hasDescendant(
586 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000587}
588
589AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
590 internal::Matcher<NamedDecl>, InnerMatcher) {
591 const NamedDecl *Template = Node.getTemplatedDecl();
592 return Template && InnerMatcher.matches(*Template, Finder, Builder);
593}
594
Gabor Marton19f4f392018-06-25 13:04:37 +0000595TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000596 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000597 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000598 "template<typename T> class dummy { void f() { dummy X(*this); } };"
599 "typedef dummy<int> declToImport;"
600 "template class dummy<int>;",
601 Lang_CXX, "", Lang_CXX, Verifier,
602 typedefDecl(hasType(templateSpecializationType(
603 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
604 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
605 hasName("f"),
606 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
607 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
608 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000609 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000610}
611
Gabor Marton19f4f392018-06-25 13:04:37 +0000612TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000613 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000614 testImport(
615 "void declToImport() { int b; switch (b) { case 1: break; } }",
616 Lang_C, "", Lang_C, Verifier,
617 functionDecl(hasDescendant(
618 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000619}
620
Gabor Marton19f4f392018-06-25 13:04:37 +0000621TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000622 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000623 testImport(
624 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
625 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000626 functionDecl(hasDescendant(
627 varDecl(
628 hasName("C"),
629 hasType(asString("int")),
630 hasInitializer(
631 stmtExpr(
632 hasAnySubstatement(declStmt(hasSingleDecl(
633 varDecl(
634 hasName("X"),
635 hasType(asString("int")),
636 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000637 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000638 hasDescendant(
639 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000640}
641
Gabor Marton19f4f392018-06-25 13:04:37 +0000642TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000643 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000644 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000645 "void declToImport() { (void)(true ? 1 : -5); }",
646 Lang_CXX, "", Lang_CXX, Verifier,
647 functionDecl(hasDescendant(
648 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000649 hasCondition(cxxBoolLiteral(equals(true))),
650 hasTrueExpression(integerLiteral(equals(1))),
651 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000652 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
653 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000654}
655
Gabor Marton19f4f392018-06-25 13:04:37 +0000656TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000657 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000658 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000659 "void declToImport() { (void)(1 ?: -5); }",
660 Lang_CXX, "", Lang_CXX, Verifier,
661 functionDecl(hasDescendant(
662 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000663 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000664 implicitCastExpr(
665 hasSourceExpression(opaqueValueExpr(
666 hasSourceExpression(integerLiteral(equals(1))))),
667 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000668 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000669 opaqueValueExpr(
670 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000671 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000672 unaryOperator(
673 hasOperatorName("-"),
674 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000675}
676
Gabor Marton19f4f392018-06-25 13:04:37 +0000677TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000678 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000679 testImport(
680 "void declToImport() {"
681 " struct point { double x; double y; };"
682 " struct point ptarray[10] = "
683 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
684 Lang_C, "", Lang_C, Verifier,
685 functionDecl(hasDescendant(
686 initListExpr(
687 has(designatedInitExpr(
688 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000689 hasDescendant(floatLiteral(equals(1.0))),
690 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000691 has(designatedInitExpr(
692 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000693 hasDescendant(floatLiteral(equals(2.0))),
694 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000695 has(designatedInitExpr(
696 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000697 hasDescendant(floatLiteral(equals(1.0))),
698 hasDescendant(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000699}
700
Gabor Marton19f4f392018-06-25 13:04:37 +0000701TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000702 MatchVerifier<Decl> Verifier;
703 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000704 testImport(
705 "void declToImport() { (void)__func__; }",
706 Lang_CXX, "", Lang_CXX, Verifier,
707 functionDecl(hasDescendant(
708 predefinedExpr(
709 hasType(
710 asString("const char [13]")),
711 has(stringLiteral(hasType(
712 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000713}
714
Gabor Marton19f4f392018-06-25 13:04:37 +0000715TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000716 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000717 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000718 "void declToImport() {"
719 " struct point { double x; double y; };"
720 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
721 " [0].x = 1.0 }; }",
722 Lang_CXX, "", Lang_CXX, Verifier,
723 functionDecl(hasDescendant(
724 initListExpr(
725 has(
726 cxxConstructExpr(
727 requiresZeroInitialization())),
728 has(
729 initListExpr(
730 hasType(asString("struct point")),
731 has(floatLiteral(equals(1.0))),
732 has(implicitValueInitExpr(
733 hasType(asString("double")))))),
734 has(
735 initListExpr(
736 hasType(asString("struct point")),
737 has(floatLiteral(equals(2.0))),
738 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000739}
740
741
Aleksei Sidorina693b372016-09-28 10:16:56 +0000742const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
743
Gabor Marton19f4f392018-06-25 13:04:37 +0000744TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000745 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000746 testImport(
747 "void declToImport(__builtin_va_list list, ...) {"
748 " (void)__builtin_va_arg(list, int); }",
749 Lang_CXX, "", Lang_CXX, Verifier,
750 functionDecl(hasDescendant(
751 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000752}
753
Gabor Marton19f4f392018-06-25 13:04:37 +0000754TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000755 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000756 testImport(
757 "struct C {};"
758 "void declToImport() { C c = C(); }",
759 Lang_CXX, "", Lang_CXX, Verifier,
760 functionDecl(hasDescendant(
761 exprWithCleanups(has(cxxConstructExpr(
762 has(materializeTemporaryExpr(has(implicitCastExpr(
763 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000764}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000765
Gabor Marton19f4f392018-06-25 13:04:37 +0000766TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000767 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000768 testImport(
769 "void declToImport() { typedef _Atomic(int) a_int; }",
770 Lang_CXX11, "", Lang_CXX11, Verifier,
771 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000772}
773
Gabor Marton19f4f392018-06-25 13:04:37 +0000774TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000775 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000776 testImport(
777 "template <typename T> void declToImport() { };",
778 Lang_CXX, "", Lang_CXX, Verifier,
779 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000780}
781
Gabor Marton19f4f392018-06-25 13:04:37 +0000782TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000783 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000784 testImport(
785 "template <typename T> struct C { T t; };"
786 "template <typename T> void declToImport() {"
787 " C<T> d;"
788 " (void)d.t;"
789 "}"
790 "void instantiate() { declToImport<int>(); }",
791 Lang_CXX, "", Lang_CXX, Verifier,
792 functionTemplateDecl(hasDescendant(
793 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
794 testImport(
795 "template <typename T> struct C { T t; };"
796 "template <typename T> void declToImport() {"
797 " C<T> d;"
798 " (void)(&d)->t;"
799 "}"
800 "void instantiate() { declToImport<int>(); }",
801 Lang_CXX, "", Lang_CXX, Verifier,
802 functionTemplateDecl(hasDescendant(
803 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000804}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000805
Gabor Marton19f4f392018-06-25 13:04:37 +0000806TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000807 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000808 testImport(
809 "template <int K>"
810 "struct dummy { static const int i = K; };"
811 "template <int K> using dummy2 = dummy<K>;"
812 "int declToImport() { return dummy2<3>::i; }",
813 Lang_CXX11, "", Lang_CXX11, Verifier,
814 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000815 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000816 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
817}
818
819const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
820 varTemplateSpecializationDecl;
821
Gabor Marton19f4f392018-06-25 13:04:37 +0000822TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000823 MatchVerifier<Decl> Verifier;
824 testImport(
825 "template <typename T>"
826 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000827 "void declToImport() { (void)pi<int>; }",
828 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000829 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000830 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000831 unless(hasAncestor(translationUnitDecl(has(varDecl(
832 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000833}
834
Gabor Marton19f4f392018-06-25 13:04:37 +0000835TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000836 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000837 testImport(
838 "template <typename... Args>"
839 "struct dummy {"
840 " dummy(Args... args) {}"
841 " static const int i = 4;"
842 "};"
843 "int declToImport() { return dummy<int>::i; }",
844 Lang_CXX11, "", Lang_CXX11, Verifier,
845 functionDecl(hasDescendant(
846 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000847}
848
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000849const internal::VariadicDynCastAllOfMatcher<Type,
850 DependentTemplateSpecializationType>
851 dependentTemplateSpecializationType;
852
Gabor Marton19f4f392018-06-25 13:04:37 +0000853TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000854 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000855 testImport(
856 "template<typename T>"
857 "struct A;"
858 "template<typename T>"
859 "struct declToImport {"
860 " typename A<T>::template B<T> a;"
861 "};",
862 Lang_CXX, "", Lang_CXX, Verifier,
863 classTemplateDecl(has(cxxRecordDecl(has(
864 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000865}
866
867const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
868 sizeOfPackExpr;
869
Gabor Marton19f4f392018-06-25 13:04:37 +0000870TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000871 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000872 testImport(
873 "template <typename... Ts>"
874 "void declToImport() {"
875 " const int i = sizeof...(Ts);"
876 "};"
877 "void g() { declToImport<int>(); }",
878 Lang_CXX11, "", Lang_CXX11, Verifier,
879 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000880 testImport(
881 "template <typename... Ts>"
882 "using X = int[sizeof...(Ts)];"
883 "template <typename... Us>"
884 "struct Y {"
885 " X<Us..., int, double, int, Us...> f;"
886 "};"
887 "Y<float, int> declToImport;",
888 Lang_CXX11, "", Lang_CXX11, Verifier,
889 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
890 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
891}
892
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000893/// \brief Matches __builtin_types_compatible_p:
894/// GNU extension to check equivalent types
895/// Given
896/// \code
897/// __builtin_types_compatible_p(int, int)
898/// \endcode
899// will generate TypeTraitExpr <...> 'int'
900const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
901
Gabor Marton19f4f392018-06-25 13:04:37 +0000902TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000903 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000904 testImport(
905 "void declToImport() { "
906 " (void)__builtin_types_compatible_p(int, int);"
907 "}",
908 Lang_C, "", Lang_C, Verifier,
909 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000910}
911
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000912const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
913
Gabor Marton19f4f392018-06-25 13:04:37 +0000914TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000915 MatchVerifier<Decl> Verifier;
916 testImport(
917 "namespace std { class type_info {}; }"
918 "void declToImport() {"
919 " int x;"
920 " auto a = typeid(int); auto b = typeid(x);"
921 "}",
922 Lang_CXX11, "", Lang_CXX11, Verifier,
923 functionDecl(
924 hasDescendant(varDecl(
925 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
926 hasDescendant(varDecl(
927 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
928}
929
Gabor Marton19f4f392018-06-25 13:04:37 +0000930TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000931 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000932 testImport(
933 "template<typename T> struct declToImport {"
934 " void m() { (void)__is_pod(T); }"
935 "};"
936 "void f() { declToImport<int>().m(); }",
937 Lang_CXX11, "", Lang_CXX11, Verifier,
938 classTemplateDecl(has(cxxRecordDecl(has(
939 functionDecl(hasDescendant(
940 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000941}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000942
Gabor Marton6e1510c2018-07-12 11:50:21 +0000943TEST_P(ImportDecl, ImportRecordDeclInFunc) {
944 MatchVerifier<Decl> Verifier;
945 testImport("int declToImport() { "
946 " struct data_t {int a;int b;};"
947 " struct data_t d;"
948 " return 0;"
949 "}",
950 Lang_C, "", Lang_C, Verifier,
951 functionDecl(hasBody(compoundStmt(
952 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
953}
954
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000955TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000956 Decl *FromTU = getTuDecl("int declToImport() { "
957 " struct data_t {int a;int b;};"
958 " struct data_t d;"
959 " return 0;"
960 "}",
961 Lang_C, "input.c");
Gabor Martonfe68e292018-08-06 14:38:37 +0000962 auto *FromVar =
Gabor Marton6e1510c2018-07-12 11:50:21 +0000963 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
964 ASSERT_TRUE(FromVar);
965 auto ToType =
966 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
967 EXPECT_FALSE(ToType.isNull());
968}
969
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000970TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000971 // This construct is not supported by ASTImporter.
Gabor Martonfe68e292018-08-06 14:38:37 +0000972 Decl *FromTU = getTuDecl(
973 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
974 Lang_C, "input.c");
975 auto *From = FirstDeclMatcher<FunctionDecl>().match(
976 FromTU, functionDecl(hasName("declToImport")));
Gabor Marton6e1510c2018-07-12 11:50:21 +0000977 ASSERT_TRUE(From);
Gabor Martonfe68e292018-08-06 14:38:37 +0000978 auto *To = Import(From, Lang_C);
979 EXPECT_EQ(To, nullptr);
980}
981
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000982TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +0000983 Decl *FromTU = getTuDecl(
984 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
985 "int declToImport(){ return NONAME_SIZEOF(int); }",
986 Lang_C, "input.c");
987 auto *From = FirstDeclMatcher<FunctionDecl>().match(
988 FromTU, functionDecl(hasName("declToImport")));
989 ASSERT_TRUE(From);
990 auto *To = Import(From, Lang_C);
991 ASSERT_TRUE(To);
992 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
993 To, functionDecl(hasName("declToImport"),
994 hasDescendant(unaryExprOrTypeTraitExpr()))));
995}
996
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000997TEST_P(ASTImporterOptionSpecificTestBase,
998 ImportRecordDeclInFuncParamsFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +0000999 // This construct is not supported by ASTImporter.
1000 Decl *FromTU = getTuDecl(
1001 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
1002 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
1003 Lang_C, "input.c");
1004 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1005 FromTU, functionDecl(hasName("declToImport")));
1006 ASSERT_TRUE(From);
1007 auto *To = Import(From, Lang_C);
Gabor Marton6e1510c2018-07-12 11:50:21 +00001008 EXPECT_EQ(To, nullptr);
1009}
1010
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001011const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1012 cxxPseudoDestructorExpr;
1013
Gabor Marton19f4f392018-06-25 13:04:37 +00001014TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001015 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001016 testImport(
1017 "typedef int T;"
1018 "void declToImport(int *p) {"
1019 " T t;"
1020 " p->T::~T();"
1021 "}",
1022 Lang_CXX, "", Lang_CXX, Verifier,
1023 functionDecl(hasDescendant(
1024 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001025}
1026
Gabor Marton19f4f392018-06-25 13:04:37 +00001027TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001028 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001029 testImport(
1030 "namespace foo { int bar; }"
1031 "void declToImport() { using foo::bar; }",
1032 Lang_CXX, "", Lang_CXX, Verifier,
1033 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001034}
1035
1036/// \brief Matches shadow declarations introduced into a scope by a
1037/// (resolved) using declaration.
1038///
1039/// Given
1040/// \code
1041/// namespace n { int f; }
1042/// namespace declToImport { using n::f; }
1043/// \endcode
1044/// usingShadowDecl()
1045/// matches \code f \endcode
1046const internal::VariadicDynCastAllOfMatcher<Decl,
1047 UsingShadowDecl> usingShadowDecl;
1048
Gabor Marton19f4f392018-06-25 13:04:37 +00001049TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001050 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001051 testImport(
1052 "namespace foo { int bar; }"
1053 "namespace declToImport { using foo::bar; }",
1054 Lang_CXX, "", Lang_CXX, Verifier,
1055 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001056}
1057
Gabor Marton19f4f392018-06-25 13:04:37 +00001058TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001059 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001060 testImport(
1061 "template<typename T> int foo();"
1062 "template <typename T> void declToImport() {"
1063 " (void)::foo<T>;"
1064 " (void)::template foo<T>;"
1065 "}"
1066 "void instantiate() { declToImport<int>(); }",
1067 Lang_CXX, "", Lang_CXX, Verifier,
1068 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001069}
1070
Gabor Marton19f4f392018-06-25 13:04:37 +00001071TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001072 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001073 testImport(
1074 "template <typename T> struct C { T t; };"
1075 "template <typename T> void declToImport() {"
1076 " C<T> d;"
1077 " d.t = T();"
1078 "}"
1079 "void instantiate() { declToImport<int>(); }",
1080 Lang_CXX, "", Lang_CXX, Verifier,
1081 functionTemplateDecl(hasDescendant(
1082 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1083 testImport(
1084 "template <typename T> struct C { T t; };"
1085 "template <typename T> void declToImport() {"
1086 " C<T> d;"
1087 " (&d)->t = T();"
1088 "}"
1089 "void instantiate() { declToImport<int>(); }",
1090 Lang_CXX, "", Lang_CXX, Verifier,
1091 functionTemplateDecl(hasDescendant(
1092 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001093}
1094
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001095/// Check that function "declToImport()" (which is the templated function
1096/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1097/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001098TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001099 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001100 testImport(
1101 "template <typename T> void declToImport() { T a = 1; }"
1102 "void instantiate() { declToImport<int>(); }",
1103 Lang_CXX, "", Lang_CXX, Verifier,
1104 functionTemplateDecl(hasAncestor(translationUnitDecl(
1105 unless(has(functionDecl(hasName("declToImport"))))))));
1106 testImport(
1107 "template <typename T> struct declToImport { T t; };"
1108 "void instantiate() { declToImport<int>(); }",
1109 Lang_CXX, "", Lang_CXX, Verifier,
1110 classTemplateDecl(hasAncestor(translationUnitDecl(
1111 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001112}
1113
Gabor Marton19f4f392018-06-25 13:04:37 +00001114TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001115 MatchVerifier<Decl> Verifier;
1116 auto Code =
1117 R"s(
1118 struct declToImport {
1119 template <typename T0> struct X;
1120 template <typename T0> struct X<T0 *> {};
1121 };
1122 )s";
1123 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1124 recordDecl(has(classTemplateDecl()),
1125 has(classTemplateSpecializationDecl())));
1126}
1127
Gabor Marton19f4f392018-06-25 13:04:37 +00001128TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001129 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001130 testImport(
1131 "class declToImport {"
1132 " void f() { *this = declToImport(); }"
1133 "};",
1134 Lang_CXX, "", Lang_CXX, Verifier,
1135 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1136 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001137}
1138
Gabor Marton19f4f392018-06-25 13:04:37 +00001139TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001140 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001141 testImport(
1142 "template<typename T, int Size> class declToImport {"
1143 " T data[Size];"
1144 "};",
1145 Lang_CXX, "", Lang_CXX, Verifier,
1146 classTemplateDecl(has(cxxRecordDecl(
1147 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001148}
1149
Balazs Keri5f4fd8b2019-03-14 14:20:23 +00001150TEST_P(ASTImporterOptionSpecificTestBase, ImportBeginLocOfDeclRefExpr) {
1151 Decl *FromTU = getTuDecl(
1152 "class A { public: static int X; }; void f() { (void)A::X; }", Lang_CXX);
1153 auto From = FirstDeclMatcher<FunctionDecl>().match(
1154 FromTU, functionDecl(hasName("f")));
1155 ASSERT_TRUE(From);
1156 ASSERT_TRUE(
1157 cast<CStyleCastExpr>(cast<CompoundStmt>(From->getBody())->body_front())
1158 ->getSubExpr()
1159 ->getBeginLoc()
1160 .isValid());
1161 FunctionDecl *To = Import(From, Lang_CXX);
1162 ASSERT_TRUE(To);
1163 ASSERT_TRUE(
1164 cast<CStyleCastExpr>(cast<CompoundStmt>(To->getBody())->body_front())
1165 ->getSubExpr()
1166 ->getBeginLoc()
1167 .isValid());
1168}
1169
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001170TEST_P(ASTImporterOptionSpecificTestBase,
1171 ImportOfTemplatedDeclOfClassTemplateDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001172 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1173 auto From =
1174 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1175 ASSERT_TRUE(From);
1176 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1177 ASSERT_TRUE(To);
1178 Decl *ToTemplated = To->getTemplatedDecl();
1179 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1180 EXPECT_TRUE(ToTemplated1);
1181 EXPECT_EQ(ToTemplated1, ToTemplated);
1182}
1183
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001184TEST_P(ASTImporterOptionSpecificTestBase,
1185 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001186 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1187 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1188 FromTU, functionTemplateDecl());
1189 ASSERT_TRUE(From);
1190 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1191 ASSERT_TRUE(To);
1192 Decl *ToTemplated = To->getTemplatedDecl();
1193 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1194 EXPECT_TRUE(ToTemplated1);
1195 EXPECT_EQ(ToTemplated1, ToTemplated);
1196}
1197
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001198TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton6578a4a2018-06-25 11:38:43 +00001199 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1200 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1201 auto FromFT =
1202 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1203 ASSERT_TRUE(FromFT);
1204
1205 auto ToTemplated =
1206 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1207 EXPECT_TRUE(ToTemplated);
1208 auto ToTU = ToTemplated->getTranslationUnitDecl();
1209 auto ToFT =
1210 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1211 EXPECT_TRUE(ToFT);
1212}
1213
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001214TEST_P(ASTImporterOptionSpecificTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001215 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001216 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1217 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1218 FromTU, functionTemplateDecl());
1219 ASSERT_TRUE(FromFT);
1220
1221 auto ToTemplated =
1222 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1223 EXPECT_TRUE(ToTemplated);
1224 auto ToTU = ToTemplated->getTranslationUnitDecl();
1225 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1226 ToTU, functionTemplateDecl());
1227 EXPECT_TRUE(ToFT);
1228}
1229
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001230TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001231 auto Code =
1232 R"(
1233 namespace x {
1234 template<class X> struct S1{};
1235 template<class X> struct S2{};
1236 template<class X> struct S3{};
1237 }
1238 )";
1239 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1240 auto FromNs =
1241 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1242 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1243 ASSERT_TRUE(ToNs);
1244 auto From =
1245 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1246 classTemplateDecl(
1247 hasName("S2")));
1248 auto To =
1249 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1250 classTemplateDecl(
1251 hasName("S2")));
1252 ASSERT_TRUE(From);
1253 ASSERT_TRUE(To);
1254 auto ToTemplated = To->getTemplatedDecl();
1255 auto ToTemplated1 =
1256 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1257 EXPECT_TRUE(ToTemplated1);
1258 ASSERT_EQ(ToTemplated1, ToTemplated);
1259}
1260
Tom Roeder521f0042019-02-26 19:26:41 +00001261TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {
1262 // This tests the import of isConditionTrue directly to make sure the importer
1263 // gets it right.
1264 Decl *From, *To;
1265 std::tie(From, To) = getImportedDecl(
1266 "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }",
1267 Lang_C, "", Lang_C);
1268
1269 auto ToResults = match(chooseExpr().bind("choose"), To->getASTContext());
1270 auto FromResults = match(chooseExpr().bind("choose"), From->getASTContext());
1271
1272 const ChooseExpr *FromChooseExpr =
1273 selectFirst<ChooseExpr>("choose", FromResults);
1274 ASSERT_TRUE(FromChooseExpr);
1275
1276 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>("choose", ToResults);
1277 ASSERT_TRUE(ToChooseExpr);
1278
1279 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());
1280 EXPECT_EQ(FromChooseExpr->isConditionDependent(),
1281 ToChooseExpr->isConditionDependent());
1282}
1283
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001284TEST_P(ASTImporterOptionSpecificTestBase,
1285 ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001286 Decl *From, *To;
1287 std::tie(From, To) = getImportedDecl(
1288 R"(
1289 template <typename T> struct X {};
1290
1291 void declToImport(int y, X<int> &x) {}
1292
1293 template <> struct X<int> {
1294 void g() {
1295 X<int> x;
1296 declToImport(0, x);
1297 }
1298 };
1299 )",
1300 Lang_CXX, "", Lang_CXX);
1301
1302 MatchVerifier<Decl> Verifier;
1303 auto Matcher = functionDecl(hasName("declToImport"),
1304 parameterCountIs(2),
1305 hasParameter(0, hasName("y")),
1306 hasParameter(1, hasName("x")),
1307 hasParameter(1, hasType(asString("X<int> &"))));
1308 ASSERT_TRUE(Verifier.match(From, Matcher));
1309 EXPECT_TRUE(Verifier.match(To, Matcher));
1310}
1311
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001312TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001313 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1314 Decl *From, *To;
1315 std::tie(From, To) =
1316 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1317 "void instantiate() { declToImport<int>(); }",
1318 Lang_CXX, "", Lang_CXX);
1319
1320 auto Check = [](Decl *D) -> bool {
1321 auto TU = D->getTranslationUnitDecl();
1322 for (auto Child : TU->decls()) {
1323 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1324 if (FD->getNameAsString() == "declToImport") {
1325 GTEST_NONFATAL_FAILURE_(
1326 "TU should not contain any FunctionDecl with name declToImport");
1327 return false;
1328 }
1329 }
1330 }
1331 return true;
1332 };
1333
1334 ASSERT_TRUE(Check(From));
1335 EXPECT_TRUE(Check(To));
1336}
1337
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001338TEST_P(ASTImporterOptionSpecificTestBase,
1339 TUshouldNotContainTemplatedDeclOfClassTemplates) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001340 Decl *From, *To;
1341 std::tie(From, To) =
1342 getImportedDecl("template <typename T> struct declToImport { T t; };"
1343 "void instantiate() { declToImport<int>(); }",
1344 Lang_CXX, "", Lang_CXX);
1345
1346 auto Check = [](Decl *D) -> bool {
1347 auto TU = D->getTranslationUnitDecl();
1348 for (auto Child : TU->decls()) {
1349 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1350 if (RD->getNameAsString() == "declToImport") {
1351 GTEST_NONFATAL_FAILURE_(
1352 "TU should not contain any CXXRecordDecl with name declToImport");
1353 return false;
1354 }
1355 }
1356 }
1357 return true;
1358 };
1359
1360 ASSERT_TRUE(Check(From));
1361 EXPECT_TRUE(Check(To));
1362}
1363
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001364TEST_P(ASTImporterOptionSpecificTestBase,
1365 TUshouldNotContainTemplatedDeclOfTypeAlias) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001366 Decl *From, *To;
1367 std::tie(From, To) =
1368 getImportedDecl(
1369 "template <typename T> struct X {};"
1370 "template <typename T> using declToImport = X<T>;"
1371 "void instantiate() { declToImport<int> a; }",
1372 Lang_CXX11, "", Lang_CXX11);
1373
1374 auto Check = [](Decl *D) -> bool {
1375 auto TU = D->getTranslationUnitDecl();
1376 for (auto Child : TU->decls()) {
1377 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1378 if (AD->getNameAsString() == "declToImport") {
1379 GTEST_NONFATAL_FAILURE_(
1380 "TU should not contain any TypeAliasDecl with name declToImport");
1381 return false;
1382 }
1383 }
1384 }
1385 return true;
1386 };
1387
1388 ASSERT_TRUE(Check(From));
1389 EXPECT_TRUE(Check(To));
1390}
1391
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001392TEST_P(ASTImporterOptionSpecificTestBase,
1393 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001394
1395 Decl *From, *To;
1396 std::tie(From, To) = getImportedDecl(
1397 R"(
1398 template<class T>
1399 class Base {};
1400 class declToImport : public Base<declToImport> {};
1401 )",
1402 Lang_CXX, "", Lang_CXX);
1403
1404 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1405 auto Pattern =
1406 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1407 ASSERT_TRUE(
1408 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1409 EXPECT_TRUE(
1410 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1411
1412 // Check that the ClassTemplateSpecializationDecl is the child of the
1413 // ClassTemplateDecl.
1414 Pattern = translationUnitDecl(has(classTemplateDecl(
1415 hasName("Base"), has(classTemplateSpecializationDecl()))));
1416 ASSERT_TRUE(
1417 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1418 EXPECT_TRUE(
1419 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1420}
1421
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001422AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1423 size_t Index = 0;
Balazs Keri6e086692019-09-02 07:17:01 +00001424 for (Decl *D : Node.decls()) {
1425 if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D)) {
1426 auto *ND = cast<NamedDecl>(D);
1427 if (Index == Order.size())
1428 return false;
1429 if (ND->getName() != Order[Index])
1430 return false;
1431 ++Index;
1432 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001433 }
1434 return Index == Order.size();
1435}
1436
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001437TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001438 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1439 Decl *From, *To;
1440 std::tie(From, To) = getImportedDecl(
1441 R"(
1442 namespace NS {
1443 template<class T>
1444 class X {};
1445 template class X<int>;
1446 }
1447 )",
1448 Lang_CXX, "", Lang_CXX, "NS");
1449
1450 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1451 // ClassTemplateDecl.
1452 auto Pattern = namespaceDecl(has(classTemplateDecl(
1453 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1454 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1455 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1456
1457 // Check that the ClassTemplateSpecializationDecl is the child of the
1458 // NamespaceDecl.
1459 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1460 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1461 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1462}
1463
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001464TEST_P(ASTImporterOptionSpecificTestBase,
1465 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001466 Decl *From, *To;
1467 std::tie(From, To) =
1468 getImportedDecl(
1469 "struct declToImport { int a; int b; };",
1470 Lang_CXX11, "", Lang_CXX11);
1471
1472 MatchVerifier<Decl> Verifier;
1473 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1474 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1475}
1476
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001477TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton48b16e12019-07-25 09:07:17 +00001478 CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001479 Decl *From, *To;
1480 std::tie(From, To) = getImportedDecl(
1481 // The original recursive algorithm of ASTImporter first imports 'c' then
1482 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1483 R"s(
1484 struct declToImport {
1485 int a = c + b;
1486 int b = 1;
1487 int c = 2;
1488 };
1489 )s",
1490 Lang_CXX11, "", Lang_CXX11);
1491
1492 MatchVerifier<Decl> Verifier;
1493 ASSERT_TRUE(
1494 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1495 EXPECT_TRUE(
1496 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1497}
1498
Balazs Keri6e086692019-09-02 07:17:01 +00001499TEST_P(ASTImporterOptionSpecificTestBase,
1500 CXXRecordDeclFieldAndIndirectFieldOrder) {
1501 Decl *From, *To;
1502 std::tie(From, To) = getImportedDecl(
1503 // First field is "a", then the field for unnamed union, then "b" and "c"
1504 // from it (indirect fields), then "d".
1505 R"s(
1506 struct declToImport {
1507 int a = d;
1508 union {
1509 int b;
1510 int c;
1511 };
1512 int d;
1513 };
1514 )s",
1515 Lang_CXX11, "", Lang_CXX11);
1516
1517 MatchVerifier<Decl> Verifier;
1518 ASSERT_TRUE(Verifier.match(
1519 From, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1520 EXPECT_TRUE(Verifier.match(
1521 To, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1522}
1523
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001524TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001525 Decl *From, *To;
1526 std::tie(From, To) = getImportedDecl(
1527 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001528 struct declToImport {
1529 };
1530 )",
1531 Lang_CXX, "", Lang_CXX);
1532
1533 MatchVerifier<Decl> Verifier;
1534 // Match the implicit Decl.
1535 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1536 ASSERT_TRUE(Verifier.match(From, Matcher));
1537 EXPECT_TRUE(Verifier.match(To, Matcher));
1538}
1539
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001540TEST_P(ASTImporterOptionSpecificTestBase,
1541 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
Gabor Martona3af5672018-05-23 14:24:02 +00001542 Decl *From, *To;
1543 std::tie(From, To) = getImportedDecl(
1544 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001545 template <typename U>
1546 struct declToImport {
1547 };
1548 )",
1549 Lang_CXX, "", Lang_CXX);
1550
1551 MatchVerifier<Decl> Verifier;
1552 // Match the implicit Decl.
1553 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1554 ASSERT_TRUE(Verifier.match(From, Matcher));
1555 EXPECT_TRUE(Verifier.match(To, Matcher));
1556}
1557
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001558TEST_P(ASTImporterOptionSpecificTestBase,
1559 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001560 Decl *From, *To;
1561 std::tie(From, To) = getImportedDecl(
1562 R"(
1563 template<class T>
1564 class Base {};
1565 class declToImport : public Base<declToImport> {};
1566 )",
1567 Lang_CXX, "", Lang_CXX);
1568
1569 auto hasImplicitClass = has(cxxRecordDecl());
1570 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1571 hasName("Base"),
1572 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1573 ASSERT_TRUE(
1574 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1575 EXPECT_TRUE(
1576 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1577}
1578
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001579TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001580 Decl *From, *To;
1581 std::tie(From, To) =
1582 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1583
1584 MatchVerifier<Decl> Verifier;
1585 auto Matcher = functionDecl();
1586 ASSERT_TRUE(Verifier.match(From, Matcher));
1587 EXPECT_TRUE(Verifier.match(To, Matcher));
1588 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1589}
1590
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001591TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001592 Decl *FromTU = getTuDecl(
1593 R"(
1594 struct X {};
1595 void operator<<(int, X);
1596 )",
1597 Lang_CXX);
1598 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1599 const Decl *To = Import(From, Lang_CXX);
1600 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1601}
1602
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001603TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001604 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1605 Decl *From, *To;
1606 std::tie(From, To) = getImportedDecl(
1607 R"(
1608 template<class T>
1609 class Base { int a; };
1610 class declToImport : Base<declToImport> {};
1611 )",
1612 Lang_CXX, "", Lang_CXX);
1613
1614 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1615 hasName("Base"),
1616 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1617 ASSERT_TRUE(
1618 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1619 EXPECT_TRUE(
1620 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1621}
1622
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001623TEST_P(ASTImporterOptionSpecificTestBase,
1624 ImportDefinitionOfClassTemplateAfterFwdDecl) {
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001625 {
1626 Decl *FromTU = getTuDecl(
1627 R"(
1628 template <typename T>
1629 struct B;
1630 )",
1631 Lang_CXX, "input0.cc");
1632 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1633 FromTU, classTemplateDecl(hasName("B")));
1634
1635 Import(FromD, Lang_CXX);
1636 }
1637
1638 {
1639 Decl *FromTU = getTuDecl(
1640 R"(
1641 template <typename T>
1642 struct B {
1643 void f();
1644 };
1645 )",
1646 Lang_CXX, "input1.cc");
1647 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1648 FromTU, functionDecl(hasName("f")));
1649 Import(FromD, Lang_CXX);
1650 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1651 FromTU, classTemplateDecl(hasName("B")));
1652 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1653 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1654 }
1655}
1656
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001657TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001658 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1659 Decl *ToTU = getToTuDecl(
1660 R"(
1661 template <typename T>
1662 struct B {
1663 void f();
1664 };
1665
1666 template <typename T>
1667 struct B;
1668 )",
1669 Lang_CXX);
1670 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1671 [](const ClassTemplateDecl *T) {
1672 return T->isThisDeclarationADefinition();
1673 })
1674 .match(ToTU, classTemplateDecl()));
1675
1676 Decl *FromTU = getTuDecl(
1677 R"(
1678 template <typename T>
1679 struct B {
1680 void f();
1681 };
1682 )",
1683 Lang_CXX, "input1.cc");
1684 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1685 FromTU, classTemplateDecl(hasName("B")));
1686
1687 Import(FromD, Lang_CXX);
1688
1689 // We should have only one definition.
1690 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1691 [](const ClassTemplateDecl *T) {
1692 return T->isThisDeclarationADefinition();
1693 })
1694 .match(ToTU, classTemplateDecl()));
1695}
1696
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001697TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001698 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1699 Decl *ToTU = getToTuDecl(
1700 R"(
1701 struct B {
1702 void f();
1703 };
1704
1705 struct B;
1706 )",
1707 Lang_CXX);
1708 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001709 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001710
1711 Decl *FromTU = getTuDecl(
1712 R"(
1713 struct B {
1714 void f();
1715 };
1716 )",
1717 Lang_CXX, "input1.cc");
1718 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1719 FromTU, cxxRecordDecl(hasName("B")));
1720
1721 Import(FromD, Lang_CXX);
1722
1723 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001724 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001725}
1726
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001727static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1728 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1729 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1730 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1731 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1732}
1733static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1734 SourceManager &SM1, SourceManager &SM2) {
1735 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1736 FullSourceLoc{ Range2.getBegin(), SM2 });
1737 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1738 FullSourceLoc{ Range2.getEnd(), SM2 });
1739}
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001740TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001741 Decl *FromTU = getTuDecl(
1742 R"(
1743 #define MFOO(arg) arg = arg + 1
1744
1745 void foo() {
1746 int a = 5;
1747 MFOO(a);
1748 }
1749 )",
1750 Lang_CXX);
1751 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1752 auto ToD = Import(FromD, Lang_CXX);
1753
1754 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1755 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1756 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1757 auto FromRHS =
1758 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1759
1760 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1761 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1762 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1763 FromSM);
1764 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1765 FromSM);
1766 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1767 FromSM);
1768}
1769
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001770TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001771 Decl *FromTU = getTuDecl(
1772 R"(
1773 #define FUNC_INT void declToImport
1774 #define FUNC FUNC_INT
1775 FUNC(int a);
1776 )",
1777 Lang_CXX);
1778 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1779 auto ToD = Import(FromD, Lang_CXX);
1780
1781 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1782 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1783 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1784 FromSM);
1785}
1786
Gabor Marton9581c332018-05-23 13:53:36 +00001787TEST_P(
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001788 ASTImporterOptionSpecificTestBase,
1789 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
Gabor Marton9581c332018-05-23 13:53:36 +00001790 Decl *ToTU = getToTuDecl(
1791 R"(
1792 template <typename T>
1793 struct B;
1794
1795 template <>
1796 struct B<int> {};
1797
1798 template <>
1799 struct B<int>;
1800 )",
1801 Lang_CXX);
1802 // We should have only one definition.
1803 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1804 [](const ClassTemplateSpecializationDecl *T) {
1805 return T->isThisDeclarationADefinition();
1806 })
1807 .match(ToTU, classTemplateSpecializationDecl()));
1808
1809 Decl *FromTU = getTuDecl(
1810 R"(
1811 template <typename T>
1812 struct B;
1813
1814 template <>
1815 struct B<int> {};
1816 )",
1817 Lang_CXX, "input1.cc");
1818 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1819 FromTU, classTemplateSpecializationDecl(hasName("B")));
1820
1821 Import(FromD, Lang_CXX);
1822
1823 // We should have only one definition.
1824 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1825 [](const ClassTemplateSpecializationDecl *T) {
1826 return T->isThisDeclarationADefinition();
1827 })
1828 .match(ToTU, classTemplateSpecializationDecl()));
1829}
1830
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001831TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
Gabor Marton0bebf952018-07-05 09:51:13 +00001832 Decl *FromTU = getTuDecl(
1833 R"(
1834 struct { int a; int b; } object0 = { 2, 3 };
1835 struct { int x; int y; int z; } object1;
1836 )",
1837 Lang_CXX, "input0.cc");
1838
Gabor Marton0bebf952018-07-05 09:51:13 +00001839 auto *Obj0 =
1840 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1841 auto *From0 = getRecordDecl(Obj0);
1842 auto *Obj1 =
1843 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1844 auto *From1 = getRecordDecl(Obj1);
1845
1846 auto *To0 = Import(From0, Lang_CXX);
1847 auto *To1 = Import(From1, Lang_CXX);
1848
1849 EXPECT_TRUE(To0);
1850 EXPECT_TRUE(To1);
1851 EXPECT_NE(To0, To1);
1852 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1853}
1854
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001855TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001856 auto *Code =
1857 R"(
1858 struct X {
1859 struct { int a; };
1860 struct { int b; };
1861 };
1862 )";
1863 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
1864
1865 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
1866
1867 auto *X0 =
1868 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1869 auto *X1 =
1870 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1871 Import(X0, Lang_C);
1872 Import(X1, Lang_C);
1873
1874 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1875 // We expect no (ODR) warning during the import.
1876 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1877 EXPECT_EQ(1u,
1878 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1879}
1880
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001881TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001882 Decl *FromTU0 = getTuDecl(
1883 R"(
1884 struct X {
1885 struct { int a; };
1886 struct { int b; };
1887 };
1888 )",
1889 Lang_C, "input0.c");
1890
1891 Decl *FromTU1 = getTuDecl(
1892 R"(
1893 struct X { // reversed order
1894 struct { int b; };
1895 struct { int a; };
1896 };
1897 )",
1898 Lang_C, "input1.c");
1899
1900 auto *X0 =
1901 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1902 auto *X1 =
1903 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1904 Import(X0, Lang_C);
1905 Import(X1, Lang_C);
1906
1907 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1908 // We expect one (ODR) warning during the import.
1909 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
Gabor Martonf035b752019-08-27 11:36:10 +00001910 EXPECT_EQ(1u,
Gabor Marton7df342a2018-12-17 12:42:12 +00001911 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1912}
1913
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001914TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001915 auto Pattern = varDecl(hasName("x"));
1916 VarDecl *Imported1;
1917 {
1918 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1919 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1920 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1921 }
1922 VarDecl *Imported2;
1923 {
1924 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1925 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1926 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1927 }
1928 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1929 EXPECT_FALSE(Imported2->isUsed(false));
1930 {
1931 Decl *FromTU =
1932 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
Gabor Martonac3a5d62018-09-17 12:04:52 +00001933 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1934 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00001935 Import(FromD, Lang_CXX);
1936 }
1937 EXPECT_TRUE(Imported2->isUsed(false));
1938}
1939
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001940TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001941 auto Pattern = varDecl(hasName("x"));
1942 VarDecl *ExistingD;
1943 {
1944 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
1945 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1946 }
1947 EXPECT_FALSE(ExistingD->isUsed(false));
1948 {
1949 Decl *FromTU = getTuDecl(
1950 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
1951 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1952 FromTU, functionDecl(hasName("f")));
1953 Import(FromD, Lang_CXX);
1954 }
1955 EXPECT_TRUE(ExistingD->isUsed(false));
1956}
1957
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001958TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001959 auto Pattern = varDecl(hasName("a"));
1960 VarDecl *ExistingD;
1961 {
1962 Decl *ToTU = getToTuDecl(
1963 R"(
1964 struct A {
1965 static const int a = 1;
1966 };
1967 )", Lang_CXX);
1968 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1969 }
1970 EXPECT_FALSE(ExistingD->isUsed(false));
1971 {
1972 Decl *FromTU = getTuDecl(
1973 R"(
1974 struct A {
1975 static const int a = 1;
1976 };
1977 const int *f() { return &A::a; } // requires storage,
1978 // thus used flag will be set
1979 )", Lang_CXX, "input1.cc");
1980 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
1981 FromTU, functionDecl(hasName("f")));
1982 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1983 ASSERT_TRUE(FromD->isUsed(false));
1984 Import(FromFunD, Lang_CXX);
1985 }
1986 EXPECT_TRUE(ExistingD->isUsed(false));
1987}
1988
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001989TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001990 auto Pattern = varDecl(hasName("x"));
1991
1992 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
1993 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1994
1995 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1996
1997 ASSERT_FALSE(Imported1->isUsed(false));
1998
1999 FromD->setIsUsed();
2000 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
2001
2002 EXPECT_EQ(Imported1, Imported2);
2003 EXPECT_TRUE(Imported2->isUsed(false));
2004}
2005
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002006struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
Peter Szecsidedda6f2018-03-30 22:03:29 +00002007
Gabor Marton5254e642018-06-27 13:32:50 +00002008TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002009 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2010 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002011 auto *From =
2012 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00002013
Gabor Marton5254e642018-06-27 13:32:50 +00002014 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002015 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2016
Gabor Marton5254e642018-06-27 13:32:50 +00002017 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2018 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2019 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2020 EXPECT_TRUE(ImportedD == To0);
2021 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2022 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2023 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002024}
2025
2026TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
2027 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2028 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002029 auto *From =
2030 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00002031
Gabor Marton5254e642018-06-27 13:32:50 +00002032 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002033 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2034
Gabor Marton5254e642018-06-27 13:32:50 +00002035 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2036 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2037 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2038 EXPECT_TRUE(ImportedD == To1);
2039 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2040 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2041 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002042}
2043
Peter Szecsidedda6f2018-03-30 22:03:29 +00002044TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2045 auto Code =
2046 R"(
2047 struct B { virtual void f(); };
2048 void B::f() {}
2049 struct D : B { void f(); };
2050 )";
2051 auto Pattern =
2052 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2053 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2054 CXXMethodDecl *Proto =
2055 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2056
2057 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2058 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2059 EXPECT_EQ(To->size_overridden_methods(), 1u);
2060}
2061
2062TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2063 auto Code =
2064 R"(
2065 struct B { virtual void f(); };
2066 void B::f() {}
2067 )";
2068 auto Pattern =
2069 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2070 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2071 CXXMethodDecl *Proto =
2072 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2073 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2074
2075 ASSERT_TRUE(Proto->isVirtual());
2076 ASSERT_TRUE(Def->isVirtual());
2077 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2078 EXPECT_TRUE(To->isVirtual());
2079}
2080
Gabor Marton5254e642018-06-27 13:32:50 +00002081TEST_P(ImportFunctions,
2082 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2083 Decl *ToTU = getToTuDecl(
2084 R"(
2085 void f() {}
2086 void f();
2087 )",
2088 Lang_CXX);
2089 ASSERT_EQ(1u,
2090 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2091 return FD->doesThisDeclarationHaveABody();
2092 }).match(ToTU, functionDecl()));
2093
2094 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2095 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2096
2097 Import(FromD, Lang_CXX);
2098
2099 EXPECT_EQ(1u,
2100 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2101 return FD->doesThisDeclarationHaveABody();
2102 }).match(ToTU, functionDecl()));
2103}
2104
Shafik Yaghmour96b3d202019-01-28 21:55:33 +00002105TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
2106 auto Code =
2107 R"(
2108 struct B { virtual void f(); };
2109 struct D:B { void f(); };
2110 )";
2111 auto BFP =
2112 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2113 auto DFP =
2114 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2115
2116 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2117 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2118 Import(DF, Lang_CXX);
2119
2120 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2121 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2122 Import(BF, Lang_CXX);
2123
2124 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2125
2126 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2127 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2128}
2129
2130TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2131 auto CodeWithoutDef =
2132 R"(
2133 struct B { virtual void f(); };
2134 struct D:B { void f(); };
2135 )";
2136 auto CodeWithDef =
2137 R"(
2138 struct B { virtual void f(){}; };
2139 struct D:B { void f(){}; };
2140 )";
2141 auto BFP =
2142 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2143 auto DFP =
2144 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2145 auto BFDefP = cxxMethodDecl(
2146 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2147 auto DFDefP = cxxMethodDecl(
2148 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2149 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
2150
2151 {
2152 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX, "input0.cc");
2153 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
2154 Import(FromD, Lang_CXX);
2155 }
2156 {
2157 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX, "input1.cc");
2158 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
2159 Import(FromB, Lang_CXX);
2160 }
2161
2162 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2163
2164 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2165 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2166 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2167 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2168 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2169}
2170
2171TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2172 auto Code =
2173 R"(
2174 struct B { virtual void f(); };
2175 struct D:B { void f(); };
2176 void B::f(){};
2177 )";
2178
2179 auto BFP =
2180 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2181 auto BFDefP = cxxMethodDecl(
2182 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2183 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
2184 unless(isDefinition()));
2185
2186 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2187 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2188 Import(D, Lang_CXX);
2189
2190 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2191 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2192 Import(B, Lang_CXX);
2193
2194 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2195
2196 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2197 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2198
2199 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2200 ToTU, cxxRecordDecl(hasName("B")));
2201 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2202 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2203 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2204
2205 // The definition should be out-of-class.
2206 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2207 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2208 ToBFOutOfClass->getLexicalDeclContext());
2209 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2210 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2211
2212 // Check that the redecl chain is intact.
2213 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2214}
2215
2216TEST_P(ImportFunctions,
2217 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2218 auto CodeTU0 =
2219 R"(
2220 struct B { virtual void f(); };
2221 struct D:B { void f(); };
2222 )";
2223 auto CodeTU1 =
2224 R"(
2225 struct B { virtual void f(); };
2226 struct D:B { void f(); };
2227 void B::f(){}
2228 void D::f(){}
2229 void foo(B &b, D &d) { b.f(); d.f(); }
2230 )";
2231
2232 auto BFP =
2233 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2234 auto BFDefP = cxxMethodDecl(
2235 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2236 auto DFP =
2237 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2238 auto DFDefP = cxxMethodDecl(
2239 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2240 auto FooDef = functionDecl(hasName("foo"));
2241
2242 {
2243 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX, "input0.cc");
2244 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2245 Import(D, Lang_CXX);
2246 }
2247
2248 {
2249 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX, "input1.cc");
2250 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2251 Import(Foo, Lang_CXX);
2252 }
2253
2254 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2255
2256 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2257 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2258 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2259 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2260
2261 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2262 ToTU, cxxRecordDecl(hasName("B")));
2263 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2264 ToTU, cxxRecordDecl(hasName("D")));
2265 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2266 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2267 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2268 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2269 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2270 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2271
2272 // The definition should be out-of-class.
2273 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2274 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2275 ToBFOutOfClass->getLexicalDeclContext());
2276 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2277 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2278
2279 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2280 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2281 ToDFOutOfClass->getLexicalDeclContext());
2282 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2283 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2284
2285 // Check that the redecl chain is intact.
2286 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2287 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2288}
2289
Gabor Marton458d1452019-02-14 13:07:03 +00002290TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2291 std::string Code = "static int v; static int v = 0;";
2292 auto Pattern = varDecl(hasName("v"));
2293
2294 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C, "input0.c");
2295
2296 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2297 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2298
2299 auto *To0 = Import(From0, Lang_C);
2300 auto *To1 = Import(From1, Lang_C);
2301
2302 EXPECT_TRUE(To0);
2303 ASSERT_TRUE(To1);
2304 EXPECT_NE(To0, To1);
2305 EXPECT_EQ(To1->getPreviousDecl(), To0);
2306}
2307
2308TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2309 TranslationUnitDecl *FromTu = getTuDecl(
2310 "namespace NS0 { namespace { void f(); } }"
2311 "namespace NS1 { namespace { void f(); } }",
2312 Lang_CXX, "input0.cc");
2313 auto Pattern = functionDecl(hasName("f"));
2314
2315 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2316 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2317
2318 auto *ToF0 = Import(FromF0, Lang_CXX);
2319 auto *ToF1 = Import(FromF1, Lang_CXX);
2320
2321 EXPECT_TRUE(ToF0);
2322 ASSERT_TRUE(ToF1);
2323 EXPECT_NE(ToF0, ToF1);
2324 EXPECT_FALSE(ToF1->getPreviousDecl());
2325}
2326
2327TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2328 {
2329 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",
2330 Lang_CXX, "input0.cc");
2331 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2332 FromTU, functionDecl(hasName("g0")));
2333
2334 Import(FromD, Lang_CXX);
2335 }
2336 {
2337 Decl *FromTU =
2338 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",
2339 Lang_CXX, "input1.cc");
2340 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2341 FromTU, functionDecl(hasName("g1")));
2342 Import(FromD, Lang_CXX);
2343 }
2344
2345 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2346 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2347 2u);
2348}
2349
Gabor Marton302f3002019-02-15 12:04:05 +00002350TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2351 Decl *FromTU = getTuDecl(
2352 R"(
2353 void foo() {
2354 (void)[]() { ; };
2355 }
2356 )",
2357 Lang_CXX11);
2358 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2359 FromTU, functionDecl(hasName("foo")));
2360 auto *ToD = Import(FromD, Lang_CXX);
2361 EXPECT_TRUE(ToD);
2362 CXXRecordDecl *LambdaRec =
2363 cast<LambdaExpr>(cast<CStyleCastExpr>(
2364 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2365 ->getSubExpr())
2366 ->getLambdaClass();
2367 EXPECT_TRUE(LambdaRec->getDestructor());
2368}
2369
Gabor Marton5caba302019-03-07 13:38:20 +00002370TEST_P(ImportFunctions,
2371 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2372 Decl *FromTU = getTuDecl(
2373 R"(
2374 struct X {
2375 template <typename T>
2376 void foo(){}
2377 };
2378 void f() {
2379 X x;
2380 x.foo<int>();
2381 }
2382 )",
2383 Lang_CXX);
2384 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2385 FromTU, functionDecl(hasName("f")));
2386 auto *ToD = Import(FromD, Lang_CXX);
2387 EXPECT_TRUE(ToD);
2388 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
2389 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr()))));
2390}
2391
2392TEST_P(ImportFunctions,
2393 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2394 Decl *FromTU = getTuDecl(
2395 R"(
2396 struct X {
2397 template <typename T>
2398 void foo(){}
2399 };
2400 template <typename T>
2401 void f() {
2402 X x;
2403 x.foo<T>();
2404 }
2405 void g() {
2406 f<int>();
2407 }
2408 )",
2409 Lang_CXX);
2410 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2411 FromTU, functionDecl(hasName("g")));
2412 auto *ToD = Import(FromD, Lang_CXX);
2413 EXPECT_TRUE(ToD);
2414 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2415 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match(
2416 ToTU, translationUnitDecl(hasDescendant(
2417 functionDecl(hasName("f"), hasDescendant(declRefExpr()))))));
2418}
2419
Balazs Kerie9719f92019-08-07 12:40:17 +00002420struct ImportFunctionTemplates : ASTImporterOptionSpecificTestBase {};
2421
2422TEST_P(ImportFunctionTemplates, ImportFunctionTemplateInRecordDeclTwice) {
2423 auto Code =
2424 R"(
2425 class X {
2426 template <class T>
2427 void f(T t);
2428 };
2429 )";
2430 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2431 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2432 FromTU1, functionTemplateDecl(hasName("f")));
2433 auto *ToD1 = Import(FromD1, Lang_CXX);
2434 Decl *FromTU2 = getTuDecl(Code, Lang_CXX, "input2.cc");
2435 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2436 FromTU2, functionTemplateDecl(hasName("f")));
2437 auto *ToD2 = Import(FromD2, Lang_CXX);
2438 EXPECT_EQ(ToD1, ToD2);
2439}
2440
2441TEST_P(ImportFunctionTemplates,
2442 ImportFunctionTemplateWithDefInRecordDeclTwice) {
2443 auto Code =
2444 R"(
2445 class X {
2446 template <class T>
2447 void f(T t);
2448 };
2449 template <class T>
2450 void X::f(T t) {};
2451 )";
2452 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2453 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2454 FromTU1, functionTemplateDecl(hasName("f")));
2455 auto *ToD1 = Import(FromD1, Lang_CXX);
2456 Decl *FromTU2 = getTuDecl(Code, Lang_CXX, "input2.cc");
2457 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2458 FromTU2, functionTemplateDecl(hasName("f")));
2459 auto *ToD2 = Import(FromD2, Lang_CXX);
2460 EXPECT_EQ(ToD1, ToD2);
2461}
2462
Gabor Martonf035b752019-08-27 11:36:10 +00002463TEST_P(ImportFunctionTemplates,
2464 ImportFunctionWhenThereIsAFunTemplateWithSameName) {
2465 getToTuDecl(
2466 R"(
2467 template <typename T>
2468 void foo(T) {}
2469 void foo();
2470 )",
2471 Lang_CXX);
2472 Decl *FromTU = getTuDecl("void foo();", Lang_CXX);
2473 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2474 FromTU, functionDecl(hasName("foo")));
2475 auto *ImportedD = Import(FromD, Lang_CXX);
2476 EXPECT_TRUE(ImportedD);
2477}
2478
2479TEST_P(ImportFunctionTemplates,
2480 ImportConstructorWhenThereIsAFunTemplateWithSameName) {
2481 auto Code =
2482 R"(
2483 struct Foo {
2484 template <typename T>
2485 Foo(T) {}
2486 Foo();
2487 };
2488 )";
2489 getToTuDecl(Code, Lang_CXX);
2490 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2491 auto *FromD =
2492 LastDeclMatcher<CXXConstructorDecl>().match(FromTU, cxxConstructorDecl());
2493 auto *ImportedD = Import(FromD, Lang_CXX);
2494 EXPECT_TRUE(ImportedD);
2495}
2496
2497TEST_P(ImportFunctionTemplates,
2498 ImportOperatorWhenThereIsAFunTemplateWithSameName) {
2499 getToTuDecl(
2500 R"(
2501 template <typename T>
2502 void operator<(T,T) {}
2503 struct X{};
2504 void operator<(X, X);
2505 )",
2506 Lang_CXX);
2507 Decl *FromTU = getTuDecl(
2508 R"(
2509 struct X{};
2510 void operator<(X, X);
2511 )",
2512 Lang_CXX);
2513 auto *FromD = LastDeclMatcher<FunctionDecl>().match(
2514 FromTU, functionDecl(hasOverloadedOperatorName("<")));
2515 auto *ImportedD = Import(FromD, Lang_CXX);
2516 EXPECT_TRUE(ImportedD);
2517}
2518
Gabor Marton5254e642018-06-27 13:32:50 +00002519struct ImportFriendFunctions : ImportFunctions {};
2520
2521TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2522 auto Pattern = functionDecl(hasName("f"));
2523
2524 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2525 "void f();",
2526 Lang_CXX,
2527 "input0.cc");
2528 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2529
2530 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2531 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2532 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2533 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2534 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2535 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2536 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2537}
2538
2539TEST_P(ImportFriendFunctions,
2540 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2541 auto Pattern = functionDecl(hasName("f"));
2542
2543 Decl *FromTU = getTuDecl("void f();"
2544 "struct X { friend void f(); };",
2545 Lang_CXX, "input0.cc");
2546 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2547
2548 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2549 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2550 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2551 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2552 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2553 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2554 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2555}
2556
2557TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2558 auto Pattern = functionDecl(hasName("f"));
2559
2560 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2561 "void f();",
2562 Lang_CXX,
2563 "input0.cc");
2564 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2565
2566 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2567 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2568 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2569 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2570 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2571 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2572 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2573}
2574
2575TEST_P(ImportFriendFunctions,
2576 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2577 auto Pattern = functionDecl(hasName("f"));
2578
2579 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2580 "void f(){}",
2581 Lang_CXX, "input0.cc");
2582 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2583
2584 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2585 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2586 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2587 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2588 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2589 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2590 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2591}
2592
Gabor Marton1d51e3e2019-05-20 10:38:14 +00002593TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDefWithClass) {
Gabor Marton5254e642018-06-27 13:32:50 +00002594 auto Pattern = functionDecl(hasName("f"));
2595
2596 Decl *FromTU = getTuDecl(
2597 R"(
2598 class X;
2599 void f(X *x){}
2600 class X{
2601 friend void f(X *x);
2602 };
2603 )",
2604 Lang_CXX, "input0.cc");
2605 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2606
2607 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2608 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2609 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2610 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2611 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2612 .match(ToTU, friendDecl())
2613 ->getFriendDecl());
2614 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2615 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2616 // The parameters must refer the same type
2617 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2618 (*ImportedD->param_begin())->getOriginalType());
2619}
2620
Gabor Marton5254e642018-06-27 13:32:50 +00002621TEST_P(ImportFriendFunctions,
Gabor Marton1d51e3e2019-05-20 10:38:14 +00002622 ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002623 auto Pattern = functionDecl(hasName("f"));
2624
2625 Decl *FromTU = getTuDecl(
2626 R"(
2627 class X;
2628 void f(X *x){}
2629 class X{
2630 friend void f(X *x);
2631 };
2632 )",
2633 Lang_CXX, "input0.cc");
2634 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2635
2636 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2637 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2638 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2639 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2640 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2641 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2642
2643 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2644 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2645 // The parameters must refer the same type
2646 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2647 (*ImportedD->param_begin())->getOriginalType());
2648}
2649
2650TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2651 auto Pattern = functionDecl(hasName("f"));
2652
2653 FunctionDecl *ImportedD;
2654 {
2655 Decl *FromTU =
2656 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2657 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2658 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2659 }
2660 FunctionDecl *ImportedD1;
2661 {
2662 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2663 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2664 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2665 }
2666
2667 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2668 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2669 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2670 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2671 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2672}
2673
Balazs Keri89632b82018-08-21 14:32:21 +00002674TEST_P(ImportFriendFunctions, Lookup) {
2675 auto FunctionPattern = functionDecl(hasName("f"));
2676 auto ClassPattern = cxxRecordDecl(hasName("X"));
2677
2678 TranslationUnitDecl *FromTU =
2679 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2680 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2681 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2682 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2683 {
2684 auto FromName = FromD->getDeclName();
2685 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2686 auto LookupRes = Class->noload_lookup(FromName);
2687 ASSERT_EQ(LookupRes.size(), 0u);
2688 LookupRes = FromTU->noload_lookup(FromName);
2689 ASSERT_EQ(LookupRes.size(), 1u);
2690 }
2691
2692 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2693 auto ToName = ToD->getDeclName();
2694
2695 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2696 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2697 auto LookupRes = Class->noload_lookup(ToName);
2698 EXPECT_EQ(LookupRes.size(), 0u);
2699 LookupRes = ToTU->noload_lookup(ToName);
2700 EXPECT_EQ(LookupRes.size(), 1u);
2701
2702 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2703 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2704 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2705 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2706}
2707
2708TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2709 auto FunctionPattern = functionDecl(hasName("f"));
2710 auto ClassPattern = cxxRecordDecl(hasName("X"));
2711
2712 TranslationUnitDecl *FromTU = getTuDecl(
2713 "struct X { friend void f(); };"
2714 // This proto decl makes f available to normal
2715 // lookup, otherwise it is hidden.
2716 // Normal C++ lookup (implemented in
2717 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2718 // returns the found `NamedDecl` only if the set IDNS is matched
2719 "void f();",
2720 Lang_CXX, "input0.cc");
2721 auto *FromFriend =
2722 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2723 auto *FromNormal =
2724 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2725 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2726 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2727 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2728 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2729
2730 auto FromName = FromFriend->getDeclName();
2731 auto *FromClass =
2732 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2733 auto LookupRes = FromClass->noload_lookup(FromName);
2734 ASSERT_EQ(LookupRes.size(), 0u);
2735 LookupRes = FromTU->noload_lookup(FromName);
2736 ASSERT_EQ(LookupRes.size(), 1u);
2737
2738 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2739 auto ToName = ToFriend->getDeclName();
2740
2741 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2742 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2743 LookupRes = ToClass->noload_lookup(ToName);
2744 EXPECT_EQ(LookupRes.size(), 0u);
2745 LookupRes = ToTU->noload_lookup(ToName);
2746 // Test is disabled because this result is 2.
2747 EXPECT_EQ(LookupRes.size(), 1u);
2748
2749 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2750 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2751 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2752 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2753 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2754 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2755 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2756}
2757
2758TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2759 auto FunctionPattern = functionDecl(hasName("f"));
2760 auto ClassPattern = cxxRecordDecl(hasName("X"));
2761
2762 TranslationUnitDecl *FromTU = getTuDecl(
2763 "void f();"
2764 "struct X { friend void f(); };",
2765 Lang_CXX, "input0.cc");
2766 auto *FromNormal =
2767 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2768 auto *FromFriend =
2769 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2770 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2771 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2772 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2773 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2774
2775 auto FromName = FromNormal->getDeclName();
2776 auto *FromClass =
2777 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2778 auto LookupRes = FromClass->noload_lookup(FromName);
2779 ASSERT_EQ(LookupRes.size(), 0u);
2780 LookupRes = FromTU->noload_lookup(FromName);
2781 ASSERT_EQ(LookupRes.size(), 1u);
2782
2783 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2784 auto ToName = ToNormal->getDeclName();
2785 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2786
2787 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2788 LookupRes = ToClass->noload_lookup(ToName);
2789 EXPECT_EQ(LookupRes.size(), 0u);
2790 LookupRes = ToTU->noload_lookup(ToName);
2791 EXPECT_EQ(LookupRes.size(), 1u);
2792
2793 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2794 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2795 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2796 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2797 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2798 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2799 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2800}
2801
2802TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2803 auto Pattern = functionDecl(hasName("f"));
2804
2805 TranslationUnitDecl *FromNormalTU =
2806 getTuDecl("void f();", Lang_CXX, "input0.cc");
2807 auto *FromNormalF =
2808 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2809 TranslationUnitDecl *FromFriendTU =
2810 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2811 auto *FromFriendF =
2812 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2813 auto FromNormalName = FromNormalF->getDeclName();
2814 auto FromFriendName = FromFriendF->getDeclName();
2815
2816 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2817 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2818 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2819 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2820 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2821 ASSERT_EQ(LookupRes.size(), 1u);
2822 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2823 ASSERT_EQ(LookupRes.size(), 1u);
2824
2825 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2826 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2827 auto ToName = ToNormalF->getDeclName();
2828 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2829 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2830 LookupRes = ToTU->noload_lookup(ToName);
2831 EXPECT_EQ(LookupRes.size(), 1u);
2832 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00002833
Balazs Keri89632b82018-08-21 14:32:21 +00002834 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
2835 LookupRes = ToTU->noload_lookup(ToName);
2836 EXPECT_EQ(LookupRes.size(), 1u);
2837 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2838
2839 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2840 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2841
2842 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2843 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2844}
2845
2846TEST_P(ImportFriendFunctions, ImportFriendList) {
2847 TranslationUnitDecl *FromTU = getTuDecl(
2848 "struct X { friend void f(); };"
2849 "void f();",
2850 Lang_CXX, "input0.cc");
2851 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2852 FromTU, functionDecl(hasName("f")));
2853
2854 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2855 FromTU, cxxRecordDecl(hasName("X")));
2856 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2857 auto FromFriends = FromClass->friends();
2858 unsigned int FrN = 0;
2859 for (auto Fr : FromFriends) {
2860 ASSERT_EQ(Fr, FromFriend);
2861 ++FrN;
2862 }
2863 ASSERT_EQ(FrN, 1u);
2864
2865 Import(FromFriendF, Lang_CXX);
2866 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2867 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2868 ToTU, cxxRecordDecl(hasName("X")));
2869 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2870 auto ToFriends = ToClass->friends();
2871 FrN = 0;
2872 for (auto Fr : ToFriends) {
2873 EXPECT_EQ(Fr, ToFriend);
2874 ++FrN;
2875 }
2876 EXPECT_EQ(FrN, 1u);
2877}
2878
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002879AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2880 InnerMatcher) {
2881 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2882 return InnerMatcher.matches(*Typedef, Finder, Builder);
2883 return false;
2884}
2885
Gabor Marton19f4f392018-06-25 13:04:37 +00002886TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002887 CodeFiles Samples{{"main.c",
2888 {"void foo();"
2889 "void moo();"
2890 "int main() { foo(); moo(); }",
2891 Lang_C}},
2892
2893 {"foo.c",
2894 {"typedef enum { THING_VALUE } thing_t;"
2895 "void conflict(thing_t type);"
2896 "void foo() { (void)THING_VALUE; }"
2897 "void conflict(thing_t type) {}",
2898 Lang_C}},
2899
2900 {"moo.c",
2901 {"typedef enum { THING_VALUE } thing_t;"
2902 "void conflict(thing_t type);"
2903 "void moo() { conflict(THING_VALUE); }",
2904 Lang_C}}};
2905
2906 auto VerificationMatcher =
2907 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2908 hasTypedefForAnonDecl(hasName("thing_t")));
2909
2910 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2911 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2912
2913 testImportSequence(
2914 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2915 // Just check that there is only one enum decl in the result AST.
2916 "main.c", enumDecl(), VerificationMatcher);
2917
2918 // For different import order, result should be the same.
2919 testImportSequence(
2920 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2921 // Check that there is only one enum decl in the result AST.
2922 "main.c", enumDecl(), VerificationMatcher);
2923}
2924
Gabor Marton48b16e12019-07-25 09:07:17 +00002925TEST_P(ImportDecl, ImportFieldOrder) {
2926 MatchVerifier<Decl> Verifier;
2927 testImport("struct declToImport {"
2928 " int b = a + 2;"
2929 " int a = 5;"
2930 "};",
2931 Lang_CXX11, "", Lang_CXX11, Verifier,
2932 recordDecl(hasFieldOrder({"b", "a"})));
2933}
2934
Peter Szecsice7f3182018-05-07 12:08:27 +00002935const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2936 dependentScopeDeclRefExpr;
2937
Gabor Marton19f4f392018-06-25 13:04:37 +00002938TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002939 MatchVerifier<Decl> Verifier;
2940 testImport("template <typename T> struct S { static T foo; };"
2941 "template <typename T> void declToImport() {"
2942 " (void) S<T>::foo;"
2943 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002944 "void instantiate() { declToImport<int>(); }"
2945 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002946 Lang_CXX11, "", Lang_CXX11, Verifier,
2947 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2948 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2949
2950 testImport("template <typename T> struct S {"
2951 "template<typename S> static void foo(){};"
2952 "};"
2953 "template <typename T> void declToImport() {"
2954 " S<T>::template foo<T>();"
2955 "}"
2956 "void instantiate() { declToImport<int>(); }",
2957 Lang_CXX11, "", Lang_CXX11, Verifier,
2958 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2959 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2960}
2961
2962const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2963 dependentNameType;
2964
Gabor Marton19f4f392018-06-25 13:04:37 +00002965TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002966 MatchVerifier<Decl> Verifier;
2967 testImport("template <typename T> struct declToImport {"
2968 " typedef typename T::type dependent_name;"
2969 "};",
2970 Lang_CXX11, "", Lang_CXX11, Verifier,
2971 classTemplateDecl(has(
2972 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2973}
2974
Gabor Marton19f4f392018-06-25 13:04:37 +00002975TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002976 MatchVerifier<Decl> Verifier;
2977 testImport("struct S { template <typename T> void mem(); };"
2978 "template <typename U> void declToImport() {"
2979 " S s;"
2980 " s.mem<U>();"
2981 "}"
2982 "void instantiate() { declToImport<int>(); }",
2983 Lang_CXX11, "", Lang_CXX11, Verifier,
2984 functionTemplateDecl(has(functionDecl(has(
2985 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2986}
2987
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002988class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
Balazs Keri1d20cc22018-07-16 12:16:39 +00002989public:
2990 static constexpr auto DefaultCode = R"(
2991 struct A { int x; };
2992 void f() {
2993 A a;
2994 A a1(a);
2995 A a2(A{});
2996 a = a1;
2997 a = A{};
2998 a.~A();
2999 })";
3000
3001 template <typename MatcherType>
3002 void testImportOf(
3003 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3004 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
3005 }
3006
3007 template <typename MatcherType>
3008 void testNoImportOf(
3009 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3010 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
3011 }
3012
3013private:
3014 template <typename MatcherType>
3015 void test(const MatcherType &MethodMatcher,
3016 const char *Code, unsigned int ExpectedCount) {
3017 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
3018
3019 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3020 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3021 ToTU, ClassMatcher);
3022
Balazs Keri2f752ba2018-07-16 14:05:18 +00003023 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003024
3025 {
3026 CXXMethodDecl *Method =
3027 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
3028 ToClass->removeDecl(Method);
Gabor Marton2afbfb62019-07-01 15:37:07 +00003029 SharedStatePtr->getLookupTable()->remove(Method);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003030 }
3031
Balazs Keri2f752ba2018-07-16 14:05:18 +00003032 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003033
3034 Decl *ImportedClass = nullptr;
3035 {
3036 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
3037 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3038 FromTU, ClassMatcher);
3039 ImportedClass = Import(FromClass, Lang_CXX11);
3040 }
3041
3042 EXPECT_EQ(ToClass, ImportedClass);
3043 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
3044 ExpectedCount);
3045 }
3046};
3047
3048TEST_P(ImportImplicitMethods, DefaultConstructor) {
3049 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
3050}
3051
3052TEST_P(ImportImplicitMethods, CopyConstructor) {
3053 testImportOf(cxxConstructorDecl(isCopyConstructor()));
3054}
3055
3056TEST_P(ImportImplicitMethods, MoveConstructor) {
3057 testImportOf(cxxConstructorDecl(isMoveConstructor()));
3058}
3059
3060TEST_P(ImportImplicitMethods, Destructor) {
3061 testImportOf(cxxDestructorDecl());
3062}
3063
3064TEST_P(ImportImplicitMethods, CopyAssignment) {
3065 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
3066}
3067
3068TEST_P(ImportImplicitMethods, MoveAssignment) {
3069 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
3070}
3071
3072TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
3073 auto Code = R"(
3074 struct A { A() { int x; } };
3075 )";
3076 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3077}
3078
3079TEST_P(ImportImplicitMethods, DoNotImportDefault) {
3080 auto Code = R"(
3081 struct A { A() = default; };
3082 )";
3083 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3084}
3085
3086TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
3087 auto Code = R"(
3088 struct A { A() = delete; };
3089 )";
3090 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3091}
3092
3093TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
3094 auto Code = R"(
3095 struct A { void f() { } };
3096 )";
3097 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
3098}
3099
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003100TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003101 Decl *ToR1;
3102 {
3103 Decl *FromTU = getTuDecl(
3104 "struct A { };", Lang_CXX, "input0.cc");
3105 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3106 FromTU, cxxRecordDecl(hasName("A")));
3107
3108 ToR1 = Import(FromR, Lang_CXX);
3109 }
3110
3111 Decl *ToR2;
3112 {
3113 Decl *FromTU = getTuDecl(
3114 "struct A { };", Lang_CXX, "input1.cc");
3115 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3116 FromTU, cxxRecordDecl(hasName("A")));
3117
3118 ToR2 = Import(FromR, Lang_CXX);
3119 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00003120
Balazs Keric7797c42018-07-11 09:37:24 +00003121 EXPECT_EQ(ToR1, ToR2);
3122}
3123
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003124TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003125 Decl *ToR1;
3126 {
3127 Decl *FromTU = getTuDecl(
3128 "struct A { int x; };", Lang_CXX, "input0.cc");
3129 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3130 FromTU, cxxRecordDecl(hasName("A")));
3131 ToR1 = Import(FromR, Lang_CXX);
3132 }
3133 Decl *ToR2;
3134 {
3135 Decl *FromTU = getTuDecl(
3136 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3137 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3138 FromTU, cxxRecordDecl(hasName("A")));
3139 ToR2 = Import(FromR, Lang_CXX);
3140 }
3141 EXPECT_NE(ToR1, ToR2);
3142}
3143
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003144TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003145 Decl *ToF1;
3146 {
3147 Decl *FromTU = getTuDecl(
3148 "struct A { int x; };", Lang_CXX, "input0.cc");
3149 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3150 FromTU, fieldDecl(hasName("x")));
3151 ToF1 = Import(FromF, Lang_CXX);
3152 }
3153 Decl *ToF2;
3154 {
3155 Decl *FromTU = getTuDecl(
3156 "struct A { int x; };", Lang_CXX, "input1.cc");
3157 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3158 FromTU, fieldDecl(hasName("x")));
3159 ToF2 = Import(FromF, Lang_CXX);
3160 }
3161 EXPECT_EQ(ToF1, ToF2);
3162}
3163
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003164TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003165 Decl *ToF1;
3166 {
3167 Decl *FromTU = getTuDecl(
3168 "struct A { int x; };", Lang_CXX, "input0.cc");
3169 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3170 FromTU, fieldDecl(hasName("x")));
3171 ToF1 = Import(FromF, Lang_CXX);
3172 }
3173 Decl *ToF2;
3174 {
3175 Decl *FromTU = getTuDecl(
3176 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3177 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3178 FromTU, fieldDecl(hasName("x")));
3179 ToF2 = Import(FromF, Lang_CXX);
3180 }
3181 EXPECT_NE(ToF1, ToF2);
3182}
3183
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003184TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003185 Decl *ToM1;
3186 {
3187 Decl *FromTU = getTuDecl(
3188 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
3189 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3190 FromTU, functionDecl(hasName("x"), isDefinition()));
3191 ToM1 = Import(FromM, Lang_CXX);
3192 }
3193 Decl *ToM2;
3194 {
3195 Decl *FromTU = getTuDecl(
3196 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
3197 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3198 FromTU, functionDecl(hasName("x"), isDefinition()));
3199 ToM2 = Import(FromM, Lang_CXX);
3200 }
3201 EXPECT_EQ(ToM1, ToM2);
3202}
3203
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003204TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003205 Decl *ToM1;
3206 {
3207 Decl *FromTU = getTuDecl(
3208 "struct A { void x(); }; void A::x() { }",
3209 Lang_CXX, "input0.cc");
3210 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3211 FromTU, functionDecl(hasName("x"), isDefinition()));
3212 ToM1 = Import(FromM, Lang_CXX);
3213 }
3214 Decl *ToM2;
3215 {
3216 Decl *FromTU = getTuDecl(
3217 "struct A { void x() const; }; void A::x() const { }",
3218 Lang_CXX, "input1.cc");
3219 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3220 FromTU, functionDecl(hasName("x"), isDefinition()));
3221 ToM2 = Import(FromM, Lang_CXX);
3222 }
3223 EXPECT_NE(ToM1, ToM2);
3224}
3225
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003226TEST_P(ASTImporterOptionSpecificTestBase,
3227 ImportUnnamedStructsWithRecursingField) {
Gabor Martonf086fa82018-07-17 12:06:36 +00003228 Decl *FromTU = getTuDecl(
3229 R"(
3230 struct A {
3231 struct {
3232 struct A *next;
3233 } entry0;
3234 struct {
3235 struct A *next;
3236 } entry1;
3237 };
3238 )",
3239 Lang_C, "input0.cc");
3240 auto *From =
3241 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3242
3243 Import(From, Lang_C);
3244
3245 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3246 auto *Entry0 =
3247 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3248 auto *Entry1 =
3249 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3250 auto *R0 = getRecordDecl(Entry0);
3251 auto *R1 = getRecordDecl(Entry1);
3252 EXPECT_NE(R0, R1);
3253 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3254 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3255 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3256 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3257}
3258
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003259TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
Balazs Keri2544b4b2018-08-08 09:40:57 +00003260 Decl *FromTU = getTuDecl(
3261 R"(
3262 void f(int X, int Y, bool Z) {
3263 (void)[X, Y, Z] { (void)Z; };
3264 }
3265 )",
3266 Lang_CXX11, "input0.cc");
3267 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3268 FromTU, functionDecl(hasName("f")));
3269 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3270 EXPECT_TRUE(ToF);
3271
3272 CXXRecordDecl *FromLambda =
3273 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3274 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3275
3276 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3277 EXPECT_TRUE(ToLambda);
3278
3279 // Check if the fields of the lambda class are imported in correct order.
3280 unsigned FromIndex = 0u;
3281 for (auto *FromField : FromLambda->fields()) {
3282 ASSERT_FALSE(FromField->getDeclName());
3283 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3284 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00003285 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3286 EXPECT_TRUE(ToIndex);
3287 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00003288 ++FromIndex;
3289 }
3290
3291 EXPECT_EQ(FromIndex, 3u);
3292}
3293
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003294TEST_P(ASTImporterOptionSpecificTestBase,
3295 MergeFieldDeclsOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003296 std::string ClassTemplate =
3297 R"(
3298 template <typename T>
3299 struct X {
3300 int a{0}; // FieldDecl with InitListExpr
3301 X(char) : a(3) {} // (1)
3302 X(int) {} // (2)
3303 };
3304 )";
3305 Decl *ToTU = getToTuDecl(ClassTemplate +
3306 R"(
3307 void foo() {
3308 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3309 X<char> xc('c');
3310 }
3311 )", Lang_CXX11);
3312 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3313 ToTU, classTemplateSpecializationDecl(hasName("X")));
3314 // FieldDecl without InitlistExpr:
3315 auto *ToField = *ToSpec->field_begin();
3316 ASSERT_TRUE(ToField);
3317 ASSERT_FALSE(ToField->getInClassInitializer());
3318 Decl *FromTU = getTuDecl(ClassTemplate +
3319 R"(
3320 void bar() {
3321 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3322 X<char> xc(1);
3323 }
3324 )", Lang_CXX11);
3325 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3326 FromTU, classTemplateSpecializationDecl(hasName("X")));
3327 // FieldDecl with InitlistExpr:
3328 auto *FromField = *FromSpec->field_begin();
3329 ASSERT_TRUE(FromField);
3330 ASSERT_TRUE(FromField->getInClassInitializer());
3331
3332 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3333 ASSERT_TRUE(ImportedSpec);
3334 EXPECT_EQ(ImportedSpec, ToSpec);
3335 // After the import, the FieldDecl has to be merged, thus it should have the
3336 // InitListExpr.
3337 EXPECT_TRUE(ToField->getInClassInitializer());
3338}
3339
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003340TEST_P(ASTImporterOptionSpecificTestBase,
3341 MergeFunctionOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003342 std::string ClassTemplate =
3343 R"(
3344 template <typename T>
3345 struct X {
3346 void f() {}
3347 void g() {}
3348 };
3349 )";
3350 Decl *ToTU = getToTuDecl(ClassTemplate +
3351 R"(
3352 void foo() {
3353 X<char> x;
3354 x.f();
3355 }
3356 )", Lang_CXX11);
3357 Decl *FromTU = getTuDecl(ClassTemplate +
3358 R"(
3359 void bar() {
3360 X<char> x;
3361 x.g();
3362 }
3363 )", Lang_CXX11);
3364 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3365 FromTU, classTemplateSpecializationDecl(hasName("X")));
3366 auto FunPattern = functionDecl(hasName("g"),
3367 hasParent(classTemplateSpecializationDecl()));
3368 auto *FromFun =
3369 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3370 auto *ToFun =
3371 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3372 ASSERT_TRUE(FromFun->hasBody());
3373 ASSERT_FALSE(ToFun->hasBody());
3374 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3375 ASSERT_TRUE(ImportedSpec);
3376 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3377 ToTU, classTemplateSpecializationDecl(hasName("X")));
3378 EXPECT_EQ(ImportedSpec, ToSpec);
3379 EXPECT_TRUE(ToFun->hasBody());
3380}
3381
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003382TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003383 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3384 std::string ClassTemplate =
3385 R"(
3386 template <typename T>
3387 struct X {};
3388 )";
3389 Decl *ToTU = getToTuDecl(ClassTemplate +
3390 R"(
3391 template <>
3392 struct X<char> {
3393 int a;
3394 };
3395 void foo() {
3396 X<char> x;
3397 }
3398 )",
3399 Lang_CXX11);
3400 Decl *FromTU = getTuDecl(ClassTemplate +
3401 R"(
3402 template <>
3403 struct X<char> {
3404 int b;
3405 };
3406 void foo() {
3407 X<char> x;
3408 }
3409 )",
3410 Lang_CXX11);
3411 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3412 FromTU, classTemplateSpecializationDecl(hasName("X")));
3413 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3414
3415 // We expect one (ODR) warning during the import.
3416 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3417
3418 // The second specialization is different from the first, thus it violates
3419 // ODR, consequently we expect to keep the first specialization only, which is
3420 // already in the "To" context.
Gabor Marton7f8c4002019-03-19 13:34:10 +00003421 EXPECT_FALSE(ImportedSpec);
3422 EXPECT_EQ(1u,
3423 DeclCounter<ClassTemplateSpecializationDecl>().match(
3424 ToTU, classTemplateSpecializationDecl(hasName("X"))));
Gabor Marton42e15de2018-08-22 11:52:14 +00003425}
3426
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003427TEST_P(ASTImporterOptionSpecificTestBase,
3428 MergeCtorOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003429 std::string ClassTemplate =
3430 R"(
3431 template <typename T>
3432 struct X {
3433 X(char) {}
3434 X(int) {}
3435 };
3436 )";
3437 Decl *ToTU = getToTuDecl(ClassTemplate +
3438 R"(
3439 void foo() {
3440 X<char> x('c');
3441 }
3442 )", Lang_CXX11);
3443 Decl *FromTU = getTuDecl(ClassTemplate +
3444 R"(
3445 void bar() {
3446 X<char> x(1);
3447 }
3448 )", Lang_CXX11);
3449 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3450 FromTU, classTemplateSpecializationDecl(hasName("X")));
3451 // Match the void(int) ctor.
3452 auto CtorPattern =
3453 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3454 hasParent(classTemplateSpecializationDecl()));
3455 auto *FromCtor =
3456 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3457 auto *ToCtor =
3458 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3459 ASSERT_TRUE(FromCtor->hasBody());
3460 ASSERT_FALSE(ToCtor->hasBody());
3461 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3462 ASSERT_TRUE(ImportedSpec);
3463 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3464 ToTU, classTemplateSpecializationDecl(hasName("X")));
3465 EXPECT_EQ(ImportedSpec, ToSpec);
3466 EXPECT_TRUE(ToCtor->hasBody());
3467}
3468
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003469TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003470 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3471 auto Code =
3472 R"(
3473 // primary template
3474 template<class T1, class T2, int I>
3475 class A {};
3476
3477 // partial specialization
3478 template<class T, int I>
3479 class A<T, T*, I> {};
3480 )";
3481 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3482 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3483 auto *FromSpec =
3484 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3485 FromTU, classTemplatePartialSpecializationDecl());
3486 auto *ToSpec =
3487 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3488 ToTU, classTemplatePartialSpecializationDecl());
3489
3490 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3491 EXPECT_EQ(ImportedSpec, ToSpec);
3492 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3493 ToTU, classTemplatePartialSpecializationDecl()));
3494}
3495
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003496TEST_P(ASTImporterOptionSpecificTestBase,
3497 ClassTemplateSpecializationsShouldNotBeDuplicated) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003498 auto Code =
3499 R"(
3500 // primary template
3501 template<class T1, class T2, int I>
3502 class A {};
3503
3504 // full specialization
3505 template<>
3506 class A<int, int, 1> {};
3507 )";
3508 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3509 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3510 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3511 FromTU, classTemplateSpecializationDecl());
3512 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3513 ToTU, classTemplateSpecializationDecl());
3514
3515 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3516 EXPECT_EQ(ImportedSpec, ToSpec);
3517 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3518 ToTU, classTemplateSpecializationDecl()));
3519}
3520
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003521TEST_P(ASTImporterOptionSpecificTestBase,
3522 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003523 std::string PrimaryTemplate =
3524 R"(
3525 template<class T1, class T2, int I>
3526 class A {};
3527 )";
3528 auto PartialSpec =
3529 R"(
3530 template<class T, int I>
3531 class A<T, T*, I> {};
3532 )";
3533 auto FullSpec =
3534 R"(
3535 template<>
3536 class A<int, int, 1> {};
3537 )";
3538 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3539 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3540 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3541 FromTU, classTemplateSpecializationDecl());
3542
3543 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3544 EXPECT_TRUE(ImportedSpec);
3545 // Check the number of partial specializations.
3546 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3547 ToTU, classTemplatePartialSpecializationDecl()));
3548 // Check the number of full specializations.
3549 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3550 ToTU, classTemplateSpecializationDecl(
3551 unless(classTemplatePartialSpecializationDecl()))));
3552}
3553
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003554TEST_P(ASTImporterOptionSpecificTestBase,
3555 InitListExprValueKindShouldBeImported) {
Gabor Martona20ce602018-09-03 13:10:53 +00003556 Decl *TU = getTuDecl(
3557 R"(
3558 const int &init();
3559 void foo() { const int &a{init()}; }
3560 )", Lang_CXX11, "input0.cc");
3561 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3562 ASSERT_TRUE(FromD->getAnyInitializer());
3563 auto *InitExpr = FromD->getAnyInitializer();
3564 ASSERT_TRUE(InitExpr);
3565 ASSERT_TRUE(InitExpr->isGLValue());
3566
3567 auto *ToD = Import(FromD, Lang_CXX11);
3568 EXPECT_TRUE(ToD);
3569 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3570 EXPECT_TRUE(ToInitExpr);
3571 EXPECT_TRUE(ToInitExpr->isGLValue());
3572}
3573
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003574struct ImportVariables : ASTImporterOptionSpecificTestBase {};
Gabor Martonac3a5d62018-09-17 12:04:52 +00003575
3576TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3577 Decl *FromTU = getTuDecl(
3578 R"(
3579 struct A {
3580 static const int a = 1 + 2;
3581 };
3582 const int A::a;
3583 )", Lang_CXX, "input1.cc");
3584
3585 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3586 FromTU, varDecl(hasName("a"))); // Decl with init
3587 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3588 FromTU, varDecl(hasName("a"))); // Decl with definition
3589 ASSERT_NE(FromDWithInit, FromDWithDef);
3590 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3591
3592 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3593 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3594 ASSERT_TRUE(ToD0);
3595 ASSERT_TRUE(ToD1);
3596 EXPECT_NE(ToD0, ToD1);
3597 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3598}
3599
3600TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3601 auto StructA =
3602 R"(
3603 struct A {
3604 static const int a = 1 + 2;
3605 };
3606 )";
3607 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3608 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3609 "input1.cc");
3610
3611 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3612 FromTU, varDecl(hasName("a"))); // Decl with init
3613 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3614 FromTU, varDecl(hasName("a"))); // Decl with definition
3615 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3616 ASSERT_TRUE(FromDWithInit->getInit());
3617 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3618 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3619 ASSERT_FALSE(FromDWithDef->getInit());
3620
3621 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3622 ToTU, varDecl(hasName("a"))); // Decl with init
3623 ASSERT_TRUE(ToD->getInit());
3624 ASSERT_FALSE(ToD->getDefinition());
3625
3626 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3627 EXPECT_TRUE(ImportedD->getAnyInitializer());
3628 EXPECT_TRUE(ImportedD->getDefinition());
3629}
3630
3631TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3632 auto StructA =
3633 R"(
3634 struct A {
3635 static const int a;
3636 };
3637 )";
3638 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3639 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3640 Lang_CXX, "input1.cc");
3641
3642 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3643 FromTU, varDecl(hasName("a")));
3644 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3645 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3646 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3647 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3648 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3649 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3650 ASSERT_TRUE(FromDWithDef->getInit());
3651
3652 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3653 ToTU, varDecl(hasName("a")));
3654 ASSERT_FALSE(ToD->getInit());
3655 ASSERT_FALSE(ToD->getDefinition());
3656
3657 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3658 EXPECT_TRUE(ImportedD->getAnyInitializer());
3659 EXPECT_TRUE(ImportedD->getDefinition());
3660}
3661
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003662struct ImportClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003663
Gabor Marton54058b52018-12-17 13:53:12 +00003664TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3665 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
3666 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3667 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3668 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3669 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3670
3671 Decl *ImportedDef = Import(FromDef, Lang_C);
3672
3673 EXPECT_NE(ImportedDef, ToProto);
3674 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3675 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3676 EXPECT_TRUE(ImportedDef == ToDef);
3677 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3678 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3679 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3680}
3681
3682TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3683 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
3684 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
3685 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3686 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3687 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3688
3689 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3690
3691 EXPECT_NE(ImportedDef, ToProto);
3692 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3693 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3694 EXPECT_TRUE(ImportedDef == ToDef);
3695 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3696 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3697 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3698}
3699
3700TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3701 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
3702 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3703 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3704 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3705 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3706
3707 Decl *ImportedProto = Import(FromProto, Lang_C);
3708 Decl *ImportedDef = Import(FromDef, Lang_C);
3709 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3710
3711 EXPECT_NE(ImportedDef, ImportedProto);
3712 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3713 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3714 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3715 EXPECT_TRUE(ImportedDef == ToDef);
3716 EXPECT_TRUE(ImportedProto == ToProto);
3717 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3718 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3719 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3720}
3721
Gabor Marton7df342a2018-12-17 12:42:12 +00003722
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003723struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003724
3725TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
3726 Decl *FromTU = getTuDecl(
3727 R"(
3728 class A {
3729 template <int I> class F {};
3730 class X {
3731 template <int I> friend class F;
3732 };
3733 };
3734 )",
3735 Lang_CXX, "input0.cc");
3736
3737 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3738 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
3739 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
3740 FromTU, cxxRecordDecl(hasName("F")));
3741
3742 ASSERT_TRUE(FromClass);
3743 ASSERT_TRUE(FromFriendClass);
3744 ASSERT_NE(FromClass, FromFriendClass);
3745 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
3746 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
3747 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3748 FromClass->getDescribedClassTemplate());
3749
3750 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
3751 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
3752
3753 EXPECT_TRUE(ToClass);
3754 EXPECT_TRUE(ToFriendClass);
3755 EXPECT_NE(ToClass, ToFriendClass);
3756 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
3757 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
3758 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3759 ToClass->getDescribedClassTemplate());
3760}
3761
3762TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
3763 Decl *FromTu = getTuDecl(
3764 R"(
3765 class declToImport {
3766 friend class declToImport;
3767 };
3768 )",
3769 Lang_CXX, "input.cc");
3770
3771 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
3772 FromTu, cxxRecordDecl(hasName("declToImport")));
3773 auto *ToD = Import(FromD, Lang_CXX);
3774 auto Pattern = cxxRecordDecl(has(friendDecl()));
3775 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3776 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3777}
3778
3779TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
3780 Decl *FromTu = getTuDecl(
3781 R"(
3782 template<class A> class declToImport {
3783 template<class A1> friend class declToImport;
3784 };
3785 )",
3786 Lang_CXX, "input.cc");
3787
3788 auto *FromD =
3789 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
3790 auto *ToD = Import(FromD, Lang_CXX);
3791
3792 auto Pattern = classTemplateDecl(
3793 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
3794 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3795 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3796
3797 auto *Class =
3798 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
3799 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
3800 EXPECT_NE(Friend->getFriendDecl(), Class);
3801 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
3802}
3803
3804TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
3805 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
3806
3807 ClassTemplateSpecializationDecl *Imported1;
3808 {
3809 Decl *FromTU = getTuDecl("template<class T> class X;"
3810 "struct Y { friend class X<int>; };",
3811 Lang_CXX, "input0.cc");
3812 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3813 FromTU, Pattern);
3814
3815 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3816 }
3817 ClassTemplateSpecializationDecl *Imported2;
3818 {
3819 Decl *FromTU = getTuDecl("template<class T> class X;"
3820 "template<> class X<int>{};"
3821 "struct Z { friend class X<int>; };",
3822 Lang_CXX, "input1.cc");
3823 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3824 FromTU, Pattern);
3825
3826 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3827 }
3828
3829 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3830 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
3831 2u);
3832 ASSERT_TRUE(Imported2->getPreviousDecl());
3833 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
3834}
3835
3836TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
3837 Decl *FromTU0 = getTuDecl(
3838 R"(
3839 class X {
3840 class Y;
3841 };
3842 class X::Y {
3843 template <typename T>
3844 friend class F; // The decl context of F is the global namespace.
3845 };
3846 )",
3847 Lang_CXX, "input0.cc");
3848 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3849 FromTU0, classTemplateDecl(hasName("F")));
3850 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3851 Decl *FromTU1 = getTuDecl(
3852 R"(
3853 template <typename T>
3854 class F {};
3855 )",
3856 Lang_CXX, "input1.cc");
3857 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3858 FromTU1, classTemplateDecl(hasName("F")));
3859 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3860 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
3861 Imported1->getTemplatedDecl()->getTypeForDecl());
3862}
3863
3864TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
3865 Decl *From, *To;
3866 std::tie(From, To) =
3867 getImportedDecl("class declToImport {};", Lang_CXX,
3868 "class Y { friend class declToImport; };", Lang_CXX);
3869 auto *Imported = cast<CXXRecordDecl>(To);
3870
3871 EXPECT_TRUE(Imported->getPreviousDecl());
3872}
3873
3874TEST_P(ImportFriendClasses,
3875 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
3876 Decl *ToTU = getToTuDecl(
3877 R"(
3878 class X {
3879 class Y;
3880 };
3881 class X::Y {
3882 template <typename T>
3883 friend class F; // The decl context of F is the global namespace.
3884 };
3885 )",
3886 Lang_CXX);
3887 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
3888 ToTU, classTemplateDecl(hasName("F")));
3889 Decl *FromTU = getTuDecl(
3890 R"(
3891 template <typename T>
3892 class F {};
3893 )",
3894 Lang_CXX, "input0.cc");
3895 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3896 FromTU, classTemplateDecl(hasName("F")));
3897 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3898 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3899 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
3900 EXPECT_EQ(ToDecl->getTemplatedDecl(),
3901 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3902}
3903
3904TEST_P(ImportFriendClasses,
3905 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
3906 Decl *FromTU0 = getTuDecl(
3907 R"(
3908 class X {
3909 class Y;
3910 };
3911 class X::Y {
3912 template <typename T>
3913 friend class F; // The decl context of F is the global namespace.
3914 };
3915 )",
3916 Lang_CXX, "input0.cc");
3917 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3918 FromTU0, classTemplateDecl(hasName("F")));
3919 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3920 Decl *FromTU1 = getTuDecl(
3921 R"(
3922 template <typename T>
3923 class F {};
3924 )",
3925 Lang_CXX, "input1.cc");
3926 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3927 FromTU1, classTemplateDecl(hasName("F")));
3928 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3929 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3930 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3931 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
3932 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3933}
3934
3935TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
3936 Decl *FromTU0 = getTuDecl(
3937 R"(
3938 class X {
3939 class Y;
3940 };
3941 class X::Y {
3942 friend class F; // The decl context of F is the global namespace.
3943 };
3944 )",
3945 Lang_CXX, "input0.cc");
3946 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
3947 QualType FT = Friend->getFriendType()->getType();
3948 FT = FromTU0->getASTContext().getCanonicalType(FT);
3949 auto *Fwd = cast<TagType>(FT)->getDecl();
3950 auto *ImportedFwd = Import(Fwd, Lang_CXX);
3951 Decl *FromTU1 = getTuDecl(
3952 R"(
3953 class F {};
3954 )",
3955 Lang_CXX, "input1.cc");
3956 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
3957 FromTU1, cxxRecordDecl(hasName("F")));
3958 auto *ImportedDef = Import(Definition, Lang_CXX);
3959 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3960 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3961}
3962
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003963TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Gabor Marton54058b52018-12-17 13:53:12 +00003964 auto *Code = R"(
3965 template <class T>
3966 struct X {
3967 friend void foo(){}
3968 };
3969 )";
3970 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
3971 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
3972 ToTU, functionDecl(hasName("foo")));
3973
3974 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
3975 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
3976 FromTU, functionDecl(hasName("foo")));
3977 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
3978 EXPECT_EQ(ImportedFoo, ToFoo);
3979}
3980
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003981struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton61d862a2018-05-18 09:08:47 +00003982
3983TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
3984 Decl *TU = getTuDecl(
3985 R"(
3986 namespace NS {
3987
3988 template <typename T>
3989 struct S {};
3990 template struct S<int>;
3991
3992 inline namespace INS {
3993 template <typename T>
3994 struct S {};
3995 template struct S<int>;
3996 }
3997
3998 }
3999 )", Lang_CXX11, "input0.cc");
4000 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4001 TU, namespaceDecl());
4002 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4003 TU, classTemplateSpecializationDecl());
4004 ASSERT_TRUE(NS->containsDecl(Spec));
4005
4006 NS->removeDecl(Spec);
4007 EXPECT_FALSE(NS->containsDecl(Spec));
4008}
4009
Gabor Marton7df342a2018-12-17 12:42:12 +00004010TEST_P(DeclContextTest,
4011 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4012 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
4013 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4014 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4015
4016 // Investigate the list.
4017 auto *DC = A0->getDeclContext();
4018 ASSERT_TRUE(DC->containsDecl(A0));
4019 ASSERT_TRUE(DC->containsDecl(A1));
4020
4021 // Investigate the lookup table.
4022 auto *Map = DC->getLookupPtr();
4023 ASSERT_TRUE(Map);
4024 auto I = Map->find(A0->getDeclName());
4025 ASSERT_NE(I, Map->end());
4026 StoredDeclsList &L = I->second;
4027 // The lookup table contains the most recent decl of A.
4028 ASSERT_NE(L.getAsDecl(), A0);
4029 ASSERT_EQ(L.getAsDecl(), A1);
4030
4031 ASSERT_TRUE(L.getAsDecl());
4032 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4033 // The point here is to have a Vec with only one element, which is not the
4034 // one we are going to delete from the DC later.
4035 L.setHasExternalDecls();
4036 ASSERT_TRUE(L.getAsVector());
4037 ASSERT_EQ(1u, L.getAsVector()->size());
4038
4039 // This asserts in the old implementation.
4040 DC->removeDecl(A0);
4041 EXPECT_FALSE(DC->containsDecl(A0));
4042}
4043
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004044struct ImportFunctionTemplateSpecializations
4045 : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +00004046
4047TEST_P(ImportFunctionTemplateSpecializations,
4048 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4049
4050 Decl *FromTU = getTuDecl(
4051 R"(
4052 template<class T>
4053 int f() { return 0; }
4054 void foo() { f<int>(); }
4055 )",
4056 Lang_CXX, "input0.cc");
4057
4058 // Check that the function template instantiation is NOT the child of the TU.
4059 auto Pattern = translationUnitDecl(
4060 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
4061 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4062
4063 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4064 FromTU, functionDecl(hasName("foo")));
4065 ASSERT_TRUE(Import(Foo, Lang_CXX));
4066
4067 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4068 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4069}
4070
4071TEST_P(ImportFunctionTemplateSpecializations,
4072 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4073
4074 Decl *FromTU = getTuDecl(
4075 R"(
4076 template<class T>
4077 int f() { return 0; }
4078 template int f<int>();
4079 )",
4080 Lang_CXX, "input0.cc");
4081
4082 // Check that the function template instantiation is NOT the child of the TU.
4083 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4084 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4085 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4086
4087 ASSERT_TRUE(
4088 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
4089
4090 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4091 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4092}
4093
4094TEST_P(ImportFunctionTemplateSpecializations,
4095 TUshouldContainFunctionTemplateSpecialization) {
4096
4097 Decl *FromTU = getTuDecl(
4098 R"(
4099 template<class T>
4100 int f() { return 0; }
4101 template <> int f<int>() { return 4; }
4102 )",
4103 Lang_CXX, "input0.cc");
4104
4105 // Check that the function template specialization is the child of the TU.
4106 auto Specialization =
4107 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4108 auto Pattern = translationUnitDecl(has(Specialization));
4109 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4110
4111 ASSERT_TRUE(
4112 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
4113
4114 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4115 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4116}
4117
4118TEST_P(ImportFunctionTemplateSpecializations,
4119 FunctionTemplateSpecializationRedeclChain) {
4120
4121 Decl *FromTU = getTuDecl(
4122 R"(
4123 template<class T>
4124 int f() { return 0; }
4125 template <> int f<int>() { return 4; }
4126 )",
4127 Lang_CXX, "input0.cc");
4128
4129 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4130 hasParent(translationUnitDecl()));
4131 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4132 {
4133 auto *TU = FromTU;
4134 auto *SpecD = FromSpecD;
4135 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4136 TU, functionTemplateDecl());
4137 auto *FirstSpecD = *(TemplateD->spec_begin());
4138 ASSERT_EQ(SpecD, FirstSpecD);
4139 ASSERT_TRUE(SpecD->getPreviousDecl());
4140 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4141 ->doesThisDeclarationHaveABody());
4142 }
4143
4144 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
4145
4146 {
4147 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4148 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4149 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4150 TU, functionTemplateDecl());
4151 auto *FirstSpecD = *(TemplateD->spec_begin());
4152 EXPECT_EQ(SpecD, FirstSpecD);
4153 ASSERT_TRUE(SpecD->getPreviousDecl());
4154 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4155 ->doesThisDeclarationHaveABody());
4156 }
4157}
4158
4159TEST_P(ImportFunctionTemplateSpecializations,
4160 MatchNumberOfFunctionTemplateSpecializations) {
4161
4162 Decl *FromTU = getTuDecl(
4163 R"(
4164 template <typename T> constexpr int f() { return 0; }
4165 template <> constexpr int f<int>() { return 4; }
4166 void foo() {
4167 static_assert(f<char>() == 0, "");
4168 static_assert(f<int>() == 4, "");
4169 }
4170 )",
4171 Lang_CXX11, "input0.cc");
4172 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4173 FromTU, functionDecl(hasName("foo")));
4174
4175 Import(FromD, Lang_CXX11);
4176 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4177 EXPECT_EQ(
4178 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4179 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4180}
4181
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004182TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton17d39672018-11-26 15:54:08 +00004183 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4184 {
4185 Decl *FromTU = getTuDecl(
4186 R"(
4187 template <typename T>
4188 struct B;
4189 )",
4190 Lang_CXX, "input0.cc");
4191 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4192 FromTU, classTemplateDecl(hasName("B")));
4193
4194 Import(FromD, Lang_CXX);
4195 }
4196
4197 {
4198 Decl *FromTU = getTuDecl(
4199 R"(
4200 template <typename T>
4201 struct B {
4202 void f();
4203 B* b;
4204 };
4205 )",
4206 Lang_CXX, "input1.cc");
4207 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4208 FromTU, functionDecl(hasName("f")));
4209 Import(FromD, Lang_CXX);
4210 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4211 FromTU, classTemplateDecl(hasName("B")));
4212 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
4213 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4214
4215 // We expect no (ODR) warning during the import.
4216 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4217 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4218 }
4219}
4220
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004221TEST_P(ASTImporterOptionSpecificTestBase,
4222 ImportingTypedefShouldImportTheCompleteType) {
Gabor Martonb93baf62018-11-27 09:51:36 +00004223 // We already have an incomplete underlying type in the "To" context.
4224 auto Code =
4225 R"(
4226 template <typename T>
4227 struct S {
4228 void foo();
4229 };
4230 using U = S<int>;
4231 )";
4232 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4233 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4234 typedefNameDecl(hasName("U")));
4235 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4236
4237 // The "From" context has the same typedef, but the underlying type is
4238 // complete this time.
4239 Decl *FromTU = getTuDecl(std::string(Code) +
4240 R"(
4241 void foo(U* u) {
4242 u->foo();
4243 }
4244 )", Lang_CXX11);
4245 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4246 typedefNameDecl(hasName("U")));
4247 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4248
4249 // The imported type should be complete.
4250 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4251 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4252}
4253
Balazs Keri1efc9742019-05-07 10:55:11 +00004254TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) {
4255 auto Code =
4256 R"(
4257 template<class T>
4258 int f() { return 0; }
4259 template <> int f<int>() { return 4; }
4260 )";
4261
4262 Decl *FromTU = getTuDecl(Code, Lang_CXX);
4263 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU,
4264 functionDecl(hasName("f"), isExplicitTemplateSpecialization()));
Balazs Kerib7d8cff2019-05-07 14:53:04 +00004265 ASSERT_EQ(FromD->getNumTemplateParameterLists(), 1u);
Balazs Keri1efc9742019-05-07 10:55:11 +00004266
4267 auto *ToD = Import(FromD, Lang_CXX);
4268 // The template parameter list should exist.
Balazs Kerib7d8cff2019-05-07 14:53:04 +00004269 EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u);
Balazs Keri1efc9742019-05-07 10:55:11 +00004270}
4271
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004272struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton54058b52018-12-17 13:53:12 +00004273
4274TEST_P(ASTImporterLookupTableTest, OneDecl) {
4275 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
4276 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4277 ASTImporterLookupTable LT(*ToTU);
4278 auto Res = LT.lookup(ToTU, D->getDeclName());
4279 ASSERT_EQ(Res.size(), 1u);
4280 EXPECT_EQ(*Res.begin(), D);
4281}
4282
4283static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4284 for (Decl *D : DC->decls()) {
4285 if (auto *ND = dyn_cast<NamedDecl>(D))
4286 if (ND->getDeclName() == Name)
4287 return ND;
4288 }
4289 return nullptr;
Martin Storsjo85833392018-12-18 08:36:16 +00004290}
Gabor Marton54058b52018-12-17 13:53:12 +00004291
4292TEST_P(ASTImporterLookupTableTest,
4293 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4294 auto *Code = R"(
4295 template <class T>
4296 struct X {
4297 friend void foo(){}
4298 };
4299 )";
4300 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4301 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
4302 ToTU, classTemplateDecl(hasName("X")));
4303 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4304 ToTU, functionDecl(hasName("foo")));
4305 DeclContext *FooDC = Foo->getDeclContext();
4306 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4307 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
4308 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4309 DeclarationName FooName = Foo->getDeclName();
4310
4311 // Cannot find in the LookupTable of its DC (TUDecl)
4312 SmallVector<NamedDecl *, 2> FoundDecls;
4313 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4314 EXPECT_EQ(FoundDecls.size(), 0u);
4315
4316 // Cannot find in the LookupTable of its LexicalDC (X)
4317 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4318 EXPECT_EQ(FoundDecls.size(), 0u);
4319
4320 // Can't find in the list of Decls of the DC.
4321 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4322
4323 // Can't find in the list of Decls of the LexicalDC
4324 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
4325
4326 // ASTImporter specific lookup finds it.
4327 ASTImporterLookupTable LT(*ToTU);
4328 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4329 ASSERT_EQ(Res.size(), 1u);
4330 EXPECT_EQ(*Res.begin(), Foo);
4331}
4332
4333TEST_P(ASTImporterLookupTableTest,
4334 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
4335 TranslationUnitDecl *ToTU =
4336 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
4337 auto *Foo =
4338 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
4339 auto *A =
4340 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4341 DeclContext *FooDC = Foo->getDeclContext();
4342 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4343 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
4344 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4345 DeclarationName FooName = Foo->getDeclName();
4346
4347 // Cannot find in the LookupTable of its DC (TUDecl).
4348 SmallVector<NamedDecl *, 2> FoundDecls;
4349 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4350 EXPECT_EQ(FoundDecls.size(), 0u);
4351
4352 // Cannot find in the LookupTable of its LexicalDC (A).
4353 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4354 EXPECT_EQ(FoundDecls.size(), 0u);
4355
4356 // Can't find in the list of Decls of the DC.
4357 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4358
4359 // Can find in the list of Decls of the LexicalDC.
4360 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
4361
4362 // ASTImporter specific lookup finds it.
4363 ASTImporterLookupTable LT(*ToTU);
4364 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4365 ASSERT_EQ(Res.size(), 1u);
4366 EXPECT_EQ(*Res.begin(), Foo);
4367}
4368
4369TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
4370 TranslationUnitDecl *ToTU =
4371 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
4372 DeclarationName VName = FirstDeclMatcher<VarDecl>()
4373 .match(ToTU, varDecl(hasName("V")))
4374 ->getDeclName();
4375 auto *A =
4376 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4377 auto *B =
4378 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
4379
4380 ASTImporterLookupTable LT(*ToTU);
4381
4382 auto Res = LT.lookup(cast<DeclContext>(A), VName);
4383 ASSERT_EQ(Res.size(), 1u);
4384 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4385 ToTU, fieldDecl(hasName("V"),
4386 hasParent(recordDecl(hasName("A"))))));
4387 Res = LT.lookup(cast<DeclContext>(B), VName);
4388 ASSERT_EQ(Res.size(), 1u);
4389 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4390 ToTU, fieldDecl(hasName("V"),
4391 hasParent(recordDecl(hasName("B"))))));
4392 Res = LT.lookup(ToTU, VName);
4393 ASSERT_EQ(Res.size(), 1u);
4394 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
4395 ToTU, varDecl(hasName("V"),
4396 hasParent(translationUnitDecl()))));
4397}
4398
4399TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
4400 TranslationUnitDecl *ToTU = getToTuDecl(
4401 R"(
4402 void foo();
4403 void foo(int);
4404 void foo(int, int);
4405 )",
4406 Lang_CXX);
4407
4408 ASTImporterLookupTable LT(*ToTU);
4409 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4410 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4411 DeclarationName Name = F0->getDeclName();
4412 auto Res = LT.lookup(ToTU, Name);
4413 EXPECT_EQ(Res.size(), 3u);
4414 EXPECT_EQ(Res.count(F0), 1u);
4415 EXPECT_EQ(Res.count(F2), 1u);
4416}
4417
Gabor Martona9cab312019-02-08 09:19:34 +00004418TEST_P(ASTImporterLookupTableTest,
4419 DifferentOperatorsShouldHaveDifferentResultSet) {
4420 TranslationUnitDecl *ToTU = getToTuDecl(
4421 R"(
4422 struct X{};
4423 void operator+(X, X);
4424 void operator-(X, X);
4425 )",
4426 Lang_CXX);
4427
4428 ASTImporterLookupTable LT(*ToTU);
4429 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
4430 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4431 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
4432 ToTU, functionDecl(hasOverloadedOperatorName("-")));
4433 DeclarationName NamePlus = FPlus->getDeclName();
4434 auto ResPlus = LT.lookup(ToTU, NamePlus);
4435 EXPECT_EQ(ResPlus.size(), 1u);
4436 EXPECT_EQ(ResPlus.count(FPlus), 1u);
4437 EXPECT_EQ(ResPlus.count(FMinus), 0u);
4438 DeclarationName NameMinus = FMinus->getDeclName();
4439 auto ResMinus = LT.lookup(ToTU, NameMinus);
4440 EXPECT_EQ(ResMinus.size(), 1u);
4441 EXPECT_EQ(ResMinus.count(FMinus), 1u);
4442 EXPECT_EQ(ResMinus.count(FPlus), 0u);
4443 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
4444}
4445
4446TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
4447 TranslationUnitDecl *ToTU = getToTuDecl(
4448 R"(
4449 struct X {};
4450 void operator+(X, X);
4451 )",
4452 Lang_CXX);
4453 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
4454 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4455
4456 Decl *FromTU = getTuDecl(
4457 R"(
4458 struct X {};
4459 void operator+(X, X);
4460 )",
4461 Lang_CXX);
4462 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
4463 FromTU, functionDecl(hasOverloadedOperatorName("+")));
4464
4465 // FromPlus have a different TU, thus its DeclarationName is different too.
4466 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
4467
4468 ASTImporterLookupTable LT(*ToTU);
4469 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
4470 ASSERT_EQ(Res.size(), 1u);
4471 EXPECT_EQ(*Res.begin(), ToPlus);
4472
4473 // FromPlus have a different TU, thus its DeclarationName is different too.
4474 Res = LT.lookup(ToTU, FromPlus->getDeclName());
4475 ASSERT_EQ(Res.size(), 0u);
4476}
4477
Gabor Martondd2b76e2019-06-11 13:35:25 +00004478static const RecordDecl *getRecordDeclOfFriend(FriendDecl *FD) {
4479 QualType Ty = FD->getFriendType()->getType().getCanonicalType();
4480 return cast<RecordType>(Ty)->getDecl();
Gabor Marton54058b52018-12-17 13:53:12 +00004481}
4482
Gabor Martondd2b76e2019-06-11 13:35:25 +00004483TEST_P(ASTImporterLookupTableTest,
4484 LookupFindsFwdFriendClassDeclWithElaboratedType) {
Gabor Marton54058b52018-12-17 13:53:12 +00004485 TranslationUnitDecl *ToTU = getToTuDecl(
4486 R"(
4487 class Y { friend class F; };
4488 )",
4489 Lang_CXX);
4490
4491 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4492 // So we must dig up the underlying CXXRecordDecl.
4493 ASTImporterLookupTable LT(*ToTU);
4494 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4495 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4496 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
4497 ToTU, cxxRecordDecl(hasName("Y")));
4498
4499 DeclarationName Name = RD->getDeclName();
4500 auto Res = LT.lookup(ToTU, Name);
4501 EXPECT_EQ(Res.size(), 1u);
4502 EXPECT_EQ(*Res.begin(), RD);
4503
4504 Res = LT.lookup(Y, Name);
4505 EXPECT_EQ(Res.size(), 0u);
4506}
4507
Gabor Martondd2b76e2019-06-11 13:35:25 +00004508TEST_P(ASTImporterLookupTableTest,
4509 LookupFindsFwdFriendClassDeclWithUnelaboratedType) {
4510 TranslationUnitDecl *ToTU = getToTuDecl(
4511 R"(
4512 class F;
4513 class Y { friend F; };
4514 )",
4515 Lang_CXX11);
4516
4517 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4518 // So we must dig up the underlying CXXRecordDecl.
4519 ASTImporterLookupTable LT(*ToTU);
4520 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4521 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4522 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, cxxRecordDecl(hasName("Y")));
4523
4524 DeclarationName Name = RD->getDeclName();
4525 auto Res = LT.lookup(ToTU, Name);
4526 EXPECT_EQ(Res.size(), 1u);
4527 EXPECT_EQ(*Res.begin(), RD);
4528
4529 Res = LT.lookup(Y, Name);
4530 EXPECT_EQ(Res.size(), 0u);
4531}
4532
4533TEST_P(ASTImporterLookupTableTest,
4534 LookupFindsFriendClassDeclWithTypeAliasDoesNotAssert) {
4535 TranslationUnitDecl *ToTU = getToTuDecl(
4536 R"(
4537 class F;
4538 using alias_of_f = F;
4539 class Y { friend alias_of_f; };
4540 )",
4541 Lang_CXX11);
4542
4543 // ASTImporterLookupTable constructor handles using declarations correctly,
4544 // no assert is expected.
4545 ASTImporterLookupTable LT(*ToTU);
4546
4547 auto *Alias = FirstDeclMatcher<TypeAliasDecl>().match(
4548 ToTU, typeAliasDecl(hasName("alias_of_f")));
4549 DeclarationName Name = Alias->getDeclName();
4550 auto Res = LT.lookup(ToTU, Name);
4551 EXPECT_EQ(Res.count(Alias), 1u);
4552}
4553
Gabor Marton54058b52018-12-17 13:53:12 +00004554TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
4555 TranslationUnitDecl *ToTU = getToTuDecl(
4556 R"(
4557 class Y { template <class T> friend class F; };
4558 )",
4559 Lang_CXX);
4560
4561 ASTImporterLookupTable LT(*ToTU);
4562 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4563 ToTU, classTemplateDecl(hasName("F")));
4564 DeclarationName Name = F->getDeclName();
4565 auto Res = LT.lookup(ToTU, Name);
4566 EXPECT_EQ(Res.size(), 2u);
4567 EXPECT_EQ(Res.count(F), 1u);
4568 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4569}
4570
4571TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
4572 TranslationUnitDecl *ToTU = getToTuDecl(
4573 R"(
4574 template <typename T>
4575 class F;
4576
4577 template <typename T>
4578 class Y {
4579 friend class F<T>;
4580 };
4581 )",
4582 Lang_CXX);
4583
4584 ASTImporterLookupTable LT(*ToTU);
4585 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4586 ToTU, classTemplateDecl(hasName("F")));
4587 DeclarationName Name = F->getDeclName();
4588 auto Res = LT.lookup(ToTU, Name);
4589 EXPECT_EQ(Res.size(), 2u);
4590 EXPECT_EQ(Res.count(F), 1u);
4591 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4592}
4593
4594TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
4595 TranslationUnitDecl *ToTU = getToTuDecl(
4596 R"(
4597 template <typename T>
4598 class F;
4599
4600 class Y {
4601 friend class F<int>;
4602 };
4603 )",
4604 Lang_CXX);
4605
4606 ASTImporterLookupTable LT(*ToTU);
4607 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4608 ToTU, classTemplateDecl(hasName("F")));
4609 DeclarationName Name = F->getDeclName();
4610 auto Res = LT.lookup(ToTU, Name);
4611 ASSERT_EQ(Res.size(), 3u);
4612 EXPECT_EQ(Res.count(F), 1u);
4613 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4614 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
4615}
4616
4617TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
4618 TranslationUnitDecl *ToTU = getToTuDecl(
4619 R"(
4620 class Y { friend void F(); };
4621 )",
4622 Lang_CXX);
4623
4624 ASTImporterLookupTable LT(*ToTU);
4625 auto *F =
4626 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
4627 DeclarationName Name = F->getDeclName();
4628 auto Res = LT.lookup(ToTU, Name);
4629 EXPECT_EQ(Res.size(), 1u);
4630 EXPECT_EQ(*Res.begin(), F);
4631}
4632
4633TEST_P(ASTImporterLookupTableTest,
4634 LookupFindsDeclsInClassTemplateSpecialization) {
4635 TranslationUnitDecl *ToTU = getToTuDecl(
4636 R"(
4637 template <typename T>
4638 struct X {
4639 int F;
4640 };
4641 void foo() {
4642 X<char> xc;
4643 }
4644 )",
4645 Lang_CXX);
4646
4647 ASTImporterLookupTable LT(*ToTU);
4648
4649 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
4650 ToTU, classTemplateDecl(hasName("X")));
4651 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
4652 ToTU,
4653 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
4654
4655 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4656 ToTU, classTemplateSpecializationDecl(hasName("X")));
4657 FieldDecl *FieldInSpec = *Spec->field_begin();
4658 ASSERT_TRUE(FieldInSpec);
4659
4660 DeclarationName Name = FieldInSpec->getDeclName();
4661 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
4662
4663 SmallVector<NamedDecl *, 2> FoundDecls;
4664 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
4665 EXPECT_EQ(FoundDecls.size(), 1u);
4666 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
4667
4668 auto Res = LT.lookup(TemplateDC, Name);
4669 ASSERT_EQ(Res.size(), 1u);
4670 EXPECT_EQ(*Res.begin(), FieldInTemplate);
4671
4672 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
4673 FoundDecls);
4674 EXPECT_EQ(FoundDecls.size(), 1u);
4675 EXPECT_EQ(FoundDecls[0], FieldInSpec);
4676
4677 Res = LT.lookup(cast<DeclContext>(Spec), Name);
4678 ASSERT_EQ(Res.size(), 1u);
4679 EXPECT_EQ(*Res.begin(), FieldInSpec);
4680}
4681
4682TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
4683 TranslationUnitDecl *ToTU = getToTuDecl(
4684 R"(
4685 class Y { template <class T> friend void F(); };
4686 )",
4687 Lang_CXX);
4688
4689 ASTImporterLookupTable LT(*ToTU);
4690 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
4691 ToTU, functionTemplateDecl(hasName("F")));
4692 DeclarationName Name = F->getDeclName();
4693 auto Res = LT.lookup(ToTU, Name);
4694 EXPECT_EQ(Res.size(), 2u);
4695 EXPECT_EQ(Res.count(F), 1u);
4696 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4697}
4698
4699TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
4700 TranslationUnitDecl *ToTU = getToTuDecl(
4701 R"(
4702 struct X;
4703 struct A {
4704 friend struct X;
4705 };
4706 struct B {
4707 friend struct X;
4708 };
4709 )",
4710 Lang_CXX);
4711
4712 ASTImporterLookupTable LT(*ToTU);
4713 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
4714 ToTU, cxxRecordDecl(hasName("X")));
4715 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4716 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4717 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
4718 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
4719 ASSERT_EQ(RD0, RD1);
4720 ASSERT_EQ(RD1, X);
4721
4722 DeclarationName Name = X->getDeclName();
4723 auto Res = LT.lookup(ToTU, Name);
4724 EXPECT_EQ(Res.size(), 1u);
4725 EXPECT_EQ(*Res.begin(), X);
4726}
4727
4728TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
4729 TranslationUnitDecl *ToTU = getToTuDecl(
4730 R"(
4731 enum E {
4732 A,
4733 B
4734 };
4735 )",
4736 Lang_C);
4737
4738 ASTImporterLookupTable LT(*ToTU);
4739 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
4740 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
4741 ToTU, enumConstantDecl(hasName("A")));
4742
4743 DeclarationName Name = A->getDeclName();
4744 // Redecl context is the TU.
4745 ASSERT_EQ(E->getRedeclContext(), ToTU);
4746
4747 SmallVector<NamedDecl *, 2> FoundDecls;
4748 // Normal lookup finds in the DC.
4749 E->localUncachedLookup(Name, FoundDecls);
4750 EXPECT_EQ(FoundDecls.size(), 1u);
4751
4752 // Normal lookup finds in the Redecl context.
4753 ToTU->localUncachedLookup(Name, FoundDecls);
4754 EXPECT_EQ(FoundDecls.size(), 1u);
4755
4756 // Import specific lookup finds in the DC.
4757 auto Res = LT.lookup(E, Name);
4758 ASSERT_EQ(Res.size(), 1u);
4759 EXPECT_EQ(*Res.begin(), A);
4760
4761 // Import specific lookup finds in the Redecl context.
4762 Res = LT.lookup(ToTU, Name);
4763 ASSERT_EQ(Res.size(), 1u);
4764 EXPECT_EQ(*Res.begin(), A);
4765}
4766
4767TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
4768 TranslationUnitDecl *ToTU = getToTuDecl(
4769 R"(
4770 namespace N {
4771 int A;
4772 }
4773 namespace N {
4774 }
4775 )",
4776 Lang_CXX);
4777 auto *N1 =
4778 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
4779 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
4780 DeclarationName Name = A->getDeclName();
4781
4782 ASTImporterLookupTable LT(*ToTU);
4783 auto Res = LT.lookup(N1, Name);
4784 ASSERT_EQ(Res.size(), 1u);
4785 EXPECT_EQ(*Res.begin(), A);
4786}
4787
Gabor Marton0e04ebd2019-02-11 10:27:58 +00004788TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton305a11d2019-10-07 11:34:54 +00004789 RedeclChainShouldBeCorrectAmongstNamespaces) {
Gabor Marton0e04ebd2019-02-11 10:27:58 +00004790 Decl *FromTU = getTuDecl(
4791 R"(
4792 namespace NS {
4793 struct X;
4794 struct Y {
4795 static const int I = 3;
4796 };
4797 }
4798 namespace NS {
4799 struct X { // <--- To be imported
4800 void method(int i = Y::I) {}
4801 int f;
4802 };
4803 }
4804 )",
4805 Lang_CXX);
4806 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
4807 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
4808 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
4809 FromTU,
4810 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
4811 ASSERT_NE(FromFwd, FromDef);
4812 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
4813 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4814 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
4815
4816 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX));
4817 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX));
4818 EXPECT_NE(ToFwd, ToDef);
4819 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
4820 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4821 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
4822 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4823 // We expect no (ODR) warning during the import.
4824 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4825}
4826
Gabor Martone331e632019-02-18 13:09:27 +00004827struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
4828
4829TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
4830 Decl *ToTU = getToTuDecl(
4831 R"(
4832 class X {
4833 template <typename T> friend void foo();
4834 };
4835 )",
4836 Lang_CXX);
4837 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
4838 ToTU, functionTemplateDecl(hasName("foo")));
4839
4840 Decl *FromTU = getTuDecl(
4841 R"(
4842 template <typename T> void foo();
4843 )",
4844 Lang_CXX);
4845 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
4846 FromTU, functionTemplateDecl(hasName("foo")));
4847 auto *Imported = Import(FromFoo, Lang_CXX);
4848
Gabor Marton16d98c22019-03-07 13:01:51 +00004849 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
Gabor Martone331e632019-02-18 13:09:27 +00004850}
4851
Gabor Marton303c98612019-06-25 08:00:51 +00004852struct ASTImporterWithFakeErrors : ASTImporter {
4853 using ASTImporter::ASTImporter;
4854 bool returnWithErrorInTest() override { return true; }
4855};
4856
4857struct ErrorHandlingTest : ASTImporterOptionSpecificTestBase {
4858 ErrorHandlingTest() {
4859 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
4860 ASTContext &FromContext, FileManager &FromFileManager,
Gabor Marton2afbfb62019-07-01 15:37:07 +00004861 bool MinimalImport,
4862 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
Gabor Marton303c98612019-06-25 08:00:51 +00004863 return new ASTImporterWithFakeErrors(ToContext, ToFileManager,
4864 FromContext, FromFileManager,
Gabor Marton2afbfb62019-07-01 15:37:07 +00004865 MinimalImport, SharedState);
Gabor Marton303c98612019-06-25 08:00:51 +00004866 };
4867 }
4868 // In this test we purposely report an error (UnsupportedConstruct) when
4869 // importing the below stmt.
4870 static constexpr auto* ErroneousStmt = R"( asm(""); )";
4871};
4872
4873// Check a case when no new AST node is created in the AST before encountering
4874// the error.
4875TEST_P(ErrorHandlingTest, ErrorHappensBeforeCreatingANewNode) {
4876 TranslationUnitDecl *ToTU = getToTuDecl(
4877 R"(
4878 template <typename T>
4879 class X {};
4880 template <>
4881 class X<int> { int a; };
4882 )",
4883 Lang_CXX);
4884 TranslationUnitDecl *FromTU = getTuDecl(
4885 R"(
4886 template <typename T>
4887 class X {};
4888 template <>
4889 class X<int> { double b; };
4890 )",
4891 Lang_CXX);
4892 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4893 FromTU, classTemplateSpecializationDecl(hasName("X")));
4894 ClassTemplateSpecializationDecl *ImportedSpec = Import(FromSpec, Lang_CXX);
4895 EXPECT_FALSE(ImportedSpec);
4896
4897 // The original Decl is kept, no new decl is created.
4898 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(
4899 ToTU, classTemplateSpecializationDecl(hasName("X"))),
4900 1u);
4901
4902 // But an error is set to the counterpart in the "from" context.
4903 ASTImporter *Importer = findFromTU(FromSpec)->Importer.get();
4904 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromSpec);
4905 ASSERT_TRUE(OptErr);
4906 EXPECT_EQ(OptErr->Error, ImportError::NameConflict);
4907}
4908
4909// Check a case when a new AST node is created but not linked to the AST before
4910// encountering the error.
4911TEST_P(ErrorHandlingTest,
4912 ErrorHappensAfterCreatingTheNodeButBeforeLinkingThatToTheAST) {
4913 TranslationUnitDecl *FromTU = getTuDecl(
4914 std::string("void foo() { ") + ErroneousStmt + " }",
4915 Lang_CXX);
4916 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4917 FromTU, functionDecl(hasName("foo")));
4918
4919 FunctionDecl *ImportedFoo = Import(FromFoo, Lang_CXX);
4920 EXPECT_FALSE(ImportedFoo);
4921
4922 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4923 // Created, but not linked.
4924 EXPECT_EQ(
4925 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("foo"))),
4926 0u);
4927
4928 ASTImporter *Importer = findFromTU(FromFoo)->Importer.get();
4929 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFoo);
4930 ASSERT_TRUE(OptErr);
4931 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4932}
4933
4934// Check a case when a new AST node is created and linked to the AST before
4935// encountering the error. The error is set for the counterpart of the nodes in
4936// the "from" context.
4937TEST_P(ErrorHandlingTest, ErrorHappensAfterNodeIsCreatedAndLinked) {
4938 TranslationUnitDecl *FromTU = getTuDecl(
4939 std::string(R"(
4940 void f();
4941 void f() { )") + ErroneousStmt + R"( }
4942 )",
4943 Lang_CXX);
4944 auto *FromProto = FirstDeclMatcher<FunctionDecl>().match(
4945 FromTU, functionDecl(hasName("f")));
4946 auto *FromDef =
4947 LastDeclMatcher<FunctionDecl>().match(FromTU, functionDecl(hasName("f")));
4948 FunctionDecl *ImportedProto = Import(FromProto, Lang_CXX);
4949 EXPECT_FALSE(ImportedProto); // Could not import.
4950 // However, we created two nodes in the AST. 1) the fwd decl 2) the
4951 // definition. The definition is not added to its DC, but the fwd decl is
4952 // there.
4953 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4954 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
4955 1u);
4956 // Match the fwd decl.
4957 auto *ToProto =
4958 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("f")));
4959 EXPECT_TRUE(ToProto);
4960 // An error is set to the counterpart in the "from" context both for the fwd
4961 // decl and the definition.
4962 ASTImporter *Importer = findFromTU(FromProto)->Importer.get();
4963 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromProto);
4964 ASSERT_TRUE(OptErr);
4965 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4966 OptErr = Importer->getImportDeclErrorIfAny(FromDef);
4967 ASSERT_TRUE(OptErr);
4968 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4969}
4970
Gabor Marton17c3eaf2019-07-01 12:44:39 +00004971// An error should be set for a class if we cannot import one member.
4972TEST_P(ErrorHandlingTest, ErrorIsPropagatedFromMemberToClass) {
4973 TranslationUnitDecl *FromTU = getTuDecl(
4974 std::string(R"(
4975 class X {
4976 void f() { )") + ErroneousStmt + R"( } // This member has the error
4977 // during import.
4978 void ok(); // The error should not prevent importing this.
4979 }; // An error will be set for X too.
4980 )",
4981 Lang_CXX);
4982 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
4983 FromTU, cxxRecordDecl(hasName("X")));
4984 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX);
4985
4986 // An error is set for X.
4987 EXPECT_FALSE(ImportedX);
4988 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
4989 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
4990 ASSERT_TRUE(OptErr);
4991 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4992
4993 // An error is set for f().
4994 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
4995 FromTU, cxxMethodDecl(hasName("f")));
4996 OptErr = Importer->getImportDeclErrorIfAny(FromF);
4997 ASSERT_TRUE(OptErr);
4998 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4999 // And any subsequent import should fail.
5000 CXXMethodDecl *ImportedF = Import(FromF, Lang_CXX);
5001 EXPECT_FALSE(ImportedF);
5002
Gabor Marton1ad4b992019-07-01 14:19:53 +00005003 // There is an error set for the other member too.
Gabor Marton17c3eaf2019-07-01 12:44:39 +00005004 auto *FromOK = FirstDeclMatcher<CXXMethodDecl>().match(
5005 FromTU, cxxMethodDecl(hasName("ok")));
5006 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
Gabor Marton1ad4b992019-07-01 14:19:53 +00005007 EXPECT_TRUE(OptErr);
5008 // Cannot import the other member.
Gabor Marton17c3eaf2019-07-01 12:44:39 +00005009 CXXMethodDecl *ImportedOK = Import(FromOK, Lang_CXX);
Gabor Marton1ad4b992019-07-01 14:19:53 +00005010 EXPECT_FALSE(ImportedOK);
5011}
Gabor Marton17c3eaf2019-07-01 12:44:39 +00005012
Gabor Marton1ad4b992019-07-01 14:19:53 +00005013// Check that an error propagates to the dependent AST nodes.
5014// In the below code it means that an error in X should propagate to A.
5015// And even to F since the containing A is erroneous.
5016// And to all AST nodes which we visit during the import process which finally
5017// ends up in a failure (in the error() function).
5018TEST_P(ErrorHandlingTest, ErrorPropagatesThroughImportCycles) {
5019 Decl *FromTU = getTuDecl(
5020 std::string(R"(
5021 namespace NS {
5022 class A {
5023 template <int I> class F {};
5024 class X {
5025 template <int I> friend class F;
5026 void error() { )") + ErroneousStmt + R"( }
5027 };
5028 };
5029
5030 class B {};
5031 } // NS
5032 )",
5033 Lang_CXX, "input0.cc");
5034
5035 auto *FromFRD = FirstDeclMatcher<CXXRecordDecl>().match(
5036 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
5037 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
5038 FromTU, cxxRecordDecl(hasName("A"), isDefinition()));
5039 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(
5040 FromTU, cxxRecordDecl(hasName("B"), isDefinition()));
5041 auto *FromNS = FirstDeclMatcher<NamespaceDecl>().match(
5042 FromTU, namespaceDecl(hasName("NS")));
5043
5044 // Start by importing the templated CXXRecordDecl of F.
5045 // Import fails for that.
5046 EXPECT_FALSE(Import(FromFRD, Lang_CXX));
5047 // Import fails for A.
5048 EXPECT_FALSE(Import(FromA, Lang_CXX));
5049 // But we should be able to import the independent B.
5050 EXPECT_TRUE(Import(FromB, Lang_CXX));
5051 // And the namespace.
5052 EXPECT_TRUE(Import(FromNS, Lang_CXX));
5053
5054 // An error is set to the templated CXXRecordDecl of F.
5055 ASTImporter *Importer = findFromTU(FromFRD)->Importer.get();
5056 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFRD);
5057 EXPECT_TRUE(OptErr);
5058
5059 // An error is set to A.
5060 OptErr = Importer->getImportDeclErrorIfAny(FromA);
5061 EXPECT_TRUE(OptErr);
5062
5063 // There is no error set to B.
5064 OptErr = Importer->getImportDeclErrorIfAny(FromB);
5065 EXPECT_FALSE(OptErr);
5066
5067 // There is no error set to NS.
5068 OptErr = Importer->getImportDeclErrorIfAny(FromNS);
5069 EXPECT_FALSE(OptErr);
5070
5071 // Check some of those decls whose ancestor is X, they all should have an
5072 // error set if we visited them during an import process which finally failed.
5073 // These decls are part of a cycle in an ImportPath.
5074 // There would not be any error set for these decls if we hadn't follow the
5075 // ImportPaths and the cycles.
5076 OptErr = Importer->getImportDeclErrorIfAny(
5077 FirstDeclMatcher<ClassTemplateDecl>().match(
5078 FromTU, classTemplateDecl(hasName("F"))));
5079 // An error is set to the 'F' ClassTemplateDecl.
5080 EXPECT_TRUE(OptErr);
5081 // An error is set to the FriendDecl.
5082 OptErr = Importer->getImportDeclErrorIfAny(
5083 FirstDeclMatcher<FriendDecl>().match(
5084 FromTU, friendDecl()));
5085 EXPECT_TRUE(OptErr);
5086 // An error is set to the implicit class of A.
5087 OptErr =
5088 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
5089 FromTU, cxxRecordDecl(hasName("A"), isImplicit())));
5090 EXPECT_TRUE(OptErr);
5091 // An error is set to the implicit class of X.
5092 OptErr =
5093 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
5094 FromTU, cxxRecordDecl(hasName("X"), isImplicit())));
5095 EXPECT_TRUE(OptErr);
Gabor Marton17c3eaf2019-07-01 12:44:39 +00005096}
5097
5098TEST_P(ErrorHandlingTest, ErrorIsNotPropagatedFromMemberToNamespace) {
5099 TranslationUnitDecl *FromTU = getTuDecl(
5100 std::string(R"(
5101 namespace X {
5102 void f() { )") + ErroneousStmt + R"( } // This member has the error
5103 // during import.
5104 void ok(); // The error should not prevent importing this.
5105 }; // An error will be set for X too.
5106 )",
5107 Lang_CXX);
5108 auto *FromX = FirstDeclMatcher<NamespaceDecl>().match(
5109 FromTU, namespaceDecl(hasName("X")));
5110 NamespaceDecl *ImportedX = Import(FromX, Lang_CXX);
5111
5112 // There is no error set for X.
5113 EXPECT_TRUE(ImportedX);
5114 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5115 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5116 ASSERT_FALSE(OptErr);
5117
5118 // An error is set for f().
5119 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
5120 FromTU, functionDecl(hasName("f")));
5121 OptErr = Importer->getImportDeclErrorIfAny(FromF);
5122 ASSERT_TRUE(OptErr);
5123 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5124 // And any subsequent import should fail.
5125 FunctionDecl *ImportedF = Import(FromF, Lang_CXX);
5126 EXPECT_FALSE(ImportedF);
5127
5128 // There is no error set for ok().
5129 auto *FromOK = FirstDeclMatcher<FunctionDecl>().match(
5130 FromTU, functionDecl(hasName("ok")));
5131 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
5132 EXPECT_FALSE(OptErr);
5133 // And we should be able to import.
5134 FunctionDecl *ImportedOK = Import(FromOK, Lang_CXX);
5135 EXPECT_TRUE(ImportedOK);
5136}
5137
Gabor Marton2afbfb62019-07-01 15:37:07 +00005138// An error should be set for a class if it had a previous import with an error
5139// from another TU.
5140TEST_P(ErrorHandlingTest,
5141 ImportedDeclWithErrorShouldFailTheImportOfDeclWhichMapToIt) {
5142 // We already have a fwd decl.
5143 TranslationUnitDecl *ToTU = getToTuDecl(
5144 "class X;", Lang_CXX);
5145 // Then we import a definition.
5146 {
5147 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5148 class X {
5149 void f() { )") + ErroneousStmt + R"( }
5150 void ok();
5151 };
5152 )",
5153 Lang_CXX);
5154 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5155 FromTU, cxxRecordDecl(hasName("X")));
5156 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX);
5157
5158 // An error is set for X ...
5159 EXPECT_FALSE(ImportedX);
5160 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5161 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5162 ASSERT_TRUE(OptErr);
5163 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5164 }
5165 // ... but the node had been created.
5166 auto *ToXDef = FirstDeclMatcher<CXXRecordDecl>().match(
5167 ToTU, cxxRecordDecl(hasName("X"), isDefinition()));
5168 // An error is set for "ToXDef" in the shared state.
5169 Optional<ImportError> OptErr =
5170 SharedStatePtr->getImportDeclErrorIfAny(ToXDef);
5171 ASSERT_TRUE(OptErr);
5172 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5173
5174 auto *ToXFwd = FirstDeclMatcher<CXXRecordDecl>().match(
5175 ToTU, cxxRecordDecl(hasName("X"), unless(isDefinition())));
5176 // An error is NOT set for the fwd Decl of X in the shared state.
5177 OptErr = SharedStatePtr->getImportDeclErrorIfAny(ToXFwd);
5178 ASSERT_FALSE(OptErr);
5179
5180 // Try to import X again but from another TU.
5181 {
5182 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5183 class X {
5184 void f() { )") + ErroneousStmt + R"( }
5185 void ok();
5186 };
5187 )",
5188 Lang_CXX, "input1.cc");
5189
5190 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5191 FromTU, cxxRecordDecl(hasName("X")));
5192 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX);
5193
5194 // If we did not save the errors for the "to" context then the below checks
5195 // would fail, because the lookup finds the fwd Decl of the existing
5196 // definition in the "to" context. We can reach the existing definition via
5197 // the found fwd Decl. That existing definition is structurally equivalent
5198 // (we check only the fields) with this one we want to import, so we return
5199 // with the existing definition, which is erroneous (one method is missing).
5200
5201 // The import should fail.
5202 EXPECT_FALSE(ImportedX);
5203 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5204 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5205 // And an error is set for this new X in the "from" ctx.
5206 ASSERT_TRUE(OptErr);
5207 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5208 }
5209}
5210
Balazs Kerib4fd7d42019-08-30 10:12:14 +00005211TEST_P(ErrorHandlingTest, ImportOfOverriddenMethods) {
5212 auto MatchFooA =
5213 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("A"))));
5214 auto MatchFooB =
5215 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("B"))));
5216 auto MatchFooC =
5217 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("C"))));
5218
5219 // Provoke import of a method that has overridden methods with import error.
5220 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5221 struct C;
5222 struct A {
5223 virtual void foo();
5224 void f1(C *);
5225 };
5226 void A::foo() {
5227 )") + ErroneousStmt + R"(
5228 }
5229 struct B : public A {
5230 void foo() override;
5231 };
5232 struct C : public B {
5233 void foo() override;
5234 };
5235 )",
5236 Lang_CXX11);
5237 auto *FromFooA = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooA);
5238 auto *FromFooB = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooB);
5239 auto *FromFooC = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooC);
5240
5241 EXPECT_FALSE(Import(FromFooA, Lang_CXX11));
5242 ASTImporter *Importer = findFromTU(FromFooA)->Importer.get();
5243 auto CheckError = [&Importer](Decl *FromD) {
5244 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromD);
5245 ASSERT_TRUE(OptErr);
5246 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5247 };
5248 CheckError(FromFooA);
5249 EXPECT_FALSE(Import(FromFooB, Lang_CXX11));
5250 CheckError(FromFooB);
5251 EXPECT_FALSE(Import(FromFooC, Lang_CXX11));
5252 CheckError(FromFooC);
5253}
5254
Gabor Martone73805f2019-07-08 12:49:13 +00005255TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) {
5256 Decl *FromTU = getTuDecl(
5257 R"(
5258 void f() {
5259 auto L = [](){};
5260 }
5261 )",
5262 Lang_CXX11, "input0.cc");
5263 auto Pattern = lambdaExpr();
5264 CXXRecordDecl *FromL =
5265 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5266
5267 auto ToL = Import(FromL, Lang_CXX11);
5268 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
5269 unsigned FromLSize =
5270 std::distance(FromL->decls().begin(), FromL->decls().end());
5271 EXPECT_NE(ToLSize, 0u);
5272 EXPECT_EQ(ToLSize, FromLSize);
5273}
5274
5275TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
5276 Decl *FromTU = getTuDecl(
5277 R"(
5278 template <typename F>
5279 void f(F L = [](){}) {}
5280 )",
5281 Lang_CXX11, "input0.cc");
5282 auto Pattern = lambdaExpr();
5283 CXXRecordDecl *FromL =
5284 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5285
5286 auto ToL = Import(FromL, Lang_CXX11);
5287 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
5288 unsigned FromLSize =
5289 std::distance(FromL->decls().begin(), FromL->decls().end());
5290 EXPECT_NE(ToLSize, 0u);
5291 EXPECT_EQ(ToLSize, FromLSize);
5292}
5293
Gabor Martonae512b82019-07-17 14:40:09 +00005294TEST_P(ASTImporterOptionSpecificTestBase, LambdaInGlobalScope) {
5295 Decl *FromTU = getTuDecl(
5296 R"(
5297 auto l1 = [](unsigned lp) { return 1; };
5298 auto l2 = [](int lp) { return 2; };
5299 int f(int p) {
5300 return l1(p) + l2(p);
5301 }
5302 )",
5303 Lang_CXX11, "input0.cc");
5304 FunctionDecl *FromF = FirstDeclMatcher<FunctionDecl>().match(
5305 FromTU, functionDecl(hasName("f")));
5306 FunctionDecl *ToF = Import(FromF, Lang_CXX11);
5307 EXPECT_TRUE(ToF);
5308}
5309
Balazs Keri2e160602019-08-12 10:07:38 +00005310TEST_P(ASTImporterOptionSpecificTestBase,
5311 ImportExistingFriendClassTemplateDef) {
5312 auto Code =
5313 R"(
5314 template <class T1, class T2>
5315 struct Base {
5316 template <class U1, class U2>
5317 friend struct Class;
5318 };
5319 template <class T1, class T2>
5320 struct Class { };
5321 )";
5322
5323 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
5324 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
5325
5326 auto *ToClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
5327 ToTU, classTemplateDecl(hasName("Class")));
5328 auto *ToClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
5329 ToTU, classTemplateDecl(hasName("Class")));
5330 ASSERT_FALSE(ToClassProto->isThisDeclarationADefinition());
5331 ASSERT_TRUE(ToClassDef->isThisDeclarationADefinition());
5332 // Previous friend decl is not linked to it!
5333 ASSERT_FALSE(ToClassDef->getPreviousDecl());
5334 ASSERT_EQ(ToClassDef->getMostRecentDecl(), ToClassDef);
5335 ASSERT_EQ(ToClassProto->getMostRecentDecl(), ToClassProto);
5336
5337 auto *FromClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
5338 FromTU, classTemplateDecl(hasName("Class")));
5339 auto *FromClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
5340 FromTU, classTemplateDecl(hasName("Class")));
5341 ASSERT_FALSE(FromClassProto->isThisDeclarationADefinition());
5342 ASSERT_TRUE(FromClassDef->isThisDeclarationADefinition());
5343 ASSERT_FALSE(FromClassDef->getPreviousDecl());
5344 ASSERT_EQ(FromClassDef->getMostRecentDecl(), FromClassDef);
5345 ASSERT_EQ(FromClassProto->getMostRecentDecl(), FromClassProto);
5346
5347 auto *ImportedDef = Import(FromClassDef, Lang_CXX);
5348 // At import we should find the definition for 'Class' even if the
5349 // prototype (inside 'friend') for it comes first in the AST and is not
5350 // linked to the definition.
5351 EXPECT_EQ(ImportedDef, ToClassDef);
Gabor Martonf035b752019-08-27 11:36:10 +00005352}
5353
Gabor Martonaefcf512019-07-17 13:47:46 +00005354struct LLDBLookupTest : ASTImporterOptionSpecificTestBase {
5355 LLDBLookupTest() {
5356 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
5357 ASTContext &FromContext, FileManager &FromFileManager,
5358 bool MinimalImport,
5359 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
5360 return new ASTImporter(ToContext, ToFileManager, FromContext,
5361 FromFileManager, MinimalImport,
5362 // We use the regular lookup.
5363 /*SharedState=*/nullptr);
5364 };
5365 }
5366};
5367
5368TEST_P(LLDBLookupTest, ImporterShouldFindInTransparentContext) {
5369 TranslationUnitDecl *ToTU = getToTuDecl(
5370 R"(
5371 extern "C" {
5372 class X{};
5373 };
5374 )",
5375 Lang_CXX);
5376 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(
5377 ToTU, cxxRecordDecl(hasName("X")));
5378
5379 // Set up a stub external storage.
5380 ToTU->setHasExternalLexicalStorage(true);
5381 // Set up DeclContextBits.HasLazyExternalLexicalLookups to true.
5382 ToTU->setMustBuildLookupTable();
5383 struct TestExternalASTSource : ExternalASTSource {};
5384 ToTU->getASTContext().setExternalSource(new TestExternalASTSource());
5385
5386 Decl *FromTU = getTuDecl(
5387 R"(
5388 class X;
5389 )",
5390 Lang_CXX);
5391 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5392 FromTU, cxxRecordDecl(hasName("X")));
5393 auto *ImportedX = Import(FromX, Lang_CXX);
5394 // The lookup must find the existing class definition in the LinkageSpecDecl.
5395 // Then the importer renders the existing and the new decl into one chain.
5396 EXPECT_EQ(ImportedX->getCanonicalDecl(), ToX->getCanonicalDecl());
5397}
5398
Richard Sandifordeb485fb2019-08-09 08:52:54 +00005399struct SVEBuiltins : ASTImporterOptionSpecificTestBase {};
5400
5401TEST_P(SVEBuiltins, ImportTypes) {
5402 static const char *const TypeNames[] = {
5403 "__SVInt8_t",
5404 "__SVInt16_t",
5405 "__SVInt32_t",
5406 "__SVInt64_t",
5407 "__SVUint8_t",
5408 "__SVUint16_t",
5409 "__SVUint32_t",
5410 "__SVUint64_t",
5411 "__SVFloat16_t",
5412 "__SVFloat32_t",
5413 "__SVFloat64_t",
5414 "__SVBool_t"
5415 };
5416
5417 TranslationUnitDecl *ToTU = getToTuDecl("", Lang_CXX);
5418 TranslationUnitDecl *FromTU = getTuDecl("", Lang_CXX, "input.cc");
5419 for (auto *TypeName : TypeNames) {
5420 auto *ToTypedef = FirstDeclMatcher<TypedefDecl>().match(
5421 ToTU, typedefDecl(hasName(TypeName)));
5422 QualType ToType = ToTypedef->getUnderlyingType();
5423
5424 auto *FromTypedef = FirstDeclMatcher<TypedefDecl>().match(
5425 FromTU, typedefDecl(hasName(TypeName)));
5426 QualType FromType = FromTypedef->getUnderlyingType();
5427
5428 QualType ImportedType = ImportType(FromType, FromTypedef, Lang_CXX);
5429 EXPECT_EQ(ImportedType, ToType);
5430 }
5431}
5432
Balazs Kerib427c062019-08-13 08:04:06 +00005433TEST_P(ASTImporterOptionSpecificTestBase, ImportOfDefaultImplicitFunctions) {
5434 // Test that import of implicit functions works and the functions
5435 // are merged into one chain.
5436 auto GetDeclToImport = [this](StringRef File) {
5437 Decl *FromTU = getTuDecl(
5438 R"(
5439 struct X { };
5440 // Force generating some implicit operator definitions for X.
5441 void f() { X x1, x2; x1 = x2; X *x3 = new X; delete x3; }
5442 )",
5443 Lang_CXX11, File);
5444 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
5445 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
5446 // Destructor is picked as one example of implicit function.
5447 return FromD->getDestructor();
5448 };
5449
5450 auto *ToD1 = Import(GetDeclToImport("input1.cc"), Lang_CXX11);
5451 ASSERT_TRUE(ToD1);
5452
5453 auto *ToD2 = Import(GetDeclToImport("input2.cc"), Lang_CXX11);
5454 ASSERT_TRUE(ToD2);
5455
5456 EXPECT_EQ(ToD1->getCanonicalDecl(), ToD2->getCanonicalDecl());
5457}
5458
5459TEST_P(ASTImporterOptionSpecificTestBase,
5460 ImportOfExplicitlyDefaultedOrDeleted) {
5461 Decl *FromTU = getTuDecl(
5462 R"(
5463 struct X { X() = default; X(const X&) = delete; };
5464 )",
5465 Lang_CXX11);
5466 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5467 FromTU, cxxRecordDecl(hasName("X")));
5468 auto *ImportedX = Import(FromX, Lang_CXX11);
5469 auto *Constr1 = FirstDeclMatcher<CXXConstructorDecl>().match(
5470 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));
5471 auto *Constr2 = LastDeclMatcher<CXXConstructorDecl>().match(
5472 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));
5473
5474 ASSERT_TRUE(ImportedX);
5475 EXPECT_TRUE(Constr1->isDefaulted());
5476 EXPECT_TRUE(Constr1->isExplicitlyDefaulted());
5477 EXPECT_TRUE(Constr2->isDeletedAsWritten());
5478 EXPECT_EQ(ImportedX->isAggregate(), FromX->isAggregate());
5479}
5480
Richard Sandifordeb485fb2019-08-09 08:52:54 +00005481INSTANTIATE_TEST_CASE_P(ParameterizedTests, SVEBuiltins,
5482 ::testing::Values(ArgVector{"-target",
5483 "aarch64-linux-gnu"}), );
5484
Gabor Martonf035b752019-08-27 11:36:10 +00005485INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
5486 ::testing::Values(ArgVector()), );
5487
5488INSTANTIATE_TEST_CASE_P(ParameterizedTests, CanonicalRedeclChain,
5489 ::testing::Values(ArgVector()), );
5490
Gabor Martone3e83d72019-08-30 10:55:41 +00005491TEST_P(ASTImporterOptionSpecificTestBase, LambdasAreDifferentiated) {
5492 Decl *FromTU = getTuDecl(
5493 R"(
5494 void f() {
5495 auto L0 = [](){};
5496 auto L1 = [](){};
5497 }
5498 )",
5499 Lang_CXX11, "input0.cc");
5500 auto Pattern = lambdaExpr();
5501 CXXRecordDecl *FromL0 =
5502 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5503 CXXRecordDecl *FromL1 =
5504 LastDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5505 ASSERT_NE(FromL0, FromL1);
5506
5507 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
5508 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
5509 EXPECT_NE(ToL0, ToL1);
5510}
5511
5512TEST_P(ASTImporterOptionSpecificTestBase,
5513 LambdasInFunctionParamsAreDifferentiated) {
5514 Decl *FromTU = getTuDecl(
5515 R"(
5516 template <typename F0, typename F1>
5517 void f(F0 L0 = [](){}, F1 L1 = [](){}) {}
5518 )",
5519 Lang_CXX11, "input0.cc");
5520 auto Pattern = cxxRecordDecl(isLambda());
5521 CXXRecordDecl *FromL0 =
5522 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5523 CXXRecordDecl *FromL1 =
5524 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5525 ASSERT_NE(FromL0, FromL1);
5526
5527 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
5528 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
5529 ASSERT_NE(ToL0, ToL1);
5530}
5531
5532TEST_P(ASTImporterOptionSpecificTestBase,
5533 LambdasInFunctionParamsAreDifferentiatedWhenMacroIsUsed) {
5534 Decl *FromTU = getTuDecl(
5535 R"(
5536 #define LAMBDA [](){}
5537 template <typename F0, typename F1>
5538 void f(F0 L0 = LAMBDA, F1 L1 = LAMBDA) {}
5539 )",
5540 Lang_CXX11, "input0.cc");
5541 auto Pattern = cxxRecordDecl(isLambda());
5542 CXXRecordDecl *FromL0 =
5543 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5544 CXXRecordDecl *FromL1 =
5545 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5546 ASSERT_NE(FromL0, FromL1);
5547
5548 Import(FromL0, Lang_CXX11);
5549 Import(FromL1, Lang_CXX11);
5550 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
5551 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
5552 ASSERT_NE(ToL0, ToL1);
5553}
5554
5555TEST_P(ASTImporterOptionSpecificTestBase, ImportAssignedLambda) {
5556 Decl *FromTU = getTuDecl(
5557 R"(
5558 void f() {
5559 auto x = []{} = {}; auto x2 = x;
5560 }
5561 )",
5562 Lang_CXX2a, "input0.cc");
5563 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
5564 FromTU, functionDecl(hasName("f")));
5565 // We have only one lambda class.
5566 ASSERT_EQ(
5567 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
5568 1u);
5569
5570 FunctionDecl *ToF = Import(FromF, Lang_CXX2a);
5571 EXPECT_TRUE(ToF);
5572 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5573 // We have only one lambda class after the import.
5574 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
5575 1u);
5576}
5577
5578TEST_P(ASTImporterOptionSpecificTestBase, ImportDefaultConstructibleLambdas) {
5579 Decl *FromTU = getTuDecl(
5580 R"(
5581 void f() {
5582 auto x = []{} = {};
5583 auto xb = []{} = {};
5584 }
5585 )",
5586 Lang_CXX2a, "input0.cc");
5587 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
5588 FromTU, functionDecl(hasName("f")));
5589 // We have two lambda classes.
5590 ASSERT_EQ(
5591 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
5592 2u);
5593
5594 FunctionDecl *ToF = Import(FromF, Lang_CXX2a);
5595 EXPECT_TRUE(ToF);
5596 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5597 // We have two lambda classes after the import.
5598 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
5599 2u);
5600}
5601
Gabor Marton54058b52018-12-17 13:53:12 +00005602INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
5603 DefaultTestValuesForRunOptions, );
5604
Gabor Marton1ad4b992019-07-01 14:19:53 +00005605INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportPath,
5606 ::testing::Values(ArgVector()), );
5607
Gabor Marton19f4f392018-06-25 13:04:37 +00005608INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
5609 DefaultTestValuesForRunOptions, );
5610
5611INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
5612 DefaultTestValuesForRunOptions, );
5613
5614INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
5615 DefaultTestValuesForRunOptions, );
5616
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005617INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
Gabor Marton19f4f392018-06-25 13:04:37 +00005618 DefaultTestValuesForRunOptions, );
5619
Gabor Martonf035b752019-08-27 11:36:10 +00005620INSTANTIATE_TEST_CASE_P(ParameterizedTests, ErrorHandlingTest,
5621 DefaultTestValuesForRunOptions, );
5622
Raphael Isemanne9bc35f2019-04-29 21:02:35 +00005623INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedirectingImporterTest,
5624 DefaultTestValuesForRunOptions, );
5625
Gabor Marton19f4f392018-06-25 13:04:37 +00005626INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
5627 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00005628
Gabor Martonf035b752019-08-27 11:36:10 +00005629INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionTemplates,
5630 DefaultTestValuesForRunOptions, );
5631
Gabor Martone331e632019-02-18 13:09:27 +00005632INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
5633 DefaultTestValuesForRunOptions, );
5634
Gabor Marton54058b52018-12-17 13:53:12 +00005635INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00005636 DefaultTestValuesForRunOptions, );
5637
Gabor Marton54058b52018-12-17 13:53:12 +00005638INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00005639 DefaultTestValuesForRunOptions, );
5640
Gabor Marton7df342a2018-12-17 12:42:12 +00005641INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
5642 DefaultTestValuesForRunOptions, );
5643
Gabor Marton5254e642018-06-27 13:32:50 +00005644INSTANTIATE_TEST_CASE_P(ParameterizedTests,
5645 ImportFunctionTemplateSpecializations,
5646 DefaultTestValuesForRunOptions, );
5647
Gabor Martonac3a5d62018-09-17 12:04:52 +00005648INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
5649 DefaultTestValuesForRunOptions, );
5650
5651INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
5652 DefaultTestValuesForRunOptions, );
5653
Gabor Martonaefcf512019-07-17 13:47:46 +00005654INSTANTIATE_TEST_CASE_P(ParameterizedTests, LLDBLookupTest,
5655 DefaultTestValuesForRunOptions, );
5656
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00005657} // end namespace ast_matchers
5658} // end namespace clang