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