blob: 215dc10a398327a8215e83771d4b3126102abbeb [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 Marton1d51e3e2019-05-20 10:38:14 +00002365TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDefWithClass) {
Gabor Marton5254e642018-06-27 13:32:50 +00002366 auto Pattern = functionDecl(hasName("f"));
2367
2368 Decl *FromTU = getTuDecl(
2369 R"(
2370 class X;
2371 void f(X *x){}
2372 class X{
2373 friend void f(X *x);
2374 };
2375 )",
2376 Lang_CXX, "input0.cc");
2377 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2378
2379 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2380 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2381 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2382 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2383 auto *InClassFD = cast<FunctionDecl>(FirstDeclMatcher<FriendDecl>()
2384 .match(ToTU, friendDecl())
2385 ->getFriendDecl());
2386 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2387 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2388 // The parameters must refer the same type
2389 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2390 (*ImportedD->param_begin())->getOriginalType());
2391}
2392
Gabor Marton5254e642018-06-27 13:32:50 +00002393TEST_P(ImportFriendFunctions,
Gabor Marton1d51e3e2019-05-20 10:38:14 +00002394 ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
Gabor Marton5254e642018-06-27 13:32:50 +00002395 auto Pattern = functionDecl(hasName("f"));
2396
2397 Decl *FromTU = getTuDecl(
2398 R"(
2399 class X;
2400 void f(X *x){}
2401 class X{
2402 friend void f(X *x);
2403 };
2404 )",
2405 Lang_CXX, "input0.cc");
2406 auto *FromD = LastDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2407
2408 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2409 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2410 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2411 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2412 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2413 ToTU, functionDecl(unless(hasParent(friendDecl()))));
2414
2415 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2416 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2417 // The parameters must refer the same type
2418 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2419 (*ImportedD->param_begin())->getOriginalType());
2420}
2421
2422TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2423 auto Pattern = functionDecl(hasName("f"));
2424
2425 FunctionDecl *ImportedD;
2426 {
2427 Decl *FromTU =
2428 getTuDecl("struct X { friend void f(){} };", Lang_CXX, "input0.cc");
2429 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2430 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2431 }
2432 FunctionDecl *ImportedD1;
2433 {
2434 Decl *FromTU = getTuDecl("void f();", Lang_CXX, "input1.cc");
2435 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
2436 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2437 }
2438
2439 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2440 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2441 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2442 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2443 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2444}
2445
Balazs Keri89632b82018-08-21 14:32:21 +00002446TEST_P(ImportFriendFunctions, Lookup) {
2447 auto FunctionPattern = functionDecl(hasName("f"));
2448 auto ClassPattern = cxxRecordDecl(hasName("X"));
2449
2450 TranslationUnitDecl *FromTU =
2451 getTuDecl("struct X { friend void f(); };", Lang_CXX, "input0.cc");
2452 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2453 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2454 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2455 {
2456 auto FromName = FromD->getDeclName();
2457 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2458 auto LookupRes = Class->noload_lookup(FromName);
2459 ASSERT_EQ(LookupRes.size(), 0u);
2460 LookupRes = FromTU->noload_lookup(FromName);
2461 ASSERT_EQ(LookupRes.size(), 1u);
2462 }
2463
2464 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX));
2465 auto ToName = ToD->getDeclName();
2466
2467 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2468 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2469 auto LookupRes = Class->noload_lookup(ToName);
2470 EXPECT_EQ(LookupRes.size(), 0u);
2471 LookupRes = ToTU->noload_lookup(ToName);
2472 EXPECT_EQ(LookupRes.size(), 1u);
2473
2474 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2475 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2476 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2477 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2478}
2479
2480TEST_P(ImportFriendFunctions, DISABLED_LookupWithProtoAfter) {
2481 auto FunctionPattern = functionDecl(hasName("f"));
2482 auto ClassPattern = cxxRecordDecl(hasName("X"));
2483
2484 TranslationUnitDecl *FromTU = getTuDecl(
2485 "struct X { friend void f(); };"
2486 // This proto decl makes f available to normal
2487 // lookup, otherwise it is hidden.
2488 // Normal C++ lookup (implemented in
2489 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2490 // returns the found `NamedDecl` only if the set IDNS is matched
2491 "void f();",
2492 Lang_CXX, "input0.cc");
2493 auto *FromFriend =
2494 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2495 auto *FromNormal =
2496 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2497 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2498 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2499 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2500 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2501
2502 auto FromName = FromFriend->getDeclName();
2503 auto *FromClass =
2504 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2505 auto LookupRes = FromClass->noload_lookup(FromName);
2506 ASSERT_EQ(LookupRes.size(), 0u);
2507 LookupRes = FromTU->noload_lookup(FromName);
2508 ASSERT_EQ(LookupRes.size(), 1u);
2509
2510 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX));
2511 auto ToName = ToFriend->getDeclName();
2512
2513 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2514 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2515 LookupRes = ToClass->noload_lookup(ToName);
2516 EXPECT_EQ(LookupRes.size(), 0u);
2517 LookupRes = ToTU->noload_lookup(ToName);
2518 // Test is disabled because this result is 2.
2519 EXPECT_EQ(LookupRes.size(), 1u);
2520
2521 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2522 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2523 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2524 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2525 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2526 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2527 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2528}
2529
2530TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2531 auto FunctionPattern = functionDecl(hasName("f"));
2532 auto ClassPattern = cxxRecordDecl(hasName("X"));
2533
2534 TranslationUnitDecl *FromTU = getTuDecl(
2535 "void f();"
2536 "struct X { friend void f(); };",
2537 Lang_CXX, "input0.cc");
2538 auto *FromNormal =
2539 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2540 auto *FromFriend =
2541 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2542 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2543 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2544 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2545 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2546
2547 auto FromName = FromNormal->getDeclName();
2548 auto *FromClass =
2549 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2550 auto LookupRes = FromClass->noload_lookup(FromName);
2551 ASSERT_EQ(LookupRes.size(), 0u);
2552 LookupRes = FromTU->noload_lookup(FromName);
2553 ASSERT_EQ(LookupRes.size(), 1u);
2554
2555 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX));
2556 auto ToName = ToNormal->getDeclName();
2557 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2558
2559 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2560 LookupRes = ToClass->noload_lookup(ToName);
2561 EXPECT_EQ(LookupRes.size(), 0u);
2562 LookupRes = ToTU->noload_lookup(ToName);
2563 EXPECT_EQ(LookupRes.size(), 1u);
2564
2565 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2566 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2567 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2568 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2569 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2570 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2571 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2572}
2573
2574TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
2575 auto Pattern = functionDecl(hasName("f"));
2576
2577 TranslationUnitDecl *FromNormalTU =
2578 getTuDecl("void f();", Lang_CXX, "input0.cc");
2579 auto *FromNormalF =
2580 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
2581 TranslationUnitDecl *FromFriendTU =
2582 getTuDecl("class X { friend void f(); };", Lang_CXX, "input1.cc");
2583 auto *FromFriendF =
2584 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
2585 auto FromNormalName = FromNormalF->getDeclName();
2586 auto FromFriendName = FromFriendF->getDeclName();
2587
2588 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2589 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2590 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2591 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2592 auto LookupRes = FromNormalTU->noload_lookup(FromNormalName);
2593 ASSERT_EQ(LookupRes.size(), 1u);
2594 LookupRes = FromFriendTU->noload_lookup(FromFriendName);
2595 ASSERT_EQ(LookupRes.size(), 1u);
2596
2597 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX));
2598 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2599 auto ToName = ToNormalF->getDeclName();
2600 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2601 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2602 LookupRes = ToTU->noload_lookup(ToName);
2603 EXPECT_EQ(LookupRes.size(), 1u);
2604 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
Jonas Devliegherefc514902018-10-10 13:27:25 +00002605
Balazs Keri89632b82018-08-21 14:32:21 +00002606 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX));
2607 LookupRes = ToTU->noload_lookup(ToName);
2608 EXPECT_EQ(LookupRes.size(), 1u);
2609 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2610
2611 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2612 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2613
2614 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2615 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2616}
2617
2618TEST_P(ImportFriendFunctions, ImportFriendList) {
2619 TranslationUnitDecl *FromTU = getTuDecl(
2620 "struct X { friend void f(); };"
2621 "void f();",
2622 Lang_CXX, "input0.cc");
2623 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
2624 FromTU, functionDecl(hasName("f")));
2625
2626 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2627 FromTU, cxxRecordDecl(hasName("X")));
2628 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
2629 auto FromFriends = FromClass->friends();
2630 unsigned int FrN = 0;
2631 for (auto Fr : FromFriends) {
2632 ASSERT_EQ(Fr, FromFriend);
2633 ++FrN;
2634 }
2635 ASSERT_EQ(FrN, 1u);
2636
2637 Import(FromFriendF, Lang_CXX);
2638 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2639 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2640 ToTU, cxxRecordDecl(hasName("X")));
2641 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
2642 auto ToFriends = ToClass->friends();
2643 FrN = 0;
2644 for (auto Fr : ToFriends) {
2645 EXPECT_EQ(Fr, ToFriend);
2646 ++FrN;
2647 }
2648 EXPECT_EQ(FrN, 1u);
2649}
2650
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002651AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
2652 InnerMatcher) {
2653 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
2654 return InnerMatcher.matches(*Typedef, Finder, Builder);
2655 return false;
2656}
2657
Gabor Marton19f4f392018-06-25 13:04:37 +00002658TEST_P(ImportDecl, ImportEnumSequential) {
Aleksei Sidorin04fbffc2018-04-24 10:11:53 +00002659 CodeFiles Samples{{"main.c",
2660 {"void foo();"
2661 "void moo();"
2662 "int main() { foo(); moo(); }",
2663 Lang_C}},
2664
2665 {"foo.c",
2666 {"typedef enum { THING_VALUE } thing_t;"
2667 "void conflict(thing_t type);"
2668 "void foo() { (void)THING_VALUE; }"
2669 "void conflict(thing_t type) {}",
2670 Lang_C}},
2671
2672 {"moo.c",
2673 {"typedef enum { THING_VALUE } thing_t;"
2674 "void conflict(thing_t type);"
2675 "void moo() { conflict(THING_VALUE); }",
2676 Lang_C}}};
2677
2678 auto VerificationMatcher =
2679 enumDecl(has(enumConstantDecl(hasName("THING_VALUE"))),
2680 hasTypedefForAnonDecl(hasName("thing_t")));
2681
2682 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName("foo"))},
2683 ImportMoo{"moo.c", "main.c", functionDecl(hasName("moo"))};
2684
2685 testImportSequence(
2686 Samples, {ImportFoo, ImportMoo}, // "foo", them "moo".
2687 // Just check that there is only one enum decl in the result AST.
2688 "main.c", enumDecl(), VerificationMatcher);
2689
2690 // For different import order, result should be the same.
2691 testImportSequence(
2692 Samples, {ImportMoo, ImportFoo}, // "moo", them "foo".
2693 // Check that there is only one enum decl in the result AST.
2694 "main.c", enumDecl(), VerificationMatcher);
2695}
2696
Peter Szecsice7f3182018-05-07 12:08:27 +00002697const internal::VariadicDynCastAllOfMatcher<Expr, DependentScopeDeclRefExpr>
2698 dependentScopeDeclRefExpr;
2699
Gabor Marton19f4f392018-06-25 13:04:37 +00002700TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002701 MatchVerifier<Decl> Verifier;
2702 testImport("template <typename T> struct S { static T foo; };"
2703 "template <typename T> void declToImport() {"
2704 " (void) S<T>::foo;"
2705 "}"
Gabor Marton1f6ad142018-06-29 10:25:19 +00002706 "void instantiate() { declToImport<int>(); }"
2707 "template <typename T> T S<T>::foo;",
Peter Szecsice7f3182018-05-07 12:08:27 +00002708 Lang_CXX11, "", Lang_CXX11, Verifier,
2709 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2710 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
2711
2712 testImport("template <typename T> struct S {"
2713 "template<typename S> static void foo(){};"
2714 "};"
2715 "template <typename T> void declToImport() {"
2716 " S<T>::template foo<T>();"
2717 "}"
2718 "void instantiate() { declToImport<int>(); }",
2719 Lang_CXX11, "", Lang_CXX11, Verifier,
2720 functionTemplateDecl(has(functionDecl(has(compoundStmt(
2721 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
2722}
2723
2724const internal::VariadicDynCastAllOfMatcher<Type, DependentNameType>
2725 dependentNameType;
2726
Gabor Marton19f4f392018-06-25 13:04:37 +00002727TEST_P(ImportExpr, DependentNameType) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002728 MatchVerifier<Decl> Verifier;
2729 testImport("template <typename T> struct declToImport {"
2730 " typedef typename T::type dependent_name;"
2731 "};",
2732 Lang_CXX11, "", Lang_CXX11, Verifier,
2733 classTemplateDecl(has(
2734 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
2735}
2736
Gabor Marton19f4f392018-06-25 13:04:37 +00002737TEST_P(ImportExpr, UnresolvedMemberExpr) {
Peter Szecsice7f3182018-05-07 12:08:27 +00002738 MatchVerifier<Decl> Verifier;
2739 testImport("struct S { template <typename T> void mem(); };"
2740 "template <typename U> void declToImport() {"
2741 " S s;"
2742 " s.mem<U>();"
2743 "}"
2744 "void instantiate() { declToImport<int>(); }",
2745 Lang_CXX11, "", Lang_CXX11, Verifier,
2746 functionTemplateDecl(has(functionDecl(has(
2747 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
2748}
2749
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002750class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
Balazs Keri1d20cc22018-07-16 12:16:39 +00002751public:
2752 static constexpr auto DefaultCode = R"(
2753 struct A { int x; };
2754 void f() {
2755 A a;
2756 A a1(a);
2757 A a2(A{});
2758 a = a1;
2759 a = A{};
2760 a.~A();
2761 })";
2762
2763 template <typename MatcherType>
2764 void testImportOf(
2765 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2766 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
2767 }
2768
2769 template <typename MatcherType>
2770 void testNoImportOf(
2771 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
2772 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
2773 }
2774
2775private:
2776 template <typename MatcherType>
2777 void test(const MatcherType &MethodMatcher,
2778 const char *Code, unsigned int ExpectedCount) {
2779 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
2780
2781 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
2782 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
2783 ToTU, ClassMatcher);
2784
Balazs Keri2f752ba2018-07-16 14:05:18 +00002785 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002786
2787 {
2788 CXXMethodDecl *Method =
2789 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
2790 ToClass->removeDecl(Method);
Gabor Marton54058b52018-12-17 13:53:12 +00002791 LookupTablePtr->remove(Method);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002792 }
2793
Balazs Keri2f752ba2018-07-16 14:05:18 +00002794 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
Balazs Keri1d20cc22018-07-16 12:16:39 +00002795
2796 Decl *ImportedClass = nullptr;
2797 {
2798 Decl *FromTU = getTuDecl(Code, Lang_CXX11, "input1.cc");
2799 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
2800 FromTU, ClassMatcher);
2801 ImportedClass = Import(FromClass, Lang_CXX11);
2802 }
2803
2804 EXPECT_EQ(ToClass, ImportedClass);
2805 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
2806 ExpectedCount);
2807 }
2808};
2809
2810TEST_P(ImportImplicitMethods, DefaultConstructor) {
2811 testImportOf(cxxConstructorDecl(isDefaultConstructor()));
2812}
2813
2814TEST_P(ImportImplicitMethods, CopyConstructor) {
2815 testImportOf(cxxConstructorDecl(isCopyConstructor()));
2816}
2817
2818TEST_P(ImportImplicitMethods, MoveConstructor) {
2819 testImportOf(cxxConstructorDecl(isMoveConstructor()));
2820}
2821
2822TEST_P(ImportImplicitMethods, Destructor) {
2823 testImportOf(cxxDestructorDecl());
2824}
2825
2826TEST_P(ImportImplicitMethods, CopyAssignment) {
2827 testImportOf(cxxMethodDecl(isCopyAssignmentOperator()));
2828}
2829
2830TEST_P(ImportImplicitMethods, MoveAssignment) {
2831 testImportOf(cxxMethodDecl(isMoveAssignmentOperator()));
2832}
2833
2834TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
2835 auto Code = R"(
2836 struct A { A() { int x; } };
2837 )";
2838 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2839}
2840
2841TEST_P(ImportImplicitMethods, DoNotImportDefault) {
2842 auto Code = R"(
2843 struct A { A() = default; };
2844 )";
2845 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2846}
2847
2848TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
2849 auto Code = R"(
2850 struct A { A() = delete; };
2851 )";
2852 testNoImportOf(cxxConstructorDecl(isDefaultConstructor()), Code);
2853}
2854
2855TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
2856 auto Code = R"(
2857 struct A { void f() { } };
2858 )";
2859 testNoImportOf(cxxMethodDecl(hasName("f")), Code);
2860}
2861
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002862TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00002863 Decl *ToR1;
2864 {
2865 Decl *FromTU = getTuDecl(
2866 "struct A { };", Lang_CXX, "input0.cc");
2867 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2868 FromTU, cxxRecordDecl(hasName("A")));
2869
2870 ToR1 = Import(FromR, Lang_CXX);
2871 }
2872
2873 Decl *ToR2;
2874 {
2875 Decl *FromTU = getTuDecl(
2876 "struct A { };", Lang_CXX, "input1.cc");
2877 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2878 FromTU, cxxRecordDecl(hasName("A")));
2879
2880 ToR2 = Import(FromR, Lang_CXX);
2881 }
Jonas Devliegherefc514902018-10-10 13:27:25 +00002882
Balazs Keric7797c42018-07-11 09:37:24 +00002883 EXPECT_EQ(ToR1, ToR2);
2884}
2885
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002886TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
Balazs Keric7797c42018-07-11 09:37:24 +00002887 Decl *ToR1;
2888 {
2889 Decl *FromTU = getTuDecl(
2890 "struct A { int x; };", Lang_CXX, "input0.cc");
2891 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2892 FromTU, cxxRecordDecl(hasName("A")));
2893 ToR1 = Import(FromR, Lang_CXX);
2894 }
2895 Decl *ToR2;
2896 {
2897 Decl *FromTU = getTuDecl(
2898 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2899 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
2900 FromTU, cxxRecordDecl(hasName("A")));
2901 ToR2 = Import(FromR, Lang_CXX);
2902 }
2903 EXPECT_NE(ToR1, ToR2);
2904}
2905
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002906TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00002907 Decl *ToF1;
2908 {
2909 Decl *FromTU = getTuDecl(
2910 "struct A { int x; };", Lang_CXX, "input0.cc");
2911 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2912 FromTU, fieldDecl(hasName("x")));
2913 ToF1 = Import(FromF, Lang_CXX);
2914 }
2915 Decl *ToF2;
2916 {
2917 Decl *FromTU = getTuDecl(
2918 "struct A { int x; };", Lang_CXX, "input1.cc");
2919 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2920 FromTU, fieldDecl(hasName("x")));
2921 ToF2 = Import(FromF, Lang_CXX);
2922 }
2923 EXPECT_EQ(ToF1, ToF2);
2924}
2925
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002926TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
Balazs Keric7797c42018-07-11 09:37:24 +00002927 Decl *ToF1;
2928 {
2929 Decl *FromTU = getTuDecl(
2930 "struct A { int x; };", Lang_CXX, "input0.cc");
2931 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2932 FromTU, fieldDecl(hasName("x")));
2933 ToF1 = Import(FromF, Lang_CXX);
2934 }
2935 Decl *ToF2;
2936 {
2937 Decl *FromTU = getTuDecl(
2938 "struct A { unsigned x; };", Lang_CXX, "input1.cc");
2939 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
2940 FromTU, fieldDecl(hasName("x")));
2941 ToF2 = Import(FromF, Lang_CXX);
2942 }
2943 EXPECT_NE(ToF1, ToF2);
2944}
2945
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002946TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00002947 Decl *ToM1;
2948 {
2949 Decl *FromTU = getTuDecl(
2950 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc");
2951 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2952 FromTU, functionDecl(hasName("x"), isDefinition()));
2953 ToM1 = Import(FromM, Lang_CXX);
2954 }
2955 Decl *ToM2;
2956 {
2957 Decl *FromTU = getTuDecl(
2958 "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc");
2959 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2960 FromTU, functionDecl(hasName("x"), isDefinition()));
2961 ToM2 = Import(FromM, Lang_CXX);
2962 }
2963 EXPECT_EQ(ToM1, ToM2);
2964}
2965
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002966TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
Balazs Keric7797c42018-07-11 09:37:24 +00002967 Decl *ToM1;
2968 {
2969 Decl *FromTU = getTuDecl(
2970 "struct A { void x(); }; void A::x() { }",
2971 Lang_CXX, "input0.cc");
2972 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2973 FromTU, functionDecl(hasName("x"), isDefinition()));
2974 ToM1 = Import(FromM, Lang_CXX);
2975 }
2976 Decl *ToM2;
2977 {
2978 Decl *FromTU = getTuDecl(
2979 "struct A { void x() const; }; void A::x() const { }",
2980 Lang_CXX, "input1.cc");
2981 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
2982 FromTU, functionDecl(hasName("x"), isDefinition()));
2983 ToM2 = Import(FromM, Lang_CXX);
2984 }
2985 EXPECT_NE(ToM1, ToM2);
2986}
2987
Gabor Marton0b57ccb2019-02-07 16:52:48 +00002988TEST_P(ASTImporterOptionSpecificTestBase,
2989 ImportUnnamedStructsWithRecursingField) {
Gabor Martonf086fa82018-07-17 12:06:36 +00002990 Decl *FromTU = getTuDecl(
2991 R"(
2992 struct A {
2993 struct {
2994 struct A *next;
2995 } entry0;
2996 struct {
2997 struct A *next;
2998 } entry1;
2999 };
3000 )",
3001 Lang_C, "input0.cc");
3002 auto *From =
3003 FirstDeclMatcher<RecordDecl>().match(FromTU, recordDecl(hasName("A")));
3004
3005 Import(From, Lang_C);
3006
3007 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3008 auto *Entry0 =
3009 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));
3010 auto *Entry1 =
3011 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry1")));
3012 auto *R0 = getRecordDecl(Entry0);
3013 auto *R1 = getRecordDecl(Entry1);
3014 EXPECT_NE(R0, R1);
3015 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3016 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3017 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3018 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3019}
3020
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003021TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
Balazs Keri2544b4b2018-08-08 09:40:57 +00003022 Decl *FromTU = getTuDecl(
3023 R"(
3024 void f(int X, int Y, bool Z) {
3025 (void)[X, Y, Z] { (void)Z; };
3026 }
3027 )",
3028 Lang_CXX11, "input0.cc");
3029 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3030 FromTU, functionDecl(hasName("f")));
3031 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3032 EXPECT_TRUE(ToF);
3033
3034 CXXRecordDecl *FromLambda =
3035 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3036 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3037
3038 auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
3039 EXPECT_TRUE(ToLambda);
3040
3041 // Check if the fields of the lambda class are imported in correct order.
3042 unsigned FromIndex = 0u;
3043 for (auto *FromField : FromLambda->fields()) {
3044 ASSERT_FALSE(FromField->getDeclName());
3045 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3046 EXPECT_TRUE(ToField);
Balazs Keri3b30d652018-10-19 13:32:20 +00003047 Optional<unsigned> ToIndex = ASTImporter::getFieldIndex(ToField);
3048 EXPECT_TRUE(ToIndex);
3049 EXPECT_EQ(*ToIndex, FromIndex);
Balazs Keri2544b4b2018-08-08 09:40:57 +00003050 ++FromIndex;
3051 }
3052
3053 EXPECT_EQ(FromIndex, 3u);
3054}
3055
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003056TEST_P(ASTImporterOptionSpecificTestBase,
3057 MergeFieldDeclsOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003058 std::string ClassTemplate =
3059 R"(
3060 template <typename T>
3061 struct X {
3062 int a{0}; // FieldDecl with InitListExpr
3063 X(char) : a(3) {} // (1)
3064 X(int) {} // (2)
3065 };
3066 )";
3067 Decl *ToTU = getToTuDecl(ClassTemplate +
3068 R"(
3069 void foo() {
3070 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3071 X<char> xc('c');
3072 }
3073 )", Lang_CXX11);
3074 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3075 ToTU, classTemplateSpecializationDecl(hasName("X")));
3076 // FieldDecl without InitlistExpr:
3077 auto *ToField = *ToSpec->field_begin();
3078 ASSERT_TRUE(ToField);
3079 ASSERT_FALSE(ToField->getInClassInitializer());
3080 Decl *FromTU = getTuDecl(ClassTemplate +
3081 R"(
3082 void bar() {
3083 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3084 X<char> xc(1);
3085 }
3086 )", Lang_CXX11);
3087 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3088 FromTU, classTemplateSpecializationDecl(hasName("X")));
3089 // FieldDecl with InitlistExpr:
3090 auto *FromField = *FromSpec->field_begin();
3091 ASSERT_TRUE(FromField);
3092 ASSERT_TRUE(FromField->getInClassInitializer());
3093
3094 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3095 ASSERT_TRUE(ImportedSpec);
3096 EXPECT_EQ(ImportedSpec, ToSpec);
3097 // After the import, the FieldDecl has to be merged, thus it should have the
3098 // InitListExpr.
3099 EXPECT_TRUE(ToField->getInClassInitializer());
3100}
3101
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003102TEST_P(ASTImporterOptionSpecificTestBase,
3103 MergeFunctionOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003104 std::string ClassTemplate =
3105 R"(
3106 template <typename T>
3107 struct X {
3108 void f() {}
3109 void g() {}
3110 };
3111 )";
3112 Decl *ToTU = getToTuDecl(ClassTemplate +
3113 R"(
3114 void foo() {
3115 X<char> x;
3116 x.f();
3117 }
3118 )", Lang_CXX11);
3119 Decl *FromTU = getTuDecl(ClassTemplate +
3120 R"(
3121 void bar() {
3122 X<char> x;
3123 x.g();
3124 }
3125 )", Lang_CXX11);
3126 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3127 FromTU, classTemplateSpecializationDecl(hasName("X")));
3128 auto FunPattern = functionDecl(hasName("g"),
3129 hasParent(classTemplateSpecializationDecl()));
3130 auto *FromFun =
3131 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunPattern);
3132 auto *ToFun =
3133 FirstDeclMatcher<FunctionDecl>().match(ToTU, FunPattern);
3134 ASSERT_TRUE(FromFun->hasBody());
3135 ASSERT_FALSE(ToFun->hasBody());
3136 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3137 ASSERT_TRUE(ImportedSpec);
3138 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3139 ToTU, classTemplateSpecializationDecl(hasName("X")));
3140 EXPECT_EQ(ImportedSpec, ToSpec);
3141 EXPECT_TRUE(ToFun->hasBody());
3142}
3143
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003144TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003145 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3146 std::string ClassTemplate =
3147 R"(
3148 template <typename T>
3149 struct X {};
3150 )";
3151 Decl *ToTU = getToTuDecl(ClassTemplate +
3152 R"(
3153 template <>
3154 struct X<char> {
3155 int a;
3156 };
3157 void foo() {
3158 X<char> x;
3159 }
3160 )",
3161 Lang_CXX11);
3162 Decl *FromTU = getTuDecl(ClassTemplate +
3163 R"(
3164 template <>
3165 struct X<char> {
3166 int b;
3167 };
3168 void foo() {
3169 X<char> x;
3170 }
3171 )",
3172 Lang_CXX11);
3173 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3174 FromTU, classTemplateSpecializationDecl(hasName("X")));
3175 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3176
3177 // We expect one (ODR) warning during the import.
3178 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3179
3180 // The second specialization is different from the first, thus it violates
3181 // ODR, consequently we expect to keep the first specialization only, which is
3182 // already in the "To" context.
Gabor Marton7f8c4002019-03-19 13:34:10 +00003183 EXPECT_FALSE(ImportedSpec);
3184 EXPECT_EQ(1u,
3185 DeclCounter<ClassTemplateSpecializationDecl>().match(
3186 ToTU, classTemplateSpecializationDecl(hasName("X"))));
Gabor Marton42e15de2018-08-22 11:52:14 +00003187}
3188
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003189TEST_P(ASTImporterOptionSpecificTestBase,
3190 MergeCtorOfClassTemplateSpecialization) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003191 std::string ClassTemplate =
3192 R"(
3193 template <typename T>
3194 struct X {
3195 X(char) {}
3196 X(int) {}
3197 };
3198 )";
3199 Decl *ToTU = getToTuDecl(ClassTemplate +
3200 R"(
3201 void foo() {
3202 X<char> x('c');
3203 }
3204 )", Lang_CXX11);
3205 Decl *FromTU = getTuDecl(ClassTemplate +
3206 R"(
3207 void bar() {
3208 X<char> x(1);
3209 }
3210 )", Lang_CXX11);
3211 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3212 FromTU, classTemplateSpecializationDecl(hasName("X")));
3213 // Match the void(int) ctor.
3214 auto CtorPattern =
3215 cxxConstructorDecl(hasParameter(0, varDecl(hasType(asString("int")))),
3216 hasParent(classTemplateSpecializationDecl()));
3217 auto *FromCtor =
3218 FirstDeclMatcher<CXXConstructorDecl>().match(FromTU, CtorPattern);
3219 auto *ToCtor =
3220 FirstDeclMatcher<CXXConstructorDecl>().match(ToTU, CtorPattern);
3221 ASSERT_TRUE(FromCtor->hasBody());
3222 ASSERT_FALSE(ToCtor->hasBody());
3223 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3224 ASSERT_TRUE(ImportedSpec);
3225 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3226 ToTU, classTemplateSpecializationDecl(hasName("X")));
3227 EXPECT_EQ(ImportedSpec, ToSpec);
3228 EXPECT_TRUE(ToCtor->hasBody());
3229}
3230
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003231TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton42e15de2018-08-22 11:52:14 +00003232 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3233 auto Code =
3234 R"(
3235 // primary template
3236 template<class T1, class T2, int I>
3237 class A {};
3238
3239 // partial specialization
3240 template<class T, int I>
3241 class A<T, T*, I> {};
3242 )";
3243 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3244 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3245 auto *FromSpec =
3246 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3247 FromTU, classTemplatePartialSpecializationDecl());
3248 auto *ToSpec =
3249 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3250 ToTU, classTemplatePartialSpecializationDecl());
3251
3252 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3253 EXPECT_EQ(ImportedSpec, ToSpec);
3254 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3255 ToTU, classTemplatePartialSpecializationDecl()));
3256}
3257
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003258TEST_P(ASTImporterOptionSpecificTestBase,
3259 ClassTemplateSpecializationsShouldNotBeDuplicated) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003260 auto Code =
3261 R"(
3262 // primary template
3263 template<class T1, class T2, int I>
3264 class A {};
3265
3266 // full specialization
3267 template<>
3268 class A<int, int, 1> {};
3269 )";
3270 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3271 Decl *FromTU = getTuDecl(Code, Lang_CXX11);
3272 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3273 FromTU, classTemplateSpecializationDecl());
3274 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3275 ToTU, classTemplateSpecializationDecl());
3276
3277 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3278 EXPECT_EQ(ImportedSpec, ToSpec);
3279 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3280 ToTU, classTemplateSpecializationDecl()));
3281}
3282
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003283TEST_P(ASTImporterOptionSpecificTestBase,
3284 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
Gabor Marton42e15de2018-08-22 11:52:14 +00003285 std::string PrimaryTemplate =
3286 R"(
3287 template<class T1, class T2, int I>
3288 class A {};
3289 )";
3290 auto PartialSpec =
3291 R"(
3292 template<class T, int I>
3293 class A<T, T*, I> {};
3294 )";
3295 auto FullSpec =
3296 R"(
3297 template<>
3298 class A<int, int, 1> {};
3299 )";
3300 Decl *ToTU = getToTuDecl(PrimaryTemplate + FullSpec, Lang_CXX11);
3301 Decl *FromTU = getTuDecl(PrimaryTemplate + PartialSpec, Lang_CXX11);
3302 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3303 FromTU, classTemplateSpecializationDecl());
3304
3305 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3306 EXPECT_TRUE(ImportedSpec);
3307 // Check the number of partial specializations.
3308 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3309 ToTU, classTemplatePartialSpecializationDecl()));
3310 // Check the number of full specializations.
3311 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3312 ToTU, classTemplateSpecializationDecl(
3313 unless(classTemplatePartialSpecializationDecl()))));
3314}
3315
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003316TEST_P(ASTImporterOptionSpecificTestBase,
3317 InitListExprValueKindShouldBeImported) {
Gabor Martona20ce602018-09-03 13:10:53 +00003318 Decl *TU = getTuDecl(
3319 R"(
3320 const int &init();
3321 void foo() { const int &a{init()}; }
3322 )", Lang_CXX11, "input0.cc");
3323 auto *FromD = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("a")));
3324 ASSERT_TRUE(FromD->getAnyInitializer());
3325 auto *InitExpr = FromD->getAnyInitializer();
3326 ASSERT_TRUE(InitExpr);
3327 ASSERT_TRUE(InitExpr->isGLValue());
3328
3329 auto *ToD = Import(FromD, Lang_CXX11);
3330 EXPECT_TRUE(ToD);
3331 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3332 EXPECT_TRUE(ToInitExpr);
3333 EXPECT_TRUE(ToInitExpr->isGLValue());
3334}
3335
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003336struct ImportVariables : ASTImporterOptionSpecificTestBase {};
Gabor Martonac3a5d62018-09-17 12:04:52 +00003337
3338TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3339 Decl *FromTU = getTuDecl(
3340 R"(
3341 struct A {
3342 static const int a = 1 + 2;
3343 };
3344 const int A::a;
3345 )", Lang_CXX, "input1.cc");
3346
3347 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3348 FromTU, varDecl(hasName("a"))); // Decl with init
3349 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3350 FromTU, varDecl(hasName("a"))); // Decl with definition
3351 ASSERT_NE(FromDWithInit, FromDWithDef);
3352 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3353
3354 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3355 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3356 ASSERT_TRUE(ToD0);
3357 ASSERT_TRUE(ToD1);
3358 EXPECT_NE(ToD0, ToD1);
3359 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3360}
3361
3362TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3363 auto StructA =
3364 R"(
3365 struct A {
3366 static const int a = 1 + 2;
3367 };
3368 )";
3369 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3370 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a;", Lang_CXX,
3371 "input1.cc");
3372
3373 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3374 FromTU, varDecl(hasName("a"))); // Decl with init
3375 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3376 FromTU, varDecl(hasName("a"))); // Decl with definition
3377 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3378 ASSERT_TRUE(FromDWithInit->getInit());
3379 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3380 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3381 ASSERT_FALSE(FromDWithDef->getInit());
3382
3383 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3384 ToTU, varDecl(hasName("a"))); // Decl with init
3385 ASSERT_TRUE(ToD->getInit());
3386 ASSERT_FALSE(ToD->getDefinition());
3387
3388 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3389 EXPECT_TRUE(ImportedD->getAnyInitializer());
3390 EXPECT_TRUE(ImportedD->getDefinition());
3391}
3392
3393TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3394 auto StructA =
3395 R"(
3396 struct A {
3397 static const int a;
3398 };
3399 )";
3400 Decl *ToTU = getToTuDecl(StructA, Lang_CXX);
3401 Decl *FromTU = getTuDecl(std::string(StructA) + "const int A::a = 1 + 2;",
3402 Lang_CXX, "input1.cc");
3403
3404 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3405 FromTU, varDecl(hasName("a")));
3406 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3407 FromTU, varDecl(hasName("a"))); // Decl with definition and with init.
3408 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3409 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3410 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3411 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3412 ASSERT_TRUE(FromDWithDef->getInit());
3413
3414 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3415 ToTU, varDecl(hasName("a")));
3416 ASSERT_FALSE(ToD->getInit());
3417 ASSERT_FALSE(ToD->getDefinition());
3418
3419 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3420 EXPECT_TRUE(ImportedD->getAnyInitializer());
3421 EXPECT_TRUE(ImportedD->getDefinition());
3422}
3423
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003424struct ImportClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003425
Gabor Marton54058b52018-12-17 13:53:12 +00003426TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
3427 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_C);
3428 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3429 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3430 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3431 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3432
3433 Decl *ImportedDef = Import(FromDef, Lang_C);
3434
3435 EXPECT_NE(ImportedDef, ToProto);
3436 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3437 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3438 EXPECT_TRUE(ImportedDef == ToDef);
3439 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3440 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3441 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3442}
3443
3444TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
3445 Decl *ToTU = getToTuDecl("struct A { struct X *Xp; };", Lang_CXX);
3446 Decl *FromTU1 = getTuDecl("struct X {};", Lang_CXX, "input1.cc");
3447 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3448 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3449 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3450
3451 Decl *ImportedDef = Import(FromDef, Lang_CXX);
3452
3453 EXPECT_NE(ImportedDef, ToProto);
3454 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3455 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3456 EXPECT_TRUE(ImportedDef == ToDef);
3457 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3458 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3459 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3460}
3461
3462TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
3463 Decl *FromTU0 = getTuDecl("struct A { struct X *Xp; };", Lang_C, "input0.cc");
3464 Decl *FromTU1 = getTuDecl("struct X {};", Lang_C, "input1.cc");
3465 auto Pattern = recordDecl(hasName("X"), unless(isImplicit()));
3466 auto FromProto = FirstDeclMatcher<RecordDecl>().match(FromTU0, Pattern);
3467 auto FromDef = FirstDeclMatcher<RecordDecl>().match(FromTU1, Pattern);
3468
3469 Decl *ImportedProto = Import(FromProto, Lang_C);
3470 Decl *ImportedDef = Import(FromDef, Lang_C);
3471 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
3472
3473 EXPECT_NE(ImportedDef, ImportedProto);
3474 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
3475 auto ToProto = FirstDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3476 auto ToDef = LastDeclMatcher<RecordDecl>().match(ToTU, Pattern);
3477 EXPECT_TRUE(ImportedDef == ToDef);
3478 EXPECT_TRUE(ImportedProto == ToProto);
3479 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
3480 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
3481 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
3482}
3483
Gabor Marton7df342a2018-12-17 12:42:12 +00003484
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003485struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {};
Gabor Marton7df342a2018-12-17 12:42:12 +00003486
3487TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
3488 Decl *FromTU = getTuDecl(
3489 R"(
3490 class A {
3491 template <int I> class F {};
3492 class X {
3493 template <int I> friend class F;
3494 };
3495 };
3496 )",
3497 Lang_CXX, "input0.cc");
3498
3499 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3500 FromTU, cxxRecordDecl(hasName("F"), isDefinition()));
3501 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
3502 FromTU, cxxRecordDecl(hasName("F")));
3503
3504 ASSERT_TRUE(FromClass);
3505 ASSERT_TRUE(FromFriendClass);
3506 ASSERT_NE(FromClass, FromFriendClass);
3507 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
3508 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
3509 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3510 FromClass->getDescribedClassTemplate());
3511
3512 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX));
3513 auto *ToFriendClass = cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX));
3514
3515 EXPECT_TRUE(ToClass);
3516 EXPECT_TRUE(ToFriendClass);
3517 EXPECT_NE(ToClass, ToFriendClass);
3518 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
3519 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
3520 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
3521 ToClass->getDescribedClassTemplate());
3522}
3523
3524TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
3525 Decl *FromTu = getTuDecl(
3526 R"(
3527 class declToImport {
3528 friend class declToImport;
3529 };
3530 )",
3531 Lang_CXX, "input.cc");
3532
3533 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
3534 FromTu, cxxRecordDecl(hasName("declToImport")));
3535 auto *ToD = Import(FromD, Lang_CXX);
3536 auto Pattern = cxxRecordDecl(has(friendDecl()));
3537 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3538 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3539}
3540
3541TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
3542 Decl *FromTu = getTuDecl(
3543 R"(
3544 template<class A> class declToImport {
3545 template<class A1> friend class declToImport;
3546 };
3547 )",
3548 Lang_CXX, "input.cc");
3549
3550 auto *FromD =
3551 FirstDeclMatcher<ClassTemplateDecl>().match(FromTu, classTemplateDecl());
3552 auto *ToD = Import(FromD, Lang_CXX);
3553
3554 auto Pattern = classTemplateDecl(
3555 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
3556 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
3557 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
3558
3559 auto *Class =
3560 FirstDeclMatcher<ClassTemplateDecl>().match(ToD, classTemplateDecl());
3561 auto *Friend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
3562 EXPECT_NE(Friend->getFriendDecl(), Class);
3563 EXPECT_EQ(Friend->getFriendDecl()->getPreviousDecl(), Class);
3564}
3565
3566TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
3567 auto Pattern = classTemplateSpecializationDecl(hasName("X"));
3568
3569 ClassTemplateSpecializationDecl *Imported1;
3570 {
3571 Decl *FromTU = getTuDecl("template<class T> class X;"
3572 "struct Y { friend class X<int>; };",
3573 Lang_CXX, "input0.cc");
3574 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3575 FromTU, Pattern);
3576
3577 Imported1 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3578 }
3579 ClassTemplateSpecializationDecl *Imported2;
3580 {
3581 Decl *FromTU = getTuDecl("template<class T> class X;"
3582 "template<> class X<int>{};"
3583 "struct Z { friend class X<int>; };",
3584 Lang_CXX, "input1.cc");
3585 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3586 FromTU, Pattern);
3587
3588 Imported2 = cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX));
3589 }
3590
3591 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3592 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
3593 2u);
3594 ASSERT_TRUE(Imported2->getPreviousDecl());
3595 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
3596}
3597
3598TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
3599 Decl *FromTU0 = getTuDecl(
3600 R"(
3601 class X {
3602 class Y;
3603 };
3604 class X::Y {
3605 template <typename T>
3606 friend class F; // The decl context of F is the global namespace.
3607 };
3608 )",
3609 Lang_CXX, "input0.cc");
3610 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3611 FromTU0, classTemplateDecl(hasName("F")));
3612 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3613 Decl *FromTU1 = getTuDecl(
3614 R"(
3615 template <typename T>
3616 class F {};
3617 )",
3618 Lang_CXX, "input1.cc");
3619 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3620 FromTU1, classTemplateDecl(hasName("F")));
3621 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3622 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
3623 Imported1->getTemplatedDecl()->getTypeForDecl());
3624}
3625
3626TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
3627 Decl *From, *To;
3628 std::tie(From, To) =
3629 getImportedDecl("class declToImport {};", Lang_CXX,
3630 "class Y { friend class declToImport; };", Lang_CXX);
3631 auto *Imported = cast<CXXRecordDecl>(To);
3632
3633 EXPECT_TRUE(Imported->getPreviousDecl());
3634}
3635
3636TEST_P(ImportFriendClasses,
3637 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
3638 Decl *ToTU = getToTuDecl(
3639 R"(
3640 class X {
3641 class Y;
3642 };
3643 class X::Y {
3644 template <typename T>
3645 friend class F; // The decl context of F is the global namespace.
3646 };
3647 )",
3648 Lang_CXX);
3649 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
3650 ToTU, classTemplateDecl(hasName("F")));
3651 Decl *FromTU = getTuDecl(
3652 R"(
3653 template <typename T>
3654 class F {};
3655 )",
3656 Lang_CXX, "input0.cc");
3657 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3658 FromTU, classTemplateDecl(hasName("F")));
3659 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3660 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3661 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
3662 EXPECT_EQ(ToDecl->getTemplatedDecl(),
3663 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3664}
3665
3666TEST_P(ImportFriendClasses,
3667 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
3668 Decl *FromTU0 = getTuDecl(
3669 R"(
3670 class X {
3671 class Y;
3672 };
3673 class X::Y {
3674 template <typename T>
3675 friend class F; // The decl context of F is the global namespace.
3676 };
3677 )",
3678 Lang_CXX, "input0.cc");
3679 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
3680 FromTU0, classTemplateDecl(hasName("F")));
3681 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX));
3682 Decl *FromTU1 = getTuDecl(
3683 R"(
3684 template <typename T>
3685 class F {};
3686 )",
3687 Lang_CXX, "input1.cc");
3688 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
3689 FromTU1, classTemplateDecl(hasName("F")));
3690 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX));
3691 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3692 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3693 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
3694 ImportedDef->getTemplatedDecl()->getPreviousDecl());
3695}
3696
3697TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
3698 Decl *FromTU0 = getTuDecl(
3699 R"(
3700 class X {
3701 class Y;
3702 };
3703 class X::Y {
3704 friend class F; // The decl context of F is the global namespace.
3705 };
3706 )",
3707 Lang_CXX, "input0.cc");
3708 auto *Friend = FirstDeclMatcher<FriendDecl>().match(FromTU0, friendDecl());
3709 QualType FT = Friend->getFriendType()->getType();
3710 FT = FromTU0->getASTContext().getCanonicalType(FT);
3711 auto *Fwd = cast<TagType>(FT)->getDecl();
3712 auto *ImportedFwd = Import(Fwd, Lang_CXX);
3713 Decl *FromTU1 = getTuDecl(
3714 R"(
3715 class F {};
3716 )",
3717 Lang_CXX, "input1.cc");
3718 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
3719 FromTU1, cxxRecordDecl(hasName("F")));
3720 auto *ImportedDef = Import(Definition, Lang_CXX);
3721 EXPECT_TRUE(ImportedDef->getPreviousDecl());
3722 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
3723}
3724
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003725TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Gabor Marton54058b52018-12-17 13:53:12 +00003726 auto *Code = R"(
3727 template <class T>
3728 struct X {
3729 friend void foo(){}
3730 };
3731 )";
3732 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
3733 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
3734 ToTU, functionDecl(hasName("foo")));
3735
3736 TranslationUnitDecl *FromTU = getTuDecl(Code, Lang_CXX, "input.cc");
3737 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
3738 FromTU, functionDecl(hasName("foo")));
3739 auto *ImportedFoo = Import(FromFoo, Lang_CXX);
3740 EXPECT_EQ(ImportedFoo, ToFoo);
3741}
3742
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003743struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton61d862a2018-05-18 09:08:47 +00003744
3745TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
3746 Decl *TU = getTuDecl(
3747 R"(
3748 namespace NS {
3749
3750 template <typename T>
3751 struct S {};
3752 template struct S<int>;
3753
3754 inline namespace INS {
3755 template <typename T>
3756 struct S {};
3757 template struct S<int>;
3758 }
3759
3760 }
3761 )", Lang_CXX11, "input0.cc");
3762 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
3763 TU, namespaceDecl());
3764 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3765 TU, classTemplateSpecializationDecl());
3766 ASSERT_TRUE(NS->containsDecl(Spec));
3767
3768 NS->removeDecl(Spec);
3769 EXPECT_FALSE(NS->containsDecl(Spec));
3770}
3771
Gabor Marton7df342a2018-12-17 12:42:12 +00003772TEST_P(DeclContextTest,
3773 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
3774 Decl *TU = getTuDecl("extern int A; int A;", Lang_CXX);
3775 auto *A0 = FirstDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
3776 auto *A1 = LastDeclMatcher<VarDecl>().match(TU, varDecl(hasName("A")));
3777
3778 // Investigate the list.
3779 auto *DC = A0->getDeclContext();
3780 ASSERT_TRUE(DC->containsDecl(A0));
3781 ASSERT_TRUE(DC->containsDecl(A1));
3782
3783 // Investigate the lookup table.
3784 auto *Map = DC->getLookupPtr();
3785 ASSERT_TRUE(Map);
3786 auto I = Map->find(A0->getDeclName());
3787 ASSERT_NE(I, Map->end());
3788 StoredDeclsList &L = I->second;
3789 // The lookup table contains the most recent decl of A.
3790 ASSERT_NE(L.getAsDecl(), A0);
3791 ASSERT_EQ(L.getAsDecl(), A1);
3792
3793 ASSERT_TRUE(L.getAsDecl());
3794 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
3795 // The point here is to have a Vec with only one element, which is not the
3796 // one we are going to delete from the DC later.
3797 L.setHasExternalDecls();
3798 ASSERT_TRUE(L.getAsVector());
3799 ASSERT_EQ(1u, L.getAsVector()->size());
3800
3801 // This asserts in the old implementation.
3802 DC->removeDecl(A0);
3803 EXPECT_FALSE(DC->containsDecl(A0));
3804}
3805
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003806struct ImportFunctionTemplateSpecializations
3807 : ASTImporterOptionSpecificTestBase {};
Gabor Marton5254e642018-06-27 13:32:50 +00003808
3809TEST_P(ImportFunctionTemplateSpecializations,
3810 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
3811
3812 Decl *FromTU = getTuDecl(
3813 R"(
3814 template<class T>
3815 int f() { return 0; }
3816 void foo() { f<int>(); }
3817 )",
3818 Lang_CXX, "input0.cc");
3819
3820 // Check that the function template instantiation is NOT the child of the TU.
3821 auto Pattern = translationUnitDecl(
3822 unless(has(functionDecl(hasName("f"), isTemplateInstantiation()))));
3823 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3824
3825 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
3826 FromTU, functionDecl(hasName("foo")));
3827 ASSERT_TRUE(Import(Foo, Lang_CXX));
3828
3829 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3830 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3831}
3832
3833TEST_P(ImportFunctionTemplateSpecializations,
3834 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
3835
3836 Decl *FromTU = getTuDecl(
3837 R"(
3838 template<class T>
3839 int f() { return 0; }
3840 template int f<int>();
3841 )",
3842 Lang_CXX, "input0.cc");
3843
3844 // Check that the function template instantiation is NOT the child of the TU.
3845 auto Instantiation = functionDecl(hasName("f"), isTemplateInstantiation());
3846 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
3847 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3848
3849 ASSERT_TRUE(
3850 Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation), Lang_CXX));
3851
3852 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3853 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3854}
3855
3856TEST_P(ImportFunctionTemplateSpecializations,
3857 TUshouldContainFunctionTemplateSpecialization) {
3858
3859 Decl *FromTU = getTuDecl(
3860 R"(
3861 template<class T>
3862 int f() { return 0; }
3863 template <> int f<int>() { return 4; }
3864 )",
3865 Lang_CXX, "input0.cc");
3866
3867 // Check that the function template specialization is the child of the TU.
3868 auto Specialization =
3869 functionDecl(hasName("f"), isExplicitTemplateSpecialization());
3870 auto Pattern = translationUnitDecl(has(Specialization));
3871 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
3872
3873 ASSERT_TRUE(
3874 Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization), Lang_CXX));
3875
3876 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3877 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
3878}
3879
3880TEST_P(ImportFunctionTemplateSpecializations,
3881 FunctionTemplateSpecializationRedeclChain) {
3882
3883 Decl *FromTU = getTuDecl(
3884 R"(
3885 template<class T>
3886 int f() { return 0; }
3887 template <> int f<int>() { return 4; }
3888 )",
3889 Lang_CXX, "input0.cc");
3890
3891 auto Spec = functionDecl(hasName("f"), isExplicitTemplateSpecialization(),
3892 hasParent(translationUnitDecl()));
3893 auto *FromSpecD = FirstDeclMatcher<Decl>().match(FromTU, Spec);
3894 {
3895 auto *TU = FromTU;
3896 auto *SpecD = FromSpecD;
3897 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
3898 TU, functionTemplateDecl());
3899 auto *FirstSpecD = *(TemplateD->spec_begin());
3900 ASSERT_EQ(SpecD, FirstSpecD);
3901 ASSERT_TRUE(SpecD->getPreviousDecl());
3902 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
3903 ->doesThisDeclarationHaveABody());
3904 }
3905
3906 ASSERT_TRUE(Import(FromSpecD, Lang_CXX));
3907
3908 {
3909 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
3910 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
3911 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
3912 TU, functionTemplateDecl());
3913 auto *FirstSpecD = *(TemplateD->spec_begin());
3914 EXPECT_EQ(SpecD, FirstSpecD);
3915 ASSERT_TRUE(SpecD->getPreviousDecl());
3916 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
3917 ->doesThisDeclarationHaveABody());
3918 }
3919}
3920
3921TEST_P(ImportFunctionTemplateSpecializations,
3922 MatchNumberOfFunctionTemplateSpecializations) {
3923
3924 Decl *FromTU = getTuDecl(
3925 R"(
3926 template <typename T> constexpr int f() { return 0; }
3927 template <> constexpr int f<int>() { return 4; }
3928 void foo() {
3929 static_assert(f<char>() == 0, "");
3930 static_assert(f<int>() == 4, "");
3931 }
3932 )",
3933 Lang_CXX11, "input0.cc");
3934 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
3935 FromTU, functionDecl(hasName("foo")));
3936
3937 Import(FromD, Lang_CXX11);
3938 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3939 EXPECT_EQ(
3940 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
3941 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
3942}
3943
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003944TEST_P(ASTImporterOptionSpecificTestBase,
Gabor Marton17d39672018-11-26 15:54:08 +00003945 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
3946 {
3947 Decl *FromTU = getTuDecl(
3948 R"(
3949 template <typename T>
3950 struct B;
3951 )",
3952 Lang_CXX, "input0.cc");
3953 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
3954 FromTU, classTemplateDecl(hasName("B")));
3955
3956 Import(FromD, Lang_CXX);
3957 }
3958
3959 {
3960 Decl *FromTU = getTuDecl(
3961 R"(
3962 template <typename T>
3963 struct B {
3964 void f();
3965 B* b;
3966 };
3967 )",
3968 Lang_CXX, "input1.cc");
3969 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
3970 FromTU, functionDecl(hasName("f")));
3971 Import(FromD, Lang_CXX);
3972 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
3973 FromTU, classTemplateDecl(hasName("B")));
3974 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX));
3975 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
3976
3977 // We expect no (ODR) warning during the import.
3978 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3979 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3980 }
3981}
3982
Gabor Marton0b57ccb2019-02-07 16:52:48 +00003983TEST_P(ASTImporterOptionSpecificTestBase,
3984 ImportingTypedefShouldImportTheCompleteType) {
Gabor Martonb93baf62018-11-27 09:51:36 +00003985 // We already have an incomplete underlying type in the "To" context.
3986 auto Code =
3987 R"(
3988 template <typename T>
3989 struct S {
3990 void foo();
3991 };
3992 using U = S<int>;
3993 )";
3994 Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
3995 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
3996 typedefNameDecl(hasName("U")));
3997 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
3998
3999 // The "From" context has the same typedef, but the underlying type is
4000 // complete this time.
4001 Decl *FromTU = getTuDecl(std::string(Code) +
4002 R"(
4003 void foo(U* u) {
4004 u->foo();
4005 }
4006 )", Lang_CXX11);
4007 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
4008 typedefNameDecl(hasName("U")));
4009 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
4010
4011 // The imported type should be complete.
4012 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
4013 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
4014}
4015
Balazs Keri1efc9742019-05-07 10:55:11 +00004016TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) {
4017 auto Code =
4018 R"(
4019 template<class T>
4020 int f() { return 0; }
4021 template <> int f<int>() { return 4; }
4022 )";
4023
4024 Decl *FromTU = getTuDecl(Code, Lang_CXX);
4025 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU,
4026 functionDecl(hasName("f"), isExplicitTemplateSpecialization()));
Balazs Kerib7d8cff2019-05-07 14:53:04 +00004027 ASSERT_EQ(FromD->getNumTemplateParameterLists(), 1u);
Balazs Keri1efc9742019-05-07 10:55:11 +00004028
4029 auto *ToD = Import(FromD, Lang_CXX);
4030 // The template parameter list should exist.
Balazs Kerib7d8cff2019-05-07 14:53:04 +00004031 EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u);
Balazs Keri1efc9742019-05-07 10:55:11 +00004032}
4033
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004034struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
Gabor Marton54058b52018-12-17 13:53:12 +00004035
4036TEST_P(ASTImporterLookupTableTest, OneDecl) {
4037 auto *ToTU = getToTuDecl("int a;", Lang_CXX);
4038 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("a")));
4039 ASTImporterLookupTable LT(*ToTU);
4040 auto Res = LT.lookup(ToTU, D->getDeclName());
4041 ASSERT_EQ(Res.size(), 1u);
4042 EXPECT_EQ(*Res.begin(), D);
4043}
4044
4045static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
4046 for (Decl *D : DC->decls()) {
4047 if (auto *ND = dyn_cast<NamedDecl>(D))
4048 if (ND->getDeclName() == Name)
4049 return ND;
4050 }
4051 return nullptr;
Martin Storsjo85833392018-12-18 08:36:16 +00004052}
Gabor Marton54058b52018-12-17 13:53:12 +00004053
4054TEST_P(ASTImporterLookupTableTest,
4055 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
4056 auto *Code = R"(
4057 template <class T>
4058 struct X {
4059 friend void foo(){}
4060 };
4061 )";
4062 TranslationUnitDecl *ToTU = getToTuDecl(Code, Lang_CXX);
4063 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
4064 ToTU, classTemplateDecl(hasName("X")));
4065 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4066 ToTU, functionDecl(hasName("foo")));
4067 DeclContext *FooDC = Foo->getDeclContext();
4068 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4069 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
4070 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4071 DeclarationName FooName = Foo->getDeclName();
4072
4073 // Cannot find in the LookupTable of its DC (TUDecl)
4074 SmallVector<NamedDecl *, 2> FoundDecls;
4075 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4076 EXPECT_EQ(FoundDecls.size(), 0u);
4077
4078 // Cannot find in the LookupTable of its LexicalDC (X)
4079 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4080 EXPECT_EQ(FoundDecls.size(), 0u);
4081
4082 // Can't find in the list of Decls of the DC.
4083 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4084
4085 // Can't find in the list of Decls of the LexicalDC
4086 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
4087
4088 // ASTImporter specific lookup finds it.
4089 ASTImporterLookupTable LT(*ToTU);
4090 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4091 ASSERT_EQ(Res.size(), 1u);
4092 EXPECT_EQ(*Res.begin(), Foo);
4093}
4094
4095TEST_P(ASTImporterLookupTableTest,
4096 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
4097 TranslationUnitDecl *ToTU =
4098 getToTuDecl("struct A { struct Foo *p; };", Lang_C);
4099 auto *Foo =
4100 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("Foo")));
4101 auto *A =
4102 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4103 DeclContext *FooDC = Foo->getDeclContext();
4104 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
4105 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
4106 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
4107 DeclarationName FooName = Foo->getDeclName();
4108
4109 // Cannot find in the LookupTable of its DC (TUDecl).
4110 SmallVector<NamedDecl *, 2> FoundDecls;
4111 FooDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4112 EXPECT_EQ(FoundDecls.size(), 0u);
4113
4114 // Cannot find in the LookupTable of its LexicalDC (A).
4115 FooLexicalDC->getRedeclContext()->localUncachedLookup(FooName, FoundDecls);
4116 EXPECT_EQ(FoundDecls.size(), 0u);
4117
4118 // Can't find in the list of Decls of the DC.
4119 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
4120
4121 // Can find in the list of Decls of the LexicalDC.
4122 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
4123
4124 // ASTImporter specific lookup finds it.
4125 ASTImporterLookupTable LT(*ToTU);
4126 auto Res = LT.lookup(FooDC, Foo->getDeclName());
4127 ASSERT_EQ(Res.size(), 1u);
4128 EXPECT_EQ(*Res.begin(), Foo);
4129}
4130
4131TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
4132 TranslationUnitDecl *ToTU =
4133 getToTuDecl("int V; struct A { int V; }; struct B { int V; };", Lang_C);
4134 DeclarationName VName = FirstDeclMatcher<VarDecl>()
4135 .match(ToTU, varDecl(hasName("V")))
4136 ->getDeclName();
4137 auto *A =
4138 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));
4139 auto *B =
4140 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("B")));
4141
4142 ASTImporterLookupTable LT(*ToTU);
4143
4144 auto Res = LT.lookup(cast<DeclContext>(A), VName);
4145 ASSERT_EQ(Res.size(), 1u);
4146 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4147 ToTU, fieldDecl(hasName("V"),
4148 hasParent(recordDecl(hasName("A"))))));
4149 Res = LT.lookup(cast<DeclContext>(B), VName);
4150 ASSERT_EQ(Res.size(), 1u);
4151 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
4152 ToTU, fieldDecl(hasName("V"),
4153 hasParent(recordDecl(hasName("B"))))));
4154 Res = LT.lookup(ToTU, VName);
4155 ASSERT_EQ(Res.size(), 1u);
4156 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
4157 ToTU, varDecl(hasName("V"),
4158 hasParent(translationUnitDecl()))));
4159}
4160
4161TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
4162 TranslationUnitDecl *ToTU = getToTuDecl(
4163 R"(
4164 void foo();
4165 void foo(int);
4166 void foo(int, int);
4167 )",
4168 Lang_CXX);
4169
4170 ASTImporterLookupTable LT(*ToTU);
4171 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4172 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
4173 DeclarationName Name = F0->getDeclName();
4174 auto Res = LT.lookup(ToTU, Name);
4175 EXPECT_EQ(Res.size(), 3u);
4176 EXPECT_EQ(Res.count(F0), 1u);
4177 EXPECT_EQ(Res.count(F2), 1u);
4178}
4179
Gabor Martona9cab312019-02-08 09:19:34 +00004180TEST_P(ASTImporterLookupTableTest,
4181 DifferentOperatorsShouldHaveDifferentResultSet) {
4182 TranslationUnitDecl *ToTU = getToTuDecl(
4183 R"(
4184 struct X{};
4185 void operator+(X, X);
4186 void operator-(X, X);
4187 )",
4188 Lang_CXX);
4189
4190 ASTImporterLookupTable LT(*ToTU);
4191 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
4192 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4193 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
4194 ToTU, functionDecl(hasOverloadedOperatorName("-")));
4195 DeclarationName NamePlus = FPlus->getDeclName();
4196 auto ResPlus = LT.lookup(ToTU, NamePlus);
4197 EXPECT_EQ(ResPlus.size(), 1u);
4198 EXPECT_EQ(ResPlus.count(FPlus), 1u);
4199 EXPECT_EQ(ResPlus.count(FMinus), 0u);
4200 DeclarationName NameMinus = FMinus->getDeclName();
4201 auto ResMinus = LT.lookup(ToTU, NameMinus);
4202 EXPECT_EQ(ResMinus.size(), 1u);
4203 EXPECT_EQ(ResMinus.count(FMinus), 1u);
4204 EXPECT_EQ(ResMinus.count(FPlus), 0u);
4205 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
4206}
4207
4208TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
4209 TranslationUnitDecl *ToTU = getToTuDecl(
4210 R"(
4211 struct X {};
4212 void operator+(X, X);
4213 )",
4214 Lang_CXX);
4215 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
4216 ToTU, functionDecl(hasOverloadedOperatorName("+")));
4217
4218 Decl *FromTU = getTuDecl(
4219 R"(
4220 struct X {};
4221 void operator+(X, X);
4222 )",
4223 Lang_CXX);
4224 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
4225 FromTU, functionDecl(hasOverloadedOperatorName("+")));
4226
4227 // FromPlus have a different TU, thus its DeclarationName is different too.
4228 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
4229
4230 ASTImporterLookupTable LT(*ToTU);
4231 auto Res = LT.lookup(ToTU, ToPlus->getDeclName());
4232 ASSERT_EQ(Res.size(), 1u);
4233 EXPECT_EQ(*Res.begin(), ToPlus);
4234
4235 // FromPlus have a different TU, thus its DeclarationName is different too.
4236 Res = LT.lookup(ToTU, FromPlus->getDeclName());
4237 ASSERT_EQ(Res.size(), 0u);
4238}
4239
Gabor Martondd2b76e2019-06-11 13:35:25 +00004240static const RecordDecl *getRecordDeclOfFriend(FriendDecl *FD) {
4241 QualType Ty = FD->getFriendType()->getType().getCanonicalType();
4242 return cast<RecordType>(Ty)->getDecl();
Gabor Marton54058b52018-12-17 13:53:12 +00004243}
4244
Gabor Martondd2b76e2019-06-11 13:35:25 +00004245TEST_P(ASTImporterLookupTableTest,
4246 LookupFindsFwdFriendClassDeclWithElaboratedType) {
Gabor Marton54058b52018-12-17 13:53:12 +00004247 TranslationUnitDecl *ToTU = getToTuDecl(
4248 R"(
4249 class Y { friend class F; };
4250 )",
4251 Lang_CXX);
4252
4253 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4254 // So we must dig up the underlying CXXRecordDecl.
4255 ASTImporterLookupTable LT(*ToTU);
4256 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4257 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4258 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
4259 ToTU, cxxRecordDecl(hasName("Y")));
4260
4261 DeclarationName Name = RD->getDeclName();
4262 auto Res = LT.lookup(ToTU, Name);
4263 EXPECT_EQ(Res.size(), 1u);
4264 EXPECT_EQ(*Res.begin(), RD);
4265
4266 Res = LT.lookup(Y, Name);
4267 EXPECT_EQ(Res.size(), 0u);
4268}
4269
Gabor Martondd2b76e2019-06-11 13:35:25 +00004270TEST_P(ASTImporterLookupTableTest,
4271 LookupFindsFwdFriendClassDeclWithUnelaboratedType) {
4272 TranslationUnitDecl *ToTU = getToTuDecl(
4273 R"(
4274 class F;
4275 class Y { friend F; };
4276 )",
4277 Lang_CXX11);
4278
4279 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
4280 // So we must dig up the underlying CXXRecordDecl.
4281 ASTImporterLookupTable LT(*ToTU);
4282 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4283 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
4284 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, cxxRecordDecl(hasName("Y")));
4285
4286 DeclarationName Name = RD->getDeclName();
4287 auto Res = LT.lookup(ToTU, Name);
4288 EXPECT_EQ(Res.size(), 1u);
4289 EXPECT_EQ(*Res.begin(), RD);
4290
4291 Res = LT.lookup(Y, Name);
4292 EXPECT_EQ(Res.size(), 0u);
4293}
4294
4295TEST_P(ASTImporterLookupTableTest,
4296 LookupFindsFriendClassDeclWithTypeAliasDoesNotAssert) {
4297 TranslationUnitDecl *ToTU = getToTuDecl(
4298 R"(
4299 class F;
4300 using alias_of_f = F;
4301 class Y { friend alias_of_f; };
4302 )",
4303 Lang_CXX11);
4304
4305 // ASTImporterLookupTable constructor handles using declarations correctly,
4306 // no assert is expected.
4307 ASTImporterLookupTable LT(*ToTU);
4308
4309 auto *Alias = FirstDeclMatcher<TypeAliasDecl>().match(
4310 ToTU, typeAliasDecl(hasName("alias_of_f")));
4311 DeclarationName Name = Alias->getDeclName();
4312 auto Res = LT.lookup(ToTU, Name);
4313 EXPECT_EQ(Res.count(Alias), 1u);
4314}
4315
Gabor Marton54058b52018-12-17 13:53:12 +00004316TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
4317 TranslationUnitDecl *ToTU = getToTuDecl(
4318 R"(
4319 class Y { template <class T> friend class F; };
4320 )",
4321 Lang_CXX);
4322
4323 ASTImporterLookupTable LT(*ToTU);
4324 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4325 ToTU, classTemplateDecl(hasName("F")));
4326 DeclarationName Name = F->getDeclName();
4327 auto Res = LT.lookup(ToTU, Name);
4328 EXPECT_EQ(Res.size(), 2u);
4329 EXPECT_EQ(Res.count(F), 1u);
4330 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4331}
4332
4333TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
4334 TranslationUnitDecl *ToTU = getToTuDecl(
4335 R"(
4336 template <typename T>
4337 class F;
4338
4339 template <typename T>
4340 class Y {
4341 friend class F<T>;
4342 };
4343 )",
4344 Lang_CXX);
4345
4346 ASTImporterLookupTable LT(*ToTU);
4347 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4348 ToTU, classTemplateDecl(hasName("F")));
4349 DeclarationName Name = F->getDeclName();
4350 auto Res = LT.lookup(ToTU, Name);
4351 EXPECT_EQ(Res.size(), 2u);
4352 EXPECT_EQ(Res.count(F), 1u);
4353 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4354}
4355
4356TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
4357 TranslationUnitDecl *ToTU = getToTuDecl(
4358 R"(
4359 template <typename T>
4360 class F;
4361
4362 class Y {
4363 friend class F<int>;
4364 };
4365 )",
4366 Lang_CXX);
4367
4368 ASTImporterLookupTable LT(*ToTU);
4369 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
4370 ToTU, classTemplateDecl(hasName("F")));
4371 DeclarationName Name = F->getDeclName();
4372 auto Res = LT.lookup(ToTU, Name);
4373 ASSERT_EQ(Res.size(), 3u);
4374 EXPECT_EQ(Res.count(F), 1u);
4375 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4376 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
4377}
4378
4379TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
4380 TranslationUnitDecl *ToTU = getToTuDecl(
4381 R"(
4382 class Y { friend void F(); };
4383 )",
4384 Lang_CXX);
4385
4386 ASTImporterLookupTable LT(*ToTU);
4387 auto *F =
4388 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("F")));
4389 DeclarationName Name = F->getDeclName();
4390 auto Res = LT.lookup(ToTU, Name);
4391 EXPECT_EQ(Res.size(), 1u);
4392 EXPECT_EQ(*Res.begin(), F);
4393}
4394
4395TEST_P(ASTImporterLookupTableTest,
4396 LookupFindsDeclsInClassTemplateSpecialization) {
4397 TranslationUnitDecl *ToTU = getToTuDecl(
4398 R"(
4399 template <typename T>
4400 struct X {
4401 int F;
4402 };
4403 void foo() {
4404 X<char> xc;
4405 }
4406 )",
4407 Lang_CXX);
4408
4409 ASTImporterLookupTable LT(*ToTU);
4410
4411 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
4412 ToTU, classTemplateDecl(hasName("X")));
4413 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
4414 ToTU,
4415 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
4416
4417 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4418 ToTU, classTemplateSpecializationDecl(hasName("X")));
4419 FieldDecl *FieldInSpec = *Spec->field_begin();
4420 ASSERT_TRUE(FieldInSpec);
4421
4422 DeclarationName Name = FieldInSpec->getDeclName();
4423 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
4424
4425 SmallVector<NamedDecl *, 2> FoundDecls;
4426 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
4427 EXPECT_EQ(FoundDecls.size(), 1u);
4428 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
4429
4430 auto Res = LT.lookup(TemplateDC, Name);
4431 ASSERT_EQ(Res.size(), 1u);
4432 EXPECT_EQ(*Res.begin(), FieldInTemplate);
4433
4434 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
4435 FoundDecls);
4436 EXPECT_EQ(FoundDecls.size(), 1u);
4437 EXPECT_EQ(FoundDecls[0], FieldInSpec);
4438
4439 Res = LT.lookup(cast<DeclContext>(Spec), Name);
4440 ASSERT_EQ(Res.size(), 1u);
4441 EXPECT_EQ(*Res.begin(), FieldInSpec);
4442}
4443
4444TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
4445 TranslationUnitDecl *ToTU = getToTuDecl(
4446 R"(
4447 class Y { template <class T> friend void F(); };
4448 )",
4449 Lang_CXX);
4450
4451 ASTImporterLookupTable LT(*ToTU);
4452 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
4453 ToTU, functionTemplateDecl(hasName("F")));
4454 DeclarationName Name = F->getDeclName();
4455 auto Res = LT.lookup(ToTU, Name);
4456 EXPECT_EQ(Res.size(), 2u);
4457 EXPECT_EQ(Res.count(F), 1u);
4458 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
4459}
4460
4461TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
4462 TranslationUnitDecl *ToTU = getToTuDecl(
4463 R"(
4464 struct X;
4465 struct A {
4466 friend struct X;
4467 };
4468 struct B {
4469 friend struct X;
4470 };
4471 )",
4472 Lang_CXX);
4473
4474 ASTImporterLookupTable LT(*ToTU);
4475 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
4476 ToTU, cxxRecordDecl(hasName("X")));
4477 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4478 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
4479 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
4480 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
4481 ASSERT_EQ(RD0, RD1);
4482 ASSERT_EQ(RD1, X);
4483
4484 DeclarationName Name = X->getDeclName();
4485 auto Res = LT.lookup(ToTU, Name);
4486 EXPECT_EQ(Res.size(), 1u);
4487 EXPECT_EQ(*Res.begin(), X);
4488}
4489
4490TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
4491 TranslationUnitDecl *ToTU = getToTuDecl(
4492 R"(
4493 enum E {
4494 A,
4495 B
4496 };
4497 )",
4498 Lang_C);
4499
4500 ASTImporterLookupTable LT(*ToTU);
4501 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName("E")));
4502 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
4503 ToTU, enumConstantDecl(hasName("A")));
4504
4505 DeclarationName Name = A->getDeclName();
4506 // Redecl context is the TU.
4507 ASSERT_EQ(E->getRedeclContext(), ToTU);
4508
4509 SmallVector<NamedDecl *, 2> FoundDecls;
4510 // Normal lookup finds in the DC.
4511 E->localUncachedLookup(Name, FoundDecls);
4512 EXPECT_EQ(FoundDecls.size(), 1u);
4513
4514 // Normal lookup finds in the Redecl context.
4515 ToTU->localUncachedLookup(Name, FoundDecls);
4516 EXPECT_EQ(FoundDecls.size(), 1u);
4517
4518 // Import specific lookup finds in the DC.
4519 auto Res = LT.lookup(E, Name);
4520 ASSERT_EQ(Res.size(), 1u);
4521 EXPECT_EQ(*Res.begin(), A);
4522
4523 // Import specific lookup finds in the Redecl context.
4524 Res = LT.lookup(ToTU, Name);
4525 ASSERT_EQ(Res.size(), 1u);
4526 EXPECT_EQ(*Res.begin(), A);
4527}
4528
4529TEST_P(ASTImporterLookupTableTest, LookupSearchesInTheWholeRedeclChain) {
4530 TranslationUnitDecl *ToTU = getToTuDecl(
4531 R"(
4532 namespace N {
4533 int A;
4534 }
4535 namespace N {
4536 }
4537 )",
4538 Lang_CXX);
4539 auto *N1 =
4540 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName("N")));
4541 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName("A")));
4542 DeclarationName Name = A->getDeclName();
4543
4544 ASTImporterLookupTable LT(*ToTU);
4545 auto Res = LT.lookup(N1, Name);
4546 ASSERT_EQ(Res.size(), 1u);
4547 EXPECT_EQ(*Res.begin(), A);
4548}
4549
Gabor Marton19f4f392018-06-25 13:04:37 +00004550INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
4551 ::testing::Values(ArgVector()), );
4552
Gabor Marton5254e642018-06-27 13:32:50 +00004553INSTANTIATE_TEST_CASE_P(
4554 ParameterizedTests, CanonicalRedeclChain,
4555 ::testing::Values(ArgVector()),);
4556
Gabor Marton0e04ebd2019-02-11 10:27:58 +00004557// FIXME This test is disabled currently, upcoming patches will make it
4558// possible to enable.
4559TEST_P(ASTImporterOptionSpecificTestBase,
4560 DISABLED_RedeclChainShouldBeCorrectAmongstNamespaces) {
4561 Decl *FromTU = getTuDecl(
4562 R"(
4563 namespace NS {
4564 struct X;
4565 struct Y {
4566 static const int I = 3;
4567 };
4568 }
4569 namespace NS {
4570 struct X { // <--- To be imported
4571 void method(int i = Y::I) {}
4572 int f;
4573 };
4574 }
4575 )",
4576 Lang_CXX);
4577 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
4578 FromTU, cxxRecordDecl(hasName("X"), unless(isImplicit())));
4579 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
4580 FromTU,
4581 cxxRecordDecl(hasName("X"), isDefinition(), unless(isImplicit())));
4582 ASSERT_NE(FromFwd, FromDef);
4583 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
4584 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
4585 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
4586
4587 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX));
4588 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX));
4589 EXPECT_NE(ToFwd, ToDef);
4590 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
4591 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4592 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
4593 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4594 // We expect no (ODR) warning during the import.
4595 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
4596}
4597
Gabor Martone331e632019-02-18 13:09:27 +00004598struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
4599
4600TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
4601 Decl *ToTU = getToTuDecl(
4602 R"(
4603 class X {
4604 template <typename T> friend void foo();
4605 };
4606 )",
4607 Lang_CXX);
4608 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
4609 ToTU, functionTemplateDecl(hasName("foo")));
4610
4611 Decl *FromTU = getTuDecl(
4612 R"(
4613 template <typename T> void foo();
4614 )",
4615 Lang_CXX);
4616 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
4617 FromTU, functionTemplateDecl(hasName("foo")));
4618 auto *Imported = Import(FromFoo, Lang_CXX);
4619
Gabor Marton16d98c22019-03-07 13:01:51 +00004620 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
Gabor Martone331e632019-02-18 13:09:27 +00004621}
4622
Gabor Marton303c98612019-06-25 08:00:51 +00004623struct ASTImporterWithFakeErrors : ASTImporter {
4624 using ASTImporter::ASTImporter;
4625 bool returnWithErrorInTest() override { return true; }
4626};
4627
4628struct ErrorHandlingTest : ASTImporterOptionSpecificTestBase {
4629 ErrorHandlingTest() {
4630 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
4631 ASTContext &FromContext, FileManager &FromFileManager,
4632 bool MinimalImport, ASTImporterLookupTable *LookupTable) {
4633 return new ASTImporterWithFakeErrors(ToContext, ToFileManager,
4634 FromContext, FromFileManager,
4635 MinimalImport, LookupTable);
4636 };
4637 }
4638 // In this test we purposely report an error (UnsupportedConstruct) when
4639 // importing the below stmt.
4640 static constexpr auto* ErroneousStmt = R"( asm(""); )";
4641};
4642
4643// Check a case when no new AST node is created in the AST before encountering
4644// the error.
4645TEST_P(ErrorHandlingTest, ErrorHappensBeforeCreatingANewNode) {
4646 TranslationUnitDecl *ToTU = getToTuDecl(
4647 R"(
4648 template <typename T>
4649 class X {};
4650 template <>
4651 class X<int> { int a; };
4652 )",
4653 Lang_CXX);
4654 TranslationUnitDecl *FromTU = getTuDecl(
4655 R"(
4656 template <typename T>
4657 class X {};
4658 template <>
4659 class X<int> { double b; };
4660 )",
4661 Lang_CXX);
4662 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4663 FromTU, classTemplateSpecializationDecl(hasName("X")));
4664 ClassTemplateSpecializationDecl *ImportedSpec = Import(FromSpec, Lang_CXX);
4665 EXPECT_FALSE(ImportedSpec);
4666
4667 // The original Decl is kept, no new decl is created.
4668 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(
4669 ToTU, classTemplateSpecializationDecl(hasName("X"))),
4670 1u);
4671
4672 // But an error is set to the counterpart in the "from" context.
4673 ASTImporter *Importer = findFromTU(FromSpec)->Importer.get();
4674 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromSpec);
4675 ASSERT_TRUE(OptErr);
4676 EXPECT_EQ(OptErr->Error, ImportError::NameConflict);
4677}
4678
4679// Check a case when a new AST node is created but not linked to the AST before
4680// encountering the error.
4681TEST_P(ErrorHandlingTest,
4682 ErrorHappensAfterCreatingTheNodeButBeforeLinkingThatToTheAST) {
4683 TranslationUnitDecl *FromTU = getTuDecl(
4684 std::string("void foo() { ") + ErroneousStmt + " }",
4685 Lang_CXX);
4686 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4687 FromTU, functionDecl(hasName("foo")));
4688
4689 FunctionDecl *ImportedFoo = Import(FromFoo, Lang_CXX);
4690 EXPECT_FALSE(ImportedFoo);
4691
4692 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4693 // Created, but not linked.
4694 EXPECT_EQ(
4695 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("foo"))),
4696 0u);
4697
4698 ASTImporter *Importer = findFromTU(FromFoo)->Importer.get();
4699 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromFoo);
4700 ASSERT_TRUE(OptErr);
4701 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4702}
4703
4704// Check a case when a new AST node is created and linked to the AST before
4705// encountering the error. The error is set for the counterpart of the nodes in
4706// the "from" context.
4707TEST_P(ErrorHandlingTest, ErrorHappensAfterNodeIsCreatedAndLinked) {
4708 TranslationUnitDecl *FromTU = getTuDecl(
4709 std::string(R"(
4710 void f();
4711 void f() { )") + ErroneousStmt + R"( }
4712 )",
4713 Lang_CXX);
4714 auto *FromProto = FirstDeclMatcher<FunctionDecl>().match(
4715 FromTU, functionDecl(hasName("f")));
4716 auto *FromDef =
4717 LastDeclMatcher<FunctionDecl>().match(FromTU, functionDecl(hasName("f")));
4718 FunctionDecl *ImportedProto = Import(FromProto, Lang_CXX);
4719 EXPECT_FALSE(ImportedProto); // Could not import.
4720 // However, we created two nodes in the AST. 1) the fwd decl 2) the
4721 // definition. The definition is not added to its DC, but the fwd decl is
4722 // there.
4723 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4724 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
4725 1u);
4726 // Match the fwd decl.
4727 auto *ToProto =
4728 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName("f")));
4729 EXPECT_TRUE(ToProto);
4730 // An error is set to the counterpart in the "from" context both for the fwd
4731 // decl and the definition.
4732 ASTImporter *Importer = findFromTU(FromProto)->Importer.get();
4733 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromProto);
4734 ASSERT_TRUE(OptErr);
4735 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4736 OptErr = Importer->getImportDeclErrorIfAny(FromDef);
4737 ASSERT_TRUE(OptErr);
4738 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4739}
4740
Gabor Marton17c3eaf2019-07-01 12:44:39 +00004741// An error should be set for a class if we cannot import one member.
4742TEST_P(ErrorHandlingTest, ErrorIsPropagatedFromMemberToClass) {
4743 TranslationUnitDecl *FromTU = getTuDecl(
4744 std::string(R"(
4745 class X {
4746 void f() { )") + ErroneousStmt + R"( } // This member has the error
4747 // during import.
4748 void ok(); // The error should not prevent importing this.
4749 }; // An error will be set for X too.
4750 )",
4751 Lang_CXX);
4752 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
4753 FromTU, cxxRecordDecl(hasName("X")));
4754 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX);
4755
4756 // An error is set for X.
4757 EXPECT_FALSE(ImportedX);
4758 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
4759 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
4760 ASSERT_TRUE(OptErr);
4761 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4762
4763 // An error is set for f().
4764 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
4765 FromTU, cxxMethodDecl(hasName("f")));
4766 OptErr = Importer->getImportDeclErrorIfAny(FromF);
4767 ASSERT_TRUE(OptErr);
4768 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4769 // And any subsequent import should fail.
4770 CXXMethodDecl *ImportedF = Import(FromF, Lang_CXX);
4771 EXPECT_FALSE(ImportedF);
4772
4773 // There is no error set for ok().
4774 auto *FromOK = FirstDeclMatcher<CXXMethodDecl>().match(
4775 FromTU, cxxMethodDecl(hasName("ok")));
4776 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
4777 EXPECT_FALSE(OptErr);
4778 // And we should be able to import.
4779 CXXMethodDecl *ImportedOK = Import(FromOK, Lang_CXX);
4780 EXPECT_TRUE(ImportedOK);
4781
4782 // Unwary clients may access X even if the error is set, so, at least make
4783 // sure the class is set to be complete.
4784 CXXRecordDecl *ToX = cast<CXXRecordDecl>(ImportedOK->getDeclContext());
4785 EXPECT_TRUE(ToX->isCompleteDefinition());
4786}
4787
4788TEST_P(ErrorHandlingTest, ErrorIsNotPropagatedFromMemberToNamespace) {
4789 TranslationUnitDecl *FromTU = getTuDecl(
4790 std::string(R"(
4791 namespace X {
4792 void f() { )") + ErroneousStmt + R"( } // This member has the error
4793 // during import.
4794 void ok(); // The error should not prevent importing this.
4795 }; // An error will be set for X too.
4796 )",
4797 Lang_CXX);
4798 auto *FromX = FirstDeclMatcher<NamespaceDecl>().match(
4799 FromTU, namespaceDecl(hasName("X")));
4800 NamespaceDecl *ImportedX = Import(FromX, Lang_CXX);
4801
4802 // There is no error set for X.
4803 EXPECT_TRUE(ImportedX);
4804 ASTImporter *Importer = findFromTU(FromX)->Importer.get();
4805 Optional<ImportError> OptErr = Importer->getImportDeclErrorIfAny(FromX);
4806 ASSERT_FALSE(OptErr);
4807
4808 // An error is set for f().
4809 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
4810 FromTU, functionDecl(hasName("f")));
4811 OptErr = Importer->getImportDeclErrorIfAny(FromF);
4812 ASSERT_TRUE(OptErr);
4813 EXPECT_EQ(OptErr->Error, ImportError::UnsupportedConstruct);
4814 // And any subsequent import should fail.
4815 FunctionDecl *ImportedF = Import(FromF, Lang_CXX);
4816 EXPECT_FALSE(ImportedF);
4817
4818 // There is no error set for ok().
4819 auto *FromOK = FirstDeclMatcher<FunctionDecl>().match(
4820 FromTU, functionDecl(hasName("ok")));
4821 OptErr = Importer->getImportDeclErrorIfAny(FromOK);
4822 EXPECT_FALSE(OptErr);
4823 // And we should be able to import.
4824 FunctionDecl *ImportedOK = Import(FromOK, Lang_CXX);
4825 EXPECT_TRUE(ImportedOK);
4826}
4827
Gabor Marton303c98612019-06-25 08:00:51 +00004828INSTANTIATE_TEST_CASE_P(ParameterizedTests, ErrorHandlingTest,
4829 DefaultTestValuesForRunOptions, );
4830
Gabor Marton54058b52018-12-17 13:53:12 +00004831INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
4832 DefaultTestValuesForRunOptions, );
4833
Gabor Marton19f4f392018-06-25 13:04:37 +00004834INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportExpr,
4835 DefaultTestValuesForRunOptions, );
4836
4837INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportType,
4838 DefaultTestValuesForRunOptions, );
4839
4840INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
4841 DefaultTestValuesForRunOptions, );
4842
Gabor Marton0b57ccb2019-02-07 16:52:48 +00004843INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
Gabor Marton19f4f392018-06-25 13:04:37 +00004844 DefaultTestValuesForRunOptions, );
4845
Raphael Isemanne9bc35f2019-04-29 21:02:35 +00004846INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedirectingImporterTest,
4847 DefaultTestValuesForRunOptions, );
4848
Gabor Marton19f4f392018-06-25 13:04:37 +00004849INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
4850 DefaultTestValuesForRunOptions, );
Gabor Marton61d862a2018-05-18 09:08:47 +00004851
Gabor Martone331e632019-02-18 13:09:27 +00004852INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
4853 DefaultTestValuesForRunOptions, );
4854
Gabor Marton54058b52018-12-17 13:53:12 +00004855INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
Gabor Marton5254e642018-06-27 13:32:50 +00004856 DefaultTestValuesForRunOptions, );
4857
Gabor Marton54058b52018-12-17 13:53:12 +00004858INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
Gabor Marton7df342a2018-12-17 12:42:12 +00004859 DefaultTestValuesForRunOptions, );
4860
Gabor Marton7df342a2018-12-17 12:42:12 +00004861INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendClasses,
4862 DefaultTestValuesForRunOptions, );
4863
Gabor Marton5254e642018-06-27 13:32:50 +00004864INSTANTIATE_TEST_CASE_P(ParameterizedTests,
4865 ImportFunctionTemplateSpecializations,
4866 DefaultTestValuesForRunOptions, );
4867
Gabor Martonac3a5d62018-09-17 12:04:52 +00004868INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportImplicitMethods,
4869 DefaultTestValuesForRunOptions, );
4870
4871INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
4872 DefaultTestValuesForRunOptions, );
4873
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00004874} // end namespace ast_matchers
4875} // end namespace clang