blob: 72ff3be03cd02871390d00d5afc0af8dab292e5e [file] [log] [blame]
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00001//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00006//
7//===----------------------------------------------------------------------===//
8//
9// Tests for the correct import of AST nodes from one AST context to another.
10//
11//===----------------------------------------------------------------------===//
12
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000013#include "llvm/ADT/StringMap.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000014
Gabor Marton3c72fe12019-05-13 10:06:25 +000015#include "clang/AST/DeclContextInternals.h"
16
17#include "ASTImporterFixtures.h"
18#include "MatchVerifier.h"
19
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000020namespace clang {
21namespace ast_matchers {
22
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000023using internal::Matcher;
24using internal::BindableMatcher;
25using llvm::StringMap;
26
Gabor Marton19f4f392018-06-25 13:04:37 +000027// Base class for those tests which use the family of `testImport` functions.
Gabor Marton0b57ccb2019-02-07 16:52:48 +000028class TestImportBase : public CompilerOptionSpecificTest,
29 public ::testing::WithParamInterface<ArgVector> {
Adam Baloghe4192a82018-06-15 06:45:39 +000030
Gabor Marton19f4f392018-06-25 13:04:37 +000031 template <typename NodeType>
Balazs Keria1f6b102019-04-08 13:59:15 +000032 llvm::Expected<NodeType> importNode(ASTUnit *From, ASTUnit *To,
33 ASTImporter &Importer, NodeType Node) {
Gabor Marton19f4f392018-06-25 13:04:37 +000034 ASTContext &ToCtx = To->getASTContext();
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000035
Gabor Marton19f4f392018-06-25 13:04:37 +000036 // Add 'From' file to virtual file system so importer can 'find' it
37 // while importing SourceLocations. It is safe to add same file multiple
38 // times - it just isn't replaced.
39 StringRef FromFileName = From->getMainFileName();
40 createVirtualFileIfNeeded(To, FromFileName,
41 From->getBufferForFile(FromFileName));
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000042
Gabor Marton5ac6d492019-05-15 10:29:48 +000043 auto Imported = Importer.Import(Node);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000044
Balazs Keria1f6b102019-04-08 13:59:15 +000045 if (Imported) {
46 // This should dump source locations and assert if some source locations
47 // were not imported.
48 SmallString<1024> ImportChecker;
49 llvm::raw_svector_ostream ToNothing(ImportChecker);
50 ToCtx.getTranslationUnitDecl()->print(ToNothing);
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000051
Balazs Keria1f6b102019-04-08 13:59:15 +000052 // This traverses the AST to catch certain bugs like poorly or not
53 // implemented subtrees.
54 (*Imported)->dump(ToNothing);
55 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000056
Gabor Marton19f4f392018-06-25 13:04:37 +000057 return Imported;
58 }
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000059
Gabor Marton19f4f392018-06-25 13:04:37 +000060 template <typename NodeType>
61 testing::AssertionResult
62 testImport(const std::string &FromCode, const ArgVector &FromArgs,
63 const std::string &ToCode, const ArgVector &ToArgs,
64 MatchVerifier<NodeType> &Verifier,
65 const BindableMatcher<NodeType> &SearchMatcher,
66 const BindableMatcher<NodeType> &VerificationMatcher) {
67 const char *const InputFileName = "input.cc";
68 const char *const OutputFileName = "output.cc";
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +000069
Gabor Marton19f4f392018-06-25 13:04:37 +000070 std::unique_ptr<ASTUnit> FromAST = tooling::buildASTFromCodeWithArgs(
71 FromCode, FromArgs, InputFileName),
72 ToAST = tooling::buildASTFromCodeWithArgs(
73 ToCode, ToArgs, OutputFileName);
74
75 ASTContext &FromCtx = FromAST->getASTContext(),
76 &ToCtx = ToAST->getASTContext();
77
78 ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx,
79 FromAST->getFileManager(), false);
80
81 auto FoundNodes = match(SearchMatcher, FromCtx);
82 if (FoundNodes.size() != 1)
83 return testing::AssertionFailure()
84 << "Multiple potential nodes were found!";
85
86 auto ToImport = selectFirst<NodeType>(DeclToImportID, FoundNodes);
87 if (!ToImport)
88 return testing::AssertionFailure() << "Node type mismatch!";
89
90 // Sanity check: the node being imported should match in the same way as
91 // the result node.
92 BindableMatcher<NodeType> WrapperMatcher(VerificationMatcher);
93 EXPECT_TRUE(Verifier.match(ToImport, WrapperMatcher));
94
95 auto Imported = importNode(FromAST.get(), ToAST.get(), Importer, ToImport);
Balazs Keria1f6b102019-04-08 13:59:15 +000096 if (!Imported) {
97 std::string ErrorText;
98 handleAllErrors(
99 Imported.takeError(),
100 [&ErrorText](const ImportError &Err) { ErrorText = Err.message(); });
101 return testing::AssertionFailure()
102 << "Import failed, error: \"" << ErrorText << "\"!";
103 }
Gabor Marton19f4f392018-06-25 13:04:37 +0000104
Balazs Keria1f6b102019-04-08 13:59:15 +0000105 return Verifier.match(*Imported, WrapperMatcher);
Gabor Marton19f4f392018-06-25 13:04:37 +0000106 }
107
108 template <typename NodeType>
109 testing::AssertionResult
110 testImport(const std::string &FromCode, const ArgVector &FromArgs,
111 const std::string &ToCode, const ArgVector &ToArgs,
112 MatchVerifier<NodeType> &Verifier,
113 const BindableMatcher<NodeType> &VerificationMatcher) {
114 return testImport(
115 FromCode, FromArgs, ToCode, ToArgs, Verifier,
116 translationUnitDecl(
117 has(namedDecl(hasName(DeclToImportID)).bind(DeclToImportID))),
118 VerificationMatcher);
119 }
120
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000121protected:
122 ArgVector getExtraArgs() const override { return GetParam(); }
123
Gabor Marton19f4f392018-06-25 13:04:37 +0000124public:
125
126 /// Test how AST node named "declToImport" located in the translation unit
127 /// of "FromCode" virtual file is imported to "ToCode" virtual file.
128 /// The verification is done by running AMatcher over the imported node.
129 template <typename NodeType, typename MatcherType>
130 void testImport(const std::string &FromCode, Language FromLang,
131 const std::string &ToCode, Language ToLang,
132 MatchVerifier<NodeType> &Verifier,
133 const MatcherType &AMatcher) {
134 ArgVector FromArgs = getArgVectorForLanguage(FromLang),
135 ToArgs = getArgVectorForLanguage(ToLang);
136 EXPECT_TRUE(
137 testImport(FromCode, FromArgs, ToCode, ToArgs, Verifier, AMatcher));
138 }
139
140 struct ImportAction {
141 StringRef FromFilename;
142 StringRef ToFilename;
143 // FIXME: Generalize this to support other node kinds.
144 BindableMatcher<Decl> ImportPredicate;
145
146 ImportAction(StringRef FromFilename, StringRef ToFilename,
147 DeclarationMatcher ImportPredicate)
148 : FromFilename(FromFilename), ToFilename(ToFilename),
149 ImportPredicate(ImportPredicate) {}
150
151 ImportAction(StringRef FromFilename, StringRef ToFilename,
152 const std::string &DeclName)
153 : FromFilename(FromFilename), ToFilename(ToFilename),
154 ImportPredicate(namedDecl(hasName(DeclName))) {}
155 };
156
157 using SingleASTUnit = std::unique_ptr<ASTUnit>;
158 using AllASTUnits = StringMap<SingleASTUnit>;
159
160 struct CodeEntry {
161 std::string CodeSample;
162 Language Lang;
163 };
164
165 using CodeFiles = StringMap<CodeEntry>;
166
167 /// Builds an ASTUnit for one potential compile options set.
168 SingleASTUnit createASTUnit(StringRef FileName, const CodeEntry &CE) const {
169 ArgVector Args = getArgVectorForLanguage(CE.Lang);
170 auto AST = tooling::buildASTFromCodeWithArgs(CE.CodeSample, Args, FileName);
171 EXPECT_TRUE(AST.get());
172 return AST;
173 }
174
175 /// Test an arbitrary sequence of imports for a set of given in-memory files.
176 /// The verification is done by running VerificationMatcher against a
177 /// specified AST node inside of one of given files.
178 /// \param CodeSamples Map whose key is the file name and the value is the
179 /// file content.
180 /// \param ImportActions Sequence of imports. Each import in sequence
181 /// specifies "from file" and "to file" and a matcher that is used for
182 /// searching a declaration for import in "from file".
183 /// \param FileForFinalCheck Name of virtual file for which the final check is
184 /// applied.
185 /// \param FinalSelectPredicate Matcher that specifies the AST node in the
186 /// FileForFinalCheck for which the verification will be done.
187 /// \param VerificationMatcher Matcher that will be used for verification
188 /// after all imports in sequence are done.
189 void testImportSequence(const CodeFiles &CodeSamples,
190 const std::vector<ImportAction> &ImportActions,
191 StringRef FileForFinalCheck,
192 BindableMatcher<Decl> FinalSelectPredicate,
193 BindableMatcher<Decl> VerificationMatcher) {
194 AllASTUnits AllASTs;
195 using ImporterKey = std::pair<const ASTUnit *, const ASTUnit *>;
196 llvm::DenseMap<ImporterKey, std::unique_ptr<ASTImporter>> Importers;
197
198 auto GenASTsIfNeeded = [this, &AllASTs, &CodeSamples](StringRef Filename) {
199 if (!AllASTs.count(Filename)) {
200 auto Found = CodeSamples.find(Filename);
201 assert(Found != CodeSamples.end() && "Wrong file for import!");
202 AllASTs[Filename] = createASTUnit(Filename, Found->getValue());
203 }
204 };
205
206 for (const ImportAction &Action : ImportActions) {
207 StringRef FromFile = Action.FromFilename, ToFile = Action.ToFilename;
208 GenASTsIfNeeded(FromFile);
209 GenASTsIfNeeded(ToFile);
210
211 ASTUnit *From = AllASTs[FromFile].get();
212 ASTUnit *To = AllASTs[ToFile].get();
213
214 // Create a new importer if needed.
215 std::unique_ptr<ASTImporter> &ImporterRef = Importers[{From, To}];
216 if (!ImporterRef)
217 ImporterRef.reset(new ASTImporter(
218 To->getASTContext(), To->getFileManager(), From->getASTContext(),
219 From->getFileManager(), false));
220
221 // Find the declaration and import it.
222 auto FoundDecl = match(Action.ImportPredicate.bind(DeclToImportID),
223 From->getASTContext());
224 EXPECT_TRUE(FoundDecl.size() == 1);
225 const Decl *ToImport = selectFirst<Decl>(DeclToImportID, FoundDecl);
226 auto Imported = importNode(From, To, *ImporterRef, ToImport);
Balazs Keria1f6b102019-04-08 13:59:15 +0000227 EXPECT_TRUE(static_cast<bool>(Imported));
228 if (!Imported)
229 llvm::consumeError(Imported.takeError());
Gabor Marton19f4f392018-06-25 13:04:37 +0000230 }
231
232 // Find the declaration and import it.
233 auto FoundDecl = match(FinalSelectPredicate.bind(DeclToVerifyID),
234 AllASTs[FileForFinalCheck]->getASTContext());
235 EXPECT_TRUE(FoundDecl.size() == 1);
236 const Decl *ToVerify = selectFirst<Decl>(DeclToVerifyID, FoundDecl);
237 MatchVerifier<Decl> Verifier;
238 EXPECT_TRUE(
239 Verifier.match(ToVerify, BindableMatcher<Decl>(VerificationMatcher)));
240 }
241};
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000242
Gabor Martonf086fa82018-07-17 12:06:36 +0000243template <typename T> RecordDecl *getRecordDecl(T *D) {
244 auto *ET = cast<ElaboratedType>(D->getType().getTypePtr());
245 return cast<RecordType>(ET->getNamedType().getTypePtr())->getDecl();
Nico Weberb980b5c2018-07-17 14:20:02 +0000246}
Gabor Martonf086fa82018-07-17 12:06:36 +0000247
Gabor Marton19f4f392018-06-25 13:04:37 +0000248struct ImportExpr : TestImportBase {};
249struct ImportType : TestImportBase {};
250struct ImportDecl : TestImportBase {};
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +0000251
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000252struct CanonicalRedeclChain : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +0000253
254TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
255 Decl *FromTU = getTuDecl("void f();", Lang_CXX);
256 auto Pattern = functionDecl(hasName("f"));
257 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
258
259 auto Redecls = getCanonicalForwardRedeclChain(D0);
260 ASSERT_EQ(Redecls.size(), 1u);
261 EXPECT_EQ(D0, Redecls[0]);
262}
263
264TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
265 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
266 auto Pattern = functionDecl(hasName("f"));
267 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
268 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
269 FunctionDecl *D1 = D2->getPreviousDecl();
270
271 auto Redecls = getCanonicalForwardRedeclChain(D0);
272 ASSERT_EQ(Redecls.size(), 3u);
273 EXPECT_EQ(D0, Redecls[0]);
274 EXPECT_EQ(D1, Redecls[1]);
275 EXPECT_EQ(D2, Redecls[2]);
276}
277
278TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
279 Decl *FromTU = getTuDecl("void f(); void f(); void f();", Lang_CXX);
280 auto Pattern = functionDecl(hasName("f"));
281 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
282 auto *D2 = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
283 FunctionDecl *D1 = D2->getPreviousDecl();
284
285 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
286 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
287 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
288
289 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
290 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
291}
292
Raphael Isemanne9bc35f2019-04-29 21:02:35 +0000293namespace {
294struct RedirectingImporter : public ASTImporter {
295 using ASTImporter::ASTImporter;
296
297protected:
298 llvm::Expected<Decl *> ImportImpl(Decl *FromD) override {
299 auto *ND = dyn_cast<NamedDecl>(FromD);
300 if (!ND || ND->getName() != "shouldNotBeImported")
301 return ASTImporter::ImportImpl(FromD);
302 for (Decl *D : getToContext().getTranslationUnitDecl()->decls()) {
303 if (auto *ND = dyn_cast<NamedDecl>(D))
304 if (ND->getName() == "realDecl") {
305 RegisterImportedDecl(FromD, ND);
306 return ND;
307 }
308 }
309 return ASTImporter::ImportImpl(FromD);
310 }
311};
312
313} // namespace
314
315struct RedirectingImporterTest : ASTImporterOptionSpecificTestBase {
316 RedirectingImporterTest() {
317 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
318 ASTContext &FromContext, FileManager &FromFileManager,
319 bool MinimalImport, ASTImporterLookupTable *LookupTable) {
320 return new RedirectingImporter(ToContext, ToFileManager, FromContext,
321 FromFileManager, MinimalImport,
322 LookupTable);
323 };
324 }
325};
326
327// Test that an ASTImporter subclass can intercept an import call.
328TEST_P(RedirectingImporterTest, InterceptImport) {
329 Decl *From, *To;
330 std::tie(From, To) =
331 getImportedDecl("class shouldNotBeImported {};", Lang_CXX,
332 "class realDecl {};", Lang_CXX, "shouldNotBeImported");
333 auto *Imported = cast<CXXRecordDecl>(To);
334 EXPECT_EQ(Imported->getQualifiedNameAsString(), "realDecl");
335
336 // Make sure our importer prevented the importing of the decl.
337 auto *ToTU = Imported->getTranslationUnitDecl();
338 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
339 unsigned count =
340 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
341 EXPECT_EQ(0U, count);
342}
343
344// Test that when we indirectly import a declaration the custom ASTImporter
345// is still intercepting the import.
346TEST_P(RedirectingImporterTest, InterceptIndirectImport) {
347 Decl *From, *To;
348 std::tie(From, To) =
349 getImportedDecl("class shouldNotBeImported {};"
350 "class F { shouldNotBeImported f; };",
351 Lang_CXX, "class realDecl {};", Lang_CXX, "F");
352
353 // Make sure our ASTImporter prevented the importing of the decl.
354 auto *ToTU = To->getTranslationUnitDecl();
355 auto Pattern = functionDecl(hasName("shouldNotBeImported"));
356 unsigned count =
357 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
358 EXPECT_EQ(0U, count);
359}
360
Gabor Marton19f4f392018-06-25 13:04:37 +0000361TEST_P(ImportExpr, ImportStringLiteral) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000362 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000363 testImport(
364 "void declToImport() { (void)\"foo\"; }",
365 Lang_CXX, "", Lang_CXX, Verifier,
366 functionDecl(hasDescendant(
367 stringLiteral(hasType(asString("const char [4]"))))));
368 testImport(
369 "void declToImport() { (void)L\"foo\"; }",
370 Lang_CXX, "", Lang_CXX, Verifier,
371 functionDecl(hasDescendant(
372 stringLiteral(hasType(asString("const wchar_t [4]"))))));
373 testImport(
374 "void declToImport() { (void) \"foo\" \"bar\"; }",
375 Lang_CXX, "", Lang_CXX, Verifier,
376 functionDecl(hasDescendant(
377 stringLiteral(hasType(asString("const char [7]"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000378}
379
Tom Roeder521f0042019-02-26 19:26:41 +0000380TEST_P(ImportExpr, ImportChooseExpr) {
381 MatchVerifier<Decl> Verifier;
382
383 // This case tests C code that is not condition-dependent and has a true
384 // condition.
385 testImport(
386 "void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }",
387 Lang_C, "", Lang_C, Verifier,
388 functionDecl(hasDescendant(chooseExpr())));
389}
390
Gabor Marton19f4f392018-06-25 13:04:37 +0000391TEST_P(ImportExpr, ImportGNUNullExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000392 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000393 testImport(
394 "void declToImport() { (void)__null; }",
395 Lang_CXX, "", Lang_CXX, Verifier,
396 functionDecl(hasDescendant(gnuNullExpr(hasType(isInteger())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000397}
398
Gabor Marton19f4f392018-06-25 13:04:37 +0000399TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000400 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000401 testImport(
402 "void declToImport() { (void)nullptr; }",
403 Lang_CXX11, "", Lang_CXX11, Verifier,
404 functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000405}
406
407
Gabor Marton19f4f392018-06-25 13:04:37 +0000408TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000409 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000410 testImport(
411 "void declToImport() { (void)1.0; }",
412 Lang_C, "", Lang_C, Verifier,
413 functionDecl(hasDescendant(
414 floatLiteral(equals(1.0), hasType(asString("double"))))));
415 testImport(
416 "void declToImport() { (void)1.0e-5f; }",
417 Lang_C, "", Lang_C, Verifier,
418 functionDecl(hasDescendant(
419 floatLiteral(equals(1.0e-5f), hasType(asString("float"))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000420}
421
Gabor Martonbf7f18b2018-08-09 12:18:07 +0000422TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
423 MatchVerifier<Decl> Verifier;
424 testImport(
425 "void declToImport() { (void)1.0i; }",
426 Lang_CXX14, "", Lang_CXX14, Verifier,
427 functionDecl(hasDescendant(imaginaryLiteral())));
428}
429
Gabor Marton19f4f392018-06-25 13:04:37 +0000430TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000431 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000432 testImport(
433 "void declToImport() {"
434 " struct s { int x; long y; unsigned z; }; "
435 " (void)(struct s){ 42, 0L, 1U }; }",
436 Lang_CXX, "", Lang_CXX, Verifier,
437 functionDecl(hasDescendant(
438 compoundLiteralExpr(
439 hasType(asString("struct s")),
440 has(initListExpr(
441 hasType(asString("struct s")),
442 has(integerLiteral(
443 equals(42), hasType(asString("int")))),
444 has(integerLiteral(
445 equals(0), hasType(asString("long")))),
446 has(integerLiteral(
447 equals(1), hasType(asString("unsigned int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000448}
449
Gabor Marton19f4f392018-06-25 13:04:37 +0000450TEST_P(ImportExpr, ImportCXXThisExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000451 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000452 testImport(
453 "class declToImport { void f() { (void)this; } };",
454 Lang_CXX, "", Lang_CXX, Verifier,
455 cxxRecordDecl(
456 hasMethod(
457 hasDescendant(
458 cxxThisExpr(
459 hasType(
460 asString("class declToImport *")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000461}
462
Gabor Marton19f4f392018-06-25 13:04:37 +0000463TEST_P(ImportExpr, ImportAtomicExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000464 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000465 testImport(
466 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
467 Lang_C, "", Lang_C, Verifier,
468 functionDecl(hasDescendant(
469 atomicExpr(
470 has(ignoringParenImpCasts(
471 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
472 hasType(asString("int *"))))),
473 has(integerLiteral(equals(1), hasType(asString("int"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000474}
475
Gabor Marton19f4f392018-06-25 13:04:37 +0000476TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000477 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000478 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000479 "void declToImport() { loop: goto loop; (void)&&loop; }",
480 Lang_C, "", Lang_C, Verifier,
481 functionDecl(
482 hasDescendant(
483 labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
484 hasDescendant(
485 addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000486}
487
488AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
489 internal::Matcher<NamedDecl>, InnerMatcher) {
490 const NamedDecl *Template = Node.getTemplatedDecl();
491 return Template && InnerMatcher.matches(*Template, Finder, Builder);
492}
493
Gabor Marton19f4f392018-06-25 13:04:37 +0000494TEST_P(ImportExpr, ImportParenListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000495 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000496 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000497 "template<typename T> class dummy { void f() { dummy X(*this); } };"
498 "typedef dummy<int> declToImport;"
499 "template class dummy<int>;",
500 Lang_CXX, "", Lang_CXX, Verifier,
501 typedefDecl(hasType(templateSpecializationType(
502 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
503 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
504 hasName("f"),
505 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
506 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
507 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000508 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000509}
510
Gabor Marton19f4f392018-06-25 13:04:37 +0000511TEST_P(ImportExpr, ImportSwitch) {
Gabor Horvath480892b2017-10-18 09:25:18 +0000512 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000513 testImport(
514 "void declToImport() { int b; switch (b) { case 1: break; } }",
515 Lang_C, "", Lang_C, Verifier,
516 functionDecl(hasDescendant(
517 switchStmt(has(compoundStmt(has(caseStmt())))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000518}
519
Gabor Marton19f4f392018-06-25 13:04:37 +0000520TEST_P(ImportExpr, ImportStmtExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000521 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000522 testImport(
523 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
524 Lang_C, "", Lang_C, Verifier,
Gabor Marton1f6ad142018-06-29 10:25:19 +0000525 functionDecl(hasDescendant(
526 varDecl(
527 hasName("C"),
528 hasType(asString("int")),
529 hasInitializer(
530 stmtExpr(
531 hasAnySubstatement(declStmt(hasSingleDecl(
532 varDecl(
533 hasName("X"),
534 hasType(asString("int")),
535 hasInitializer(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000536 integerLiteral(equals(4))))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000537 hasDescendant(
538 implicitCastExpr())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000539}
540
Gabor Marton19f4f392018-06-25 13:04:37 +0000541TEST_P(ImportExpr, ImportConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000542 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000543 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000544 "void declToImport() { (void)(true ? 1 : -5); }",
545 Lang_CXX, "", Lang_CXX, Verifier,
546 functionDecl(hasDescendant(
547 conditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000548 hasCondition(cxxBoolLiteral(equals(true))),
549 hasTrueExpression(integerLiteral(equals(1))),
550 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000551 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))))
552 )));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000553}
554
Gabor Marton19f4f392018-06-25 13:04:37 +0000555TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000556 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000557 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000558 "void declToImport() { (void)(1 ?: -5); }",
559 Lang_CXX, "", Lang_CXX, Verifier,
560 functionDecl(hasDescendant(
561 binaryConditionalOperator(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000562 hasCondition(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000563 implicitCastExpr(
564 hasSourceExpression(opaqueValueExpr(
565 hasSourceExpression(integerLiteral(equals(1))))),
566 hasType(booleanType()))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000567 hasTrueExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000568 opaqueValueExpr(
569 hasSourceExpression(integerLiteral(equals(1))))),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000570 hasFalseExpression(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000571 unaryOperator(
572 hasOperatorName("-"),
573 hasUnaryOperand(integerLiteral(equals(5)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000574}
575
Gabor Marton19f4f392018-06-25 13:04:37 +0000576TEST_P(ImportExpr, ImportDesignatedInitExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000577 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000578 testImport(
579 "void declToImport() {"
580 " struct point { double x; double y; };"
581 " struct point ptarray[10] = "
582 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
583 Lang_C, "", Lang_C, Verifier,
584 functionDecl(hasDescendant(
585 initListExpr(
586 has(designatedInitExpr(
587 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000588 hasDescendant(floatLiteral(equals(1.0))),
589 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000590 has(designatedInitExpr(
591 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000592 hasDescendant(floatLiteral(equals(2.0))),
593 hasDescendant(integerLiteral(equals(2))))),
Gabor Marton1f6ad142018-06-29 10:25:19 +0000594 has(designatedInitExpr(
595 designatorCountIs(2),
Bill Wendling8003edc2018-11-09 00:41:36 +0000596 hasDescendant(floatLiteral(equals(1.0))),
597 hasDescendant(integerLiteral(equals(0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000598}
599
Gabor Marton19f4f392018-06-25 13:04:37 +0000600TEST_P(ImportExpr, ImportPredefinedExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000601 MatchVerifier<Decl> Verifier;
602 // __func__ expands as StringLiteral("declToImport")
Gabor Marton1f6ad142018-06-29 10:25:19 +0000603 testImport(
604 "void declToImport() { (void)__func__; }",
605 Lang_CXX, "", Lang_CXX, Verifier,
606 functionDecl(hasDescendant(
607 predefinedExpr(
608 hasType(
609 asString("const char [13]")),
610 has(stringLiteral(hasType(
611 asString("const char [13]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000612}
613
Gabor Marton19f4f392018-06-25 13:04:37 +0000614TEST_P(ImportExpr, ImportInitListExpr) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000615 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000616 testImport(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000617 "void declToImport() {"
618 " struct point { double x; double y; };"
619 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
620 " [0].x = 1.0 }; }",
621 Lang_CXX, "", Lang_CXX, Verifier,
622 functionDecl(hasDescendant(
623 initListExpr(
624 has(
625 cxxConstructExpr(
626 requiresZeroInitialization())),
627 has(
628 initListExpr(
629 hasType(asString("struct point")),
630 has(floatLiteral(equals(1.0))),
631 has(implicitValueInitExpr(
632 hasType(asString("double")))))),
633 has(
634 initListExpr(
635 hasType(asString("struct point")),
636 has(floatLiteral(equals(2.0))),
637 has(floatLiteral(equals(1.0)))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000638}
639
640
Aleksei Sidorina693b372016-09-28 10:16:56 +0000641const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
642
Gabor Marton19f4f392018-06-25 13:04:37 +0000643TEST_P(ImportExpr, ImportVAArgExpr) {
Aleksei Sidorina693b372016-09-28 10:16:56 +0000644 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000645 testImport(
646 "void declToImport(__builtin_va_list list, ...) {"
647 " (void)__builtin_va_arg(list, int); }",
648 Lang_CXX, "", Lang_CXX, Verifier,
649 functionDecl(hasDescendant(
650 cStyleCastExpr(hasSourceExpression(vaArgExpr())))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000651}
652
Gabor Marton19f4f392018-06-25 13:04:37 +0000653TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000654 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000655 testImport(
656 "struct C {};"
657 "void declToImport() { C c = C(); }",
658 Lang_CXX, "", Lang_CXX, Verifier,
659 functionDecl(hasDescendant(
660 exprWithCleanups(has(cxxConstructExpr(
661 has(materializeTemporaryExpr(has(implicitCastExpr(
662 has(cxxTemporaryObjectExpr())))))))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000663}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000664
Gabor Marton19f4f392018-06-25 13:04:37 +0000665TEST_P(ImportType, ImportAtomicType) {
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000666 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000667 testImport(
668 "void declToImport() { typedef _Atomic(int) a_int; }",
669 Lang_CXX11, "", Lang_CXX11, Verifier,
670 functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000671}
672
Gabor Marton19f4f392018-06-25 13:04:37 +0000673TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000674 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000675 testImport(
676 "template <typename T> void declToImport() { };",
677 Lang_CXX, "", Lang_CXX, Verifier,
678 functionTemplateDecl());
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000679}
680
Gabor Marton19f4f392018-06-25 13:04:37 +0000681TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000682 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000683 testImport(
684 "template <typename T> struct C { T t; };"
685 "template <typename T> void declToImport() {"
686 " C<T> d;"
687 " (void)d.t;"
688 "}"
689 "void instantiate() { declToImport<int>(); }",
690 Lang_CXX, "", Lang_CXX, Verifier,
691 functionTemplateDecl(hasDescendant(
692 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
693 testImport(
694 "template <typename T> struct C { T t; };"
695 "template <typename T> void declToImport() {"
696 " C<T> d;"
697 " (void)(&d)->t;"
698 "}"
699 "void instantiate() { declToImport<int>(); }",
700 Lang_CXX, "", Lang_CXX, Verifier,
701 functionTemplateDecl(hasDescendant(
702 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000703}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000704
Gabor Marton19f4f392018-06-25 13:04:37 +0000705TEST_P(ImportType, ImportTypeAliasTemplate) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000706 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000707 testImport(
708 "template <int K>"
709 "struct dummy { static const int i = K; };"
710 "template <int K> using dummy2 = dummy<K>;"
711 "int declToImport() { return dummy2<3>::i; }",
712 Lang_CXX11, "", Lang_CXX11, Verifier,
713 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000714 hasDescendant(implicitCastExpr(has(declRefExpr()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000715 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
716}
717
718const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
719 varTemplateSpecializationDecl;
720
Gabor Marton19f4f392018-06-25 13:04:37 +0000721TEST_P(ImportDecl, ImportVarTemplate) {
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000722 MatchVerifier<Decl> Verifier;
723 testImport(
724 "template <typename T>"
725 "T pi = T(3.1415926535897932385L);"
Gabor Marton1f6ad142018-06-29 10:25:19 +0000726 "void declToImport() { (void)pi<int>; }",
727 Lang_CXX14, "", Lang_CXX14, Verifier,
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000728 functionDecl(
Gabor Marton1f6ad142018-06-29 10:25:19 +0000729 hasDescendant(declRefExpr(to(varTemplateSpecializationDecl()))),
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000730 unless(hasAncestor(translationUnitDecl(has(varDecl(
731 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000732}
733
Gabor Marton19f4f392018-06-25 13:04:37 +0000734TEST_P(ImportType, ImportPackExpansion) {
Gabor Horvath7a91c082017-11-14 11:30:38 +0000735 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000736 testImport(
737 "template <typename... Args>"
738 "struct dummy {"
739 " dummy(Args... args) {}"
740 " static const int i = 4;"
741 "};"
742 "int declToImport() { return dummy<int>::i; }",
743 Lang_CXX11, "", Lang_CXX11, Verifier,
744 functionDecl(hasDescendant(
745 returnStmt(has(implicitCastExpr(has(declRefExpr())))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000746}
747
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000748const internal::VariadicDynCastAllOfMatcher<Type,
749 DependentTemplateSpecializationType>
750 dependentTemplateSpecializationType;
751
Gabor Marton19f4f392018-06-25 13:04:37 +0000752TEST_P(ImportType, ImportDependentTemplateSpecialization) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000753 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000754 testImport(
755 "template<typename T>"
756 "struct A;"
757 "template<typename T>"
758 "struct declToImport {"
759 " typename A<T>::template B<T> a;"
760 "};",
761 Lang_CXX, "", Lang_CXX, Verifier,
762 classTemplateDecl(has(cxxRecordDecl(has(
763 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000764}
765
766const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
767 sizeOfPackExpr;
768
Gabor Marton19f4f392018-06-25 13:04:37 +0000769TEST_P(ImportExpr, ImportSizeOfPackExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000770 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000771 testImport(
772 "template <typename... Ts>"
773 "void declToImport() {"
774 " const int i = sizeof...(Ts);"
775 "};"
776 "void g() { declToImport<int>(); }",
777 Lang_CXX11, "", Lang_CXX11, Verifier,
778 functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000779 testImport(
780 "template <typename... Ts>"
781 "using X = int[sizeof...(Ts)];"
782 "template <typename... Us>"
783 "struct Y {"
784 " X<Us..., int, double, int, Us...> f;"
785 "};"
786 "Y<float, int> declToImport;",
787 Lang_CXX11, "", Lang_CXX11, Verifier,
788 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
789 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
790}
791
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000792/// \brief Matches __builtin_types_compatible_p:
793/// GNU extension to check equivalent types
794/// Given
795/// \code
796/// __builtin_types_compatible_p(int, int)
797/// \endcode
798// will generate TypeTraitExpr <...> 'int'
799const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
800
Gabor Marton19f4f392018-06-25 13:04:37 +0000801TEST_P(ImportExpr, ImportTypeTraitExpr) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000802 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000803 testImport(
804 "void declToImport() { "
805 " (void)__builtin_types_compatible_p(int, int);"
806 "}",
807 Lang_C, "", Lang_C, Verifier,
808 functionDecl(hasDescendant(typeTraitExpr(hasType(asString("int"))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000809}
810
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000811const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
812
Gabor Marton19f4f392018-06-25 13:04:37 +0000813TEST_P(ImportExpr, ImportCXXTypeidExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000814 MatchVerifier<Decl> Verifier;
815 testImport(
816 "namespace std { class type_info {}; }"
817 "void declToImport() {"
818 " int x;"
819 " auto a = typeid(int); auto b = typeid(x);"
820 "}",
821 Lang_CXX11, "", Lang_CXX11, Verifier,
822 functionDecl(
823 hasDescendant(varDecl(
824 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
825 hasDescendant(varDecl(
826 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
827}
828
Gabor Marton19f4f392018-06-25 13:04:37 +0000829TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000830 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000831 testImport(
832 "template<typename T> struct declToImport {"
833 " void m() { (void)__is_pod(T); }"
834 "};"
835 "void f() { declToImport<int>().m(); }",
836 Lang_CXX11, "", Lang_CXX11, Verifier,
837 classTemplateDecl(has(cxxRecordDecl(has(
838 functionDecl(hasDescendant(
839 typeTraitExpr(hasType(booleanType())))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000840}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000841
Gabor Marton6e1510c2018-07-12 11:50:21 +0000842TEST_P(ImportDecl, ImportRecordDeclInFunc) {
843 MatchVerifier<Decl> Verifier;
844 testImport("int declToImport() { "
845 " struct data_t {int a;int b;};"
846 " struct data_t d;"
847 " return 0;"
848 "}",
849 Lang_C, "", Lang_C, Verifier,
850 functionDecl(hasBody(compoundStmt(
851 has(declStmt(hasSingleDecl(varDecl(hasName("d")))))))));
852}
853
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000854TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000855 Decl *FromTU = getTuDecl("int declToImport() { "
856 " struct data_t {int a;int b;};"
857 " struct data_t d;"
858 " return 0;"
859 "}",
860 Lang_C, "input.c");
Gabor Martonfe68e292018-08-06 14:38:37 +0000861 auto *FromVar =
Gabor Marton6e1510c2018-07-12 11:50:21 +0000862 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("d")));
863 ASSERT_TRUE(FromVar);
864 auto ToType =
865 ImportType(FromVar->getType().getCanonicalType(), FromVar, Lang_C);
866 EXPECT_FALSE(ToType.isNull());
867}
868
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000869TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {
Gabor Marton6e1510c2018-07-12 11:50:21 +0000870 // This construct is not supported by ASTImporter.
Gabor Martonfe68e292018-08-06 14:38:37 +0000871 Decl *FromTU = getTuDecl(
872 "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
873 Lang_C, "input.c");
874 auto *From = FirstDeclMatcher<FunctionDecl>().match(
875 FromTU, functionDecl(hasName("declToImport")));
Gabor Marton6e1510c2018-07-12 11:50:21 +0000876 ASSERT_TRUE(From);
Gabor Martonfe68e292018-08-06 14:38:37 +0000877 auto *To = Import(From, Lang_C);
878 EXPECT_EQ(To, nullptr);
879}
880
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000881TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +0000882 Decl *FromTU = getTuDecl(
883 "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
884 "int declToImport(){ return NONAME_SIZEOF(int); }",
885 Lang_C, "input.c");
886 auto *From = FirstDeclMatcher<FunctionDecl>().match(
887 FromTU, functionDecl(hasName("declToImport")));
888 ASSERT_TRUE(From);
889 auto *To = Import(From, Lang_C);
890 ASSERT_TRUE(To);
891 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
892 To, functionDecl(hasName("declToImport"),
893 hasDescendant(unaryExprOrTypeTraitExpr()))));
894}
895
Gabor Marton0b57ccb2019-02-07 16:52:48 +0000896TEST_P(ASTImporterOptionSpecificTestBase,
897 ImportRecordDeclInFuncParamsFromMacro) {
Gabor Martonfe68e292018-08-06 14:38:37 +0000898 // This construct is not supported by ASTImporter.
899 Decl *FromTU = getTuDecl(
900 "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
901 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
902 Lang_C, "input.c");
903 auto *From = FirstDeclMatcher<FunctionDecl>().match(
904 FromTU, functionDecl(hasName("declToImport")));
905 ASSERT_TRUE(From);
906 auto *To = Import(From, Lang_C);
Gabor Marton6e1510c2018-07-12 11:50:21 +0000907 EXPECT_EQ(To, nullptr);
908}
909
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000910const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
911 cxxPseudoDestructorExpr;
912
Gabor Marton19f4f392018-06-25 13:04:37 +0000913TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000914 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000915 testImport(
916 "typedef int T;"
917 "void declToImport(int *p) {"
918 " T t;"
919 " p->T::~T();"
920 "}",
921 Lang_CXX, "", Lang_CXX, Verifier,
922 functionDecl(hasDescendant(
923 callExpr(has(cxxPseudoDestructorExpr())))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000924}
925
Gabor Marton19f4f392018-06-25 13:04:37 +0000926TEST_P(ImportDecl, ImportUsingDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000927 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000928 testImport(
929 "namespace foo { int bar; }"
930 "void declToImport() { using foo::bar; }",
931 Lang_CXX, "", Lang_CXX, Verifier,
932 functionDecl(hasDescendant(usingDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000933}
934
935/// \brief Matches shadow declarations introduced into a scope by a
936/// (resolved) using declaration.
937///
938/// Given
939/// \code
940/// namespace n { int f; }
941/// namespace declToImport { using n::f; }
942/// \endcode
943/// usingShadowDecl()
944/// matches \code f \endcode
945const internal::VariadicDynCastAllOfMatcher<Decl,
946 UsingShadowDecl> usingShadowDecl;
947
Gabor Marton19f4f392018-06-25 13:04:37 +0000948TEST_P(ImportDecl, ImportUsingShadowDecl) {
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000949 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000950 testImport(
951 "namespace foo { int bar; }"
952 "namespace declToImport { using foo::bar; }",
953 Lang_CXX, "", Lang_CXX, Verifier,
954 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000955}
956
Gabor Marton19f4f392018-06-25 13:04:37 +0000957TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000958 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000959 testImport(
960 "template<typename T> int foo();"
961 "template <typename T> void declToImport() {"
962 " (void)::foo<T>;"
963 " (void)::template foo<T>;"
964 "}"
965 "void instantiate() { declToImport<int>(); }",
966 Lang_CXX, "", Lang_CXX, Verifier,
967 functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000968}
969
Gabor Marton19f4f392018-06-25 13:04:37 +0000970TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000971 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000972 testImport(
973 "template <typename T> struct C { T t; };"
974 "template <typename T> void declToImport() {"
975 " C<T> d;"
976 " d.t = T();"
977 "}"
978 "void instantiate() { declToImport<int>(); }",
979 Lang_CXX, "", Lang_CXX, Verifier,
980 functionTemplateDecl(hasDescendant(
981 binaryOperator(has(cxxUnresolvedConstructExpr())))));
982 testImport(
983 "template <typename T> struct C { T t; };"
984 "template <typename T> void declToImport() {"
985 " C<T> d;"
986 " (&d)->t = T();"
987 "}"
988 "void instantiate() { declToImport<int>(); }",
989 Lang_CXX, "", Lang_CXX, Verifier,
990 functionTemplateDecl(hasDescendant(
991 binaryOperator(has(cxxUnresolvedConstructExpr())))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000992}
993
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000994/// Check that function "declToImport()" (which is the templated function
995/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
996/// Same for class template declarations.
Gabor Marton19f4f392018-06-25 13:04:37 +0000997TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000998 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +0000999 testImport(
1000 "template <typename T> void declToImport() { T a = 1; }"
1001 "void instantiate() { declToImport<int>(); }",
1002 Lang_CXX, "", Lang_CXX, Verifier,
1003 functionTemplateDecl(hasAncestor(translationUnitDecl(
1004 unless(has(functionDecl(hasName("declToImport"))))))));
1005 testImport(
1006 "template <typename T> struct declToImport { T t; };"
1007 "void instantiate() { declToImport<int>(); }",
1008 Lang_CXX, "", Lang_CXX, Verifier,
1009 classTemplateDecl(hasAncestor(translationUnitDecl(
1010 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +00001011}
1012
Gabor Marton19f4f392018-06-25 13:04:37 +00001013TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001014 MatchVerifier<Decl> Verifier;
1015 auto Code =
1016 R"s(
1017 struct declToImport {
1018 template <typename T0> struct X;
1019 template <typename T0> struct X<T0 *> {};
1020 };
1021 )s";
1022 testImport(Code, Lang_CXX, "", Lang_CXX, Verifier,
1023 recordDecl(has(classTemplateDecl()),
1024 has(classTemplateSpecializationDecl())));
1025}
1026
Gabor Marton19f4f392018-06-25 13:04:37 +00001027TEST_P(ImportExpr, CXXOperatorCallExpr) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001028 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001029 testImport(
1030 "class declToImport {"
1031 " void f() { *this = declToImport(); }"
1032 "};",
1033 Lang_CXX, "", Lang_CXX, Verifier,
1034 cxxRecordDecl(has(cxxMethodDecl(hasDescendant(
1035 cxxOperatorCallExpr())))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001036}
1037
Gabor Marton19f4f392018-06-25 13:04:37 +00001038TEST_P(ImportExpr, DependentSizedArrayType) {
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001039 MatchVerifier<Decl> Verifier;
Gabor Marton1f6ad142018-06-29 10:25:19 +00001040 testImport(
1041 "template<typename T, int Size> class declToImport {"
1042 " T data[Size];"
1043 "};",
1044 Lang_CXX, "", Lang_CXX, Verifier,
1045 classTemplateDecl(has(cxxRecordDecl(
1046 has(fieldDecl(hasType(dependentSizedArrayType())))))));
Gabor Horvathc78d99a2018-01-27 16:11:45 +00001047}
1048
Balazs Keri5f4fd8b2019-03-14 14:20:23 +00001049TEST_P(ASTImporterOptionSpecificTestBase, ImportBeginLocOfDeclRefExpr) {
1050 Decl *FromTU = getTuDecl(
1051 "class A { public: static int X; }; void f() { (void)A::X; }", Lang_CXX);
1052 auto From = FirstDeclMatcher<FunctionDecl>().match(
1053 FromTU, functionDecl(hasName("f")));
1054 ASSERT_TRUE(From);
1055 ASSERT_TRUE(
1056 cast<CStyleCastExpr>(cast<CompoundStmt>(From->getBody())->body_front())
1057 ->getSubExpr()
1058 ->getBeginLoc()
1059 .isValid());
1060 FunctionDecl *To = Import(From, Lang_CXX);
1061 ASSERT_TRUE(To);
1062 ASSERT_TRUE(
1063 cast<CStyleCastExpr>(cast<CompoundStmt>(To->getBody())->body_front())
1064 ->getSubExpr()
1065 ->getBeginLoc()
1066 .isValid());
1067}
1068
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001069TEST_P(ASTImporterOptionSpecificTestBase,
1070 ImportOfTemplatedDeclOfClassTemplateDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001071 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1072 auto From =
1073 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1074 ASSERT_TRUE(From);
1075 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX));
1076 ASSERT_TRUE(To);
1077 Decl *ToTemplated = To->getTemplatedDecl();
1078 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1079 EXPECT_TRUE(ToTemplated1);
1080 EXPECT_EQ(ToTemplated1, ToTemplated);
1081}
1082
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001083TEST_P(ASTImporterOptionSpecificTestBase,
1084 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001085 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1086 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1087 FromTU, functionTemplateDecl());
1088 ASSERT_TRUE(From);
1089 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX));
1090 ASSERT_TRUE(To);
1091 Decl *ToTemplated = To->getTemplatedDecl();
1092 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX);
1093 EXPECT_TRUE(ToTemplated1);
1094 EXPECT_EQ(ToTemplated1, ToTemplated);
1095}
1096
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001097TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton6578a4a2018-06-25 11:38:43 +00001098 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1099 Decl *FromTU = getTuDecl("template<class X> struct S{};", Lang_CXX);
1100 auto FromFT =
1101 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, classTemplateDecl());
1102 ASSERT_TRUE(FromFT);
1103
1104 auto ToTemplated =
1105 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1106 EXPECT_TRUE(ToTemplated);
1107 auto ToTU = ToTemplated->getTranslationUnitDecl();
1108 auto ToFT =
1109 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1110 EXPECT_TRUE(ToFT);
1111}
1112
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001113TEST_P(ASTImporterOptionSpecificTestBase,
Balazs Keria35798d2018-07-17 09:52:41 +00001114 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
Gabor Marton6578a4a2018-06-25 11:38:43 +00001115 Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX);
1116 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1117 FromTU, functionTemplateDecl());
1118 ASSERT_TRUE(FromFT);
1119
1120 auto ToTemplated =
1121 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX));
1122 EXPECT_TRUE(ToTemplated);
1123 auto ToTU = ToTemplated->getTranslationUnitDecl();
1124 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1125 ToTU, functionTemplateDecl());
1126 EXPECT_TRUE(ToFT);
1127}
1128
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001129TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
Gabor Martona0df7a92018-05-30 09:19:26 +00001130 auto Code =
1131 R"(
1132 namespace x {
1133 template<class X> struct S1{};
1134 template<class X> struct S2{};
1135 template<class X> struct S3{};
1136 }
1137 )";
1138 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1139 auto FromNs =
1140 FirstDeclMatcher<NamespaceDecl>().match(FromTU, namespaceDecl());
1141 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX));
1142 ASSERT_TRUE(ToNs);
1143 auto From =
1144 FirstDeclMatcher<ClassTemplateDecl>().match(FromTU,
1145 classTemplateDecl(
1146 hasName("S2")));
1147 auto To =
1148 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1149 classTemplateDecl(
1150 hasName("S2")));
1151 ASSERT_TRUE(From);
1152 ASSERT_TRUE(To);
1153 auto ToTemplated = To->getTemplatedDecl();
1154 auto ToTemplated1 =
1155 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX));
1156 EXPECT_TRUE(ToTemplated1);
1157 ASSERT_EQ(ToTemplated1, ToTemplated);
1158}
1159
Tom Roeder521f0042019-02-26 19:26:41 +00001160TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {
1161 // This tests the import of isConditionTrue directly to make sure the importer
1162 // gets it right.
1163 Decl *From, *To;
1164 std::tie(From, To) = getImportedDecl(
1165 "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }",
1166 Lang_C, "", Lang_C);
1167
1168 auto ToResults = match(chooseExpr().bind("choose"), To->getASTContext());
1169 auto FromResults = match(chooseExpr().bind("choose"), From->getASTContext());
1170
1171 const ChooseExpr *FromChooseExpr =
1172 selectFirst<ChooseExpr>("choose", FromResults);
1173 ASSERT_TRUE(FromChooseExpr);
1174
1175 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>("choose", ToResults);
1176 ASSERT_TRUE(ToChooseExpr);
1177
1178 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());
1179 EXPECT_EQ(FromChooseExpr->isConditionDependent(),
1180 ToChooseExpr->isConditionDependent());
1181}
1182
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001183TEST_P(ASTImporterOptionSpecificTestBase,
1184 ImportFunctionWithBackReferringParameter) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001185 Decl *From, *To;
1186 std::tie(From, To) = getImportedDecl(
1187 R"(
1188 template <typename T> struct X {};
1189
1190 void declToImport(int y, X<int> &x) {}
1191
1192 template <> struct X<int> {
1193 void g() {
1194 X<int> x;
1195 declToImport(0, x);
1196 }
1197 };
1198 )",
1199 Lang_CXX, "", Lang_CXX);
1200
1201 MatchVerifier<Decl> Verifier;
1202 auto Matcher = functionDecl(hasName("declToImport"),
1203 parameterCountIs(2),
1204 hasParameter(0, hasName("y")),
1205 hasParameter(1, hasName("x")),
1206 hasParameter(1, hasType(asString("X<int> &"))));
1207 ASSERT_TRUE(Verifier.match(From, Matcher));
1208 EXPECT_TRUE(Verifier.match(To, Matcher));
1209}
1210
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001211TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001212 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1213 Decl *From, *To;
1214 std::tie(From, To) =
1215 getImportedDecl("template <typename T> void declToImport() { T a = 1; }"
1216 "void instantiate() { declToImport<int>(); }",
1217 Lang_CXX, "", Lang_CXX);
1218
1219 auto Check = [](Decl *D) -> bool {
1220 auto TU = D->getTranslationUnitDecl();
1221 for (auto Child : TU->decls()) {
1222 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1223 if (FD->getNameAsString() == "declToImport") {
1224 GTEST_NONFATAL_FAILURE_(
1225 "TU should not contain any FunctionDecl with name declToImport");
1226 return false;
1227 }
1228 }
1229 }
1230 return true;
1231 };
1232
1233 ASSERT_TRUE(Check(From));
1234 EXPECT_TRUE(Check(To));
1235}
1236
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001237TEST_P(ASTImporterOptionSpecificTestBase,
1238 TUshouldNotContainTemplatedDeclOfClassTemplates) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001239 Decl *From, *To;
1240 std::tie(From, To) =
1241 getImportedDecl("template <typename T> struct declToImport { T t; };"
1242 "void instantiate() { declToImport<int>(); }",
1243 Lang_CXX, "", Lang_CXX);
1244
1245 auto Check = [](Decl *D) -> bool {
1246 auto TU = D->getTranslationUnitDecl();
1247 for (auto Child : TU->decls()) {
1248 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1249 if (RD->getNameAsString() == "declToImport") {
1250 GTEST_NONFATAL_FAILURE_(
1251 "TU should not contain any CXXRecordDecl with name declToImport");
1252 return false;
1253 }
1254 }
1255 }
1256 return true;
1257 };
1258
1259 ASSERT_TRUE(Check(From));
1260 EXPECT_TRUE(Check(To));
1261}
1262
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001263TEST_P(ASTImporterOptionSpecificTestBase,
1264 TUshouldNotContainTemplatedDeclOfTypeAlias) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001265 Decl *From, *To;
1266 std::tie(From, To) =
1267 getImportedDecl(
1268 "template <typename T> struct X {};"
1269 "template <typename T> using declToImport = X<T>;"
1270 "void instantiate() { declToImport<int> a; }",
1271 Lang_CXX11, "", Lang_CXX11);
1272
1273 auto Check = [](Decl *D) -> bool {
1274 auto TU = D->getTranslationUnitDecl();
1275 for (auto Child : TU->decls()) {
1276 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1277 if (AD->getNameAsString() == "declToImport") {
1278 GTEST_NONFATAL_FAILURE_(
1279 "TU should not contain any TypeAliasDecl with name declToImport");
1280 return false;
1281 }
1282 }
1283 }
1284 return true;
1285 };
1286
1287 ASSERT_TRUE(Check(From));
1288 EXPECT_TRUE(Check(To));
1289}
1290
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001291TEST_P(ASTImporterOptionSpecificTestBase,
1292 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001293
1294 Decl *From, *To;
1295 std::tie(From, To) = getImportedDecl(
1296 R"(
1297 template<class T>
1298 class Base {};
1299 class declToImport : public Base<declToImport> {};
1300 )",
1301 Lang_CXX, "", Lang_CXX);
1302
1303 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1304 auto Pattern =
1305 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1306 ASSERT_TRUE(
1307 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1308 EXPECT_TRUE(
1309 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1310
1311 // Check that the ClassTemplateSpecializationDecl is the child of the
1312 // ClassTemplateDecl.
1313 Pattern = translationUnitDecl(has(classTemplateDecl(
1314 hasName("Base"), has(classTemplateSpecializationDecl()))));
1315 ASSERT_TRUE(
1316 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1317 EXPECT_TRUE(
1318 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1319}
1320
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00001321AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1322 size_t Index = 0;
1323 for (FieldDecl *Field : Node.fields()) {
1324 if (Index == Order.size())
1325 return false;
1326 if (Field->getName() != Order[Index])
1327 return false;
1328 ++Index;
1329 }
1330 return Index == Order.size();
1331}
1332
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001333TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001334 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1335 Decl *From, *To;
1336 std::tie(From, To) = getImportedDecl(
1337 R"(
1338 namespace NS {
1339 template<class T>
1340 class X {};
1341 template class X<int>;
1342 }
1343 )",
1344 Lang_CXX, "", Lang_CXX, "NS");
1345
1346 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1347 // ClassTemplateDecl.
1348 auto Pattern = namespaceDecl(has(classTemplateDecl(
1349 hasName("X"), unless(has(classTemplateSpecializationDecl())))));
1350 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1351 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1352
1353 // Check that the ClassTemplateSpecializationDecl is the child of the
1354 // NamespaceDecl.
1355 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName("X"))));
1356 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1357 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1358}
1359
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001360TEST_P(ASTImporterOptionSpecificTestBase,
1361 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001362 Decl *From, *To;
1363 std::tie(From, To) =
1364 getImportedDecl(
1365 "struct declToImport { int a; int b; };",
1366 Lang_CXX11, "", Lang_CXX11);
1367
1368 MatchVerifier<Decl> Verifier;
1369 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1370 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1371}
1372
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001373TEST_P(ASTImporterOptionSpecificTestBase,
Davide Italiano93a64ef2018-10-30 20:46:29 +00001374 DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001375 Decl *From, *To;
1376 std::tie(From, To) = getImportedDecl(
1377 // The original recursive algorithm of ASTImporter first imports 'c' then
1378 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1379 R"s(
1380 struct declToImport {
1381 int a = c + b;
1382 int b = 1;
1383 int c = 2;
1384 };
1385 )s",
1386 Lang_CXX11, "", Lang_CXX11);
1387
1388 MatchVerifier<Decl> Verifier;
1389 ASSERT_TRUE(
1390 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1391 EXPECT_TRUE(
1392 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1393}
1394
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001395TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001396 Decl *From, *To;
1397 std::tie(From, To) = getImportedDecl(
1398 R"(
Gabor Martona3af5672018-05-23 14:24:02 +00001399 struct declToImport {
1400 };
1401 )",
1402 Lang_CXX, "", Lang_CXX);
1403
1404 MatchVerifier<Decl> Verifier;
1405 // Match the implicit Decl.
1406 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1407 ASSERT_TRUE(Verifier.match(From, Matcher));
1408 EXPECT_TRUE(Verifier.match(To, Matcher));
1409}
1410
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001411TEST_P(ASTImporterOptionSpecificTestBase,
1412 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
Gabor Martona3af5672018-05-23 14:24:02 +00001413 Decl *From, *To;
1414 std::tie(From, To) = getImportedDecl(
1415 R"(
Peter Szecsidedda6f2018-03-30 22:03:29 +00001416 template <typename U>
1417 struct declToImport {
1418 };
1419 )",
1420 Lang_CXX, "", Lang_CXX);
1421
1422 MatchVerifier<Decl> Verifier;
1423 // Match the implicit Decl.
1424 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1425 ASSERT_TRUE(Verifier.match(From, Matcher));
1426 EXPECT_TRUE(Verifier.match(To, Matcher));
1427}
1428
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001429TEST_P(ASTImporterOptionSpecificTestBase,
1430 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001431 Decl *From, *To;
1432 std::tie(From, To) = getImportedDecl(
1433 R"(
1434 template<class T>
1435 class Base {};
1436 class declToImport : public Base<declToImport> {};
1437 )",
1438 Lang_CXX, "", Lang_CXX);
1439
1440 auto hasImplicitClass = has(cxxRecordDecl());
1441 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1442 hasName("Base"),
1443 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1444 ASSERT_TRUE(
1445 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1446 EXPECT_TRUE(
1447 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1448}
1449
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001450TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001451 Decl *From, *To;
1452 std::tie(From, To) =
1453 getImportedDecl("void declToImport() {}", Lang_CXX, "", Lang_CXX);
1454
1455 MatchVerifier<Decl> Verifier;
1456 auto Matcher = functionDecl();
1457 ASSERT_TRUE(Verifier.match(From, Matcher));
1458 EXPECT_TRUE(Verifier.match(To, Matcher));
1459 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1460}
1461
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001462TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001463 Decl *FromTU = getTuDecl(
1464 R"(
1465 struct X {};
1466 void operator<<(int, X);
1467 )",
1468 Lang_CXX);
1469 Decl *From = LastDeclMatcher<Decl>{}.match(FromTU, functionDecl());
1470 const Decl *To = Import(From, Lang_CXX);
1471 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1472}
1473
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001474TEST_P(ASTImporterOptionSpecificTestBase,
Peter Szecsidedda6f2018-03-30 22:03:29 +00001475 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1476 Decl *From, *To;
1477 std::tie(From, To) = getImportedDecl(
1478 R"(
1479 template<class T>
1480 class Base { int a; };
1481 class declToImport : Base<declToImport> {};
1482 )",
1483 Lang_CXX, "", Lang_CXX);
1484
1485 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1486 hasName("Base"),
1487 has(classTemplateSpecializationDecl(has(fieldDecl(hasName("a"))))))));
1488 ASSERT_TRUE(
1489 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1490 EXPECT_TRUE(
1491 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1492}
1493
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001494TEST_P(ASTImporterOptionSpecificTestBase,
1495 ImportDefinitionOfClassTemplateAfterFwdDecl) {
Aleksei Sidorin761c2242018-05-15 11:09:07 +00001496 {
1497 Decl *FromTU = getTuDecl(
1498 R"(
1499 template <typename T>
1500 struct B;
1501 )",
1502 Lang_CXX, "input0.cc");
1503 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1504 FromTU, classTemplateDecl(hasName("B")));
1505
1506 Import(FromD, Lang_CXX);
1507 }
1508
1509 {
1510 Decl *FromTU = getTuDecl(
1511 R"(
1512 template <typename T>
1513 struct B {
1514 void f();
1515 };
1516 )",
1517 Lang_CXX, "input1.cc");
1518 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1519 FromTU, functionDecl(hasName("f")));
1520 Import(FromD, Lang_CXX);
1521 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1522 FromTU, classTemplateDecl(hasName("B")));
1523 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
1524 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1525 }
1526}
1527
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001528TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001529 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1530 Decl *ToTU = getToTuDecl(
1531 R"(
1532 template <typename T>
1533 struct B {
1534 void f();
1535 };
1536
1537 template <typename T>
1538 struct B;
1539 )",
1540 Lang_CXX);
1541 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1542 [](const ClassTemplateDecl *T) {
1543 return T->isThisDeclarationADefinition();
1544 })
1545 .match(ToTU, classTemplateDecl()));
1546
1547 Decl *FromTU = getTuDecl(
1548 R"(
1549 template <typename T>
1550 struct B {
1551 void f();
1552 };
1553 )",
1554 Lang_CXX, "input1.cc");
1555 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1556 FromTU, classTemplateDecl(hasName("B")));
1557
1558 Import(FromD, Lang_CXX);
1559
1560 // We should have only one definition.
1561 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1562 [](const ClassTemplateDecl *T) {
1563 return T->isThisDeclarationADefinition();
1564 })
1565 .match(ToTU, classTemplateDecl()));
1566}
1567
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001568TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton9581c332018-05-23 13:53:36 +00001569 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1570 Decl *ToTU = getToTuDecl(
1571 R"(
1572 struct B {
1573 void f();
1574 };
1575
1576 struct B;
1577 )",
1578 Lang_CXX);
1579 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001580 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001581
1582 Decl *FromTU = getTuDecl(
1583 R"(
1584 struct B {
1585 void f();
1586 };
1587 )",
1588 Lang_CXX, "input1.cc");
1589 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1590 FromTU, cxxRecordDecl(hasName("B")));
1591
1592 Import(FromD, Lang_CXX);
1593
1594 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
Hans Wennborgd0a8ad32018-05-24 10:49:38 +00001595 ToTU, cxxRecordDecl(unless(isImplicit()))));
Gabor Marton9581c332018-05-23 13:53:36 +00001596}
1597
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001598static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1599 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1600 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1601 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1602 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1603}
1604static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1605 SourceManager &SM1, SourceManager &SM2) {
1606 CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
1607 FullSourceLoc{ Range2.getBegin(), SM2 });
1608 CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
1609 FullSourceLoc{ Range2.getEnd(), SM2 });
1610}
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001611TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001612 Decl *FromTU = getTuDecl(
1613 R"(
1614 #define MFOO(arg) arg = arg + 1
1615
1616 void foo() {
1617 int a = 5;
1618 MFOO(a);
1619 }
1620 )",
1621 Lang_CXX);
1622 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1623 auto ToD = Import(FromD, Lang_CXX);
1624
1625 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1626 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
1627 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1628 auto FromRHS =
1629 LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
1630
1631 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1632 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1633 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1634 FromSM);
1635 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1636 FromSM);
1637 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1638 FromSM);
1639}
1640
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001641TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
Rafael Stahl29f37fb2018-07-04 13:34:05 +00001642 Decl *FromTU = getTuDecl(
1643 R"(
1644 #define FUNC_INT void declToImport
1645 #define FUNC FUNC_INT
1646 FUNC(int a);
1647 )",
1648 Lang_CXX);
1649 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1650 auto ToD = Import(FromD, Lang_CXX);
1651
1652 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1653 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1654 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1655 FromSM);
1656}
1657
Gabor Marton9581c332018-05-23 13:53:36 +00001658TEST_P(
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001659 ASTImporterOptionSpecificTestBase,
1660 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
Gabor Marton9581c332018-05-23 13:53:36 +00001661 Decl *ToTU = getToTuDecl(
1662 R"(
1663 template <typename T>
1664 struct B;
1665
1666 template <>
1667 struct B<int> {};
1668
1669 template <>
1670 struct B<int>;
1671 )",
1672 Lang_CXX);
1673 // We should have only one definition.
1674 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1675 [](const ClassTemplateSpecializationDecl *T) {
1676 return T->isThisDeclarationADefinition();
1677 })
1678 .match(ToTU, classTemplateSpecializationDecl()));
1679
1680 Decl *FromTU = getTuDecl(
1681 R"(
1682 template <typename T>
1683 struct B;
1684
1685 template <>
1686 struct B<int> {};
1687 )",
1688 Lang_CXX, "input1.cc");
1689 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1690 FromTU, classTemplateSpecializationDecl(hasName("B")));
1691
1692 Import(FromD, Lang_CXX);
1693
1694 // We should have only one definition.
1695 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
1696 [](const ClassTemplateSpecializationDecl *T) {
1697 return T->isThisDeclarationADefinition();
1698 })
1699 .match(ToTU, classTemplateSpecializationDecl()));
1700}
1701
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001702TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
Gabor Marton0bebf952018-07-05 09:51:13 +00001703 Decl *FromTU = getTuDecl(
1704 R"(
1705 struct { int a; int b; } object0 = { 2, 3 };
1706 struct { int x; int y; int z; } object1;
1707 )",
1708 Lang_CXX, "input0.cc");
1709
Gabor Marton0bebf952018-07-05 09:51:13 +00001710 auto *Obj0 =
1711 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object0")));
1712 auto *From0 = getRecordDecl(Obj0);
1713 auto *Obj1 =
1714 FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("object1")));
1715 auto *From1 = getRecordDecl(Obj1);
1716
1717 auto *To0 = Import(From0, Lang_CXX);
1718 auto *To1 = Import(From1, Lang_CXX);
1719
1720 EXPECT_TRUE(To0);
1721 EXPECT_TRUE(To1);
1722 EXPECT_NE(To0, To1);
1723 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
1724}
1725
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001726TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001727 auto *Code =
1728 R"(
1729 struct X {
1730 struct { int a; };
1731 struct { int b; };
1732 };
1733 )";
1734 Decl *FromTU0 = getTuDecl(Code, Lang_C, "input0.c");
1735
1736 Decl *FromTU1 = getTuDecl(Code, Lang_C, "input1.c");
1737
1738 auto *X0 =
1739 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1740 auto *X1 =
1741 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1742 Import(X0, Lang_C);
1743 Import(X1, Lang_C);
1744
1745 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1746 // We expect no (ODR) warning during the import.
1747 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1748 EXPECT_EQ(1u,
1749 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1750}
1751
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001752TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
Gabor Marton7df342a2018-12-17 12:42:12 +00001753 Decl *FromTU0 = getTuDecl(
1754 R"(
1755 struct X {
1756 struct { int a; };
1757 struct { int b; };
1758 };
1759 )",
1760 Lang_C, "input0.c");
1761
1762 Decl *FromTU1 = getTuDecl(
1763 R"(
1764 struct X { // reversed order
1765 struct { int b; };
1766 struct { int a; };
1767 };
1768 )",
1769 Lang_C, "input1.c");
1770
1771 auto *X0 =
1772 FirstDeclMatcher<RecordDecl>().match(FromTU0, recordDecl(hasName("X")));
1773 auto *X1 =
1774 FirstDeclMatcher<RecordDecl>().match(FromTU1, recordDecl(hasName("X")));
1775 Import(X0, Lang_C);
1776 Import(X1, Lang_C);
1777
1778 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1779 // We expect one (ODR) warning during the import.
1780 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
1781 EXPECT_EQ(2u,
1782 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
1783}
1784
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001785TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001786 auto Pattern = varDecl(hasName("x"));
1787 VarDecl *Imported1;
1788 {
1789 Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc");
1790 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1791 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1792 }
1793 VarDecl *Imported2;
1794 {
1795 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc");
1796 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1797 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1798 }
1799 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
1800 EXPECT_FALSE(Imported2->isUsed(false));
1801 {
1802 Decl *FromTU =
1803 getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc");
Gabor Martonac3a5d62018-09-17 12:04:52 +00001804 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1805 FromTU, functionDecl(hasName("f")));
Gabor Marton26f72a92018-07-12 09:42:05 +00001806 Import(FromD, Lang_CXX);
1807 }
1808 EXPECT_TRUE(Imported2->isUsed(false));
1809}
1810
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001811TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001812 auto Pattern = varDecl(hasName("x"));
1813 VarDecl *ExistingD;
1814 {
1815 Decl *ToTU = getToTuDecl("int x = 1;", Lang_CXX);
1816 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1817 }
1818 EXPECT_FALSE(ExistingD->isUsed(false));
1819 {
1820 Decl *FromTU = getTuDecl(
1821 "int x = 1; int f() { return x; }", Lang_CXX, "input1.cc");
1822 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
1823 FromTU, functionDecl(hasName("f")));
1824 Import(FromD, Lang_CXX);
1825 }
1826 EXPECT_TRUE(ExistingD->isUsed(false));
1827}
1828
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001829TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
Gabor Martonac3a5d62018-09-17 12:04:52 +00001830 auto Pattern = varDecl(hasName("a"));
1831 VarDecl *ExistingD;
1832 {
1833 Decl *ToTU = getToTuDecl(
1834 R"(
1835 struct A {
1836 static const int a = 1;
1837 };
1838 )", Lang_CXX);
1839 ExistingD = FirstDeclMatcher<VarDecl>().match(ToTU, Pattern);
1840 }
1841 EXPECT_FALSE(ExistingD->isUsed(false));
1842 {
1843 Decl *FromTU = getTuDecl(
1844 R"(
1845 struct A {
1846 static const int a = 1;
1847 };
1848 const int *f() { return &A::a; } // requires storage,
1849 // thus used flag will be set
1850 )", Lang_CXX, "input1.cc");
1851 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
1852 FromTU, functionDecl(hasName("f")));
1853 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1854 ASSERT_TRUE(FromD->isUsed(false));
1855 Import(FromFunD, Lang_CXX);
1856 }
1857 EXPECT_TRUE(ExistingD->isUsed(false));
1858}
1859
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001860TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
Gabor Marton26f72a92018-07-12 09:42:05 +00001861 auto Pattern = varDecl(hasName("x"));
1862
1863 Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc");
1864 auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
1865
1866 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX));
1867
1868 ASSERT_FALSE(Imported1->isUsed(false));
1869
1870 FromD->setIsUsed();
1871 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX));
1872
1873 EXPECT_EQ(Imported1, Imported2);
1874 EXPECT_TRUE(Imported2->isUsed(false));
1875}
1876
Gabor Marton0b57ccb2019-02-07 16:52:48 +00001877struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
Peter Szecsidedda6f2018-03-30 22:03:29 +00001878
Gabor Marton5254e642018-06-27 13:32:50 +00001879TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
Peter Szecsidedda6f2018-03-30 22:03:29 +00001880 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1881 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001882 auto *From =
1883 FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Proto
Peter Szecsidedda6f2018-03-30 22:03:29 +00001884
Gabor Marton5254e642018-06-27 13:32:50 +00001885 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001886 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1887
Gabor Marton5254e642018-06-27 13:32:50 +00001888 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1889 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1890 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1891 EXPECT_TRUE(ImportedD == To0);
1892 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1893 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1894 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001895}
1896
1897TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
1898 Decl *FromTU = getTuDecl("void f(); void f() { f(); }", Lang_CXX);
1899 auto Pattern = functionDecl(hasName("f"));
Gabor Marton5254e642018-06-27 13:32:50 +00001900 auto *From =
1901 LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern); // Def
Peter Szecsidedda6f2018-03-30 22:03:29 +00001902
Gabor Marton5254e642018-06-27 13:32:50 +00001903 Decl *ImportedD = Import(From, Lang_CXX);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001904 Decl *ToTU = ImportedD->getTranslationUnitDecl();
1905
Gabor Marton5254e642018-06-27 13:32:50 +00001906 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
1907 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1908 auto *To1 = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
1909 EXPECT_TRUE(ImportedD == To1);
1910 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
1911 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
1912 EXPECT_EQ(To1->getPreviousDecl(), To0);
Peter Szecsidedda6f2018-03-30 22:03:29 +00001913}
1914
Peter Szecsidedda6f2018-03-30 22:03:29 +00001915TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
1916 auto Code =
1917 R"(
1918 struct B { virtual void f(); };
1919 void B::f() {}
1920 struct D : B { void f(); };
1921 )";
1922 auto Pattern =
1923 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
1924 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1925 CXXMethodDecl *Proto =
1926 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1927
1928 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
1929 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1930 EXPECT_EQ(To->size_overridden_methods(), 1u);
1931}
1932
1933TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
1934 auto Code =
1935 R"(
1936 struct B { virtual void f(); };
1937 void B::f() {}
1938 )";
1939 auto Pattern =
1940 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1941 Decl *FromTU = getTuDecl(Code, Lang_CXX);
1942 CXXMethodDecl *Proto =
1943 FirstDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1944 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(FromTU, Pattern);
1945
1946 ASSERT_TRUE(Proto->isVirtual());
1947 ASSERT_TRUE(Def->isVirtual());
1948 CXXMethodDecl *To = cast<CXXMethodDecl>(Import(Proto, Lang_CXX));
1949 EXPECT_TRUE(To->isVirtual());
1950}
1951
Gabor Marton5254e642018-06-27 13:32:50 +00001952TEST_P(ImportFunctions,
1953 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
1954 Decl *ToTU = getToTuDecl(
1955 R"(
1956 void f() {}
1957 void f();
1958 )",
1959 Lang_CXX);
1960 ASSERT_EQ(1u,
1961 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
1962 return FD->doesThisDeclarationHaveABody();
1963 }).match(ToTU, functionDecl()));
1964
1965 Decl *FromTU = getTuDecl("void f() {}", Lang_CXX, "input0.cc");
1966 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
1967
1968 Import(FromD, Lang_CXX);
1969
1970 EXPECT_EQ(1u,
1971 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
1972 return FD->doesThisDeclarationHaveABody();
1973 }).match(ToTU, functionDecl()));
1974}
1975
Shafik Yaghmour96b3d202019-01-28 21:55:33 +00001976TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
1977 auto Code =
1978 R"(
1979 struct B { virtual void f(); };
1980 struct D:B { void f(); };
1981 )";
1982 auto BFP =
1983 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
1984 auto DFP =
1985 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
1986
1987 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
1988 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
1989 Import(DF, Lang_CXX);
1990
1991 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
1992 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
1993 Import(BF, Lang_CXX);
1994
1995 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
1996
1997 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
1998 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
1999}
2000
2001TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2002 auto CodeWithoutDef =
2003 R"(
2004 struct B { virtual void f(); };
2005 struct D:B { void f(); };
2006 )";
2007 auto CodeWithDef =
2008 R"(
2009 struct B { virtual void f(){}; };
2010 struct D:B { void f(){}; };
2011 )";
2012 auto BFP =
2013 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2014 auto DFP =
2015 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2016 auto BFDefP = cxxMethodDecl(
2017 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2018 auto DFDefP = cxxMethodDecl(
2019 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2020 auto FDefAllP = cxxMethodDecl(hasName("f"), isDefinition());
2021
2022 {
2023 Decl *FromTU = getTuDecl(CodeWithDef, Lang_CXX, "input0.cc");
2024 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, DFP);
2025 Import(FromD, Lang_CXX);
2026 }
2027 {
2028 Decl *FromTU = getTuDecl(CodeWithoutDef, Lang_CXX, "input1.cc");
2029 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(FromTU, BFP);
2030 Import(FromB, Lang_CXX);
2031 }
2032
2033 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2034
2035 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2036 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2037 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2038 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2039 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2040}
2041
2042TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2043 auto Code =
2044 R"(
2045 struct B { virtual void f(); };
2046 struct D:B { void f(); };
2047 void B::f(){};
2048 )";
2049
2050 auto BFP =
2051 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2052 auto BFDefP = cxxMethodDecl(
2053 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2054 auto DFP = cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))),
2055 unless(isDefinition()));
2056
2057 Decl *FromTU0 = getTuDecl(Code, Lang_CXX);
2058 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2059 Import(D, Lang_CXX);
2060
2061 Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc");
2062 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(FromTU1, BFP);
2063 Import(B, Lang_CXX);
2064
2065 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2066
2067 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2068 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2069
2070 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2071 ToTU, cxxRecordDecl(hasName("B")));
2072 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2073 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2074 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2075
2076 // The definition should be out-of-class.
2077 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2078 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2079 ToBFOutOfClass->getLexicalDeclContext());
2080 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2081 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2082
2083 // Check that the redecl chain is intact.
2084 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2085}
2086
2087TEST_P(ImportFunctions,
2088 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2089 auto CodeTU0 =
2090 R"(
2091 struct B { virtual void f(); };
2092 struct D:B { void f(); };
2093 )";
2094 auto CodeTU1 =
2095 R"(
2096 struct B { virtual void f(); };
2097 struct D:B { void f(); };
2098 void B::f(){}
2099 void D::f(){}
2100 void foo(B &b, D &d) { b.f(); d.f(); }
2101 )";
2102
2103 auto BFP =
2104 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("B"))));
2105 auto BFDefP = cxxMethodDecl(
2106 hasName("f"), hasParent(cxxRecordDecl(hasName("B"))), isDefinition());
2107 auto DFP =
2108 cxxMethodDecl(hasName("f"), hasParent(cxxRecordDecl(hasName("D"))));
2109 auto DFDefP = cxxMethodDecl(
2110 hasName("f"), hasParent(cxxRecordDecl(hasName("D"))), isDefinition());
2111 auto FooDef = functionDecl(hasName("foo"));
2112
2113 {
2114 Decl *FromTU0 = getTuDecl(CodeTU0, Lang_CXX, "input0.cc");
2115 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(FromTU0, DFP);
2116 Import(D, Lang_CXX);
2117 }
2118
2119 {
2120 Decl *FromTU1 = getTuDecl(CodeTU1, Lang_CXX, "input1.cc");
2121 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(FromTU1, FooDef);
2122 Import(Foo, Lang_CXX);
2123 }
2124
2125 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2126
2127 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2128 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2129 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2130 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2131
2132 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2133 ToTU, cxxRecordDecl(hasName("B")));
2134 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2135 ToTU, cxxRecordDecl(hasName("D")));
2136 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2137 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2138 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2139 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2140 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2141 ToTU, cxxMethodDecl(hasName("f"), isDefinition()));
2142
2143 // The definition should be out-of-class.
2144 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2145 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2146 ToBFOutOfClass->getLexicalDeclContext());
2147 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2148 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2149
2150 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2151 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2152 ToDFOutOfClass->getLexicalDeclContext());
2153 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2154 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2155
2156 // Check that the redecl chain is intact.
2157 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2158 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2159}
2160
Gabor Marton458d1452019-02-14 13:07:03 +00002161TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2162 std::string Code = "static int v; static int v = 0;";
2163 auto Pattern = varDecl(hasName("v"));
2164
2165 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_C, "input0.c");
2166
2167 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2168 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2169
2170 auto *To0 = Import(From0, Lang_C);
2171 auto *To1 = Import(From1, Lang_C);
2172
2173 EXPECT_TRUE(To0);
2174 ASSERT_TRUE(To1);
2175 EXPECT_NE(To0, To1);
2176 EXPECT_EQ(To1->getPreviousDecl(), To0);
2177}
2178
2179TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2180 TranslationUnitDecl *FromTu = getTuDecl(
2181 "namespace NS0 { namespace { void f(); } }"
2182 "namespace NS1 { namespace { void f(); } }",
2183 Lang_CXX, "input0.cc");
2184 auto Pattern = functionDecl(hasName("f"));
2185
2186 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2187 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2188
2189 auto *ToF0 = Import(FromF0, Lang_CXX);
2190 auto *ToF1 = Import(FromF1, Lang_CXX);
2191
2192 EXPECT_TRUE(ToF0);
2193 ASSERT_TRUE(ToF1);
2194 EXPECT_NE(ToF0, ToF1);
2195 EXPECT_FALSE(ToF1->getPreviousDecl());
2196}
2197
2198TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2199 {
2200 Decl *FromTU = getTuDecl("namespace { void f() {} } void g0() { f(); }",
2201 Lang_CXX, "input0.cc");
2202 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2203 FromTU, functionDecl(hasName("g0")));
2204
2205 Import(FromD, Lang_CXX);
2206 }
2207 {
2208 Decl *FromTU =
2209 getTuDecl("namespace { void f() { int a; } } void g1() { f(); }",
2210 Lang_CXX, "input1.cc");
2211 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2212 FromTU, functionDecl(hasName("g1")));
2213 Import(FromD, Lang_CXX);
2214 }
2215
2216 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2217 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2218 2u);
2219}
2220
Gabor Marton302f3002019-02-15 12:04:05 +00002221TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2222 Decl *FromTU = getTuDecl(
2223 R"(
2224 void foo() {
2225 (void)[]() { ; };
2226 }
2227 )",
2228 Lang_CXX11);
2229 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2230 FromTU, functionDecl(hasName("foo")));
2231 auto *ToD = Import(FromD, Lang_CXX);
2232 EXPECT_TRUE(ToD);
2233 CXXRecordDecl *LambdaRec =
2234 cast<LambdaExpr>(cast<CStyleCastExpr>(
2235 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2236 ->getSubExpr())
2237 ->getLambdaClass();
2238 EXPECT_TRUE(LambdaRec->getDestructor());
2239}
2240
Gabor Marton5caba302019-03-07 13:38:20 +00002241TEST_P(ImportFunctions,
2242 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2243 Decl *FromTU = getTuDecl(
2244 R"(
2245 struct X {
2246 template <typename T>
2247 void foo(){}
2248 };
2249 void f() {
2250 X x;
2251 x.foo<int>();
2252 }
2253 )",
2254 Lang_CXX);
2255 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2256 FromTU, functionDecl(hasName("f")));
2257 auto *ToD = Import(FromD, Lang_CXX);
2258 EXPECT_TRUE(ToD);
2259 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
2260 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr()))));
2261}
2262
2263TEST_P(ImportFunctions,
2264 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2265 Decl *FromTU = getTuDecl(
2266 R"(
2267 struct X {
2268 template <typename T>
2269 void foo(){}
2270 };
2271 template <typename T>
2272 void f() {
2273 X x;
2274 x.foo<T>();
2275 }
2276 void g() {
2277 f<int>();
2278 }
2279 )",
2280 Lang_CXX);
2281 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2282 FromTU, functionDecl(hasName("g")));
2283 auto *ToD = Import(FromD, Lang_CXX);
2284 EXPECT_TRUE(ToD);
2285 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2286 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match(
2287 ToTU, translationUnitDecl(hasDescendant(
2288 functionDecl(hasName("f"), hasDescendant(declRefExpr()))))));
2289}
2290
Gabor Marton5254e642018-06-27 13:32:50 +00002291struct ImportFriendFunctions : ImportFunctions {};
2292
2293TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2294 auto Pattern = functionDecl(hasName("f"));
2295
2296 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2297 "void f();",
2298 Lang_CXX,
2299 "input0.cc");
2300 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2301
2302 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2303 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2304 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2305 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2306 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2307 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2308 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2309}
2310
2311TEST_P(ImportFriendFunctions,
2312 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2313 auto Pattern = functionDecl(hasName("f"));
2314
2315 Decl *FromTU = getTuDecl("void f();"
2316 "struct X { friend void f(); };",
2317 Lang_CXX, "input0.cc");
2318 auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2319
2320 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2321 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2322 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2323 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2324 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2325 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2326 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2327}
2328
2329TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2330 auto Pattern = functionDecl(hasName("f"));
2331
2332 Decl *FromTU = getTuDecl("struct X { friend void f(){} };"
2333 "void f();",
2334 Lang_CXX,
2335 "input0.cc");
2336 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2337
2338 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2339 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2340 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2341 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2342 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2343 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2344 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2345}
2346
2347TEST_P(ImportFriendFunctions,
2348 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2349 auto Pattern = functionDecl(hasName("f"));
2350
2351 Decl *FromTU = getTuDecl("struct X { friend void f(); };"
2352 "void f(){}",
2353 Lang_CXX, "input0.cc");
2354 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2355
2356 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2357 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2358 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2359 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2360 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(ToTU, Pattern);
2361 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2362 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2363}
2364
Gabor Marton26f72a92018-07-12 09:42:05 +00002365// Disabled temporarily, because the new structural equivalence check
2366// (https://reviews.llvm.org/D48628) breaks it.
2367// PreviousDecl is not set because there is no structural match.
2368// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002369TEST_P(ImportFriendFunctions,
2370 DISABLED_ImportFriendFunctionRedeclChainDefWithClass) {
2371 auto Pattern = functionDecl(hasName("f"));
2372
2373 Decl *FromTU = getTuDecl(
2374 R"(
2375 class X;
2376 void f(X *x){}
2377 class X{
2378 friend void f(X *x);
2379 };
2380 )",
2381 Lang_CXX, "input0.cc");
2382 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2383
2384 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2385 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2386 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2387 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2388 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2389 .match(ToTU, friendDecl())
2390 ->getFriendDecl());
2391 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2392 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2393 // The parameters must refer the same type
2394 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2395 (*ImportedD->param_begin())->getOriginalType());
2396}
2397
Gabor Marton26f72a92018-07-12 09:42:05 +00002398// Disabled temporarily, because the new structural equivalence check
2399// (https://reviews.llvm.org/D48628) breaks it.
2400// PreviousDecl is not set because there is no structural match.
2401// FIXME Enable!
Gabor Marton5254e642018-06-27 13:32:50 +00002402TEST_P(ImportFriendFunctions,
Gabor Marton26f72a92018-07-12 09:42:05 +00002403 DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002404 auto Pattern = functionDecl(hasName("f"));
2405
2406 Decl *FromTU = getTuDecl(
2407 R"(
2408 class X;
2409 void f(X *x){}
2410 class X{
2411 friend void f(X *x);
2412 };
2413 )",
2414 Lang_CXX, "input0.cc");
2415 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2416
2417 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2418 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2419 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2420 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2421 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2422 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2423
2424 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2425 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2426 // The parameters must refer the same type
2427 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2428 (*ImportedD->param_begin())->getOriginalType());
2429}
2430
2431TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2432 auto Pattern = functionDecl(hasName("f"));
2433
2434 FunctionDecl *ImportedD;
2435 {
2436 Decl *FromTU =
2437 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2438 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2439 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2440 }
2441 FunctionDecl *ImportedD1;
2442 {
2443 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2444 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2445 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2446 }
2447
2448 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2449 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2450 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2451 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2452 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2453}
2454
Balazs Keri89632b82018-08-21 14:32:21 +00002455TEST_P(ImportFriendFunctions, Lookup) {
2456 auto FunctionPattern = functionDecl(hasName("f"));
2457 auto ClassPattern = cxxRecordDecl(hasName("X"));
2458
2459 TranslationUnitDecl *FromTU =
2460 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2461 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2462 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2463 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2464 {
2465 auto FromName = FromD->getDeclName();
2466 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2467 auto LookupRes = Class->noload_lookup(FromName);
2468 ASSERT_EQ(LookupRes.size(), 0u);
2469 LookupRes = FromTU->noload_lookup(FromName);
2470 ASSERT_EQ(LookupRes.size(), 1u);
2471 }
2472
2473 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2474 auto ToName = ToD->getDeclName();
2475
2476 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2477 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2478 auto LookupRes = Class->noload_lookup(ToName);
2479 EXPECT_EQ(LookupRes.size(), 0u);
2480 LookupRes = ToTU->noload_lookup(ToName);
2481 EXPECT_EQ(LookupRes.size(), 1u);
2482
2483 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2484 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2485 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2486 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2487}
2488
2489TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2490 auto FunctionPattern = functionDecl(hasName("f"));
2491 auto ClassPattern = cxxRecordDecl(hasName("X"));
2492
2493 TranslationUnitDecl *FromTU = getTuDecl(
2494 "struct X { friend void f(); };"
2495 // This proto decl makes f available to normal
2496 // lookup, otherwise it is hidden.
2497 // Normal C++ lookup (implemented in
2498 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2499 // returns the found `NamedDecl` only if the set IDNS is matched
2500 "void f();",
2501 Lang_CXX, "input0.cc");
2502 auto *FromFriend =
2503 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2504 auto *FromNormal =
2505 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2506 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2507 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2508 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2509 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2510
2511 auto FromName = FromFriend->getDeclName();
2512 auto *FromClass =
2513 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2514 auto LookupRes = FromClass->noload_lookup(FromName);
2515 ASSERT_EQ(LookupRes.size(), 0u);
2516 LookupRes = FromTU->noload_lookup(FromName);
2517 ASSERT_EQ(LookupRes.size(), 1u);
2518
2519 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2520 auto ToName = ToFriend->getDeclName();
2521
2522 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2523 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2524 LookupRes = ToClass->noload_lookup(ToName);
2525 EXPECT_EQ(LookupRes.size(), 0u);
2526 LookupRes = ToTU->noload_lookup(ToName);
2527 // Test is disabled because this result is 2.
2528 EXPECT_EQ(LookupRes.size(), 1u);
2529
2530 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2531 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2532 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2533 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2534 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2535 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2536 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2537}
2538
2539TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2540 auto FunctionPattern = functionDecl(hasName("f"));
2541 auto ClassPattern = cxxRecordDecl(hasName("X"));
2542
2543 TranslationUnitDecl *FromTU = getTuDecl(
2544 "void f();"
2545 "struct X { friend void f(); };",
2546 Lang_CXX, "input0.cc");
2547 auto *FromNormal =
2548 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2549 auto *FromFriend =
2550 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2551 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2552 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2553 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2554 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2555
2556 auto FromName = FromNormal->getDeclName();
2557 auto *FromClass =
2558 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2559 auto LookupRes = FromClass->noload_lookup(FromName);
2560 ASSERT_EQ(LookupRes.size(), 0u);
2561 LookupRes = FromTU->noload_lookup(FromName);
2562 ASSERT_EQ(LookupRes.size(), 1u);
2563
2564 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2565 auto ToName = ToNormal->getDeclName();
2566 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2567
2568 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2569 LookupRes = ToClass->noload_lookup(ToName);
2570 EXPECT_EQ(LookupRes.size(), 0u);
2571 LookupRes = ToTU->noload_lookup(ToName);
2572 EXPECT_EQ(LookupRes.size(), 1u);
2573
2574 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2575 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2576 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2577 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2578 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2579 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2580 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2581}
2582
2583TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2584 auto Pattern = functionDecl(hasName("f"));
2585
2586 TranslationUnitDecl *FromNormalTU =
2587 getTuDecl("void f();", Lang_CXX, "input0.cc");
2588 auto *FromNormalF =
2589 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2590 TranslationUnitDecl *FromFriendTU =
2591 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2592 auto *FromFriendF =
2593 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2594 auto FromNormalName = FromNormalF->getDeclName();
2595 auto FromFriendName = FromFriendF->getDeclName();
2596
2597 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2598 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2599 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2600 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2601 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2602 ASSERT_EQ(LookupRes.size(), 1u);
2603 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2604 ASSERT_EQ(LookupRes.size(), 1u);
2605
2606 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2607 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2608 auto ToName = ToNormalF->getDeclName();
2609 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2610 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2611 LookupRes = ToTU->noload_lookup(ToName);
2612 EXPECT_EQ(LookupRes.size(), 1u);
2613 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00002614
Balazs Keri89632b82018-08-21 14:32:21 +00002615 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
2616 LookupRes = ToTU->noload_lookup(ToName);
2617 EXPECT_EQ(LookupRes.size(), 1u);
2618 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2619
2620 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2621 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2622
2623 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2624 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2625}
2626
2627TEST_P(ImportFriendFunctions, ImportFriendList) {
2628 TranslationUnitDecl *FromTU = getTuDecl(
2629 "struct X { friend void f(); };"
2630 "void f();",
2631 Lang_CXX, "input0.cc");
2632 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2633 FromTU, functionDecl(hasName("f")));
2634
2635 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2636 FromTU, cxxRecordDecl(hasName("X")));
2637 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2638 auto FromFriends = FromClass->friends();
2639 unsigned int FrN = 0;
2640 for (auto Fr : FromFriends) {
2641 ASSERT_EQ(Fr, FromFriend);
2642 ++FrN;
2643 }
2644 ASSERT_EQ(FrN, 1u);
2645
2646 Import(FromFriendF, Lang_CXX);
2647 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2648 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2649 ToTU, cxxRecordDecl(hasName("X")));
2650 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2651 auto ToFriends = ToClass->friends();
2652 FrN = 0;
2653 for (auto Fr : ToFriends) {
2654 EXPECT_EQ(Fr, ToFriend);
2655 ++FrN;
2656 }
2657 EXPECT_EQ(FrN, 1u);
2658}
2659
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002660AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2661 InnerMatcher) {
2662 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2663 return InnerMatcher.matches(*Typedef, Finder, Builder);
2664 return false;
2665}
2666
Gabor Marton19f4f392018-06-25 13:04:37 +00002667TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002668 CodeFiles Samples{{"main.c",
2669 {"void foo();"
2670 "void moo();"
2671 "int main() { foo(); moo(); }",
2672 Lang_C}},
2673
2674 {"foo.c",
2675 {"typedef enum { THING_VALUE } thing_t;"
2676 "void conflict(thing_t type);"
2677 "void foo() { (void)THING_VALUE; }"
2678 "void conflict(thing_t type) {}",
2679 Lang_C}},
2680
2681 {"moo.c",
2682 {"typedef enum { THING_VALUE } thing_t;"
2683 "void conflict(thing_t type);"
2684 "void moo() { conflict(THING_VALUE); }",
2685 Lang_C}}};
2686
2687 auto VerificationMatcher =
2688 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2689 hasTypedefForAnonDecl(hasName("thing_t")));
2690
2691 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2692 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2693
2694 testImportSequence(
2695 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2696 // Just check that there is only one enum decl in the result AST.
2697 "main.c", enumDecl(), VerificationMatcher);
2698
2699 // For different import order, result should be the same.
2700 testImportSequence(
2701 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2702 // Check that there is only one enum decl in the result AST.
2703 "main.c", enumDecl(), VerificationMatcher);
2704}
2705
Peter Szecsice7f3182018-05-07 12:08:27 +00002706const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2707 dependentScopeDeclRefExpr;
2708
Gabor Marton19f4f392018-06-25 13:04:37 +00002709TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002710 MatchVerifier<Decl> Verifier;
2711 testImport("template <typename T> struct S { static T foo; };"
2712 "template <typename T> void declToImport() {"
2713 " (void) S<T>::foo;"
2714 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002715 "void instantiate() { declToImport<int>(); }"
2716 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002717 Lang_CXX11, "", Lang_CXX11, Verifier,
2718 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2719 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2720
2721 testImport("template <typename T> struct S {"
2722 "template<typename S> static void foo(){};"
2723 "};"
2724 "template <typename T> void declToImport() {"
2725 " S<T>::template foo<T>();"
2726 "}"
2727 "void instantiate() { declToImport<int>(); }",
2728 Lang_CXX11, "", Lang_CXX11, Verifier,
2729 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2730 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2731}
2732
2733const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2734 dependentNameType;
2735
Gabor Marton19f4f392018-06-25 13:04:37 +00002736TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002737 MatchVerifier<Decl> Verifier;
2738 testImport("template <typename T> struct declToImport {"
2739 " typedef typename T::type dependent_name;"
2740 "};",
2741 Lang_CXX11, "", Lang_CXX11, Verifier,
2742 classTemplateDecl(has(
2743 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2744}
2745
Gabor Marton19f4f392018-06-25 13:04:37 +00002746TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002747 MatchVerifier<Decl> Verifier;
2748 testImport("struct S { template <typename T> void mem(); };"
2749 "template <typename U> void declToImport() {"
2750 " S s;"
2751 " s.mem<U>();"
2752 "}"
2753 "void instantiate() { declToImport<int>(); }",
2754 Lang_CXX11, "", Lang_CXX11, Verifier,
2755 functionTemplateDecl(has(functionDecl(has(
2756 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2757}
2758
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002759class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
Balazs Keri1d20cc22018-07-16 12:16:39 +00002760public:
2761 static constexpr auto DefaultCode = R"(
2762 struct A { int x; };
2763 void f() {
2764 A a;
2765 A a1(a);
2766 A a2(A{});
2767 a = a1;
2768 a = A{};
2769 a.~A();
2770 })";
2771
2772 template <typename MatcherType>
2773 void testImportOf(
2774 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2775 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
2776 }
2777
2778 template <typename MatcherType>
2779 void testNoImportOf(
2780 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2781 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
2782 }
2783
2784private:
2785 template <typename MatcherType>
2786 void test(const MatcherType &MethodMatcher,
2787 const char *Code, unsigned int ExpectedCount) {
2788 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
2789
2790 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
2791 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2792 ToTU, ClassMatcher);
2793
Balazs Keri2f752ba2018-07-16 14:05:18 +00002794 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002795
2796 {
2797 CXXMethodDecl *Method =
2798 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
2799 ToClass->removeDecl(Method);
Gabor Marton54058b52018-12-17 13:53:12 +00002800 LookupTablePtr->remove(Method);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002801 }
2802
Balazs Keri2f752ba2018-07-16 14:05:18 +00002803 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002804
2805 Decl *ImportedClass = nullptr;
2806 {
2807 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
2808 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2809 FromTU, ClassMatcher);
2810 ImportedClass = Import(FromClass, Lang_CXX11);
2811 }
2812
2813 EXPECT_EQ(ToClass, ImportedClass);
2814 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
2815 ExpectedCount);
2816 }
2817};
2818
2819TEST_P(ImportImplicitMethods, DefaultConstructor) {
2820 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
2821}
2822
2823TEST_P(ImportImplicitMethods, CopyConstructor) {
2824 testImportOf(cxxConstructorDecl(isCopyConstructor()));
2825}
2826
2827TEST_P(ImportImplicitMethods, MoveConstructor) {
2828 testImportOf(cxxConstructorDecl(isMoveConstructor()));
2829}
2830
2831TEST_P(ImportImplicitMethods, Destructor) {
2832 testImportOf(cxxDestructorDecl());
2833}
2834
2835TEST_P(ImportImplicitMethods, CopyAssignment) {
2836 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
2837}
2838
2839TEST_P(ImportImplicitMethods, MoveAssignment) {
2840 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
2841}
2842
2843TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
2844 auto Code = R"(
2845 struct A { A() { int x; } };
2846 )";
2847 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2848}
2849
2850TEST_P(ImportImplicitMethods, DoNotImportDefault) {
2851 auto Code = R"(
2852 struct A { A() = default; };
2853 )";
2854 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2855}
2856
2857TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
2858 auto Code = R"(
2859 struct A { A() = delete; };
2860 )";
2861 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2862}
2863
2864TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
2865 auto Code = R"(
2866 struct A { void f() { } };
2867 )";
2868 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
2869}
2870
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002871TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00002872 Decl *ToR1;
2873 {
2874 Decl *FromTU = getTuDecl(
2875 "struct A { };", Lang_CXX, "input0.cc");
2876 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2877 FromTU, cxxRecordDecl(hasName("A")));
2878
2879 ToR1 = Import(FromR, Lang_CXX);
2880 }
2881
2882 Decl *ToR2;
2883 {
2884 Decl *FromTU = getTuDecl(
2885 "struct A { };", Lang_CXX, "input1.cc");
2886 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2887 FromTU, cxxRecordDecl(hasName("A")));
2888
2889 ToR2 = Import(FromR, Lang_CXX);
2890 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00002891
Balazs Keric7797c42018-07-11 09:37:24 +00002892 EXPECT_EQ(ToR1, ToR2);
2893}
2894
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002895TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00002896 Decl *ToR1;
2897 {
2898 Decl *FromTU = getTuDecl(
2899 "struct A { int x; };", Lang_CXX, "input0.cc");
2900 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2901 FromTU, cxxRecordDecl(hasName("A")));
2902 ToR1 = Import(FromR, Lang_CXX);
2903 }
2904 Decl *ToR2;
2905 {
2906 Decl *FromTU = getTuDecl(
2907 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2908 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2909 FromTU, cxxRecordDecl(hasName("A")));
2910 ToR2 = Import(FromR, Lang_CXX);
2911 }
2912 EXPECT_NE(ToR1, ToR2);
2913}
2914
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002915TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00002916 Decl *ToF1;
2917 {
2918 Decl *FromTU = getTuDecl(
2919 "struct A { int x; };", Lang_CXX, "input0.cc");
2920 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2921 FromTU, fieldDecl(hasName("x")));
2922 ToF1 = Import(FromF, Lang_CXX);
2923 }
2924 Decl *ToF2;
2925 {
2926 Decl *FromTU = getTuDecl(
2927 "struct A { int x; };", Lang_CXX, "input1.cc");
2928 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2929 FromTU, fieldDecl(hasName("x")));
2930 ToF2 = Import(FromF, Lang_CXX);
2931 }
2932 EXPECT_EQ(ToF1, ToF2);
2933}
2934
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002935TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00002936 Decl *ToF1;
2937 {
2938 Decl *FromTU = getTuDecl(
2939 "struct A { int x; };", Lang_CXX, "input0.cc");
2940 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2941 FromTU, fieldDecl(hasName("x")));
2942 ToF1 = Import(FromF, Lang_CXX);
2943 }
2944 Decl *ToF2;
2945 {
2946 Decl *FromTU = getTuDecl(
2947 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2948 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2949 FromTU, fieldDecl(hasName("x")));
2950 ToF2 = Import(FromF, Lang_CXX);
2951 }
2952 EXPECT_NE(ToF1, ToF2);
2953}
2954
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002955TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00002956 Decl *ToM1;
2957 {
2958 Decl *FromTU = getTuDecl(
2959 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
2960 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2961 FromTU, functionDecl(hasName("x"), isDefinition()));
2962 ToM1 = Import(FromM, Lang_CXX);
2963 }
2964 Decl *ToM2;
2965 {
2966 Decl *FromTU = getTuDecl(
2967 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
2968 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2969 FromTU, functionDecl(hasName("x"), isDefinition()));
2970 ToM2 = Import(FromM, Lang_CXX);
2971 }
2972 EXPECT_EQ(ToM1, ToM2);
2973}
2974
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002975TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00002976 Decl *ToM1;
2977 {
2978 Decl *FromTU = getTuDecl(
2979 "struct A { void x(); }; void A::x() { }",
2980 Lang_CXX, "input0.cc");
2981 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2982 FromTU, functionDecl(hasName("x"), isDefinition()));
2983 ToM1 = Import(FromM, Lang_CXX);
2984 }
2985 Decl *ToM2;
2986 {
2987 Decl *FromTU = getTuDecl(
2988 "struct A { void x() const; }; void A::x() const { }",
2989 Lang_CXX, "input1.cc");
2990 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2991 FromTU, functionDecl(hasName("x"), isDefinition()));
2992 ToM2 = Import(FromM, Lang_CXX);
2993 }
2994 EXPECT_NE(ToM1, ToM2);
2995}
2996
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002997TEST_P(ASTImporterOptionSpecificTestBase,
2998 ImportUnnamedStructsWithRecursingField) {
Gabor Martonf086fa82018-07-17 12:06:36 +00002999 Decl *FromTU = getTuDecl(
3000 R"(
3001 struct A {
3002 struct {
3003 struct A *next;
3004 } entry0;
3005 struct {
3006 struct A *next;
3007 } entry1;
3008 };
3009 )",
3010 Lang_C, "input0.cc");
3011 auto *From =
3012 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3013
3014 Import(From, Lang_C);
3015
3016 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3017 auto *Entry0 =
3018 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3019 auto *Entry1 =
3020 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3021 auto *R0 = getRecordDecl(Entry0);
3022 auto *R1 = getRecordDecl(Entry1);
3023 EXPECT_NE(R0, R1);
3024 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3025 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3026 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3027 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3028}
3029
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003030TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
Balazs Keri2544b4b2018-08-08 09:40:57 +00003031 Decl *FromTU = getTuDecl(
3032 R"(
3033 void f(int X, int Y, bool Z) {
3034 (void)[X, Y, Z] { (void)Z; };
3035 }
3036 )",
3037 Lang_CXX11, "input0.cc");
3038 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3039 FromTU, functionDecl(hasName("f")));
3040 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3041 EXPECT_TRUE(ToF);
3042
3043 CXXRecordDecl *FromLambda =
3044 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3045 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3046
3047 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3048 EXPECT_TRUE(ToLambda);
3049
3050 // Check if the fields of the lambda class are imported in correct order.
3051 unsigned FromIndex = 0u;
3052 for (auto *FromField : FromLambda->fields()) {
3053 ASSERT_FALSE(FromField->getDeclName());
3054 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3055 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00003056 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3057 EXPECT_TRUE(ToIndex);
3058 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00003059 ++FromIndex;
3060 }
3061
3062 EXPECT_EQ(FromIndex, 3u);
3063}
3064
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003065TEST_P(ASTImporterOptionSpecificTestBase,
3066 MergeFieldDeclsOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003067 std::string ClassTemplate =
3068 R"(
3069 template <typename T>
3070 struct X {
3071 int a{0}; // FieldDecl with InitListExpr
3072 X(char) : a(3) {} // (1)
3073 X(int) {} // (2)
3074 };
3075 )";
3076 Decl *ToTU = getToTuDecl(ClassTemplate +
3077 R"(
3078 void foo() {
3079 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3080 X<char> xc('c');
3081 }
3082 )", Lang_CXX11);
3083 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3084 ToTU, classTemplateSpecializationDecl(hasName("X")));
3085 // FieldDecl without InitlistExpr:
3086 auto *ToField = *ToSpec->field_begin();
3087 ASSERT_TRUE(ToField);
3088 ASSERT_FALSE(ToField->getInClassInitializer());
3089 Decl *FromTU = getTuDecl(ClassTemplate +
3090 R"(
3091 void bar() {
3092 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3093 X<char> xc(1);
3094 }
3095 )", Lang_CXX11);
3096 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3097 FromTU, classTemplateSpecializationDecl(hasName("X")));
3098 // FieldDecl with InitlistExpr:
3099 auto *FromField = *FromSpec->field_begin();
3100 ASSERT_TRUE(FromField);
3101 ASSERT_TRUE(FromField->getInClassInitializer());
3102
3103 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3104 ASSERT_TRUE(ImportedSpec);
3105 EXPECT_EQ(ImportedSpec, ToSpec);
3106 // After the import, the FieldDecl has to be merged, thus it should have the
3107 // InitListExpr.
3108 EXPECT_TRUE(ToField->getInClassInitializer());
3109}
3110
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003111TEST_P(ASTImporterOptionSpecificTestBase,
3112 MergeFunctionOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003113 std::string ClassTemplate =
3114 R"(
3115 template <typename T>
3116 struct X {
3117 void f() {}
3118 void g() {}
3119 };
3120 )";
3121 Decl *ToTU = getToTuDecl(ClassTemplate +
3122 R"(
3123 void foo() {
3124 X<char> x;
3125 x.f();
3126 }
3127 )", Lang_CXX11);
3128 Decl *FromTU = getTuDecl(ClassTemplate +
3129 R"(
3130 void bar() {
3131 X<char> x;
3132 x.g();
3133 }
3134 )", Lang_CXX11);
3135 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3136 FromTU, classTemplateSpecializationDecl(hasName("X")));
3137 auto FunPattern = functionDecl(hasName("g"),
3138 hasParent(classTemplateSpecializationDecl()));
3139 auto *FromFun =
3140 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3141 auto *ToFun =
3142 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3143 ASSERT_TRUE(FromFun->hasBody());
3144 ASSERT_FALSE(ToFun->hasBody());
3145 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3146 ASSERT_TRUE(ImportedSpec);
3147 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3148 ToTU, classTemplateSpecializationDecl(hasName("X")));
3149 EXPECT_EQ(ImportedSpec, ToSpec);
3150 EXPECT_TRUE(ToFun->hasBody());
3151}
3152
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003153TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003154 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3155 std::string ClassTemplate =
3156 R"(
3157 template <typename T>
3158 struct X {};
3159 )";
3160 Decl *ToTU = getToTuDecl(ClassTemplate +
3161 R"(
3162 template <>
3163 struct X<char> {
3164 int a;
3165 };
3166 void foo() {
3167 X<char> x;
3168 }
3169 )",
3170 Lang_CXX11);
3171 Decl *FromTU = getTuDecl(ClassTemplate +
3172 R"(
3173 template <>
3174 struct X<char> {
3175 int b;
3176 };
3177 void foo() {
3178 X<char> x;
3179 }
3180 )",
3181 Lang_CXX11);
3182 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3183 FromTU, classTemplateSpecializationDecl(hasName("X")));
3184 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3185
3186 // We expect one (ODR) warning during the import.
3187 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3188
3189 // The second specialization is different from the first, thus it violates
3190 // ODR, consequently we expect to keep the first specialization only, which is
3191 // already in the "To" context.
Gabor Marton7f8c4002019-03-19 13:34:10 +00003192 EXPECT_FALSE(ImportedSpec);
3193 EXPECT_EQ(1u,
3194 DeclCounter<ClassTemplateSpecializationDecl>().match(
3195 ToTU, classTemplateSpecializationDecl(hasName("X"))));
Gabor Marton42e15de2018-08-22 11:52:14 +00003196}
3197
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003198TEST_P(ASTImporterOptionSpecificTestBase,
3199 MergeCtorOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003200 std::string ClassTemplate =
3201 R"(
3202 template <typename T>
3203 struct X {
3204 X(char) {}
3205 X(int) {}
3206 };
3207 )";
3208 Decl *ToTU = getToTuDecl(ClassTemplate +
3209 R"(
3210 void foo() {
3211 X<char> x('c');
3212 }
3213 )", Lang_CXX11);
3214 Decl *FromTU = getTuDecl(ClassTemplate +
3215 R"(
3216 void bar() {
3217 X<char> x(1);
3218 }
3219 )", Lang_CXX11);
3220 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3221 FromTU, classTemplateSpecializationDecl(hasName("X")));
3222 // Match the void(int) ctor.
3223 auto CtorPattern =
3224 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3225 hasParent(classTemplateSpecializationDecl()));
3226 auto *FromCtor =
3227 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3228 auto *ToCtor =
3229 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3230 ASSERT_TRUE(FromCtor->hasBody());
3231 ASSERT_FALSE(ToCtor->hasBody());
3232 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3233 ASSERT_TRUE(ImportedSpec);
3234 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3235 ToTU, classTemplateSpecializationDecl(hasName("X")));
3236 EXPECT_EQ(ImportedSpec, ToSpec);
3237 EXPECT_TRUE(ToCtor->hasBody());
3238}
3239
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003240TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003241 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3242 auto Code =
3243 R"(
3244 // primary template
3245 template<class T1, class T2, int I>
3246 class A {};
3247
3248 // partial specialization
3249 template<class T, int I>
3250 class A<T, T*, I> {};
3251 )";
3252 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3253 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3254 auto *FromSpec =
3255 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3256 FromTU, classTemplatePartialSpecializationDecl());
3257 auto *ToSpec =
3258 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3259 ToTU, classTemplatePartialSpecializationDecl());
3260
3261 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3262 EXPECT_EQ(ImportedSpec, ToSpec);
3263 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3264 ToTU, classTemplatePartialSpecializationDecl()));
3265}
3266
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003267TEST_P(ASTImporterOptionSpecificTestBase,
3268 ClassTemplateSpecializationsShouldNotBeDuplicated) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003269 auto Code =
3270 R"(
3271 // primary template
3272 template<class T1, class T2, int I>
3273 class A {};
3274
3275 // full specialization
3276 template<>
3277 class A<int, int, 1> {};
3278 )";
3279 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3280 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3281 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3282 FromTU, classTemplateSpecializationDecl());
3283 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3284 ToTU, classTemplateSpecializationDecl());
3285
3286 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3287 EXPECT_EQ(ImportedSpec, ToSpec);
3288 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3289 ToTU, classTemplateSpecializationDecl()));
3290}
3291
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003292TEST_P(ASTImporterOptionSpecificTestBase,
3293 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003294 std::string PrimaryTemplate =
3295 R"(
3296 template<class T1, class T2, int I>
3297 class A {};
3298 )";
3299 auto PartialSpec =
3300 R"(
3301 template<class T, int I>
3302 class A<T, T*, I> {};
3303 )";
3304 auto FullSpec =
3305 R"(
3306 template<>
3307 class A<int, int, 1> {};
3308 )";
3309 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3310 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3311 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3312 FromTU, classTemplateSpecializationDecl());
3313
3314 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3315 EXPECT_TRUE(ImportedSpec);
3316 // Check the number of partial specializations.
3317 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3318 ToTU, classTemplatePartialSpecializationDecl()));
3319 // Check the number of full specializations.
3320 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3321 ToTU, classTemplateSpecializationDecl(
3322 unless(classTemplatePartialSpecializationDecl()))));
3323}
3324
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003325TEST_P(ASTImporterOptionSpecificTestBase,
3326 InitListExprValueKindShouldBeImported) {
Gabor Martona20ce602018-09-03 13:10:53 +00003327 Decl *TU = getTuDecl(
3328 R"(
3329 const int &init();
3330 void foo() { const int &a{init()}; }
3331 )", Lang_CXX11, "input0.cc");
3332 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3333 ASSERT_TRUE(FromD->getAnyInitializer());
3334 auto *InitExpr = FromD->getAnyInitializer();
3335 ASSERT_TRUE(InitExpr);
3336 ASSERT_TRUE(InitExpr->isGLValue());
3337
3338 auto *ToD = Import(FromD, Lang_CXX11);
3339 EXPECT_TRUE(ToD);
3340 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3341 EXPECT_TRUE(ToInitExpr);
3342 EXPECT_TRUE(ToInitExpr->isGLValue());
3343}
3344
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003345struct ImportVariables : ASTImporterOptionSpecificTestBase {};
Gabor Martonac3a5d62018-09-17 12:04:52 +00003346
3347TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3348 Decl *FromTU = getTuDecl(
3349 R"(
3350 struct A {
3351 static const int a = 1 + 2;
3352 };
3353 const int A::a;
3354 )", Lang_CXX, "input1.cc");
3355
3356 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3357 FromTU, varDecl(hasName("a"))); // Decl with init
3358 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3359 FromTU, varDecl(hasName("a"))); // Decl with definition
3360 ASSERT_NE(FromDWithInit, FromDWithDef);
3361 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3362
3363 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3364 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3365 ASSERT_TRUE(ToD0);
3366 ASSERT_TRUE(ToD1);
3367 EXPECT_NE(ToD0, ToD1);
3368 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3369}
3370
3371TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3372 auto StructA =
3373 R"(
3374 struct A {
3375 static const int a = 1 + 2;
3376 };
3377 )";
3378 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3379 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3380 "input1.cc");
3381
3382 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3383 FromTU, varDecl(hasName("a"))); // Decl with init
3384 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3385 FromTU, varDecl(hasName("a"))); // Decl with definition
3386 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3387 ASSERT_TRUE(FromDWithInit->getInit());
3388 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3389 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3390 ASSERT_FALSE(FromDWithDef->getInit());
3391
3392 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3393 ToTU, varDecl(hasName("a"))); // Decl with init
3394 ASSERT_TRUE(ToD->getInit());
3395 ASSERT_FALSE(ToD->getDefinition());
3396
3397 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3398 EXPECT_TRUE(ImportedD->getAnyInitializer());
3399 EXPECT_TRUE(ImportedD->getDefinition());
3400}
3401
3402TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3403 auto StructA =
3404 R"(
3405 struct A {
3406 static const int a;
3407 };
3408 )";
3409 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3410 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3411 Lang_CXX, "input1.cc");
3412
3413 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3414 FromTU, varDecl(hasName("a")));
3415 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3416 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3417 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3418 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3419 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3420 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3421 ASSERT_TRUE(FromDWithDef->getInit());
3422
3423 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3424 ToTU, varDecl(hasName("a")));
3425 ASSERT_FALSE(ToD->getInit());
3426 ASSERT_FALSE(ToD->getDefinition());
3427
3428 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3429 EXPECT_TRUE(ImportedD->getAnyInitializer());
3430 EXPECT_TRUE(ImportedD->getDefinition());
3431}
3432
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003433struct ImportClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003434
Gabor Marton54058b52018-12-17 13:53:12 +00003435TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3436 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
3437 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3438 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3439 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3440 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3441
3442 Decl *ImportedDef = Import(FromDef, Lang_C);
3443
3444 EXPECT_NE(ImportedDef, ToProto);
3445 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3446 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3447 EXPECT_TRUE(ImportedDef == ToDef);
3448 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3449 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3450 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3451}
3452
3453TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3454 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
3455 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
3456 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3457 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3458 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3459
3460 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3461
3462 EXPECT_NE(ImportedDef, ToProto);
3463 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3464 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3465 EXPECT_TRUE(ImportedDef == ToDef);
3466 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3467 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3468 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3469}
3470
3471TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3472 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
3473 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3474 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3475 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3476 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3477
3478 Decl *ImportedProto = Import(FromProto, Lang_C);
3479 Decl *ImportedDef = Import(FromDef, Lang_C);
3480 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3481
3482 EXPECT_NE(ImportedDef, ImportedProto);
3483 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3484 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3485 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3486 EXPECT_TRUE(ImportedDef == ToDef);
3487 EXPECT_TRUE(ImportedProto == ToProto);
3488 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3489 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3490 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3491}
3492
Gabor Marton7df342a2018-12-17 12:42:12 +00003493
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003494struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003495
3496TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
3497 Decl *FromTU = getTuDecl(
3498 R"(
3499 class A {
3500 template <int I> class F {};
3501 class X {
3502 template <int I> friend class F;
3503 };
3504 };
3505 )",
3506 Lang_CXX, "input0.cc");
3507
3508 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3509 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
3510 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
3511 FromTU, cxxRecordDecl(hasName("F")));
3512
3513 ASSERT_TRUE(FromClass);
3514 ASSERT_TRUE(FromFriendClass);
3515 ASSERT_NE(FromClass, FromFriendClass);
3516 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
3517 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
3518 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3519 FromClass->getDescribedClassTemplate());
3520
3521 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
3522 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
3523
3524 EXPECT_TRUE(ToClass);
3525 EXPECT_TRUE(ToFriendClass);
3526 EXPECT_NE(ToClass, ToFriendClass);
3527 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
3528 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
3529 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3530 ToClass->getDescribedClassTemplate());
3531}
3532
3533TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
3534 Decl *FromTu = getTuDecl(
3535 R"(
3536 class declToImport {
3537 friend class declToImport;
3538 };
3539 )",
3540 Lang_CXX, "input.cc");
3541
3542 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
3543 FromTu, cxxRecordDecl(hasName("declToImport")));
3544 auto *ToD = Import(FromD, Lang_CXX);
3545 auto Pattern = cxxRecordDecl(has(friendDecl()));
3546 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3547 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3548}
3549
3550TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
3551 Decl *FromTu = getTuDecl(
3552 R"(
3553 template<class A> class declToImport {
3554 template<class A1> friend class declToImport;
3555 };
3556 )",
3557 Lang_CXX, "input.cc");
3558
3559 auto *FromD =
3560 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
3561 auto *ToD = Import(FromD, Lang_CXX);
3562
3563 auto Pattern = classTemplateDecl(
3564 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
3565 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3566 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3567
3568 auto *Class =
3569 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
3570 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
3571 EXPECT_NE(Friend->getFriendDecl(), Class);
3572 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
3573}
3574
3575TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
3576 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
3577
3578 ClassTemplateSpecializationDecl *Imported1;
3579 {
3580 Decl *FromTU = getTuDecl("template<class T> class X;"
3581 "struct Y { friend class X<int>; };",
3582 Lang_CXX, "input0.cc");
3583 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3584 FromTU, Pattern);
3585
3586 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3587 }
3588 ClassTemplateSpecializationDecl *Imported2;
3589 {
3590 Decl *FromTU = getTuDecl("template<class T> class X;"
3591 "template<> class X<int>{};"
3592 "struct Z { friend class X<int>; };",
3593 Lang_CXX, "input1.cc");
3594 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3595 FromTU, Pattern);
3596
3597 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3598 }
3599
3600 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3601 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
3602 2u);
3603 ASSERT_TRUE(Imported2->getPreviousDecl());
3604 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
3605}
3606
3607TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
3608 Decl *FromTU0 = getTuDecl(
3609 R"(
3610 class X {
3611 class Y;
3612 };
3613 class X::Y {
3614 template <typename T>
3615 friend class F; // The decl context of F is the global namespace.
3616 };
3617 )",
3618 Lang_CXX, "input0.cc");
3619 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3620 FromTU0, classTemplateDecl(hasName("F")));
3621 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3622 Decl *FromTU1 = getTuDecl(
3623 R"(
3624 template <typename T>
3625 class F {};
3626 )",
3627 Lang_CXX, "input1.cc");
3628 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3629 FromTU1, classTemplateDecl(hasName("F")));
3630 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3631 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
3632 Imported1->getTemplatedDecl()->getTypeForDecl());
3633}
3634
3635TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
3636 Decl *From, *To;
3637 std::tie(From, To) =
3638 getImportedDecl("class declToImport {};", Lang_CXX,
3639 "class Y { friend class declToImport; };", Lang_CXX);
3640 auto *Imported = cast<CXXRecordDecl>(To);
3641
3642 EXPECT_TRUE(Imported->getPreviousDecl());
3643}
3644
3645TEST_P(ImportFriendClasses,
3646 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
3647 Decl *ToTU = getToTuDecl(
3648 R"(
3649 class X {
3650 class Y;
3651 };
3652 class X::Y {
3653 template <typename T>
3654 friend class F; // The decl context of F is the global namespace.
3655 };
3656 )",
3657 Lang_CXX);
3658 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
3659 ToTU, classTemplateDecl(hasName("F")));
3660 Decl *FromTU = getTuDecl(
3661 R"(
3662 template <typename T>
3663 class F {};
3664 )",
3665 Lang_CXX, "input0.cc");
3666 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3667 FromTU, classTemplateDecl(hasName("F")));
3668 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3669 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3670 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
3671 EXPECT_EQ(ToDecl->getTemplatedDecl(),
3672 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3673}
3674
3675TEST_P(ImportFriendClasses,
3676 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
3677 Decl *FromTU0 = getTuDecl(
3678 R"(
3679 class X {
3680 class Y;
3681 };
3682 class X::Y {
3683 template <typename T>
3684 friend class F; // The decl context of F is the global namespace.
3685 };
3686 )",
3687 Lang_CXX, "input0.cc");
3688 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3689 FromTU0, classTemplateDecl(hasName("F")));
3690 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3691 Decl *FromTU1 = getTuDecl(
3692 R"(
3693 template <typename T>
3694 class F {};
3695 )",
3696 Lang_CXX, "input1.cc");
3697 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3698 FromTU1, classTemplateDecl(hasName("F")));
3699 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3700 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3701 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3702 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
3703 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3704}
3705
3706TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
3707 Decl *FromTU0 = getTuDecl(
3708 R"(
3709 class X {
3710 class Y;
3711 };
3712 class X::Y {
3713 friend class F; // The decl context of F is the global namespace.
3714 };
3715 )",
3716 Lang_CXX, "input0.cc");
3717 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
3718 QualType FT = Friend->getFriendType()->getType();
3719 FT = FromTU0->getASTContext().getCanonicalType(FT);
3720 auto *Fwd = cast<TagType>(FT)->getDecl();
3721 auto *ImportedFwd = Import(Fwd, Lang_CXX);
3722 Decl *FromTU1 = getTuDecl(
3723 R"(
3724 class F {};
3725 )",
3726 Lang_CXX, "input1.cc");
3727 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
3728 FromTU1, cxxRecordDecl(hasName("F")));
3729 auto *ImportedDef = Import(Definition, Lang_CXX);
3730 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3731 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3732}
3733
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003734TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Gabor Marton54058b52018-12-17 13:53:12 +00003735 auto *Code = R"(
3736 template <class T>
3737 struct X {
3738 friend void foo(){}
3739 };
3740 )";
3741 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
3742 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
3743 ToTU, functionDecl(hasName("foo")));
3744
3745 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
3746 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
3747 FromTU, functionDecl(hasName("foo")));
3748 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
3749 EXPECT_EQ(ImportedFoo, ToFoo);
3750}
3751
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003752struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton61d862a2018-05-18 09:08:47 +00003753
3754TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
3755 Decl *TU = getTuDecl(
3756 R"(
3757 namespace NS {
3758
3759 template <typename T>
3760 struct S {};
3761 template struct S<int>;
3762
3763 inline namespace INS {
3764 template <typename T>
3765 struct S {};
3766 template struct S<int>;
3767 }
3768
3769 }
3770 )", Lang_CXX11, "input0.cc");
3771 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
3772 TU, namespaceDecl());
3773 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3774 TU, classTemplateSpecializationDecl());
3775 ASSERT_TRUE(NS->containsDecl(Spec));
3776
3777 NS->removeDecl(Spec);
3778 EXPECT_FALSE(NS->containsDecl(Spec));
3779}
3780
Gabor Marton7df342a2018-12-17 12:42:12 +00003781TEST_P(DeclContextTest,
3782 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
3783 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
3784 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
3785 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
3786
3787 // Investigate the list.
3788 auto *DC = A0->getDeclContext();
3789 ASSERT_TRUE(DC->containsDecl(A0));
3790 ASSERT_TRUE(DC->containsDecl(A1));
3791
3792 // Investigate the lookup table.
3793 auto *Map = DC->getLookupPtr();
3794 ASSERT_TRUE(Map);
3795 auto I = Map->find(A0->getDeclName());
3796 ASSERT_NE(I, Map->end());
3797 StoredDeclsList &L = I->second;
3798 // The lookup table contains the most recent decl of A.
3799 ASSERT_NE(L.getAsDecl(), A0);
3800 ASSERT_EQ(L.getAsDecl(), A1);
3801
3802 ASSERT_TRUE(L.getAsDecl());
3803 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
3804 // The point here is to have a Vec with only one element, which is not the
3805 // one we are going to delete from the DC later.
3806 L.setHasExternalDecls();
3807 ASSERT_TRUE(L.getAsVector());
3808 ASSERT_EQ(1u, L.getAsVector()->size());
3809
3810 // This asserts in the old implementation.
3811 DC->removeDecl(A0);
3812 EXPECT_FALSE(DC->containsDecl(A0));
3813}
3814
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003815struct ImportFunctionTemplateSpecializations
3816 : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +00003817
3818TEST_P(ImportFunctionTemplateSpecializations,
3819 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
3820
3821 Decl *FromTU = getTuDecl(
3822 R"(
3823 template<class T>
3824 int f() { return 0; }
3825 void foo() { f<int>(); }
3826 )",
3827 Lang_CXX, "input0.cc");
3828
3829 // Check that the function template instantiation is NOT the child of the TU.
3830 auto Pattern = translationUnitDecl(
3831 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
3832 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3833
3834 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
3835 FromTU, functionDecl(hasName("foo")));
3836 ASSERT_TRUE(Import(Foo, Lang_CXX));
3837
3838 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3839 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3840}
3841
3842TEST_P(ImportFunctionTemplateSpecializations,
3843 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
3844
3845 Decl *FromTU = getTuDecl(
3846 R"(
3847 template<class T>
3848 int f() { return 0; }
3849 template int f<int>();
3850 )",
3851 Lang_CXX, "input0.cc");
3852
3853 // Check that the function template instantiation is NOT the child of the TU.
3854 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
3855 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
3856 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3857
3858 ASSERT_TRUE(
3859 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
3860
3861 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3862 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3863}
3864
3865TEST_P(ImportFunctionTemplateSpecializations,
3866 TUshouldContainFunctionTemplateSpecialization) {
3867
3868 Decl *FromTU = getTuDecl(
3869 R"(
3870 template<class T>
3871 int f() { return 0; }
3872 template <> int f<int>() { return 4; }
3873 )",
3874 Lang_CXX, "input0.cc");
3875
3876 // Check that the function template specialization is the child of the TU.
3877 auto Specialization =
3878 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3879 auto Pattern = translationUnitDecl(has(Specialization));
3880 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3881
3882 ASSERT_TRUE(
3883 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
3884
3885 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3886 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3887}
3888
3889TEST_P(ImportFunctionTemplateSpecializations,
3890 FunctionTemplateSpecializationRedeclChain) {
3891
3892 Decl *FromTU = getTuDecl(
3893 R"(
3894 template<class T>
3895 int f() { return 0; }
3896 template <> int f<int>() { return 4; }
3897 )",
3898 Lang_CXX, "input0.cc");
3899
3900 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
3901 hasParent(translationUnitDecl()));
3902 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
3903 {
3904 auto *TU = FromTU;
3905 auto *SpecD = FromSpecD;
3906 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
3907 TU, functionTemplateDecl());
3908 auto *FirstSpecD = *(TemplateD->spec_begin());
3909 ASSERT_EQ(SpecD, FirstSpecD);
3910 ASSERT_TRUE(SpecD->getPreviousDecl());
3911 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
3912 ->doesThisDeclarationHaveABody());
3913 }
3914
3915 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
3916
3917 {
3918 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
3919 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
3920 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
3921 TU, functionTemplateDecl());
3922 auto *FirstSpecD = *(TemplateD->spec_begin());
3923 EXPECT_EQ(SpecD, FirstSpecD);
3924 ASSERT_TRUE(SpecD->getPreviousDecl());
3925 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
3926 ->doesThisDeclarationHaveABody());
3927 }
3928}
3929
3930TEST_P(ImportFunctionTemplateSpecializations,
3931 MatchNumberOfFunctionTemplateSpecializations) {
3932
3933 Decl *FromTU = getTuDecl(
3934 R"(
3935 template <typename T> constexpr int f() { return 0; }
3936 template <> constexpr int f<int>() { return 4; }
3937 void foo() {
3938 static_assert(f<char>() == 0, "");
3939 static_assert(f<int>() == 4, "");
3940 }
3941 )",
3942 Lang_CXX11, "input0.cc");
3943 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
3944 FromTU, functionDecl(hasName("foo")));
3945
3946 Import(FromD, Lang_CXX11);
3947 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3948 EXPECT_EQ(
3949 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
3950 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
3951}
3952
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003953TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton17d39672018-11-26 15:54:08 +00003954 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
3955 {
3956 Decl *FromTU = getTuDecl(
3957 R"(
3958 template <typename T>
3959 struct B;
3960 )",
3961 Lang_CXX, "input0.cc");
3962 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
3963 FromTU, classTemplateDecl(hasName("B")));
3964
3965 Import(FromD, Lang_CXX);
3966 }
3967
3968 {
3969 Decl *FromTU = getTuDecl(
3970 R"(
3971 template <typename T>
3972 struct B {
3973 void f();
3974 B* b;
3975 };
3976 )",
3977 Lang_CXX, "input1.cc");
3978 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
3979 FromTU, functionDecl(hasName("f")));
3980 Import(FromD, Lang_CXX);
3981 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
3982 FromTU, classTemplateDecl(hasName("B")));
3983 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
3984 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
3985
3986 // We expect no (ODR) warning during the import.
3987 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3988 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3989 }
3990}
3991
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003992TEST_P(ASTImporterOptionSpecificTestBase,
3993 ImportingTypedefShouldImportTheCompleteType) {
Gabor Martonb93baf62018-11-27 09:51:36 +00003994 // We already have an incomplete underlying type in the "To" context.
3995 auto Code =
3996 R"(
3997 template <typename T>
3998 struct S {
3999 void foo();
4000 };
4001 using U = S<int>;
4002 )";
4003 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
4004 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
4005 typedefNameDecl(hasName("U")));
4006 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
4007
4008 // The "From" context has the same typedef, but the underlying type is
4009 // complete this time.
4010 Decl *FromTU = getTuDecl(std::string(Code) +
4011 R"(
4012 void foo(U* u) {
4013 u->foo();
4014 }
4015 )", Lang_CXX11);
4016 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4017 typedefNameDecl(hasName("U")));
4018 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4019
4020 // The imported type should be complete.
4021 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4022 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4023}
4024
Balazs Keri1efc9742019-05-07 10:55:11 +00004025TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) {
4026 auto Code =
4027 R"(
4028 template<class T>
4029 int f() { return 0; }
4030 template <> int f<int>() { return 4; }
4031 )";
4032
4033 Decl *FromTU = getTuDecl(Code, Lang_CXX);
4034 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU,
4035 functionDecl(hasName("f"), isExplicitTemplateSpecialization()));
Balazs Kerib7d8cff2019-05-07 14:53:04 +00004036 ASSERT_EQ(FromD->getNumTemplateParameterLists(), 1u);
Balazs Keri1efc9742019-05-07 10:55:11 +00004037
4038 auto *ToD = Import(FromD, Lang_CXX);
4039 // The template parameter list should exist.
Balazs Kerib7d8cff2019-05-07 14:53:04 +00004040 EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u);
Balazs Keri1efc9742019-05-07 10:55:11 +00004041}
4042
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004043struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton54058b52018-12-17 13:53:12 +00004044
4045TEST_P(ASTImporterLookupTableTest, OneDecl) {
4046 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
4047 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4048 ASTImporterLookupTable LT(*ToTU);
4049 auto Res = LT.lookup(ToTU, D->getDeclName());
4050 ASSERT_EQ(Res.size(), 1u);
4051 EXPECT_EQ(*Res.begin(), D);
4052}
4053
4054static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4055 for (Decl *D : DC->decls()) {
4056 if (auto *ND = dyn_cast<NamedDecl>(D))
4057 if (ND->getDeclName() == Name)
4058 return ND;
4059 }
4060 return nullptr;
Martin Storsjo85833392018-12-18 08:36:16 +00004061}
Gabor Marton54058b52018-12-17 13:53:12 +00004062
4063TEST_P(ASTImporterLookupTableTest,
4064 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4065 auto *Code = R"(
4066 template <class T>
4067 struct X {
4068 friend void foo(){}
4069 };
4070 )";
4071 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4072 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
4073 ToTU, classTemplateDecl(hasName("X")));
4074 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4075 ToTU, functionDecl(hasName("foo")));
4076 DeclContext *FooDC = Foo->getDeclContext();
4077 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4078 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
4079 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4080 DeclarationName FooName = Foo->getDeclName();
4081
4082 // Cannot find in the LookupTable of its DC (TUDecl)
4083 SmallVector<NamedDecl *, 2> FoundDecls;
4084 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4085 EXPECT_EQ(FoundDecls.size(), 0u);
4086
4087 // Cannot find in the LookupTable of its LexicalDC (X)
4088 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4089 EXPECT_EQ(FoundDecls.size(), 0u);
4090
4091 // Can't find in the list of Decls of the DC.
4092 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4093
4094 // Can't find in the list of Decls of the LexicalDC
4095 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
4096
4097 // ASTImporter specific lookup finds it.
4098 ASTImporterLookupTable LT(*ToTU);
4099 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4100 ASSERT_EQ(Res.size(), 1u);
4101 EXPECT_EQ(*Res.begin(), Foo);
4102}
4103
4104TEST_P(ASTImporterLookupTableTest,
4105 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
4106 TranslationUnitDecl *ToTU =
4107 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
4108 auto *Foo =
4109 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
4110 auto *A =
4111 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4112 DeclContext *FooDC = Foo->getDeclContext();
4113 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4114 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
4115 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4116 DeclarationName FooName = Foo->getDeclName();
4117
4118 // Cannot find in the LookupTable of its DC (TUDecl).
4119 SmallVector<NamedDecl *, 2> FoundDecls;
4120 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4121 EXPECT_EQ(FoundDecls.size(), 0u);
4122
4123 // Cannot find in the LookupTable of its LexicalDC (A).
4124 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4125 EXPECT_EQ(FoundDecls.size(), 0u);
4126
4127 // Can't find in the list of Decls of the DC.
4128 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4129
4130 // Can find in the list of Decls of the LexicalDC.
4131 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
4132
4133 // ASTImporter specific lookup finds it.
4134 ASTImporterLookupTable LT(*ToTU);
4135 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4136 ASSERT_EQ(Res.size(), 1u);
4137 EXPECT_EQ(*Res.begin(), Foo);
4138}
4139
4140TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
4141 TranslationUnitDecl *ToTU =
4142 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
4143 DeclarationName VName = FirstDeclMatcher<VarDecl>()
4144 .match(ToTU, varDecl(hasName("V")))
4145 ->getDeclName();
4146 auto *A =
4147 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4148 auto *B =
4149 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
4150
4151 ASTImporterLookupTable LT(*ToTU);
4152
4153 auto Res = LT.lookup(cast<DeclContext>(A), VName);
4154 ASSERT_EQ(Res.size(), 1u);
4155 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4156 ToTU, fieldDecl(hasName("V"),
4157 hasParent(recordDecl(hasName("A"))))));
4158 Res = LT.lookup(cast<DeclContext>(B), VName);
4159 ASSERT_EQ(Res.size(), 1u);
4160 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4161 ToTU, fieldDecl(hasName("V"),
4162 hasParent(recordDecl(hasName("B"))))));
4163 Res = LT.lookup(ToTU, VName);
4164 ASSERT_EQ(Res.size(), 1u);
4165 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
4166 ToTU, varDecl(hasName("V"),
4167 hasParent(translationUnitDecl()))));
4168}
4169
4170TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
4171 TranslationUnitDecl *ToTU = getToTuDecl(
4172 R"(
4173 void foo();
4174 void foo(int);
4175 void foo(int, int);
4176 )",
4177 Lang_CXX);
4178
4179 ASTImporterLookupTable LT(*ToTU);
4180 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4181 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4182 DeclarationName Name = F0->getDeclName();
4183 auto Res = LT.lookup(ToTU, Name);
4184 EXPECT_EQ(Res.size(), 3u);
4185 EXPECT_EQ(Res.count(F0), 1u);
4186 EXPECT_EQ(Res.count(F2), 1u);
4187}
4188
Gabor Martona9cab312019-02-08 09:19:34 +00004189TEST_P(ASTImporterLookupTableTest,
4190 DifferentOperatorsShouldHaveDifferentResultSet) {
4191 TranslationUnitDecl *ToTU = getToTuDecl(
4192 R"(
4193 struct X{};
4194 void operator+(X, X);
4195 void operator-(X, X);
4196 )",
4197 Lang_CXX);
4198
4199 ASTImporterLookupTable LT(*ToTU);
4200 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
4201 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4202 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
4203 ToTU, functionDecl(hasOverloadedOperatorName("-")));
4204 DeclarationName NamePlus = FPlus->getDeclName();
4205 auto ResPlus = LT.lookup(ToTU, NamePlus);
4206 EXPECT_EQ(ResPlus.size(), 1u);
4207 EXPECT_EQ(ResPlus.count(FPlus), 1u);
4208 EXPECT_EQ(ResPlus.count(FMinus), 0u);
4209 DeclarationName NameMinus = FMinus->getDeclName();
4210 auto ResMinus = LT.lookup(ToTU, NameMinus);
4211 EXPECT_EQ(ResMinus.size(), 1u);
4212 EXPECT_EQ(ResMinus.count(FMinus), 1u);
4213 EXPECT_EQ(ResMinus.count(FPlus), 0u);
4214 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
4215}
4216
4217TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
4218 TranslationUnitDecl *ToTU = getToTuDecl(
4219 R"(
4220 struct X {};
4221 void operator+(X, X);
4222 )",
4223 Lang_CXX);
4224 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
4225 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4226
4227 Decl *FromTU = getTuDecl(
4228 R"(
4229 struct X {};
4230 void operator+(X, X);
4231 )",
4232 Lang_CXX);
4233 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
4234 FromTU, functionDecl(hasOverloadedOperatorName("+")));
4235
4236 // FromPlus have a different TU, thus its DeclarationName is different too.
4237 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
4238
4239 ASTImporterLookupTable LT(*ToTU);
4240 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
4241 ASSERT_EQ(Res.size(), 1u);
4242 EXPECT_EQ(*Res.begin(), ToPlus);
4243
4244 // FromPlus have a different TU, thus its DeclarationName is different too.
4245 Res = LT.lookup(ToTU, FromPlus->getDeclName());
4246 ASSERT_EQ(Res.size(), 0u);
4247}
4248
Gabor Marton54058b52018-12-17 13:53:12 +00004249static const RecordDecl * getRecordDeclOfFriend(FriendDecl *FD) {
4250 QualType Ty = FD->getFriendType()->getType();
4251 QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
4252 return cast<RecordType>(NamedTy)->getDecl();
4253}
4254
4255TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassDecl) {
4256 TranslationUnitDecl *ToTU = getToTuDecl(
4257 R"(
4258 class Y { friend class F; };
4259 )",
4260 Lang_CXX);
4261
4262 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4263 // So we must dig up the underlying CXXRecordDecl.
4264 ASTImporterLookupTable LT(*ToTU);
4265 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4266 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4267 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
4268 ToTU, cxxRecordDecl(hasName("Y")));
4269
4270 DeclarationName Name = RD->getDeclName();
4271 auto Res = LT.lookup(ToTU, Name);
4272 EXPECT_EQ(Res.size(), 1u);
4273 EXPECT_EQ(*Res.begin(), RD);
4274
4275 Res = LT.lookup(Y, Name);
4276 EXPECT_EQ(Res.size(), 0u);
4277}
4278
4279TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
4280 TranslationUnitDecl *ToTU = getToTuDecl(
4281 R"(
4282 class Y { template <class T> friend class F; };
4283 )",
4284 Lang_CXX);
4285
4286 ASTImporterLookupTable LT(*ToTU);
4287 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4288 ToTU, classTemplateDecl(hasName("F")));
4289 DeclarationName Name = F->getDeclName();
4290 auto Res = LT.lookup(ToTU, Name);
4291 EXPECT_EQ(Res.size(), 2u);
4292 EXPECT_EQ(Res.count(F), 1u);
4293 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4294}
4295
4296TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
4297 TranslationUnitDecl *ToTU = getToTuDecl(
4298 R"(
4299 template <typename T>
4300 class F;
4301
4302 template <typename T>
4303 class Y {
4304 friend class F<T>;
4305 };
4306 )",
4307 Lang_CXX);
4308
4309 ASTImporterLookupTable LT(*ToTU);
4310 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4311 ToTU, classTemplateDecl(hasName("F")));
4312 DeclarationName Name = F->getDeclName();
4313 auto Res = LT.lookup(ToTU, Name);
4314 EXPECT_EQ(Res.size(), 2u);
4315 EXPECT_EQ(Res.count(F), 1u);
4316 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4317}
4318
4319TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
4320 TranslationUnitDecl *ToTU = getToTuDecl(
4321 R"(
4322 template <typename T>
4323 class F;
4324
4325 class Y {
4326 friend class F<int>;
4327 };
4328 )",
4329 Lang_CXX);
4330
4331 ASTImporterLookupTable LT(*ToTU);
4332 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4333 ToTU, classTemplateDecl(hasName("F")));
4334 DeclarationName Name = F->getDeclName();
4335 auto Res = LT.lookup(ToTU, Name);
4336 ASSERT_EQ(Res.size(), 3u);
4337 EXPECT_EQ(Res.count(F), 1u);
4338 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4339 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
4340}
4341
4342TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
4343 TranslationUnitDecl *ToTU = getToTuDecl(
4344 R"(
4345 class Y { friend void F(); };
4346 )",
4347 Lang_CXX);
4348
4349 ASTImporterLookupTable LT(*ToTU);
4350 auto *F =
4351 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
4352 DeclarationName Name = F->getDeclName();
4353 auto Res = LT.lookup(ToTU, Name);
4354 EXPECT_EQ(Res.size(), 1u);
4355 EXPECT_EQ(*Res.begin(), F);
4356}
4357
4358TEST_P(ASTImporterLookupTableTest,
4359 LookupFindsDeclsInClassTemplateSpecialization) {
4360 TranslationUnitDecl *ToTU = getToTuDecl(
4361 R"(
4362 template <typename T>
4363 struct X {
4364 int F;
4365 };
4366 void foo() {
4367 X<char> xc;
4368 }
4369 )",
4370 Lang_CXX);
4371
4372 ASTImporterLookupTable LT(*ToTU);
4373
4374 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
4375 ToTU, classTemplateDecl(hasName("X")));
4376 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
4377 ToTU,
4378 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
4379
4380 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4381 ToTU, classTemplateSpecializationDecl(hasName("X")));
4382 FieldDecl *FieldInSpec = *Spec->field_begin();
4383 ASSERT_TRUE(FieldInSpec);
4384
4385 DeclarationName Name = FieldInSpec->getDeclName();
4386 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
4387
4388 SmallVector<NamedDecl *, 2> FoundDecls;
4389 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
4390 EXPECT_EQ(FoundDecls.size(), 1u);
4391 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
4392
4393 auto Res = LT.lookup(TemplateDC, Name);
4394 ASSERT_EQ(Res.size(), 1u);
4395 EXPECT_EQ(*Res.begin(), FieldInTemplate);
4396
4397 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
4398 FoundDecls);
4399 EXPECT_EQ(FoundDecls.size(), 1u);
4400 EXPECT_EQ(FoundDecls[0], FieldInSpec);
4401
4402 Res = LT.lookup(cast<DeclContext>(Spec), Name);
4403 ASSERT_EQ(Res.size(), 1u);
4404 EXPECT_EQ(*Res.begin(), FieldInSpec);
4405}
4406
4407TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
4408 TranslationUnitDecl *ToTU = getToTuDecl(
4409 R"(
4410 class Y { template <class T> friend void F(); };
4411 )",
4412 Lang_CXX);
4413
4414 ASTImporterLookupTable LT(*ToTU);
4415 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
4416 ToTU, functionTemplateDecl(hasName("F")));
4417 DeclarationName Name = F->getDeclName();
4418 auto Res = LT.lookup(ToTU, Name);
4419 EXPECT_EQ(Res.size(), 2u);
4420 EXPECT_EQ(Res.count(F), 1u);
4421 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4422}
4423
4424TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
4425 TranslationUnitDecl *ToTU = getToTuDecl(
4426 R"(
4427 struct X;
4428 struct A {
4429 friend struct X;
4430 };
4431 struct B {
4432 friend struct X;
4433 };
4434 )",
4435 Lang_CXX);
4436
4437 ASTImporterLookupTable LT(*ToTU);
4438 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
4439 ToTU, cxxRecordDecl(hasName("X")));
4440 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4441 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4442 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
4443 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
4444 ASSERT_EQ(RD0, RD1);
4445 ASSERT_EQ(RD1, X);
4446
4447 DeclarationName Name = X->getDeclName();
4448 auto Res = LT.lookup(ToTU, Name);
4449 EXPECT_EQ(Res.size(), 1u);
4450 EXPECT_EQ(*Res.begin(), X);
4451}
4452
4453TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
4454 TranslationUnitDecl *ToTU = getToTuDecl(
4455 R"(
4456 enum E {
4457 A,
4458 B
4459 };
4460 )",
4461 Lang_C);
4462
4463 ASTImporterLookupTable LT(*ToTU);
4464 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
4465 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
4466 ToTU, enumConstantDecl(hasName("A")));
4467
4468 DeclarationName Name = A->getDeclName();
4469 // Redecl context is the TU.
4470 ASSERT_EQ(E->getRedeclContext(), ToTU);
4471
4472 SmallVector<NamedDecl *, 2> FoundDecls;
4473 // Normal lookup finds in the DC.
4474 E->localUncachedLookup(Name, FoundDecls);
4475 EXPECT_EQ(FoundDecls.size(), 1u);
4476
4477 // Normal lookup finds in the Redecl context.
4478 ToTU->localUncachedLookup(Name, FoundDecls);
4479 EXPECT_EQ(FoundDecls.size(), 1u);
4480
4481 // Import specific lookup finds in the DC.
4482 auto Res = LT.lookup(E, Name);
4483 ASSERT_EQ(Res.size(), 1u);
4484 EXPECT_EQ(*Res.begin(), A);
4485
4486 // Import specific lookup finds in the Redecl context.
4487 Res = LT.lookup(ToTU, Name);
4488 ASSERT_EQ(Res.size(), 1u);
4489 EXPECT_EQ(*Res.begin(), A);
4490}
4491
4492TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
4493 TranslationUnitDecl *ToTU = getToTuDecl(
4494 R"(
4495 namespace N {
4496 int A;
4497 }
4498 namespace N {
4499 }
4500 )",
4501 Lang_CXX);
4502 auto *N1 =
4503 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
4504 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
4505 DeclarationName Name = A->getDeclName();
4506
4507 ASTImporterLookupTable LT(*ToTU);
4508 auto Res = LT.lookup(N1, Name);
4509 ASSERT_EQ(Res.size(), 1u);
4510 EXPECT_EQ(*Res.begin(), A);
4511}
4512
Gabor Marton19f4f392018-06-25 13:04:37 +00004513INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
4514 ::testing::Values(ArgVector()), );
4515
Gabor Marton5254e642018-06-27 13:32:50 +00004516INSTANTIATE_TEST_CASE_P(
4517 ParameterizedTests, CanonicalRedeclChain,
4518 ::testing::Values(ArgVector()),);
4519
Gabor Marton0e04ebd2019-02-11 10:27:58 +00004520// FIXME This test is disabled currently, upcoming patches will make it
4521// possible to enable.
4522TEST_P(ASTImporterOptionSpecificTestBase,
4523 DISABLED_RedeclChainShouldBeCorrectAmongstNamespaces) {
4524 Decl *FromTU = getTuDecl(
4525 R"(
4526 namespace NS {
4527 struct X;
4528 struct Y {
4529 static const int I = 3;
4530 };
4531 }
4532 namespace NS {
4533 struct X { // <--- To be imported
4534 void method(int i = Y::I) {}
4535 int f;
4536 };
4537 }
4538 )",
4539 Lang_CXX);
4540 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
4541 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
4542 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
4543 FromTU,
4544 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
4545 ASSERT_NE(FromFwd, FromDef);
4546 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
4547 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4548 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
4549
4550 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX));
4551 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX));
4552 EXPECT_NE(ToFwd, ToDef);
4553 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
4554 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4555 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
4556 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4557 // We expect no (ODR) warning during the import.
4558 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4559}
4560
Gabor Martone331e632019-02-18 13:09:27 +00004561struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
4562
4563TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
4564 Decl *ToTU = getToTuDecl(
4565 R"(
4566 class X {
4567 template <typename T> friend void foo();
4568 };
4569 )",
4570 Lang_CXX);
4571 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
4572 ToTU, functionTemplateDecl(hasName("foo")));
4573
4574 Decl *FromTU = getTuDecl(
4575 R"(
4576 template <typename T> void foo();
4577 )",
4578 Lang_CXX);
4579 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
4580 FromTU, functionTemplateDecl(hasName("foo")));
4581 auto *Imported = Import(FromFoo, Lang_CXX);
4582
Gabor Marton16d98c22019-03-07 13:01:51 +00004583 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
Gabor Martone331e632019-02-18 13:09:27 +00004584}
4585
Gabor Marton54058b52018-12-17 13:53:12 +00004586INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
4587 DefaultTestValuesForRunOptions, );
4588
Gabor Marton19f4f392018-06-25 13:04:37 +00004589INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
4590 DefaultTestValuesForRunOptions, );
4591
4592INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
4593 DefaultTestValuesForRunOptions, );
4594
4595INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
4596 DefaultTestValuesForRunOptions, );
4597
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004598INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
Gabor Marton19f4f392018-06-25 13:04:37 +00004599 DefaultTestValuesForRunOptions, );
4600
Raphael Isemanne9bc35f2019-04-29 21:02:35 +00004601INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedirectingImporterTest,
4602 DefaultTestValuesForRunOptions, );
4603
Gabor Marton19f4f392018-06-25 13:04:37 +00004604INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
4605 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00004606
Gabor Martone331e632019-02-18 13:09:27 +00004607INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
4608 DefaultTestValuesForRunOptions, );
4609
Gabor Marton54058b52018-12-17 13:53:12 +00004610INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00004611 DefaultTestValuesForRunOptions, );
4612
Gabor Marton54058b52018-12-17 13:53:12 +00004613INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00004614 DefaultTestValuesForRunOptions, );
4615
Gabor Marton7df342a2018-12-17 12:42:12 +00004616INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
4617 DefaultTestValuesForRunOptions, );
4618
Gabor Marton5254e642018-06-27 13:32:50 +00004619INSTANTIATE_TEST_CASE_P(ParameterizedTests,
4620 ImportFunctionTemplateSpecializations,
4621 DefaultTestValuesForRunOptions, );
4622
Gabor Martonac3a5d62018-09-17 12:04:52 +00004623INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
4624 DefaultTestValuesForRunOptions, );
4625
4626INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
4627 DefaultTestValuesForRunOptions, );
4628
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00004629} // end namespace ast_matchers
4630} // end namespace clang