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