blob: 8c3dc6caba56b5e22c2a7a2b4f781ba85d08bdf5 [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
Gabor Marton25234fd2019-12-12 17:13:35 +010013#include "clang/ASTMatchers/ASTMatchers.h"
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000014#include "llvm/ADT/StringMap.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000015
Gabor Marton3c72fe12019-05-13 10:06:25 +000016#include "clang/AST/DeclContextInternals.h"
Gabor Marton25234fd2019-12-12 17:13:35 +010017#include "gtest/gtest.h"
Gabor Marton3c72fe12019-05-13 10:06:25 +000018
19#include "ASTImporterFixtures.h"
20#include "MatchVerifier.h"
21
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000022namespace clang {
23namespace ast_matchers {
24
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000025using internal::Matcher;
26using internal::BindableMatcher;
27using llvm::StringMap;
28
Gabor Marton19f4f392018-06-25 13:04:37 +000029// Base class for those tests which use the family of `testImport` functions.
Gabor Marton0b57ccb2019-02-07 16:52:48 +000030class TestImportBase : public CompilerOptionSpecificTest,
31 public ::testing::WithParamInterface<ArgVector> {
Adam Baloghe4192a82018-06-15 06:45:39 +000032
Gabor Marton19f4f392018-06-25 13:04:37 +000033 template <typename NodeType>
Balazs Keria1f6b102019-04-08 13:59:15 +000034 llvm::Expected<NodeType> importNode(ASTUnit *From, ASTUnit *To,
35 ASTImporter &Importer, NodeType Node) {
Gabor Marton19f4f392018-06-25 13:04:37 +000036 ASTContext &ToCtx = To->getASTContext();
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000037
Gabor Marton19f4f392018-06-25 13:04:37 +000038 // Add 'From' file to virtual file system so importer can 'find' it
39 // while importing SourceLocations. It is safe to add same file multiple
40 // times - it just isn't replaced.
41 StringRef FromFileName = From->getMainFileName();
42 createVirtualFileIfNeeded(To, FromFileName,
43 From->getBufferForFile(FromFileName));
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000044
Gabor Marton5ac6d492019-05-15 10:29:48 +000045 auto Imported = Importer.Import(Node);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000046
Balazs Keria1f6b102019-04-08 13:59:15 +000047 if (Imported) {
48 // This should dump source locations and assert if some source locations
49 // were not imported.
50 SmallString<1024> ImportChecker;
51 llvm::raw_svector_ostream ToNothing(ImportChecker);
52 ToCtx.getTranslationUnitDecl()->print(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000053
Balazs Keria1f6b102019-04-08 13:59:15 +000054 // This traverses the AST to catch certain bugs like poorly or not
55 // implemented subtrees.
56 (*Imported)->dump(ToNothing);
57 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000058
Gabor Marton19f4f392018-06-25 13:04:37 +000059 return Imported;
60 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000061
Gabor Marton19f4f392018-06-25 13:04:37 +000062 template <typename NodeType>
63 testing::AssertionResult
64 testImport(const std::string &FromCode, const ArgVector &FromArgs,
65 const std::string &ToCode, const ArgVector &ToArgs,
66 MatchVerifier<NodeType> &Verifier,
67 const BindableMatcher<NodeType> &SearchMatcher,
68 const BindableMatcher<NodeType> &VerificationMatcher) {
69 const char *const InputFileName = "input.cc";
70 const char *const OutputFileName = "output.cc";
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000071
Gabor Marton19f4f392018-06-25 13:04:37 +000072 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
73 FromCode, FromArgs, InputFileName),
74 ToAST = tooling::buildASTFromCodeWithArgs(
75 ToCode, ToArgs, OutputFileName);
76
77 ASTContext &FromCtx = FromAST->getASTContext(),
78 &ToCtx = ToAST->getASTContext();
79
80 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
81 FromAST->getFileManager(), false);
82
83 auto FoundNodes = match(SearchMatcher, FromCtx);
84 if (FoundNodes.size() != 1)
85 return testing::AssertionFailure()
86 << "Multiple potential nodes were found!";
87
88 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
89 if (!ToImport)
90 return testing::AssertionFailure() << "Node type mismatch!";
91
92 // Sanity check: the node being imported should match in the same way as
93 // the result node.
94 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
95 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
96
97 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
Balazs Keria1f6b102019-04-08 13:59:15 +000098 if (!Imported) {
99 std::string ErrorText;
100 handleAllErrors(
101 Imported.takeError(),
102 [&ErrorText](const ImportError &Err) { ErrorText = Err.message(); });
103 return testing::AssertionFailure()
104 << "Import failed, error: \"" << ErrorText << "\"!";
105 }
Gabor Marton19f4f392018-06-25 13:04:37 +0000106
Balazs Keria1f6b102019-04-08 13:59:15 +0000107 return Verifier.match(*Imported, WrapperMatcher);
Gabor Marton19f4f392018-06-25 13:04:37 +0000108 }
109
110 template <typename NodeType>
111 testing::AssertionResult
112 testImport(const std::string &FromCode, const ArgVector &FromArgs,
113 const std::string &ToCode, const ArgVector &ToArgs,
114 MatchVerifier<NodeType> &Verifier,
115 const BindableMatcher<NodeType> &VerificationMatcher) {
116 return testImport(
117 FromCode, FromArgs, ToCode, ToArgs, Verifier,
Benjamin Krameradcd0262020-01-28 20:23:46 +0100118 translationUnitDecl(has(namedDecl(hasName(std::string(DeclToImportID)))
119 .bind(DeclToImportID))),
Gabor Marton19f4f392018-06-25 13:04:37 +0000120 VerificationMatcher);
121 }
122
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000123protected:
124 ArgVector getExtraArgs() const override { return GetParam(); }
125
Gabor Marton19f4f392018-06-25 13:04:37 +0000126public:
127
128 /// Test how AST node named "declToImport" located in the translation unit
129 /// of "FromCode" virtual file is imported to "ToCode" virtual file.
130 /// The verification is done by running AMatcher over the imported node.
131 template <typename NodeType, typename MatcherType>
132 void testImport(const std::string &FromCode, Language FromLang,
133 const std::string &ToCode, Language ToLang,
134 MatchVerifier<NodeType> &Verifier,
135 const MatcherType &AMatcher) {
136 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
137 ToArgs = getArgVectorForLanguage(ToLang);
138 EXPECT_TRUE(
139 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
140 }
141
142 struct ImportAction {
143 StringRef FromFilename;
144 StringRef ToFilename;
145 // FIXME: Generalize this to support other node kinds.
146 BindableMatcher<Decl> ImportPredicate;
147
148 ImportAction(StringRef FromFilename, StringRef ToFilename,
149 DeclarationMatcher ImportPredicate)
150 : FromFilename(FromFilename), ToFilename(ToFilename),
151 ImportPredicate(ImportPredicate) {}
152
153 ImportAction(StringRef FromFilename, StringRef ToFilename,
154 const std::string &DeclName)
155 : FromFilename(FromFilename), ToFilename(ToFilename),
156 ImportPredicate(namedDecl(hasName(DeclName))) {}
157 };
158
159 using SingleASTUnit = std::unique_ptr<ASTUnit>;
160 using AllASTUnits = StringMap<SingleASTUnit>;
161
162 struct CodeEntry {
163 std::string CodeSample;
164 Language Lang;
165 };
166
167 using CodeFiles = StringMap<CodeEntry>;
168
169 /// Builds an ASTUnit for one potential compile options set.
170 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
171 ArgVector Args = getArgVectorForLanguage(CE.Lang);
172 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
173 EXPECT_TRUE(AST.get());
174 return AST;
175 }
176
177 /// Test an arbitrary sequence of imports for a set of given in-memory files.
178 /// The verification is done by running VerificationMatcher against a
179 /// specified AST node inside of one of given files.
180 /// \param CodeSamples Map whose key is the file name and the value is the
181 /// file content.
182 /// \param ImportActions Sequence of imports. Each import in sequence
183 /// specifies "from file" and "to file" and a matcher that is used for
184 /// searching a declaration for import in "from file".
185 /// \param FileForFinalCheck Name of virtual file for which the final check is
186 /// applied.
187 /// \param FinalSelectPredicate Matcher that specifies the AST node in the
188 /// FileForFinalCheck for which the verification will be done.
189 /// \param VerificationMatcher Matcher that will be used for verification
190 /// after all imports in sequence are done.
191 void testImportSequence(const CodeFiles &CodeSamples,
192 const std::vector<ImportAction> &ImportActions,
193 StringRef FileForFinalCheck,
194 BindableMatcher<Decl> FinalSelectPredicate,
195 BindableMatcher<Decl> VerificationMatcher) {
196 AllASTUnits AllASTs;
197 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
198 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
199
200 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
201 if (!AllASTs.count(Filename)) {
202 auto Found = CodeSamples.find(Filename);
203 assert(Found != CodeSamples.end() && "Wrong file for import!");
204 AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
205 }
206 };
207
208 for (const ImportAction &Action : ImportActions) {
209 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
210 GenASTsIfNeeded(FromFile);
211 GenASTsIfNeeded(ToFile);
212
213 ASTUnit *From = AllASTs[FromFile].get();
214 ASTUnit *To = AllASTs[ToFile].get();
215
216 // Create a new importer if needed.
217 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
218 if (!ImporterRef)
219 ImporterRef.reset(new ASTImporter(
220 To->getASTContext(), To->getFileManager(), From->getASTContext(),
221 From->getFileManager(), false));
222
223 // Find the declaration and import it.
224 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
225 From->getASTContext());
226 EXPECT_TRUE(FoundDecl.size() == 1);
227 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
228 auto Imported = importNode(From, To, *ImporterRef, ToImport);
Balazs Keria1f6b102019-04-08 13:59:15 +0000229 EXPECT_TRUE(static_cast<bool>(Imported));
230 if (!Imported)
231 llvm::consumeError(Imported.takeError());
Gabor Marton19f4f392018-06-25 13:04:37 +0000232 }
233
234 // Find the declaration and import it.
235 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
236 AllASTs[FileForFinalCheck]->getASTContext());
237 EXPECT_TRUE(FoundDecl.size() == 1);
238 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
239 MatchVerifier<Decl> Verifier;
240 EXPECT_TRUE(
241 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
242 }
243};
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000244
Gabor Martonf086fa82018-07-17 12:06:36 +0000245template <typename T> RecordDecl *getRecordDecl(T *D) {
246 auto *ET = cast<ElaboratedType>(D->getType().getTypePtr());
247 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
Nico Weberb980b5c2018-07-17 14:20:02 +0000248}
Gabor Martonf086fa82018-07-17 12:06:36 +0000249
Gabor Martonbc5b7e22019-12-04 17:12:08 +0100250static const RecordDecl *getRecordDeclOfFriend(FriendDecl *FD) {
251 QualType Ty = FD->getFriendType()->getType().getCanonicalType();
252 return cast<RecordType>(Ty)->getDecl();
253}
254
Gabor Marton19f4f392018-06-25 13:04:37 +0000255struct ImportExpr : TestImportBase {};
256struct ImportType : TestImportBase {};
257struct ImportDecl : TestImportBase {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000258
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000259struct CanonicalRedeclChain : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +0000260
261TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
262 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
263 auto Pattern = functionDecl(hasName("f"));
264 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
265
266 auto Redecls = getCanonicalForwardRedeclChain(D0);
267 ASSERT_EQ(Redecls.size(), 1u);
268 EXPECT_EQ(D0, Redecls[0]);
269}
270
271TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
272 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
273 auto Pattern = functionDecl(hasName("f"));
274 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
275 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
276 FunctionDecl *D1 = D2->getPreviousDecl();
277
278 auto Redecls = getCanonicalForwardRedeclChain(D0);
279 ASSERT_EQ(Redecls.size(), 3u);
280 EXPECT_EQ(D0, Redecls[0]);
281 EXPECT_EQ(D1, Redecls[1]);
282 EXPECT_EQ(D2, Redecls[2]);
283}
284
285TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
286 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
287 auto Pattern = functionDecl(hasName("f"));
288 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
289 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
290 FunctionDecl *D1 = D2->getPreviousDecl();
291
292 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
293 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
294 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
295
296 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
297 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
298}
299
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000300namespace {
301struct RedirectingImporter : public ASTImporter {
302 using ASTImporter::ASTImporter;
303
304protected:
305 llvm::Expected<Decl *> ImportImpl(Decl *FromD) override {
306 auto *ND = dyn_cast<NamedDecl>(FromD);
307 if (!ND || ND->getName() != "shouldNotBeImported")
308 return ASTImporter::ImportImpl(FromD);
309 for (Decl *D : getToContext().getTranslationUnitDecl()->decls()) {
310 if (auto *ND = dyn_cast<NamedDecl>(D))
311 if (ND->getName() == "realDecl") {
312 RegisterImportedDecl(FromD, ND);
313 return ND;
314 }
315 }
316 return ASTImporter::ImportImpl(FromD);
317 }
318};
319
320} // namespace
321
322struct RedirectingImporterTest : ASTImporterOptionSpecificTestBase {
323 RedirectingImporterTest() {
324 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
325 ASTContext &FromContext, FileManager &FromFileManager,
Gabor Marton2afbfb62019-07-01 15:37:07 +0000326 bool MinimalImport,
327 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000328 return new RedirectingImporter(ToContext, ToFileManager, FromContext,
329 FromFileManager, MinimalImport,
Gabor Marton2afbfb62019-07-01 15:37:07 +0000330 SharedState);
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000331 };
332 }
333};
334
335// Test that an ASTImporter subclass can intercept an import call.
336TEST_P(RedirectingImporterTest, InterceptImport) {
337 Decl *From, *To;
338 std::tie(From, To) =
339 getImportedDecl("class shouldNotBeImported {};", Lang_CXX,
340 "class realDecl {};", Lang_CXX, "shouldNotBeImported");
341 auto *Imported = cast<CXXRecordDecl>(To);
342 EXPECT_EQ(Imported->getQualifiedNameAsString(), "realDecl");
343
344 // Make sure our importer prevented the importing of the decl.
345 auto *ToTU = Imported->getTranslationUnitDecl();
346 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
347 unsigned count =
348 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
349 EXPECT_EQ(0U, count);
350}
351
352// Test that when we indirectly import a declaration the custom ASTImporter
353// is still intercepting the import.
354TEST_P(RedirectingImporterTest, InterceptIndirectImport) {
355 Decl *From, *To;
356 std::tie(From, To) =
357 getImportedDecl("class shouldNotBeImported {};"
358 "class F { shouldNotBeImported f; };",
359 Lang_CXX, "class realDecl {};", Lang_CXX, "F");
360
361 // Make sure our ASTImporter prevented the importing of the decl.
362 auto *ToTU = To->getTranslationUnitDecl();
363 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
364 unsigned count =
365 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
366 EXPECT_EQ(0U, count);
367}
368
Gabor Marton1ad4b992019-07-01 14:19:53 +0000369struct ImportPath : ASTImporterOptionSpecificTestBase {
370 Decl *FromTU;
371 FunctionDecl *D0, *D1, *D2;
372 ImportPath() {
373 FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
374 auto Pattern = functionDecl(hasName("f"));
375 D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
376 D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
377 D1 = D2->getPreviousDecl();
378 }
379};
380
381TEST_P(ImportPath, Push) {
382 ASTImporter::ImportPathTy path;
383 path.push(D0);
384 EXPECT_FALSE(path.hasCycleAtBack());
385}
386
387TEST_P(ImportPath, SmallCycle) {
388 ASTImporter::ImportPathTy path;
389 path.push(D0);
390 path.push(D0);
391 EXPECT_TRUE(path.hasCycleAtBack());
392 path.pop();
393 EXPECT_FALSE(path.hasCycleAtBack());
394 path.push(D0);
395 EXPECT_TRUE(path.hasCycleAtBack());
396}
397
398TEST_P(ImportPath, GetSmallCycle) {
399 ASTImporter::ImportPathTy path;
400 path.push(D0);
401 path.push(D0);
402 EXPECT_TRUE(path.hasCycleAtBack());
403 std::array<Decl* ,2> Res;
404 int i = 0;
405 for (Decl *Di : path.getCycleAtBack()) {
406 Res[i++] = Di;
407 }
408 ASSERT_EQ(i, 2);
409 EXPECT_EQ(Res[0], D0);
410 EXPECT_EQ(Res[1], D0);
411}
412
413TEST_P(ImportPath, GetCycle) {
414 ASTImporter::ImportPathTy path;
415 path.push(D0);
416 path.push(D1);
417 path.push(D2);
418 path.push(D0);
419 EXPECT_TRUE(path.hasCycleAtBack());
420 std::array<Decl* ,4> Res;
421 int i = 0;
422 for (Decl *Di : path.getCycleAtBack()) {
423 Res[i++] = Di;
424 }
425 ASSERT_EQ(i, 4);
426 EXPECT_EQ(Res[0], D0);
427 EXPECT_EQ(Res[1], D2);
428 EXPECT_EQ(Res[2], D1);
429 EXPECT_EQ(Res[3], D0);
430}
431
432TEST_P(ImportPath, CycleAfterCycle) {
433 ASTImporter::ImportPathTy path;
434 path.push(D0);
435 path.push(D1);
436 path.push(D0);
437 path.push(D1);
438 path.push(D2);
439 path.push(D0);
440 EXPECT_TRUE(path.hasCycleAtBack());
441 std::array<Decl* ,4> Res;
442 int i = 0;
443 for (Decl *Di : path.getCycleAtBack()) {
444 Res[i++] = Di;
445 }
446 ASSERT_EQ(i, 4);
447 EXPECT_EQ(Res[0], D0);
448 EXPECT_EQ(Res[1], D2);
449 EXPECT_EQ(Res[2], D1);
450 EXPECT_EQ(Res[3], D0);
451
452 path.pop();
453 path.pop();
454 path.pop();
455 EXPECT_TRUE(path.hasCycleAtBack());
456 i = 0;
457 for (Decl *Di : path.getCycleAtBack()) {
458 Res[i++] = Di;
459 }
460 ASSERT_EQ(i, 3);
461 EXPECT_EQ(Res[0], D0);
462 EXPECT_EQ(Res[1], D1);
463 EXPECT_EQ(Res[2], D0);
464
465 path.pop();
466 EXPECT_FALSE(path.hasCycleAtBack());
467}
468
Gabor Marton19f4f392018-06-25 13:04:37 +0000469TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000470 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000471 testImport(
472 "void declToImport() { (void)\"foo\"; }",
473 Lang_CXX, "", Lang_CXX, Verifier,
474 functionDecl(hasDescendant(
475 stringLiteral(hasType(asString("const char [4]"))))));
476 testImport(
477 "void declToImport() { (void)L\"foo\"; }",
478 Lang_CXX, "", Lang_CXX, Verifier,
479 functionDecl(hasDescendant(
480 stringLiteral(hasType(asString("const wchar_t [4]"))))));
481 testImport(
482 "void declToImport() { (void) \"foo\" \"bar\"; }",
483 Lang_CXX, "", Lang_CXX, Verifier,
484 functionDecl(hasDescendant(
485 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000486}
487
Tom Roeder521f0042019-02-26 19:26:41 +0000488TEST_P(ImportExpr, ImportChooseExpr) {
489 MatchVerifier<Decl> Verifier;
490
491 // This case tests C code that is not condition-dependent and has a true
492 // condition.
493 testImport(
494 "void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }",
495 Lang_C, "", Lang_C, Verifier,
496 functionDecl(hasDescendant(chooseExpr())));
497}
498
Gabor Marton19f4f392018-06-25 13:04:37 +0000499TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000500 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000501 testImport(
502 "void declToImport() { (void)__null; }",
503 Lang_CXX, "", Lang_CXX, Verifier,
504 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000505}
506
Gabor Marton19f4f392018-06-25 13:04:37 +0000507TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000508 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000509 testImport(
510 "void declToImport() { (void)nullptr; }",
511 Lang_CXX11, "", Lang_CXX11, Verifier,
512 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000513}
514
515
Gabor Marton19f4f392018-06-25 13:04:37 +0000516TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000517 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000518 testImport(
519 "void declToImport() { (void)1.0; }",
520 Lang_C, "", Lang_C, Verifier,
521 functionDecl(hasDescendant(
522 floatLiteral(equals(1.0), hasType(asString("double"))))));
523 testImport(
524 "void declToImport() { (void)1.0e-5f; }",
525 Lang_C, "", Lang_C, Verifier,
526 functionDecl(hasDescendant(
527 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000528}
529
Gabor Martonbf7f18b2018-08-09 12:18:07 +0000530TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
531 MatchVerifier<Decl> Verifier;
532 testImport(
533 "void declToImport() { (void)1.0i; }",
534 Lang_CXX14, "", Lang_CXX14, Verifier,
535 functionDecl(hasDescendant(imaginaryLiteral())));
536}
537
Gabor Marton19f4f392018-06-25 13:04:37 +0000538TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000539 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000540 testImport(
541 "void declToImport() {"
542 " struct s { int x; long y; unsigned z; }; "
543 " (void)(struct s){ 42, 0L, 1U }; }",
544 Lang_CXX, "", Lang_CXX, Verifier,
545 functionDecl(hasDescendant(
546 compoundLiteralExpr(
547 hasType(asString("struct s")),
548 has(initListExpr(
549 hasType(asString("struct s")),
550 has(integerLiteral(
551 equals(42), hasType(asString("int")))),
552 has(integerLiteral(
553 equals(0), hasType(asString("long")))),
554 has(integerLiteral(
555 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000556}
557
Gabor Marton19f4f392018-06-25 13:04:37 +0000558TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000559 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000560 testImport(
561 "class declToImport { void f() { (void)this; } };",
562 Lang_CXX, "", Lang_CXX, Verifier,
563 cxxRecordDecl(
564 hasMethod(
565 hasDescendant(
566 cxxThisExpr(
567 hasType(
568 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000569}
570
Gabor Marton19f4f392018-06-25 13:04:37 +0000571TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000572 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000573 testImport(
574 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
575 Lang_C, "", Lang_C, Verifier,
576 functionDecl(hasDescendant(
577 atomicExpr(
578 has(ignoringParenImpCasts(
579 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
580 hasType(asString("int *"))))),
581 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000582}
583
Gabor Marton19f4f392018-06-25 13:04:37 +0000584TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000585 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000586 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000587 "void declToImport() { loop: goto loop; (void)&&loop; }",
588 Lang_C, "", Lang_C, Verifier,
589 functionDecl(
590 hasDescendant(
591 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
592 hasDescendant(
593 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000594}
595
596AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
597 internal::Matcher<NamedDecl>, InnerMatcher) {
598 const NamedDecl *Template = Node.getTemplatedDecl();
599 return Template && InnerMatcher.matches(*Template, Finder, Builder);
600}
601
Gabor Marton19f4f392018-06-25 13:04:37 +0000602TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000603 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000604 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000605 "template<typename T> class dummy { void f() { dummy X(*this); } };"
606 "typedef dummy<int> declToImport;"
607 "template class dummy<int>;",
608 Lang_CXX, "", Lang_CXX, Verifier,
609 typedefDecl(hasType(templateSpecializationType(
610 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
611 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
612 hasName("f"),
613 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
614 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
615 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000616 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000617}
618
Gabor Marton19f4f392018-06-25 13:04:37 +0000619TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000620 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000621 testImport(
622 "void declToImport() { int b; switch (b) { case 1: break; } }",
623 Lang_C, "", Lang_C, Verifier,
624 functionDecl(hasDescendant(
625 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000626}
627
Gabor Marton19f4f392018-06-25 13:04:37 +0000628TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000629 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000630 testImport(
631 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
632 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000633 functionDecl(hasDescendant(
634 varDecl(
635 hasName("C"),
636 hasType(asString("int")),
637 hasInitializer(
638 stmtExpr(
639 hasAnySubstatement(declStmt(hasSingleDecl(
640 varDecl(
641 hasName("X"),
642 hasType(asString("int")),
643 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000644 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000645 hasDescendant(
646 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000647}
648
Gabor Marton19f4f392018-06-25 13:04:37 +0000649TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000650 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000651 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000652 "void declToImport() { (void)(true ? 1 : -5); }",
653 Lang_CXX, "", Lang_CXX, Verifier,
654 functionDecl(hasDescendant(
655 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000656 hasCondition(cxxBoolLiteral(equals(true))),
657 hasTrueExpression(integerLiteral(equals(1))),
658 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000659 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
660 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000661}
662
Gabor Marton19f4f392018-06-25 13:04:37 +0000663TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000664 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000665 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000666 "void declToImport() { (void)(1 ?: -5); }",
667 Lang_CXX, "", Lang_CXX, Verifier,
668 functionDecl(hasDescendant(
669 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000670 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000671 implicitCastExpr(
672 hasSourceExpression(opaqueValueExpr(
673 hasSourceExpression(integerLiteral(equals(1))))),
674 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000675 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000676 opaqueValueExpr(
677 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000678 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000679 unaryOperator(
680 hasOperatorName("-"),
681 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000682}
683
Gabor Marton19f4f392018-06-25 13:04:37 +0000684TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000685 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000686 testImport(
687 "void declToImport() {"
688 " struct point { double x; double y; };"
689 " struct point ptarray[10] = "
690 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
691 Lang_C, "", Lang_C, Verifier,
692 functionDecl(hasDescendant(
693 initListExpr(
694 has(designatedInitExpr(
695 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000696 hasDescendant(floatLiteral(equals(1.0))),
697 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000698 has(designatedInitExpr(
699 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000700 hasDescendant(floatLiteral(equals(2.0))),
701 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000702 has(designatedInitExpr(
703 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000704 hasDescendant(floatLiteral(equals(1.0))),
705 hasDescendant(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000706}
707
Gabor Marton19f4f392018-06-25 13:04:37 +0000708TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000709 MatchVerifier<Decl> Verifier;
710 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000711 testImport(
712 "void declToImport() { (void)__func__; }",
713 Lang_CXX, "", Lang_CXX, Verifier,
714 functionDecl(hasDescendant(
715 predefinedExpr(
716 hasType(
717 asString("const char [13]")),
718 has(stringLiteral(hasType(
719 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000720}
721
Gabor Marton19f4f392018-06-25 13:04:37 +0000722TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000723 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000724 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000725 "void declToImport() {"
726 " struct point { double x; double y; };"
727 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
728 " [0].x = 1.0 }; }",
729 Lang_CXX, "", Lang_CXX, Verifier,
730 functionDecl(hasDescendant(
731 initListExpr(
732 has(
733 cxxConstructExpr(
734 requiresZeroInitialization())),
735 has(
736 initListExpr(
737 hasType(asString("struct point")),
738 has(floatLiteral(equals(1.0))),
739 has(implicitValueInitExpr(
740 hasType(asString("double")))))),
741 has(
742 initListExpr(
743 hasType(asString("struct point")),
744 has(floatLiteral(equals(2.0))),
745 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000746}
747
748
Aleksei Sidorina693b372016-09-28 10:16:56 +0000749const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
750
Gabor Marton19f4f392018-06-25 13:04:37 +0000751TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000752 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000753 testImport(
754 "void declToImport(__builtin_va_list list, ...) {"
755 " (void)__builtin_va_arg(list, int); }",
756 Lang_CXX, "", Lang_CXX, Verifier,
757 functionDecl(hasDescendant(
758 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000759}
760
Gabor Marton19f4f392018-06-25 13:04:37 +0000761TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000762 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000763 testImport(
764 "struct C {};"
765 "void declToImport() { C c = C(); }",
766 Lang_CXX, "", Lang_CXX, Verifier,
767 functionDecl(hasDescendant(
768 exprWithCleanups(has(cxxConstructExpr(
769 has(materializeTemporaryExpr(has(implicitCastExpr(
770 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000771}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000772
Gabor Marton19f4f392018-06-25 13:04:37 +0000773TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000774 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000775 testImport(
776 "void declToImport() { typedef _Atomic(int) a_int; }",
777 Lang_CXX11, "", Lang_CXX11, Verifier,
778 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000779}
780
Gabor Marton19f4f392018-06-25 13:04:37 +0000781TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000782 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000783 testImport(
784 "template <typename T> void declToImport() { };",
785 Lang_CXX, "", Lang_CXX, Verifier,
786 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000787}
788
Gabor Marton19f4f392018-06-25 13:04:37 +0000789TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000790 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000791 testImport(
792 "template <typename T> struct C { T t; };"
793 "template <typename T> void declToImport() {"
794 " C<T> d;"
795 " (void)d.t;"
796 "}"
797 "void instantiate() { declToImport<int>(); }",
798 Lang_CXX, "", Lang_CXX, Verifier,
799 functionTemplateDecl(hasDescendant(
800 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
801 testImport(
802 "template <typename T> struct C { T t; };"
803 "template <typename T> void declToImport() {"
804 " C<T> d;"
805 " (void)(&d)->t;"
806 "}"
807 "void instantiate() { declToImport<int>(); }",
808 Lang_CXX, "", Lang_CXX, Verifier,
809 functionTemplateDecl(hasDescendant(
810 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000811}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000812
Gabor Marton19f4f392018-06-25 13:04:37 +0000813TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000814 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000815 testImport(
816 "template <int K>"
817 "struct dummy { static const int i = K; };"
818 "template <int K> using dummy2 = dummy<K>;"
819 "int declToImport() { return dummy2<3>::i; }",
820 Lang_CXX11, "", Lang_CXX11, Verifier,
821 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000822 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000823 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
824}
825
826const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
827 varTemplateSpecializationDecl;
828
Gabor Marton19f4f392018-06-25 13:04:37 +0000829TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000830 MatchVerifier<Decl> Verifier;
831 testImport(
832 "template <typename T>"
833 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000834 "void declToImport() { (void)pi<int>; }",
835 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000836 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000837 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000838 unless(hasAncestor(translationUnitDecl(has(varDecl(
839 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000840}
841
Gabor Marton19f4f392018-06-25 13:04:37 +0000842TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000843 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000844 testImport(
845 "template <typename... Args>"
846 "struct dummy {"
847 " dummy(Args... args) {}"
848 " static const int i = 4;"
849 "};"
850 "int declToImport() { return dummy<int>::i; }",
851 Lang_CXX11, "", Lang_CXX11, Verifier,
852 functionDecl(hasDescendant(
853 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000854}
855
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000856const internal::VariadicDynCastAllOfMatcher<Type,
857 DependentTemplateSpecializationType>
858 dependentTemplateSpecializationType;
859
Gabor Marton19f4f392018-06-25 13:04:37 +0000860TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000861 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000862 testImport(
863 "template<typename T>"
864 "struct A;"
865 "template<typename T>"
866 "struct declToImport {"
867 " typename A<T>::template B<T> a;"
868 "};",
869 Lang_CXX, "", Lang_CXX, Verifier,
870 classTemplateDecl(has(cxxRecordDecl(has(
871 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000872}
873
874const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
875 sizeOfPackExpr;
876
Gabor Marton19f4f392018-06-25 13:04:37 +0000877TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000878 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000879 testImport(
880 "template <typename... Ts>"
881 "void declToImport() {"
882 " const int i = sizeof...(Ts);"
883 "};"
884 "void g() { declToImport<int>(); }",
885 Lang_CXX11, "", Lang_CXX11, Verifier,
886 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000887 testImport(
888 "template <typename... Ts>"
889 "using X = int[sizeof...(Ts)];"
890 "template <typename... Us>"
891 "struct Y {"
892 " X<Us..., int, double, int, Us...> f;"
893 "};"
894 "Y<float, int> declToImport;",
895 Lang_CXX11, "", Lang_CXX11, Verifier,
896 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
897 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
898}
899
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000900/// \brief Matches __builtin_types_compatible_p:
901/// GNU extension to check equivalent types
902/// Given
903/// \code
904/// __builtin_types_compatible_p(int, int)
905/// \endcode
906// will generate TypeTraitExpr <...> 'int'
907const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
908
Gabor Marton19f4f392018-06-25 13:04:37 +0000909TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000910 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000911 testImport(
912 "void declToImport() { "
913 " (void)__builtin_types_compatible_p(int, int);"
914 "}",
915 Lang_C, "", Lang_C, Verifier,
916 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000917}
918
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000919const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
920
Gabor Marton19f4f392018-06-25 13:04:37 +0000921TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000922 MatchVerifier<Decl> Verifier;
923 testImport(
924 "namespace std { class type_info {}; }"
925 "void declToImport() {"
926 " int x;"
927 " auto a = typeid(int); auto b = typeid(x);"
928 "}",
929 Lang_CXX11, "", Lang_CXX11, Verifier,
930 functionDecl(
931 hasDescendant(varDecl(
932 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
933 hasDescendant(varDecl(
934 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
935}
936
Gabor Marton19f4f392018-06-25 13:04:37 +0000937TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000938 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000939 testImport(
940 "template<typename T> struct declToImport {"
941 " void m() { (void)__is_pod(T); }"
942 "};"
943 "void f() { declToImport<int>().m(); }",
944 Lang_CXX11, "", Lang_CXX11, Verifier,
945 classTemplateDecl(has(cxxRecordDecl(has(
946 functionDecl(hasDescendant(
947 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000948}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000949
Gabor Marton6e1510c2018-07-12 11:50:21 +0000950TEST_P(ImportDecl, ImportRecordDeclInFunc) {
951 MatchVerifier<Decl> Verifier;
952 testImport("int declToImport() { "
953 " struct data_t {int a;int b;};"
954 " struct data_t d;"
955 " return 0;"
956 "}",
957 Lang_C, "", Lang_C, Verifier,
958 functionDecl(hasBody(compoundStmt(
959 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
960}
961
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000962TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000963 Decl *FromTU = getTuDecl("int declToImport() { "
964 " struct data_t {int a;int b;};"
965 " struct data_t d;"
966 " return 0;"
967 "}",
968 Lang_C, "input.c");
Gabor Martonfe68e292018-08-06 14:38:37 +0000969 auto *FromVar =
Gabor Marton6e1510c2018-07-12 11:50:21 +0000970 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
971 ASSERT_TRUE(FromVar);
972 auto ToType =
973 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
974 EXPECT_FALSE(ToType.isNull());
975}
976
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000977TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000978 // This construct is not supported by ASTImporter.
Gabor Martonfe68e292018-08-06 14:38:37 +0000979 Decl *FromTU = getTuDecl(
980 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
981 Lang_C, "input.c");
982 auto *From = FirstDeclMatcher<FunctionDecl>().match(
983 FromTU, functionDecl(hasName("declToImport")));
Gabor Marton6e1510c2018-07-12 11:50:21 +0000984 ASSERT_TRUE(From);
Gabor Martonfe68e292018-08-06 14:38:37 +0000985 auto *To = Import(From, Lang_C);
986 EXPECT_EQ(To, nullptr);
987}
988
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000989TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +0000990 Decl *FromTU = getTuDecl(
991 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
992 "int declToImport(){ return NONAME_SIZEOF(int); }",
993 Lang_C, "input.c");
994 auto *From = FirstDeclMatcher<FunctionDecl>().match(
995 FromTU, functionDecl(hasName("declToImport")));
996 ASSERT_TRUE(From);
997 auto *To = Import(From, Lang_C);
998 ASSERT_TRUE(To);
999 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
1000 To, functionDecl(hasName("declToImport"),
1001 hasDescendant(unaryExprOrTypeTraitExpr()))));
1002}
1003
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001004TEST_P(ASTImporterOptionSpecificTestBase,
1005 ImportRecordDeclInFuncParamsFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +00001006 // This construct is not supported by ASTImporter.
1007 Decl *FromTU = getTuDecl(
1008 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
1009 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
1010 Lang_C, "input.c");
1011 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1012 FromTU, functionDecl(hasName("declToImport")));
1013 ASSERT_TRUE(From);
1014 auto *To = Import(From, Lang_C);
Gabor Marton6e1510c2018-07-12 11:50:21 +00001015 EXPECT_EQ(To, nullptr);
1016}
1017
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001018const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1019 cxxPseudoDestructorExpr;
1020
Gabor Marton19f4f392018-06-25 13:04:37 +00001021TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001022 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001023 testImport(
1024 "typedef int T;"
1025 "void declToImport(int *p) {"
1026 " T t;"
1027 " p->T::~T();"
1028 "}",
1029 Lang_CXX, "", Lang_CXX, Verifier,
1030 functionDecl(hasDescendant(
1031 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001032}
1033
Gabor Marton19f4f392018-06-25 13:04:37 +00001034TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001035 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001036 testImport(
1037 "namespace foo { int bar; }"
1038 "void declToImport() { using foo::bar; }",
1039 Lang_CXX, "", Lang_CXX, Verifier,
1040 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001041}
1042
1043/// \brief Matches shadow declarations introduced into a scope by a
1044/// (resolved) using declaration.
1045///
1046/// Given
1047/// \code
1048/// namespace n { int f; }
1049/// namespace declToImport { using n::f; }
1050/// \endcode
1051/// usingShadowDecl()
1052/// matches \code f \endcode
1053const internal::VariadicDynCastAllOfMatcher<Decl,
1054 UsingShadowDecl> usingShadowDecl;
1055
Gabor Marton19f4f392018-06-25 13:04:37 +00001056TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001057 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001058 testImport(
1059 "namespace foo { int bar; }"
1060 "namespace declToImport { using foo::bar; }",
1061 Lang_CXX, "", Lang_CXX, Verifier,
1062 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001063}
1064
Gabor Marton19f4f392018-06-25 13:04:37 +00001065TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001066 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001067 testImport(
1068 "template<typename T> int foo();"
1069 "template <typename T> void declToImport() {"
1070 " (void)::foo<T>;"
1071 " (void)::template foo<T>;"
1072 "}"
1073 "void instantiate() { declToImport<int>(); }",
1074 Lang_CXX, "", Lang_CXX, Verifier,
1075 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001076}
1077
Gabor Marton19f4f392018-06-25 13:04:37 +00001078TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001079 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001080 testImport(
1081 "template <typename T> struct C { T t; };"
1082 "template <typename T> void declToImport() {"
1083 " C<T> d;"
1084 " d.t = T();"
1085 "}"
1086 "void instantiate() { declToImport<int>(); }",
1087 Lang_CXX, "", Lang_CXX, Verifier,
1088 functionTemplateDecl(hasDescendant(
1089 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1090 testImport(
1091 "template <typename T> struct C { T t; };"
1092 "template <typename T> void declToImport() {"
1093 " C<T> d;"
1094 " (&d)->t = T();"
1095 "}"
1096 "void instantiate() { declToImport<int>(); }",
1097 Lang_CXX, "", Lang_CXX, Verifier,
1098 functionTemplateDecl(hasDescendant(
1099 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001100}
1101
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001102/// Check that function "declToImport()" (which is the templated function
1103/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1104/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001105TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001106 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001107 testImport(
1108 "template <typename T> void declToImport() { T a = 1; }"
1109 "void instantiate() { declToImport<int>(); }",
1110 Lang_CXX, "", Lang_CXX, Verifier,
1111 functionTemplateDecl(hasAncestor(translationUnitDecl(
1112 unless(has(functionDecl(hasName("declToImport"))))))));
1113 testImport(
1114 "template <typename T> struct declToImport { T t; };"
1115 "void instantiate() { declToImport<int>(); }",
1116 Lang_CXX, "", Lang_CXX, Verifier,
1117 classTemplateDecl(hasAncestor(translationUnitDecl(
1118 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001119}
1120
Gabor Marton19f4f392018-06-25 13:04:37 +00001121TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001122 MatchVerifier<Decl> Verifier;
1123 auto Code =
1124 R"s(
1125 struct declToImport {
1126 template <typename T0> struct X;
1127 template <typename T0> struct X<T0 *> {};
1128 };
1129 )s";
1130 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1131 recordDecl(has(classTemplateDecl()),
1132 has(classTemplateSpecializationDecl())));
1133}
1134
Gabor Marton19f4f392018-06-25 13:04:37 +00001135TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001136 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001137 testImport(
1138 "class declToImport {"
1139 " void f() { *this = declToImport(); }"
1140 "};",
1141 Lang_CXX, "", Lang_CXX, Verifier,
1142 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1143 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001144}
1145
Gabor Marton19f4f392018-06-25 13:04:37 +00001146TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001147 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001148 testImport(
1149 "template<typename T, int Size> class declToImport {"
1150 " T data[Size];"
1151 "};",
1152 Lang_CXX, "", Lang_CXX, Verifier,
1153 classTemplateDecl(has(cxxRecordDecl(
1154 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001155}
1156
Balazs Keri5f4fd8b2019-03-14 14:20:23 +00001157TEST_P(ASTImporterOptionSpecificTestBase, ImportBeginLocOfDeclRefExpr) {
1158 Decl *FromTU = getTuDecl(
1159 "class A { public: static int X; }; void f() { (void)A::X; }", Lang_CXX);
1160 auto From = FirstDeclMatcher<FunctionDecl>().match(
1161 FromTU, functionDecl(hasName("f")));
1162 ASSERT_TRUE(From);
1163 ASSERT_TRUE(
1164 cast<CStyleCastExpr>(cast<CompoundStmt>(From->getBody())->body_front())
1165 ->getSubExpr()
1166 ->getBeginLoc()
1167 .isValid());
1168 FunctionDecl *To = Import(From, Lang_CXX);
1169 ASSERT_TRUE(To);
1170 ASSERT_TRUE(
1171 cast<CStyleCastExpr>(cast<CompoundStmt>(To->getBody())->body_front())
1172 ->getSubExpr()
1173 ->getBeginLoc()
1174 .isValid());
1175}
1176
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001177TEST_P(ASTImporterOptionSpecificTestBase,
1178 ImportOfTemplatedDeclOfClassTemplateDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001179 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1180 auto From =
1181 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1182 ASSERT_TRUE(From);
1183 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1184 ASSERT_TRUE(To);
1185 Decl *ToTemplated = To->getTemplatedDecl();
1186 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1187 EXPECT_TRUE(ToTemplated1);
1188 EXPECT_EQ(ToTemplated1, ToTemplated);
1189}
1190
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001191TEST_P(ASTImporterOptionSpecificTestBase,
1192 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001193 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1194 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1195 FromTU, functionTemplateDecl());
1196 ASSERT_TRUE(From);
1197 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1198 ASSERT_TRUE(To);
1199 Decl *ToTemplated = To->getTemplatedDecl();
1200 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1201 EXPECT_TRUE(ToTemplated1);
1202 EXPECT_EQ(ToTemplated1, ToTemplated);
1203}
1204
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001205TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton6578a4a2018-06-25 11:38:43 +00001206 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1207 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1208 auto FromFT =
1209 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1210 ASSERT_TRUE(FromFT);
1211
1212 auto ToTemplated =
1213 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1214 EXPECT_TRUE(ToTemplated);
1215 auto ToTU = ToTemplated->getTranslationUnitDecl();
1216 auto ToFT =
1217 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1218 EXPECT_TRUE(ToFT);
1219}
1220
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001221TEST_P(ASTImporterOptionSpecificTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001222 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001223 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1224 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1225 FromTU, functionTemplateDecl());
1226 ASSERT_TRUE(FromFT);
1227
1228 auto ToTemplated =
1229 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1230 EXPECT_TRUE(ToTemplated);
1231 auto ToTU = ToTemplated->getTranslationUnitDecl();
1232 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1233 ToTU, functionTemplateDecl());
1234 EXPECT_TRUE(ToFT);
1235}
1236
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001237TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001238 auto Code =
1239 R"(
1240 namespace x {
1241 template<class X> struct S1{};
1242 template<class X> struct S2{};
1243 template<class X> struct S3{};
1244 }
1245 )";
1246 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1247 auto FromNs =
1248 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1249 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1250 ASSERT_TRUE(ToNs);
1251 auto From =
1252 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1253 classTemplateDecl(
1254 hasName("S2")));
1255 auto To =
1256 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1257 classTemplateDecl(
1258 hasName("S2")));
1259 ASSERT_TRUE(From);
1260 ASSERT_TRUE(To);
1261 auto ToTemplated = To->getTemplatedDecl();
1262 auto ToTemplated1 =
1263 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1264 EXPECT_TRUE(ToTemplated1);
1265 ASSERT_EQ(ToTemplated1, ToTemplated);
1266}
1267
Tom Roeder521f0042019-02-26 19:26:41 +00001268TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {
1269 // This tests the import of isConditionTrue directly to make sure the importer
1270 // gets it right.
1271 Decl *From, *To;
1272 std::tie(From, To) = getImportedDecl(
1273 "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }",
1274 Lang_C, "", Lang_C);
1275
1276 auto ToResults = match(chooseExpr().bind("choose"), To->getASTContext());
1277 auto FromResults = match(chooseExpr().bind("choose"), From->getASTContext());
1278
1279 const ChooseExpr *FromChooseExpr =
1280 selectFirst<ChooseExpr>("choose", FromResults);
1281 ASSERT_TRUE(FromChooseExpr);
1282
1283 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>("choose", ToResults);
1284 ASSERT_TRUE(ToChooseExpr);
1285
1286 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());
1287 EXPECT_EQ(FromChooseExpr->isConditionDependent(),
1288 ToChooseExpr->isConditionDependent());
1289}
1290
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001291TEST_P(ASTImporterOptionSpecificTestBase,
1292 ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001293 Decl *From, *To;
1294 std::tie(From, To) = getImportedDecl(
1295 R"(
1296 template <typename T> struct X {};
1297
1298 void declToImport(int y, X<int> &x) {}
1299
1300 template <> struct X<int> {
1301 void g() {
1302 X<int> x;
1303 declToImport(0, x);
1304 }
1305 };
1306 )",
1307 Lang_CXX, "", Lang_CXX);
1308
1309 MatchVerifier<Decl> Verifier;
1310 auto Matcher = functionDecl(hasName("declToImport"),
1311 parameterCountIs(2),
1312 hasParameter(0, hasName("y")),
1313 hasParameter(1, hasName("x")),
1314 hasParameter(1, hasType(asString("X<int> &"))));
1315 ASSERT_TRUE(Verifier.match(From, Matcher));
1316 EXPECT_TRUE(Verifier.match(To, Matcher));
1317}
1318
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001319TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001320 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1321 Decl *From, *To;
1322 std::tie(From, To) =
1323 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1324 "void instantiate() { declToImport<int>(); }",
1325 Lang_CXX, "", Lang_CXX);
1326
1327 auto Check = [](Decl *D) -> bool {
1328 auto TU = D->getTranslationUnitDecl();
1329 for (auto Child : TU->decls()) {
1330 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1331 if (FD->getNameAsString() == "declToImport") {
1332 GTEST_NONFATAL_FAILURE_(
1333 "TU should not contain any FunctionDecl with name declToImport");
1334 return false;
1335 }
1336 }
1337 }
1338 return true;
1339 };
1340
1341 ASSERT_TRUE(Check(From));
1342 EXPECT_TRUE(Check(To));
1343}
1344
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001345TEST_P(ASTImporterOptionSpecificTestBase,
1346 TUshouldNotContainTemplatedDeclOfClassTemplates) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001347 Decl *From, *To;
1348 std::tie(From, To) =
1349 getImportedDecl("template <typename T> struct declToImport { T t; };"
1350 "void instantiate() { declToImport<int>(); }",
1351 Lang_CXX, "", Lang_CXX);
1352
1353 auto Check = [](Decl *D) -> bool {
1354 auto TU = D->getTranslationUnitDecl();
1355 for (auto Child : TU->decls()) {
1356 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1357 if (RD->getNameAsString() == "declToImport") {
1358 GTEST_NONFATAL_FAILURE_(
1359 "TU should not contain any CXXRecordDecl with name declToImport");
1360 return false;
1361 }
1362 }
1363 }
1364 return true;
1365 };
1366
1367 ASSERT_TRUE(Check(From));
1368 EXPECT_TRUE(Check(To));
1369}
1370
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001371TEST_P(ASTImporterOptionSpecificTestBase,
1372 TUshouldNotContainTemplatedDeclOfTypeAlias) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001373 Decl *From, *To;
1374 std::tie(From, To) =
1375 getImportedDecl(
1376 "template <typename T> struct X {};"
1377 "template <typename T> using declToImport = X<T>;"
1378 "void instantiate() { declToImport<int> a; }",
1379 Lang_CXX11, "", Lang_CXX11);
1380
1381 auto Check = [](Decl *D) -> bool {
1382 auto TU = D->getTranslationUnitDecl();
1383 for (auto Child : TU->decls()) {
1384 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1385 if (AD->getNameAsString() == "declToImport") {
1386 GTEST_NONFATAL_FAILURE_(
1387 "TU should not contain any TypeAliasDecl with name declToImport");
1388 return false;
1389 }
1390 }
1391 }
1392 return true;
1393 };
1394
1395 ASSERT_TRUE(Check(From));
1396 EXPECT_TRUE(Check(To));
1397}
1398
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001399TEST_P(ASTImporterOptionSpecificTestBase,
1400 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001401
1402 Decl *From, *To;
1403 std::tie(From, To) = getImportedDecl(
1404 R"(
1405 template<class T>
1406 class Base {};
1407 class declToImport : public Base<declToImport> {};
1408 )",
1409 Lang_CXX, "", Lang_CXX);
1410
1411 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1412 auto Pattern =
1413 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1414 ASSERT_TRUE(
1415 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1416 EXPECT_TRUE(
1417 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1418
1419 // Check that the ClassTemplateSpecializationDecl is the child of the
1420 // ClassTemplateDecl.
1421 Pattern = translationUnitDecl(has(classTemplateDecl(
1422 hasName("Base"), has(classTemplateSpecializationDecl()))));
1423 ASSERT_TRUE(
1424 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1425 EXPECT_TRUE(
1426 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1427}
1428
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001429AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1430 size_t Index = 0;
Balazs Keri6e086692019-09-02 07:17:01 +00001431 for (Decl *D : Node.decls()) {
1432 if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D)) {
1433 auto *ND = cast<NamedDecl>(D);
1434 if (Index == Order.size())
1435 return false;
1436 if (ND->getName() != Order[Index])
1437 return false;
1438 ++Index;
1439 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001440 }
1441 return Index == Order.size();
1442}
1443
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001444TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001445 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1446 Decl *From, *To;
1447 std::tie(From, To) = getImportedDecl(
1448 R"(
1449 namespace NS {
1450 template<class T>
1451 class X {};
1452 template class X<int>;
1453 }
1454 )",
1455 Lang_CXX, "", Lang_CXX, "NS");
1456
1457 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1458 // ClassTemplateDecl.
1459 auto Pattern = namespaceDecl(has(classTemplateDecl(
1460 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1461 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1462 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1463
1464 // Check that the ClassTemplateSpecializationDecl is the child of the
1465 // NamespaceDecl.
1466 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1467 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1468 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1469}
1470
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001471TEST_P(ASTImporterOptionSpecificTestBase,
1472 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001473 Decl *From, *To;
1474 std::tie(From, To) =
1475 getImportedDecl(
1476 "struct declToImport { int a; int b; };",
1477 Lang_CXX11, "", Lang_CXX11);
1478
1479 MatchVerifier<Decl> Verifier;
1480 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1481 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1482}
1483
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001484TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton48b16e12019-07-25 09:07:17 +00001485 CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001486 Decl *From, *To;
1487 std::tie(From, To) = getImportedDecl(
1488 // The original recursive algorithm of ASTImporter first imports 'c' then
1489 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1490 R"s(
1491 struct declToImport {
1492 int a = c + b;
1493 int b = 1;
1494 int c = 2;
1495 };
1496 )s",
1497 Lang_CXX11, "", Lang_CXX11);
1498
1499 MatchVerifier<Decl> Verifier;
1500 ASSERT_TRUE(
1501 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1502 EXPECT_TRUE(
1503 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1504}
1505
Balazs Keri6e086692019-09-02 07:17:01 +00001506TEST_P(ASTImporterOptionSpecificTestBase,
1507 CXXRecordDeclFieldAndIndirectFieldOrder) {
1508 Decl *From, *To;
1509 std::tie(From, To) = getImportedDecl(
1510 // First field is "a", then the field for unnamed union, then "b" and "c"
1511 // from it (indirect fields), then "d".
1512 R"s(
1513 struct declToImport {
1514 int a = d;
1515 union {
1516 int b;
1517 int c;
1518 };
1519 int d;
1520 };
1521 )s",
1522 Lang_CXX11, "", Lang_CXX11);
1523
1524 MatchVerifier<Decl> Verifier;
1525 ASSERT_TRUE(Verifier.match(
1526 From, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1527 EXPECT_TRUE(Verifier.match(
1528 To, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1529}
1530
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001531TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001532 Decl *From, *To;
1533 std::tie(From, To) = getImportedDecl(
1534 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001535 struct declToImport {
1536 };
1537 )",
1538 Lang_CXX, "", Lang_CXX);
1539
1540 MatchVerifier<Decl> Verifier;
1541 // Match the implicit Decl.
1542 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1543 ASSERT_TRUE(Verifier.match(From, Matcher));
1544 EXPECT_TRUE(Verifier.match(To, Matcher));
1545}
1546
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001547TEST_P(ASTImporterOptionSpecificTestBase,
1548 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
Gabor Martona3af5672018-05-23 14:24:02 +00001549 Decl *From, *To;
1550 std::tie(From, To) = getImportedDecl(
1551 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001552 template <typename U>
1553 struct declToImport {
1554 };
1555 )",
1556 Lang_CXX, "", Lang_CXX);
1557
1558 MatchVerifier<Decl> Verifier;
1559 // Match the implicit Decl.
1560 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1561 ASSERT_TRUE(Verifier.match(From, Matcher));
1562 EXPECT_TRUE(Verifier.match(To, Matcher));
1563}
1564
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001565TEST_P(ASTImporterOptionSpecificTestBase,
1566 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001567 Decl *From, *To;
1568 std::tie(From, To) = getImportedDecl(
1569 R"(
1570 template<class T>
1571 class Base {};
1572 class declToImport : public Base<declToImport> {};
1573 )",
1574 Lang_CXX, "", Lang_CXX);
1575
1576 auto hasImplicitClass = has(cxxRecordDecl());
1577 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1578 hasName("Base"),
1579 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1580 ASSERT_TRUE(
1581 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1582 EXPECT_TRUE(
1583 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1584}
1585
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001586TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001587 Decl *From, *To;
1588 std::tie(From, To) =
1589 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1590
1591 MatchVerifier<Decl> Verifier;
1592 auto Matcher = functionDecl();
1593 ASSERT_TRUE(Verifier.match(From, Matcher));
1594 EXPECT_TRUE(Verifier.match(To, Matcher));
1595 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1596}
1597
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001598TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001599 Decl *FromTU = getTuDecl(
1600 R"(
1601 struct X {};
1602 void operator<<(int, X);
1603 )",
1604 Lang_CXX);
1605 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1606 const Decl *To = Import(From, Lang_CXX);
1607 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1608}
1609
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001610TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001611 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1612 Decl *From, *To;
1613 std::tie(From, To) = getImportedDecl(
1614 R"(
1615 template<class T>
1616 class Base { int a; };
1617 class declToImport : Base<declToImport> {};
1618 )",
1619 Lang_CXX, "", Lang_CXX);
1620
1621 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1622 hasName("Base"),
1623 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1624 ASSERT_TRUE(
1625 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1626 EXPECT_TRUE(
1627 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1628}
1629
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001630TEST_P(ASTImporterOptionSpecificTestBase,
1631 ImportDefinitionOfClassTemplateAfterFwdDecl) {
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001632 {
1633 Decl *FromTU = getTuDecl(
1634 R"(
1635 template <typename T>
1636 struct B;
1637 )",
1638 Lang_CXX, "input0.cc");
1639 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1640 FromTU, classTemplateDecl(hasName("B")));
1641
1642 Import(FromD, Lang_CXX);
1643 }
1644
1645 {
1646 Decl *FromTU = getTuDecl(
1647 R"(
1648 template <typename T>
1649 struct B {
1650 void f();
1651 };
1652 )",
1653 Lang_CXX, "input1.cc");
1654 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1655 FromTU, functionDecl(hasName("f")));
1656 Import(FromD, Lang_CXX);
1657 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1658 FromTU, classTemplateDecl(hasName("B")));
1659 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1660 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1661 }
1662}
1663
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001664TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001665 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1666 Decl *ToTU = getToTuDecl(
1667 R"(
1668 template <typename T>
1669 struct B {
1670 void f();
1671 };
1672
1673 template <typename T>
1674 struct B;
1675 )",
1676 Lang_CXX);
1677 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1678 [](const ClassTemplateDecl *T) {
1679 return T->isThisDeclarationADefinition();
1680 })
1681 .match(ToTU, classTemplateDecl()));
1682
1683 Decl *FromTU = getTuDecl(
1684 R"(
1685 template <typename T>
1686 struct B {
1687 void f();
1688 };
1689 )",
1690 Lang_CXX, "input1.cc");
1691 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1692 FromTU, classTemplateDecl(hasName("B")));
1693
1694 Import(FromD, Lang_CXX);
1695
1696 // We should have only one definition.
1697 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1698 [](const ClassTemplateDecl *T) {
1699 return T->isThisDeclarationADefinition();
1700 })
1701 .match(ToTU, classTemplateDecl()));
1702}
1703
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001704TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001705 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1706 Decl *ToTU = getToTuDecl(
1707 R"(
1708 struct B {
1709 void f();
1710 };
1711
1712 struct B;
1713 )",
1714 Lang_CXX);
1715 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001716 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001717
1718 Decl *FromTU = getTuDecl(
1719 R"(
1720 struct B {
1721 void f();
1722 };
1723 )",
1724 Lang_CXX, "input1.cc");
1725 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1726 FromTU, cxxRecordDecl(hasName("B")));
1727
1728 Import(FromD, Lang_CXX);
1729
1730 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001731 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001732}
1733
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001734static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1735 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1736 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1737 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1738 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1739}
1740static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1741 SourceManager &SM1, SourceManager &SM2) {
1742 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1743 FullSourceLoc{ Range2.getBegin(), SM2 });
1744 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1745 FullSourceLoc{ Range2.getEnd(), SM2 });
1746}
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001747TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001748 Decl *FromTU = getTuDecl(
1749 R"(
1750 #define MFOO(arg) arg = arg + 1
1751
1752 void foo() {
1753 int a = 5;
1754 MFOO(a);
1755 }
1756 )",
1757 Lang_CXX);
1758 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1759 auto ToD = Import(FromD, Lang_CXX);
1760
1761 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1762 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1763 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1764 auto FromRHS =
1765 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1766
1767 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1768 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1769 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1770 FromSM);
1771 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1772 FromSM);
1773 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1774 FromSM);
1775}
1776
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001777TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001778 Decl *FromTU = getTuDecl(
1779 R"(
1780 #define FUNC_INT void declToImport
1781 #define FUNC FUNC_INT
1782 FUNC(int a);
1783 )",
1784 Lang_CXX);
1785 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1786 auto ToD = Import(FromD, Lang_CXX);
1787
1788 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1789 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1790 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1791 FromSM);
1792}
1793
Gabor Marton9581c332018-05-23 13:53:36 +00001794TEST_P(
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001795 ASTImporterOptionSpecificTestBase,
1796 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
Gabor Marton9581c332018-05-23 13:53:36 +00001797 Decl *ToTU = getToTuDecl(
1798 R"(
1799 template <typename T>
1800 struct B;
1801
1802 template <>
1803 struct B<int> {};
1804
1805 template <>
1806 struct B<int>;
1807 )",
1808 Lang_CXX);
1809 // We should have only one definition.
1810 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1811 [](const ClassTemplateSpecializationDecl *T) {
1812 return T->isThisDeclarationADefinition();
1813 })
1814 .match(ToTU, classTemplateSpecializationDecl()));
1815
1816 Decl *FromTU = getTuDecl(
1817 R"(
1818 template <typename T>
1819 struct B;
1820
1821 template <>
1822 struct B<int> {};
1823 )",
1824 Lang_CXX, "input1.cc");
1825 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1826 FromTU, classTemplateSpecializationDecl(hasName("B")));
1827
1828 Import(FromD, Lang_CXX);
1829
1830 // We should have only one definition.
1831 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1832 [](const ClassTemplateSpecializationDecl *T) {
1833 return T->isThisDeclarationADefinition();
1834 })
1835 .match(ToTU, classTemplateSpecializationDecl()));
1836}
1837
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001838TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
Gabor Marton0bebf952018-07-05 09:51:13 +00001839 Decl *FromTU = getTuDecl(
1840 R"(
1841 struct { int a; int b; } object0 = { 2, 3 };
1842 struct { int x; int y; int z; } object1;
1843 )",
1844 Lang_CXX, "input0.cc");
1845
Gabor Marton0bebf952018-07-05 09:51:13 +00001846 auto *Obj0 =
1847 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1848 auto *From0 = getRecordDecl(Obj0);
1849 auto *Obj1 =
1850 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1851 auto *From1 = getRecordDecl(Obj1);
1852
1853 auto *To0 = Import(From0, Lang_CXX);
1854 auto *To1 = Import(From1, Lang_CXX);
1855
1856 EXPECT_TRUE(To0);
1857 EXPECT_TRUE(To1);
1858 EXPECT_NE(To0, To1);
1859 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1860}
1861
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001862TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001863 auto *Code =
1864 R"(
1865 struct X {
1866 struct { int a; };
1867 struct { int b; };
1868 };
1869 )";
1870 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
1871
1872 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
1873
1874 auto *X0 =
1875 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1876 auto *X1 =
1877 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1878 Import(X0, Lang_C);
1879 Import(X1, Lang_C);
1880
1881 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1882 // We expect no (ODR) warning during the import.
1883 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1884 EXPECT_EQ(1u,
1885 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1886}
1887
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001888TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001889 Decl *FromTU0 = getTuDecl(
1890 R"(
1891 struct X {
1892 struct { int a; };
1893 struct { int b; };
1894 };
1895 )",
1896 Lang_C, "input0.c");
1897
1898 Decl *FromTU1 = getTuDecl(
1899 R"(
1900 struct X { // reversed order
1901 struct { int b; };
1902 struct { int a; };
1903 };
1904 )",
1905 Lang_C, "input1.c");
1906
1907 auto *X0 =
1908 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1909 auto *X1 =
1910 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1911 Import(X0, Lang_C);
1912 Import(X1, Lang_C);
1913
1914 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1915 // We expect one (ODR) warning during the import.
1916 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
Gabor Martonf035b752019-08-27 11:36:10 +00001917 EXPECT_EQ(1u,
Gabor Marton7df342a2018-12-17 12:42:12 +00001918 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1919}
1920
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001921TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001922 auto Pattern = varDecl(hasName("x"));
1923 VarDecl *Imported1;
1924 {
1925 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1926 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1927 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1928 }
1929 VarDecl *Imported2;
1930 {
1931 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1932 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1933 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1934 }
1935 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1936 EXPECT_FALSE(Imported2->isUsed(false));
1937 {
1938 Decl *FromTU =
1939 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
Gabor Martonac3a5d62018-09-17 12:04:52 +00001940 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1941 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00001942 Import(FromD, Lang_CXX);
1943 }
1944 EXPECT_TRUE(Imported2->isUsed(false));
1945}
1946
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001947TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001948 auto Pattern = varDecl(hasName("x"));
1949 VarDecl *ExistingD;
1950 {
1951 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
1952 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1953 }
1954 EXPECT_FALSE(ExistingD->isUsed(false));
1955 {
1956 Decl *FromTU = getTuDecl(
1957 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
1958 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1959 FromTU, functionDecl(hasName("f")));
1960 Import(FromD, Lang_CXX);
1961 }
1962 EXPECT_TRUE(ExistingD->isUsed(false));
1963}
1964
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001965TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001966 auto Pattern = varDecl(hasName("a"));
1967 VarDecl *ExistingD;
1968 {
1969 Decl *ToTU = getToTuDecl(
1970 R"(
1971 struct A {
1972 static const int a = 1;
1973 };
1974 )", Lang_CXX);
1975 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1976 }
1977 EXPECT_FALSE(ExistingD->isUsed(false));
1978 {
1979 Decl *FromTU = getTuDecl(
1980 R"(
1981 struct A {
1982 static const int a = 1;
1983 };
1984 const int *f() { return &A::a; } // requires storage,
1985 // thus used flag will be set
1986 )", Lang_CXX, "input1.cc");
1987 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
1988 FromTU, functionDecl(hasName("f")));
1989 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1990 ASSERT_TRUE(FromD->isUsed(false));
1991 Import(FromFunD, Lang_CXX);
1992 }
1993 EXPECT_TRUE(ExistingD->isUsed(false));
1994}
1995
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001996TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001997 auto Pattern = varDecl(hasName("x"));
1998
1999 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
2000 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2001
2002 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
2003
2004 ASSERT_FALSE(Imported1->isUsed(false));
2005
2006 FromD->setIsUsed();
2007 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
2008
2009 EXPECT_EQ(Imported1, Imported2);
2010 EXPECT_TRUE(Imported2->isUsed(false));
2011}
2012
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002013struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
Peter Szecsidedda6f2018-03-30 22:03:29 +00002014
Gabor Marton5254e642018-06-27 13:32:50 +00002015TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002016 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2017 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002018 auto *From =
2019 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00002020
Gabor Marton5254e642018-06-27 13:32:50 +00002021 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002022 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2023
Gabor Marton5254e642018-06-27 13:32:50 +00002024 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2025 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2026 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2027 EXPECT_TRUE(ImportedD == To0);
2028 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2029 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2030 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002031}
2032
2033TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
2034 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2035 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002036 auto *From =
2037 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00002038
Gabor Marton5254e642018-06-27 13:32:50 +00002039 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002040 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2041
Gabor Marton5254e642018-06-27 13:32:50 +00002042 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2043 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2044 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2045 EXPECT_TRUE(ImportedD == To1);
2046 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2047 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2048 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002049}
2050
Peter Szecsidedda6f2018-03-30 22:03:29 +00002051TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2052 auto Code =
2053 R"(
2054 struct B { virtual void f(); };
2055 void B::f() {}
2056 struct D : B { void f(); };
2057 )";
2058 auto Pattern =
2059 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2060 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2061 CXXMethodDecl *Proto =
2062 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2063
2064 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2065 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2066 EXPECT_EQ(To->size_overridden_methods(), 1u);
2067}
2068
2069TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2070 auto Code =
2071 R"(
2072 struct B { virtual void f(); };
2073 void B::f() {}
2074 )";
2075 auto Pattern =
2076 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2077 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2078 CXXMethodDecl *Proto =
2079 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2080 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2081
2082 ASSERT_TRUE(Proto->isVirtual());
2083 ASSERT_TRUE(Def->isVirtual());
2084 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2085 EXPECT_TRUE(To->isVirtual());
2086}
2087
Gabor Marton5254e642018-06-27 13:32:50 +00002088TEST_P(ImportFunctions,
2089 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2090 Decl *ToTU = getToTuDecl(
2091 R"(
2092 void f() {}
2093 void f();
2094 )",
2095 Lang_CXX);
2096 ASSERT_EQ(1u,
2097 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2098 return FD->doesThisDeclarationHaveABody();
2099 }).match(ToTU, functionDecl()));
2100
2101 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2102 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2103
2104 Import(FromD, Lang_CXX);
2105
2106 EXPECT_EQ(1u,
2107 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2108 return FD->doesThisDeclarationHaveABody();
2109 }).match(ToTU, functionDecl()));
2110}
2111
Shafik Yaghmour96b3d202019-01-28 21:55:33 +00002112TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
2113 auto Code =
2114 R"(
2115 struct B { virtual void f(); };
2116 struct D:B { void f(); };
2117 )";
2118 auto BFP =
2119 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2120 auto DFP =
2121 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2122
2123 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2124 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2125 Import(DF, Lang_CXX);
2126
2127 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2128 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2129 Import(BF, Lang_CXX);
2130
2131 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2132
2133 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2134 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2135}
2136
2137TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2138 auto CodeWithoutDef =
2139 R"(
2140 struct B { virtual void f(); };
2141 struct D:B { void f(); };
2142 )";
2143 auto CodeWithDef =
2144 R"(
2145 struct B { virtual void f(){}; };
2146 struct D:B { void f(){}; };
2147 )";
2148 auto BFP =
2149 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2150 auto DFP =
2151 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2152 auto BFDefP = cxxMethodDecl(
2153 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2154 auto DFDefP = cxxMethodDecl(
2155 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2156 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
2157
2158 {
2159 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX, "input0.cc");
2160 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
2161 Import(FromD, Lang_CXX);
2162 }
2163 {
2164 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX, "input1.cc");
2165 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
2166 Import(FromB, Lang_CXX);
2167 }
2168
2169 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2170
2171 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2172 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2173 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2174 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2175 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2176}
2177
2178TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2179 auto Code =
2180 R"(
2181 struct B { virtual void f(); };
2182 struct D:B { void f(); };
2183 void B::f(){};
2184 )";
2185
2186 auto BFP =
2187 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2188 auto BFDefP = cxxMethodDecl(
2189 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2190 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
2191 unless(isDefinition()));
2192
2193 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2194 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2195 Import(D, Lang_CXX);
2196
2197 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2198 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2199 Import(B, Lang_CXX);
2200
2201 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2202
2203 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2204 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2205
2206 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2207 ToTU, cxxRecordDecl(hasName("B")));
2208 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2209 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2210 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2211
2212 // The definition should be out-of-class.
2213 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2214 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2215 ToBFOutOfClass->getLexicalDeclContext());
2216 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2217 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2218
2219 // Check that the redecl chain is intact.
2220 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2221}
2222
2223TEST_P(ImportFunctions,
2224 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2225 auto CodeTU0 =
2226 R"(
2227 struct B { virtual void f(); };
2228 struct D:B { void f(); };
2229 )";
2230 auto CodeTU1 =
2231 R"(
2232 struct B { virtual void f(); };
2233 struct D:B { void f(); };
2234 void B::f(){}
2235 void D::f(){}
2236 void foo(B &b, D &d) { b.f(); d.f(); }
2237 )";
2238
2239 auto BFP =
2240 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2241 auto BFDefP = cxxMethodDecl(
2242 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2243 auto DFP =
2244 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2245 auto DFDefP = cxxMethodDecl(
2246 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2247 auto FooDef = functionDecl(hasName("foo"));
2248
2249 {
2250 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX, "input0.cc");
2251 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2252 Import(D, Lang_CXX);
2253 }
2254
2255 {
2256 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX, "input1.cc");
2257 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2258 Import(Foo, Lang_CXX);
2259 }
2260
2261 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2262
2263 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2264 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2265 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2266 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2267
2268 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2269 ToTU, cxxRecordDecl(hasName("B")));
2270 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2271 ToTU, cxxRecordDecl(hasName("D")));
2272 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2273 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2274 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2275 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2276 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2277 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2278
2279 // The definition should be out-of-class.
2280 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2281 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2282 ToBFOutOfClass->getLexicalDeclContext());
2283 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2284 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2285
2286 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2287 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2288 ToDFOutOfClass->getLexicalDeclContext());
2289 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2290 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2291
2292 // Check that the redecl chain is intact.
2293 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2294 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2295}
2296
Gabor Marton458d1452019-02-14 13:07:03 +00002297TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2298 std::string Code = "static int v; static int v = 0;";
2299 auto Pattern = varDecl(hasName("v"));
2300
2301 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C, "input0.c");
2302
2303 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2304 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2305
2306 auto *To0 = Import(From0, Lang_C);
2307 auto *To1 = Import(From1, Lang_C);
2308
2309 EXPECT_TRUE(To0);
2310 ASSERT_TRUE(To1);
2311 EXPECT_NE(To0, To1);
2312 EXPECT_EQ(To1->getPreviousDecl(), To0);
2313}
2314
2315TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2316 TranslationUnitDecl *FromTu = getTuDecl(
2317 "namespace NS0 { namespace { void f(); } }"
2318 "namespace NS1 { namespace { void f(); } }",
2319 Lang_CXX, "input0.cc");
2320 auto Pattern = functionDecl(hasName("f"));
2321
2322 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2323 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2324
2325 auto *ToF0 = Import(FromF0, Lang_CXX);
2326 auto *ToF1 = Import(FromF1, Lang_CXX);
2327
2328 EXPECT_TRUE(ToF0);
2329 ASSERT_TRUE(ToF1);
2330 EXPECT_NE(ToF0, ToF1);
2331 EXPECT_FALSE(ToF1->getPreviousDecl());
2332}
2333
2334TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2335 {
2336 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",
2337 Lang_CXX, "input0.cc");
2338 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2339 FromTU, functionDecl(hasName("g0")));
2340
2341 Import(FromD, Lang_CXX);
2342 }
2343 {
2344 Decl *FromTU =
2345 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",
2346 Lang_CXX, "input1.cc");
2347 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2348 FromTU, functionDecl(hasName("g1")));
2349 Import(FromD, Lang_CXX);
2350 }
2351
2352 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2353 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2354 2u);
2355}
2356
Gabor Marton302f3002019-02-15 12:04:05 +00002357TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2358 Decl *FromTU = getTuDecl(
2359 R"(
2360 void foo() {
2361 (void)[]() { ; };
2362 }
2363 )",
2364 Lang_CXX11);
2365 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2366 FromTU, functionDecl(hasName("foo")));
2367 auto *ToD = Import(FromD, Lang_CXX);
2368 EXPECT_TRUE(ToD);
2369 CXXRecordDecl *LambdaRec =
2370 cast<LambdaExpr>(cast<CStyleCastExpr>(
2371 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2372 ->getSubExpr())
2373 ->getLambdaClass();
2374 EXPECT_TRUE(LambdaRec->getDestructor());
2375}
2376
Gabor Marton5caba302019-03-07 13:38:20 +00002377TEST_P(ImportFunctions,
2378 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2379 Decl *FromTU = getTuDecl(
2380 R"(
2381 struct X {
2382 template <typename T>
2383 void foo(){}
2384 };
2385 void f() {
2386 X x;
2387 x.foo<int>();
2388 }
2389 )",
2390 Lang_CXX);
2391 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2392 FromTU, functionDecl(hasName("f")));
2393 auto *ToD = Import(FromD, Lang_CXX);
2394 EXPECT_TRUE(ToD);
2395 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
2396 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr()))));
2397}
2398
2399TEST_P(ImportFunctions,
2400 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2401 Decl *FromTU = getTuDecl(
2402 R"(
2403 struct X {
2404 template <typename T>
2405 void foo(){}
2406 };
2407 template <typename T>
2408 void f() {
2409 X x;
2410 x.foo<T>();
2411 }
2412 void g() {
2413 f<int>();
2414 }
2415 )",
2416 Lang_CXX);
2417 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2418 FromTU, functionDecl(hasName("g")));
2419 auto *ToD = Import(FromD, Lang_CXX);
2420 EXPECT_TRUE(ToD);
2421 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2422 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match(
2423 ToTU, translationUnitDecl(hasDescendant(
2424 functionDecl(hasName("f"), hasDescendant(declRefExpr()))))));
2425}
2426
Balazs Kerie9719f92019-08-07 12:40:17 +00002427struct ImportFunctionTemplates : ASTImporterOptionSpecificTestBase {};
2428
2429TEST_P(ImportFunctionTemplates, ImportFunctionTemplateInRecordDeclTwice) {
2430 auto Code =
2431 R"(
2432 class X {
2433 template <class T>
2434 void f(T t);
2435 };
2436 )";
2437 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2438 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2439 FromTU1, functionTemplateDecl(hasName("f")));
2440 auto *ToD1 = Import(FromD1, Lang_CXX);
2441 Decl *FromTU2 = getTuDecl(Code, Lang_CXX, "input2.cc");
2442 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2443 FromTU2, functionTemplateDecl(hasName("f")));
2444 auto *ToD2 = Import(FromD2, Lang_CXX);
2445 EXPECT_EQ(ToD1, ToD2);
2446}
2447
2448TEST_P(ImportFunctionTemplates,
2449 ImportFunctionTemplateWithDefInRecordDeclTwice) {
2450 auto Code =
2451 R"(
2452 class X {
2453 template <class T>
2454 void f(T t);
2455 };
2456 template <class T>
2457 void X::f(T t) {};
2458 )";
2459 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2460 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2461 FromTU1, functionTemplateDecl(hasName("f")));
2462 auto *ToD1 = Import(FromD1, Lang_CXX);
2463 Decl *FromTU2 = getTuDecl(Code, Lang_CXX, "input2.cc");
2464 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2465 FromTU2, functionTemplateDecl(hasName("f")));
2466 auto *ToD2 = Import(FromD2, Lang_CXX);
2467 EXPECT_EQ(ToD1, ToD2);
2468}
2469
Gabor Martonf035b752019-08-27 11:36:10 +00002470TEST_P(ImportFunctionTemplates,
2471 ImportFunctionWhenThereIsAFunTemplateWithSameName) {
2472 getToTuDecl(
2473 R"(
2474 template <typename T>
2475 void foo(T) {}
2476 void foo();
2477 )",
2478 Lang_CXX);
2479 Decl *FromTU = getTuDecl("void foo();", Lang_CXX);
2480 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2481 FromTU, functionDecl(hasName("foo")));
2482 auto *ImportedD = Import(FromD, Lang_CXX);
2483 EXPECT_TRUE(ImportedD);
2484}
2485
2486TEST_P(ImportFunctionTemplates,
2487 ImportConstructorWhenThereIsAFunTemplateWithSameName) {
2488 auto Code =
2489 R"(
2490 struct Foo {
2491 template <typename T>
2492 Foo(T) {}
2493 Foo();
2494 };
2495 )";
2496 getToTuDecl(Code, Lang_CXX);
2497 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2498 auto *FromD =
2499 LastDeclMatcher<CXXConstructorDecl>().match(FromTU, cxxConstructorDecl());
2500 auto *ImportedD = Import(FromD, Lang_CXX);
2501 EXPECT_TRUE(ImportedD);
2502}
2503
2504TEST_P(ImportFunctionTemplates,
2505 ImportOperatorWhenThereIsAFunTemplateWithSameName) {
2506 getToTuDecl(
2507 R"(
2508 template <typename T>
2509 void operator<(T,T) {}
2510 struct X{};
2511 void operator<(X, X);
2512 )",
2513 Lang_CXX);
2514 Decl *FromTU = getTuDecl(
2515 R"(
2516 struct X{};
2517 void operator<(X, X);
2518 )",
2519 Lang_CXX);
2520 auto *FromD = LastDeclMatcher<FunctionDecl>().match(
2521 FromTU, functionDecl(hasOverloadedOperatorName("<")));
2522 auto *ImportedD = Import(FromD, Lang_CXX);
2523 EXPECT_TRUE(ImportedD);
2524}
2525
Gabor Marton5254e642018-06-27 13:32:50 +00002526struct ImportFriendFunctions : ImportFunctions {};
2527
2528TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2529 auto Pattern = functionDecl(hasName("f"));
2530
2531 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2532 "void f();",
2533 Lang_CXX,
2534 "input0.cc");
2535 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2536
2537 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2538 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2539 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2540 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2541 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2542 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2543 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2544}
2545
2546TEST_P(ImportFriendFunctions,
2547 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2548 auto Pattern = functionDecl(hasName("f"));
2549
2550 Decl *FromTU = getTuDecl("void f();"
2551 "struct X { friend void f(); };",
2552 Lang_CXX, "input0.cc");
2553 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2554
2555 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2556 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2557 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2558 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2559 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2560 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2561 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2562}
2563
2564TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2565 auto Pattern = functionDecl(hasName("f"));
2566
2567 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2568 "void f();",
2569 Lang_CXX,
2570 "input0.cc");
2571 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2572
2573 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2574 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2575 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2576 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2577 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2578 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2579 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2580}
2581
2582TEST_P(ImportFriendFunctions,
2583 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2584 auto Pattern = functionDecl(hasName("f"));
2585
2586 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2587 "void f(){}",
2588 Lang_CXX, "input0.cc");
2589 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2590
2591 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2592 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2593 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2594 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2595 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2596 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2597 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2598}
2599
Gabor Marton1d51e3e2019-05-20 10:38:14 +00002600TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDefWithClass) {
Gabor Marton5254e642018-06-27 13:32:50 +00002601 auto Pattern = functionDecl(hasName("f"));
2602
2603 Decl *FromTU = getTuDecl(
2604 R"(
2605 class X;
2606 void f(X *x){}
2607 class X{
2608 friend void f(X *x);
2609 };
2610 )",
2611 Lang_CXX, "input0.cc");
2612 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2613
2614 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2615 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2616 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2617 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2618 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2619 .match(ToTU, friendDecl())
2620 ->getFriendDecl());
2621 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2622 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2623 // The parameters must refer the same type
2624 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2625 (*ImportedD->param_begin())->getOriginalType());
2626}
2627
Gabor Marton5254e642018-06-27 13:32:50 +00002628TEST_P(ImportFriendFunctions,
Gabor Marton1d51e3e2019-05-20 10:38:14 +00002629 ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002630 auto Pattern = functionDecl(hasName("f"));
2631
2632 Decl *FromTU = getTuDecl(
2633 R"(
2634 class X;
2635 void f(X *x){}
2636 class X{
2637 friend void f(X *x);
2638 };
2639 )",
2640 Lang_CXX, "input0.cc");
2641 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2642
2643 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2644 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2645 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2646 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2647 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2648 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2649
2650 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2651 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2652 // The parameters must refer the same type
2653 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2654 (*ImportedD->param_begin())->getOriginalType());
2655}
2656
2657TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2658 auto Pattern = functionDecl(hasName("f"));
2659
2660 FunctionDecl *ImportedD;
2661 {
2662 Decl *FromTU =
2663 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2664 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2665 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2666 }
2667 FunctionDecl *ImportedD1;
2668 {
2669 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2670 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2671 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2672 }
2673
2674 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2675 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2676 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2677 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2678 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2679}
2680
Balazs Keri89632b82018-08-21 14:32:21 +00002681TEST_P(ImportFriendFunctions, Lookup) {
2682 auto FunctionPattern = functionDecl(hasName("f"));
2683 auto ClassPattern = cxxRecordDecl(hasName("X"));
2684
2685 TranslationUnitDecl *FromTU =
2686 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2687 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2688 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2689 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2690 {
2691 auto FromName = FromD->getDeclName();
2692 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2693 auto LookupRes = Class->noload_lookup(FromName);
2694 ASSERT_EQ(LookupRes.size(), 0u);
2695 LookupRes = FromTU->noload_lookup(FromName);
2696 ASSERT_EQ(LookupRes.size(), 1u);
2697 }
2698
2699 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2700 auto ToName = ToD->getDeclName();
2701
2702 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2703 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2704 auto LookupRes = Class->noload_lookup(ToName);
2705 EXPECT_EQ(LookupRes.size(), 0u);
2706 LookupRes = ToTU->noload_lookup(ToName);
2707 EXPECT_EQ(LookupRes.size(), 1u);
2708
2709 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2710 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2711 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2712 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2713}
2714
Gabor Martonbc5b7e22019-12-04 17:12:08 +01002715TEST_P(ImportFriendFunctions, LookupWithProtoAfter) {
Balazs Keri89632b82018-08-21 14:32:21 +00002716 auto FunctionPattern = functionDecl(hasName("f"));
2717 auto ClassPattern = cxxRecordDecl(hasName("X"));
2718
2719 TranslationUnitDecl *FromTU = getTuDecl(
2720 "struct X { friend void f(); };"
2721 // This proto decl makes f available to normal
2722 // lookup, otherwise it is hidden.
2723 // Normal C++ lookup (implemented in
2724 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2725 // returns the found `NamedDecl` only if the set IDNS is matched
2726 "void f();",
2727 Lang_CXX, "input0.cc");
2728 auto *FromFriend =
2729 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2730 auto *FromNormal =
2731 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2732 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2733 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2734 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2735 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2736
2737 auto FromName = FromFriend->getDeclName();
2738 auto *FromClass =
2739 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2740 auto LookupRes = FromClass->noload_lookup(FromName);
2741 ASSERT_EQ(LookupRes.size(), 0u);
2742 LookupRes = FromTU->noload_lookup(FromName);
2743 ASSERT_EQ(LookupRes.size(), 1u);
2744
2745 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2746 auto ToName = ToFriend->getDeclName();
2747
2748 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2749 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2750 LookupRes = ToClass->noload_lookup(ToName);
2751 EXPECT_EQ(LookupRes.size(), 0u);
2752 LookupRes = ToTU->noload_lookup(ToName);
2753 // Test is disabled because this result is 2.
2754 EXPECT_EQ(LookupRes.size(), 1u);
2755
2756 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2757 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2758 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2759 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2760 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2761 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2762 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2763}
2764
2765TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2766 auto FunctionPattern = functionDecl(hasName("f"));
2767 auto ClassPattern = cxxRecordDecl(hasName("X"));
2768
2769 TranslationUnitDecl *FromTU = getTuDecl(
2770 "void f();"
2771 "struct X { friend void f(); };",
2772 Lang_CXX, "input0.cc");
2773 auto *FromNormal =
2774 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2775 auto *FromFriend =
2776 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2777 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2778 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2779 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2780 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2781
2782 auto FromName = FromNormal->getDeclName();
2783 auto *FromClass =
2784 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2785 auto LookupRes = FromClass->noload_lookup(FromName);
2786 ASSERT_EQ(LookupRes.size(), 0u);
2787 LookupRes = FromTU->noload_lookup(FromName);
2788 ASSERT_EQ(LookupRes.size(), 1u);
2789
2790 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2791 auto ToName = ToNormal->getDeclName();
2792 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2793
2794 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2795 LookupRes = ToClass->noload_lookup(ToName);
2796 EXPECT_EQ(LookupRes.size(), 0u);
2797 LookupRes = ToTU->noload_lookup(ToName);
2798 EXPECT_EQ(LookupRes.size(), 1u);
2799
2800 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2801 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2802 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2803 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2804 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2805 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2806 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2807}
2808
2809TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2810 auto Pattern = functionDecl(hasName("f"));
2811
2812 TranslationUnitDecl *FromNormalTU =
2813 getTuDecl("void f();", Lang_CXX, "input0.cc");
2814 auto *FromNormalF =
2815 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2816 TranslationUnitDecl *FromFriendTU =
2817 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2818 auto *FromFriendF =
2819 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2820 auto FromNormalName = FromNormalF->getDeclName();
2821 auto FromFriendName = FromFriendF->getDeclName();
2822
2823 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2824 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2825 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2826 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2827 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2828 ASSERT_EQ(LookupRes.size(), 1u);
2829 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2830 ASSERT_EQ(LookupRes.size(), 1u);
2831
2832 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2833 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2834 auto ToName = ToNormalF->getDeclName();
2835 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2836 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2837 LookupRes = ToTU->noload_lookup(ToName);
2838 EXPECT_EQ(LookupRes.size(), 1u);
2839 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00002840
Balazs Keri89632b82018-08-21 14:32:21 +00002841 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
2842 LookupRes = ToTU->noload_lookup(ToName);
2843 EXPECT_EQ(LookupRes.size(), 1u);
2844 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2845
2846 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2847 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2848
2849 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2850 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2851}
2852
2853TEST_P(ImportFriendFunctions, ImportFriendList) {
2854 TranslationUnitDecl *FromTU = getTuDecl(
2855 "struct X { friend void f(); };"
2856 "void f();",
2857 Lang_CXX, "input0.cc");
2858 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2859 FromTU, functionDecl(hasName("f")));
2860
2861 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2862 FromTU, cxxRecordDecl(hasName("X")));
2863 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2864 auto FromFriends = FromClass->friends();
2865 unsigned int FrN = 0;
2866 for (auto Fr : FromFriends) {
2867 ASSERT_EQ(Fr, FromFriend);
2868 ++FrN;
2869 }
2870 ASSERT_EQ(FrN, 1u);
2871
2872 Import(FromFriendF, Lang_CXX);
2873 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2874 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2875 ToTU, cxxRecordDecl(hasName("X")));
2876 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2877 auto ToFriends = ToClass->friends();
2878 FrN = 0;
2879 for (auto Fr : ToFriends) {
2880 EXPECT_EQ(Fr, ToFriend);
2881 ++FrN;
2882 }
2883 EXPECT_EQ(FrN, 1u);
2884}
2885
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002886AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2887 InnerMatcher) {
2888 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2889 return InnerMatcher.matches(*Typedef, Finder, Builder);
2890 return false;
2891}
2892
Gabor Marton19f4f392018-06-25 13:04:37 +00002893TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002894 CodeFiles Samples{{"main.c",
2895 {"void foo();"
2896 "void moo();"
2897 "int main() { foo(); moo(); }",
2898 Lang_C}},
2899
2900 {"foo.c",
2901 {"typedef enum { THING_VALUE } thing_t;"
2902 "void conflict(thing_t type);"
2903 "void foo() { (void)THING_VALUE; }"
2904 "void conflict(thing_t type) {}",
2905 Lang_C}},
2906
2907 {"moo.c",
2908 {"typedef enum { THING_VALUE } thing_t;"
2909 "void conflict(thing_t type);"
2910 "void moo() { conflict(THING_VALUE); }",
2911 Lang_C}}};
2912
2913 auto VerificationMatcher =
2914 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2915 hasTypedefForAnonDecl(hasName("thing_t")));
2916
2917 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2918 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2919
2920 testImportSequence(
2921 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2922 // Just check that there is only one enum decl in the result AST.
2923 "main.c", enumDecl(), VerificationMatcher);
2924
2925 // For different import order, result should be the same.
2926 testImportSequence(
2927 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2928 // Check that there is only one enum decl in the result AST.
2929 "main.c", enumDecl(), VerificationMatcher);
2930}
2931
Gabor Marton48b16e12019-07-25 09:07:17 +00002932TEST_P(ImportDecl, ImportFieldOrder) {
2933 MatchVerifier<Decl> Verifier;
2934 testImport("struct declToImport {"
2935 " int b = a + 2;"
2936 " int a = 5;"
2937 "};",
2938 Lang_CXX11, "", Lang_CXX11, Verifier,
2939 recordDecl(hasFieldOrder({"b", "a"})));
2940}
2941
Peter Szecsice7f3182018-05-07 12:08:27 +00002942const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2943 dependentScopeDeclRefExpr;
2944
Gabor Marton19f4f392018-06-25 13:04:37 +00002945TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002946 MatchVerifier<Decl> Verifier;
2947 testImport("template <typename T> struct S { static T foo; };"
2948 "template <typename T> void declToImport() {"
2949 " (void) S<T>::foo;"
2950 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002951 "void instantiate() { declToImport<int>(); }"
2952 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002953 Lang_CXX11, "", Lang_CXX11, Verifier,
2954 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2955 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2956
2957 testImport("template <typename T> struct S {"
2958 "template<typename S> static void foo(){};"
2959 "};"
2960 "template <typename T> void declToImport() {"
2961 " S<T>::template foo<T>();"
2962 "}"
2963 "void instantiate() { declToImport<int>(); }",
2964 Lang_CXX11, "", Lang_CXX11, Verifier,
2965 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2966 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2967}
2968
2969const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2970 dependentNameType;
2971
Gabor Marton19f4f392018-06-25 13:04:37 +00002972TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002973 MatchVerifier<Decl> Verifier;
2974 testImport("template <typename T> struct declToImport {"
2975 " typedef typename T::type dependent_name;"
2976 "};",
2977 Lang_CXX11, "", Lang_CXX11, Verifier,
2978 classTemplateDecl(has(
2979 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2980}
2981
Gabor Marton19f4f392018-06-25 13:04:37 +00002982TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002983 MatchVerifier<Decl> Verifier;
2984 testImport("struct S { template <typename T> void mem(); };"
2985 "template <typename U> void declToImport() {"
2986 " S s;"
2987 " s.mem<U>();"
2988 "}"
2989 "void instantiate() { declToImport<int>(); }",
2990 Lang_CXX11, "", Lang_CXX11, Verifier,
2991 functionTemplateDecl(has(functionDecl(has(
2992 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2993}
2994
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002995class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
Balazs Keri1d20cc22018-07-16 12:16:39 +00002996public:
2997 static constexpr auto DefaultCode = R"(
2998 struct A { int x; };
2999 void f() {
3000 A a;
3001 A a1(a);
3002 A a2(A{});
3003 a = a1;
3004 a = A{};
3005 a.~A();
3006 })";
3007
3008 template <typename MatcherType>
3009 void testImportOf(
3010 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3011 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
3012 }
3013
3014 template <typename MatcherType>
3015 void testNoImportOf(
3016 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3017 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
3018 }
3019
3020private:
3021 template <typename MatcherType>
3022 void test(const MatcherType &MethodMatcher,
3023 const char *Code, unsigned int ExpectedCount) {
3024 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
3025
3026 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3027 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3028 ToTU, ClassMatcher);
3029
Balazs Keri2f752ba2018-07-16 14:05:18 +00003030 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003031
3032 {
3033 CXXMethodDecl *Method =
3034 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
3035 ToClass->removeDecl(Method);
Gabor Marton2afbfb62019-07-01 15:37:07 +00003036 SharedStatePtr->getLookupTable()->remove(Method);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003037 }
3038
Balazs Keri2f752ba2018-07-16 14:05:18 +00003039 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003040
3041 Decl *ImportedClass = nullptr;
3042 {
3043 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
3044 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3045 FromTU, ClassMatcher);
3046 ImportedClass = Import(FromClass, Lang_CXX11);
3047 }
3048
3049 EXPECT_EQ(ToClass, ImportedClass);
3050 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
3051 ExpectedCount);
3052 }
3053};
3054
3055TEST_P(ImportImplicitMethods, DefaultConstructor) {
3056 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
3057}
3058
3059TEST_P(ImportImplicitMethods, CopyConstructor) {
3060 testImportOf(cxxConstructorDecl(isCopyConstructor()));
3061}
3062
3063TEST_P(ImportImplicitMethods, MoveConstructor) {
3064 testImportOf(cxxConstructorDecl(isMoveConstructor()));
3065}
3066
3067TEST_P(ImportImplicitMethods, Destructor) {
3068 testImportOf(cxxDestructorDecl());
3069}
3070
3071TEST_P(ImportImplicitMethods, CopyAssignment) {
3072 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
3073}
3074
3075TEST_P(ImportImplicitMethods, MoveAssignment) {
3076 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
3077}
3078
3079TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
3080 auto Code = R"(
3081 struct A { A() { int x; } };
3082 )";
3083 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3084}
3085
3086TEST_P(ImportImplicitMethods, DoNotImportDefault) {
3087 auto Code = R"(
3088 struct A { A() = default; };
3089 )";
3090 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3091}
3092
3093TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
3094 auto Code = R"(
3095 struct A { A() = delete; };
3096 )";
3097 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3098}
3099
3100TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
3101 auto Code = R"(
3102 struct A { void f() { } };
3103 )";
3104 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
3105}
3106
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003107TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003108 Decl *ToR1;
3109 {
3110 Decl *FromTU = getTuDecl(
3111 "struct A { };", Lang_CXX, "input0.cc");
3112 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3113 FromTU, cxxRecordDecl(hasName("A")));
3114
3115 ToR1 = Import(FromR, Lang_CXX);
3116 }
3117
3118 Decl *ToR2;
3119 {
3120 Decl *FromTU = getTuDecl(
3121 "struct A { };", Lang_CXX, "input1.cc");
3122 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3123 FromTU, cxxRecordDecl(hasName("A")));
3124
3125 ToR2 = Import(FromR, Lang_CXX);
3126 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00003127
Balazs Keric7797c42018-07-11 09:37:24 +00003128 EXPECT_EQ(ToR1, ToR2);
3129}
3130
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003131TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003132 Decl *ToR1;
3133 {
3134 Decl *FromTU = getTuDecl(
3135 "struct A { int x; };", Lang_CXX, "input0.cc");
3136 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3137 FromTU, cxxRecordDecl(hasName("A")));
3138 ToR1 = Import(FromR, Lang_CXX);
3139 }
3140 Decl *ToR2;
3141 {
3142 Decl *FromTU = getTuDecl(
3143 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3144 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3145 FromTU, cxxRecordDecl(hasName("A")));
3146 ToR2 = Import(FromR, Lang_CXX);
3147 }
3148 EXPECT_NE(ToR1, ToR2);
3149}
3150
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003151TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003152 Decl *ToF1;
3153 {
3154 Decl *FromTU = getTuDecl(
3155 "struct A { int x; };", Lang_CXX, "input0.cc");
3156 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3157 FromTU, fieldDecl(hasName("x")));
3158 ToF1 = Import(FromF, Lang_CXX);
3159 }
3160 Decl *ToF2;
3161 {
3162 Decl *FromTU = getTuDecl(
3163 "struct A { int x; };", Lang_CXX, "input1.cc");
3164 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3165 FromTU, fieldDecl(hasName("x")));
3166 ToF2 = Import(FromF, Lang_CXX);
3167 }
3168 EXPECT_EQ(ToF1, ToF2);
3169}
3170
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003171TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003172 Decl *ToF1;
3173 {
3174 Decl *FromTU = getTuDecl(
3175 "struct A { int x; };", Lang_CXX, "input0.cc");
3176 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3177 FromTU, fieldDecl(hasName("x")));
3178 ToF1 = Import(FromF, Lang_CXX);
3179 }
3180 Decl *ToF2;
3181 {
3182 Decl *FromTU = getTuDecl(
3183 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3184 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3185 FromTU, fieldDecl(hasName("x")));
3186 ToF2 = Import(FromF, Lang_CXX);
3187 }
3188 EXPECT_NE(ToF1, ToF2);
3189}
3190
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003191TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003192 Decl *ToM1;
3193 {
3194 Decl *FromTU = getTuDecl(
3195 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
3196 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3197 FromTU, functionDecl(hasName("x"), isDefinition()));
3198 ToM1 = Import(FromM, Lang_CXX);
3199 }
3200 Decl *ToM2;
3201 {
3202 Decl *FromTU = getTuDecl(
3203 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
3204 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3205 FromTU, functionDecl(hasName("x"), isDefinition()));
3206 ToM2 = Import(FromM, Lang_CXX);
3207 }
3208 EXPECT_EQ(ToM1, ToM2);
3209}
3210
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003211TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003212 Decl *ToM1;
3213 {
3214 Decl *FromTU = getTuDecl(
3215 "struct A { void x(); }; void A::x() { }",
3216 Lang_CXX, "input0.cc");
3217 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3218 FromTU, functionDecl(hasName("x"), isDefinition()));
3219 ToM1 = Import(FromM, Lang_CXX);
3220 }
3221 Decl *ToM2;
3222 {
3223 Decl *FromTU = getTuDecl(
3224 "struct A { void x() const; }; void A::x() const { }",
3225 Lang_CXX, "input1.cc");
3226 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3227 FromTU, functionDecl(hasName("x"), isDefinition()));
3228 ToM2 = Import(FromM, Lang_CXX);
3229 }
3230 EXPECT_NE(ToM1, ToM2);
3231}
3232
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003233TEST_P(ASTImporterOptionSpecificTestBase,
3234 ImportUnnamedStructsWithRecursingField) {
Gabor Martonf086fa82018-07-17 12:06:36 +00003235 Decl *FromTU = getTuDecl(
3236 R"(
3237 struct A {
3238 struct {
3239 struct A *next;
3240 } entry0;
3241 struct {
3242 struct A *next;
3243 } entry1;
3244 };
3245 )",
3246 Lang_C, "input0.cc");
3247 auto *From =
3248 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3249
3250 Import(From, Lang_C);
3251
3252 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3253 auto *Entry0 =
3254 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3255 auto *Entry1 =
3256 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3257 auto *R0 = getRecordDecl(Entry0);
3258 auto *R1 = getRecordDecl(Entry1);
3259 EXPECT_NE(R0, R1);
3260 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3261 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3262 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3263 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3264}
3265
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003266TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
Balazs Keri2544b4b2018-08-08 09:40:57 +00003267 Decl *FromTU = getTuDecl(
3268 R"(
3269 void f(int X, int Y, bool Z) {
3270 (void)[X, Y, Z] { (void)Z; };
3271 }
3272 )",
3273 Lang_CXX11, "input0.cc");
3274 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3275 FromTU, functionDecl(hasName("f")));
3276 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3277 EXPECT_TRUE(ToF);
3278
3279 CXXRecordDecl *FromLambda =
3280 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3281 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3282
3283 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3284 EXPECT_TRUE(ToLambda);
3285
3286 // Check if the fields of the lambda class are imported in correct order.
3287 unsigned FromIndex = 0u;
3288 for (auto *FromField : FromLambda->fields()) {
3289 ASSERT_FALSE(FromField->getDeclName());
3290 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3291 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00003292 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3293 EXPECT_TRUE(ToIndex);
3294 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00003295 ++FromIndex;
3296 }
3297
3298 EXPECT_EQ(FromIndex, 3u);
3299}
3300
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003301TEST_P(ASTImporterOptionSpecificTestBase,
3302 MergeFieldDeclsOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003303 std::string ClassTemplate =
3304 R"(
3305 template <typename T>
3306 struct X {
3307 int a{0}; // FieldDecl with InitListExpr
3308 X(char) : a(3) {} // (1)
3309 X(int) {} // (2)
3310 };
3311 )";
3312 Decl *ToTU = getToTuDecl(ClassTemplate +
3313 R"(
3314 void foo() {
3315 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3316 X<char> xc('c');
3317 }
3318 )", Lang_CXX11);
3319 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3320 ToTU, classTemplateSpecializationDecl(hasName("X")));
3321 // FieldDecl without InitlistExpr:
3322 auto *ToField = *ToSpec->field_begin();
3323 ASSERT_TRUE(ToField);
3324 ASSERT_FALSE(ToField->getInClassInitializer());
3325 Decl *FromTU = getTuDecl(ClassTemplate +
3326 R"(
3327 void bar() {
3328 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3329 X<char> xc(1);
3330 }
3331 )", Lang_CXX11);
3332 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3333 FromTU, classTemplateSpecializationDecl(hasName("X")));
3334 // FieldDecl with InitlistExpr:
3335 auto *FromField = *FromSpec->field_begin();
3336 ASSERT_TRUE(FromField);
3337 ASSERT_TRUE(FromField->getInClassInitializer());
3338
3339 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3340 ASSERT_TRUE(ImportedSpec);
3341 EXPECT_EQ(ImportedSpec, ToSpec);
3342 // After the import, the FieldDecl has to be merged, thus it should have the
3343 // InitListExpr.
3344 EXPECT_TRUE(ToField->getInClassInitializer());
3345}
3346
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003347TEST_P(ASTImporterOptionSpecificTestBase,
3348 MergeFunctionOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003349 std::string ClassTemplate =
3350 R"(
3351 template <typename T>
3352 struct X {
3353 void f() {}
3354 void g() {}
3355 };
3356 )";
3357 Decl *ToTU = getToTuDecl(ClassTemplate +
3358 R"(
3359 void foo() {
3360 X<char> x;
3361 x.f();
3362 }
3363 )", Lang_CXX11);
3364 Decl *FromTU = getTuDecl(ClassTemplate +
3365 R"(
3366 void bar() {
3367 X<char> x;
3368 x.g();
3369 }
3370 )", Lang_CXX11);
3371 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3372 FromTU, classTemplateSpecializationDecl(hasName("X")));
3373 auto FunPattern = functionDecl(hasName("g"),
3374 hasParent(classTemplateSpecializationDecl()));
3375 auto *FromFun =
3376 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3377 auto *ToFun =
3378 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3379 ASSERT_TRUE(FromFun->hasBody());
3380 ASSERT_FALSE(ToFun->hasBody());
3381 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3382 ASSERT_TRUE(ImportedSpec);
3383 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3384 ToTU, classTemplateSpecializationDecl(hasName("X")));
3385 EXPECT_EQ(ImportedSpec, ToSpec);
3386 EXPECT_TRUE(ToFun->hasBody());
3387}
3388
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003389TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003390 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3391 std::string ClassTemplate =
3392 R"(
3393 template <typename T>
3394 struct X {};
3395 )";
3396 Decl *ToTU = getToTuDecl(ClassTemplate +
3397 R"(
3398 template <>
3399 struct X<char> {
3400 int a;
3401 };
3402 void foo() {
3403 X<char> x;
3404 }
3405 )",
3406 Lang_CXX11);
3407 Decl *FromTU = getTuDecl(ClassTemplate +
3408 R"(
3409 template <>
3410 struct X<char> {
3411 int b;
3412 };
3413 void foo() {
3414 X<char> x;
3415 }
3416 )",
3417 Lang_CXX11);
3418 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3419 FromTU, classTemplateSpecializationDecl(hasName("X")));
3420 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3421
3422 // We expect one (ODR) warning during the import.
3423 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3424
3425 // The second specialization is different from the first, thus it violates
3426 // ODR, consequently we expect to keep the first specialization only, which is
3427 // already in the "To" context.
Gabor Marton7f8c4002019-03-19 13:34:10 +00003428 EXPECT_FALSE(ImportedSpec);
3429 EXPECT_EQ(1u,
3430 DeclCounter<ClassTemplateSpecializationDecl>().match(
3431 ToTU, classTemplateSpecializationDecl(hasName("X"))));
Gabor Marton42e15de2018-08-22 11:52:14 +00003432}
3433
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003434TEST_P(ASTImporterOptionSpecificTestBase,
3435 MergeCtorOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003436 std::string ClassTemplate =
3437 R"(
3438 template <typename T>
3439 struct X {
3440 X(char) {}
3441 X(int) {}
3442 };
3443 )";
3444 Decl *ToTU = getToTuDecl(ClassTemplate +
3445 R"(
3446 void foo() {
3447 X<char> x('c');
3448 }
3449 )", Lang_CXX11);
3450 Decl *FromTU = getTuDecl(ClassTemplate +
3451 R"(
3452 void bar() {
3453 X<char> x(1);
3454 }
3455 )", Lang_CXX11);
3456 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3457 FromTU, classTemplateSpecializationDecl(hasName("X")));
3458 // Match the void(int) ctor.
3459 auto CtorPattern =
3460 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3461 hasParent(classTemplateSpecializationDecl()));
3462 auto *FromCtor =
3463 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3464 auto *ToCtor =
3465 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3466 ASSERT_TRUE(FromCtor->hasBody());
3467 ASSERT_FALSE(ToCtor->hasBody());
3468 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3469 ASSERT_TRUE(ImportedSpec);
3470 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3471 ToTU, classTemplateSpecializationDecl(hasName("X")));
3472 EXPECT_EQ(ImportedSpec, ToSpec);
3473 EXPECT_TRUE(ToCtor->hasBody());
3474}
3475
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003476TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003477 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3478 auto Code =
3479 R"(
3480 // primary template
3481 template<class T1, class T2, int I>
3482 class A {};
3483
3484 // partial specialization
3485 template<class T, int I>
3486 class A<T, T*, I> {};
3487 )";
3488 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3489 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3490 auto *FromSpec =
3491 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3492 FromTU, classTemplatePartialSpecializationDecl());
3493 auto *ToSpec =
3494 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3495 ToTU, classTemplatePartialSpecializationDecl());
3496
3497 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3498 EXPECT_EQ(ImportedSpec, ToSpec);
3499 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3500 ToTU, classTemplatePartialSpecializationDecl()));
3501}
3502
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003503TEST_P(ASTImporterOptionSpecificTestBase,
3504 ClassTemplateSpecializationsShouldNotBeDuplicated) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003505 auto Code =
3506 R"(
3507 // primary template
3508 template<class T1, class T2, int I>
3509 class A {};
3510
3511 // full specialization
3512 template<>
3513 class A<int, int, 1> {};
3514 )";
3515 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3516 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3517 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3518 FromTU, classTemplateSpecializationDecl());
3519 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3520 ToTU, classTemplateSpecializationDecl());
3521
3522 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3523 EXPECT_EQ(ImportedSpec, ToSpec);
3524 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3525 ToTU, classTemplateSpecializationDecl()));
3526}
3527
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003528TEST_P(ASTImporterOptionSpecificTestBase,
3529 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003530 std::string PrimaryTemplate =
3531 R"(
3532 template<class T1, class T2, int I>
3533 class A {};
3534 )";
3535 auto PartialSpec =
3536 R"(
3537 template<class T, int I>
3538 class A<T, T*, I> {};
3539 )";
3540 auto FullSpec =
3541 R"(
3542 template<>
3543 class A<int, int, 1> {};
3544 )";
3545 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3546 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3547 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3548 FromTU, classTemplateSpecializationDecl());
3549
3550 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3551 EXPECT_TRUE(ImportedSpec);
3552 // Check the number of partial specializations.
3553 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3554 ToTU, classTemplatePartialSpecializationDecl()));
3555 // Check the number of full specializations.
3556 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3557 ToTU, classTemplateSpecializationDecl(
3558 unless(classTemplatePartialSpecializationDecl()))));
3559}
3560
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003561TEST_P(ASTImporterOptionSpecificTestBase,
3562 InitListExprValueKindShouldBeImported) {
Gabor Martona20ce602018-09-03 13:10:53 +00003563 Decl *TU = getTuDecl(
3564 R"(
3565 const int &init();
3566 void foo() { const int &a{init()}; }
3567 )", Lang_CXX11, "input0.cc");
3568 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3569 ASSERT_TRUE(FromD->getAnyInitializer());
3570 auto *InitExpr = FromD->getAnyInitializer();
3571 ASSERT_TRUE(InitExpr);
3572 ASSERT_TRUE(InitExpr->isGLValue());
3573
3574 auto *ToD = Import(FromD, Lang_CXX11);
3575 EXPECT_TRUE(ToD);
3576 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3577 EXPECT_TRUE(ToInitExpr);
3578 EXPECT_TRUE(ToInitExpr->isGLValue());
3579}
3580
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003581struct ImportVariables : ASTImporterOptionSpecificTestBase {};
Gabor Martonac3a5d62018-09-17 12:04:52 +00003582
3583TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3584 Decl *FromTU = getTuDecl(
3585 R"(
3586 struct A {
3587 static const int a = 1 + 2;
3588 };
3589 const int A::a;
3590 )", Lang_CXX, "input1.cc");
3591
3592 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3593 FromTU, varDecl(hasName("a"))); // Decl with init
3594 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3595 FromTU, varDecl(hasName("a"))); // Decl with definition
3596 ASSERT_NE(FromDWithInit, FromDWithDef);
3597 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3598
3599 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3600 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3601 ASSERT_TRUE(ToD0);
3602 ASSERT_TRUE(ToD1);
3603 EXPECT_NE(ToD0, ToD1);
3604 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3605}
3606
3607TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3608 auto StructA =
3609 R"(
3610 struct A {
3611 static const int a = 1 + 2;
3612 };
3613 )";
3614 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3615 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3616 "input1.cc");
3617
3618 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3619 FromTU, varDecl(hasName("a"))); // Decl with init
3620 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3621 FromTU, varDecl(hasName("a"))); // Decl with definition
3622 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3623 ASSERT_TRUE(FromDWithInit->getInit());
3624 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3625 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3626 ASSERT_FALSE(FromDWithDef->getInit());
3627
3628 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3629 ToTU, varDecl(hasName("a"))); // Decl with init
3630 ASSERT_TRUE(ToD->getInit());
3631 ASSERT_FALSE(ToD->getDefinition());
3632
3633 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3634 EXPECT_TRUE(ImportedD->getAnyInitializer());
3635 EXPECT_TRUE(ImportedD->getDefinition());
3636}
3637
3638TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3639 auto StructA =
3640 R"(
3641 struct A {
3642 static const int a;
3643 };
3644 )";
3645 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3646 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3647 Lang_CXX, "input1.cc");
3648
3649 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3650 FromTU, varDecl(hasName("a")));
3651 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3652 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3653 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3654 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3655 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3656 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3657 ASSERT_TRUE(FromDWithDef->getInit());
3658
3659 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3660 ToTU, varDecl(hasName("a")));
3661 ASSERT_FALSE(ToD->getInit());
3662 ASSERT_FALSE(ToD->getDefinition());
3663
3664 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3665 EXPECT_TRUE(ImportedD->getAnyInitializer());
3666 EXPECT_TRUE(ImportedD->getDefinition());
3667}
3668
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003669struct ImportClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003670
Gabor Marton54058b52018-12-17 13:53:12 +00003671TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3672 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
3673 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3674 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3675 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3676 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3677
3678 Decl *ImportedDef = Import(FromDef, Lang_C);
3679
3680 EXPECT_NE(ImportedDef, ToProto);
3681 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3682 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3683 EXPECT_TRUE(ImportedDef == ToDef);
3684 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3685 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3686 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3687}
3688
3689TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3690 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
3691 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
3692 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3693 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3694 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3695
3696 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3697
3698 EXPECT_NE(ImportedDef, ToProto);
3699 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3700 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3701 EXPECT_TRUE(ImportedDef == ToDef);
3702 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3703 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3704 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3705}
3706
3707TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3708 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
3709 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3710 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3711 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3712 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3713
3714 Decl *ImportedProto = Import(FromProto, Lang_C);
3715 Decl *ImportedDef = Import(FromDef, Lang_C);
3716 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3717
3718 EXPECT_NE(ImportedDef, ImportedProto);
3719 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3720 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3721 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3722 EXPECT_TRUE(ImportedDef == ToDef);
3723 EXPECT_TRUE(ImportedProto == ToProto);
3724 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3725 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3726 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3727}
3728
Gabor Marton7df342a2018-12-17 12:42:12 +00003729
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003730struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003731
3732TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
3733 Decl *FromTU = getTuDecl(
3734 R"(
3735 class A {
3736 template <int I> class F {};
3737 class X {
3738 template <int I> friend class F;
3739 };
3740 };
3741 )",
3742 Lang_CXX, "input0.cc");
3743
3744 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3745 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
3746 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
3747 FromTU, cxxRecordDecl(hasName("F")));
3748
3749 ASSERT_TRUE(FromClass);
3750 ASSERT_TRUE(FromFriendClass);
3751 ASSERT_NE(FromClass, FromFriendClass);
3752 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
3753 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
3754 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3755 FromClass->getDescribedClassTemplate());
3756
3757 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
3758 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
3759
3760 EXPECT_TRUE(ToClass);
3761 EXPECT_TRUE(ToFriendClass);
3762 EXPECT_NE(ToClass, ToFriendClass);
3763 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
3764 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
3765 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3766 ToClass->getDescribedClassTemplate());
3767}
3768
3769TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
3770 Decl *FromTu = getTuDecl(
3771 R"(
3772 class declToImport {
3773 friend class declToImport;
3774 };
3775 )",
3776 Lang_CXX, "input.cc");
3777
3778 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
3779 FromTu, cxxRecordDecl(hasName("declToImport")));
3780 auto *ToD = Import(FromD, Lang_CXX);
3781 auto Pattern = cxxRecordDecl(has(friendDecl()));
3782 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3783 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3784}
3785
Gabor Martonbc5b7e22019-12-04 17:12:08 +01003786TEST_P(ImportFriendClasses, UndeclaredFriendClassShouldNotBeVisible) {
3787 Decl *FromTu = getTuDecl("class X { friend class Y; };", Lang_CXX, "from.cc");
3788 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
3789 FromTu, cxxRecordDecl(hasName("X")));
3790 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTu, friendDecl());
3791 RecordDecl *FromRecordOfFriend =
3792 const_cast<RecordDecl *>(getRecordDeclOfFriend(FromFriend));
3793
3794 ASSERT_EQ(FromRecordOfFriend->getDeclContext(), cast<DeclContext>(FromTu));
3795 ASSERT_EQ(FromRecordOfFriend->getLexicalDeclContext(),
3796 cast<DeclContext>(FromX));
3797 ASSERT_FALSE(
3798 FromRecordOfFriend->getDeclContext()->containsDecl(FromRecordOfFriend));
3799 ASSERT_FALSE(FromRecordOfFriend->getLexicalDeclContext()->containsDecl(
3800 FromRecordOfFriend));
3801 ASSERT_FALSE(FromRecordOfFriend->getLookupParent()
3802 ->lookup(FromRecordOfFriend->getDeclName())
3803 .empty());
3804
3805 auto *ToX = Import(FromX, Lang_CXX);
3806 ASSERT_TRUE(ToX);
3807
3808 Decl *ToTu = ToX->getTranslationUnitDecl();
3809 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTu, friendDecl());
3810 RecordDecl *ToRecordOfFriend =
3811 const_cast<RecordDecl *>(getRecordDeclOfFriend(ToFriend));
3812
3813 ASSERT_EQ(ToRecordOfFriend->getDeclContext(), cast<DeclContext>(ToTu));
3814 ASSERT_EQ(ToRecordOfFriend->getLexicalDeclContext(), cast<DeclContext>(ToX));
3815 EXPECT_FALSE(
3816 ToRecordOfFriend->getDeclContext()->containsDecl(ToRecordOfFriend));
3817 EXPECT_FALSE(ToRecordOfFriend->getLexicalDeclContext()->containsDecl(
3818 ToRecordOfFriend));
3819 EXPECT_FALSE(ToRecordOfFriend->getLookupParent()
3820 ->lookup(ToRecordOfFriend->getDeclName())
3821 .empty());
3822}
3823
Gabor Marton7df342a2018-12-17 12:42:12 +00003824TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
3825 Decl *FromTu = getTuDecl(
3826 R"(
3827 template<class A> class declToImport {
3828 template<class A1> friend class declToImport;
3829 };
3830 )",
3831 Lang_CXX, "input.cc");
3832
3833 auto *FromD =
3834 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
3835 auto *ToD = Import(FromD, Lang_CXX);
3836
3837 auto Pattern = classTemplateDecl(
3838 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
3839 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3840 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3841
3842 auto *Class =
3843 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
3844 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
3845 EXPECT_NE(Friend->getFriendDecl(), Class);
3846 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
3847}
3848
3849TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
3850 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
3851
3852 ClassTemplateSpecializationDecl *Imported1;
3853 {
3854 Decl *FromTU = getTuDecl("template<class T> class X;"
3855 "struct Y { friend class X<int>; };",
3856 Lang_CXX, "input0.cc");
3857 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3858 FromTU, Pattern);
3859
3860 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3861 }
3862 ClassTemplateSpecializationDecl *Imported2;
3863 {
3864 Decl *FromTU = getTuDecl("template<class T> class X;"
3865 "template<> class X<int>{};"
3866 "struct Z { friend class X<int>; };",
3867 Lang_CXX, "input1.cc");
3868 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3869 FromTU, Pattern);
3870
3871 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3872 }
3873
3874 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3875 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
3876 2u);
3877 ASSERT_TRUE(Imported2->getPreviousDecl());
3878 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
3879}
3880
3881TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
3882 Decl *FromTU0 = getTuDecl(
3883 R"(
3884 class X {
3885 class Y;
3886 };
3887 class X::Y {
3888 template <typename T>
3889 friend class F; // The decl context of F is the global namespace.
3890 };
3891 )",
3892 Lang_CXX, "input0.cc");
3893 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3894 FromTU0, classTemplateDecl(hasName("F")));
3895 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3896 Decl *FromTU1 = getTuDecl(
3897 R"(
3898 template <typename T>
3899 class F {};
3900 )",
3901 Lang_CXX, "input1.cc");
3902 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3903 FromTU1, classTemplateDecl(hasName("F")));
3904 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3905 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
3906 Imported1->getTemplatedDecl()->getTypeForDecl());
3907}
3908
3909TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
3910 Decl *From, *To;
3911 std::tie(From, To) =
3912 getImportedDecl("class declToImport {};", Lang_CXX,
3913 "class Y { friend class declToImport; };", Lang_CXX);
3914 auto *Imported = cast<CXXRecordDecl>(To);
3915
3916 EXPECT_TRUE(Imported->getPreviousDecl());
3917}
3918
3919TEST_P(ImportFriendClasses,
3920 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
3921 Decl *ToTU = getToTuDecl(
3922 R"(
3923 class X {
3924 class Y;
3925 };
3926 class X::Y {
3927 template <typename T>
3928 friend class F; // The decl context of F is the global namespace.
3929 };
3930 )",
3931 Lang_CXX);
3932 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
3933 ToTU, classTemplateDecl(hasName("F")));
3934 Decl *FromTU = getTuDecl(
3935 R"(
3936 template <typename T>
3937 class F {};
3938 )",
3939 Lang_CXX, "input0.cc");
3940 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3941 FromTU, classTemplateDecl(hasName("F")));
3942 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3943 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3944 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
3945 EXPECT_EQ(ToDecl->getTemplatedDecl(),
3946 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3947}
3948
3949TEST_P(ImportFriendClasses,
3950 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
3951 Decl *FromTU0 = getTuDecl(
3952 R"(
3953 class X {
3954 class Y;
3955 };
3956 class X::Y {
3957 template <typename T>
3958 friend class F; // The decl context of F is the global namespace.
3959 };
3960 )",
3961 Lang_CXX, "input0.cc");
3962 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3963 FromTU0, classTemplateDecl(hasName("F")));
3964 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3965 Decl *FromTU1 = getTuDecl(
3966 R"(
3967 template <typename T>
3968 class F {};
3969 )",
3970 Lang_CXX, "input1.cc");
3971 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3972 FromTU1, classTemplateDecl(hasName("F")));
3973 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3974 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3975 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3976 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
3977 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3978}
3979
3980TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
3981 Decl *FromTU0 = getTuDecl(
3982 R"(
3983 class X {
3984 class Y;
3985 };
3986 class X::Y {
3987 friend class F; // The decl context of F is the global namespace.
3988 };
3989 )",
3990 Lang_CXX, "input0.cc");
3991 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
3992 QualType FT = Friend->getFriendType()->getType();
3993 FT = FromTU0->getASTContext().getCanonicalType(FT);
3994 auto *Fwd = cast<TagType>(FT)->getDecl();
3995 auto *ImportedFwd = Import(Fwd, Lang_CXX);
3996 Decl *FromTU1 = getTuDecl(
3997 R"(
3998 class F {};
3999 )",
4000 Lang_CXX, "input1.cc");
4001 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
4002 FromTU1, cxxRecordDecl(hasName("F")));
4003 auto *ImportedDef = Import(Definition, Lang_CXX);
4004 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4005 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4006}
4007
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004008TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Gabor Marton54058b52018-12-17 13:53:12 +00004009 auto *Code = R"(
4010 template <class T>
4011 struct X {
4012 friend void foo(){}
4013 };
4014 )";
4015 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4016 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
4017 ToTU, functionDecl(hasName("foo")));
4018
4019 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
4020 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4021 FromTU, functionDecl(hasName("foo")));
4022 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
4023 EXPECT_EQ(ImportedFoo, ToFoo);
4024}
4025
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004026struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton61d862a2018-05-18 09:08:47 +00004027
4028TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
4029 Decl *TU = getTuDecl(
4030 R"(
4031 namespace NS {
4032
4033 template <typename T>
4034 struct S {};
4035 template struct S<int>;
4036
4037 inline namespace INS {
4038 template <typename T>
4039 struct S {};
4040 template struct S<int>;
4041 }
4042
4043 }
4044 )", Lang_CXX11, "input0.cc");
4045 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4046 TU, namespaceDecl());
4047 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4048 TU, classTemplateSpecializationDecl());
4049 ASSERT_TRUE(NS->containsDecl(Spec));
4050
4051 NS->removeDecl(Spec);
4052 EXPECT_FALSE(NS->containsDecl(Spec));
4053}
4054
Gabor Marton7df342a2018-12-17 12:42:12 +00004055TEST_P(DeclContextTest,
4056 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4057 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
4058 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4059 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4060
4061 // Investigate the list.
4062 auto *DC = A0->getDeclContext();
4063 ASSERT_TRUE(DC->containsDecl(A0));
4064 ASSERT_TRUE(DC->containsDecl(A1));
4065
4066 // Investigate the lookup table.
4067 auto *Map = DC->getLookupPtr();
4068 ASSERT_TRUE(Map);
4069 auto I = Map->find(A0->getDeclName());
4070 ASSERT_NE(I, Map->end());
4071 StoredDeclsList &L = I->second;
4072 // The lookup table contains the most recent decl of A.
4073 ASSERT_NE(L.getAsDecl(), A0);
4074 ASSERT_EQ(L.getAsDecl(), A1);
4075
4076 ASSERT_TRUE(L.getAsDecl());
4077 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4078 // The point here is to have a Vec with only one element, which is not the
4079 // one we are going to delete from the DC later.
4080 L.setHasExternalDecls();
4081 ASSERT_TRUE(L.getAsVector());
4082 ASSERT_EQ(1u, L.getAsVector()->size());
4083
4084 // This asserts in the old implementation.
4085 DC->removeDecl(A0);
4086 EXPECT_FALSE(DC->containsDecl(A0));
4087}
4088
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004089struct ImportFunctionTemplateSpecializations
4090 : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +00004091
4092TEST_P(ImportFunctionTemplateSpecializations,
4093 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4094
4095 Decl *FromTU = getTuDecl(
4096 R"(
4097 template<class T>
4098 int f() { return 0; }
4099 void foo() { f<int>(); }
4100 )",
4101 Lang_CXX, "input0.cc");
4102
4103 // Check that the function template instantiation is NOT the child of the TU.
4104 auto Pattern = translationUnitDecl(
4105 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
4106 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4107
4108 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4109 FromTU, functionDecl(hasName("foo")));
4110 ASSERT_TRUE(Import(Foo, Lang_CXX));
4111
4112 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4113 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4114}
4115
4116TEST_P(ImportFunctionTemplateSpecializations,
4117 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4118
4119 Decl *FromTU = getTuDecl(
4120 R"(
4121 template<class T>
4122 int f() { return 0; }
4123 template int f<int>();
4124 )",
4125 Lang_CXX, "input0.cc");
4126
4127 // Check that the function template instantiation is NOT the child of the TU.
4128 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4129 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4130 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4131
4132 ASSERT_TRUE(
4133 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
4134
4135 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4136 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4137}
4138
4139TEST_P(ImportFunctionTemplateSpecializations,
4140 TUshouldContainFunctionTemplateSpecialization) {
4141
4142 Decl *FromTU = getTuDecl(
4143 R"(
4144 template<class T>
4145 int f() { return 0; }
4146 template <> int f<int>() { return 4; }
4147 )",
4148 Lang_CXX, "input0.cc");
4149
4150 // Check that the function template specialization is the child of the TU.
4151 auto Specialization =
4152 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4153 auto Pattern = translationUnitDecl(has(Specialization));
4154 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4155
4156 ASSERT_TRUE(
4157 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
4158
4159 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4160 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4161}
4162
4163TEST_P(ImportFunctionTemplateSpecializations,
4164 FunctionTemplateSpecializationRedeclChain) {
4165
4166 Decl *FromTU = getTuDecl(
4167 R"(
4168 template<class T>
4169 int f() { return 0; }
4170 template <> int f<int>() { return 4; }
4171 )",
4172 Lang_CXX, "input0.cc");
4173
4174 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4175 hasParent(translationUnitDecl()));
4176 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4177 {
4178 auto *TU = FromTU;
4179 auto *SpecD = FromSpecD;
4180 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4181 TU, functionTemplateDecl());
4182 auto *FirstSpecD = *(TemplateD->spec_begin());
4183 ASSERT_EQ(SpecD, FirstSpecD);
4184 ASSERT_TRUE(SpecD->getPreviousDecl());
4185 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4186 ->doesThisDeclarationHaveABody());
4187 }
4188
4189 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
4190
4191 {
4192 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4193 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4194 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4195 TU, functionTemplateDecl());
4196 auto *FirstSpecD = *(TemplateD->spec_begin());
4197 EXPECT_EQ(SpecD, FirstSpecD);
4198 ASSERT_TRUE(SpecD->getPreviousDecl());
4199 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4200 ->doesThisDeclarationHaveABody());
4201 }
4202}
4203
4204TEST_P(ImportFunctionTemplateSpecializations,
4205 MatchNumberOfFunctionTemplateSpecializations) {
4206
4207 Decl *FromTU = getTuDecl(
4208 R"(
4209 template <typename T> constexpr int f() { return 0; }
4210 template <> constexpr int f<int>() { return 4; }
4211 void foo() {
4212 static_assert(f<char>() == 0, "");
4213 static_assert(f<int>() == 4, "");
4214 }
4215 )",
4216 Lang_CXX11, "input0.cc");
4217 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4218 FromTU, functionDecl(hasName("foo")));
4219
4220 Import(FromD, Lang_CXX11);
4221 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4222 EXPECT_EQ(
4223 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4224 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4225}
4226
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004227TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton17d39672018-11-26 15:54:08 +00004228 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4229 {
4230 Decl *FromTU = getTuDecl(
4231 R"(
4232 template <typename T>
4233 struct B;
4234 )",
4235 Lang_CXX, "input0.cc");
4236 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4237 FromTU, classTemplateDecl(hasName("B")));
4238
4239 Import(FromD, Lang_CXX);
4240 }
4241
4242 {
4243 Decl *FromTU = getTuDecl(
4244 R"(
4245 template <typename T>
4246 struct B {
4247 void f();
4248 B* b;
4249 };
4250 )",
4251 Lang_CXX, "input1.cc");
4252 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4253 FromTU, functionDecl(hasName("f")));
4254 Import(FromD, Lang_CXX);
4255 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4256 FromTU, classTemplateDecl(hasName("B")));
4257 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
4258 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4259
4260 // We expect no (ODR) warning during the import.
4261 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4262 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4263 }
4264}
4265
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004266TEST_P(ASTImporterOptionSpecificTestBase,
4267 ImportingTypedefShouldImportTheCompleteType) {
Gabor Martonb93baf62018-11-27 09:51:36 +00004268 // We already have an incomplete underlying type in the "To" context.
4269 auto Code =
4270 R"(
4271 template <typename T>
4272 struct S {
4273 void foo();
4274 };
4275 using U = S<int>;
4276 )";
4277 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4278 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4279 typedefNameDecl(hasName("U")));
4280 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4281
4282 // The "From" context has the same typedef, but the underlying type is
4283 // complete this time.
4284 Decl *FromTU = getTuDecl(std::string(Code) +
4285 R"(
4286 void foo(U* u) {
4287 u->foo();
4288 }
4289 )", Lang_CXX11);
4290 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4291 typedefNameDecl(hasName("U")));
4292 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4293
4294 // The imported type should be complete.
4295 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4296 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4297}
4298
Balazs Keri1efc9742019-05-07 10:55:11 +00004299TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) {
4300 auto Code =
4301 R"(
4302 template<class T>
4303 int f() { return 0; }
4304 template <> int f<int>() { return 4; }
4305 )";
4306
4307 Decl *FromTU = getTuDecl(Code, Lang_CXX);
4308 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU,
4309 functionDecl(hasName("f"), isExplicitTemplateSpecialization()));
Balazs Kerib7d8cff2019-05-07 14:53:04 +00004310 ASSERT_EQ(FromD->getNumTemplateParameterLists(), 1u);
Balazs Keri1efc9742019-05-07 10:55:11 +00004311
4312 auto *ToD = Import(FromD, Lang_CXX);
4313 // The template parameter list should exist.
Balazs Kerib7d8cff2019-05-07 14:53:04 +00004314 EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u);
Balazs Keri1efc9742019-05-07 10:55:11 +00004315}
4316
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004317struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton54058b52018-12-17 13:53:12 +00004318
4319TEST_P(ASTImporterLookupTableTest, OneDecl) {
4320 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
4321 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4322 ASTImporterLookupTable LT(*ToTU);
4323 auto Res = LT.lookup(ToTU, D->getDeclName());
4324 ASSERT_EQ(Res.size(), 1u);
4325 EXPECT_EQ(*Res.begin(), D);
4326}
4327
4328static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4329 for (Decl *D : DC->decls()) {
4330 if (auto *ND = dyn_cast<NamedDecl>(D))
4331 if (ND->getDeclName() == Name)
4332 return ND;
4333 }
4334 return nullptr;
Martin Storsjo85833392018-12-18 08:36:16 +00004335}
Gabor Marton54058b52018-12-17 13:53:12 +00004336
4337TEST_P(ASTImporterLookupTableTest,
4338 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4339 auto *Code = R"(
4340 template <class T>
4341 struct X {
4342 friend void foo(){}
4343 };
4344 )";
4345 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4346 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
4347 ToTU, classTemplateDecl(hasName("X")));
4348 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4349 ToTU, functionDecl(hasName("foo")));
4350 DeclContext *FooDC = Foo->getDeclContext();
4351 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4352 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
4353 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4354 DeclarationName FooName = Foo->getDeclName();
4355
4356 // Cannot find in the LookupTable of its DC (TUDecl)
4357 SmallVector<NamedDecl *, 2> FoundDecls;
4358 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4359 EXPECT_EQ(FoundDecls.size(), 0u);
4360
4361 // Cannot find in the LookupTable of its LexicalDC (X)
4362 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4363 EXPECT_EQ(FoundDecls.size(), 0u);
4364
4365 // Can't find in the list of Decls of the DC.
4366 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4367
4368 // Can't find in the list of Decls of the LexicalDC
4369 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
4370
4371 // ASTImporter specific lookup finds it.
4372 ASTImporterLookupTable LT(*ToTU);
4373 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4374 ASSERT_EQ(Res.size(), 1u);
4375 EXPECT_EQ(*Res.begin(), Foo);
4376}
4377
4378TEST_P(ASTImporterLookupTableTest,
4379 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
4380 TranslationUnitDecl *ToTU =
4381 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
4382 auto *Foo =
4383 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
4384 auto *A =
4385 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4386 DeclContext *FooDC = Foo->getDeclContext();
4387 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4388 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
4389 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4390 DeclarationName FooName = Foo->getDeclName();
4391
4392 // Cannot find in the LookupTable of its DC (TUDecl).
4393 SmallVector<NamedDecl *, 2> FoundDecls;
4394 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4395 EXPECT_EQ(FoundDecls.size(), 0u);
4396
4397 // Cannot find in the LookupTable of its LexicalDC (A).
4398 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4399 EXPECT_EQ(FoundDecls.size(), 0u);
4400
4401 // Can't find in the list of Decls of the DC.
4402 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4403
4404 // Can find in the list of Decls of the LexicalDC.
4405 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
4406
4407 // ASTImporter specific lookup finds it.
4408 ASTImporterLookupTable LT(*ToTU);
4409 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4410 ASSERT_EQ(Res.size(), 1u);
4411 EXPECT_EQ(*Res.begin(), Foo);
4412}
4413
4414TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
4415 TranslationUnitDecl *ToTU =
4416 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
4417 DeclarationName VName = FirstDeclMatcher<VarDecl>()
4418 .match(ToTU, varDecl(hasName("V")))
4419 ->getDeclName();
4420 auto *A =
4421 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4422 auto *B =
4423 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
4424
4425 ASTImporterLookupTable LT(*ToTU);
4426
4427 auto Res = LT.lookup(cast<DeclContext>(A), VName);
4428 ASSERT_EQ(Res.size(), 1u);
4429 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4430 ToTU, fieldDecl(hasName("V"),
4431 hasParent(recordDecl(hasName("A"))))));
4432 Res = LT.lookup(cast<DeclContext>(B), VName);
4433 ASSERT_EQ(Res.size(), 1u);
4434 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4435 ToTU, fieldDecl(hasName("V"),
4436 hasParent(recordDecl(hasName("B"))))));
4437 Res = LT.lookup(ToTU, VName);
4438 ASSERT_EQ(Res.size(), 1u);
4439 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
4440 ToTU, varDecl(hasName("V"),
4441 hasParent(translationUnitDecl()))));
4442}
4443
4444TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
4445 TranslationUnitDecl *ToTU = getToTuDecl(
4446 R"(
4447 void foo();
4448 void foo(int);
4449 void foo(int, int);
4450 )",
4451 Lang_CXX);
4452
4453 ASTImporterLookupTable LT(*ToTU);
4454 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4455 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4456 DeclarationName Name = F0->getDeclName();
4457 auto Res = LT.lookup(ToTU, Name);
4458 EXPECT_EQ(Res.size(), 3u);
4459 EXPECT_EQ(Res.count(F0), 1u);
4460 EXPECT_EQ(Res.count(F2), 1u);
4461}
4462
Gabor Martona9cab312019-02-08 09:19:34 +00004463TEST_P(ASTImporterLookupTableTest,
4464 DifferentOperatorsShouldHaveDifferentResultSet) {
4465 TranslationUnitDecl *ToTU = getToTuDecl(
4466 R"(
4467 struct X{};
4468 void operator+(X, X);
4469 void operator-(X, X);
4470 )",
4471 Lang_CXX);
4472
4473 ASTImporterLookupTable LT(*ToTU);
4474 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
4475 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4476 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
4477 ToTU, functionDecl(hasOverloadedOperatorName("-")));
4478 DeclarationName NamePlus = FPlus->getDeclName();
4479 auto ResPlus = LT.lookup(ToTU, NamePlus);
4480 EXPECT_EQ(ResPlus.size(), 1u);
4481 EXPECT_EQ(ResPlus.count(FPlus), 1u);
4482 EXPECT_EQ(ResPlus.count(FMinus), 0u);
4483 DeclarationName NameMinus = FMinus->getDeclName();
4484 auto ResMinus = LT.lookup(ToTU, NameMinus);
4485 EXPECT_EQ(ResMinus.size(), 1u);
4486 EXPECT_EQ(ResMinus.count(FMinus), 1u);
4487 EXPECT_EQ(ResMinus.count(FPlus), 0u);
4488 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
4489}
4490
4491TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
4492 TranslationUnitDecl *ToTU = getToTuDecl(
4493 R"(
4494 struct X {};
4495 void operator+(X, X);
4496 )",
4497 Lang_CXX);
4498 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
4499 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4500
4501 Decl *FromTU = getTuDecl(
4502 R"(
4503 struct X {};
4504 void operator+(X, X);
4505 )",
4506 Lang_CXX);
4507 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
4508 FromTU, functionDecl(hasOverloadedOperatorName("+")));
4509
4510 // FromPlus have a different TU, thus its DeclarationName is different too.
4511 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
4512
4513 ASTImporterLookupTable LT(*ToTU);
4514 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
4515 ASSERT_EQ(Res.size(), 1u);
4516 EXPECT_EQ(*Res.begin(), ToPlus);
4517
4518 // FromPlus have a different TU, thus its DeclarationName is different too.
4519 Res = LT.lookup(ToTU, FromPlus->getDeclName());
4520 ASSERT_EQ(Res.size(), 0u);
4521}
4522
Gabor Martondd2b76e2019-06-11 13:35:25 +00004523TEST_P(ASTImporterLookupTableTest,
4524 LookupFindsFwdFriendClassDeclWithElaboratedType) {
Gabor Marton54058b52018-12-17 13:53:12 +00004525 TranslationUnitDecl *ToTU = getToTuDecl(
4526 R"(
4527 class Y { friend class F; };
4528 )",
4529 Lang_CXX);
4530
4531 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4532 // So we must dig up the underlying CXXRecordDecl.
4533 ASTImporterLookupTable LT(*ToTU);
4534 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4535 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4536 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
4537 ToTU, cxxRecordDecl(hasName("Y")));
4538
4539 DeclarationName Name = RD->getDeclName();
4540 auto Res = LT.lookup(ToTU, Name);
4541 EXPECT_EQ(Res.size(), 1u);
4542 EXPECT_EQ(*Res.begin(), RD);
4543
4544 Res = LT.lookup(Y, Name);
4545 EXPECT_EQ(Res.size(), 0u);
4546}
4547
Gabor Martondd2b76e2019-06-11 13:35:25 +00004548TEST_P(ASTImporterLookupTableTest,
4549 LookupFindsFwdFriendClassDeclWithUnelaboratedType) {
4550 TranslationUnitDecl *ToTU = getToTuDecl(
4551 R"(
4552 class F;
4553 class Y { friend F; };
4554 )",
4555 Lang_CXX11);
4556
4557 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4558 // So we must dig up the underlying CXXRecordDecl.
4559 ASTImporterLookupTable LT(*ToTU);
4560 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4561 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4562 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, cxxRecordDecl(hasName("Y")));
4563
4564 DeclarationName Name = RD->getDeclName();
4565 auto Res = LT.lookup(ToTU, Name);
4566 EXPECT_EQ(Res.size(), 1u);
4567 EXPECT_EQ(*Res.begin(), RD);
4568
4569 Res = LT.lookup(Y, Name);
4570 EXPECT_EQ(Res.size(), 0u);
4571}
4572
4573TEST_P(ASTImporterLookupTableTest,
4574 LookupFindsFriendClassDeclWithTypeAliasDoesNotAssert) {
4575 TranslationUnitDecl *ToTU = getToTuDecl(
4576 R"(
4577 class F;
4578 using alias_of_f = F;
4579 class Y { friend alias_of_f; };
4580 )",
4581 Lang_CXX11);
4582
4583 // ASTImporterLookupTable constructor handles using declarations correctly,
4584 // no assert is expected.
4585 ASTImporterLookupTable LT(*ToTU);
4586
4587 auto *Alias = FirstDeclMatcher<TypeAliasDecl>().match(
4588 ToTU, typeAliasDecl(hasName("alias_of_f")));
4589 DeclarationName Name = Alias->getDeclName();
4590 auto Res = LT.lookup(ToTU, Name);
4591 EXPECT_EQ(Res.count(Alias), 1u);
4592}
4593
Gabor Marton54058b52018-12-17 13:53:12 +00004594TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
4595 TranslationUnitDecl *ToTU = getToTuDecl(
4596 R"(
4597 class Y { template <class T> friend class F; };
4598 )",
4599 Lang_CXX);
4600
4601 ASTImporterLookupTable LT(*ToTU);
4602 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4603 ToTU, classTemplateDecl(hasName("F")));
4604 DeclarationName Name = F->getDeclName();
4605 auto Res = LT.lookup(ToTU, Name);
4606 EXPECT_EQ(Res.size(), 2u);
4607 EXPECT_EQ(Res.count(F), 1u);
4608 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4609}
4610
4611TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
4612 TranslationUnitDecl *ToTU = getToTuDecl(
4613 R"(
4614 template <typename T>
4615 class F;
4616
4617 template <typename T>
4618 class Y {
4619 friend class F<T>;
4620 };
4621 )",
4622 Lang_CXX);
4623
4624 ASTImporterLookupTable LT(*ToTU);
4625 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4626 ToTU, classTemplateDecl(hasName("F")));
4627 DeclarationName Name = F->getDeclName();
4628 auto Res = LT.lookup(ToTU, Name);
4629 EXPECT_EQ(Res.size(), 2u);
4630 EXPECT_EQ(Res.count(F), 1u);
4631 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4632}
4633
4634TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
4635 TranslationUnitDecl *ToTU = getToTuDecl(
4636 R"(
4637 template <typename T>
4638 class F;
4639
4640 class Y {
4641 friend class F<int>;
4642 };
4643 )",
4644 Lang_CXX);
4645
4646 ASTImporterLookupTable LT(*ToTU);
4647 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4648 ToTU, classTemplateDecl(hasName("F")));
4649 DeclarationName Name = F->getDeclName();
4650 auto Res = LT.lookup(ToTU, Name);
4651 ASSERT_EQ(Res.size(), 3u);
4652 EXPECT_EQ(Res.count(F), 1u);
4653 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4654 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
4655}
4656
4657TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
4658 TranslationUnitDecl *ToTU = getToTuDecl(
4659 R"(
4660 class Y { friend void F(); };
4661 )",
4662 Lang_CXX);
4663
4664 ASTImporterLookupTable LT(*ToTU);
4665 auto *F =
4666 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
4667 DeclarationName Name = F->getDeclName();
4668 auto Res = LT.lookup(ToTU, Name);
4669 EXPECT_EQ(Res.size(), 1u);
4670 EXPECT_EQ(*Res.begin(), F);
4671}
4672
4673TEST_P(ASTImporterLookupTableTest,
4674 LookupFindsDeclsInClassTemplateSpecialization) {
4675 TranslationUnitDecl *ToTU = getToTuDecl(
4676 R"(
4677 template <typename T>
4678 struct X {
4679 int F;
4680 };
4681 void foo() {
4682 X<char> xc;
4683 }
4684 )",
4685 Lang_CXX);
4686
4687 ASTImporterLookupTable LT(*ToTU);
4688
4689 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
4690 ToTU, classTemplateDecl(hasName("X")));
4691 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
4692 ToTU,
4693 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
4694
4695 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4696 ToTU, classTemplateSpecializationDecl(hasName("X")));
4697 FieldDecl *FieldInSpec = *Spec->field_begin();
4698 ASSERT_TRUE(FieldInSpec);
4699
4700 DeclarationName Name = FieldInSpec->getDeclName();
4701 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
4702
4703 SmallVector<NamedDecl *, 2> FoundDecls;
4704 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
4705 EXPECT_EQ(FoundDecls.size(), 1u);
4706 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
4707
4708 auto Res = LT.lookup(TemplateDC, Name);
4709 ASSERT_EQ(Res.size(), 1u);
4710 EXPECT_EQ(*Res.begin(), FieldInTemplate);
4711
4712 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
4713 FoundDecls);
4714 EXPECT_EQ(FoundDecls.size(), 1u);
4715 EXPECT_EQ(FoundDecls[0], FieldInSpec);
4716
4717 Res = LT.lookup(cast<DeclContext>(Spec), Name);
4718 ASSERT_EQ(Res.size(), 1u);
4719 EXPECT_EQ(*Res.begin(), FieldInSpec);
4720}
4721
4722TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
4723 TranslationUnitDecl *ToTU = getToTuDecl(
4724 R"(
4725 class Y { template <class T> friend void F(); };
4726 )",
4727 Lang_CXX);
4728
4729 ASTImporterLookupTable LT(*ToTU);
4730 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
4731 ToTU, functionTemplateDecl(hasName("F")));
4732 DeclarationName Name = F->getDeclName();
4733 auto Res = LT.lookup(ToTU, Name);
4734 EXPECT_EQ(Res.size(), 2u);
4735 EXPECT_EQ(Res.count(F), 1u);
4736 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4737}
4738
4739TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
4740 TranslationUnitDecl *ToTU = getToTuDecl(
4741 R"(
4742 struct X;
4743 struct A {
4744 friend struct X;
4745 };
4746 struct B {
4747 friend struct X;
4748 };
4749 )",
4750 Lang_CXX);
4751
4752 ASTImporterLookupTable LT(*ToTU);
4753 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
4754 ToTU, cxxRecordDecl(hasName("X")));
4755 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4756 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4757 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
4758 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
4759 ASSERT_EQ(RD0, RD1);
4760 ASSERT_EQ(RD1, X);
4761
4762 DeclarationName Name = X->getDeclName();
4763 auto Res = LT.lookup(ToTU, Name);
4764 EXPECT_EQ(Res.size(), 1u);
4765 EXPECT_EQ(*Res.begin(), X);
4766}
4767
4768TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
4769 TranslationUnitDecl *ToTU = getToTuDecl(
4770 R"(
4771 enum E {
4772 A,
4773 B
4774 };
4775 )",
4776 Lang_C);
4777
4778 ASTImporterLookupTable LT(*ToTU);
4779 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
4780 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
4781 ToTU, enumConstantDecl(hasName("A")));
4782
4783 DeclarationName Name = A->getDeclName();
4784 // Redecl context is the TU.
4785 ASSERT_EQ(E->getRedeclContext(), ToTU);
4786
4787 SmallVector<NamedDecl *, 2> FoundDecls;
4788 // Normal lookup finds in the DC.
4789 E->localUncachedLookup(Name, FoundDecls);
4790 EXPECT_EQ(FoundDecls.size(), 1u);
4791
4792 // Normal lookup finds in the Redecl context.
4793 ToTU->localUncachedLookup(Name, FoundDecls);
4794 EXPECT_EQ(FoundDecls.size(), 1u);
4795
4796 // Import specific lookup finds in the DC.
4797 auto Res = LT.lookup(E, Name);
4798 ASSERT_EQ(Res.size(), 1u);
4799 EXPECT_EQ(*Res.begin(), A);
4800
4801 // Import specific lookup finds in the Redecl context.
4802 Res = LT.lookup(ToTU, Name);
4803 ASSERT_EQ(Res.size(), 1u);
4804 EXPECT_EQ(*Res.begin(), A);
4805}
4806
4807TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
4808 TranslationUnitDecl *ToTU = getToTuDecl(
4809 R"(
4810 namespace N {
4811 int A;
4812 }
4813 namespace N {
4814 }
4815 )",
4816 Lang_CXX);
4817 auto *N1 =
4818 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
4819 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
4820 DeclarationName Name = A->getDeclName();
4821
4822 ASTImporterLookupTable LT(*ToTU);
4823 auto Res = LT.lookup(N1, Name);
4824 ASSERT_EQ(Res.size(), 1u);
4825 EXPECT_EQ(*Res.begin(), A);
4826}
4827
Gabor Marton0e04ebd2019-02-11 10:27:58 +00004828TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton305a11d2019-10-07 11:34:54 +00004829 RedeclChainShouldBeCorrectAmongstNamespaces) {
Gabor Marton0e04ebd2019-02-11 10:27:58 +00004830 Decl *FromTU = getTuDecl(
4831 R"(
4832 namespace NS {
4833 struct X;
4834 struct Y {
4835 static const int I = 3;
4836 };
4837 }
4838 namespace NS {
4839 struct X { // <--- To be imported
4840 void method(int i = Y::I) {}
4841 int f;
4842 };
4843 }
4844 )",
4845 Lang_CXX);
4846 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
4847 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
4848 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
4849 FromTU,
4850 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
4851 ASSERT_NE(FromFwd, FromDef);
4852 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
4853 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4854 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
4855
4856 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX));
4857 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX));
4858 EXPECT_NE(ToFwd, ToDef);
4859 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
4860 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4861 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
4862 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4863 // We expect no (ODR) warning during the import.
4864 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4865}
4866
Gabor Martone331e632019-02-18 13:09:27 +00004867struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
4868
4869TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
4870 Decl *ToTU = getToTuDecl(
4871 R"(
4872 class X {
4873 template <typename T> friend void foo();
4874 };
4875 )",
4876 Lang_CXX);
4877 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
4878 ToTU, functionTemplateDecl(hasName("foo")));
4879
4880 Decl *FromTU = getTuDecl(
4881 R"(
4882 template <typename T> void foo();
4883 )",
4884 Lang_CXX);
4885 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
4886 FromTU, functionTemplateDecl(hasName("foo")));
4887 auto *Imported = Import(FromFoo, Lang_CXX);
4888
Gabor Marton16d98c22019-03-07 13:01:51 +00004889 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
Gabor Martone331e632019-02-18 13:09:27 +00004890}
4891
Gabor Marton303c98612019-06-25 08:00:51 +00004892struct ASTImporterWithFakeErrors : ASTImporter {
4893 using ASTImporter::ASTImporter;
4894 bool returnWithErrorInTest() override { return true; }
4895};
4896
4897struct ErrorHandlingTest : ASTImporterOptionSpecificTestBase {
4898 ErrorHandlingTest() {
4899 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
4900 ASTContext &FromContext, FileManager &FromFileManager,
Gabor Marton2afbfb62019-07-01 15:37:07 +00004901 bool MinimalImport,
4902 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
Gabor Marton303c98612019-06-25 08:00:51 +00004903 return new ASTImporterWithFakeErrors(ToContext, ToFileManager,
4904 FromContext, FromFileManager,
Gabor Marton2afbfb62019-07-01 15:37:07 +00004905 MinimalImport, SharedState);
Gabor Marton303c98612019-06-25 08:00:51 +00004906 };
4907 }
4908 // In this test we purposely report an error (UnsupportedConstruct) when
4909 // importing the below stmt.
4910 static constexpr auto* ErroneousStmt = R"( asm(""); )";
4911};
4912
4913// Check a case when no new AST node is created in the AST before encountering
4914// the error.
4915TEST_P(ErrorHandlingTest, ErrorHappensBeforeCreatingANewNode) {
4916 TranslationUnitDecl *ToTU = getToTuDecl(
4917 R"(
4918 template <typename T>
4919 class X {};
4920 template <>
4921 class X<int> { int a; };
4922 )",
4923 Lang_CXX);
4924 TranslationUnitDecl *FromTU = getTuDecl(
4925 R"(
4926 template <typename T>
4927 class X {};
4928 template <>
4929 class X<int> { double b; };
4930 )",
4931 Lang_CXX);
4932 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4933 FromTU, classTemplateSpecializationDecl(hasName("X")));
4934 ClassTemplateSpecializationDecl *ImportedSpec = Import(FromSpec, Lang_CXX);
4935 EXPECT_FALSE(ImportedSpec);
4936
4937 // The original Decl is kept, no new decl is created.
4938 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(
4939 ToTU, classTemplateSpecializationDecl(hasName("X"))),
4940 1u);
4941
4942 // But an error is set to the counterpart in the "from" context.
4943 ASTImporter *Importer = findFromTU(FromSpec)->Importer.get();
4944 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromSpec);
4945 ASSERT_TRUE(OptErr);
4946 EXPECT_EQ(OptErr->Error, ImportError::NameConflict);
4947}
4948
4949// Check a case when a new AST node is created but not linked to the AST before
4950// encountering the error.
4951TEST_P(ErrorHandlingTest,
4952 ErrorHappensAfterCreatingTheNodeButBeforeLinkingThatToTheAST) {
4953 TranslationUnitDecl *FromTU = getTuDecl(
4954 std::string("void foo() { ") + ErroneousStmt + " }",
4955 Lang_CXX);
4956 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4957 FromTU, functionDecl(hasName("foo")));
4958
4959 FunctionDecl *ImportedFoo = Import(FromFoo, Lang_CXX);
4960 EXPECT_FALSE(ImportedFoo);
4961
4962 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4963 // Created, but not linked.
4964 EXPECT_EQ(
4965 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("foo"))),
4966 0u);
4967
4968 ASTImporter *Importer = findFromTU(FromFoo)->Importer.get();
4969 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFoo);
4970 ASSERT_TRUE(OptErr);
4971 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4972}
4973
4974// Check a case when a new AST node is created and linked to the AST before
4975// encountering the error. The error is set for the counterpart of the nodes in
4976// the "from" context.
4977TEST_P(ErrorHandlingTest, ErrorHappensAfterNodeIsCreatedAndLinked) {
4978 TranslationUnitDecl *FromTU = getTuDecl(
4979 std::string(R"(
4980 void f();
4981 void f() { )") + ErroneousStmt + R"( }
4982 )",
4983 Lang_CXX);
4984 auto *FromProto = FirstDeclMatcher<FunctionDecl>().match(
4985 FromTU, functionDecl(hasName("f")));
4986 auto *FromDef =
4987 LastDeclMatcher<FunctionDecl>().match(FromTU, functionDecl(hasName("f")));
4988 FunctionDecl *ImportedProto = Import(FromProto, Lang_CXX);
4989 EXPECT_FALSE(ImportedProto); // Could not import.
4990 // However, we created two nodes in the AST. 1) the fwd decl 2) the
4991 // definition. The definition is not added to its DC, but the fwd decl is
4992 // there.
4993 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4994 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
4995 1u);
4996 // Match the fwd decl.
4997 auto *ToProto =
4998 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("f")));
4999 EXPECT_TRUE(ToProto);
5000 // An error is set to the counterpart in the "from" context both for the fwd
5001 // decl and the definition.
5002 ASTImporter *Importer = findFromTU(FromProto)->Importer.get();
5003 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromProto);
5004 ASSERT_TRUE(OptErr);
5005 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5006 OptErr = Importer->getImportDeclErrorIfAny(FromDef);
5007 ASSERT_TRUE(OptErr);
5008 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5009}
5010
Gabor Marton17c3eaf2019-07-01 12:44:39 +00005011// An error should be set for a class if we cannot import one member.
5012TEST_P(ErrorHandlingTest, ErrorIsPropagatedFromMemberToClass) {
5013 TranslationUnitDecl *FromTU = getTuDecl(
5014 std::string(R"(
5015 class X {
5016 void f() { )") + ErroneousStmt + R"( } // This member has the error
5017 // during import.
5018 void ok(); // The error should not prevent importing this.
5019 }; // An error will be set for X too.
5020 )",
5021 Lang_CXX);
5022 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5023 FromTU, cxxRecordDecl(hasName("X")));
5024 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX);
5025
5026 // An error is set for X.
5027 EXPECT_FALSE(ImportedX);
5028 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5029 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5030 ASSERT_TRUE(OptErr);
5031 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5032
5033 // An error is set for f().
5034 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
5035 FromTU, cxxMethodDecl(hasName("f")));
5036 OptErr = Importer->getImportDeclErrorIfAny(FromF);
5037 ASSERT_TRUE(OptErr);
5038 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5039 // And any subsequent import should fail.
5040 CXXMethodDecl *ImportedF = Import(FromF, Lang_CXX);
5041 EXPECT_FALSE(ImportedF);
5042
Gabor Marton1ad4b992019-07-01 14:19:53 +00005043 // There is an error set for the other member too.
Gabor Marton17c3eaf2019-07-01 12:44:39 +00005044 auto *FromOK = FirstDeclMatcher<CXXMethodDecl>().match(
5045 FromTU, cxxMethodDecl(hasName("ok")));
5046 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
Gabor Marton1ad4b992019-07-01 14:19:53 +00005047 EXPECT_TRUE(OptErr);
5048 // Cannot import the other member.
Gabor Marton17c3eaf2019-07-01 12:44:39 +00005049 CXXMethodDecl *ImportedOK = Import(FromOK, Lang_CXX);
Gabor Marton1ad4b992019-07-01 14:19:53 +00005050 EXPECT_FALSE(ImportedOK);
5051}
Gabor Marton17c3eaf2019-07-01 12:44:39 +00005052
Gabor Marton1ad4b992019-07-01 14:19:53 +00005053// Check that an error propagates to the dependent AST nodes.
5054// In the below code it means that an error in X should propagate to A.
5055// And even to F since the containing A is erroneous.
5056// And to all AST nodes which we visit during the import process which finally
5057// ends up in a failure (in the error() function).
5058TEST_P(ErrorHandlingTest, ErrorPropagatesThroughImportCycles) {
5059 Decl *FromTU = getTuDecl(
5060 std::string(R"(
5061 namespace NS {
5062 class A {
5063 template <int I> class F {};
5064 class X {
5065 template <int I> friend class F;
5066 void error() { )") + ErroneousStmt + R"( }
5067 };
5068 };
5069
5070 class B {};
5071 } // NS
5072 )",
5073 Lang_CXX, "input0.cc");
5074
5075 auto *FromFRD = FirstDeclMatcher<CXXRecordDecl>().match(
5076 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
5077 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
5078 FromTU, cxxRecordDecl(hasName("A"), isDefinition()));
5079 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(
5080 FromTU, cxxRecordDecl(hasName("B"), isDefinition()));
5081 auto *FromNS = FirstDeclMatcher<NamespaceDecl>().match(
5082 FromTU, namespaceDecl(hasName("NS")));
5083
5084 // Start by importing the templated CXXRecordDecl of F.
5085 // Import fails for that.
5086 EXPECT_FALSE(Import(FromFRD, Lang_CXX));
5087 // Import fails for A.
5088 EXPECT_FALSE(Import(FromA, Lang_CXX));
5089 // But we should be able to import the independent B.
5090 EXPECT_TRUE(Import(FromB, Lang_CXX));
5091 // And the namespace.
5092 EXPECT_TRUE(Import(FromNS, Lang_CXX));
5093
5094 // An error is set to the templated CXXRecordDecl of F.
5095 ASTImporter *Importer = findFromTU(FromFRD)->Importer.get();
5096 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFRD);
5097 EXPECT_TRUE(OptErr);
5098
5099 // An error is set to A.
5100 OptErr = Importer->getImportDeclErrorIfAny(FromA);
5101 EXPECT_TRUE(OptErr);
5102
5103 // There is no error set to B.
5104 OptErr = Importer->getImportDeclErrorIfAny(FromB);
5105 EXPECT_FALSE(OptErr);
5106
5107 // There is no error set to NS.
5108 OptErr = Importer->getImportDeclErrorIfAny(FromNS);
5109 EXPECT_FALSE(OptErr);
5110
5111 // Check some of those decls whose ancestor is X, they all should have an
5112 // error set if we visited them during an import process which finally failed.
5113 // These decls are part of a cycle in an ImportPath.
5114 // There would not be any error set for these decls if we hadn't follow the
5115 // ImportPaths and the cycles.
5116 OptErr = Importer->getImportDeclErrorIfAny(
5117 FirstDeclMatcher<ClassTemplateDecl>().match(
5118 FromTU, classTemplateDecl(hasName("F"))));
5119 // An error is set to the 'F' ClassTemplateDecl.
5120 EXPECT_TRUE(OptErr);
5121 // An error is set to the FriendDecl.
5122 OptErr = Importer->getImportDeclErrorIfAny(
5123 FirstDeclMatcher<FriendDecl>().match(
5124 FromTU, friendDecl()));
5125 EXPECT_TRUE(OptErr);
5126 // An error is set to the implicit class of A.
5127 OptErr =
5128 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
5129 FromTU, cxxRecordDecl(hasName("A"), isImplicit())));
5130 EXPECT_TRUE(OptErr);
5131 // An error is set to the implicit class of X.
5132 OptErr =
5133 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
5134 FromTU, cxxRecordDecl(hasName("X"), isImplicit())));
5135 EXPECT_TRUE(OptErr);
Gabor Marton17c3eaf2019-07-01 12:44:39 +00005136}
5137
5138TEST_P(ErrorHandlingTest, ErrorIsNotPropagatedFromMemberToNamespace) {
5139 TranslationUnitDecl *FromTU = getTuDecl(
5140 std::string(R"(
5141 namespace X {
5142 void f() { )") + ErroneousStmt + R"( } // This member has the error
5143 // during import.
5144 void ok(); // The error should not prevent importing this.
5145 }; // An error will be set for X too.
5146 )",
5147 Lang_CXX);
5148 auto *FromX = FirstDeclMatcher<NamespaceDecl>().match(
5149 FromTU, namespaceDecl(hasName("X")));
5150 NamespaceDecl *ImportedX = Import(FromX, Lang_CXX);
5151
5152 // There is no error set for X.
5153 EXPECT_TRUE(ImportedX);
5154 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5155 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5156 ASSERT_FALSE(OptErr);
5157
5158 // An error is set for f().
5159 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
5160 FromTU, functionDecl(hasName("f")));
5161 OptErr = Importer->getImportDeclErrorIfAny(FromF);
5162 ASSERT_TRUE(OptErr);
5163 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5164 // And any subsequent import should fail.
5165 FunctionDecl *ImportedF = Import(FromF, Lang_CXX);
5166 EXPECT_FALSE(ImportedF);
5167
5168 // There is no error set for ok().
5169 auto *FromOK = FirstDeclMatcher<FunctionDecl>().match(
5170 FromTU, functionDecl(hasName("ok")));
5171 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
5172 EXPECT_FALSE(OptErr);
5173 // And we should be able to import.
5174 FunctionDecl *ImportedOK = Import(FromOK, Lang_CXX);
5175 EXPECT_TRUE(ImportedOK);
5176}
5177
Gabor Marton2afbfb62019-07-01 15:37:07 +00005178// An error should be set for a class if it had a previous import with an error
5179// from another TU.
5180TEST_P(ErrorHandlingTest,
5181 ImportedDeclWithErrorShouldFailTheImportOfDeclWhichMapToIt) {
5182 // We already have a fwd decl.
5183 TranslationUnitDecl *ToTU = getToTuDecl(
5184 "class X;", Lang_CXX);
5185 // Then we import a definition.
5186 {
5187 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5188 class X {
5189 void f() { )") + ErroneousStmt + R"( }
5190 void ok();
5191 };
5192 )",
5193 Lang_CXX);
5194 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5195 FromTU, cxxRecordDecl(hasName("X")));
5196 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX);
5197
5198 // An error is set for X ...
5199 EXPECT_FALSE(ImportedX);
5200 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5201 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5202 ASSERT_TRUE(OptErr);
5203 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5204 }
5205 // ... but the node had been created.
5206 auto *ToXDef = FirstDeclMatcher<CXXRecordDecl>().match(
5207 ToTU, cxxRecordDecl(hasName("X"), isDefinition()));
5208 // An error is set for "ToXDef" in the shared state.
5209 Optional<ImportError> OptErr =
5210 SharedStatePtr->getImportDeclErrorIfAny(ToXDef);
5211 ASSERT_TRUE(OptErr);
5212 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5213
5214 auto *ToXFwd = FirstDeclMatcher<CXXRecordDecl>().match(
5215 ToTU, cxxRecordDecl(hasName("X"), unless(isDefinition())));
5216 // An error is NOT set for the fwd Decl of X in the shared state.
5217 OptErr = SharedStatePtr->getImportDeclErrorIfAny(ToXFwd);
5218 ASSERT_FALSE(OptErr);
5219
5220 // Try to import X again but from another TU.
5221 {
5222 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5223 class X {
5224 void f() { )") + ErroneousStmt + R"( }
5225 void ok();
5226 };
5227 )",
5228 Lang_CXX, "input1.cc");
5229
5230 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5231 FromTU, cxxRecordDecl(hasName("X")));
5232 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX);
5233
5234 // If we did not save the errors for the "to" context then the below checks
5235 // would fail, because the lookup finds the fwd Decl of the existing
5236 // definition in the "to" context. We can reach the existing definition via
5237 // the found fwd Decl. That existing definition is structurally equivalent
5238 // (we check only the fields) with this one we want to import, so we return
5239 // with the existing definition, which is erroneous (one method is missing).
5240
5241 // The import should fail.
5242 EXPECT_FALSE(ImportedX);
5243 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5244 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5245 // And an error is set for this new X in the "from" ctx.
5246 ASSERT_TRUE(OptErr);
5247 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5248 }
5249}
5250
Balazs Kerib4fd7d42019-08-30 10:12:14 +00005251TEST_P(ErrorHandlingTest, ImportOfOverriddenMethods) {
5252 auto MatchFooA =
5253 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("A"))));
5254 auto MatchFooB =
5255 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("B"))));
5256 auto MatchFooC =
5257 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("C"))));
5258
5259 // Provoke import of a method that has overridden methods with import error.
5260 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5261 struct C;
5262 struct A {
5263 virtual void foo();
5264 void f1(C *);
5265 };
5266 void A::foo() {
5267 )") + ErroneousStmt + R"(
5268 }
5269 struct B : public A {
5270 void foo() override;
5271 };
5272 struct C : public B {
5273 void foo() override;
5274 };
5275 )",
5276 Lang_CXX11);
5277 auto *FromFooA = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooA);
5278 auto *FromFooB = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooB);
5279 auto *FromFooC = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooC);
5280
5281 EXPECT_FALSE(Import(FromFooA, Lang_CXX11));
5282 ASTImporter *Importer = findFromTU(FromFooA)->Importer.get();
5283 auto CheckError = [&Importer](Decl *FromD) {
5284 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromD);
5285 ASSERT_TRUE(OptErr);
5286 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5287 };
5288 CheckError(FromFooA);
5289 EXPECT_FALSE(Import(FromFooB, Lang_CXX11));
5290 CheckError(FromFooB);
5291 EXPECT_FALSE(Import(FromFooC, Lang_CXX11));
5292 CheckError(FromFooC);
5293}
5294
Gabor Martone73805f2019-07-08 12:49:13 +00005295TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) {
5296 Decl *FromTU = getTuDecl(
5297 R"(
5298 void f() {
5299 auto L = [](){};
5300 }
5301 )",
5302 Lang_CXX11, "input0.cc");
5303 auto Pattern = lambdaExpr();
5304 CXXRecordDecl *FromL =
5305 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5306
5307 auto ToL = Import(FromL, Lang_CXX11);
5308 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
5309 unsigned FromLSize =
5310 std::distance(FromL->decls().begin(), FromL->decls().end());
5311 EXPECT_NE(ToLSize, 0u);
5312 EXPECT_EQ(ToLSize, FromLSize);
5313}
5314
5315TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
5316 Decl *FromTU = getTuDecl(
5317 R"(
5318 template <typename F>
5319 void f(F L = [](){}) {}
5320 )",
5321 Lang_CXX11, "input0.cc");
5322 auto Pattern = lambdaExpr();
5323 CXXRecordDecl *FromL =
5324 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5325
5326 auto ToL = Import(FromL, Lang_CXX11);
5327 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
5328 unsigned FromLSize =
5329 std::distance(FromL->decls().begin(), FromL->decls().end());
5330 EXPECT_NE(ToLSize, 0u);
5331 EXPECT_EQ(ToLSize, FromLSize);
5332}
5333
Gabor Martonae512b82019-07-17 14:40:09 +00005334TEST_P(ASTImporterOptionSpecificTestBase, LambdaInGlobalScope) {
5335 Decl *FromTU = getTuDecl(
5336 R"(
5337 auto l1 = [](unsigned lp) { return 1; };
5338 auto l2 = [](int lp) { return 2; };
5339 int f(int p) {
5340 return l1(p) + l2(p);
5341 }
5342 )",
5343 Lang_CXX11, "input0.cc");
5344 FunctionDecl *FromF = FirstDeclMatcher<FunctionDecl>().match(
5345 FromTU, functionDecl(hasName("f")));
5346 FunctionDecl *ToF = Import(FromF, Lang_CXX11);
5347 EXPECT_TRUE(ToF);
5348}
5349
Balazs Keri2e160602019-08-12 10:07:38 +00005350TEST_P(ASTImporterOptionSpecificTestBase,
5351 ImportExistingFriendClassTemplateDef) {
5352 auto Code =
5353 R"(
5354 template <class T1, class T2>
5355 struct Base {
5356 template <class U1, class U2>
5357 friend struct Class;
5358 };
5359 template <class T1, class T2>
5360 struct Class { };
5361 )";
5362
5363 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
5364 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
5365
5366 auto *ToClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
5367 ToTU, classTemplateDecl(hasName("Class")));
5368 auto *ToClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
5369 ToTU, classTemplateDecl(hasName("Class")));
5370 ASSERT_FALSE(ToClassProto->isThisDeclarationADefinition());
5371 ASSERT_TRUE(ToClassDef->isThisDeclarationADefinition());
5372 // Previous friend decl is not linked to it!
5373 ASSERT_FALSE(ToClassDef->getPreviousDecl());
5374 ASSERT_EQ(ToClassDef->getMostRecentDecl(), ToClassDef);
5375 ASSERT_EQ(ToClassProto->getMostRecentDecl(), ToClassProto);
5376
5377 auto *FromClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
5378 FromTU, classTemplateDecl(hasName("Class")));
5379 auto *FromClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
5380 FromTU, classTemplateDecl(hasName("Class")));
5381 ASSERT_FALSE(FromClassProto->isThisDeclarationADefinition());
5382 ASSERT_TRUE(FromClassDef->isThisDeclarationADefinition());
5383 ASSERT_FALSE(FromClassDef->getPreviousDecl());
5384 ASSERT_EQ(FromClassDef->getMostRecentDecl(), FromClassDef);
5385 ASSERT_EQ(FromClassProto->getMostRecentDecl(), FromClassProto);
5386
5387 auto *ImportedDef = Import(FromClassDef, Lang_CXX);
5388 // At import we should find the definition for 'Class' even if the
5389 // prototype (inside 'friend') for it comes first in the AST and is not
5390 // linked to the definition.
5391 EXPECT_EQ(ImportedDef, ToClassDef);
Gabor Martonf035b752019-08-27 11:36:10 +00005392}
5393
Gabor Martonaefcf512019-07-17 13:47:46 +00005394struct LLDBLookupTest : ASTImporterOptionSpecificTestBase {
5395 LLDBLookupTest() {
5396 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
5397 ASTContext &FromContext, FileManager &FromFileManager,
5398 bool MinimalImport,
5399 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
5400 return new ASTImporter(ToContext, ToFileManager, FromContext,
5401 FromFileManager, MinimalImport,
5402 // We use the regular lookup.
5403 /*SharedState=*/nullptr);
5404 };
5405 }
5406};
5407
5408TEST_P(LLDBLookupTest, ImporterShouldFindInTransparentContext) {
5409 TranslationUnitDecl *ToTU = getToTuDecl(
5410 R"(
5411 extern "C" {
5412 class X{};
5413 };
5414 )",
5415 Lang_CXX);
5416 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(
5417 ToTU, cxxRecordDecl(hasName("X")));
5418
5419 // Set up a stub external storage.
5420 ToTU->setHasExternalLexicalStorage(true);
5421 // Set up DeclContextBits.HasLazyExternalLexicalLookups to true.
5422 ToTU->setMustBuildLookupTable();
5423 struct TestExternalASTSource : ExternalASTSource {};
5424 ToTU->getASTContext().setExternalSource(new TestExternalASTSource());
5425
5426 Decl *FromTU = getTuDecl(
5427 R"(
5428 class X;
5429 )",
5430 Lang_CXX);
5431 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5432 FromTU, cxxRecordDecl(hasName("X")));
5433 auto *ImportedX = Import(FromX, Lang_CXX);
5434 // The lookup must find the existing class definition in the LinkageSpecDecl.
5435 // Then the importer renders the existing and the new decl into one chain.
5436 EXPECT_EQ(ImportedX->getCanonicalDecl(), ToX->getCanonicalDecl());
5437}
5438
Richard Sandifordeb485fb2019-08-09 08:52:54 +00005439struct SVEBuiltins : ASTImporterOptionSpecificTestBase {};
5440
5441TEST_P(SVEBuiltins, ImportTypes) {
5442 static const char *const TypeNames[] = {
5443 "__SVInt8_t",
5444 "__SVInt16_t",
5445 "__SVInt32_t",
5446 "__SVInt64_t",
5447 "__SVUint8_t",
5448 "__SVUint16_t",
5449 "__SVUint32_t",
5450 "__SVUint64_t",
5451 "__SVFloat16_t",
5452 "__SVFloat32_t",
5453 "__SVFloat64_t",
5454 "__SVBool_t"
5455 };
5456
5457 TranslationUnitDecl *ToTU = getToTuDecl("", Lang_CXX);
5458 TranslationUnitDecl *FromTU = getTuDecl("", Lang_CXX, "input.cc");
5459 for (auto *TypeName : TypeNames) {
5460 auto *ToTypedef = FirstDeclMatcher<TypedefDecl>().match(
5461 ToTU, typedefDecl(hasName(TypeName)));
5462 QualType ToType = ToTypedef->getUnderlyingType();
5463
5464 auto *FromTypedef = FirstDeclMatcher<TypedefDecl>().match(
5465 FromTU, typedefDecl(hasName(TypeName)));
5466 QualType FromType = FromTypedef->getUnderlyingType();
5467
5468 QualType ImportedType = ImportType(FromType, FromTypedef, Lang_CXX);
5469 EXPECT_EQ(ImportedType, ToType);
5470 }
5471}
5472
Balazs Kerib427c062019-08-13 08:04:06 +00005473TEST_P(ASTImporterOptionSpecificTestBase, ImportOfDefaultImplicitFunctions) {
5474 // Test that import of implicit functions works and the functions
5475 // are merged into one chain.
5476 auto GetDeclToImport = [this](StringRef File) {
5477 Decl *FromTU = getTuDecl(
5478 R"(
5479 struct X { };
5480 // Force generating some implicit operator definitions for X.
5481 void f() { X x1, x2; x1 = x2; X *x3 = new X; delete x3; }
5482 )",
5483 Lang_CXX11, File);
5484 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
5485 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
5486 // Destructor is picked as one example of implicit function.
5487 return FromD->getDestructor();
5488 };
5489
5490 auto *ToD1 = Import(GetDeclToImport("input1.cc"), Lang_CXX11);
5491 ASSERT_TRUE(ToD1);
5492
5493 auto *ToD2 = Import(GetDeclToImport("input2.cc"), Lang_CXX11);
5494 ASSERT_TRUE(ToD2);
5495
5496 EXPECT_EQ(ToD1->getCanonicalDecl(), ToD2->getCanonicalDecl());
5497}
5498
5499TEST_P(ASTImporterOptionSpecificTestBase,
5500 ImportOfExplicitlyDefaultedOrDeleted) {
5501 Decl *FromTU = getTuDecl(
5502 R"(
5503 struct X { X() = default; X(const X&) = delete; };
5504 )",
5505 Lang_CXX11);
5506 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5507 FromTU, cxxRecordDecl(hasName("X")));
5508 auto *ImportedX = Import(FromX, Lang_CXX11);
5509 auto *Constr1 = FirstDeclMatcher<CXXConstructorDecl>().match(
5510 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));
5511 auto *Constr2 = LastDeclMatcher<CXXConstructorDecl>().match(
5512 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));
5513
5514 ASSERT_TRUE(ImportedX);
5515 EXPECT_TRUE(Constr1->isDefaulted());
5516 EXPECT_TRUE(Constr1->isExplicitlyDefaulted());
5517 EXPECT_TRUE(Constr2->isDeletedAsWritten());
5518 EXPECT_EQ(ImportedX->isAggregate(), FromX->isAggregate());
5519}
5520
Richard Sandifordeb485fb2019-08-09 08:52:54 +00005521INSTANTIATE_TEST_CASE_P(ParameterizedTests, SVEBuiltins,
5522 ::testing::Values(ArgVector{"-target",
5523 "aarch64-linux-gnu"}), );
5524
Gabor Martonf035b752019-08-27 11:36:10 +00005525INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
5526 ::testing::Values(ArgVector()), );
5527
5528INSTANTIATE_TEST_CASE_P(ParameterizedTests, CanonicalRedeclChain,
5529 ::testing::Values(ArgVector()), );
5530
Gabor Martone3e83d72019-08-30 10:55:41 +00005531TEST_P(ASTImporterOptionSpecificTestBase, LambdasAreDifferentiated) {
5532 Decl *FromTU = getTuDecl(
5533 R"(
5534 void f() {
5535 auto L0 = [](){};
5536 auto L1 = [](){};
5537 }
5538 )",
5539 Lang_CXX11, "input0.cc");
5540 auto Pattern = lambdaExpr();
5541 CXXRecordDecl *FromL0 =
5542 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5543 CXXRecordDecl *FromL1 =
5544 LastDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5545 ASSERT_NE(FromL0, FromL1);
5546
5547 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
5548 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
5549 EXPECT_NE(ToL0, ToL1);
5550}
5551
5552TEST_P(ASTImporterOptionSpecificTestBase,
5553 LambdasInFunctionParamsAreDifferentiated) {
5554 Decl *FromTU = getTuDecl(
5555 R"(
5556 template <typename F0, typename F1>
5557 void f(F0 L0 = [](){}, F1 L1 = [](){}) {}
5558 )",
5559 Lang_CXX11, "input0.cc");
5560 auto Pattern = cxxRecordDecl(isLambda());
5561 CXXRecordDecl *FromL0 =
5562 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5563 CXXRecordDecl *FromL1 =
5564 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5565 ASSERT_NE(FromL0, FromL1);
5566
5567 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
5568 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
5569 ASSERT_NE(ToL0, ToL1);
5570}
5571
5572TEST_P(ASTImporterOptionSpecificTestBase,
5573 LambdasInFunctionParamsAreDifferentiatedWhenMacroIsUsed) {
5574 Decl *FromTU = getTuDecl(
5575 R"(
5576 #define LAMBDA [](){}
5577 template <typename F0, typename F1>
5578 void f(F0 L0 = LAMBDA, F1 L1 = LAMBDA) {}
5579 )",
5580 Lang_CXX11, "input0.cc");
5581 auto Pattern = cxxRecordDecl(isLambda());
5582 CXXRecordDecl *FromL0 =
5583 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5584 CXXRecordDecl *FromL1 =
5585 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5586 ASSERT_NE(FromL0, FromL1);
5587
5588 Import(FromL0, Lang_CXX11);
5589 Import(FromL1, Lang_CXX11);
5590 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
5591 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
5592 ASSERT_NE(ToL0, ToL1);
5593}
5594
5595TEST_P(ASTImporterOptionSpecificTestBase, ImportAssignedLambda) {
5596 Decl *FromTU = getTuDecl(
5597 R"(
5598 void f() {
5599 auto x = []{} = {}; auto x2 = x;
5600 }
5601 )",
5602 Lang_CXX2a, "input0.cc");
5603 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
5604 FromTU, functionDecl(hasName("f")));
5605 // We have only one lambda class.
5606 ASSERT_EQ(
5607 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
5608 1u);
5609
5610 FunctionDecl *ToF = Import(FromF, Lang_CXX2a);
5611 EXPECT_TRUE(ToF);
5612 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5613 // We have only one lambda class after the import.
5614 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
5615 1u);
5616}
5617
5618TEST_P(ASTImporterOptionSpecificTestBase, ImportDefaultConstructibleLambdas) {
5619 Decl *FromTU = getTuDecl(
5620 R"(
5621 void f() {
5622 auto x = []{} = {};
5623 auto xb = []{} = {};
5624 }
5625 )",
5626 Lang_CXX2a, "input0.cc");
5627 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
5628 FromTU, functionDecl(hasName("f")));
5629 // We have two lambda classes.
5630 ASSERT_EQ(
5631 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
5632 2u);
5633
5634 FunctionDecl *ToF = Import(FromF, Lang_CXX2a);
5635 EXPECT_TRUE(ToF);
5636 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5637 // We have two lambda classes after the import.
5638 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
5639 2u);
5640}
5641
Raphael Isemann164e0fc2019-12-06 18:10:23 +01005642TEST_P(ASTImporterOptionSpecificTestBase, ImplicitlyDeclareSelf) {
5643 Decl *FromTU = getTuDecl(R"(
5644 __attribute__((objc_root_class))
5645 @interface Root
5646 @end
5647 @interface C : Root
5648 -(void)method;
5649 @end
5650 @implementation C
5651 -(void)method {}
5652 @end
5653 )",
5654 Lang_OBJCXX, "input.mm");
5655 auto *FromMethod = LastDeclMatcher<ObjCMethodDecl>().match(
5656 FromTU, namedDecl(hasName("method")));
5657 ASSERT_TRUE(FromMethod);
5658 auto ToMethod = Import(FromMethod, Lang_OBJCXX);
5659 ASSERT_TRUE(ToMethod);
5660
5661 // Both methods should have their implicit parameters.
5662 EXPECT_TRUE(FromMethod->getSelfDecl() != nullptr);
5663 EXPECT_TRUE(ToMethod->getSelfDecl() != nullptr);
5664}
5665
Gabor Marton25234fd2019-12-12 17:13:35 +01005666struct ImportAutoFunctions : ASTImporterOptionSpecificTestBase {};
5667
5668TEST_P(ImportAutoFunctions, ReturnWithTypedefDeclaredInside) {
5669 Decl *FromTU = getTuDecl(
5670 R"(
5671 auto X = [](long l) {
5672 using int_type = long;
5673 auto dur = 13;
5674 return static_cast<int_type>(dur);
5675 };
5676 )",
5677 Lang_CXX14, "input0.cc");
5678 CXXMethodDecl *From =
5679 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, cxxMethodDecl());
5680
5681 // Explicitly set the return type of the lambda's operator() to the TypeAlias.
5682 // Normally the return type would be the built-in 'long' type. However, there
5683 // are cases when Clang does not use the canonical type and the TypeAlias is
5684 // used. I could not create such an AST from regular source code, it requires
5685 // some special state in the preprocessor. I've found such an AST when Clang
5686 // parsed libcxx/src/filesystem/directory_iterator.cpp, but could not reduce
5687 // that with creduce, because after preprocessing, the AST no longer
5688 // contained the TypeAlias as a return type of the lambda.
5689 ASTContext &Ctx = From->getASTContext();
5690 TypeAliasDecl *FromTA =
5691 FirstDeclMatcher<TypeAliasDecl>().match(FromTU, typeAliasDecl());
5692 QualType TT = Ctx.getTypedefType(FromTA);
5693 const FunctionProtoType *FPT = cast<FunctionProtoType>(From->getType());
5694 QualType NewFunType =
5695 Ctx.getFunctionType(TT, FPT->getParamTypes(), FPT->getExtProtoInfo());
5696 From->setType(NewFunType);
5697
5698 CXXMethodDecl *To = Import(From, Lang_CXX14);
5699 EXPECT_TRUE(To);
5700 EXPECT_TRUE(isa<TypedefType>(To->getReturnType()));
5701}
5702
5703TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside) {
5704 Decl *FromTU = getTuDecl(
5705 R"(
5706 auto foo() {
5707 struct X {};
5708 return X();
5709 }
5710 )",
5711 Lang_CXX14, "input0.cc");
5712 FunctionDecl *From =
5713 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5714
5715 FunctionDecl *To = Import(From, Lang_CXX14);
5716 EXPECT_TRUE(To);
5717 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5718}
5719
5720TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside2) {
5721 Decl *FromTU = getTuDecl(
5722 R"(
5723 auto foo() {
5724 struct X {};
5725 return X();
5726 }
5727 )",
5728 Lang_CXX14, "input0.cc");
5729 FunctionDecl *From =
5730 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5731
5732 // This time import the type directly.
5733 QualType ToT = ImportType(From->getType(), From, Lang_CXX14);
5734 const FunctionProtoType *FPT = cast<FunctionProtoType>(ToT);
5735 EXPECT_TRUE(isa<AutoType>(FPT->getReturnType()));
5736}
5737
5738TEST_P(ImportAutoFunctions, ReturnWithTypedefToStructDeclaredInside) {
5739 Decl *FromTU = getTuDecl(
5740 R"(
5741 auto foo() {
5742 struct X {};
5743 using Y = X;
5744 return Y();
5745 }
5746 )",
5747 Lang_CXX14, "input0.cc");
5748 FunctionDecl *From =
5749 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5750
5751 FunctionDecl *To = Import(From, Lang_CXX14);
5752 EXPECT_TRUE(To);
5753 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5754}
5755
5756TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredNestedInside) {
5757 Decl *FromTU = getTuDecl(
5758 R"(
5759 auto foo() {
5760 struct X { struct Y{}; };
5761 return X::Y();
5762 }
5763 )",
5764 Lang_CXX14, "input0.cc");
5765 FunctionDecl *From =
5766 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5767
5768 FunctionDecl *To = Import(From, Lang_CXX14);
5769 EXPECT_TRUE(To);
5770 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5771}
5772
5773TEST_P(ImportAutoFunctions, ReturnWithInternalLambdaType) {
5774 Decl *FromTU = getTuDecl(
5775 R"(
5776 auto f() {
5777 auto l = []() {
5778 struct X {};
5779 return X();
5780 };
5781 return l();
5782 }
5783 )",
5784 Lang_CXX17, "input0.cc");
5785 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5786 FromTU, functionDecl(hasName("f")));
5787
5788 FunctionDecl *To = Import(From, Lang_CXX17);
5789 EXPECT_TRUE(To);
5790 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5791}
5792
5793TEST_P(ImportAutoFunctions, ReturnWithTypeInIf) {
5794 Decl *FromTU = getTuDecl(
5795 R"(
5796 auto f() {
5797 if (struct X {} x; true)
5798 return X();
5799 else
5800 return X();
5801 }
5802 )",
5803 Lang_CXX17, "input0.cc");
5804 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5805 FromTU, functionDecl(hasName("f")));
5806
5807 FunctionDecl *To = Import(From, Lang_CXX17);
5808 EXPECT_TRUE(To);
5809 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5810}
5811
5812TEST_P(ImportAutoFunctions, ReturnWithTypeInFor) {
5813 Decl *FromTU = getTuDecl(
5814 R"(
5815 auto f() {
5816 for (struct X {} x;;)
5817 return X();
5818 }
5819 )",
5820 Lang_CXX17, "input0.cc");
5821 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5822 FromTU, functionDecl(hasName("f")));
5823
5824 FunctionDecl *To = Import(From, Lang_CXX17);
5825 EXPECT_TRUE(To);
5826 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5827}
5828
5829TEST_P(ImportAutoFunctions, ReturnWithTypeInSwitch) {
5830 Decl *FromTU = getTuDecl(
5831 R"(
5832 auto f() {
5833 switch (struct X {} x; 10) {
5834 case 10:
5835 return X();
5836 }
5837 }
5838 )",
5839 Lang_CXX17, "input0.cc");
5840 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5841 FromTU, functionDecl(hasName("f")));
5842
5843 FunctionDecl *To = Import(From, Lang_CXX17);
5844 EXPECT_TRUE(To);
5845 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5846}
5847
Gabor Marton54058b52018-12-17 13:53:12 +00005848INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
5849 DefaultTestValuesForRunOptions, );
5850
Gabor Marton1ad4b992019-07-01 14:19:53 +00005851INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportPath,
5852 ::testing::Values(ArgVector()), );
5853
Gabor Marton19f4f392018-06-25 13:04:37 +00005854INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
5855 DefaultTestValuesForRunOptions, );
5856
5857INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
5858 DefaultTestValuesForRunOptions, );
5859
5860INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
5861 DefaultTestValuesForRunOptions, );
5862
Gabor Marton0b57ccb2019-02-07 16:52:48 +00005863INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
Gabor Marton19f4f392018-06-25 13:04:37 +00005864 DefaultTestValuesForRunOptions, );
5865
Gabor Martonf035b752019-08-27 11:36:10 +00005866INSTANTIATE_TEST_CASE_P(ParameterizedTests, ErrorHandlingTest,
5867 DefaultTestValuesForRunOptions, );
5868
Raphael Isemanne9bc35f2019-04-29 21:02:35 +00005869INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedirectingImporterTest,
5870 DefaultTestValuesForRunOptions, );
5871
Gabor Marton19f4f392018-06-25 13:04:37 +00005872INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
5873 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00005874
Gabor Marton25234fd2019-12-12 17:13:35 +01005875INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportAutoFunctions,
5876 DefaultTestValuesForRunOptions, );
5877
Gabor Martonf035b752019-08-27 11:36:10 +00005878INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionTemplates,
5879 DefaultTestValuesForRunOptions, );
5880
Gabor Martone331e632019-02-18 13:09:27 +00005881INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
5882 DefaultTestValuesForRunOptions, );
5883
Gabor Marton54058b52018-12-17 13:53:12 +00005884INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00005885 DefaultTestValuesForRunOptions, );
5886
Gabor Marton54058b52018-12-17 13:53:12 +00005887INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00005888 DefaultTestValuesForRunOptions, );
5889
Gabor Marton7df342a2018-12-17 12:42:12 +00005890INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
5891 DefaultTestValuesForRunOptions, );
5892
Gabor Marton5254e642018-06-27 13:32:50 +00005893INSTANTIATE_TEST_CASE_P(ParameterizedTests,
5894 ImportFunctionTemplateSpecializations,
5895 DefaultTestValuesForRunOptions, );
5896
Gabor Martonac3a5d62018-09-17 12:04:52 +00005897INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
5898 DefaultTestValuesForRunOptions, );
5899
5900INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
5901 DefaultTestValuesForRunOptions, );
5902
Gabor Martonaefcf512019-07-17 13:47:46 +00005903INSTANTIATE_TEST_CASE_P(ParameterizedTests, LLDBLookupTest,
5904 DefaultTestValuesForRunOptions, );
5905
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00005906} // end namespace ast_matchers
5907} // end namespace clang