blob: 78b67d836b9cd0c14f50188d3d8cf8a42bbb2269 [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;
1424 for (FieldDecl *Field : Node.fields()) {
1425 if (Index == Order.size())
1426 return false;
1427 if (Field->getName() != Order[Index])
1428 return false;
1429 ++Index;
1430 }
1431 return Index == Order.size();
1432}
1433
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001434TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001435 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1436 Decl *From, *To;
1437 std::tie(From, To) = getImportedDecl(
1438 R"(
1439 namespace NS {
1440 template<class T>
1441 class X {};
1442 template class X<int>;
1443 }
1444 )",
1445 Lang_CXX, "", Lang_CXX, "NS");
1446
1447 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1448 // ClassTemplateDecl.
1449 auto Pattern = namespaceDecl(has(classTemplateDecl(
1450 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1451 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1452 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1453
1454 // Check that the ClassTemplateSpecializationDecl is the child of the
1455 // NamespaceDecl.
1456 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1457 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1458 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1459}
1460
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001461TEST_P(ASTImporterOptionSpecificTestBase,
1462 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001463 Decl *From, *To;
1464 std::tie(From, To) =
1465 getImportedDecl(
1466 "struct declToImport { int a; int b; };",
1467 Lang_CXX11, "", Lang_CXX11);
1468
1469 MatchVerifier<Decl> Verifier;
1470 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1471 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1472}
1473
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001474TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton48b16e12019-07-25 09:07:17 +00001475 CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001476 Decl *From, *To;
1477 std::tie(From, To) = getImportedDecl(
1478 // The original recursive algorithm of ASTImporter first imports 'c' then
1479 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1480 R"s(
1481 struct declToImport {
1482 int a = c + b;
1483 int b = 1;
1484 int c = 2;
1485 };
1486 )s",
1487 Lang_CXX11, "", Lang_CXX11);
1488
1489 MatchVerifier<Decl> Verifier;
1490 ASSERT_TRUE(
1491 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1492 EXPECT_TRUE(
1493 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1494}
1495
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001496TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001497 Decl *From, *To;
1498 std::tie(From, To) = getImportedDecl(
1499 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001500 struct declToImport {
1501 };
1502 )",
1503 Lang_CXX, "", Lang_CXX);
1504
1505 MatchVerifier<Decl> Verifier;
1506 // Match the implicit Decl.
1507 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1508 ASSERT_TRUE(Verifier.match(From, Matcher));
1509 EXPECT_TRUE(Verifier.match(To, Matcher));
1510}
1511
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001512TEST_P(ASTImporterOptionSpecificTestBase,
1513 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
Gabor Martona3af5672018-05-23 14:24:02 +00001514 Decl *From, *To;
1515 std::tie(From, To) = getImportedDecl(
1516 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001517 template <typename U>
1518 struct declToImport {
1519 };
1520 )",
1521 Lang_CXX, "", Lang_CXX);
1522
1523 MatchVerifier<Decl> Verifier;
1524 // Match the implicit Decl.
1525 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1526 ASSERT_TRUE(Verifier.match(From, Matcher));
1527 EXPECT_TRUE(Verifier.match(To, Matcher));
1528}
1529
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001530TEST_P(ASTImporterOptionSpecificTestBase,
1531 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001532 Decl *From, *To;
1533 std::tie(From, To) = getImportedDecl(
1534 R"(
1535 template<class T>
1536 class Base {};
1537 class declToImport : public Base<declToImport> {};
1538 )",
1539 Lang_CXX, "", Lang_CXX);
1540
1541 auto hasImplicitClass = has(cxxRecordDecl());
1542 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1543 hasName("Base"),
1544 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1545 ASSERT_TRUE(
1546 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1547 EXPECT_TRUE(
1548 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1549}
1550
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001551TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001552 Decl *From, *To;
1553 std::tie(From, To) =
1554 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1555
1556 MatchVerifier<Decl> Verifier;
1557 auto Matcher = functionDecl();
1558 ASSERT_TRUE(Verifier.match(From, Matcher));
1559 EXPECT_TRUE(Verifier.match(To, Matcher));
1560 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1561}
1562
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001563TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001564 Decl *FromTU = getTuDecl(
1565 R"(
1566 struct X {};
1567 void operator<<(int, X);
1568 )",
1569 Lang_CXX);
1570 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1571 const Decl *To = Import(From, Lang_CXX);
1572 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1573}
1574
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001575TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001576 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1577 Decl *From, *To;
1578 std::tie(From, To) = getImportedDecl(
1579 R"(
1580 template<class T>
1581 class Base { int a; };
1582 class declToImport : Base<declToImport> {};
1583 )",
1584 Lang_CXX, "", Lang_CXX);
1585
1586 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1587 hasName("Base"),
1588 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1589 ASSERT_TRUE(
1590 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1591 EXPECT_TRUE(
1592 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1593}
1594
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001595TEST_P(ASTImporterOptionSpecificTestBase,
1596 ImportDefinitionOfClassTemplateAfterFwdDecl) {
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001597 {
1598 Decl *FromTU = getTuDecl(
1599 R"(
1600 template <typename T>
1601 struct B;
1602 )",
1603 Lang_CXX, "input0.cc");
1604 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1605 FromTU, classTemplateDecl(hasName("B")));
1606
1607 Import(FromD, Lang_CXX);
1608 }
1609
1610 {
1611 Decl *FromTU = getTuDecl(
1612 R"(
1613 template <typename T>
1614 struct B {
1615 void f();
1616 };
1617 )",
1618 Lang_CXX, "input1.cc");
1619 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1620 FromTU, functionDecl(hasName("f")));
1621 Import(FromD, Lang_CXX);
1622 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1623 FromTU, classTemplateDecl(hasName("B")));
1624 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1625 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1626 }
1627}
1628
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001629TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001630 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1631 Decl *ToTU = getToTuDecl(
1632 R"(
1633 template <typename T>
1634 struct B {
1635 void f();
1636 };
1637
1638 template <typename T>
1639 struct B;
1640 )",
1641 Lang_CXX);
1642 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1643 [](const ClassTemplateDecl *T) {
1644 return T->isThisDeclarationADefinition();
1645 })
1646 .match(ToTU, classTemplateDecl()));
1647
1648 Decl *FromTU = getTuDecl(
1649 R"(
1650 template <typename T>
1651 struct B {
1652 void f();
1653 };
1654 )",
1655 Lang_CXX, "input1.cc");
1656 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1657 FromTU, classTemplateDecl(hasName("B")));
1658
1659 Import(FromD, Lang_CXX);
1660
1661 // We should have only one definition.
1662 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1663 [](const ClassTemplateDecl *T) {
1664 return T->isThisDeclarationADefinition();
1665 })
1666 .match(ToTU, classTemplateDecl()));
1667}
1668
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001669TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001670 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1671 Decl *ToTU = getToTuDecl(
1672 R"(
1673 struct B {
1674 void f();
1675 };
1676
1677 struct B;
1678 )",
1679 Lang_CXX);
1680 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001681 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001682
1683 Decl *FromTU = getTuDecl(
1684 R"(
1685 struct B {
1686 void f();
1687 };
1688 )",
1689 Lang_CXX, "input1.cc");
1690 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1691 FromTU, cxxRecordDecl(hasName("B")));
1692
1693 Import(FromD, Lang_CXX);
1694
1695 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001696 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001697}
1698
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001699static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1700 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1701 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1702 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1703 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1704}
1705static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1706 SourceManager &SM1, SourceManager &SM2) {
1707 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1708 FullSourceLoc{ Range2.getBegin(), SM2 });
1709 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1710 FullSourceLoc{ Range2.getEnd(), SM2 });
1711}
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001712TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001713 Decl *FromTU = getTuDecl(
1714 R"(
1715 #define MFOO(arg) arg = arg + 1
1716
1717 void foo() {
1718 int a = 5;
1719 MFOO(a);
1720 }
1721 )",
1722 Lang_CXX);
1723 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1724 auto ToD = Import(FromD, Lang_CXX);
1725
1726 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1727 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1728 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1729 auto FromRHS =
1730 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1731
1732 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1733 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1734 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1735 FromSM);
1736 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1737 FromSM);
1738 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1739 FromSM);
1740}
1741
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001742TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001743 Decl *FromTU = getTuDecl(
1744 R"(
1745 #define FUNC_INT void declToImport
1746 #define FUNC FUNC_INT
1747 FUNC(int a);
1748 )",
1749 Lang_CXX);
1750 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1751 auto ToD = Import(FromD, Lang_CXX);
1752
1753 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1754 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1755 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1756 FromSM);
1757}
1758
Gabor Marton9581c332018-05-23 13:53:36 +00001759TEST_P(
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001760 ASTImporterOptionSpecificTestBase,
1761 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
Gabor Marton9581c332018-05-23 13:53:36 +00001762 Decl *ToTU = getToTuDecl(
1763 R"(
1764 template <typename T>
1765 struct B;
1766
1767 template <>
1768 struct B<int> {};
1769
1770 template <>
1771 struct B<int>;
1772 )",
1773 Lang_CXX);
1774 // We should have only one definition.
1775 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1776 [](const ClassTemplateSpecializationDecl *T) {
1777 return T->isThisDeclarationADefinition();
1778 })
1779 .match(ToTU, classTemplateSpecializationDecl()));
1780
1781 Decl *FromTU = getTuDecl(
1782 R"(
1783 template <typename T>
1784 struct B;
1785
1786 template <>
1787 struct B<int> {};
1788 )",
1789 Lang_CXX, "input1.cc");
1790 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1791 FromTU, classTemplateSpecializationDecl(hasName("B")));
1792
1793 Import(FromD, Lang_CXX);
1794
1795 // We should have only one definition.
1796 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1797 [](const ClassTemplateSpecializationDecl *T) {
1798 return T->isThisDeclarationADefinition();
1799 })
1800 .match(ToTU, classTemplateSpecializationDecl()));
1801}
1802
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001803TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
Gabor Marton0bebf952018-07-05 09:51:13 +00001804 Decl *FromTU = getTuDecl(
1805 R"(
1806 struct { int a; int b; } object0 = { 2, 3 };
1807 struct { int x; int y; int z; } object1;
1808 )",
1809 Lang_CXX, "input0.cc");
1810
Gabor Marton0bebf952018-07-05 09:51:13 +00001811 auto *Obj0 =
1812 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1813 auto *From0 = getRecordDecl(Obj0);
1814 auto *Obj1 =
1815 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1816 auto *From1 = getRecordDecl(Obj1);
1817
1818 auto *To0 = Import(From0, Lang_CXX);
1819 auto *To1 = Import(From1, Lang_CXX);
1820
1821 EXPECT_TRUE(To0);
1822 EXPECT_TRUE(To1);
1823 EXPECT_NE(To0, To1);
1824 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1825}
1826
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001827TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001828 auto *Code =
1829 R"(
1830 struct X {
1831 struct { int a; };
1832 struct { int b; };
1833 };
1834 )";
1835 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
1836
1837 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
1838
1839 auto *X0 =
1840 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1841 auto *X1 =
1842 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1843 Import(X0, Lang_C);
1844 Import(X1, Lang_C);
1845
1846 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1847 // We expect no (ODR) warning during the import.
1848 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1849 EXPECT_EQ(1u,
1850 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1851}
1852
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001853TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001854 Decl *FromTU0 = getTuDecl(
1855 R"(
1856 struct X {
1857 struct { int a; };
1858 struct { int b; };
1859 };
1860 )",
1861 Lang_C, "input0.c");
1862
1863 Decl *FromTU1 = getTuDecl(
1864 R"(
1865 struct X { // reversed order
1866 struct { int b; };
1867 struct { int a; };
1868 };
1869 )",
1870 Lang_C, "input1.c");
1871
1872 auto *X0 =
1873 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1874 auto *X1 =
1875 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1876 Import(X0, Lang_C);
1877 Import(X1, Lang_C);
1878
1879 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1880 // We expect one (ODR) warning during the import.
1881 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1882 EXPECT_EQ(2u,
1883 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1884}
1885
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001886TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001887 auto Pattern = varDecl(hasName("x"));
1888 VarDecl *Imported1;
1889 {
1890 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1891 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1892 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1893 }
1894 VarDecl *Imported2;
1895 {
1896 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1897 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1898 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1899 }
1900 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1901 EXPECT_FALSE(Imported2->isUsed(false));
1902 {
1903 Decl *FromTU =
1904 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
Gabor Martonac3a5d62018-09-17 12:04:52 +00001905 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1906 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00001907 Import(FromD, Lang_CXX);
1908 }
1909 EXPECT_TRUE(Imported2->isUsed(false));
1910}
1911
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001912TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001913 auto Pattern = varDecl(hasName("x"));
1914 VarDecl *ExistingD;
1915 {
1916 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
1917 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1918 }
1919 EXPECT_FALSE(ExistingD->isUsed(false));
1920 {
1921 Decl *FromTU = getTuDecl(
1922 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
1923 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1924 FromTU, functionDecl(hasName("f")));
1925 Import(FromD, Lang_CXX);
1926 }
1927 EXPECT_TRUE(ExistingD->isUsed(false));
1928}
1929
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001930TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001931 auto Pattern = varDecl(hasName("a"));
1932 VarDecl *ExistingD;
1933 {
1934 Decl *ToTU = getToTuDecl(
1935 R"(
1936 struct A {
1937 static const int a = 1;
1938 };
1939 )", Lang_CXX);
1940 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1941 }
1942 EXPECT_FALSE(ExistingD->isUsed(false));
1943 {
1944 Decl *FromTU = getTuDecl(
1945 R"(
1946 struct A {
1947 static const int a = 1;
1948 };
1949 const int *f() { return &A::a; } // requires storage,
1950 // thus used flag will be set
1951 )", Lang_CXX, "input1.cc");
1952 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
1953 FromTU, functionDecl(hasName("f")));
1954 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1955 ASSERT_TRUE(FromD->isUsed(false));
1956 Import(FromFunD, Lang_CXX);
1957 }
1958 EXPECT_TRUE(ExistingD->isUsed(false));
1959}
1960
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001961TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001962 auto Pattern = varDecl(hasName("x"));
1963
1964 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
1965 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1966
1967 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1968
1969 ASSERT_FALSE(Imported1->isUsed(false));
1970
1971 FromD->setIsUsed();
1972 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1973
1974 EXPECT_EQ(Imported1, Imported2);
1975 EXPECT_TRUE(Imported2->isUsed(false));
1976}
1977
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001978struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
Peter Szecsidedda6f2018-03-30 22:03:29 +00001979
Gabor Marton5254e642018-06-27 13:32:50 +00001980TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001981 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1982 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001983 auto *From =
1984 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00001985
Gabor Marton5254e642018-06-27 13:32:50 +00001986 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001987 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1988
Gabor Marton5254e642018-06-27 13:32:50 +00001989 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1990 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1991 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1992 EXPECT_TRUE(ImportedD == To0);
1993 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1994 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1995 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001996}
1997
1998TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1999 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2000 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002001 auto *From =
2002 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00002003
Gabor Marton5254e642018-06-27 13:32:50 +00002004 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002005 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2006
Gabor Marton5254e642018-06-27 13:32:50 +00002007 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2008 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2009 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2010 EXPECT_TRUE(ImportedD == To1);
2011 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2012 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2013 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002014}
2015
Peter Szecsidedda6f2018-03-30 22:03:29 +00002016TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2017 auto Code =
2018 R"(
2019 struct B { virtual void f(); };
2020 void B::f() {}
2021 struct D : B { void f(); };
2022 )";
2023 auto Pattern =
2024 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2025 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2026 CXXMethodDecl *Proto =
2027 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2028
2029 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2030 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2031 EXPECT_EQ(To->size_overridden_methods(), 1u);
2032}
2033
2034TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2035 auto Code =
2036 R"(
2037 struct B { virtual void f(); };
2038 void B::f() {}
2039 )";
2040 auto Pattern =
2041 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2042 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2043 CXXMethodDecl *Proto =
2044 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2045 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2046
2047 ASSERT_TRUE(Proto->isVirtual());
2048 ASSERT_TRUE(Def->isVirtual());
2049 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2050 EXPECT_TRUE(To->isVirtual());
2051}
2052
Gabor Marton5254e642018-06-27 13:32:50 +00002053TEST_P(ImportFunctions,
2054 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2055 Decl *ToTU = getToTuDecl(
2056 R"(
2057 void f() {}
2058 void f();
2059 )",
2060 Lang_CXX);
2061 ASSERT_EQ(1u,
2062 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2063 return FD->doesThisDeclarationHaveABody();
2064 }).match(ToTU, functionDecl()));
2065
2066 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2067 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2068
2069 Import(FromD, Lang_CXX);
2070
2071 EXPECT_EQ(1u,
2072 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2073 return FD->doesThisDeclarationHaveABody();
2074 }).match(ToTU, functionDecl()));
2075}
2076
Shafik Yaghmour96b3d202019-01-28 21:55:33 +00002077TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
2078 auto Code =
2079 R"(
2080 struct B { virtual void f(); };
2081 struct D:B { void f(); };
2082 )";
2083 auto BFP =
2084 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2085 auto DFP =
2086 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2087
2088 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2089 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2090 Import(DF, Lang_CXX);
2091
2092 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2093 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2094 Import(BF, Lang_CXX);
2095
2096 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2097
2098 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2099 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2100}
2101
2102TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2103 auto CodeWithoutDef =
2104 R"(
2105 struct B { virtual void f(); };
2106 struct D:B { void f(); };
2107 )";
2108 auto CodeWithDef =
2109 R"(
2110 struct B { virtual void f(){}; };
2111 struct D:B { void f(){}; };
2112 )";
2113 auto BFP =
2114 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2115 auto DFP =
2116 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2117 auto BFDefP = cxxMethodDecl(
2118 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2119 auto DFDefP = cxxMethodDecl(
2120 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2121 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
2122
2123 {
2124 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX, "input0.cc");
2125 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
2126 Import(FromD, Lang_CXX);
2127 }
2128 {
2129 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX, "input1.cc");
2130 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
2131 Import(FromB, Lang_CXX);
2132 }
2133
2134 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2135
2136 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2137 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2138 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2139 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2140 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2141}
2142
2143TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2144 auto Code =
2145 R"(
2146 struct B { virtual void f(); };
2147 struct D:B { void f(); };
2148 void B::f(){};
2149 )";
2150
2151 auto BFP =
2152 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2153 auto BFDefP = cxxMethodDecl(
2154 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2155 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
2156 unless(isDefinition()));
2157
2158 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2159 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2160 Import(D, Lang_CXX);
2161
2162 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2163 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2164 Import(B, Lang_CXX);
2165
2166 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2167
2168 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2169 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2170
2171 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2172 ToTU, cxxRecordDecl(hasName("B")));
2173 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2174 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2175 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2176
2177 // The definition should be out-of-class.
2178 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2179 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2180 ToBFOutOfClass->getLexicalDeclContext());
2181 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2182 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2183
2184 // Check that the redecl chain is intact.
2185 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2186}
2187
2188TEST_P(ImportFunctions,
2189 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2190 auto CodeTU0 =
2191 R"(
2192 struct B { virtual void f(); };
2193 struct D:B { void f(); };
2194 )";
2195 auto CodeTU1 =
2196 R"(
2197 struct B { virtual void f(); };
2198 struct D:B { void f(); };
2199 void B::f(){}
2200 void D::f(){}
2201 void foo(B &b, D &d) { b.f(); d.f(); }
2202 )";
2203
2204 auto BFP =
2205 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2206 auto BFDefP = cxxMethodDecl(
2207 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2208 auto DFP =
2209 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2210 auto DFDefP = cxxMethodDecl(
2211 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2212 auto FooDef = functionDecl(hasName("foo"));
2213
2214 {
2215 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX, "input0.cc");
2216 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2217 Import(D, Lang_CXX);
2218 }
2219
2220 {
2221 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX, "input1.cc");
2222 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2223 Import(Foo, Lang_CXX);
2224 }
2225
2226 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2227
2228 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2229 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2230 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2231 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2232
2233 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2234 ToTU, cxxRecordDecl(hasName("B")));
2235 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2236 ToTU, cxxRecordDecl(hasName("D")));
2237 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2238 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2239 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2240 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2241 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2242 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2243
2244 // The definition should be out-of-class.
2245 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2246 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2247 ToBFOutOfClass->getLexicalDeclContext());
2248 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2249 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2250
2251 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2252 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2253 ToDFOutOfClass->getLexicalDeclContext());
2254 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2255 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2256
2257 // Check that the redecl chain is intact.
2258 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2259 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2260}
2261
Gabor Marton458d1452019-02-14 13:07:03 +00002262TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2263 std::string Code = "static int v; static int v = 0;";
2264 auto Pattern = varDecl(hasName("v"));
2265
2266 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C, "input0.c");
2267
2268 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2269 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2270
2271 auto *To0 = Import(From0, Lang_C);
2272 auto *To1 = Import(From1, Lang_C);
2273
2274 EXPECT_TRUE(To0);
2275 ASSERT_TRUE(To1);
2276 EXPECT_NE(To0, To1);
2277 EXPECT_EQ(To1->getPreviousDecl(), To0);
2278}
2279
2280TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2281 TranslationUnitDecl *FromTu = getTuDecl(
2282 "namespace NS0 { namespace { void f(); } }"
2283 "namespace NS1 { namespace { void f(); } }",
2284 Lang_CXX, "input0.cc");
2285 auto Pattern = functionDecl(hasName("f"));
2286
2287 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2288 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2289
2290 auto *ToF0 = Import(FromF0, Lang_CXX);
2291 auto *ToF1 = Import(FromF1, Lang_CXX);
2292
2293 EXPECT_TRUE(ToF0);
2294 ASSERT_TRUE(ToF1);
2295 EXPECT_NE(ToF0, ToF1);
2296 EXPECT_FALSE(ToF1->getPreviousDecl());
2297}
2298
2299TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2300 {
2301 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",
2302 Lang_CXX, "input0.cc");
2303 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2304 FromTU, functionDecl(hasName("g0")));
2305
2306 Import(FromD, Lang_CXX);
2307 }
2308 {
2309 Decl *FromTU =
2310 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",
2311 Lang_CXX, "input1.cc");
2312 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2313 FromTU, functionDecl(hasName("g1")));
2314 Import(FromD, Lang_CXX);
2315 }
2316
2317 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2318 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2319 2u);
2320}
2321
Gabor Marton302f3002019-02-15 12:04:05 +00002322TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2323 Decl *FromTU = getTuDecl(
2324 R"(
2325 void foo() {
2326 (void)[]() { ; };
2327 }
2328 )",
2329 Lang_CXX11);
2330 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2331 FromTU, functionDecl(hasName("foo")));
2332 auto *ToD = Import(FromD, Lang_CXX);
2333 EXPECT_TRUE(ToD);
2334 CXXRecordDecl *LambdaRec =
2335 cast<LambdaExpr>(cast<CStyleCastExpr>(
2336 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2337 ->getSubExpr())
2338 ->getLambdaClass();
2339 EXPECT_TRUE(LambdaRec->getDestructor());
2340}
2341
Gabor Marton5caba302019-03-07 13:38:20 +00002342TEST_P(ImportFunctions,
2343 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2344 Decl *FromTU = getTuDecl(
2345 R"(
2346 struct X {
2347 template <typename T>
2348 void foo(){}
2349 };
2350 void f() {
2351 X x;
2352 x.foo<int>();
2353 }
2354 )",
2355 Lang_CXX);
2356 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2357 FromTU, functionDecl(hasName("f")));
2358 auto *ToD = Import(FromD, Lang_CXX);
2359 EXPECT_TRUE(ToD);
2360 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
2361 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr()))));
2362}
2363
2364TEST_P(ImportFunctions,
2365 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2366 Decl *FromTU = getTuDecl(
2367 R"(
2368 struct X {
2369 template <typename T>
2370 void foo(){}
2371 };
2372 template <typename T>
2373 void f() {
2374 X x;
2375 x.foo<T>();
2376 }
2377 void g() {
2378 f<int>();
2379 }
2380 )",
2381 Lang_CXX);
2382 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2383 FromTU, functionDecl(hasName("g")));
2384 auto *ToD = Import(FromD, Lang_CXX);
2385 EXPECT_TRUE(ToD);
2386 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2387 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match(
2388 ToTU, translationUnitDecl(hasDescendant(
2389 functionDecl(hasName("f"), hasDescendant(declRefExpr()))))));
2390}
2391
Balazs Kerie9719f92019-08-07 12:40:17 +00002392struct ImportFunctionTemplates : ASTImporterOptionSpecificTestBase {};
2393
2394TEST_P(ImportFunctionTemplates, ImportFunctionTemplateInRecordDeclTwice) {
2395 auto Code =
2396 R"(
2397 class X {
2398 template <class T>
2399 void f(T t);
2400 };
2401 )";
2402 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2403 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2404 FromTU1, functionTemplateDecl(hasName("f")));
2405 auto *ToD1 = Import(FromD1, Lang_CXX);
2406 Decl *FromTU2 = getTuDecl(Code, Lang_CXX, "input2.cc");
2407 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2408 FromTU2, functionTemplateDecl(hasName("f")));
2409 auto *ToD2 = Import(FromD2, Lang_CXX);
2410 EXPECT_EQ(ToD1, ToD2);
2411}
2412
2413TEST_P(ImportFunctionTemplates,
2414 ImportFunctionTemplateWithDefInRecordDeclTwice) {
2415 auto Code =
2416 R"(
2417 class X {
2418 template <class T>
2419 void f(T t);
2420 };
2421 template <class T>
2422 void X::f(T t) {};
2423 )";
2424 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2425 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2426 FromTU1, functionTemplateDecl(hasName("f")));
2427 auto *ToD1 = Import(FromD1, Lang_CXX);
2428 Decl *FromTU2 = getTuDecl(Code, Lang_CXX, "input2.cc");
2429 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2430 FromTU2, functionTemplateDecl(hasName("f")));
2431 auto *ToD2 = Import(FromD2, Lang_CXX);
2432 EXPECT_EQ(ToD1, ToD2);
2433}
2434
Gabor Marton5254e642018-06-27 13:32:50 +00002435struct ImportFriendFunctions : ImportFunctions {};
2436
2437TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2438 auto Pattern = functionDecl(hasName("f"));
2439
2440 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2441 "void f();",
2442 Lang_CXX,
2443 "input0.cc");
2444 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2445
2446 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2447 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2448 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2449 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2450 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2451 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2452 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2453}
2454
2455TEST_P(ImportFriendFunctions,
2456 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2457 auto Pattern = functionDecl(hasName("f"));
2458
2459 Decl *FromTU = getTuDecl("void f();"
2460 "struct X { friend void f(); };",
2461 Lang_CXX, "input0.cc");
2462 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2463
2464 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2465 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2466 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2467 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2468 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2469 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2470 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2471}
2472
2473TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2474 auto Pattern = functionDecl(hasName("f"));
2475
2476 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2477 "void f();",
2478 Lang_CXX,
2479 "input0.cc");
2480 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2481
2482 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2483 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2484 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2485 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2486 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2487 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2488 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2489}
2490
2491TEST_P(ImportFriendFunctions,
2492 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2493 auto Pattern = functionDecl(hasName("f"));
2494
2495 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2496 "void f(){}",
2497 Lang_CXX, "input0.cc");
2498 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2499
2500 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2501 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2502 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2503 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2504 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2505 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2506 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2507}
2508
Gabor Marton1d51e3e2019-05-20 10:38:14 +00002509TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDefWithClass) {
Gabor Marton5254e642018-06-27 13:32:50 +00002510 auto Pattern = functionDecl(hasName("f"));
2511
2512 Decl *FromTU = getTuDecl(
2513 R"(
2514 class X;
2515 void f(X *x){}
2516 class X{
2517 friend void f(X *x);
2518 };
2519 )",
2520 Lang_CXX, "input0.cc");
2521 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2522
2523 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2524 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2525 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2526 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2527 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2528 .match(ToTU, friendDecl())
2529 ->getFriendDecl());
2530 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2531 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2532 // The parameters must refer the same type
2533 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2534 (*ImportedD->param_begin())->getOriginalType());
2535}
2536
Gabor Marton5254e642018-06-27 13:32:50 +00002537TEST_P(ImportFriendFunctions,
Gabor Marton1d51e3e2019-05-20 10:38:14 +00002538 ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002539 auto Pattern = functionDecl(hasName("f"));
2540
2541 Decl *FromTU = getTuDecl(
2542 R"(
2543 class X;
2544 void f(X *x){}
2545 class X{
2546 friend void f(X *x);
2547 };
2548 )",
2549 Lang_CXX, "input0.cc");
2550 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2551
2552 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2553 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2554 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2555 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2556 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2557 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2558
2559 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2560 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2561 // The parameters must refer the same type
2562 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2563 (*ImportedD->param_begin())->getOriginalType());
2564}
2565
2566TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2567 auto Pattern = functionDecl(hasName("f"));
2568
2569 FunctionDecl *ImportedD;
2570 {
2571 Decl *FromTU =
2572 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2573 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2574 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2575 }
2576 FunctionDecl *ImportedD1;
2577 {
2578 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2579 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2580 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2581 }
2582
2583 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2584 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2585 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2586 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2587 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2588}
2589
Balazs Keri89632b82018-08-21 14:32:21 +00002590TEST_P(ImportFriendFunctions, Lookup) {
2591 auto FunctionPattern = functionDecl(hasName("f"));
2592 auto ClassPattern = cxxRecordDecl(hasName("X"));
2593
2594 TranslationUnitDecl *FromTU =
2595 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2596 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2597 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2598 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2599 {
2600 auto FromName = FromD->getDeclName();
2601 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2602 auto LookupRes = Class->noload_lookup(FromName);
2603 ASSERT_EQ(LookupRes.size(), 0u);
2604 LookupRes = FromTU->noload_lookup(FromName);
2605 ASSERT_EQ(LookupRes.size(), 1u);
2606 }
2607
2608 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2609 auto ToName = ToD->getDeclName();
2610
2611 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2612 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2613 auto LookupRes = Class->noload_lookup(ToName);
2614 EXPECT_EQ(LookupRes.size(), 0u);
2615 LookupRes = ToTU->noload_lookup(ToName);
2616 EXPECT_EQ(LookupRes.size(), 1u);
2617
2618 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2619 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2620 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2621 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2622}
2623
2624TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2625 auto FunctionPattern = functionDecl(hasName("f"));
2626 auto ClassPattern = cxxRecordDecl(hasName("X"));
2627
2628 TranslationUnitDecl *FromTU = getTuDecl(
2629 "struct X { friend void f(); };"
2630 // This proto decl makes f available to normal
2631 // lookup, otherwise it is hidden.
2632 // Normal C++ lookup (implemented in
2633 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2634 // returns the found `NamedDecl` only if the set IDNS is matched
2635 "void f();",
2636 Lang_CXX, "input0.cc");
2637 auto *FromFriend =
2638 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2639 auto *FromNormal =
2640 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2641 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2642 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2643 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2644 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2645
2646 auto FromName = FromFriend->getDeclName();
2647 auto *FromClass =
2648 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2649 auto LookupRes = FromClass->noload_lookup(FromName);
2650 ASSERT_EQ(LookupRes.size(), 0u);
2651 LookupRes = FromTU->noload_lookup(FromName);
2652 ASSERT_EQ(LookupRes.size(), 1u);
2653
2654 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2655 auto ToName = ToFriend->getDeclName();
2656
2657 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2658 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2659 LookupRes = ToClass->noload_lookup(ToName);
2660 EXPECT_EQ(LookupRes.size(), 0u);
2661 LookupRes = ToTU->noload_lookup(ToName);
2662 // Test is disabled because this result is 2.
2663 EXPECT_EQ(LookupRes.size(), 1u);
2664
2665 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2666 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2667 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2668 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2669 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2670 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2671 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2672}
2673
2674TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2675 auto FunctionPattern = functionDecl(hasName("f"));
2676 auto ClassPattern = cxxRecordDecl(hasName("X"));
2677
2678 TranslationUnitDecl *FromTU = getTuDecl(
2679 "void f();"
2680 "struct X { friend void f(); };",
2681 Lang_CXX, "input0.cc");
2682 auto *FromNormal =
2683 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2684 auto *FromFriend =
2685 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2686 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2687 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2688 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2689 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2690
2691 auto FromName = FromNormal->getDeclName();
2692 auto *FromClass =
2693 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2694 auto LookupRes = FromClass->noload_lookup(FromName);
2695 ASSERT_EQ(LookupRes.size(), 0u);
2696 LookupRes = FromTU->noload_lookup(FromName);
2697 ASSERT_EQ(LookupRes.size(), 1u);
2698
2699 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2700 auto ToName = ToNormal->getDeclName();
2701 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2702
2703 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2704 LookupRes = ToClass->noload_lookup(ToName);
2705 EXPECT_EQ(LookupRes.size(), 0u);
2706 LookupRes = ToTU->noload_lookup(ToName);
2707 EXPECT_EQ(LookupRes.size(), 1u);
2708
2709 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2710 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2711 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2712 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2713 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2714 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2715 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2716}
2717
2718TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2719 auto Pattern = functionDecl(hasName("f"));
2720
2721 TranslationUnitDecl *FromNormalTU =
2722 getTuDecl("void f();", Lang_CXX, "input0.cc");
2723 auto *FromNormalF =
2724 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2725 TranslationUnitDecl *FromFriendTU =
2726 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2727 auto *FromFriendF =
2728 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2729 auto FromNormalName = FromNormalF->getDeclName();
2730 auto FromFriendName = FromFriendF->getDeclName();
2731
2732 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2733 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2734 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2735 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2736 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2737 ASSERT_EQ(LookupRes.size(), 1u);
2738 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2739 ASSERT_EQ(LookupRes.size(), 1u);
2740
2741 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2742 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2743 auto ToName = ToNormalF->getDeclName();
2744 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2745 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2746 LookupRes = ToTU->noload_lookup(ToName);
2747 EXPECT_EQ(LookupRes.size(), 1u);
2748 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00002749
Balazs Keri89632b82018-08-21 14:32:21 +00002750 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
2751 LookupRes = ToTU->noload_lookup(ToName);
2752 EXPECT_EQ(LookupRes.size(), 1u);
2753 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2754
2755 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2756 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2757
2758 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2759 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2760}
2761
2762TEST_P(ImportFriendFunctions, ImportFriendList) {
2763 TranslationUnitDecl *FromTU = getTuDecl(
2764 "struct X { friend void f(); };"
2765 "void f();",
2766 Lang_CXX, "input0.cc");
2767 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2768 FromTU, functionDecl(hasName("f")));
2769
2770 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2771 FromTU, cxxRecordDecl(hasName("X")));
2772 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2773 auto FromFriends = FromClass->friends();
2774 unsigned int FrN = 0;
2775 for (auto Fr : FromFriends) {
2776 ASSERT_EQ(Fr, FromFriend);
2777 ++FrN;
2778 }
2779 ASSERT_EQ(FrN, 1u);
2780
2781 Import(FromFriendF, Lang_CXX);
2782 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2783 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2784 ToTU, cxxRecordDecl(hasName("X")));
2785 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2786 auto ToFriends = ToClass->friends();
2787 FrN = 0;
2788 for (auto Fr : ToFriends) {
2789 EXPECT_EQ(Fr, ToFriend);
2790 ++FrN;
2791 }
2792 EXPECT_EQ(FrN, 1u);
2793}
2794
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002795AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2796 InnerMatcher) {
2797 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2798 return InnerMatcher.matches(*Typedef, Finder, Builder);
2799 return false;
2800}
2801
Gabor Marton19f4f392018-06-25 13:04:37 +00002802TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002803 CodeFiles Samples{{"main.c",
2804 {"void foo();"
2805 "void moo();"
2806 "int main() { foo(); moo(); }",
2807 Lang_C}},
2808
2809 {"foo.c",
2810 {"typedef enum { THING_VALUE } thing_t;"
2811 "void conflict(thing_t type);"
2812 "void foo() { (void)THING_VALUE; }"
2813 "void conflict(thing_t type) {}",
2814 Lang_C}},
2815
2816 {"moo.c",
2817 {"typedef enum { THING_VALUE } thing_t;"
2818 "void conflict(thing_t type);"
2819 "void moo() { conflict(THING_VALUE); }",
2820 Lang_C}}};
2821
2822 auto VerificationMatcher =
2823 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2824 hasTypedefForAnonDecl(hasName("thing_t")));
2825
2826 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2827 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2828
2829 testImportSequence(
2830 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2831 // Just check that there is only one enum decl in the result AST.
2832 "main.c", enumDecl(), VerificationMatcher);
2833
2834 // For different import order, result should be the same.
2835 testImportSequence(
2836 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2837 // Check that there is only one enum decl in the result AST.
2838 "main.c", enumDecl(), VerificationMatcher);
2839}
2840
Gabor Marton48b16e12019-07-25 09:07:17 +00002841TEST_P(ImportDecl, ImportFieldOrder) {
2842 MatchVerifier<Decl> Verifier;
2843 testImport("struct declToImport {"
2844 " int b = a + 2;"
2845 " int a = 5;"
2846 "};",
2847 Lang_CXX11, "", Lang_CXX11, Verifier,
2848 recordDecl(hasFieldOrder({"b", "a"})));
2849}
2850
Peter Szecsice7f3182018-05-07 12:08:27 +00002851const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2852 dependentScopeDeclRefExpr;
2853
Gabor Marton19f4f392018-06-25 13:04:37 +00002854TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002855 MatchVerifier<Decl> Verifier;
2856 testImport("template <typename T> struct S { static T foo; };"
2857 "template <typename T> void declToImport() {"
2858 " (void) S<T>::foo;"
2859 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002860 "void instantiate() { declToImport<int>(); }"
2861 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002862 Lang_CXX11, "", Lang_CXX11, Verifier,
2863 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2864 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2865
2866 testImport("template <typename T> struct S {"
2867 "template<typename S> static void foo(){};"
2868 "};"
2869 "template <typename T> void declToImport() {"
2870 " S<T>::template foo<T>();"
2871 "}"
2872 "void instantiate() { declToImport<int>(); }",
2873 Lang_CXX11, "", Lang_CXX11, Verifier,
2874 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2875 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2876}
2877
2878const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2879 dependentNameType;
2880
Gabor Marton19f4f392018-06-25 13:04:37 +00002881TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002882 MatchVerifier<Decl> Verifier;
2883 testImport("template <typename T> struct declToImport {"
2884 " typedef typename T::type dependent_name;"
2885 "};",
2886 Lang_CXX11, "", Lang_CXX11, Verifier,
2887 classTemplateDecl(has(
2888 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2889}
2890
Gabor Marton19f4f392018-06-25 13:04:37 +00002891TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002892 MatchVerifier<Decl> Verifier;
2893 testImport("struct S { template <typename T> void mem(); };"
2894 "template <typename U> void declToImport() {"
2895 " S s;"
2896 " s.mem<U>();"
2897 "}"
2898 "void instantiate() { declToImport<int>(); }",
2899 Lang_CXX11, "", Lang_CXX11, Verifier,
2900 functionTemplateDecl(has(functionDecl(has(
2901 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2902}
2903
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002904class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
Balazs Keri1d20cc22018-07-16 12:16:39 +00002905public:
2906 static constexpr auto DefaultCode = R"(
2907 struct A { int x; };
2908 void f() {
2909 A a;
2910 A a1(a);
2911 A a2(A{});
2912 a = a1;
2913 a = A{};
2914 a.~A();
2915 })";
2916
2917 template <typename MatcherType>
2918 void testImportOf(
2919 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2920 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
2921 }
2922
2923 template <typename MatcherType>
2924 void testNoImportOf(
2925 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2926 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
2927 }
2928
2929private:
2930 template <typename MatcherType>
2931 void test(const MatcherType &MethodMatcher,
2932 const char *Code, unsigned int ExpectedCount) {
2933 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
2934
2935 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
2936 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2937 ToTU, ClassMatcher);
2938
Balazs Keri2f752ba2018-07-16 14:05:18 +00002939 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002940
2941 {
2942 CXXMethodDecl *Method =
2943 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
2944 ToClass->removeDecl(Method);
Gabor Marton2afbfb62019-07-01 15:37:07 +00002945 SharedStatePtr->getLookupTable()->remove(Method);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002946 }
2947
Balazs Keri2f752ba2018-07-16 14:05:18 +00002948 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002949
2950 Decl *ImportedClass = nullptr;
2951 {
2952 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
2953 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2954 FromTU, ClassMatcher);
2955 ImportedClass = Import(FromClass, Lang_CXX11);
2956 }
2957
2958 EXPECT_EQ(ToClass, ImportedClass);
2959 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
2960 ExpectedCount);
2961 }
2962};
2963
2964TEST_P(ImportImplicitMethods, DefaultConstructor) {
2965 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
2966}
2967
2968TEST_P(ImportImplicitMethods, CopyConstructor) {
2969 testImportOf(cxxConstructorDecl(isCopyConstructor()));
2970}
2971
2972TEST_P(ImportImplicitMethods, MoveConstructor) {
2973 testImportOf(cxxConstructorDecl(isMoveConstructor()));
2974}
2975
2976TEST_P(ImportImplicitMethods, Destructor) {
2977 testImportOf(cxxDestructorDecl());
2978}
2979
2980TEST_P(ImportImplicitMethods, CopyAssignment) {
2981 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
2982}
2983
2984TEST_P(ImportImplicitMethods, MoveAssignment) {
2985 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
2986}
2987
2988TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
2989 auto Code = R"(
2990 struct A { A() { int x; } };
2991 )";
2992 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2993}
2994
2995TEST_P(ImportImplicitMethods, DoNotImportDefault) {
2996 auto Code = R"(
2997 struct A { A() = default; };
2998 )";
2999 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3000}
3001
3002TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
3003 auto Code = R"(
3004 struct A { A() = delete; };
3005 )";
3006 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3007}
3008
3009TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
3010 auto Code = R"(
3011 struct A { void f() { } };
3012 )";
3013 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
3014}
3015
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003016TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003017 Decl *ToR1;
3018 {
3019 Decl *FromTU = getTuDecl(
3020 "struct A { };", Lang_CXX, "input0.cc");
3021 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3022 FromTU, cxxRecordDecl(hasName("A")));
3023
3024 ToR1 = Import(FromR, Lang_CXX);
3025 }
3026
3027 Decl *ToR2;
3028 {
3029 Decl *FromTU = getTuDecl(
3030 "struct A { };", Lang_CXX, "input1.cc");
3031 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3032 FromTU, cxxRecordDecl(hasName("A")));
3033
3034 ToR2 = Import(FromR, Lang_CXX);
3035 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00003036
Balazs Keric7797c42018-07-11 09:37:24 +00003037 EXPECT_EQ(ToR1, ToR2);
3038}
3039
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003040TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003041 Decl *ToR1;
3042 {
3043 Decl *FromTU = getTuDecl(
3044 "struct A { int x; };", Lang_CXX, "input0.cc");
3045 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3046 FromTU, cxxRecordDecl(hasName("A")));
3047 ToR1 = Import(FromR, Lang_CXX);
3048 }
3049 Decl *ToR2;
3050 {
3051 Decl *FromTU = getTuDecl(
3052 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3053 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3054 FromTU, cxxRecordDecl(hasName("A")));
3055 ToR2 = Import(FromR, Lang_CXX);
3056 }
3057 EXPECT_NE(ToR1, ToR2);
3058}
3059
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003060TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003061 Decl *ToF1;
3062 {
3063 Decl *FromTU = getTuDecl(
3064 "struct A { int x; };", Lang_CXX, "input0.cc");
3065 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3066 FromTU, fieldDecl(hasName("x")));
3067 ToF1 = Import(FromF, Lang_CXX);
3068 }
3069 Decl *ToF2;
3070 {
3071 Decl *FromTU = getTuDecl(
3072 "struct A { int x; };", Lang_CXX, "input1.cc");
3073 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3074 FromTU, fieldDecl(hasName("x")));
3075 ToF2 = Import(FromF, Lang_CXX);
3076 }
3077 EXPECT_EQ(ToF1, ToF2);
3078}
3079
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003080TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003081 Decl *ToF1;
3082 {
3083 Decl *FromTU = getTuDecl(
3084 "struct A { int x; };", Lang_CXX, "input0.cc");
3085 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3086 FromTU, fieldDecl(hasName("x")));
3087 ToF1 = Import(FromF, Lang_CXX);
3088 }
3089 Decl *ToF2;
3090 {
3091 Decl *FromTU = getTuDecl(
3092 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3093 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3094 FromTU, fieldDecl(hasName("x")));
3095 ToF2 = Import(FromF, Lang_CXX);
3096 }
3097 EXPECT_NE(ToF1, ToF2);
3098}
3099
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003100TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003101 Decl *ToM1;
3102 {
3103 Decl *FromTU = getTuDecl(
3104 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
3105 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3106 FromTU, functionDecl(hasName("x"), isDefinition()));
3107 ToM1 = Import(FromM, Lang_CXX);
3108 }
3109 Decl *ToM2;
3110 {
3111 Decl *FromTU = getTuDecl(
3112 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
3113 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3114 FromTU, functionDecl(hasName("x"), isDefinition()));
3115 ToM2 = Import(FromM, Lang_CXX);
3116 }
3117 EXPECT_EQ(ToM1, ToM2);
3118}
3119
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003120TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003121 Decl *ToM1;
3122 {
3123 Decl *FromTU = getTuDecl(
3124 "struct A { void x(); }; void A::x() { }",
3125 Lang_CXX, "input0.cc");
3126 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3127 FromTU, functionDecl(hasName("x"), isDefinition()));
3128 ToM1 = Import(FromM, Lang_CXX);
3129 }
3130 Decl *ToM2;
3131 {
3132 Decl *FromTU = getTuDecl(
3133 "struct A { void x() const; }; void A::x() const { }",
3134 Lang_CXX, "input1.cc");
3135 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3136 FromTU, functionDecl(hasName("x"), isDefinition()));
3137 ToM2 = Import(FromM, Lang_CXX);
3138 }
3139 EXPECT_NE(ToM1, ToM2);
3140}
3141
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003142TEST_P(ASTImporterOptionSpecificTestBase,
3143 ImportUnnamedStructsWithRecursingField) {
Gabor Martonf086fa82018-07-17 12:06:36 +00003144 Decl *FromTU = getTuDecl(
3145 R"(
3146 struct A {
3147 struct {
3148 struct A *next;
3149 } entry0;
3150 struct {
3151 struct A *next;
3152 } entry1;
3153 };
3154 )",
3155 Lang_C, "input0.cc");
3156 auto *From =
3157 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3158
3159 Import(From, Lang_C);
3160
3161 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3162 auto *Entry0 =
3163 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3164 auto *Entry1 =
3165 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3166 auto *R0 = getRecordDecl(Entry0);
3167 auto *R1 = getRecordDecl(Entry1);
3168 EXPECT_NE(R0, R1);
3169 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3170 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3171 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3172 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3173}
3174
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003175TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
Balazs Keri2544b4b2018-08-08 09:40:57 +00003176 Decl *FromTU = getTuDecl(
3177 R"(
3178 void f(int X, int Y, bool Z) {
3179 (void)[X, Y, Z] { (void)Z; };
3180 }
3181 )",
3182 Lang_CXX11, "input0.cc");
3183 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3184 FromTU, functionDecl(hasName("f")));
3185 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3186 EXPECT_TRUE(ToF);
3187
3188 CXXRecordDecl *FromLambda =
3189 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3190 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3191
3192 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3193 EXPECT_TRUE(ToLambda);
3194
3195 // Check if the fields of the lambda class are imported in correct order.
3196 unsigned FromIndex = 0u;
3197 for (auto *FromField : FromLambda->fields()) {
3198 ASSERT_FALSE(FromField->getDeclName());
3199 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3200 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00003201 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3202 EXPECT_TRUE(ToIndex);
3203 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00003204 ++FromIndex;
3205 }
3206
3207 EXPECT_EQ(FromIndex, 3u);
3208}
3209
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003210TEST_P(ASTImporterOptionSpecificTestBase,
3211 MergeFieldDeclsOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003212 std::string ClassTemplate =
3213 R"(
3214 template <typename T>
3215 struct X {
3216 int a{0}; // FieldDecl with InitListExpr
3217 X(char) : a(3) {} // (1)
3218 X(int) {} // (2)
3219 };
3220 )";
3221 Decl *ToTU = getToTuDecl(ClassTemplate +
3222 R"(
3223 void foo() {
3224 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3225 X<char> xc('c');
3226 }
3227 )", Lang_CXX11);
3228 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3229 ToTU, classTemplateSpecializationDecl(hasName("X")));
3230 // FieldDecl without InitlistExpr:
3231 auto *ToField = *ToSpec->field_begin();
3232 ASSERT_TRUE(ToField);
3233 ASSERT_FALSE(ToField->getInClassInitializer());
3234 Decl *FromTU = getTuDecl(ClassTemplate +
3235 R"(
3236 void bar() {
3237 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3238 X<char> xc(1);
3239 }
3240 )", Lang_CXX11);
3241 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3242 FromTU, classTemplateSpecializationDecl(hasName("X")));
3243 // FieldDecl with InitlistExpr:
3244 auto *FromField = *FromSpec->field_begin();
3245 ASSERT_TRUE(FromField);
3246 ASSERT_TRUE(FromField->getInClassInitializer());
3247
3248 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3249 ASSERT_TRUE(ImportedSpec);
3250 EXPECT_EQ(ImportedSpec, ToSpec);
3251 // After the import, the FieldDecl has to be merged, thus it should have the
3252 // InitListExpr.
3253 EXPECT_TRUE(ToField->getInClassInitializer());
3254}
3255
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003256TEST_P(ASTImporterOptionSpecificTestBase,
3257 MergeFunctionOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003258 std::string ClassTemplate =
3259 R"(
3260 template <typename T>
3261 struct X {
3262 void f() {}
3263 void g() {}
3264 };
3265 )";
3266 Decl *ToTU = getToTuDecl(ClassTemplate +
3267 R"(
3268 void foo() {
3269 X<char> x;
3270 x.f();
3271 }
3272 )", Lang_CXX11);
3273 Decl *FromTU = getTuDecl(ClassTemplate +
3274 R"(
3275 void bar() {
3276 X<char> x;
3277 x.g();
3278 }
3279 )", Lang_CXX11);
3280 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3281 FromTU, classTemplateSpecializationDecl(hasName("X")));
3282 auto FunPattern = functionDecl(hasName("g"),
3283 hasParent(classTemplateSpecializationDecl()));
3284 auto *FromFun =
3285 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3286 auto *ToFun =
3287 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3288 ASSERT_TRUE(FromFun->hasBody());
3289 ASSERT_FALSE(ToFun->hasBody());
3290 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3291 ASSERT_TRUE(ImportedSpec);
3292 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3293 ToTU, classTemplateSpecializationDecl(hasName("X")));
3294 EXPECT_EQ(ImportedSpec, ToSpec);
3295 EXPECT_TRUE(ToFun->hasBody());
3296}
3297
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003298TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003299 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3300 std::string ClassTemplate =
3301 R"(
3302 template <typename T>
3303 struct X {};
3304 )";
3305 Decl *ToTU = getToTuDecl(ClassTemplate +
3306 R"(
3307 template <>
3308 struct X<char> {
3309 int a;
3310 };
3311 void foo() {
3312 X<char> x;
3313 }
3314 )",
3315 Lang_CXX11);
3316 Decl *FromTU = getTuDecl(ClassTemplate +
3317 R"(
3318 template <>
3319 struct X<char> {
3320 int b;
3321 };
3322 void foo() {
3323 X<char> x;
3324 }
3325 )",
3326 Lang_CXX11);
3327 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3328 FromTU, classTemplateSpecializationDecl(hasName("X")));
3329 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3330
3331 // We expect one (ODR) warning during the import.
3332 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3333
3334 // The second specialization is different from the first, thus it violates
3335 // ODR, consequently we expect to keep the first specialization only, which is
3336 // already in the "To" context.
Gabor Marton7f8c4002019-03-19 13:34:10 +00003337 EXPECT_FALSE(ImportedSpec);
3338 EXPECT_EQ(1u,
3339 DeclCounter<ClassTemplateSpecializationDecl>().match(
3340 ToTU, classTemplateSpecializationDecl(hasName("X"))));
Gabor Marton42e15de2018-08-22 11:52:14 +00003341}
3342
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003343TEST_P(ASTImporterOptionSpecificTestBase,
3344 MergeCtorOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003345 std::string ClassTemplate =
3346 R"(
3347 template <typename T>
3348 struct X {
3349 X(char) {}
3350 X(int) {}
3351 };
3352 )";
3353 Decl *ToTU = getToTuDecl(ClassTemplate +
3354 R"(
3355 void foo() {
3356 X<char> x('c');
3357 }
3358 )", Lang_CXX11);
3359 Decl *FromTU = getTuDecl(ClassTemplate +
3360 R"(
3361 void bar() {
3362 X<char> x(1);
3363 }
3364 )", Lang_CXX11);
3365 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3366 FromTU, classTemplateSpecializationDecl(hasName("X")));
3367 // Match the void(int) ctor.
3368 auto CtorPattern =
3369 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3370 hasParent(classTemplateSpecializationDecl()));
3371 auto *FromCtor =
3372 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3373 auto *ToCtor =
3374 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3375 ASSERT_TRUE(FromCtor->hasBody());
3376 ASSERT_FALSE(ToCtor->hasBody());
3377 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3378 ASSERT_TRUE(ImportedSpec);
3379 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3380 ToTU, classTemplateSpecializationDecl(hasName("X")));
3381 EXPECT_EQ(ImportedSpec, ToSpec);
3382 EXPECT_TRUE(ToCtor->hasBody());
3383}
3384
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003385TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003386 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3387 auto Code =
3388 R"(
3389 // primary template
3390 template<class T1, class T2, int I>
3391 class A {};
3392
3393 // partial specialization
3394 template<class T, int I>
3395 class A<T, T*, I> {};
3396 )";
3397 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3398 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3399 auto *FromSpec =
3400 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3401 FromTU, classTemplatePartialSpecializationDecl());
3402 auto *ToSpec =
3403 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3404 ToTU, classTemplatePartialSpecializationDecl());
3405
3406 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3407 EXPECT_EQ(ImportedSpec, ToSpec);
3408 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3409 ToTU, classTemplatePartialSpecializationDecl()));
3410}
3411
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003412TEST_P(ASTImporterOptionSpecificTestBase,
3413 ClassTemplateSpecializationsShouldNotBeDuplicated) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003414 auto Code =
3415 R"(
3416 // primary template
3417 template<class T1, class T2, int I>
3418 class A {};
3419
3420 // full specialization
3421 template<>
3422 class A<int, int, 1> {};
3423 )";
3424 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3425 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3426 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3427 FromTU, classTemplateSpecializationDecl());
3428 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3429 ToTU, classTemplateSpecializationDecl());
3430
3431 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3432 EXPECT_EQ(ImportedSpec, ToSpec);
3433 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3434 ToTU, classTemplateSpecializationDecl()));
3435}
3436
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003437TEST_P(ASTImporterOptionSpecificTestBase,
3438 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003439 std::string PrimaryTemplate =
3440 R"(
3441 template<class T1, class T2, int I>
3442 class A {};
3443 )";
3444 auto PartialSpec =
3445 R"(
3446 template<class T, int I>
3447 class A<T, T*, I> {};
3448 )";
3449 auto FullSpec =
3450 R"(
3451 template<>
3452 class A<int, int, 1> {};
3453 )";
3454 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3455 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3456 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3457 FromTU, classTemplateSpecializationDecl());
3458
3459 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3460 EXPECT_TRUE(ImportedSpec);
3461 // Check the number of partial specializations.
3462 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3463 ToTU, classTemplatePartialSpecializationDecl()));
3464 // Check the number of full specializations.
3465 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3466 ToTU, classTemplateSpecializationDecl(
3467 unless(classTemplatePartialSpecializationDecl()))));
3468}
3469
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003470TEST_P(ASTImporterOptionSpecificTestBase,
3471 InitListExprValueKindShouldBeImported) {
Gabor Martona20ce602018-09-03 13:10:53 +00003472 Decl *TU = getTuDecl(
3473 R"(
3474 const int &init();
3475 void foo() { const int &a{init()}; }
3476 )", Lang_CXX11, "input0.cc");
3477 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3478 ASSERT_TRUE(FromD->getAnyInitializer());
3479 auto *InitExpr = FromD->getAnyInitializer();
3480 ASSERT_TRUE(InitExpr);
3481 ASSERT_TRUE(InitExpr->isGLValue());
3482
3483 auto *ToD = Import(FromD, Lang_CXX11);
3484 EXPECT_TRUE(ToD);
3485 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3486 EXPECT_TRUE(ToInitExpr);
3487 EXPECT_TRUE(ToInitExpr->isGLValue());
3488}
3489
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003490struct ImportVariables : ASTImporterOptionSpecificTestBase {};
Gabor Martonac3a5d62018-09-17 12:04:52 +00003491
3492TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3493 Decl *FromTU = getTuDecl(
3494 R"(
3495 struct A {
3496 static const int a = 1 + 2;
3497 };
3498 const int A::a;
3499 )", Lang_CXX, "input1.cc");
3500
3501 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3502 FromTU, varDecl(hasName("a"))); // Decl with init
3503 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3504 FromTU, varDecl(hasName("a"))); // Decl with definition
3505 ASSERT_NE(FromDWithInit, FromDWithDef);
3506 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3507
3508 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3509 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3510 ASSERT_TRUE(ToD0);
3511 ASSERT_TRUE(ToD1);
3512 EXPECT_NE(ToD0, ToD1);
3513 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3514}
3515
3516TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3517 auto StructA =
3518 R"(
3519 struct A {
3520 static const int a = 1 + 2;
3521 };
3522 )";
3523 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3524 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3525 "input1.cc");
3526
3527 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3528 FromTU, varDecl(hasName("a"))); // Decl with init
3529 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3530 FromTU, varDecl(hasName("a"))); // Decl with definition
3531 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3532 ASSERT_TRUE(FromDWithInit->getInit());
3533 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3534 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3535 ASSERT_FALSE(FromDWithDef->getInit());
3536
3537 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3538 ToTU, varDecl(hasName("a"))); // Decl with init
3539 ASSERT_TRUE(ToD->getInit());
3540 ASSERT_FALSE(ToD->getDefinition());
3541
3542 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3543 EXPECT_TRUE(ImportedD->getAnyInitializer());
3544 EXPECT_TRUE(ImportedD->getDefinition());
3545}
3546
3547TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3548 auto StructA =
3549 R"(
3550 struct A {
3551 static const int a;
3552 };
3553 )";
3554 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3555 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3556 Lang_CXX, "input1.cc");
3557
3558 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3559 FromTU, varDecl(hasName("a")));
3560 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3561 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3562 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3563 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3564 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3565 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3566 ASSERT_TRUE(FromDWithDef->getInit());
3567
3568 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3569 ToTU, varDecl(hasName("a")));
3570 ASSERT_FALSE(ToD->getInit());
3571 ASSERT_FALSE(ToD->getDefinition());
3572
3573 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3574 EXPECT_TRUE(ImportedD->getAnyInitializer());
3575 EXPECT_TRUE(ImportedD->getDefinition());
3576}
3577
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003578struct ImportClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003579
Gabor Marton54058b52018-12-17 13:53:12 +00003580TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3581 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
3582 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3583 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3584 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3585 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3586
3587 Decl *ImportedDef = Import(FromDef, Lang_C);
3588
3589 EXPECT_NE(ImportedDef, ToProto);
3590 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3591 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3592 EXPECT_TRUE(ImportedDef == ToDef);
3593 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3594 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3595 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3596}
3597
3598TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3599 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
3600 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
3601 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3602 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3603 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3604
3605 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3606
3607 EXPECT_NE(ImportedDef, ToProto);
3608 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3609 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3610 EXPECT_TRUE(ImportedDef == ToDef);
3611 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3612 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3613 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3614}
3615
3616TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3617 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
3618 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3619 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3620 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3621 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3622
3623 Decl *ImportedProto = Import(FromProto, Lang_C);
3624 Decl *ImportedDef = Import(FromDef, Lang_C);
3625 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3626
3627 EXPECT_NE(ImportedDef, ImportedProto);
3628 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3629 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3630 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3631 EXPECT_TRUE(ImportedDef == ToDef);
3632 EXPECT_TRUE(ImportedProto == ToProto);
3633 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3634 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3635 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3636}
3637
Gabor Marton7df342a2018-12-17 12:42:12 +00003638
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003639struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003640
3641TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
3642 Decl *FromTU = getTuDecl(
3643 R"(
3644 class A {
3645 template <int I> class F {};
3646 class X {
3647 template <int I> friend class F;
3648 };
3649 };
3650 )",
3651 Lang_CXX, "input0.cc");
3652
3653 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3654 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
3655 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
3656 FromTU, cxxRecordDecl(hasName("F")));
3657
3658 ASSERT_TRUE(FromClass);
3659 ASSERT_TRUE(FromFriendClass);
3660 ASSERT_NE(FromClass, FromFriendClass);
3661 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
3662 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
3663 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3664 FromClass->getDescribedClassTemplate());
3665
3666 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
3667 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
3668
3669 EXPECT_TRUE(ToClass);
3670 EXPECT_TRUE(ToFriendClass);
3671 EXPECT_NE(ToClass, ToFriendClass);
3672 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
3673 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
3674 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3675 ToClass->getDescribedClassTemplate());
3676}
3677
3678TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
3679 Decl *FromTu = getTuDecl(
3680 R"(
3681 class declToImport {
3682 friend class declToImport;
3683 };
3684 )",
3685 Lang_CXX, "input.cc");
3686
3687 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
3688 FromTu, cxxRecordDecl(hasName("declToImport")));
3689 auto *ToD = Import(FromD, Lang_CXX);
3690 auto Pattern = cxxRecordDecl(has(friendDecl()));
3691 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3692 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3693}
3694
3695TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
3696 Decl *FromTu = getTuDecl(
3697 R"(
3698 template<class A> class declToImport {
3699 template<class A1> friend class declToImport;
3700 };
3701 )",
3702 Lang_CXX, "input.cc");
3703
3704 auto *FromD =
3705 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
3706 auto *ToD = Import(FromD, Lang_CXX);
3707
3708 auto Pattern = classTemplateDecl(
3709 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
3710 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3711 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3712
3713 auto *Class =
3714 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
3715 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
3716 EXPECT_NE(Friend->getFriendDecl(), Class);
3717 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
3718}
3719
3720TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
3721 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
3722
3723 ClassTemplateSpecializationDecl *Imported1;
3724 {
3725 Decl *FromTU = getTuDecl("template<class T> class X;"
3726 "struct Y { friend class X<int>; };",
3727 Lang_CXX, "input0.cc");
3728 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3729 FromTU, Pattern);
3730
3731 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3732 }
3733 ClassTemplateSpecializationDecl *Imported2;
3734 {
3735 Decl *FromTU = getTuDecl("template<class T> class X;"
3736 "template<> class X<int>{};"
3737 "struct Z { friend class X<int>; };",
3738 Lang_CXX, "input1.cc");
3739 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3740 FromTU, Pattern);
3741
3742 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3743 }
3744
3745 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3746 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
3747 2u);
3748 ASSERT_TRUE(Imported2->getPreviousDecl());
3749 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
3750}
3751
3752TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
3753 Decl *FromTU0 = getTuDecl(
3754 R"(
3755 class X {
3756 class Y;
3757 };
3758 class X::Y {
3759 template <typename T>
3760 friend class F; // The decl context of F is the global namespace.
3761 };
3762 )",
3763 Lang_CXX, "input0.cc");
3764 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3765 FromTU0, classTemplateDecl(hasName("F")));
3766 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3767 Decl *FromTU1 = getTuDecl(
3768 R"(
3769 template <typename T>
3770 class F {};
3771 )",
3772 Lang_CXX, "input1.cc");
3773 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3774 FromTU1, classTemplateDecl(hasName("F")));
3775 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3776 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
3777 Imported1->getTemplatedDecl()->getTypeForDecl());
3778}
3779
3780TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
3781 Decl *From, *To;
3782 std::tie(From, To) =
3783 getImportedDecl("class declToImport {};", Lang_CXX,
3784 "class Y { friend class declToImport; };", Lang_CXX);
3785 auto *Imported = cast<CXXRecordDecl>(To);
3786
3787 EXPECT_TRUE(Imported->getPreviousDecl());
3788}
3789
3790TEST_P(ImportFriendClasses,
3791 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
3792 Decl *ToTU = getToTuDecl(
3793 R"(
3794 class X {
3795 class Y;
3796 };
3797 class X::Y {
3798 template <typename T>
3799 friend class F; // The decl context of F is the global namespace.
3800 };
3801 )",
3802 Lang_CXX);
3803 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
3804 ToTU, classTemplateDecl(hasName("F")));
3805 Decl *FromTU = getTuDecl(
3806 R"(
3807 template <typename T>
3808 class F {};
3809 )",
3810 Lang_CXX, "input0.cc");
3811 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3812 FromTU, classTemplateDecl(hasName("F")));
3813 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3814 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3815 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
3816 EXPECT_EQ(ToDecl->getTemplatedDecl(),
3817 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3818}
3819
3820TEST_P(ImportFriendClasses,
3821 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
3822 Decl *FromTU0 = getTuDecl(
3823 R"(
3824 class X {
3825 class Y;
3826 };
3827 class X::Y {
3828 template <typename T>
3829 friend class F; // The decl context of F is the global namespace.
3830 };
3831 )",
3832 Lang_CXX, "input0.cc");
3833 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3834 FromTU0, classTemplateDecl(hasName("F")));
3835 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3836 Decl *FromTU1 = getTuDecl(
3837 R"(
3838 template <typename T>
3839 class F {};
3840 )",
3841 Lang_CXX, "input1.cc");
3842 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3843 FromTU1, classTemplateDecl(hasName("F")));
3844 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3845 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3846 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3847 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
3848 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3849}
3850
3851TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
3852 Decl *FromTU0 = getTuDecl(
3853 R"(
3854 class X {
3855 class Y;
3856 };
3857 class X::Y {
3858 friend class F; // The decl context of F is the global namespace.
3859 };
3860 )",
3861 Lang_CXX, "input0.cc");
3862 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
3863 QualType FT = Friend->getFriendType()->getType();
3864 FT = FromTU0->getASTContext().getCanonicalType(FT);
3865 auto *Fwd = cast<TagType>(FT)->getDecl();
3866 auto *ImportedFwd = Import(Fwd, Lang_CXX);
3867 Decl *FromTU1 = getTuDecl(
3868 R"(
3869 class F {};
3870 )",
3871 Lang_CXX, "input1.cc");
3872 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
3873 FromTU1, cxxRecordDecl(hasName("F")));
3874 auto *ImportedDef = Import(Definition, Lang_CXX);
3875 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3876 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3877}
3878
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003879TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Gabor Marton54058b52018-12-17 13:53:12 +00003880 auto *Code = R"(
3881 template <class T>
3882 struct X {
3883 friend void foo(){}
3884 };
3885 )";
3886 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
3887 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
3888 ToTU, functionDecl(hasName("foo")));
3889
3890 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
3891 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
3892 FromTU, functionDecl(hasName("foo")));
3893 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
3894 EXPECT_EQ(ImportedFoo, ToFoo);
3895}
3896
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003897struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton61d862a2018-05-18 09:08:47 +00003898
3899TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
3900 Decl *TU = getTuDecl(
3901 R"(
3902 namespace NS {
3903
3904 template <typename T>
3905 struct S {};
3906 template struct S<int>;
3907
3908 inline namespace INS {
3909 template <typename T>
3910 struct S {};
3911 template struct S<int>;
3912 }
3913
3914 }
3915 )", Lang_CXX11, "input0.cc");
3916 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
3917 TU, namespaceDecl());
3918 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3919 TU, classTemplateSpecializationDecl());
3920 ASSERT_TRUE(NS->containsDecl(Spec));
3921
3922 NS->removeDecl(Spec);
3923 EXPECT_FALSE(NS->containsDecl(Spec));
3924}
3925
Gabor Marton7df342a2018-12-17 12:42:12 +00003926TEST_P(DeclContextTest,
3927 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
3928 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
3929 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
3930 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
3931
3932 // Investigate the list.
3933 auto *DC = A0->getDeclContext();
3934 ASSERT_TRUE(DC->containsDecl(A0));
3935 ASSERT_TRUE(DC->containsDecl(A1));
3936
3937 // Investigate the lookup table.
3938 auto *Map = DC->getLookupPtr();
3939 ASSERT_TRUE(Map);
3940 auto I = Map->find(A0->getDeclName());
3941 ASSERT_NE(I, Map->end());
3942 StoredDeclsList &L = I->second;
3943 // The lookup table contains the most recent decl of A.
3944 ASSERT_NE(L.getAsDecl(), A0);
3945 ASSERT_EQ(L.getAsDecl(), A1);
3946
3947 ASSERT_TRUE(L.getAsDecl());
3948 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
3949 // The point here is to have a Vec with only one element, which is not the
3950 // one we are going to delete from the DC later.
3951 L.setHasExternalDecls();
3952 ASSERT_TRUE(L.getAsVector());
3953 ASSERT_EQ(1u, L.getAsVector()->size());
3954
3955 // This asserts in the old implementation.
3956 DC->removeDecl(A0);
3957 EXPECT_FALSE(DC->containsDecl(A0));
3958}
3959
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003960struct ImportFunctionTemplateSpecializations
3961 : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +00003962
3963TEST_P(ImportFunctionTemplateSpecializations,
3964 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
3965
3966 Decl *FromTU = getTuDecl(
3967 R"(
3968 template<class T>
3969 int f() { return 0; }
3970 void foo() { f<int>(); }
3971 )",
3972 Lang_CXX, "input0.cc");
3973
3974 // Check that the function template instantiation is NOT the child of the TU.
3975 auto Pattern = translationUnitDecl(
3976 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
3977 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3978
3979 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
3980 FromTU, functionDecl(hasName("foo")));
3981 ASSERT_TRUE(Import(Foo, Lang_CXX));
3982
3983 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3984 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3985}
3986
3987TEST_P(ImportFunctionTemplateSpecializations,
3988 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
3989
3990 Decl *FromTU = getTuDecl(
3991 R"(
3992 template<class T>
3993 int f() { return 0; }
3994 template int f<int>();
3995 )",
3996 Lang_CXX, "input0.cc");
3997
3998 // Check that the function template instantiation is NOT the child of the TU.
3999 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4000 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4001 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4002
4003 ASSERT_TRUE(
4004 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
4005
4006 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4007 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4008}
4009
4010TEST_P(ImportFunctionTemplateSpecializations,
4011 TUshouldContainFunctionTemplateSpecialization) {
4012
4013 Decl *FromTU = getTuDecl(
4014 R"(
4015 template<class T>
4016 int f() { return 0; }
4017 template <> int f<int>() { return 4; }
4018 )",
4019 Lang_CXX, "input0.cc");
4020
4021 // Check that the function template specialization is the child of the TU.
4022 auto Specialization =
4023 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4024 auto Pattern = translationUnitDecl(has(Specialization));
4025 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4026
4027 ASSERT_TRUE(
4028 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
4029
4030 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4031 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4032}
4033
4034TEST_P(ImportFunctionTemplateSpecializations,
4035 FunctionTemplateSpecializationRedeclChain) {
4036
4037 Decl *FromTU = getTuDecl(
4038 R"(
4039 template<class T>
4040 int f() { return 0; }
4041 template <> int f<int>() { return 4; }
4042 )",
4043 Lang_CXX, "input0.cc");
4044
4045 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4046 hasParent(translationUnitDecl()));
4047 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4048 {
4049 auto *TU = FromTU;
4050 auto *SpecD = FromSpecD;
4051 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4052 TU, functionTemplateDecl());
4053 auto *FirstSpecD = *(TemplateD->spec_begin());
4054 ASSERT_EQ(SpecD, FirstSpecD);
4055 ASSERT_TRUE(SpecD->getPreviousDecl());
4056 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4057 ->doesThisDeclarationHaveABody());
4058 }
4059
4060 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
4061
4062 {
4063 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4064 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4065 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4066 TU, functionTemplateDecl());
4067 auto *FirstSpecD = *(TemplateD->spec_begin());
4068 EXPECT_EQ(SpecD, FirstSpecD);
4069 ASSERT_TRUE(SpecD->getPreviousDecl());
4070 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4071 ->doesThisDeclarationHaveABody());
4072 }
4073}
4074
4075TEST_P(ImportFunctionTemplateSpecializations,
4076 MatchNumberOfFunctionTemplateSpecializations) {
4077
4078 Decl *FromTU = getTuDecl(
4079 R"(
4080 template <typename T> constexpr int f() { return 0; }
4081 template <> constexpr int f<int>() { return 4; }
4082 void foo() {
4083 static_assert(f<char>() == 0, "");
4084 static_assert(f<int>() == 4, "");
4085 }
4086 )",
4087 Lang_CXX11, "input0.cc");
4088 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4089 FromTU, functionDecl(hasName("foo")));
4090
4091 Import(FromD, Lang_CXX11);
4092 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4093 EXPECT_EQ(
4094 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4095 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4096}
4097
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004098TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton17d39672018-11-26 15:54:08 +00004099 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4100 {
4101 Decl *FromTU = getTuDecl(
4102 R"(
4103 template <typename T>
4104 struct B;
4105 )",
4106 Lang_CXX, "input0.cc");
4107 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4108 FromTU, classTemplateDecl(hasName("B")));
4109
4110 Import(FromD, Lang_CXX);
4111 }
4112
4113 {
4114 Decl *FromTU = getTuDecl(
4115 R"(
4116 template <typename T>
4117 struct B {
4118 void f();
4119 B* b;
4120 };
4121 )",
4122 Lang_CXX, "input1.cc");
4123 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4124 FromTU, functionDecl(hasName("f")));
4125 Import(FromD, Lang_CXX);
4126 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4127 FromTU, classTemplateDecl(hasName("B")));
4128 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
4129 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4130
4131 // We expect no (ODR) warning during the import.
4132 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4133 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4134 }
4135}
4136
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004137TEST_P(ASTImporterOptionSpecificTestBase,
4138 ImportingTypedefShouldImportTheCompleteType) {
Gabor Martonb93baf62018-11-27 09:51:36 +00004139 // We already have an incomplete underlying type in the "To" context.
4140 auto Code =
4141 R"(
4142 template <typename T>
4143 struct S {
4144 void foo();
4145 };
4146 using U = S<int>;
4147 )";
4148 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4149 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4150 typedefNameDecl(hasName("U")));
4151 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4152
4153 // The "From" context has the same typedef, but the underlying type is
4154 // complete this time.
4155 Decl *FromTU = getTuDecl(std::string(Code) +
4156 R"(
4157 void foo(U* u) {
4158 u->foo();
4159 }
4160 )", Lang_CXX11);
4161 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4162 typedefNameDecl(hasName("U")));
4163 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4164
4165 // The imported type should be complete.
4166 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4167 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4168}
4169
Balazs Keri1efc9742019-05-07 10:55:11 +00004170TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) {
4171 auto Code =
4172 R"(
4173 template<class T>
4174 int f() { return 0; }
4175 template <> int f<int>() { return 4; }
4176 )";
4177
4178 Decl *FromTU = getTuDecl(Code, Lang_CXX);
4179 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU,
4180 functionDecl(hasName("f"), isExplicitTemplateSpecialization()));
Balazs Kerib7d8cff2019-05-07 14:53:04 +00004181 ASSERT_EQ(FromD->getNumTemplateParameterLists(), 1u);
Balazs Keri1efc9742019-05-07 10:55:11 +00004182
4183 auto *ToD = Import(FromD, Lang_CXX);
4184 // The template parameter list should exist.
Balazs Kerib7d8cff2019-05-07 14:53:04 +00004185 EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u);
Balazs Keri1efc9742019-05-07 10:55:11 +00004186}
4187
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004188struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton54058b52018-12-17 13:53:12 +00004189
4190TEST_P(ASTImporterLookupTableTest, OneDecl) {
4191 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
4192 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4193 ASTImporterLookupTable LT(*ToTU);
4194 auto Res = LT.lookup(ToTU, D->getDeclName());
4195 ASSERT_EQ(Res.size(), 1u);
4196 EXPECT_EQ(*Res.begin(), D);
4197}
4198
4199static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4200 for (Decl *D : DC->decls()) {
4201 if (auto *ND = dyn_cast<NamedDecl>(D))
4202 if (ND->getDeclName() == Name)
4203 return ND;
4204 }
4205 return nullptr;
Martin Storsjo85833392018-12-18 08:36:16 +00004206}
Gabor Marton54058b52018-12-17 13:53:12 +00004207
4208TEST_P(ASTImporterLookupTableTest,
4209 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4210 auto *Code = R"(
4211 template <class T>
4212 struct X {
4213 friend void foo(){}
4214 };
4215 )";
4216 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4217 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
4218 ToTU, classTemplateDecl(hasName("X")));
4219 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4220 ToTU, functionDecl(hasName("foo")));
4221 DeclContext *FooDC = Foo->getDeclContext();
4222 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4223 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
4224 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4225 DeclarationName FooName = Foo->getDeclName();
4226
4227 // Cannot find in the LookupTable of its DC (TUDecl)
4228 SmallVector<NamedDecl *, 2> FoundDecls;
4229 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4230 EXPECT_EQ(FoundDecls.size(), 0u);
4231
4232 // Cannot find in the LookupTable of its LexicalDC (X)
4233 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4234 EXPECT_EQ(FoundDecls.size(), 0u);
4235
4236 // Can't find in the list of Decls of the DC.
4237 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4238
4239 // Can't find in the list of Decls of the LexicalDC
4240 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
4241
4242 // ASTImporter specific lookup finds it.
4243 ASTImporterLookupTable LT(*ToTU);
4244 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4245 ASSERT_EQ(Res.size(), 1u);
4246 EXPECT_EQ(*Res.begin(), Foo);
4247}
4248
4249TEST_P(ASTImporterLookupTableTest,
4250 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
4251 TranslationUnitDecl *ToTU =
4252 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
4253 auto *Foo =
4254 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
4255 auto *A =
4256 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4257 DeclContext *FooDC = Foo->getDeclContext();
4258 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4259 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
4260 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4261 DeclarationName FooName = Foo->getDeclName();
4262
4263 // Cannot find in the LookupTable of its DC (TUDecl).
4264 SmallVector<NamedDecl *, 2> FoundDecls;
4265 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4266 EXPECT_EQ(FoundDecls.size(), 0u);
4267
4268 // Cannot find in the LookupTable of its LexicalDC (A).
4269 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4270 EXPECT_EQ(FoundDecls.size(), 0u);
4271
4272 // Can't find in the list of Decls of the DC.
4273 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4274
4275 // Can find in the list of Decls of the LexicalDC.
4276 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
4277
4278 // ASTImporter specific lookup finds it.
4279 ASTImporterLookupTable LT(*ToTU);
4280 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4281 ASSERT_EQ(Res.size(), 1u);
4282 EXPECT_EQ(*Res.begin(), Foo);
4283}
4284
4285TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
4286 TranslationUnitDecl *ToTU =
4287 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
4288 DeclarationName VName = FirstDeclMatcher<VarDecl>()
4289 .match(ToTU, varDecl(hasName("V")))
4290 ->getDeclName();
4291 auto *A =
4292 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4293 auto *B =
4294 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
4295
4296 ASTImporterLookupTable LT(*ToTU);
4297
4298 auto Res = LT.lookup(cast<DeclContext>(A), VName);
4299 ASSERT_EQ(Res.size(), 1u);
4300 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4301 ToTU, fieldDecl(hasName("V"),
4302 hasParent(recordDecl(hasName("A"))))));
4303 Res = LT.lookup(cast<DeclContext>(B), VName);
4304 ASSERT_EQ(Res.size(), 1u);
4305 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4306 ToTU, fieldDecl(hasName("V"),
4307 hasParent(recordDecl(hasName("B"))))));
4308 Res = LT.lookup(ToTU, VName);
4309 ASSERT_EQ(Res.size(), 1u);
4310 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
4311 ToTU, varDecl(hasName("V"),
4312 hasParent(translationUnitDecl()))));
4313}
4314
4315TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
4316 TranslationUnitDecl *ToTU = getToTuDecl(
4317 R"(
4318 void foo();
4319 void foo(int);
4320 void foo(int, int);
4321 )",
4322 Lang_CXX);
4323
4324 ASTImporterLookupTable LT(*ToTU);
4325 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4326 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4327 DeclarationName Name = F0->getDeclName();
4328 auto Res = LT.lookup(ToTU, Name);
4329 EXPECT_EQ(Res.size(), 3u);
4330 EXPECT_EQ(Res.count(F0), 1u);
4331 EXPECT_EQ(Res.count(F2), 1u);
4332}
4333
Gabor Martona9cab312019-02-08 09:19:34 +00004334TEST_P(ASTImporterLookupTableTest,
4335 DifferentOperatorsShouldHaveDifferentResultSet) {
4336 TranslationUnitDecl *ToTU = getToTuDecl(
4337 R"(
4338 struct X{};
4339 void operator+(X, X);
4340 void operator-(X, X);
4341 )",
4342 Lang_CXX);
4343
4344 ASTImporterLookupTable LT(*ToTU);
4345 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
4346 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4347 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
4348 ToTU, functionDecl(hasOverloadedOperatorName("-")));
4349 DeclarationName NamePlus = FPlus->getDeclName();
4350 auto ResPlus = LT.lookup(ToTU, NamePlus);
4351 EXPECT_EQ(ResPlus.size(), 1u);
4352 EXPECT_EQ(ResPlus.count(FPlus), 1u);
4353 EXPECT_EQ(ResPlus.count(FMinus), 0u);
4354 DeclarationName NameMinus = FMinus->getDeclName();
4355 auto ResMinus = LT.lookup(ToTU, NameMinus);
4356 EXPECT_EQ(ResMinus.size(), 1u);
4357 EXPECT_EQ(ResMinus.count(FMinus), 1u);
4358 EXPECT_EQ(ResMinus.count(FPlus), 0u);
4359 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
4360}
4361
4362TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
4363 TranslationUnitDecl *ToTU = getToTuDecl(
4364 R"(
4365 struct X {};
4366 void operator+(X, X);
4367 )",
4368 Lang_CXX);
4369 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
4370 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4371
4372 Decl *FromTU = getTuDecl(
4373 R"(
4374 struct X {};
4375 void operator+(X, X);
4376 )",
4377 Lang_CXX);
4378 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
4379 FromTU, functionDecl(hasOverloadedOperatorName("+")));
4380
4381 // FromPlus have a different TU, thus its DeclarationName is different too.
4382 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
4383
4384 ASTImporterLookupTable LT(*ToTU);
4385 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
4386 ASSERT_EQ(Res.size(), 1u);
4387 EXPECT_EQ(*Res.begin(), ToPlus);
4388
4389 // FromPlus have a different TU, thus its DeclarationName is different too.
4390 Res = LT.lookup(ToTU, FromPlus->getDeclName());
4391 ASSERT_EQ(Res.size(), 0u);
4392}
4393
Gabor Martondd2b76e2019-06-11 13:35:25 +00004394static const RecordDecl *getRecordDeclOfFriend(FriendDecl *FD) {
4395 QualType Ty = FD->getFriendType()->getType().getCanonicalType();
4396 return cast<RecordType>(Ty)->getDecl();
Gabor Marton54058b52018-12-17 13:53:12 +00004397}
4398
Gabor Martondd2b76e2019-06-11 13:35:25 +00004399TEST_P(ASTImporterLookupTableTest,
4400 LookupFindsFwdFriendClassDeclWithElaboratedType) {
Gabor Marton54058b52018-12-17 13:53:12 +00004401 TranslationUnitDecl *ToTU = getToTuDecl(
4402 R"(
4403 class Y { friend class F; };
4404 )",
4405 Lang_CXX);
4406
4407 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4408 // So we must dig up the underlying CXXRecordDecl.
4409 ASTImporterLookupTable LT(*ToTU);
4410 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4411 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4412 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
4413 ToTU, cxxRecordDecl(hasName("Y")));
4414
4415 DeclarationName Name = RD->getDeclName();
4416 auto Res = LT.lookup(ToTU, Name);
4417 EXPECT_EQ(Res.size(), 1u);
4418 EXPECT_EQ(*Res.begin(), RD);
4419
4420 Res = LT.lookup(Y, Name);
4421 EXPECT_EQ(Res.size(), 0u);
4422}
4423
Gabor Martondd2b76e2019-06-11 13:35:25 +00004424TEST_P(ASTImporterLookupTableTest,
4425 LookupFindsFwdFriendClassDeclWithUnelaboratedType) {
4426 TranslationUnitDecl *ToTU = getToTuDecl(
4427 R"(
4428 class F;
4429 class Y { friend F; };
4430 )",
4431 Lang_CXX11);
4432
4433 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4434 // So we must dig up the underlying CXXRecordDecl.
4435 ASTImporterLookupTable LT(*ToTU);
4436 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4437 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4438 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, cxxRecordDecl(hasName("Y")));
4439
4440 DeclarationName Name = RD->getDeclName();
4441 auto Res = LT.lookup(ToTU, Name);
4442 EXPECT_EQ(Res.size(), 1u);
4443 EXPECT_EQ(*Res.begin(), RD);
4444
4445 Res = LT.lookup(Y, Name);
4446 EXPECT_EQ(Res.size(), 0u);
4447}
4448
4449TEST_P(ASTImporterLookupTableTest,
4450 LookupFindsFriendClassDeclWithTypeAliasDoesNotAssert) {
4451 TranslationUnitDecl *ToTU = getToTuDecl(
4452 R"(
4453 class F;
4454 using alias_of_f = F;
4455 class Y { friend alias_of_f; };
4456 )",
4457 Lang_CXX11);
4458
4459 // ASTImporterLookupTable constructor handles using declarations correctly,
4460 // no assert is expected.
4461 ASTImporterLookupTable LT(*ToTU);
4462
4463 auto *Alias = FirstDeclMatcher<TypeAliasDecl>().match(
4464 ToTU, typeAliasDecl(hasName("alias_of_f")));
4465 DeclarationName Name = Alias->getDeclName();
4466 auto Res = LT.lookup(ToTU, Name);
4467 EXPECT_EQ(Res.count(Alias), 1u);
4468}
4469
Gabor Marton54058b52018-12-17 13:53:12 +00004470TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
4471 TranslationUnitDecl *ToTU = getToTuDecl(
4472 R"(
4473 class Y { template <class T> friend class F; };
4474 )",
4475 Lang_CXX);
4476
4477 ASTImporterLookupTable LT(*ToTU);
4478 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4479 ToTU, classTemplateDecl(hasName("F")));
4480 DeclarationName Name = F->getDeclName();
4481 auto Res = LT.lookup(ToTU, Name);
4482 EXPECT_EQ(Res.size(), 2u);
4483 EXPECT_EQ(Res.count(F), 1u);
4484 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4485}
4486
4487TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
4488 TranslationUnitDecl *ToTU = getToTuDecl(
4489 R"(
4490 template <typename T>
4491 class F;
4492
4493 template <typename T>
4494 class Y {
4495 friend class F<T>;
4496 };
4497 )",
4498 Lang_CXX);
4499
4500 ASTImporterLookupTable LT(*ToTU);
4501 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4502 ToTU, classTemplateDecl(hasName("F")));
4503 DeclarationName Name = F->getDeclName();
4504 auto Res = LT.lookup(ToTU, Name);
4505 EXPECT_EQ(Res.size(), 2u);
4506 EXPECT_EQ(Res.count(F), 1u);
4507 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4508}
4509
4510TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
4511 TranslationUnitDecl *ToTU = getToTuDecl(
4512 R"(
4513 template <typename T>
4514 class F;
4515
4516 class Y {
4517 friend class F<int>;
4518 };
4519 )",
4520 Lang_CXX);
4521
4522 ASTImporterLookupTable LT(*ToTU);
4523 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4524 ToTU, classTemplateDecl(hasName("F")));
4525 DeclarationName Name = F->getDeclName();
4526 auto Res = LT.lookup(ToTU, Name);
4527 ASSERT_EQ(Res.size(), 3u);
4528 EXPECT_EQ(Res.count(F), 1u);
4529 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4530 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
4531}
4532
4533TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
4534 TranslationUnitDecl *ToTU = getToTuDecl(
4535 R"(
4536 class Y { friend void F(); };
4537 )",
4538 Lang_CXX);
4539
4540 ASTImporterLookupTable LT(*ToTU);
4541 auto *F =
4542 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
4543 DeclarationName Name = F->getDeclName();
4544 auto Res = LT.lookup(ToTU, Name);
4545 EXPECT_EQ(Res.size(), 1u);
4546 EXPECT_EQ(*Res.begin(), F);
4547}
4548
4549TEST_P(ASTImporterLookupTableTest,
4550 LookupFindsDeclsInClassTemplateSpecialization) {
4551 TranslationUnitDecl *ToTU = getToTuDecl(
4552 R"(
4553 template <typename T>
4554 struct X {
4555 int F;
4556 };
4557 void foo() {
4558 X<char> xc;
4559 }
4560 )",
4561 Lang_CXX);
4562
4563 ASTImporterLookupTable LT(*ToTU);
4564
4565 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
4566 ToTU, classTemplateDecl(hasName("X")));
4567 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
4568 ToTU,
4569 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
4570
4571 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4572 ToTU, classTemplateSpecializationDecl(hasName("X")));
4573 FieldDecl *FieldInSpec = *Spec->field_begin();
4574 ASSERT_TRUE(FieldInSpec);
4575
4576 DeclarationName Name = FieldInSpec->getDeclName();
4577 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
4578
4579 SmallVector<NamedDecl *, 2> FoundDecls;
4580 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
4581 EXPECT_EQ(FoundDecls.size(), 1u);
4582 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
4583
4584 auto Res = LT.lookup(TemplateDC, Name);
4585 ASSERT_EQ(Res.size(), 1u);
4586 EXPECT_EQ(*Res.begin(), FieldInTemplate);
4587
4588 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
4589 FoundDecls);
4590 EXPECT_EQ(FoundDecls.size(), 1u);
4591 EXPECT_EQ(FoundDecls[0], FieldInSpec);
4592
4593 Res = LT.lookup(cast<DeclContext>(Spec), Name);
4594 ASSERT_EQ(Res.size(), 1u);
4595 EXPECT_EQ(*Res.begin(), FieldInSpec);
4596}
4597
4598TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
4599 TranslationUnitDecl *ToTU = getToTuDecl(
4600 R"(
4601 class Y { template <class T> friend void F(); };
4602 )",
4603 Lang_CXX);
4604
4605 ASTImporterLookupTable LT(*ToTU);
4606 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
4607 ToTU, functionTemplateDecl(hasName("F")));
4608 DeclarationName Name = F->getDeclName();
4609 auto Res = LT.lookup(ToTU, Name);
4610 EXPECT_EQ(Res.size(), 2u);
4611 EXPECT_EQ(Res.count(F), 1u);
4612 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4613}
4614
4615TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
4616 TranslationUnitDecl *ToTU = getToTuDecl(
4617 R"(
4618 struct X;
4619 struct A {
4620 friend struct X;
4621 };
4622 struct B {
4623 friend struct X;
4624 };
4625 )",
4626 Lang_CXX);
4627
4628 ASTImporterLookupTable LT(*ToTU);
4629 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
4630 ToTU, cxxRecordDecl(hasName("X")));
4631 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4632 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4633 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
4634 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
4635 ASSERT_EQ(RD0, RD1);
4636 ASSERT_EQ(RD1, X);
4637
4638 DeclarationName Name = X->getDeclName();
4639 auto Res = LT.lookup(ToTU, Name);
4640 EXPECT_EQ(Res.size(), 1u);
4641 EXPECT_EQ(*Res.begin(), X);
4642}
4643
4644TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
4645 TranslationUnitDecl *ToTU = getToTuDecl(
4646 R"(
4647 enum E {
4648 A,
4649 B
4650 };
4651 )",
4652 Lang_C);
4653
4654 ASTImporterLookupTable LT(*ToTU);
4655 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
4656 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
4657 ToTU, enumConstantDecl(hasName("A")));
4658
4659 DeclarationName Name = A->getDeclName();
4660 // Redecl context is the TU.
4661 ASSERT_EQ(E->getRedeclContext(), ToTU);
4662
4663 SmallVector<NamedDecl *, 2> FoundDecls;
4664 // Normal lookup finds in the DC.
4665 E->localUncachedLookup(Name, FoundDecls);
4666 EXPECT_EQ(FoundDecls.size(), 1u);
4667
4668 // Normal lookup finds in the Redecl context.
4669 ToTU->localUncachedLookup(Name, FoundDecls);
4670 EXPECT_EQ(FoundDecls.size(), 1u);
4671
4672 // Import specific lookup finds in the DC.
4673 auto Res = LT.lookup(E, Name);
4674 ASSERT_EQ(Res.size(), 1u);
4675 EXPECT_EQ(*Res.begin(), A);
4676
4677 // Import specific lookup finds in the Redecl context.
4678 Res = LT.lookup(ToTU, Name);
4679 ASSERT_EQ(Res.size(), 1u);
4680 EXPECT_EQ(*Res.begin(), A);
4681}
4682
4683TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
4684 TranslationUnitDecl *ToTU = getToTuDecl(
4685 R"(
4686 namespace N {
4687 int A;
4688 }
4689 namespace N {
4690 }
4691 )",
4692 Lang_CXX);
4693 auto *N1 =
4694 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
4695 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
4696 DeclarationName Name = A->getDeclName();
4697
4698 ASTImporterLookupTable LT(*ToTU);
4699 auto Res = LT.lookup(N1, Name);
4700 ASSERT_EQ(Res.size(), 1u);
4701 EXPECT_EQ(*Res.begin(), A);
4702}
4703
Gabor Marton5254e642018-06-27 13:32:50 +00004704
Gabor Marton0e04ebd2019-02-11 10:27:58 +00004705// FIXME This test is disabled currently, upcoming patches will make it
4706// possible to enable.
4707TEST_P(ASTImporterOptionSpecificTestBase,
4708 DISABLED_RedeclChainShouldBeCorrectAmongstNamespaces) {
4709 Decl *FromTU = getTuDecl(
4710 R"(
4711 namespace NS {
4712 struct X;
4713 struct Y {
4714 static const int I = 3;
4715 };
4716 }
4717 namespace NS {
4718 struct X { // <--- To be imported
4719 void method(int i = Y::I) {}
4720 int f;
4721 };
4722 }
4723 )",
4724 Lang_CXX);
4725 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
4726 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
4727 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
4728 FromTU,
4729 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
4730 ASSERT_NE(FromFwd, FromDef);
4731 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
4732 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4733 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
4734
4735 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX));
4736 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX));
4737 EXPECT_NE(ToFwd, ToDef);
4738 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
4739 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4740 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
4741 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4742 // We expect no (ODR) warning during the import.
4743 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4744}
4745
Gabor Martone331e632019-02-18 13:09:27 +00004746struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
4747
4748TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
4749 Decl *ToTU = getToTuDecl(
4750 R"(
4751 class X {
4752 template <typename T> friend void foo();
4753 };
4754 )",
4755 Lang_CXX);
4756 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
4757 ToTU, functionTemplateDecl(hasName("foo")));
4758
4759 Decl *FromTU = getTuDecl(
4760 R"(
4761 template <typename T> void foo();
4762 )",
4763 Lang_CXX);
4764 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
4765 FromTU, functionTemplateDecl(hasName("foo")));
4766 auto *Imported = Import(FromFoo, Lang_CXX);
4767
Gabor Marton16d98c22019-03-07 13:01:51 +00004768 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
Gabor Martone331e632019-02-18 13:09:27 +00004769}
4770
Gabor Marton303c98612019-06-25 08:00:51 +00004771struct ASTImporterWithFakeErrors : ASTImporter {
4772 using ASTImporter::ASTImporter;
4773 bool returnWithErrorInTest() override { return true; }
4774};
4775
4776struct ErrorHandlingTest : ASTImporterOptionSpecificTestBase {
4777 ErrorHandlingTest() {
4778 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
4779 ASTContext &FromContext, FileManager &FromFileManager,
Gabor Marton2afbfb62019-07-01 15:37:07 +00004780 bool MinimalImport,
4781 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
Gabor Marton303c98612019-06-25 08:00:51 +00004782 return new ASTImporterWithFakeErrors(ToContext, ToFileManager,
4783 FromContext, FromFileManager,
Gabor Marton2afbfb62019-07-01 15:37:07 +00004784 MinimalImport, SharedState);
Gabor Marton303c98612019-06-25 08:00:51 +00004785 };
4786 }
4787 // In this test we purposely report an error (UnsupportedConstruct) when
4788 // importing the below stmt.
4789 static constexpr auto* ErroneousStmt = R"( asm(""); )";
4790};
4791
4792// Check a case when no new AST node is created in the AST before encountering
4793// the error.
4794TEST_P(ErrorHandlingTest, ErrorHappensBeforeCreatingANewNode) {
4795 TranslationUnitDecl *ToTU = getToTuDecl(
4796 R"(
4797 template <typename T>
4798 class X {};
4799 template <>
4800 class X<int> { int a; };
4801 )",
4802 Lang_CXX);
4803 TranslationUnitDecl *FromTU = getTuDecl(
4804 R"(
4805 template <typename T>
4806 class X {};
4807 template <>
4808 class X<int> { double b; };
4809 )",
4810 Lang_CXX);
4811 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4812 FromTU, classTemplateSpecializationDecl(hasName("X")));
4813 ClassTemplateSpecializationDecl *ImportedSpec = Import(FromSpec, Lang_CXX);
4814 EXPECT_FALSE(ImportedSpec);
4815
4816 // The original Decl is kept, no new decl is created.
4817 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(
4818 ToTU, classTemplateSpecializationDecl(hasName("X"))),
4819 1u);
4820
4821 // But an error is set to the counterpart in the "from" context.
4822 ASTImporter *Importer = findFromTU(FromSpec)->Importer.get();
4823 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromSpec);
4824 ASSERT_TRUE(OptErr);
4825 EXPECT_EQ(OptErr->Error, ImportError::NameConflict);
4826}
4827
4828// Check a case when a new AST node is created but not linked to the AST before
4829// encountering the error.
4830TEST_P(ErrorHandlingTest,
4831 ErrorHappensAfterCreatingTheNodeButBeforeLinkingThatToTheAST) {
4832 TranslationUnitDecl *FromTU = getTuDecl(
4833 std::string("void foo() { ") + ErroneousStmt + " }",
4834 Lang_CXX);
4835 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4836 FromTU, functionDecl(hasName("foo")));
4837
4838 FunctionDecl *ImportedFoo = Import(FromFoo, Lang_CXX);
4839 EXPECT_FALSE(ImportedFoo);
4840
4841 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4842 // Created, but not linked.
4843 EXPECT_EQ(
4844 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("foo"))),
4845 0u);
4846
4847 ASTImporter *Importer = findFromTU(FromFoo)->Importer.get();
4848 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFoo);
4849 ASSERT_TRUE(OptErr);
4850 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4851}
4852
4853// Check a case when a new AST node is created and linked to the AST before
4854// encountering the error. The error is set for the counterpart of the nodes in
4855// the "from" context.
4856TEST_P(ErrorHandlingTest, ErrorHappensAfterNodeIsCreatedAndLinked) {
4857 TranslationUnitDecl *FromTU = getTuDecl(
4858 std::string(R"(
4859 void f();
4860 void f() { )") + ErroneousStmt + R"( }
4861 )",
4862 Lang_CXX);
4863 auto *FromProto = FirstDeclMatcher<FunctionDecl>().match(
4864 FromTU, functionDecl(hasName("f")));
4865 auto *FromDef =
4866 LastDeclMatcher<FunctionDecl>().match(FromTU, functionDecl(hasName("f")));
4867 FunctionDecl *ImportedProto = Import(FromProto, Lang_CXX);
4868 EXPECT_FALSE(ImportedProto); // Could not import.
4869 // However, we created two nodes in the AST. 1) the fwd decl 2) the
4870 // definition. The definition is not added to its DC, but the fwd decl is
4871 // there.
4872 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4873 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
4874 1u);
4875 // Match the fwd decl.
4876 auto *ToProto =
4877 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("f")));
4878 EXPECT_TRUE(ToProto);
4879 // An error is set to the counterpart in the "from" context both for the fwd
4880 // decl and the definition.
4881 ASTImporter *Importer = findFromTU(FromProto)->Importer.get();
4882 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromProto);
4883 ASSERT_TRUE(OptErr);
4884 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4885 OptErr = Importer->getImportDeclErrorIfAny(FromDef);
4886 ASSERT_TRUE(OptErr);
4887 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4888}
4889
Gabor Marton17c3eaf2019-07-01 12:44:39 +00004890// An error should be set for a class if we cannot import one member.
4891TEST_P(ErrorHandlingTest, ErrorIsPropagatedFromMemberToClass) {
4892 TranslationUnitDecl *FromTU = getTuDecl(
4893 std::string(R"(
4894 class X {
4895 void f() { )") + ErroneousStmt + R"( } // This member has the error
4896 // during import.
4897 void ok(); // The error should not prevent importing this.
4898 }; // An error will be set for X too.
4899 )",
4900 Lang_CXX);
4901 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
4902 FromTU, cxxRecordDecl(hasName("X")));
4903 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX);
4904
4905 // An error is set for X.
4906 EXPECT_FALSE(ImportedX);
4907 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
4908 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
4909 ASSERT_TRUE(OptErr);
4910 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4911
4912 // An error is set for f().
4913 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
4914 FromTU, cxxMethodDecl(hasName("f")));
4915 OptErr = Importer->getImportDeclErrorIfAny(FromF);
4916 ASSERT_TRUE(OptErr);
4917 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4918 // And any subsequent import should fail.
4919 CXXMethodDecl *ImportedF = Import(FromF, Lang_CXX);
4920 EXPECT_FALSE(ImportedF);
4921
Gabor Marton1ad4b992019-07-01 14:19:53 +00004922 // There is an error set for the other member too.
Gabor Marton17c3eaf2019-07-01 12:44:39 +00004923 auto *FromOK = FirstDeclMatcher<CXXMethodDecl>().match(
4924 FromTU, cxxMethodDecl(hasName("ok")));
4925 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
Gabor Marton1ad4b992019-07-01 14:19:53 +00004926 EXPECT_TRUE(OptErr);
4927 // Cannot import the other member.
Gabor Marton17c3eaf2019-07-01 12:44:39 +00004928 CXXMethodDecl *ImportedOK = Import(FromOK, Lang_CXX);
Gabor Marton1ad4b992019-07-01 14:19:53 +00004929 EXPECT_FALSE(ImportedOK);
4930}
Gabor Marton17c3eaf2019-07-01 12:44:39 +00004931
Gabor Marton1ad4b992019-07-01 14:19:53 +00004932// Check that an error propagates to the dependent AST nodes.
4933// In the below code it means that an error in X should propagate to A.
4934// And even to F since the containing A is erroneous.
4935// And to all AST nodes which we visit during the import process which finally
4936// ends up in a failure (in the error() function).
4937TEST_P(ErrorHandlingTest, ErrorPropagatesThroughImportCycles) {
4938 Decl *FromTU = getTuDecl(
4939 std::string(R"(
4940 namespace NS {
4941 class A {
4942 template <int I> class F {};
4943 class X {
4944 template <int I> friend class F;
4945 void error() { )") + ErroneousStmt + R"( }
4946 };
4947 };
4948
4949 class B {};
4950 } // NS
4951 )",
4952 Lang_CXX, "input0.cc");
4953
4954 auto *FromFRD = FirstDeclMatcher<CXXRecordDecl>().match(
4955 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
4956 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
4957 FromTU, cxxRecordDecl(hasName("A"), isDefinition()));
4958 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(
4959 FromTU, cxxRecordDecl(hasName("B"), isDefinition()));
4960 auto *FromNS = FirstDeclMatcher<NamespaceDecl>().match(
4961 FromTU, namespaceDecl(hasName("NS")));
4962
4963 // Start by importing the templated CXXRecordDecl of F.
4964 // Import fails for that.
4965 EXPECT_FALSE(Import(FromFRD, Lang_CXX));
4966 // Import fails for A.
4967 EXPECT_FALSE(Import(FromA, Lang_CXX));
4968 // But we should be able to import the independent B.
4969 EXPECT_TRUE(Import(FromB, Lang_CXX));
4970 // And the namespace.
4971 EXPECT_TRUE(Import(FromNS, Lang_CXX));
4972
4973 // An error is set to the templated CXXRecordDecl of F.
4974 ASTImporter *Importer = findFromTU(FromFRD)->Importer.get();
4975 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFRD);
4976 EXPECT_TRUE(OptErr);
4977
4978 // An error is set to A.
4979 OptErr = Importer->getImportDeclErrorIfAny(FromA);
4980 EXPECT_TRUE(OptErr);
4981
4982 // There is no error set to B.
4983 OptErr = Importer->getImportDeclErrorIfAny(FromB);
4984 EXPECT_FALSE(OptErr);
4985
4986 // There is no error set to NS.
4987 OptErr = Importer->getImportDeclErrorIfAny(FromNS);
4988 EXPECT_FALSE(OptErr);
4989
4990 // Check some of those decls whose ancestor is X, they all should have an
4991 // error set if we visited them during an import process which finally failed.
4992 // These decls are part of a cycle in an ImportPath.
4993 // There would not be any error set for these decls if we hadn't follow the
4994 // ImportPaths and the cycles.
4995 OptErr = Importer->getImportDeclErrorIfAny(
4996 FirstDeclMatcher<ClassTemplateDecl>().match(
4997 FromTU, classTemplateDecl(hasName("F"))));
4998 // An error is set to the 'F' ClassTemplateDecl.
4999 EXPECT_TRUE(OptErr);
5000 // An error is set to the FriendDecl.
5001 OptErr = Importer->getImportDeclErrorIfAny(
5002 FirstDeclMatcher<FriendDecl>().match(
5003 FromTU, friendDecl()));
5004 EXPECT_TRUE(OptErr);
5005 // An error is set to the implicit class of A.
5006 OptErr =
5007 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
5008 FromTU, cxxRecordDecl(hasName("A"), isImplicit())));
5009 EXPECT_TRUE(OptErr);
5010 // An error is set to the implicit class of X.
5011 OptErr =
5012 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
5013 FromTU, cxxRecordDecl(hasName("X"), isImplicit())));
5014 EXPECT_TRUE(OptErr);
Gabor Marton17c3eaf2019-07-01 12:44:39 +00005015}
5016
5017TEST_P(ErrorHandlingTest, ErrorIsNotPropagatedFromMemberToNamespace) {
5018 TranslationUnitDecl *FromTU = getTuDecl(
5019 std::string(R"(
5020 namespace X {
5021 void f() { )") + ErroneousStmt + R"( } // This member has the error
5022 // during import.
5023 void ok(); // The error should not prevent importing this.
5024 }; // An error will be set for X too.
5025 )",
5026 Lang_CXX);
5027 auto *FromX = FirstDeclMatcher<NamespaceDecl>().match(
5028 FromTU, namespaceDecl(hasName("X")));
5029 NamespaceDecl *ImportedX = Import(FromX, Lang_CXX);
5030
5031 // There is no error set for X.
5032 EXPECT_TRUE(ImportedX);
5033 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5034 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5035 ASSERT_FALSE(OptErr);
5036
5037 // An error is set for f().
5038 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
5039 FromTU, functionDecl(hasName("f")));
5040 OptErr = Importer->getImportDeclErrorIfAny(FromF);
5041 ASSERT_TRUE(OptErr);
5042 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5043 // And any subsequent import should fail.
5044 FunctionDecl *ImportedF = Import(FromF, Lang_CXX);
5045 EXPECT_FALSE(ImportedF);
5046
5047 // There is no error set for ok().
5048 auto *FromOK = FirstDeclMatcher<FunctionDecl>().match(
5049 FromTU, functionDecl(hasName("ok")));
5050 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
5051 EXPECT_FALSE(OptErr);
5052 // And we should be able to import.
5053 FunctionDecl *ImportedOK = Import(FromOK, Lang_CXX);
5054 EXPECT_TRUE(ImportedOK);
5055}
5056
Gabor Marton2afbfb62019-07-01 15:37:07 +00005057// An error should be set for a class if it had a previous import with an error
5058// from another TU.
5059TEST_P(ErrorHandlingTest,
5060 ImportedDeclWithErrorShouldFailTheImportOfDeclWhichMapToIt) {
5061 // We already have a fwd decl.
5062 TranslationUnitDecl *ToTU = getToTuDecl(
5063 "class X;", Lang_CXX);
5064 // Then we import a definition.
5065 {
5066 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5067 class X {
5068 void f() { )") + ErroneousStmt + R"( }
5069 void ok();
5070 };
5071 )",
5072 Lang_CXX);
5073 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5074 FromTU, cxxRecordDecl(hasName("X")));
5075 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX);
5076
5077 // An error is set for X ...
5078 EXPECT_FALSE(ImportedX);
5079 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5080 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5081 ASSERT_TRUE(OptErr);
5082 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5083 }
5084 // ... but the node had been created.
5085 auto *ToXDef = FirstDeclMatcher<CXXRecordDecl>().match(
5086 ToTU, cxxRecordDecl(hasName("X"), isDefinition()));
5087 // An error is set for "ToXDef" in the shared state.
5088 Optional<ImportError> OptErr =
5089 SharedStatePtr->getImportDeclErrorIfAny(ToXDef);
5090 ASSERT_TRUE(OptErr);
5091 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5092
5093 auto *ToXFwd = FirstDeclMatcher<CXXRecordDecl>().match(
5094 ToTU, cxxRecordDecl(hasName("X"), unless(isDefinition())));
5095 // An error is NOT set for the fwd Decl of X in the shared state.
5096 OptErr = SharedStatePtr->getImportDeclErrorIfAny(ToXFwd);
5097 ASSERT_FALSE(OptErr);
5098
5099 // Try to import X again but from another TU.
5100 {
5101 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5102 class X {
5103 void f() { )") + ErroneousStmt + R"( }
5104 void ok();
5105 };
5106 )",
5107 Lang_CXX, "input1.cc");
5108
5109 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5110 FromTU, cxxRecordDecl(hasName("X")));
5111 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX);
5112
5113 // If we did not save the errors for the "to" context then the below checks
5114 // would fail, because the lookup finds the fwd Decl of the existing
5115 // definition in the "to" context. We can reach the existing definition via
5116 // the found fwd Decl. That existing definition is structurally equivalent
5117 // (we check only the fields) with this one we want to import, so we return
5118 // with the existing definition, which is erroneous (one method is missing).
5119
5120 // The import should fail.
5121 EXPECT_FALSE(ImportedX);
5122 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5123 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5124 // And an error is set for this new X in the "from" ctx.
5125 ASSERT_TRUE(OptErr);
5126 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5127 }
5128}
5129
Gabor Marton303c98612019-06-25 08:00:51 +00005130INSTANTIATE_TEST_CASE_P(ParameterizedTests, ErrorHandlingTest,
5131 DefaultTestValuesForRunOptions, );
5132
Gabor Marton1ad4b992019-07-01 14:19:53 +00005133INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
5134 ::testing::Values(ArgVector()), );
5135
5136INSTANTIATE_TEST_CASE_P(ParameterizedTests, CanonicalRedeclChain,
5137 ::testing::Values(ArgVector()), );
5138
Gabor Martone73805f2019-07-08 12:49:13 +00005139TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) {
5140 Decl *FromTU = getTuDecl(
5141 R"(
5142 void f() {
5143 auto L = [](){};
5144 }
5145 )",
5146 Lang_CXX11, "input0.cc");
5147 auto Pattern = lambdaExpr();
5148 CXXRecordDecl *FromL =
5149 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5150
5151 auto ToL = Import(FromL, Lang_CXX11);
5152 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
5153 unsigned FromLSize =
5154 std::distance(FromL->decls().begin(), FromL->decls().end());
5155 EXPECT_NE(ToLSize, 0u);
5156 EXPECT_EQ(ToLSize, FromLSize);
5157}
5158
5159TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
5160 Decl *FromTU = getTuDecl(
5161 R"(
5162 template <typename F>
5163 void f(F L = [](){}) {}
5164 )",
5165 Lang_CXX11, "input0.cc");
5166 auto Pattern = lambdaExpr();
5167 CXXRecordDecl *FromL =
5168 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5169
5170 auto ToL = Import(FromL, Lang_CXX11);
5171 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
5172 unsigned FromLSize =
5173 std::distance(FromL->decls().begin(), FromL->decls().end());
5174 EXPECT_NE(ToLSize, 0u);
5175 EXPECT_EQ(ToLSize, FromLSize);
5176}
5177
Gabor Martonae512b82019-07-17 14:40:09 +00005178TEST_P(ASTImporterOptionSpecificTestBase, LambdaInGlobalScope) {
5179 Decl *FromTU = getTuDecl(
5180 R"(
5181 auto l1 = [](unsigned lp) { return 1; };
5182 auto l2 = [](int lp) { return 2; };
5183 int f(int p) {
5184 return l1(p) + l2(p);
5185 }
5186 )",
5187 Lang_CXX11, "input0.cc");
5188 FunctionDecl *FromF = FirstDeclMatcher<FunctionDecl>().match(
5189 FromTU, functionDecl(hasName("f")));
5190 FunctionDecl *ToF = Import(FromF, Lang_CXX11);
5191 EXPECT_TRUE(ToF);
5192}
5193
Balazs Keri2e160602019-08-12 10:07:38 +00005194TEST_P(ASTImporterOptionSpecificTestBase,
5195 ImportExistingFriendClassTemplateDef) {
5196 auto Code =
5197 R"(
5198 template <class T1, class T2>
5199 struct Base {
5200 template <class U1, class U2>
5201 friend struct Class;
5202 };
5203 template <class T1, class T2>
5204 struct Class { };
5205 )";
5206
5207 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
5208 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
5209
5210 auto *ToClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
5211 ToTU, classTemplateDecl(hasName("Class")));
5212 auto *ToClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
5213 ToTU, classTemplateDecl(hasName("Class")));
5214 ASSERT_FALSE(ToClassProto->isThisDeclarationADefinition());
5215 ASSERT_TRUE(ToClassDef->isThisDeclarationADefinition());
5216 // Previous friend decl is not linked to it!
5217 ASSERT_FALSE(ToClassDef->getPreviousDecl());
5218 ASSERT_EQ(ToClassDef->getMostRecentDecl(), ToClassDef);
5219 ASSERT_EQ(ToClassProto->getMostRecentDecl(), ToClassProto);
5220
5221 auto *FromClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
5222 FromTU, classTemplateDecl(hasName("Class")));
5223 auto *FromClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
5224 FromTU, classTemplateDecl(hasName("Class")));
5225 ASSERT_FALSE(FromClassProto->isThisDeclarationADefinition());
5226 ASSERT_TRUE(FromClassDef->isThisDeclarationADefinition());
5227 ASSERT_FALSE(FromClassDef->getPreviousDecl());
5228 ASSERT_EQ(FromClassDef->getMostRecentDecl(), FromClassDef);
5229 ASSERT_EQ(FromClassProto->getMostRecentDecl(), FromClassProto);
5230
5231 auto *ImportedDef = Import(FromClassDef, Lang_CXX);
5232 // At import we should find the definition for 'Class' even if the
5233 // prototype (inside 'friend') for it comes first in the AST and is not
5234 // linked to the definition.
5235 EXPECT_EQ(ImportedDef, ToClassDef);
5236}
5237
Gabor Martonaefcf512019-07-17 13:47:46 +00005238struct LLDBLookupTest : ASTImporterOptionSpecificTestBase {
5239 LLDBLookupTest() {
5240 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
5241 ASTContext &FromContext, FileManager &FromFileManager,
5242 bool MinimalImport,
5243 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
5244 return new ASTImporter(ToContext, ToFileManager, FromContext,
5245 FromFileManager, MinimalImport,
5246 // We use the regular lookup.
5247 /*SharedState=*/nullptr);
5248 };
5249 }
5250};
5251
5252TEST_P(LLDBLookupTest, ImporterShouldFindInTransparentContext) {
5253 TranslationUnitDecl *ToTU = getToTuDecl(
5254 R"(
5255 extern "C" {
5256 class X{};
5257 };
5258 )",
5259 Lang_CXX);
5260 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(
5261 ToTU, cxxRecordDecl(hasName("X")));
5262
5263 // Set up a stub external storage.
5264 ToTU->setHasExternalLexicalStorage(true);
5265 // Set up DeclContextBits.HasLazyExternalLexicalLookups to true.
5266 ToTU->setMustBuildLookupTable();
5267 struct TestExternalASTSource : ExternalASTSource {};
5268 ToTU->getASTContext().setExternalSource(new TestExternalASTSource());
5269
5270 Decl *FromTU = getTuDecl(
5271 R"(
5272 class X;
5273 )",
5274 Lang_CXX);
5275 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5276 FromTU, cxxRecordDecl(hasName("X")));
5277 auto *ImportedX = Import(FromX, Lang_CXX);
5278 // The lookup must find the existing class definition in the LinkageSpecDecl.
5279 // Then the importer renders the existing and the new decl into one chain.
5280 EXPECT_EQ(ImportedX->getCanonicalDecl(), ToX->getCanonicalDecl());
5281}
5282
Richard Sandifordeb485fb2019-08-09 08:52:54 +00005283struct SVEBuiltins : ASTImporterOptionSpecificTestBase {};
5284
5285TEST_P(SVEBuiltins, ImportTypes) {
5286 static const char *const TypeNames[] = {
5287 "__SVInt8_t",
5288 "__SVInt16_t",
5289 "__SVInt32_t",
5290 "__SVInt64_t",
5291 "__SVUint8_t",
5292 "__SVUint16_t",
5293 "__SVUint32_t",
5294 "__SVUint64_t",
5295 "__SVFloat16_t",
5296 "__SVFloat32_t",
5297 "__SVFloat64_t",
5298 "__SVBool_t"
5299 };
5300
5301 TranslationUnitDecl *ToTU = getToTuDecl("", Lang_CXX);
5302 TranslationUnitDecl *FromTU = getTuDecl("", Lang_CXX, "input.cc");
5303 for (auto *TypeName : TypeNames) {
5304 auto *ToTypedef = FirstDeclMatcher<TypedefDecl>().match(
5305 ToTU, typedefDecl(hasName(TypeName)));
5306 QualType ToType = ToTypedef->getUnderlyingType();
5307
5308 auto *FromTypedef = FirstDeclMatcher<TypedefDecl>().match(
5309 FromTU, typedefDecl(hasName(TypeName)));
5310 QualType FromType = FromTypedef->getUnderlyingType();
5311
5312 QualType ImportedType = ImportType(FromType, FromTypedef, Lang_CXX);
5313 EXPECT_EQ(ImportedType, ToType);
5314 }
5315}
5316
Balazs Kerib427c062019-08-13 08:04:06 +00005317TEST_P(ASTImporterOptionSpecificTestBase, ImportOfDefaultImplicitFunctions) {
5318 // Test that import of implicit functions works and the functions
5319 // are merged into one chain.
5320 auto GetDeclToImport = [this](StringRef File) {
5321 Decl *FromTU = getTuDecl(
5322 R"(
5323 struct X { };
5324 // Force generating some implicit operator definitions for X.
5325 void f() { X x1, x2; x1 = x2; X *x3 = new X; delete x3; }
5326 )",
5327 Lang_CXX11, File);
5328 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
5329 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
5330 // Destructor is picked as one example of implicit function.
5331 return FromD->getDestructor();
5332 };
5333
5334 auto *ToD1 = Import(GetDeclToImport("input1.cc"), Lang_CXX11);
5335 ASSERT_TRUE(ToD1);
5336
5337 auto *ToD2 = Import(GetDeclToImport("input2.cc"), Lang_CXX11);
5338 ASSERT_TRUE(ToD2);
5339
5340 EXPECT_EQ(ToD1->getCanonicalDecl(), ToD2->getCanonicalDecl());
5341}
5342
5343TEST_P(ASTImporterOptionSpecificTestBase,
5344 ImportOfExplicitlyDefaultedOrDeleted) {
5345 Decl *FromTU = getTuDecl(
5346 R"(
5347 struct X { X() = default; X(const X&) = delete; };
5348 )",
5349 Lang_CXX11);
5350 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5351 FromTU, cxxRecordDecl(hasName("X")));
5352 auto *ImportedX = Import(FromX, Lang_CXX11);
5353 auto *Constr1 = FirstDeclMatcher<CXXConstructorDecl>().match(
5354 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));
5355 auto *Constr2 = LastDeclMatcher<CXXConstructorDecl>().match(
5356 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));
5357
5358 ASSERT_TRUE(ImportedX);
5359 EXPECT_TRUE(Constr1->isDefaulted());
5360 EXPECT_TRUE(Constr1->isExplicitlyDefaulted());
5361 EXPECT_TRUE(Constr2->isDeletedAsWritten());
5362 EXPECT_EQ(ImportedX->isAggregate(), FromX->isAggregate());
5363}
5364
Richard Sandifordeb485fb2019-08-09 08:52:54 +00005365INSTANTIATE_TEST_CASE_P(ParameterizedTests, SVEBuiltins,
5366 ::testing::Values(ArgVector{"-target",
5367 "aarch64-linux-gnu"}), );
5368
Gabor Marton54058b52018-12-17 13:53:12 +00005369INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
5370 DefaultTestValuesForRunOptions, );
5371
Gabor Marton1ad4b992019-07-01 14:19:53 +00005372INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportPath,
5373 ::testing::Values(ArgVector()), );
5374
Gabor Marton19f4f392018-06-25 13:04:37 +00005375INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
5376 DefaultTestValuesForRunOptions, );
5377
5378INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
5379 DefaultTestValuesForRunOptions, );
5380
5381INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
5382 DefaultTestValuesForRunOptions, );
5383
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005384INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
Gabor Marton19f4f392018-06-25 13:04:37 +00005385 DefaultTestValuesForRunOptions, );
5386
Raphael Isemanne9bc35f2019-04-29 21:02:35 +00005387INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedirectingImporterTest,
5388 DefaultTestValuesForRunOptions, );
5389
Gabor Marton19f4f392018-06-25 13:04:37 +00005390INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
5391 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00005392
Gabor Martone331e632019-02-18 13:09:27 +00005393INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
5394 DefaultTestValuesForRunOptions, );
5395
Gabor Marton54058b52018-12-17 13:53:12 +00005396INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00005397 DefaultTestValuesForRunOptions, );
5398
Balazs Kerie9719f92019-08-07 12:40:17 +00005399INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionTemplates,
5400 DefaultTestValuesForRunOptions, );
5401
Gabor Marton54058b52018-12-17 13:53:12 +00005402INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00005403 DefaultTestValuesForRunOptions, );
5404
Gabor Marton7df342a2018-12-17 12:42:12 +00005405INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
5406 DefaultTestValuesForRunOptions, );
5407
Gabor Marton5254e642018-06-27 13:32:50 +00005408INSTANTIATE_TEST_CASE_P(ParameterizedTests,
5409 ImportFunctionTemplateSpecializations,
5410 DefaultTestValuesForRunOptions, );
5411
Gabor Martonac3a5d62018-09-17 12:04:52 +00005412INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
5413 DefaultTestValuesForRunOptions, );
5414
5415INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
5416 DefaultTestValuesForRunOptions, );
5417
Gabor Martonaefcf512019-07-17 13:47:46 +00005418INSTANTIATE_TEST_CASE_P(ParameterizedTests, LLDBLookupTest,
5419 DefaultTestValuesForRunOptions, );
5420
Balazs Kerib427c062019-08-13 08:04:06 +00005421
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00005422} // end namespace ast_matchers
5423} // end namespace clang