blob: 36003957d2e1a5a8f93254546d120138bcd26bf4 [file] [log] [blame]
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00001//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00006//
7//===----------------------------------------------------------------------===//
8//
9// Tests for the correct import of AST nodes from one AST context to another.
10//
11//===----------------------------------------------------------------------===//
12
Gabor Marton25234fd2019-12-12 17:13:35 +010013#include "clang/ASTMatchers/ASTMatchers.h"
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000014#include "llvm/ADT/StringMap.h"
Raphael Isemann9f1e81f2020-04-27 10:06:56 +020015#include "llvm/Support/SmallVectorMemoryBuffer.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000016
Gabor Marton3c72fe12019-05-13 10:06:25 +000017#include "clang/AST/DeclContextInternals.h"
Gabor Marton25234fd2019-12-12 17:13:35 +010018#include "gtest/gtest.h"
Gabor Marton3c72fe12019-05-13 10:06:25 +000019
20#include "ASTImporterFixtures.h"
21#include "MatchVerifier.h"
22
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000023namespace clang {
24namespace ast_matchers {
25
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000026using internal::Matcher;
27using internal::BindableMatcher;
28using llvm::StringMap;
29
Gabor Marton19f4f392018-06-25 13:04:37 +000030// Base class for those tests which use the family of `testImport` functions.
Gabor Marton0b57ccb2019-02-07 16:52:48 +000031class TestImportBase : public CompilerOptionSpecificTest,
32 public ::testing::WithParamInterface<ArgVector> {
Adam Baloghe4192a82018-06-15 06:45:39 +000033
Gabor Marton19f4f392018-06-25 13:04:37 +000034 template <typename NodeType>
Balazs Keria1f6b102019-04-08 13:59:15 +000035 llvm::Expected<NodeType> importNode(ASTUnit *From, ASTUnit *To,
36 ASTImporter &Importer, NodeType Node) {
Gabor Marton19f4f392018-06-25 13:04:37 +000037 ASTContext &ToCtx = To->getASTContext();
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000038
Gabor Marton19f4f392018-06-25 13:04:37 +000039 // Add 'From' file to virtual file system so importer can 'find' it
40 // while importing SourceLocations. It is safe to add same file multiple
41 // times - it just isn't replaced.
42 StringRef FromFileName = From->getMainFileName();
43 createVirtualFileIfNeeded(To, FromFileName,
44 From->getBufferForFile(FromFileName));
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000045
Gabor Marton5ac6d492019-05-15 10:29:48 +000046 auto Imported = Importer.Import(Node);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000047
Balazs Keria1f6b102019-04-08 13:59:15 +000048 if (Imported) {
49 // This should dump source locations and assert if some source locations
50 // were not imported.
51 SmallString<1024> ImportChecker;
52 llvm::raw_svector_ostream ToNothing(ImportChecker);
53 ToCtx.getTranslationUnitDecl()->print(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000054
Balazs Keria1f6b102019-04-08 13:59:15 +000055 // This traverses the AST to catch certain bugs like poorly or not
56 // implemented subtrees.
57 (*Imported)->dump(ToNothing);
58 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000059
Gabor Marton19f4f392018-06-25 13:04:37 +000060 return Imported;
61 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000062
Gabor Marton19f4f392018-06-25 13:04:37 +000063 template <typename NodeType>
64 testing::AssertionResult
65 testImport(const std::string &FromCode, const ArgVector &FromArgs,
66 const std::string &ToCode, const ArgVector &ToArgs,
67 MatchVerifier<NodeType> &Verifier,
68 const BindableMatcher<NodeType> &SearchMatcher,
69 const BindableMatcher<NodeType> &VerificationMatcher) {
70 const char *const InputFileName = "input.cc";
71 const char *const OutputFileName = "output.cc";
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000072
Gabor Marton19f4f392018-06-25 13:04:37 +000073 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
74 FromCode, FromArgs, InputFileName),
75 ToAST = tooling::buildASTFromCodeWithArgs(
76 ToCode, ToArgs, OutputFileName);
77
78 ASTContext &FromCtx = FromAST->getASTContext(),
79 &ToCtx = ToAST->getASTContext();
80
81 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
82 FromAST->getFileManager(), false);
83
84 auto FoundNodes = match(SearchMatcher, FromCtx);
85 if (FoundNodes.size() != 1)
86 return testing::AssertionFailure()
87 << "Multiple potential nodes were found!";
88
89 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
90 if (!ToImport)
91 return testing::AssertionFailure() << "Node type mismatch!";
92
93 // Sanity check: the node being imported should match in the same way as
94 // the result node.
95 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
96 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
97
98 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
Balazs Keria1f6b102019-04-08 13:59:15 +000099 if (!Imported) {
100 std::string ErrorText;
101 handleAllErrors(
102 Imported.takeError(),
103 [&ErrorText](const ImportError &Err) { ErrorText = Err.message(); });
104 return testing::AssertionFailure()
105 << "Import failed, error: \"" << ErrorText << "\"!";
106 }
Gabor Marton19f4f392018-06-25 13:04:37 +0000107
Balazs Keria1f6b102019-04-08 13:59:15 +0000108 return Verifier.match(*Imported, WrapperMatcher);
Gabor Marton19f4f392018-06-25 13:04:37 +0000109 }
110
111 template <typename NodeType>
112 testing::AssertionResult
113 testImport(const std::string &FromCode, const ArgVector &FromArgs,
114 const std::string &ToCode, const ArgVector &ToArgs,
115 MatchVerifier<NodeType> &Verifier,
116 const BindableMatcher<NodeType> &VerificationMatcher) {
117 return testImport(
118 FromCode, FromArgs, ToCode, ToArgs, Verifier,
Benjamin Kramer4e3f4f02020-01-29 10:52:25 +0100119 translationUnitDecl(
120 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
Gabor Marton19f4f392018-06-25 13:04:37 +0000121 VerificationMatcher);
122 }
123
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000124protected:
125 ArgVector getExtraArgs() const override { return GetParam(); }
126
Gabor Marton19f4f392018-06-25 13:04:37 +0000127public:
128
129 /// Test how AST node named "declToImport" located in the translation unit
130 /// of "FromCode" virtual file is imported to "ToCode" virtual file.
131 /// The verification is done by running AMatcher over the imported node.
132 template <typename NodeType, typename MatcherType>
133 void testImport(const std::string &FromCode, Language FromLang,
134 const std::string &ToCode, Language ToLang,
135 MatchVerifier<NodeType> &Verifier,
136 const MatcherType &AMatcher) {
137 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
138 ToArgs = getArgVectorForLanguage(ToLang);
139 EXPECT_TRUE(
140 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
141 }
142
143 struct ImportAction {
144 StringRef FromFilename;
145 StringRef ToFilename;
146 // FIXME: Generalize this to support other node kinds.
147 BindableMatcher<Decl> ImportPredicate;
148
149 ImportAction(StringRef FromFilename, StringRef ToFilename,
150 DeclarationMatcher ImportPredicate)
151 : FromFilename(FromFilename), ToFilename(ToFilename),
152 ImportPredicate(ImportPredicate) {}
153
154 ImportAction(StringRef FromFilename, StringRef ToFilename,
155 const std::string &DeclName)
156 : FromFilename(FromFilename), ToFilename(ToFilename),
157 ImportPredicate(namedDecl(hasName(DeclName))) {}
158 };
159
160 using SingleASTUnit = std::unique_ptr<ASTUnit>;
161 using AllASTUnits = StringMap<SingleASTUnit>;
162
163 struct CodeEntry {
164 std::string CodeSample;
165 Language Lang;
166 };
167
168 using CodeFiles = StringMap<CodeEntry>;
169
170 /// Builds an ASTUnit for one potential compile options set.
171 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
172 ArgVector Args = getArgVectorForLanguage(CE.Lang);
173 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
174 EXPECT_TRUE(AST.get());
175 return AST;
176 }
177
178 /// Test an arbitrary sequence of imports for a set of given in-memory files.
179 /// The verification is done by running VerificationMatcher against a
180 /// specified AST node inside of one of given files.
181 /// \param CodeSamples Map whose key is the file name and the value is the
182 /// file content.
183 /// \param ImportActions Sequence of imports. Each import in sequence
184 /// specifies "from file" and "to file" and a matcher that is used for
185 /// searching a declaration for import in "from file".
186 /// \param FileForFinalCheck Name of virtual file for which the final check is
187 /// applied.
188 /// \param FinalSelectPredicate Matcher that specifies the AST node in the
189 /// FileForFinalCheck for which the verification will be done.
190 /// \param VerificationMatcher Matcher that will be used for verification
191 /// after all imports in sequence are done.
192 void testImportSequence(const CodeFiles &CodeSamples,
193 const std::vector<ImportAction> &ImportActions,
194 StringRef FileForFinalCheck,
195 BindableMatcher<Decl> FinalSelectPredicate,
196 BindableMatcher<Decl> VerificationMatcher) {
197 AllASTUnits AllASTs;
198 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
199 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
200
201 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
202 if (!AllASTs.count(Filename)) {
203 auto Found = CodeSamples.find(Filename);
204 assert(Found != CodeSamples.end() && "Wrong file for import!");
205 AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
206 }
207 };
208
209 for (const ImportAction &Action : ImportActions) {
210 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
211 GenASTsIfNeeded(FromFile);
212 GenASTsIfNeeded(ToFile);
213
214 ASTUnit *From = AllASTs[FromFile].get();
215 ASTUnit *To = AllASTs[ToFile].get();
216
217 // Create a new importer if needed.
218 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
219 if (!ImporterRef)
220 ImporterRef.reset(new ASTImporter(
221 To->getASTContext(), To->getFileManager(), From->getASTContext(),
222 From->getFileManager(), false));
223
224 // Find the declaration and import it.
225 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
226 From->getASTContext());
227 EXPECT_TRUE(FoundDecl.size() == 1);
228 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
229 auto Imported = importNode(From, To, *ImporterRef, ToImport);
Balazs Keria1f6b102019-04-08 13:59:15 +0000230 EXPECT_TRUE(static_cast<bool>(Imported));
231 if (!Imported)
232 llvm::consumeError(Imported.takeError());
Gabor Marton19f4f392018-06-25 13:04:37 +0000233 }
234
235 // Find the declaration and import it.
236 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
237 AllASTs[FileForFinalCheck]->getASTContext());
238 EXPECT_TRUE(FoundDecl.size() == 1);
239 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
240 MatchVerifier<Decl> Verifier;
241 EXPECT_TRUE(
242 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
243 }
244};
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000245
Gabor Martonf086fa82018-07-17 12:06:36 +0000246template <typename T> RecordDecl *getRecordDecl(T *D) {
247 auto *ET = cast<ElaboratedType>(D->getType().getTypePtr());
248 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
Nico Weberb980b5c2018-07-17 14:20:02 +0000249}
Gabor Martonf086fa82018-07-17 12:06:36 +0000250
Gabor Martonbc5b7e22019-12-04 17:12:08 +0100251static const RecordDecl *getRecordDeclOfFriend(FriendDecl *FD) {
252 QualType Ty = FD->getFriendType()->getType().getCanonicalType();
253 return cast<RecordType>(Ty)->getDecl();
254}
255
Gabor Marton19f4f392018-06-25 13:04:37 +0000256struct ImportExpr : TestImportBase {};
257struct ImportType : TestImportBase {};
258struct ImportDecl : TestImportBase {};
Vince Bridgers789215d2020-04-06 08:22:35 -0500259struct ImportFixedPointExpr : ImportExpr {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000260
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000261struct CanonicalRedeclChain : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +0000262
263TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
264 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
265 auto Pattern = functionDecl(hasName("f"));
266 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
267
268 auto Redecls = getCanonicalForwardRedeclChain(D0);
269 ASSERT_EQ(Redecls.size(), 1u);
270 EXPECT_EQ(D0, Redecls[0]);
271}
272
273TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
274 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
275 auto Pattern = functionDecl(hasName("f"));
276 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
277 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
278 FunctionDecl *D1 = D2->getPreviousDecl();
279
280 auto Redecls = getCanonicalForwardRedeclChain(D0);
281 ASSERT_EQ(Redecls.size(), 3u);
282 EXPECT_EQ(D0, Redecls[0]);
283 EXPECT_EQ(D1, Redecls[1]);
284 EXPECT_EQ(D2, Redecls[2]);
285}
286
287TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
288 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
289 auto Pattern = functionDecl(hasName("f"));
290 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
291 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
292 FunctionDecl *D1 = D2->getPreviousDecl();
293
294 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
295 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
296 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
297
298 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
299 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
300}
301
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000302namespace {
303struct RedirectingImporter : public ASTImporter {
304 using ASTImporter::ASTImporter;
305
306protected:
307 llvm::Expected<Decl *> ImportImpl(Decl *FromD) override {
308 auto *ND = dyn_cast<NamedDecl>(FromD);
309 if (!ND || ND->getName() != "shouldNotBeImported")
310 return ASTImporter::ImportImpl(FromD);
311 for (Decl *D : getToContext().getTranslationUnitDecl()->decls()) {
312 if (auto *ND = dyn_cast<NamedDecl>(D))
313 if (ND->getName() == "realDecl") {
314 RegisterImportedDecl(FromD, ND);
315 return ND;
316 }
317 }
318 return ASTImporter::ImportImpl(FromD);
319 }
320};
321
322} // namespace
323
324struct RedirectingImporterTest : ASTImporterOptionSpecificTestBase {
325 RedirectingImporterTest() {
326 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
327 ASTContext &FromContext, FileManager &FromFileManager,
Gabor Marton2afbfb62019-07-01 15:37:07 +0000328 bool MinimalImport,
329 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000330 return new RedirectingImporter(ToContext, ToFileManager, FromContext,
331 FromFileManager, MinimalImport,
Gabor Marton2afbfb62019-07-01 15:37:07 +0000332 SharedState);
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000333 };
334 }
335};
336
337// Test that an ASTImporter subclass can intercept an import call.
338TEST_P(RedirectingImporterTest, InterceptImport) {
339 Decl *From, *To;
340 std::tie(From, To) =
341 getImportedDecl("class shouldNotBeImported {};", Lang_CXX,
342 "class realDecl {};", Lang_CXX, "shouldNotBeImported");
343 auto *Imported = cast<CXXRecordDecl>(To);
344 EXPECT_EQ(Imported->getQualifiedNameAsString(), "realDecl");
345
346 // Make sure our importer prevented the importing of the decl.
347 auto *ToTU = Imported->getTranslationUnitDecl();
348 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
349 unsigned count =
350 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
351 EXPECT_EQ(0U, count);
352}
353
354// Test that when we indirectly import a declaration the custom ASTImporter
355// is still intercepting the import.
356TEST_P(RedirectingImporterTest, InterceptIndirectImport) {
357 Decl *From, *To;
358 std::tie(From, To) =
359 getImportedDecl("class shouldNotBeImported {};"
360 "class F { shouldNotBeImported f; };",
361 Lang_CXX, "class realDecl {};", Lang_CXX, "F");
362
363 // Make sure our ASTImporter prevented the importing of the decl.
364 auto *ToTU = To->getTranslationUnitDecl();
365 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
366 unsigned count =
367 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
368 EXPECT_EQ(0U, count);
369}
370
Gabor Marton1ad4b992019-07-01 14:19:53 +0000371struct ImportPath : ASTImporterOptionSpecificTestBase {
372 Decl *FromTU;
373 FunctionDecl *D0, *D1, *D2;
374 ImportPath() {
375 FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
376 auto Pattern = functionDecl(hasName("f"));
377 D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
378 D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
379 D1 = D2->getPreviousDecl();
380 }
381};
382
383TEST_P(ImportPath, Push) {
384 ASTImporter::ImportPathTy path;
385 path.push(D0);
386 EXPECT_FALSE(path.hasCycleAtBack());
387}
388
389TEST_P(ImportPath, SmallCycle) {
390 ASTImporter::ImportPathTy path;
391 path.push(D0);
392 path.push(D0);
393 EXPECT_TRUE(path.hasCycleAtBack());
394 path.pop();
395 EXPECT_FALSE(path.hasCycleAtBack());
396 path.push(D0);
397 EXPECT_TRUE(path.hasCycleAtBack());
398}
399
400TEST_P(ImportPath, GetSmallCycle) {
401 ASTImporter::ImportPathTy path;
402 path.push(D0);
403 path.push(D0);
404 EXPECT_TRUE(path.hasCycleAtBack());
405 std::array<Decl* ,2> Res;
406 int i = 0;
407 for (Decl *Di : path.getCycleAtBack()) {
408 Res[i++] = Di;
409 }
410 ASSERT_EQ(i, 2);
411 EXPECT_EQ(Res[0], D0);
412 EXPECT_EQ(Res[1], D0);
413}
414
415TEST_P(ImportPath, GetCycle) {
416 ASTImporter::ImportPathTy path;
417 path.push(D0);
418 path.push(D1);
419 path.push(D2);
420 path.push(D0);
421 EXPECT_TRUE(path.hasCycleAtBack());
422 std::array<Decl* ,4> Res;
423 int i = 0;
424 for (Decl *Di : path.getCycleAtBack()) {
425 Res[i++] = Di;
426 }
427 ASSERT_EQ(i, 4);
428 EXPECT_EQ(Res[0], D0);
429 EXPECT_EQ(Res[1], D2);
430 EXPECT_EQ(Res[2], D1);
431 EXPECT_EQ(Res[3], D0);
432}
433
434TEST_P(ImportPath, CycleAfterCycle) {
435 ASTImporter::ImportPathTy path;
436 path.push(D0);
437 path.push(D1);
438 path.push(D0);
439 path.push(D1);
440 path.push(D2);
441 path.push(D0);
442 EXPECT_TRUE(path.hasCycleAtBack());
443 std::array<Decl* ,4> Res;
444 int i = 0;
445 for (Decl *Di : path.getCycleAtBack()) {
446 Res[i++] = Di;
447 }
448 ASSERT_EQ(i, 4);
449 EXPECT_EQ(Res[0], D0);
450 EXPECT_EQ(Res[1], D2);
451 EXPECT_EQ(Res[2], D1);
452 EXPECT_EQ(Res[3], D0);
453
454 path.pop();
455 path.pop();
456 path.pop();
457 EXPECT_TRUE(path.hasCycleAtBack());
458 i = 0;
459 for (Decl *Di : path.getCycleAtBack()) {
460 Res[i++] = Di;
461 }
462 ASSERT_EQ(i, 3);
463 EXPECT_EQ(Res[0], D0);
464 EXPECT_EQ(Res[1], D1);
465 EXPECT_EQ(Res[2], D0);
466
467 path.pop();
468 EXPECT_FALSE(path.hasCycleAtBack());
469}
470
Gabor Marton19f4f392018-06-25 13:04:37 +0000471TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000472 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000473 testImport(
474 "void declToImport() { (void)\"foo\"; }",
475 Lang_CXX, "", Lang_CXX, Verifier,
476 functionDecl(hasDescendant(
477 stringLiteral(hasType(asString("const char [4]"))))));
478 testImport(
479 "void declToImport() { (void)L\"foo\"; }",
480 Lang_CXX, "", Lang_CXX, Verifier,
481 functionDecl(hasDescendant(
482 stringLiteral(hasType(asString("const wchar_t [4]"))))));
483 testImport(
484 "void declToImport() { (void) \"foo\" \"bar\"; }",
485 Lang_CXX, "", Lang_CXX, Verifier,
486 functionDecl(hasDescendant(
487 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000488}
489
Tom Roeder521f0042019-02-26 19:26:41 +0000490TEST_P(ImportExpr, ImportChooseExpr) {
491 MatchVerifier<Decl> Verifier;
492
493 // This case tests C code that is not condition-dependent and has a true
494 // condition.
495 testImport(
496 "void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }",
497 Lang_C, "", Lang_C, Verifier,
498 functionDecl(hasDescendant(chooseExpr())));
499}
500
Gabor Marton19f4f392018-06-25 13:04:37 +0000501TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000502 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000503 testImport(
504 "void declToImport() { (void)__null; }",
505 Lang_CXX, "", Lang_CXX, Verifier,
506 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000507}
508
Gabor Marton19f4f392018-06-25 13:04:37 +0000509TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000510 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000511 testImport(
512 "void declToImport() { (void)nullptr; }",
513 Lang_CXX11, "", Lang_CXX11, Verifier,
514 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000515}
516
517
Gabor Marton19f4f392018-06-25 13:04:37 +0000518TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000519 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000520 testImport(
521 "void declToImport() { (void)1.0; }",
522 Lang_C, "", Lang_C, Verifier,
523 functionDecl(hasDescendant(
524 floatLiteral(equals(1.0), hasType(asString("double"))))));
525 testImport(
526 "void declToImport() { (void)1.0e-5f; }",
527 Lang_C, "", Lang_C, Verifier,
528 functionDecl(hasDescendant(
529 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000530}
531
Vince Bridgers789215d2020-04-06 08:22:35 -0500532TEST_P(ImportFixedPointExpr, ImportFixedPointerLiteralExpr) {
533 MatchVerifier<Decl> Verifier;
534 testImport("void declToImport() { (void)1.0k; }", Lang_C, "", Lang_C,
535 Verifier, functionDecl(hasDescendant(fixedPointLiteral())));
536 testImport("void declToImport() { (void)0.75r; }", Lang_C, "", Lang_C,
537 Verifier, functionDecl(hasDescendant(fixedPointLiteral())));
538}
539
Gabor Martonbf7f18b2018-08-09 12:18:07 +0000540TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
541 MatchVerifier<Decl> Verifier;
542 testImport(
543 "void declToImport() { (void)1.0i; }",
544 Lang_CXX14, "", Lang_CXX14, Verifier,
545 functionDecl(hasDescendant(imaginaryLiteral())));
546}
547
Gabor Marton19f4f392018-06-25 13:04:37 +0000548TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000549 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000550 testImport(
551 "void declToImport() {"
552 " struct s { int x; long y; unsigned z; }; "
553 " (void)(struct s){ 42, 0L, 1U }; }",
554 Lang_CXX, "", Lang_CXX, Verifier,
555 functionDecl(hasDescendant(
556 compoundLiteralExpr(
557 hasType(asString("struct s")),
558 has(initListExpr(
559 hasType(asString("struct s")),
560 has(integerLiteral(
561 equals(42), hasType(asString("int")))),
562 has(integerLiteral(
563 equals(0), hasType(asString("long")))),
564 has(integerLiteral(
565 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000566}
567
Gabor Marton19f4f392018-06-25 13:04:37 +0000568TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000569 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000570 testImport(
571 "class declToImport { void f() { (void)this; } };",
572 Lang_CXX, "", Lang_CXX, Verifier,
573 cxxRecordDecl(
574 hasMethod(
575 hasDescendant(
576 cxxThisExpr(
577 hasType(
578 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000579}
580
Gabor Marton19f4f392018-06-25 13:04:37 +0000581TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000582 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000583 testImport(
584 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
585 Lang_C, "", Lang_C, Verifier,
586 functionDecl(hasDescendant(
587 atomicExpr(
588 has(ignoringParenImpCasts(
589 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
590 hasType(asString("int *"))))),
591 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000592}
593
Gabor Marton19f4f392018-06-25 13:04:37 +0000594TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000595 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000596 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000597 "void declToImport() { loop: goto loop; (void)&&loop; }",
598 Lang_C, "", Lang_C, Verifier,
599 functionDecl(
600 hasDescendant(
601 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
602 hasDescendant(
603 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000604}
605
606AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
607 internal::Matcher<NamedDecl>, InnerMatcher) {
608 const NamedDecl *Template = Node.getTemplatedDecl();
609 return Template && InnerMatcher.matches(*Template, Finder, Builder);
610}
611
Gabor Marton19f4f392018-06-25 13:04:37 +0000612TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000613 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000614 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000615 "template<typename T> class dummy { void f() { dummy X(*this); } };"
616 "typedef dummy<int> declToImport;"
617 "template class dummy<int>;",
618 Lang_CXX, "", Lang_CXX, Verifier,
619 typedefDecl(hasType(templateSpecializationType(
620 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
621 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
622 hasName("f"),
623 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
624 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
625 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000626 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000627}
628
Gabor Marton19f4f392018-06-25 13:04:37 +0000629TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000630 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000631 testImport(
632 "void declToImport() { int b; switch (b) { case 1: break; } }",
633 Lang_C, "", Lang_C, Verifier,
634 functionDecl(hasDescendant(
635 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000636}
637
Gabor Marton19f4f392018-06-25 13:04:37 +0000638TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000639 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000640 testImport(
641 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
642 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000643 functionDecl(hasDescendant(
644 varDecl(
645 hasName("C"),
646 hasType(asString("int")),
647 hasInitializer(
648 stmtExpr(
649 hasAnySubstatement(declStmt(hasSingleDecl(
650 varDecl(
651 hasName("X"),
652 hasType(asString("int")),
653 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000654 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000655 hasDescendant(
656 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000657}
658
Gabor Marton19f4f392018-06-25 13:04:37 +0000659TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000660 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000661 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000662 "void declToImport() { (void)(true ? 1 : -5); }",
663 Lang_CXX, "", Lang_CXX, Verifier,
664 functionDecl(hasDescendant(
665 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000666 hasCondition(cxxBoolLiteral(equals(true))),
667 hasTrueExpression(integerLiteral(equals(1))),
668 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000669 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
670 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000671}
672
Gabor Marton19f4f392018-06-25 13:04:37 +0000673TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000674 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000675 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000676 "void declToImport() { (void)(1 ?: -5); }",
677 Lang_CXX, "", Lang_CXX, Verifier,
678 functionDecl(hasDescendant(
679 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000680 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000681 implicitCastExpr(
682 hasSourceExpression(opaqueValueExpr(
683 hasSourceExpression(integerLiteral(equals(1))))),
684 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000685 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000686 opaqueValueExpr(
687 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000688 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000689 unaryOperator(
690 hasOperatorName("-"),
691 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000692}
693
Gabor Marton19f4f392018-06-25 13:04:37 +0000694TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000695 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000696 testImport(
697 "void declToImport() {"
698 " struct point { double x; double y; };"
699 " struct point ptarray[10] = "
700 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
701 Lang_C, "", Lang_C, Verifier,
702 functionDecl(hasDescendant(
703 initListExpr(
704 has(designatedInitExpr(
705 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000706 hasDescendant(floatLiteral(equals(1.0))),
707 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000708 has(designatedInitExpr(
709 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000710 hasDescendant(floatLiteral(equals(2.0))),
711 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000712 has(designatedInitExpr(
713 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000714 hasDescendant(floatLiteral(equals(1.0))),
715 hasDescendant(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000716}
717
Gabor Marton19f4f392018-06-25 13:04:37 +0000718TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000719 MatchVerifier<Decl> Verifier;
720 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000721 testImport(
722 "void declToImport() { (void)__func__; }",
723 Lang_CXX, "", Lang_CXX, Verifier,
724 functionDecl(hasDescendant(
725 predefinedExpr(
726 hasType(
727 asString("const char [13]")),
728 has(stringLiteral(hasType(
729 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000730}
731
Gabor Marton19f4f392018-06-25 13:04:37 +0000732TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000733 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000734 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000735 "void declToImport() {"
736 " struct point { double x; double y; };"
737 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
738 " [0].x = 1.0 }; }",
739 Lang_CXX, "", Lang_CXX, Verifier,
740 functionDecl(hasDescendant(
741 initListExpr(
742 has(
743 cxxConstructExpr(
744 requiresZeroInitialization())),
745 has(
746 initListExpr(
747 hasType(asString("struct point")),
748 has(floatLiteral(equals(1.0))),
749 has(implicitValueInitExpr(
750 hasType(asString("double")))))),
751 has(
752 initListExpr(
753 hasType(asString("struct point")),
754 has(floatLiteral(equals(2.0))),
755 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000756}
757
758
Aleksei Sidorina693b372016-09-28 10:16:56 +0000759const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
760
Gabor Marton19f4f392018-06-25 13:04:37 +0000761TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000762 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000763 testImport(
764 "void declToImport(__builtin_va_list list, ...) {"
765 " (void)__builtin_va_arg(list, int); }",
766 Lang_CXX, "", Lang_CXX, Verifier,
767 functionDecl(hasDescendant(
768 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000769}
770
Gabor Marton19f4f392018-06-25 13:04:37 +0000771TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000772 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000773 testImport(
774 "struct C {};"
775 "void declToImport() { C c = C(); }",
776 Lang_CXX, "", Lang_CXX, Verifier,
777 functionDecl(hasDescendant(
778 exprWithCleanups(has(cxxConstructExpr(
779 has(materializeTemporaryExpr(has(implicitCastExpr(
780 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000781}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000782
Gabor Marton19f4f392018-06-25 13:04:37 +0000783TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000784 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000785 testImport(
786 "void declToImport() { typedef _Atomic(int) a_int; }",
787 Lang_CXX11, "", Lang_CXX11, Verifier,
788 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000789}
790
Gabor Marton19f4f392018-06-25 13:04:37 +0000791TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000792 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000793 testImport(
794 "template <typename T> void declToImport() { };",
795 Lang_CXX, "", Lang_CXX, Verifier,
796 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000797}
798
Gabor Marton19f4f392018-06-25 13:04:37 +0000799TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000800 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000801 testImport(
802 "template <typename T> struct C { T t; };"
803 "template <typename T> void declToImport() {"
804 " C<T> d;"
805 " (void)d.t;"
806 "}"
807 "void instantiate() { declToImport<int>(); }",
808 Lang_CXX, "", Lang_CXX, Verifier,
809 functionTemplateDecl(hasDescendant(
810 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
811 testImport(
812 "template <typename T> struct C { T t; };"
813 "template <typename T> void declToImport() {"
814 " C<T> d;"
815 " (void)(&d)->t;"
816 "}"
817 "void instantiate() { declToImport<int>(); }",
818 Lang_CXX, "", Lang_CXX, Verifier,
819 functionTemplateDecl(hasDescendant(
820 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000821}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000822
Gabor Marton19f4f392018-06-25 13:04:37 +0000823TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000824 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000825 testImport(
826 "template <int K>"
827 "struct dummy { static const int i = K; };"
828 "template <int K> using dummy2 = dummy<K>;"
829 "int declToImport() { return dummy2<3>::i; }",
830 Lang_CXX11, "", Lang_CXX11, Verifier,
831 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000832 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000833 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
834}
835
836const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
837 varTemplateSpecializationDecl;
838
Gabor Marton19f4f392018-06-25 13:04:37 +0000839TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000840 MatchVerifier<Decl> Verifier;
841 testImport(
842 "template <typename T>"
843 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000844 "void declToImport() { (void)pi<int>; }",
845 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000846 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000847 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000848 unless(hasAncestor(translationUnitDecl(has(varDecl(
849 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000850}
851
Gabor Marton19f4f392018-06-25 13:04:37 +0000852TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000853 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000854 testImport(
855 "template <typename... Args>"
856 "struct dummy {"
857 " dummy(Args... args) {}"
858 " static const int i = 4;"
859 "};"
860 "int declToImport() { return dummy<int>::i; }",
861 Lang_CXX11, "", Lang_CXX11, Verifier,
862 functionDecl(hasDescendant(
863 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000864}
865
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000866const internal::VariadicDynCastAllOfMatcher<Type,
867 DependentTemplateSpecializationType>
868 dependentTemplateSpecializationType;
869
Gabor Marton19f4f392018-06-25 13:04:37 +0000870TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000871 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000872 testImport(
873 "template<typename T>"
874 "struct A;"
875 "template<typename T>"
876 "struct declToImport {"
877 " typename A<T>::template B<T> a;"
878 "};",
879 Lang_CXX, "", Lang_CXX, Verifier,
880 classTemplateDecl(has(cxxRecordDecl(has(
881 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000882}
883
884const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
885 sizeOfPackExpr;
886
Gabor Marton19f4f392018-06-25 13:04:37 +0000887TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000888 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000889 testImport(
890 "template <typename... Ts>"
891 "void declToImport() {"
892 " const int i = sizeof...(Ts);"
893 "};"
894 "void g() { declToImport<int>(); }",
895 Lang_CXX11, "", Lang_CXX11, Verifier,
896 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000897 testImport(
898 "template <typename... Ts>"
899 "using X = int[sizeof...(Ts)];"
900 "template <typename... Us>"
901 "struct Y {"
902 " X<Us..., int, double, int, Us...> f;"
903 "};"
904 "Y<float, int> declToImport;",
905 Lang_CXX11, "", Lang_CXX11, Verifier,
906 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
907 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
908}
909
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000910/// \brief Matches __builtin_types_compatible_p:
911/// GNU extension to check equivalent types
912/// Given
913/// \code
914/// __builtin_types_compatible_p(int, int)
915/// \endcode
916// will generate TypeTraitExpr <...> 'int'
917const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
918
Gabor Marton19f4f392018-06-25 13:04:37 +0000919TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000920 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000921 testImport(
922 "void declToImport() { "
923 " (void)__builtin_types_compatible_p(int, int);"
924 "}",
925 Lang_C, "", Lang_C, Verifier,
926 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000927}
928
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000929const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
930
Gabor Marton19f4f392018-06-25 13:04:37 +0000931TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000932 MatchVerifier<Decl> Verifier;
933 testImport(
934 "namespace std { class type_info {}; }"
935 "void declToImport() {"
936 " int x;"
937 " auto a = typeid(int); auto b = typeid(x);"
938 "}",
939 Lang_CXX11, "", Lang_CXX11, Verifier,
940 functionDecl(
941 hasDescendant(varDecl(
942 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
943 hasDescendant(varDecl(
944 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
945}
946
Gabor Marton19f4f392018-06-25 13:04:37 +0000947TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000948 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000949 testImport(
950 "template<typename T> struct declToImport {"
951 " void m() { (void)__is_pod(T); }"
952 "};"
953 "void f() { declToImport<int>().m(); }",
954 Lang_CXX11, "", Lang_CXX11, Verifier,
955 classTemplateDecl(has(cxxRecordDecl(has(
956 functionDecl(hasDescendant(
957 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000958}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000959
Gabor Marton6e1510c2018-07-12 11:50:21 +0000960TEST_P(ImportDecl, ImportRecordDeclInFunc) {
961 MatchVerifier<Decl> Verifier;
962 testImport("int declToImport() { "
963 " struct data_t {int a;int b;};"
964 " struct data_t d;"
965 " return 0;"
966 "}",
967 Lang_C, "", Lang_C, Verifier,
968 functionDecl(hasBody(compoundStmt(
969 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
970}
971
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000972TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000973 Decl *FromTU = getTuDecl("int declToImport() { "
974 " struct data_t {int a;int b;};"
975 " struct data_t d;"
976 " return 0;"
977 "}",
978 Lang_C, "input.c");
Gabor Martonfe68e292018-08-06 14:38:37 +0000979 auto *FromVar =
Gabor Marton6e1510c2018-07-12 11:50:21 +0000980 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
981 ASSERT_TRUE(FromVar);
982 auto ToType =
983 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
984 EXPECT_FALSE(ToType.isNull());
985}
986
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000987TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000988 // This construct is not supported by ASTImporter.
Gabor Martonfe68e292018-08-06 14:38:37 +0000989 Decl *FromTU = getTuDecl(
990 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
991 Lang_C, "input.c");
992 auto *From = FirstDeclMatcher<FunctionDecl>().match(
993 FromTU, functionDecl(hasName("declToImport")));
Gabor Marton6e1510c2018-07-12 11:50:21 +0000994 ASSERT_TRUE(From);
Gabor Martonfe68e292018-08-06 14:38:37 +0000995 auto *To = Import(From, Lang_C);
996 EXPECT_EQ(To, nullptr);
997}
998
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000999TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +00001000 Decl *FromTU = getTuDecl(
1001 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
1002 "int declToImport(){ return NONAME_SIZEOF(int); }",
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);
1008 ASSERT_TRUE(To);
1009 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
1010 To, functionDecl(hasName("declToImport"),
1011 hasDescendant(unaryExprOrTypeTraitExpr()))));
1012}
1013
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001014TEST_P(ASTImporterOptionSpecificTestBase,
1015 ImportRecordDeclInFuncParamsFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +00001016 // This construct is not supported by ASTImporter.
1017 Decl *FromTU = getTuDecl(
1018 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
1019 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
1020 Lang_C, "input.c");
1021 auto *From = FirstDeclMatcher<FunctionDecl>().match(
1022 FromTU, functionDecl(hasName("declToImport")));
1023 ASSERT_TRUE(From);
1024 auto *To = Import(From, Lang_C);
Gabor Marton6e1510c2018-07-12 11:50:21 +00001025 EXPECT_EQ(To, nullptr);
1026}
1027
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001028const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
1029 cxxPseudoDestructorExpr;
1030
Gabor Marton19f4f392018-06-25 13:04:37 +00001031TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001032 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001033 testImport(
1034 "typedef int T;"
1035 "void declToImport(int *p) {"
1036 " T t;"
1037 " p->T::~T();"
1038 "}",
1039 Lang_CXX, "", Lang_CXX, Verifier,
1040 functionDecl(hasDescendant(
1041 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +00001042}
1043
Gabor Marton19f4f392018-06-25 13:04:37 +00001044TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001045 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001046 testImport(
1047 "namespace foo { int bar; }"
1048 "void declToImport() { using foo::bar; }",
1049 Lang_CXX, "", Lang_CXX, Verifier,
1050 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001051}
1052
1053/// \brief Matches shadow declarations introduced into a scope by a
1054/// (resolved) using declaration.
1055///
1056/// Given
1057/// \code
1058/// namespace n { int f; }
1059/// namespace declToImport { using n::f; }
1060/// \endcode
1061/// usingShadowDecl()
1062/// matches \code f \endcode
1063const internal::VariadicDynCastAllOfMatcher<Decl,
1064 UsingShadowDecl> usingShadowDecl;
1065
Gabor Marton19f4f392018-06-25 13:04:37 +00001066TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001067 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001068 testImport(
1069 "namespace foo { int bar; }"
1070 "namespace declToImport { using foo::bar; }",
1071 Lang_CXX, "", Lang_CXX, Verifier,
1072 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +00001073}
1074
Gabor Marton19f4f392018-06-25 13:04:37 +00001075TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001076 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001077 testImport(
1078 "template<typename T> int foo();"
1079 "template <typename T> void declToImport() {"
1080 " (void)::foo<T>;"
1081 " (void)::template foo<T>;"
1082 "}"
1083 "void instantiate() { declToImport<int>(); }",
1084 Lang_CXX, "", Lang_CXX, Verifier,
1085 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001086}
1087
Gabor Marton19f4f392018-06-25 13:04:37 +00001088TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001089 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001090 testImport(
1091 "template <typename T> struct C { T t; };"
1092 "template <typename T> void declToImport() {"
1093 " C<T> d;"
1094 " d.t = T();"
1095 "}"
1096 "void instantiate() { declToImport<int>(); }",
1097 Lang_CXX, "", Lang_CXX, Verifier,
1098 functionTemplateDecl(hasDescendant(
1099 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1100 testImport(
1101 "template <typename T> struct C { T t; };"
1102 "template <typename T> void declToImport() {"
1103 " C<T> d;"
1104 " (&d)->t = T();"
1105 "}"
1106 "void instantiate() { declToImport<int>(); }",
1107 Lang_CXX, "", Lang_CXX, Verifier,
1108 functionTemplateDecl(hasDescendant(
1109 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +00001110}
1111
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001112/// Check that function "declToImport()" (which is the templated function
1113/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1114/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +00001115TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001116 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001117 testImport(
1118 "template <typename T> void declToImport() { T a = 1; }"
1119 "void instantiate() { declToImport<int>(); }",
1120 Lang_CXX, "", Lang_CXX, Verifier,
1121 functionTemplateDecl(hasAncestor(translationUnitDecl(
1122 unless(has(functionDecl(hasName("declToImport"))))))));
1123 testImport(
1124 "template <typename T> struct declToImport { T t; };"
1125 "void instantiate() { declToImport<int>(); }",
1126 Lang_CXX, "", Lang_CXX, Verifier,
1127 classTemplateDecl(hasAncestor(translationUnitDecl(
1128 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001129}
1130
Gabor Marton19f4f392018-06-25 13:04:37 +00001131TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001132 MatchVerifier<Decl> Verifier;
1133 auto Code =
1134 R"s(
1135 struct declToImport {
1136 template <typename T0> struct X;
1137 template <typename T0> struct X<T0 *> {};
1138 };
1139 )s";
1140 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1141 recordDecl(has(classTemplateDecl()),
1142 has(classTemplateSpecializationDecl())));
1143}
1144
Gabor Marton19f4f392018-06-25 13:04:37 +00001145TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001146 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001147 testImport(
1148 "class declToImport {"
1149 " void f() { *this = declToImport(); }"
1150 "};",
1151 Lang_CXX, "", Lang_CXX, Verifier,
1152 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1153 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001154}
1155
Gabor Marton19f4f392018-06-25 13:04:37 +00001156TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001157 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001158 testImport(
1159 "template<typename T, int Size> class declToImport {"
1160 " T data[Size];"
1161 "};",
1162 Lang_CXX, "", Lang_CXX, Verifier,
1163 classTemplateDecl(has(cxxRecordDecl(
1164 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001165}
1166
Balazs Keri5f4fd8b2019-03-14 14:20:23 +00001167TEST_P(ASTImporterOptionSpecificTestBase, ImportBeginLocOfDeclRefExpr) {
1168 Decl *FromTU = getTuDecl(
1169 "class A { public: static int X; }; void f() { (void)A::X; }", Lang_CXX);
1170 auto From = FirstDeclMatcher<FunctionDecl>().match(
1171 FromTU, functionDecl(hasName("f")));
1172 ASSERT_TRUE(From);
1173 ASSERT_TRUE(
1174 cast<CStyleCastExpr>(cast<CompoundStmt>(From->getBody())->body_front())
1175 ->getSubExpr()
1176 ->getBeginLoc()
1177 .isValid());
1178 FunctionDecl *To = Import(From, Lang_CXX);
1179 ASSERT_TRUE(To);
1180 ASSERT_TRUE(
1181 cast<CStyleCastExpr>(cast<CompoundStmt>(To->getBody())->body_front())
1182 ->getSubExpr()
1183 ->getBeginLoc()
1184 .isValid());
1185}
1186
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001187TEST_P(ASTImporterOptionSpecificTestBase,
1188 ImportOfTemplatedDeclOfClassTemplateDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001189 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1190 auto From =
1191 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1192 ASSERT_TRUE(From);
1193 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1194 ASSERT_TRUE(To);
1195 Decl *ToTemplated = To->getTemplatedDecl();
1196 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1197 EXPECT_TRUE(ToTemplated1);
1198 EXPECT_EQ(ToTemplated1, ToTemplated);
1199}
1200
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001201TEST_P(ASTImporterOptionSpecificTestBase,
1202 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001203 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1204 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1205 FromTU, functionTemplateDecl());
1206 ASSERT_TRUE(From);
1207 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1208 ASSERT_TRUE(To);
1209 Decl *ToTemplated = To->getTemplatedDecl();
1210 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1211 EXPECT_TRUE(ToTemplated1);
1212 EXPECT_EQ(ToTemplated1, ToTemplated);
1213}
1214
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001215TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton6578a4a2018-06-25 11:38:43 +00001216 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1217 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1218 auto FromFT =
1219 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1220 ASSERT_TRUE(FromFT);
1221
1222 auto ToTemplated =
1223 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1224 EXPECT_TRUE(ToTemplated);
1225 auto ToTU = ToTemplated->getTranslationUnitDecl();
1226 auto ToFT =
1227 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1228 EXPECT_TRUE(ToFT);
1229}
1230
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001231TEST_P(ASTImporterOptionSpecificTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001232 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001233 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1234 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1235 FromTU, functionTemplateDecl());
1236 ASSERT_TRUE(FromFT);
1237
1238 auto ToTemplated =
1239 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1240 EXPECT_TRUE(ToTemplated);
1241 auto ToTU = ToTemplated->getTranslationUnitDecl();
1242 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1243 ToTU, functionTemplateDecl());
1244 EXPECT_TRUE(ToFT);
1245}
1246
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001247TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001248 auto Code =
1249 R"(
1250 namespace x {
1251 template<class X> struct S1{};
1252 template<class X> struct S2{};
1253 template<class X> struct S3{};
1254 }
1255 )";
1256 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1257 auto FromNs =
1258 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1259 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1260 ASSERT_TRUE(ToNs);
1261 auto From =
1262 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1263 classTemplateDecl(
1264 hasName("S2")));
1265 auto To =
1266 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1267 classTemplateDecl(
1268 hasName("S2")));
1269 ASSERT_TRUE(From);
1270 ASSERT_TRUE(To);
1271 auto ToTemplated = To->getTemplatedDecl();
1272 auto ToTemplated1 =
1273 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1274 EXPECT_TRUE(ToTemplated1);
1275 ASSERT_EQ(ToTemplated1, ToTemplated);
1276}
1277
Tom Roeder521f0042019-02-26 19:26:41 +00001278TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {
1279 // This tests the import of isConditionTrue directly to make sure the importer
1280 // gets it right.
1281 Decl *From, *To;
1282 std::tie(From, To) = getImportedDecl(
1283 "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }",
1284 Lang_C, "", Lang_C);
1285
1286 auto ToResults = match(chooseExpr().bind("choose"), To->getASTContext());
1287 auto FromResults = match(chooseExpr().bind("choose"), From->getASTContext());
1288
1289 const ChooseExpr *FromChooseExpr =
1290 selectFirst<ChooseExpr>("choose", FromResults);
1291 ASSERT_TRUE(FromChooseExpr);
1292
1293 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>("choose", ToResults);
1294 ASSERT_TRUE(ToChooseExpr);
1295
1296 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());
1297 EXPECT_EQ(FromChooseExpr->isConditionDependent(),
1298 ToChooseExpr->isConditionDependent());
1299}
1300
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001301TEST_P(ASTImporterOptionSpecificTestBase,
1302 ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001303 Decl *From, *To;
1304 std::tie(From, To) = getImportedDecl(
1305 R"(
1306 template <typename T> struct X {};
1307
1308 void declToImport(int y, X<int> &x) {}
1309
1310 template <> struct X<int> {
1311 void g() {
1312 X<int> x;
1313 declToImport(0, x);
1314 }
1315 };
1316 )",
1317 Lang_CXX, "", Lang_CXX);
1318
1319 MatchVerifier<Decl> Verifier;
1320 auto Matcher = functionDecl(hasName("declToImport"),
1321 parameterCountIs(2),
1322 hasParameter(0, hasName("y")),
1323 hasParameter(1, hasName("x")),
1324 hasParameter(1, hasType(asString("X<int> &"))));
1325 ASSERT_TRUE(Verifier.match(From, Matcher));
1326 EXPECT_TRUE(Verifier.match(To, Matcher));
1327}
1328
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001329TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001330 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1331 Decl *From, *To;
1332 std::tie(From, To) =
1333 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1334 "void instantiate() { declToImport<int>(); }",
1335 Lang_CXX, "", Lang_CXX);
1336
1337 auto Check = [](Decl *D) -> bool {
1338 auto TU = D->getTranslationUnitDecl();
1339 for (auto Child : TU->decls()) {
1340 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1341 if (FD->getNameAsString() == "declToImport") {
1342 GTEST_NONFATAL_FAILURE_(
1343 "TU should not contain any FunctionDecl with name declToImport");
1344 return false;
1345 }
1346 }
1347 }
1348 return true;
1349 };
1350
1351 ASSERT_TRUE(Check(From));
1352 EXPECT_TRUE(Check(To));
1353}
1354
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001355TEST_P(ASTImporterOptionSpecificTestBase,
1356 TUshouldNotContainTemplatedDeclOfClassTemplates) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001357 Decl *From, *To;
1358 std::tie(From, To) =
1359 getImportedDecl("template <typename T> struct declToImport { T t; };"
1360 "void instantiate() { declToImport<int>(); }",
1361 Lang_CXX, "", Lang_CXX);
1362
1363 auto Check = [](Decl *D) -> bool {
1364 auto TU = D->getTranslationUnitDecl();
1365 for (auto Child : TU->decls()) {
1366 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1367 if (RD->getNameAsString() == "declToImport") {
1368 GTEST_NONFATAL_FAILURE_(
1369 "TU should not contain any CXXRecordDecl with name declToImport");
1370 return false;
1371 }
1372 }
1373 }
1374 return true;
1375 };
1376
1377 ASSERT_TRUE(Check(From));
1378 EXPECT_TRUE(Check(To));
1379}
1380
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001381TEST_P(ASTImporterOptionSpecificTestBase,
1382 TUshouldNotContainTemplatedDeclOfTypeAlias) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001383 Decl *From, *To;
1384 std::tie(From, To) =
1385 getImportedDecl(
1386 "template <typename T> struct X {};"
1387 "template <typename T> using declToImport = X<T>;"
1388 "void instantiate() { declToImport<int> a; }",
1389 Lang_CXX11, "", Lang_CXX11);
1390
1391 auto Check = [](Decl *D) -> bool {
1392 auto TU = D->getTranslationUnitDecl();
1393 for (auto Child : TU->decls()) {
1394 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1395 if (AD->getNameAsString() == "declToImport") {
1396 GTEST_NONFATAL_FAILURE_(
1397 "TU should not contain any TypeAliasDecl with name declToImport");
1398 return false;
1399 }
1400 }
1401 }
1402 return true;
1403 };
1404
1405 ASSERT_TRUE(Check(From));
1406 EXPECT_TRUE(Check(To));
1407}
1408
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001409TEST_P(ASTImporterOptionSpecificTestBase,
1410 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001411
1412 Decl *From, *To;
1413 std::tie(From, To) = getImportedDecl(
1414 R"(
1415 template<class T>
1416 class Base {};
1417 class declToImport : public Base<declToImport> {};
1418 )",
1419 Lang_CXX, "", Lang_CXX);
1420
1421 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1422 auto Pattern =
1423 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1424 ASSERT_TRUE(
1425 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1426 EXPECT_TRUE(
1427 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1428
1429 // Check that the ClassTemplateSpecializationDecl is the child of the
1430 // ClassTemplateDecl.
1431 Pattern = translationUnitDecl(has(classTemplateDecl(
1432 hasName("Base"), has(classTemplateSpecializationDecl()))));
1433 ASSERT_TRUE(
1434 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1435 EXPECT_TRUE(
1436 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1437}
1438
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001439AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1440 size_t Index = 0;
Balazs Keri6e086692019-09-02 07:17:01 +00001441 for (Decl *D : Node.decls()) {
1442 if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D)) {
1443 auto *ND = cast<NamedDecl>(D);
1444 if (Index == Order.size())
1445 return false;
1446 if (ND->getName() != Order[Index])
1447 return false;
1448 ++Index;
1449 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001450 }
1451 return Index == Order.size();
1452}
1453
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001454TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001455 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1456 Decl *From, *To;
1457 std::tie(From, To) = getImportedDecl(
1458 R"(
1459 namespace NS {
1460 template<class T>
1461 class X {};
1462 template class X<int>;
1463 }
1464 )",
1465 Lang_CXX, "", Lang_CXX, "NS");
1466
1467 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1468 // ClassTemplateDecl.
1469 auto Pattern = namespaceDecl(has(classTemplateDecl(
1470 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1471 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1472 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1473
1474 // Check that the ClassTemplateSpecializationDecl is the child of the
1475 // NamespaceDecl.
1476 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1477 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1478 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1479}
1480
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001481TEST_P(ASTImporterOptionSpecificTestBase,
1482 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001483 Decl *From, *To;
1484 std::tie(From, To) =
1485 getImportedDecl(
1486 "struct declToImport { int a; int b; };",
1487 Lang_CXX11, "", Lang_CXX11);
1488
1489 MatchVerifier<Decl> Verifier;
1490 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1491 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1492}
1493
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001494TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton48b16e12019-07-25 09:07:17 +00001495 CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001496 Decl *From, *To;
1497 std::tie(From, To) = getImportedDecl(
1498 // The original recursive algorithm of ASTImporter first imports 'c' then
1499 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1500 R"s(
1501 struct declToImport {
1502 int a = c + b;
1503 int b = 1;
1504 int c = 2;
1505 };
1506 )s",
1507 Lang_CXX11, "", Lang_CXX11);
1508
1509 MatchVerifier<Decl> Verifier;
1510 ASSERT_TRUE(
1511 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1512 EXPECT_TRUE(
1513 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1514}
1515
Balazs Keri6e086692019-09-02 07:17:01 +00001516TEST_P(ASTImporterOptionSpecificTestBase,
1517 CXXRecordDeclFieldAndIndirectFieldOrder) {
1518 Decl *From, *To;
1519 std::tie(From, To) = getImportedDecl(
1520 // First field is "a", then the field for unnamed union, then "b" and "c"
1521 // from it (indirect fields), then "d".
1522 R"s(
1523 struct declToImport {
1524 int a = d;
1525 union {
1526 int b;
1527 int c;
1528 };
1529 int d;
1530 };
1531 )s",
1532 Lang_CXX11, "", Lang_CXX11);
1533
1534 MatchVerifier<Decl> Verifier;
1535 ASSERT_TRUE(Verifier.match(
1536 From, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1537 EXPECT_TRUE(Verifier.match(
1538 To, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1539}
1540
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001541TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001542 Decl *From, *To;
1543 std::tie(From, To) = getImportedDecl(
1544 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001545 struct declToImport {
1546 };
1547 )",
1548 Lang_CXX, "", Lang_CXX);
1549
1550 MatchVerifier<Decl> Verifier;
1551 // Match the implicit Decl.
1552 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1553 ASSERT_TRUE(Verifier.match(From, Matcher));
1554 EXPECT_TRUE(Verifier.match(To, Matcher));
1555}
1556
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001557TEST_P(ASTImporterOptionSpecificTestBase,
1558 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
Gabor Martona3af5672018-05-23 14:24:02 +00001559 Decl *From, *To;
1560 std::tie(From, To) = getImportedDecl(
1561 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001562 template <typename U>
1563 struct declToImport {
1564 };
1565 )",
1566 Lang_CXX, "", Lang_CXX);
1567
1568 MatchVerifier<Decl> Verifier;
1569 // Match the implicit Decl.
1570 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1571 ASSERT_TRUE(Verifier.match(From, Matcher));
1572 EXPECT_TRUE(Verifier.match(To, Matcher));
1573}
1574
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001575TEST_P(ASTImporterOptionSpecificTestBase,
1576 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001577 Decl *From, *To;
1578 std::tie(From, To) = getImportedDecl(
1579 R"(
1580 template<class T>
1581 class Base {};
1582 class declToImport : public Base<declToImport> {};
1583 )",
1584 Lang_CXX, "", Lang_CXX);
1585
1586 auto hasImplicitClass = has(cxxRecordDecl());
1587 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1588 hasName("Base"),
1589 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1590 ASSERT_TRUE(
1591 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1592 EXPECT_TRUE(
1593 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1594}
1595
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001596TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001597 Decl *From, *To;
1598 std::tie(From, To) =
1599 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1600
1601 MatchVerifier<Decl> Verifier;
1602 auto Matcher = functionDecl();
1603 ASSERT_TRUE(Verifier.match(From, Matcher));
1604 EXPECT_TRUE(Verifier.match(To, Matcher));
1605 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1606}
1607
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001608TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001609 Decl *FromTU = getTuDecl(
1610 R"(
1611 struct X {};
1612 void operator<<(int, X);
1613 )",
1614 Lang_CXX);
1615 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1616 const Decl *To = Import(From, Lang_CXX);
1617 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1618}
1619
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001620TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001621 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1622 Decl *From, *To;
1623 std::tie(From, To) = getImportedDecl(
1624 R"(
1625 template<class T>
1626 class Base { int a; };
1627 class declToImport : Base<declToImport> {};
1628 )",
1629 Lang_CXX, "", Lang_CXX);
1630
1631 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1632 hasName("Base"),
1633 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1634 ASSERT_TRUE(
1635 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1636 EXPECT_TRUE(
1637 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1638}
1639
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001640TEST_P(ASTImporterOptionSpecificTestBase,
1641 ImportDefinitionOfClassTemplateAfterFwdDecl) {
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001642 {
1643 Decl *FromTU = getTuDecl(
1644 R"(
1645 template <typename T>
1646 struct B;
1647 )",
1648 Lang_CXX, "input0.cc");
1649 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1650 FromTU, classTemplateDecl(hasName("B")));
1651
1652 Import(FromD, Lang_CXX);
1653 }
1654
1655 {
1656 Decl *FromTU = getTuDecl(
1657 R"(
1658 template <typename T>
1659 struct B {
1660 void f();
1661 };
1662 )",
1663 Lang_CXX, "input1.cc");
1664 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1665 FromTU, functionDecl(hasName("f")));
1666 Import(FromD, Lang_CXX);
1667 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1668 FromTU, classTemplateDecl(hasName("B")));
1669 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1670 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1671 }
1672}
1673
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001674TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001675 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1676 Decl *ToTU = getToTuDecl(
1677 R"(
1678 template <typename T>
1679 struct B {
1680 void f();
1681 };
1682
1683 template <typename T>
1684 struct B;
1685 )",
1686 Lang_CXX);
1687 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1688 [](const ClassTemplateDecl *T) {
1689 return T->isThisDeclarationADefinition();
1690 })
1691 .match(ToTU, classTemplateDecl()));
1692
1693 Decl *FromTU = getTuDecl(
1694 R"(
1695 template <typename T>
1696 struct B {
1697 void f();
1698 };
1699 )",
1700 Lang_CXX, "input1.cc");
1701 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1702 FromTU, classTemplateDecl(hasName("B")));
1703
1704 Import(FromD, Lang_CXX);
1705
1706 // We should have only one definition.
1707 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1708 [](const ClassTemplateDecl *T) {
1709 return T->isThisDeclarationADefinition();
1710 })
1711 .match(ToTU, classTemplateDecl()));
1712}
1713
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001714TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001715 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1716 Decl *ToTU = getToTuDecl(
1717 R"(
1718 struct B {
1719 void f();
1720 };
1721
1722 struct B;
1723 )",
1724 Lang_CXX);
1725 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001726 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001727
1728 Decl *FromTU = getTuDecl(
1729 R"(
1730 struct B {
1731 void f();
1732 };
1733 )",
1734 Lang_CXX, "input1.cc");
1735 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1736 FromTU, cxxRecordDecl(hasName("B")));
1737
1738 Import(FromD, Lang_CXX);
1739
1740 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001741 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001742}
1743
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001744static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1745 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1746 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1747 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1748 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1749}
1750static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1751 SourceManager &SM1, SourceManager &SM2) {
1752 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1753 FullSourceLoc{ Range2.getBegin(), SM2 });
1754 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1755 FullSourceLoc{ Range2.getEnd(), SM2 });
1756}
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001757TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001758 Decl *FromTU = getTuDecl(
1759 R"(
1760 #define MFOO(arg) arg = arg + 1
1761
1762 void foo() {
1763 int a = 5;
1764 MFOO(a);
1765 }
1766 )",
1767 Lang_CXX);
1768 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1769 auto ToD = Import(FromD, Lang_CXX);
1770
1771 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1772 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1773 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1774 auto FromRHS =
1775 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1776
1777 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1778 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1779 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1780 FromSM);
1781 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1782 FromSM);
1783 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1784 FromSM);
1785}
1786
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001787TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001788 Decl *FromTU = getTuDecl(
1789 R"(
1790 #define FUNC_INT void declToImport
1791 #define FUNC FUNC_INT
1792 FUNC(int a);
1793 )",
1794 Lang_CXX);
1795 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1796 auto ToD = Import(FromD, Lang_CXX);
1797
1798 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1799 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1800 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1801 FromSM);
1802}
1803
Gabor Marton9581c332018-05-23 13:53:36 +00001804TEST_P(
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001805 ASTImporterOptionSpecificTestBase,
1806 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
Gabor Marton9581c332018-05-23 13:53:36 +00001807 Decl *ToTU = getToTuDecl(
1808 R"(
1809 template <typename T>
1810 struct B;
1811
1812 template <>
1813 struct B<int> {};
1814
1815 template <>
1816 struct B<int>;
1817 )",
1818 Lang_CXX);
1819 // We should have only one definition.
1820 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1821 [](const ClassTemplateSpecializationDecl *T) {
1822 return T->isThisDeclarationADefinition();
1823 })
1824 .match(ToTU, classTemplateSpecializationDecl()));
1825
1826 Decl *FromTU = getTuDecl(
1827 R"(
1828 template <typename T>
1829 struct B;
1830
1831 template <>
1832 struct B<int> {};
1833 )",
1834 Lang_CXX, "input1.cc");
1835 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1836 FromTU, classTemplateSpecializationDecl(hasName("B")));
1837
1838 Import(FromD, Lang_CXX);
1839
1840 // We should have only one definition.
1841 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1842 [](const ClassTemplateSpecializationDecl *T) {
1843 return T->isThisDeclarationADefinition();
1844 })
1845 .match(ToTU, classTemplateSpecializationDecl()));
1846}
1847
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001848TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
Gabor Marton0bebf952018-07-05 09:51:13 +00001849 Decl *FromTU = getTuDecl(
1850 R"(
1851 struct { int a; int b; } object0 = { 2, 3 };
1852 struct { int x; int y; int z; } object1;
1853 )",
1854 Lang_CXX, "input0.cc");
1855
Gabor Marton0bebf952018-07-05 09:51:13 +00001856 auto *Obj0 =
1857 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1858 auto *From0 = getRecordDecl(Obj0);
1859 auto *Obj1 =
1860 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1861 auto *From1 = getRecordDecl(Obj1);
1862
1863 auto *To0 = Import(From0, Lang_CXX);
1864 auto *To1 = Import(From1, Lang_CXX);
1865
1866 EXPECT_TRUE(To0);
1867 EXPECT_TRUE(To1);
1868 EXPECT_NE(To0, To1);
1869 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1870}
1871
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001872TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001873 auto *Code =
1874 R"(
1875 struct X {
1876 struct { int a; };
1877 struct { int b; };
1878 };
1879 )";
1880 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
1881
1882 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
1883
1884 auto *X0 =
1885 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1886 auto *X1 =
1887 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1888 Import(X0, Lang_C);
1889 Import(X1, Lang_C);
1890
1891 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1892 // We expect no (ODR) warning during the import.
1893 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1894 EXPECT_EQ(1u,
1895 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1896}
1897
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001898TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001899 Decl *FromTU0 = getTuDecl(
1900 R"(
1901 struct X {
1902 struct { int a; };
1903 struct { int b; };
1904 };
1905 )",
1906 Lang_C, "input0.c");
1907
1908 Decl *FromTU1 = getTuDecl(
1909 R"(
1910 struct X { // reversed order
1911 struct { int b; };
1912 struct { int a; };
1913 };
1914 )",
1915 Lang_C, "input1.c");
1916
1917 auto *X0 =
1918 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1919 auto *X1 =
1920 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1921 Import(X0, Lang_C);
1922 Import(X1, Lang_C);
1923
1924 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1925 // We expect one (ODR) warning during the import.
1926 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
Gabor Martonf035b752019-08-27 11:36:10 +00001927 EXPECT_EQ(1u,
Gabor Marton7df342a2018-12-17 12:42:12 +00001928 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1929}
1930
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001931TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001932 auto Pattern = varDecl(hasName("x"));
1933 VarDecl *Imported1;
1934 {
1935 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1936 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1937 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1938 }
1939 VarDecl *Imported2;
1940 {
1941 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1942 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1943 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1944 }
1945 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1946 EXPECT_FALSE(Imported2->isUsed(false));
1947 {
1948 Decl *FromTU =
1949 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
Gabor Martonac3a5d62018-09-17 12:04:52 +00001950 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1951 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00001952 Import(FromD, Lang_CXX);
1953 }
1954 EXPECT_TRUE(Imported2->isUsed(false));
1955}
1956
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001957TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001958 auto Pattern = varDecl(hasName("x"));
1959 VarDecl *ExistingD;
1960 {
1961 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
1962 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1963 }
1964 EXPECT_FALSE(ExistingD->isUsed(false));
1965 {
1966 Decl *FromTU = getTuDecl(
1967 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
1968 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1969 FromTU, functionDecl(hasName("f")));
1970 Import(FromD, Lang_CXX);
1971 }
1972 EXPECT_TRUE(ExistingD->isUsed(false));
1973}
1974
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001975TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001976 auto Pattern = varDecl(hasName("a"));
1977 VarDecl *ExistingD;
1978 {
1979 Decl *ToTU = getToTuDecl(
1980 R"(
1981 struct A {
1982 static const int a = 1;
1983 };
1984 )", Lang_CXX);
1985 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1986 }
1987 EXPECT_FALSE(ExistingD->isUsed(false));
1988 {
1989 Decl *FromTU = getTuDecl(
1990 R"(
1991 struct A {
1992 static const int a = 1;
1993 };
1994 const int *f() { return &A::a; } // requires storage,
1995 // thus used flag will be set
1996 )", Lang_CXX, "input1.cc");
1997 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
1998 FromTU, functionDecl(hasName("f")));
1999 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2000 ASSERT_TRUE(FromD->isUsed(false));
2001 Import(FromFunD, Lang_CXX);
2002 }
2003 EXPECT_TRUE(ExistingD->isUsed(false));
2004}
2005
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002006TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00002007 auto Pattern = varDecl(hasName("x"));
2008
2009 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
2010 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
2011
2012 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
2013
2014 ASSERT_FALSE(Imported1->isUsed(false));
2015
2016 FromD->setIsUsed();
2017 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
2018
2019 EXPECT_EQ(Imported1, Imported2);
2020 EXPECT_TRUE(Imported2->isUsed(false));
2021}
2022
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002023struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
Peter Szecsidedda6f2018-03-30 22:03:29 +00002024
Gabor Marton5254e642018-06-27 13:32:50 +00002025TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00002026 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2027 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002028 auto *From =
2029 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00002030
Gabor Marton5254e642018-06-27 13:32:50 +00002031 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002032 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2033
Gabor Marton5254e642018-06-27 13:32:50 +00002034 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2035 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2036 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2037 EXPECT_TRUE(ImportedD == To0);
2038 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2039 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2040 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002041}
2042
2043TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
2044 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
2045 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00002046 auto *From =
2047 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00002048
Gabor Marton5254e642018-06-27 13:32:50 +00002049 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002050 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2051
Gabor Marton5254e642018-06-27 13:32:50 +00002052 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2053 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2054 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2055 EXPECT_TRUE(ImportedD == To1);
2056 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2057 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2058 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00002059}
2060
Peter Szecsidedda6f2018-03-30 22:03:29 +00002061TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2062 auto Code =
2063 R"(
2064 struct B { virtual void f(); };
2065 void B::f() {}
2066 struct D : B { void f(); };
2067 )";
2068 auto Pattern =
2069 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2070 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2071 CXXMethodDecl *Proto =
2072 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2073
2074 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2075 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2076 EXPECT_EQ(To->size_overridden_methods(), 1u);
2077}
2078
2079TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2080 auto Code =
2081 R"(
2082 struct B { virtual void f(); };
2083 void B::f() {}
2084 )";
2085 auto Pattern =
2086 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2087 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2088 CXXMethodDecl *Proto =
2089 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2090 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
2091
2092 ASSERT_TRUE(Proto->isVirtual());
2093 ASSERT_TRUE(Def->isVirtual());
2094 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
2095 EXPECT_TRUE(To->isVirtual());
2096}
2097
Gabor Marton5254e642018-06-27 13:32:50 +00002098TEST_P(ImportFunctions,
2099 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2100 Decl *ToTU = getToTuDecl(
2101 R"(
2102 void f() {}
2103 void f();
2104 )",
2105 Lang_CXX);
2106 ASSERT_EQ(1u,
2107 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2108 return FD->doesThisDeclarationHaveABody();
2109 }).match(ToTU, functionDecl()));
2110
2111 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
2112 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
2113
2114 Import(FromD, Lang_CXX);
2115
2116 EXPECT_EQ(1u,
2117 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2118 return FD->doesThisDeclarationHaveABody();
2119 }).match(ToTU, functionDecl()));
2120}
2121
Shafik Yaghmour96b3d202019-01-28 21:55:33 +00002122TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
2123 auto Code =
2124 R"(
2125 struct B { virtual void f(); };
2126 struct D:B { void f(); };
2127 )";
2128 auto BFP =
2129 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2130 auto DFP =
2131 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2132
2133 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2134 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2135 Import(DF, Lang_CXX);
2136
2137 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2138 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2139 Import(BF, Lang_CXX);
2140
2141 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2142
2143 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2144 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2145}
2146
2147TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2148 auto CodeWithoutDef =
2149 R"(
2150 struct B { virtual void f(); };
2151 struct D:B { void f(); };
2152 )";
2153 auto CodeWithDef =
2154 R"(
2155 struct B { virtual void f(){}; };
2156 struct D:B { void f(){}; };
2157 )";
2158 auto BFP =
2159 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2160 auto DFP =
2161 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2162 auto BFDefP = cxxMethodDecl(
2163 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2164 auto DFDefP = cxxMethodDecl(
2165 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2166 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
2167
2168 {
2169 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX, "input0.cc");
2170 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
2171 Import(FromD, Lang_CXX);
2172 }
2173 {
2174 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX, "input1.cc");
2175 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
2176 Import(FromB, Lang_CXX);
2177 }
2178
2179 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2180
2181 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2182 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2183 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2184 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2185 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2186}
2187
2188TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2189 auto Code =
2190 R"(
2191 struct B { virtual void f(); };
2192 struct D:B { void f(); };
2193 void B::f(){};
2194 )";
2195
2196 auto BFP =
2197 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2198 auto BFDefP = cxxMethodDecl(
2199 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2200 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
2201 unless(isDefinition()));
2202
2203 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2204 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2205 Import(D, Lang_CXX);
2206
2207 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2208 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2209 Import(B, Lang_CXX);
2210
2211 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2212
2213 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2214 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2215
2216 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2217 ToTU, cxxRecordDecl(hasName("B")));
2218 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2219 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2220 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2221
2222 // The definition should be out-of-class.
2223 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2224 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2225 ToBFOutOfClass->getLexicalDeclContext());
2226 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2227 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2228
2229 // Check that the redecl chain is intact.
2230 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2231}
2232
2233TEST_P(ImportFunctions,
2234 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2235 auto CodeTU0 =
2236 R"(
2237 struct B { virtual void f(); };
2238 struct D:B { void f(); };
2239 )";
2240 auto CodeTU1 =
2241 R"(
2242 struct B { virtual void f(); };
2243 struct D:B { void f(); };
2244 void B::f(){}
2245 void D::f(){}
2246 void foo(B &b, D &d) { b.f(); d.f(); }
2247 )";
2248
2249 auto BFP =
2250 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2251 auto BFDefP = cxxMethodDecl(
2252 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2253 auto DFP =
2254 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2255 auto DFDefP = cxxMethodDecl(
2256 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2257 auto FooDef = functionDecl(hasName("foo"));
2258
2259 {
2260 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX, "input0.cc");
2261 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2262 Import(D, Lang_CXX);
2263 }
2264
2265 {
2266 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX, "input1.cc");
2267 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2268 Import(Foo, Lang_CXX);
2269 }
2270
2271 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2272
2273 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2274 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2275 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2276 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2277
2278 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2279 ToTU, cxxRecordDecl(hasName("B")));
2280 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2281 ToTU, cxxRecordDecl(hasName("D")));
2282 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2283 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2284 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2285 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2286 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2287 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2288
2289 // The definition should be out-of-class.
2290 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2291 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2292 ToBFOutOfClass->getLexicalDeclContext());
2293 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2294 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2295
2296 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2297 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2298 ToDFOutOfClass->getLexicalDeclContext());
2299 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2300 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2301
2302 // Check that the redecl chain is intact.
2303 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2304 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2305}
2306
Gabor Marton458d1452019-02-14 13:07:03 +00002307TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2308 std::string Code = "static int v; static int v = 0;";
2309 auto Pattern = varDecl(hasName("v"));
2310
2311 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C, "input0.c");
2312
2313 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2314 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2315
2316 auto *To0 = Import(From0, Lang_C);
2317 auto *To1 = Import(From1, Lang_C);
2318
2319 EXPECT_TRUE(To0);
2320 ASSERT_TRUE(To1);
2321 EXPECT_NE(To0, To1);
2322 EXPECT_EQ(To1->getPreviousDecl(), To0);
2323}
2324
2325TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2326 TranslationUnitDecl *FromTu = getTuDecl(
2327 "namespace NS0 { namespace { void f(); } }"
2328 "namespace NS1 { namespace { void f(); } }",
2329 Lang_CXX, "input0.cc");
2330 auto Pattern = functionDecl(hasName("f"));
2331
2332 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2333 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2334
2335 auto *ToF0 = Import(FromF0, Lang_CXX);
2336 auto *ToF1 = Import(FromF1, Lang_CXX);
2337
2338 EXPECT_TRUE(ToF0);
2339 ASSERT_TRUE(ToF1);
2340 EXPECT_NE(ToF0, ToF1);
2341 EXPECT_FALSE(ToF1->getPreviousDecl());
2342}
2343
2344TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2345 {
2346 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",
2347 Lang_CXX, "input0.cc");
2348 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2349 FromTU, functionDecl(hasName("g0")));
2350
2351 Import(FromD, Lang_CXX);
2352 }
2353 {
2354 Decl *FromTU =
2355 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",
2356 Lang_CXX, "input1.cc");
2357 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2358 FromTU, functionDecl(hasName("g1")));
2359 Import(FromD, Lang_CXX);
2360 }
2361
2362 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2363 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2364 2u);
2365}
2366
Gabor Marton302f3002019-02-15 12:04:05 +00002367TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2368 Decl *FromTU = getTuDecl(
2369 R"(
2370 void foo() {
2371 (void)[]() { ; };
2372 }
2373 )",
2374 Lang_CXX11);
2375 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2376 FromTU, functionDecl(hasName("foo")));
2377 auto *ToD = Import(FromD, Lang_CXX);
2378 EXPECT_TRUE(ToD);
2379 CXXRecordDecl *LambdaRec =
2380 cast<LambdaExpr>(cast<CStyleCastExpr>(
2381 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2382 ->getSubExpr())
2383 ->getLambdaClass();
2384 EXPECT_TRUE(LambdaRec->getDestructor());
2385}
2386
Gabor Marton5caba302019-03-07 13:38:20 +00002387TEST_P(ImportFunctions,
2388 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2389 Decl *FromTU = getTuDecl(
2390 R"(
2391 struct X {
2392 template <typename T>
2393 void foo(){}
2394 };
2395 void f() {
2396 X x;
2397 x.foo<int>();
2398 }
2399 )",
2400 Lang_CXX);
2401 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2402 FromTU, functionDecl(hasName("f")));
2403 auto *ToD = Import(FromD, Lang_CXX);
2404 EXPECT_TRUE(ToD);
2405 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
2406 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr()))));
2407}
2408
2409TEST_P(ImportFunctions,
2410 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2411 Decl *FromTU = getTuDecl(
2412 R"(
2413 struct X {
2414 template <typename T>
2415 void foo(){}
2416 };
2417 template <typename T>
2418 void f() {
2419 X x;
2420 x.foo<T>();
2421 }
2422 void g() {
2423 f<int>();
2424 }
2425 )",
2426 Lang_CXX);
2427 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2428 FromTU, functionDecl(hasName("g")));
2429 auto *ToD = Import(FromD, Lang_CXX);
2430 EXPECT_TRUE(ToD);
2431 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2432 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match(
2433 ToTU, translationUnitDecl(hasDescendant(
2434 functionDecl(hasName("f"), hasDescendant(declRefExpr()))))));
2435}
2436
Balazs Kerie9719f92019-08-07 12:40:17 +00002437struct ImportFunctionTemplates : ASTImporterOptionSpecificTestBase {};
2438
2439TEST_P(ImportFunctionTemplates, ImportFunctionTemplateInRecordDeclTwice) {
2440 auto Code =
2441 R"(
2442 class X {
2443 template <class T>
2444 void f(T t);
2445 };
2446 )";
2447 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2448 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2449 FromTU1, functionTemplateDecl(hasName("f")));
2450 auto *ToD1 = Import(FromD1, Lang_CXX);
2451 Decl *FromTU2 = getTuDecl(Code, Lang_CXX, "input2.cc");
2452 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2453 FromTU2, functionTemplateDecl(hasName("f")));
2454 auto *ToD2 = Import(FromD2, Lang_CXX);
2455 EXPECT_EQ(ToD1, ToD2);
2456}
2457
2458TEST_P(ImportFunctionTemplates,
2459 ImportFunctionTemplateWithDefInRecordDeclTwice) {
2460 auto Code =
2461 R"(
2462 class X {
2463 template <class T>
2464 void f(T t);
2465 };
2466 template <class T>
2467 void X::f(T t) {};
2468 )";
2469 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2470 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2471 FromTU1, functionTemplateDecl(hasName("f")));
2472 auto *ToD1 = Import(FromD1, Lang_CXX);
2473 Decl *FromTU2 = getTuDecl(Code, Lang_CXX, "input2.cc");
2474 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2475 FromTU2, functionTemplateDecl(hasName("f")));
2476 auto *ToD2 = Import(FromD2, Lang_CXX);
2477 EXPECT_EQ(ToD1, ToD2);
2478}
2479
Gabor Martonf035b752019-08-27 11:36:10 +00002480TEST_P(ImportFunctionTemplates,
2481 ImportFunctionWhenThereIsAFunTemplateWithSameName) {
2482 getToTuDecl(
2483 R"(
2484 template <typename T>
2485 void foo(T) {}
2486 void foo();
2487 )",
2488 Lang_CXX);
2489 Decl *FromTU = getTuDecl("void foo();", Lang_CXX);
2490 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2491 FromTU, functionDecl(hasName("foo")));
2492 auto *ImportedD = Import(FromD, Lang_CXX);
2493 EXPECT_TRUE(ImportedD);
2494}
2495
2496TEST_P(ImportFunctionTemplates,
2497 ImportConstructorWhenThereIsAFunTemplateWithSameName) {
2498 auto Code =
2499 R"(
2500 struct Foo {
2501 template <typename T>
2502 Foo(T) {}
2503 Foo();
2504 };
2505 )";
2506 getToTuDecl(Code, Lang_CXX);
2507 Decl *FromTU = getTuDecl(Code, Lang_CXX);
2508 auto *FromD =
2509 LastDeclMatcher<CXXConstructorDecl>().match(FromTU, cxxConstructorDecl());
2510 auto *ImportedD = Import(FromD, Lang_CXX);
2511 EXPECT_TRUE(ImportedD);
2512}
2513
2514TEST_P(ImportFunctionTemplates,
2515 ImportOperatorWhenThereIsAFunTemplateWithSameName) {
2516 getToTuDecl(
2517 R"(
2518 template <typename T>
2519 void operator<(T,T) {}
2520 struct X{};
2521 void operator<(X, X);
2522 )",
2523 Lang_CXX);
2524 Decl *FromTU = getTuDecl(
2525 R"(
2526 struct X{};
2527 void operator<(X, X);
2528 )",
2529 Lang_CXX);
2530 auto *FromD = LastDeclMatcher<FunctionDecl>().match(
2531 FromTU, functionDecl(hasOverloadedOperatorName("<")));
2532 auto *ImportedD = Import(FromD, Lang_CXX);
2533 EXPECT_TRUE(ImportedD);
2534}
2535
Gabor Marton5254e642018-06-27 13:32:50 +00002536struct ImportFriendFunctions : ImportFunctions {};
2537
2538TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2539 auto Pattern = functionDecl(hasName("f"));
2540
2541 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2542 "void f();",
2543 Lang_CXX,
2544 "input0.cc");
2545 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2546
2547 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2548 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2549 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2550 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2551 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2552 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2553 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2554}
2555
2556TEST_P(ImportFriendFunctions,
2557 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2558 auto Pattern = functionDecl(hasName("f"));
2559
2560 Decl *FromTU = getTuDecl("void f();"
2561 "struct X { friend void f(); };",
2562 Lang_CXX, "input0.cc");
2563 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2564
2565 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2566 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2567 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2568 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2569 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2570 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2571 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2572}
2573
2574TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2575 auto Pattern = functionDecl(hasName("f"));
2576
2577 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2578 "void f();",
2579 Lang_CXX,
2580 "input0.cc");
2581 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2582
2583 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2584 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2585 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2586 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2587 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2588 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2589 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2590}
2591
2592TEST_P(ImportFriendFunctions,
2593 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2594 auto Pattern = functionDecl(hasName("f"));
2595
2596 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2597 "void f(){}",
2598 Lang_CXX, "input0.cc");
2599 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2600
2601 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2602 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2603 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2604 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2605 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2606 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2607 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2608}
2609
Gabor Marton1d51e3e2019-05-20 10:38:14 +00002610TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDefWithClass) {
Gabor Marton5254e642018-06-27 13:32:50 +00002611 auto Pattern = functionDecl(hasName("f"));
2612
2613 Decl *FromTU = getTuDecl(
2614 R"(
2615 class X;
2616 void f(X *x){}
2617 class X{
2618 friend void f(X *x);
2619 };
2620 )",
2621 Lang_CXX, "input0.cc");
2622 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2623
2624 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2625 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2626 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2627 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2628 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2629 .match(ToTU, friendDecl())
2630 ->getFriendDecl());
2631 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2632 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2633 // The parameters must refer the same type
2634 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2635 (*ImportedD->param_begin())->getOriginalType());
2636}
2637
Gabor Marton5254e642018-06-27 13:32:50 +00002638TEST_P(ImportFriendFunctions,
Gabor Marton1d51e3e2019-05-20 10:38:14 +00002639 ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002640 auto Pattern = functionDecl(hasName("f"));
2641
2642 Decl *FromTU = getTuDecl(
2643 R"(
2644 class X;
2645 void f(X *x){}
2646 class X{
2647 friend void f(X *x);
2648 };
2649 )",
2650 Lang_CXX, "input0.cc");
2651 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2652
2653 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2654 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2655 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2656 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2657 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2658 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2659
2660 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2661 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2662 // The parameters must refer the same type
2663 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2664 (*ImportedD->param_begin())->getOriginalType());
2665}
2666
2667TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2668 auto Pattern = functionDecl(hasName("f"));
2669
2670 FunctionDecl *ImportedD;
2671 {
2672 Decl *FromTU =
2673 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2674 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2675 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2676 }
2677 FunctionDecl *ImportedD1;
2678 {
2679 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2680 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2681 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2682 }
2683
2684 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2685 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2686 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2687 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2688 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2689}
2690
Balazs Keri89632b82018-08-21 14:32:21 +00002691TEST_P(ImportFriendFunctions, Lookup) {
2692 auto FunctionPattern = functionDecl(hasName("f"));
2693 auto ClassPattern = cxxRecordDecl(hasName("X"));
2694
2695 TranslationUnitDecl *FromTU =
2696 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2697 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2698 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2699 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2700 {
2701 auto FromName = FromD->getDeclName();
2702 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2703 auto LookupRes = Class->noload_lookup(FromName);
2704 ASSERT_EQ(LookupRes.size(), 0u);
2705 LookupRes = FromTU->noload_lookup(FromName);
2706 ASSERT_EQ(LookupRes.size(), 1u);
2707 }
2708
2709 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2710 auto ToName = ToD->getDeclName();
2711
2712 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2713 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2714 auto LookupRes = Class->noload_lookup(ToName);
2715 EXPECT_EQ(LookupRes.size(), 0u);
2716 LookupRes = ToTU->noload_lookup(ToName);
2717 EXPECT_EQ(LookupRes.size(), 1u);
2718
2719 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2720 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2721 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2722 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2723}
2724
Gabor Martonbc5b7e22019-12-04 17:12:08 +01002725TEST_P(ImportFriendFunctions, LookupWithProtoAfter) {
Balazs Keri89632b82018-08-21 14:32:21 +00002726 auto FunctionPattern = functionDecl(hasName("f"));
2727 auto ClassPattern = cxxRecordDecl(hasName("X"));
2728
2729 TranslationUnitDecl *FromTU = getTuDecl(
2730 "struct X { friend void f(); };"
2731 // This proto decl makes f available to normal
2732 // lookup, otherwise it is hidden.
2733 // Normal C++ lookup (implemented in
2734 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2735 // returns the found `NamedDecl` only if the set IDNS is matched
2736 "void f();",
2737 Lang_CXX, "input0.cc");
2738 auto *FromFriend =
2739 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2740 auto *FromNormal =
2741 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2742 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2743 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2744 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2745 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2746
2747 auto FromName = FromFriend->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 *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2756 auto ToName = ToFriend->getDeclName();
2757
2758 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
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 // Test is disabled because this result is 2.
2764 EXPECT_EQ(LookupRes.size(), 1u);
2765
2766 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2767 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2768 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2769 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2770 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2771 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2772 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2773}
2774
2775TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2776 auto FunctionPattern = functionDecl(hasName("f"));
2777 auto ClassPattern = cxxRecordDecl(hasName("X"));
2778
2779 TranslationUnitDecl *FromTU = getTuDecl(
2780 "void f();"
2781 "struct X { friend void f(); };",
2782 Lang_CXX, "input0.cc");
2783 auto *FromNormal =
2784 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2785 auto *FromFriend =
2786 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2787 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2788 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2789 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2790 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2791
2792 auto FromName = FromNormal->getDeclName();
2793 auto *FromClass =
2794 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2795 auto LookupRes = FromClass->noload_lookup(FromName);
2796 ASSERT_EQ(LookupRes.size(), 0u);
2797 LookupRes = FromTU->noload_lookup(FromName);
2798 ASSERT_EQ(LookupRes.size(), 1u);
2799
2800 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2801 auto ToName = ToNormal->getDeclName();
2802 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2803
2804 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2805 LookupRes = ToClass->noload_lookup(ToName);
2806 EXPECT_EQ(LookupRes.size(), 0u);
2807 LookupRes = ToTU->noload_lookup(ToName);
2808 EXPECT_EQ(LookupRes.size(), 1u);
2809
2810 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2811 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2812 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2813 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2814 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2815 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2816 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2817}
2818
2819TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2820 auto Pattern = functionDecl(hasName("f"));
2821
2822 TranslationUnitDecl *FromNormalTU =
2823 getTuDecl("void f();", Lang_CXX, "input0.cc");
2824 auto *FromNormalF =
2825 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2826 TranslationUnitDecl *FromFriendTU =
2827 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2828 auto *FromFriendF =
2829 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2830 auto FromNormalName = FromNormalF->getDeclName();
2831 auto FromFriendName = FromFriendF->getDeclName();
2832
2833 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2834 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2835 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2836 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2837 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2838 ASSERT_EQ(LookupRes.size(), 1u);
2839 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2840 ASSERT_EQ(LookupRes.size(), 1u);
2841
2842 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2843 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2844 auto ToName = ToNormalF->getDeclName();
2845 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2846 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2847 LookupRes = ToTU->noload_lookup(ToName);
2848 EXPECT_EQ(LookupRes.size(), 1u);
2849 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00002850
Balazs Keri89632b82018-08-21 14:32:21 +00002851 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
2852 LookupRes = ToTU->noload_lookup(ToName);
2853 EXPECT_EQ(LookupRes.size(), 1u);
2854 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2855
2856 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2857 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2858
2859 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2860 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2861}
2862
2863TEST_P(ImportFriendFunctions, ImportFriendList) {
2864 TranslationUnitDecl *FromTU = getTuDecl(
2865 "struct X { friend void f(); };"
2866 "void f();",
2867 Lang_CXX, "input0.cc");
2868 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2869 FromTU, functionDecl(hasName("f")));
2870
2871 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2872 FromTU, cxxRecordDecl(hasName("X")));
2873 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2874 auto FromFriends = FromClass->friends();
2875 unsigned int FrN = 0;
2876 for (auto Fr : FromFriends) {
2877 ASSERT_EQ(Fr, FromFriend);
2878 ++FrN;
2879 }
2880 ASSERT_EQ(FrN, 1u);
2881
2882 Import(FromFriendF, Lang_CXX);
2883 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2884 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2885 ToTU, cxxRecordDecl(hasName("X")));
2886 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2887 auto ToFriends = ToClass->friends();
2888 FrN = 0;
2889 for (auto Fr : ToFriends) {
2890 EXPECT_EQ(Fr, ToFriend);
2891 ++FrN;
2892 }
2893 EXPECT_EQ(FrN, 1u);
2894}
2895
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002896AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2897 InnerMatcher) {
2898 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2899 return InnerMatcher.matches(*Typedef, Finder, Builder);
2900 return false;
2901}
2902
Gabor Marton19f4f392018-06-25 13:04:37 +00002903TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002904 CodeFiles Samples{{"main.c",
2905 {"void foo();"
2906 "void moo();"
2907 "int main() { foo(); moo(); }",
2908 Lang_C}},
2909
2910 {"foo.c",
2911 {"typedef enum { THING_VALUE } thing_t;"
2912 "void conflict(thing_t type);"
2913 "void foo() { (void)THING_VALUE; }"
2914 "void conflict(thing_t type) {}",
2915 Lang_C}},
2916
2917 {"moo.c",
2918 {"typedef enum { THING_VALUE } thing_t;"
2919 "void conflict(thing_t type);"
2920 "void moo() { conflict(THING_VALUE); }",
2921 Lang_C}}};
2922
2923 auto VerificationMatcher =
2924 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2925 hasTypedefForAnonDecl(hasName("thing_t")));
2926
2927 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2928 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2929
2930 testImportSequence(
2931 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2932 // Just check that there is only one enum decl in the result AST.
2933 "main.c", enumDecl(), VerificationMatcher);
2934
2935 // For different import order, result should be the same.
2936 testImportSequence(
2937 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2938 // Check that there is only one enum decl in the result AST.
2939 "main.c", enumDecl(), VerificationMatcher);
2940}
2941
Gabor Marton48b16e12019-07-25 09:07:17 +00002942TEST_P(ImportDecl, ImportFieldOrder) {
2943 MatchVerifier<Decl> Verifier;
2944 testImport("struct declToImport {"
2945 " int b = a + 2;"
2946 " int a = 5;"
2947 "};",
2948 Lang_CXX11, "", Lang_CXX11, Verifier,
2949 recordDecl(hasFieldOrder({"b", "a"})));
2950}
2951
Peter Szecsice7f3182018-05-07 12:08:27 +00002952const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2953 dependentScopeDeclRefExpr;
2954
Gabor Marton19f4f392018-06-25 13:04:37 +00002955TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002956 MatchVerifier<Decl> Verifier;
2957 testImport("template <typename T> struct S { static T foo; };"
2958 "template <typename T> void declToImport() {"
2959 " (void) S<T>::foo;"
2960 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002961 "void instantiate() { declToImport<int>(); }"
2962 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002963 Lang_CXX11, "", Lang_CXX11, Verifier,
2964 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2965 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2966
2967 testImport("template <typename T> struct S {"
2968 "template<typename S> static void foo(){};"
2969 "};"
2970 "template <typename T> void declToImport() {"
2971 " S<T>::template foo<T>();"
2972 "}"
2973 "void instantiate() { declToImport<int>(); }",
2974 Lang_CXX11, "", Lang_CXX11, Verifier,
2975 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2976 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2977}
2978
2979const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2980 dependentNameType;
2981
Gabor Marton19f4f392018-06-25 13:04:37 +00002982TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002983 MatchVerifier<Decl> Verifier;
2984 testImport("template <typename T> struct declToImport {"
2985 " typedef typename T::type dependent_name;"
2986 "};",
2987 Lang_CXX11, "", Lang_CXX11, Verifier,
2988 classTemplateDecl(has(
2989 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2990}
2991
Gabor Marton19f4f392018-06-25 13:04:37 +00002992TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002993 MatchVerifier<Decl> Verifier;
2994 testImport("struct S { template <typename T> void mem(); };"
2995 "template <typename U> void declToImport() {"
2996 " S s;"
2997 " s.mem<U>();"
2998 "}"
2999 "void instantiate() { declToImport<int>(); }",
3000 Lang_CXX11, "", Lang_CXX11, Verifier,
3001 functionTemplateDecl(has(functionDecl(has(
3002 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
3003}
3004
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003005class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
Balazs Keri1d20cc22018-07-16 12:16:39 +00003006public:
3007 static constexpr auto DefaultCode = R"(
3008 struct A { int x; };
3009 void f() {
3010 A a;
3011 A a1(a);
3012 A a2(A{});
3013 a = a1;
3014 a = A{};
3015 a.~A();
3016 })";
3017
3018 template <typename MatcherType>
3019 void testImportOf(
3020 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3021 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
3022 }
3023
3024 template <typename MatcherType>
3025 void testNoImportOf(
3026 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3027 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
3028 }
3029
3030private:
3031 template <typename MatcherType>
3032 void test(const MatcherType &MethodMatcher,
3033 const char *Code, unsigned int ExpectedCount) {
3034 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
3035
3036 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3037 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3038 ToTU, ClassMatcher);
3039
Balazs Keri2f752ba2018-07-16 14:05:18 +00003040 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003041
3042 {
3043 CXXMethodDecl *Method =
3044 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
3045 ToClass->removeDecl(Method);
Gabor Marton2afbfb62019-07-01 15:37:07 +00003046 SharedStatePtr->getLookupTable()->remove(Method);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003047 }
3048
Balazs Keri2f752ba2018-07-16 14:05:18 +00003049 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00003050
3051 Decl *ImportedClass = nullptr;
3052 {
3053 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
3054 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3055 FromTU, ClassMatcher);
3056 ImportedClass = Import(FromClass, Lang_CXX11);
3057 }
3058
3059 EXPECT_EQ(ToClass, ImportedClass);
3060 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
3061 ExpectedCount);
3062 }
3063};
3064
3065TEST_P(ImportImplicitMethods, DefaultConstructor) {
3066 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
3067}
3068
3069TEST_P(ImportImplicitMethods, CopyConstructor) {
3070 testImportOf(cxxConstructorDecl(isCopyConstructor()));
3071}
3072
3073TEST_P(ImportImplicitMethods, MoveConstructor) {
3074 testImportOf(cxxConstructorDecl(isMoveConstructor()));
3075}
3076
3077TEST_P(ImportImplicitMethods, Destructor) {
3078 testImportOf(cxxDestructorDecl());
3079}
3080
3081TEST_P(ImportImplicitMethods, CopyAssignment) {
3082 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
3083}
3084
3085TEST_P(ImportImplicitMethods, MoveAssignment) {
3086 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
3087}
3088
3089TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
3090 auto Code = R"(
3091 struct A { A() { int x; } };
3092 )";
3093 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3094}
3095
3096TEST_P(ImportImplicitMethods, DoNotImportDefault) {
3097 auto Code = R"(
3098 struct A { A() = default; };
3099 )";
3100 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3101}
3102
3103TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
3104 auto Code = R"(
3105 struct A { A() = delete; };
3106 )";
3107 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
3108}
3109
3110TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
3111 auto Code = R"(
3112 struct A { void f() { } };
3113 )";
3114 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
3115}
3116
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003117TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003118 Decl *ToR1;
3119 {
3120 Decl *FromTU = getTuDecl(
3121 "struct A { };", Lang_CXX, "input0.cc");
3122 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3123 FromTU, cxxRecordDecl(hasName("A")));
3124
3125 ToR1 = Import(FromR, Lang_CXX);
3126 }
3127
3128 Decl *ToR2;
3129 {
3130 Decl *FromTU = getTuDecl(
3131 "struct A { };", Lang_CXX, "input1.cc");
3132 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3133 FromTU, cxxRecordDecl(hasName("A")));
3134
3135 ToR2 = Import(FromR, Lang_CXX);
3136 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00003137
Balazs Keric7797c42018-07-11 09:37:24 +00003138 EXPECT_EQ(ToR1, ToR2);
3139}
3140
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003141TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00003142 Decl *ToR1;
3143 {
3144 Decl *FromTU = getTuDecl(
3145 "struct A { int x; };", Lang_CXX, "input0.cc");
3146 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3147 FromTU, cxxRecordDecl(hasName("A")));
3148 ToR1 = Import(FromR, Lang_CXX);
3149 }
3150 Decl *ToR2;
3151 {
3152 Decl *FromTU = getTuDecl(
3153 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3154 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3155 FromTU, cxxRecordDecl(hasName("A")));
3156 ToR2 = Import(FromR, Lang_CXX);
3157 }
3158 EXPECT_NE(ToR1, ToR2);
3159}
3160
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003161TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003162 Decl *ToF1;
3163 {
3164 Decl *FromTU = getTuDecl(
3165 "struct A { int x; };", Lang_CXX, "input0.cc");
3166 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3167 FromTU, fieldDecl(hasName("x")));
3168 ToF1 = Import(FromF, Lang_CXX);
3169 }
3170 Decl *ToF2;
3171 {
3172 Decl *FromTU = getTuDecl(
3173 "struct A { int x; };", Lang_CXX, "input1.cc");
3174 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3175 FromTU, fieldDecl(hasName("x")));
3176 ToF2 = Import(FromF, Lang_CXX);
3177 }
3178 EXPECT_EQ(ToF1, ToF2);
3179}
3180
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003181TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00003182 Decl *ToF1;
3183 {
3184 Decl *FromTU = getTuDecl(
3185 "struct A { int x; };", Lang_CXX, "input0.cc");
3186 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3187 FromTU, fieldDecl(hasName("x")));
3188 ToF1 = Import(FromF, Lang_CXX);
3189 }
3190 Decl *ToF2;
3191 {
3192 Decl *FromTU = getTuDecl(
3193 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
3194 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3195 FromTU, fieldDecl(hasName("x")));
3196 ToF2 = Import(FromF, Lang_CXX);
3197 }
3198 EXPECT_NE(ToF1, ToF2);
3199}
3200
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003201TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003202 Decl *ToM1;
3203 {
3204 Decl *FromTU = getTuDecl(
3205 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
3206 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3207 FromTU, functionDecl(hasName("x"), isDefinition()));
3208 ToM1 = Import(FromM, Lang_CXX);
3209 }
3210 Decl *ToM2;
3211 {
3212 Decl *FromTU = getTuDecl(
3213 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
3214 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3215 FromTU, functionDecl(hasName("x"), isDefinition()));
3216 ToM2 = Import(FromM, Lang_CXX);
3217 }
3218 EXPECT_EQ(ToM1, ToM2);
3219}
3220
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003221TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00003222 Decl *ToM1;
3223 {
3224 Decl *FromTU = getTuDecl(
3225 "struct A { void x(); }; void A::x() { }",
3226 Lang_CXX, "input0.cc");
3227 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3228 FromTU, functionDecl(hasName("x"), isDefinition()));
3229 ToM1 = Import(FromM, Lang_CXX);
3230 }
3231 Decl *ToM2;
3232 {
3233 Decl *FromTU = getTuDecl(
3234 "struct A { void x() const; }; void A::x() const { }",
3235 Lang_CXX, "input1.cc");
3236 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3237 FromTU, functionDecl(hasName("x"), isDefinition()));
3238 ToM2 = Import(FromM, Lang_CXX);
3239 }
3240 EXPECT_NE(ToM1, ToM2);
3241}
3242
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003243TEST_P(ASTImporterOptionSpecificTestBase,
3244 ImportUnnamedStructsWithRecursingField) {
Gabor Martonf086fa82018-07-17 12:06:36 +00003245 Decl *FromTU = getTuDecl(
3246 R"(
3247 struct A {
3248 struct {
3249 struct A *next;
3250 } entry0;
3251 struct {
3252 struct A *next;
3253 } entry1;
3254 };
3255 )",
3256 Lang_C, "input0.cc");
3257 auto *From =
3258 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3259
3260 Import(From, Lang_C);
3261
3262 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3263 auto *Entry0 =
3264 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3265 auto *Entry1 =
3266 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3267 auto *R0 = getRecordDecl(Entry0);
3268 auto *R1 = getRecordDecl(Entry1);
3269 EXPECT_NE(R0, R1);
3270 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3271 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3272 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3273 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3274}
3275
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003276TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
Balazs Keri2544b4b2018-08-08 09:40:57 +00003277 Decl *FromTU = getTuDecl(
3278 R"(
3279 void f(int X, int Y, bool Z) {
3280 (void)[X, Y, Z] { (void)Z; };
3281 }
3282 )",
3283 Lang_CXX11, "input0.cc");
3284 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3285 FromTU, functionDecl(hasName("f")));
3286 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3287 EXPECT_TRUE(ToF);
3288
3289 CXXRecordDecl *FromLambda =
3290 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3291 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3292
3293 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3294 EXPECT_TRUE(ToLambda);
3295
3296 // Check if the fields of the lambda class are imported in correct order.
3297 unsigned FromIndex = 0u;
3298 for (auto *FromField : FromLambda->fields()) {
3299 ASSERT_FALSE(FromField->getDeclName());
3300 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3301 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00003302 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3303 EXPECT_TRUE(ToIndex);
3304 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00003305 ++FromIndex;
3306 }
3307
3308 EXPECT_EQ(FromIndex, 3u);
3309}
3310
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003311TEST_P(ASTImporterOptionSpecificTestBase,
3312 MergeFieldDeclsOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003313 std::string ClassTemplate =
3314 R"(
3315 template <typename T>
3316 struct X {
3317 int a{0}; // FieldDecl with InitListExpr
3318 X(char) : a(3) {} // (1)
3319 X(int) {} // (2)
3320 };
3321 )";
3322 Decl *ToTU = getToTuDecl(ClassTemplate +
3323 R"(
3324 void foo() {
3325 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3326 X<char> xc('c');
3327 }
3328 )", Lang_CXX11);
3329 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3330 ToTU, classTemplateSpecializationDecl(hasName("X")));
3331 // FieldDecl without InitlistExpr:
3332 auto *ToField = *ToSpec->field_begin();
3333 ASSERT_TRUE(ToField);
3334 ASSERT_FALSE(ToField->getInClassInitializer());
3335 Decl *FromTU = getTuDecl(ClassTemplate +
3336 R"(
3337 void bar() {
3338 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3339 X<char> xc(1);
3340 }
3341 )", Lang_CXX11);
3342 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3343 FromTU, classTemplateSpecializationDecl(hasName("X")));
3344 // FieldDecl with InitlistExpr:
3345 auto *FromField = *FromSpec->field_begin();
3346 ASSERT_TRUE(FromField);
3347 ASSERT_TRUE(FromField->getInClassInitializer());
3348
3349 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3350 ASSERT_TRUE(ImportedSpec);
3351 EXPECT_EQ(ImportedSpec, ToSpec);
3352 // After the import, the FieldDecl has to be merged, thus it should have the
3353 // InitListExpr.
3354 EXPECT_TRUE(ToField->getInClassInitializer());
3355}
3356
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003357TEST_P(ASTImporterOptionSpecificTestBase,
3358 MergeFunctionOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003359 std::string ClassTemplate =
3360 R"(
3361 template <typename T>
3362 struct X {
3363 void f() {}
3364 void g() {}
3365 };
3366 )";
3367 Decl *ToTU = getToTuDecl(ClassTemplate +
3368 R"(
3369 void foo() {
3370 X<char> x;
3371 x.f();
3372 }
3373 )", Lang_CXX11);
3374 Decl *FromTU = getTuDecl(ClassTemplate +
3375 R"(
3376 void bar() {
3377 X<char> x;
3378 x.g();
3379 }
3380 )", Lang_CXX11);
3381 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3382 FromTU, classTemplateSpecializationDecl(hasName("X")));
3383 auto FunPattern = functionDecl(hasName("g"),
3384 hasParent(classTemplateSpecializationDecl()));
3385 auto *FromFun =
3386 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3387 auto *ToFun =
3388 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3389 ASSERT_TRUE(FromFun->hasBody());
3390 ASSERT_FALSE(ToFun->hasBody());
3391 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3392 ASSERT_TRUE(ImportedSpec);
3393 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3394 ToTU, classTemplateSpecializationDecl(hasName("X")));
3395 EXPECT_EQ(ImportedSpec, ToSpec);
3396 EXPECT_TRUE(ToFun->hasBody());
3397}
3398
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003399TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003400 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3401 std::string ClassTemplate =
3402 R"(
3403 template <typename T>
3404 struct X {};
3405 )";
3406 Decl *ToTU = getToTuDecl(ClassTemplate +
3407 R"(
3408 template <>
3409 struct X<char> {
3410 int a;
3411 };
3412 void foo() {
3413 X<char> x;
3414 }
3415 )",
3416 Lang_CXX11);
3417 Decl *FromTU = getTuDecl(ClassTemplate +
3418 R"(
3419 template <>
3420 struct X<char> {
3421 int b;
3422 };
3423 void foo() {
3424 X<char> x;
3425 }
3426 )",
3427 Lang_CXX11);
3428 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3429 FromTU, classTemplateSpecializationDecl(hasName("X")));
3430 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3431
3432 // We expect one (ODR) warning during the import.
3433 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3434
3435 // The second specialization is different from the first, thus it violates
3436 // ODR, consequently we expect to keep the first specialization only, which is
3437 // already in the "To" context.
Gabor Marton7f8c4002019-03-19 13:34:10 +00003438 EXPECT_FALSE(ImportedSpec);
3439 EXPECT_EQ(1u,
3440 DeclCounter<ClassTemplateSpecializationDecl>().match(
3441 ToTU, classTemplateSpecializationDecl(hasName("X"))));
Gabor Marton42e15de2018-08-22 11:52:14 +00003442}
3443
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003444TEST_P(ASTImporterOptionSpecificTestBase,
3445 MergeCtorOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003446 std::string ClassTemplate =
3447 R"(
3448 template <typename T>
3449 struct X {
3450 X(char) {}
3451 X(int) {}
3452 };
3453 )";
3454 Decl *ToTU = getToTuDecl(ClassTemplate +
3455 R"(
3456 void foo() {
3457 X<char> x('c');
3458 }
3459 )", Lang_CXX11);
3460 Decl *FromTU = getTuDecl(ClassTemplate +
3461 R"(
3462 void bar() {
3463 X<char> x(1);
3464 }
3465 )", Lang_CXX11);
3466 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3467 FromTU, classTemplateSpecializationDecl(hasName("X")));
3468 // Match the void(int) ctor.
3469 auto CtorPattern =
3470 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3471 hasParent(classTemplateSpecializationDecl()));
3472 auto *FromCtor =
3473 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3474 auto *ToCtor =
3475 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3476 ASSERT_TRUE(FromCtor->hasBody());
3477 ASSERT_FALSE(ToCtor->hasBody());
3478 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3479 ASSERT_TRUE(ImportedSpec);
3480 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3481 ToTU, classTemplateSpecializationDecl(hasName("X")));
3482 EXPECT_EQ(ImportedSpec, ToSpec);
3483 EXPECT_TRUE(ToCtor->hasBody());
3484}
3485
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003486TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003487 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3488 auto Code =
3489 R"(
3490 // primary template
3491 template<class T1, class T2, int I>
3492 class A {};
3493
3494 // partial specialization
3495 template<class T, int I>
3496 class A<T, T*, I> {};
3497 )";
3498 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3499 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3500 auto *FromSpec =
3501 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3502 FromTU, classTemplatePartialSpecializationDecl());
3503 auto *ToSpec =
3504 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3505 ToTU, classTemplatePartialSpecializationDecl());
3506
3507 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3508 EXPECT_EQ(ImportedSpec, ToSpec);
3509 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3510 ToTU, classTemplatePartialSpecializationDecl()));
3511}
3512
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003513TEST_P(ASTImporterOptionSpecificTestBase,
3514 ClassTemplateSpecializationsShouldNotBeDuplicated) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003515 auto Code =
3516 R"(
3517 // primary template
3518 template<class T1, class T2, int I>
3519 class A {};
3520
3521 // full specialization
3522 template<>
3523 class A<int, int, 1> {};
3524 )";
3525 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3526 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3527 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3528 FromTU, classTemplateSpecializationDecl());
3529 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3530 ToTU, classTemplateSpecializationDecl());
3531
3532 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3533 EXPECT_EQ(ImportedSpec, ToSpec);
3534 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3535 ToTU, classTemplateSpecializationDecl()));
3536}
3537
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003538TEST_P(ASTImporterOptionSpecificTestBase,
3539 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003540 std::string PrimaryTemplate =
3541 R"(
3542 template<class T1, class T2, int I>
3543 class A {};
3544 )";
3545 auto PartialSpec =
3546 R"(
3547 template<class T, int I>
3548 class A<T, T*, I> {};
3549 )";
3550 auto FullSpec =
3551 R"(
3552 template<>
3553 class A<int, int, 1> {};
3554 )";
3555 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3556 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3557 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3558 FromTU, classTemplateSpecializationDecl());
3559
3560 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3561 EXPECT_TRUE(ImportedSpec);
3562 // Check the number of partial specializations.
3563 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3564 ToTU, classTemplatePartialSpecializationDecl()));
3565 // Check the number of full specializations.
3566 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3567 ToTU, classTemplateSpecializationDecl(
3568 unless(classTemplatePartialSpecializationDecl()))));
3569}
3570
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003571TEST_P(ASTImporterOptionSpecificTestBase,
3572 InitListExprValueKindShouldBeImported) {
Gabor Martona20ce602018-09-03 13:10:53 +00003573 Decl *TU = getTuDecl(
3574 R"(
3575 const int &init();
3576 void foo() { const int &a{init()}; }
3577 )", Lang_CXX11, "input0.cc");
3578 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3579 ASSERT_TRUE(FromD->getAnyInitializer());
3580 auto *InitExpr = FromD->getAnyInitializer();
3581 ASSERT_TRUE(InitExpr);
3582 ASSERT_TRUE(InitExpr->isGLValue());
3583
3584 auto *ToD = Import(FromD, Lang_CXX11);
3585 EXPECT_TRUE(ToD);
3586 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3587 EXPECT_TRUE(ToInitExpr);
3588 EXPECT_TRUE(ToInitExpr->isGLValue());
3589}
3590
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003591struct ImportVariables : ASTImporterOptionSpecificTestBase {};
Gabor Martonac3a5d62018-09-17 12:04:52 +00003592
3593TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3594 Decl *FromTU = getTuDecl(
3595 R"(
3596 struct A {
3597 static const int a = 1 + 2;
3598 };
3599 const int A::a;
3600 )", Lang_CXX, "input1.cc");
3601
3602 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3603 FromTU, varDecl(hasName("a"))); // Decl with init
3604 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3605 FromTU, varDecl(hasName("a"))); // Decl with definition
3606 ASSERT_NE(FromDWithInit, FromDWithDef);
3607 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3608
3609 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3610 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3611 ASSERT_TRUE(ToD0);
3612 ASSERT_TRUE(ToD1);
3613 EXPECT_NE(ToD0, ToD1);
3614 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3615}
3616
3617TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3618 auto StructA =
3619 R"(
3620 struct A {
3621 static const int a = 1 + 2;
3622 };
3623 )";
3624 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3625 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3626 "input1.cc");
3627
3628 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3629 FromTU, varDecl(hasName("a"))); // Decl with init
3630 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3631 FromTU, varDecl(hasName("a"))); // Decl with definition
3632 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3633 ASSERT_TRUE(FromDWithInit->getInit());
3634 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3635 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3636 ASSERT_FALSE(FromDWithDef->getInit());
3637
3638 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3639 ToTU, varDecl(hasName("a"))); // Decl with init
3640 ASSERT_TRUE(ToD->getInit());
3641 ASSERT_FALSE(ToD->getDefinition());
3642
3643 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3644 EXPECT_TRUE(ImportedD->getAnyInitializer());
3645 EXPECT_TRUE(ImportedD->getDefinition());
3646}
3647
3648TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3649 auto StructA =
3650 R"(
3651 struct A {
3652 static const int a;
3653 };
3654 )";
3655 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3656 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3657 Lang_CXX, "input1.cc");
3658
3659 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3660 FromTU, varDecl(hasName("a")));
3661 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3662 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3663 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3664 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3665 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3666 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3667 ASSERT_TRUE(FromDWithDef->getInit());
3668
3669 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3670 ToTU, varDecl(hasName("a")));
3671 ASSERT_FALSE(ToD->getInit());
3672 ASSERT_FALSE(ToD->getDefinition());
3673
3674 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3675 EXPECT_TRUE(ImportedD->getAnyInitializer());
3676 EXPECT_TRUE(ImportedD->getDefinition());
3677}
3678
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003679struct ImportClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003680
Gabor Marton54058b52018-12-17 13:53:12 +00003681TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3682 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
3683 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3684 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3685 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3686 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3687
3688 Decl *ImportedDef = Import(FromDef, Lang_C);
3689
3690 EXPECT_NE(ImportedDef, ToProto);
3691 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3692 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3693 EXPECT_TRUE(ImportedDef == ToDef);
3694 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3695 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3696 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3697}
3698
3699TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3700 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
3701 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
3702 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3703 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3704 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3705
3706 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3707
3708 EXPECT_NE(ImportedDef, ToProto);
3709 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3710 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3711 EXPECT_TRUE(ImportedDef == ToDef);
3712 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3713 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3714 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3715}
3716
3717TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3718 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
3719 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3720 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3721 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3722 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3723
3724 Decl *ImportedProto = Import(FromProto, Lang_C);
3725 Decl *ImportedDef = Import(FromDef, Lang_C);
3726 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3727
3728 EXPECT_NE(ImportedDef, ImportedProto);
3729 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3730 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3731 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3732 EXPECT_TRUE(ImportedDef == ToDef);
3733 EXPECT_TRUE(ImportedProto == ToProto);
3734 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3735 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3736 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3737}
3738
Gabor Marton7df342a2018-12-17 12:42:12 +00003739
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003740struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003741
3742TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
3743 Decl *FromTU = getTuDecl(
3744 R"(
3745 class A {
3746 template <int I> class F {};
3747 class X {
3748 template <int I> friend class F;
3749 };
3750 };
3751 )",
3752 Lang_CXX, "input0.cc");
3753
3754 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3755 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
3756 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
3757 FromTU, cxxRecordDecl(hasName("F")));
3758
3759 ASSERT_TRUE(FromClass);
3760 ASSERT_TRUE(FromFriendClass);
3761 ASSERT_NE(FromClass, FromFriendClass);
3762 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
3763 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
3764 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3765 FromClass->getDescribedClassTemplate());
3766
3767 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
3768 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
3769
3770 EXPECT_TRUE(ToClass);
3771 EXPECT_TRUE(ToFriendClass);
3772 EXPECT_NE(ToClass, ToFriendClass);
3773 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
3774 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
3775 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3776 ToClass->getDescribedClassTemplate());
3777}
3778
3779TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
3780 Decl *FromTu = getTuDecl(
3781 R"(
3782 class declToImport {
3783 friend class declToImport;
3784 };
3785 )",
3786 Lang_CXX, "input.cc");
3787
3788 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
3789 FromTu, cxxRecordDecl(hasName("declToImport")));
3790 auto *ToD = Import(FromD, Lang_CXX);
3791 auto Pattern = cxxRecordDecl(has(friendDecl()));
3792 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3793 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3794}
3795
Gabor Martonbc5b7e22019-12-04 17:12:08 +01003796TEST_P(ImportFriendClasses, UndeclaredFriendClassShouldNotBeVisible) {
3797 Decl *FromTu = getTuDecl("class X { friend class Y; };", Lang_CXX, "from.cc");
3798 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
3799 FromTu, cxxRecordDecl(hasName("X")));
3800 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTu, friendDecl());
3801 RecordDecl *FromRecordOfFriend =
3802 const_cast<RecordDecl *>(getRecordDeclOfFriend(FromFriend));
3803
3804 ASSERT_EQ(FromRecordOfFriend->getDeclContext(), cast<DeclContext>(FromTu));
3805 ASSERT_EQ(FromRecordOfFriend->getLexicalDeclContext(),
3806 cast<DeclContext>(FromX));
3807 ASSERT_FALSE(
3808 FromRecordOfFriend->getDeclContext()->containsDecl(FromRecordOfFriend));
3809 ASSERT_FALSE(FromRecordOfFriend->getLexicalDeclContext()->containsDecl(
3810 FromRecordOfFriend));
3811 ASSERT_FALSE(FromRecordOfFriend->getLookupParent()
3812 ->lookup(FromRecordOfFriend->getDeclName())
3813 .empty());
3814
3815 auto *ToX = Import(FromX, Lang_CXX);
3816 ASSERT_TRUE(ToX);
3817
3818 Decl *ToTu = ToX->getTranslationUnitDecl();
3819 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTu, friendDecl());
3820 RecordDecl *ToRecordOfFriend =
3821 const_cast<RecordDecl *>(getRecordDeclOfFriend(ToFriend));
3822
3823 ASSERT_EQ(ToRecordOfFriend->getDeclContext(), cast<DeclContext>(ToTu));
3824 ASSERT_EQ(ToRecordOfFriend->getLexicalDeclContext(), cast<DeclContext>(ToX));
3825 EXPECT_FALSE(
3826 ToRecordOfFriend->getDeclContext()->containsDecl(ToRecordOfFriend));
3827 EXPECT_FALSE(ToRecordOfFriend->getLexicalDeclContext()->containsDecl(
3828 ToRecordOfFriend));
3829 EXPECT_FALSE(ToRecordOfFriend->getLookupParent()
3830 ->lookup(ToRecordOfFriend->getDeclName())
3831 .empty());
3832}
3833
Gabor Marton7df342a2018-12-17 12:42:12 +00003834TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
3835 Decl *FromTu = getTuDecl(
3836 R"(
3837 template<class A> class declToImport {
3838 template<class A1> friend class declToImport;
3839 };
3840 )",
3841 Lang_CXX, "input.cc");
3842
3843 auto *FromD =
3844 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
3845 auto *ToD = Import(FromD, Lang_CXX);
3846
3847 auto Pattern = classTemplateDecl(
3848 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
3849 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3850 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3851
3852 auto *Class =
3853 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
3854 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
3855 EXPECT_NE(Friend->getFriendDecl(), Class);
3856 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
3857}
3858
3859TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
3860 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
3861
3862 ClassTemplateSpecializationDecl *Imported1;
3863 {
3864 Decl *FromTU = getTuDecl("template<class T> class X;"
3865 "struct Y { friend class X<int>; };",
3866 Lang_CXX, "input0.cc");
3867 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3868 FromTU, Pattern);
3869
3870 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3871 }
3872 ClassTemplateSpecializationDecl *Imported2;
3873 {
3874 Decl *FromTU = getTuDecl("template<class T> class X;"
3875 "template<> class X<int>{};"
3876 "struct Z { friend class X<int>; };",
3877 Lang_CXX, "input1.cc");
3878 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3879 FromTU, Pattern);
3880
3881 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3882 }
3883
3884 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3885 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
3886 2u);
3887 ASSERT_TRUE(Imported2->getPreviousDecl());
3888 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
3889}
3890
3891TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
3892 Decl *FromTU0 = getTuDecl(
3893 R"(
3894 class X {
3895 class Y;
3896 };
3897 class X::Y {
3898 template <typename T>
3899 friend class F; // The decl context of F is the global namespace.
3900 };
3901 )",
3902 Lang_CXX, "input0.cc");
3903 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3904 FromTU0, classTemplateDecl(hasName("F")));
3905 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3906 Decl *FromTU1 = getTuDecl(
3907 R"(
3908 template <typename T>
3909 class F {};
3910 )",
3911 Lang_CXX, "input1.cc");
3912 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3913 FromTU1, classTemplateDecl(hasName("F")));
3914 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3915 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
3916 Imported1->getTemplatedDecl()->getTypeForDecl());
3917}
3918
3919TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
3920 Decl *From, *To;
3921 std::tie(From, To) =
3922 getImportedDecl("class declToImport {};", Lang_CXX,
3923 "class Y { friend class declToImport; };", Lang_CXX);
3924 auto *Imported = cast<CXXRecordDecl>(To);
3925
3926 EXPECT_TRUE(Imported->getPreviousDecl());
3927}
3928
3929TEST_P(ImportFriendClasses,
3930 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
3931 Decl *ToTU = getToTuDecl(
3932 R"(
3933 class X {
3934 class Y;
3935 };
3936 class X::Y {
3937 template <typename T>
3938 friend class F; // The decl context of F is the global namespace.
3939 };
3940 )",
3941 Lang_CXX);
3942 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
3943 ToTU, classTemplateDecl(hasName("F")));
3944 Decl *FromTU = getTuDecl(
3945 R"(
3946 template <typename T>
3947 class F {};
3948 )",
3949 Lang_CXX, "input0.cc");
3950 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3951 FromTU, classTemplateDecl(hasName("F")));
3952 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3953 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3954 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
3955 EXPECT_EQ(ToDecl->getTemplatedDecl(),
3956 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3957}
3958
3959TEST_P(ImportFriendClasses,
3960 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
3961 Decl *FromTU0 = getTuDecl(
3962 R"(
3963 class X {
3964 class Y;
3965 };
3966 class X::Y {
3967 template <typename T>
3968 friend class F; // The decl context of F is the global namespace.
3969 };
3970 )",
3971 Lang_CXX, "input0.cc");
3972 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3973 FromTU0, classTemplateDecl(hasName("F")));
3974 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3975 Decl *FromTU1 = getTuDecl(
3976 R"(
3977 template <typename T>
3978 class F {};
3979 )",
3980 Lang_CXX, "input1.cc");
3981 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3982 FromTU1, classTemplateDecl(hasName("F")));
3983 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3984 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3985 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3986 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
3987 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3988}
3989
3990TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
3991 Decl *FromTU0 = getTuDecl(
3992 R"(
3993 class X {
3994 class Y;
3995 };
3996 class X::Y {
3997 friend class F; // The decl context of F is the global namespace.
3998 };
3999 )",
4000 Lang_CXX, "input0.cc");
4001 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
4002 QualType FT = Friend->getFriendType()->getType();
4003 FT = FromTU0->getASTContext().getCanonicalType(FT);
4004 auto *Fwd = cast<TagType>(FT)->getDecl();
4005 auto *ImportedFwd = Import(Fwd, Lang_CXX);
4006 Decl *FromTU1 = getTuDecl(
4007 R"(
4008 class F {};
4009 )",
4010 Lang_CXX, "input1.cc");
4011 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
4012 FromTU1, cxxRecordDecl(hasName("F")));
4013 auto *ImportedDef = Import(Definition, Lang_CXX);
4014 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4015 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4016}
4017
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004018TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Gabor Marton54058b52018-12-17 13:53:12 +00004019 auto *Code = R"(
4020 template <class T>
4021 struct X {
4022 friend void foo(){}
4023 };
4024 )";
4025 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4026 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
4027 ToTU, functionDecl(hasName("foo")));
4028
4029 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
4030 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4031 FromTU, functionDecl(hasName("foo")));
4032 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
4033 EXPECT_EQ(ImportedFoo, ToFoo);
4034}
4035
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004036struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton61d862a2018-05-18 09:08:47 +00004037
4038TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
4039 Decl *TU = getTuDecl(
4040 R"(
4041 namespace NS {
4042
4043 template <typename T>
4044 struct S {};
4045 template struct S<int>;
4046
4047 inline namespace INS {
4048 template <typename T>
4049 struct S {};
4050 template struct S<int>;
4051 }
4052
4053 }
4054 )", Lang_CXX11, "input0.cc");
4055 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4056 TU, namespaceDecl());
4057 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4058 TU, classTemplateSpecializationDecl());
4059 ASSERT_TRUE(NS->containsDecl(Spec));
4060
4061 NS->removeDecl(Spec);
4062 EXPECT_FALSE(NS->containsDecl(Spec));
4063}
4064
Gabor Marton7df342a2018-12-17 12:42:12 +00004065TEST_P(DeclContextTest,
4066 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4067 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
4068 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4069 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
4070
4071 // Investigate the list.
4072 auto *DC = A0->getDeclContext();
4073 ASSERT_TRUE(DC->containsDecl(A0));
4074 ASSERT_TRUE(DC->containsDecl(A1));
4075
4076 // Investigate the lookup table.
4077 auto *Map = DC->getLookupPtr();
4078 ASSERT_TRUE(Map);
4079 auto I = Map->find(A0->getDeclName());
4080 ASSERT_NE(I, Map->end());
4081 StoredDeclsList &L = I->second;
4082 // The lookup table contains the most recent decl of A.
4083 ASSERT_NE(L.getAsDecl(), A0);
4084 ASSERT_EQ(L.getAsDecl(), A1);
4085
4086 ASSERT_TRUE(L.getAsDecl());
4087 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4088 // The point here is to have a Vec with only one element, which is not the
4089 // one we are going to delete from the DC later.
4090 L.setHasExternalDecls();
4091 ASSERT_TRUE(L.getAsVector());
4092 ASSERT_EQ(1u, L.getAsVector()->size());
4093
4094 // This asserts in the old implementation.
4095 DC->removeDecl(A0);
4096 EXPECT_FALSE(DC->containsDecl(A0));
4097}
4098
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004099struct ImportFunctionTemplateSpecializations
4100 : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +00004101
4102TEST_P(ImportFunctionTemplateSpecializations,
4103 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4104
4105 Decl *FromTU = getTuDecl(
4106 R"(
4107 template<class T>
4108 int f() { return 0; }
4109 void foo() { f<int>(); }
4110 )",
4111 Lang_CXX, "input0.cc");
4112
4113 // Check that the function template instantiation is NOT the child of the TU.
4114 auto Pattern = translationUnitDecl(
4115 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
4116 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4117
4118 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4119 FromTU, functionDecl(hasName("foo")));
4120 ASSERT_TRUE(Import(Foo, Lang_CXX));
4121
4122 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4123 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4124}
4125
4126TEST_P(ImportFunctionTemplateSpecializations,
4127 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4128
4129 Decl *FromTU = getTuDecl(
4130 R"(
4131 template<class T>
4132 int f() { return 0; }
4133 template int f<int>();
4134 )",
4135 Lang_CXX, "input0.cc");
4136
4137 // Check that the function template instantiation is NOT the child of the TU.
4138 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
4139 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4140 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4141
4142 ASSERT_TRUE(
4143 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
4144
4145 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4146 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4147}
4148
4149TEST_P(ImportFunctionTemplateSpecializations,
4150 TUshouldContainFunctionTemplateSpecialization) {
4151
4152 Decl *FromTU = getTuDecl(
4153 R"(
4154 template<class T>
4155 int f() { return 0; }
4156 template <> int f<int>() { return 4; }
4157 )",
4158 Lang_CXX, "input0.cc");
4159
4160 // Check that the function template specialization is the child of the TU.
4161 auto Specialization =
4162 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
4163 auto Pattern = translationUnitDecl(has(Specialization));
4164 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4165
4166 ASSERT_TRUE(
4167 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
4168
4169 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4170 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4171}
4172
4173TEST_P(ImportFunctionTemplateSpecializations,
4174 FunctionTemplateSpecializationRedeclChain) {
4175
4176 Decl *FromTU = getTuDecl(
4177 R"(
4178 template<class T>
4179 int f() { return 0; }
4180 template <> int f<int>() { return 4; }
4181 )",
4182 Lang_CXX, "input0.cc");
4183
4184 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
4185 hasParent(translationUnitDecl()));
4186 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
4187 {
4188 auto *TU = FromTU;
4189 auto *SpecD = FromSpecD;
4190 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4191 TU, functionTemplateDecl());
4192 auto *FirstSpecD = *(TemplateD->spec_begin());
4193 ASSERT_EQ(SpecD, FirstSpecD);
4194 ASSERT_TRUE(SpecD->getPreviousDecl());
4195 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4196 ->doesThisDeclarationHaveABody());
4197 }
4198
4199 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
4200
4201 {
4202 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4203 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4204 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4205 TU, functionTemplateDecl());
4206 auto *FirstSpecD = *(TemplateD->spec_begin());
4207 EXPECT_EQ(SpecD, FirstSpecD);
4208 ASSERT_TRUE(SpecD->getPreviousDecl());
4209 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4210 ->doesThisDeclarationHaveABody());
4211 }
4212}
4213
4214TEST_P(ImportFunctionTemplateSpecializations,
4215 MatchNumberOfFunctionTemplateSpecializations) {
4216
4217 Decl *FromTU = getTuDecl(
4218 R"(
4219 template <typename T> constexpr int f() { return 0; }
4220 template <> constexpr int f<int>() { return 4; }
4221 void foo() {
4222 static_assert(f<char>() == 0, "");
4223 static_assert(f<int>() == 4, "");
4224 }
4225 )",
4226 Lang_CXX11, "input0.cc");
4227 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4228 FromTU, functionDecl(hasName("foo")));
4229
4230 Import(FromD, Lang_CXX11);
4231 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4232 EXPECT_EQ(
4233 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4234 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4235}
4236
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004237TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton17d39672018-11-26 15:54:08 +00004238 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4239 {
4240 Decl *FromTU = getTuDecl(
4241 R"(
4242 template <typename T>
4243 struct B;
4244 )",
4245 Lang_CXX, "input0.cc");
4246 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4247 FromTU, classTemplateDecl(hasName("B")));
4248
4249 Import(FromD, Lang_CXX);
4250 }
4251
4252 {
4253 Decl *FromTU = getTuDecl(
4254 R"(
4255 template <typename T>
4256 struct B {
4257 void f();
4258 B* b;
4259 };
4260 )",
4261 Lang_CXX, "input1.cc");
4262 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4263 FromTU, functionDecl(hasName("f")));
4264 Import(FromD, Lang_CXX);
4265 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
4266 FromTU, classTemplateDecl(hasName("B")));
4267 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
4268 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
4269
4270 // We expect no (ODR) warning during the import.
4271 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4272 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4273 }
4274}
4275
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004276TEST_P(ASTImporterOptionSpecificTestBase,
4277 ImportingTypedefShouldImportTheCompleteType) {
Gabor Martonb93baf62018-11-27 09:51:36 +00004278 // We already have an incomplete underlying type in the "To" context.
4279 auto Code =
4280 R"(
4281 template <typename T>
4282 struct S {
4283 void foo();
4284 };
4285 using U = S<int>;
4286 )";
4287 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4288 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4289 typedefNameDecl(hasName("U")));
4290 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4291
4292 // The "From" context has the same typedef, but the underlying type is
4293 // complete this time.
4294 Decl *FromTU = getTuDecl(std::string(Code) +
4295 R"(
4296 void foo(U* u) {
4297 u->foo();
4298 }
4299 )", Lang_CXX11);
4300 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4301 typedefNameDecl(hasName("U")));
4302 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4303
4304 // The imported type should be complete.
4305 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4306 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4307}
4308
Balazs Keri1efc9742019-05-07 10:55:11 +00004309TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) {
4310 auto Code =
4311 R"(
4312 template<class T>
4313 int f() { return 0; }
4314 template <> int f<int>() { return 4; }
4315 )";
4316
4317 Decl *FromTU = getTuDecl(Code, Lang_CXX);
4318 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU,
4319 functionDecl(hasName("f"), isExplicitTemplateSpecialization()));
Balazs Kerib7d8cff2019-05-07 14:53:04 +00004320 ASSERT_EQ(FromD->getNumTemplateParameterLists(), 1u);
Balazs Keri1efc9742019-05-07 10:55:11 +00004321
4322 auto *ToD = Import(FromD, Lang_CXX);
4323 // The template parameter list should exist.
Balazs Kerib7d8cff2019-05-07 14:53:04 +00004324 EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u);
Balazs Keri1efc9742019-05-07 10:55:11 +00004325}
4326
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004327struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton54058b52018-12-17 13:53:12 +00004328
4329TEST_P(ASTImporterLookupTableTest, OneDecl) {
4330 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
4331 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4332 ASTImporterLookupTable LT(*ToTU);
4333 auto Res = LT.lookup(ToTU, D->getDeclName());
4334 ASSERT_EQ(Res.size(), 1u);
4335 EXPECT_EQ(*Res.begin(), D);
4336}
4337
4338static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4339 for (Decl *D : DC->decls()) {
4340 if (auto *ND = dyn_cast<NamedDecl>(D))
4341 if (ND->getDeclName() == Name)
4342 return ND;
4343 }
4344 return nullptr;
Martin Storsjo85833392018-12-18 08:36:16 +00004345}
Gabor Marton54058b52018-12-17 13:53:12 +00004346
4347TEST_P(ASTImporterLookupTableTest,
4348 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4349 auto *Code = R"(
4350 template <class T>
4351 struct X {
4352 friend void foo(){}
4353 };
4354 )";
4355 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4356 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
4357 ToTU, classTemplateDecl(hasName("X")));
4358 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4359 ToTU, functionDecl(hasName("foo")));
4360 DeclContext *FooDC = Foo->getDeclContext();
4361 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4362 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
4363 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4364 DeclarationName FooName = Foo->getDeclName();
4365
4366 // Cannot find in the LookupTable of its DC (TUDecl)
4367 SmallVector<NamedDecl *, 2> FoundDecls;
4368 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4369 EXPECT_EQ(FoundDecls.size(), 0u);
4370
4371 // Cannot find in the LookupTable of its LexicalDC (X)
4372 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4373 EXPECT_EQ(FoundDecls.size(), 0u);
4374
4375 // Can't find in the list of Decls of the DC.
4376 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4377
4378 // Can't find in the list of Decls of the LexicalDC
4379 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
4380
4381 // ASTImporter specific lookup finds it.
4382 ASTImporterLookupTable LT(*ToTU);
4383 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4384 ASSERT_EQ(Res.size(), 1u);
4385 EXPECT_EQ(*Res.begin(), Foo);
4386}
4387
4388TEST_P(ASTImporterLookupTableTest,
4389 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
4390 TranslationUnitDecl *ToTU =
4391 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
4392 auto *Foo =
4393 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
4394 auto *A =
4395 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4396 DeclContext *FooDC = Foo->getDeclContext();
4397 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4398 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
4399 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4400 DeclarationName FooName = Foo->getDeclName();
4401
4402 // Cannot find in the LookupTable of its DC (TUDecl).
4403 SmallVector<NamedDecl *, 2> FoundDecls;
4404 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4405 EXPECT_EQ(FoundDecls.size(), 0u);
4406
4407 // Cannot find in the LookupTable of its LexicalDC (A).
4408 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4409 EXPECT_EQ(FoundDecls.size(), 0u);
4410
4411 // Can't find in the list of Decls of the DC.
4412 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4413
4414 // Can find in the list of Decls of the LexicalDC.
4415 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
4416
4417 // ASTImporter specific lookup finds it.
4418 ASTImporterLookupTable LT(*ToTU);
4419 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4420 ASSERT_EQ(Res.size(), 1u);
4421 EXPECT_EQ(*Res.begin(), Foo);
4422}
4423
4424TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
4425 TranslationUnitDecl *ToTU =
4426 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
4427 DeclarationName VName = FirstDeclMatcher<VarDecl>()
4428 .match(ToTU, varDecl(hasName("V")))
4429 ->getDeclName();
4430 auto *A =
4431 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4432 auto *B =
4433 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
4434
4435 ASTImporterLookupTable LT(*ToTU);
4436
4437 auto Res = LT.lookup(cast<DeclContext>(A), VName);
4438 ASSERT_EQ(Res.size(), 1u);
4439 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4440 ToTU, fieldDecl(hasName("V"),
4441 hasParent(recordDecl(hasName("A"))))));
4442 Res = LT.lookup(cast<DeclContext>(B), VName);
4443 ASSERT_EQ(Res.size(), 1u);
4444 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4445 ToTU, fieldDecl(hasName("V"),
4446 hasParent(recordDecl(hasName("B"))))));
4447 Res = LT.lookup(ToTU, VName);
4448 ASSERT_EQ(Res.size(), 1u);
4449 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
4450 ToTU, varDecl(hasName("V"),
4451 hasParent(translationUnitDecl()))));
4452}
4453
4454TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
4455 TranslationUnitDecl *ToTU = getToTuDecl(
4456 R"(
4457 void foo();
4458 void foo(int);
4459 void foo(int, int);
4460 )",
4461 Lang_CXX);
4462
4463 ASTImporterLookupTable LT(*ToTU);
4464 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4465 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4466 DeclarationName Name = F0->getDeclName();
4467 auto Res = LT.lookup(ToTU, Name);
4468 EXPECT_EQ(Res.size(), 3u);
4469 EXPECT_EQ(Res.count(F0), 1u);
4470 EXPECT_EQ(Res.count(F2), 1u);
4471}
4472
Gabor Martona9cab312019-02-08 09:19:34 +00004473TEST_P(ASTImporterLookupTableTest,
4474 DifferentOperatorsShouldHaveDifferentResultSet) {
4475 TranslationUnitDecl *ToTU = getToTuDecl(
4476 R"(
4477 struct X{};
4478 void operator+(X, X);
4479 void operator-(X, X);
4480 )",
4481 Lang_CXX);
4482
4483 ASTImporterLookupTable LT(*ToTU);
4484 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
4485 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4486 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
4487 ToTU, functionDecl(hasOverloadedOperatorName("-")));
4488 DeclarationName NamePlus = FPlus->getDeclName();
4489 auto ResPlus = LT.lookup(ToTU, NamePlus);
4490 EXPECT_EQ(ResPlus.size(), 1u);
4491 EXPECT_EQ(ResPlus.count(FPlus), 1u);
4492 EXPECT_EQ(ResPlus.count(FMinus), 0u);
4493 DeclarationName NameMinus = FMinus->getDeclName();
4494 auto ResMinus = LT.lookup(ToTU, NameMinus);
4495 EXPECT_EQ(ResMinus.size(), 1u);
4496 EXPECT_EQ(ResMinus.count(FMinus), 1u);
4497 EXPECT_EQ(ResMinus.count(FPlus), 0u);
4498 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
4499}
4500
4501TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
4502 TranslationUnitDecl *ToTU = getToTuDecl(
4503 R"(
4504 struct X {};
4505 void operator+(X, X);
4506 )",
4507 Lang_CXX);
4508 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
4509 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4510
4511 Decl *FromTU = getTuDecl(
4512 R"(
4513 struct X {};
4514 void operator+(X, X);
4515 )",
4516 Lang_CXX);
4517 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
4518 FromTU, functionDecl(hasOverloadedOperatorName("+")));
4519
4520 // FromPlus have a different TU, thus its DeclarationName is different too.
4521 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
4522
4523 ASTImporterLookupTable LT(*ToTU);
4524 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
4525 ASSERT_EQ(Res.size(), 1u);
4526 EXPECT_EQ(*Res.begin(), ToPlus);
4527
4528 // FromPlus have a different TU, thus its DeclarationName is different too.
4529 Res = LT.lookup(ToTU, FromPlus->getDeclName());
4530 ASSERT_EQ(Res.size(), 0u);
4531}
4532
Gabor Martondd2b76e2019-06-11 13:35:25 +00004533TEST_P(ASTImporterLookupTableTest,
4534 LookupFindsFwdFriendClassDeclWithElaboratedType) {
Gabor Marton54058b52018-12-17 13:53:12 +00004535 TranslationUnitDecl *ToTU = getToTuDecl(
4536 R"(
4537 class Y { friend class F; };
4538 )",
4539 Lang_CXX);
4540
4541 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4542 // So we must dig up the underlying CXXRecordDecl.
4543 ASTImporterLookupTable LT(*ToTU);
4544 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4545 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4546 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
4547 ToTU, cxxRecordDecl(hasName("Y")));
4548
4549 DeclarationName Name = RD->getDeclName();
4550 auto Res = LT.lookup(ToTU, Name);
4551 EXPECT_EQ(Res.size(), 1u);
4552 EXPECT_EQ(*Res.begin(), RD);
4553
4554 Res = LT.lookup(Y, Name);
4555 EXPECT_EQ(Res.size(), 0u);
4556}
4557
Gabor Martondd2b76e2019-06-11 13:35:25 +00004558TEST_P(ASTImporterLookupTableTest,
4559 LookupFindsFwdFriendClassDeclWithUnelaboratedType) {
4560 TranslationUnitDecl *ToTU = getToTuDecl(
4561 R"(
4562 class F;
4563 class Y { friend F; };
4564 )",
4565 Lang_CXX11);
4566
4567 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4568 // So we must dig up the underlying CXXRecordDecl.
4569 ASTImporterLookupTable LT(*ToTU);
4570 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4571 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4572 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, cxxRecordDecl(hasName("Y")));
4573
4574 DeclarationName Name = RD->getDeclName();
4575 auto Res = LT.lookup(ToTU, Name);
4576 EXPECT_EQ(Res.size(), 1u);
4577 EXPECT_EQ(*Res.begin(), RD);
4578
4579 Res = LT.lookup(Y, Name);
4580 EXPECT_EQ(Res.size(), 0u);
4581}
4582
4583TEST_P(ASTImporterLookupTableTest,
4584 LookupFindsFriendClassDeclWithTypeAliasDoesNotAssert) {
4585 TranslationUnitDecl *ToTU = getToTuDecl(
4586 R"(
4587 class F;
4588 using alias_of_f = F;
4589 class Y { friend alias_of_f; };
4590 )",
4591 Lang_CXX11);
4592
4593 // ASTImporterLookupTable constructor handles using declarations correctly,
4594 // no assert is expected.
4595 ASTImporterLookupTable LT(*ToTU);
4596
4597 auto *Alias = FirstDeclMatcher<TypeAliasDecl>().match(
4598 ToTU, typeAliasDecl(hasName("alias_of_f")));
4599 DeclarationName Name = Alias->getDeclName();
4600 auto Res = LT.lookup(ToTU, Name);
4601 EXPECT_EQ(Res.count(Alias), 1u);
4602}
4603
Gabor Marton54058b52018-12-17 13:53:12 +00004604TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
4605 TranslationUnitDecl *ToTU = getToTuDecl(
4606 R"(
4607 class Y { template <class T> friend class F; };
4608 )",
4609 Lang_CXX);
4610
4611 ASTImporterLookupTable LT(*ToTU);
4612 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4613 ToTU, classTemplateDecl(hasName("F")));
4614 DeclarationName Name = F->getDeclName();
4615 auto Res = LT.lookup(ToTU, Name);
4616 EXPECT_EQ(Res.size(), 2u);
4617 EXPECT_EQ(Res.count(F), 1u);
4618 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4619}
4620
4621TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
4622 TranslationUnitDecl *ToTU = getToTuDecl(
4623 R"(
4624 template <typename T>
4625 class F;
4626
4627 template <typename T>
4628 class Y {
4629 friend class F<T>;
4630 };
4631 )",
4632 Lang_CXX);
4633
4634 ASTImporterLookupTable LT(*ToTU);
4635 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4636 ToTU, classTemplateDecl(hasName("F")));
4637 DeclarationName Name = F->getDeclName();
4638 auto Res = LT.lookup(ToTU, Name);
4639 EXPECT_EQ(Res.size(), 2u);
4640 EXPECT_EQ(Res.count(F), 1u);
4641 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4642}
4643
4644TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
4645 TranslationUnitDecl *ToTU = getToTuDecl(
4646 R"(
4647 template <typename T>
4648 class F;
4649
4650 class Y {
4651 friend class F<int>;
4652 };
4653 )",
4654 Lang_CXX);
4655
4656 ASTImporterLookupTable LT(*ToTU);
4657 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4658 ToTU, classTemplateDecl(hasName("F")));
4659 DeclarationName Name = F->getDeclName();
4660 auto Res = LT.lookup(ToTU, Name);
4661 ASSERT_EQ(Res.size(), 3u);
4662 EXPECT_EQ(Res.count(F), 1u);
4663 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4664 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
4665}
4666
4667TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
4668 TranslationUnitDecl *ToTU = getToTuDecl(
4669 R"(
4670 class Y { friend void F(); };
4671 )",
4672 Lang_CXX);
4673
4674 ASTImporterLookupTable LT(*ToTU);
4675 auto *F =
4676 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
4677 DeclarationName Name = F->getDeclName();
4678 auto Res = LT.lookup(ToTU, Name);
4679 EXPECT_EQ(Res.size(), 1u);
4680 EXPECT_EQ(*Res.begin(), F);
4681}
4682
4683TEST_P(ASTImporterLookupTableTest,
4684 LookupFindsDeclsInClassTemplateSpecialization) {
4685 TranslationUnitDecl *ToTU = getToTuDecl(
4686 R"(
4687 template <typename T>
4688 struct X {
4689 int F;
4690 };
4691 void foo() {
4692 X<char> xc;
4693 }
4694 )",
4695 Lang_CXX);
4696
4697 ASTImporterLookupTable LT(*ToTU);
4698
4699 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
4700 ToTU, classTemplateDecl(hasName("X")));
4701 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
4702 ToTU,
4703 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
4704
4705 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4706 ToTU, classTemplateSpecializationDecl(hasName("X")));
4707 FieldDecl *FieldInSpec = *Spec->field_begin();
4708 ASSERT_TRUE(FieldInSpec);
4709
4710 DeclarationName Name = FieldInSpec->getDeclName();
4711 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
4712
4713 SmallVector<NamedDecl *, 2> FoundDecls;
4714 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
4715 EXPECT_EQ(FoundDecls.size(), 1u);
4716 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
4717
4718 auto Res = LT.lookup(TemplateDC, Name);
4719 ASSERT_EQ(Res.size(), 1u);
4720 EXPECT_EQ(*Res.begin(), FieldInTemplate);
4721
4722 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
4723 FoundDecls);
4724 EXPECT_EQ(FoundDecls.size(), 1u);
4725 EXPECT_EQ(FoundDecls[0], FieldInSpec);
4726
4727 Res = LT.lookup(cast<DeclContext>(Spec), Name);
4728 ASSERT_EQ(Res.size(), 1u);
4729 EXPECT_EQ(*Res.begin(), FieldInSpec);
4730}
4731
4732TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
4733 TranslationUnitDecl *ToTU = getToTuDecl(
4734 R"(
4735 class Y { template <class T> friend void F(); };
4736 )",
4737 Lang_CXX);
4738
4739 ASTImporterLookupTable LT(*ToTU);
4740 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
4741 ToTU, functionTemplateDecl(hasName("F")));
4742 DeclarationName Name = F->getDeclName();
4743 auto Res = LT.lookup(ToTU, Name);
4744 EXPECT_EQ(Res.size(), 2u);
4745 EXPECT_EQ(Res.count(F), 1u);
4746 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4747}
4748
4749TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
4750 TranslationUnitDecl *ToTU = getToTuDecl(
4751 R"(
4752 struct X;
4753 struct A {
4754 friend struct X;
4755 };
4756 struct B {
4757 friend struct X;
4758 };
4759 )",
4760 Lang_CXX);
4761
4762 ASTImporterLookupTable LT(*ToTU);
4763 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
4764 ToTU, cxxRecordDecl(hasName("X")));
4765 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4766 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4767 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
4768 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
4769 ASSERT_EQ(RD0, RD1);
4770 ASSERT_EQ(RD1, X);
4771
4772 DeclarationName Name = X->getDeclName();
4773 auto Res = LT.lookup(ToTU, Name);
4774 EXPECT_EQ(Res.size(), 1u);
4775 EXPECT_EQ(*Res.begin(), X);
4776}
4777
4778TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
4779 TranslationUnitDecl *ToTU = getToTuDecl(
4780 R"(
4781 enum E {
4782 A,
4783 B
4784 };
4785 )",
4786 Lang_C);
4787
4788 ASTImporterLookupTable LT(*ToTU);
4789 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
4790 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
4791 ToTU, enumConstantDecl(hasName("A")));
4792
4793 DeclarationName Name = A->getDeclName();
4794 // Redecl context is the TU.
4795 ASSERT_EQ(E->getRedeclContext(), ToTU);
4796
4797 SmallVector<NamedDecl *, 2> FoundDecls;
4798 // Normal lookup finds in the DC.
4799 E->localUncachedLookup(Name, FoundDecls);
4800 EXPECT_EQ(FoundDecls.size(), 1u);
4801
4802 // Normal lookup finds in the Redecl context.
4803 ToTU->localUncachedLookup(Name, FoundDecls);
4804 EXPECT_EQ(FoundDecls.size(), 1u);
4805
4806 // Import specific lookup finds in the DC.
4807 auto Res = LT.lookup(E, Name);
4808 ASSERT_EQ(Res.size(), 1u);
4809 EXPECT_EQ(*Res.begin(), A);
4810
4811 // Import specific lookup finds in the Redecl context.
4812 Res = LT.lookup(ToTU, Name);
4813 ASSERT_EQ(Res.size(), 1u);
4814 EXPECT_EQ(*Res.begin(), A);
4815}
4816
4817TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
4818 TranslationUnitDecl *ToTU = getToTuDecl(
4819 R"(
4820 namespace N {
4821 int A;
4822 }
4823 namespace N {
4824 }
4825 )",
4826 Lang_CXX);
4827 auto *N1 =
4828 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
4829 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
4830 DeclarationName Name = A->getDeclName();
4831
4832 ASTImporterLookupTable LT(*ToTU);
4833 auto Res = LT.lookup(N1, Name);
4834 ASSERT_EQ(Res.size(), 1u);
4835 EXPECT_EQ(*Res.begin(), A);
4836}
4837
Gabor Marton0e04ebd2019-02-11 10:27:58 +00004838TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton305a11d2019-10-07 11:34:54 +00004839 RedeclChainShouldBeCorrectAmongstNamespaces) {
Gabor Marton0e04ebd2019-02-11 10:27:58 +00004840 Decl *FromTU = getTuDecl(
4841 R"(
4842 namespace NS {
4843 struct X;
4844 struct Y {
4845 static const int I = 3;
4846 };
4847 }
4848 namespace NS {
4849 struct X { // <--- To be imported
4850 void method(int i = Y::I) {}
4851 int f;
4852 };
4853 }
4854 )",
4855 Lang_CXX);
4856 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
4857 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
4858 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
4859 FromTU,
4860 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
4861 ASSERT_NE(FromFwd, FromDef);
4862 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
4863 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4864 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
4865
4866 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX));
4867 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX));
4868 EXPECT_NE(ToFwd, ToDef);
4869 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
4870 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4871 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
4872 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4873 // We expect no (ODR) warning during the import.
4874 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4875}
4876
Gabor Martone331e632019-02-18 13:09:27 +00004877struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
4878
4879TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
4880 Decl *ToTU = getToTuDecl(
4881 R"(
4882 class X {
4883 template <typename T> friend void foo();
4884 };
4885 )",
4886 Lang_CXX);
4887 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
4888 ToTU, functionTemplateDecl(hasName("foo")));
4889
4890 Decl *FromTU = getTuDecl(
4891 R"(
4892 template <typename T> void foo();
4893 )",
4894 Lang_CXX);
4895 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
4896 FromTU, functionTemplateDecl(hasName("foo")));
4897 auto *Imported = Import(FromFoo, Lang_CXX);
4898
Gabor Marton16d98c22019-03-07 13:01:51 +00004899 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
Gabor Martone331e632019-02-18 13:09:27 +00004900}
4901
Gabor Marton303c98612019-06-25 08:00:51 +00004902struct ASTImporterWithFakeErrors : ASTImporter {
4903 using ASTImporter::ASTImporter;
4904 bool returnWithErrorInTest() override { return true; }
4905};
4906
4907struct ErrorHandlingTest : ASTImporterOptionSpecificTestBase {
4908 ErrorHandlingTest() {
4909 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
4910 ASTContext &FromContext, FileManager &FromFileManager,
Gabor Marton2afbfb62019-07-01 15:37:07 +00004911 bool MinimalImport,
4912 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
Gabor Marton303c98612019-06-25 08:00:51 +00004913 return new ASTImporterWithFakeErrors(ToContext, ToFileManager,
4914 FromContext, FromFileManager,
Gabor Marton2afbfb62019-07-01 15:37:07 +00004915 MinimalImport, SharedState);
Gabor Marton303c98612019-06-25 08:00:51 +00004916 };
4917 }
4918 // In this test we purposely report an error (UnsupportedConstruct) when
4919 // importing the below stmt.
4920 static constexpr auto* ErroneousStmt = R"( asm(""); )";
4921};
4922
4923// Check a case when no new AST node is created in the AST before encountering
4924// the error.
4925TEST_P(ErrorHandlingTest, ErrorHappensBeforeCreatingANewNode) {
4926 TranslationUnitDecl *ToTU = getToTuDecl(
4927 R"(
4928 template <typename T>
4929 class X {};
4930 template <>
4931 class X<int> { int a; };
4932 )",
4933 Lang_CXX);
4934 TranslationUnitDecl *FromTU = getTuDecl(
4935 R"(
4936 template <typename T>
4937 class X {};
4938 template <>
4939 class X<int> { double b; };
4940 )",
4941 Lang_CXX);
4942 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4943 FromTU, classTemplateSpecializationDecl(hasName("X")));
4944 ClassTemplateSpecializationDecl *ImportedSpec = Import(FromSpec, Lang_CXX);
4945 EXPECT_FALSE(ImportedSpec);
4946
4947 // The original Decl is kept, no new decl is created.
4948 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(
4949 ToTU, classTemplateSpecializationDecl(hasName("X"))),
4950 1u);
4951
4952 // But an error is set to the counterpart in the "from" context.
4953 ASTImporter *Importer = findFromTU(FromSpec)->Importer.get();
4954 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromSpec);
4955 ASSERT_TRUE(OptErr);
4956 EXPECT_EQ(OptErr->Error, ImportError::NameConflict);
4957}
4958
4959// Check a case when a new AST node is created but not linked to the AST before
4960// encountering the error.
4961TEST_P(ErrorHandlingTest,
4962 ErrorHappensAfterCreatingTheNodeButBeforeLinkingThatToTheAST) {
4963 TranslationUnitDecl *FromTU = getTuDecl(
4964 std::string("void foo() { ") + ErroneousStmt + " }",
4965 Lang_CXX);
4966 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4967 FromTU, functionDecl(hasName("foo")));
4968
4969 FunctionDecl *ImportedFoo = Import(FromFoo, Lang_CXX);
4970 EXPECT_FALSE(ImportedFoo);
4971
4972 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4973 // Created, but not linked.
4974 EXPECT_EQ(
4975 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("foo"))),
4976 0u);
4977
4978 ASTImporter *Importer = findFromTU(FromFoo)->Importer.get();
4979 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFoo);
4980 ASSERT_TRUE(OptErr);
4981 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4982}
4983
4984// Check a case when a new AST node is created and linked to the AST before
4985// encountering the error. The error is set for the counterpart of the nodes in
4986// the "from" context.
4987TEST_P(ErrorHandlingTest, ErrorHappensAfterNodeIsCreatedAndLinked) {
4988 TranslationUnitDecl *FromTU = getTuDecl(
4989 std::string(R"(
4990 void f();
4991 void f() { )") + ErroneousStmt + R"( }
4992 )",
4993 Lang_CXX);
4994 auto *FromProto = FirstDeclMatcher<FunctionDecl>().match(
4995 FromTU, functionDecl(hasName("f")));
4996 auto *FromDef =
4997 LastDeclMatcher<FunctionDecl>().match(FromTU, functionDecl(hasName("f")));
4998 FunctionDecl *ImportedProto = Import(FromProto, Lang_CXX);
4999 EXPECT_FALSE(ImportedProto); // Could not import.
5000 // However, we created two nodes in the AST. 1) the fwd decl 2) the
5001 // definition. The definition is not added to its DC, but the fwd decl is
5002 // there.
5003 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5004 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
5005 1u);
5006 // Match the fwd decl.
5007 auto *ToProto =
5008 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("f")));
5009 EXPECT_TRUE(ToProto);
5010 // An error is set to the counterpart in the "from" context both for the fwd
5011 // decl and the definition.
5012 ASTImporter *Importer = findFromTU(FromProto)->Importer.get();
5013 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromProto);
5014 ASSERT_TRUE(OptErr);
5015 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5016 OptErr = Importer->getImportDeclErrorIfAny(FromDef);
5017 ASSERT_TRUE(OptErr);
5018 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5019}
5020
Gabor Marton17c3eaf2019-07-01 12:44:39 +00005021// An error should be set for a class if we cannot import one member.
5022TEST_P(ErrorHandlingTest, ErrorIsPropagatedFromMemberToClass) {
5023 TranslationUnitDecl *FromTU = getTuDecl(
5024 std::string(R"(
5025 class X {
5026 void f() { )") + ErroneousStmt + R"( } // This member has the error
5027 // during import.
5028 void ok(); // The error should not prevent importing this.
5029 }; // An error will be set for X too.
5030 )",
5031 Lang_CXX);
5032 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5033 FromTU, cxxRecordDecl(hasName("X")));
5034 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX);
5035
5036 // An error is set for X.
5037 EXPECT_FALSE(ImportedX);
5038 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5039 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5040 ASSERT_TRUE(OptErr);
5041 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5042
5043 // An error is set for f().
5044 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
5045 FromTU, cxxMethodDecl(hasName("f")));
5046 OptErr = Importer->getImportDeclErrorIfAny(FromF);
5047 ASSERT_TRUE(OptErr);
5048 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5049 // And any subsequent import should fail.
5050 CXXMethodDecl *ImportedF = Import(FromF, Lang_CXX);
5051 EXPECT_FALSE(ImportedF);
5052
Gabor Marton1ad4b992019-07-01 14:19:53 +00005053 // There is an error set for the other member too.
Gabor Marton17c3eaf2019-07-01 12:44:39 +00005054 auto *FromOK = FirstDeclMatcher<CXXMethodDecl>().match(
5055 FromTU, cxxMethodDecl(hasName("ok")));
5056 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
Gabor Marton1ad4b992019-07-01 14:19:53 +00005057 EXPECT_TRUE(OptErr);
5058 // Cannot import the other member.
Gabor Marton17c3eaf2019-07-01 12:44:39 +00005059 CXXMethodDecl *ImportedOK = Import(FromOK, Lang_CXX);
Gabor Marton1ad4b992019-07-01 14:19:53 +00005060 EXPECT_FALSE(ImportedOK);
5061}
Gabor Marton17c3eaf2019-07-01 12:44:39 +00005062
Gabor Marton1ad4b992019-07-01 14:19:53 +00005063// Check that an error propagates to the dependent AST nodes.
5064// In the below code it means that an error in X should propagate to A.
5065// And even to F since the containing A is erroneous.
5066// And to all AST nodes which we visit during the import process which finally
5067// ends up in a failure (in the error() function).
5068TEST_P(ErrorHandlingTest, ErrorPropagatesThroughImportCycles) {
5069 Decl *FromTU = getTuDecl(
5070 std::string(R"(
5071 namespace NS {
5072 class A {
5073 template <int I> class F {};
5074 class X {
5075 template <int I> friend class F;
5076 void error() { )") + ErroneousStmt + R"( }
5077 };
5078 };
5079
5080 class B {};
5081 } // NS
5082 )",
5083 Lang_CXX, "input0.cc");
5084
5085 auto *FromFRD = FirstDeclMatcher<CXXRecordDecl>().match(
5086 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
5087 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
5088 FromTU, cxxRecordDecl(hasName("A"), isDefinition()));
5089 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(
5090 FromTU, cxxRecordDecl(hasName("B"), isDefinition()));
5091 auto *FromNS = FirstDeclMatcher<NamespaceDecl>().match(
5092 FromTU, namespaceDecl(hasName("NS")));
5093
5094 // Start by importing the templated CXXRecordDecl of F.
5095 // Import fails for that.
5096 EXPECT_FALSE(Import(FromFRD, Lang_CXX));
5097 // Import fails for A.
5098 EXPECT_FALSE(Import(FromA, Lang_CXX));
5099 // But we should be able to import the independent B.
5100 EXPECT_TRUE(Import(FromB, Lang_CXX));
5101 // And the namespace.
5102 EXPECT_TRUE(Import(FromNS, Lang_CXX));
5103
5104 // An error is set to the templated CXXRecordDecl of F.
5105 ASTImporter *Importer = findFromTU(FromFRD)->Importer.get();
5106 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFRD);
5107 EXPECT_TRUE(OptErr);
5108
5109 // An error is set to A.
5110 OptErr = Importer->getImportDeclErrorIfAny(FromA);
5111 EXPECT_TRUE(OptErr);
5112
5113 // There is no error set to B.
5114 OptErr = Importer->getImportDeclErrorIfAny(FromB);
5115 EXPECT_FALSE(OptErr);
5116
5117 // There is no error set to NS.
5118 OptErr = Importer->getImportDeclErrorIfAny(FromNS);
5119 EXPECT_FALSE(OptErr);
5120
5121 // Check some of those decls whose ancestor is X, they all should have an
5122 // error set if we visited them during an import process which finally failed.
5123 // These decls are part of a cycle in an ImportPath.
5124 // There would not be any error set for these decls if we hadn't follow the
5125 // ImportPaths and the cycles.
5126 OptErr = Importer->getImportDeclErrorIfAny(
5127 FirstDeclMatcher<ClassTemplateDecl>().match(
5128 FromTU, classTemplateDecl(hasName("F"))));
5129 // An error is set to the 'F' ClassTemplateDecl.
5130 EXPECT_TRUE(OptErr);
5131 // An error is set to the FriendDecl.
5132 OptErr = Importer->getImportDeclErrorIfAny(
5133 FirstDeclMatcher<FriendDecl>().match(
5134 FromTU, friendDecl()));
5135 EXPECT_TRUE(OptErr);
5136 // An error is set to the implicit class of A.
5137 OptErr =
5138 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
5139 FromTU, cxxRecordDecl(hasName("A"), isImplicit())));
5140 EXPECT_TRUE(OptErr);
5141 // An error is set to the implicit class of X.
5142 OptErr =
5143 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
5144 FromTU, cxxRecordDecl(hasName("X"), isImplicit())));
5145 EXPECT_TRUE(OptErr);
Gabor Marton17c3eaf2019-07-01 12:44:39 +00005146}
5147
5148TEST_P(ErrorHandlingTest, ErrorIsNotPropagatedFromMemberToNamespace) {
5149 TranslationUnitDecl *FromTU = getTuDecl(
5150 std::string(R"(
5151 namespace X {
5152 void f() { )") + ErroneousStmt + R"( } // This member has the error
5153 // during import.
5154 void ok(); // The error should not prevent importing this.
5155 }; // An error will be set for X too.
5156 )",
5157 Lang_CXX);
5158 auto *FromX = FirstDeclMatcher<NamespaceDecl>().match(
5159 FromTU, namespaceDecl(hasName("X")));
5160 NamespaceDecl *ImportedX = Import(FromX, Lang_CXX);
5161
5162 // There is no error set for X.
5163 EXPECT_TRUE(ImportedX);
5164 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5165 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5166 ASSERT_FALSE(OptErr);
5167
5168 // An error is set for f().
5169 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
5170 FromTU, functionDecl(hasName("f")));
5171 OptErr = Importer->getImportDeclErrorIfAny(FromF);
5172 ASSERT_TRUE(OptErr);
5173 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5174 // And any subsequent import should fail.
5175 FunctionDecl *ImportedF = Import(FromF, Lang_CXX);
5176 EXPECT_FALSE(ImportedF);
5177
5178 // There is no error set for ok().
5179 auto *FromOK = FirstDeclMatcher<FunctionDecl>().match(
5180 FromTU, functionDecl(hasName("ok")));
5181 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
5182 EXPECT_FALSE(OptErr);
5183 // And we should be able to import.
5184 FunctionDecl *ImportedOK = Import(FromOK, Lang_CXX);
5185 EXPECT_TRUE(ImportedOK);
5186}
5187
Gabor Marton2afbfb62019-07-01 15:37:07 +00005188// An error should be set for a class if it had a previous import with an error
5189// from another TU.
5190TEST_P(ErrorHandlingTest,
5191 ImportedDeclWithErrorShouldFailTheImportOfDeclWhichMapToIt) {
5192 // We already have a fwd decl.
5193 TranslationUnitDecl *ToTU = getToTuDecl(
5194 "class X;", Lang_CXX);
5195 // Then we import a definition.
5196 {
5197 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5198 class X {
5199 void f() { )") + ErroneousStmt + R"( }
5200 void ok();
5201 };
5202 )",
5203 Lang_CXX);
5204 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5205 FromTU, cxxRecordDecl(hasName("X")));
5206 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX);
5207
5208 // An error is set for X ...
5209 EXPECT_FALSE(ImportedX);
5210 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5211 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5212 ASSERT_TRUE(OptErr);
5213 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5214 }
5215 // ... but the node had been created.
5216 auto *ToXDef = FirstDeclMatcher<CXXRecordDecl>().match(
5217 ToTU, cxxRecordDecl(hasName("X"), isDefinition()));
5218 // An error is set for "ToXDef" in the shared state.
5219 Optional<ImportError> OptErr =
5220 SharedStatePtr->getImportDeclErrorIfAny(ToXDef);
5221 ASSERT_TRUE(OptErr);
5222 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5223
5224 auto *ToXFwd = FirstDeclMatcher<CXXRecordDecl>().match(
5225 ToTU, cxxRecordDecl(hasName("X"), unless(isDefinition())));
5226 // An error is NOT set for the fwd Decl of X in the shared state.
5227 OptErr = SharedStatePtr->getImportDeclErrorIfAny(ToXFwd);
5228 ASSERT_FALSE(OptErr);
5229
5230 // Try to import X again but from another TU.
5231 {
5232 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5233 class X {
5234 void f() { )") + ErroneousStmt + R"( }
5235 void ok();
5236 };
5237 )",
5238 Lang_CXX, "input1.cc");
5239
5240 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5241 FromTU, cxxRecordDecl(hasName("X")));
5242 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX);
5243
5244 // If we did not save the errors for the "to" context then the below checks
5245 // would fail, because the lookup finds the fwd Decl of the existing
5246 // definition in the "to" context. We can reach the existing definition via
5247 // the found fwd Decl. That existing definition is structurally equivalent
5248 // (we check only the fields) with this one we want to import, so we return
5249 // with the existing definition, which is erroneous (one method is missing).
5250
5251 // The import should fail.
5252 EXPECT_FALSE(ImportedX);
5253 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
5254 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
5255 // And an error is set for this new X in the "from" ctx.
5256 ASSERT_TRUE(OptErr);
5257 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5258 }
5259}
5260
Balazs Kerib4fd7d42019-08-30 10:12:14 +00005261TEST_P(ErrorHandlingTest, ImportOfOverriddenMethods) {
5262 auto MatchFooA =
5263 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("A"))));
5264 auto MatchFooB =
5265 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("B"))));
5266 auto MatchFooC =
5267 functionDecl(hasName("foo"), hasAncestor(cxxRecordDecl(hasName("C"))));
5268
5269 // Provoke import of a method that has overridden methods with import error.
5270 TranslationUnitDecl *FromTU = getTuDecl(std::string(R"(
5271 struct C;
5272 struct A {
5273 virtual void foo();
5274 void f1(C *);
5275 };
5276 void A::foo() {
5277 )") + ErroneousStmt + R"(
5278 }
5279 struct B : public A {
5280 void foo() override;
5281 };
5282 struct C : public B {
5283 void foo() override;
5284 };
5285 )",
5286 Lang_CXX11);
5287 auto *FromFooA = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooA);
5288 auto *FromFooB = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooB);
5289 auto *FromFooC = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooC);
5290
5291 EXPECT_FALSE(Import(FromFooA, Lang_CXX11));
5292 ASTImporter *Importer = findFromTU(FromFooA)->Importer.get();
5293 auto CheckError = [&Importer](Decl *FromD) {
5294 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromD);
5295 ASSERT_TRUE(OptErr);
5296 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
5297 };
5298 CheckError(FromFooA);
5299 EXPECT_FALSE(Import(FromFooB, Lang_CXX11));
5300 CheckError(FromFooB);
5301 EXPECT_FALSE(Import(FromFooC, Lang_CXX11));
5302 CheckError(FromFooC);
5303}
5304
Gabor Martone73805f2019-07-08 12:49:13 +00005305TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) {
5306 Decl *FromTU = getTuDecl(
5307 R"(
5308 void f() {
5309 auto L = [](){};
5310 }
5311 )",
5312 Lang_CXX11, "input0.cc");
5313 auto Pattern = lambdaExpr();
5314 CXXRecordDecl *FromL =
5315 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5316
5317 auto ToL = Import(FromL, Lang_CXX11);
5318 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
5319 unsigned FromLSize =
5320 std::distance(FromL->decls().begin(), FromL->decls().end());
5321 EXPECT_NE(ToLSize, 0u);
5322 EXPECT_EQ(ToLSize, FromLSize);
5323}
5324
5325TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
5326 Decl *FromTU = getTuDecl(
5327 R"(
5328 template <typename F>
5329 void f(F L = [](){}) {}
5330 )",
5331 Lang_CXX11, "input0.cc");
5332 auto Pattern = lambdaExpr();
5333 CXXRecordDecl *FromL =
5334 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5335
5336 auto ToL = Import(FromL, Lang_CXX11);
5337 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
5338 unsigned FromLSize =
5339 std::distance(FromL->decls().begin(), FromL->decls().end());
5340 EXPECT_NE(ToLSize, 0u);
5341 EXPECT_EQ(ToLSize, FromLSize);
5342}
5343
Gabor Martonae512b82019-07-17 14:40:09 +00005344TEST_P(ASTImporterOptionSpecificTestBase, LambdaInGlobalScope) {
5345 Decl *FromTU = getTuDecl(
5346 R"(
5347 auto l1 = [](unsigned lp) { return 1; };
5348 auto l2 = [](int lp) { return 2; };
5349 int f(int p) {
5350 return l1(p) + l2(p);
5351 }
5352 )",
5353 Lang_CXX11, "input0.cc");
5354 FunctionDecl *FromF = FirstDeclMatcher<FunctionDecl>().match(
5355 FromTU, functionDecl(hasName("f")));
5356 FunctionDecl *ToF = Import(FromF, Lang_CXX11);
5357 EXPECT_TRUE(ToF);
5358}
5359
Balazs Keri2e160602019-08-12 10:07:38 +00005360TEST_P(ASTImporterOptionSpecificTestBase,
5361 ImportExistingFriendClassTemplateDef) {
5362 auto Code =
5363 R"(
5364 template <class T1, class T2>
5365 struct Base {
5366 template <class U1, class U2>
5367 friend struct Class;
5368 };
5369 template <class T1, class T2>
5370 struct Class { };
5371 )";
5372
5373 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
5374 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
5375
5376 auto *ToClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
5377 ToTU, classTemplateDecl(hasName("Class")));
5378 auto *ToClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
5379 ToTU, classTemplateDecl(hasName("Class")));
5380 ASSERT_FALSE(ToClassProto->isThisDeclarationADefinition());
5381 ASSERT_TRUE(ToClassDef->isThisDeclarationADefinition());
5382 // Previous friend decl is not linked to it!
5383 ASSERT_FALSE(ToClassDef->getPreviousDecl());
5384 ASSERT_EQ(ToClassDef->getMostRecentDecl(), ToClassDef);
5385 ASSERT_EQ(ToClassProto->getMostRecentDecl(), ToClassProto);
5386
5387 auto *FromClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
5388 FromTU, classTemplateDecl(hasName("Class")));
5389 auto *FromClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
5390 FromTU, classTemplateDecl(hasName("Class")));
5391 ASSERT_FALSE(FromClassProto->isThisDeclarationADefinition());
5392 ASSERT_TRUE(FromClassDef->isThisDeclarationADefinition());
5393 ASSERT_FALSE(FromClassDef->getPreviousDecl());
5394 ASSERT_EQ(FromClassDef->getMostRecentDecl(), FromClassDef);
5395 ASSERT_EQ(FromClassProto->getMostRecentDecl(), FromClassProto);
5396
5397 auto *ImportedDef = Import(FromClassDef, Lang_CXX);
5398 // At import we should find the definition for 'Class' even if the
5399 // prototype (inside 'friend') for it comes first in the AST and is not
5400 // linked to the definition.
5401 EXPECT_EQ(ImportedDef, ToClassDef);
Gabor Martonf035b752019-08-27 11:36:10 +00005402}
5403
Gabor Martonaefcf512019-07-17 13:47:46 +00005404struct LLDBLookupTest : ASTImporterOptionSpecificTestBase {
5405 LLDBLookupTest() {
5406 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
5407 ASTContext &FromContext, FileManager &FromFileManager,
5408 bool MinimalImport,
5409 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
5410 return new ASTImporter(ToContext, ToFileManager, FromContext,
5411 FromFileManager, MinimalImport,
5412 // We use the regular lookup.
5413 /*SharedState=*/nullptr);
5414 };
5415 }
5416};
5417
5418TEST_P(LLDBLookupTest, ImporterShouldFindInTransparentContext) {
5419 TranslationUnitDecl *ToTU = getToTuDecl(
5420 R"(
5421 extern "C" {
5422 class X{};
5423 };
5424 )",
5425 Lang_CXX);
5426 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(
5427 ToTU, cxxRecordDecl(hasName("X")));
5428
5429 // Set up a stub external storage.
5430 ToTU->setHasExternalLexicalStorage(true);
5431 // Set up DeclContextBits.HasLazyExternalLexicalLookups to true.
5432 ToTU->setMustBuildLookupTable();
5433 struct TestExternalASTSource : ExternalASTSource {};
5434 ToTU->getASTContext().setExternalSource(new TestExternalASTSource());
5435
5436 Decl *FromTU = getTuDecl(
5437 R"(
5438 class X;
5439 )",
5440 Lang_CXX);
5441 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5442 FromTU, cxxRecordDecl(hasName("X")));
5443 auto *ImportedX = Import(FromX, Lang_CXX);
5444 // The lookup must find the existing class definition in the LinkageSpecDecl.
5445 // Then the importer renders the existing and the new decl into one chain.
5446 EXPECT_EQ(ImportedX->getCanonicalDecl(), ToX->getCanonicalDecl());
5447}
5448
Richard Sandifordeb485fb2019-08-09 08:52:54 +00005449struct SVEBuiltins : ASTImporterOptionSpecificTestBase {};
5450
5451TEST_P(SVEBuiltins, ImportTypes) {
5452 static const char *const TypeNames[] = {
5453 "__SVInt8_t",
5454 "__SVInt16_t",
5455 "__SVInt32_t",
5456 "__SVInt64_t",
5457 "__SVUint8_t",
5458 "__SVUint16_t",
5459 "__SVUint32_t",
5460 "__SVUint64_t",
5461 "__SVFloat16_t",
5462 "__SVFloat32_t",
5463 "__SVFloat64_t",
5464 "__SVBool_t"
5465 };
5466
5467 TranslationUnitDecl *ToTU = getToTuDecl("", Lang_CXX);
5468 TranslationUnitDecl *FromTU = getTuDecl("", Lang_CXX, "input.cc");
5469 for (auto *TypeName : TypeNames) {
5470 auto *ToTypedef = FirstDeclMatcher<TypedefDecl>().match(
5471 ToTU, typedefDecl(hasName(TypeName)));
5472 QualType ToType = ToTypedef->getUnderlyingType();
5473
5474 auto *FromTypedef = FirstDeclMatcher<TypedefDecl>().match(
5475 FromTU, typedefDecl(hasName(TypeName)));
5476 QualType FromType = FromTypedef->getUnderlyingType();
5477
5478 QualType ImportedType = ImportType(FromType, FromTypedef, Lang_CXX);
5479 EXPECT_EQ(ImportedType, ToType);
5480 }
5481}
5482
Balazs Kerib427c062019-08-13 08:04:06 +00005483TEST_P(ASTImporterOptionSpecificTestBase, ImportOfDefaultImplicitFunctions) {
5484 // Test that import of implicit functions works and the functions
5485 // are merged into one chain.
5486 auto GetDeclToImport = [this](StringRef File) {
5487 Decl *FromTU = getTuDecl(
5488 R"(
5489 struct X { };
5490 // Force generating some implicit operator definitions for X.
5491 void f() { X x1, x2; x1 = x2; X *x3 = new X; delete x3; }
5492 )",
5493 Lang_CXX11, File);
5494 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
5495 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
5496 // Destructor is picked as one example of implicit function.
5497 return FromD->getDestructor();
5498 };
5499
5500 auto *ToD1 = Import(GetDeclToImport("input1.cc"), Lang_CXX11);
5501 ASSERT_TRUE(ToD1);
5502
5503 auto *ToD2 = Import(GetDeclToImport("input2.cc"), Lang_CXX11);
5504 ASSERT_TRUE(ToD2);
5505
5506 EXPECT_EQ(ToD1->getCanonicalDecl(), ToD2->getCanonicalDecl());
5507}
5508
5509TEST_P(ASTImporterOptionSpecificTestBase,
5510 ImportOfExplicitlyDefaultedOrDeleted) {
5511 Decl *FromTU = getTuDecl(
5512 R"(
5513 struct X { X() = default; X(const X&) = delete; };
5514 )",
5515 Lang_CXX11);
5516 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
5517 FromTU, cxxRecordDecl(hasName("X")));
5518 auto *ImportedX = Import(FromX, Lang_CXX11);
5519 auto *Constr1 = FirstDeclMatcher<CXXConstructorDecl>().match(
5520 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));
5521 auto *Constr2 = LastDeclMatcher<CXXConstructorDecl>().match(
5522 ImportedX, cxxConstructorDecl(hasName("X"), unless(isImplicit())));
5523
5524 ASSERT_TRUE(ImportedX);
5525 EXPECT_TRUE(Constr1->isDefaulted());
5526 EXPECT_TRUE(Constr1->isExplicitlyDefaulted());
5527 EXPECT_TRUE(Constr2->isDeletedAsWritten());
5528 EXPECT_EQ(ImportedX->isAggregate(), FromX->isAggregate());
5529}
5530
Richard Sandifordeb485fb2019-08-09 08:52:54 +00005531INSTANTIATE_TEST_CASE_P(ParameterizedTests, SVEBuiltins,
5532 ::testing::Values(ArgVector{"-target",
5533 "aarch64-linux-gnu"}), );
5534
Gabor Martonf035b752019-08-27 11:36:10 +00005535INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
5536 ::testing::Values(ArgVector()), );
5537
5538INSTANTIATE_TEST_CASE_P(ParameterizedTests, CanonicalRedeclChain,
5539 ::testing::Values(ArgVector()), );
5540
Gabor Martone3e83d72019-08-30 10:55:41 +00005541TEST_P(ASTImporterOptionSpecificTestBase, LambdasAreDifferentiated) {
5542 Decl *FromTU = getTuDecl(
5543 R"(
5544 void f() {
5545 auto L0 = [](){};
5546 auto L1 = [](){};
5547 }
5548 )",
5549 Lang_CXX11, "input0.cc");
5550 auto Pattern = lambdaExpr();
5551 CXXRecordDecl *FromL0 =
5552 FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5553 CXXRecordDecl *FromL1 =
5554 LastDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5555 ASSERT_NE(FromL0, FromL1);
5556
5557 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
5558 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
5559 EXPECT_NE(ToL0, ToL1);
5560}
5561
5562TEST_P(ASTImporterOptionSpecificTestBase,
5563 LambdasInFunctionParamsAreDifferentiated) {
5564 Decl *FromTU = getTuDecl(
5565 R"(
5566 template <typename F0, typename F1>
5567 void f(F0 L0 = [](){}, F1 L1 = [](){}) {}
5568 )",
5569 Lang_CXX11, "input0.cc");
5570 auto Pattern = cxxRecordDecl(isLambda());
5571 CXXRecordDecl *FromL0 =
5572 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5573 CXXRecordDecl *FromL1 =
5574 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5575 ASSERT_NE(FromL0, FromL1);
5576
5577 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
5578 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
5579 ASSERT_NE(ToL0, ToL1);
5580}
5581
5582TEST_P(ASTImporterOptionSpecificTestBase,
5583 LambdasInFunctionParamsAreDifferentiatedWhenMacroIsUsed) {
5584 Decl *FromTU = getTuDecl(
5585 R"(
5586 #define LAMBDA [](){}
5587 template <typename F0, typename F1>
5588 void f(F0 L0 = LAMBDA, F1 L1 = LAMBDA) {}
5589 )",
5590 Lang_CXX11, "input0.cc");
5591 auto Pattern = cxxRecordDecl(isLambda());
5592 CXXRecordDecl *FromL0 =
5593 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5594 CXXRecordDecl *FromL1 =
5595 LastDeclMatcher<CXXRecordDecl>().match(FromTU, Pattern);
5596 ASSERT_NE(FromL0, FromL1);
5597
5598 Import(FromL0, Lang_CXX11);
5599 Import(FromL1, Lang_CXX11);
5600 CXXRecordDecl *ToL0 = Import(FromL0, Lang_CXX11);
5601 CXXRecordDecl *ToL1 = Import(FromL1, Lang_CXX11);
5602 ASSERT_NE(ToL0, ToL1);
5603}
5604
5605TEST_P(ASTImporterOptionSpecificTestBase, ImportAssignedLambda) {
5606 Decl *FromTU = getTuDecl(
5607 R"(
5608 void f() {
5609 auto x = []{} = {}; auto x2 = x;
5610 }
5611 )",
5612 Lang_CXX2a, "input0.cc");
5613 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
5614 FromTU, functionDecl(hasName("f")));
5615 // We have only one lambda class.
5616 ASSERT_EQ(
5617 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
5618 1u);
5619
5620 FunctionDecl *ToF = Import(FromF, Lang_CXX2a);
5621 EXPECT_TRUE(ToF);
5622 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5623 // We have only one lambda class after the import.
5624 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
5625 1u);
5626}
5627
5628TEST_P(ASTImporterOptionSpecificTestBase, ImportDefaultConstructibleLambdas) {
5629 Decl *FromTU = getTuDecl(
5630 R"(
5631 void f() {
5632 auto x = []{} = {};
5633 auto xb = []{} = {};
5634 }
5635 )",
5636 Lang_CXX2a, "input0.cc");
5637 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
5638 FromTU, functionDecl(hasName("f")));
5639 // We have two lambda classes.
5640 ASSERT_EQ(
5641 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
5642 2u);
5643
5644 FunctionDecl *ToF = Import(FromF, Lang_CXX2a);
5645 EXPECT_TRUE(ToF);
5646 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5647 // We have two lambda classes after the import.
5648 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
5649 2u);
5650}
5651
Raphael Isemann164e0fc2019-12-06 18:10:23 +01005652TEST_P(ASTImporterOptionSpecificTestBase, ImplicitlyDeclareSelf) {
5653 Decl *FromTU = getTuDecl(R"(
5654 __attribute__((objc_root_class))
5655 @interface Root
5656 @end
5657 @interface C : Root
5658 -(void)method;
5659 @end
5660 @implementation C
5661 -(void)method {}
5662 @end
5663 )",
5664 Lang_OBJCXX, "input.mm");
5665 auto *FromMethod = LastDeclMatcher<ObjCMethodDecl>().match(
5666 FromTU, namedDecl(hasName("method")));
5667 ASSERT_TRUE(FromMethod);
5668 auto ToMethod = Import(FromMethod, Lang_OBJCXX);
5669 ASSERT_TRUE(ToMethod);
5670
5671 // Both methods should have their implicit parameters.
5672 EXPECT_TRUE(FromMethod->getSelfDecl() != nullptr);
5673 EXPECT_TRUE(ToMethod->getSelfDecl() != nullptr);
5674}
5675
Gabor Marton25234fd2019-12-12 17:13:35 +01005676struct ImportAutoFunctions : ASTImporterOptionSpecificTestBase {};
5677
5678TEST_P(ImportAutoFunctions, ReturnWithTypedefDeclaredInside) {
5679 Decl *FromTU = getTuDecl(
5680 R"(
5681 auto X = [](long l) {
5682 using int_type = long;
5683 auto dur = 13;
5684 return static_cast<int_type>(dur);
5685 };
5686 )",
5687 Lang_CXX14, "input0.cc");
5688 CXXMethodDecl *From =
5689 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, cxxMethodDecl());
5690
5691 // Explicitly set the return type of the lambda's operator() to the TypeAlias.
5692 // Normally the return type would be the built-in 'long' type. However, there
5693 // are cases when Clang does not use the canonical type and the TypeAlias is
5694 // used. I could not create such an AST from regular source code, it requires
5695 // some special state in the preprocessor. I've found such an AST when Clang
5696 // parsed libcxx/src/filesystem/directory_iterator.cpp, but could not reduce
5697 // that with creduce, because after preprocessing, the AST no longer
5698 // contained the TypeAlias as a return type of the lambda.
5699 ASTContext &Ctx = From->getASTContext();
5700 TypeAliasDecl *FromTA =
5701 FirstDeclMatcher<TypeAliasDecl>().match(FromTU, typeAliasDecl());
5702 QualType TT = Ctx.getTypedefType(FromTA);
5703 const FunctionProtoType *FPT = cast<FunctionProtoType>(From->getType());
5704 QualType NewFunType =
5705 Ctx.getFunctionType(TT, FPT->getParamTypes(), FPT->getExtProtoInfo());
5706 From->setType(NewFunType);
5707
5708 CXXMethodDecl *To = Import(From, Lang_CXX14);
5709 EXPECT_TRUE(To);
5710 EXPECT_TRUE(isa<TypedefType>(To->getReturnType()));
5711}
5712
5713TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside) {
5714 Decl *FromTU = getTuDecl(
5715 R"(
5716 auto foo() {
5717 struct X {};
5718 return X();
5719 }
5720 )",
5721 Lang_CXX14, "input0.cc");
5722 FunctionDecl *From =
5723 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5724
5725 FunctionDecl *To = Import(From, Lang_CXX14);
5726 EXPECT_TRUE(To);
5727 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5728}
5729
5730TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside2) {
5731 Decl *FromTU = getTuDecl(
5732 R"(
5733 auto foo() {
5734 struct X {};
5735 return X();
5736 }
5737 )",
5738 Lang_CXX14, "input0.cc");
5739 FunctionDecl *From =
5740 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5741
5742 // This time import the type directly.
5743 QualType ToT = ImportType(From->getType(), From, Lang_CXX14);
5744 const FunctionProtoType *FPT = cast<FunctionProtoType>(ToT);
5745 EXPECT_TRUE(isa<AutoType>(FPT->getReturnType()));
5746}
5747
5748TEST_P(ImportAutoFunctions, ReturnWithTypedefToStructDeclaredInside) {
5749 Decl *FromTU = getTuDecl(
5750 R"(
5751 auto foo() {
5752 struct X {};
5753 using Y = X;
5754 return Y();
5755 }
5756 )",
5757 Lang_CXX14, "input0.cc");
5758 FunctionDecl *From =
5759 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5760
5761 FunctionDecl *To = Import(From, Lang_CXX14);
5762 EXPECT_TRUE(To);
5763 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5764}
5765
5766TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredNestedInside) {
5767 Decl *FromTU = getTuDecl(
5768 R"(
5769 auto foo() {
5770 struct X { struct Y{}; };
5771 return X::Y();
5772 }
5773 )",
5774 Lang_CXX14, "input0.cc");
5775 FunctionDecl *From =
5776 FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
5777
5778 FunctionDecl *To = Import(From, Lang_CXX14);
5779 EXPECT_TRUE(To);
5780 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5781}
5782
5783TEST_P(ImportAutoFunctions, ReturnWithInternalLambdaType) {
5784 Decl *FromTU = getTuDecl(
5785 R"(
5786 auto f() {
5787 auto l = []() {
5788 struct X {};
5789 return X();
5790 };
5791 return l();
5792 }
5793 )",
5794 Lang_CXX17, "input0.cc");
5795 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5796 FromTU, functionDecl(hasName("f")));
5797
5798 FunctionDecl *To = Import(From, Lang_CXX17);
5799 EXPECT_TRUE(To);
5800 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5801}
5802
5803TEST_P(ImportAutoFunctions, ReturnWithTypeInIf) {
5804 Decl *FromTU = getTuDecl(
5805 R"(
5806 auto f() {
5807 if (struct X {} x; true)
5808 return X();
5809 else
5810 return X();
5811 }
5812 )",
5813 Lang_CXX17, "input0.cc");
5814 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5815 FromTU, functionDecl(hasName("f")));
5816
5817 FunctionDecl *To = Import(From, Lang_CXX17);
5818 EXPECT_TRUE(To);
5819 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5820}
5821
5822TEST_P(ImportAutoFunctions, ReturnWithTypeInFor) {
5823 Decl *FromTU = getTuDecl(
5824 R"(
5825 auto f() {
5826 for (struct X {} x;;)
5827 return X();
5828 }
5829 )",
5830 Lang_CXX17, "input0.cc");
5831 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5832 FromTU, functionDecl(hasName("f")));
5833
5834 FunctionDecl *To = Import(From, Lang_CXX17);
5835 EXPECT_TRUE(To);
5836 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5837}
5838
5839TEST_P(ImportAutoFunctions, ReturnWithTypeInSwitch) {
5840 Decl *FromTU = getTuDecl(
5841 R"(
5842 auto f() {
5843 switch (struct X {} x; 10) {
5844 case 10:
5845 return X();
5846 }
5847 }
5848 )",
5849 Lang_CXX17, "input0.cc");
5850 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
5851 FromTU, functionDecl(hasName("f")));
5852
5853 FunctionDecl *To = Import(From, Lang_CXX17);
5854 EXPECT_TRUE(To);
5855 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
5856}
5857
Raphael Isemanna37734f2020-02-17 19:43:33 +01005858struct ImportSourceLocations : ASTImporterOptionSpecificTestBase {};
5859
5860TEST_P(ImportSourceLocations, PreserveFileIDTreeStructure) {
5861 // Tests that the FileID tree structure (with the links being the include
5862 // chains) is preserved while importing other files (which need to be
5863 // added to this structure with fake include locations.
5864
5865 SourceLocation Location1;
5866 {
5867 auto Pattern = varDecl(hasName("X"));
5868 Decl *FromTU = getTuDecl("int X;", Lang_C, "input0.c");
5869 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
5870
5871 Location1 = Import(FromD, Lang_C)->getLocation();
5872 }
5873 SourceLocation Location2;
5874 {
5875 auto Pattern = varDecl(hasName("Y"));
5876 Decl *FromTU = getTuDecl("int Y;", Lang_C, "input1.c");
5877 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
5878
5879 Location2 = Import(FromD, Lang_C)->getLocation();
5880 }
5881
5882 SourceManager &ToSM = ToAST->getSourceManager();
5883 FileID FileID1 = ToSM.getFileID(Location1);
5884 FileID FileID2 = ToSM.getFileID(Location2);
5885
5886 // Check that the imported files look like as if they were included from the
5887 // start of the main file.
5888 SourceLocation FileStart = ToSM.getLocForStartOfFile(ToSM.getMainFileID());
5889 EXPECT_NE(FileID1, ToSM.getMainFileID());
5890 EXPECT_NE(FileID2, ToSM.getMainFileID());
5891 EXPECT_EQ(ToSM.getIncludeLoc(FileID1), FileStart);
5892 EXPECT_EQ(ToSM.getIncludeLoc(FileID2), FileStart);
5893
5894 // Let the SourceManager check the order of the locations. The order should
5895 // be the order in which the declarations are imported.
5896 EXPECT_TRUE(ToSM.isBeforeInTranslationUnit(Location1, Location2));
5897 EXPECT_FALSE(ToSM.isBeforeInTranslationUnit(Location2, Location1));
5898}
5899
Raphael Isemann9f1e81f2020-04-27 10:06:56 +02005900TEST_P(ImportSourceLocations, NormalFileBuffer) {
5901 // Test importing normal file buffers.
5902
5903 std::string Path = "input0.c";
5904 std::string Source = "int X;";
5905 TranslationUnitDecl *FromTU = getTuDecl(Source, Lang_C, Path);
5906
5907 SourceLocation ImportedLoc;
5908 {
5909 // Import the VarDecl to trigger the importing of the FileID.
5910 auto Pattern = varDecl(hasName("X"));
5911 VarDecl *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
5912 ImportedLoc = Import(FromD, Lang_C)->getLocation();
5913 }
5914
5915 // Make sure the imported buffer has the original contents.
5916 SourceManager &ToSM = ToAST->getSourceManager();
5917 FileID ImportedID = ToSM.getFileID(ImportedLoc);
5918 EXPECT_EQ(Source, ToSM.getBuffer(ImportedID, SourceLocation())->getBuffer());
5919}
5920
5921TEST_P(ImportSourceLocations, OverwrittenFileBuffer) {
5922 // Test importing overwritten file buffers.
5923
5924 std::string Path = "input0.c";
5925 TranslationUnitDecl *FromTU = getTuDecl("int X;", Lang_C, Path);
5926
5927 // Overwrite the file buffer for our input file with new content.
5928 const std::string Contents = "overwritten contents";
5929 SourceLocation ImportedLoc;
5930 {
5931 SourceManager &FromSM = FromTU->getASTContext().getSourceManager();
5932 clang::FileManager &FM = FromSM.getFileManager();
5933 const clang::FileEntry &FE =
5934 *FM.getVirtualFile(Path, static_cast<off_t>(Contents.size()), 0);
5935
5936 llvm::SmallVector<char, 64> Buffer;
5937 Buffer.append(Contents.begin(), Contents.end());
5938 auto FileContents =
5939 std::make_unique<llvm::SmallVectorMemoryBuffer>(std::move(Buffer), Path);
5940 FromSM.overrideFileContents(&FE, std::move(FileContents));
5941
5942 // Import the VarDecl to trigger the importing of the FileID.
5943 auto Pattern = varDecl(hasName("X"));
5944 VarDecl *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
5945 ImportedLoc = Import(FromD, Lang_C)->getLocation();
5946 }
5947
5948 // Make sure the imported buffer has the overwritten contents.
5949 SourceManager &ToSM = ToAST->getSourceManager();
5950 FileID ImportedID = ToSM.getFileID(ImportedLoc);
5951 EXPECT_EQ(Contents,
5952 ToSM.getBuffer(ImportedID, SourceLocation())->getBuffer());
5953}
5954
Balázs Kérib17f2922020-02-28 08:32:32 +01005955TEST_P(ASTImporterOptionSpecificTestBase, ImportExprOfAlignmentAttr) {
5956 // Test if import of these packed and aligned attributes does not trigger an
5957 // error situation where source location from 'From' context is referenced in
5958 // 'To' context through evaluation of the alignof attribute.
5959 // This happens if the 'alignof(A)' expression is not imported correctly.
5960 Decl *FromTU = getTuDecl(
5961 R"(
5962 struct __attribute__((packed)) A { int __attribute__((aligned(8))) X; };
5963 struct alignas(alignof(A)) S {};
5964 )",
5965 Lang_CXX11, "input.cc");
5966 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
5967 FromTU, cxxRecordDecl(hasName("S"), unless(isImplicit())));
5968 ASSERT_TRUE(FromD);
5969
5970 auto *ToD = Import(FromD, Lang_CXX11);
5971 ASSERT_TRUE(ToD);
5972
5973 auto *FromAttr = FromD->getAttr<AlignedAttr>();
5974 auto *ToAttr = ToD->getAttr<AlignedAttr>();
5975 EXPECT_EQ(FromAttr->isInherited(), ToAttr->isInherited());
5976 EXPECT_EQ(FromAttr->isPackExpansion(), ToAttr->isPackExpansion());
5977 EXPECT_EQ(FromAttr->isImplicit(), ToAttr->isImplicit());
5978 EXPECT_EQ(FromAttr->getSyntax(), ToAttr->getSyntax());
5979 EXPECT_EQ(FromAttr->getSemanticSpelling(), ToAttr->getSemanticSpelling());
5980 EXPECT_TRUE(ToAttr->getAlignmentExpr());
5981
5982 auto *ToA = FirstDeclMatcher<CXXRecordDecl>().match(
5983 ToD->getTranslationUnitDecl(),
5984 cxxRecordDecl(hasName("A"), unless(isImplicit())));
5985 // Ensure that 'struct A' was imported (through reference from attribute of
5986 // 'S').
5987 EXPECT_TRUE(ToA);
5988}
5989
Vince Bridgers789215d2020-04-06 08:22:35 -05005990template <typename T>
5991auto ExtendWithOptions(const T &Values, const ArgVector &Args) {
5992 auto Copy = Values;
5993 for (ArgVector &ArgV : Copy) {
5994 for (const std::string &Arg : Args) {
5995 ArgV.push_back(Arg);
5996 }
5997 }
5998 return ::testing::ValuesIn(Copy);
5999}
6000
shafikdef7c7f2020-04-23 15:16:34 -07006001struct ImportWithExternalSource : ASTImporterOptionSpecificTestBase {
6002 ImportWithExternalSource() {
6003 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
6004 ASTContext &FromContext, FileManager &FromFileManager,
6005 bool MinimalImport,
6006 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
6007 return new ASTImporter(ToContext, ToFileManager, FromContext,
6008 FromFileManager, MinimalImport,
6009 // We use the regular lookup.
6010 /*SharedState=*/nullptr);
6011 };
6012 }
6013};
6014
6015/// An ExternalASTSource that keeps track of the tags is completed.
6016struct SourceWithCompletedTagList : clang::ExternalASTSource {
6017 std::vector<clang::TagDecl *> &CompletedTags;
6018 SourceWithCompletedTagList(std::vector<clang::TagDecl *> &CompletedTags)
6019 : CompletedTags(CompletedTags) {}
6020 void CompleteType(TagDecl *Tag) override {
6021 auto *Record = cast<CXXRecordDecl>(Tag);
6022 Record->startDefinition();
6023 Record->completeDefinition();
6024 CompletedTags.push_back(Tag);
6025 }
shafikdef7c7f2020-04-23 15:16:34 -07006026};
6027
6028TEST_P(ImportWithExternalSource, CompleteRecordBeforeImporting) {
6029 // Create an empty TU.
6030 TranslationUnitDecl *FromTU = getTuDecl("", Lang_CXX, "input.cpp");
6031
6032 // Create and add the test ExternalASTSource.
6033 std::vector<clang::TagDecl *> CompletedTags;
6034 IntrusiveRefCntPtr<ExternalASTSource> source =
6035 new SourceWithCompletedTagList(CompletedTags);
6036 clang::ASTContext &Context = FromTU->getASTContext();
6037 Context.setExternalSource(std::move(source));
6038
6039 // Create a dummy class by hand with external lexical storage.
6040 IdentifierInfo &Ident = Context.Idents.get("test_class");
6041 auto *Record = CXXRecordDecl::Create(
6042 Context, TTK_Class, FromTU, SourceLocation(), SourceLocation(), &Ident);
6043 Record->setHasExternalLexicalStorage();
6044 FromTU->addDecl(Record);
6045
6046 // Do a minimal import of the created class.
6047 EXPECT_EQ(0U, CompletedTags.size());
6048 Import(Record, Lang_CXX);
6049 EXPECT_EQ(0U, CompletedTags.size());
6050
6051 // Import the definition of the created class.
6052 llvm::Error Err = findFromTU(Record)->Importer->ImportDefinition(Record);
6053 EXPECT_FALSE((bool)Err);
6054 consumeError(std::move(Err));
6055
6056 // Make sure the class was completed once.
6057 EXPECT_EQ(1U, CompletedTags.size());
6058 EXPECT_EQ(Record, CompletedTags.front());
6059}
6060
Gabor Marton54058b52018-12-17 13:53:12 +00006061INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
6062 DefaultTestValuesForRunOptions, );
6063
Gabor Marton1ad4b992019-07-01 14:19:53 +00006064INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportPath,
6065 ::testing::Values(ArgVector()), );
6066
Gabor Marton19f4f392018-06-25 13:04:37 +00006067INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
6068 DefaultTestValuesForRunOptions, );
6069
Vince Bridgers789215d2020-04-06 08:22:35 -05006070INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFixedPointExpr,
6071 ExtendWithOptions(DefaultTestArrayForRunOptions,
6072 ArgVector{"-ffixed-point"}), );
6073
Gabor Marton19f4f392018-06-25 13:04:37 +00006074INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
6075 DefaultTestValuesForRunOptions, );
6076
6077INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
6078 DefaultTestValuesForRunOptions, );
6079
Gabor Marton0b57ccb2019-02-07 16:52:48 +00006080INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
Gabor Marton19f4f392018-06-25 13:04:37 +00006081 DefaultTestValuesForRunOptions, );
6082
Gabor Martonf035b752019-08-27 11:36:10 +00006083INSTANTIATE_TEST_CASE_P(ParameterizedTests, ErrorHandlingTest,
6084 DefaultTestValuesForRunOptions, );
6085
Raphael Isemanne9bc35f2019-04-29 21:02:35 +00006086INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedirectingImporterTest,
6087 DefaultTestValuesForRunOptions, );
6088
Gabor Marton19f4f392018-06-25 13:04:37 +00006089INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
6090 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00006091
Gabor Marton25234fd2019-12-12 17:13:35 +01006092INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportAutoFunctions,
6093 DefaultTestValuesForRunOptions, );
6094
Gabor Martonf035b752019-08-27 11:36:10 +00006095INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionTemplates,
6096 DefaultTestValuesForRunOptions, );
6097
Gabor Martone331e632019-02-18 13:09:27 +00006098INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
6099 DefaultTestValuesForRunOptions, );
6100
Gabor Marton54058b52018-12-17 13:53:12 +00006101INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00006102 DefaultTestValuesForRunOptions, );
6103
Gabor Marton54058b52018-12-17 13:53:12 +00006104INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00006105 DefaultTestValuesForRunOptions, );
6106
Gabor Marton7df342a2018-12-17 12:42:12 +00006107INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
6108 DefaultTestValuesForRunOptions, );
6109
Gabor Marton5254e642018-06-27 13:32:50 +00006110INSTANTIATE_TEST_CASE_P(ParameterizedTests,
6111 ImportFunctionTemplateSpecializations,
6112 DefaultTestValuesForRunOptions, );
6113
Gabor Martonac3a5d62018-09-17 12:04:52 +00006114INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
6115 DefaultTestValuesForRunOptions, );
6116
6117INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
6118 DefaultTestValuesForRunOptions, );
6119
Gabor Martonaefcf512019-07-17 13:47:46 +00006120INSTANTIATE_TEST_CASE_P(ParameterizedTests, LLDBLookupTest,
6121 DefaultTestValuesForRunOptions, );
6122
Raphael Isemanna37734f2020-02-17 19:43:33 +01006123INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportSourceLocations,
6124 DefaultTestValuesForRunOptions, );
6125
shafikdef7c7f2020-04-23 15:16:34 -07006126INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportWithExternalSource,
6127 DefaultTestValuesForRunOptions, );
6128
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00006129} // end namespace ast_matchers
6130} // end namespace clang