blob: d517d633c43eaebc62b467d84deaf53a01059b83 [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,
319 bool MinimalImport, ASTImporterLookupTable *LookupTable) {
320 return new RedirectingImporter(ToContext, ToFileManager, FromContext,
321 FromFileManager, MinimalImport,
322 LookupTable);
323 };
324 }
325};
326
327// Test that an ASTImporter subclass can intercept an import call.
328TEST_P(RedirectingImporterTest, InterceptImport) {
329 Decl *From, *To;
330 std::tie(From, To) =
331 getImportedDecl("class shouldNotBeImported {};", Lang_CXX,
332 "class realDecl {};", Lang_CXX, "shouldNotBeImported");
333 auto *Imported = cast<CXXRecordDecl>(To);
334 EXPECT_EQ(Imported->getQualifiedNameAsString(), "realDecl");
335
336 // Make sure our importer prevented the importing of the decl.
337 auto *ToTU = Imported->getTranslationUnitDecl();
338 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
339 unsigned count =
340 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
341 EXPECT_EQ(0U, count);
342}
343
344// Test that when we indirectly import a declaration the custom ASTImporter
345// is still intercepting the import.
346TEST_P(RedirectingImporterTest, InterceptIndirectImport) {
347 Decl *From, *To;
348 std::tie(From, To) =
349 getImportedDecl("class shouldNotBeImported {};"
350 "class F { shouldNotBeImported f; };",
351 Lang_CXX, "class realDecl {};", Lang_CXX, "F");
352
353 // Make sure our ASTImporter prevented the importing of the decl.
354 auto *ToTU = To->getTranslationUnitDecl();
355 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
356 unsigned count =
357 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
358 EXPECT_EQ(0U, count);
359}
360
Gabor Marton1ad4b992019-07-01 14:19:53 +0000361struct ImportPath : ASTImporterOptionSpecificTestBase {
362 Decl *FromTU;
363 FunctionDecl *D0, *D1, *D2;
364 ImportPath() {
365 FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
366 auto Pattern = functionDecl(hasName("f"));
367 D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
368 D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
369 D1 = D2->getPreviousDecl();
370 }
371};
372
373TEST_P(ImportPath, Push) {
374 ASTImporter::ImportPathTy path;
375 path.push(D0);
376 EXPECT_FALSE(path.hasCycleAtBack());
377}
378
379TEST_P(ImportPath, SmallCycle) {
380 ASTImporter::ImportPathTy path;
381 path.push(D0);
382 path.push(D0);
383 EXPECT_TRUE(path.hasCycleAtBack());
384 path.pop();
385 EXPECT_FALSE(path.hasCycleAtBack());
386 path.push(D0);
387 EXPECT_TRUE(path.hasCycleAtBack());
388}
389
390TEST_P(ImportPath, GetSmallCycle) {
391 ASTImporter::ImportPathTy path;
392 path.push(D0);
393 path.push(D0);
394 EXPECT_TRUE(path.hasCycleAtBack());
395 std::array<Decl* ,2> Res;
396 int i = 0;
397 for (Decl *Di : path.getCycleAtBack()) {
398 Res[i++] = Di;
399 }
400 ASSERT_EQ(i, 2);
401 EXPECT_EQ(Res[0], D0);
402 EXPECT_EQ(Res[1], D0);
403}
404
405TEST_P(ImportPath, GetCycle) {
406 ASTImporter::ImportPathTy path;
407 path.push(D0);
408 path.push(D1);
409 path.push(D2);
410 path.push(D0);
411 EXPECT_TRUE(path.hasCycleAtBack());
412 std::array<Decl* ,4> Res;
413 int i = 0;
414 for (Decl *Di : path.getCycleAtBack()) {
415 Res[i++] = Di;
416 }
417 ASSERT_EQ(i, 4);
418 EXPECT_EQ(Res[0], D0);
419 EXPECT_EQ(Res[1], D2);
420 EXPECT_EQ(Res[2], D1);
421 EXPECT_EQ(Res[3], D0);
422}
423
424TEST_P(ImportPath, CycleAfterCycle) {
425 ASTImporter::ImportPathTy path;
426 path.push(D0);
427 path.push(D1);
428 path.push(D0);
429 path.push(D1);
430 path.push(D2);
431 path.push(D0);
432 EXPECT_TRUE(path.hasCycleAtBack());
433 std::array<Decl* ,4> Res;
434 int i = 0;
435 for (Decl *Di : path.getCycleAtBack()) {
436 Res[i++] = Di;
437 }
438 ASSERT_EQ(i, 4);
439 EXPECT_EQ(Res[0], D0);
440 EXPECT_EQ(Res[1], D2);
441 EXPECT_EQ(Res[2], D1);
442 EXPECT_EQ(Res[3], D0);
443
444 path.pop();
445 path.pop();
446 path.pop();
447 EXPECT_TRUE(path.hasCycleAtBack());
448 i = 0;
449 for (Decl *Di : path.getCycleAtBack()) {
450 Res[i++] = Di;
451 }
452 ASSERT_EQ(i, 3);
453 EXPECT_EQ(Res[0], D0);
454 EXPECT_EQ(Res[1], D1);
455 EXPECT_EQ(Res[2], D0);
456
457 path.pop();
458 EXPECT_FALSE(path.hasCycleAtBack());
459}
460
Gabor Marton19f4f392018-06-25 13:04:37 +0000461TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000462 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000463 testImport(
464 "void declToImport() { (void)\"foo\"; }",
465 Lang_CXX, "", Lang_CXX, Verifier,
466 functionDecl(hasDescendant(
467 stringLiteral(hasType(asString("const char [4]"))))));
468 testImport(
469 "void declToImport() { (void)L\"foo\"; }",
470 Lang_CXX, "", Lang_CXX, Verifier,
471 functionDecl(hasDescendant(
472 stringLiteral(hasType(asString("const wchar_t [4]"))))));
473 testImport(
474 "void declToImport() { (void) \"foo\" \"bar\"; }",
475 Lang_CXX, "", Lang_CXX, Verifier,
476 functionDecl(hasDescendant(
477 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000478}
479
Tom Roeder521f0042019-02-26 19:26:41 +0000480TEST_P(ImportExpr, ImportChooseExpr) {
481 MatchVerifier<Decl> Verifier;
482
483 // This case tests C code that is not condition-dependent and has a true
484 // condition.
485 testImport(
486 "void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }",
487 Lang_C, "", Lang_C, Verifier,
488 functionDecl(hasDescendant(chooseExpr())));
489}
490
Gabor Marton19f4f392018-06-25 13:04:37 +0000491TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000492 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000493 testImport(
494 "void declToImport() { (void)__null; }",
495 Lang_CXX, "", Lang_CXX, Verifier,
496 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000497}
498
Gabor Marton19f4f392018-06-25 13:04:37 +0000499TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000500 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000501 testImport(
502 "void declToImport() { (void)nullptr; }",
503 Lang_CXX11, "", Lang_CXX11, Verifier,
504 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000505}
506
507
Gabor Marton19f4f392018-06-25 13:04:37 +0000508TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000509 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000510 testImport(
511 "void declToImport() { (void)1.0; }",
512 Lang_C, "", Lang_C, Verifier,
513 functionDecl(hasDescendant(
514 floatLiteral(equals(1.0), hasType(asString("double"))))));
515 testImport(
516 "void declToImport() { (void)1.0e-5f; }",
517 Lang_C, "", Lang_C, Verifier,
518 functionDecl(hasDescendant(
519 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000520}
521
Gabor Martonbf7f18b2018-08-09 12:18:07 +0000522TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
523 MatchVerifier<Decl> Verifier;
524 testImport(
525 "void declToImport() { (void)1.0i; }",
526 Lang_CXX14, "", Lang_CXX14, Verifier,
527 functionDecl(hasDescendant(imaginaryLiteral())));
528}
529
Gabor Marton19f4f392018-06-25 13:04:37 +0000530TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000531 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000532 testImport(
533 "void declToImport() {"
534 " struct s { int x; long y; unsigned z; }; "
535 " (void)(struct s){ 42, 0L, 1U }; }",
536 Lang_CXX, "", Lang_CXX, Verifier,
537 functionDecl(hasDescendant(
538 compoundLiteralExpr(
539 hasType(asString("struct s")),
540 has(initListExpr(
541 hasType(asString("struct s")),
542 has(integerLiteral(
543 equals(42), hasType(asString("int")))),
544 has(integerLiteral(
545 equals(0), hasType(asString("long")))),
546 has(integerLiteral(
547 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000548}
549
Gabor Marton19f4f392018-06-25 13:04:37 +0000550TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000551 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000552 testImport(
553 "class declToImport { void f() { (void)this; } };",
554 Lang_CXX, "", Lang_CXX, Verifier,
555 cxxRecordDecl(
556 hasMethod(
557 hasDescendant(
558 cxxThisExpr(
559 hasType(
560 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000561}
562
Gabor Marton19f4f392018-06-25 13:04:37 +0000563TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000564 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000565 testImport(
566 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
567 Lang_C, "", Lang_C, Verifier,
568 functionDecl(hasDescendant(
569 atomicExpr(
570 has(ignoringParenImpCasts(
571 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
572 hasType(asString("int *"))))),
573 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000574}
575
Gabor Marton19f4f392018-06-25 13:04:37 +0000576TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000577 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000578 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000579 "void declToImport() { loop: goto loop; (void)&&loop; }",
580 Lang_C, "", Lang_C, Verifier,
581 functionDecl(
582 hasDescendant(
583 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
584 hasDescendant(
585 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000586}
587
588AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
589 internal::Matcher<NamedDecl>, InnerMatcher) {
590 const NamedDecl *Template = Node.getTemplatedDecl();
591 return Template && InnerMatcher.matches(*Template, Finder, Builder);
592}
593
Gabor Marton19f4f392018-06-25 13:04:37 +0000594TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000595 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000596 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000597 "template<typename T> class dummy { void f() { dummy X(*this); } };"
598 "typedef dummy<int> declToImport;"
599 "template class dummy<int>;",
600 Lang_CXX, "", Lang_CXX, Verifier,
601 typedefDecl(hasType(templateSpecializationType(
602 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
603 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
604 hasName("f"),
605 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
606 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
607 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000608 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000609}
610
Gabor Marton19f4f392018-06-25 13:04:37 +0000611TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000612 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000613 testImport(
614 "void declToImport() { int b; switch (b) { case 1: break; } }",
615 Lang_C, "", Lang_C, Verifier,
616 functionDecl(hasDescendant(
617 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000618}
619
Gabor Marton19f4f392018-06-25 13:04:37 +0000620TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000621 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000622 testImport(
623 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
624 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000625 functionDecl(hasDescendant(
626 varDecl(
627 hasName("C"),
628 hasType(asString("int")),
629 hasInitializer(
630 stmtExpr(
631 hasAnySubstatement(declStmt(hasSingleDecl(
632 varDecl(
633 hasName("X"),
634 hasType(asString("int")),
635 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000636 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000637 hasDescendant(
638 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000639}
640
Gabor Marton19f4f392018-06-25 13:04:37 +0000641TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000642 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000643 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000644 "void declToImport() { (void)(true ? 1 : -5); }",
645 Lang_CXX, "", Lang_CXX, Verifier,
646 functionDecl(hasDescendant(
647 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000648 hasCondition(cxxBoolLiteral(equals(true))),
649 hasTrueExpression(integerLiteral(equals(1))),
650 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000651 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
652 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000653}
654
Gabor Marton19f4f392018-06-25 13:04:37 +0000655TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000656 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000657 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000658 "void declToImport() { (void)(1 ?: -5); }",
659 Lang_CXX, "", Lang_CXX, Verifier,
660 functionDecl(hasDescendant(
661 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000662 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000663 implicitCastExpr(
664 hasSourceExpression(opaqueValueExpr(
665 hasSourceExpression(integerLiteral(equals(1))))),
666 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000667 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000668 opaqueValueExpr(
669 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000670 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000671 unaryOperator(
672 hasOperatorName("-"),
673 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000674}
675
Gabor Marton19f4f392018-06-25 13:04:37 +0000676TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000677 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000678 testImport(
679 "void declToImport() {"
680 " struct point { double x; double y; };"
681 " struct point ptarray[10] = "
682 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
683 Lang_C, "", Lang_C, Verifier,
684 functionDecl(hasDescendant(
685 initListExpr(
686 has(designatedInitExpr(
687 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000688 hasDescendant(floatLiteral(equals(1.0))),
689 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000690 has(designatedInitExpr(
691 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000692 hasDescendant(floatLiteral(equals(2.0))),
693 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000694 has(designatedInitExpr(
695 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000696 hasDescendant(floatLiteral(equals(1.0))),
697 hasDescendant(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000698}
699
Gabor Marton19f4f392018-06-25 13:04:37 +0000700TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000701 MatchVerifier<Decl> Verifier;
702 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000703 testImport(
704 "void declToImport() { (void)__func__; }",
705 Lang_CXX, "", Lang_CXX, Verifier,
706 functionDecl(hasDescendant(
707 predefinedExpr(
708 hasType(
709 asString("const char [13]")),
710 has(stringLiteral(hasType(
711 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000712}
713
Gabor Marton19f4f392018-06-25 13:04:37 +0000714TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000715 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000716 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000717 "void declToImport() {"
718 " struct point { double x; double y; };"
719 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
720 " [0].x = 1.0 }; }",
721 Lang_CXX, "", Lang_CXX, Verifier,
722 functionDecl(hasDescendant(
723 initListExpr(
724 has(
725 cxxConstructExpr(
726 requiresZeroInitialization())),
727 has(
728 initListExpr(
729 hasType(asString("struct point")),
730 has(floatLiteral(equals(1.0))),
731 has(implicitValueInitExpr(
732 hasType(asString("double")))))),
733 has(
734 initListExpr(
735 hasType(asString("struct point")),
736 has(floatLiteral(equals(2.0))),
737 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000738}
739
740
Aleksei Sidorina693b372016-09-28 10:16:56 +0000741const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
742
Gabor Marton19f4f392018-06-25 13:04:37 +0000743TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000744 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000745 testImport(
746 "void declToImport(__builtin_va_list list, ...) {"
747 " (void)__builtin_va_arg(list, int); }",
748 Lang_CXX, "", Lang_CXX, Verifier,
749 functionDecl(hasDescendant(
750 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000751}
752
Gabor Marton19f4f392018-06-25 13:04:37 +0000753TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000754 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000755 testImport(
756 "struct C {};"
757 "void declToImport() { C c = C(); }",
758 Lang_CXX, "", Lang_CXX, Verifier,
759 functionDecl(hasDescendant(
760 exprWithCleanups(has(cxxConstructExpr(
761 has(materializeTemporaryExpr(has(implicitCastExpr(
762 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000763}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000764
Gabor Marton19f4f392018-06-25 13:04:37 +0000765TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000766 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000767 testImport(
768 "void declToImport() { typedef _Atomic(int) a_int; }",
769 Lang_CXX11, "", Lang_CXX11, Verifier,
770 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000771}
772
Gabor Marton19f4f392018-06-25 13:04:37 +0000773TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000774 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000775 testImport(
776 "template <typename T> void declToImport() { };",
777 Lang_CXX, "", Lang_CXX, Verifier,
778 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000779}
780
Gabor Marton19f4f392018-06-25 13:04:37 +0000781TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000782 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000783 testImport(
784 "template <typename T> struct C { T t; };"
785 "template <typename T> void declToImport() {"
786 " C<T> d;"
787 " (void)d.t;"
788 "}"
789 "void instantiate() { declToImport<int>(); }",
790 Lang_CXX, "", Lang_CXX, Verifier,
791 functionTemplateDecl(hasDescendant(
792 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
793 testImport(
794 "template <typename T> struct C { T t; };"
795 "template <typename T> void declToImport() {"
796 " C<T> d;"
797 " (void)(&d)->t;"
798 "}"
799 "void instantiate() { declToImport<int>(); }",
800 Lang_CXX, "", Lang_CXX, Verifier,
801 functionTemplateDecl(hasDescendant(
802 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000803}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000804
Gabor Marton19f4f392018-06-25 13:04:37 +0000805TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000806 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000807 testImport(
808 "template <int K>"
809 "struct dummy { static const int i = K; };"
810 "template <int K> using dummy2 = dummy<K>;"
811 "int declToImport() { return dummy2<3>::i; }",
812 Lang_CXX11, "", Lang_CXX11, Verifier,
813 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000814 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000815 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
816}
817
818const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
819 varTemplateSpecializationDecl;
820
Gabor Marton19f4f392018-06-25 13:04:37 +0000821TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000822 MatchVerifier<Decl> Verifier;
823 testImport(
824 "template <typename T>"
825 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000826 "void declToImport() { (void)pi<int>; }",
827 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000828 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000829 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000830 unless(hasAncestor(translationUnitDecl(has(varDecl(
831 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000832}
833
Gabor Marton19f4f392018-06-25 13:04:37 +0000834TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000835 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000836 testImport(
837 "template <typename... Args>"
838 "struct dummy {"
839 " dummy(Args... args) {}"
840 " static const int i = 4;"
841 "};"
842 "int declToImport() { return dummy<int>::i; }",
843 Lang_CXX11, "", Lang_CXX11, Verifier,
844 functionDecl(hasDescendant(
845 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000846}
847
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000848const internal::VariadicDynCastAllOfMatcher<Type,
849 DependentTemplateSpecializationType>
850 dependentTemplateSpecializationType;
851
Gabor Marton19f4f392018-06-25 13:04:37 +0000852TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000853 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000854 testImport(
855 "template<typename T>"
856 "struct A;"
857 "template<typename T>"
858 "struct declToImport {"
859 " typename A<T>::template B<T> a;"
860 "};",
861 Lang_CXX, "", Lang_CXX, Verifier,
862 classTemplateDecl(has(cxxRecordDecl(has(
863 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000864}
865
866const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
867 sizeOfPackExpr;
868
Gabor Marton19f4f392018-06-25 13:04:37 +0000869TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000870 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000871 testImport(
872 "template <typename... Ts>"
873 "void declToImport() {"
874 " const int i = sizeof...(Ts);"
875 "};"
876 "void g() { declToImport<int>(); }",
877 Lang_CXX11, "", Lang_CXX11, Verifier,
878 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000879 testImport(
880 "template <typename... Ts>"
881 "using X = int[sizeof...(Ts)];"
882 "template <typename... Us>"
883 "struct Y {"
884 " X<Us..., int, double, int, Us...> f;"
885 "};"
886 "Y<float, int> declToImport;",
887 Lang_CXX11, "", Lang_CXX11, Verifier,
888 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
889 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
890}
891
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000892/// \brief Matches __builtin_types_compatible_p:
893/// GNU extension to check equivalent types
894/// Given
895/// \code
896/// __builtin_types_compatible_p(int, int)
897/// \endcode
898// will generate TypeTraitExpr <...> 'int'
899const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
900
Gabor Marton19f4f392018-06-25 13:04:37 +0000901TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000902 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000903 testImport(
904 "void declToImport() { "
905 " (void)__builtin_types_compatible_p(int, int);"
906 "}",
907 Lang_C, "", Lang_C, Verifier,
908 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000909}
910
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000911const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
912
Gabor Marton19f4f392018-06-25 13:04:37 +0000913TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000914 MatchVerifier<Decl> Verifier;
915 testImport(
916 "namespace std { class type_info {}; }"
917 "void declToImport() {"
918 " int x;"
919 " auto a = typeid(int); auto b = typeid(x);"
920 "}",
921 Lang_CXX11, "", Lang_CXX11, Verifier,
922 functionDecl(
923 hasDescendant(varDecl(
924 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
925 hasDescendant(varDecl(
926 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
927}
928
Gabor Marton19f4f392018-06-25 13:04:37 +0000929TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000930 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000931 testImport(
932 "template<typename T> struct declToImport {"
933 " void m() { (void)__is_pod(T); }"
934 "};"
935 "void f() { declToImport<int>().m(); }",
936 Lang_CXX11, "", Lang_CXX11, Verifier,
937 classTemplateDecl(has(cxxRecordDecl(has(
938 functionDecl(hasDescendant(
939 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000940}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000941
Gabor Marton6e1510c2018-07-12 11:50:21 +0000942TEST_P(ImportDecl, ImportRecordDeclInFunc) {
943 MatchVerifier<Decl> Verifier;
944 testImport("int declToImport() { "
945 " struct data_t {int a;int b;};"
946 " struct data_t d;"
947 " return 0;"
948 "}",
949 Lang_C, "", Lang_C, Verifier,
950 functionDecl(hasBody(compoundStmt(
951 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
952}
953
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000954TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000955 Decl *FromTU = getTuDecl("int declToImport() { "
956 " struct data_t {int a;int b;};"
957 " struct data_t d;"
958 " return 0;"
959 "}",
960 Lang_C, "input.c");
Gabor Martonfe68e292018-08-06 14:38:37 +0000961 auto *FromVar =
Gabor Marton6e1510c2018-07-12 11:50:21 +0000962 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
963 ASSERT_TRUE(FromVar);
964 auto ToType =
965 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
966 EXPECT_FALSE(ToType.isNull());
967}
968
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000969TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000970 // This construct is not supported by ASTImporter.
Gabor Martonfe68e292018-08-06 14:38:37 +0000971 Decl *FromTU = getTuDecl(
972 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
973 Lang_C, "input.c");
974 auto *From = FirstDeclMatcher<FunctionDecl>().match(
975 FromTU, functionDecl(hasName("declToImport")));
Gabor Marton6e1510c2018-07-12 11:50:21 +0000976 ASSERT_TRUE(From);
Gabor Martonfe68e292018-08-06 14:38:37 +0000977 auto *To = Import(From, Lang_C);
978 EXPECT_EQ(To, nullptr);
979}
980
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000981TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +0000982 Decl *FromTU = getTuDecl(
983 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
984 "int declToImport(){ return NONAME_SIZEOF(int); }",
985 Lang_C, "input.c");
986 auto *From = FirstDeclMatcher<FunctionDecl>().match(
987 FromTU, functionDecl(hasName("declToImport")));
988 ASSERT_TRUE(From);
989 auto *To = Import(From, Lang_C);
990 ASSERT_TRUE(To);
991 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
992 To, functionDecl(hasName("declToImport"),
993 hasDescendant(unaryExprOrTypeTraitExpr()))));
994}
995
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000996TEST_P(ASTImporterOptionSpecificTestBase,
997 ImportRecordDeclInFuncParamsFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +0000998 // This construct is not supported by ASTImporter.
999 Decl *FromTU = getTuDecl(
1000 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
1001 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
1002 Lang_C, "input.c");
1003 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1004 FromTU, functionDecl(hasName("declToImport")));
1005 ASSERT_TRUE(From);
1006 auto *To = Import(From, Lang_C);
Gabor Marton6e1510c2018-07-12 11:50:21 +00001007 EXPECT_EQ(To, nullptr);
1008}
1009
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001010const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1011 cxxPseudoDestructorExpr;
1012
Gabor Marton19f4f392018-06-25 13:04:37 +00001013TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001014 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001015 testImport(
1016 "typedef int T;"
1017 "void declToImport(int *p) {"
1018 " T t;"
1019 " p->T::~T();"
1020 "}",
1021 Lang_CXX, "", Lang_CXX, Verifier,
1022 functionDecl(hasDescendant(
1023 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001024}
1025
Gabor Marton19f4f392018-06-25 13:04:37 +00001026TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001027 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001028 testImport(
1029 "namespace foo { int bar; }"
1030 "void declToImport() { using foo::bar; }",
1031 Lang_CXX, "", Lang_CXX, Verifier,
1032 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001033}
1034
1035/// \brief Matches shadow declarations introduced into a scope by a
1036/// (resolved) using declaration.
1037///
1038/// Given
1039/// \code
1040/// namespace n { int f; }
1041/// namespace declToImport { using n::f; }
1042/// \endcode
1043/// usingShadowDecl()
1044/// matches \code f \endcode
1045const internal::VariadicDynCastAllOfMatcher<Decl,
1046 UsingShadowDecl> usingShadowDecl;
1047
Gabor Marton19f4f392018-06-25 13:04:37 +00001048TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001049 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001050 testImport(
1051 "namespace foo { int bar; }"
1052 "namespace declToImport { using foo::bar; }",
1053 Lang_CXX, "", Lang_CXX, Verifier,
1054 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001055}
1056
Gabor Marton19f4f392018-06-25 13:04:37 +00001057TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001058 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001059 testImport(
1060 "template<typename T> int foo();"
1061 "template <typename T> void declToImport() {"
1062 " (void)::foo<T>;"
1063 " (void)::template foo<T>;"
1064 "}"
1065 "void instantiate() { declToImport<int>(); }",
1066 Lang_CXX, "", Lang_CXX, Verifier,
1067 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001068}
1069
Gabor Marton19f4f392018-06-25 13:04:37 +00001070TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001071 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001072 testImport(
1073 "template <typename T> struct C { T t; };"
1074 "template <typename T> void declToImport() {"
1075 " C<T> d;"
1076 " d.t = T();"
1077 "}"
1078 "void instantiate() { declToImport<int>(); }",
1079 Lang_CXX, "", Lang_CXX, Verifier,
1080 functionTemplateDecl(hasDescendant(
1081 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1082 testImport(
1083 "template <typename T> struct C { T t; };"
1084 "template <typename T> void declToImport() {"
1085 " C<T> d;"
1086 " (&d)->t = T();"
1087 "}"
1088 "void instantiate() { declToImport<int>(); }",
1089 Lang_CXX, "", Lang_CXX, Verifier,
1090 functionTemplateDecl(hasDescendant(
1091 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001092}
1093
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001094/// Check that function "declToImport()" (which is the templated function
1095/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1096/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001097TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001098 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001099 testImport(
1100 "template <typename T> void declToImport() { T a = 1; }"
1101 "void instantiate() { declToImport<int>(); }",
1102 Lang_CXX, "", Lang_CXX, Verifier,
1103 functionTemplateDecl(hasAncestor(translationUnitDecl(
1104 unless(has(functionDecl(hasName("declToImport"))))))));
1105 testImport(
1106 "template <typename T> struct declToImport { T t; };"
1107 "void instantiate() { declToImport<int>(); }",
1108 Lang_CXX, "", Lang_CXX, Verifier,
1109 classTemplateDecl(hasAncestor(translationUnitDecl(
1110 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001111}
1112
Gabor Marton19f4f392018-06-25 13:04:37 +00001113TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001114 MatchVerifier<Decl> Verifier;
1115 auto Code =
1116 R"s(
1117 struct declToImport {
1118 template <typename T0> struct X;
1119 template <typename T0> struct X<T0 *> {};
1120 };
1121 )s";
1122 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1123 recordDecl(has(classTemplateDecl()),
1124 has(classTemplateSpecializationDecl())));
1125}
1126
Gabor Marton19f4f392018-06-25 13:04:37 +00001127TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001128 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001129 testImport(
1130 "class declToImport {"
1131 " void f() { *this = declToImport(); }"
1132 "};",
1133 Lang_CXX, "", Lang_CXX, Verifier,
1134 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1135 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001136}
1137
Gabor Marton19f4f392018-06-25 13:04:37 +00001138TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001139 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001140 testImport(
1141 "template<typename T, int Size> class declToImport {"
1142 " T data[Size];"
1143 "};",
1144 Lang_CXX, "", Lang_CXX, Verifier,
1145 classTemplateDecl(has(cxxRecordDecl(
1146 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001147}
1148
Balazs Keri5f4fd8b2019-03-14 14:20:23 +00001149TEST_P(ASTImporterOptionSpecificTestBase, ImportBeginLocOfDeclRefExpr) {
1150 Decl *FromTU = getTuDecl(
1151 "class A { public: static int X; }; void f() { (void)A::X; }", Lang_CXX);
1152 auto From = FirstDeclMatcher<FunctionDecl>().match(
1153 FromTU, functionDecl(hasName("f")));
1154 ASSERT_TRUE(From);
1155 ASSERT_TRUE(
1156 cast<CStyleCastExpr>(cast<CompoundStmt>(From->getBody())->body_front())
1157 ->getSubExpr()
1158 ->getBeginLoc()
1159 .isValid());
1160 FunctionDecl *To = Import(From, Lang_CXX);
1161 ASSERT_TRUE(To);
1162 ASSERT_TRUE(
1163 cast<CStyleCastExpr>(cast<CompoundStmt>(To->getBody())->body_front())
1164 ->getSubExpr()
1165 ->getBeginLoc()
1166 .isValid());
1167}
1168
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001169TEST_P(ASTImporterOptionSpecificTestBase,
1170 ImportOfTemplatedDeclOfClassTemplateDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001171 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1172 auto From =
1173 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1174 ASSERT_TRUE(From);
1175 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1176 ASSERT_TRUE(To);
1177 Decl *ToTemplated = To->getTemplatedDecl();
1178 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1179 EXPECT_TRUE(ToTemplated1);
1180 EXPECT_EQ(ToTemplated1, ToTemplated);
1181}
1182
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001183TEST_P(ASTImporterOptionSpecificTestBase,
1184 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001185 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1186 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1187 FromTU, functionTemplateDecl());
1188 ASSERT_TRUE(From);
1189 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1190 ASSERT_TRUE(To);
1191 Decl *ToTemplated = To->getTemplatedDecl();
1192 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1193 EXPECT_TRUE(ToTemplated1);
1194 EXPECT_EQ(ToTemplated1, ToTemplated);
1195}
1196
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001197TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton6578a4a2018-06-25 11:38:43 +00001198 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1199 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1200 auto FromFT =
1201 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1202 ASSERT_TRUE(FromFT);
1203
1204 auto ToTemplated =
1205 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1206 EXPECT_TRUE(ToTemplated);
1207 auto ToTU = ToTemplated->getTranslationUnitDecl();
1208 auto ToFT =
1209 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1210 EXPECT_TRUE(ToFT);
1211}
1212
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001213TEST_P(ASTImporterOptionSpecificTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001214 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001215 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1216 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1217 FromTU, functionTemplateDecl());
1218 ASSERT_TRUE(FromFT);
1219
1220 auto ToTemplated =
1221 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1222 EXPECT_TRUE(ToTemplated);
1223 auto ToTU = ToTemplated->getTranslationUnitDecl();
1224 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1225 ToTU, functionTemplateDecl());
1226 EXPECT_TRUE(ToFT);
1227}
1228
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001229TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001230 auto Code =
1231 R"(
1232 namespace x {
1233 template<class X> struct S1{};
1234 template<class X> struct S2{};
1235 template<class X> struct S3{};
1236 }
1237 )";
1238 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1239 auto FromNs =
1240 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1241 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1242 ASSERT_TRUE(ToNs);
1243 auto From =
1244 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1245 classTemplateDecl(
1246 hasName("S2")));
1247 auto To =
1248 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1249 classTemplateDecl(
1250 hasName("S2")));
1251 ASSERT_TRUE(From);
1252 ASSERT_TRUE(To);
1253 auto ToTemplated = To->getTemplatedDecl();
1254 auto ToTemplated1 =
1255 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1256 EXPECT_TRUE(ToTemplated1);
1257 ASSERT_EQ(ToTemplated1, ToTemplated);
1258}
1259
Tom Roeder521f0042019-02-26 19:26:41 +00001260TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {
1261 // This tests the import of isConditionTrue directly to make sure the importer
1262 // gets it right.
1263 Decl *From, *To;
1264 std::tie(From, To) = getImportedDecl(
1265 "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }",
1266 Lang_C, "", Lang_C);
1267
1268 auto ToResults = match(chooseExpr().bind("choose"), To->getASTContext());
1269 auto FromResults = match(chooseExpr().bind("choose"), From->getASTContext());
1270
1271 const ChooseExpr *FromChooseExpr =
1272 selectFirst<ChooseExpr>("choose", FromResults);
1273 ASSERT_TRUE(FromChooseExpr);
1274
1275 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>("choose", ToResults);
1276 ASSERT_TRUE(ToChooseExpr);
1277
1278 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());
1279 EXPECT_EQ(FromChooseExpr->isConditionDependent(),
1280 ToChooseExpr->isConditionDependent());
1281}
1282
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001283TEST_P(ASTImporterOptionSpecificTestBase,
1284 ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001285 Decl *From, *To;
1286 std::tie(From, To) = getImportedDecl(
1287 R"(
1288 template <typename T> struct X {};
1289
1290 void declToImport(int y, X<int> &x) {}
1291
1292 template <> struct X<int> {
1293 void g() {
1294 X<int> x;
1295 declToImport(0, x);
1296 }
1297 };
1298 )",
1299 Lang_CXX, "", Lang_CXX);
1300
1301 MatchVerifier<Decl> Verifier;
1302 auto Matcher = functionDecl(hasName("declToImport"),
1303 parameterCountIs(2),
1304 hasParameter(0, hasName("y")),
1305 hasParameter(1, hasName("x")),
1306 hasParameter(1, hasType(asString("X<int> &"))));
1307 ASSERT_TRUE(Verifier.match(From, Matcher));
1308 EXPECT_TRUE(Verifier.match(To, Matcher));
1309}
1310
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001311TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001312 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1313 Decl *From, *To;
1314 std::tie(From, To) =
1315 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1316 "void instantiate() { declToImport<int>(); }",
1317 Lang_CXX, "", Lang_CXX);
1318
1319 auto Check = [](Decl *D) -> bool {
1320 auto TU = D->getTranslationUnitDecl();
1321 for (auto Child : TU->decls()) {
1322 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1323 if (FD->getNameAsString() == "declToImport") {
1324 GTEST_NONFATAL_FAILURE_(
1325 "TU should not contain any FunctionDecl with name declToImport");
1326 return false;
1327 }
1328 }
1329 }
1330 return true;
1331 };
1332
1333 ASSERT_TRUE(Check(From));
1334 EXPECT_TRUE(Check(To));
1335}
1336
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001337TEST_P(ASTImporterOptionSpecificTestBase,
1338 TUshouldNotContainTemplatedDeclOfClassTemplates) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001339 Decl *From, *To;
1340 std::tie(From, To) =
1341 getImportedDecl("template <typename T> struct declToImport { T t; };"
1342 "void instantiate() { declToImport<int>(); }",
1343 Lang_CXX, "", Lang_CXX);
1344
1345 auto Check = [](Decl *D) -> bool {
1346 auto TU = D->getTranslationUnitDecl();
1347 for (auto Child : TU->decls()) {
1348 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1349 if (RD->getNameAsString() == "declToImport") {
1350 GTEST_NONFATAL_FAILURE_(
1351 "TU should not contain any CXXRecordDecl with name declToImport");
1352 return false;
1353 }
1354 }
1355 }
1356 return true;
1357 };
1358
1359 ASSERT_TRUE(Check(From));
1360 EXPECT_TRUE(Check(To));
1361}
1362
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001363TEST_P(ASTImporterOptionSpecificTestBase,
1364 TUshouldNotContainTemplatedDeclOfTypeAlias) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001365 Decl *From, *To;
1366 std::tie(From, To) =
1367 getImportedDecl(
1368 "template <typename T> struct X {};"
1369 "template <typename T> using declToImport = X<T>;"
1370 "void instantiate() { declToImport<int> a; }",
1371 Lang_CXX11, "", Lang_CXX11);
1372
1373 auto Check = [](Decl *D) -> bool {
1374 auto TU = D->getTranslationUnitDecl();
1375 for (auto Child : TU->decls()) {
1376 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1377 if (AD->getNameAsString() == "declToImport") {
1378 GTEST_NONFATAL_FAILURE_(
1379 "TU should not contain any TypeAliasDecl with name declToImport");
1380 return false;
1381 }
1382 }
1383 }
1384 return true;
1385 };
1386
1387 ASSERT_TRUE(Check(From));
1388 EXPECT_TRUE(Check(To));
1389}
1390
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001391TEST_P(ASTImporterOptionSpecificTestBase,
1392 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001393
1394 Decl *From, *To;
1395 std::tie(From, To) = getImportedDecl(
1396 R"(
1397 template<class T>
1398 class Base {};
1399 class declToImport : public Base<declToImport> {};
1400 )",
1401 Lang_CXX, "", Lang_CXX);
1402
1403 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1404 auto Pattern =
1405 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1406 ASSERT_TRUE(
1407 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1408 EXPECT_TRUE(
1409 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1410
1411 // Check that the ClassTemplateSpecializationDecl is the child of the
1412 // ClassTemplateDecl.
1413 Pattern = translationUnitDecl(has(classTemplateDecl(
1414 hasName("Base"), has(classTemplateSpecializationDecl()))));
1415 ASSERT_TRUE(
1416 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1417 EXPECT_TRUE(
1418 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1419}
1420
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001421AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1422 size_t Index = 0;
1423 for (FieldDecl *Field : Node.fields()) {
1424 if (Index == Order.size())
1425 return false;
1426 if (Field->getName() != Order[Index])
1427 return false;
1428 ++Index;
1429 }
1430 return Index == Order.size();
1431}
1432
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001433TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001434 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1435 Decl *From, *To;
1436 std::tie(From, To) = getImportedDecl(
1437 R"(
1438 namespace NS {
1439 template<class T>
1440 class X {};
1441 template class X<int>;
1442 }
1443 )",
1444 Lang_CXX, "", Lang_CXX, "NS");
1445
1446 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1447 // ClassTemplateDecl.
1448 auto Pattern = namespaceDecl(has(classTemplateDecl(
1449 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1450 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1451 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1452
1453 // Check that the ClassTemplateSpecializationDecl is the child of the
1454 // NamespaceDecl.
1455 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1456 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1457 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1458}
1459
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001460TEST_P(ASTImporterOptionSpecificTestBase,
1461 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001462 Decl *From, *To;
1463 std::tie(From, To) =
1464 getImportedDecl(
1465 "struct declToImport { int a; int b; };",
1466 Lang_CXX11, "", Lang_CXX11);
1467
1468 MatchVerifier<Decl> Verifier;
1469 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1470 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1471}
1472
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001473TEST_P(ASTImporterOptionSpecificTestBase,
Davide Italiano93a64ef2018-10-30 20:46:29 +00001474 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001475 Decl *From, *To;
1476 std::tie(From, To) = getImportedDecl(
1477 // The original recursive algorithm of ASTImporter first imports 'c' then
1478 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1479 R"s(
1480 struct declToImport {
1481 int a = c + b;
1482 int b = 1;
1483 int c = 2;
1484 };
1485 )s",
1486 Lang_CXX11, "", Lang_CXX11);
1487
1488 MatchVerifier<Decl> Verifier;
1489 ASSERT_TRUE(
1490 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1491 EXPECT_TRUE(
1492 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1493}
1494
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001495TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001496 Decl *From, *To;
1497 std::tie(From, To) = getImportedDecl(
1498 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001499 struct declToImport {
1500 };
1501 )",
1502 Lang_CXX, "", Lang_CXX);
1503
1504 MatchVerifier<Decl> Verifier;
1505 // Match the implicit Decl.
1506 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1507 ASSERT_TRUE(Verifier.match(From, Matcher));
1508 EXPECT_TRUE(Verifier.match(To, Matcher));
1509}
1510
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001511TEST_P(ASTImporterOptionSpecificTestBase,
1512 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
Gabor Martona3af5672018-05-23 14:24:02 +00001513 Decl *From, *To;
1514 std::tie(From, To) = getImportedDecl(
1515 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001516 template <typename U>
1517 struct declToImport {
1518 };
1519 )",
1520 Lang_CXX, "", Lang_CXX);
1521
1522 MatchVerifier<Decl> Verifier;
1523 // Match the implicit Decl.
1524 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1525 ASSERT_TRUE(Verifier.match(From, Matcher));
1526 EXPECT_TRUE(Verifier.match(To, Matcher));
1527}
1528
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001529TEST_P(ASTImporterOptionSpecificTestBase,
1530 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001531 Decl *From, *To;
1532 std::tie(From, To) = getImportedDecl(
1533 R"(
1534 template<class T>
1535 class Base {};
1536 class declToImport : public Base<declToImport> {};
1537 )",
1538 Lang_CXX, "", Lang_CXX);
1539
1540 auto hasImplicitClass = has(cxxRecordDecl());
1541 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1542 hasName("Base"),
1543 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1544 ASSERT_TRUE(
1545 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1546 EXPECT_TRUE(
1547 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1548}
1549
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001550TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001551 Decl *From, *To;
1552 std::tie(From, To) =
1553 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1554
1555 MatchVerifier<Decl> Verifier;
1556 auto Matcher = functionDecl();
1557 ASSERT_TRUE(Verifier.match(From, Matcher));
1558 EXPECT_TRUE(Verifier.match(To, Matcher));
1559 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1560}
1561
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001562TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001563 Decl *FromTU = getTuDecl(
1564 R"(
1565 struct X {};
1566 void operator<<(int, X);
1567 )",
1568 Lang_CXX);
1569 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1570 const Decl *To = Import(From, Lang_CXX);
1571 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1572}
1573
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001574TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001575 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1576 Decl *From, *To;
1577 std::tie(From, To) = getImportedDecl(
1578 R"(
1579 template<class T>
1580 class Base { int a; };
1581 class declToImport : Base<declToImport> {};
1582 )",
1583 Lang_CXX, "", Lang_CXX);
1584
1585 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1586 hasName("Base"),
1587 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1588 ASSERT_TRUE(
1589 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1590 EXPECT_TRUE(
1591 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1592}
1593
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001594TEST_P(ASTImporterOptionSpecificTestBase,
1595 ImportDefinitionOfClassTemplateAfterFwdDecl) {
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001596 {
1597 Decl *FromTU = getTuDecl(
1598 R"(
1599 template <typename T>
1600 struct B;
1601 )",
1602 Lang_CXX, "input0.cc");
1603 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1604 FromTU, classTemplateDecl(hasName("B")));
1605
1606 Import(FromD, Lang_CXX);
1607 }
1608
1609 {
1610 Decl *FromTU = getTuDecl(
1611 R"(
1612 template <typename T>
1613 struct B {
1614 void f();
1615 };
1616 )",
1617 Lang_CXX, "input1.cc");
1618 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1619 FromTU, functionDecl(hasName("f")));
1620 Import(FromD, Lang_CXX);
1621 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1622 FromTU, classTemplateDecl(hasName("B")));
1623 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1624 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1625 }
1626}
1627
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001628TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001629 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1630 Decl *ToTU = getToTuDecl(
1631 R"(
1632 template <typename T>
1633 struct B {
1634 void f();
1635 };
1636
1637 template <typename T>
1638 struct B;
1639 )",
1640 Lang_CXX);
1641 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1642 [](const ClassTemplateDecl *T) {
1643 return T->isThisDeclarationADefinition();
1644 })
1645 .match(ToTU, classTemplateDecl()));
1646
1647 Decl *FromTU = getTuDecl(
1648 R"(
1649 template <typename T>
1650 struct B {
1651 void f();
1652 };
1653 )",
1654 Lang_CXX, "input1.cc");
1655 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1656 FromTU, classTemplateDecl(hasName("B")));
1657
1658 Import(FromD, Lang_CXX);
1659
1660 // We should have only one definition.
1661 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1662 [](const ClassTemplateDecl *T) {
1663 return T->isThisDeclarationADefinition();
1664 })
1665 .match(ToTU, classTemplateDecl()));
1666}
1667
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001668TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001669 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1670 Decl *ToTU = getToTuDecl(
1671 R"(
1672 struct B {
1673 void f();
1674 };
1675
1676 struct B;
1677 )",
1678 Lang_CXX);
1679 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001680 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001681
1682 Decl *FromTU = getTuDecl(
1683 R"(
1684 struct B {
1685 void f();
1686 };
1687 )",
1688 Lang_CXX, "input1.cc");
1689 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1690 FromTU, cxxRecordDecl(hasName("B")));
1691
1692 Import(FromD, Lang_CXX);
1693
1694 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001695 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001696}
1697
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001698static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1699 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1700 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1701 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1702 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1703}
1704static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1705 SourceManager &SM1, SourceManager &SM2) {
1706 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1707 FullSourceLoc{ Range2.getBegin(), SM2 });
1708 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1709 FullSourceLoc{ Range2.getEnd(), SM2 });
1710}
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001711TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001712 Decl *FromTU = getTuDecl(
1713 R"(
1714 #define MFOO(arg) arg = arg + 1
1715
1716 void foo() {
1717 int a = 5;
1718 MFOO(a);
1719 }
1720 )",
1721 Lang_CXX);
1722 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1723 auto ToD = Import(FromD, Lang_CXX);
1724
1725 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1726 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1727 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1728 auto FromRHS =
1729 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1730
1731 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1732 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1733 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1734 FromSM);
1735 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1736 FromSM);
1737 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1738 FromSM);
1739}
1740
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001741TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001742 Decl *FromTU = getTuDecl(
1743 R"(
1744 #define FUNC_INT void declToImport
1745 #define FUNC FUNC_INT
1746 FUNC(int a);
1747 )",
1748 Lang_CXX);
1749 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1750 auto ToD = Import(FromD, Lang_CXX);
1751
1752 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1753 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1754 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1755 FromSM);
1756}
1757
Gabor Marton9581c332018-05-23 13:53:36 +00001758TEST_P(
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001759 ASTImporterOptionSpecificTestBase,
1760 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
Gabor Marton9581c332018-05-23 13:53:36 +00001761 Decl *ToTU = getToTuDecl(
1762 R"(
1763 template <typename T>
1764 struct B;
1765
1766 template <>
1767 struct B<int> {};
1768
1769 template <>
1770 struct B<int>;
1771 )",
1772 Lang_CXX);
1773 // We should have only one definition.
1774 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1775 [](const ClassTemplateSpecializationDecl *T) {
1776 return T->isThisDeclarationADefinition();
1777 })
1778 .match(ToTU, classTemplateSpecializationDecl()));
1779
1780 Decl *FromTU = getTuDecl(
1781 R"(
1782 template <typename T>
1783 struct B;
1784
1785 template <>
1786 struct B<int> {};
1787 )",
1788 Lang_CXX, "input1.cc");
1789 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1790 FromTU, classTemplateSpecializationDecl(hasName("B")));
1791
1792 Import(FromD, Lang_CXX);
1793
1794 // We should have only one definition.
1795 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1796 [](const ClassTemplateSpecializationDecl *T) {
1797 return T->isThisDeclarationADefinition();
1798 })
1799 .match(ToTU, classTemplateSpecializationDecl()));
1800}
1801
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001802TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
Gabor Marton0bebf952018-07-05 09:51:13 +00001803 Decl *FromTU = getTuDecl(
1804 R"(
1805 struct { int a; int b; } object0 = { 2, 3 };
1806 struct { int x; int y; int z; } object1;
1807 )",
1808 Lang_CXX, "input0.cc");
1809
Gabor Marton0bebf952018-07-05 09:51:13 +00001810 auto *Obj0 =
1811 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1812 auto *From0 = getRecordDecl(Obj0);
1813 auto *Obj1 =
1814 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1815 auto *From1 = getRecordDecl(Obj1);
1816
1817 auto *To0 = Import(From0, Lang_CXX);
1818 auto *To1 = Import(From1, Lang_CXX);
1819
1820 EXPECT_TRUE(To0);
1821 EXPECT_TRUE(To1);
1822 EXPECT_NE(To0, To1);
1823 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1824}
1825
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001826TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001827 auto *Code =
1828 R"(
1829 struct X {
1830 struct { int a; };
1831 struct { int b; };
1832 };
1833 )";
1834 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
1835
1836 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
1837
1838 auto *X0 =
1839 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1840 auto *X1 =
1841 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1842 Import(X0, Lang_C);
1843 Import(X1, Lang_C);
1844
1845 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1846 // We expect no (ODR) warning during the import.
1847 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1848 EXPECT_EQ(1u,
1849 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1850}
1851
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001852TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001853 Decl *FromTU0 = getTuDecl(
1854 R"(
1855 struct X {
1856 struct { int a; };
1857 struct { int b; };
1858 };
1859 )",
1860 Lang_C, "input0.c");
1861
1862 Decl *FromTU1 = getTuDecl(
1863 R"(
1864 struct X { // reversed order
1865 struct { int b; };
1866 struct { int a; };
1867 };
1868 )",
1869 Lang_C, "input1.c");
1870
1871 auto *X0 =
1872 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1873 auto *X1 =
1874 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1875 Import(X0, Lang_C);
1876 Import(X1, Lang_C);
1877
1878 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1879 // We expect one (ODR) warning during the import.
1880 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1881 EXPECT_EQ(2u,
1882 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1883}
1884
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001885TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001886 auto Pattern = varDecl(hasName("x"));
1887 VarDecl *Imported1;
1888 {
1889 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1890 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1891 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1892 }
1893 VarDecl *Imported2;
1894 {
1895 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1896 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1897 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1898 }
1899 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1900 EXPECT_FALSE(Imported2->isUsed(false));
1901 {
1902 Decl *FromTU =
1903 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
Gabor Martonac3a5d62018-09-17 12:04:52 +00001904 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1905 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00001906 Import(FromD, Lang_CXX);
1907 }
1908 EXPECT_TRUE(Imported2->isUsed(false));
1909}
1910
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001911TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001912 auto Pattern = varDecl(hasName("x"));
1913 VarDecl *ExistingD;
1914 {
1915 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
1916 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1917 }
1918 EXPECT_FALSE(ExistingD->isUsed(false));
1919 {
1920 Decl *FromTU = getTuDecl(
1921 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
1922 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1923 FromTU, functionDecl(hasName("f")));
1924 Import(FromD, Lang_CXX);
1925 }
1926 EXPECT_TRUE(ExistingD->isUsed(false));
1927}
1928
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001929TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001930 auto Pattern = varDecl(hasName("a"));
1931 VarDecl *ExistingD;
1932 {
1933 Decl *ToTU = getToTuDecl(
1934 R"(
1935 struct A {
1936 static const int a = 1;
1937 };
1938 )", Lang_CXX);
1939 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1940 }
1941 EXPECT_FALSE(ExistingD->isUsed(false));
1942 {
1943 Decl *FromTU = getTuDecl(
1944 R"(
1945 struct A {
1946 static const int a = 1;
1947 };
1948 const int *f() { return &A::a; } // requires storage,
1949 // thus used flag will be set
1950 )", Lang_CXX, "input1.cc");
1951 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
1952 FromTU, functionDecl(hasName("f")));
1953 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1954 ASSERT_TRUE(FromD->isUsed(false));
1955 Import(FromFunD, Lang_CXX);
1956 }
1957 EXPECT_TRUE(ExistingD->isUsed(false));
1958}
1959
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001960TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001961 auto Pattern = varDecl(hasName("x"));
1962
1963 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
1964 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1965
1966 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1967
1968 ASSERT_FALSE(Imported1->isUsed(false));
1969
1970 FromD->setIsUsed();
1971 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1972
1973 EXPECT_EQ(Imported1, Imported2);
1974 EXPECT_TRUE(Imported2->isUsed(false));
1975}
1976
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001977struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
Peter Szecsidedda6f2018-03-30 22:03:29 +00001978
Gabor Marton5254e642018-06-27 13:32:50 +00001979TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001980 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1981 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001982 auto *From =
1983 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00001984
Gabor Marton5254e642018-06-27 13:32:50 +00001985 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001986 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1987
Gabor Marton5254e642018-06-27 13:32:50 +00001988 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1989 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1990 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1991 EXPECT_TRUE(ImportedD == To0);
1992 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1993 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1994 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001995}
1996
1997TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1998 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1999 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002000 auto *From =
2001 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00002002
Gabor Marton5254e642018-06-27 13:32:50 +00002003 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002004 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2005
Gabor Marton5254e642018-06-27 13:32:50 +00002006 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2007 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2008 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2009 EXPECT_TRUE(ImportedD == To1);
2010 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2011 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2012 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002013}
2014
Peter Szecsidedda6f2018-03-30 22:03:29 +00002015TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2016 auto Code =
2017 R"(
2018 struct B { virtual void f(); };
2019 void B::f() {}
2020 struct D : B { void f(); };
2021 )";
2022 auto Pattern =
2023 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2024 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2025 CXXMethodDecl *Proto =
2026 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2027
2028 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2029 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2030 EXPECT_EQ(To->size_overridden_methods(), 1u);
2031}
2032
2033TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2034 auto Code =
2035 R"(
2036 struct B { virtual void f(); };
2037 void B::f() {}
2038 )";
2039 auto Pattern =
2040 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2041 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2042 CXXMethodDecl *Proto =
2043 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2044 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2045
2046 ASSERT_TRUE(Proto->isVirtual());
2047 ASSERT_TRUE(Def->isVirtual());
2048 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2049 EXPECT_TRUE(To->isVirtual());
2050}
2051
Gabor Marton5254e642018-06-27 13:32:50 +00002052TEST_P(ImportFunctions,
2053 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2054 Decl *ToTU = getToTuDecl(
2055 R"(
2056 void f() {}
2057 void f();
2058 )",
2059 Lang_CXX);
2060 ASSERT_EQ(1u,
2061 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2062 return FD->doesThisDeclarationHaveABody();
2063 }).match(ToTU, functionDecl()));
2064
2065 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2066 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2067
2068 Import(FromD, Lang_CXX);
2069
2070 EXPECT_EQ(1u,
2071 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2072 return FD->doesThisDeclarationHaveABody();
2073 }).match(ToTU, functionDecl()));
2074}
2075
Shafik Yaghmour96b3d202019-01-28 21:55:33 +00002076TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
2077 auto Code =
2078 R"(
2079 struct B { virtual void f(); };
2080 struct D:B { void f(); };
2081 )";
2082 auto BFP =
2083 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2084 auto DFP =
2085 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2086
2087 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2088 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2089 Import(DF, Lang_CXX);
2090
2091 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2092 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2093 Import(BF, Lang_CXX);
2094
2095 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2096
2097 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2098 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2099}
2100
2101TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2102 auto CodeWithoutDef =
2103 R"(
2104 struct B { virtual void f(); };
2105 struct D:B { void f(); };
2106 )";
2107 auto CodeWithDef =
2108 R"(
2109 struct B { virtual void f(){}; };
2110 struct D:B { void f(){}; };
2111 )";
2112 auto BFP =
2113 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2114 auto DFP =
2115 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2116 auto BFDefP = cxxMethodDecl(
2117 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2118 auto DFDefP = cxxMethodDecl(
2119 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2120 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
2121
2122 {
2123 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX, "input0.cc");
2124 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
2125 Import(FromD, Lang_CXX);
2126 }
2127 {
2128 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX, "input1.cc");
2129 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
2130 Import(FromB, Lang_CXX);
2131 }
2132
2133 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2134
2135 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2136 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2137 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2138 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2139 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2140}
2141
2142TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2143 auto Code =
2144 R"(
2145 struct B { virtual void f(); };
2146 struct D:B { void f(); };
2147 void B::f(){};
2148 )";
2149
2150 auto BFP =
2151 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2152 auto BFDefP = cxxMethodDecl(
2153 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2154 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
2155 unless(isDefinition()));
2156
2157 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2158 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2159 Import(D, Lang_CXX);
2160
2161 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2162 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2163 Import(B, Lang_CXX);
2164
2165 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2166
2167 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2168 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2169
2170 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2171 ToTU, cxxRecordDecl(hasName("B")));
2172 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2173 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2174 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2175
2176 // The definition should be out-of-class.
2177 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2178 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2179 ToBFOutOfClass->getLexicalDeclContext());
2180 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2181 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2182
2183 // Check that the redecl chain is intact.
2184 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2185}
2186
2187TEST_P(ImportFunctions,
2188 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2189 auto CodeTU0 =
2190 R"(
2191 struct B { virtual void f(); };
2192 struct D:B { void f(); };
2193 )";
2194 auto CodeTU1 =
2195 R"(
2196 struct B { virtual void f(); };
2197 struct D:B { void f(); };
2198 void B::f(){}
2199 void D::f(){}
2200 void foo(B &b, D &d) { b.f(); d.f(); }
2201 )";
2202
2203 auto BFP =
2204 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2205 auto BFDefP = cxxMethodDecl(
2206 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2207 auto DFP =
2208 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2209 auto DFDefP = cxxMethodDecl(
2210 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2211 auto FooDef = functionDecl(hasName("foo"));
2212
2213 {
2214 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX, "input0.cc");
2215 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2216 Import(D, Lang_CXX);
2217 }
2218
2219 {
2220 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX, "input1.cc");
2221 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2222 Import(Foo, Lang_CXX);
2223 }
2224
2225 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2226
2227 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2228 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2229 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2230 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2231
2232 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2233 ToTU, cxxRecordDecl(hasName("B")));
2234 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2235 ToTU, cxxRecordDecl(hasName("D")));
2236 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2237 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2238 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2239 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2240 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2241 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2242
2243 // The definition should be out-of-class.
2244 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2245 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2246 ToBFOutOfClass->getLexicalDeclContext());
2247 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2248 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2249
2250 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2251 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2252 ToDFOutOfClass->getLexicalDeclContext());
2253 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2254 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2255
2256 // Check that the redecl chain is intact.
2257 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2258 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2259}
2260
Gabor Marton458d1452019-02-14 13:07:03 +00002261TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2262 std::string Code = "static int v; static int v = 0;";
2263 auto Pattern = varDecl(hasName("v"));
2264
2265 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C, "input0.c");
2266
2267 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2268 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2269
2270 auto *To0 = Import(From0, Lang_C);
2271 auto *To1 = Import(From1, Lang_C);
2272
2273 EXPECT_TRUE(To0);
2274 ASSERT_TRUE(To1);
2275 EXPECT_NE(To0, To1);
2276 EXPECT_EQ(To1->getPreviousDecl(), To0);
2277}
2278
2279TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2280 TranslationUnitDecl *FromTu = getTuDecl(
2281 "namespace NS0 { namespace { void f(); } }"
2282 "namespace NS1 { namespace { void f(); } }",
2283 Lang_CXX, "input0.cc");
2284 auto Pattern = functionDecl(hasName("f"));
2285
2286 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2287 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2288
2289 auto *ToF0 = Import(FromF0, Lang_CXX);
2290 auto *ToF1 = Import(FromF1, Lang_CXX);
2291
2292 EXPECT_TRUE(ToF0);
2293 ASSERT_TRUE(ToF1);
2294 EXPECT_NE(ToF0, ToF1);
2295 EXPECT_FALSE(ToF1->getPreviousDecl());
2296}
2297
2298TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2299 {
2300 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",
2301 Lang_CXX, "input0.cc");
2302 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2303 FromTU, functionDecl(hasName("g0")));
2304
2305 Import(FromD, Lang_CXX);
2306 }
2307 {
2308 Decl *FromTU =
2309 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",
2310 Lang_CXX, "input1.cc");
2311 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2312 FromTU, functionDecl(hasName("g1")));
2313 Import(FromD, Lang_CXX);
2314 }
2315
2316 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2317 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2318 2u);
2319}
2320
Gabor Marton302f3002019-02-15 12:04:05 +00002321TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2322 Decl *FromTU = getTuDecl(
2323 R"(
2324 void foo() {
2325 (void)[]() { ; };
2326 }
2327 )",
2328 Lang_CXX11);
2329 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2330 FromTU, functionDecl(hasName("foo")));
2331 auto *ToD = Import(FromD, Lang_CXX);
2332 EXPECT_TRUE(ToD);
2333 CXXRecordDecl *LambdaRec =
2334 cast<LambdaExpr>(cast<CStyleCastExpr>(
2335 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2336 ->getSubExpr())
2337 ->getLambdaClass();
2338 EXPECT_TRUE(LambdaRec->getDestructor());
2339}
2340
Gabor Marton5caba302019-03-07 13:38:20 +00002341TEST_P(ImportFunctions,
2342 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2343 Decl *FromTU = getTuDecl(
2344 R"(
2345 struct X {
2346 template <typename T>
2347 void foo(){}
2348 };
2349 void f() {
2350 X x;
2351 x.foo<int>();
2352 }
2353 )",
2354 Lang_CXX);
2355 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2356 FromTU, functionDecl(hasName("f")));
2357 auto *ToD = Import(FromD, Lang_CXX);
2358 EXPECT_TRUE(ToD);
2359 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
2360 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr()))));
2361}
2362
2363TEST_P(ImportFunctions,
2364 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2365 Decl *FromTU = getTuDecl(
2366 R"(
2367 struct X {
2368 template <typename T>
2369 void foo(){}
2370 };
2371 template <typename T>
2372 void f() {
2373 X x;
2374 x.foo<T>();
2375 }
2376 void g() {
2377 f<int>();
2378 }
2379 )",
2380 Lang_CXX);
2381 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2382 FromTU, functionDecl(hasName("g")));
2383 auto *ToD = Import(FromD, Lang_CXX);
2384 EXPECT_TRUE(ToD);
2385 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2386 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match(
2387 ToTU, translationUnitDecl(hasDescendant(
2388 functionDecl(hasName("f"), hasDescendant(declRefExpr()))))));
2389}
2390
Gabor Marton5254e642018-06-27 13:32:50 +00002391struct ImportFriendFunctions : ImportFunctions {};
2392
2393TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2394 auto Pattern = functionDecl(hasName("f"));
2395
2396 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2397 "void f();",
2398 Lang_CXX,
2399 "input0.cc");
2400 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2401
2402 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2403 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2404 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2405 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2406 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2407 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2408 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2409}
2410
2411TEST_P(ImportFriendFunctions,
2412 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2413 auto Pattern = functionDecl(hasName("f"));
2414
2415 Decl *FromTU = getTuDecl("void f();"
2416 "struct X { friend void f(); };",
2417 Lang_CXX, "input0.cc");
2418 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2419
2420 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2421 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2422 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2423 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2424 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2425 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2426 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2427}
2428
2429TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2430 auto Pattern = functionDecl(hasName("f"));
2431
2432 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2433 "void f();",
2434 Lang_CXX,
2435 "input0.cc");
2436 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2437
2438 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2439 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2440 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2441 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2442 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2443 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2444 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2445}
2446
2447TEST_P(ImportFriendFunctions,
2448 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2449 auto Pattern = functionDecl(hasName("f"));
2450
2451 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2452 "void f(){}",
2453 Lang_CXX, "input0.cc");
2454 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2455
2456 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2457 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2458 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2459 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2460 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2461 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2462 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2463}
2464
Gabor Marton1d51e3e2019-05-20 10:38:14 +00002465TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDefWithClass) {
Gabor Marton5254e642018-06-27 13:32:50 +00002466 auto Pattern = functionDecl(hasName("f"));
2467
2468 Decl *FromTU = getTuDecl(
2469 R"(
2470 class X;
2471 void f(X *x){}
2472 class X{
2473 friend void f(X *x);
2474 };
2475 )",
2476 Lang_CXX, "input0.cc");
2477 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2478
2479 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2480 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2481 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2482 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2483 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2484 .match(ToTU, friendDecl())
2485 ->getFriendDecl());
2486 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2487 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2488 // The parameters must refer the same type
2489 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2490 (*ImportedD->param_begin())->getOriginalType());
2491}
2492
Gabor Marton5254e642018-06-27 13:32:50 +00002493TEST_P(ImportFriendFunctions,
Gabor Marton1d51e3e2019-05-20 10:38:14 +00002494 ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002495 auto Pattern = functionDecl(hasName("f"));
2496
2497 Decl *FromTU = getTuDecl(
2498 R"(
2499 class X;
2500 void f(X *x){}
2501 class X{
2502 friend void f(X *x);
2503 };
2504 )",
2505 Lang_CXX, "input0.cc");
2506 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2507
2508 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2509 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2510 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2511 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2512 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2513 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2514
2515 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2516 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2517 // The parameters must refer the same type
2518 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2519 (*ImportedD->param_begin())->getOriginalType());
2520}
2521
2522TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2523 auto Pattern = functionDecl(hasName("f"));
2524
2525 FunctionDecl *ImportedD;
2526 {
2527 Decl *FromTU =
2528 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2529 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2530 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2531 }
2532 FunctionDecl *ImportedD1;
2533 {
2534 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2535 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2536 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2537 }
2538
2539 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2540 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2541 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2542 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2543 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2544}
2545
Balazs Keri89632b82018-08-21 14:32:21 +00002546TEST_P(ImportFriendFunctions, Lookup) {
2547 auto FunctionPattern = functionDecl(hasName("f"));
2548 auto ClassPattern = cxxRecordDecl(hasName("X"));
2549
2550 TranslationUnitDecl *FromTU =
2551 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2552 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2553 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2554 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2555 {
2556 auto FromName = FromD->getDeclName();
2557 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2558 auto LookupRes = Class->noload_lookup(FromName);
2559 ASSERT_EQ(LookupRes.size(), 0u);
2560 LookupRes = FromTU->noload_lookup(FromName);
2561 ASSERT_EQ(LookupRes.size(), 1u);
2562 }
2563
2564 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2565 auto ToName = ToD->getDeclName();
2566
2567 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2568 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2569 auto LookupRes = Class->noload_lookup(ToName);
2570 EXPECT_EQ(LookupRes.size(), 0u);
2571 LookupRes = ToTU->noload_lookup(ToName);
2572 EXPECT_EQ(LookupRes.size(), 1u);
2573
2574 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2575 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2576 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2577 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2578}
2579
2580TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2581 auto FunctionPattern = functionDecl(hasName("f"));
2582 auto ClassPattern = cxxRecordDecl(hasName("X"));
2583
2584 TranslationUnitDecl *FromTU = getTuDecl(
2585 "struct X { friend void f(); };"
2586 // This proto decl makes f available to normal
2587 // lookup, otherwise it is hidden.
2588 // Normal C++ lookup (implemented in
2589 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2590 // returns the found `NamedDecl` only if the set IDNS is matched
2591 "void f();",
2592 Lang_CXX, "input0.cc");
2593 auto *FromFriend =
2594 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2595 auto *FromNormal =
2596 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2597 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2598 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2599 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2600 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2601
2602 auto FromName = FromFriend->getDeclName();
2603 auto *FromClass =
2604 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2605 auto LookupRes = FromClass->noload_lookup(FromName);
2606 ASSERT_EQ(LookupRes.size(), 0u);
2607 LookupRes = FromTU->noload_lookup(FromName);
2608 ASSERT_EQ(LookupRes.size(), 1u);
2609
2610 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2611 auto ToName = ToFriend->getDeclName();
2612
2613 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2614 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2615 LookupRes = ToClass->noload_lookup(ToName);
2616 EXPECT_EQ(LookupRes.size(), 0u);
2617 LookupRes = ToTU->noload_lookup(ToName);
2618 // Test is disabled because this result is 2.
2619 EXPECT_EQ(LookupRes.size(), 1u);
2620
2621 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2622 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2623 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2624 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2625 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2626 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2627 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2628}
2629
2630TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2631 auto FunctionPattern = functionDecl(hasName("f"));
2632 auto ClassPattern = cxxRecordDecl(hasName("X"));
2633
2634 TranslationUnitDecl *FromTU = getTuDecl(
2635 "void f();"
2636 "struct X { friend void f(); };",
2637 Lang_CXX, "input0.cc");
2638 auto *FromNormal =
2639 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2640 auto *FromFriend =
2641 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2642 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2643 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2644 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2645 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2646
2647 auto FromName = FromNormal->getDeclName();
2648 auto *FromClass =
2649 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2650 auto LookupRes = FromClass->noload_lookup(FromName);
2651 ASSERT_EQ(LookupRes.size(), 0u);
2652 LookupRes = FromTU->noload_lookup(FromName);
2653 ASSERT_EQ(LookupRes.size(), 1u);
2654
2655 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2656 auto ToName = ToNormal->getDeclName();
2657 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2658
2659 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2660 LookupRes = ToClass->noload_lookup(ToName);
2661 EXPECT_EQ(LookupRes.size(), 0u);
2662 LookupRes = ToTU->noload_lookup(ToName);
2663 EXPECT_EQ(LookupRes.size(), 1u);
2664
2665 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2666 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2667 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2668 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2669 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2670 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2671 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2672}
2673
2674TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2675 auto Pattern = functionDecl(hasName("f"));
2676
2677 TranslationUnitDecl *FromNormalTU =
2678 getTuDecl("void f();", Lang_CXX, "input0.cc");
2679 auto *FromNormalF =
2680 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2681 TranslationUnitDecl *FromFriendTU =
2682 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2683 auto *FromFriendF =
2684 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2685 auto FromNormalName = FromNormalF->getDeclName();
2686 auto FromFriendName = FromFriendF->getDeclName();
2687
2688 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2689 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2690 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2691 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2692 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2693 ASSERT_EQ(LookupRes.size(), 1u);
2694 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2695 ASSERT_EQ(LookupRes.size(), 1u);
2696
2697 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2698 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2699 auto ToName = ToNormalF->getDeclName();
2700 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2701 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2702 LookupRes = ToTU->noload_lookup(ToName);
2703 EXPECT_EQ(LookupRes.size(), 1u);
2704 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00002705
Balazs Keri89632b82018-08-21 14:32:21 +00002706 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
2707 LookupRes = ToTU->noload_lookup(ToName);
2708 EXPECT_EQ(LookupRes.size(), 1u);
2709 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2710
2711 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2712 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2713
2714 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2715 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2716}
2717
2718TEST_P(ImportFriendFunctions, ImportFriendList) {
2719 TranslationUnitDecl *FromTU = getTuDecl(
2720 "struct X { friend void f(); };"
2721 "void f();",
2722 Lang_CXX, "input0.cc");
2723 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2724 FromTU, functionDecl(hasName("f")));
2725
2726 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2727 FromTU, cxxRecordDecl(hasName("X")));
2728 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2729 auto FromFriends = FromClass->friends();
2730 unsigned int FrN = 0;
2731 for (auto Fr : FromFriends) {
2732 ASSERT_EQ(Fr, FromFriend);
2733 ++FrN;
2734 }
2735 ASSERT_EQ(FrN, 1u);
2736
2737 Import(FromFriendF, Lang_CXX);
2738 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2739 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2740 ToTU, cxxRecordDecl(hasName("X")));
2741 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2742 auto ToFriends = ToClass->friends();
2743 FrN = 0;
2744 for (auto Fr : ToFriends) {
2745 EXPECT_EQ(Fr, ToFriend);
2746 ++FrN;
2747 }
2748 EXPECT_EQ(FrN, 1u);
2749}
2750
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002751AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2752 InnerMatcher) {
2753 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2754 return InnerMatcher.matches(*Typedef, Finder, Builder);
2755 return false;
2756}
2757
Gabor Marton19f4f392018-06-25 13:04:37 +00002758TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002759 CodeFiles Samples{{"main.c",
2760 {"void foo();"
2761 "void moo();"
2762 "int main() { foo(); moo(); }",
2763 Lang_C}},
2764
2765 {"foo.c",
2766 {"typedef enum { THING_VALUE } thing_t;"
2767 "void conflict(thing_t type);"
2768 "void foo() { (void)THING_VALUE; }"
2769 "void conflict(thing_t type) {}",
2770 Lang_C}},
2771
2772 {"moo.c",
2773 {"typedef enum { THING_VALUE } thing_t;"
2774 "void conflict(thing_t type);"
2775 "void moo() { conflict(THING_VALUE); }",
2776 Lang_C}}};
2777
2778 auto VerificationMatcher =
2779 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2780 hasTypedefForAnonDecl(hasName("thing_t")));
2781
2782 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2783 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2784
2785 testImportSequence(
2786 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2787 // Just check that there is only one enum decl in the result AST.
2788 "main.c", enumDecl(), VerificationMatcher);
2789
2790 // For different import order, result should be the same.
2791 testImportSequence(
2792 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2793 // Check that there is only one enum decl in the result AST.
2794 "main.c", enumDecl(), VerificationMatcher);
2795}
2796
Peter Szecsice7f3182018-05-07 12:08:27 +00002797const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2798 dependentScopeDeclRefExpr;
2799
Gabor Marton19f4f392018-06-25 13:04:37 +00002800TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002801 MatchVerifier<Decl> Verifier;
2802 testImport("template <typename T> struct S { static T foo; };"
2803 "template <typename T> void declToImport() {"
2804 " (void) S<T>::foo;"
2805 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002806 "void instantiate() { declToImport<int>(); }"
2807 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002808 Lang_CXX11, "", Lang_CXX11, Verifier,
2809 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2810 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2811
2812 testImport("template <typename T> struct S {"
2813 "template<typename S> static void foo(){};"
2814 "};"
2815 "template <typename T> void declToImport() {"
2816 " S<T>::template foo<T>();"
2817 "}"
2818 "void instantiate() { declToImport<int>(); }",
2819 Lang_CXX11, "", Lang_CXX11, Verifier,
2820 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2821 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2822}
2823
2824const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2825 dependentNameType;
2826
Gabor Marton19f4f392018-06-25 13:04:37 +00002827TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002828 MatchVerifier<Decl> Verifier;
2829 testImport("template <typename T> struct declToImport {"
2830 " typedef typename T::type dependent_name;"
2831 "};",
2832 Lang_CXX11, "", Lang_CXX11, Verifier,
2833 classTemplateDecl(has(
2834 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2835}
2836
Gabor Marton19f4f392018-06-25 13:04:37 +00002837TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002838 MatchVerifier<Decl> Verifier;
2839 testImport("struct S { template <typename T> void mem(); };"
2840 "template <typename U> void declToImport() {"
2841 " S s;"
2842 " s.mem<U>();"
2843 "}"
2844 "void instantiate() { declToImport<int>(); }",
2845 Lang_CXX11, "", Lang_CXX11, Verifier,
2846 functionTemplateDecl(has(functionDecl(has(
2847 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2848}
2849
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002850class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
Balazs Keri1d20cc22018-07-16 12:16:39 +00002851public:
2852 static constexpr auto DefaultCode = R"(
2853 struct A { int x; };
2854 void f() {
2855 A a;
2856 A a1(a);
2857 A a2(A{});
2858 a = a1;
2859 a = A{};
2860 a.~A();
2861 })";
2862
2863 template <typename MatcherType>
2864 void testImportOf(
2865 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2866 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
2867 }
2868
2869 template <typename MatcherType>
2870 void testNoImportOf(
2871 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2872 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
2873 }
2874
2875private:
2876 template <typename MatcherType>
2877 void test(const MatcherType &MethodMatcher,
2878 const char *Code, unsigned int ExpectedCount) {
2879 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
2880
2881 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
2882 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2883 ToTU, ClassMatcher);
2884
Balazs Keri2f752ba2018-07-16 14:05:18 +00002885 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002886
2887 {
2888 CXXMethodDecl *Method =
2889 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
2890 ToClass->removeDecl(Method);
Gabor Marton54058b52018-12-17 13:53:12 +00002891 LookupTablePtr->remove(Method);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002892 }
2893
Balazs Keri2f752ba2018-07-16 14:05:18 +00002894 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002895
2896 Decl *ImportedClass = nullptr;
2897 {
2898 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
2899 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2900 FromTU, ClassMatcher);
2901 ImportedClass = Import(FromClass, Lang_CXX11);
2902 }
2903
2904 EXPECT_EQ(ToClass, ImportedClass);
2905 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
2906 ExpectedCount);
2907 }
2908};
2909
2910TEST_P(ImportImplicitMethods, DefaultConstructor) {
2911 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
2912}
2913
2914TEST_P(ImportImplicitMethods, CopyConstructor) {
2915 testImportOf(cxxConstructorDecl(isCopyConstructor()));
2916}
2917
2918TEST_P(ImportImplicitMethods, MoveConstructor) {
2919 testImportOf(cxxConstructorDecl(isMoveConstructor()));
2920}
2921
2922TEST_P(ImportImplicitMethods, Destructor) {
2923 testImportOf(cxxDestructorDecl());
2924}
2925
2926TEST_P(ImportImplicitMethods, CopyAssignment) {
2927 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
2928}
2929
2930TEST_P(ImportImplicitMethods, MoveAssignment) {
2931 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
2932}
2933
2934TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
2935 auto Code = R"(
2936 struct A { A() { int x; } };
2937 )";
2938 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2939}
2940
2941TEST_P(ImportImplicitMethods, DoNotImportDefault) {
2942 auto Code = R"(
2943 struct A { A() = default; };
2944 )";
2945 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2946}
2947
2948TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
2949 auto Code = R"(
2950 struct A { A() = delete; };
2951 )";
2952 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2953}
2954
2955TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
2956 auto Code = R"(
2957 struct A { void f() { } };
2958 )";
2959 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
2960}
2961
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002962TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00002963 Decl *ToR1;
2964 {
2965 Decl *FromTU = getTuDecl(
2966 "struct A { };", Lang_CXX, "input0.cc");
2967 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2968 FromTU, cxxRecordDecl(hasName("A")));
2969
2970 ToR1 = Import(FromR, Lang_CXX);
2971 }
2972
2973 Decl *ToR2;
2974 {
2975 Decl *FromTU = getTuDecl(
2976 "struct A { };", Lang_CXX, "input1.cc");
2977 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2978 FromTU, cxxRecordDecl(hasName("A")));
2979
2980 ToR2 = Import(FromR, Lang_CXX);
2981 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00002982
Balazs Keric7797c42018-07-11 09:37:24 +00002983 EXPECT_EQ(ToR1, ToR2);
2984}
2985
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002986TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00002987 Decl *ToR1;
2988 {
2989 Decl *FromTU = getTuDecl(
2990 "struct A { int x; };", Lang_CXX, "input0.cc");
2991 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2992 FromTU, cxxRecordDecl(hasName("A")));
2993 ToR1 = Import(FromR, Lang_CXX);
2994 }
2995 Decl *ToR2;
2996 {
2997 Decl *FromTU = getTuDecl(
2998 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2999 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3000 FromTU, cxxRecordDecl(hasName("A")));
3001 ToR2 = Import(FromR, Lang_CXX);
3002 }
3003 EXPECT_NE(ToR1, ToR2);
3004}
3005
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003006TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003007 Decl *ToF1;
3008 {
3009 Decl *FromTU = getTuDecl(
3010 "struct A { int x; };", Lang_CXX, "input0.cc");
3011 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3012 FromTU, fieldDecl(hasName("x")));
3013 ToF1 = Import(FromF, Lang_CXX);
3014 }
3015 Decl *ToF2;
3016 {
3017 Decl *FromTU = getTuDecl(
3018 "struct A { int x; };", Lang_CXX, "input1.cc");
3019 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3020 FromTU, fieldDecl(hasName("x")));
3021 ToF2 = Import(FromF, Lang_CXX);
3022 }
3023 EXPECT_EQ(ToF1, ToF2);
3024}
3025
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003026TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003027 Decl *ToF1;
3028 {
3029 Decl *FromTU = getTuDecl(
3030 "struct A { int x; };", Lang_CXX, "input0.cc");
3031 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3032 FromTU, fieldDecl(hasName("x")));
3033 ToF1 = Import(FromF, Lang_CXX);
3034 }
3035 Decl *ToF2;
3036 {
3037 Decl *FromTU = getTuDecl(
3038 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3039 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3040 FromTU, fieldDecl(hasName("x")));
3041 ToF2 = Import(FromF, Lang_CXX);
3042 }
3043 EXPECT_NE(ToF1, ToF2);
3044}
3045
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003046TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003047 Decl *ToM1;
3048 {
3049 Decl *FromTU = getTuDecl(
3050 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
3051 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3052 FromTU, functionDecl(hasName("x"), isDefinition()));
3053 ToM1 = Import(FromM, Lang_CXX);
3054 }
3055 Decl *ToM2;
3056 {
3057 Decl *FromTU = getTuDecl(
3058 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
3059 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3060 FromTU, functionDecl(hasName("x"), isDefinition()));
3061 ToM2 = Import(FromM, Lang_CXX);
3062 }
3063 EXPECT_EQ(ToM1, ToM2);
3064}
3065
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003066TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003067 Decl *ToM1;
3068 {
3069 Decl *FromTU = getTuDecl(
3070 "struct A { void x(); }; void A::x() { }",
3071 Lang_CXX, "input0.cc");
3072 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3073 FromTU, functionDecl(hasName("x"), isDefinition()));
3074 ToM1 = Import(FromM, Lang_CXX);
3075 }
3076 Decl *ToM2;
3077 {
3078 Decl *FromTU = getTuDecl(
3079 "struct A { void x() const; }; void A::x() const { }",
3080 Lang_CXX, "input1.cc");
3081 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3082 FromTU, functionDecl(hasName("x"), isDefinition()));
3083 ToM2 = Import(FromM, Lang_CXX);
3084 }
3085 EXPECT_NE(ToM1, ToM2);
3086}
3087
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003088TEST_P(ASTImporterOptionSpecificTestBase,
3089 ImportUnnamedStructsWithRecursingField) {
Gabor Martonf086fa82018-07-17 12:06:36 +00003090 Decl *FromTU = getTuDecl(
3091 R"(
3092 struct A {
3093 struct {
3094 struct A *next;
3095 } entry0;
3096 struct {
3097 struct A *next;
3098 } entry1;
3099 };
3100 )",
3101 Lang_C, "input0.cc");
3102 auto *From =
3103 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3104
3105 Import(From, Lang_C);
3106
3107 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3108 auto *Entry0 =
3109 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3110 auto *Entry1 =
3111 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3112 auto *R0 = getRecordDecl(Entry0);
3113 auto *R1 = getRecordDecl(Entry1);
3114 EXPECT_NE(R0, R1);
3115 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3116 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3117 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3118 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3119}
3120
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003121TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
Balazs Keri2544b4b2018-08-08 09:40:57 +00003122 Decl *FromTU = getTuDecl(
3123 R"(
3124 void f(int X, int Y, bool Z) {
3125 (void)[X, Y, Z] { (void)Z; };
3126 }
3127 )",
3128 Lang_CXX11, "input0.cc");
3129 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3130 FromTU, functionDecl(hasName("f")));
3131 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3132 EXPECT_TRUE(ToF);
3133
3134 CXXRecordDecl *FromLambda =
3135 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3136 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3137
3138 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3139 EXPECT_TRUE(ToLambda);
3140
3141 // Check if the fields of the lambda class are imported in correct order.
3142 unsigned FromIndex = 0u;
3143 for (auto *FromField : FromLambda->fields()) {
3144 ASSERT_FALSE(FromField->getDeclName());
3145 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3146 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00003147 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3148 EXPECT_TRUE(ToIndex);
3149 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00003150 ++FromIndex;
3151 }
3152
3153 EXPECT_EQ(FromIndex, 3u);
3154}
3155
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003156TEST_P(ASTImporterOptionSpecificTestBase,
3157 MergeFieldDeclsOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003158 std::string ClassTemplate =
3159 R"(
3160 template <typename T>
3161 struct X {
3162 int a{0}; // FieldDecl with InitListExpr
3163 X(char) : a(3) {} // (1)
3164 X(int) {} // (2)
3165 };
3166 )";
3167 Decl *ToTU = getToTuDecl(ClassTemplate +
3168 R"(
3169 void foo() {
3170 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3171 X<char> xc('c');
3172 }
3173 )", Lang_CXX11);
3174 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3175 ToTU, classTemplateSpecializationDecl(hasName("X")));
3176 // FieldDecl without InitlistExpr:
3177 auto *ToField = *ToSpec->field_begin();
3178 ASSERT_TRUE(ToField);
3179 ASSERT_FALSE(ToField->getInClassInitializer());
3180 Decl *FromTU = getTuDecl(ClassTemplate +
3181 R"(
3182 void bar() {
3183 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3184 X<char> xc(1);
3185 }
3186 )", Lang_CXX11);
3187 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3188 FromTU, classTemplateSpecializationDecl(hasName("X")));
3189 // FieldDecl with InitlistExpr:
3190 auto *FromField = *FromSpec->field_begin();
3191 ASSERT_TRUE(FromField);
3192 ASSERT_TRUE(FromField->getInClassInitializer());
3193
3194 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3195 ASSERT_TRUE(ImportedSpec);
3196 EXPECT_EQ(ImportedSpec, ToSpec);
3197 // After the import, the FieldDecl has to be merged, thus it should have the
3198 // InitListExpr.
3199 EXPECT_TRUE(ToField->getInClassInitializer());
3200}
3201
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003202TEST_P(ASTImporterOptionSpecificTestBase,
3203 MergeFunctionOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003204 std::string ClassTemplate =
3205 R"(
3206 template <typename T>
3207 struct X {
3208 void f() {}
3209 void g() {}
3210 };
3211 )";
3212 Decl *ToTU = getToTuDecl(ClassTemplate +
3213 R"(
3214 void foo() {
3215 X<char> x;
3216 x.f();
3217 }
3218 )", Lang_CXX11);
3219 Decl *FromTU = getTuDecl(ClassTemplate +
3220 R"(
3221 void bar() {
3222 X<char> x;
3223 x.g();
3224 }
3225 )", Lang_CXX11);
3226 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3227 FromTU, classTemplateSpecializationDecl(hasName("X")));
3228 auto FunPattern = functionDecl(hasName("g"),
3229 hasParent(classTemplateSpecializationDecl()));
3230 auto *FromFun =
3231 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3232 auto *ToFun =
3233 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3234 ASSERT_TRUE(FromFun->hasBody());
3235 ASSERT_FALSE(ToFun->hasBody());
3236 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3237 ASSERT_TRUE(ImportedSpec);
3238 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3239 ToTU, classTemplateSpecializationDecl(hasName("X")));
3240 EXPECT_EQ(ImportedSpec, ToSpec);
3241 EXPECT_TRUE(ToFun->hasBody());
3242}
3243
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003244TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003245 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3246 std::string ClassTemplate =
3247 R"(
3248 template <typename T>
3249 struct X {};
3250 )";
3251 Decl *ToTU = getToTuDecl(ClassTemplate +
3252 R"(
3253 template <>
3254 struct X<char> {
3255 int a;
3256 };
3257 void foo() {
3258 X<char> x;
3259 }
3260 )",
3261 Lang_CXX11);
3262 Decl *FromTU = getTuDecl(ClassTemplate +
3263 R"(
3264 template <>
3265 struct X<char> {
3266 int b;
3267 };
3268 void foo() {
3269 X<char> x;
3270 }
3271 )",
3272 Lang_CXX11);
3273 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3274 FromTU, classTemplateSpecializationDecl(hasName("X")));
3275 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3276
3277 // We expect one (ODR) warning during the import.
3278 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3279
3280 // The second specialization is different from the first, thus it violates
3281 // ODR, consequently we expect to keep the first specialization only, which is
3282 // already in the "To" context.
Gabor Marton7f8c4002019-03-19 13:34:10 +00003283 EXPECT_FALSE(ImportedSpec);
3284 EXPECT_EQ(1u,
3285 DeclCounter<ClassTemplateSpecializationDecl>().match(
3286 ToTU, classTemplateSpecializationDecl(hasName("X"))));
Gabor Marton42e15de2018-08-22 11:52:14 +00003287}
3288
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003289TEST_P(ASTImporterOptionSpecificTestBase,
3290 MergeCtorOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003291 std::string ClassTemplate =
3292 R"(
3293 template <typename T>
3294 struct X {
3295 X(char) {}
3296 X(int) {}
3297 };
3298 )";
3299 Decl *ToTU = getToTuDecl(ClassTemplate +
3300 R"(
3301 void foo() {
3302 X<char> x('c');
3303 }
3304 )", Lang_CXX11);
3305 Decl *FromTU = getTuDecl(ClassTemplate +
3306 R"(
3307 void bar() {
3308 X<char> x(1);
3309 }
3310 )", Lang_CXX11);
3311 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3312 FromTU, classTemplateSpecializationDecl(hasName("X")));
3313 // Match the void(int) ctor.
3314 auto CtorPattern =
3315 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3316 hasParent(classTemplateSpecializationDecl()));
3317 auto *FromCtor =
3318 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3319 auto *ToCtor =
3320 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3321 ASSERT_TRUE(FromCtor->hasBody());
3322 ASSERT_FALSE(ToCtor->hasBody());
3323 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3324 ASSERT_TRUE(ImportedSpec);
3325 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3326 ToTU, classTemplateSpecializationDecl(hasName("X")));
3327 EXPECT_EQ(ImportedSpec, ToSpec);
3328 EXPECT_TRUE(ToCtor->hasBody());
3329}
3330
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003331TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003332 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3333 auto Code =
3334 R"(
3335 // primary template
3336 template<class T1, class T2, int I>
3337 class A {};
3338
3339 // partial specialization
3340 template<class T, int I>
3341 class A<T, T*, I> {};
3342 )";
3343 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3344 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3345 auto *FromSpec =
3346 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3347 FromTU, classTemplatePartialSpecializationDecl());
3348 auto *ToSpec =
3349 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3350 ToTU, classTemplatePartialSpecializationDecl());
3351
3352 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3353 EXPECT_EQ(ImportedSpec, ToSpec);
3354 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3355 ToTU, classTemplatePartialSpecializationDecl()));
3356}
3357
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003358TEST_P(ASTImporterOptionSpecificTestBase,
3359 ClassTemplateSpecializationsShouldNotBeDuplicated) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003360 auto Code =
3361 R"(
3362 // primary template
3363 template<class T1, class T2, int I>
3364 class A {};
3365
3366 // full specialization
3367 template<>
3368 class A<int, int, 1> {};
3369 )";
3370 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3371 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3372 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3373 FromTU, classTemplateSpecializationDecl());
3374 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3375 ToTU, classTemplateSpecializationDecl());
3376
3377 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3378 EXPECT_EQ(ImportedSpec, ToSpec);
3379 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3380 ToTU, classTemplateSpecializationDecl()));
3381}
3382
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003383TEST_P(ASTImporterOptionSpecificTestBase,
3384 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003385 std::string PrimaryTemplate =
3386 R"(
3387 template<class T1, class T2, int I>
3388 class A {};
3389 )";
3390 auto PartialSpec =
3391 R"(
3392 template<class T, int I>
3393 class A<T, T*, I> {};
3394 )";
3395 auto FullSpec =
3396 R"(
3397 template<>
3398 class A<int, int, 1> {};
3399 )";
3400 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3401 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3402 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3403 FromTU, classTemplateSpecializationDecl());
3404
3405 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3406 EXPECT_TRUE(ImportedSpec);
3407 // Check the number of partial specializations.
3408 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3409 ToTU, classTemplatePartialSpecializationDecl()));
3410 // Check the number of full specializations.
3411 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3412 ToTU, classTemplateSpecializationDecl(
3413 unless(classTemplatePartialSpecializationDecl()))));
3414}
3415
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003416TEST_P(ASTImporterOptionSpecificTestBase,
3417 InitListExprValueKindShouldBeImported) {
Gabor Martona20ce602018-09-03 13:10:53 +00003418 Decl *TU = getTuDecl(
3419 R"(
3420 const int &init();
3421 void foo() { const int &a{init()}; }
3422 )", Lang_CXX11, "input0.cc");
3423 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3424 ASSERT_TRUE(FromD->getAnyInitializer());
3425 auto *InitExpr = FromD->getAnyInitializer();
3426 ASSERT_TRUE(InitExpr);
3427 ASSERT_TRUE(InitExpr->isGLValue());
3428
3429 auto *ToD = Import(FromD, Lang_CXX11);
3430 EXPECT_TRUE(ToD);
3431 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3432 EXPECT_TRUE(ToInitExpr);
3433 EXPECT_TRUE(ToInitExpr->isGLValue());
3434}
3435
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003436struct ImportVariables : ASTImporterOptionSpecificTestBase {};
Gabor Martonac3a5d62018-09-17 12:04:52 +00003437
3438TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3439 Decl *FromTU = getTuDecl(
3440 R"(
3441 struct A {
3442 static const int a = 1 + 2;
3443 };
3444 const int A::a;
3445 )", Lang_CXX, "input1.cc");
3446
3447 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3448 FromTU, varDecl(hasName("a"))); // Decl with init
3449 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3450 FromTU, varDecl(hasName("a"))); // Decl with definition
3451 ASSERT_NE(FromDWithInit, FromDWithDef);
3452 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3453
3454 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3455 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3456 ASSERT_TRUE(ToD0);
3457 ASSERT_TRUE(ToD1);
3458 EXPECT_NE(ToD0, ToD1);
3459 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3460}
3461
3462TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3463 auto StructA =
3464 R"(
3465 struct A {
3466 static const int a = 1 + 2;
3467 };
3468 )";
3469 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3470 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3471 "input1.cc");
3472
3473 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3474 FromTU, varDecl(hasName("a"))); // Decl with init
3475 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3476 FromTU, varDecl(hasName("a"))); // Decl with definition
3477 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3478 ASSERT_TRUE(FromDWithInit->getInit());
3479 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3480 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3481 ASSERT_FALSE(FromDWithDef->getInit());
3482
3483 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3484 ToTU, varDecl(hasName("a"))); // Decl with init
3485 ASSERT_TRUE(ToD->getInit());
3486 ASSERT_FALSE(ToD->getDefinition());
3487
3488 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3489 EXPECT_TRUE(ImportedD->getAnyInitializer());
3490 EXPECT_TRUE(ImportedD->getDefinition());
3491}
3492
3493TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3494 auto StructA =
3495 R"(
3496 struct A {
3497 static const int a;
3498 };
3499 )";
3500 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3501 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3502 Lang_CXX, "input1.cc");
3503
3504 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3505 FromTU, varDecl(hasName("a")));
3506 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3507 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3508 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3509 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3510 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3511 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3512 ASSERT_TRUE(FromDWithDef->getInit());
3513
3514 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3515 ToTU, varDecl(hasName("a")));
3516 ASSERT_FALSE(ToD->getInit());
3517 ASSERT_FALSE(ToD->getDefinition());
3518
3519 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3520 EXPECT_TRUE(ImportedD->getAnyInitializer());
3521 EXPECT_TRUE(ImportedD->getDefinition());
3522}
3523
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003524struct ImportClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003525
Gabor Marton54058b52018-12-17 13:53:12 +00003526TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3527 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
3528 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3529 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3530 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3531 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3532
3533 Decl *ImportedDef = Import(FromDef, Lang_C);
3534
3535 EXPECT_NE(ImportedDef, ToProto);
3536 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3537 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3538 EXPECT_TRUE(ImportedDef == ToDef);
3539 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3540 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3541 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3542}
3543
3544TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3545 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
3546 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
3547 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3548 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3549 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3550
3551 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3552
3553 EXPECT_NE(ImportedDef, ToProto);
3554 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3555 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3556 EXPECT_TRUE(ImportedDef == ToDef);
3557 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3558 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3559 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3560}
3561
3562TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3563 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
3564 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3565 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3566 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3567 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3568
3569 Decl *ImportedProto = Import(FromProto, Lang_C);
3570 Decl *ImportedDef = Import(FromDef, Lang_C);
3571 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3572
3573 EXPECT_NE(ImportedDef, ImportedProto);
3574 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3575 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3576 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3577 EXPECT_TRUE(ImportedDef == ToDef);
3578 EXPECT_TRUE(ImportedProto == ToProto);
3579 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3580 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3581 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3582}
3583
Gabor Marton7df342a2018-12-17 12:42:12 +00003584
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003585struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003586
3587TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
3588 Decl *FromTU = getTuDecl(
3589 R"(
3590 class A {
3591 template <int I> class F {};
3592 class X {
3593 template <int I> friend class F;
3594 };
3595 };
3596 )",
3597 Lang_CXX, "input0.cc");
3598
3599 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3600 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
3601 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
3602 FromTU, cxxRecordDecl(hasName("F")));
3603
3604 ASSERT_TRUE(FromClass);
3605 ASSERT_TRUE(FromFriendClass);
3606 ASSERT_NE(FromClass, FromFriendClass);
3607 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
3608 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
3609 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3610 FromClass->getDescribedClassTemplate());
3611
3612 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
3613 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
3614
3615 EXPECT_TRUE(ToClass);
3616 EXPECT_TRUE(ToFriendClass);
3617 EXPECT_NE(ToClass, ToFriendClass);
3618 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
3619 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
3620 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3621 ToClass->getDescribedClassTemplate());
3622}
3623
3624TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
3625 Decl *FromTu = getTuDecl(
3626 R"(
3627 class declToImport {
3628 friend class declToImport;
3629 };
3630 )",
3631 Lang_CXX, "input.cc");
3632
3633 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
3634 FromTu, cxxRecordDecl(hasName("declToImport")));
3635 auto *ToD = Import(FromD, Lang_CXX);
3636 auto Pattern = cxxRecordDecl(has(friendDecl()));
3637 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3638 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3639}
3640
3641TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
3642 Decl *FromTu = getTuDecl(
3643 R"(
3644 template<class A> class declToImport {
3645 template<class A1> friend class declToImport;
3646 };
3647 )",
3648 Lang_CXX, "input.cc");
3649
3650 auto *FromD =
3651 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
3652 auto *ToD = Import(FromD, Lang_CXX);
3653
3654 auto Pattern = classTemplateDecl(
3655 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
3656 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3657 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3658
3659 auto *Class =
3660 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
3661 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
3662 EXPECT_NE(Friend->getFriendDecl(), Class);
3663 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
3664}
3665
3666TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
3667 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
3668
3669 ClassTemplateSpecializationDecl *Imported1;
3670 {
3671 Decl *FromTU = getTuDecl("template<class T> class X;"
3672 "struct Y { friend class X<int>; };",
3673 Lang_CXX, "input0.cc");
3674 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3675 FromTU, Pattern);
3676
3677 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3678 }
3679 ClassTemplateSpecializationDecl *Imported2;
3680 {
3681 Decl *FromTU = getTuDecl("template<class T> class X;"
3682 "template<> class X<int>{};"
3683 "struct Z { friend class X<int>; };",
3684 Lang_CXX, "input1.cc");
3685 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3686 FromTU, Pattern);
3687
3688 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3689 }
3690
3691 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3692 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
3693 2u);
3694 ASSERT_TRUE(Imported2->getPreviousDecl());
3695 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
3696}
3697
3698TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
3699 Decl *FromTU0 = getTuDecl(
3700 R"(
3701 class X {
3702 class Y;
3703 };
3704 class X::Y {
3705 template <typename T>
3706 friend class F; // The decl context of F is the global namespace.
3707 };
3708 )",
3709 Lang_CXX, "input0.cc");
3710 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3711 FromTU0, classTemplateDecl(hasName("F")));
3712 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3713 Decl *FromTU1 = getTuDecl(
3714 R"(
3715 template <typename T>
3716 class F {};
3717 )",
3718 Lang_CXX, "input1.cc");
3719 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3720 FromTU1, classTemplateDecl(hasName("F")));
3721 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3722 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
3723 Imported1->getTemplatedDecl()->getTypeForDecl());
3724}
3725
3726TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
3727 Decl *From, *To;
3728 std::tie(From, To) =
3729 getImportedDecl("class declToImport {};", Lang_CXX,
3730 "class Y { friend class declToImport; };", Lang_CXX);
3731 auto *Imported = cast<CXXRecordDecl>(To);
3732
3733 EXPECT_TRUE(Imported->getPreviousDecl());
3734}
3735
3736TEST_P(ImportFriendClasses,
3737 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
3738 Decl *ToTU = getToTuDecl(
3739 R"(
3740 class X {
3741 class Y;
3742 };
3743 class X::Y {
3744 template <typename T>
3745 friend class F; // The decl context of F is the global namespace.
3746 };
3747 )",
3748 Lang_CXX);
3749 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
3750 ToTU, classTemplateDecl(hasName("F")));
3751 Decl *FromTU = getTuDecl(
3752 R"(
3753 template <typename T>
3754 class F {};
3755 )",
3756 Lang_CXX, "input0.cc");
3757 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3758 FromTU, classTemplateDecl(hasName("F")));
3759 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3760 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3761 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
3762 EXPECT_EQ(ToDecl->getTemplatedDecl(),
3763 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3764}
3765
3766TEST_P(ImportFriendClasses,
3767 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
3768 Decl *FromTU0 = getTuDecl(
3769 R"(
3770 class X {
3771 class Y;
3772 };
3773 class X::Y {
3774 template <typename T>
3775 friend class F; // The decl context of F is the global namespace.
3776 };
3777 )",
3778 Lang_CXX, "input0.cc");
3779 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3780 FromTU0, classTemplateDecl(hasName("F")));
3781 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3782 Decl *FromTU1 = getTuDecl(
3783 R"(
3784 template <typename T>
3785 class F {};
3786 )",
3787 Lang_CXX, "input1.cc");
3788 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3789 FromTU1, classTemplateDecl(hasName("F")));
3790 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3791 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3792 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3793 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
3794 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3795}
3796
3797TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
3798 Decl *FromTU0 = getTuDecl(
3799 R"(
3800 class X {
3801 class Y;
3802 };
3803 class X::Y {
3804 friend class F; // The decl context of F is the global namespace.
3805 };
3806 )",
3807 Lang_CXX, "input0.cc");
3808 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
3809 QualType FT = Friend->getFriendType()->getType();
3810 FT = FromTU0->getASTContext().getCanonicalType(FT);
3811 auto *Fwd = cast<TagType>(FT)->getDecl();
3812 auto *ImportedFwd = Import(Fwd, Lang_CXX);
3813 Decl *FromTU1 = getTuDecl(
3814 R"(
3815 class F {};
3816 )",
3817 Lang_CXX, "input1.cc");
3818 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
3819 FromTU1, cxxRecordDecl(hasName("F")));
3820 auto *ImportedDef = Import(Definition, Lang_CXX);
3821 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3822 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3823}
3824
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003825TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Gabor Marton54058b52018-12-17 13:53:12 +00003826 auto *Code = R"(
3827 template <class T>
3828 struct X {
3829 friend void foo(){}
3830 };
3831 )";
3832 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
3833 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
3834 ToTU, functionDecl(hasName("foo")));
3835
3836 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
3837 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
3838 FromTU, functionDecl(hasName("foo")));
3839 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
3840 EXPECT_EQ(ImportedFoo, ToFoo);
3841}
3842
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003843struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton61d862a2018-05-18 09:08:47 +00003844
3845TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
3846 Decl *TU = getTuDecl(
3847 R"(
3848 namespace NS {
3849
3850 template <typename T>
3851 struct S {};
3852 template struct S<int>;
3853
3854 inline namespace INS {
3855 template <typename T>
3856 struct S {};
3857 template struct S<int>;
3858 }
3859
3860 }
3861 )", Lang_CXX11, "input0.cc");
3862 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
3863 TU, namespaceDecl());
3864 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3865 TU, classTemplateSpecializationDecl());
3866 ASSERT_TRUE(NS->containsDecl(Spec));
3867
3868 NS->removeDecl(Spec);
3869 EXPECT_FALSE(NS->containsDecl(Spec));
3870}
3871
Gabor Marton7df342a2018-12-17 12:42:12 +00003872TEST_P(DeclContextTest,
3873 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
3874 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
3875 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
3876 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
3877
3878 // Investigate the list.
3879 auto *DC = A0->getDeclContext();
3880 ASSERT_TRUE(DC->containsDecl(A0));
3881 ASSERT_TRUE(DC->containsDecl(A1));
3882
3883 // Investigate the lookup table.
3884 auto *Map = DC->getLookupPtr();
3885 ASSERT_TRUE(Map);
3886 auto I = Map->find(A0->getDeclName());
3887 ASSERT_NE(I, Map->end());
3888 StoredDeclsList &L = I->second;
3889 // The lookup table contains the most recent decl of A.
3890 ASSERT_NE(L.getAsDecl(), A0);
3891 ASSERT_EQ(L.getAsDecl(), A1);
3892
3893 ASSERT_TRUE(L.getAsDecl());
3894 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
3895 // The point here is to have a Vec with only one element, which is not the
3896 // one we are going to delete from the DC later.
3897 L.setHasExternalDecls();
3898 ASSERT_TRUE(L.getAsVector());
3899 ASSERT_EQ(1u, L.getAsVector()->size());
3900
3901 // This asserts in the old implementation.
3902 DC->removeDecl(A0);
3903 EXPECT_FALSE(DC->containsDecl(A0));
3904}
3905
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003906struct ImportFunctionTemplateSpecializations
3907 : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +00003908
3909TEST_P(ImportFunctionTemplateSpecializations,
3910 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
3911
3912 Decl *FromTU = getTuDecl(
3913 R"(
3914 template<class T>
3915 int f() { return 0; }
3916 void foo() { f<int>(); }
3917 )",
3918 Lang_CXX, "input0.cc");
3919
3920 // Check that the function template instantiation is NOT the child of the TU.
3921 auto Pattern = translationUnitDecl(
3922 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
3923 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3924
3925 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
3926 FromTU, functionDecl(hasName("foo")));
3927 ASSERT_TRUE(Import(Foo, Lang_CXX));
3928
3929 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3930 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3931}
3932
3933TEST_P(ImportFunctionTemplateSpecializations,
3934 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
3935
3936 Decl *FromTU = getTuDecl(
3937 R"(
3938 template<class T>
3939 int f() { return 0; }
3940 template int f<int>();
3941 )",
3942 Lang_CXX, "input0.cc");
3943
3944 // Check that the function template instantiation is NOT the child of the TU.
3945 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
3946 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
3947 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3948
3949 ASSERT_TRUE(
3950 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
3951
3952 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3953 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3954}
3955
3956TEST_P(ImportFunctionTemplateSpecializations,
3957 TUshouldContainFunctionTemplateSpecialization) {
3958
3959 Decl *FromTU = getTuDecl(
3960 R"(
3961 template<class T>
3962 int f() { return 0; }
3963 template <> int f<int>() { return 4; }
3964 )",
3965 Lang_CXX, "input0.cc");
3966
3967 // Check that the function template specialization is the child of the TU.
3968 auto Specialization =
3969 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3970 auto Pattern = translationUnitDecl(has(Specialization));
3971 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3972
3973 ASSERT_TRUE(
3974 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
3975
3976 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3977 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3978}
3979
3980TEST_P(ImportFunctionTemplateSpecializations,
3981 FunctionTemplateSpecializationRedeclChain) {
3982
3983 Decl *FromTU = getTuDecl(
3984 R"(
3985 template<class T>
3986 int f() { return 0; }
3987 template <> int f<int>() { return 4; }
3988 )",
3989 Lang_CXX, "input0.cc");
3990
3991 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
3992 hasParent(translationUnitDecl()));
3993 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
3994 {
3995 auto *TU = FromTU;
3996 auto *SpecD = FromSpecD;
3997 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
3998 TU, functionTemplateDecl());
3999 auto *FirstSpecD = *(TemplateD->spec_begin());
4000 ASSERT_EQ(SpecD, FirstSpecD);
4001 ASSERT_TRUE(SpecD->getPreviousDecl());
4002 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4003 ->doesThisDeclarationHaveABody());
4004 }
4005
4006 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
4007
4008 {
4009 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4010 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4011 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4012 TU, functionTemplateDecl());
4013 auto *FirstSpecD = *(TemplateD->spec_begin());
4014 EXPECT_EQ(SpecD, FirstSpecD);
4015 ASSERT_TRUE(SpecD->getPreviousDecl());
4016 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4017 ->doesThisDeclarationHaveABody());
4018 }
4019}
4020
4021TEST_P(ImportFunctionTemplateSpecializations,
4022 MatchNumberOfFunctionTemplateSpecializations) {
4023
4024 Decl *FromTU = getTuDecl(
4025 R"(
4026 template <typename T> constexpr int f() { return 0; }
4027 template <> constexpr int f<int>() { return 4; }
4028 void foo() {
4029 static_assert(f<char>() == 0, "");
4030 static_assert(f<int>() == 4, "");
4031 }
4032 )",
4033 Lang_CXX11, "input0.cc");
4034 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4035 FromTU, functionDecl(hasName("foo")));
4036
4037 Import(FromD, Lang_CXX11);
4038 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4039 EXPECT_EQ(
4040 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4041 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4042}
4043
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004044TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton17d39672018-11-26 15:54:08 +00004045 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4046 {
4047 Decl *FromTU = getTuDecl(
4048 R"(
4049 template <typename T>
4050 struct B;
4051 )",
4052 Lang_CXX, "input0.cc");
4053 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4054 FromTU, classTemplateDecl(hasName("B")));
4055
4056 Import(FromD, Lang_CXX);
4057 }
4058
4059 {
4060 Decl *FromTU = getTuDecl(
4061 R"(
4062 template <typename T>
4063 struct B {
4064 void f();
4065 B* b;
4066 };
4067 )",
4068 Lang_CXX, "input1.cc");
4069 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4070 FromTU, functionDecl(hasName("f")));
4071 Import(FromD, Lang_CXX);
4072 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4073 FromTU, classTemplateDecl(hasName("B")));
4074 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
4075 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4076
4077 // We expect no (ODR) warning during the import.
4078 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4079 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4080 }
4081}
4082
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004083TEST_P(ASTImporterOptionSpecificTestBase,
4084 ImportingTypedefShouldImportTheCompleteType) {
Gabor Martonb93baf62018-11-27 09:51:36 +00004085 // We already have an incomplete underlying type in the "To" context.
4086 auto Code =
4087 R"(
4088 template <typename T>
4089 struct S {
4090 void foo();
4091 };
4092 using U = S<int>;
4093 )";
4094 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4095 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4096 typedefNameDecl(hasName("U")));
4097 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4098
4099 // The "From" context has the same typedef, but the underlying type is
4100 // complete this time.
4101 Decl *FromTU = getTuDecl(std::string(Code) +
4102 R"(
4103 void foo(U* u) {
4104 u->foo();
4105 }
4106 )", Lang_CXX11);
4107 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4108 typedefNameDecl(hasName("U")));
4109 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4110
4111 // The imported type should be complete.
4112 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4113 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4114}
4115
Balazs Keri1efc9742019-05-07 10:55:11 +00004116TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) {
4117 auto Code =
4118 R"(
4119 template<class T>
4120 int f() { return 0; }
4121 template <> int f<int>() { return 4; }
4122 )";
4123
4124 Decl *FromTU = getTuDecl(Code, Lang_CXX);
4125 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU,
4126 functionDecl(hasName("f"), isExplicitTemplateSpecialization()));
Balazs Kerib7d8cff2019-05-07 14:53:04 +00004127 ASSERT_EQ(FromD->getNumTemplateParameterLists(), 1u);
Balazs Keri1efc9742019-05-07 10:55:11 +00004128
4129 auto *ToD = Import(FromD, Lang_CXX);
4130 // The template parameter list should exist.
Balazs Kerib7d8cff2019-05-07 14:53:04 +00004131 EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u);
Balazs Keri1efc9742019-05-07 10:55:11 +00004132}
4133
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004134struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton54058b52018-12-17 13:53:12 +00004135
4136TEST_P(ASTImporterLookupTableTest, OneDecl) {
4137 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
4138 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4139 ASTImporterLookupTable LT(*ToTU);
4140 auto Res = LT.lookup(ToTU, D->getDeclName());
4141 ASSERT_EQ(Res.size(), 1u);
4142 EXPECT_EQ(*Res.begin(), D);
4143}
4144
4145static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4146 for (Decl *D : DC->decls()) {
4147 if (auto *ND = dyn_cast<NamedDecl>(D))
4148 if (ND->getDeclName() == Name)
4149 return ND;
4150 }
4151 return nullptr;
Martin Storsjo85833392018-12-18 08:36:16 +00004152}
Gabor Marton54058b52018-12-17 13:53:12 +00004153
4154TEST_P(ASTImporterLookupTableTest,
4155 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4156 auto *Code = R"(
4157 template <class T>
4158 struct X {
4159 friend void foo(){}
4160 };
4161 )";
4162 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4163 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
4164 ToTU, classTemplateDecl(hasName("X")));
4165 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4166 ToTU, functionDecl(hasName("foo")));
4167 DeclContext *FooDC = Foo->getDeclContext();
4168 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4169 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
4170 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4171 DeclarationName FooName = Foo->getDeclName();
4172
4173 // Cannot find in the LookupTable of its DC (TUDecl)
4174 SmallVector<NamedDecl *, 2> FoundDecls;
4175 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4176 EXPECT_EQ(FoundDecls.size(), 0u);
4177
4178 // Cannot find in the LookupTable of its LexicalDC (X)
4179 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4180 EXPECT_EQ(FoundDecls.size(), 0u);
4181
4182 // Can't find in the list of Decls of the DC.
4183 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4184
4185 // Can't find in the list of Decls of the LexicalDC
4186 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
4187
4188 // ASTImporter specific lookup finds it.
4189 ASTImporterLookupTable LT(*ToTU);
4190 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4191 ASSERT_EQ(Res.size(), 1u);
4192 EXPECT_EQ(*Res.begin(), Foo);
4193}
4194
4195TEST_P(ASTImporterLookupTableTest,
4196 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
4197 TranslationUnitDecl *ToTU =
4198 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
4199 auto *Foo =
4200 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
4201 auto *A =
4202 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4203 DeclContext *FooDC = Foo->getDeclContext();
4204 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4205 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
4206 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4207 DeclarationName FooName = Foo->getDeclName();
4208
4209 // Cannot find in the LookupTable of its DC (TUDecl).
4210 SmallVector<NamedDecl *, 2> FoundDecls;
4211 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4212 EXPECT_EQ(FoundDecls.size(), 0u);
4213
4214 // Cannot find in the LookupTable of its LexicalDC (A).
4215 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4216 EXPECT_EQ(FoundDecls.size(), 0u);
4217
4218 // Can't find in the list of Decls of the DC.
4219 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4220
4221 // Can find in the list of Decls of the LexicalDC.
4222 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
4223
4224 // ASTImporter specific lookup finds it.
4225 ASTImporterLookupTable LT(*ToTU);
4226 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4227 ASSERT_EQ(Res.size(), 1u);
4228 EXPECT_EQ(*Res.begin(), Foo);
4229}
4230
4231TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
4232 TranslationUnitDecl *ToTU =
4233 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
4234 DeclarationName VName = FirstDeclMatcher<VarDecl>()
4235 .match(ToTU, varDecl(hasName("V")))
4236 ->getDeclName();
4237 auto *A =
4238 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4239 auto *B =
4240 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
4241
4242 ASTImporterLookupTable LT(*ToTU);
4243
4244 auto Res = LT.lookup(cast<DeclContext>(A), VName);
4245 ASSERT_EQ(Res.size(), 1u);
4246 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4247 ToTU, fieldDecl(hasName("V"),
4248 hasParent(recordDecl(hasName("A"))))));
4249 Res = LT.lookup(cast<DeclContext>(B), VName);
4250 ASSERT_EQ(Res.size(), 1u);
4251 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4252 ToTU, fieldDecl(hasName("V"),
4253 hasParent(recordDecl(hasName("B"))))));
4254 Res = LT.lookup(ToTU, VName);
4255 ASSERT_EQ(Res.size(), 1u);
4256 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
4257 ToTU, varDecl(hasName("V"),
4258 hasParent(translationUnitDecl()))));
4259}
4260
4261TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
4262 TranslationUnitDecl *ToTU = getToTuDecl(
4263 R"(
4264 void foo();
4265 void foo(int);
4266 void foo(int, int);
4267 )",
4268 Lang_CXX);
4269
4270 ASTImporterLookupTable LT(*ToTU);
4271 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4272 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4273 DeclarationName Name = F0->getDeclName();
4274 auto Res = LT.lookup(ToTU, Name);
4275 EXPECT_EQ(Res.size(), 3u);
4276 EXPECT_EQ(Res.count(F0), 1u);
4277 EXPECT_EQ(Res.count(F2), 1u);
4278}
4279
Gabor Martona9cab312019-02-08 09:19:34 +00004280TEST_P(ASTImporterLookupTableTest,
4281 DifferentOperatorsShouldHaveDifferentResultSet) {
4282 TranslationUnitDecl *ToTU = getToTuDecl(
4283 R"(
4284 struct X{};
4285 void operator+(X, X);
4286 void operator-(X, X);
4287 )",
4288 Lang_CXX);
4289
4290 ASTImporterLookupTable LT(*ToTU);
4291 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
4292 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4293 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
4294 ToTU, functionDecl(hasOverloadedOperatorName("-")));
4295 DeclarationName NamePlus = FPlus->getDeclName();
4296 auto ResPlus = LT.lookup(ToTU, NamePlus);
4297 EXPECT_EQ(ResPlus.size(), 1u);
4298 EXPECT_EQ(ResPlus.count(FPlus), 1u);
4299 EXPECT_EQ(ResPlus.count(FMinus), 0u);
4300 DeclarationName NameMinus = FMinus->getDeclName();
4301 auto ResMinus = LT.lookup(ToTU, NameMinus);
4302 EXPECT_EQ(ResMinus.size(), 1u);
4303 EXPECT_EQ(ResMinus.count(FMinus), 1u);
4304 EXPECT_EQ(ResMinus.count(FPlus), 0u);
4305 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
4306}
4307
4308TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
4309 TranslationUnitDecl *ToTU = getToTuDecl(
4310 R"(
4311 struct X {};
4312 void operator+(X, X);
4313 )",
4314 Lang_CXX);
4315 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
4316 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4317
4318 Decl *FromTU = getTuDecl(
4319 R"(
4320 struct X {};
4321 void operator+(X, X);
4322 )",
4323 Lang_CXX);
4324 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
4325 FromTU, functionDecl(hasOverloadedOperatorName("+")));
4326
4327 // FromPlus have a different TU, thus its DeclarationName is different too.
4328 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
4329
4330 ASTImporterLookupTable LT(*ToTU);
4331 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
4332 ASSERT_EQ(Res.size(), 1u);
4333 EXPECT_EQ(*Res.begin(), ToPlus);
4334
4335 // FromPlus have a different TU, thus its DeclarationName is different too.
4336 Res = LT.lookup(ToTU, FromPlus->getDeclName());
4337 ASSERT_EQ(Res.size(), 0u);
4338}
4339
Gabor Martondd2b76e2019-06-11 13:35:25 +00004340static const RecordDecl *getRecordDeclOfFriend(FriendDecl *FD) {
4341 QualType Ty = FD->getFriendType()->getType().getCanonicalType();
4342 return cast<RecordType>(Ty)->getDecl();
Gabor Marton54058b52018-12-17 13:53:12 +00004343}
4344
Gabor Martondd2b76e2019-06-11 13:35:25 +00004345TEST_P(ASTImporterLookupTableTest,
4346 LookupFindsFwdFriendClassDeclWithElaboratedType) {
Gabor Marton54058b52018-12-17 13:53:12 +00004347 TranslationUnitDecl *ToTU = getToTuDecl(
4348 R"(
4349 class Y { friend class F; };
4350 )",
4351 Lang_CXX);
4352
4353 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4354 // So we must dig up the underlying CXXRecordDecl.
4355 ASTImporterLookupTable LT(*ToTU);
4356 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4357 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4358 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
4359 ToTU, cxxRecordDecl(hasName("Y")));
4360
4361 DeclarationName Name = RD->getDeclName();
4362 auto Res = LT.lookup(ToTU, Name);
4363 EXPECT_EQ(Res.size(), 1u);
4364 EXPECT_EQ(*Res.begin(), RD);
4365
4366 Res = LT.lookup(Y, Name);
4367 EXPECT_EQ(Res.size(), 0u);
4368}
4369
Gabor Martondd2b76e2019-06-11 13:35:25 +00004370TEST_P(ASTImporterLookupTableTest,
4371 LookupFindsFwdFriendClassDeclWithUnelaboratedType) {
4372 TranslationUnitDecl *ToTU = getToTuDecl(
4373 R"(
4374 class F;
4375 class Y { friend F; };
4376 )",
4377 Lang_CXX11);
4378
4379 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4380 // So we must dig up the underlying CXXRecordDecl.
4381 ASTImporterLookupTable LT(*ToTU);
4382 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4383 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4384 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, cxxRecordDecl(hasName("Y")));
4385
4386 DeclarationName Name = RD->getDeclName();
4387 auto Res = LT.lookup(ToTU, Name);
4388 EXPECT_EQ(Res.size(), 1u);
4389 EXPECT_EQ(*Res.begin(), RD);
4390
4391 Res = LT.lookup(Y, Name);
4392 EXPECT_EQ(Res.size(), 0u);
4393}
4394
4395TEST_P(ASTImporterLookupTableTest,
4396 LookupFindsFriendClassDeclWithTypeAliasDoesNotAssert) {
4397 TranslationUnitDecl *ToTU = getToTuDecl(
4398 R"(
4399 class F;
4400 using alias_of_f = F;
4401 class Y { friend alias_of_f; };
4402 )",
4403 Lang_CXX11);
4404
4405 // ASTImporterLookupTable constructor handles using declarations correctly,
4406 // no assert is expected.
4407 ASTImporterLookupTable LT(*ToTU);
4408
4409 auto *Alias = FirstDeclMatcher<TypeAliasDecl>().match(
4410 ToTU, typeAliasDecl(hasName("alias_of_f")));
4411 DeclarationName Name = Alias->getDeclName();
4412 auto Res = LT.lookup(ToTU, Name);
4413 EXPECT_EQ(Res.count(Alias), 1u);
4414}
4415
Gabor Marton54058b52018-12-17 13:53:12 +00004416TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
4417 TranslationUnitDecl *ToTU = getToTuDecl(
4418 R"(
4419 class Y { template <class T> friend class F; };
4420 )",
4421 Lang_CXX);
4422
4423 ASTImporterLookupTable LT(*ToTU);
4424 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4425 ToTU, classTemplateDecl(hasName("F")));
4426 DeclarationName Name = F->getDeclName();
4427 auto Res = LT.lookup(ToTU, Name);
4428 EXPECT_EQ(Res.size(), 2u);
4429 EXPECT_EQ(Res.count(F), 1u);
4430 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4431}
4432
4433TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
4434 TranslationUnitDecl *ToTU = getToTuDecl(
4435 R"(
4436 template <typename T>
4437 class F;
4438
4439 template <typename T>
4440 class Y {
4441 friend class F<T>;
4442 };
4443 )",
4444 Lang_CXX);
4445
4446 ASTImporterLookupTable LT(*ToTU);
4447 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4448 ToTU, classTemplateDecl(hasName("F")));
4449 DeclarationName Name = F->getDeclName();
4450 auto Res = LT.lookup(ToTU, Name);
4451 EXPECT_EQ(Res.size(), 2u);
4452 EXPECT_EQ(Res.count(F), 1u);
4453 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4454}
4455
4456TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
4457 TranslationUnitDecl *ToTU = getToTuDecl(
4458 R"(
4459 template <typename T>
4460 class F;
4461
4462 class Y {
4463 friend class F<int>;
4464 };
4465 )",
4466 Lang_CXX);
4467
4468 ASTImporterLookupTable LT(*ToTU);
4469 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4470 ToTU, classTemplateDecl(hasName("F")));
4471 DeclarationName Name = F->getDeclName();
4472 auto Res = LT.lookup(ToTU, Name);
4473 ASSERT_EQ(Res.size(), 3u);
4474 EXPECT_EQ(Res.count(F), 1u);
4475 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4476 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
4477}
4478
4479TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
4480 TranslationUnitDecl *ToTU = getToTuDecl(
4481 R"(
4482 class Y { friend void F(); };
4483 )",
4484 Lang_CXX);
4485
4486 ASTImporterLookupTable LT(*ToTU);
4487 auto *F =
4488 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
4489 DeclarationName Name = F->getDeclName();
4490 auto Res = LT.lookup(ToTU, Name);
4491 EXPECT_EQ(Res.size(), 1u);
4492 EXPECT_EQ(*Res.begin(), F);
4493}
4494
4495TEST_P(ASTImporterLookupTableTest,
4496 LookupFindsDeclsInClassTemplateSpecialization) {
4497 TranslationUnitDecl *ToTU = getToTuDecl(
4498 R"(
4499 template <typename T>
4500 struct X {
4501 int F;
4502 };
4503 void foo() {
4504 X<char> xc;
4505 }
4506 )",
4507 Lang_CXX);
4508
4509 ASTImporterLookupTable LT(*ToTU);
4510
4511 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
4512 ToTU, classTemplateDecl(hasName("X")));
4513 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
4514 ToTU,
4515 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
4516
4517 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4518 ToTU, classTemplateSpecializationDecl(hasName("X")));
4519 FieldDecl *FieldInSpec = *Spec->field_begin();
4520 ASSERT_TRUE(FieldInSpec);
4521
4522 DeclarationName Name = FieldInSpec->getDeclName();
4523 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
4524
4525 SmallVector<NamedDecl *, 2> FoundDecls;
4526 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
4527 EXPECT_EQ(FoundDecls.size(), 1u);
4528 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
4529
4530 auto Res = LT.lookup(TemplateDC, Name);
4531 ASSERT_EQ(Res.size(), 1u);
4532 EXPECT_EQ(*Res.begin(), FieldInTemplate);
4533
4534 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
4535 FoundDecls);
4536 EXPECT_EQ(FoundDecls.size(), 1u);
4537 EXPECT_EQ(FoundDecls[0], FieldInSpec);
4538
4539 Res = LT.lookup(cast<DeclContext>(Spec), Name);
4540 ASSERT_EQ(Res.size(), 1u);
4541 EXPECT_EQ(*Res.begin(), FieldInSpec);
4542}
4543
4544TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
4545 TranslationUnitDecl *ToTU = getToTuDecl(
4546 R"(
4547 class Y { template <class T> friend void F(); };
4548 )",
4549 Lang_CXX);
4550
4551 ASTImporterLookupTable LT(*ToTU);
4552 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
4553 ToTU, functionTemplateDecl(hasName("F")));
4554 DeclarationName Name = F->getDeclName();
4555 auto Res = LT.lookup(ToTU, Name);
4556 EXPECT_EQ(Res.size(), 2u);
4557 EXPECT_EQ(Res.count(F), 1u);
4558 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4559}
4560
4561TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
4562 TranslationUnitDecl *ToTU = getToTuDecl(
4563 R"(
4564 struct X;
4565 struct A {
4566 friend struct X;
4567 };
4568 struct B {
4569 friend struct X;
4570 };
4571 )",
4572 Lang_CXX);
4573
4574 ASTImporterLookupTable LT(*ToTU);
4575 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
4576 ToTU, cxxRecordDecl(hasName("X")));
4577 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4578 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4579 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
4580 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
4581 ASSERT_EQ(RD0, RD1);
4582 ASSERT_EQ(RD1, X);
4583
4584 DeclarationName Name = X->getDeclName();
4585 auto Res = LT.lookup(ToTU, Name);
4586 EXPECT_EQ(Res.size(), 1u);
4587 EXPECT_EQ(*Res.begin(), X);
4588}
4589
4590TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
4591 TranslationUnitDecl *ToTU = getToTuDecl(
4592 R"(
4593 enum E {
4594 A,
4595 B
4596 };
4597 )",
4598 Lang_C);
4599
4600 ASTImporterLookupTable LT(*ToTU);
4601 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
4602 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
4603 ToTU, enumConstantDecl(hasName("A")));
4604
4605 DeclarationName Name = A->getDeclName();
4606 // Redecl context is the TU.
4607 ASSERT_EQ(E->getRedeclContext(), ToTU);
4608
4609 SmallVector<NamedDecl *, 2> FoundDecls;
4610 // Normal lookup finds in the DC.
4611 E->localUncachedLookup(Name, FoundDecls);
4612 EXPECT_EQ(FoundDecls.size(), 1u);
4613
4614 // Normal lookup finds in the Redecl context.
4615 ToTU->localUncachedLookup(Name, FoundDecls);
4616 EXPECT_EQ(FoundDecls.size(), 1u);
4617
4618 // Import specific lookup finds in the DC.
4619 auto Res = LT.lookup(E, Name);
4620 ASSERT_EQ(Res.size(), 1u);
4621 EXPECT_EQ(*Res.begin(), A);
4622
4623 // Import specific lookup finds in the Redecl context.
4624 Res = LT.lookup(ToTU, Name);
4625 ASSERT_EQ(Res.size(), 1u);
4626 EXPECT_EQ(*Res.begin(), A);
4627}
4628
4629TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
4630 TranslationUnitDecl *ToTU = getToTuDecl(
4631 R"(
4632 namespace N {
4633 int A;
4634 }
4635 namespace N {
4636 }
4637 )",
4638 Lang_CXX);
4639 auto *N1 =
4640 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
4641 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
4642 DeclarationName Name = A->getDeclName();
4643
4644 ASTImporterLookupTable LT(*ToTU);
4645 auto Res = LT.lookup(N1, Name);
4646 ASSERT_EQ(Res.size(), 1u);
4647 EXPECT_EQ(*Res.begin(), A);
4648}
4649
Gabor Marton5254e642018-06-27 13:32:50 +00004650
Gabor Marton0e04ebd2019-02-11 10:27:58 +00004651// FIXME This test is disabled currently, upcoming patches will make it
4652// possible to enable.
4653TEST_P(ASTImporterOptionSpecificTestBase,
4654 DISABLED_RedeclChainShouldBeCorrectAmongstNamespaces) {
4655 Decl *FromTU = getTuDecl(
4656 R"(
4657 namespace NS {
4658 struct X;
4659 struct Y {
4660 static const int I = 3;
4661 };
4662 }
4663 namespace NS {
4664 struct X { // <--- To be imported
4665 void method(int i = Y::I) {}
4666 int f;
4667 };
4668 }
4669 )",
4670 Lang_CXX);
4671 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
4672 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
4673 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
4674 FromTU,
4675 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
4676 ASSERT_NE(FromFwd, FromDef);
4677 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
4678 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4679 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
4680
4681 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX));
4682 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX));
4683 EXPECT_NE(ToFwd, ToDef);
4684 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
4685 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4686 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
4687 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4688 // We expect no (ODR) warning during the import.
4689 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4690}
4691
Gabor Martone331e632019-02-18 13:09:27 +00004692struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
4693
4694TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
4695 Decl *ToTU = getToTuDecl(
4696 R"(
4697 class X {
4698 template <typename T> friend void foo();
4699 };
4700 )",
4701 Lang_CXX);
4702 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
4703 ToTU, functionTemplateDecl(hasName("foo")));
4704
4705 Decl *FromTU = getTuDecl(
4706 R"(
4707 template <typename T> void foo();
4708 )",
4709 Lang_CXX);
4710 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
4711 FromTU, functionTemplateDecl(hasName("foo")));
4712 auto *Imported = Import(FromFoo, Lang_CXX);
4713
Gabor Marton16d98c22019-03-07 13:01:51 +00004714 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
Gabor Martone331e632019-02-18 13:09:27 +00004715}
4716
Gabor Marton303c98612019-06-25 08:00:51 +00004717struct ASTImporterWithFakeErrors : ASTImporter {
4718 using ASTImporter::ASTImporter;
4719 bool returnWithErrorInTest() override { return true; }
4720};
4721
4722struct ErrorHandlingTest : ASTImporterOptionSpecificTestBase {
4723 ErrorHandlingTest() {
4724 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
4725 ASTContext &FromContext, FileManager &FromFileManager,
4726 bool MinimalImport, ASTImporterLookupTable *LookupTable) {
4727 return new ASTImporterWithFakeErrors(ToContext, ToFileManager,
4728 FromContext, FromFileManager,
4729 MinimalImport, LookupTable);
4730 };
4731 }
4732 // In this test we purposely report an error (UnsupportedConstruct) when
4733 // importing the below stmt.
4734 static constexpr auto* ErroneousStmt = R"( asm(""); )";
4735};
4736
4737// Check a case when no new AST node is created in the AST before encountering
4738// the error.
4739TEST_P(ErrorHandlingTest, ErrorHappensBeforeCreatingANewNode) {
4740 TranslationUnitDecl *ToTU = getToTuDecl(
4741 R"(
4742 template <typename T>
4743 class X {};
4744 template <>
4745 class X<int> { int a; };
4746 )",
4747 Lang_CXX);
4748 TranslationUnitDecl *FromTU = getTuDecl(
4749 R"(
4750 template <typename T>
4751 class X {};
4752 template <>
4753 class X<int> { double b; };
4754 )",
4755 Lang_CXX);
4756 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4757 FromTU, classTemplateSpecializationDecl(hasName("X")));
4758 ClassTemplateSpecializationDecl *ImportedSpec = Import(FromSpec, Lang_CXX);
4759 EXPECT_FALSE(ImportedSpec);
4760
4761 // The original Decl is kept, no new decl is created.
4762 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(
4763 ToTU, classTemplateSpecializationDecl(hasName("X"))),
4764 1u);
4765
4766 // But an error is set to the counterpart in the "from" context.
4767 ASTImporter *Importer = findFromTU(FromSpec)->Importer.get();
4768 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromSpec);
4769 ASSERT_TRUE(OptErr);
4770 EXPECT_EQ(OptErr->Error, ImportError::NameConflict);
4771}
4772
4773// Check a case when a new AST node is created but not linked to the AST before
4774// encountering the error.
4775TEST_P(ErrorHandlingTest,
4776 ErrorHappensAfterCreatingTheNodeButBeforeLinkingThatToTheAST) {
4777 TranslationUnitDecl *FromTU = getTuDecl(
4778 std::string("void foo() { ") + ErroneousStmt + " }",
4779 Lang_CXX);
4780 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4781 FromTU, functionDecl(hasName("foo")));
4782
4783 FunctionDecl *ImportedFoo = Import(FromFoo, Lang_CXX);
4784 EXPECT_FALSE(ImportedFoo);
4785
4786 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4787 // Created, but not linked.
4788 EXPECT_EQ(
4789 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("foo"))),
4790 0u);
4791
4792 ASTImporter *Importer = findFromTU(FromFoo)->Importer.get();
4793 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFoo);
4794 ASSERT_TRUE(OptErr);
4795 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4796}
4797
4798// Check a case when a new AST node is created and linked to the AST before
4799// encountering the error. The error is set for the counterpart of the nodes in
4800// the "from" context.
4801TEST_P(ErrorHandlingTest, ErrorHappensAfterNodeIsCreatedAndLinked) {
4802 TranslationUnitDecl *FromTU = getTuDecl(
4803 std::string(R"(
4804 void f();
4805 void f() { )") + ErroneousStmt + R"( }
4806 )",
4807 Lang_CXX);
4808 auto *FromProto = FirstDeclMatcher<FunctionDecl>().match(
4809 FromTU, functionDecl(hasName("f")));
4810 auto *FromDef =
4811 LastDeclMatcher<FunctionDecl>().match(FromTU, functionDecl(hasName("f")));
4812 FunctionDecl *ImportedProto = Import(FromProto, Lang_CXX);
4813 EXPECT_FALSE(ImportedProto); // Could not import.
4814 // However, we created two nodes in the AST. 1) the fwd decl 2) the
4815 // definition. The definition is not added to its DC, but the fwd decl is
4816 // there.
4817 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4818 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
4819 1u);
4820 // Match the fwd decl.
4821 auto *ToProto =
4822 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("f")));
4823 EXPECT_TRUE(ToProto);
4824 // An error is set to the counterpart in the "from" context both for the fwd
4825 // decl and the definition.
4826 ASTImporter *Importer = findFromTU(FromProto)->Importer.get();
4827 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromProto);
4828 ASSERT_TRUE(OptErr);
4829 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4830 OptErr = Importer->getImportDeclErrorIfAny(FromDef);
4831 ASSERT_TRUE(OptErr);
4832 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4833}
4834
Gabor Marton17c3eaf2019-07-01 12:44:39 +00004835// An error should be set for a class if we cannot import one member.
4836TEST_P(ErrorHandlingTest, ErrorIsPropagatedFromMemberToClass) {
4837 TranslationUnitDecl *FromTU = getTuDecl(
4838 std::string(R"(
4839 class X {
4840 void f() { )") + ErroneousStmt + R"( } // This member has the error
4841 // during import.
4842 void ok(); // The error should not prevent importing this.
4843 }; // An error will be set for X too.
4844 )",
4845 Lang_CXX);
4846 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
4847 FromTU, cxxRecordDecl(hasName("X")));
4848 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX);
4849
4850 // An error is set for X.
4851 EXPECT_FALSE(ImportedX);
4852 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
4853 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
4854 ASSERT_TRUE(OptErr);
4855 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4856
4857 // An error is set for f().
4858 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
4859 FromTU, cxxMethodDecl(hasName("f")));
4860 OptErr = Importer->getImportDeclErrorIfAny(FromF);
4861 ASSERT_TRUE(OptErr);
4862 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4863 // And any subsequent import should fail.
4864 CXXMethodDecl *ImportedF = Import(FromF, Lang_CXX);
4865 EXPECT_FALSE(ImportedF);
4866
Gabor Marton1ad4b992019-07-01 14:19:53 +00004867 // There is an error set for the other member too.
Gabor Marton17c3eaf2019-07-01 12:44:39 +00004868 auto *FromOK = FirstDeclMatcher<CXXMethodDecl>().match(
4869 FromTU, cxxMethodDecl(hasName("ok")));
4870 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
Gabor Marton1ad4b992019-07-01 14:19:53 +00004871 EXPECT_TRUE(OptErr);
4872 // Cannot import the other member.
Gabor Marton17c3eaf2019-07-01 12:44:39 +00004873 CXXMethodDecl *ImportedOK = Import(FromOK, Lang_CXX);
Gabor Marton1ad4b992019-07-01 14:19:53 +00004874 EXPECT_FALSE(ImportedOK);
4875}
Gabor Marton17c3eaf2019-07-01 12:44:39 +00004876
Gabor Marton1ad4b992019-07-01 14:19:53 +00004877// Check that an error propagates to the dependent AST nodes.
4878// In the below code it means that an error in X should propagate to A.
4879// And even to F since the containing A is erroneous.
4880// And to all AST nodes which we visit during the import process which finally
4881// ends up in a failure (in the error() function).
4882TEST_P(ErrorHandlingTest, ErrorPropagatesThroughImportCycles) {
4883 Decl *FromTU = getTuDecl(
4884 std::string(R"(
4885 namespace NS {
4886 class A {
4887 template <int I> class F {};
4888 class X {
4889 template <int I> friend class F;
4890 void error() { )") + ErroneousStmt + R"( }
4891 };
4892 };
4893
4894 class B {};
4895 } // NS
4896 )",
4897 Lang_CXX, "input0.cc");
4898
4899 auto *FromFRD = FirstDeclMatcher<CXXRecordDecl>().match(
4900 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
4901 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
4902 FromTU, cxxRecordDecl(hasName("A"), isDefinition()));
4903 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(
4904 FromTU, cxxRecordDecl(hasName("B"), isDefinition()));
4905 auto *FromNS = FirstDeclMatcher<NamespaceDecl>().match(
4906 FromTU, namespaceDecl(hasName("NS")));
4907
4908 // Start by importing the templated CXXRecordDecl of F.
4909 // Import fails for that.
4910 EXPECT_FALSE(Import(FromFRD, Lang_CXX));
4911 // Import fails for A.
4912 EXPECT_FALSE(Import(FromA, Lang_CXX));
4913 // But we should be able to import the independent B.
4914 EXPECT_TRUE(Import(FromB, Lang_CXX));
4915 // And the namespace.
4916 EXPECT_TRUE(Import(FromNS, Lang_CXX));
4917
4918 // An error is set to the templated CXXRecordDecl of F.
4919 ASTImporter *Importer = findFromTU(FromFRD)->Importer.get();
4920 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFRD);
4921 EXPECT_TRUE(OptErr);
4922
4923 // An error is set to A.
4924 OptErr = Importer->getImportDeclErrorIfAny(FromA);
4925 EXPECT_TRUE(OptErr);
4926
4927 // There is no error set to B.
4928 OptErr = Importer->getImportDeclErrorIfAny(FromB);
4929 EXPECT_FALSE(OptErr);
4930
4931 // There is no error set to NS.
4932 OptErr = Importer->getImportDeclErrorIfAny(FromNS);
4933 EXPECT_FALSE(OptErr);
4934
4935 // Check some of those decls whose ancestor is X, they all should have an
4936 // error set if we visited them during an import process which finally failed.
4937 // These decls are part of a cycle in an ImportPath.
4938 // There would not be any error set for these decls if we hadn't follow the
4939 // ImportPaths and the cycles.
4940 OptErr = Importer->getImportDeclErrorIfAny(
4941 FirstDeclMatcher<ClassTemplateDecl>().match(
4942 FromTU, classTemplateDecl(hasName("F"))));
4943 // An error is set to the 'F' ClassTemplateDecl.
4944 EXPECT_TRUE(OptErr);
4945 // An error is set to the FriendDecl.
4946 OptErr = Importer->getImportDeclErrorIfAny(
4947 FirstDeclMatcher<FriendDecl>().match(
4948 FromTU, friendDecl()));
4949 EXPECT_TRUE(OptErr);
4950 // An error is set to the implicit class of A.
4951 OptErr =
4952 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
4953 FromTU, cxxRecordDecl(hasName("A"), isImplicit())));
4954 EXPECT_TRUE(OptErr);
4955 // An error is set to the implicit class of X.
4956 OptErr =
4957 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
4958 FromTU, cxxRecordDecl(hasName("X"), isImplicit())));
4959 EXPECT_TRUE(OptErr);
Gabor Marton17c3eaf2019-07-01 12:44:39 +00004960}
4961
4962TEST_P(ErrorHandlingTest, ErrorIsNotPropagatedFromMemberToNamespace) {
4963 TranslationUnitDecl *FromTU = getTuDecl(
4964 std::string(R"(
4965 namespace X {
4966 void f() { )") + ErroneousStmt + R"( } // This member has the error
4967 // during import.
4968 void ok(); // The error should not prevent importing this.
4969 }; // An error will be set for X too.
4970 )",
4971 Lang_CXX);
4972 auto *FromX = FirstDeclMatcher<NamespaceDecl>().match(
4973 FromTU, namespaceDecl(hasName("X")));
4974 NamespaceDecl *ImportedX = Import(FromX, Lang_CXX);
4975
4976 // There is no error set for X.
4977 EXPECT_TRUE(ImportedX);
4978 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
4979 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
4980 ASSERT_FALSE(OptErr);
4981
4982 // An error is set for f().
4983 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
4984 FromTU, functionDecl(hasName("f")));
4985 OptErr = Importer->getImportDeclErrorIfAny(FromF);
4986 ASSERT_TRUE(OptErr);
4987 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4988 // And any subsequent import should fail.
4989 FunctionDecl *ImportedF = Import(FromF, Lang_CXX);
4990 EXPECT_FALSE(ImportedF);
4991
4992 // There is no error set for ok().
4993 auto *FromOK = FirstDeclMatcher<FunctionDecl>().match(
4994 FromTU, functionDecl(hasName("ok")));
4995 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
4996 EXPECT_FALSE(OptErr);
4997 // And we should be able to import.
4998 FunctionDecl *ImportedOK = Import(FromOK, Lang_CXX);
4999 EXPECT_TRUE(ImportedOK);
5000}
5001
Gabor Marton303c98612019-06-25 08:00:51 +00005002INSTANTIATE_TEST_CASE_P(ParameterizedTests, ErrorHandlingTest,
5003 DefaultTestValuesForRunOptions, );
5004
Gabor Marton1ad4b992019-07-01 14:19:53 +00005005INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
5006 ::testing::Values(ArgVector()), );
5007
5008INSTANTIATE_TEST_CASE_P(ParameterizedTests, CanonicalRedeclChain,
5009 ::testing::Values(ArgVector()), );
5010
Gabor Marton54058b52018-12-17 13:53:12 +00005011INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
5012 DefaultTestValuesForRunOptions, );
5013
Gabor Marton1ad4b992019-07-01 14:19:53 +00005014INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportPath,
5015 ::testing::Values(ArgVector()), );
5016
Gabor Marton19f4f392018-06-25 13:04:37 +00005017INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
5018 DefaultTestValuesForRunOptions, );
5019
5020INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
5021 DefaultTestValuesForRunOptions, );
5022
5023INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
5024 DefaultTestValuesForRunOptions, );
5025
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005026INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
Gabor Marton19f4f392018-06-25 13:04:37 +00005027 DefaultTestValuesForRunOptions, );
5028
Raphael Isemanne9bc35f2019-04-29 21:02:35 +00005029INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedirectingImporterTest,
5030 DefaultTestValuesForRunOptions, );
5031
Gabor Marton19f4f392018-06-25 13:04:37 +00005032INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
5033 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00005034
Gabor Martone331e632019-02-18 13:09:27 +00005035INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
5036 DefaultTestValuesForRunOptions, );
5037
Gabor Marton54058b52018-12-17 13:53:12 +00005038INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00005039 DefaultTestValuesForRunOptions, );
5040
Gabor Marton54058b52018-12-17 13:53:12 +00005041INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00005042 DefaultTestValuesForRunOptions, );
5043
Gabor Marton7df342a2018-12-17 12:42:12 +00005044INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
5045 DefaultTestValuesForRunOptions, );
5046
Gabor Marton5254e642018-06-27 13:32:50 +00005047INSTANTIATE_TEST_CASE_P(ParameterizedTests,
5048 ImportFunctionTemplateSpecializations,
5049 DefaultTestValuesForRunOptions, );
5050
Gabor Martonac3a5d62018-09-17 12:04:52 +00005051INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
5052 DefaultTestValuesForRunOptions, );
5053
5054INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
5055 DefaultTestValuesForRunOptions, );
5056
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00005057} // end namespace ast_matchers
5058} // end namespace clang