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