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