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/AST/RecordLayout.h"
14#include "clang/ASTMatchers/ASTMatchers.h"
15#include "clang/Testing/CommandLineArgs.h"
16#include "llvm/Support/SmallVectorMemoryBuffer.h"
17
18#include "clang/AST/DeclContextInternals.h"
19#include "gtest/gtest.h"
20
21#include "ASTImporterFixtures.h"
22#include <optional>
23
24namespace clang {
25namespace ast_matchers {
26
27using internal::Matcher;
28
29static const RecordDecl *getRecordDeclOfFriend(FriendDecl *FD) {
30 QualType Ty = FD->getFriendType()->getType().getCanonicalType();
31 return cast<RecordType>(Val&: Ty)->getDecl();
32}
33
34struct ImportExpr : TestImportBase {};
35struct ImportType : TestImportBase {};
36struct ImportDecl : TestImportBase {};
37struct ImportFixedPointExpr : ImportExpr {};
38
39struct CanonicalRedeclChain : ASTImporterOptionSpecificTestBase {};
40
41TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
42 Decl *FromTU = getTuDecl(SrcCode: "void f();", Lang: Lang_CXX03);
43 auto Pattern = functionDecl(hasName(Name: "f"));
44 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
45
46 auto Redecls = getCanonicalForwardRedeclChain(D0);
47 ASSERT_EQ(Redecls.size(), 1u);
48 EXPECT_EQ(D0, Redecls[0]);
49}
50
51TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
52 Decl *FromTU = getTuDecl(SrcCode: "void f(); void f(); void f();", Lang: Lang_CXX03);
53 auto Pattern = functionDecl(hasName(Name: "f"));
54 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
55 auto *D2 = LastDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
56 FunctionDecl *D1 = D2->getPreviousDecl();
57
58 auto Redecls = getCanonicalForwardRedeclChain(D0);
59 ASSERT_EQ(Redecls.size(), 3u);
60 EXPECT_EQ(D0, Redecls[0]);
61 EXPECT_EQ(D1, Redecls[1]);
62 EXPECT_EQ(D2, Redecls[2]);
63}
64
65TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
66 Decl *FromTU = getTuDecl(SrcCode: "void f(); void f(); void f();", Lang: Lang_CXX03);
67 auto Pattern = functionDecl(hasName(Name: "f"));
68 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
69 auto *D2 = LastDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
70 FunctionDecl *D1 = D2->getPreviousDecl();
71
72 auto RedeclsD0 = getCanonicalForwardRedeclChain(D0);
73 auto RedeclsD1 = getCanonicalForwardRedeclChain(D1);
74 auto RedeclsD2 = getCanonicalForwardRedeclChain(D2);
75
76 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
77 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
78}
79
80namespace {
81struct RedirectingImporter : public ASTImporter {
82 using ASTImporter::ASTImporter;
83
84protected:
85 llvm::Expected<Decl *> ImportImpl(Decl *FromD) override {
86 auto *ND = dyn_cast<NamedDecl>(Val: FromD);
87 if (!ND || ND->getName() != "shouldNotBeImported")
88 return ASTImporter::ImportImpl(From: FromD);
89 for (Decl *D : getToContext().getTranslationUnitDecl()->decls()) {
90 if (auto *ND = dyn_cast<NamedDecl>(D))
91 if (ND->getName() == "realDecl") {
92 RegisterImportedDecl(FromD, ND);
93 return ND;
94 }
95 }
96 return ASTImporter::ImportImpl(From: FromD);
97 }
98};
99
100} // namespace
101
102struct RedirectingImporterTest : ASTImporterOptionSpecificTestBase {
103 RedirectingImporterTest() {
104 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
105 ASTContext &FromContext, FileManager &FromFileManager,
106 bool MinimalImport,
107 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
108 return new RedirectingImporter(ToContext, ToFileManager, FromContext,
109 FromFileManager, MinimalImport,
110 SharedState);
111 };
112 }
113};
114
115// Test that an ASTImporter subclass can intercept an import call.
116TEST_P(RedirectingImporterTest, InterceptImport) {
117 Decl *From, *To;
118 std::tie(args&: From, args&: To) =
119 getImportedDecl(FromSrcCode: "class shouldNotBeImported {};", FromLang: Lang_CXX03,
120 ToSrcCode: "class realDecl {};", ToLang: Lang_CXX03, Identifier: "shouldNotBeImported");
121 auto *Imported = cast<CXXRecordDecl>(Val: To);
122 EXPECT_EQ(Imported->getQualifiedNameAsString(), "realDecl");
123
124 // Make sure our importer prevented the importing of the decl.
125 auto *ToTU = Imported->getTranslationUnitDecl();
126 auto Pattern = functionDecl(hasName(Name: "shouldNotBeImported"));
127 unsigned count =
128 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
129 EXPECT_EQ(0U, count);
130}
131
132// Test that when we indirectly import a declaration the custom ASTImporter
133// is still intercepting the import.
134TEST_P(RedirectingImporterTest, InterceptIndirectImport) {
135 Decl *From, *To;
136 std::tie(args&: From, args&: To) =
137 getImportedDecl(FromSrcCode: "class shouldNotBeImported {};"
138 "class F { shouldNotBeImported f; };",
139 FromLang: Lang_CXX03, ToSrcCode: "class realDecl {};", ToLang: Lang_CXX03, Identifier: "F");
140
141 // Make sure our ASTImporter prevented the importing of the decl.
142 auto *ToTU = To->getTranslationUnitDecl();
143 auto Pattern = functionDecl(hasName(Name: "shouldNotBeImported"));
144 unsigned count =
145 DeclCounterWithPredicate<CXXRecordDecl>().match(ToTU, Pattern);
146 EXPECT_EQ(0U, count);
147}
148
149struct ImportPath : ASTImporterOptionSpecificTestBase {
150 Decl *FromTU;
151 FunctionDecl *D0, *D1, *D2;
152 ImportPath() {
153 FromTU = getTuDecl(SrcCode: "void f(); void f(); void f();", Lang: Lang_CXX03);
154 auto Pattern = functionDecl(hasName(Name: "f"));
155 D0 = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
156 D2 = LastDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
157 D1 = D2->getPreviousDecl();
158 }
159};
160
161TEST_P(ImportPath, Push) {
162 ASTImporter::ImportPathTy path;
163 path.push(D0);
164 EXPECT_FALSE(path.hasCycleAtBack());
165}
166
167TEST_P(ImportPath, SmallCycle) {
168 ASTImporter::ImportPathTy path;
169 path.push(D0);
170 path.push(D0);
171 EXPECT_TRUE(path.hasCycleAtBack());
172 path.pop();
173 EXPECT_FALSE(path.hasCycleAtBack());
174 path.push(D0);
175 EXPECT_TRUE(path.hasCycleAtBack());
176}
177
178TEST_P(ImportPath, GetSmallCycle) {
179 ASTImporter::ImportPathTy path;
180 path.push(D0);
181 path.push(D0);
182 EXPECT_TRUE(path.hasCycleAtBack());
183 std::array<Decl* ,2> Res;
184 int i = 0;
185 for (Decl *Di : path.getCycleAtBack()) {
186 Res[i++] = Di;
187 }
188 ASSERT_EQ(i, 2);
189 EXPECT_EQ(Res[0], D0);
190 EXPECT_EQ(Res[1], D0);
191}
192
193TEST_P(ImportPath, GetCycle) {
194 ASTImporter::ImportPathTy path;
195 path.push(D0);
196 path.push(D1);
197 path.push(D2);
198 path.push(D0);
199 EXPECT_TRUE(path.hasCycleAtBack());
200 std::array<Decl* ,4> Res;
201 int i = 0;
202 for (Decl *Di : path.getCycleAtBack()) {
203 Res[i++] = Di;
204 }
205 ASSERT_EQ(i, 4);
206 EXPECT_EQ(Res[0], D0);
207 EXPECT_EQ(Res[1], D2);
208 EXPECT_EQ(Res[2], D1);
209 EXPECT_EQ(Res[3], D0);
210}
211
212TEST_P(ImportPath, CycleAfterCycle) {
213 ASTImporter::ImportPathTy path;
214 path.push(D0);
215 path.push(D1);
216 path.push(D0);
217 path.push(D1);
218 path.push(D2);
219 path.push(D0);
220 EXPECT_TRUE(path.hasCycleAtBack());
221 std::array<Decl* ,4> Res;
222 int i = 0;
223 for (Decl *Di : path.getCycleAtBack()) {
224 Res[i++] = Di;
225 }
226 ASSERT_EQ(i, 4);
227 EXPECT_EQ(Res[0], D0);
228 EXPECT_EQ(Res[1], D2);
229 EXPECT_EQ(Res[2], D1);
230 EXPECT_EQ(Res[3], D0);
231
232 path.pop();
233 path.pop();
234 path.pop();
235 EXPECT_TRUE(path.hasCycleAtBack());
236 i = 0;
237 for (Decl *Di : path.getCycleAtBack()) {
238 Res[i++] = Di;
239 }
240 ASSERT_EQ(i, 3);
241 EXPECT_EQ(Res[0], D0);
242 EXPECT_EQ(Res[1], D1);
243 EXPECT_EQ(Res[2], D0);
244
245 path.pop();
246 EXPECT_FALSE(path.hasCycleAtBack());
247}
248
249const internal::VariadicDynCastAllOfMatcher<Stmt, SourceLocExpr> sourceLocExpr;
250
251AST_MATCHER_P(SourceLocExpr, hasBuiltinStr, StringRef, Str) {
252 return Node.getBuiltinStr() == Str;
253}
254
255TEST_P(ImportExpr, ImportSourceLocExpr) {
256 MatchVerifier<Decl> Verifier;
257 testImport(FromCode: "void declToImport() { (void)__builtin_FILE(); }", FromLang: Lang_CXX03, ToCode: "",
258 ToLang: Lang_CXX03, Verifier,
259 AMatcher: functionDecl(hasDescendant(
260 sourceLocExpr(hasBuiltinStr(Str: "__builtin_FILE")))));
261 testImport(FromCode: "void declToImport() { (void)__builtin_FILE_NAME(); }", FromLang: Lang_CXX03,
262 ToCode: "", ToLang: Lang_CXX03, Verifier,
263 AMatcher: functionDecl(hasDescendant(
264 sourceLocExpr(hasBuiltinStr(Str: "__builtin_FILE_NAME")))));
265 testImport(FromCode: "void declToImport() { (void)__builtin_COLUMN(); }", FromLang: Lang_CXX03,
266 ToCode: "", ToLang: Lang_CXX03, Verifier,
267 AMatcher: functionDecl(hasDescendant(
268 sourceLocExpr(hasBuiltinStr(Str: "__builtin_COLUMN")))));
269}
270
271TEST_P(ImportExpr, ImportStringLiteral) {
272 MatchVerifier<Decl> Verifier;
273 testImport(FromCode: "void declToImport() { (void)\"foo\"; }", FromLang: Lang_CXX03, ToCode: "",
274 ToLang: Lang_CXX03, Verifier,
275 AMatcher: functionDecl(hasDescendant(
276 stringLiteral(hasType(InnerMatcher: asString(Name: "const char[4]"))))));
277 testImport(FromCode: "void declToImport() { (void)L\"foo\"; }", FromLang: Lang_CXX03, ToCode: "",
278 ToLang: Lang_CXX03, Verifier,
279 AMatcher: functionDecl(hasDescendant(
280 stringLiteral(hasType(InnerMatcher: asString(Name: "const wchar_t[4]"))))));
281 testImport(FromCode: "void declToImport() { (void) \"foo\" \"bar\"; }", FromLang: Lang_CXX03, ToCode: "",
282 ToLang: Lang_CXX03, Verifier,
283 AMatcher: functionDecl(hasDescendant(
284 stringLiteral(hasType(InnerMatcher: asString(Name: "const char[7]"))))));
285}
286
287TEST_P(ImportExpr, ImportChooseExpr) {
288 MatchVerifier<Decl> Verifier;
289
290 // This case tests C code that is not condition-dependent and has a true
291 // condition.
292 testImport(FromCode: "void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }",
293 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
294 AMatcher: functionDecl(hasDescendant(chooseExpr())));
295}
296
297const internal::VariadicDynCastAllOfMatcher<Stmt, ShuffleVectorExpr>
298 shuffleVectorExpr;
299
300TEST_P(ImportExpr, ImportShuffleVectorExpr) {
301 MatchVerifier<Decl> Verifier;
302 constexpr auto Code = R"code(
303 typedef double vector4double __attribute__((__vector_size__(32)));
304 vector4double declToImport(vector4double a, vector4double b) {
305 return __builtin_shufflevector(a, b, 0, 1, 2, 3);
306 }
307 )code";
308 const auto Pattern = functionDecl(hasDescendant(shuffleVectorExpr(
309 allOf(has(declRefExpr(to(InnerMatcher: parmVarDecl(hasName(Name: "a"))))),
310 has(declRefExpr(to(InnerMatcher: parmVarDecl(hasName(Name: "b"))))),
311 has(constantExpr(has(integerLiteral(equals(Value: 0))))),
312 has(constantExpr(has(integerLiteral(equals(Value: 1))))),
313 has(constantExpr(has(integerLiteral(equals(Value: 2))))),
314 has(constantExpr(has(integerLiteral(equals(Value: 3)))))))));
315 testImport(FromCode: Code, FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier, AMatcher: Pattern);
316}
317
318TEST_P(ImportExpr, ImportGNUNullExpr) {
319 MatchVerifier<Decl> Verifier;
320 testImport(FromCode: "void declToImport() { (void)__null; }", FromLang: Lang_CXX03, ToCode: "",
321 ToLang: Lang_CXX03, Verifier,
322 AMatcher: functionDecl(hasDescendant(gnuNullExpr(hasType(InnerMatcher: isInteger())))));
323}
324
325TEST_P(ImportExpr, ImportGenericSelectionExpr) {
326 MatchVerifier<Decl> Verifier;
327
328 testImport(
329 FromCode: "void declToImport() { int x; (void)_Generic(x, int: 0, float: 1); }",
330 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
331 AMatcher: functionDecl(hasDescendant(genericSelectionExpr())));
332}
333
334TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
335 MatchVerifier<Decl> Verifier;
336 testImport(
337 FromCode: "void declToImport() { (void)nullptr; }",
338 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
339 AMatcher: functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
340}
341
342
343TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
344 MatchVerifier<Decl> Verifier;
345 testImport(FromCode: "void declToImport() { (void)1.0; }", FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99,
346 Verifier,
347 AMatcher: functionDecl(hasDescendant(
348 floatLiteral(equals(Value: 1.0), hasType(InnerMatcher: asString(Name: "double"))))));
349 testImport(FromCode: "void declToImport() { (void)1.0e-5f; }", FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99,
350 Verifier,
351 AMatcher: functionDecl(hasDescendant(
352 floatLiteral(equals(Value: 1.0e-5f), hasType(InnerMatcher: asString(Name: "float"))))));
353}
354
355TEST_P(ImportFixedPointExpr, ImportFixedPointerLiteralExpr) {
356 MatchVerifier<Decl> Verifier;
357 testImport(FromCode: "void declToImport() { (void)1.0k; }", FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99,
358 Verifier, AMatcher: functionDecl(hasDescendant(fixedPointLiteral())));
359 testImport(FromCode: "void declToImport() { (void)0.75r; }", FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99,
360 Verifier, AMatcher: functionDecl(hasDescendant(fixedPointLiteral())));
361}
362
363TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
364 MatchVerifier<Decl> Verifier;
365 testImport(
366 FromCode: "void declToImport() { (void)1.0i; }",
367 FromLang: Lang_CXX14, ToCode: "", ToLang: Lang_CXX14, Verifier,
368 AMatcher: functionDecl(hasDescendant(imaginaryLiteral())));
369}
370
371TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
372 MatchVerifier<Decl> Verifier;
373 testImport(FromCode: "void declToImport() {"
374 " struct s { int x; long y; unsigned z; }; "
375 " (void)(struct s){ 42, 0L, 1U }; }",
376 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
377 AMatcher: functionDecl(hasDescendant(compoundLiteralExpr(
378 hasType(InnerMatcher: asString(Name: "struct s")),
379 has(initListExpr(
380 hasType(InnerMatcher: asString(Name: "struct s")),
381 has(integerLiteral(equals(Value: 42), hasType(InnerMatcher: asString(Name: "int")))),
382 has(integerLiteral(equals(Value: 0), hasType(InnerMatcher: asString(Name: "long")))),
383 has(integerLiteral(
384 equals(Value: 1), hasType(InnerMatcher: asString(Name: "unsigned int"))))))))));
385}
386
387TEST_P(ImportExpr, ImportCXXThisExpr) {
388 MatchVerifier<Decl> Verifier;
389 testImport(FromCode: "class declToImport { void f() { (void)this; } };", FromLang: Lang_CXX03, ToCode: "",
390 ToLang: Lang_CXX03, Verifier,
391 AMatcher: cxxRecordDecl(hasMethod(InnerMatcher: hasDescendant(
392 cxxThisExpr(hasType(InnerMatcher: asString(Name: "class declToImport *")))))));
393}
394
395TEST_P(ImportExpr, ImportAtomicExpr) {
396 MatchVerifier<Decl> Verifier;
397 testImport(FromCode: "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
398 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
399 AMatcher: functionDecl(hasDescendant(atomicExpr(
400 has(ignoringParenImpCasts(
401 InnerMatcher: declRefExpr(hasDeclaration(InnerMatcher: varDecl(hasName(Name: "ptr"))),
402 hasType(InnerMatcher: asString(Name: "int *"))))),
403 has(integerLiteral(equals(Value: 1), hasType(InnerMatcher: asString(Name: "int"))))))));
404}
405
406TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
407 MatchVerifier<Decl> Verifier;
408 testImport(FromCode: "void declToImport() { loop: goto loop; (void)&&loop; }", FromLang: Lang_C99,
409 ToCode: "", ToLang: Lang_C99, Verifier,
410 AMatcher: functionDecl(hasDescendant(labelStmt(
411 hasDeclaration(InnerMatcher: labelDecl(hasName(Name: "loop"))))),
412 hasDescendant(addrLabelExpr(
413 hasDeclaration(InnerMatcher: labelDecl(hasName(Name: "loop")))))));
414}
415
416AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
417 internal::Matcher<NamedDecl>, InnerMatcher) {
418 const NamedDecl *Template = Node.getTemplatedDecl();
419 return Template && InnerMatcher.matches(Node: *Template, Finder, Builder);
420}
421
422TEST_P(ImportExpr, ImportParenListExpr) {
423 MatchVerifier<Decl> Verifier;
424 testImport(
425 FromCode: "template<typename T> class dummy { void f() { dummy X(*this); } };"
426 "typedef dummy<int> declToImport;"
427 "template class dummy<int>;",
428 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
429 AMatcher: typedefDecl(hasType(InnerMatcher: elaboratedType(namesType(InnerMatcher: templateSpecializationType(
430 hasDeclaration(InnerMatcher: classTemplateSpecializationDecl(hasSpecializedTemplate(
431 InnerMatcher: classTemplateDecl(hasTemplateDecl(InnerMatcher: cxxRecordDecl(hasMethod(
432 InnerMatcher: allOf(hasName(Name: "f"),
433 hasBody(InnerMatcher: compoundStmt(has(declStmt(hasSingleDecl(InnerMatcher: varDecl(
434 hasInitializer(InnerMatcher: parenListExpr(has(unaryOperator(
435 hasOperatorName(Name: "*"),
436 hasUnaryOperand(
437 InnerMatcher: cxxThisExpr())))))))))))))))))))))))));
438}
439
440TEST_P(ImportExpr, ImportSwitch) {
441 MatchVerifier<Decl> Verifier;
442 testImport(FromCode: "void declToImport() { int b; switch (b) { case 1: break; } }",
443 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
444 AMatcher: functionDecl(hasDescendant(
445 switchStmt(has(compoundStmt(has(caseStmt())))))));
446}
447
448TEST_P(ImportExpr, ImportStmtExpr) {
449 MatchVerifier<Decl> Verifier;
450 testImport(
451 FromCode: "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
452 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
453 AMatcher: traverse(TK: TK_AsIs,
454 InnerMatcher: functionDecl(hasDescendant(varDecl(
455 hasName(Name: "C"), hasType(InnerMatcher: asString(Name: "int")),
456 hasInitializer(InnerMatcher: stmtExpr(
457 hasAnySubstatement(InnerMatcher: declStmt(hasSingleDecl(InnerMatcher: varDecl(
458 hasName(Name: "X"), hasType(InnerMatcher: asString(Name: "int")),
459 hasInitializer(InnerMatcher: integerLiteral(equals(Value: 4))))))),
460 hasDescendant(implicitCastExpr()))))))));
461}
462
463TEST_P(ImportExpr, ImportConditionalOperator) {
464 MatchVerifier<Decl> Verifier;
465 testImport(FromCode: "void declToImport() { (void)(true ? 1 : -5); }", FromLang: Lang_CXX03, ToCode: "",
466 ToLang: Lang_CXX03, Verifier,
467 AMatcher: functionDecl(hasDescendant(conditionalOperator(
468 hasCondition(InnerMatcher: cxxBoolLiteral(equals(Value: true))),
469 hasTrueExpression(InnerMatcher: integerLiteral(equals(Value: 1))),
470 hasFalseExpression(InnerMatcher: unaryOperator(
471 hasUnaryOperand(InnerMatcher: integerLiteral(equals(Value: 5)))))))));
472}
473
474TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
475 MatchVerifier<Decl> Verifier;
476 testImport(
477 FromCode: "void declToImport() { (void)(1 ?: -5); }", FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03,
478 Verifier,
479 AMatcher: traverse(TK: TK_AsIs,
480 InnerMatcher: functionDecl(hasDescendant(binaryConditionalOperator(
481 hasCondition(InnerMatcher: implicitCastExpr(
482 hasSourceExpression(InnerMatcher: opaqueValueExpr(
483 hasSourceExpression(InnerMatcher: integerLiteral(equals(Value: 1))))),
484 hasType(InnerMatcher: booleanType()))),
485 hasTrueExpression(InnerMatcher: opaqueValueExpr(
486 hasSourceExpression(InnerMatcher: integerLiteral(equals(Value: 1))))),
487 hasFalseExpression(InnerMatcher: unaryOperator(
488 hasOperatorName(Name: "-"),
489 hasUnaryOperand(InnerMatcher: integerLiteral(equals(Value: 5))))))))));
490}
491
492TEST_P(ImportExpr, ImportDesignatedInitExpr) {
493 MatchVerifier<Decl> Verifier;
494 testImport(
495 FromCode: "void declToImport() {"
496 " struct point { double x; double y; };"
497 " struct point ptarray[10] = "
498 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
499 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
500 AMatcher: functionDecl(hasDescendant(initListExpr(
501 has(designatedInitExpr(designatorCountIs(N: 2),
502 hasDescendant(floatLiteral(equals(Value: 1.0))),
503 hasDescendant(integerLiteral(equals(Value: 2))))),
504 has(designatedInitExpr(designatorCountIs(N: 2),
505 hasDescendant(floatLiteral(equals(Value: 2.0))),
506 hasDescendant(integerLiteral(equals(Value: 2))))),
507 has(designatedInitExpr(designatorCountIs(N: 2),
508 hasDescendant(floatLiteral(equals(Value: 1.0))),
509 hasDescendant(integerLiteral(equals(Value: 0)))))))));
510}
511
512TEST_P(ImportExpr, ImportPredefinedExpr) {
513 MatchVerifier<Decl> Verifier;
514 // __func__ expands as StringLiteral("declToImport")
515 testImport(FromCode: "void declToImport() { (void)__func__; }", FromLang: Lang_CXX03, ToCode: "",
516 ToLang: Lang_CXX03, Verifier,
517 AMatcher: functionDecl(hasDescendant(predefinedExpr(
518 hasType(InnerMatcher: asString(Name: "const char[13]")),
519 has(stringLiteral(hasType(InnerMatcher: asString(Name: "const char[13]"))))))));
520}
521
522TEST_P(ImportExpr, ImportInitListExpr) {
523 MatchVerifier<Decl> Verifier;
524 testImport(FromCode: "void declToImport() {"
525 " struct point { double x; double y; };"
526 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
527 " [0].x = 1.0 }; }",
528 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
529 AMatcher: functionDecl(hasDescendant(initListExpr(
530 has(cxxConstructExpr(requiresZeroInitialization())),
531 has(initListExpr(
532 hasType(InnerMatcher: asString(Name: "point")), has(floatLiteral(equals(Value: 1.0))),
533 has(implicitValueInitExpr(hasType(InnerMatcher: asString(Name: "double")))))),
534 has(initListExpr(hasType(InnerMatcher: asString(Name: "point")),
535 has(floatLiteral(equals(Value: 2.0))),
536 has(floatLiteral(equals(Value: 1.0)))))))));
537}
538
539const internal::VariadicDynCastAllOfMatcher<Expr, CXXDefaultInitExpr>
540 cxxDefaultInitExpr;
541
542TEST_P(ImportExpr, ImportCXXDefaultInitExpr) {
543 MatchVerifier<Decl> Verifier;
544 testImport(FromCode: "class declToImport { int DefInit = 5; }; declToImport X;",
545 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
546 AMatcher: cxxRecordDecl(hasDescendant(cxxConstructorDecl(
547 hasAnyConstructorInitializer(InnerMatcher: cxxCtorInitializer(
548 withInitializer(InnerMatcher: cxxDefaultInitExpr())))))));
549 testImport(
550 FromCode: "struct X { int A = 5; }; X declToImport{};", FromLang: Lang_CXX17, ToCode: "", ToLang: Lang_CXX17,
551 Verifier,
552 AMatcher: varDecl(hasInitializer(InnerMatcher: initListExpr(hasInit(N: 0, InnerMatcher: cxxDefaultInitExpr())))));
553}
554
555const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
556
557TEST_P(ImportExpr, ImportVAArgExpr) {
558 MatchVerifier<Decl> Verifier;
559 testImport(FromCode: "void declToImport(__builtin_va_list list, ...) {"
560 " (void)__builtin_va_arg(list, int); }",
561 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
562 AMatcher: functionDecl(hasDescendant(
563 cStyleCastExpr(hasSourceExpression(InnerMatcher: vaArgExpr())))));
564}
565
566const internal::VariadicDynCastAllOfMatcher<Stmt, BuiltinBitCastExpr>
567 builtinBitCastExpr;
568
569TEST_P(ImportExpr, ImportBuiltinBitCastExpr) {
570 MatchVerifier<Decl> Verifier;
571 testImport(FromCode: "void declToImport(int X) {"
572 " (void)__builtin_bit_cast(float, X); }",
573 FromLang: Lang_CXX20, ToCode: "", ToLang: Lang_CXX20, Verifier,
574 AMatcher: functionDecl(hasDescendant(
575 cStyleCastExpr(hasSourceExpression(InnerMatcher: builtinBitCastExpr())))));
576}
577
578TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
579 MatchVerifier<Decl> Verifier;
580 testImport(
581 FromCode: "struct C {};"
582 "void declToImport() { C c = C(); }",
583 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
584 AMatcher: traverse(TK: TK_AsIs,
585 InnerMatcher: functionDecl(hasDescendant(exprWithCleanups(has(cxxConstructExpr(
586 has(materializeTemporaryExpr(has(implicitCastExpr(
587 has(cxxTemporaryObjectExpr()))))))))))));
588}
589
590TEST_P(ImportType, ImportAtomicType) {
591 MatchVerifier<Decl> Verifier;
592 testImport(
593 FromCode: "void declToImport() { typedef _Atomic(int) a_int; }",
594 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
595 AMatcher: functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
596}
597
598TEST_P(ImportType, ImportBitIntType) {
599 const AstTypeMatcher<BitIntType> bitIntType;
600 MatchVerifier<Decl> Verifier;
601 testImport(FromCode: "_BitInt(10) declToImport;", FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
602 AMatcher: varDecl(hasType(InnerMatcher: bitIntType())));
603}
604
605TEST_P(ImportType, ImportDependentBitIntType) {
606 const AstTypeMatcher<DependentBitIntType> dependentBitIntType;
607 MatchVerifier<Decl> Verifier;
608 testImport(FromCode: "template<int Width> using declToImport = _BitInt(Width);",
609 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
610 AMatcher: typeAliasTemplateDecl(
611 has(typeAliasDecl(hasType(InnerMatcher: dependentBitIntType())))));
612}
613
614TEST_P(ImportType, ImportDependentAddressSpaceType) {
615 const AstTypeMatcher<DependentAddressSpaceType> dependentAddressSpaceType;
616 MatchVerifier<Decl> Verifier;
617 testImport(
618 FromCode: R"(
619 template<typename T, int AddrSpace>
620 using declToImport = T __attribute__((address_space(AddrSpace)));
621 )",
622 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
623 AMatcher: typeAliasTemplateDecl(
624 has(typeAliasDecl(hasType(InnerMatcher: dependentAddressSpaceType())))));
625}
626
627TEST_P(ImportType, ImportVectorType) {
628 const AstTypeMatcher<VectorType> vectorType;
629 MatchVerifier<Decl> Verifier;
630 testImport(FromCode: "typedef int __attribute__((vector_size(12))) declToImport;",
631 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
632 AMatcher: typedefDecl(hasType(InnerMatcher: vectorType())));
633}
634
635TEST_P(ImportType, ImportDependentVectorType) {
636 const AstTypeMatcher<DependentVectorType> dependentVectorType;
637 MatchVerifier<Decl> Verifier;
638 testImport(
639 FromCode: R"(
640 template<typename T, int Size>
641 using declToImport = T __attribute__((vector_size(Size)));
642 )",
643 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
644 AMatcher: typeAliasTemplateDecl(
645 has(typeAliasDecl(hasType(InnerMatcher: dependentVectorType())))));
646}
647
648struct ImportOpenCLPipe : ImportType {
649 std::vector<std::string> getExtraArgs() const override {
650 return {"-x", "cl", "-cl-no-stdinc", "-cl-std=CL2.0"};
651 }
652};
653
654TEST_P(ImportOpenCLPipe, ImportPipeType) {
655 const AstTypeMatcher<PipeType> pipeType;
656 MatchVerifier<Decl> Verifier;
657 testImport(FromCode: "typedef pipe int declToImport;", FromLang: Lang_OpenCL, ToCode: "", ToLang: Lang_OpenCL,
658 Verifier, AMatcher: typedefDecl(hasType(InnerMatcher: pipeType())));
659}
660
661struct ImportMatrixType : ImportType {
662 std::vector<std::string> getExtraArgs() const override {
663 return {"-fenable-matrix"};
664 }
665};
666
667TEST_P(ImportMatrixType, ImportConstantMatrixType) {
668 const AstTypeMatcher<ConstantMatrixType> constantMatrixType;
669 MatchVerifier<Decl> Verifier;
670 testImport(FromCode: "typedef int __attribute__((matrix_type(5, 5))) declToImport;",
671 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
672 AMatcher: typedefDecl(hasType(InnerMatcher: constantMatrixType())));
673}
674
675TEST_P(ImportMatrixType, ImportDependentSizedMatrixType) {
676 const AstTypeMatcher<DependentSizedMatrixType> dependentSizedMatrixType;
677 MatchVerifier<Decl> Verifier;
678 testImport(
679 FromCode: R"(
680 template<typename T, int Rows, int Cols>
681 using declToImport = T __attribute__((matrix_type(Rows, Cols)));
682 )",
683 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
684 AMatcher: typeAliasTemplateDecl(
685 has(typeAliasDecl(hasType(InnerMatcher: dependentSizedMatrixType())))));
686}
687
688TEST_P(ImportType, ImportUsingType) {
689 MatchVerifier<Decl> Verifier;
690 testImport(FromCode: "struct C {};"
691 "void declToImport() { using ::C; new C{}; }",
692 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
693 AMatcher: functionDecl(hasDescendant(cxxNewExpr(hasType(InnerMatcher: pointerType(
694 pointee(elaboratedType(namesType(InnerMatcher: usingType())))))))));
695}
696
697TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
698 MatchVerifier<Decl> Verifier;
699 testImport(FromCode: "template <typename T> void declToImport() { };", FromLang: Lang_CXX03, ToCode: "",
700 ToLang: Lang_CXX03, Verifier, AMatcher: functionTemplateDecl());
701}
702
703TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
704 MatchVerifier<Decl> Verifier;
705 testImport(FromCode: "template <typename T> struct C { T t; };"
706 "template <typename T> void declToImport() {"
707 " C<T> d;"
708 " (void)d.t;"
709 "}"
710 "void instantiate() { declToImport<int>(); }",
711 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
712 AMatcher: functionTemplateDecl(hasDescendant(
713 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
714 testImport(FromCode: "template <typename T> struct C { T t; };"
715 "template <typename T> void declToImport() {"
716 " C<T> d;"
717 " (void)(&d)->t;"
718 "}"
719 "void instantiate() { declToImport<int>(); }",
720 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
721 AMatcher: functionTemplateDecl(hasDescendant(
722 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
723}
724
725TEST_P(ImportType, ImportTypeAliasTemplate) {
726 MatchVerifier<Decl> Verifier;
727 testImport(
728 FromCode: "template <int K>"
729 "struct dummy { static const int i = K; };"
730 "template <int K> using dummy2 = dummy<K>;"
731 "int declToImport() { return dummy2<3>::i; }",
732 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
733 AMatcher: traverse(TK: TK_AsIs,
734 InnerMatcher: functionDecl(hasDescendant(implicitCastExpr(has(declRefExpr()))),
735 unless(hasAncestor(
736 translationUnitDecl(has(typeAliasDecl())))))));
737}
738
739const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
740 varTemplateSpecializationDecl;
741
742TEST_P(ImportDecl, ImportVarTemplate) {
743 MatchVerifier<Decl> Verifier;
744 testImport(
745 FromCode: "template <typename T>"
746 "T pi = T(3.1415926535897932385L);"
747 "void declToImport() { (void)pi<int>; }",
748 FromLang: Lang_CXX14, ToCode: "", ToLang: Lang_CXX14, Verifier,
749 AMatcher: functionDecl(
750 hasDescendant(declRefExpr(to(InnerMatcher: varTemplateSpecializationDecl()))),
751 unless(hasAncestor(translationUnitDecl(has(varDecl(
752 hasName(Name: "pi"), unless(varTemplateSpecializationDecl()))))))));
753}
754
755TEST_P(ImportType, ImportPackExpansion) {
756 MatchVerifier<Decl> Verifier;
757 testImport(FromCode: "template <typename... Args>"
758 "struct dummy {"
759 " dummy(Args... args) {}"
760 " static const int i = 4;"
761 "};"
762 "int declToImport() { return dummy<int>::i; }",
763 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
764 AMatcher: traverse(TK: TK_AsIs, InnerMatcher: functionDecl(hasDescendant(returnStmt(has(
765 implicitCastExpr(has(declRefExpr()))))))));
766}
767
768TEST_P(ImportType, ImportDependentTemplateSpecialization) {
769 MatchVerifier<Decl> Verifier;
770 testImport(FromCode: "template<typename T>"
771 "struct A;"
772 "template<typename T>"
773 "struct declToImport {"
774 " typename A<T>::template B<T> a;"
775 "};",
776 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
777 AMatcher: classTemplateDecl(has(cxxRecordDecl(has(
778 fieldDecl(hasType(InnerMatcher: dependentTemplateSpecializationType())))))));
779}
780
781TEST_P(ImportType, ImportDeducedTemplateSpecialization) {
782 MatchVerifier<Decl> Verifier;
783 testImport(FromCode: "template <typename T>"
784 "class C { public: C(T); };"
785 "C declToImport(123);",
786 FromLang: Lang_CXX17, ToCode: "", ToLang: Lang_CXX17, Verifier,
787 AMatcher: varDecl(hasType(InnerMatcher: elaboratedType(
788 namesType(InnerMatcher: deducedTemplateSpecializationType())))));
789}
790
791const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
792 sizeOfPackExpr;
793
794TEST_P(ImportExpr, ImportSizeOfPackExpr) {
795 MatchVerifier<Decl> Verifier;
796 testImport(
797 FromCode: "template <typename... Ts>"
798 "void declToImport() {"
799 " const int i = sizeof...(Ts);"
800 "};"
801 "void g() { declToImport<int>(); }",
802 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
803 AMatcher: functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
804 testImport(
805 FromCode: "template <typename... Ts>"
806 "using X = int[sizeof...(Ts)];"
807 "template <typename... Us>"
808 "struct Y {"
809 " X<Us..., int, double, int, Us...> f;"
810 "};"
811 "Y<float, int> declToImport;",
812 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
813 AMatcher: varDecl(hasType(InnerMatcher: classTemplateSpecializationDecl(has(fieldDecl(hasType(
814 InnerMatcher: hasUnqualifiedDesugaredType(InnerMatcher: constantArrayType(hasSize(N: 7))))))))));
815}
816
817TEST_P(ImportExpr, ImportCXXFoldExpr) {
818 auto Match1 = cxxFoldExpr(hasOperatorName(Name: "+"), isLeftFold(),
819 unless(hasFoldInit(InnerMacher: expr())));
820 auto Match2 =
821 cxxFoldExpr(hasOperatorName(Name: "-"), isLeftFold(), hasFoldInit(InnerMacher: expr()));
822 auto Match3 = cxxFoldExpr(hasOperatorName(Name: "*"), isRightFold(),
823 unless(hasFoldInit(InnerMacher: expr())));
824 auto Match4 =
825 cxxFoldExpr(hasOperatorName(Name: "/"), isRightFold(), hasFoldInit(InnerMacher: expr()));
826
827 MatchVerifier<Decl> Verifier;
828 testImport(FromCode: "template <typename... Ts>"
829 "void declToImport(Ts... args) {"
830 " const int i1 = (... + args);"
831 " const int i2 = (1 - ... - args);"
832 " const int i3 = (args * ...);"
833 " const int i4 = (args / ... / 1);"
834 "};"
835 "void g() { declToImport(1, 2, 3, 4, 5); }",
836 FromLang: Lang_CXX17, ToCode: "", ToLang: Lang_CXX17, Verifier,
837 AMatcher: functionTemplateDecl(hasDescendant(Match1), hasDescendant(Match2),
838 hasDescendant(Match3),
839 hasDescendant(Match4)));
840}
841
842/// \brief Matches __builtin_types_compatible_p:
843/// GNU extension to check equivalent types
844/// Given
845/// \code
846/// __builtin_types_compatible_p(int, int)
847/// \endcode
848// will generate TypeTraitExpr <...> 'int'
849const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
850
851TEST_P(ImportExpr, ImportTypeTraitExpr) {
852 MatchVerifier<Decl> Verifier;
853 testImport(
854 FromCode: "void declToImport() { "
855 " (void)__builtin_types_compatible_p(int, int);"
856 "}",
857 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
858 AMatcher: functionDecl(hasDescendant(typeTraitExpr(hasType(InnerMatcher: asString(Name: "int"))))));
859}
860
861const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
862
863TEST_P(ImportExpr, ImportCXXTypeidExpr) {
864 MatchVerifier<Decl> Verifier;
865 testImport(
866 FromCode: "namespace std { class type_info {}; }"
867 "void declToImport() {"
868 " int x;"
869 " auto a = typeid(int); auto b = typeid(x);"
870 "}",
871 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
872 AMatcher: traverse(
873 TK: TK_AsIs,
874 InnerMatcher: functionDecl(
875 hasDescendant(varDecl(hasName(Name: "a"), hasInitializer(InnerMatcher: hasDescendant(
876 cxxTypeidExpr())))),
877 hasDescendant(varDecl(hasName(Name: "b"), hasInitializer(InnerMatcher: hasDescendant(
878 cxxTypeidExpr())))))));
879}
880
881TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
882 MatchVerifier<Decl> Verifier;
883 testImport(
884 FromCode: "template<typename T> struct declToImport {"
885 " void m() { (void)__is_pod(T); }"
886 "};"
887 "void f() { declToImport<int>().m(); }",
888 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
889 AMatcher: classTemplateDecl(has(cxxRecordDecl(has(
890 functionDecl(hasDescendant(
891 typeTraitExpr(hasType(InnerMatcher: booleanType())))))))));
892}
893
894TEST_P(ImportDecl, ImportRecordDeclInFunc) {
895 MatchVerifier<Decl> Verifier;
896 testImport(FromCode: "int declToImport() { "
897 " struct data_t {int a;int b;};"
898 " struct data_t d;"
899 " return 0;"
900 "}",
901 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
902 AMatcher: functionDecl(hasBody(InnerMatcher: compoundStmt(
903 has(declStmt(hasSingleDecl(InnerMatcher: varDecl(hasName(Name: "d")))))))));
904}
905
906TEST_P(ImportDecl, ImportedVarDeclPreservesThreadLocalStorage) {
907 MatchVerifier<Decl> Verifier;
908 testImport(FromCode: "thread_local int declToImport;", FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11,
909 Verifier, AMatcher: varDecl(hasThreadStorageDuration()));
910}
911
912TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {
913 Decl *FromTU = getTuDecl(SrcCode: "int declToImport() { "
914 " struct data_t {int a;int b;};"
915 " struct data_t d;"
916 " return 0;"
917 "}",
918 Lang: Lang_C99, FileName: "input.c");
919 auto *FromVar =
920 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "d")));
921 ASSERT_TRUE(FromVar);
922 auto ToType =
923 ImportType(FromType: FromVar->getType().getCanonicalType(), TUDecl: FromVar, ToLang: Lang_C99);
924 EXPECT_FALSE(ToType.isNull());
925}
926
927TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {
928 // This construct is not supported by ASTImporter.
929 Decl *FromTU = getTuDecl(
930 SrcCode: "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
931 Lang: Lang_C99, FileName: "input.c");
932 auto *From = FirstDeclMatcher<FunctionDecl>().match(
933 D: FromTU, AMatcher: functionDecl(hasName(Name: "declToImport")));
934 ASSERT_TRUE(From);
935 auto *To = Import(From, Lang_C99);
936 EXPECT_EQ(To, nullptr);
937}
938
939TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {
940 Decl *FromTU =
941 getTuDecl(SrcCode: "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
942 "int declToImport(){ return NONAME_SIZEOF(int); }",
943 Lang: Lang_C99, FileName: "input.c");
944 auto *From = FirstDeclMatcher<FunctionDecl>().match(
945 D: FromTU, AMatcher: functionDecl(hasName(Name: "declToImport")));
946 ASSERT_TRUE(From);
947 auto *To = Import(From, Lang_C99);
948 ASSERT_TRUE(To);
949 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
950 To, functionDecl(hasName("declToImport"),
951 hasDescendant(unaryExprOrTypeTraitExpr()))));
952}
953
954TEST_P(ASTImporterOptionSpecificTestBase,
955 ImportRecordDeclInFuncParamsFromMacro) {
956 // This construct is not supported by ASTImporter.
957 Decl *FromTU =
958 getTuDecl(SrcCode: "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
959 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
960 Lang: Lang_C99, FileName: "input.c");
961 auto *From = FirstDeclMatcher<FunctionDecl>().match(
962 D: FromTU, AMatcher: functionDecl(hasName(Name: "declToImport")));
963 ASSERT_TRUE(From);
964 auto *To = Import(From, Lang_C99);
965 EXPECT_EQ(To, nullptr);
966}
967
968const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
969 cxxPseudoDestructorExpr;
970
971TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
972 MatchVerifier<Decl> Verifier;
973 testImport(
974 FromCode: "typedef int T;"
975 "void declToImport(int *p) {"
976 " T t;"
977 " p->T::~T();"
978 "}",
979 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
980 AMatcher: functionDecl(hasDescendant(callExpr(has(cxxPseudoDestructorExpr())))));
981}
982
983TEST_P(ImportDecl, ImportUsingDecl) {
984 MatchVerifier<Decl> Verifier;
985 testImport(FromCode: "namespace foo { int bar; }"
986 "void declToImport() { using foo::bar; }",
987 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
988 AMatcher: functionDecl(hasDescendant(usingDecl(hasName(Name: "bar")))));
989}
990
991TEST_P(ImportDecl, ImportUsingTemplate) {
992 MatchVerifier<Decl> Verifier;
993 testImport(FromCode: "namespace ns { template <typename T> struct S {}; }"
994 "template <template <typename> class T> class X {};"
995 "void declToImport() {"
996 "using ns::S; X<S> xi; }",
997 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
998 AMatcher: functionDecl(hasDescendant(varDecl(hasTypeLoc(Inner: elaboratedTypeLoc(
999 hasNamedTypeLoc(InnerMatcher: templateSpecializationTypeLoc(
1000 hasAnyTemplateArgumentLoc(InnerMatcher: templateArgumentLoc())))))))));
1001}
1002
1003TEST_P(ImportDecl, ImportUsingEnumDecl) {
1004 MatchVerifier<Decl> Verifier;
1005 testImport(FromCode: "namespace foo { enum bar { baz, toto, quux }; }"
1006 "void declToImport() { using enum foo::bar; }",
1007 FromLang: Lang_CXX20, ToCode: "", ToLang: Lang_CXX20, Verifier,
1008 AMatcher: functionDecl(hasDescendant(usingEnumDecl(hasName(Name: "bar")))));
1009}
1010
1011const internal::VariadicDynCastAllOfMatcher<Decl, UsingPackDecl> usingPackDecl;
1012
1013TEST_P(ImportDecl, ImportUsingPackDecl) {
1014 MatchVerifier<Decl> Verifier;
1015 testImport(
1016 FromCode: "struct A { int operator()() { return 1; } };"
1017 "struct B { int operator()() { return 2; } };"
1018 "template<typename ...T> struct C : T... { using T::operator()...; };"
1019 "C<A, B> declToImport;",
1020 FromLang: Lang_CXX20, ToCode: "", ToLang: Lang_CXX20, Verifier,
1021 AMatcher: varDecl(hasType(InnerMatcher: elaboratedType(namesType(InnerMatcher: templateSpecializationType(
1022 hasDeclaration(InnerMatcher: classTemplateSpecializationDecl(
1023 hasDescendant(usingPackDecl())))))))));
1024}
1025
1026/// \brief Matches shadow declarations introduced into a scope by a
1027/// (resolved) using declaration.
1028///
1029/// Given
1030/// \code
1031/// namespace n { int f; }
1032/// namespace declToImport { using n::f; }
1033/// \endcode
1034/// usingShadowDecl()
1035/// matches \code f \endcode
1036const internal::VariadicDynCastAllOfMatcher<Decl,
1037 UsingShadowDecl> usingShadowDecl;
1038
1039TEST_P(ImportDecl, ImportUsingShadowDecl) {
1040 MatchVerifier<Decl> Verifier;
1041 // from using-decl
1042 testImport(FromCode: "namespace foo { int bar; }"
1043 "namespace declToImport { using foo::bar; }",
1044 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1045 AMatcher: namespaceDecl(has(usingShadowDecl(hasName(Name: "bar")))));
1046 // from using-enum-decl
1047 testImport(FromCode: "namespace foo { enum bar {baz, toto, quux }; }"
1048 "namespace declToImport { using enum foo::bar; }",
1049 FromLang: Lang_CXX20, ToCode: "", ToLang: Lang_CXX20, Verifier,
1050 AMatcher: namespaceDecl(has(usingShadowDecl(hasName(Name: "baz")))));
1051}
1052
1053TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
1054 MatchVerifier<Decl> Verifier;
1055 testImport(FromCode: "template<typename T> int foo();"
1056 "template <typename T> void declToImport() {"
1057 " (void)::foo<T>;"
1058 " (void)::template foo<T>;"
1059 "}"
1060 "void instantiate() { declToImport<int>(); }",
1061 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1062 AMatcher: functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
1063}
1064
1065TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
1066 MatchVerifier<Decl> Verifier;
1067 testImport(FromCode: "template <typename T> struct C { T t; };"
1068 "template <typename T> void declToImport() {"
1069 " C<T> d;"
1070 " d.t = T();"
1071 "}"
1072 "void instantiate() { declToImport<int>(); }",
1073 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1074 AMatcher: functionTemplateDecl(hasDescendant(
1075 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1076 testImport(FromCode: "template <typename T> struct C { T t; };"
1077 "template <typename T> void declToImport() {"
1078 " C<T> d;"
1079 " (&d)->t = T();"
1080 "}"
1081 "void instantiate() { declToImport<int>(); }",
1082 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1083 AMatcher: functionTemplateDecl(hasDescendant(
1084 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1085}
1086
1087/// Check that function "declToImport()" (which is the templated function
1088/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1089/// Same for class template declarations.
1090TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
1091 MatchVerifier<Decl> Verifier;
1092 testImport(FromCode: "template <typename T> void declToImport() { T a = 1; }"
1093 "void instantiate() { declToImport<int>(); }",
1094 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1095 AMatcher: functionTemplateDecl(hasAncestor(translationUnitDecl(
1096 unless(has(functionDecl(hasName(Name: "declToImport"))))))));
1097 testImport(FromCode: "template <typename T> struct declToImport { T t; };"
1098 "void instantiate() { declToImport<int>(); }",
1099 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1100 AMatcher: classTemplateDecl(hasAncestor(translationUnitDecl(
1101 unless(has(cxxRecordDecl(hasName(Name: "declToImport"))))))));
1102}
1103
1104TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
1105 MatchVerifier<Decl> Verifier;
1106 auto Code =
1107 R"s(
1108 struct declToImport {
1109 template <typename T0> struct X;
1110 template <typename T0> struct X<T0 *> {};
1111 };
1112 )s";
1113 testImport(FromCode: Code, FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1114 AMatcher: recordDecl(has(classTemplateDecl()),
1115 has(classTemplateSpecializationDecl())));
1116}
1117
1118TEST_P(ImportExpr, CXXOperatorCallExpr) {
1119 MatchVerifier<Decl> Verifier;
1120 testImport(
1121 FromCode: "class declToImport {"
1122 " void f() { *this = declToImport(); }"
1123 "};",
1124 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1125 AMatcher: cxxRecordDecl(has(cxxMethodDecl(hasDescendant(cxxOperatorCallExpr())))));
1126}
1127
1128TEST_P(ImportExpr, DependentSizedArrayType) {
1129 MatchVerifier<Decl> Verifier;
1130 testImport(FromCode: "template<typename T, int Size> class declToImport {"
1131 " T data[Size];"
1132 "};",
1133 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1134 AMatcher: classTemplateDecl(has(cxxRecordDecl(
1135 has(fieldDecl(hasType(InnerMatcher: dependentSizedArrayType())))))));
1136}
1137
1138TEST_P(ImportExpr, DependentSizedExtVectorType) {
1139 MatchVerifier<Decl> Verifier;
1140 testImport(FromCode: "template<typename T, int Size>"
1141 "class declToImport {"
1142 " typedef T __attribute__((ext_vector_type(Size))) type;"
1143 "};",
1144 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1145 AMatcher: classTemplateDecl(has(cxxRecordDecl(
1146 has(typedefDecl(hasType(InnerMatcher: dependentSizedExtVectorType())))))));
1147}
1148
1149TEST_P(ASTImporterOptionSpecificTestBase, ImportUsingPackDecl) {
1150 Decl *FromTU = getTuDecl(
1151 SrcCode: "struct A { int operator()() { return 1; } };"
1152 "struct B { int operator()() { return 2; } };"
1153 "template<typename ...T> struct C : T... { using T::operator()...; };"
1154 "C<A, B> Var;",
1155 Lang: Lang_CXX20);
1156
1157 auto From = FirstDeclMatcher<UsingPackDecl>().match(D: FromTU, AMatcher: usingPackDecl());
1158 ASSERT_TRUE(From);
1159 auto To = cast<UsingPackDecl>(Import(From, Lang_CXX20));
1160 ASSERT_TRUE(To);
1161
1162 ArrayRef<NamedDecl *> FromExpansions = From->expansions();
1163 ArrayRef<NamedDecl *> ToExpansions = To->expansions();
1164 ASSERT_EQ(FromExpansions.size(), ToExpansions.size());
1165 for (unsigned int I = 0; I < FromExpansions.size(); ++I) {
1166 auto ImportedExpansion = Import(From: FromExpansions[I], Lang: Lang_CXX20);
1167 EXPECT_EQ(ImportedExpansion, ToExpansions[I]);
1168 }
1169
1170 auto ImportedDC = cast<Decl>(Import(From->getDeclContext(), Lang_CXX20));
1171 EXPECT_EQ(ImportedDC, cast<Decl>(To->getDeclContext()));
1172}
1173
1174TEST_P(ASTImporterOptionSpecificTestBase, TemplateTypeParmDeclNoDefaultArg) {
1175 Decl *FromTU = getTuDecl(SrcCode: "template<typename T> struct X {};", Lang: Lang_CXX03);
1176 auto From = FirstDeclMatcher<TemplateTypeParmDecl>().match(
1177 D: FromTU, AMatcher: templateTypeParmDecl(hasName(Name: "T")));
1178 TemplateTypeParmDecl *To = Import(From, Lang_CXX03);
1179 ASSERT_FALSE(To->hasDefaultArgument());
1180}
1181
1182TEST_P(ASTImporterOptionSpecificTestBase, TemplateTypeParmDeclDefaultArg) {
1183 Decl *FromTU =
1184 getTuDecl(SrcCode: "template<typename T = int> struct X {};", Lang: Lang_CXX03);
1185 auto From = FirstDeclMatcher<TemplateTypeParmDecl>().match(
1186 D: FromTU, AMatcher: templateTypeParmDecl(hasName(Name: "T")));
1187 TemplateTypeParmDecl *To = Import(From, Lang_CXX03);
1188 ASSERT_TRUE(To->hasDefaultArgument());
1189 QualType ToArg = To->getDefaultArgument().getArgument().getAsType();
1190 ASSERT_EQ(ToArg, QualType(To->getASTContext().IntTy));
1191}
1192
1193TEST_P(ASTImporterOptionSpecificTestBase, ImportBeginLocOfDeclRefExpr) {
1194 Decl *FromTU =
1195 getTuDecl(SrcCode: "class A { public: static int X; }; void f() { (void)A::X; }",
1196 Lang: Lang_CXX03);
1197 auto From = FirstDeclMatcher<FunctionDecl>().match(
1198 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
1199 ASSERT_TRUE(From);
1200 ASSERT_TRUE(
1201 cast<CStyleCastExpr>(cast<CompoundStmt>(From->getBody())->body_front())
1202 ->getSubExpr()
1203 ->getBeginLoc()
1204 .isValid());
1205 FunctionDecl *To = Import(From, Lang_CXX03);
1206 ASSERT_TRUE(To);
1207 ASSERT_TRUE(
1208 cast<CStyleCastExpr>(cast<CompoundStmt>(To->getBody())->body_front())
1209 ->getSubExpr()
1210 ->getBeginLoc()
1211 .isValid());
1212}
1213
1214TEST_P(ASTImporterOptionSpecificTestBase,
1215 TemplateTemplateParmDeclNoDefaultArg) {
1216 Decl *FromTU = getTuDecl(SrcCode: R"(
1217 template<template<typename> typename TT> struct Y {};
1218 )",
1219 Lang: Lang_CXX17);
1220 auto From = FirstDeclMatcher<TemplateTemplateParmDecl>().match(
1221 D: FromTU, AMatcher: templateTemplateParmDecl(hasName(Name: "TT")));
1222 TemplateTemplateParmDecl *To = Import(From, Lang_CXX17);
1223 ASSERT_FALSE(To->hasDefaultArgument());
1224}
1225
1226TEST_P(ASTImporterOptionSpecificTestBase, TemplateTemplateParmDeclDefaultArg) {
1227 Decl *FromTU = getTuDecl(SrcCode: R"(
1228 template<typename T> struct X {};
1229 template<template<typename> typename TT = X> struct Y {};
1230 )",
1231 Lang: Lang_CXX17);
1232 auto From = FirstDeclMatcher<TemplateTemplateParmDecl>().match(
1233 D: FromTU, AMatcher: templateTemplateParmDecl(hasName(Name: "TT")));
1234 TemplateTemplateParmDecl *To = Import(From, Lang_CXX17);
1235 ASSERT_TRUE(To->hasDefaultArgument());
1236 const TemplateArgument &ToDefaultArg = To->getDefaultArgument().getArgument();
1237 ASSERT_TRUE(To->isTemplateDecl());
1238 TemplateDecl *ToTemplate = ToDefaultArg.getAsTemplate().getAsTemplateDecl();
1239
1240 // Find the default argument template 'X' in the AST and compare it against
1241 // the default argument we got.
1242 auto ToExpectedDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
1243 To->getTranslationUnitDecl(), classTemplateDecl(hasName(Name: "X")));
1244 ASSERT_EQ(ToTemplate, ToExpectedDecl);
1245}
1246
1247TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclNoDefaultArg) {
1248 Decl *FromTU = getTuDecl(SrcCode: "template<int N> struct X {};", Lang: Lang_CXX03);
1249 auto From = FirstDeclMatcher<NonTypeTemplateParmDecl>().match(
1250 D: FromTU, AMatcher: nonTypeTemplateParmDecl(hasName(Name: "N")));
1251 NonTypeTemplateParmDecl *To = Import(From, Lang_CXX03);
1252 ASSERT_FALSE(To->hasDefaultArgument());
1253}
1254
1255TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclDefaultArg) {
1256 Decl *FromTU = getTuDecl(SrcCode: "template<int S = 1> struct X {};", Lang: Lang_CXX03);
1257 auto From = FirstDeclMatcher<NonTypeTemplateParmDecl>().match(
1258 D: FromTU, AMatcher: nonTypeTemplateParmDecl(hasName(Name: "S")));
1259 NonTypeTemplateParmDecl *To = Import(From, Lang_CXX03);
1260 ASSERT_TRUE(To->hasDefaultArgument());
1261 Stmt *ToArg = To->getDefaultArgument().getArgument().getAsExpr();
1262 ASSERT_TRUE(isa<IntegerLiteral>(ToArg));
1263 ASSERT_EQ(cast<IntegerLiteral>(ToArg)->getValue().getLimitedValue(), 1U);
1264}
1265
1266TEST_P(ASTImporterOptionSpecificTestBase, TemplateArgumentsDefaulted) {
1267 Decl *FromTU = getTuDecl(SrcCode: R"(
1268 template<typename T> struct X {};
1269 template<typename TP = double,
1270 int NTTP = 50,
1271 template<typename> typename TT = X> struct S {};
1272 S<> s;
1273 )",
1274 Lang: Lang_CXX17);
1275 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1276 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "S")));
1277 ASSERT_TRUE(FromSpec);
1278 auto *ToSpec = Import(FromSpec, Lang_CXX03);
1279 ASSERT_TRUE(ToSpec);
1280 auto const &TList = ToSpec->getTemplateArgs();
1281 for (auto const &Arg : TList.asArray()) {
1282 ASSERT_TRUE(Arg.getIsDefaulted());
1283 }
1284}
1285
1286TEST_P(ASTImporterOptionSpecificTestBase,
1287 ImportOfTemplatedDeclOfClassTemplateDecl) {
1288 Decl *FromTU = getTuDecl(SrcCode: "template<class X> struct S{};", Lang: Lang_CXX03);
1289 auto From =
1290 FirstDeclMatcher<ClassTemplateDecl>().match(D: FromTU, AMatcher: classTemplateDecl());
1291 ASSERT_TRUE(From);
1292 auto To = cast<ClassTemplateDecl>(Import(From, Lang_CXX03));
1293 ASSERT_TRUE(To);
1294 Decl *ToTemplated = To->getTemplatedDecl();
1295 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX03);
1296 EXPECT_TRUE(ToTemplated1);
1297 EXPECT_EQ(ToTemplated1, ToTemplated);
1298}
1299
1300TEST_P(ASTImporterOptionSpecificTestBase,
1301 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
1302 Decl *FromTU = getTuDecl(SrcCode: "template<class X> void f(){}", Lang: Lang_CXX03);
1303 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1304 D: FromTU, AMatcher: functionTemplateDecl());
1305 ASSERT_TRUE(From);
1306 auto To = cast<FunctionTemplateDecl>(Import(From, Lang_CXX03));
1307 ASSERT_TRUE(To);
1308 Decl *ToTemplated = To->getTemplatedDecl();
1309 Decl *ToTemplated1 = Import(From->getTemplatedDecl(), Lang_CXX03);
1310 EXPECT_TRUE(ToTemplated1);
1311 EXPECT_EQ(ToTemplated1, ToTemplated);
1312}
1313
1314TEST_P(ASTImporterOptionSpecificTestBase,
1315 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1316 Decl *FromTU = getTuDecl(SrcCode: "template<class X> struct S{};", Lang: Lang_CXX03);
1317 auto FromFT =
1318 FirstDeclMatcher<ClassTemplateDecl>().match(D: FromTU, AMatcher: classTemplateDecl());
1319 ASSERT_TRUE(FromFT);
1320
1321 auto ToTemplated =
1322 cast<CXXRecordDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX03));
1323 EXPECT_TRUE(ToTemplated);
1324 auto ToTU = ToTemplated->getTranslationUnitDecl();
1325 auto ToFT =
1326 FirstDeclMatcher<ClassTemplateDecl>().match(ToTU, classTemplateDecl());
1327 EXPECT_TRUE(ToFT);
1328}
1329
1330TEST_P(ASTImporterOptionSpecificTestBase,
1331 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
1332 Decl *FromTU = getTuDecl(SrcCode: "template<class X> void f(){}", Lang: Lang_CXX03);
1333 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1334 D: FromTU, AMatcher: functionTemplateDecl());
1335 ASSERT_TRUE(FromFT);
1336
1337 auto ToTemplated =
1338 cast<FunctionDecl>(Import(FromFT->getTemplatedDecl(), Lang_CXX03));
1339 EXPECT_TRUE(ToTemplated);
1340 auto ToTU = ToTemplated->getTranslationUnitDecl();
1341 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1342 ToTU, functionTemplateDecl());
1343 EXPECT_TRUE(ToFT);
1344}
1345
1346TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
1347 auto Code =
1348 R"(
1349 namespace x {
1350 template<class X> struct S1{};
1351 template<class X> struct S2{};
1352 template<class X> struct S3{};
1353 }
1354 )";
1355 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
1356 auto FromNs =
1357 FirstDeclMatcher<NamespaceDecl>().match(D: FromTU, AMatcher: namespaceDecl());
1358 auto ToNs = cast<NamespaceDecl>(Import(FromNs, Lang_CXX03));
1359 ASSERT_TRUE(ToNs);
1360 auto From =
1361 FirstDeclMatcher<ClassTemplateDecl>().match(D: FromTU,
1362 AMatcher: classTemplateDecl(
1363 hasName(Name: "S2")));
1364 auto To =
1365 FirstDeclMatcher<ClassTemplateDecl>().match(ToNs,
1366 classTemplateDecl(
1367 hasName(Name: "S2")));
1368 ASSERT_TRUE(From);
1369 ASSERT_TRUE(To);
1370 auto ToTemplated = To->getTemplatedDecl();
1371 auto ToTemplated1 =
1372 cast<CXXRecordDecl>(Import(From->getTemplatedDecl(), Lang_CXX03));
1373 EXPECT_TRUE(ToTemplated1);
1374 ASSERT_EQ(ToTemplated1, ToTemplated);
1375}
1376
1377TEST_P(ASTImporterOptionSpecificTestBase,
1378 ImportTemplateSpecializationStaticMember) {
1379 auto FromCode =
1380 R"(
1381 template <typename H> class Test{
1382 public:
1383 static const unsigned int length;
1384 };
1385
1386 template<> const unsigned int Test<int>::length;
1387 template<> const unsigned int Test<int>::length = 0;
1388 )";
1389 auto ToCode =
1390 R"(
1391 template <typename H> class Test {
1392 public:
1393 static const unsigned int length;
1394 };
1395
1396 template <> const unsigned int Test<int>::length;
1397
1398 void foo() { int i = 1 / Test<int>::length; }
1399 )";
1400 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX14);
1401 auto FromDecl = FirstDeclMatcher<VarDecl>().match(
1402 D: FromTU, AMatcher: varDecl(hasName(Name: "length"), isDefinition()));
1403 Decl *ToTu = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX14);
1404 auto ToX = Import(FromDecl, Lang_CXX03);
1405 auto ToDecl = FirstDeclMatcher<VarDecl>().match(
1406 D: ToTu, AMatcher: varDecl(hasName(Name: "length"), isDefinition()));
1407 EXPECT_TRUE(ToX);
1408 EXPECT_EQ(ToX, ToDecl);
1409}
1410
1411TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {
1412 // This tests the import of isConditionTrue directly to make sure the importer
1413 // gets it right.
1414 Decl *From, *To;
1415 std::tie(args&: From, args&: To) = getImportedDecl(
1416 FromSrcCode: "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }", FromLang: Lang_C99,
1417 ToSrcCode: "", ToLang: Lang_C99);
1418
1419 auto ToResults = match(Matcher: chooseExpr().bind(ID: "choose"), Context&: To->getASTContext());
1420 auto FromResults = match(Matcher: chooseExpr().bind(ID: "choose"), Context&: From->getASTContext());
1421
1422 const ChooseExpr *FromChooseExpr =
1423 selectFirst<ChooseExpr>(BoundTo: "choose", Results: FromResults);
1424 ASSERT_TRUE(FromChooseExpr);
1425
1426 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>(BoundTo: "choose", Results: ToResults);
1427 ASSERT_TRUE(ToChooseExpr);
1428
1429 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());
1430 EXPECT_EQ(FromChooseExpr->isConditionDependent(),
1431 ToChooseExpr->isConditionDependent());
1432}
1433
1434TEST_P(ASTImporterOptionSpecificTestBase, ImportConvertVectorExpr) {
1435 Decl *From, *To;
1436 std::tie(args&: From, args&: To) = getImportedDecl(
1437 FromSrcCode: "typedef double v4double __attribute__((__vector_size__(32)));"
1438 "typedef float v4float __attribute__((__vector_size__(16)));"
1439 "v4float vf;"
1440 "void declToImport() { (void)__builtin_convertvector(vf, v4double); }",
1441 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1442
1443 auto ToResults =
1444 match(Matcher: convertVectorExpr().bind(ID: "convert"), Context&: To->getASTContext());
1445 auto FromResults =
1446 match(Matcher: convertVectorExpr().bind(ID: "convert"), Context&: From->getASTContext());
1447
1448 const ConvertVectorExpr *FromConvertVectorExpr =
1449 selectFirst<ConvertVectorExpr>(BoundTo: "convert", Results: FromResults);
1450 ASSERT_TRUE(FromConvertVectorExpr);
1451
1452 const ConvertVectorExpr *ToConvertVectorExpr =
1453 selectFirst<ConvertVectorExpr>(BoundTo: "convert", Results: ToResults);
1454 ASSERT_TRUE(ToConvertVectorExpr);
1455}
1456
1457TEST_P(ASTImporterOptionSpecificTestBase, ImportGenericSelectionExpr) {
1458 Decl *From, *To;
1459 std::tie(args&: From, args&: To) = getImportedDecl(
1460 FromSrcCode: R"(
1461 int declToImport() {
1462 int x;
1463 return _Generic(x, int: 0, default: 1);
1464 }
1465 )",
1466 FromLang: Lang_C99, ToSrcCode: "", ToLang: Lang_C99);
1467
1468 auto ToResults =
1469 match(Matcher: genericSelectionExpr().bind(ID: "expr"), Context&: To->getASTContext());
1470 auto FromResults =
1471 match(Matcher: genericSelectionExpr().bind(ID: "expr"), Context&: From->getASTContext());
1472
1473 const GenericSelectionExpr *FromGenericSelectionExpr =
1474 selectFirst<GenericSelectionExpr>(BoundTo: "expr", Results: FromResults);
1475 ASSERT_TRUE(FromGenericSelectionExpr);
1476
1477 const GenericSelectionExpr *ToGenericSelectionExpr =
1478 selectFirst<GenericSelectionExpr>(BoundTo: "expr", Results: ToResults);
1479 ASSERT_TRUE(ToGenericSelectionExpr);
1480
1481 EXPECT_EQ(FromGenericSelectionExpr->isResultDependent(),
1482 ToGenericSelectionExpr->isResultDependent());
1483 EXPECT_EQ(FromGenericSelectionExpr->getResultIndex(),
1484 ToGenericSelectionExpr->getResultIndex());
1485}
1486
1487TEST_P(ASTImporterOptionSpecificTestBase,
1488 ImportFunctionWithBackReferringParameter) {
1489 Decl *From, *To;
1490 std::tie(args&: From, args&: To) = getImportedDecl(
1491 FromSrcCode: R"(
1492 template <typename T> struct X {};
1493
1494 void declToImport(int y, X<int> &x) {}
1495
1496 template <> struct X<int> {
1497 void g() {
1498 X<int> x;
1499 declToImport(0, x);
1500 }
1501 };
1502 )",
1503 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1504
1505 MatchVerifier<Decl> Verifier;
1506 auto Matcher = functionDecl(hasName(Name: "declToImport"),
1507 parameterCountIs(N: 2),
1508 hasParameter(N: 0, InnerMatcher: hasName(Name: "y")),
1509 hasParameter(N: 1, InnerMatcher: hasName(Name: "x")),
1510 hasParameter(N: 1, InnerMatcher: hasType(InnerMatcher: asString(Name: "X<int> &"))));
1511 ASSERT_TRUE(Verifier.match(From, Matcher));
1512 EXPECT_TRUE(Verifier.match(To, Matcher));
1513}
1514
1515TEST_P(ASTImporterOptionSpecificTestBase,
1516 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1517 Decl *From, *To;
1518 std::tie(args&: From, args&: To) =
1519 getImportedDecl(FromSrcCode: "template <typename T> void declToImport() { T a = 1; }"
1520 "void instantiate() { declToImport<int>(); }",
1521 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1522
1523 auto Check = [](Decl *D) -> bool {
1524 auto TU = D->getTranslationUnitDecl();
1525 for (auto Child : TU->decls()) {
1526 if (auto *FD = dyn_cast<FunctionDecl>(Child)) {
1527 if (FD->getNameAsString() == "declToImport") {
1528 GTEST_NONFATAL_FAILURE_(
1529 "TU should not contain any FunctionDecl with name declToImport");
1530 return false;
1531 }
1532 }
1533 }
1534 return true;
1535 };
1536
1537 ASSERT_TRUE(Check(From));
1538 EXPECT_TRUE(Check(To));
1539}
1540
1541TEST_P(ASTImporterOptionSpecificTestBase,
1542 TUshouldNotContainTemplatedDeclOfClassTemplates) {
1543 Decl *From, *To;
1544 std::tie(args&: From, args&: To) =
1545 getImportedDecl(FromSrcCode: "template <typename T> struct declToImport { T t; };"
1546 "void instantiate() { declToImport<int>(); }",
1547 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1548
1549 auto Check = [](Decl *D) -> bool {
1550 auto TU = D->getTranslationUnitDecl();
1551 for (auto Child : TU->decls()) {
1552 if (auto *RD = dyn_cast<CXXRecordDecl>(Child)) {
1553 if (RD->getNameAsString() == "declToImport") {
1554 GTEST_NONFATAL_FAILURE_(
1555 "TU should not contain any CXXRecordDecl with name declToImport");
1556 return false;
1557 }
1558 }
1559 }
1560 return true;
1561 };
1562
1563 ASSERT_TRUE(Check(From));
1564 EXPECT_TRUE(Check(To));
1565}
1566
1567TEST_P(ASTImporterOptionSpecificTestBase,
1568 TUshouldNotContainTemplatedDeclOfTypeAlias) {
1569 Decl *From, *To;
1570 std::tie(args&: From, args&: To) =
1571 getImportedDecl(
1572 FromSrcCode: "template <typename T> struct X {};"
1573 "template <typename T> using declToImport = X<T>;"
1574 "void instantiate() { declToImport<int> a; }",
1575 FromLang: Lang_CXX11, ToSrcCode: "", ToLang: Lang_CXX11);
1576
1577 auto Check = [](Decl *D) -> bool {
1578 auto TU = D->getTranslationUnitDecl();
1579 for (auto Child : TU->decls()) {
1580 if (auto *AD = dyn_cast<TypeAliasDecl>(Child)) {
1581 if (AD->getNameAsString() == "declToImport") {
1582 GTEST_NONFATAL_FAILURE_(
1583 "TU should not contain any TypeAliasDecl with name declToImport");
1584 return false;
1585 }
1586 }
1587 }
1588 return true;
1589 };
1590
1591 ASSERT_TRUE(Check(From));
1592 EXPECT_TRUE(Check(To));
1593}
1594
1595TEST_P(ASTImporterOptionSpecificTestBase,
1596 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
1597
1598 Decl *From, *To;
1599 std::tie(args&: From, args&: To) = getImportedDecl(
1600 FromSrcCode: R"(
1601 template<class T>
1602 class Base {};
1603 class declToImport : public Base<declToImport> {};
1604 )",
1605 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1606
1607 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1608 auto Pattern =
1609 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1610 ASSERT_TRUE(
1611 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1612 EXPECT_TRUE(
1613 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1614
1615 // Check that the ClassTemplateSpecializationDecl is the child of the
1616 // ClassTemplateDecl.
1617 Pattern = translationUnitDecl(has(classTemplateDecl(
1618 hasName(Name: "Base"), has(classTemplateSpecializationDecl()))));
1619 ASSERT_TRUE(
1620 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1621 EXPECT_TRUE(
1622 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1623}
1624
1625AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1626 size_t Index = 0;
1627 for (Decl *D : Node.decls()) {
1628 if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D)) {
1629 auto *ND = cast<NamedDecl>(D);
1630 if (Index == Order.size())
1631 return false;
1632 if (ND->getName() != Order[Index])
1633 return false;
1634 ++Index;
1635 }
1636 }
1637 return Index == Order.size();
1638}
1639
1640TEST_P(ASTImporterOptionSpecificTestBase,
1641 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1642 Decl *From, *To;
1643 std::tie(args&: From, args&: To) = getImportedDecl(
1644 FromSrcCode: R"(
1645 namespace NS {
1646 template<class T>
1647 class X {};
1648 template class X<int>;
1649 }
1650 )",
1651 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03, Identifier: "NS");
1652
1653 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1654 // ClassTemplateDecl.
1655 auto Pattern = namespaceDecl(has(classTemplateDecl(
1656 hasName(Name: "X"), unless(has(classTemplateSpecializationDecl())))));
1657 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1658 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1659
1660 // Check that the ClassTemplateSpecializationDecl is the child of the
1661 // NamespaceDecl.
1662 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName(Name: "X"))));
1663 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1664 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1665}
1666
1667TEST_P(ASTImporterOptionSpecificTestBase,
1668 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1669 Decl *From, *To;
1670 std::tie(args&: From, args&: To) =
1671 getImportedDecl(
1672 FromSrcCode: "struct declToImport { int a; int b; };",
1673 FromLang: Lang_CXX11, ToSrcCode: "", ToLang: Lang_CXX11);
1674
1675 MatchVerifier<Decl> Verifier;
1676 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1677 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1678}
1679
1680TEST_P(ASTImporterOptionSpecificTestBase,
1681 CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1682 Decl *From, *To;
1683 std::tie(args&: From, args&: To) = getImportedDecl(
1684 // The original recursive algorithm of ASTImporter first imports 'c' then
1685 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1686 FromSrcCode: R"s(
1687 struct declToImport {
1688 int a = c + b;
1689 int b = 1;
1690 int c = 2;
1691 };
1692 )s",
1693 FromLang: Lang_CXX11, ToSrcCode: "", ToLang: Lang_CXX11);
1694
1695 MatchVerifier<Decl> Verifier;
1696 ASSERT_TRUE(
1697 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1698 EXPECT_TRUE(
1699 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1700}
1701
1702TEST_P(ASTImporterOptionSpecificTestBase,
1703 CXXRecordDeclFieldAndIndirectFieldOrder) {
1704 Decl *From, *To;
1705 std::tie(args&: From, args&: To) = getImportedDecl(
1706 // First field is "a", then the field for unnamed union, then "b" and "c"
1707 // from it (indirect fields), then "d".
1708 FromSrcCode: R"s(
1709 struct declToImport {
1710 int a = d;
1711 union {
1712 int b;
1713 int c;
1714 };
1715 int d;
1716 };
1717 )s",
1718 FromLang: Lang_CXX11, ToSrcCode: "", ToLang: Lang_CXX11);
1719
1720 MatchVerifier<Decl> Verifier;
1721 ASSERT_TRUE(Verifier.match(
1722 From, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1723 EXPECT_TRUE(Verifier.match(
1724 To, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1725}
1726
1727TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
1728 Decl *From, *To;
1729 std::tie(args&: From, args&: To) = getImportedDecl(
1730 FromSrcCode: R"(
1731 struct declToImport {
1732 };
1733 )",
1734 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1735
1736 MatchVerifier<Decl> Verifier;
1737 // Match the implicit Decl.
1738 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1739 ASSERT_TRUE(Verifier.match(From, Matcher));
1740 EXPECT_TRUE(Verifier.match(To, Matcher));
1741}
1742
1743TEST_P(ASTImporterOptionSpecificTestBase,
1744 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1745 Decl *From, *To;
1746 std::tie(args&: From, args&: To) = getImportedDecl(
1747 FromSrcCode: R"(
1748 template <typename U>
1749 struct declToImport {
1750 };
1751 )",
1752 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1753
1754 MatchVerifier<Decl> Verifier;
1755 // Match the implicit Decl.
1756 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1757 ASSERT_TRUE(Verifier.match(From, Matcher));
1758 EXPECT_TRUE(Verifier.match(To, Matcher));
1759}
1760
1761TEST_P(ASTImporterOptionSpecificTestBase,
1762 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
1763 Decl *From, *To;
1764 std::tie(args&: From, args&: To) = getImportedDecl(
1765 FromSrcCode: R"(
1766 template<class T>
1767 class Base {};
1768 class declToImport : public Base<declToImport> {};
1769 )",
1770 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1771
1772 auto hasImplicitClass = has(cxxRecordDecl());
1773 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1774 hasName(Name: "Base"),
1775 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1776 ASSERT_TRUE(
1777 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1778 EXPECT_TRUE(
1779 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1780}
1781
1782TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
1783 Decl *From, *To;
1784 std::tie(args&: From, args&: To) =
1785 getImportedDecl(FromSrcCode: "void declToImport() {}", FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1786
1787 MatchVerifier<Decl> Verifier;
1788 auto Matcher = functionDecl();
1789 ASSERT_TRUE(Verifier.match(From, Matcher));
1790 EXPECT_TRUE(Verifier.match(To, Matcher));
1791 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1792}
1793
1794TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
1795 Decl *FromTU = getTuDecl(
1796 SrcCode: R"(
1797 struct X {};
1798 void operator<<(int, X);
1799 )",
1800 Lang: Lang_CXX03);
1801 Decl *From = LastDeclMatcher<Decl>{}.match(D: FromTU, AMatcher: functionDecl());
1802 const Decl *To = Import(From, ToLang: Lang_CXX03);
1803 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1804}
1805
1806TEST_P(ASTImporterOptionSpecificTestBase,
1807 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1808 Decl *From, *To;
1809 std::tie(args&: From, args&: To) = getImportedDecl(
1810 FromSrcCode: R"(
1811 template<class T>
1812 class Base { int a; };
1813 class declToImport : Base<declToImport> {};
1814 )",
1815 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1816
1817 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1818 hasName(Name: "Base"),
1819 has(classTemplateSpecializationDecl(has(fieldDecl(hasName(Name: "a"))))))));
1820 ASSERT_TRUE(
1821 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1822 EXPECT_TRUE(
1823 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1824}
1825
1826TEST_P(ASTImporterOptionSpecificTestBase,
1827 ImportDefinitionOfClassTemplateAfterFwdDecl) {
1828 {
1829 Decl *FromTU = getTuDecl(
1830 SrcCode: R"(
1831 template <typename T>
1832 struct B;
1833 )",
1834 Lang: Lang_CXX03, FileName: "input0.cc");
1835 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1836 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "B")));
1837
1838 Import(FromD, Lang_CXX03);
1839 }
1840
1841 {
1842 Decl *FromTU = getTuDecl(
1843 SrcCode: R"(
1844 template <typename T>
1845 struct B {
1846 void f();
1847 };
1848 )",
1849 Lang: Lang_CXX03, FileName: "input1.cc");
1850 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1851 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
1852 Import(From: FromD, Lang: Lang_CXX03);
1853 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1854 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "B")));
1855 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX03));
1856 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1857 }
1858}
1859
1860TEST_P(ASTImporterOptionSpecificTestBase,
1861 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1862 Decl *ToTU = getToTuDecl(
1863 ToSrcCode: R"(
1864 template <typename T>
1865 struct B {
1866 void f();
1867 };
1868
1869 template <typename T>
1870 struct B;
1871 )",
1872 ToLang: Lang_CXX03);
1873 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1874 [](const ClassTemplateDecl *T) {
1875 return T->isThisDeclarationADefinition();
1876 })
1877 .match(ToTU, classTemplateDecl()));
1878
1879 Decl *FromTU = getTuDecl(
1880 SrcCode: R"(
1881 template <typename T>
1882 struct B {
1883 void f();
1884 };
1885 )",
1886 Lang: Lang_CXX03, FileName: "input1.cc");
1887 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1888 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "B")));
1889
1890 Import(From: FromD, Lang: Lang_CXX03);
1891
1892 // We should have only one definition.
1893 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1894 [](const ClassTemplateDecl *T) {
1895 return T->isThisDeclarationADefinition();
1896 })
1897 .match(ToTU, classTemplateDecl()));
1898}
1899
1900TEST_P(ASTImporterOptionSpecificTestBase,
1901 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1902 Decl *ToTU = getToTuDecl(
1903 ToSrcCode: R"(
1904 struct B {
1905 void f();
1906 };
1907
1908 struct B;
1909 )",
1910 ToLang: Lang_CXX03);
1911 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
1912 ToTU, cxxRecordDecl(unless(isImplicit()))));
1913
1914 Decl *FromTU = getTuDecl(
1915 SrcCode: R"(
1916 struct B {
1917 void f();
1918 };
1919 )",
1920 Lang: Lang_CXX03, FileName: "input1.cc");
1921 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1922 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "B")));
1923
1924 Import(FromD, Lang_CXX03);
1925
1926 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
1927 ToTU, cxxRecordDecl(unless(isImplicit()))));
1928}
1929
1930static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1931 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1932 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1933 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1934 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1935}
1936static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1937 SourceManager &SM1, SourceManager &SM2) {
1938 CompareSourceLocs(Loc1: FullSourceLoc{ Range1.getBegin(), SM1 },
1939 Loc2: FullSourceLoc{ Range2.getBegin(), SM2 });
1940 CompareSourceLocs(Loc1: FullSourceLoc{ Range1.getEnd(), SM1 },
1941 Loc2: FullSourceLoc{ Range2.getEnd(), SM2 });
1942}
1943TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
1944 Decl *FromTU = getTuDecl(
1945 SrcCode: R"(
1946 #define MFOO(arg) arg = arg + 1
1947
1948 void foo() {
1949 int a = 5;
1950 MFOO(a);
1951 }
1952 )",
1953 Lang: Lang_CXX03);
1954 auto FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: functionDecl());
1955 auto ToD = Import(FromD, Lang_CXX03);
1956
1957 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
1958 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(D: FromTU, AMatcher: declRefExpr());
1959 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
1960 auto FromRHS =
1961 LastDeclMatcher<IntegerLiteral>().match(D: FromTU, AMatcher: integerLiteral());
1962
1963 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1964 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1965 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1966 FromSM);
1967 CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
1968 FromSM);
1969 CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
1970 FromSM);
1971}
1972
1973TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
1974 Decl *FromTU = getTuDecl(
1975 SrcCode: R"(
1976 #define FUNC_INT void declToImport
1977 #define FUNC FUNC_INT
1978 FUNC(int a);
1979 )",
1980 Lang: Lang_CXX03);
1981 auto FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: functionDecl());
1982 auto ToD = Import(FromD, Lang_CXX03);
1983
1984 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1985 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1986 CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
1987 FromSM);
1988}
1989
1990TEST_P(
1991 ASTImporterOptionSpecificTestBase,
1992 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
1993 Decl *ToTU = getToTuDecl(
1994 ToSrcCode: R"(
1995 template <typename T>
1996 struct B;
1997
1998 template <>
1999 struct B<int> {};
2000
2001 template <>
2002 struct B<int>;
2003 )",
2004 ToLang: Lang_CXX03);
2005 // We should have only one definition.
2006 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
2007 [](const ClassTemplateSpecializationDecl *T) {
2008 return T->isThisDeclarationADefinition();
2009 })
2010 .match(ToTU, classTemplateSpecializationDecl()));
2011
2012 Decl *FromTU = getTuDecl(
2013 SrcCode: R"(
2014 template <typename T>
2015 struct B;
2016
2017 template <>
2018 struct B<int> {};
2019 )",
2020 Lang: Lang_CXX03, FileName: "input1.cc");
2021 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
2022 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "B")));
2023
2024 Import(FromD, Lang_CXX03);
2025
2026 // We should have only one definition.
2027 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
2028 [](const ClassTemplateSpecializationDecl *T) {
2029 return T->isThisDeclarationADefinition();
2030 })
2031 .match(ToTU, classTemplateSpecializationDecl()));
2032}
2033
2034TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
2035 Decl *FromTU = getTuDecl(
2036 SrcCode: R"(
2037 struct { int a; int b; } object0 = { 2, 3 };
2038 struct { int x; int y; int z; } object1;
2039 )",
2040 Lang: Lang_CXX03, FileName: "input0.cc");
2041
2042 auto *Obj0 =
2043 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "object0")));
2044 auto *From0 = getRecordDecl(Obj0);
2045 auto *Obj1 =
2046 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "object1")));
2047 auto *From1 = getRecordDecl(Obj1);
2048
2049 auto *To0 = Import(From0, Lang_CXX03);
2050 auto *To1 = Import(From1, Lang_CXX03);
2051
2052 EXPECT_TRUE(To0);
2053 EXPECT_TRUE(To1);
2054 EXPECT_NE(To0, To1);
2055 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
2056}
2057
2058TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
2059 auto *Code =
2060 R"(
2061 struct X {
2062 struct { int a; };
2063 struct { int b; };
2064 };
2065 )";
2066 Decl *FromTU0 = getTuDecl(SrcCode: Code, Lang: Lang_C99, FileName: "input0.c");
2067
2068 Decl *FromTU1 = getTuDecl(SrcCode: Code, Lang: Lang_C99, FileName: "input1.c");
2069
2070 auto *X0 =
2071 FirstDeclMatcher<RecordDecl>().match(D: FromTU0, AMatcher: recordDecl(hasName(Name: "X")));
2072 auto *X1 =
2073 FirstDeclMatcher<RecordDecl>().match(D: FromTU1, AMatcher: recordDecl(hasName(Name: "X")));
2074 Import(X0, Lang_C99);
2075 Import(X1, Lang_C99);
2076
2077 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2078 // We expect no (ODR) warning during the import.
2079 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
2080 EXPECT_EQ(1u,
2081 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
2082}
2083
2084TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
2085 Decl *FromTU0 = getTuDecl(
2086 SrcCode: R"(
2087 struct X {
2088 struct { int a; };
2089 struct { int b; };
2090 };
2091 )",
2092 Lang: Lang_C99, FileName: "input0.c");
2093
2094 Decl *FromTU1 = getTuDecl(
2095 SrcCode: R"(
2096 struct X { // reversed order
2097 struct { int b; };
2098 struct { int a; };
2099 };
2100 )",
2101 Lang: Lang_C99, FileName: "input1.c");
2102
2103 auto *X0 =
2104 FirstDeclMatcher<RecordDecl>().match(D: FromTU0, AMatcher: recordDecl(hasName(Name: "X")));
2105 auto *X1 =
2106 FirstDeclMatcher<RecordDecl>().match(D: FromTU1, AMatcher: recordDecl(hasName(Name: "X")));
2107 Import(X0, Lang_C99);
2108 Import(X1, Lang_C99);
2109
2110 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2111 // We expect one (ODR) warning during the import.
2112 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
2113 EXPECT_EQ(1u,
2114 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
2115}
2116
2117TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
2118 auto Pattern = varDecl(hasName(Name: "x"));
2119 VarDecl *Imported1;
2120 {
2121 Decl *FromTU = getTuDecl(SrcCode: "extern int x;", Lang: Lang_CXX03, FileName: "input0.cc");
2122 auto *FromD = FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: Pattern);
2123 Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX03));
2124 }
2125 VarDecl *Imported2;
2126 {
2127 Decl *FromTU = getTuDecl(SrcCode: "int x;", Lang: Lang_CXX03, FileName: "input1.cc");
2128 auto *FromD = FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: Pattern);
2129 Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX03));
2130 }
2131 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
2132 EXPECT_FALSE(Imported2->isUsed(false));
2133 {
2134 Decl *FromTU = getTuDecl(SrcCode: "extern int x; int f() { return x; }", Lang: Lang_CXX03,
2135 FileName: "input2.cc");
2136 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2137 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
2138 Import(FromD, Lang_CXX03);
2139 }
2140 EXPECT_TRUE(Imported2->isUsed(false));
2141}
2142
2143TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
2144 auto Pattern = varDecl(hasName(Name: "x"));
2145 VarDecl *ExistingD;
2146 {
2147 Decl *ToTU = getToTuDecl(ToSrcCode: "int x = 1;", ToLang: Lang_CXX03);
2148 ExistingD = FirstDeclMatcher<VarDecl>().match(D: ToTU, AMatcher: Pattern);
2149 }
2150 EXPECT_FALSE(ExistingD->isUsed(false));
2151 {
2152 Decl *FromTU =
2153 getTuDecl(SrcCode: "int x = 1; int f() { return x; }", Lang: Lang_CXX03, FileName: "input1.cc");
2154 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2155 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
2156 Import(FromD, Lang_CXX03);
2157 }
2158 EXPECT_TRUE(ExistingD->isUsed(false));
2159}
2160
2161TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
2162 auto Pattern = varDecl(hasName(Name: "a"));
2163 VarDecl *ExistingD;
2164 {
2165 Decl *ToTU = getToTuDecl(
2166 ToSrcCode: R"(
2167 struct A {
2168 static const int a = 1;
2169 };
2170 )",
2171 ToLang: Lang_CXX03);
2172 ExistingD = FirstDeclMatcher<VarDecl>().match(D: ToTU, AMatcher: Pattern);
2173 }
2174 EXPECT_FALSE(ExistingD->isUsed(false));
2175 {
2176 Decl *FromTU = getTuDecl(
2177 SrcCode: R"(
2178 struct A {
2179 static const int a = 1;
2180 };
2181 const int *f() { return &A::a; } // requires storage,
2182 // thus used flag will be set
2183 )",
2184 Lang: Lang_CXX03, FileName: "input1.cc");
2185 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
2186 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
2187 auto *FromD = FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: Pattern);
2188 ASSERT_TRUE(FromD->isUsed(false));
2189 Import(FromFunD, Lang_CXX03);
2190 }
2191 EXPECT_TRUE(ExistingD->isUsed(false));
2192}
2193
2194TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
2195 auto Pattern = varDecl(hasName(Name: "x"));
2196
2197 Decl *FromTU = getTuDecl(SrcCode: "int x;", Lang: Lang_CXX03, FileName: "input0.cc");
2198 auto *FromD = FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: Pattern);
2199
2200 auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX03));
2201
2202 ASSERT_FALSE(Imported1->isUsed(false));
2203
2204 FromD->setIsUsed();
2205 auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX03));
2206
2207 EXPECT_EQ(Imported1, Imported2);
2208 EXPECT_TRUE(Imported2->isUsed(false));
2209}
2210
2211struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
2212
2213TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
2214 Decl *FromTU = getTuDecl(SrcCode: "void f(); void f() { f(); }", Lang: Lang_CXX03);
2215 auto Pattern = functionDecl(hasName(Name: "f"));
2216 auto *From =
2217 FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern); // Proto
2218
2219 Decl *ImportedD = Import(From, Lang_CXX03);
2220 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2221
2222 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2223 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2224 auto *To1 = LastDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2225 EXPECT_TRUE(ImportedD == To0);
2226 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2227 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2228 EXPECT_EQ(To1->getPreviousDecl(), To0);
2229}
2230
2231TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
2232 Decl *FromTU = getTuDecl(SrcCode: "void f(); void f() { f(); }", Lang: Lang_CXX03);
2233 auto Pattern = functionDecl(hasName(Name: "f"));
2234 auto *From =
2235 LastDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern); // Def
2236
2237 Decl *ImportedD = Import(From, Lang_CXX03);
2238 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2239
2240 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2241 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2242 auto *To1 = LastDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2243 EXPECT_TRUE(ImportedD == To1);
2244 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2245 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2246 EXPECT_EQ(To1->getPreviousDecl(), To0);
2247}
2248
2249TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2250 auto Code =
2251 R"(
2252 struct B { virtual void f(); };
2253 void B::f() {}
2254 struct D : B { void f(); };
2255 )";
2256 auto Pattern =
2257 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "D"))));
2258 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
2259 CXXMethodDecl *Proto =
2260 FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU, AMatcher: Pattern);
2261
2262 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2263 CXXMethodDecl *To = cast<CXXMethodDecl>(Val: Import(From: Proto, Lang: Lang_CXX03));
2264 EXPECT_EQ(To->size_overridden_methods(), 1u);
2265}
2266
2267TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2268 auto Code =
2269 R"(
2270 struct B { virtual void f(); };
2271 void B::f() {}
2272 )";
2273 auto Pattern =
2274 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))));
2275 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
2276 CXXMethodDecl *Proto =
2277 FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU, AMatcher: Pattern);
2278 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(D: FromTU, AMatcher: Pattern);
2279
2280 ASSERT_TRUE(Proto->isVirtual());
2281 ASSERT_TRUE(Def->isVirtual());
2282 CXXMethodDecl *To = cast<CXXMethodDecl>(Val: Import(From: Proto, Lang: Lang_CXX03));
2283 EXPECT_TRUE(To->isVirtual());
2284}
2285
2286TEST_P(ImportFunctions,
2287 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2288 Decl *ToTU = getToTuDecl(
2289 ToSrcCode: R"(
2290 void f() {}
2291 void f();
2292 )",
2293 ToLang: Lang_CXX03);
2294 ASSERT_EQ(1u,
2295 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2296 return FD->doesThisDeclarationHaveABody();
2297 }).match(ToTU, functionDecl()));
2298
2299 Decl *FromTU = getTuDecl(SrcCode: "void f() {}", Lang: Lang_CXX03, FileName: "input0.cc");
2300 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: functionDecl());
2301
2302 Import(FromD, Lang_CXX03);
2303
2304 EXPECT_EQ(1u,
2305 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2306 return FD->doesThisDeclarationHaveABody();
2307 }).match(ToTU, functionDecl()));
2308}
2309
2310TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
2311 auto Code =
2312 R"(
2313 struct B { virtual void f(); };
2314 struct D:B { void f(); };
2315 )";
2316 auto BFP =
2317 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))));
2318 auto DFP =
2319 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "D"))));
2320
2321 Decl *FromTU0 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
2322 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU0, AMatcher: DFP);
2323 Import(DF, Lang_CXX03);
2324
2325 Decl *FromTU1 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input1.cc");
2326 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU1, AMatcher: BFP);
2327 Import(BF, Lang_CXX03);
2328
2329 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2330
2331 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2332 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2333}
2334
2335TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2336 auto CodeWithoutDef =
2337 R"(
2338 struct B { virtual void f(); };
2339 struct D:B { void f(); };
2340 )";
2341 auto CodeWithDef =
2342 R"(
2343 struct B { virtual void f(){}; };
2344 struct D:B { void f(){}; };
2345 )";
2346 auto BFP =
2347 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))));
2348 auto DFP =
2349 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "D"))));
2350 auto BFDefP = cxxMethodDecl(
2351 hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))), isDefinition());
2352 auto DFDefP = cxxMethodDecl(
2353 hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "D"))), isDefinition());
2354 auto FDefAllP = cxxMethodDecl(hasName(Name: "f"), isDefinition());
2355
2356 {
2357 Decl *FromTU = getTuDecl(SrcCode: CodeWithDef, Lang: Lang_CXX03, FileName: "input0.cc");
2358 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU, AMatcher: DFP);
2359 Import(FromD, Lang_CXX03);
2360 }
2361 {
2362 Decl *FromTU = getTuDecl(SrcCode: CodeWithoutDef, Lang: Lang_CXX03, FileName: "input1.cc");
2363 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU, AMatcher: BFP);
2364 Import(FromB, Lang_CXX03);
2365 }
2366
2367 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2368
2369 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2370 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2371 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2372 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2373 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2374}
2375
2376TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2377 auto Code =
2378 R"(
2379 struct B { virtual void f(); };
2380 struct D:B { void f(); };
2381 void B::f(){};
2382 )";
2383
2384 auto BFP =
2385 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))));
2386 auto BFDefP = cxxMethodDecl(
2387 hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))), isDefinition());
2388 auto DFP = cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "D"))),
2389 unless(isDefinition()));
2390
2391 Decl *FromTU0 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
2392 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU0, AMatcher: DFP);
2393 Import(D, Lang_CXX03);
2394
2395 Decl *FromTU1 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input1.cc");
2396 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU1, AMatcher: BFP);
2397 Import(B, Lang_CXX03);
2398
2399 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2400
2401 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2402 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2403
2404 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2405 ToTU, cxxRecordDecl(hasName(Name: "B")));
2406 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2407 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2408 ToTU, cxxMethodDecl(hasName(Name: "f"), isDefinition()));
2409
2410 // The definition should be out-of-class.
2411 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2412 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2413 ToBFOutOfClass->getLexicalDeclContext());
2414 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2415 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2416
2417 // Check that the redecl chain is intact.
2418 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2419}
2420
2421TEST_P(ImportFunctions,
2422 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2423 auto CodeTU0 =
2424 R"(
2425 struct B { virtual void f(); };
2426 struct D:B { void f(); };
2427 )";
2428 auto CodeTU1 =
2429 R"(
2430 struct B { virtual void f(); };
2431 struct D:B { void f(); };
2432 void B::f(){}
2433 void D::f(){}
2434 void foo(B &b, D &d) { b.f(); d.f(); }
2435 )";
2436
2437 auto BFP =
2438 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))));
2439 auto BFDefP = cxxMethodDecl(
2440 hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))), isDefinition());
2441 auto DFP =
2442 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "D"))));
2443 auto DFDefP = cxxMethodDecl(
2444 hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "D"))), isDefinition());
2445 auto FooDef = functionDecl(hasName(Name: "foo"));
2446
2447 {
2448 Decl *FromTU0 = getTuDecl(SrcCode: CodeTU0, Lang: Lang_CXX03, FileName: "input0.cc");
2449 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU0, AMatcher: DFP);
2450 Import(D, Lang_CXX03);
2451 }
2452
2453 {
2454 Decl *FromTU1 = getTuDecl(SrcCode: CodeTU1, Lang: Lang_CXX03, FileName: "input1.cc");
2455 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(D: FromTU1, AMatcher: FooDef);
2456 Import(Foo, Lang_CXX03);
2457 }
2458
2459 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2460
2461 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2462 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2463 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2464 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2465
2466 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2467 ToTU, cxxRecordDecl(hasName(Name: "B")));
2468 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2469 ToTU, cxxRecordDecl(hasName(Name: "D")));
2470 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, BFP);
2471 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2472 ToTU, cxxMethodDecl(hasName(Name: "f"), isDefinition()));
2473 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(ToTU, DFP);
2474 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2475 ToTU, cxxMethodDecl(hasName(Name: "f"), isDefinition()));
2476
2477 // The definition should be out-of-class.
2478 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2479 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2480 ToBFOutOfClass->getLexicalDeclContext());
2481 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2482 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2483
2484 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2485 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2486 ToDFOutOfClass->getLexicalDeclContext());
2487 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2488 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2489
2490 // Check that the redecl chain is intact.
2491 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2492 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2493}
2494
2495TEST_P(ASTImporterOptionSpecificTestBase,
2496 ImportVirtualOverriddenMethodOnALoop) {
2497 // B::f() calls => f1() ==> C ==> C::f()
2498 // \
2499 // \---- A::f()
2500 //
2501 // C::f()'s ImportOverriddenMethods() asserts B::isVirtual(), so B::f()'s
2502 // ImportOverriddenMethods() should be completed before B::f()'s body
2503 const char *Code =
2504 R"(
2505 void f1();
2506 class A {
2507 virtual void f(){}
2508 };
2509 class B: public A {
2510 void f() override {
2511 f1();
2512 }
2513 };
2514 class C: public B {
2515 void f() override {}
2516 };
2517 void f1() { C c; }
2518 )";
2519 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
2520
2521 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
2522 D: FromTU, AMatcher: cxxMethodDecl(hasName(Name: "B::f")));
2523
2524 auto *ToBF = Import(FromF, Lang_CXX11);
2525 EXPECT_TRUE(ToBF->isVirtual());
2526
2527 auto *ToCF = FirstDeclMatcher<CXXMethodDecl>().match(
2528 ToBF->getTranslationUnitDecl(), cxxMethodDecl(hasName(Name: "C::f")));
2529 EXPECT_TRUE(ToCF->isVirtual());
2530}
2531
2532TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2533 std::string Code = "static int v; static int v = 0;";
2534 auto Pattern = varDecl(hasName(Name: "v"));
2535
2536 TranslationUnitDecl *FromTu = getTuDecl(SrcCode: Code, Lang: Lang_C99, FileName: "input0.c");
2537
2538 auto *From0 = FirstDeclMatcher<VarDecl>().match(FromTu, Pattern);
2539 auto *From1 = LastDeclMatcher<VarDecl>().match(FromTu, Pattern);
2540
2541 auto *To0 = Import(From0, Lang_C99);
2542 auto *To1 = Import(From1, Lang_C99);
2543
2544 EXPECT_TRUE(To0);
2545 ASSERT_TRUE(To1);
2546 EXPECT_NE(To0, To1);
2547 EXPECT_EQ(To1->getPreviousDecl(), To0);
2548}
2549
2550TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2551 TranslationUnitDecl *FromTu =
2552 getTuDecl(SrcCode: "namespace NS0 { namespace { void f(); } }"
2553 "namespace NS1 { namespace { void f(); } }",
2554 Lang: Lang_CXX03, FileName: "input0.cc");
2555 auto Pattern = functionDecl(hasName(Name: "f"));
2556
2557 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2558 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(FromTu, Pattern);
2559
2560 auto *ToF0 = Import(FromF0, Lang_CXX03);
2561 auto *ToF1 = Import(FromF1, Lang_CXX03);
2562
2563 EXPECT_TRUE(ToF0);
2564 ASSERT_TRUE(ToF1);
2565 EXPECT_NE(ToF0, ToF1);
2566 EXPECT_FALSE(ToF1->getPreviousDecl());
2567}
2568
2569TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2570 {
2571 Decl *FromTU = getTuDecl(SrcCode: "namespace { void f() {} } void g0() { f(); }",
2572 Lang: Lang_CXX03, FileName: "input0.cc");
2573 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2574 D: FromTU, AMatcher: functionDecl(hasName(Name: "g0")));
2575
2576 Import(FromD, Lang_CXX03);
2577 }
2578 {
2579 Decl *FromTU =
2580 getTuDecl(SrcCode: "namespace { void f() { int a; } } void g1() { f(); }",
2581 Lang: Lang_CXX03, FileName: "input1.cc");
2582 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2583 D: FromTU, AMatcher: functionDecl(hasName(Name: "g1")));
2584 Import(FromD, Lang_CXX03);
2585 }
2586
2587 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2588 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2589 2u);
2590}
2591
2592TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2593 Decl *FromTU = getTuDecl(
2594 SrcCode: R"(
2595 void foo() {
2596 (void)[]() { ; };
2597 }
2598 )",
2599 Lang: Lang_CXX11);
2600 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2601 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo")));
2602 auto *ToD = Import(FromD, Lang_CXX03);
2603 EXPECT_TRUE(ToD);
2604 CXXRecordDecl *LambdaRec =
2605 cast<LambdaExpr>(cast<CStyleCastExpr>(
2606 *cast<CompoundStmt>(ToD->getBody())->body_begin())
2607 ->getSubExpr())
2608 ->getLambdaClass();
2609 EXPECT_TRUE(LambdaRec->getDestructor());
2610}
2611
2612TEST_P(ImportFunctions,
2613 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2614 Decl *FromTU = getTuDecl(
2615 SrcCode: R"(
2616 struct X {
2617 template <typename T>
2618 void foo(){}
2619 };
2620 void f() {
2621 X x;
2622 x.foo<int>();
2623 }
2624 )",
2625 Lang: Lang_CXX03);
2626 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2627 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
2628 auto *ToD = Import(FromD, Lang_CXX03);
2629 EXPECT_TRUE(ToD);
2630 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
2631 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr()))));
2632}
2633
2634TEST_P(ImportFunctions,
2635 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2636 Decl *FromTU = getTuDecl(
2637 SrcCode: R"(
2638 struct X {
2639 template <typename T>
2640 void foo(){}
2641 };
2642 template <typename T>
2643 void f() {
2644 X x;
2645 x.foo<T>();
2646 }
2647 void g() {
2648 f<int>();
2649 }
2650 )",
2651 Lang: Lang_CXX03);
2652 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2653 D: FromTU, AMatcher: functionDecl(hasName(Name: "g")));
2654 auto *ToD = Import(FromD, Lang_CXX03);
2655 EXPECT_TRUE(ToD);
2656 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2657 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match(
2658 ToTU, translationUnitDecl(hasDescendant(
2659 functionDecl(hasName("f"), hasDescendant(declRefExpr()))))));
2660}
2661
2662struct ImportFunctionTemplates : ASTImporterOptionSpecificTestBase {};
2663
2664TEST_P(ImportFunctionTemplates, ImportFunctionTemplateInRecordDeclTwice) {
2665 auto Code =
2666 R"(
2667 class X {
2668 template <class T>
2669 void f(T t);
2670 };
2671 )";
2672 Decl *FromTU1 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input1.cc");
2673 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2674 D: FromTU1, AMatcher: functionTemplateDecl(hasName(Name: "f")));
2675 auto *ToD1 = Import(FromD1, Lang_CXX03);
2676 Decl *FromTU2 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input2.cc");
2677 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2678 D: FromTU2, AMatcher: functionTemplateDecl(hasName(Name: "f")));
2679 auto *ToD2 = Import(FromD2, Lang_CXX03);
2680 EXPECT_EQ(ToD1, ToD2);
2681}
2682
2683TEST_P(ImportFunctionTemplates,
2684 ImportFunctionTemplateWithDefInRecordDeclTwice) {
2685 auto Code =
2686 R"(
2687 class X {
2688 template <class T>
2689 void f(T t);
2690 };
2691 template <class T>
2692 void X::f(T t) {};
2693 )";
2694 Decl *FromTU1 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input1.cc");
2695 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2696 D: FromTU1, AMatcher: functionTemplateDecl(hasName(Name: "f")));
2697 auto *ToD1 = Import(FromD1, Lang_CXX03);
2698 Decl *FromTU2 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input2.cc");
2699 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2700 D: FromTU2, AMatcher: functionTemplateDecl(hasName(Name: "f")));
2701 auto *ToD2 = Import(FromD2, Lang_CXX03);
2702 EXPECT_EQ(ToD1, ToD2);
2703}
2704
2705TEST_P(ImportFunctionTemplates,
2706 ImportFunctionWhenThereIsAFunTemplateWithSameName) {
2707 getToTuDecl(
2708 ToSrcCode: R"(
2709 template <typename T>
2710 void foo(T) {}
2711 void foo();
2712 )",
2713 ToLang: Lang_CXX03);
2714 Decl *FromTU = getTuDecl(SrcCode: "void foo();", Lang: Lang_CXX03);
2715 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2716 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo")));
2717 auto *ImportedD = Import(FromD, Lang_CXX03);
2718 EXPECT_TRUE(ImportedD);
2719}
2720
2721TEST_P(ImportFunctionTemplates,
2722 ImportConstructorWhenThereIsAFunTemplateWithSameName) {
2723 auto Code =
2724 R"(
2725 struct Foo {
2726 template <typename T>
2727 Foo(T) {}
2728 Foo();
2729 };
2730 )";
2731 getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX03);
2732 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
2733 auto *FromD =
2734 LastDeclMatcher<CXXConstructorDecl>().match(D: FromTU, AMatcher: cxxConstructorDecl());
2735 auto *ImportedD = Import(FromD, Lang_CXX03);
2736 EXPECT_TRUE(ImportedD);
2737}
2738
2739TEST_P(ImportFunctionTemplates,
2740 ImportOperatorWhenThereIsAFunTemplateWithSameName) {
2741 getToTuDecl(
2742 ToSrcCode: R"(
2743 template <typename T>
2744 void operator<(T,T) {}
2745 struct X{};
2746 void operator<(X, X);
2747 )",
2748 ToLang: Lang_CXX03);
2749 Decl *FromTU = getTuDecl(
2750 SrcCode: R"(
2751 struct X{};
2752 void operator<(X, X);
2753 )",
2754 Lang: Lang_CXX03);
2755 auto *FromD = LastDeclMatcher<FunctionDecl>().match(
2756 D: FromTU, AMatcher: functionDecl(hasOverloadedOperatorName(Name: "<")));
2757 auto *ImportedD = Import(FromD, Lang_CXX03);
2758 EXPECT_TRUE(ImportedD);
2759}
2760
2761struct ImportFriendFunctions : ImportFunctions {};
2762
2763TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2764 auto Pattern = functionDecl(hasName(Name: "f"));
2765
2766 Decl *FromTU = getTuDecl(SrcCode: "struct X { friend void f(); };"
2767 "void f();",
2768 Lang: Lang_CXX03, FileName: "input0.cc");
2769 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2770
2771 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2772 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2773 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2774 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2775 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2776 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2777 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2778}
2779
2780TEST_P(ImportFriendFunctions,
2781 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2782 auto Pattern = functionDecl(hasName(Name: "f"));
2783
2784 Decl *FromTU = getTuDecl(SrcCode: "void f();"
2785 "struct X { friend void f(); };",
2786 Lang: Lang_CXX03, FileName: "input0.cc");
2787 auto FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2788
2789 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2790 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2791 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2792 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2793 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2794 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2795 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2796}
2797
2798TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2799 auto Pattern = functionDecl(hasName(Name: "f"));
2800
2801 Decl *FromTU = getTuDecl(SrcCode: "struct X { friend void f(){} };"
2802 "void f();",
2803 Lang: Lang_CXX03, FileName: "input0.cc");
2804 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2805
2806 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2807 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2808 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2809 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2810 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2811 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2812 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2813}
2814
2815TEST_P(ImportFriendFunctions,
2816 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2817 auto Pattern = functionDecl(hasName(Name: "f"));
2818
2819 Decl *FromTU = getTuDecl(SrcCode: "struct X { friend void f(); };"
2820 "void f(){}",
2821 Lang: Lang_CXX03, FileName: "input0.cc");
2822 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2823
2824 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2825 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2826 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2827 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2828 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2829 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2830 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2831}
2832
2833TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDefWithClass) {
2834 auto Pattern = functionDecl(hasName(Name: "f"));
2835
2836 Decl *FromTU = getTuDecl(
2837 SrcCode: R"(
2838 class X;
2839 void f(X *x){}
2840 class X{
2841 friend void f(X *x);
2842 };
2843 )",
2844 Lang: Lang_CXX03, FileName: "input0.cc");
2845 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2846
2847 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2848 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2849 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2850 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2851 auto *InClassFD = cast<FunctionDecl>(Val: FirstDeclMatcher<FriendDecl>()
2852 .match(D: ToTU, AMatcher: friendDecl())
2853 ->getFriendDecl());
2854 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2855 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2856 // The parameters must refer the same type
2857 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2858 (*ImportedD->param_begin())->getOriginalType());
2859}
2860
2861TEST_P(ImportFriendFunctions,
2862 ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
2863 auto Pattern = functionDecl(hasName(Name: "f"));
2864
2865 Decl *FromTU = getTuDecl(
2866 SrcCode: R"(
2867 class X;
2868 void f(X *x){}
2869 class X{
2870 friend void f(X *x);
2871 };
2872 )",
2873 Lang: Lang_CXX03, FileName: "input0.cc");
2874 auto *FromD = LastDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2875
2876 auto *ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2877 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2878 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2879 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2880 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2881 D: ToTU, AMatcher: functionDecl(unless(hasParent(friendDecl()))));
2882
2883 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2884 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2885 // The parameters must refer the same type
2886 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2887 (*ImportedD->param_begin())->getOriginalType());
2888}
2889
2890TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2891 auto Pattern = functionDecl(hasName(Name: "f"));
2892
2893 FunctionDecl *ImportedD;
2894 {
2895 Decl *FromTU =
2896 getTuDecl(SrcCode: "struct X { friend void f(){} };", Lang: Lang_CXX03, FileName: "input0.cc");
2897 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2898 ImportedD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2899 }
2900 FunctionDecl *ImportedD1;
2901 {
2902 Decl *FromTU = getTuDecl(SrcCode: "void f();", Lang: Lang_CXX03, FileName: "input1.cc");
2903 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2904 ImportedD1 = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2905 }
2906
2907 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2908 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2909 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2910 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2911 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2912}
2913
2914TEST_P(ImportFriendFunctions, Lookup) {
2915 auto FunctionPattern = functionDecl(hasName(Name: "f"));
2916 auto ClassPattern = cxxRecordDecl(hasName(Name: "X"));
2917
2918 TranslationUnitDecl *FromTU =
2919 getTuDecl(SrcCode: "struct X { friend void f(); };", Lang: Lang_CXX03, FileName: "input0.cc");
2920 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2921 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2922 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2923 {
2924 auto FromName = FromD->getDeclName();
2925 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2926 auto LookupRes = Class->noload_lookup(FromName);
2927 ASSERT_TRUE(LookupRes.empty());
2928 LookupRes = FromTU->noload_lookup(Name: FromName);
2929 ASSERT_TRUE(LookupRes.isSingleResult());
2930 }
2931
2932 auto *ToD = cast<FunctionDecl>(Import(FromD, Lang_CXX03));
2933 auto ToName = ToD->getDeclName();
2934
2935 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2936 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2937 auto LookupRes = Class->noload_lookup(ToName);
2938 EXPECT_TRUE(LookupRes.empty());
2939 LookupRes = ToTU->noload_lookup(Name: ToName);
2940 EXPECT_TRUE(LookupRes.isSingleResult());
2941
2942 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2943 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2944 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2945 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2946}
2947
2948TEST_P(ImportFriendFunctions, LookupWithProtoAfter) {
2949 auto FunctionPattern = functionDecl(hasName(Name: "f"));
2950 auto ClassPattern = cxxRecordDecl(hasName(Name: "X"));
2951
2952 TranslationUnitDecl *FromTU =
2953 getTuDecl(SrcCode: "struct X { friend void f(); };"
2954 // This proto decl makes f available to normal
2955 // lookup, otherwise it is hidden.
2956 // Normal C++ lookup (implemented in
2957 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2958 // returns the found `NamedDecl` only if the set IDNS is matched
2959 "void f();",
2960 Lang: Lang_CXX03, FileName: "input0.cc");
2961 auto *FromFriend =
2962 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2963 auto *FromNormal =
2964 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
2965 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2966 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2967 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2968 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2969
2970 auto FromName = FromFriend->getDeclName();
2971 auto *FromClass =
2972 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
2973 auto LookupRes = FromClass->noload_lookup(FromName);
2974 ASSERT_TRUE(LookupRes.empty());
2975 LookupRes = FromTU->noload_lookup(Name: FromName);
2976 ASSERT_TRUE(LookupRes.isSingleResult());
2977
2978 auto *ToFriend = cast<FunctionDecl>(Import(FromFriend, Lang_CXX03));
2979 auto ToName = ToFriend->getDeclName();
2980
2981 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2982 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
2983 LookupRes = ToClass->noload_lookup(ToName);
2984 EXPECT_TRUE(LookupRes.empty());
2985 LookupRes = ToTU->noload_lookup(Name: ToName);
2986 // Test is disabled because this result is 2.
2987 EXPECT_TRUE(LookupRes.isSingleResult());
2988
2989 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2990 ToFriend = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2991 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
2992 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2993 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2994 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2995 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2996}
2997
2998TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
2999 auto FunctionPattern = functionDecl(hasName(Name: "f"));
3000 auto ClassPattern = cxxRecordDecl(hasName(Name: "X"));
3001
3002 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: "void f();"
3003 "struct X { friend void f(); };",
3004 Lang: Lang_CXX03, FileName: "input0.cc");
3005 auto *FromNormal =
3006 FirstDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
3007 auto *FromFriend =
3008 LastDeclMatcher<FunctionDecl>().match(FromTU, FunctionPattern);
3009 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3010 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3011 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3012 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3013
3014 auto FromName = FromNormal->getDeclName();
3015 auto *FromClass =
3016 FirstDeclMatcher<CXXRecordDecl>().match(FromTU, ClassPattern);
3017 auto LookupRes = FromClass->noload_lookup(FromName);
3018 ASSERT_TRUE(LookupRes.empty());
3019 LookupRes = FromTU->noload_lookup(Name: FromName);
3020 ASSERT_TRUE(LookupRes.isSingleResult());
3021
3022 auto *ToNormal = cast<FunctionDecl>(Import(FromNormal, Lang_CXX03));
3023 auto ToName = ToNormal->getDeclName();
3024 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3025
3026 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, ClassPattern);
3027 LookupRes = ToClass->noload_lookup(ToName);
3028 EXPECT_TRUE(LookupRes.empty());
3029 LookupRes = ToTU->noload_lookup(Name: ToName);
3030 EXPECT_TRUE(LookupRes.isSingleResult());
3031
3032 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
3033 ToNormal = FirstDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
3034 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(ToTU, FunctionPattern);
3035 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3036 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3037 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3038 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3039}
3040
3041TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
3042 auto Pattern = functionDecl(hasName(Name: "f"));
3043
3044 TranslationUnitDecl *FromNormalTU =
3045 getTuDecl(SrcCode: "void f();", Lang: Lang_CXX03, FileName: "input0.cc");
3046 auto *FromNormalF =
3047 FirstDeclMatcher<FunctionDecl>().match(FromNormalTU, Pattern);
3048 TranslationUnitDecl *FromFriendTU =
3049 getTuDecl(SrcCode: "class X { friend void f(); };", Lang: Lang_CXX03, FileName: "input1.cc");
3050 auto *FromFriendF =
3051 FirstDeclMatcher<FunctionDecl>().match(FromFriendTU, Pattern);
3052 auto FromNormalName = FromNormalF->getDeclName();
3053 auto FromFriendName = FromFriendF->getDeclName();
3054
3055 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3056 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3057 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3058 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3059 auto LookupRes = FromNormalTU->noload_lookup(Name: FromNormalName);
3060 ASSERT_TRUE(LookupRes.isSingleResult());
3061 LookupRes = FromFriendTU->noload_lookup(Name: FromFriendName);
3062 ASSERT_TRUE(LookupRes.isSingleResult());
3063
3064 auto *ToNormalF = cast<FunctionDecl>(Import(FromNormalF, Lang_CXX03));
3065 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3066 auto ToName = ToNormalF->getDeclName();
3067 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3068 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3069 LookupRes = ToTU->noload_lookup(Name: ToName);
3070 EXPECT_TRUE(LookupRes.isSingleResult());
3071 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
3072
3073 auto *ToFriendF = cast<FunctionDecl>(Import(FromFriendF, Lang_CXX03));
3074 LookupRes = ToTU->noload_lookup(Name: ToName);
3075 EXPECT_TRUE(LookupRes.isSingleResult());
3076 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3077
3078 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3079 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3080
3081 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3082 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3083}
3084
3085TEST_P(ImportFriendFunctions, ImportFriendList) {
3086 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: "struct X { friend void f(); };"
3087 "void f();",
3088 Lang: Lang_CXX03, FileName: "input0.cc");
3089 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
3090 FromTU, functionDecl(hasName(Name: "f")));
3091
3092 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3093 FromTU, cxxRecordDecl(hasName(Name: "X")));
3094 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(FromTU, friendDecl());
3095 auto FromFriends = FromClass->friends();
3096 unsigned int FrN = 0;
3097 for (auto Fr : FromFriends) {
3098 ASSERT_EQ(Fr, FromFriend);
3099 ++FrN;
3100 }
3101 ASSERT_EQ(FrN, 1u);
3102
3103 Import(FromFriendF, Lang_CXX03);
3104 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3105 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3106 ToTU, cxxRecordDecl(hasName(Name: "X")));
3107 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
3108 auto ToFriends = ToClass->friends();
3109 FrN = 0;
3110 for (auto Fr : ToFriends) {
3111 EXPECT_EQ(Fr, ToFriend);
3112 ++FrN;
3113 }
3114 EXPECT_EQ(FrN, 1u);
3115}
3116
3117AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
3118 InnerMatcher) {
3119 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
3120 return InnerMatcher.matches(Node: *Typedef, Finder, Builder);
3121 return false;
3122}
3123
3124TEST_P(ImportDecl, ImportEnumSequential) {
3125 CodeFiles Samples{{"main.c",
3126 {.CodeSample: "void foo();"
3127 "void moo();"
3128 "int main() { foo(); moo(); }",
3129 .Lang: Lang_C99}},
3130
3131 {"foo.c",
3132 {.CodeSample: "typedef enum { THING_VALUE } thing_t;"
3133 "void conflict(thing_t type);"
3134 "void foo() { (void)THING_VALUE; }"
3135 "void conflict(thing_t type) {}",
3136 .Lang: Lang_C99}},
3137
3138 {"moo.c",
3139 {.CodeSample: "typedef enum { THING_VALUE } thing_t;"
3140 "void conflict(thing_t type);"
3141 "void moo() { conflict(THING_VALUE); }",
3142 .Lang: Lang_C99}}};
3143
3144 auto VerificationMatcher =
3145 enumDecl(has(enumConstantDecl(hasName(Name: "THING_VALUE"))),
3146 hasTypedefForAnonDecl(InnerMatcher: hasName(Name: "thing_t")));
3147
3148 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName(Name: "foo"))},
3149 ImportMoo{"moo.c", "main.c", functionDecl(hasName(Name: "moo"))};
3150
3151 testImportSequence(
3152 CodeSamples: Samples, ImportActions: {ImportFoo, ImportMoo}, // "foo", them "moo".
3153 // Just check that there is only one enum decl in the result AST.
3154 FileForFinalCheck: "main.c", FinalSelectPredicate: enumDecl(), VerificationMatcher);
3155
3156 // For different import order, result should be the same.
3157 testImportSequence(
3158 CodeSamples: Samples, ImportActions: {ImportMoo, ImportFoo}, // "moo", them "foo".
3159 // Check that there is only one enum decl in the result AST.
3160 FileForFinalCheck: "main.c", FinalSelectPredicate: enumDecl(), VerificationMatcher);
3161}
3162
3163TEST_P(ImportDecl, ImportFieldOrder) {
3164 MatchVerifier<Decl> Verifier;
3165 testImport(FromCode: "struct declToImport {"
3166 " int b = a + 2;"
3167 " int a = 5;"
3168 "};",
3169 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
3170 AMatcher: recordDecl(hasFieldOrder(Order: {"b", "a"})));
3171}
3172
3173TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
3174 MatchVerifier<Decl> Verifier;
3175 testImport(FromCode: "template <typename T> struct S { static T foo; };"
3176 "template <typename T> void declToImport() {"
3177 " (void) S<T>::foo;"
3178 "}"
3179 "void instantiate() { declToImport<int>(); }"
3180 "template <typename T> T S<T>::foo;",
3181 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
3182 AMatcher: functionTemplateDecl(has(functionDecl(has(compoundStmt(
3183 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
3184
3185 testImport(FromCode: "template <typename T> struct S {"
3186 "template<typename S> static void foo(){};"
3187 "};"
3188 "template <typename T> void declToImport() {"
3189 " S<T>::template foo<T>();"
3190 "}"
3191 "void instantiate() { declToImport<int>(); }",
3192 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
3193 AMatcher: functionTemplateDecl(has(functionDecl(has(compoundStmt(
3194 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
3195}
3196
3197TEST_P(ImportExpr, DependentNameType) {
3198 MatchVerifier<Decl> Verifier;
3199 testImport(FromCode: "template <typename T> struct declToImport {"
3200 " typedef typename T::type dependent_name;"
3201 "};",
3202 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
3203 AMatcher: classTemplateDecl(has(
3204 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
3205}
3206
3207TEST_P(ImportExpr, UnresolvedMemberExpr) {
3208 MatchVerifier<Decl> Verifier;
3209 testImport(FromCode: "struct S { template <typename T> void mem(); };"
3210 "template <typename U> void declToImport() {"
3211 " S s;"
3212 " s.mem<U>();"
3213 "}"
3214 "void instantiate() { declToImport<int>(); }",
3215 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
3216 AMatcher: functionTemplateDecl(has(functionDecl(has(
3217 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
3218}
3219
3220class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
3221public:
3222 static constexpr auto DefaultCode = R"(
3223 struct A { int x; };
3224 void f() {
3225 A a;
3226 A a1(a);
3227 A a2(A{});
3228 a = a1;
3229 a = A{};
3230 a.~A();
3231 })";
3232
3233 template <typename MatcherType>
3234 void testImportOf(
3235 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3236 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
3237 }
3238
3239 template <typename MatcherType>
3240 void testNoImportOf(
3241 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3242 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
3243 }
3244
3245private:
3246 template <typename MatcherType>
3247 void test(const MatcherType &MethodMatcher,
3248 const char *Code, unsigned int ExpectedCount) {
3249 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
3250
3251 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX11);
3252 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3253 D: ToTU, AMatcher: ClassMatcher);
3254
3255 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
3256
3257 {
3258 CXXMethodDecl *Method =
3259 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
3260 ToClass->removeDecl(Method);
3261 SharedStatePtr->getLookupTable()->remove(Method);
3262 }
3263
3264 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
3265
3266 Decl *ImportedClass = nullptr;
3267 {
3268 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11, FileName: "input1.cc");
3269 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3270 D: FromTU, AMatcher: ClassMatcher);
3271 ImportedClass = Import(FromClass, Lang_CXX11);
3272 }
3273
3274 EXPECT_EQ(ToClass, ImportedClass);
3275 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
3276 ExpectedCount);
3277 }
3278};
3279
3280TEST_P(ImportImplicitMethods, DefaultConstructor) {
3281 testImportOf(MethodMatcher: cxxConstructorDecl(isDefaultConstructor()));
3282}
3283
3284TEST_P(ImportImplicitMethods, CopyConstructor) {
3285 testImportOf(MethodMatcher: cxxConstructorDecl(isCopyConstructor()));
3286}
3287
3288TEST_P(ImportImplicitMethods, MoveConstructor) {
3289 testImportOf(MethodMatcher: cxxConstructorDecl(isMoveConstructor()));
3290}
3291
3292TEST_P(ImportImplicitMethods, Destructor) {
3293 testImportOf(MethodMatcher: cxxDestructorDecl());
3294}
3295
3296TEST_P(ImportImplicitMethods, CopyAssignment) {
3297 testImportOf(MethodMatcher: cxxMethodDecl(isCopyAssignmentOperator()));
3298}
3299
3300TEST_P(ImportImplicitMethods, MoveAssignment) {
3301 testImportOf(MethodMatcher: cxxMethodDecl(isMoveAssignmentOperator()));
3302}
3303
3304TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
3305 auto Code = R"(
3306 struct A { A() { int x; } };
3307 )";
3308 testNoImportOf(MethodMatcher: cxxConstructorDecl(isDefaultConstructor()), Code);
3309}
3310
3311TEST_P(ImportImplicitMethods, DoNotImportDefault) {
3312 auto Code = R"(
3313 struct A { A() = default; };
3314 )";
3315 testNoImportOf(MethodMatcher: cxxConstructorDecl(isDefaultConstructor()), Code);
3316}
3317
3318TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
3319 auto Code = R"(
3320 struct A { A() = delete; };
3321 )";
3322 testNoImportOf(MethodMatcher: cxxConstructorDecl(isDefaultConstructor()), Code);
3323}
3324
3325TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
3326 auto Code = R"(
3327 struct A { void f() { } };
3328 )";
3329 testNoImportOf(MethodMatcher: cxxMethodDecl(hasName(Name: "f")), Code);
3330}
3331
3332TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
3333 Decl *ToR1;
3334 {
3335 Decl *FromTU = getTuDecl(SrcCode: "struct A { };", Lang: Lang_CXX03, FileName: "input0.cc");
3336 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3337 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
3338
3339 ToR1 = Import(FromR, Lang_CXX03);
3340 }
3341
3342 Decl *ToR2;
3343 {
3344 Decl *FromTU = getTuDecl(SrcCode: "struct A { };", Lang: Lang_CXX03, FileName: "input1.cc");
3345 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3346 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
3347
3348 ToR2 = Import(FromR, Lang_CXX03);
3349 }
3350
3351 EXPECT_EQ(ToR1, ToR2);
3352}
3353
3354TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
3355 Decl *ToR1;
3356 {
3357 Decl *FromTU = getTuDecl(SrcCode: "struct A { int x; };", Lang: Lang_CXX03, FileName: "input0.cc");
3358 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3359 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
3360 ToR1 = Import(FromR, Lang_CXX03);
3361 }
3362 Decl *ToR2;
3363 {
3364 Decl *FromTU =
3365 getTuDecl(SrcCode: "struct A { unsigned x; };", Lang: Lang_CXX03, FileName: "input1.cc");
3366 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3367 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
3368 ToR2 = Import(FromR, Lang_CXX03);
3369 }
3370 EXPECT_NE(ToR1, ToR2);
3371}
3372
3373TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
3374 Decl *ToF1;
3375 {
3376 Decl *FromTU = getTuDecl(SrcCode: "struct A { int x; };", Lang: Lang_CXX03, FileName: "input0.cc");
3377 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3378 D: FromTU, AMatcher: fieldDecl(hasName(Name: "x")));
3379 ToF1 = Import(FromF, Lang_CXX03);
3380 }
3381 Decl *ToF2;
3382 {
3383 Decl *FromTU = getTuDecl(SrcCode: "struct A { int x; };", Lang: Lang_CXX03, FileName: "input1.cc");
3384 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3385 D: FromTU, AMatcher: fieldDecl(hasName(Name: "x")));
3386 ToF2 = Import(FromF, Lang_CXX03);
3387 }
3388 EXPECT_EQ(ToF1, ToF2);
3389}
3390
3391TEST_P(ASTImporterOptionSpecificTestBase, ImportBitfields) {
3392 Decl *FromTU = getTuDecl(SrcCode: "struct A { unsigned x : 3; };", Lang: Lang_CXX03);
3393 auto *FromF =
3394 FirstDeclMatcher<FieldDecl>().match(D: FromTU, AMatcher: fieldDecl(hasName(Name: "x")));
3395
3396 ASSERT_TRUE(FromF->isBitField());
3397 ASSERT_EQ(3u, FromF->getBitWidthValue());
3398 auto *ToField = Import(FromF, Lang_CXX03);
3399
3400 EXPECT_TRUE(ToField->isBitField());
3401 EXPECT_EQ(3u, ToField->getBitWidthValue());
3402
3403 const auto *FromBT = FromF->getBitWidth()->getType()->getAs<BuiltinType>();
3404 const auto *ToBT = ToField->getBitWidth()->getType()->getAs<BuiltinType>();
3405 ASSERT_TRUE(FromBT);
3406 ASSERT_EQ(BuiltinType::Int, FromBT->getKind());
3407 EXPECT_TRUE(ToBT);
3408 EXPECT_EQ(BuiltinType::Int, ToBT->getKind());
3409}
3410
3411struct ImportBlock : ASTImporterOptionSpecificTestBase {};
3412TEST_P(ImportBlock, ImportBlocksAreUnsupported) {
3413 const auto *Code = R"(
3414 void test_block__capture_null() {
3415 int *p = 0;
3416 ^(){
3417 *p = 1;
3418 }();
3419 })";
3420 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
3421 auto *FromBlock = FirstDeclMatcher<BlockDecl>().match(D: FromTU, AMatcher: blockDecl());
3422 ASSERT_TRUE(FromBlock);
3423
3424 auto ToBlockOrError = importOrError(From: FromBlock, ToLang: Lang_CXX03);
3425
3426 const auto ExpectUnsupportedConstructError = [](const ASTImportError &Error) {
3427 EXPECT_EQ(ASTImportError::UnsupportedConstruct, Error.Error);
3428 };
3429 llvm::handleAllErrors(ToBlockOrError.takeError(),
3430 ExpectUnsupportedConstructError);
3431}
3432
3433TEST_P(ASTImporterOptionSpecificTestBase, ImportParmVarDecl) {
3434 const auto *Code = R"(
3435 template <typename T> struct Wrapper {
3436 Wrapper(T Value = {}) {}
3437 };
3438 template class Wrapper<int>;
3439 )";
3440 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
3441 auto *FromVar = FirstDeclMatcher<ParmVarDecl>().match(
3442 D: FromTU, AMatcher: parmVarDecl(hasType(InnerMatcher: asString(Name: "int"))));
3443 ASSERT_TRUE(FromVar);
3444 ASSERT_TRUE(FromVar->hasUninstantiatedDefaultArg());
3445 ASSERT_TRUE(FromVar->getUninstantiatedDefaultArg());
3446 ASSERT_FALSE(FromVar->isExplicitObjectParameter());
3447
3448 const auto *ToVar = Import(FromVar, Lang_CXX11);
3449 EXPECT_TRUE(ToVar);
3450 EXPECT_TRUE(ToVar->hasUninstantiatedDefaultArg());
3451 EXPECT_TRUE(ToVar->getUninstantiatedDefaultArg());
3452 EXPECT_NE(FromVar->getUninstantiatedDefaultArg(),
3453 ToVar->getUninstantiatedDefaultArg());
3454 EXPECT_FALSE(ToVar->isExplicitObjectParameter());
3455}
3456
3457TEST_P(ASTImporterOptionSpecificTestBase, ImportParmVarDecl_Explicit) {
3458 const auto *Code = R"(
3459 struct Wrapper {
3460 void func(this Wrapper) {}
3461 };
3462 )";
3463 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX23);
3464 auto *FromVar = FirstDeclMatcher<ParmVarDecl>().match(D: FromTU, AMatcher: parmVarDecl());
3465 ASSERT_TRUE(FromVar);
3466 ASSERT_TRUE(FromVar->isExplicitObjectParameter());
3467
3468 const auto *ToVar = Import(FromVar, Lang_CXX23);
3469 EXPECT_TRUE(ToVar);
3470 EXPECT_TRUE(ToVar->isExplicitObjectParameter());
3471 EXPECT_NE(ToVar->getExplicitObjectParamThisLoc(),
3472 FromVar->getExplicitObjectParamThisLoc());
3473}
3474
3475TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
3476 Decl *ToF1;
3477 {
3478 Decl *FromTU = getTuDecl(SrcCode: "struct A { int x; };", Lang: Lang_CXX03, FileName: "input0.cc");
3479 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3480 D: FromTU, AMatcher: fieldDecl(hasName(Name: "x")));
3481 ToF1 = Import(FromF, Lang_CXX03);
3482 }
3483 Decl *ToF2;
3484 {
3485 Decl *FromTU =
3486 getTuDecl(SrcCode: "struct A { unsigned x; };", Lang: Lang_CXX03, FileName: "input1.cc");
3487 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3488 D: FromTU, AMatcher: fieldDecl(hasName(Name: "x")));
3489 ToF2 = Import(FromF, Lang_CXX03);
3490 }
3491 EXPECT_NE(ToF1, ToF2);
3492}
3493
3494TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
3495 Decl *ToM1;
3496 {
3497 Decl *FromTU = getTuDecl(SrcCode: "struct A { void x(); }; void A::x() { }",
3498 Lang: Lang_CXX03, FileName: "input0.cc");
3499 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3500 D: FromTU, AMatcher: functionDecl(hasName(Name: "x"), isDefinition()));
3501 ToM1 = Import(FromM, Lang_CXX03);
3502 }
3503 Decl *ToM2;
3504 {
3505 Decl *FromTU = getTuDecl(SrcCode: "struct A { void x(); }; void A::x() { }",
3506 Lang: Lang_CXX03, FileName: "input1.cc");
3507 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3508 D: FromTU, AMatcher: functionDecl(hasName(Name: "x"), isDefinition()));
3509 ToM2 = Import(FromM, Lang_CXX03);
3510 }
3511 EXPECT_EQ(ToM1, ToM2);
3512}
3513
3514TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
3515 Decl *ToM1;
3516 {
3517 Decl *FromTU = getTuDecl(SrcCode: "struct A { void x(); }; void A::x() { }",
3518 Lang: Lang_CXX03, FileName: "input0.cc");
3519 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3520 D: FromTU, AMatcher: functionDecl(hasName(Name: "x"), isDefinition()));
3521 ToM1 = Import(FromM, Lang_CXX03);
3522 }
3523 Decl *ToM2;
3524 {
3525 Decl *FromTU =
3526 getTuDecl(SrcCode: "struct A { void x() const; }; void A::x() const { }",
3527 Lang: Lang_CXX03, FileName: "input1.cc");
3528 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3529 D: FromTU, AMatcher: functionDecl(hasName(Name: "x"), isDefinition()));
3530 ToM2 = Import(FromM, Lang_CXX03);
3531 }
3532 EXPECT_NE(ToM1, ToM2);
3533}
3534
3535TEST_P(ASTImporterOptionSpecificTestBase,
3536 ImportUnnamedStructsWithRecursingField) {
3537 Decl *FromTU = getTuDecl(
3538 SrcCode: R"(
3539 struct A {
3540 struct {
3541 struct A *next;
3542 } entry0;
3543 struct {
3544 struct A *next;
3545 } entry1;
3546 };
3547 )",
3548 Lang: Lang_C99, FileName: "input0.cc");
3549 auto *From =
3550 FirstDeclMatcher<RecordDecl>().match(D: FromTU, AMatcher: recordDecl(hasName(Name: "A")));
3551
3552 Import(From, Lang_C99);
3553
3554 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3555 auto *Entry0 =
3556 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName(Name: "entry0")));
3557 auto *Entry1 =
3558 FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName(Name: "entry1")));
3559 auto *R0 = getRecordDecl(Entry0);
3560 auto *R1 = getRecordDecl(Entry1);
3561 EXPECT_NE(R0, R1);
3562 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3563 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3564 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3565 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3566}
3567
3568TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
3569 Decl *FromTU = getTuDecl(
3570 SrcCode: R"(
3571 void f(int X, int Y, bool Z) {
3572 (void)[X, Y, Z] { (void)Z; };
3573 }
3574 )",
3575 Lang: Lang_CXX11, FileName: "input0.cc");
3576 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3577 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
3578 auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
3579 EXPECT_TRUE(ToF);
3580
3581 CXXRecordDecl *FromLambda =
3582 cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
3583 FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3584
3585 auto *ToLambda = cast_or_null<CXXRecordDecl>(Val: Import(From: FromLambda, Lang: Lang_CXX11));
3586 EXPECT_TRUE(ToLambda);
3587
3588 // Check if the fields of the lambda class are imported in correct order.
3589 unsigned FromIndex = 0u;
3590 for (auto *FromField : FromLambda->fields()) {
3591 ASSERT_FALSE(FromField->getDeclName());
3592 auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
3593 EXPECT_TRUE(ToField);
3594 UnsignedOrNone ToIndex = ASTImporter::getFieldIndex(ToField);
3595 EXPECT_TRUE(ToIndex);
3596 EXPECT_EQ(*ToIndex, FromIndex);
3597 ++FromIndex;
3598 }
3599
3600 EXPECT_EQ(FromIndex, 3u);
3601}
3602
3603TEST_P(ASTImporterOptionSpecificTestBase,
3604 MergeFieldDeclsOfClassTemplateSpecialization) {
3605 std::string ClassTemplate =
3606 R"(
3607 template <typename T>
3608 struct X {
3609 int a{0}; // FieldDecl with InitListExpr
3610 X(char) : a(3) {} // (1)
3611 X(int) {} // (2)
3612 };
3613 )";
3614 Decl *ToTU = getToTuDecl(ToSrcCode: ClassTemplate +
3615 R"(
3616 void foo() {
3617 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3618 X<char> xc('c');
3619 }
3620 )", ToLang: Lang_CXX11);
3621 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3622 D: ToTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
3623 // FieldDecl without InitlistExpr:
3624 auto *ToField = *ToSpec->field_begin();
3625 ASSERT_TRUE(ToField);
3626 ASSERT_FALSE(ToField->getInClassInitializer());
3627 Decl *FromTU = getTuDecl(SrcCode: ClassTemplate +
3628 R"(
3629 void bar() {
3630 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3631 X<char> xc(1);
3632 }
3633 )", Lang: Lang_CXX11);
3634 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3635 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
3636 // FieldDecl with InitlistExpr:
3637 auto *FromField = *FromSpec->field_begin();
3638 ASSERT_TRUE(FromField);
3639 ASSERT_TRUE(FromField->getInClassInitializer());
3640
3641 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3642 ASSERT_TRUE(ImportedSpec);
3643 EXPECT_EQ(ImportedSpec, ToSpec);
3644 // After the import, the FieldDecl has to be merged, thus it should have the
3645 // InitListExpr.
3646 EXPECT_TRUE(ToField->getInClassInitializer());
3647}
3648
3649TEST_P(ASTImporterOptionSpecificTestBase,
3650 MergeFunctionOfClassTemplateSpecialization) {
3651 std::string ClassTemplate =
3652 R"(
3653 template <typename T>
3654 struct X {
3655 void f() {}
3656 void g() {}
3657 };
3658 )";
3659 Decl *ToTU = getToTuDecl(ToSrcCode: ClassTemplate +
3660 R"(
3661 void foo() {
3662 X<char> x;
3663 x.f();
3664 }
3665 )", ToLang: Lang_CXX11);
3666 Decl *FromTU = getTuDecl(SrcCode: ClassTemplate +
3667 R"(
3668 void bar() {
3669 X<char> x;
3670 x.g();
3671 }
3672 )", Lang: Lang_CXX11);
3673 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3674 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
3675 auto FunPattern = functionDecl(hasName(Name: "g"),
3676 hasParent(classTemplateSpecializationDecl()));
3677 auto *FromFun =
3678 FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: FunPattern);
3679 auto *ToFun =
3680 FirstDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: FunPattern);
3681 ASSERT_TRUE(FromFun->hasBody());
3682 ASSERT_FALSE(ToFun->hasBody());
3683 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3684 ASSERT_TRUE(ImportedSpec);
3685 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3686 D: ToTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
3687 EXPECT_EQ(ImportedSpec, ToSpec);
3688 EXPECT_TRUE(ToFun->hasBody());
3689}
3690
3691TEST_P(ASTImporterOptionSpecificTestBase, MergeTemplateSpecWithForwardDecl) {
3692 std::string ClassTemplate =
3693 R"(
3694 template<typename T>
3695 struct X { int m; };
3696 template<>
3697 struct X<int> { int m; };
3698 )";
3699 // Append a forward decl for our template specialization.
3700 getToTuDecl(ToSrcCode: ClassTemplate + "template<> struct X<int>;", ToLang: Lang_CXX11);
3701 Decl *FromTU = getTuDecl(SrcCode: ClassTemplate, Lang: Lang_CXX11);
3702 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3703 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X"), isDefinition()));
3704 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3705 // Check that our definition got merged with the existing definition.
3706 EXPECT_TRUE(FromSpec->isThisDeclarationADefinition());
3707 EXPECT_TRUE(ImportedSpec->isThisDeclarationADefinition());
3708}
3709
3710TEST_P(ASTImporterOptionSpecificTestBase,
3711 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3712 std::string ClassTemplate =
3713 R"(
3714 template <typename T>
3715 struct X {};
3716 )";
3717 Decl *ToTU = getToTuDecl(ToSrcCode: ClassTemplate +
3718 R"(
3719 template <>
3720 struct X<char> {
3721 int a;
3722 };
3723 void foo() {
3724 X<char> x;
3725 }
3726 )",
3727 ToLang: Lang_CXX11);
3728 Decl *FromTU = getTuDecl(SrcCode: ClassTemplate +
3729 R"(
3730 template <>
3731 struct X<char> {
3732 int b;
3733 };
3734 void foo() {
3735 X<char> x;
3736 }
3737 )",
3738 Lang: Lang_CXX11);
3739 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3740 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
3741 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3742
3743 // We expect one (ODR) warning during the import.
3744 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3745
3746 // The second specialization is different from the first, thus it violates
3747 // ODR, consequently we expect to keep the first specialization only, which is
3748 // already in the "To" context.
3749 EXPECT_FALSE(ImportedSpec);
3750 EXPECT_EQ(1u,
3751 DeclCounter<ClassTemplateSpecializationDecl>().match(
3752 ToTU, classTemplateSpecializationDecl(hasName("X"))));
3753}
3754
3755TEST_P(ASTImporterOptionSpecificTestBase,
3756 MergeCtorOfClassTemplateSpecialization) {
3757 std::string ClassTemplate =
3758 R"(
3759 template <typename T>
3760 struct X {
3761 X(char) {}
3762 X(int) {}
3763 };
3764 )";
3765 Decl *ToTU = getToTuDecl(ToSrcCode: ClassTemplate +
3766 R"(
3767 void foo() {
3768 X<char> x('c');
3769 }
3770 )", ToLang: Lang_CXX11);
3771 Decl *FromTU = getTuDecl(SrcCode: ClassTemplate +
3772 R"(
3773 void bar() {
3774 X<char> x(1);
3775 }
3776 )", Lang: Lang_CXX11);
3777 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3778 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
3779 // Match the void(int) ctor.
3780 auto CtorPattern =
3781 cxxConstructorDecl(hasParameter(N: 0, InnerMatcher: varDecl(hasType(InnerMatcher: asString(Name: "int")))),
3782 hasParent(classTemplateSpecializationDecl()));
3783 auto *FromCtor =
3784 FirstDeclMatcher<CXXConstructorDecl>().match(D: FromTU, AMatcher: CtorPattern);
3785 auto *ToCtor =
3786 FirstDeclMatcher<CXXConstructorDecl>().match(D: ToTU, AMatcher: CtorPattern);
3787 ASSERT_TRUE(FromCtor->hasBody());
3788 ASSERT_FALSE(ToCtor->hasBody());
3789 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3790 ASSERT_TRUE(ImportedSpec);
3791 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3792 D: ToTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
3793 EXPECT_EQ(ImportedSpec, ToSpec);
3794 EXPECT_TRUE(ToCtor->hasBody());
3795}
3796
3797TEST_P(ASTImporterOptionSpecificTestBase, ClassTemplateFriendDecl) {
3798 const auto *Code =
3799 R"(
3800 template <class T> class X { friend T; };
3801 struct Y {};
3802 template class X<Y>;
3803 )";
3804 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX11);
3805 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
3806 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3807 D: FromTU, AMatcher: classTemplateSpecializationDecl());
3808 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3809 D: ToTU, AMatcher: classTemplateSpecializationDecl());
3810
3811 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3812 EXPECT_EQ(ImportedSpec, ToSpec);
3813 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3814 ToTU, classTemplateSpecializationDecl()));
3815}
3816
3817TEST_P(ASTImporterOptionSpecificTestBase,
3818 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3819 auto Code =
3820 R"(
3821 // primary template
3822 template<class T1, class T2, int I>
3823 class A {};
3824
3825 // partial specialization
3826 template<class T, int I>
3827 class A<T, T*, I> {};
3828 )";
3829 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX11);
3830 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
3831 auto *FromSpec =
3832 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3833 D: FromTU, AMatcher: classTemplatePartialSpecializationDecl());
3834 auto *ToSpec =
3835 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3836 D: ToTU, AMatcher: classTemplatePartialSpecializationDecl());
3837
3838 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3839 EXPECT_EQ(ImportedSpec, ToSpec);
3840 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3841 ToTU, classTemplatePartialSpecializationDecl()));
3842}
3843
3844TEST_P(ASTImporterOptionSpecificTestBase,
3845 ClassTemplateSpecializationsShouldNotBeDuplicated) {
3846 auto Code =
3847 R"(
3848 // primary template
3849 template<class T1, class T2, int I>
3850 class A {};
3851
3852 // full specialization
3853 template<>
3854 class A<int, int, 1> {};
3855 )";
3856 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX11);
3857 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
3858 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3859 D: FromTU, AMatcher: classTemplateSpecializationDecl());
3860 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3861 D: ToTU, AMatcher: classTemplateSpecializationDecl());
3862
3863 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3864 EXPECT_EQ(ImportedSpec, ToSpec);
3865 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3866 ToTU, classTemplateSpecializationDecl()));
3867}
3868
3869TEST_P(ASTImporterOptionSpecificTestBase,
3870 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
3871 std::string PrimaryTemplate =
3872 R"(
3873 template<class T1, class T2, int I>
3874 class A {};
3875 )";
3876 auto PartialSpec =
3877 R"(
3878 template<class T, int I>
3879 class A<T, T*, I> {};
3880 )";
3881 auto FullSpec =
3882 R"(
3883 template<>
3884 class A<int, int, 1> {};
3885 )";
3886 Decl *ToTU = getToTuDecl(ToSrcCode: PrimaryTemplate + FullSpec, ToLang: Lang_CXX11);
3887 Decl *FromTU = getTuDecl(SrcCode: PrimaryTemplate + PartialSpec, Lang: Lang_CXX11);
3888 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3889 D: FromTU, AMatcher: classTemplateSpecializationDecl());
3890
3891 auto *ImportedSpec = Import(FromSpec, Lang_CXX11);
3892 EXPECT_TRUE(ImportedSpec);
3893 // Check the number of partial specializations.
3894 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3895 ToTU, classTemplatePartialSpecializationDecl()));
3896 // Check the number of full specializations.
3897 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3898 ToTU, classTemplateSpecializationDecl(
3899 unless(classTemplatePartialSpecializationDecl()))));
3900}
3901
3902TEST_P(ASTImporterOptionSpecificTestBase,
3903 InitListExprValueKindShouldBeImported) {
3904 Decl *TU = getTuDecl(
3905 SrcCode: R"(
3906 const int &init();
3907 void foo() { const int &a{init()}; }
3908 )", Lang: Lang_CXX11, FileName: "input0.cc");
3909 auto *FromD = FirstDeclMatcher<VarDecl>().match(D: TU, AMatcher: varDecl(hasName(Name: "a")));
3910 ASSERT_TRUE(FromD->getAnyInitializer());
3911 auto *InitExpr = FromD->getAnyInitializer();
3912 ASSERT_TRUE(InitExpr);
3913 ASSERT_TRUE(InitExpr->isGLValue());
3914
3915 auto *ToD = Import(FromD, Lang_CXX11);
3916 EXPECT_TRUE(ToD);
3917 auto *ToInitExpr = cast<VarDecl>(ToD)->getAnyInitializer();
3918 EXPECT_TRUE(ToInitExpr);
3919 EXPECT_TRUE(ToInitExpr->isGLValue());
3920}
3921
3922struct ImportVariables : ASTImporterOptionSpecificTestBase {};
3923
3924TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
3925 Decl *FromTU = getTuDecl(
3926 SrcCode: R"(
3927 struct A {
3928 static const int a = 1 + 2;
3929 };
3930 const int A::a;
3931 )",
3932 Lang: Lang_CXX03, FileName: "input1.cc");
3933
3934 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3935 D: FromTU, AMatcher: varDecl(hasName(Name: "a"))); // Decl with init
3936 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3937 D: FromTU, AMatcher: varDecl(hasName(Name: "a"))); // Decl with definition
3938 ASSERT_NE(FromDWithInit, FromDWithDef);
3939 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
3940
3941 auto *ToD0 = cast<VarDecl>(Import(FromDWithInit, Lang_CXX11));
3942 auto *ToD1 = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3943 ASSERT_TRUE(ToD0);
3944 ASSERT_TRUE(ToD1);
3945 EXPECT_NE(ToD0, ToD1);
3946 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
3947}
3948
3949TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
3950 auto StructA =
3951 R"(
3952 struct A {
3953 static const int a = 1 + 2;
3954 };
3955 )";
3956 Decl *ToTU = getToTuDecl(ToSrcCode: StructA, ToLang: Lang_CXX03);
3957 Decl *FromTU = getTuDecl(SrcCode: std::string(StructA) + "const int A::a;", Lang: Lang_CXX03,
3958 FileName: "input1.cc");
3959
3960 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
3961 D: FromTU, AMatcher: varDecl(hasName(Name: "a"))); // Decl with init
3962 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3963 D: FromTU, AMatcher: varDecl(hasName(Name: "a"))); // Decl with definition
3964 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
3965 ASSERT_TRUE(FromDWithInit->getInit());
3966 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
3967 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3968 ASSERT_FALSE(FromDWithDef->getInit());
3969
3970 auto *ToD = FirstDeclMatcher<VarDecl>().match(
3971 D: ToTU, AMatcher: varDecl(hasName(Name: "a"))); // Decl with init
3972 ASSERT_TRUE(ToD->getInit());
3973 ASSERT_FALSE(ToD->getDefinition());
3974
3975 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
3976 EXPECT_TRUE(ImportedD->getAnyInitializer());
3977 EXPECT_TRUE(ImportedD->getDefinition());
3978}
3979
3980TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
3981 auto StructA =
3982 R"(
3983 struct A {
3984 static const int a;
3985 };
3986 )";
3987 Decl *ToTU = getToTuDecl(ToSrcCode: StructA, ToLang: Lang_CXX03);
3988 Decl *FromTU = getTuDecl(SrcCode: std::string(StructA) + "const int A::a = 1 + 2;",
3989 Lang: Lang_CXX03, FileName: "input1.cc");
3990
3991 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
3992 D: FromTU, AMatcher: varDecl(hasName(Name: "a")));
3993 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
3994 D: FromTU, AMatcher: varDecl(hasName(Name: "a"))); // Decl with definition and with init.
3995 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
3996 ASSERT_FALSE(FromDDeclarationOnly->getInit());
3997 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
3998 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
3999 ASSERT_TRUE(FromDWithDef->getInit());
4000
4001 auto *ToD = FirstDeclMatcher<VarDecl>().match(
4002 D: ToTU, AMatcher: varDecl(hasName(Name: "a")));
4003 ASSERT_FALSE(ToD->getInit());
4004 ASSERT_FALSE(ToD->getDefinition());
4005
4006 auto *ImportedD = cast<VarDecl>(Import(FromDWithDef, Lang_CXX11));
4007 EXPECT_TRUE(ImportedD->getAnyInitializer());
4008 EXPECT_TRUE(ImportedD->getDefinition());
4009}
4010
4011TEST_P(ImportVariables, ImportBindingDecl) {
4012 Decl *From, *To;
4013 std::tie(args&: From, args&: To) = getImportedDecl(
4014 FromSrcCode: R"(
4015 void declToImport() {
4016 int a[2] = {1,2};
4017 auto [x1,y1] = a;
4018 auto& [x2,y2] = a;
4019
4020 struct S {
4021 mutable int x1 : 2;
4022 volatile double y1;
4023 };
4024 S b;
4025 const auto [x3, y3] = b;
4026 };
4027 )",
4028 FromLang: Lang_CXX17, ToSrcCode: "", ToLang: Lang_CXX17);
4029
4030 TranslationUnitDecl *FromTU = From->getTranslationUnitDecl();
4031 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
4032 FromTU, functionDecl(hasName(Name: "declToImport")));
4033 auto *ToF = Import(FromF, Lang_CXX17);
4034 EXPECT_TRUE(ToF);
4035
4036 auto VerifyImport = [&](llvm::StringRef BindName) {
4037 auto *FromB = FirstDeclMatcher<BindingDecl>().match(
4038 FromF, bindingDecl(hasName(Name: BindName)));
4039 ASSERT_TRUE(FromB);
4040 auto *ToB = Import(FromB, Lang_CXX17);
4041 EXPECT_TRUE(ToB);
4042 EXPECT_EQ(FromB->getBinding() != nullptr, ToB->getBinding() != nullptr);
4043 EXPECT_EQ(FromB->getDecomposedDecl() != nullptr,
4044 ToB->getDecomposedDecl() != nullptr);
4045 EXPECT_EQ(FromB->getHoldingVar() != nullptr,
4046 ToB->getHoldingVar() != nullptr);
4047 };
4048
4049 VerifyImport("x1");
4050 VerifyImport("y1");
4051 VerifyImport("x2");
4052 VerifyImport("y2");
4053 VerifyImport("x3");
4054 VerifyImport("y3");
4055}
4056
4057TEST_P(ImportVariables, ImportDecompositionDeclArray) {
4058 Decl *From, *To;
4059 std::tie(args&: From, args&: To) = getImportedDecl(
4060 FromSrcCode: R"(
4061 void declToImport() {
4062 int a[2] = {1,2};
4063 auto [x1,y1] = a;
4064 };
4065 )",
4066 FromLang: Lang_CXX17, ToSrcCode: "", ToLang: Lang_CXX17);
4067
4068 TranslationUnitDecl *FromTU = From->getTranslationUnitDecl();
4069 auto *FromDecomp =
4070 FirstDeclMatcher<DecompositionDecl>().match(FromTU, decompositionDecl());
4071 auto *ToDecomp = Import(FromDecomp, Lang_CXX17);
4072 EXPECT_TRUE(ToDecomp);
4073
4074 ArrayRef<BindingDecl *> FromB = FromDecomp->bindings();
4075 ArrayRef<BindingDecl *> ToB = ToDecomp->bindings();
4076 EXPECT_EQ(FromB.size(), ToB.size());
4077 for (unsigned int I = 0; I < FromB.size(); ++I) {
4078 auto *ToBI = Import(From: FromB[I], Lang: Lang_CXX17);
4079 EXPECT_EQ(ToBI, ToB[I]);
4080 }
4081}
4082
4083struct ImportClasses : ASTImporterOptionSpecificTestBase {};
4084
4085TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
4086 Decl *ToTU = getToTuDecl(ToSrcCode: "struct A { struct X *Xp; };", ToLang: Lang_C99);
4087 Decl *FromTU1 = getTuDecl(SrcCode: "struct X {};", Lang: Lang_C99, FileName: "input1.cc");
4088 auto Pattern = recordDecl(hasName(Name: "X"), unless(isImplicit()));
4089 auto ToProto = FirstDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: Pattern);
4090 auto FromDef = FirstDeclMatcher<RecordDecl>().match(D: FromTU1, AMatcher: Pattern);
4091
4092 Decl *ImportedDef = Import(FromDef, Lang_C99);
4093
4094 EXPECT_NE(ImportedDef, ToProto);
4095 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
4096 auto ToDef = LastDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: Pattern);
4097 EXPECT_TRUE(ImportedDef == ToDef);
4098 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4099 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4100 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
4101}
4102
4103TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
4104 Decl *ToTU = getToTuDecl(ToSrcCode: "struct A { struct X *Xp; };", ToLang: Lang_CXX03);
4105 Decl *FromTU1 = getTuDecl(SrcCode: "struct X {};", Lang: Lang_CXX03, FileName: "input1.cc");
4106 auto Pattern = recordDecl(hasName(Name: "X"), unless(isImplicit()));
4107 auto ToProto = FirstDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: Pattern);
4108 auto FromDef = FirstDeclMatcher<RecordDecl>().match(D: FromTU1, AMatcher: Pattern);
4109
4110 Decl *ImportedDef = Import(FromDef, Lang_CXX03);
4111
4112 EXPECT_NE(ImportedDef, ToProto);
4113 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
4114 auto ToDef = LastDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: Pattern);
4115 EXPECT_TRUE(ImportedDef == ToDef);
4116 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4117 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4118 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
4119}
4120
4121TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
4122 Decl *FromTU0 =
4123 getTuDecl(SrcCode: "struct A { struct X *Xp; };", Lang: Lang_C99, FileName: "input0.cc");
4124 Decl *FromTU1 = getTuDecl(SrcCode: "struct X {};", Lang: Lang_C99, FileName: "input1.cc");
4125 auto Pattern = recordDecl(hasName(Name: "X"), unless(isImplicit()));
4126 auto FromProto = FirstDeclMatcher<RecordDecl>().match(D: FromTU0, AMatcher: Pattern);
4127 auto FromDef = FirstDeclMatcher<RecordDecl>().match(D: FromTU1, AMatcher: Pattern);
4128
4129 Decl *ImportedProto = Import(FromProto, Lang_C99);
4130 Decl *ImportedDef = Import(FromDef, Lang_C99);
4131 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4132
4133 EXPECT_NE(ImportedDef, ImportedProto);
4134 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
4135 auto ToProto = FirstDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: Pattern);
4136 auto ToDef = LastDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: Pattern);
4137 EXPECT_TRUE(ImportedDef == ToDef);
4138 EXPECT_TRUE(ImportedProto == ToProto);
4139 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4140 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4141 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
4142}
4143
4144struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {
4145 void testRecursiveFriendClassTemplate(Decl *FromTu) {
4146 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4147 D: FromTu, AMatcher: classTemplateDecl());
4148
4149 auto Pattern = classTemplateDecl(
4150 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
4151 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4152
4153 auto *FromFriend =
4154 FirstDeclMatcher<FriendDecl>().match(FromD, friendDecl());
4155 auto *FromRecordOfFriend =
4156 cast<ClassTemplateDecl>(FromFriend->getFriendDecl())
4157 ->getTemplatedDecl();
4158 EXPECT_NE(FromRecordOfFriend, FromD->getTemplatedDecl());
4159 EXPECT_TRUE(FromRecordOfFriend->getPreviousDecl() == nullptr);
4160
4161 auto *FromDC = FromRecordOfFriend->getDeclContext();
4162 auto *FromLexicalDC = FromRecordOfFriend->getLexicalDeclContext();
4163 ASSERT_EQ(FromDC, cast<DeclContext>(FromTu));
4164 ASSERT_EQ(FromLexicalDC, cast<DeclContext>(FromD->getTemplatedDecl()));
4165
4166 ASSERT_FALSE(FromDC->containsDecl(FromRecordOfFriend));
4167 ASSERT_FALSE(FromLexicalDC->containsDecl(FromRecordOfFriend));
4168 ASSERT_FALSE(cast<RecordDecl>(FromRecordOfFriend)
4169 ->getLookupParent()
4170 ->lookup(FromRecordOfFriend->getDeclName())
4171 .empty());
4172
4173 auto *ToD = Import(From: FromD, Lang: Lang_CXX03);
4174 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4175
4176 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(ToD, friendDecl());
4177 auto *ToRecordOfFriend =
4178 cast<ClassTemplateDecl>(ToFriend->getFriendDecl())->getTemplatedDecl();
4179
4180 EXPECT_NE(ToRecordOfFriend, ToD->getTemplatedDecl());
4181 EXPECT_TRUE(ToRecordOfFriend->getPreviousDecl() == nullptr);
4182
4183 auto *ToDC = ToRecordOfFriend->getDeclContext();
4184 auto *ToLexicalDC = ToRecordOfFriend->getLexicalDeclContext();
4185 ASSERT_EQ(ToDC, cast<DeclContext>(ToD->getTranslationUnitDecl()));
4186 ASSERT_EQ(ToLexicalDC, cast<DeclContext>(ToD->getTemplatedDecl()));
4187
4188 ASSERT_FALSE(ToDC->containsDecl(ToRecordOfFriend));
4189 ASSERT_FALSE(ToLexicalDC->containsDecl(ToRecordOfFriend));
4190 ASSERT_FALSE(cast<RecordDecl>(ToRecordOfFriend)
4191 ->getLookupParent()
4192 ->lookup(ToRecordOfFriend->getDeclName())
4193 .empty());
4194 }
4195
4196 void testRepeatedFriendImport(const char *Code) {
4197 Decl *ToTu = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX03);
4198 Decl *FromTu = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "from.cc");
4199
4200 auto *ToFriend1 = FirstDeclMatcher<FriendDecl>().match(D: ToTu, AMatcher: friendDecl());
4201 auto *ToFriend2 = LastDeclMatcher<FriendDecl>().match(D: ToTu, AMatcher: friendDecl());
4202 auto *FromFriend1 =
4203 FirstDeclMatcher<FriendDecl>().match(D: FromTu, AMatcher: friendDecl());
4204 auto *FromFriend2 =
4205 LastDeclMatcher<FriendDecl>().match(D: FromTu, AMatcher: friendDecl());
4206
4207 FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
4208 FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
4209
4210 EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
4211 EXPECT_EQ(ToFriend1, ToImportedFriend1);
4212 EXPECT_EQ(ToFriend2, ToImportedFriend2);
4213 }
4214};
4215
4216TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
4217 Decl *FromTU = getTuDecl(
4218 SrcCode: R"(
4219 class A {
4220 template <int I> class F {};
4221 class X {
4222 template <int I> friend class F;
4223 };
4224 };
4225 )",
4226 Lang: Lang_CXX03, FileName: "input0.cc");
4227
4228 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
4229 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "F"), isDefinition()));
4230 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
4231 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "F")));
4232
4233 ASSERT_TRUE(FromClass);
4234 ASSERT_TRUE(FromFriendClass);
4235 ASSERT_NE(FromClass, FromFriendClass);
4236 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
4237 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
4238 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4239 FromClass->getDescribedClassTemplate());
4240
4241 auto *ToClass = cast<CXXRecordDecl>(Import(FromClass, Lang_CXX03));
4242 auto *ToFriendClass =
4243 cast<CXXRecordDecl>(Import(FromFriendClass, Lang_CXX03));
4244
4245 EXPECT_TRUE(ToClass);
4246 EXPECT_TRUE(ToFriendClass);
4247 EXPECT_NE(ToClass, ToFriendClass);
4248 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
4249 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
4250 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4251 ToClass->getDescribedClassTemplate());
4252}
4253
4254TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
4255 Decl *FromTu = getTuDecl(
4256 SrcCode: R"(
4257 class declToImport {
4258 friend class declToImport;
4259 };
4260 )",
4261 Lang: Lang_CXX03, FileName: "input.cc");
4262
4263 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
4264 D: FromTu, AMatcher: cxxRecordDecl(hasName(Name: "declToImport")));
4265 auto *ToD = Import(FromD, Lang_CXX03);
4266 auto Pattern = cxxRecordDecl(has(friendDecl()));
4267 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4268 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4269}
4270
4271TEST_P(ImportFriendClasses, UndeclaredFriendClassShouldNotBeVisible) {
4272 Decl *FromTu =
4273 getTuDecl(SrcCode: "class X { friend class Y; };", Lang: Lang_CXX03, FileName: "from.cc");
4274 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
4275 D: FromTu, AMatcher: cxxRecordDecl(hasName(Name: "X")));
4276 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(D: FromTu, AMatcher: friendDecl());
4277 RecordDecl *FromRecordOfFriend =
4278 const_cast<RecordDecl *>(getRecordDeclOfFriend(FromFriend));
4279
4280 ASSERT_EQ(FromRecordOfFriend->getDeclContext(), cast<DeclContext>(FromTu));
4281 ASSERT_EQ(FromRecordOfFriend->getLexicalDeclContext(),
4282 cast<DeclContext>(FromX));
4283 ASSERT_FALSE(
4284 FromRecordOfFriend->getDeclContext()->containsDecl(FromRecordOfFriend));
4285 ASSERT_FALSE(FromRecordOfFriend->getLexicalDeclContext()->containsDecl(
4286 FromRecordOfFriend));
4287 ASSERT_FALSE(FromRecordOfFriend->getLookupParent()
4288 ->lookup(FromRecordOfFriend->getDeclName())
4289 .empty());
4290
4291 auto *ToX = Import(FromX, Lang_CXX03);
4292 ASSERT_TRUE(ToX);
4293
4294 Decl *ToTu = ToX->getTranslationUnitDecl();
4295 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(D: ToTu, AMatcher: friendDecl());
4296 RecordDecl *ToRecordOfFriend =
4297 const_cast<RecordDecl *>(getRecordDeclOfFriend(ToFriend));
4298
4299 ASSERT_EQ(ToRecordOfFriend->getDeclContext(), cast<DeclContext>(ToTu));
4300 ASSERT_EQ(ToRecordOfFriend->getLexicalDeclContext(), cast<DeclContext>(ToX));
4301 EXPECT_FALSE(
4302 ToRecordOfFriend->getDeclContext()->containsDecl(ToRecordOfFriend));
4303 EXPECT_FALSE(ToRecordOfFriend->getLexicalDeclContext()->containsDecl(
4304 ToRecordOfFriend));
4305 EXPECT_FALSE(ToRecordOfFriend->getLookupParent()
4306 ->lookup(ToRecordOfFriend->getDeclName())
4307 .empty());
4308}
4309
4310TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
4311 Decl *FromTu = getTuDecl(
4312 SrcCode: R"(
4313 template<class A> class declToImport {
4314 template<class A1> friend class declToImport;
4315 };
4316 )",
4317 Lang: Lang_CXX03, FileName: "input.cc");
4318
4319 testRecursiveFriendClassTemplate(FromTu);
4320}
4321
4322TEST_P(ImportFriendClasses,
4323 ImportOfRecursiveFriendClassTemplateWithNonTypeParm) {
4324 Decl *FromTu = getTuDecl(
4325 SrcCode: R"(
4326 template<class A1, A1 A> class declToImport {
4327 template<class B1, B1> friend class declToImport;
4328 };
4329 )",
4330 Lang: Lang_CXX03, FileName: "input.cc");
4331 testRecursiveFriendClassTemplate(FromTu);
4332}
4333
4334TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
4335 auto Pattern = classTemplateSpecializationDecl(hasName(Name: "X"));
4336
4337 ClassTemplateSpecializationDecl *Imported1;
4338 {
4339 Decl *FromTU = getTuDecl(SrcCode: "template<class T> class X;"
4340 "struct Y { friend class X<int>; };",
4341 Lang: Lang_CXX03, FileName: "input0.cc");
4342 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4343 D: FromTU, AMatcher: Pattern);
4344
4345 Imported1 =
4346 cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX03));
4347 }
4348 ClassTemplateSpecializationDecl *Imported2;
4349 {
4350 Decl *FromTU = getTuDecl(SrcCode: "template<class T> class X;"
4351 "template<> class X<int>{};"
4352 "struct Z { friend class X<int>; };",
4353 Lang: Lang_CXX03, FileName: "input1.cc");
4354 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4355 D: FromTU, AMatcher: Pattern);
4356
4357 Imported2 =
4358 cast<ClassTemplateSpecializationDecl>(Import(FromD, Lang_CXX03));
4359 }
4360
4361 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4362 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
4363 2u);
4364 ASSERT_TRUE(Imported2->getPreviousDecl());
4365 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
4366}
4367
4368TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
4369 Decl *FromTU0 = getTuDecl(
4370 SrcCode: R"(
4371 class X {
4372 class Y;
4373 };
4374 class X::Y {
4375 template <typename T>
4376 friend class F; // The decl context of F is the global namespace.
4377 };
4378 )",
4379 Lang: Lang_CXX03, FileName: "input0.cc");
4380 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4381 D: FromTU0, AMatcher: classTemplateDecl(hasName(Name: "F")));
4382 auto *Imported0 = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX03));
4383 Decl *FromTU1 = getTuDecl(
4384 SrcCode: R"(
4385 template <typename T>
4386 class F {};
4387 )",
4388 Lang: Lang_CXX03, FileName: "input1.cc");
4389 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4390 D: FromTU1, AMatcher: classTemplateDecl(hasName(Name: "F")));
4391 auto *Imported1 = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX03));
4392 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
4393 Imported1->getTemplatedDecl()->getTypeForDecl());
4394}
4395
4396TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
4397 Decl *From, *To;
4398 std::tie(args&: From, args&: To) =
4399 getImportedDecl(FromSrcCode: "class declToImport {};", FromLang: Lang_CXX03,
4400 ToSrcCode: "class Y { friend class declToImport; };", ToLang: Lang_CXX03);
4401 auto *Imported = cast<CXXRecordDecl>(Val: To);
4402
4403 EXPECT_TRUE(Imported->getPreviousDecl());
4404}
4405
4406TEST_P(ImportFriendClasses, SkipComparingFriendTemplateDepth) {
4407 Decl *ToTU = getToTuDecl(
4408 ToSrcCode: R"(
4409 template <class T, T U>
4410 class A;
4411
4412 template <class T, T U>
4413 class A {
4414 public:
4415 template <class P, P Q>
4416 friend class A;
4417
4418 A(T x) :x(x) {}
4419
4420 private:
4421 T x;
4422 };
4423 )",
4424 ToLang: Lang_CXX11);
4425
4426 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4427 D: ToTU,
4428 AMatcher: classTemplateDecl(has(cxxRecordDecl(hasDefinition(), hasName(Name: "A")))));
4429 Decl *FromTU = getTuDecl(
4430 SrcCode: R"(
4431 template <class T, T U>
4432 class A;
4433
4434 template <class T, T U>
4435 class A {
4436 public:
4437 template <class P, P Q>
4438 friend class A;
4439
4440 A(T x) : x(x) {}
4441
4442 private:
4443 T x;
4444 };
4445
4446 A<int,3> a1(0);
4447 )",
4448 Lang: Lang_CXX11, FileName: "input1.cc");
4449 auto *FromA = FirstDeclMatcher<ClassTemplateDecl>().match(
4450 D: FromTU,
4451 AMatcher: classTemplateDecl(has(cxxRecordDecl(hasDefinition(), hasName(Name: "A")))));
4452 auto *ToA = Import(FromA, Lang_CXX11);
4453 EXPECT_TRUE(ToA);
4454 EXPECT_EQ(Fwd->getTemplatedDecl()->getTypeForDecl(),
4455 ToA->getTemplatedDecl()->getTypeForDecl());
4456}
4457
4458TEST_P(ImportFriendClasses,
4459 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
4460 Decl *ToTU = getToTuDecl(
4461 ToSrcCode: R"(
4462 class X {
4463 class Y;
4464 };
4465 class X::Y {
4466 template <typename T>
4467 friend class F; // The decl context of F is the global namespace.
4468 };
4469 )",
4470 ToLang: Lang_CXX03);
4471 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
4472 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "F")));
4473 Decl *FromTU = getTuDecl(
4474 SrcCode: R"(
4475 template <typename T>
4476 class F {};
4477 )",
4478 Lang: Lang_CXX03, FileName: "input0.cc");
4479 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4480 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "F")));
4481 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX03));
4482 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4483 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
4484 EXPECT_EQ(ToDecl->getTemplatedDecl(),
4485 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4486}
4487
4488TEST_P(ImportFriendClasses,
4489 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
4490 Decl *FromTU0 = getTuDecl(
4491 SrcCode: R"(
4492 class X {
4493 class Y;
4494 };
4495 class X::Y {
4496 template <typename T>
4497 friend class F; // The decl context of F is the global namespace.
4498 };
4499 )",
4500 Lang: Lang_CXX03, FileName: "input0.cc");
4501 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4502 D: FromTU0, AMatcher: classTemplateDecl(hasName(Name: "F")));
4503 auto *ImportedFwd = cast<ClassTemplateDecl>(Import(Fwd, Lang_CXX03));
4504 Decl *FromTU1 = getTuDecl(
4505 SrcCode: R"(
4506 template <typename T>
4507 class F {};
4508 )",
4509 Lang: Lang_CXX03, FileName: "input1.cc");
4510 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4511 D: FromTU1, AMatcher: classTemplateDecl(hasName(Name: "F")));
4512 auto *ImportedDef = cast<ClassTemplateDecl>(Import(Definition, Lang_CXX03));
4513 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4514 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4515 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
4516 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4517}
4518
4519TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
4520 Decl *FromTU0 = getTuDecl(
4521 SrcCode: R"(
4522 class X {
4523 class Y;
4524 };
4525 class X::Y {
4526 friend class F; // The decl context of F is the global namespace.
4527 };
4528 )",
4529 Lang: Lang_CXX03, FileName: "input0.cc");
4530 auto *Friend = FirstDeclMatcher<FriendDecl>().match(D: FromTU0, AMatcher: friendDecl());
4531 QualType FT = Friend->getFriendType()->getType();
4532 FT = FromTU0->getASTContext().getCanonicalType(T: FT);
4533 auto *Fwd = cast<TagType>(Val&: FT)->getDecl();
4534 auto *ImportedFwd = Import(Fwd, Lang_CXX03);
4535 Decl *FromTU1 = getTuDecl(
4536 SrcCode: R"(
4537 class F {};
4538 )",
4539 Lang: Lang_CXX03, FileName: "input1.cc");
4540 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
4541 D: FromTU1, AMatcher: cxxRecordDecl(hasName(Name: "F")));
4542 auto *ImportedDef = Import(Definition, Lang_CXX03);
4543 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4544 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4545}
4546
4547TEST_P(ImportFriendClasses,
4548 ImportFriendTemplatesInDependentContext_DefToFriend) {
4549 Decl *ToTU = getToTuDecl(
4550 ToSrcCode: R"(
4551 template<class T1>
4552 struct X {
4553 template<class T2>
4554 friend struct Y;
4555 };
4556 )",
4557 ToLang: Lang_CXX03);
4558 auto *ToYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4559 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4560 Decl *FromTU = getTuDecl(
4561 SrcCode: R"(
4562 template<class T1>
4563 struct Y {};
4564 )",
4565 Lang: Lang_CXX03, FileName: "input0.cc");
4566 auto *FromYDef = FirstDeclMatcher<ClassTemplateDecl>().match(
4567 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4568 auto *ImportedYDef = Import(FromYDef, Lang_CXX03);
4569 EXPECT_TRUE(ImportedYDef);
4570 EXPECT_FALSE(ImportedYDef->getPreviousDecl());
4571 EXPECT_NE(ImportedYDef, ToYFriend);
4572}
4573
4574TEST_P(ImportFriendClasses,
4575 ImportFriendTemplatesInDependentContext_DefToFriend_NE) {
4576 getToTuDecl(
4577 ToSrcCode: R"(
4578 template<class T1>
4579 struct X {
4580 template<class T2>
4581 friend struct Y;
4582 };
4583 )",
4584 ToLang: Lang_CXX03);
4585 Decl *FromTU = getTuDecl(
4586 SrcCode: R"(
4587 template<class T1, class T2>
4588 struct Y {};
4589 )",
4590 Lang: Lang_CXX03, FileName: "input0.cc");
4591 auto *FromYDef = FirstDeclMatcher<ClassTemplateDecl>().match(
4592 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4593 auto *ImportedYDef = Import(FromYDef, Lang_CXX03);
4594 EXPECT_FALSE(ImportedYDef);
4595}
4596
4597TEST_P(ImportFriendClasses,
4598 ImportFriendTemplatesInDependentContext_FriendToFriend) {
4599 Decl *ToTU = getToTuDecl(
4600 ToSrcCode: R"(
4601 template<class T1>
4602 struct X {
4603 template<class T2>
4604 friend struct Y;
4605 };
4606 )",
4607 ToLang: Lang_CXX03);
4608 auto *ToYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4609 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4610 Decl *FromTU = getTuDecl(
4611 SrcCode: R"(
4612 template<class T1>
4613 struct X {
4614 template<class T2>
4615 friend struct Y;
4616 };
4617 )",
4618 Lang: Lang_CXX03, FileName: "input0.cc");
4619 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4620 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4621 auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03);
4622 EXPECT_TRUE(ImportedYFriend);
4623 EXPECT_FALSE(ImportedYFriend->getPreviousDecl());
4624 EXPECT_NE(ImportedYFriend, ToYFriend);
4625}
4626
4627TEST_P(ImportFriendClasses,
4628 ImportFriendTemplatesInDependentContext_FriendToFriend_NE) {
4629 getToTuDecl(
4630 ToSrcCode: R"(
4631 template<class T1>
4632 struct X {
4633 template<class T2>
4634 friend struct Y;
4635 };
4636 )",
4637 ToLang: Lang_CXX03);
4638 Decl *FromTU = getTuDecl(
4639 SrcCode: R"(
4640 template<class T1>
4641 struct X {
4642 template<class T2, class T3>
4643 friend struct Y;
4644 };
4645 )",
4646 Lang: Lang_CXX03, FileName: "input0.cc");
4647 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4648 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4649 auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03);
4650 EXPECT_FALSE(ImportedYFriend);
4651}
4652
4653TEST_P(ImportFriendClasses,
4654 ImportFriendTemplatesInDependentContext_FriendToDef) {
4655 Decl *ToTU = getToTuDecl(
4656 ToSrcCode: R"(
4657 template<class T1>
4658 struct Y {};
4659 )",
4660 ToLang: Lang_CXX03);
4661 auto *ToYDef = FirstDeclMatcher<ClassTemplateDecl>().match(
4662 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4663 Decl *FromTU = getTuDecl(
4664 SrcCode: R"(
4665 template<class T1>
4666 struct X {
4667 template<class T2>
4668 friend struct Y;
4669 };
4670 )",
4671 Lang: Lang_CXX03, FileName: "input0.cc");
4672 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4673 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4674 auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03);
4675 EXPECT_TRUE(ImportedYFriend);
4676 EXPECT_FALSE(ImportedYFriend->getPreviousDecl());
4677 EXPECT_NE(ImportedYFriend, ToYDef);
4678}
4679
4680TEST_P(ImportFriendClasses,
4681 ImportFriendTemplatesInDependentContext_FriendToDef_NE) {
4682 getToTuDecl(
4683 ToSrcCode: R"(
4684 template<class T1>
4685 struct Y {};
4686 )",
4687 ToLang: Lang_CXX03);
4688 Decl *FromTU = getTuDecl(
4689 SrcCode: R"(
4690 template<class T1>
4691 struct X {
4692 template<class T2, class T3>
4693 friend struct Y;
4694 };
4695 )",
4696 Lang: Lang_CXX03, FileName: "input0.cc");
4697 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4698 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4699 auto *ImportedYFriend = Import(FromYFriend, Lang_CXX03);
4700 EXPECT_FALSE(ImportedYFriend);
4701}
4702
4703TEST_P(ImportFriendClasses, ImportOfRepeatedFriendType) {
4704 const char *Code =
4705 R"(
4706 class Container {
4707 friend class X;
4708 friend class X;
4709 };
4710 )";
4711 testRepeatedFriendImport(Code);
4712}
4713
4714TEST_P(ImportFriendClasses, ImportOfRepeatedFriendDecl) {
4715 const char *Code =
4716 R"(
4717 class Container {
4718 friend void f();
4719 friend void f();
4720 };
4721 )";
4722 testRepeatedFriendImport(Code);
4723}
4724
4725TEST_P(ImportFriendClasses, ImportOfRepeatedFriendFunctionTemplateDecl) {
4726 const char *Code =
4727 R"(
4728 template <class T>
4729 class Container {
4730 template <class U> friend void m();
4731 template <class U> friend void m();
4732 };
4733 )";
4734 testRepeatedFriendImport(Code);
4735}
4736
4737TEST_P(ImportFriendClasses, ImportOfRepeatedFriendClassTemplateDecl) {
4738 const char *Code =
4739 R"(
4740 template <class T>
4741 class Container {
4742 template <class U> friend class X;
4743 template <class U> friend class X;
4744 };
4745 )";
4746 testRepeatedFriendImport(Code);
4747}
4748
4749TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
4750 auto *Code = R"(
4751 template <class T>
4752 struct X {
4753 friend void foo(){}
4754 };
4755 )";
4756 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX03);
4757 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
4758 ToTU, functionDecl(hasName(Name: "foo")));
4759
4760 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input.cc");
4761 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4762 FromTU, functionDecl(hasName(Name: "foo")));
4763 auto *ImportedFoo = Import(FromFoo, Lang_CXX03);
4764 EXPECT_EQ(ImportedFoo, ToFoo);
4765}
4766
4767struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
4768
4769TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
4770 Decl *TU = getTuDecl(
4771 SrcCode: R"(
4772 namespace NS {
4773
4774 template <typename T>
4775 struct S {};
4776 template struct S<int>;
4777
4778 inline namespace INS {
4779 template <typename T>
4780 struct S {};
4781 template struct S<int>;
4782 }
4783
4784 }
4785 )", Lang: Lang_CXX11, FileName: "input0.cc");
4786 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4787 D: TU, AMatcher: namespaceDecl());
4788 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4789 D: TU, AMatcher: classTemplateSpecializationDecl());
4790 ASSERT_TRUE(NS->containsDecl(Spec));
4791
4792 NS->removeDecl(Spec);
4793 EXPECT_FALSE(NS->containsDecl(Spec));
4794}
4795
4796TEST_P(DeclContextTest,
4797 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4798 Decl *TU = getTuDecl(SrcCode: "extern int A; int A;", Lang: Lang_CXX03);
4799 auto *A0 = FirstDeclMatcher<VarDecl>().match(D: TU, AMatcher: varDecl(hasName(Name: "A")));
4800 auto *A1 = LastDeclMatcher<VarDecl>().match(D: TU, AMatcher: varDecl(hasName(Name: "A")));
4801
4802 // Investigate the list.
4803 auto *DC = A0->getDeclContext();
4804 ASSERT_TRUE(DC->containsDecl(A0));
4805 ASSERT_TRUE(DC->containsDecl(A1));
4806
4807 // Investigate the lookup table.
4808 auto *Map = DC->getLookupPtr();
4809 ASSERT_TRUE(Map);
4810 auto I = Map->find(A0->getDeclName());
4811 ASSERT_NE(I, Map->end());
4812 StoredDeclsList &L = I->second;
4813 // The lookup table contains the most recent decl of A.
4814 ASSERT_NE(L.getAsDecl(), A0);
4815 ASSERT_EQ(L.getAsDecl(), A1);
4816
4817 ASSERT_TRUE(L.getAsDecl());
4818 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4819 // We do not have a list with one element.
4820 L.setHasExternalDecls();
4821 ASSERT_FALSE(L.getAsList());
4822 auto Results = L.getLookupResult();
4823 ASSERT_EQ(1u, std::distance(Results.begin(), Results.end()));
4824
4825 // This asserts in the old implementation.
4826 DC->removeDecl(A0);
4827 EXPECT_FALSE(DC->containsDecl(A0));
4828
4829 // Make sure we do not leave a StoredDeclsList with no entries.
4830 DC->removeDecl(A1);
4831 ASSERT_EQ(Map->find(A1->getDeclName()), Map->end());
4832}
4833
4834struct ImportFunctionTemplateSpecializations
4835 : ASTImporterOptionSpecificTestBase {};
4836
4837TEST_P(ImportFunctionTemplateSpecializations,
4838 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4839
4840 Decl *FromTU = getTuDecl(
4841 SrcCode: R"(
4842 template<class T>
4843 int f() { return 0; }
4844 void foo() { f<int>(); }
4845 )",
4846 Lang: Lang_CXX03, FileName: "input0.cc");
4847
4848 // Check that the function template instantiation is NOT the child of the TU.
4849 auto Pattern = translationUnitDecl(
4850 unless(has(functionDecl(hasName(Name: "f"), isTemplateInstantiation()))));
4851 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4852
4853 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4854 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo")));
4855 ASSERT_TRUE(Import(Foo, Lang_CXX03));
4856
4857 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4858 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4859}
4860
4861TEST_P(ImportFunctionTemplateSpecializations,
4862 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4863
4864 Decl *FromTU = getTuDecl(
4865 SrcCode: R"(
4866 template<class T>
4867 int f() { return 0; }
4868 template int f<int>();
4869 )",
4870 Lang: Lang_CXX03, FileName: "input0.cc");
4871
4872 // Check that the function template instantiation is NOT the child of the TU.
4873 auto Instantiation = functionDecl(hasName(Name: "f"), isTemplateInstantiation());
4874 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4875 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4876
4877 ASSERT_TRUE(Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation),
4878 Lang_CXX03));
4879
4880 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4881 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4882}
4883
4884TEST_P(ImportFunctionTemplateSpecializations,
4885 TUshouldContainFunctionTemplateSpecialization) {
4886
4887 Decl *FromTU = getTuDecl(
4888 SrcCode: R"(
4889 template<class T>
4890 int f() { return 0; }
4891 template <> int f<int>() { return 4; }
4892 )",
4893 Lang: Lang_CXX03, FileName: "input0.cc");
4894
4895 // Check that the function template specialization is the child of the TU.
4896 auto Specialization =
4897 functionDecl(hasName(Name: "f"), isExplicitTemplateSpecialization());
4898 auto Pattern = translationUnitDecl(has(Specialization));
4899 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4900
4901 ASSERT_TRUE(Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization),
4902 Lang_CXX03));
4903
4904 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4905 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4906}
4907
4908TEST_P(ImportFunctionTemplateSpecializations,
4909 FunctionTemplateSpecializationRedeclChain) {
4910
4911 Decl *FromTU = getTuDecl(
4912 SrcCode: R"(
4913 template<class T>
4914 int f() { return 0; }
4915 template <> int f<int>() { return 4; }
4916 )",
4917 Lang: Lang_CXX03, FileName: "input0.cc");
4918
4919 auto Spec = functionDecl(hasName(Name: "f"), isExplicitTemplateSpecialization(),
4920 hasParent(translationUnitDecl()));
4921 auto *FromSpecD = FirstDeclMatcher<Decl>().match(D: FromTU, AMatcher: Spec);
4922 {
4923 auto *TU = FromTU;
4924 auto *SpecD = FromSpecD;
4925 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4926 TU, functionTemplateDecl());
4927 auto *FirstSpecD = *(TemplateD->spec_begin());
4928 ASSERT_EQ(SpecD, FirstSpecD);
4929 ASSERT_TRUE(SpecD->getPreviousDecl());
4930 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4931 ->doesThisDeclarationHaveABody());
4932 }
4933
4934 ASSERT_TRUE(Import(FromSpecD, Lang_CXX03));
4935
4936 {
4937 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
4938 auto *SpecD = FirstDeclMatcher<Decl>().match(TU, Spec);
4939 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
4940 TU, functionTemplateDecl());
4941 auto *FirstSpecD = *(TemplateD->spec_begin());
4942 EXPECT_EQ(SpecD, FirstSpecD);
4943 ASSERT_TRUE(SpecD->getPreviousDecl());
4944 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
4945 ->doesThisDeclarationHaveABody());
4946 }
4947}
4948
4949TEST_P(ImportFunctionTemplateSpecializations,
4950 MatchNumberOfFunctionTemplateSpecializations) {
4951
4952 Decl *FromTU = getTuDecl(
4953 SrcCode: R"(
4954 template <typename T> constexpr int f() { return 0; }
4955 template <> constexpr int f<int>() { return 4; }
4956 void foo() {
4957 static_assert(f<char>() == 0, "");
4958 static_assert(f<int>() == 4, "");
4959 }
4960 )",
4961 Lang: Lang_CXX11, FileName: "input0.cc");
4962 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
4963 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo")));
4964
4965 Import(FromD, Lang_CXX11);
4966 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4967 EXPECT_EQ(
4968 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
4969 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
4970}
4971
4972TEST_P(ASTImporterOptionSpecificTestBase,
4973 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
4974 {
4975 Decl *FromTU = getTuDecl(
4976 SrcCode: R"(
4977 template <typename T>
4978 struct B;
4979 )",
4980 Lang: Lang_CXX03, FileName: "input0.cc");
4981 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4982 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "B")));
4983
4984 Import(FromD, Lang_CXX03);
4985 }
4986
4987 {
4988 Decl *FromTU = getTuDecl(
4989 SrcCode: R"(
4990 template <typename T>
4991 struct B {
4992 void f();
4993 B* b;
4994 };
4995 )",
4996 Lang: Lang_CXX03, FileName: "input1.cc");
4997 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
4998 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
4999 Import(From: FromD, Lang: Lang_CXX03);
5000 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
5001 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "B")));
5002 auto *ToCTD = cast<ClassTemplateDecl>(Import(FromCTD, Lang_CXX03));
5003 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
5004
5005 // We expect no (ODR) warning during the import.
5006 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5007 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
5008 }
5009}
5010
5011TEST_P(ASTImporterOptionSpecificTestBase,
5012 ImportingTypedefShouldImportTheCompleteType) {
5013 // We already have an incomplete underlying type in the "To" context.
5014 auto Code =
5015 R"(
5016 template <typename T>
5017 struct S {
5018 void foo();
5019 };
5020 using U = S<int>;
5021 )";
5022 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX11);
5023 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(D: ToTU,
5024 AMatcher: typedefNameDecl(hasName(Name: "U")));
5025 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
5026
5027 // The "From" context has the same typedef, but the underlying type is
5028 // complete this time.
5029 Decl *FromTU = getTuDecl(SrcCode: std::string(Code) +
5030 R"(
5031 void foo(U* u) {
5032 u->foo();
5033 }
5034 )", Lang: Lang_CXX11);
5035 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(D: FromTU,
5036 AMatcher: typedefNameDecl(hasName(Name: "U")));
5037 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
5038
5039 // The imported type should be complete.
5040 auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
5041 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
5042}
5043
5044TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) {
5045 auto Code =
5046 R"(
5047 template<class T>
5048 int f() { return 0; }
5049 template <> int f<int>() { return 4; }
5050 )";
5051
5052 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
5053 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU,
5054 AMatcher: functionDecl(hasName(Name: "f"), isExplicitTemplateSpecialization()));
5055 ASSERT_EQ(FromD->getNumTemplateParameterLists(), 1u);
5056
5057 auto *ToD = Import(FromD, Lang_CXX03);
5058 // The template parameter list should exist.
5059 EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u);
5060}
5061
5062const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateDecl>
5063 varTemplateDecl;
5064
5065const internal::VariadicDynCastAllOfMatcher<
5066 Decl, VarTemplatePartialSpecializationDecl>
5067 varTemplatePartialSpecializationDecl;
5068
5069TEST_P(ASTImporterOptionSpecificTestBase,
5070 FunctionTemplateParameterDeclContext) {
5071 constexpr auto Code =
5072 R"(
5073 template<class T>
5074 void f() {};
5075 )";
5076
5077 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
5078
5079 auto *FromD = FirstDeclMatcher<FunctionTemplateDecl>().match(
5080 D: FromTU, AMatcher: functionTemplateDecl(hasName(Name: "f")));
5081
5082 ASSERT_EQ(FromD->getTemplateParameters()->getParam(0)->getDeclContext(),
5083 FromD->getTemplatedDecl());
5084
5085 auto *ToD = Import(FromD, Lang_CXX11);
5086 EXPECT_EQ(ToD->getTemplateParameters()->getParam(0)->getDeclContext(),
5087 ToD->getTemplatedDecl());
5088 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5089 ToD->getTemplatedDecl(), ToD->getTemplateParameters()->getParam(0)));
5090}
5091
5092TEST_P(ASTImporterOptionSpecificTestBase, ClassTemplateParameterDeclContext) {
5093 constexpr auto Code =
5094 R"(
5095 template<class T1, class T2>
5096 struct S {};
5097 template<class T2>
5098 struct S<int, T2> {};
5099 )";
5100
5101 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
5102
5103 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
5104 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "S")));
5105 auto *FromDPart =
5106 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
5107 D: FromTU, AMatcher: classTemplatePartialSpecializationDecl(hasName(Name: "S")));
5108
5109 ASSERT_EQ(FromD->getTemplateParameters()->getParam(0)->getDeclContext(),
5110 FromD->getTemplatedDecl());
5111 ASSERT_EQ(FromDPart->getTemplateParameters()->getParam(0)->getDeclContext(),
5112 FromDPart);
5113
5114 auto *ToD = Import(FromD, Lang_CXX11);
5115 auto *ToDPart = Import(FromDPart, Lang_CXX11);
5116
5117 EXPECT_EQ(ToD->getTemplateParameters()->getParam(0)->getDeclContext(),
5118 ToD->getTemplatedDecl());
5119 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5120 ToD->getTemplatedDecl(), ToD->getTemplateParameters()->getParam(0)));
5121
5122 EXPECT_EQ(ToDPart->getTemplateParameters()->getParam(0)->getDeclContext(),
5123 ToDPart);
5124 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5125 ToDPart, ToDPart->getTemplateParameters()->getParam(0)));
5126}
5127
5128TEST_P(ASTImporterOptionSpecificTestBase,
5129 CXXDeductionGuideTemplateParameterDeclContext) {
5130 Decl *FromTU = getTuDecl(
5131 SrcCode: R"(
5132 template <typename T> struct A {
5133 A(T);
5134 };
5135 A a{(int)0};
5136 )",
5137 Lang: Lang_CXX17, FileName: "input.cc");
5138// clang-format off
5139/*
5140|-ClassTemplateDecl 0x1fe5000 <input.cc:2:7, line:4:7> line:2:36 A
5141| |-TemplateTypeParmDecl 0x1fe4eb0 <col:17, col:26> col:26 referenced typename depth 0 index 0 T
5142| |-CXXRecordDecl 0x1fe4f70 <col:29, line:4:7> line:2:36 struct A definition
5143
5144|-FunctionTemplateDecl 0x1fe5860 <line:2:7, line:3:12> col:9 implicit <deduction guide for A>
5145| |-TemplateTypeParmDecl 0x1fe4eb0 <line:2:17, col:26> col:26 referenced typename depth 0 index 0 T
5146| |-CXXDeductionGuideDecl 0x1fe57a8 <line:3:9, col:12> col:9 implicit <deduction guide for A> 'auto (T) -> A<T>'
5147| | `-ParmVarDecl 0x1fe56b0 <col:11> col:12 'T'
5148| `-CXXDeductionGuideDecl 0x20515d8 <col:9, col:12> col:9 implicit used <deduction guide for A> 'auto (int) -> A<int>'
5149| |-TemplateArgument type 'int'
5150| | `-BuiltinType 0x20587e0 'int'
5151| `-ParmVarDecl 0x2051388 <col:11> col:12 'int'
5152`-FunctionTemplateDecl 0x1fe5a78 <line:2:7, col:36> col:36 implicit <deduction guide for A>
5153 |-TemplateTypeParmDecl 0x1fe4eb0 <col:17, col:26> col:26 referenced typename depth 0 index 0 T
5154 `-CXXDeductionGuideDecl 0x1fe59c0 <col:36> col:36 implicit <deduction guide for A> 'auto (A<T>) -> A<T>'
5155 `-ParmVarDecl 0x1fe5958 <col:36> col:36 'A<T>'
5156*/
5157// clang-format on
5158 auto *FromD1 = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
5159 D: FromTU, AMatcher: cxxDeductionGuideDecl());
5160 auto *FromD2 = LastDeclMatcher<CXXDeductionGuideDecl>().match(
5161 D: FromTU, AMatcher: cxxDeductionGuideDecl());
5162
5163 NamedDecl *P1 =
5164 FromD1->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(
5165 0);
5166 NamedDecl *P2 =
5167 FromD2->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(
5168 0);
5169 DeclContext *DC = P1->getDeclContext();
5170
5171 ASSERT_EQ(P1, P2);
5172 ASSERT_TRUE(DC == FromD1 || DC == FromD2);
5173
5174 auto *ToD1 = Import(FromD1, Lang_CXX17);
5175 auto *ToD2 = Import(FromD2, Lang_CXX17);
5176 ASSERT_TRUE(ToD1 && ToD2);
5177
5178 P1 = ToD1->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(
5179 0);
5180 P2 = ToD2->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(
5181 0);
5182 DC = P1->getDeclContext();
5183
5184 EXPECT_EQ(P1, P2);
5185 EXPECT_TRUE(DC == ToD1 || DC == ToD2);
5186
5187 ASTImporterLookupTable *Tbl = SharedStatePtr->getLookupTable();
5188 if (Tbl->contains(DC: ToD1, ND: P1)) {
5189 EXPECT_FALSE(Tbl->contains(ToD2, P1));
5190 } else {
5191 EXPECT_TRUE(Tbl->contains(ToD2, P1));
5192 }
5193}
5194
5195TEST_P(ASTImporterOptionSpecificTestBase, RecordVarTemplateDecl) {
5196 Decl *ToTU = getToTuDecl(
5197 ToSrcCode: R"(
5198 template <class T>
5199 class A {
5200 public:
5201 template <class U>
5202 static constexpr bool X = true;
5203 };
5204 )",
5205 ToLang: Lang_CXX14);
5206
5207 auto *ToTUX = FirstDeclMatcher<VarTemplateDecl>().match(
5208 D: ToTU, AMatcher: varTemplateDecl(hasName(Name: "X")));
5209 Decl *FromTU = getTuDecl(
5210 SrcCode: R"(
5211 template <class T>
5212 class A {
5213 public:
5214 template <class U>
5215 static constexpr bool X = true;
5216 };
5217 )",
5218 Lang: Lang_CXX14, FileName: "input1.cc");
5219 auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match(
5220 D: FromTU, AMatcher: varTemplateDecl(hasName(Name: "X")));
5221 auto *ToX = Import(FromX, Lang_CXX11);
5222 EXPECT_TRUE(ToX);
5223 EXPECT_EQ(ToTUX, ToX);
5224}
5225
5226TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateDeclConflict) {
5227 getToTuDecl(
5228 ToSrcCode: R"(
5229 template <class U>
5230 constexpr int X = 1;
5231 )",
5232 ToLang: Lang_CXX14);
5233
5234 Decl *FromTU = getTuDecl(
5235 SrcCode: R"(
5236 template <class U>
5237 constexpr int X = 2;
5238 )",
5239 Lang: Lang_CXX14, FileName: "input1.cc");
5240 auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match(
5241 D: FromTU, AMatcher: varTemplateDecl(hasName(Name: "X")));
5242 auto *ToX = Import(FromX, Lang_CXX11);
5243 // FIXME: This import should fail.
5244 EXPECT_TRUE(ToX);
5245}
5246
5247TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateStaticDefinition) {
5248 Decl *ToTU = getToTuDecl(
5249 ToSrcCode: R"(
5250 struct A {
5251 template <class U>
5252 static int X;
5253 };
5254 )",
5255 ToLang: Lang_CXX14);
5256 auto *ToX = FirstDeclMatcher<VarTemplateDecl>().match(
5257 D: ToTU, AMatcher: varTemplateDecl(hasName(Name: "X")));
5258 ASSERT_FALSE(ToX->isThisDeclarationADefinition());
5259
5260 Decl *FromTU = getTuDecl(
5261 SrcCode: R"(
5262 struct A {
5263 template <class U>
5264 static int X;
5265 };
5266 template <class U>
5267 int A::X = 2;
5268 )",
5269 Lang: Lang_CXX14, FileName: "input1.cc");
5270 auto *FromXDef = LastDeclMatcher<VarTemplateDecl>().match(
5271 D: FromTU, AMatcher: varTemplateDecl(hasName(Name: "X")));
5272 ASSERT_TRUE(FromXDef->isThisDeclarationADefinition());
5273 auto *ToXDef = Import(FromXDef, Lang_CXX14);
5274 EXPECT_TRUE(ToXDef);
5275 EXPECT_TRUE(ToXDef->isThisDeclarationADefinition());
5276 EXPECT_EQ(ToXDef->getPreviousDecl(), ToX);
5277}
5278
5279TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateSpecializationDeclValue) {
5280 Decl *ToTU = getToTuDecl(
5281 ToSrcCode: R"(
5282 template <class U>
5283 constexpr int X = U::Value;
5284 struct A { static constexpr int Value = 1; };
5285 constexpr int Y = X<A>;
5286 )",
5287 ToLang: Lang_CXX14);
5288
5289 auto *ToTUX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(
5290 D: ToTU, AMatcher: varTemplateSpecializationDecl(hasName(Name: "X")));
5291 Decl *FromTU = getTuDecl(
5292 SrcCode: R"(
5293 template <class U>
5294 constexpr int X = U::Value;
5295 struct A { static constexpr int Value = 1; };
5296 constexpr int Y = X<A>;
5297 )",
5298 Lang: Lang_CXX14, FileName: "input1.cc");
5299 auto *FromX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(
5300 D: FromTU, AMatcher: varTemplateSpecializationDecl(hasName(Name: "X")));
5301 auto *ToX = Import(FromX, Lang_CXX14);
5302 EXPECT_TRUE(ToX);
5303 EXPECT_EQ(ToTUX, ToX);
5304}
5305
5306TEST_P(ASTImporterOptionSpecificTestBase,
5307 VarTemplateSpecializationDeclValueConflict) {
5308 getToTuDecl(
5309 ToSrcCode: R"(
5310 template <class U>
5311 constexpr int X = U::Value;
5312 struct A { static constexpr int Value = 1; };
5313 constexpr int Y = X<A>;
5314 )",
5315 ToLang: Lang_CXX14);
5316
5317 Decl *FromTU = getTuDecl(
5318 SrcCode: R"(
5319 template <class U>
5320 constexpr int X = U::Value;
5321 struct A { static constexpr int Value = 2; };
5322 constexpr int Y = X<A>;
5323 )",
5324 Lang: Lang_CXX14, FileName: "input1.cc");
5325 auto *FromX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(
5326 D: FromTU, AMatcher: varTemplateSpecializationDecl(hasName(Name: "X")));
5327 auto *ToX = Import(FromX, Lang_CXX14);
5328 EXPECT_FALSE(ToX);
5329}
5330
5331TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateDeclInlineWithCXX17) {
5332 Decl *FromTU = getTuDecl(
5333 SrcCode: R"(
5334 struct S {
5335 template <unsigned> static constexpr bool X = true;
5336 };
5337 )",
5338 Lang: Lang_CXX17, FileName: "input1.cc");
5339 Decl *FromTU2 = getTuDecl(
5340 SrcCode: R"(
5341 struct S {
5342 template <unsigned> static constexpr bool X = true;
5343 template <typename T> void get() { X<sizeof(T)>; }
5344 };
5345 template <typename U> U qvariant_cast(const S &v) { return v.get; }
5346 )",
5347 Lang: Lang_CXX17, FileName: "input2.cc");
5348 auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match(
5349 D: FromTU, AMatcher: varTemplateDecl(hasName(Name: "X")));
5350 auto *ToX = Import(FromX, Lang_CXX17);
5351 ASSERT_TRUE(ToX);
5352 auto *FromX2 = FirstDeclMatcher<VarTemplateDecl>().match(
5353 D: FromTU2, AMatcher: varTemplateDecl(hasName(Name: "X")));
5354 auto *ToX2 = Import(FromX2, Lang_CXX17);
5355 EXPECT_TRUE(ToX2);
5356 EXPECT_EQ(ToX, ToX2);
5357}
5358
5359TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateParameterDeclContext) {
5360 constexpr auto Code =
5361 R"(
5362 template<class T1, class T2>
5363 int X1;
5364 template<class T2>
5365 int X1<int, T2>;
5366
5367 namespace Ns {
5368 template<class T1, class T2>
5369 int X2;
5370 template<class T2>
5371 int X2<int, T2>;
5372 }
5373 )";
5374
5375 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX14);
5376
5377 auto *FromD1 = FirstDeclMatcher<VarTemplateDecl>().match(
5378 D: FromTU, AMatcher: varTemplateDecl(hasName(Name: "X1")));
5379 auto *FromD1Part =
5380 FirstDeclMatcher<VarTemplatePartialSpecializationDecl>().match(
5381 D: FromTU, AMatcher: varTemplatePartialSpecializationDecl(hasName(Name: "X1")));
5382 auto *FromD2 = FirstDeclMatcher<VarTemplateDecl>().match(
5383 D: FromTU, AMatcher: varTemplateDecl(hasName(Name: "X2")));
5384 auto *FromD2Part =
5385 FirstDeclMatcher<VarTemplatePartialSpecializationDecl>().match(
5386 D: FromTU, AMatcher: varTemplatePartialSpecializationDecl(hasName(Name: "X2")));
5387
5388 ASSERT_EQ(FromD1->getTemplateParameters()->getParam(0)->getDeclContext(),
5389 FromD1->getDeclContext());
5390 ASSERT_EQ(FromD2->getTemplateParameters()->getParam(0)->getDeclContext(),
5391 FromD2->getDeclContext());
5392
5393 ASSERT_EQ(FromD1Part->getTemplateParameters()->getParam(0)->getDeclContext(),
5394 FromD1Part->getDeclContext());
5395 // FIXME: VarTemplatePartialSpecializationDecl does not update ("adopt")
5396 // template parameter decl context
5397 // ASSERT_EQ(FromD2Part->getTemplateParameters()->getParam(0)->getDeclContext(),
5398 // FromD2Part->getDeclContext());
5399
5400 auto *ToD1 = Import(FromD1, Lang_CXX14);
5401 auto *ToD2 = Import(FromD2, Lang_CXX14);
5402
5403 auto *ToD1Part = Import(FromD1Part, Lang_CXX14);
5404 auto *ToD2Part = Import(FromD2Part, Lang_CXX14);
5405
5406 EXPECT_EQ(ToD1->getTemplateParameters()->getParam(0)->getDeclContext(),
5407 ToD1->getDeclContext());
5408 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5409 ToD1->getDeclContext(), ToD1->getTemplateParameters()->getParam(0)));
5410 EXPECT_EQ(ToD2->getTemplateParameters()->getParam(0)->getDeclContext(),
5411 ToD2->getDeclContext());
5412 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5413 ToD2->getDeclContext(), ToD2->getTemplateParameters()->getParam(0)));
5414
5415 EXPECT_EQ(ToD1Part->getTemplateParameters()->getParam(0)->getDeclContext(),
5416 ToD1Part->getDeclContext());
5417 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5418 ToD1Part->getDeclContext(),
5419 ToD1Part->getTemplateParameters()->getParam(0)));
5420 // EXPECT_EQ(ToD2Part->getTemplateParameters()->getParam(0)->getDeclContext(),
5421 // ToD2Part->getDeclContext());
5422 // EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5423 // ToD2Part->getDeclContext(),
5424 // ToD2Part->getTemplateParameters()->getParam(0)));
5425 (void)ToD2Part;
5426}
5427
5428TEST_P(ASTImporterOptionSpecificTestBase,
5429 TypeAliasTemplateParameterDeclContext) {
5430 constexpr auto Code =
5431 R"(
5432 template<class T1, class T2>
5433 struct S {};
5434 template<class T> using S1 = S<T, int>;
5435 namespace Ns {
5436 template<class T> using S2 = S<T, int>;
5437 }
5438 )";
5439
5440 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
5441
5442 auto *FromD1 = FirstDeclMatcher<TypeAliasTemplateDecl>().match(
5443 D: FromTU, AMatcher: typeAliasTemplateDecl(hasName(Name: "S1")));
5444 auto *FromD2 = FirstDeclMatcher<TypeAliasTemplateDecl>().match(
5445 D: FromTU, AMatcher: typeAliasTemplateDecl(hasName(Name: "S2")));
5446
5447 ASSERT_EQ(FromD1->getTemplateParameters()->getParam(0)->getDeclContext(),
5448 FromD1->getDeclContext());
5449 ASSERT_EQ(FromD2->getTemplateParameters()->getParam(0)->getDeclContext(),
5450 FromD2->getDeclContext());
5451
5452 auto *ToD1 = Import(FromD1, Lang_CXX11);
5453 auto *ToD2 = Import(FromD2, Lang_CXX11);
5454
5455 EXPECT_EQ(ToD1->getTemplateParameters()->getParam(0)->getDeclContext(),
5456 ToD1->getDeclContext());
5457 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5458 ToD1->getDeclContext(), ToD1->getTemplateParameters()->getParam(0)));
5459 EXPECT_EQ(ToD2->getTemplateParameters()->getParam(0)->getDeclContext(),
5460 ToD2->getDeclContext());
5461 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5462 ToD2->getDeclContext(), ToD2->getTemplateParameters()->getParam(0)));
5463}
5464
5465TEST_P(ASTImporterOptionSpecificTestBase, ImportSubstTemplateTypeParmType) {
5466 constexpr auto Code = R"(
5467 template <class A1, class... A2> struct A {
5468 using B = A1(A2...);
5469 };
5470 template struct A<void, char, float, int, short>;
5471 )";
5472 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11, FileName: "input.cpp");
5473 auto *FromClass = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
5474 D: FromTU, AMatcher: classTemplateSpecializationDecl());
5475
5476 auto testType = [&](ASTContext &Ctx, const char *Name,
5477 UnsignedOrNone PackIndex) {
5478 const auto *Subst = selectFirst<SubstTemplateTypeParmType>(
5479 BoundTo: "sttp", Results: match(Matcher: substTemplateTypeParmType(
5480 hasReplacementType(hasCanonicalType(InnerMatcher: asString(Name))))
5481 .bind(ID: "sttp"),
5482 Context&: Ctx));
5483 const char *ExpectedTemplateParamName = PackIndex ? "A2" : "A1";
5484 ASSERT_TRUE(Subst);
5485 ASSERT_EQ(Subst->getReplacedParameter()->getIdentifier()->getName(),
5486 ExpectedTemplateParamName);
5487 ASSERT_EQ(Subst->getPackIndex(), PackIndex);
5488 };
5489 auto tests = [&](ASTContext &Ctx) {
5490 testType(Ctx, "void", std::nullopt);
5491 testType(Ctx, "char", 3u);
5492 testType(Ctx, "float", 2u);
5493 testType(Ctx, "int", 1u);
5494 testType(Ctx, "short", 0u);
5495 };
5496
5497 tests(FromTU->getASTContext());
5498
5499 ClassTemplateSpecializationDecl *ToClass = Import(FromClass, Lang_CXX11);
5500 tests(ToClass->getASTContext());
5501}
5502
5503const AstTypeMatcher<SubstTemplateTypeParmPackType>
5504 substTemplateTypeParmPackType;
5505
5506TEST_P(ASTImporterOptionSpecificTestBase, ImportSubstTemplateTypeParmPackType) {
5507 constexpr auto Code = R"(
5508 template<typename ...T> struct D {
5509 template<typename... U> using B = int(int (*...p)(T, U));
5510 template<typename U1, typename U2> D(B<U1, U2>*);
5511 };
5512 int f(int(int, int), int(int, int));
5513
5514 using asd = D<float, double, float>::B<int, long, int>;
5515 )";
5516 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11, FileName: "input.cpp");
5517 auto *FromClass = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
5518 D: FromTU, AMatcher: classTemplateSpecializationDecl());
5519
5520 {
5521 ASTContext &FromCtx = FromTU->getASTContext();
5522 const auto *FromSubstPack = selectFirst<SubstTemplateTypeParmPackType>(
5523 BoundTo: "pack", Results: match(Matcher: substTemplateTypeParmPackType().bind(ID: "pack"), Context&: FromCtx));
5524
5525 ASSERT_TRUE(FromSubstPack);
5526 ASSERT_EQ(FromSubstPack->getIdentifier()->getName(), "T");
5527 ArrayRef<TemplateArgument> FromArgPack =
5528 FromSubstPack->getArgumentPack().pack_elements();
5529 ASSERT_EQ(FromArgPack.size(), 3u);
5530 ASSERT_EQ(FromArgPack[0].getAsType(), FromCtx.FloatTy);
5531 ASSERT_EQ(FromArgPack[1].getAsType(), FromCtx.DoubleTy);
5532 ASSERT_EQ(FromArgPack[2].getAsType(), FromCtx.FloatTy);
5533 }
5534 {
5535 // Let's do the import.
5536 ClassTemplateSpecializationDecl *ToClass = Import(FromClass, Lang_CXX11);
5537 ASTContext &ToCtx = ToClass->getASTContext();
5538
5539 const auto *ToSubstPack = selectFirst<SubstTemplateTypeParmPackType>(
5540 BoundTo: "pack", Results: match(Matcher: substTemplateTypeParmPackType().bind(ID: "pack"), Context&: ToCtx));
5541
5542 // Check if it meets the requirements.
5543 ASSERT_TRUE(ToSubstPack);
5544 ASSERT_EQ(ToSubstPack->getIdentifier()->getName(), "T");
5545 ArrayRef<TemplateArgument> ToArgPack =
5546 ToSubstPack->getArgumentPack().pack_elements();
5547 ASSERT_EQ(ToArgPack.size(), 3u);
5548 ASSERT_EQ(ToArgPack[0].getAsType(), ToCtx.FloatTy);
5549 ASSERT_EQ(ToArgPack[1].getAsType(), ToCtx.DoubleTy);
5550 ASSERT_EQ(ToArgPack[2].getAsType(), ToCtx.FloatTy);
5551 }
5552}
5553
5554struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
5555
5556TEST_P(ASTImporterLookupTableTest, OneDecl) {
5557 auto *ToTU = getToTuDecl(ToSrcCode: "int a;", ToLang: Lang_CXX03);
5558 auto *D = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName(Name: "a")));
5559 ASTImporterLookupTable LT(*ToTU);
5560 auto Res = LT.lookup(DC: ToTU, Name: D->getDeclName());
5561 ASSERT_EQ(Res.size(), 1u);
5562 EXPECT_EQ(*Res.begin(), D);
5563}
5564
5565static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
5566 for (Decl *D : DC->decls()) {
5567 if (auto *ND = dyn_cast<NamedDecl>(Val: D))
5568 if (ND->getDeclName() == Name)
5569 return ND;
5570 }
5571 return nullptr;
5572}
5573
5574TEST_P(ASTImporterLookupTableTest,
5575 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
5576 auto *Code = R"(
5577 template <class T>
5578 struct X {
5579 friend void foo(){}
5580 };
5581 )";
5582 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX03);
5583 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
5584 ToTU, classTemplateDecl(hasName(Name: "X")));
5585 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
5586 ToTU, functionDecl(hasName(Name: "foo")));
5587 DeclContext *FooDC = Foo->getDeclContext();
5588 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
5589 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
5590 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
5591 DeclarationName FooName = Foo->getDeclName();
5592
5593 // Cannot find in the LookupTable of its DC (TUDecl)
5594 SmallVector<NamedDecl *, 2> FoundDecls;
5595 FooDC->getRedeclContext()->localUncachedLookup(Name: FooName, Results&: FoundDecls);
5596 EXPECT_EQ(FoundDecls.size(), 0u);
5597
5598 // Cannot find in the LookupTable of its LexicalDC (X)
5599 FooLexicalDC->getRedeclContext()->localUncachedLookup(Name: FooName, Results&: FoundDecls);
5600 EXPECT_EQ(FoundDecls.size(), 0u);
5601
5602 // Can't find in the list of Decls of the DC.
5603 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
5604
5605 // Can't find in the list of Decls of the LexicalDC
5606 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
5607
5608 // ASTImporter specific lookup finds it.
5609 ASTImporterLookupTable LT(*ToTU);
5610 auto Res = LT.lookup(DC: FooDC, Name: Foo->getDeclName());
5611 ASSERT_EQ(Res.size(), 1u);
5612 EXPECT_EQ(*Res.begin(), Foo);
5613}
5614
5615TEST_P(ASTImporterLookupTableTest,
5616 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
5617 TranslationUnitDecl *ToTU =
5618 getToTuDecl(ToSrcCode: "struct A { struct Foo *p; };", ToLang: Lang_C99);
5619 auto *Foo =
5620 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName(Name: "Foo")));
5621 auto *A =
5622 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName(Name: "A")));
5623 DeclContext *FooDC = Foo->getDeclContext();
5624 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
5625 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
5626 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
5627 DeclarationName FooName = Foo->getDeclName();
5628
5629 // Cannot find in the LookupTable of its DC (TUDecl).
5630 SmallVector<NamedDecl *, 2> FoundDecls;
5631 FooDC->getRedeclContext()->localUncachedLookup(Name: FooName, Results&: FoundDecls);
5632 EXPECT_EQ(FoundDecls.size(), 0u);
5633
5634 // Finds via linear search of its LexicalDC (A).
5635 FooLexicalDC->getRedeclContext()->localUncachedLookup(Name: FooName, Results&: FoundDecls);
5636 EXPECT_EQ(FoundDecls.size(), 1u);
5637
5638 // Can't find in the list of Decls of the DC.
5639 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
5640
5641 // Can find in the list of Decls of the LexicalDC.
5642 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
5643
5644 // ASTImporter specific lookup finds it.
5645 ASTImporterLookupTable LT(*ToTU);
5646 auto Res = LT.lookup(DC: FooDC, Name: Foo->getDeclName());
5647 ASSERT_EQ(Res.size(), 1u);
5648 EXPECT_EQ(*Res.begin(), Foo);
5649}
5650
5651TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
5652 TranslationUnitDecl *ToTU =
5653 getToTuDecl(ToSrcCode: "int V; struct A { int V; }; struct B { int V; };", ToLang: Lang_C99);
5654 DeclarationName VName = FirstDeclMatcher<VarDecl>()
5655 .match(ToTU, varDecl(hasName(Name: "V")))
5656 ->getDeclName();
5657 auto *A =
5658 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName(Name: "A")));
5659 auto *B =
5660 FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName(Name: "B")));
5661
5662 ASTImporterLookupTable LT(*ToTU);
5663
5664 auto Res = LT.lookup(DC: cast<DeclContext>(A), Name: VName);
5665 ASSERT_EQ(Res.size(), 1u);
5666 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5667 ToTU, fieldDecl(hasName("V"),
5668 hasParent(recordDecl(hasName("A"))))));
5669 Res = LT.lookup(DC: cast<DeclContext>(B), Name: VName);
5670 ASSERT_EQ(Res.size(), 1u);
5671 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5672 ToTU, fieldDecl(hasName("V"),
5673 hasParent(recordDecl(hasName("B"))))));
5674 Res = LT.lookup(ToTU, VName);
5675 ASSERT_EQ(Res.size(), 1u);
5676 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
5677 ToTU, varDecl(hasName("V"),
5678 hasParent(translationUnitDecl()))));
5679}
5680
5681TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
5682 TranslationUnitDecl *ToTU = getToTuDecl(
5683 ToSrcCode: R"(
5684 void foo();
5685 void foo(int);
5686 void foo(int, int);
5687 )",
5688 ToLang: Lang_CXX03);
5689
5690 ASTImporterLookupTable LT(*ToTU);
5691 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5692 auto *F2 = LastDeclMatcher<FunctionDecl>().match(ToTU, functionDecl());
5693 DeclarationName Name = F0->getDeclName();
5694 auto Res = LT.lookup(ToTU, Name);
5695 EXPECT_EQ(Res.size(), 3u);
5696 EXPECT_EQ(Res.count(F0), 1u);
5697 EXPECT_EQ(Res.count(F2), 1u);
5698}
5699
5700TEST_P(ASTImporterLookupTableTest,
5701 DifferentOperatorsShouldHaveDifferentResultSet) {
5702 TranslationUnitDecl *ToTU = getToTuDecl(
5703 ToSrcCode: R"(
5704 struct X{};
5705 void operator+(X, X);
5706 void operator-(X, X);
5707 )",
5708 ToLang: Lang_CXX03);
5709
5710 ASTImporterLookupTable LT(*ToTU);
5711 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
5712 ToTU, functionDecl(hasOverloadedOperatorName(Name: "+")));
5713 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
5714 ToTU, functionDecl(hasOverloadedOperatorName(Name: "-")));
5715 DeclarationName NamePlus = FPlus->getDeclName();
5716 auto ResPlus = LT.lookup(ToTU, NamePlus);
5717 EXPECT_EQ(ResPlus.size(), 1u);
5718 EXPECT_EQ(ResPlus.count(FPlus), 1u);
5719 EXPECT_EQ(ResPlus.count(FMinus), 0u);
5720 DeclarationName NameMinus = FMinus->getDeclName();
5721 auto ResMinus = LT.lookup(ToTU, NameMinus);
5722 EXPECT_EQ(ResMinus.size(), 1u);
5723 EXPECT_EQ(ResMinus.count(FMinus), 1u);
5724 EXPECT_EQ(ResMinus.count(FPlus), 0u);
5725 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
5726}
5727
5728TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
5729 TranslationUnitDecl *ToTU = getToTuDecl(
5730 ToSrcCode: R"(
5731 struct X {};
5732 void operator+(X, X);
5733 )",
5734 ToLang: Lang_CXX03);
5735 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
5736 ToTU, functionDecl(hasOverloadedOperatorName(Name: "+")));
5737
5738 Decl *FromTU = getTuDecl(
5739 SrcCode: R"(
5740 struct X {};
5741 void operator+(X, X);
5742 )",
5743 Lang: Lang_CXX03);
5744 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
5745 D: FromTU, AMatcher: functionDecl(hasOverloadedOperatorName(Name: "+")));
5746
5747 // FromPlus have a different TU, thus its DeclarationName is different too.
5748 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
5749
5750 ASTImporterLookupTable LT(*ToTU);
5751 auto Res = LT.lookup(DC: ToTU, Name: ToPlus->getDeclName());
5752 ASSERT_EQ(Res.size(), 1u);
5753 EXPECT_EQ(*Res.begin(), ToPlus);
5754
5755 // FromPlus have a different TU, thus its DeclarationName is different too.
5756 Res = LT.lookup(DC: ToTU, Name: FromPlus->getDeclName());
5757 ASSERT_EQ(Res.size(), 0u);
5758}
5759
5760TEST_P(ASTImporterLookupTableTest,
5761 LookupFindsFwdFriendClassDeclWithElaboratedType) {
5762 TranslationUnitDecl *ToTU = getToTuDecl(
5763 ToSrcCode: R"(
5764 class Y { friend class F; };
5765 )",
5766 ToLang: Lang_CXX03);
5767
5768 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
5769 // So we must dig up the underlying CXXRecordDecl.
5770 ASTImporterLookupTable LT(*ToTU);
5771 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5772 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
5773 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
5774 ToTU, cxxRecordDecl(hasName(Name: "Y")));
5775
5776 DeclarationName Name = RD->getDeclName();
5777 auto Res = LT.lookup(ToTU, Name);
5778 EXPECT_EQ(Res.size(), 1u);
5779 EXPECT_EQ(*Res.begin(), RD);
5780
5781 Res = LT.lookup(DC: Y, Name);
5782 EXPECT_EQ(Res.size(), 0u);
5783}
5784
5785TEST_P(ASTImporterLookupTableTest,
5786 LookupFindsFwdFriendClassDeclWithUnelaboratedType) {
5787 TranslationUnitDecl *ToTU = getToTuDecl(
5788 ToSrcCode: R"(
5789 class F;
5790 class Y { friend F; };
5791 )",
5792 ToLang: Lang_CXX11);
5793
5794 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
5795 // So we must dig up the underlying CXXRecordDecl.
5796 ASTImporterLookupTable LT(*ToTU);
5797 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
5798 const RecordDecl *RD = getRecordDeclOfFriend(FriendD);
5799 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(ToTU, cxxRecordDecl(hasName(Name: "Y")));
5800
5801 DeclarationName Name = RD->getDeclName();
5802 auto Res = LT.lookup(ToTU, Name);
5803 EXPECT_EQ(Res.size(), 1u);
5804 EXPECT_EQ(*Res.begin(), RD);
5805
5806 Res = LT.lookup(DC: Y, Name);
5807 EXPECT_EQ(Res.size(), 0u);
5808}
5809
5810TEST_P(ASTImporterLookupTableTest,
5811 LookupFindsFriendClassDeclWithTypeAliasDoesNotAssert) {
5812 TranslationUnitDecl *ToTU = getToTuDecl(
5813 ToSrcCode: R"(
5814 class F;
5815 using alias_of_f = F;
5816 class Y { friend alias_of_f; };
5817 )",
5818 ToLang: Lang_CXX11);
5819
5820 // ASTImporterLookupTable constructor handles using declarations correctly,
5821 // no assert is expected.
5822 ASTImporterLookupTable LT(*ToTU);
5823
5824 auto *Alias = FirstDeclMatcher<TypeAliasDecl>().match(
5825 ToTU, typeAliasDecl(hasName(Name: "alias_of_f")));
5826 DeclarationName Name = Alias->getDeclName();
5827 auto Res = LT.lookup(ToTU, Name);
5828 EXPECT_EQ(Res.count(Alias), 1u);
5829}
5830
5831TEST_P(ASTImporterLookupTableTest,
5832 LookupFindsFriendClassDeclWithUsingTypeDoesNotAssert) {
5833 TranslationUnitDecl *ToTU = getToTuDecl(
5834 ToSrcCode: R"(
5835 namespace a {
5836 namespace b { class InnerClass; }
5837 using b::InnerClass;
5838 }
5839 class B {
5840 friend a::InnerClass;
5841 };
5842 )",
5843 ToLang: Lang_CXX11);
5844
5845 // ASTImporterLookupTable constructor handles friend with using-type without
5846 // asserts.
5847 ASTImporterLookupTable LT(*ToTU);
5848
5849 auto *Using = FirstDeclMatcher<UsingDecl>().match(
5850 ToTU, usingDecl(hasName(Name: "InnerClass")));
5851 DeclarationName Name = Using->getDeclName();
5852 auto Res = LT.lookup(ToTU, Name);
5853 EXPECT_EQ(Res.size(), 0u);
5854 auto *NsA = FirstDeclMatcher<NamespaceDecl>().match(
5855 ToTU, namespaceDecl(hasName(Name: "a")));
5856 auto *RecordB = FirstDeclMatcher<CXXRecordDecl>().match(
5857 ToTU, cxxRecordDecl(hasName(Name: "B")));
5858 auto Res1 = LT.lookup(DC: NsA, Name);
5859 EXPECT_EQ(Res1.count(Using), 1u);
5860 auto Res2 = LT.lookup(DC: RecordB, Name);
5861 EXPECT_EQ(Res2.size(), 0u);
5862}
5863
5864TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
5865 TranslationUnitDecl *ToTU = getToTuDecl(
5866 ToSrcCode: R"(
5867 class Y { template <class T> friend class F; };
5868 )",
5869 ToLang: Lang_CXX03);
5870
5871 ASTImporterLookupTable LT(*ToTU);
5872 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5873 ToTU, classTemplateDecl(hasName(Name: "F")));
5874 DeclarationName Name = F->getDeclName();
5875 auto Res = LT.lookup(ToTU, Name);
5876 EXPECT_EQ(Res.size(), 2u);
5877 EXPECT_EQ(Res.count(F), 1u);
5878 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5879}
5880
5881TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
5882 TranslationUnitDecl *ToTU = getToTuDecl(
5883 ToSrcCode: R"(
5884 template <typename T>
5885 class F;
5886
5887 template <typename T>
5888 class Y {
5889 friend class F<T>;
5890 };
5891 )",
5892 ToLang: Lang_CXX03);
5893
5894 ASTImporterLookupTable LT(*ToTU);
5895 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5896 ToTU, classTemplateDecl(hasName(Name: "F")));
5897 DeclarationName Name = F->getDeclName();
5898 auto Res = LT.lookup(ToTU, Name);
5899 EXPECT_EQ(Res.size(), 2u);
5900 EXPECT_EQ(Res.count(F), 1u);
5901 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5902}
5903
5904TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
5905 TranslationUnitDecl *ToTU = getToTuDecl(
5906 ToSrcCode: R"(
5907 template <typename T>
5908 class F;
5909
5910 class Y {
5911 friend class F<int>;
5912 };
5913 )",
5914 ToLang: Lang_CXX03);
5915
5916 ASTImporterLookupTable LT(*ToTU);
5917 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5918 ToTU, classTemplateDecl(hasName(Name: "F")));
5919 DeclarationName Name = F->getDeclName();
5920 auto Res = LT.lookup(ToTU, Name);
5921 ASSERT_EQ(Res.size(), 3u);
5922 EXPECT_EQ(Res.count(F), 1u);
5923 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5924 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
5925}
5926
5927TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
5928 TranslationUnitDecl *ToTU = getToTuDecl(
5929 ToSrcCode: R"(
5930 class Y { friend void F(); };
5931 )",
5932 ToLang: Lang_CXX03);
5933
5934 ASTImporterLookupTable LT(*ToTU);
5935 auto *F =
5936 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName(Name: "F")));
5937 DeclarationName Name = F->getDeclName();
5938 auto Res = LT.lookup(ToTU, Name);
5939 EXPECT_EQ(Res.size(), 1u);
5940 EXPECT_EQ(*Res.begin(), F);
5941}
5942
5943TEST_P(ASTImporterLookupTableTest,
5944 LookupFindsDeclsInClassTemplateSpecialization) {
5945 TranslationUnitDecl *ToTU = getToTuDecl(
5946 ToSrcCode: R"(
5947 template <typename T>
5948 struct X {
5949 int F;
5950 };
5951 void foo() {
5952 X<char> xc;
5953 }
5954 )",
5955 ToLang: Lang_CXX03);
5956
5957 ASTImporterLookupTable LT(*ToTU);
5958
5959 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
5960 ToTU, classTemplateDecl(hasName(Name: "X")));
5961 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
5962 ToTU,
5963 fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
5964
5965 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
5966 ToTU, classTemplateSpecializationDecl(hasName(Name: "X")));
5967 FieldDecl *FieldInSpec = *Spec->field_begin();
5968 ASSERT_TRUE(FieldInSpec);
5969
5970 DeclarationName Name = FieldInSpec->getDeclName();
5971 auto TemplateDC = cast<DeclContext>(Template->getTemplatedDecl());
5972
5973 SmallVector<NamedDecl *, 2> FoundDecls;
5974 TemplateDC->getRedeclContext()->localUncachedLookup(Name, FoundDecls);
5975 EXPECT_EQ(FoundDecls.size(), 1u);
5976 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
5977
5978 auto Res = LT.lookup(DC: TemplateDC, Name);
5979 ASSERT_EQ(Res.size(), 1u);
5980 EXPECT_EQ(*Res.begin(), FieldInTemplate);
5981
5982 cast<DeclContext>(Spec)->getRedeclContext()->localUncachedLookup(Name,
5983 FoundDecls);
5984 EXPECT_EQ(FoundDecls.size(), 1u);
5985 EXPECT_EQ(FoundDecls[0], FieldInSpec);
5986
5987 Res = LT.lookup(DC: cast<DeclContext>(Spec), Name);
5988 ASSERT_EQ(Res.size(), 1u);
5989 EXPECT_EQ(*Res.begin(), FieldInSpec);
5990}
5991
5992TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
5993 TranslationUnitDecl *ToTU = getToTuDecl(
5994 ToSrcCode: R"(
5995 class Y { template <class T> friend void F(); };
5996 )",
5997 ToLang: Lang_CXX03);
5998
5999 ASTImporterLookupTable LT(*ToTU);
6000 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
6001 ToTU, functionTemplateDecl(hasName(Name: "F")));
6002 DeclarationName Name = F->getDeclName();
6003 auto Res = LT.lookup(ToTU, Name);
6004 EXPECT_EQ(Res.size(), 2u);
6005 EXPECT_EQ(Res.count(F), 1u);
6006 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
6007}
6008
6009TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
6010 TranslationUnitDecl *ToTU = getToTuDecl(
6011 ToSrcCode: R"(
6012 struct X;
6013 struct A {
6014 friend struct X;
6015 };
6016 struct B {
6017 friend struct X;
6018 };
6019 )",
6020 ToLang: Lang_CXX03);
6021
6022 ASTImporterLookupTable LT(*ToTU);
6023 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
6024 ToTU, cxxRecordDecl(hasName(Name: "X")));
6025 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
6026 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(ToTU, friendDecl());
6027 const RecordDecl *RD0 = getRecordDeclOfFriend(FriendD0);
6028 const RecordDecl *RD1 = getRecordDeclOfFriend(FriendD1);
6029 ASSERT_EQ(RD0, RD1);
6030 ASSERT_EQ(RD1, X);
6031
6032 DeclarationName Name = X->getDeclName();
6033 auto Res = LT.lookup(ToTU, Name);
6034 EXPECT_EQ(Res.size(), 1u);
6035 EXPECT_EQ(*Res.begin(), X);
6036}
6037
6038TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
6039 TranslationUnitDecl *ToTU = getToTuDecl(
6040 ToSrcCode: R"(
6041 enum E {
6042 A,
6043 B
6044 };
6045 )",
6046 ToLang: Lang_C99);
6047
6048 ASTImporterLookupTable LT(*ToTU);
6049 auto *E = FirstDeclMatcher<EnumDecl>().match(ToTU, enumDecl(hasName(Name: "E")));
6050 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
6051 ToTU, enumConstantDecl(hasName(Name: "A")));
6052
6053 DeclarationName Name = A->getDeclName();
6054 // Redecl context is the TU.
6055 ASSERT_EQ(E->getRedeclContext(), ToTU);
6056
6057 SmallVector<NamedDecl *, 2> FoundDecls;
6058 // Normal lookup finds in the DC.
6059 E->localUncachedLookup(Name, FoundDecls);
6060 EXPECT_EQ(FoundDecls.size(), 1u);
6061
6062 // Normal lookup finds in the Redecl context.
6063 ToTU->localUncachedLookup(Name, FoundDecls);
6064 EXPECT_EQ(FoundDecls.size(), 1u);
6065
6066 // Import specific lookup finds in the DC.
6067 auto Res = LT.lookup(DC: E, Name);
6068 ASSERT_EQ(Res.size(), 1u);
6069 EXPECT_EQ(*Res.begin(), A);
6070
6071 // Import specific lookup finds in the Redecl context.
6072 Res = LT.lookup(ToTU, Name);
6073 ASSERT_EQ(Res.size(), 1u);
6074 EXPECT_EQ(*Res.begin(), A);
6075}
6076
6077TEST_P(ASTImporterLookupTableTest, LookupSearchesInActualNamespaceOnly) {
6078 TranslationUnitDecl *ToTU = getToTuDecl(
6079 ToSrcCode: R"(
6080 namespace N {
6081 int A;
6082 }
6083 namespace N {
6084 }
6085 )",
6086 ToLang: Lang_CXX03);
6087 auto *N1 = FirstDeclMatcher<NamespaceDecl>().match(
6088 ToTU, namespaceDecl(hasName(Name: "N")));
6089 auto *N2 =
6090 LastDeclMatcher<NamespaceDecl>().match(ToTU, namespaceDecl(hasName(Name: "N")));
6091 auto *A = FirstDeclMatcher<VarDecl>().match(ToTU, varDecl(hasName(Name: "A")));
6092 DeclarationName Name = A->getDeclName();
6093
6094 ASTImporterLookupTable LT(*ToTU);
6095 auto Res = LT.lookup(DC: N1, Name);
6096 ASSERT_EQ(Res.size(), 1u);
6097 EXPECT_EQ(*Res.begin(), A);
6098 EXPECT_TRUE(LT.lookup(N2, Name).empty());
6099}
6100
6101TEST_P(ASTImporterOptionSpecificTestBase,
6102 RedeclChainShouldBeCorrectAmongstNamespaces) {
6103 Decl *FromTU = getTuDecl(
6104 SrcCode: R"(
6105 namespace NS {
6106 struct X;
6107 struct Y {
6108 static const int I = 3;
6109 };
6110 }
6111 namespace NS {
6112 struct X { // <--- To be imported
6113 void method(int i = Y::I) {}
6114 int f;
6115 };
6116 }
6117 )",
6118 Lang: Lang_CXX03);
6119 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
6120 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X"), unless(isImplicit())));
6121 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
6122 D: FromTU,
6123 AMatcher: cxxRecordDecl(hasName(Name: "X"), isDefinition(), unless(isImplicit())));
6124 ASSERT_NE(FromFwd, FromDef);
6125 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
6126 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
6127 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
6128
6129 auto *ToDef = cast_or_null<CXXRecordDecl>(Import(FromDef, Lang_CXX03));
6130 auto *ToFwd = cast_or_null<CXXRecordDecl>(Import(FromFwd, Lang_CXX03));
6131 EXPECT_NE(ToFwd, ToDef);
6132 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
6133 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
6134 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
6135 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
6136 // We expect no (ODR) warning during the import.
6137 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
6138}
6139
6140struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
6141
6142TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
6143 Decl *ToTU = getToTuDecl(
6144 ToSrcCode: R"(
6145 class X {
6146 template <typename T> friend void foo();
6147 };
6148 )",
6149 ToLang: Lang_CXX03);
6150 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
6151 D: ToTU, AMatcher: functionTemplateDecl(hasName(Name: "foo")));
6152
6153 Decl *FromTU = getTuDecl(
6154 SrcCode: R"(
6155 template <typename T> void foo();
6156 )",
6157 Lang: Lang_CXX03);
6158 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
6159 D: FromTU, AMatcher: functionTemplateDecl(hasName(Name: "foo")));
6160 auto *Imported = Import(FromFoo, Lang_CXX03);
6161
6162 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
6163}
6164
6165TEST_P(ImportFriendFunctionTemplates, ImportFriendFunctionInsideClassTemplate) {
6166 Decl *From, *To;
6167 std::tie(args&: From, args&: To) = getImportedDecl(
6168 FromSrcCode: R"(
6169 template <typename T> struct X {
6170 template <typename U> friend void f();
6171 };
6172 )",
6173 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03, Identifier: "X");
6174
6175 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(D: From, AMatcher: friendDecl());
6176 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(D: To, AMatcher: friendDecl());
6177
6178 EXPECT_TRUE(FromFriend ==
6179 LastDeclMatcher<FriendDecl>().match(From, friendDecl()));
6180 EXPECT_TRUE(ToFriend ==
6181 LastDeclMatcher<FriendDecl>().match(To, friendDecl()));
6182
6183 auto *FromDecl = FromFriend->getFriendDecl();
6184 auto *FromDC = FromFriend->getDeclContext();
6185 auto *FromLexicalDC = FromFriend->getLexicalDeclContext();
6186
6187 EXPECT_TRUE(FromDC->containsDecl(FromFriend));
6188 EXPECT_FALSE(FromDC->containsDecl(FromDecl));
6189 EXPECT_TRUE(FromLexicalDC->containsDecl(FromFriend));
6190 EXPECT_FALSE(FromLexicalDC->containsDecl(FromDecl));
6191
6192 auto *ToDecl = ToFriend->getFriendDecl();
6193 auto *ToDC = ToFriend->getDeclContext();
6194 auto *ToLexicalDC = ToFriend->getLexicalDeclContext();
6195
6196 EXPECT_TRUE(ToDC->containsDecl(ToFriend));
6197 EXPECT_FALSE(ToDC->containsDecl(ToDecl));
6198 EXPECT_TRUE(ToLexicalDC->containsDecl(ToFriend));
6199 EXPECT_FALSE(ToLexicalDC->containsDecl(ToDecl));
6200}
6201
6202struct ASTImporterWithFakeErrors : ASTImporter {
6203 using ASTImporter::ASTImporter;
6204 bool returnWithErrorInTest() override { return true; }
6205};
6206
6207struct ErrorHandlingTest : ASTImporterOptionSpecificTestBase {
6208 ErrorHandlingTest() {
6209 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
6210 ASTContext &FromContext, FileManager &FromFileManager,
6211 bool MinimalImport,
6212 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
6213 return new ASTImporterWithFakeErrors(ToContext, ToFileManager,
6214 FromContext, FromFileManager,
6215 MinimalImport, SharedState);
6216 };
6217 }
6218 // In this test we purposely report an error (UnsupportedConstruct) when
6219 // importing the below stmt.
6220 static constexpr auto* ErroneousStmt = R"( asm(""); )";
6221};
6222
6223// Check a case when no new AST node is created in the AST before encountering
6224// the error.
6225TEST_P(ErrorHandlingTest, ErrorHappensBeforeCreatingANewNode) {
6226 TranslationUnitDecl *ToTU = getToTuDecl(
6227 ToSrcCode: R"(
6228 template <typename T>
6229 class X {};
6230 template <>
6231 class X<int> { int a; };
6232 )",
6233 ToLang: Lang_CXX03);
6234 TranslationUnitDecl *FromTU = getTuDecl(
6235 SrcCode: R"(
6236 template <typename T>
6237 class X {};
6238 template <>
6239 class X<int> { double b; };
6240 )",
6241 Lang: Lang_CXX03);
6242 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
6243 FromTU, classTemplateSpecializationDecl(hasName(Name: "X")));
6244 ClassTemplateSpecializationDecl *ImportedSpec = Import(FromSpec, Lang_CXX03);
6245 EXPECT_FALSE(ImportedSpec);
6246
6247 // The original Decl is kept, no new decl is created.
6248 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(
6249 ToTU, classTemplateSpecializationDecl(hasName("X"))),
6250 1u);
6251
6252 // But an error is set to the counterpart in the "from" context.
6253 ASTImporter *Importer = findFromTU(From: FromSpec)->Importer.get();
6254 std::optional<ASTImportError> OptErr =
6255 Importer->getImportDeclErrorIfAny(FromD: FromSpec);
6256 ASSERT_TRUE(OptErr);
6257 EXPECT_EQ(OptErr->Error, ASTImportError::NameConflict);
6258}
6259
6260// Check a case when a new AST node is created but not linked to the AST before
6261// encountering the error.
6262TEST_P(ErrorHandlingTest,
6263 ErrorHappensAfterCreatingTheNodeButBeforeLinkingThatToTheAST) {
6264 TranslationUnitDecl *FromTU = getTuDecl(
6265 SrcCode: std::string("void foo() { ") + ErroneousStmt + " }", Lang: Lang_CXX03);
6266 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
6267 FromTU, functionDecl(hasName(Name: "foo")));
6268
6269 FunctionDecl *ImportedFoo = Import(FromFoo, Lang_CXX03);
6270 EXPECT_FALSE(ImportedFoo);
6271
6272 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
6273 // Created, but not linked.
6274 EXPECT_EQ(
6275 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("foo"))),
6276 0u);
6277
6278 ASTImporter *Importer = findFromTU(From: FromFoo)->Importer.get();
6279 std::optional<ASTImportError> OptErr =
6280 Importer->getImportDeclErrorIfAny(FromD: FromFoo);
6281 ASSERT_TRUE(OptErr);
6282 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6283}
6284
6285// Check a case when a new AST node is created and linked to the AST before
6286// encountering the error. The error is set for the counterpart of the nodes in
6287// the "from" context.
6288TEST_P(ErrorHandlingTest, ErrorHappensAfterNodeIsCreatedAndLinked) {
6289 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: std::string(R"(
6290 void f();
6291 void f() { )") + ErroneousStmt + R"( }
6292 )",
6293 Lang: Lang_CXX03);
6294 auto *FromProto = FirstDeclMatcher<FunctionDecl>().match(
6295 FromTU, functionDecl(hasName(Name: "f")));
6296 auto *FromDef =
6297 LastDeclMatcher<FunctionDecl>().match(FromTU, functionDecl(hasName(Name: "f")));
6298 FunctionDecl *ImportedProto = Import(FromProto, Lang_CXX03);
6299 EXPECT_FALSE(ImportedProto); // Could not import.
6300 // However, we created two nodes in the AST. 1) the fwd decl 2) the
6301 // definition. The definition is not added to its DC, but the fwd decl is
6302 // there.
6303 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
6304 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
6305 1u);
6306 // Match the fwd decl.
6307 auto *ToProto =
6308 FirstDeclMatcher<FunctionDecl>().match(ToTU, functionDecl(hasName(Name: "f")));
6309 EXPECT_TRUE(ToProto);
6310 // An error is set to the counterpart in the "from" context both for the fwd
6311 // decl and the definition.
6312 ASTImporter *Importer = findFromTU(From: FromProto)->Importer.get();
6313 std::optional<ASTImportError> OptErr =
6314 Importer->getImportDeclErrorIfAny(FromD: FromProto);
6315 ASSERT_TRUE(OptErr);
6316 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6317 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromDef);
6318 ASSERT_TRUE(OptErr);
6319 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6320}
6321
6322// An error should be set for a class if we cannot import one member.
6323TEST_P(ErrorHandlingTest, ErrorIsPropagatedFromMemberToClass) {
6324 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: std::string(R"(
6325 class X {
6326 void f() { )") + ErroneousStmt + R"( } // This member has the error
6327 // during import.
6328 void ok(); // The error should not prevent importing this.
6329 }; // An error will be set for X too.
6330 )",
6331 Lang: Lang_CXX03);
6332 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
6333 FromTU, cxxRecordDecl(hasName(Name: "X")));
6334 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX03);
6335
6336 // An error is set for X.
6337 EXPECT_FALSE(ImportedX);
6338 ASTImporter *Importer = findFromTU(From: FromX)->Importer.get();
6339 std::optional<ASTImportError> OptErr =
6340 Importer->getImportDeclErrorIfAny(FromD: FromX);
6341 ASSERT_TRUE(OptErr);
6342 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6343
6344 // An error is set for f().
6345 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
6346 FromTU, cxxMethodDecl(hasName(Name: "f")));
6347 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromF);
6348 ASSERT_TRUE(OptErr);
6349 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6350 // And any subsequent import should fail.
6351 CXXMethodDecl *ImportedF = Import(FromF, Lang_CXX03);
6352 EXPECT_FALSE(ImportedF);
6353
6354 // There is an error set for the other member too.
6355 auto *FromOK = FirstDeclMatcher<CXXMethodDecl>().match(
6356 FromTU, cxxMethodDecl(hasName(Name: "ok")));
6357 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromOK);
6358 EXPECT_TRUE(OptErr);
6359 // Cannot import the other member.
6360 CXXMethodDecl *ImportedOK = Import(FromOK, Lang_CXX03);
6361 EXPECT_FALSE(ImportedOK);
6362}
6363
6364// Check that an error propagates to the dependent AST nodes.
6365// In the below code it means that an error in X should propagate to A.
6366// And even to F since the containing A is erroneous.
6367// And to all AST nodes which we visit during the import process which finally
6368// ends up in a failure (in the error() function).
6369TEST_P(ErrorHandlingTest, ErrorPropagatesThroughImportCycles) {
6370 Decl *FromTU = getTuDecl(SrcCode: std::string(R"(
6371 namespace NS {
6372 class A {
6373 template <int I> class F {};
6374 class X {
6375 template <int I> friend class F;
6376 void error() { )") +
6377 ErroneousStmt + R"( }
6378 };
6379 };
6380
6381 class B {};
6382 } // NS
6383 )",
6384 Lang: Lang_CXX03, FileName: "input0.cc");
6385
6386 auto *FromFRD = FirstDeclMatcher<CXXRecordDecl>().match(
6387 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "F"), isDefinition()));
6388 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
6389 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A"), isDefinition()));
6390 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(
6391 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "B"), isDefinition()));
6392 auto *FromNS = FirstDeclMatcher<NamespaceDecl>().match(
6393 D: FromTU, AMatcher: namespaceDecl(hasName(Name: "NS")));
6394
6395 // Start by importing the templated CXXRecordDecl of F.
6396 // Import fails for that.
6397 EXPECT_FALSE(Import(FromFRD, Lang_CXX03));
6398 // Import fails for A.
6399 EXPECT_FALSE(Import(FromA, Lang_CXX03));
6400 // But we should be able to import the independent B.
6401 EXPECT_TRUE(Import(FromB, Lang_CXX03));
6402 // And the namespace.
6403 EXPECT_TRUE(Import(FromNS, Lang_CXX03));
6404
6405 // An error is set to the templated CXXRecordDecl of F.
6406 ASTImporter *Importer = findFromTU(From: FromFRD)->Importer.get();
6407 std::optional<ASTImportError> OptErr =
6408 Importer->getImportDeclErrorIfAny(FromD: FromFRD);
6409 EXPECT_TRUE(OptErr);
6410
6411 // An error is set to A.
6412 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromA);
6413 EXPECT_TRUE(OptErr);
6414
6415 // There is no error set to B.
6416 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromB);
6417 EXPECT_FALSE(OptErr);
6418
6419 // There is no error set to NS.
6420 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromNS);
6421 EXPECT_FALSE(OptErr);
6422
6423 // Check some of those decls whose ancestor is X, they all should have an
6424 // error set if we visited them during an import process which finally failed.
6425 // These decls are part of a cycle in an ImportPath.
6426 // There would not be any error set for these decls if we hadn't follow the
6427 // ImportPaths and the cycles.
6428 OptErr = Importer->getImportDeclErrorIfAny(
6429 FirstDeclMatcher<ClassTemplateDecl>().match(
6430 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "F"))));
6431 // An error is set to the 'F' ClassTemplateDecl.
6432 EXPECT_TRUE(OptErr);
6433 // An error is set to the FriendDecl.
6434 OptErr = Importer->getImportDeclErrorIfAny(
6435 FirstDeclMatcher<FriendDecl>().match(
6436 D: FromTU, AMatcher: friendDecl()));
6437 EXPECT_TRUE(OptErr);
6438 // An error is set to the implicit class of A.
6439 OptErr =
6440 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
6441 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A"), isImplicit())));
6442 EXPECT_TRUE(OptErr);
6443 // An error is set to the implicit class of X.
6444 OptErr =
6445 Importer->getImportDeclErrorIfAny(FirstDeclMatcher<CXXRecordDecl>().match(
6446 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X"), isImplicit())));
6447 EXPECT_TRUE(OptErr);
6448}
6449
6450TEST_P(ErrorHandlingTest, ErrorIsNotPropagatedFromMemberToNamespace) {
6451 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: std::string(R"(
6452 namespace X {
6453 void f() { )") + ErroneousStmt + R"( } // This member has the error
6454 // during import.
6455 void ok(); // The error should not prevent importing this.
6456 }; // An error will be set for X too.
6457 )",
6458 Lang: Lang_CXX03);
6459 auto *FromX = FirstDeclMatcher<NamespaceDecl>().match(
6460 FromTU, namespaceDecl(hasName(Name: "X")));
6461 NamespaceDecl *ImportedX = Import(FromX, Lang_CXX03);
6462
6463 // There is no error set for X.
6464 EXPECT_TRUE(ImportedX);
6465 ASTImporter *Importer = findFromTU(From: FromX)->Importer.get();
6466 std::optional<ASTImportError> OptErr =
6467 Importer->getImportDeclErrorIfAny(FromD: FromX);
6468 ASSERT_FALSE(OptErr);
6469
6470 // An error is set for f().
6471 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
6472 FromTU, functionDecl(hasName(Name: "f")));
6473 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromF);
6474 ASSERT_TRUE(OptErr);
6475 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6476 // And any subsequent import should fail.
6477 FunctionDecl *ImportedF = Import(FromF, Lang_CXX03);
6478 EXPECT_FALSE(ImportedF);
6479
6480 // There is no error set for ok().
6481 auto *FromOK = FirstDeclMatcher<FunctionDecl>().match(
6482 FromTU, functionDecl(hasName(Name: "ok")));
6483 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromOK);
6484 EXPECT_FALSE(OptErr);
6485 // And we should be able to import.
6486 FunctionDecl *ImportedOK = Import(FromOK, Lang_CXX03);
6487 EXPECT_TRUE(ImportedOK);
6488}
6489
6490TEST_P(ErrorHandlingTest, ODRViolationWithinTypedefDecls) {
6491 // Importing `z` should fail - instead of crashing - due to an ODR violation.
6492 // The `bar::e` typedef sets it's DeclContext after the import is done.
6493 // However, if the importation fails, it will be left as a nullptr.
6494 // During the cleanup of the failed import, we should check whether the
6495 // DeclContext is null or not - instead of dereferencing that unconditionally.
6496 constexpr auto ToTUCode = R"(
6497 namespace X {
6498 struct bar {
6499 int odr_violation;
6500 };
6501 })";
6502 constexpr auto FromTUCode = R"(
6503 namespace X {
6504 enum b {};
6505 struct bar {
6506 typedef b e;
6507 static e d;
6508 };
6509 }
6510 int z = X::bar::d;
6511 )";
6512 Decl *ToTU = getToTuDecl(ToSrcCode: ToTUCode, ToLang: Lang_CXX11);
6513 static_cast<void>(ToTU);
6514 Decl *FromTU = getTuDecl(SrcCode: FromTUCode, Lang: Lang_CXX11);
6515 auto *FromZ =
6516 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "z")));
6517 ASSERT_TRUE(FromZ);
6518 ASSERT_TRUE(FromZ->hasInit());
6519
6520 auto *ImportedZ = Import(FromZ, Lang_CXX11);
6521 EXPECT_FALSE(ImportedZ);
6522}
6523
6524// An error should be set for a class if it had a previous import with an error
6525// from another TU.
6526TEST_P(ErrorHandlingTest,
6527 ImportedDeclWithErrorShouldFailTheImportOfDeclWhichMapToIt) {
6528 // We already have a fwd decl.
6529 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: "class X;", ToLang: Lang_CXX03);
6530 // Then we import a definition.
6531 {
6532 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: std::string(R"(
6533 class X {
6534 void f() { )") + ErroneousStmt + R"( }
6535 void ok();
6536 };
6537 )",
6538 Lang: Lang_CXX03);
6539 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
6540 FromTU, cxxRecordDecl(hasName(Name: "X")));
6541 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX03);
6542
6543 // An error is set for X ...
6544 EXPECT_FALSE(ImportedX);
6545 ASTImporter *Importer = findFromTU(From: FromX)->Importer.get();
6546 std::optional<ASTImportError> OptErr =
6547 Importer->getImportDeclErrorIfAny(FromD: FromX);
6548 ASSERT_TRUE(OptErr);
6549 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6550 }
6551 // ... but the node had been created.
6552 auto *ToXDef = FirstDeclMatcher<CXXRecordDecl>().match(
6553 ToTU, cxxRecordDecl(hasName(Name: "X"), isDefinition()));
6554 // An error is set for "ToXDef" in the shared state.
6555 std::optional<ASTImportError> OptErr =
6556 SharedStatePtr->getImportDeclErrorIfAny(ToD: ToXDef);
6557 ASSERT_TRUE(OptErr);
6558 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6559
6560 auto *ToXFwd = FirstDeclMatcher<CXXRecordDecl>().match(
6561 ToTU, cxxRecordDecl(hasName(Name: "X"), unless(isDefinition())));
6562 // An error is NOT set for the fwd Decl of X in the shared state.
6563 OptErr = SharedStatePtr->getImportDeclErrorIfAny(ToD: ToXFwd);
6564 ASSERT_FALSE(OptErr);
6565
6566 // Try to import X again but from another TU.
6567 {
6568 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: std::string(R"(
6569 class X {
6570 void f() { )") + ErroneousStmt + R"( }
6571 void ok();
6572 };
6573 )",
6574 Lang: Lang_CXX03, FileName: "input1.cc");
6575
6576 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
6577 FromTU, cxxRecordDecl(hasName(Name: "X")));
6578 CXXRecordDecl *ImportedX = Import(FromX, Lang_CXX03);
6579
6580 // If we did not save the errors for the "to" context then the below checks
6581 // would fail, because the lookup finds the fwd Decl of the existing
6582 // definition in the "to" context. We can reach the existing definition via
6583 // the found fwd Decl. That existing definition is structurally equivalent
6584 // (we check only the fields) with this one we want to import, so we return
6585 // with the existing definition, which is erroneous (one method is missing).
6586
6587 // The import should fail.
6588 EXPECT_FALSE(ImportedX);
6589 ASTImporter *Importer = findFromTU(From: FromX)->Importer.get();
6590 std::optional<ASTImportError> OptErr =
6591 Importer->getImportDeclErrorIfAny(FromD: FromX);
6592 // And an error is set for this new X in the "from" ctx.
6593 ASSERT_TRUE(OptErr);
6594 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6595 }
6596}
6597
6598TEST_P(ErrorHandlingTest, ImportOfOverriddenMethods) {
6599 auto MatchFooA =
6600 functionDecl(hasName(Name: "foo"), hasAncestor(cxxRecordDecl(hasName(Name: "A"))));
6601 auto MatchFooB =
6602 functionDecl(hasName(Name: "foo"), hasAncestor(cxxRecordDecl(hasName(Name: "B"))));
6603 auto MatchFooC =
6604 functionDecl(hasName(Name: "foo"), hasAncestor(cxxRecordDecl(hasName(Name: "C"))));
6605
6606 // Provoke import of a method that has overridden methods with import error.
6607 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: std::string(R"(
6608 struct C;
6609 struct A {
6610 virtual void foo();
6611 void f1(C *);
6612 };
6613 void A::foo() {
6614 )") + ErroneousStmt + R"(
6615 }
6616 struct B : public A {
6617 void foo() override;
6618 };
6619 struct C : public B {
6620 void foo() override;
6621 };
6622 )",
6623 Lang: Lang_CXX11);
6624 auto *FromFooA = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooA);
6625 auto *FromFooB = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooB);
6626 auto *FromFooC = FirstDeclMatcher<FunctionDecl>().match(FromTU, MatchFooC);
6627
6628 EXPECT_FALSE(Import(FromFooA, Lang_CXX11));
6629 ASTImporter *Importer = findFromTU(From: FromFooA)->Importer.get();
6630 auto CheckError = [&Importer](Decl *FromD) {
6631 std::optional<ASTImportError> OptErr =
6632 Importer->getImportDeclErrorIfAny(FromD);
6633 ASSERT_TRUE(OptErr);
6634 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6635 };
6636 CheckError(FromFooA);
6637 EXPECT_FALSE(Import(FromFooB, Lang_CXX11));
6638 CheckError(FromFooB);
6639 EXPECT_FALSE(Import(FromFooC, Lang_CXX11));
6640 CheckError(FromFooC);
6641}
6642
6643TEST_P(ErrorHandlingTest, ODRViolationWithinParmVarDecls) {
6644 // Importing of 'f' and parameter 'P' should cause an ODR error.
6645 // The error happens after the ParmVarDecl for 'P' was already created.
6646 // This is a special case because the ParmVarDecl has a temporary DeclContext.
6647 // Expected is no crash at error handling of ASTImporter.
6648 constexpr auto ToTUCode = R"(
6649 struct X {
6650 char A;
6651 };
6652 )";
6653 constexpr auto FromTUCode = R"(
6654 struct X {
6655 enum Y { Z };
6656 };
6657 void f(int P = X::Z);
6658 )";
6659 Decl *ToTU = getToTuDecl(ToSrcCode: ToTUCode, ToLang: Lang_CXX11);
6660 static_cast<void>(ToTU);
6661 Decl *FromTU = getTuDecl(SrcCode: FromTUCode, Lang: Lang_CXX11);
6662 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
6663 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
6664 ASSERT_TRUE(FromF);
6665
6666 auto *ImportedF = Import(FromF, Lang_CXX11);
6667 EXPECT_FALSE(ImportedF);
6668}
6669
6670TEST_P(ErrorHandlingTest, DoNotInheritErrorFromNonDependentChild) {
6671 // Declarations should not inherit an import error from a child object
6672 // if the declaration has no direct dependence to such a child.
6673 // For example a namespace should not get import error if one of the
6674 // declarations inside it fails to import.
6675 // There was a special case in error handling (when "import path circles" are
6676 // encountered) when this property was not held. This case is provoked by the
6677 // following code.
6678 constexpr auto ToTUCode = R"(
6679 namespace ns {
6680 struct Err {
6681 char A;
6682 };
6683 }
6684 )";
6685 constexpr auto FromTUCode = R"(
6686 namespace ns {
6687 struct A {
6688 using U = struct Err;
6689 };
6690 }
6691 namespace ns {
6692 struct Err {}; // ODR violation
6693 void f(A) {}
6694 }
6695 )";
6696
6697 Decl *ToTU = getToTuDecl(ToSrcCode: ToTUCode, ToLang: Lang_CXX11);
6698 static_cast<void>(ToTU);
6699 Decl *FromTU = getTuDecl(SrcCode: FromTUCode, Lang: Lang_CXX11);
6700 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
6701 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A"), hasDefinition()));
6702 ASSERT_TRUE(FromA);
6703 auto *ImportedA = Import(FromA, Lang_CXX11);
6704 // 'A' can not be imported: ODR error at 'Err'
6705 EXPECT_FALSE(ImportedA);
6706 // When import of 'A' failed there was a "saved import path circle" that
6707 // contained namespace 'ns' (A - U - Err - ns - f - A). This should not mean
6708 // that every object in this path fails to import.
6709
6710 Decl *FromNS = FirstDeclMatcher<NamespaceDecl>().match(
6711 D: FromTU, AMatcher: namespaceDecl(hasName(Name: "ns")));
6712 EXPECT_TRUE(FromNS);
6713 auto *ImportedNS = Import(From: FromNS, ToLang: Lang_CXX11);
6714 EXPECT_TRUE(ImportedNS);
6715}
6716
6717TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) {
6718 Decl *FromTU = getTuDecl(
6719 SrcCode: R"(
6720 void f() {
6721 auto L = [](){};
6722 }
6723 )",
6724 Lang: Lang_CXX11, FileName: "input0.cc");
6725 auto Pattern = lambdaExpr();
6726 CXXRecordDecl *FromL =
6727 FirstDeclMatcher<LambdaExpr>().match(D: FromTU, AMatcher: Pattern)->getLambdaClass();
6728
6729 auto ToL = Import(From: FromL, Lang: Lang_CXX11);
6730 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
6731 unsigned FromLSize =
6732 std::distance(FromL->decls().begin(), FromL->decls().end());
6733 EXPECT_NE(ToLSize, 0u);
6734 EXPECT_EQ(ToLSize, FromLSize);
6735 EXPECT_FALSE(FromL->isDependentLambda());
6736}
6737
6738TEST_P(ASTImporterOptionSpecificTestBase,
6739 ReturnTypeDeclaredInsideOfCXX11LambdaWithoutTrailingReturn) {
6740 Decl *From, *To;
6741 std::tie(args&: From, args&: To) = getImportedDecl(
6742 FromSrcCode: R"(
6743 void foo() {
6744 (void) []() {
6745 struct X {};
6746 return X();
6747 };
6748 }
6749 )",
6750 FromLang: Lang_CXX11, ToSrcCode: "", ToLang: Lang_CXX11, Identifier: "foo"); // c++11 only
6751 auto *ToLambda = FirstDeclMatcher<LambdaExpr>().match(D: To, AMatcher: lambdaExpr());
6752 EXPECT_TRUE(ToLambda);
6753}
6754
6755TEST_P(ASTImporterOptionSpecificTestBase,
6756 ReturnTypeDeclaredInsideOfCXX11LambdaWithTrailingReturn) {
6757 Decl *From, *To;
6758 std::tie(args&: From, args&: To) = getImportedDecl(
6759 FromSrcCode: R"(
6760 void foo() {
6761 (void) [] {
6762 struct X {};
6763 return X();
6764 };
6765 }
6766 )",
6767 FromLang: Lang_CXX11, ToSrcCode: "", ToLang: Lang_CXX11, Identifier: "foo"); // c++11 only
6768 auto *ToLambda = FirstDeclMatcher<LambdaExpr>().match(D: To, AMatcher: lambdaExpr());
6769 EXPECT_TRUE(ToLambda);
6770}
6771
6772TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
6773 Decl *FromTU = getTuDecl(
6774 SrcCode: R"(
6775 template <typename F>
6776 void f(F L = [](){}) {}
6777 )",
6778 Lang: Lang_CXX11, FileName: "input0.cc");
6779 auto Pattern = lambdaExpr();
6780 CXXRecordDecl *FromL =
6781 FirstDeclMatcher<LambdaExpr>().match(D: FromTU, AMatcher: Pattern)->getLambdaClass();
6782
6783 auto ToL = Import(From: FromL, Lang: Lang_CXX11);
6784 unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
6785 unsigned FromLSize =
6786 std::distance(FromL->decls().begin(), FromL->decls().end());
6787 EXPECT_NE(ToLSize, 0u);
6788 EXPECT_EQ(ToLSize, FromLSize);
6789 EXPECT_TRUE(FromL->isDependentLambda());
6790}
6791
6792TEST_P(ASTImporterOptionSpecificTestBase, LambdaInGlobalScope) {
6793 Decl *FromTU = getTuDecl(
6794 SrcCode: R"(
6795 auto l1 = [](unsigned lp) { return 1; };
6796 auto l2 = [](int lp) { return 2; };
6797 int f(int p) {
6798 return l1(p) + l2(p);
6799 }
6800 )",
6801 Lang: Lang_CXX11, FileName: "input0.cc");
6802 FunctionDecl *FromF = FirstDeclMatcher<FunctionDecl>().match(
6803 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
6804 FunctionDecl *ToF = Import(From: FromF, Lang: Lang_CXX11);
6805 EXPECT_TRUE(ToF);
6806}
6807
6808TEST_P(ASTImporterOptionSpecificTestBase,
6809 ImportExistingFriendClassTemplateDef) {
6810 auto Code =
6811 R"(
6812 template <class T1, class T2>
6813 struct Base {
6814 template <class U1, class U2>
6815 friend struct Class;
6816 };
6817 template <class T1, class T2>
6818 struct Class { };
6819 )";
6820
6821 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX03);
6822 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input.cc");
6823
6824 auto *ToClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
6825 ToTU, classTemplateDecl(hasName(Name: "Class")));
6826 auto *ToClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
6827 ToTU, classTemplateDecl(hasName(Name: "Class")));
6828 ASSERT_FALSE(ToClassProto->isThisDeclarationADefinition());
6829 ASSERT_TRUE(ToClassDef->isThisDeclarationADefinition());
6830 // Previous friend decl is not linked to it!
6831 ASSERT_FALSE(ToClassDef->getPreviousDecl());
6832 ASSERT_EQ(ToClassDef->getMostRecentDecl(), ToClassDef);
6833 ASSERT_EQ(ToClassProto->getMostRecentDecl(), ToClassProto);
6834
6835 auto *FromClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
6836 FromTU, classTemplateDecl(hasName(Name: "Class")));
6837 auto *FromClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
6838 FromTU, classTemplateDecl(hasName(Name: "Class")));
6839 ASSERT_FALSE(FromClassProto->isThisDeclarationADefinition());
6840 ASSERT_TRUE(FromClassDef->isThisDeclarationADefinition());
6841 ASSERT_FALSE(FromClassDef->getPreviousDecl());
6842 ASSERT_EQ(FromClassDef->getMostRecentDecl(), FromClassDef);
6843 ASSERT_EQ(FromClassProto->getMostRecentDecl(), FromClassProto);
6844
6845 auto *ImportedDef = Import(FromClassDef, Lang_CXX03);
6846 // At import we should find the definition for 'Class' even if the
6847 // prototype (inside 'friend') for it comes first in the AST and is not
6848 // linked to the definition.
6849 EXPECT_EQ(ImportedDef, ToClassDef);
6850}
6851
6852struct LLDBLookupTest : ASTImporterOptionSpecificTestBase {
6853 LLDBLookupTest() {
6854 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
6855 ASTContext &FromContext, FileManager &FromFileManager,
6856 bool MinimalImport,
6857 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
6858 return new ASTImporter(ToContext, ToFileManager, FromContext,
6859 FromFileManager, MinimalImport,
6860 // We use the regular lookup.
6861 /*SharedState=*/nullptr);
6862 };
6863 }
6864};
6865
6866TEST_P(LLDBLookupTest, ImporterShouldFindInTransparentContext) {
6867 TranslationUnitDecl *ToTU = getToTuDecl(
6868 ToSrcCode: R"(
6869 extern "C" {
6870 class X{};
6871 };
6872 )",
6873 ToLang: Lang_CXX03);
6874 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(
6875 ToTU, cxxRecordDecl(hasName(Name: "X")));
6876
6877 // Set up a stub external storage.
6878 ToTU->setHasExternalLexicalStorage(true);
6879 // Set up DeclContextBits.HasLazyExternalLexicalLookups to true.
6880 ToTU->setMustBuildLookupTable();
6881 struct TestExternalASTSource : ExternalASTSource {};
6882 ToTU->getASTContext().setExternalSource(new TestExternalASTSource());
6883
6884 Decl *FromTU = getTuDecl(
6885 SrcCode: R"(
6886 class X;
6887 )",
6888 Lang: Lang_CXX03);
6889 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
6890 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
6891 auto *ImportedX = Import(FromX, Lang_CXX03);
6892 // The lookup must find the existing class definition in the LinkageSpecDecl.
6893 // Then the importer renders the existing and the new decl into one chain.
6894 EXPECT_EQ(ImportedX->getCanonicalDecl(), ToX->getCanonicalDecl());
6895}
6896
6897struct SVEBuiltins : ASTImporterOptionSpecificTestBase {};
6898
6899TEST_P(SVEBuiltins, ImportTypes) {
6900 static const char *const TypeNames[] = {
6901 "__SVInt8_t", "__SVInt16_t", "__SVInt32_t", "__SVInt64_t",
6902 "__SVUint8_t", "__SVUint16_t", "__SVUint32_t", "__SVUint64_t",
6903 "__SVFloat16_t", "__SVBfloat16_t", "__SVFloat32_t", "__SVFloat64_t",
6904 "__SVBool_t"};
6905
6906 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: "", ToLang: Lang_CXX03);
6907 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: "", Lang: Lang_CXX03, FileName: "input.cc");
6908 for (auto *TypeName : TypeNames) {
6909 auto *ToTypedef = FirstDeclMatcher<TypedefDecl>().match(
6910 ToTU, typedefDecl(hasName(Name: TypeName)));
6911 QualType ToType = ToTypedef->getUnderlyingType();
6912
6913 auto *FromTypedef = FirstDeclMatcher<TypedefDecl>().match(
6914 FromTU, typedefDecl(hasName(Name: TypeName)));
6915 QualType FromType = FromTypedef->getUnderlyingType();
6916
6917 QualType ImportedType = ImportType(FromType, TUDecl: FromTypedef, ToLang: Lang_CXX03);
6918 EXPECT_EQ(ImportedType, ToType);
6919 }
6920}
6921
6922TEST_P(ASTImporterOptionSpecificTestBase, ImportOfDefaultImplicitFunctions) {
6923 // Test that import of implicit functions works and the functions
6924 // are merged into one chain.
6925 auto GetDeclToImport = [this](StringRef File) {
6926 Decl *FromTU = getTuDecl(
6927 SrcCode: R"(
6928 struct X { };
6929 // Force generating some implicit operator definitions for X.
6930 void f() { X x1, x2; x1 = x2; X *x3 = new X; delete x3; }
6931 )",
6932 Lang: Lang_CXX11, FileName: File);
6933 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
6934 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X"), unless(isImplicit())));
6935 // Destructor is picked as one example of implicit function.
6936 return FromD->getDestructor();
6937 };
6938
6939 auto *ToD1 = Import(GetDeclToImport("input1.cc"), Lang_CXX11);
6940 ASSERT_TRUE(ToD1);
6941
6942 auto *ToD2 = Import(GetDeclToImport("input2.cc"), Lang_CXX11);
6943 ASSERT_TRUE(ToD2);
6944
6945 EXPECT_EQ(ToD1->getCanonicalDecl(), ToD2->getCanonicalDecl());
6946}
6947
6948TEST_P(ASTImporterOptionSpecificTestBase,
6949 ImportOfExplicitlyDefaultedOrDeleted) {
6950 Decl *FromTU = getTuDecl(
6951 SrcCode: R"(
6952 struct X { X() = default; X(const X&) = delete; };
6953 )",
6954 Lang: Lang_CXX11);
6955 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
6956 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
6957 auto *ImportedX = Import(FromX, Lang_CXX11);
6958 auto *Constr1 = FirstDeclMatcher<CXXConstructorDecl>().match(
6959 ImportedX, cxxConstructorDecl(hasName(Name: "X"), unless(isImplicit())));
6960 auto *Constr2 = LastDeclMatcher<CXXConstructorDecl>().match(
6961 ImportedX, cxxConstructorDecl(hasName(Name: "X"), unless(isImplicit())));
6962
6963 ASSERT_TRUE(ImportedX);
6964 EXPECT_TRUE(Constr1->isDefaulted());
6965 EXPECT_TRUE(Constr1->isExplicitlyDefaulted());
6966 EXPECT_TRUE(Constr2->isDeletedAsWritten());
6967 EXPECT_EQ(ImportedX->isAggregate(), FromX->isAggregate());
6968}
6969
6970INSTANTIATE_TEST_SUITE_P(ParameterizedTests, SVEBuiltins,
6971 ::testing::Values(std::vector<std::string>{
6972 "-target", "aarch64-linux-gnu"}));
6973
6974INSTANTIATE_TEST_SUITE_P(ParameterizedTests, DeclContextTest,
6975 ::testing::Values(std::vector<std::string>()));
6976
6977INSTANTIATE_TEST_SUITE_P(ParameterizedTests, CanonicalRedeclChain,
6978 ::testing::Values(std::vector<std::string>()));
6979
6980TEST_P(ASTImporterOptionSpecificTestBase, LambdasAreDifferentiated) {
6981 Decl *FromTU = getTuDecl(
6982 SrcCode: R"(
6983 void f() {
6984 auto L0 = [](){};
6985 auto L1 = [](){};
6986 }
6987 )",
6988 Lang: Lang_CXX11, FileName: "input0.cc");
6989 auto Pattern = lambdaExpr();
6990 CXXRecordDecl *FromL0 =
6991 FirstDeclMatcher<LambdaExpr>().match(D: FromTU, AMatcher: Pattern)->getLambdaClass();
6992 CXXRecordDecl *FromL1 =
6993 LastDeclMatcher<LambdaExpr>().match(D: FromTU, AMatcher: Pattern)->getLambdaClass();
6994 ASSERT_NE(FromL0, FromL1);
6995
6996 CXXRecordDecl *ToL0 = Import(From: FromL0, Lang: Lang_CXX11);
6997 CXXRecordDecl *ToL1 = Import(From: FromL1, Lang: Lang_CXX11);
6998 EXPECT_NE(ToL0, ToL1);
6999}
7000
7001TEST_P(ASTImporterOptionSpecificTestBase,
7002 LambdasInFunctionParamsAreDifferentiated) {
7003 Decl *FromTU = getTuDecl(
7004 SrcCode: R"(
7005 template <typename F0, typename F1>
7006 void f(F0 L0 = [](){}, F1 L1 = [](){}) {}
7007 )",
7008 Lang: Lang_CXX11, FileName: "input0.cc");
7009 auto Pattern = cxxRecordDecl(isLambda());
7010 CXXRecordDecl *FromL0 =
7011 FirstDeclMatcher<CXXRecordDecl>().match(D: FromTU, AMatcher: Pattern);
7012 CXXRecordDecl *FromL1 =
7013 LastDeclMatcher<CXXRecordDecl>().match(D: FromTU, AMatcher: Pattern);
7014 ASSERT_NE(FromL0, FromL1);
7015
7016 CXXRecordDecl *ToL0 = Import(From: FromL0, Lang: Lang_CXX11);
7017 CXXRecordDecl *ToL1 = Import(From: FromL1, Lang: Lang_CXX11);
7018 ASSERT_NE(ToL0, ToL1);
7019}
7020
7021TEST_P(ASTImporterOptionSpecificTestBase,
7022 LambdasInFunctionParamsAreDifferentiatedWhenMacroIsUsed) {
7023 Decl *FromTU = getTuDecl(
7024 SrcCode: R"(
7025 #define LAMBDA [](){}
7026 template <typename F0, typename F1>
7027 void f(F0 L0 = LAMBDA, F1 L1 = LAMBDA) {}
7028 )",
7029 Lang: Lang_CXX11, FileName: "input0.cc");
7030 auto Pattern = cxxRecordDecl(isLambda());
7031 CXXRecordDecl *FromL0 =
7032 FirstDeclMatcher<CXXRecordDecl>().match(D: FromTU, AMatcher: Pattern);
7033 CXXRecordDecl *FromL1 =
7034 LastDeclMatcher<CXXRecordDecl>().match(D: FromTU, AMatcher: Pattern);
7035 ASSERT_NE(FromL0, FromL1);
7036
7037 Import(From: FromL0, Lang: Lang_CXX11);
7038 Import(From: FromL1, Lang: Lang_CXX11);
7039 CXXRecordDecl *ToL0 = Import(From: FromL0, Lang: Lang_CXX11);
7040 CXXRecordDecl *ToL1 = Import(From: FromL1, Lang: Lang_CXX11);
7041 ASSERT_NE(ToL0, ToL1);
7042}
7043
7044TEST_P(ASTImporterOptionSpecificTestBase, ImportAssignedLambda) {
7045 Decl *FromTU = getTuDecl(
7046 SrcCode: R"(
7047 void f() {
7048 auto x = []{} = {}; auto x2 = x;
7049 }
7050 )",
7051 Lang: Lang_CXX20, FileName: "input0.cc");
7052 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
7053 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
7054 // We have only one lambda class.
7055 ASSERT_EQ(
7056 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
7057 1u);
7058
7059 FunctionDecl *ToF = Import(FromF, Lang_CXX20);
7060 EXPECT_TRUE(ToF);
7061 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
7062 // We have only one lambda class after the import.
7063 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
7064 1u);
7065}
7066
7067TEST_P(ASTImporterOptionSpecificTestBase, ImportDefaultConstructibleLambdas) {
7068 Decl *FromTU = getTuDecl(
7069 SrcCode: R"(
7070 void f() {
7071 auto x = []{} = {};
7072 auto xb = []{} = {};
7073 }
7074 )",
7075 Lang: Lang_CXX20, FileName: "input0.cc");
7076 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
7077 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
7078 // We have two lambda classes.
7079 ASSERT_EQ(
7080 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
7081 2u);
7082
7083 FunctionDecl *ToF = Import(FromF, Lang_CXX20);
7084 EXPECT_TRUE(ToF);
7085 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
7086 // We have two lambda classes after the import.
7087 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
7088 2u);
7089}
7090
7091TEST_P(ASTImporterOptionSpecificTestBase,
7092 ImportFunctionDeclWithTypeSourceInfoWithSourceDecl) {
7093 // This code results in a lambda with implicit constructor.
7094 // The constructor's TypeSourceInfo points out the function prototype.
7095 // This prototype has an EST_Unevaluated in its exception information and a
7096 // SourceDecl that is the function declaration itself.
7097 // The test verifies that AST import of such AST does not crash.
7098 // (Here the function's TypeSourceInfo references the function itself.)
7099 Decl *FromTU = getTuDecl(
7100 SrcCode: R"(
7101 template<typename T> void f(T) { auto X = [](){}; }
7102 void g() { f(10); }
7103 )",
7104 Lang: Lang_CXX11, FileName: "input0.cc");
7105
7106 // Use LastDeclMatcher to find the LambdaExpr in the template specialization.
7107 CXXRecordDecl *FromL = LastDeclMatcher<LambdaExpr>()
7108 .match(D: FromTU, AMatcher: lambdaExpr())
7109 ->getLambdaClass();
7110
7111 CXXConstructorDecl *FromCtor = *FromL->ctor_begin();
7112 ASSERT_TRUE(FromCtor->isCopyConstructor());
7113 ASSERT_TRUE(FromCtor->getTypeSourceInfo());
7114 const auto *FromFPT = FromCtor->getType()->getAs<FunctionProtoType>();
7115 ASSERT_TRUE(FromFPT);
7116 EXPECT_EQ(FromCtor->getTypeSourceInfo()->getType().getTypePtr(), FromFPT);
7117 FunctionProtoType::ExtProtoInfo FromEPI = FromFPT->getExtProtoInfo();
7118 // If type is EST_Unevaluated, SourceDecl should be set to the parent Decl.
7119 EXPECT_EQ(FromEPI.ExceptionSpec.Type, EST_Unevaluated);
7120 EXPECT_EQ(FromEPI.ExceptionSpec.SourceDecl, FromCtor);
7121
7122 auto ToL = Import(From: FromL, Lang: Lang_CXX11);
7123
7124 // Check if the import was correct.
7125 CXXConstructorDecl *ToCtor = *ToL->ctor_begin();
7126 EXPECT_TRUE(ToCtor->getTypeSourceInfo());
7127 const auto *ToFPT = ToCtor->getType()->getAs<FunctionProtoType>();
7128 ASSERT_TRUE(ToFPT);
7129 EXPECT_EQ(ToCtor->getTypeSourceInfo()->getType().getTypePtr(), ToFPT);
7130 FunctionProtoType::ExtProtoInfo ToEPI = ToFPT->getExtProtoInfo();
7131 EXPECT_EQ(ToEPI.ExceptionSpec.Type, EST_Unevaluated);
7132 EXPECT_EQ(ToEPI.ExceptionSpec.SourceDecl, ToCtor);
7133}
7134
7135struct ImportAutoFunctions : ASTImporterOptionSpecificTestBase {
7136 void testImport(llvm::StringRef Code, clang::TestLanguage Lang = Lang_CXX14,
7137 bool FindLast = false) {
7138 Decl *FromTU = getTuDecl(SrcCode: Code, Lang, FileName: "input0.cc");
7139 FunctionDecl *From = FindLast ? LastDeclMatcher<FunctionDecl>().match(
7140 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo")))
7141 : FirstDeclMatcher<FunctionDecl>().match(
7142 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo")));
7143
7144 FunctionDecl *To = Import(From, Lang);
7145 EXPECT_TRUE(To);
7146 // We check here only that the type is auto type.
7147 // These tests are to verify that no crash happens.
7148 // The crash possibility is the presence of a reference to a declaration
7149 // in the function's body from the return type, if the function has auto
7150 // return type.
7151 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
7152 }
7153};
7154
7155TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate1) {
7156 testImport(
7157 Code: R"(
7158 template<class C>
7159 C f1() { return C(); }
7160 auto foo() {
7161 struct B {};
7162 return f1<B>();
7163 }
7164 )");
7165}
7166
7167TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate2) {
7168 testImport(
7169 Code: R"(
7170 template<class T>
7171 int f1(T t) { return 1; }
7172 auto foo() {
7173 struct B {};
7174 return f1(B());
7175 }
7176 )");
7177}
7178
7179TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate3) {
7180 testImport(
7181 Code: R"(
7182 template<class A> struct S1 {};
7183 template<class A> struct S2 {};
7184 template<class C>
7185 S1<C> f1() { return S1<C>(); }
7186 auto foo() {
7187 struct B {};
7188 return f1<S2<B *>>();
7189 }
7190 )");
7191}
7192
7193TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate4) {
7194 testImport(
7195 Code: R"(
7196 template<class... A> struct S1 {};
7197 template<class... A> struct S2 {};
7198 template<class... C>
7199 S1<C...> f1() { return S1<C...>(); }
7200 auto foo() {
7201 struct B {};
7202 return f1<S2<int, B *>, bool>();
7203 }
7204 )");
7205}
7206
7207TEST_P(ImportAutoFunctions, ReturnWithVarTemplate1) {
7208 testImport(
7209 Code: R"(
7210 template<class T> T X;
7211 auto foo() {
7212 struct A {};
7213 return X<A>;
7214 }
7215 )");
7216}
7217
7218TEST_P(ImportAutoFunctions, ReturnWithVarTemplate2) {
7219 testImport(
7220 Code: R"(
7221 template<class A> struct S1 {};
7222 template<class T> S1<T> X;
7223 auto foo() {
7224 struct A {};
7225 return X<S1<A>>;
7226 }
7227 )");
7228}
7229
7230TEST_P(ImportAutoFunctions, ReturnWithVarTemplate3) {
7231 testImport(
7232 Code: R"(
7233 template<class... A> struct S1 {};
7234 template<class... T> S1<T...> X;
7235 auto foo() {
7236 struct A {};
7237 return X<bool, S1<A, int>>;
7238 }
7239 )");
7240}
7241
7242TEST_P(ImportAutoFunctions, ReturnWithAutoUnresolvedArg) {
7243 testImport(
7244 Code: R"(
7245 template<int A>
7246 auto foo() {
7247 return 22;
7248 }
7249 )");
7250}
7251
7252TEST_P(ImportAutoFunctions, ReturnWithTemplateWithTemplateTemplateArg) {
7253 // FIXME: Is it possible to have the template arg inside the function?
7254 testImport(
7255 Code: R"(
7256 template<int> struct Tmpl {};
7257 template<template<int> class> struct TmplTmpl {};
7258 auto foo() {
7259 return TmplTmpl<Tmpl>();
7260 }
7261 )");
7262}
7263
7264TEST_P(ImportAutoFunctions, ReturnWithTemplateWithDeclarationTemplateArg) {
7265 // FIXME: Is it possible to have the template arg inside the function?
7266 testImport(
7267 Code: R"(
7268 template<const int *> struct Tmpl {};
7269 int A[10];
7270 auto foo() {
7271 return Tmpl<A>();
7272 }
7273 )");
7274}
7275
7276TEST_P(ImportAutoFunctions, ReturnWithTemplateWithNullPtrTemplateArg) {
7277 testImport(
7278 Code: R"(
7279 template<int *> struct Tmpl {};
7280 auto foo() {
7281 constexpr int* A = nullptr;
7282 return Tmpl<A>();
7283 }
7284 )");
7285}
7286
7287TEST_P(ImportAutoFunctions, ReturnWithTemplateWithIntegralTemplateArg) {
7288 testImport(
7289 Code: R"(
7290 template<int> struct Tmpl {};
7291 auto foo() {
7292 using Int = int;
7293 constexpr Int A = 7;
7294 return Tmpl<A>();
7295 }
7296 )");
7297}
7298
7299TEST_P(ImportAutoFunctions, ReturnWithTemplateWithDecltypeTypeDeclaredInside) {
7300 testImport(
7301 Code: R"(
7302 template<class> struct Tmpl {};
7303 auto foo() {
7304 struct X {};
7305 X x;
7306 return Tmpl<decltype(x)>();
7307 }
7308 )");
7309}
7310
7311TEST_P(ImportAutoFunctions, ReturnWithTemplateWithUsingTypeDeclaredInside) {
7312 testImport(
7313 Code: R"(
7314 template<class> struct Tmpl {};
7315 namespace A { struct X {}; }
7316 auto foo() {
7317 using A::X;
7318 return Tmpl<X>();
7319 }
7320 )");
7321}
7322
7323TEST_P(ImportAutoFunctions, ReturnWithTemplateWithArrayTypeDeclaredInside) {
7324 testImport(
7325 Code: R"(
7326 template<class> struct Tmpl {};
7327 auto foo() {
7328 struct X {};
7329 return Tmpl<X[10]>();
7330 }
7331 )");
7332}
7333
7334TEST_P(ImportAutoFunctions, ReturnWithTemplateWithArraySizeExprDeclaredInside) {
7335 testImport(
7336 Code: R"(
7337 template<class> struct Tmpl {};
7338 auto foo() {
7339 constexpr int S = 10;
7340 return Tmpl<int[S]>();
7341 }
7342 )");
7343}
7344
7345TEST_P(ImportAutoFunctions, ReturnWithTemplateWithPackArgDeclaredInside) {
7346 testImport(
7347 Code: R"(
7348 template<class ...> struct Tmpl {};
7349 auto foo() {
7350 using X = bool;
7351 return Tmpl<int, X>();
7352 }
7353 )");
7354}
7355
7356TEST_P(ImportAutoFunctions, ReturnWithTemplateWithIntegerArgDeclaredInside) {
7357 testImport(
7358 Code: R"(
7359 template<int> struct Tmpl {};
7360 auto foo() {
7361 constexpr int X = 1;
7362 return Tmpl<X>();
7363 }
7364 )");
7365}
7366
7367TEST_P(ImportAutoFunctions, ReturnWithTemplateWithPtrToStructDeclaredInside) {
7368 testImport(
7369 Code: R"(
7370 template<class> struct Tmpl {};
7371 auto foo() {
7372 struct X {};
7373 return Tmpl<X *>();
7374 }
7375 )");
7376}
7377
7378TEST_P(ImportAutoFunctions, ReturnWithTemplateWithRefToStructDeclaredInside) {
7379 testImport(
7380 Code: R"(
7381 template<class> struct Tmpl {};
7382 struct X {};
7383 auto foo() {
7384 using Y = X;
7385 return Tmpl<Y &>();
7386 }
7387 )");
7388}
7389
7390TEST_P(ImportAutoFunctions, ReturnWithTemplateWithStructDeclaredInside1) {
7391 testImport(
7392 Code: R"(
7393 template<class> struct Tmpl {};
7394 auto foo() {
7395 struct X {};
7396 return Tmpl<X>();
7397 }
7398 )");
7399}
7400
7401TEST_P(ImportAutoFunctions, ReturnWithTemplateWithStructDeclaredInside2) {
7402 testImport(
7403 Code: R"(
7404 template<class> struct Tmpl {};
7405 auto foo() {
7406 struct X {};
7407 return Tmpl<Tmpl<X>>();
7408 }
7409 )");
7410}
7411
7412TEST_P(ImportAutoFunctions, ReturnWithTemplateWithTypedefDeclaredInside) {
7413 testImport(
7414 Code: R"(
7415 template<class> struct Tmpl {};
7416 auto foo() {
7417 struct X {};
7418 using x_type = X;
7419 return Tmpl<x_type>();
7420 }
7421 )");
7422}
7423
7424TEST_P(ImportAutoFunctions, ReturnWithTypedefDeclaredInside) {
7425 Decl *FromTU = getTuDecl(
7426 SrcCode: R"(
7427 auto X = [](long l) {
7428 using int_type = long;
7429 auto dur = 13;
7430 return static_cast<int_type>(dur);
7431 };
7432 )",
7433 Lang: Lang_CXX14, FileName: "input0.cc");
7434 CXXMethodDecl *From =
7435 FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU, AMatcher: cxxMethodDecl());
7436
7437 // Explicitly set the return type of the lambda's operator() to the TypeAlias.
7438 // Normally the return type would be the built-in 'long' type. However, there
7439 // are cases when Clang does not use the canonical type and the TypeAlias is
7440 // used. I could not create such an AST from regular source code, it requires
7441 // some special state in the preprocessor. I've found such an AST when Clang
7442 // parsed libcxx/src/filesystem/directory_iterator.cpp, but could not reduce
7443 // that with creduce, because after preprocessing, the AST no longer
7444 // contained the TypeAlias as a return type of the lambda.
7445 ASTContext &Ctx = From->getASTContext();
7446 TypeAliasDecl *FromTA =
7447 FirstDeclMatcher<TypeAliasDecl>().match(D: FromTU, AMatcher: typeAliasDecl());
7448 QualType TT = Ctx.getTypedefType(FromTA);
7449 const FunctionProtoType *FPT = cast<FunctionProtoType>(From->getType());
7450 QualType NewFunType =
7451 Ctx.getFunctionType(ResultTy: TT, Args: FPT->getParamTypes(), EPI: FPT->getExtProtoInfo());
7452 From->setType(NewFunType);
7453
7454 CXXMethodDecl *To = Import(From, Lang: Lang_CXX14);
7455 EXPECT_TRUE(To);
7456 EXPECT_TRUE(isa<TypedefType>(To->getReturnType()));
7457}
7458
7459TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside) {
7460 testImport(
7461 Code: R"(
7462 auto foo() {
7463 struct X {};
7464 return X();
7465 }
7466 )");
7467}
7468
7469TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside2) {
7470 Decl *FromTU = getTuDecl(
7471 SrcCode: R"(
7472 auto foo() {
7473 struct X {};
7474 return X();
7475 }
7476 )",
7477 Lang: Lang_CXX14, FileName: "input0.cc");
7478 FunctionDecl *From =
7479 FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: functionDecl());
7480
7481 // This time import the type directly.
7482 QualType ToT = ImportType(FromType: From->getType(), TUDecl: From, ToLang: Lang_CXX14);
7483 const FunctionProtoType *FPT = cast<FunctionProtoType>(Val&: ToT);
7484 EXPECT_TRUE(isa<AutoType>(FPT->getReturnType()));
7485}
7486
7487TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside3) {
7488 Decl *FromTU = getTuDecl(
7489 SrcCode: R"(
7490 struct S {
7491 constexpr auto foo();
7492 };
7493 constexpr auto S::foo() {
7494 struct X {};
7495 return X();
7496 }
7497 )",
7498 Lang: Lang_CXX14, FileName: "input0.cc");
7499 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
7500 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo"), unless(hasBody(InnerMatcher: stmt()))));
7501 ASSERT_FALSE(From->isThisDeclarationADefinition());
7502
7503 FunctionDecl *To = Import(From, Lang: Lang_CXX17);
7504 EXPECT_TRUE(To);
7505 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
7506 EXPECT_FALSE(To->isThisDeclarationADefinition());
7507}
7508
7509TEST_P(ImportAutoFunctions, ReturnWithTypedefToStructDeclaredInside) {
7510 testImport(
7511 Code: R"(
7512 auto foo() {
7513 struct X {};
7514 using Y = X;
7515 return Y();
7516 }
7517 )");
7518}
7519
7520TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredNestedInside) {
7521 testImport(
7522 Code: R"(
7523 auto foo() {
7524 struct X { struct Y{}; };
7525 return X::Y();
7526 }
7527 )");
7528}
7529
7530TEST_P(ImportAutoFunctions, ReturnWithInternalLambdaType) {
7531 testImport(
7532 Code: R"(
7533 auto foo() {
7534 auto l = []() {
7535 struct X {};
7536 return X();
7537 };
7538 return l();
7539 }
7540 )",
7541 Lang: Lang_CXX17);
7542}
7543
7544TEST_P(ImportAutoFunctions, ReturnWithTypeInIf) {
7545 testImport(
7546 Code: R"(
7547 auto foo() {
7548 if (struct X {} x; true)
7549 return X();
7550 else
7551 return X();
7552 }
7553 )",
7554 Lang: Lang_CXX17);
7555}
7556
7557TEST_P(ImportAutoFunctions, ReturnWithTypeInFor) {
7558 testImport(
7559 Code: R"(
7560 auto foo() {
7561 for (struct X {} x;;)
7562 return X();
7563 }
7564 )",
7565 Lang: Lang_CXX17);
7566}
7567
7568TEST_P(ImportAutoFunctions, ReturnWithTypeInSwitch) {
7569 testImport(
7570 Code: R"(
7571 auto foo() {
7572 switch (struct X {} x; 10) {
7573 case 10:
7574 return X();
7575 }
7576 }
7577 )",
7578 Lang: Lang_CXX17);
7579}
7580
7581TEST_P(ImportAutoFunctions, ReturnWithAutoTemplateType) {
7582 testImport(
7583 Code: R"(
7584 template<class T>
7585 struct S {};
7586 template<class T>
7587 auto foo() {
7588 return S<T>{};
7589 }
7590 auto a = foo<int>();
7591 )",
7592 Lang: Lang_CXX14, /*FindLast=*/true);
7593}
7594
7595TEST_P(ImportAutoFunctions, ReturnWithSubstNonTypeTemplateParmExpr) {
7596 const char *Code =
7597 R"(
7598 template<int>
7599 struct array {};
7600
7601 template <int N>
7602 auto foo() { return array<N>(); }
7603
7604 void bar() { foo<0>(); }
7605 )";
7606 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX17);
7607
7608 auto *FromBar = FirstDeclMatcher<FunctionDecl>().match(
7609 D: FromTU, AMatcher: functionDecl(hasName(Name: "bar")));
7610
7611 auto *ToBar = Import(FromBar, Lang_CXX17);
7612 EXPECT_TRUE(ToBar);
7613}
7614
7615TEST_P(ImportAutoFunctions, ReturnWithUnaryTransformType) {
7616 const char *Code =
7617 R"(
7618 enum E { E1 };
7619
7620 template<typename T>
7621 auto foo(T v) { return static_cast<__underlying_type(T)>(v); }
7622
7623 bool bar() { return foo(E1); }
7624 )";
7625 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX17);
7626
7627 auto *FromBar = FirstDeclMatcher<FunctionDecl>().match(
7628 D: FromTU, AMatcher: functionDecl(hasName(Name: "bar")));
7629
7630 auto *ToBar = Import(FromBar, Lang_CXX17);
7631 EXPECT_TRUE(ToBar);
7632}
7633
7634struct ImportSourceLocations : ASTImporterOptionSpecificTestBase {};
7635
7636TEST_P(ImportSourceLocations, PreserveFileIDTreeStructure) {
7637 // Tests that the FileID tree structure (with the links being the include
7638 // chains) is preserved while importing other files (which need to be
7639 // added to this structure with fake include locations.
7640
7641 SourceLocation Location1;
7642 {
7643 auto Pattern = varDecl(hasName(Name: "X"));
7644 Decl *FromTU = getTuDecl(SrcCode: "int X;", Lang: Lang_C99, FileName: "input0.c");
7645 auto *FromD = FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: Pattern);
7646
7647 Location1 = Import(FromD, Lang_C99)->getLocation();
7648 }
7649 SourceLocation Location2;
7650 {
7651 auto Pattern = varDecl(hasName(Name: "Y"));
7652 Decl *FromTU = getTuDecl(SrcCode: "int Y;", Lang: Lang_C99, FileName: "input1.c");
7653 auto *FromD = FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: Pattern);
7654
7655 Location2 = Import(FromD, Lang_C99)->getLocation();
7656 }
7657
7658 SourceManager &ToSM = ToAST->getSourceManager();
7659 FileID FileID1 = ToSM.getFileID(SpellingLoc: Location1);
7660 FileID FileID2 = ToSM.getFileID(SpellingLoc: Location2);
7661
7662 // Check that the imported files look like as if they were included from the
7663 // start of the main file.
7664 SourceLocation FileStart = ToSM.getLocForStartOfFile(FID: ToSM.getMainFileID());
7665 EXPECT_NE(FileID1, ToSM.getMainFileID());
7666 EXPECT_NE(FileID2, ToSM.getMainFileID());
7667 EXPECT_EQ(ToSM.getIncludeLoc(FileID1), FileStart);
7668 EXPECT_EQ(ToSM.getIncludeLoc(FileID2), FileStart);
7669
7670 // Let the SourceManager check the order of the locations. The order should
7671 // be the order in which the declarations are imported.
7672 EXPECT_TRUE(ToSM.isBeforeInTranslationUnit(Location1, Location2));
7673 EXPECT_FALSE(ToSM.isBeforeInTranslationUnit(Location2, Location1));
7674}
7675
7676TEST_P(ImportSourceLocations, NormalFileBuffer) {
7677 // Test importing normal file buffers.
7678
7679 std::string Path = "input0.c";
7680 std::string Source = "int X;";
7681 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: Source, Lang: Lang_C99, FileName: Path);
7682
7683 SourceLocation ImportedLoc;
7684 {
7685 // Import the VarDecl to trigger the importing of the FileID.
7686 auto Pattern = varDecl(hasName(Name: "X"));
7687 VarDecl *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
7688 ImportedLoc = Import(From: FromD, Lang: Lang_C99)->getLocation();
7689 }
7690
7691 // Make sure the imported buffer has the original contents.
7692 SourceManager &ToSM = ToAST->getSourceManager();
7693 FileID ImportedID = ToSM.getFileID(SpellingLoc: ImportedLoc);
7694 EXPECT_EQ(Source,
7695 ToSM.getBufferOrFake(ImportedID, SourceLocation()).getBuffer());
7696}
7697
7698TEST_P(ImportSourceLocations, OverwrittenFileBuffer) {
7699 // Test importing overwritten file buffers.
7700
7701 std::string Path = "input0.c";
7702 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: "int X;", Lang: Lang_C99, FileName: Path);
7703
7704 // Overwrite the file buffer for our input file with new content.
7705 const std::string Contents = "overwritten contents";
7706 SourceLocation ImportedLoc;
7707 {
7708 SourceManager &FromSM = FromTU->getASTContext().getSourceManager();
7709 clang::FileManager &FM = FromSM.getFileManager();
7710 clang::FileEntryRef FE =
7711 FM.getVirtualFileRef(Filename: Path, Size: static_cast<off_t>(Contents.size()), ModificationTime: 0);
7712
7713 llvm::SmallVector<char, 64> Buffer;
7714 Buffer.append(in_start: Contents.begin(), in_end: Contents.end());
7715 auto FileContents = std::make_unique<llvm::SmallVectorMemoryBuffer>(
7716 args: std::move(Buffer), args&: Path, /*RequiresNullTerminator=*/args: false);
7717 FromSM.overrideFileContents(SourceFile: FE, Buffer: std::move(FileContents));
7718
7719 // Import the VarDecl to trigger the importing of the FileID.
7720 auto Pattern = varDecl(hasName(Name: "X"));
7721 VarDecl *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
7722 ImportedLoc = Import(From: FromD, Lang: Lang_C99)->getLocation();
7723 }
7724
7725 // Make sure the imported buffer has the overwritten contents.
7726 SourceManager &ToSM = ToAST->getSourceManager();
7727 FileID ImportedID = ToSM.getFileID(SpellingLoc: ImportedLoc);
7728 EXPECT_EQ(Contents,
7729 ToSM.getBufferOrFake(ImportedID, SourceLocation()).getBuffer());
7730}
7731
7732struct ImportAttributes : public ASTImporterOptionSpecificTestBase {
7733 void checkAttrImportCommon(const Attr *From, const Attr *To,
7734 const Decl *ToD) {
7735
7736 // Verify that dump does not crash because invalid data.
7737 ToD->dump(Out&: llvm::nulls());
7738
7739 EXPECT_EQ(From->getParsedKind(), To->getParsedKind());
7740 EXPECT_EQ(From->getSyntax(), To->getSyntax());
7741 if (From->getAttrName()) {
7742 EXPECT_TRUE(To->getAttrName());
7743 EXPECT_STREQ(From->getAttrName()->getNameStart(),
7744 To->getAttrName()->getNameStart());
7745 } else {
7746 EXPECT_FALSE(To->getAttrName());
7747 }
7748 if (From->getScopeName()) {
7749 EXPECT_TRUE(To->getScopeName());
7750 EXPECT_STREQ(From->getScopeName()->getNameStart(),
7751 To->getScopeName()->getNameStart());
7752 } else {
7753 EXPECT_FALSE(To->getScopeName());
7754 }
7755 EXPECT_EQ(From->getSpellingListIndex(), To->getSpellingListIndex());
7756 EXPECT_STREQ(From->getSpelling(), To->getSpelling());
7757 EXPECT_EQ(From->isInherited(), To->isInherited());
7758 EXPECT_EQ(From->isImplicit(), To->isImplicit());
7759 EXPECT_EQ(From->isPackExpansion(), To->isPackExpansion());
7760 EXPECT_EQ(From->isLateParsed(), To->isLateParsed());
7761 }
7762
7763 template <class DT, class AT>
7764 void importAttr(const char *Code, AT *&FromAttr, AT *&ToAttr,
7765 TestLanguage Lang = Lang_CXX11) {
7766 static_assert(std::is_base_of<Attr, AT>::value, "AT should be an Attr");
7767 static_assert(std::is_base_of<Decl, DT>::value, "DT should be a Decl");
7768
7769 Decl *FromTU = getTuDecl(SrcCode: Code, Lang, FileName: "input.cc");
7770 DT *FromD =
7771 FirstDeclMatcher<DT>().match(FromTU, namedDecl(hasName(Name: "test")));
7772 ASSERT_TRUE(FromD);
7773
7774 DT *ToD = Import(FromD, Lang_CXX11);
7775 ASSERT_TRUE(ToD);
7776
7777 FromAttr = FromD->template getAttr<AT>();
7778 ToAttr = ToD->template getAttr<AT>();
7779 ASSERT_TRUE(FromAttr);
7780 EXPECT_TRUE(ToAttr);
7781
7782 checkAttrImportCommon(From: FromAttr, To: ToAttr, ToD);
7783 }
7784
7785 template <class T> void checkImported(const T *From, const T *To) {
7786 EXPECT_TRUE(To);
7787 EXPECT_NE(From, To);
7788 }
7789
7790 template <class T>
7791 void checkImportVariadicArg(const llvm::iterator_range<T **> &From,
7792 const llvm::iterator_range<T **> &To) {
7793 for (auto FromI = From.begin(), ToI = To.begin(); FromI != From.end();
7794 ++FromI, ++ToI) {
7795 ASSERT_NE(ToI, To.end());
7796 checkImported(*FromI, *ToI);
7797 }
7798 }
7799};
7800
7801template <>
7802void ImportAttributes::checkImported<Decl>(const Decl *From, const Decl *To) {
7803 EXPECT_TRUE(To);
7804 EXPECT_NE(From, To);
7805 EXPECT_EQ(To->getTranslationUnitDecl(),
7806 ToAST->getASTContext().getTranslationUnitDecl());
7807}
7808
7809TEST_P(ImportAttributes, ImportAligned) {
7810 AlignedAttr *FromAttr, *ToAttr;
7811 importAttr<RecordDecl>(
7812 R"(
7813 struct __attribute__((packed)) A { int __attribute__((aligned(8))) X; };
7814 struct alignas(alignof(A)) test {};
7815 )",
7816 FromAttr, ToAttr);
7817 checkImported(FromAttr->getAlignmentExpr(), ToAttr->getAlignmentExpr());
7818
7819 auto *ToA = FirstDeclMatcher<CXXRecordDecl>().match(
7820 ToAST->getASTContext().getTranslationUnitDecl(),
7821 cxxRecordDecl(hasName(Name: "A"), unless(isImplicit())));
7822 // Ensure that 'struct A' was imported (through reference from attribute of
7823 // struct 'test').
7824 EXPECT_TRUE(ToA);
7825}
7826
7827TEST_P(ImportAttributes, ImportAlignValue) {
7828 AlignValueAttr *FromAttr, *ToAttr;
7829 importAttr<VarDecl>(
7830 R"(
7831 void *test __attribute__((align_value(64)));
7832 )",
7833 FromAttr, ToAttr);
7834 checkImported(FromAttr->getAlignment(), ToAttr->getAlignment());
7835}
7836
7837TEST_P(ImportAttributes, ImportFormat) {
7838 FormatAttr *FromAttr, *ToAttr;
7839 importAttr<FunctionDecl>(
7840 R"(
7841 int test(const char * fmt, ...)
7842 __attribute__ ((__format__ (__scanf__, 1, 2)));
7843 )",
7844 FromAttr, ToAttr);
7845
7846 EXPECT_EQ(FromAttr->getType()->getName(), ToAttr->getType()->getName());
7847 EXPECT_EQ(FromAttr->getFirstArg(), ToAttr->getFirstArg());
7848 EXPECT_EQ(FromAttr->getFormatIdx(), ToAttr->getFormatIdx());
7849}
7850
7851TEST_P(ImportAttributes, ImportEnableIf) {
7852 EnableIfAttr *FromAttr, *ToAttr;
7853 importAttr<FunctionDecl>(
7854 "void test(int A) __attribute__((enable_if(A == 1, \"message\")));",
7855 FromAttr, ToAttr);
7856 checkImported(FromAttr->getCond(), ToAttr->getCond());
7857 EXPECT_EQ(FromAttr->getMessage(), ToAttr->getMessage());
7858}
7859
7860TEST_P(ImportAttributes, ImportGuardedVar) {
7861 GuardedVarAttr *FromAttr, *ToAttr;
7862 importAttr<VarDecl>("int test __attribute__((guarded_var));", FromAttr,
7863 ToAttr);
7864}
7865
7866TEST_P(ImportAttributes, ImportPtGuardedVar) {
7867 PtGuardedVarAttr *FromAttr, *ToAttr;
7868 importAttr<VarDecl>("int *test __attribute__((pt_guarded_var));", FromAttr,
7869 ToAttr);
7870}
7871
7872TEST_P(ImportAttributes, ImportScopedLockable) {
7873 ScopedLockableAttr *FromAttr, *ToAttr;
7874 importAttr<CXXRecordDecl>("struct __attribute__((scoped_lockable)) test {};",
7875 FromAttr, ToAttr);
7876}
7877
7878TEST_P(ImportAttributes, ImportCapability) {
7879 CapabilityAttr *FromAttr, *ToAttr;
7880 importAttr<CXXRecordDecl>(
7881 "struct __attribute__((capability(\"cap\"))) test {};", FromAttr, ToAttr);
7882 EXPECT_EQ(FromAttr->getName(), ToAttr->getName());
7883}
7884
7885TEST_P(ImportAttributes, ImportAssertCapability) {
7886 AssertCapabilityAttr *FromAttr, *ToAttr;
7887 importAttr<FunctionDecl>(
7888 "void test(int A1, int A2) __attribute__((assert_capability(A1, A2)));",
7889 FromAttr, ToAttr);
7890 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7891}
7892
7893TEST_P(ImportAttributes, ImportAcquireCapability) {
7894 AcquireCapabilityAttr *FromAttr, *ToAttr;
7895 importAttr<FunctionDecl>(
7896 "void test(int A1, int A2) __attribute__((acquire_capability(A1, A2)));",
7897 FromAttr, ToAttr);
7898 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7899}
7900
7901TEST_P(ImportAttributes, ImportTryAcquireCapability) {
7902 TryAcquireCapabilityAttr *FromAttr, *ToAttr;
7903 importAttr<FunctionDecl>(
7904 "void test(int A1, int A2) __attribute__((try_acquire_capability(1, A1, "
7905 "A2)));",
7906 FromAttr, ToAttr);
7907 checkImported(FromAttr->getSuccessValue(), ToAttr->getSuccessValue());
7908 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7909}
7910
7911TEST_P(ImportAttributes, ImportReleaseCapability) {
7912 ReleaseCapabilityAttr *FromAttr, *ToAttr;
7913 importAttr<FunctionDecl>(
7914 "void test(int A1, int A2) __attribute__((release_capability(A1, A2)));",
7915 FromAttr, ToAttr);
7916 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7917}
7918
7919TEST_P(ImportAttributes, ImportRequiresCapability) {
7920 RequiresCapabilityAttr *FromAttr, *ToAttr;
7921 importAttr<FunctionDecl>(
7922 "void test(int A1, int A2) __attribute__((requires_capability(A1, A2)));",
7923 FromAttr, ToAttr);
7924 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7925}
7926
7927TEST_P(ImportAttributes, ImportNoThreadSafetyAnalysis) {
7928 NoThreadSafetyAnalysisAttr *FromAttr, *ToAttr;
7929 importAttr<FunctionDecl>(
7930 "void test() __attribute__((no_thread_safety_analysis));", FromAttr,
7931 ToAttr);
7932}
7933
7934TEST_P(ImportAttributes, ImportGuardedBy) {
7935 GuardedByAttr *FromAttr, *ToAttr;
7936 importAttr<VarDecl>(
7937 R"(
7938 int G;
7939 int test __attribute__((guarded_by(G)));
7940 )",
7941 FromAttr, ToAttr);
7942 checkImported(FromAttr->getArg(), ToAttr->getArg());
7943}
7944
7945TEST_P(ImportAttributes, ImportPtGuardedBy) {
7946 PtGuardedByAttr *FromAttr, *ToAttr;
7947 importAttr<VarDecl>(
7948 R"(
7949 int G;
7950 int *test __attribute__((pt_guarded_by(G)));
7951 )",
7952 FromAttr, ToAttr);
7953 checkImported(FromAttr->getArg(), ToAttr->getArg());
7954}
7955
7956TEST_P(ImportAttributes, ImportAcquiredAfter) {
7957 AcquiredAfterAttr *FromAttr, *ToAttr;
7958 importAttr<VarDecl>(
7959 R"(
7960 struct __attribute__((lockable)) L {};
7961 L A1;
7962 L A2;
7963 L test __attribute__((acquired_after(A1, A2)));
7964 )",
7965 FromAttr, ToAttr);
7966 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7967}
7968
7969TEST_P(ImportAttributes, ImportAcquiredBefore) {
7970 AcquiredBeforeAttr *FromAttr, *ToAttr;
7971 importAttr<VarDecl>(
7972 R"(
7973 struct __attribute__((lockable)) L {};
7974 L A1;
7975 L A2;
7976 L test __attribute__((acquired_before(A1, A2)));
7977 )",
7978 FromAttr, ToAttr);
7979 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7980}
7981
7982TEST_P(ImportAttributes, ImportLockReturned) {
7983 LockReturnedAttr *FromAttr, *ToAttr;
7984 importAttr<FunctionDecl>(
7985 "void test(int A1) __attribute__((lock_returned(A1)));", FromAttr,
7986 ToAttr);
7987 checkImported(FromAttr->getArg(), ToAttr->getArg());
7988}
7989
7990TEST_P(ImportAttributes, ImportLocksExcluded) {
7991 LocksExcludedAttr *FromAttr, *ToAttr;
7992 importAttr<FunctionDecl>(
7993 "void test(int A1, int A2) __attribute__((locks_excluded(A1, A2)));",
7994 FromAttr, ToAttr);
7995 checkImportVariadicArg(FromAttr->args(), ToAttr->args());
7996}
7997
7998TEST_P(ImportAttributes, ImportReentrantCapability) {
7999 ReentrantCapabilityAttr *FromAttr, *ToAttr;
8000 importAttr<CXXRecordDecl>(
8001 R"(
8002 struct __attribute__((capability("x"), reentrant_capability)) test {};
8003 )",
8004 FromAttr, ToAttr);
8005}
8006
8007TEST_P(ImportAttributes, ImportC99NoThrowAttr) {
8008 NoThrowAttr *FromAttr, *ToAttr;
8009 importAttr<FunctionDecl>("void test () __attribute__ ((__nothrow__));",
8010 FromAttr, ToAttr, Lang_C99);
8011 checkImported(FromAttr->getAttrName(), ToAttr->getAttrName());
8012}
8013
8014template <typename T>
8015auto ExtendWithOptions(const T &Values, const std::vector<std::string> &Args) {
8016 auto Copy = Values;
8017 for (std::vector<std::string> &ArgV : Copy) {
8018 for (const std::string &Arg : Args) {
8019 ArgV.push_back(x: Arg);
8020 }
8021 }
8022 return ::testing::ValuesIn(Copy);
8023}
8024
8025struct ImportWithExternalSource : ASTImporterOptionSpecificTestBase {
8026 ImportWithExternalSource() {
8027 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
8028 ASTContext &FromContext, FileManager &FromFileManager,
8029 bool MinimalImport,
8030 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
8031 return new ASTImporter(ToContext, ToFileManager, FromContext,
8032 // Use minimal import for these tests.
8033 FromFileManager, /*MinimalImport=*/true,
8034 // We use the regular lookup.
8035 /*SharedState=*/nullptr);
8036 };
8037 }
8038};
8039
8040/// An ExternalASTSource that keeps track of the tags is completed.
8041struct SourceWithCompletedTagList : clang::ExternalASTSource {
8042 std::vector<clang::TagDecl *> &CompletedTags;
8043 SourceWithCompletedTagList(std::vector<clang::TagDecl *> &CompletedTags)
8044 : CompletedTags(CompletedTags) {}
8045 void CompleteType(TagDecl *Tag) override {
8046 auto *Record = cast<CXXRecordDecl>(Val: Tag);
8047 Record->startDefinition();
8048 Record->completeDefinition();
8049 CompletedTags.push_back(x: Tag);
8050 }
8051 using clang::ExternalASTSource::CompleteType;
8052};
8053
8054TEST_P(ImportWithExternalSource, CompleteRecordBeforeImporting) {
8055 // Create an empty TU.
8056 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: "", Lang: Lang_CXX03, FileName: "input.cpp");
8057
8058 // Create and add the test ExternalASTSource.
8059 std::vector<clang::TagDecl *> CompletedTags;
8060 IntrusiveRefCntPtr<ExternalASTSource> source =
8061 new SourceWithCompletedTagList(CompletedTags);
8062 clang::ASTContext &Context = FromTU->getASTContext();
8063 Context.setExternalSource(std::move(source));
8064
8065 // Create a dummy class by hand with external lexical storage.
8066 IdentifierInfo &Ident = Context.Idents.get(Name: "test_class");
8067 auto *Record =
8068 CXXRecordDecl::Create(Context, TagTypeKind::Class, FromTU,
8069 SourceLocation(), SourceLocation(), &Ident);
8070 Record->setHasExternalLexicalStorage();
8071 FromTU->addDecl(D: Record);
8072
8073 // Do a minimal import of the created class.
8074 EXPECT_EQ(0U, CompletedTags.size());
8075 Import(Record, Lang_CXX03);
8076 EXPECT_EQ(0U, CompletedTags.size());
8077
8078 // Import the definition of the created class.
8079 llvm::Error Err = findFromTU(From: Record)->Importer->ImportDefinition(Record);
8080 EXPECT_FALSE((bool)Err);
8081 consumeError(Err: std::move(Err));
8082
8083 // Make sure the class was completed once.
8084 EXPECT_EQ(1U, CompletedTags.size());
8085 EXPECT_EQ(Record, CompletedTags.front());
8086}
8087
8088TEST_P(ImportFunctions, CTADImplicit) {
8089 Decl *FromTU = getTuDecl(
8090 SrcCode: R"(
8091 template <typename T> struct A {
8092 A(T);
8093 };
8094 A a{(int)0};
8095 )",
8096 Lang: Lang_CXX17, FileName: "input.cc");
8097 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8098 D: FromTU,
8099 AMatcher: cxxDeductionGuideDecl(hasParameter(N: 0, InnerMatcher: hasType(InnerMatcher: asString(Name: "A<T>")))));
8100 auto *ToD = Import(FromD, Lang_CXX17);
8101 ASSERT_TRUE(ToD);
8102 EXPECT_EQ(ToD->getDeductionCandidateKind(), DeductionCandidate::Copy);
8103 EXPECT_EQ(ToD->getSourceDeductionGuide(), nullptr);
8104 EXPECT_EQ(ToD->getSourceDeductionGuideKind(),
8105 CXXDeductionGuideDecl::SourceDeductionGuideKind::None);
8106 // Check that the deduced class template is also imported.
8107 EXPECT_TRUE(findFromTU(FromD)->Importer->GetAlreadyImportedOrNull(
8108 FromD->getDeducedTemplate()));
8109}
8110
8111TEST_P(ImportFunctions, CTADUserDefinedExplicit) {
8112 Decl *FromTU = getTuDecl(
8113 SrcCode: R"(
8114 template <typename T> struct A {
8115 A(T);
8116 };
8117 template <typename T> explicit A(T) -> A<float>;
8118 A a{(int)0}; // calls A<float>::A(float)
8119 )",
8120 Lang: Lang_CXX17, FileName: "input.cc");
8121 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8122 D: FromTU, AMatcher: cxxDeductionGuideDecl(unless(isImplicit())));
8123 // Not-implicit: i.e. not compiler-generated, user defined.
8124 ASSERT_FALSE(FromD->isImplicit());
8125 ASSERT_TRUE(FromD->isExplicit()); // Has the explicit keyword.
8126 auto *ToD = Import(FromD, Lang_CXX17);
8127 ASSERT_TRUE(ToD);
8128 EXPECT_FALSE(FromD->isImplicit());
8129 EXPECT_TRUE(ToD->isExplicit());
8130 EXPECT_EQ(ToD->getSourceDeductionGuide(), nullptr);
8131 EXPECT_EQ(ToD->getSourceDeductionGuideKind(),
8132 CXXDeductionGuideDecl::SourceDeductionGuideKind::None);
8133}
8134
8135TEST_P(ImportFunctions, CTADWithLocalTypedef) {
8136 Decl *TU = getTuDecl(
8137 SrcCode: R"(
8138 template <typename T> struct A {
8139 typedef T U;
8140 A(U);
8141 };
8142 A a{(int)0};
8143 )",
8144 Lang: Lang_CXX17, FileName: "input.cc");
8145 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8146 D: TU, AMatcher: cxxDeductionGuideDecl());
8147 auto *ToD = Import(FromD, Lang_CXX17);
8148 ASSERT_TRUE(ToD);
8149}
8150
8151TEST_P(ImportFunctions, CTADAliasTemplate) {
8152 Decl *TU = getTuDecl(
8153 SrcCode: R"(
8154 template <typename T> struct A {
8155 A(T);
8156 };
8157 template<typename T>
8158 using B = A<T>;
8159 B b{(int)0};
8160 )",
8161 Lang: Lang_CXX20, FileName: "input.cc");
8162 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8163 D: TU, AMatcher: cxxDeductionGuideDecl(hasParameter(N: 0, InnerMatcher: hasType(InnerMatcher: asString(Name: "int")))));
8164 auto *ToD = Import(FromD, Lang_CXX20);
8165 ASSERT_TRUE(ToD);
8166 EXPECT_TRUE(ToD->getSourceDeductionGuideKind() ==
8167 CXXDeductionGuideDecl::SourceDeductionGuideKind::Alias);
8168 EXPECT_TRUE(ToD->getSourceDeductionGuide());
8169}
8170
8171TEST_P(ImportFunctions, CTADAliasTemplateWithExplicitSourceDeductionGuide) {
8172 Decl *TU = getTuDecl(
8173 SrcCode: R"(
8174 template <typename T> struct A {
8175 A(T);
8176 };
8177 template<typename T>
8178 using B = A<T>;
8179 A(int) -> A<double>; // explicit
8180 B b{(int)0};
8181 )",
8182 Lang: Lang_CXX20, FileName: "input.cc");
8183 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8184 D: TU, AMatcher: cxxDeductionGuideDecl(hasParameter(N: 0, InnerMatcher: hasType(InnerMatcher: asString(Name: "int"))),
8185 hasName(Name: "<deduction guide for B>"),
8186 hasReturnTypeLoc(ReturnMatcher: loc(InnerMatcher: asString(Name: "A<double>")))));
8187 auto *ToD = Import(FromD, Lang_CXX20);
8188 ASSERT_TRUE(ToD);
8189 EXPECT_TRUE(ToD->getSourceDeductionGuideKind() ==
8190 CXXDeductionGuideDecl::SourceDeductionGuideKind::Alias);
8191 EXPECT_TRUE(ToD->getSourceDeductionGuide());
8192}
8193
8194TEST_P(ImportFunctions, ParmVarDeclDeclContext) {
8195 constexpr auto FromTUCode = R"(
8196 void f(int P);
8197 )";
8198 Decl *FromTU = getTuDecl(SrcCode: FromTUCode, Lang: Lang_CXX11);
8199 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
8200 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
8201 ASSERT_TRUE(FromF);
8202
8203 auto *ImportedF = Import(FromF, Lang_CXX11);
8204 EXPECT_TRUE(ImportedF);
8205 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
8206 ImportedF, ImportedF->getParamDecl(0)));
8207}
8208
8209// FIXME Move these tests out of ASTImporterTest. For that we need to factor
8210// out the ASTImporter specific pars from ASTImporterOptionSpecificTestBase
8211// into a new test Fixture. Then we should lift up this Fixture to its own
8212// implementation file and only then could we reuse the Fixture in other AST
8213// unitttests.
8214struct CTAD : ASTImporterOptionSpecificTestBase {};
8215
8216TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedef) {
8217 Decl *TU = getTuDecl(
8218 SrcCode: R"(
8219 typedef int U;
8220 template <typename T> struct A {
8221 A(U, T);
8222 };
8223 A a{(int)0, (int)0};
8224 )",
8225 Lang: Lang_CXX17, FileName: "input.cc");
8226 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8227 D: TU, AMatcher: cxxDeductionGuideDecl());
8228 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
8229 D: TU, AMatcher: typedefNameDecl(hasName(Name: "U")));
8230 ParmVarDecl *Param = Guide->getParamDecl(0);
8231 // The type of the first param (which is a typedef) should match the typedef
8232 // in the global scope.
8233 EXPECT_EQ(Param->getType()->getAs<TypedefType>()->getDecl(), Typedef);
8234}
8235
8236TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedefInParamPtr) {
8237 Decl *TU = getTuDecl(
8238 SrcCode: R"(
8239 typedef int U;
8240 template <typename T> struct A {
8241 A(U*, T);
8242 };
8243 A a{(int*)0, (int)0};
8244 )",
8245 Lang: Lang_CXX17, FileName: "input.cc");
8246 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8247 D: TU, AMatcher: cxxDeductionGuideDecl());
8248 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
8249 D: TU, AMatcher: typedefNameDecl(hasName(Name: "U")));
8250 ParmVarDecl *Param = Guide->getParamDecl(0);
8251 EXPECT_EQ(Param->getType()
8252 ->getAs<PointerType>()
8253 ->getPointeeType()
8254 ->getAs<TypedefType>()
8255 ->getDecl(),
8256 Typedef);
8257}
8258
8259TEST_P(CTAD, DeductionGuideShouldCopyALocalTypedef) {
8260 Decl *TU = getTuDecl(
8261 SrcCode: R"(
8262 template <typename T> struct A {
8263 typedef T U;
8264 A(U, T);
8265 };
8266 A a{(int)0, (int)0};
8267 )",
8268 Lang: Lang_CXX17, FileName: "input.cc");
8269 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8270 D: TU, AMatcher: cxxDeductionGuideDecl());
8271 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
8272 D: TU, AMatcher: typedefNameDecl(hasName(Name: "U")));
8273 ParmVarDecl *Param = Guide->getParamDecl(0);
8274 EXPECT_NE(Param->getType()->getAs<TypedefType>()->getDecl(), Typedef);
8275}
8276
8277INSTANTIATE_TEST_SUITE_P(ParameterizedTests, CTAD,
8278 DefaultTestValuesForRunOptions);
8279
8280TEST_P(ASTImporterOptionSpecificTestBase, TypedefWithAttribute) {
8281 Decl *TU = getTuDecl(
8282 SrcCode: R"(
8283 namespace N {
8284 typedef int X __attribute__((annotate("A")));
8285 }
8286 )",
8287 Lang: Lang_CXX17, FileName: "input.cc");
8288 auto *FromD =
8289 FirstDeclMatcher<TypedefDecl>().match(D: TU, AMatcher: typedefDecl(hasName(Name: "X")));
8290 auto *ToD = Import(FromD, Lang_CXX17);
8291 ASSERT_TRUE(ToD);
8292 ASSERT_EQ(ToD->getAttrs().size(), 1U);
8293 auto *ToAttr = dyn_cast<AnnotateAttr>(ToD->getAttrs()[0]);
8294 ASSERT_TRUE(ToAttr);
8295 EXPECT_EQ(ToAttr->getAnnotation(), "A");
8296}
8297
8298TEST_P(ASTImporterOptionSpecificTestBase,
8299 ImportOfTemplatedDeclWhenPreviousDeclHasNoDescribedTemplateSet) {
8300 Decl *FromTU = getTuDecl(
8301 SrcCode: R"(
8302
8303 namespace std {
8304 template<typename T>
8305 class basic_stringbuf;
8306 }
8307 namespace std {
8308 class char_traits;
8309 template<typename T = char_traits>
8310 class basic_stringbuf;
8311 }
8312 namespace std {
8313 template<typename T>
8314 class basic_stringbuf {};
8315 }
8316
8317 )",
8318 Lang: Lang_CXX11);
8319
8320 auto *From1 = FirstDeclMatcher<ClassTemplateDecl>().match(
8321 D: FromTU,
8322 AMatcher: classTemplateDecl(hasName(Name: "basic_stringbuf"), unless(isImplicit())));
8323 auto *To1 = cast_or_null<ClassTemplateDecl>(Import(From1, Lang_CXX11));
8324 EXPECT_TRUE(To1);
8325
8326 auto *From2 = LastDeclMatcher<ClassTemplateDecl>().match(
8327 D: FromTU,
8328 AMatcher: classTemplateDecl(hasName(Name: "basic_stringbuf"), unless(isImplicit())));
8329 auto *To2 = cast_or_null<ClassTemplateDecl>(Import(From2, Lang_CXX11));
8330 EXPECT_TRUE(To2);
8331}
8332
8333TEST_P(ASTImporterOptionSpecificTestBase, ImportOfCapturedVLAType) {
8334 Decl *FromTU = getTuDecl(
8335 SrcCode: R"(
8336 void declToImport(int N) {
8337 int VLA[N];
8338 [&VLA] {}; // FieldDecl inside the lambda.
8339 }
8340 )",
8341 Lang: Lang_CXX14);
8342 auto *FromFD = FirstDeclMatcher<FieldDecl>().match(D: FromTU, AMatcher: fieldDecl());
8343 ASSERT_TRUE(FromFD);
8344 ASSERT_TRUE(FromFD->hasCapturedVLAType());
8345
8346 auto *ToFD = Import(FromFD, Lang_CXX14);
8347 EXPECT_TRUE(ToFD);
8348 EXPECT_TRUE(ToFD->hasCapturedVLAType());
8349 EXPECT_NE(FromFD->getCapturedVLAType(), ToFD->getCapturedVLAType());
8350}
8351
8352TEST_P(ASTImporterOptionSpecificTestBase, ImportEnumMemberSpecialization) {
8353 Decl *FromTU = getTuDecl(
8354 SrcCode: R"(
8355 template <class T> struct A {
8356 enum tagname { enumerator };
8357 };
8358 template struct A<int>;
8359 )",
8360 Lang: Lang_CXX03);
8361 auto *FromD = FirstDeclMatcher<EnumDecl>().match(
8362 D: FromTU, AMatcher: enumDecl(hasName(Name: "tagname"),
8363 hasParent(classTemplateSpecializationDecl())));
8364 ASSERT_TRUE(FromD);
8365 ASSERT_TRUE(FromD->getMemberSpecializationInfo());
8366
8367 auto *ToD = Import(FromD, Lang_CXX03);
8368 EXPECT_TRUE(ToD);
8369 EXPECT_TRUE(ToD->getMemberSpecializationInfo());
8370 EXPECT_EQ(FromD->getTemplateSpecializationKind(),
8371 ToD->getTemplateSpecializationKind());
8372}
8373
8374TEST_P(ASTImporterOptionSpecificTestBase, ImportIsInheritingConstructorBit) {
8375 Decl *FromTU = getTuDecl(
8376 SrcCode: R"(
8377 struct A {
8378 A(int);
8379 };
8380 struct B : A {
8381 using A::A; // Inherited ctor.
8382 };
8383 void f() {
8384 (B(0));
8385 }
8386 )",
8387 Lang: Lang_CXX11);
8388 auto *FromD = FirstDeclMatcher<CXXConstructorDecl>().match(
8389 D: FromTU, AMatcher: cxxConstructorDecl(isInheritingConstructor()));
8390 ASSERT_TRUE(FromD);
8391 ASSERT_TRUE(FromD->isInheritingConstructor());
8392
8393 auto *ToD = Import(FromD, Lang_CXX11);
8394 ASSERT_TRUE(ToD);
8395 EXPECT_TRUE(ToD->isInheritingConstructor());
8396}
8397
8398TEST_P(ASTImporterOptionSpecificTestBase, ImportConstructorUsingShadow) {
8399 TranslationUnitDecl *FromTU = getTuDecl(
8400 SrcCode: R"(
8401 struct A {
8402 A(int, int);
8403 };
8404 struct B : A {
8405 using A::A;
8406 };
8407 struct C : B {
8408 using B::B;
8409 };
8410 )",
8411 Lang: Lang_CXX11);
8412
8413 auto CheckAST = [](TranslationUnitDecl *TU, CXXRecordDecl *RecordC) {
8414 auto *RecordA = FirstDeclMatcher<CXXRecordDecl>().match(
8415 TU, cxxRecordDecl(hasName(Name: "A")));
8416 auto *RecordB = FirstDeclMatcher<CXXRecordDecl>().match(
8417 TU, cxxRecordDecl(hasName(Name: "B")));
8418 auto *ConstrA = FirstDeclMatcher<CXXConstructorDecl>().match(
8419 TU, cxxConstructorDecl(hasParent(equalsNode(RecordA)),
8420 parameterCountIs(N: 2)));
8421 auto *ShadowBA = cast<ConstructorUsingShadowDecl>(
8422 FirstDeclMatcher<UsingShadowDecl>().match(
8423 TU, usingShadowDecl(hasParent(equalsNode(RecordB)),
8424 hasTargetDecl(equalsNode(ConstrA)))));
8425 auto *ShadowCA = cast<ConstructorUsingShadowDecl>(
8426 FirstDeclMatcher<UsingShadowDecl>().match(
8427 TU, usingShadowDecl(hasParent(equalsNode(RecordC)),
8428 hasTargetDecl(equalsNode(ConstrA)))));
8429 EXPECT_EQ(ShadowBA->getTargetDecl(), ConstrA);
8430 EXPECT_EQ(ShadowBA->getNominatedBaseClass(), RecordA);
8431 EXPECT_EQ(ShadowBA->getConstructedBaseClass(), RecordA);
8432 EXPECT_EQ(ShadowBA->getNominatedBaseClassShadowDecl(), nullptr);
8433 EXPECT_EQ(ShadowBA->getConstructedBaseClassShadowDecl(), nullptr);
8434 EXPECT_FALSE(ShadowBA->constructsVirtualBase());
8435 EXPECT_EQ(ShadowCA->getTargetDecl(), ConstrA);
8436 EXPECT_EQ(ShadowCA->getNominatedBaseClass(), RecordB);
8437 EXPECT_EQ(ShadowCA->getConstructedBaseClass(), RecordB);
8438 EXPECT_EQ(ShadowCA->getNominatedBaseClassShadowDecl(), ShadowBA);
8439 EXPECT_EQ(ShadowCA->getConstructedBaseClassShadowDecl(), ShadowBA);
8440 EXPECT_FALSE(ShadowCA->constructsVirtualBase());
8441 };
8442
8443 auto *FromC = FirstDeclMatcher<CXXRecordDecl>().match(
8444 FromTU, cxxRecordDecl(hasName(Name: "C")));
8445
8446 auto *ToC = Import(FromC, Lang_CXX11);
8447 TranslationUnitDecl *ToTU = ToC->getTranslationUnitDecl();
8448
8449 CheckAST(FromTU, FromC);
8450 CheckAST(ToTU, ToC);
8451}
8452
8453TEST_P(ASTImporterOptionSpecificTestBase,
8454 ImportFunctionDeclBitShouldNotOverwriteCtorDeclBits) {
8455 Decl *From, *To;
8456 std::tie(args&: From, args&: To) = getImportedDecl(
8457 FromSrcCode: R"s(
8458 struct A {
8459 A() : m() {}
8460 int m;
8461 };
8462
8463 A foo() { A a; return a; }
8464 A bar() { return {}; }
8465 )s",
8466 FromLang: Lang_CXX17,
8467 ToSrcCode: R"s(
8468 struct A {
8469 A() : m() {}
8470 int m;
8471 };
8472 A baz() { return {}; }
8473 )s",
8474 ToLang: Lang_CXX17, Identifier: "A");
8475
8476 auto HasCtorInit =
8477 hasAnyConstructorInitializer(InnerMatcher: cxxCtorInitializer(isMemberInitializer()));
8478 auto ImpMoveCtor =
8479 cxxConstructorDecl(isMoveConstructor(), isImplicit(), HasCtorInit);
8480
8481 auto *FromImpMoveCtor = FirstDeclMatcher<CXXConstructorDecl>().match(
8482 D: From, AMatcher: ImpMoveCtor);
8483 auto *ToImpMoveCtor = FirstDeclMatcher<CXXConstructorDecl>().match(
8484 D: To, AMatcher: ImpMoveCtor);
8485
8486 EXPECT_TRUE(FromImpMoveCtor->getNumCtorInitializers() == 1);
8487 EXPECT_FALSE(FromImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
8488
8489 EXPECT_TRUE(ToImpMoveCtor->getNumCtorInitializers() == 1);
8490 EXPECT_FALSE(ToImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
8491 EXPECT_TRUE(*ToImpMoveCtor->init_begin());
8492}
8493
8494AST_MATCHER_P(UsingShadowDecl, hasIntroducerDecl, internal::Matcher<NamedDecl>,
8495 InnerMatcher) {
8496 return InnerMatcher.matches(*Node.getIntroducer(), Finder, Builder);
8497}
8498
8499TEST_P(ASTImporterOptionSpecificTestBase,
8500 ImportConstructorUsingShadowVirtualBase) {
8501 TranslationUnitDecl *FromTU = getTuDecl(
8502 SrcCode: R"(
8503 struct A { A(int, int); };
8504 struct B : A { using A::A; };
8505
8506 struct V1 : virtual B { using B::B; };
8507 struct V2 : virtual B { using B::B; };
8508
8509 struct D2 : V1, V2 {
8510 using V1::V1;
8511 using V2::V2;
8512 };
8513 )",
8514 Lang: Lang_CXX11);
8515
8516 auto CheckAST = [](TranslationUnitDecl *TU, CXXRecordDecl *RecordD2) {
8517 auto *RecordA = FirstDeclMatcher<CXXRecordDecl>().match(
8518 TU, cxxRecordDecl(hasName(Name: "A")));
8519 auto *RecordB = FirstDeclMatcher<CXXRecordDecl>().match(
8520 TU, cxxRecordDecl(hasName(Name: "B")));
8521 auto *RecordV1 = FirstDeclMatcher<CXXRecordDecl>().match(
8522 TU, cxxRecordDecl(hasName(Name: "V1")));
8523 auto *RecordV2 = FirstDeclMatcher<CXXRecordDecl>().match(
8524 TU, cxxRecordDecl(hasName(Name: "V2")));
8525 auto *ConstrA = FirstDeclMatcher<CXXConstructorDecl>().match(
8526 TU, cxxConstructorDecl(hasParent(equalsNode(RecordA)),
8527 parameterCountIs(N: 2)));
8528 auto *ConstrB = FirstDeclMatcher<CXXConstructorDecl>().match(
8529 TU, cxxConstructorDecl(hasParent(equalsNode(RecordB)),
8530 isCopyConstructor()));
8531 auto *UsingD2V1 = FirstDeclMatcher<UsingDecl>().match(
8532 TU, usingDecl(hasParent(equalsNode(RecordD2))));
8533 auto *UsingD2V2 = LastDeclMatcher<UsingDecl>().match(
8534 TU, usingDecl(hasParent(equalsNode(RecordD2))));
8535 auto *ShadowBA = cast<ConstructorUsingShadowDecl>(
8536 FirstDeclMatcher<UsingShadowDecl>().match(
8537 TU, usingShadowDecl(hasParent(equalsNode(RecordB)),
8538 hasTargetDecl(equalsNode(ConstrA)))));
8539 auto *ShadowV1A = cast<ConstructorUsingShadowDecl>(
8540 FirstDeclMatcher<UsingShadowDecl>().match(
8541 TU, usingShadowDecl(hasParent(equalsNode(RecordV1)),
8542 hasTargetDecl(equalsNode(ConstrA)))));
8543 auto *ShadowV1B = cast<ConstructorUsingShadowDecl>(
8544 FirstDeclMatcher<UsingShadowDecl>().match(
8545 TU, usingShadowDecl(hasParent(equalsNode(RecordV1)),
8546 hasTargetDecl(equalsNode(ConstrB)))));
8547 auto *ShadowV2A = cast<ConstructorUsingShadowDecl>(
8548 FirstDeclMatcher<UsingShadowDecl>().match(
8549 TU, usingShadowDecl(hasParent(equalsNode(RecordV2)),
8550 hasTargetDecl(equalsNode(ConstrA)))));
8551 auto *ShadowV2B = cast<ConstructorUsingShadowDecl>(
8552 FirstDeclMatcher<UsingShadowDecl>().match(
8553 TU, usingShadowDecl(hasParent(equalsNode(RecordV2)),
8554 hasTargetDecl(equalsNode(ConstrB)))));
8555 auto *ShadowD2V1A = cast<ConstructorUsingShadowDecl>(
8556 FirstDeclMatcher<UsingShadowDecl>().match(
8557 TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),
8558 hasIntroducerDecl(equalsNode(UsingD2V1)),
8559 hasTargetDecl(equalsNode(ConstrA)))));
8560 auto *ShadowD2V1B = cast<ConstructorUsingShadowDecl>(
8561 FirstDeclMatcher<UsingShadowDecl>().match(
8562 TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),
8563 hasIntroducerDecl(equalsNode(UsingD2V1)),
8564 hasTargetDecl(equalsNode(ConstrB)))));
8565 auto *ShadowD2V2A = cast<ConstructorUsingShadowDecl>(
8566 FirstDeclMatcher<UsingShadowDecl>().match(
8567 TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),
8568 hasIntroducerDecl(equalsNode(UsingD2V2)),
8569 hasTargetDecl(equalsNode(ConstrA)))));
8570 auto *ShadowD2V2B = cast<ConstructorUsingShadowDecl>(
8571 FirstDeclMatcher<UsingShadowDecl>().match(
8572 TU, usingShadowDecl(hasParent(equalsNode(RecordD2)),
8573 hasIntroducerDecl(equalsNode(UsingD2V2)),
8574 hasTargetDecl(equalsNode(ConstrB)))));
8575
8576 EXPECT_EQ(ShadowD2V1A->getTargetDecl(), ConstrA);
8577 EXPECT_EQ(ShadowD2V1A->getNominatedBaseClassShadowDecl(), ShadowV1A);
8578 EXPECT_EQ(ShadowD2V1A->getNominatedBaseClass(), RecordV1);
8579 EXPECT_EQ(ShadowD2V1A->getConstructedBaseClassShadowDecl(), ShadowBA);
8580 EXPECT_EQ(ShadowD2V1A->getConstructedBaseClass(), RecordB);
8581 EXPECT_TRUE(ShadowD2V1A->constructsVirtualBase());
8582 EXPECT_EQ(ShadowD2V1B->getTargetDecl(), ConstrB);
8583 EXPECT_EQ(ShadowD2V1B->getNominatedBaseClassShadowDecl(), ShadowV1B);
8584 EXPECT_EQ(ShadowD2V1B->getNominatedBaseClass(), RecordV1);
8585 EXPECT_EQ(ShadowD2V1B->getConstructedBaseClassShadowDecl(), nullptr);
8586 EXPECT_EQ(ShadowD2V1B->getConstructedBaseClass(), RecordB);
8587 EXPECT_TRUE(ShadowD2V1B->constructsVirtualBase());
8588 EXPECT_EQ(ShadowD2V2A->getTargetDecl(), ConstrA);
8589 EXPECT_EQ(ShadowD2V2A->getNominatedBaseClassShadowDecl(), ShadowV2A);
8590 EXPECT_EQ(ShadowD2V2A->getNominatedBaseClass(), RecordV2);
8591 EXPECT_EQ(ShadowD2V2A->getConstructedBaseClassShadowDecl(), ShadowBA);
8592 EXPECT_EQ(ShadowD2V2A->getConstructedBaseClass(), RecordB);
8593 EXPECT_TRUE(ShadowD2V2A->constructsVirtualBase());
8594 EXPECT_EQ(ShadowD2V2B->getTargetDecl(), ConstrB);
8595 EXPECT_EQ(ShadowD2V2B->getNominatedBaseClassShadowDecl(), ShadowV2B);
8596 EXPECT_EQ(ShadowD2V2B->getNominatedBaseClass(), RecordV2);
8597 EXPECT_EQ(ShadowD2V2B->getConstructedBaseClassShadowDecl(), nullptr);
8598 EXPECT_EQ(ShadowD2V2B->getConstructedBaseClass(), RecordB);
8599 EXPECT_TRUE(ShadowD2V2B->constructsVirtualBase());
8600
8601 EXPECT_TRUE(ShadowV1A->constructsVirtualBase());
8602 EXPECT_TRUE(ShadowV1B->constructsVirtualBase());
8603 EXPECT_TRUE(ShadowV2A->constructsVirtualBase());
8604 EXPECT_TRUE(ShadowV2B->constructsVirtualBase());
8605 EXPECT_FALSE(ShadowBA->constructsVirtualBase());
8606 };
8607
8608 auto *FromD2 = FirstDeclMatcher<CXXRecordDecl>().match(
8609 FromTU, cxxRecordDecl(hasName(Name: "D2")));
8610
8611 auto *ToD2 = Import(FromD2, Lang_CXX11);
8612 TranslationUnitDecl *ToTU = ToD2->getTranslationUnitDecl();
8613
8614 CheckAST(FromTU, FromD2);
8615 CheckAST(ToTU, ToD2);
8616}
8617
8618TEST_P(ASTImporterOptionSpecificTestBase, ImportUsingShadowList) {
8619 TranslationUnitDecl *FromTU = getTuDecl(
8620 SrcCode: R"(
8621 struct A {
8622 void f();
8623 void f(int);
8624 };
8625 struct B : A {
8626 using A::f;
8627 };
8628 )",
8629 Lang: Lang_CXX11);
8630
8631 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(
8632 FromTU, cxxRecordDecl(hasName(Name: "B")));
8633
8634 auto *ToB = Import(FromB, Lang_CXX11);
8635 TranslationUnitDecl *ToTU = ToB->getTranslationUnitDecl();
8636
8637 auto *ToUsing = FirstDeclMatcher<UsingDecl>().match(
8638 ToTU, usingDecl(hasParent(equalsNode(ToB))));
8639 auto *ToUsingShadowF1 = FirstDeclMatcher<UsingShadowDecl>().match(
8640 ToTU, usingShadowDecl(hasTargetDecl(
8641 InnerMatcher: functionDecl(hasName(Name: "f"), parameterCountIs(N: 0)))));
8642 auto *ToUsingShadowF2 = FirstDeclMatcher<UsingShadowDecl>().match(
8643 ToTU, usingShadowDecl(hasTargetDecl(
8644 InnerMatcher: functionDecl(hasName(Name: "f"), parameterCountIs(N: 1)))));
8645
8646 EXPECT_EQ(ToUsing->shadow_size(), 2u);
8647 auto ShadowI = ToUsing->shadow_begin();
8648 EXPECT_EQ(*ShadowI, ToUsingShadowF1);
8649 ++ShadowI;
8650 EXPECT_EQ(*ShadowI, ToUsingShadowF2);
8651}
8652
8653AST_MATCHER_P(FunctionTemplateDecl, templateParameterCountIs, unsigned, Cnt) {
8654 return Node.getTemplateParameters()->size() == Cnt;
8655}
8656
8657TEST_P(ASTImporterOptionSpecificTestBase, ImportDeductionGuide) {
8658 TranslationUnitDecl *FromTU = getTuDecl(
8659 SrcCode: R"(
8660 template<class> class A { };
8661 template<class T> class B {
8662 template<class T1, typename = A<T>> B(T1);
8663 };
8664 template<class T>
8665 B(T, T) -> B<int>;
8666 )",
8667 Lang: Lang_CXX17);
8668
8669 // Get the implicit deduction guide for (non-default) constructor of 'B'.
8670 auto *FromDGCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(
8671 FromTU, functionTemplateDecl(templateParameterCountIs(Cnt: 3)));
8672 // Implicit deduction guide for copy constructor of 'B'.
8673 auto *FromDGCopyCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(
8674 FromTU, functionTemplateDecl(templateParameterCountIs(Cnt: 1), isImplicit()));
8675 // User defined deduction guide.
8676 auto *FromDGOther = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8677 FromTU, cxxDeductionGuideDecl(unless(isImplicit())));
8678
8679 TemplateParameterList *FromDGCtorTP = FromDGCtor->getTemplateParameters();
8680 // Don't know why exactly but this is the DeclContext here.
8681 EXPECT_EQ(FromDGCtorTP->getParam(0)->getDeclContext(),
8682 FromDGCopyCtor->getTemplatedDecl());
8683 EXPECT_EQ(FromDGCtorTP->getParam(1)->getDeclContext(),
8684 FromDGCtor->getTemplatedDecl());
8685 EXPECT_EQ(FromDGCtorTP->getParam(2)->getDeclContext(),
8686 FromDGCtor->getTemplatedDecl());
8687 EXPECT_EQ(
8688 FromDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),
8689 FromDGCopyCtor->getTemplatedDecl());
8690 EXPECT_EQ(FromDGOther->getDescribedTemplate()
8691 ->getTemplateParameters()
8692 ->getParam(0)
8693 ->getDeclContext(),
8694 FromDGOther);
8695
8696 auto *ToDGCtor = Import(FromDGCtor, Lang_CXX17);
8697 auto *ToDGCopyCtor = Import(FromDGCopyCtor, Lang_CXX17);
8698 auto *ToDGOther = Import(FromDGOther, Lang_CXX17);
8699 ASSERT_TRUE(ToDGCtor);
8700 ASSERT_TRUE(ToDGCopyCtor);
8701 ASSERT_TRUE(ToDGOther);
8702
8703 TemplateParameterList *ToDGCtorTP = ToDGCtor->getTemplateParameters();
8704 EXPECT_EQ(ToDGCtorTP->getParam(0)->getDeclContext(),
8705 ToDGCopyCtor->getTemplatedDecl());
8706 EXPECT_EQ(ToDGCtorTP->getParam(1)->getDeclContext(),
8707 ToDGCtor->getTemplatedDecl());
8708 EXPECT_EQ(ToDGCtorTP->getParam(2)->getDeclContext(),
8709 ToDGCtor->getTemplatedDecl());
8710 EXPECT_EQ(
8711 ToDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),
8712 ToDGCopyCtor->getTemplatedDecl());
8713 EXPECT_EQ(ToDGOther->getDescribedTemplate()
8714 ->getTemplateParameters()
8715 ->getParam(0)
8716 ->getDeclContext(),
8717 ToDGOther);
8718}
8719
8720TEST_P(ASTImporterOptionSpecificTestBase, ImportDeductionGuideDifferentOrder) {
8721 // This test demonstrates that the DeclContext of the imported object is
8722 // dependent on the order of import. The test is an exact copy of the previous
8723 // one except at the indicated locations.
8724 TranslationUnitDecl *FromTU = getTuDecl(
8725 SrcCode: R"(
8726 template<class> class A { };
8727 template<class T> class B {
8728 template<class T1, typename = A<T>> B(T1);
8729 };
8730 template<class T>
8731 B(T, T) -> B<int>;
8732 )",
8733 Lang: Lang_CXX17);
8734
8735 // Get the implicit deduction guide for (non-default) constructor of 'B'.
8736 auto *FromDGCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(
8737 FromTU, functionTemplateDecl(templateParameterCountIs(Cnt: 3)));
8738 // Implicit deduction guide for copy constructor of 'B'.
8739 auto *FromDGCopyCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(
8740 FromTU, functionTemplateDecl(templateParameterCountIs(Cnt: 1), isImplicit()));
8741 // User defined deduction guide.
8742 auto *FromDGOther = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8743 FromTU, cxxDeductionGuideDecl(unless(isImplicit())));
8744
8745 TemplateParameterList *FromDGCtorTP = FromDGCtor->getTemplateParameters();
8746 // Don't know why exactly but this is the DeclContext here.
8747 EXPECT_EQ(FromDGCtorTP->getParam(0)->getDeclContext(),
8748 FromDGCopyCtor->getTemplatedDecl());
8749 EXPECT_EQ(FromDGCtorTP->getParam(1)->getDeclContext(),
8750 FromDGCtor->getTemplatedDecl());
8751 EXPECT_EQ(FromDGCtorTP->getParam(2)->getDeclContext(),
8752 FromDGCtor->getTemplatedDecl());
8753 EXPECT_EQ(
8754 FromDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),
8755 FromDGCopyCtor->getTemplatedDecl());
8756 EXPECT_EQ(FromDGOther->getDescribedTemplate()
8757 ->getTemplateParameters()
8758 ->getParam(0)
8759 ->getDeclContext(),
8760 FromDGOther);
8761
8762 // Here the import of 'ToDGCopyCtor' and 'ToDGCtor' is reversed relative to
8763 // the previous test.
8764 auto *ToDGCopyCtor = Import(FromDGCopyCtor, Lang_CXX17);
8765 auto *ToDGCtor = Import(FromDGCtor, Lang_CXX17);
8766 auto *ToDGOther = Import(FromDGOther, Lang_CXX17);
8767 ASSERT_TRUE(ToDGCtor);
8768 ASSERT_TRUE(ToDGCopyCtor);
8769 ASSERT_TRUE(ToDGOther);
8770
8771 TemplateParameterList *ToDGCtorTP = ToDGCtor->getTemplateParameters();
8772 // Next line: DeclContext is different relative to the previous test.
8773 EXPECT_EQ(ToDGCtorTP->getParam(0)->getDeclContext(),
8774 ToDGCtor->getTemplatedDecl());
8775 EXPECT_EQ(ToDGCtorTP->getParam(1)->getDeclContext(),
8776 ToDGCtor->getTemplatedDecl());
8777 EXPECT_EQ(ToDGCtorTP->getParam(2)->getDeclContext(),
8778 ToDGCtor->getTemplatedDecl());
8779 // Next line: DeclContext is different relative to the previous test.
8780 EXPECT_EQ(
8781 ToDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),
8782 ToDGCtor->getTemplatedDecl());
8783 EXPECT_EQ(ToDGOther->getDescribedTemplate()
8784 ->getTemplateParameters()
8785 ->getParam(0)
8786 ->getDeclContext(),
8787 ToDGOther);
8788}
8789
8790TEST_P(ASTImporterOptionSpecificTestBase,
8791 ImportFieldsFirstForCorrectRecordLayout) {
8792 // UnaryOperator(&) triggers RecordLayout computation, which relies on
8793 // correctly imported fields.
8794 auto Code =
8795 R"(
8796 class A {
8797 int m() {
8798 return &((A *)0)->f1 - &((A *)0)->f2;
8799 }
8800 int f1;
8801 int f2;
8802 };
8803 )";
8804 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
8805
8806 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
8807 D: FromTU, AMatcher: cxxMethodDecl(hasName(Name: "A::m")));
8808 Import(FromF, Lang_CXX11);
8809}
8810
8811TEST_P(ASTImporterOptionSpecificTestBase,
8812 ImportCirularRefFieldsWithoutCorruptedRecordLayoutCache) {
8813 // Import sequence: A => A.b => B => B.f() => ... => UnaryOperator(&) => ...
8814 //
8815 // UnaryOperator(&) should not introduce invalid RecordLayout since 'A' is
8816 // still not completely imported.
8817 auto Code =
8818 R"(
8819 class B;
8820 class A {
8821 B* b;
8822 int c;
8823 };
8824 class B {
8825 A *f() { return &((B *)0)->a; }
8826 A a;
8827 };
8828 )";
8829
8830 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
8831 getTuDecl(SrcCode: Code, Lang: Lang_CXX11), cxxRecordDecl(hasName(Name: "A")));
8832 FromR = FromR->getDefinition();
8833 auto &FromAST = FromR->getASTContext();
8834 auto *ToR = Import(FromR, Lang_CXX11);
8835 auto &ToAST = ToR->getASTContext();
8836
8837 uint64_t SecondFieldOffset = FromAST.getTypeSize(FromAST.VoidPtrTy);
8838
8839 EXPECT_TRUE(FromR->isCompleteDefinition());
8840 const auto &FromLayout = FromAST.getASTRecordLayout(FromR);
8841 EXPECT_TRUE(FromLayout.getFieldOffset(0) == 0);
8842 EXPECT_TRUE(FromLayout.getFieldOffset(1) == SecondFieldOffset);
8843
8844 EXPECT_TRUE(ToR->isCompleteDefinition());
8845 const auto &ToLayout = ToAST.getASTRecordLayout(ToR);
8846 EXPECT_TRUE(ToLayout.getFieldOffset(0) == 0);
8847 EXPECT_TRUE(ToLayout.getFieldOffset(1) == SecondFieldOffset);
8848}
8849
8850TEST_P(ASTImporterOptionSpecificTestBase,
8851 ImportRecordWithLayoutRequestingExpr) {
8852 TranslationUnitDecl *FromTU = getTuDecl(
8853 SrcCode: R"(
8854 struct A {
8855 int idx;
8856 static void foo(A x) {
8857 (void)&"text"[x.idx];
8858 }
8859 };
8860 )",
8861 Lang: Lang_CXX11);
8862
8863 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
8864 FromTU, cxxRecordDecl(hasName(Name: "A")));
8865
8866 // Test that during import of 'foo' the record layout can be obtained without
8867 // crash.
8868 auto *ToA = Import(FromA, Lang_CXX11);
8869 EXPECT_TRUE(ToA);
8870 EXPECT_TRUE(ToA->isCompleteDefinition());
8871}
8872
8873TEST_P(ASTImporterOptionSpecificTestBase,
8874 ImportRecordWithLayoutRequestingExprDifferentRecord) {
8875 TranslationUnitDecl *FromTU = getTuDecl(
8876 SrcCode: R"(
8877 struct B;
8878 struct A {
8879 int idx;
8880 B *b;
8881 };
8882 struct B {
8883 static void foo(A x) {
8884 (void)&"text"[x.idx];
8885 }
8886 };
8887 )",
8888 Lang: Lang_CXX11);
8889
8890 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
8891 FromTU, cxxRecordDecl(hasName(Name: "A")));
8892
8893 // Test that during import of 'foo' the record layout (of 'A') can be obtained
8894 // without crash. It is not possible to have all of the fields of 'A' imported
8895 // at that time (without big code changes).
8896 auto *ToA = Import(FromA, Lang_CXX11);
8897 EXPECT_TRUE(ToA);
8898 EXPECT_TRUE(ToA->isCompleteDefinition());
8899}
8900
8901TEST_P(ASTImporterOptionSpecificTestBase, ImportInClassInitializerFromField) {
8902 // Encounter import of a field when the field already exists but has the
8903 // in-class initializer expression not yet set. Such case can occur in the AST
8904 // of generated template specializations.
8905 // The first code forces to create a template specialization of
8906 // `A<int>` but without implicit constructors.
8907 // The second ("From") code contains a variable of type `A<int>`, this
8908 // results in a template specialization that has constructors and
8909 // CXXDefaultInitExpr nodes.
8910 Decl *ToTU = getToTuDecl(
8911 ToSrcCode: R"(
8912 void f();
8913 template<typename> struct A { int X = 1; };
8914 struct B { A<int> Y; };
8915 )",
8916 ToLang: Lang_CXX11);
8917 auto *ToX = FirstDeclMatcher<FieldDecl>().match(
8918 D: ToTU,
8919 AMatcher: fieldDecl(hasName(Name: "X"), hasParent(classTemplateSpecializationDecl())));
8920 ASSERT_TRUE(ToX->hasInClassInitializer());
8921 ASSERT_FALSE(ToX->getInClassInitializer());
8922
8923 Decl *FromTU = getTuDecl(
8924 SrcCode: R"(
8925 void f();
8926 template<typename> struct A { int X = 1; };
8927 struct B { A<int> Y; };
8928 //
8929 A<int> Z;
8930 )",
8931 Lang: Lang_CXX11, FileName: "input1.cc");
8932 auto *FromX = FirstDeclMatcher<FieldDecl>().match(
8933 D: FromTU,
8934 AMatcher: fieldDecl(hasName(Name: "X"), hasParent(classTemplateSpecializationDecl())));
8935
8936 auto *ToXImported = Import(FromX, Lang_CXX11);
8937 EXPECT_EQ(ToXImported, ToX);
8938 EXPECT_TRUE(ToX->getInClassInitializer());
8939}
8940
8941TEST_P(ASTImporterOptionSpecificTestBase,
8942 ImportInClassInitializerFromCXXDefaultInitExpr) {
8943 // Encounter AST import of a CXXDefaultInitExpr where the "to-field"
8944 // of it exists but has the in-class initializer not set yet.
8945 Decl *ToTU = getToTuDecl(
8946 ToSrcCode: R"(
8947 namespace N {
8948 template<typename> int b;
8949 struct X;
8950 }
8951 template<typename> struct A { N::X *X = nullptr; };
8952 struct B { A<int> Y; };
8953 )",
8954 ToLang: Lang_CXX14);
8955 auto *ToX = FirstDeclMatcher<FieldDecl>().match(
8956 D: ToTU,
8957 AMatcher: fieldDecl(hasName(Name: "X"), hasParent(classTemplateSpecializationDecl())));
8958 ASSERT_TRUE(ToX->hasInClassInitializer());
8959 ASSERT_FALSE(ToX->getInClassInitializer());
8960
8961 Decl *FromTU = getTuDecl(
8962 SrcCode: R"(
8963 namespace N {
8964 template<typename> int b;
8965 struct X;
8966 }
8967 template<typename> struct A { N::X *X = nullptr; };
8968 struct B { A<int> Y; };
8969 //
8970 void f() {
8971 (void)A<int>{};
8972 }
8973 struct C {
8974 C(): attr(new A<int>{}){}
8975 A<int> *attr;
8976 const int value = N::b<C>;
8977 };
8978 )",
8979 Lang: Lang_CXX14, FileName: "input1.cc");
8980 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
8981 D: FromTU, AMatcher: functionDecl(hasName(Name: "f"), isDefinition()));
8982 auto *ToF = Import(FromF, Lang_CXX11);
8983 EXPECT_TRUE(ToF);
8984 EXPECT_TRUE(ToX->getInClassInitializer());
8985}
8986
8987TEST_P(ASTImporterOptionSpecificTestBase, ImportRecursiveFieldInitializer) {
8988 const char *Code =
8989 R"(
8990 struct AP_TECS;
8991
8992 struct AP_Landing {
8993 AP_TECS *TECS_controller;
8994 };
8995
8996 struct AP_TECS {
8997 AP_Landing landing;
8998 };
8999
9000 class Plane {
9001 AP_TECS TECS_controller{landing};
9002 AP_Landing landing{&TECS_controller};
9003 };
9004 )";
9005 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9006
9007 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
9008 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "Plane")));
9009 for (FieldDecl *F : FromR->fields())
9010 EXPECT_TRUE(F->getInClassInitializer());
9011 auto *ToR = Import(FromR, Lang_CXX11);
9012 for (FieldDecl *F : ToR->fields())
9013 EXPECT_TRUE(F->getInClassInitializer());
9014}
9015
9016TEST_P(ASTImporterOptionSpecificTestBase, ImportFieldInitializerWithItself) {
9017 const char *Code =
9018 R"(
9019 class A {
9020 int a{a};
9021 };
9022 )";
9023 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9024 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9025 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
9026 EXPECT_TRUE(FromA->field_begin()->getInClassInitializer());
9027 auto *ToA = Import(FromA, Lang_CXX11);
9028 EXPECT_TRUE(ToA->field_begin()->getInClassInitializer());
9029}
9030
9031TEST_P(ASTImporterOptionSpecificTestBase, ImportRecursiveFieldInitializer1) {
9032 // FIXME: This is a example of recursive field initialization that is not
9033 // supported.
9034 // The following import chain occurs (not complete):
9035 // import of A => A.a => in-class initializer of A.a => ref_B() => B => B.b
9036 // => in-class initializer of B.b => ref_A() => CXXConstructExpr for A =>
9037 // CXXDefaultInitExpr for A.a => in-class initializer of A.a
9038 // in-class initializer of A.a is created in two different instances in this
9039 // case (import of FieldDecl and CXXDefaultInitExpr). Probably not a big
9040 // problem because it is an Expr (the second construction can be ignored
9041 // instead of assert). But such recursive init code should not occur in
9042 // practice.
9043 const char *Code =
9044 R"(
9045 static int ref_A();
9046 static int ref_B();
9047 struct A {
9048 int a = ref_B();
9049 };
9050 struct B {
9051 int b = ref_A();
9052 };
9053 int ref_B() { B b; return b.b; }
9054 int ref_A() { A a; return a.a; }
9055 )";
9056 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9057 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9058 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
9059 EXPECT_TRUE(FromA->field_begin()->getInClassInitializer());
9060 // auto *ToA = Import(FromA, Lang_CXX11);
9061 // EXPECT_TRUE(ToA->field_begin()->getInClassInitializer());
9062}
9063
9064TEST_P(ASTImporterOptionSpecificTestBase, isNewDecl) {
9065 Decl *FromTU = getTuDecl(
9066 SrcCode: R"(
9067 int bar() {
9068 return 0;
9069 }
9070 void other() {
9071 bar();
9072 }
9073 )",
9074 Lang: Lang_CXX11);
9075 Decl *ToTU = getToTuDecl(
9076 ToSrcCode: R"(
9077 int bar() {
9078 return 0;
9079 }
9080 )",
9081 ToLang: Lang_CXX11);
9082 auto *FromOther = FirstDeclMatcher<FunctionDecl>().match(
9083 D: FromTU, AMatcher: functionDecl(hasName(Name: "other")));
9084 ASSERT_TRUE(FromOther);
9085
9086 auto *ToOther = Import(FromOther, Lang_CXX11);
9087 ASSERT_TRUE(ToOther);
9088
9089 auto *ToBar = FirstDeclMatcher<FunctionDecl>().match(
9090 D: ToTU, AMatcher: functionDecl(hasName(Name: "bar")));
9091
9092 EXPECT_TRUE(SharedStatePtr->isNewDecl(ToOther));
9093 EXPECT_FALSE(SharedStatePtr->isNewDecl(ToBar));
9094}
9095
9096struct ImportInjectedClassNameType : public ASTImporterOptionSpecificTestBase {
9097protected:
9098 const CXXRecordDecl *findInjected(const CXXRecordDecl *Parent) {
9099 for (Decl *Found : Parent->decls()) {
9100 const auto *Record = dyn_cast<CXXRecordDecl>(Found);
9101 if (Record && Record->isInjectedClassName())
9102 return Record;
9103 }
9104 return nullptr;
9105 }
9106
9107 void checkInjType(const CXXRecordDecl *D) {
9108 // The whole redecl chain should have the same InjectedClassNameType
9109 // instance. The injected record declaration is a separate chain, this
9110 // should contain the same type too.
9111 const Type *Ty = nullptr;
9112 for (const Decl *ReD : D->redecls()) {
9113 const auto *ReRD = cast<CXXRecordDecl>(ReD);
9114 EXPECT_TRUE(ReRD->getTypeForDecl());
9115 EXPECT_TRUE(!Ty || Ty == ReRD->getTypeForDecl());
9116 Ty = ReRD->getTypeForDecl();
9117 }
9118 ASSERT_TRUE(Ty);
9119 const auto *InjTy = Ty->castAs<InjectedClassNameType>();
9120 EXPECT_TRUE(InjTy);
9121 if (CXXRecordDecl *Def = D->getDefinition()) {
9122 const CXXRecordDecl *InjRD = findInjected(Parent: Def);
9123 EXPECT_TRUE(InjRD);
9124 EXPECT_EQ(InjRD->getTypeForDecl(), InjTy);
9125 }
9126 }
9127
9128 void testImport(Decl *ToTU, Decl *FromTU, Decl *FromD) {
9129 checkInjType(D: cast<CXXRecordDecl>(Val: FromD));
9130 Decl *ToD = Import(From: FromD, ToLang: Lang_CXX11);
9131 if (auto *ToRD = dyn_cast<CXXRecordDecl>(Val: ToD))
9132 checkInjType(D: ToRD);
9133 }
9134
9135 const char *ToCodeA =
9136 R"(
9137 template <class T>
9138 struct A;
9139 )";
9140 const char *ToCodeADef =
9141 R"(
9142 template <class T>
9143 struct A {
9144 typedef A T1;
9145 };
9146 )";
9147 const char *ToCodeC =
9148 R"(
9149 template <class T>
9150 struct C;
9151 )";
9152 const char *ToCodeCDef =
9153 R"(
9154 template <class T>
9155 struct A {
9156 typedef A T1;
9157 };
9158
9159 template <class T1, class T2>
9160 struct B {};
9161
9162 template<class T>
9163 struct C {
9164 typedef typename A<T>::T1 T1;
9165 typedef B<T1, T> T2;
9166 typedef B<T1, C> T3;
9167 };
9168 )";
9169 const char *FromCode =
9170 R"(
9171 template <class T>
9172 struct A;
9173 template <class T>
9174 struct A {
9175 typedef A T1;
9176 };
9177 template <class T>
9178 struct A;
9179
9180 template <class T1, class T2>
9181 struct B {};
9182
9183 template <class T>
9184 struct C;
9185 template <class T>
9186 struct C {
9187 typedef typename A<T>::T1 T1;
9188 typedef B<T1, T> T2;
9189 typedef B<T1, C> T3;
9190 };
9191 template <class T>
9192 struct C;
9193
9194 template <class T>
9195 struct D {
9196 void f(typename C<T>::T3 *);
9197 };
9198 )";
9199};
9200
9201TEST_P(ImportInjectedClassNameType, ImportADef) {
9202 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeA, ToLang: Lang_CXX11);
9203 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9204 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9205 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A"), isDefinition()));
9206 testImport(ToTU, FromTU, FromD: FromA);
9207}
9208
9209TEST_P(ImportInjectedClassNameType, ImportAFirst) {
9210 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeA, ToLang: Lang_CXX11);
9211 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9212 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9213 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
9214 testImport(ToTU, FromTU, FromD: FromA);
9215}
9216
9217TEST_P(ImportInjectedClassNameType, ImportALast) {
9218 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeA, ToLang: Lang_CXX11);
9219 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9220 auto *FromA = LastDeclMatcher<CXXRecordDecl>().match(
9221 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
9222 testImport(ToTU, FromTU, FromD: FromA);
9223}
9224
9225TEST_P(ImportInjectedClassNameType, ImportADefToDef) {
9226 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeADef, ToLang: Lang_CXX11);
9227 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9228 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9229 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A"), isDefinition()));
9230 testImport(ToTU, FromTU, FromD: FromA);
9231}
9232
9233TEST_P(ImportInjectedClassNameType, ImportAFirstToDef) {
9234 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeADef, ToLang: Lang_CXX11);
9235 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9236 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9237 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
9238 testImport(ToTU, FromTU, FromD: FromA);
9239}
9240
9241TEST_P(ImportInjectedClassNameType, ImportALastToDef) {
9242 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeADef, ToLang: Lang_CXX11);
9243 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9244 auto *FromA = LastDeclMatcher<CXXRecordDecl>().match(
9245 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
9246 testImport(ToTU, FromTU, FromD: FromA);
9247}
9248
9249TEST_P(ImportInjectedClassNameType, ImportCDef) {
9250 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeC, ToLang: Lang_CXX11);
9251 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9252 auto *FromC = FirstDeclMatcher<CXXRecordDecl>().match(
9253 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "C"), isDefinition()));
9254 testImport(ToTU, FromTU, FromD: FromC);
9255}
9256
9257TEST_P(ImportInjectedClassNameType, ImportCLast) {
9258 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeC, ToLang: Lang_CXX11);
9259 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9260 auto *FromC = LastDeclMatcher<CXXRecordDecl>().match(
9261 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "C")));
9262 testImport(ToTU, FromTU, FromD: FromC);
9263}
9264
9265TEST_P(ImportInjectedClassNameType, ImportCDefToDef) {
9266 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeCDef, ToLang: Lang_CXX11);
9267 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9268 auto *FromC = FirstDeclMatcher<CXXRecordDecl>().match(
9269 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "C"), isDefinition()));
9270 testImport(ToTU, FromTU, FromD: FromC);
9271}
9272
9273TEST_P(ImportInjectedClassNameType, ImportCLastToDef) {
9274 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeCDef, ToLang: Lang_CXX11);
9275 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9276 auto *FromC = LastDeclMatcher<CXXRecordDecl>().match(
9277 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "C")));
9278 testImport(ToTU, FromTU, FromD: FromC);
9279}
9280
9281TEST_P(ImportInjectedClassNameType, ImportD) {
9282 Decl *ToTU = getToTuDecl(ToSrcCode: "", ToLang: Lang_CXX11);
9283 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9284 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
9285 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "D"), isDefinition()));
9286 testImport(ToTU, FromTU, FromD: FromD);
9287}
9288
9289TEST_P(ImportInjectedClassNameType, ImportDToDef) {
9290 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeCDef, ToLang: Lang_CXX11);
9291 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9292 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
9293 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "D"), isDefinition()));
9294 testImport(ToTU, FromTU, FromD: FromD);
9295}
9296
9297TEST_P(ImportInjectedClassNameType, ImportTypedefType) {
9298 Decl *ToTU = getToTuDecl(
9299 ToSrcCode: R"(
9300 template <class T>
9301 struct A {
9302 typedef A A1;
9303 void f(A1 *);
9304 };
9305 )",
9306 ToLang: Lang_CXX11);
9307 Decl *FromTU = getTuDecl(
9308 SrcCode: R"(
9309 template <class T>
9310 struct A {
9311 typedef A A1;
9312 void f(A1 *);
9313 };
9314 template<class T>
9315 void A<T>::f(A::A1 *) {}
9316 )",
9317 Lang: Lang_CXX11);
9318
9319 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
9320 D: FromTU, AMatcher: functionDecl(hasName(Name: "f"), isDefinition()));
9321 auto *ToF = Import(FromF, Lang_CXX11);
9322 EXPECT_TRUE(ToF);
9323 ASTContext &ToCtx = ToF->getDeclContext()->getParentASTContext();
9324
9325 auto *ToA1 =
9326 FirstDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "A1")));
9327 QualType ToInjTypedef = ToA1->getUnderlyingType().getCanonicalType();
9328 QualType ToInjParmVar =
9329 ToF->parameters()[0]->getType().getDesugaredType(ToCtx);
9330 ToInjParmVar =
9331 ToInjParmVar->getAs<PointerType>()->getPointeeType().getCanonicalType();
9332 EXPECT_TRUE(isa<InjectedClassNameType>(ToInjTypedef));
9333 EXPECT_TRUE(isa<InjectedClassNameType>(ToInjParmVar));
9334 EXPECT_TRUE(ToCtx.hasSameType(ToInjTypedef, ToInjParmVar));
9335}
9336
9337TEST_P(ASTImporterOptionSpecificTestBase, ImportMacroQualifiedType) {
9338 Decl *From, *To;
9339 std::tie(args&: From, args&: To) = getImportedDecl(
9340 FromSrcCode: R"(
9341 #define CDECL __attribute__((cdecl))
9342 typedef void (CDECL *X)();
9343 )",
9344 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03, Identifier: "X");
9345
9346 auto *FromTy =
9347 FirstDeclMatcher<MacroQualifiedType>().match(D: From, AMatcher: macroQualifiedType());
9348 auto *ToTy =
9349 FirstDeclMatcher<MacroQualifiedType>().match(D: To, AMatcher: macroQualifiedType());
9350
9351 EXPECT_TRUE(isa<AttributedType>(FromTy->getUnderlyingType()));
9352 EXPECT_TRUE(isa<AttributedType>(ToTy->getUnderlyingType()));
9353}
9354
9355TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplateName) {
9356 constexpr auto TestCode = R"(
9357 template <class T>
9358 struct A;
9359 template <class T>
9360 struct A {};
9361 template <template<class> class T = A>
9362 struct B {};
9363 using C = B<>;
9364 )";
9365 Decl *ToTU = getToTuDecl(ToSrcCode: TestCode, ToLang: Lang_CXX11);
9366 Decl *FromTU = getTuDecl(SrcCode: TestCode, Lang: Lang_CXX11);
9367
9368 auto *ToUsingFirst = FirstDeclMatcher<TypeAliasDecl>().match(
9369 D: ToTU, AMatcher: typeAliasDecl(hasName(Name: "C")));
9370
9371 auto *FromUsing = FirstDeclMatcher<TypeAliasDecl>().match(
9372 D: FromTU, AMatcher: typeAliasDecl(hasName(Name: "C")));
9373 auto *ToUsing = Import(FromUsing, Lang_CXX11);
9374 EXPECT_TRUE(ToUsing);
9375
9376 auto *ToB = FirstDeclMatcher<ClassTemplateDecl>().match(
9377 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "B")));
9378 auto *ToB1 = LastDeclMatcher<ClassTemplateDecl>().match(
9379 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "B")));
9380 // One template definition of 'B' should exist.
9381 EXPECT_EQ(ToB, ToB1);
9382
9383 // These declarations are imported separately.
9384 EXPECT_NE(ToUsingFirst, ToUsing);
9385
9386 auto SpB = ToB->spec_begin();
9387 auto SpE = ToB->spec_end();
9388 EXPECT_TRUE(SpB != SpE);
9389 ClassTemplateSpecializationDecl *Spec1 = *SpB;
9390 ++SpB;
9391 // The template 'B' should have one specialization (with default argument).
9392 EXPECT_TRUE(SpB == SpE);
9393
9394 // Even if 'B' has one specialization with the default arguments, the AST
9395 // contains after the import two specializations that are linked in the
9396 // declaration chain. The 'spec_begin' iteration does not find these because
9397 // the template arguments are the same. But the imported type alias has the
9398 // link to the second specialization. The template name object in these
9399 // specializations must point to the same (and one) instance of definition of
9400 // 'B'.
9401 auto *Spec2 = cast<ClassTemplateSpecializationDecl>(
9402 ToUsing->getUnderlyingType()
9403 ->getAs<TemplateSpecializationType>()
9404 ->getAsRecordDecl());
9405 EXPECT_NE(Spec1, Spec2);
9406 EXPECT_TRUE(Spec1->getPreviousDecl() == Spec2 ||
9407 Spec2->getPreviousDecl() == Spec1);
9408 TemplateDecl *Templ1 =
9409 Spec1->getTemplateArgs()[0].getAsTemplate().getAsTemplateDecl();
9410 TemplateDecl *Templ2 =
9411 Spec2->getTemplateArgs()[0].getAsTemplate().getAsTemplateDecl();
9412 EXPECT_EQ(Templ1, Templ2);
9413}
9414
9415TEST_P(ASTImporterOptionSpecificTestBase, VaListC) {
9416 Decl *FromTU = getTuDecl(SrcCode: R"(typedef __builtin_va_list va_list;)", Lang: Lang_C99);
9417
9418 auto *FromVaList = FirstDeclMatcher<TypedefDecl>().match(
9419 D: FromTU, AMatcher: typedefDecl(hasName(Name: "va_list")));
9420 ASSERT_TRUE(FromVaList);
9421
9422 auto *ToVaList = Import(FromVaList, Lang_C99);
9423 ASSERT_TRUE(ToVaList);
9424
9425 auto *ToBuiltinVaList = FirstDeclMatcher<TypedefDecl>().match(
9426 ToAST->getASTContext().getTranslationUnitDecl(),
9427 typedefDecl(hasName(Name: "__builtin_va_list")));
9428
9429 ASSERT_TRUE(ToAST->getASTContext().hasSameType(
9430 ToVaList->getUnderlyingType(), ToBuiltinVaList->getUnderlyingType()));
9431}
9432
9433TEST_P(ASTImporterOptionSpecificTestBase, VaListCpp) {
9434 Decl *FromTU = getTuDecl(SrcCode: R"(typedef __builtin_va_list va_list;)", Lang: Lang_CXX03);
9435
9436 auto *FromVaList = FirstDeclMatcher<TypedefDecl>().match(
9437 D: FromTU, AMatcher: typedefDecl(hasName(Name: "va_list")));
9438 ASSERT_TRUE(FromVaList);
9439
9440 auto *ToVaList = Import(FromVaList, Lang_CXX03);
9441 ASSERT_TRUE(ToVaList);
9442
9443 auto *ToBuiltinVaList = FirstDeclMatcher<TypedefDecl>().match(
9444 ToAST->getASTContext().getTranslationUnitDecl(),
9445 typedefDecl(hasName(Name: "__builtin_va_list")));
9446
9447 ASSERT_TRUE(ToAST->getASTContext().hasSameType(
9448 ToVaList->getUnderlyingType(), ToBuiltinVaList->getUnderlyingType()));
9449}
9450
9451TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingTypedefToRecord) {
9452 const char *Code =
9453 R"(
9454 struct S { int i; };
9455 typedef struct S T;
9456 extern T x;
9457 )";
9458 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_C99);
9459 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_C99);
9460
9461 auto *FromX =
9462 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "x")));
9463 auto *ToX = Import(FromX, Lang_C99);
9464 EXPECT_TRUE(ToX);
9465
9466 auto *Typedef1 =
9467 FirstDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T")));
9468 auto *Typedef2 =
9469 LastDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T")));
9470 EXPECT_EQ(Typedef1, Typedef2);
9471}
9472
9473TEST_P(ASTImporterOptionSpecificTestBase,
9474 ImportExistingTypedefToUnnamedRecord) {
9475 const char *Code =
9476 R"(
9477 typedef const struct { int f; } T;
9478 extern T x;
9479 )";
9480 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_C99);
9481 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_C99);
9482
9483 auto *FromX =
9484 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "x")));
9485 auto *ToX = Import(FromX, Lang_C99);
9486 EXPECT_TRUE(ToX);
9487
9488 auto *Typedef1 =
9489 FirstDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T")));
9490 auto *Typedef2 =
9491 LastDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T")));
9492 EXPECT_NE(Typedef1, Typedef2);
9493 EXPECT_NE(Typedef1->getUnderlyingType().getTypePtr(),
9494 Typedef2->getUnderlyingType().getTypePtr());
9495 EXPECT_EQ(ToX->getType()->getAs<TypedefType>()->getDecl(), Typedef2);
9496}
9497
9498TEST_P(ASTImporterOptionSpecificTestBase, ImportTwoTypedefsToUnnamedRecord) {
9499 const char *Code =
9500 R"(
9501 typedef struct { int f; } T1;
9502 typedef struct { int f; } T2;
9503 extern T1 x1;
9504 extern T2 x2;
9505 )";
9506 Decl *ToTU = getToTuDecl(ToSrcCode: "", ToLang: Lang_C99);
9507 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_C99);
9508
9509 auto *FromX1 =
9510 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "x1")));
9511 auto *FromX2 =
9512 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "x2")));
9513 auto *ToX1 = Import(FromX1, Lang_C99);
9514 EXPECT_TRUE(ToX1);
9515 auto *ToX2 = Import(FromX2, Lang_C99);
9516 EXPECT_TRUE(ToX2);
9517
9518 auto *Typedef1 =
9519 FirstDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T1")));
9520 auto *Typedef2 =
9521 FirstDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T2")));
9522 EXPECT_NE(Typedef1->getUnderlyingType().getTypePtr(),
9523 Typedef2->getUnderlyingType().getTypePtr());
9524}
9525
9526TEST_P(ASTImporterOptionSpecificTestBase,
9527 ImportExistingTypedefToUnnamedRecordPtr) {
9528 const char *Code =
9529 R"(
9530 typedef const struct { int fff; } * const T;
9531 extern T x;
9532 )";
9533 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_C99);
9534 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_C99);
9535
9536 auto *FromX =
9537 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "x")));
9538 auto *ToX = Import(FromX, Lang_C99);
9539 EXPECT_TRUE(ToX);
9540
9541 auto *Typedef1 =
9542 FirstDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T")));
9543 auto *Typedef2 =
9544 LastDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T")));
9545 // FIXME: These should be imported separately, like in the test above.
9546 // Or: In the test above these should be merged too.
9547 EXPECT_EQ(Typedef1, Typedef2);
9548
9549 auto *FromR = FirstDeclMatcher<RecordDecl>().match(
9550 D: FromTU, AMatcher: recordDecl(hasDescendant(fieldDecl(hasName(Name: "fff")))));
9551 auto *ToRExisting = FirstDeclMatcher<RecordDecl>().match(
9552 D: ToTU, AMatcher: recordDecl(hasDescendant(fieldDecl(hasName(Name: "fff")))));
9553 ASSERT_TRUE(FromR);
9554 auto *ToRImported = Import(FromR, Lang_C99);
9555 // FIXME: If typedefs are not imported separately, do not import ToRImported
9556 // separately.
9557 EXPECT_NE(ToRExisting, ToRImported);
9558}
9559
9560TEST_P(ASTImporterOptionSpecificTestBase,
9561 ImportTypedefWithDifferentUnderlyingType) {
9562 const char *Code =
9563 R"(
9564 using X1 = int;
9565 using Y1 = int;
9566
9567 using RPB1 = X1*;
9568 typedef RPB1 RPX1;
9569 using RPB1 = Y1*; // redeclared
9570 typedef RPB1 RPY1;
9571
9572 auto X = 0 ? (RPX1){} : (RPY1){};
9573 )";
9574 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9575
9576 auto *FromX =
9577 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "X")));
9578
9579 auto *FromXType = FromX->getType()->getAs<TypedefType>();
9580 EXPECT_FALSE(FromXType->typeMatchesDecl());
9581
9582 auto *ToX = Import(FromX, Lang_CXX11);
9583 auto *ToXType = ToX->getType()->getAs<TypedefType>();
9584 // FIXME: This should be false.
9585 EXPECT_TRUE(ToXType->typeMatchesDecl());
9586}
9587
9588TEST_P(ASTImporterOptionSpecificTestBase,
9589 ImportTemplateArgumentWithPointerToDifferentInstantiation) {
9590 const char *CodeTo =
9591 R"(
9592 template<class A>
9593 A f1() {
9594 return A();
9595 }
9596 template<class A, A (B)()>
9597 class X {};
9598
9599 X<int, f1<int>> x;
9600 )";
9601 const char *CodeFrom =
9602 R"(
9603 template<class A>
9604 A f1();
9605 template<class A, A (B)()>
9606 class X {};
9607
9608 X<int, f1<int>> x;
9609 )";
9610 Decl *ToTU = getToTuDecl(ToSrcCode: CodeTo, ToLang: Lang_CXX11);
9611 Decl *FromTU = getTuDecl(SrcCode: CodeFrom, Lang: Lang_CXX11);
9612
9613 auto *ToF1 = FirstDeclMatcher<FunctionDecl>().match(
9614 D: ToTU, AMatcher: functionDecl(hasName(Name: "f1"), isInstantiated()));
9615 auto *FromF1 = FirstDeclMatcher<FunctionDecl>().match(
9616 D: FromTU, AMatcher: functionDecl(hasName(Name: "f1"), isInstantiated()));
9617 EXPECT_TRUE(ToF1->isThisDeclarationADefinition());
9618 EXPECT_FALSE(FromF1->isThisDeclarationADefinition());
9619
9620 auto *ToX = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
9621 D: ToTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
9622 auto *FromX = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
9623 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
9624
9625 Decl *ToTArgF = ToX->getTemplateArgs().get(1).getAsDecl();
9626 Decl *FromTArgF = FromX->getTemplateArgs().get(1).getAsDecl();
9627 EXPECT_EQ(ToTArgF, ToF1);
9628 EXPECT_EQ(FromTArgF, FromF1);
9629
9630 auto *ToXImported = Import(FromX, Lang_CXX11);
9631 // The template argument 1 of 'X' in the "From" code points to a function
9632 // that has no definition. The import must ensure that this template argument
9633 // is imported in a way that it will point to the existing 'f1' function, not
9634 // to the 'f1' that is imported. In this way when specialization of 'X' is
9635 // imported it will have the same template arguments as the existing one.
9636 EXPECT_EQ(ToXImported, ToX);
9637 // FIXME: This matcher causes a crash "Tried to match orphan node".
9638 // The code is removed until the problem is fixed.
9639 // auto *ToF1Imported =
9640 // LastDeclMatcher<FunctionDecl>().match(ToTU,
9641 // functionDecl(hasName("f1"),isInstantiated()));
9642 // EXPECT_NE(ToF1Imported, ToF1);
9643 // EXPECT_EQ(ToF1Imported->getPreviousDecl(), ToF1);
9644}
9645
9646TEST_P(ASTImporterOptionSpecificTestBase,
9647 ImportTypeAliasTemplateAfterSimilarCalledTemplateTypeParm) {
9648 const char *Code =
9649 R"(
9650 struct S;
9651 template <typename>
9652 using Callable = S;
9653 template <typename Callable>
9654 int bindingFunctionVTable;
9655 )";
9656 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX17);
9657
9658 auto *FromCallable = FirstDeclMatcher<TypeAliasTemplateDecl>().match(
9659 D: FromTU, AMatcher: typeAliasTemplateDecl(hasName(Name: "Callable")));
9660
9661 auto *FromCallableParm = FirstDeclMatcher<TemplateTypeParmDecl>().match(
9662 D: FromTU, AMatcher: templateTypeParmDecl(hasName(Name: "Callable")));
9663
9664 auto *ToFromCallableParm = Import(FromCallableParm, Lang_CXX17);
9665 auto *ToCallable = Import(FromCallable, Lang_CXX17);
9666 EXPECT_TRUE(ToFromCallableParm);
9667 EXPECT_TRUE(ToCallable);
9668}
9669
9670TEST_P(ASTImporterOptionSpecificTestBase, ImportConflictTypeAliasTemplate) {
9671 const char *ToCode =
9672 R"(
9673 struct S;
9674 template <typename, typename>
9675 using Callable = S;
9676 )";
9677 const char *Code =
9678 R"(
9679 struct S;
9680 template <typename>
9681 using Callable = S;
9682 )";
9683 (void)getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX17);
9684 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX17);
9685
9686 auto *FromCallable = FirstDeclMatcher<TypeAliasTemplateDecl>().match(
9687 D: FromTU, AMatcher: typeAliasTemplateDecl(hasName(Name: "Callable")));
9688
9689 auto *ImportedCallable = Import(FromCallable, Lang_CXX17);
9690 EXPECT_FALSE(ImportedCallable);
9691}
9692
9693AST_MATCHER(ClassTemplateSpecializationDecl, hasInstantiatedFromMember) {
9694 if (auto Instantiate = Node.getInstantiatedFrom()) {
9695 if (auto *FromPartialSpecialization =
9696 cast<ClassTemplatePartialSpecializationDecl *>(Val&: Instantiate)) {
9697 return nullptr != FromPartialSpecialization->getInstantiatedFromMember();
9698 }
9699 }
9700 return false;
9701}
9702
9703TEST_P(ASTImporterOptionSpecificTestBase, ImportInstantiatedFromMember) {
9704 const char *Code =
9705 R"(
9706 template <typename> struct B {
9707 template <typename, bool = false> union D;
9708 template <typename T> union D<T> {};
9709 D<int> d;
9710 };
9711 B<int> b;
9712 )";
9713 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9714 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
9715 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "D"),
9716 hasInstantiatedFromMember()));
9717 auto *FromPartialSpecialization =
9718 cast<ClassTemplatePartialSpecializationDecl *>(
9719 FromD->getInstantiatedFrom());
9720 ASSERT_TRUE(FromPartialSpecialization->getInstantiatedFromMember());
9721 auto *ImportedPartialSpecialization =
9722 Import(FromPartialSpecialization, Lang_CXX11);
9723 EXPECT_TRUE(ImportedPartialSpecialization->getInstantiatedFromMember());
9724}
9725
9726AST_MATCHER_P(EnumDecl, hasEnumConstName, StringRef, ConstName) {
9727 for (EnumConstantDecl *D : Node.enumerators())
9728 if (D->getName() == ConstName)
9729 return true;
9730 return false;
9731}
9732
9733TEST_P(ASTImporterOptionSpecificTestBase, ImportAnonymousEnums) {
9734 const char *Code =
9735 R"(
9736 struct A {
9737 enum { E1, E2 } x;
9738 enum { E3, E4 } y;
9739 };
9740 )";
9741 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9742 auto *FromEnumE1 = FirstDeclMatcher<EnumDecl>().match(
9743 D: FromTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E1")));
9744 auto *ImportedEnumE1 = Import(FromEnumE1, Lang_CXX11);
9745 EXPECT_TRUE(ImportedEnumE1);
9746 auto *FromEnumE3 = FirstDeclMatcher<EnumDecl>().match(
9747 D: FromTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E3")));
9748 auto *ImportedEnumE3 = Import(FromEnumE3, Lang_CXX11);
9749 EXPECT_TRUE(ImportedEnumE3);
9750 EXPECT_NE(ImportedEnumE1, ImportedEnumE3);
9751}
9752
9753TEST_P(ASTImporterOptionSpecificTestBase, ImportFreeStandingAnonymousEnums) {
9754 const char *Code =
9755 R"(
9756 struct A {
9757 enum { E1, E2 };
9758 enum { E3, E4 };
9759 };
9760 )";
9761 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9762 auto *FromEnumE1 = FirstDeclMatcher<EnumDecl>().match(
9763 D: FromTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E1")));
9764 auto *ImportedEnumE1 = Import(FromEnumE1, Lang_CXX11);
9765 EXPECT_TRUE(ImportedEnumE1);
9766 auto *FromEnumE3 = FirstDeclMatcher<EnumDecl>().match(
9767 D: FromTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E3")));
9768 auto *ImportedEnumE3 = Import(FromEnumE3, Lang_CXX11);
9769 EXPECT_TRUE(ImportedEnumE3);
9770 EXPECT_NE(ImportedEnumE1, ImportedEnumE3);
9771}
9772
9773TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingAnonymousEnums) {
9774 const char *ToCode =
9775 R"(
9776 struct A {
9777 enum { E1, E2 } x;
9778 enum { E3, E4 } y;
9779 };
9780 )";
9781 Decl *ToTU = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
9782 auto *ToEnumE1 = FirstDeclMatcher<EnumDecl>().match(
9783 D: ToTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E1")));
9784 auto *ToEnumE3 = FirstDeclMatcher<EnumDecl>().match(
9785 D: ToTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E3")));
9786 const char *Code =
9787 R"(
9788 struct A {
9789 enum { E1, E2 } x;
9790 enum { E3, E4 } y;
9791 };
9792 )";
9793 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9794 auto *FromEnumE1 = FirstDeclMatcher<EnumDecl>().match(
9795 D: FromTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E1")));
9796 auto *ImportedEnumE1 = Import(FromEnumE1, Lang_CXX11);
9797 ASSERT_TRUE(ImportedEnumE1);
9798 EXPECT_EQ(ImportedEnumE1, ToEnumE1);
9799 auto *FromEnumE3 = FirstDeclMatcher<EnumDecl>().match(
9800 D: FromTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E3")));
9801 auto *ImportedEnumE3 = Import(FromEnumE3, Lang_CXX11);
9802 ASSERT_TRUE(ImportedEnumE3);
9803 EXPECT_EQ(ImportedEnumE3, ToEnumE3);
9804}
9805
9806TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingEmptyAnonymousEnums) {
9807 const char *ToCode =
9808 R"(
9809 struct A {
9810 enum {};
9811 };
9812 )";
9813 Decl *ToTU = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
9814 auto *ToE1 = FirstDeclMatcher<EnumDecl>().match(D: ToTU, AMatcher: enumDecl());
9815 const char *Code =
9816 R"(
9817 struct A {
9818 enum {};
9819 enum {};
9820 };
9821 )";
9822 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9823 auto *FromE1 = FirstDeclMatcher<EnumDecl>().match(D: FromTU, AMatcher: enumDecl());
9824 auto *ImportedE1 = Import(FromE1, Lang_CXX11);
9825 ASSERT_TRUE(ImportedE1);
9826 EXPECT_EQ(ImportedE1, ToE1);
9827 auto *FromE2 = LastDeclMatcher<EnumDecl>().match(D: FromTU, AMatcher: enumDecl());
9828 ASSERT_NE(FromE1, FromE2);
9829 auto *ImportedE2 = Import(FromE2, Lang_CXX11);
9830 ASSERT_TRUE(ImportedE2);
9831 // FIXME: These should not be equal, or the import should fail.
9832 EXPECT_EQ(ImportedE2, ToE1);
9833}
9834
9835TEST_P(ASTImporterOptionSpecificTestBase, ImportMultipleAnonymousEnumDecls) {
9836 Decl *ToTU = getToTuDecl(ToSrcCode: "", ToLang: Lang_CXX03);
9837 Decl *FromTU = getTuDecl(
9838 SrcCode: R"(
9839 struct foo {
9840 enum { A };
9841 enum { B };
9842 };
9843 )",
9844 Lang: Lang_CXX03);
9845
9846 auto EnumConstA = enumConstantDecl(hasName(Name: "A"));
9847 auto EnumConstB = enumConstantDecl(hasName(Name: "B"));
9848
9849 auto *FromA = FirstDeclMatcher<EnumConstantDecl>().match(D: FromTU, AMatcher: EnumConstA);
9850 auto *FromB = FirstDeclMatcher<EnumConstantDecl>().match(D: FromTU, AMatcher: EnumConstB);
9851
9852 auto *ToA = Import(FromA, Lang_CXX03);
9853 auto *ToB = Import(FromB, Lang_CXX03);
9854
9855 ASSERT_TRUE(ToA);
9856 ASSERT_TRUE(ToB);
9857
9858 auto *ToFooA = FirstDeclMatcher<CXXRecordDecl>().match(
9859 D: ToTU, AMatcher: tagDecl(has(enumDecl(has(EnumConstA)))));
9860 auto *ToFooB = FirstDeclMatcher<CXXRecordDecl>().match(
9861 D: ToTU, AMatcher: tagDecl(has(enumDecl(has(EnumConstB)))));
9862 ASSERT_EQ(ToFooA, ToFooB);
9863
9864 // different EnumDecl
9865 auto *ToEnumDeclA =
9866 FirstDeclMatcher<EnumDecl>().match(D: ToTU, AMatcher: enumDecl(has(EnumConstA)));
9867 auto *ToEnumDeclB =
9868 FirstDeclMatcher<EnumDecl>().match(D: ToTU, AMatcher: enumDecl(has(EnumConstB)));
9869 ASSERT_NE(ToEnumDeclA, ToEnumDeclB);
9870}
9871
9872struct ImportTemplateParmDeclDefaultValue
9873 : public ASTImporterOptionSpecificTestBase {
9874protected:
9875 void checkTemplateParams(RedeclarableTemplateDecl *D,
9876 RedeclarableTemplateDecl *InheritedFromD) {
9877 auto *NonTypeP =
9878 cast<NonTypeTemplateParmDecl>(D->getTemplateParameters()->getParam(0));
9879 auto *TypeP =
9880 cast<TemplateTypeParmDecl>(D->getTemplateParameters()->getParam(1));
9881 auto *TemplateP =
9882 cast<TemplateTemplateParmDecl>(D->getTemplateParameters()->getParam(2));
9883 if (InheritedFromD) {
9884 EXPECT_TRUE(NonTypeP->getDefaultArgStorage().isInherited());
9885 EXPECT_TRUE(TypeP->getDefaultArgStorage().isInherited());
9886 EXPECT_TRUE(TemplateP->getDefaultArgStorage().isInherited());
9887 EXPECT_EQ(NonTypeP->getDefaultArgStorage().getInheritedFrom(),
9888 InheritedFromD->getTemplateParameters()->getParam(0));
9889 EXPECT_EQ(TypeP->getDefaultArgStorage().getInheritedFrom(),
9890 InheritedFromD->getTemplateParameters()->getParam(1));
9891 EXPECT_EQ(TemplateP->getDefaultArgStorage().getInheritedFrom(),
9892 InheritedFromD->getTemplateParameters()->getParam(2));
9893 } else {
9894 EXPECT_FALSE(NonTypeP->getDefaultArgStorage().isInherited());
9895 EXPECT_FALSE(TypeP->getDefaultArgStorage().isInherited());
9896 EXPECT_FALSE(TemplateP->getDefaultArgStorage().isInherited());
9897 }
9898 }
9899
9900 void testImport(RedeclarableTemplateDecl *FromD1,
9901 RedeclarableTemplateDecl *FromD2,
9902 RedeclarableTemplateDecl *FromD3,
9903 RedeclarableTemplateDecl *ToExistingD1) {
9904 auto *ToD1 = Import(From: FromD1, Lang: Lang_CXX14);
9905 auto *ToD2 = Import(From: FromD2, Lang: Lang_CXX14);
9906 auto *ToD3 = Import(From: FromD3, Lang: Lang_CXX14);
9907 checkTemplateParams(D: ToD1, InheritedFromD: nullptr);
9908 checkTemplateParams(D: ToD2, InheritedFromD: ToD1);
9909 checkTemplateParams(D: ToD3, InheritedFromD: ToExistingD1 ? ToExistingD1 : ToD1);
9910 }
9911
9912 // In these tests a circular dependency is created between the template
9913 // parameter default value and the template declaration (with the same
9914 // template parameter).
9915 template <class TemplateParmDeclT>
9916 void
9917 testTemplateParmDeclCircularDependency(ClassTemplateDecl *FromD,
9918 ClassTemplateDecl *FromDInherited) {
9919 auto GetTemplateParm =
9920 [](ClassTemplateDecl *D) -> const TemplateParmDeclT * {
9921 return dyn_cast<TemplateParmDeclT>(
9922 D->getTemplateParameters()->getParam(0));
9923 };
9924
9925 ASSERT_FALSE(GetTemplateParm(FromD)->getDefaultArgStorage().isInherited());
9926 ASSERT_TRUE(
9927 GetTemplateParm(FromDInherited)->getDefaultArgStorage().isInherited());
9928
9929 auto *ToD = Import(From: FromD, Lang: Lang_CXX14);
9930 EXPECT_TRUE(ToD);
9931
9932 auto *ToDInherited = Import(From: FromDInherited, Lang: Lang_CXX14);
9933 EXPECT_TRUE(ToDInherited);
9934
9935 EXPECT_FALSE(GetTemplateParm(ToD)->getDefaultArgStorage().isInherited());
9936 EXPECT_TRUE(
9937 GetTemplateParm(ToDInherited)->getDefaultArgStorage().isInherited());
9938 EXPECT_EQ(GetTemplateParm(ToDInherited)
9939 ->getDefaultArgStorage()
9940 .getInheritedFrom(),
9941 GetTemplateParm(ToD));
9942
9943 EXPECT_EQ(ToD->getPreviousDecl(), ToDInherited);
9944 }
9945
9946 const char *CodeFunction =
9947 R"(
9948 template <class> struct X;
9949
9950 template <int A = 2, typename B = int, template<class> class C = X>
9951 void test();
9952 template <int A, typename B, template<class> class C>
9953 void test();
9954 template <int A, typename B, template<class> class C>
9955 void test() {}
9956 )";
9957
9958 const char *CodeClass =
9959 R"(
9960 namespace N {
9961 template <class> struct X;
9962
9963 template <int A = 2, typename B = int, template<class> class C = X>
9964 struct test;
9965 template <int A, typename B, template<class> class C>
9966 struct test;
9967 template <int A, typename B, template<class> class C>
9968 struct test {};
9969 }
9970 )";
9971
9972 const char *CodeVar =
9973 R"(
9974 namespace N {
9975 template <class> struct X;
9976
9977 template <int A = 2, typename B = int, template<class> class C = X>
9978 extern int test;
9979 template <int A, typename B, template<class> class C>
9980 extern int test;
9981 template <int A, typename B, template<class> class C>
9982 int test = A;
9983 }
9984 )";
9985};
9986
9987TEST_P(ImportTemplateParmDeclDefaultValue, InvisibleInheritedFrom) {
9988 const char *ToCode =
9989 R"(
9990 template <int P = 1>
9991 void f() {}
9992 )";
9993 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX14);
9994 auto *ToFDef = FirstDeclMatcher<FunctionTemplateDecl>().match(
9995 ToTU, functionTemplateDecl(hasName(Name: "f")));
9996
9997 const char *FromCode =
9998 R"(
9999 template <int P = 1>
10000 void f() {}
10001 template <int P>
10002 void f();
10003 )";
10004 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX14);
10005 auto *FromFDef = FirstDeclMatcher<FunctionTemplateDecl>().match(
10006 FromTU, functionTemplateDecl(hasName(Name: "f")));
10007 auto *FromF = LastDeclMatcher<FunctionTemplateDecl>().match(
10008 FromTU, functionTemplateDecl(hasName(Name: "f")));
10009
10010 auto *ToFDefImported = Import(FromFDef, Lang_CXX14);
10011 EXPECT_EQ(ToFDefImported, ToFDef);
10012 auto *ToF = Import(FromF, Lang_CXX14);
10013 EXPECT_NE(ToF, ToFDef);
10014 const auto *Parm = dyn_cast<NonTypeTemplateParmDecl>(
10015 ToF->getTemplateParameters()->getParam(0));
10016 EXPECT_TRUE(Parm->defaultArgumentWasInherited());
10017 // FIXME: This behavior may be confusing:
10018 // Default value is not inherited from the existing declaration, instead a new
10019 // is created at import that is similar to the existing but not reachable from
10020 // the AST.
10021 EXPECT_NE(Parm->getDefaultArgStorage().getInheritedFrom(),
10022 ToFDef->getTemplateParameters()->getParam(0));
10023}
10024
10025TEST_P(ImportTemplateParmDeclDefaultValue, DefValImportError) {
10026 const char *ToCode =
10027 R"(
10028 class X {
10029 int A;
10030 };
10031 )";
10032 getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX14);
10033
10034 const char *FromCode =
10035 R"(
10036 class X;
10037
10038 template <typename P = X>
10039 void f() {}
10040
10041 class X {
10042 char A;
10043 };
10044 )";
10045 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX14);
10046 auto *FromF = FirstDeclMatcher<FunctionTemplateDecl>().match(
10047 FromTU, functionTemplateDecl(hasName(Name: "f")));
10048
10049 auto *ToFImported = Import(FromF, Lang_CXX14);
10050 EXPECT_FALSE(ToFImported);
10051}
10052
10053TEST_P(ImportTemplateParmDeclDefaultValue, ImportFunctionTemplate) {
10054 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: CodeFunction, Lang: Lang_CXX14);
10055 auto *D3 = LastDeclMatcher<FunctionTemplateDecl>().match(
10056 FromTU, functionTemplateDecl(hasName(Name: "test") /*, hasBody(stmt())*/));
10057 auto *D2 = dyn_cast<FunctionTemplateDecl>(D3->getPreviousDecl());
10058 auto *D1 = dyn_cast<FunctionTemplateDecl>(D2->getPreviousDecl());
10059 testImport(FromD1: D1, FromD2: D2, FromD3: D3, ToExistingD1: nullptr);
10060}
10061
10062TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingFunctionTemplate) {
10063 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: CodeFunction, ToLang: Lang_CXX14);
10064 auto *ToD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
10065 ToTU, functionTemplateDecl(hasName(Name: "test")));
10066 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: CodeFunction, Lang: Lang_CXX14);
10067 auto *D3 = LastDeclMatcher<FunctionTemplateDecl>().match(
10068 FromTU, functionTemplateDecl(hasName(Name: "test")));
10069 auto *D2 = dyn_cast<FunctionTemplateDecl>(D3->getPreviousDecl());
10070 auto *D1 = dyn_cast<FunctionTemplateDecl>(D2->getPreviousDecl());
10071 testImport(FromD1: D1, FromD2: D2, FromD3: D3, ToExistingD1: ToD1);
10072}
10073
10074TEST_P(ImportTemplateParmDeclDefaultValue, ImportClassTemplate) {
10075 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: CodeClass, Lang: Lang_CXX14);
10076 auto *D3 = LastDeclMatcher<ClassTemplateDecl>().match(
10077 FromTU, classTemplateDecl(hasName(Name: "test")));
10078 auto *D2 = dyn_cast<ClassTemplateDecl>(D3->getPreviousDecl());
10079 auto *D1 = dyn_cast<ClassTemplateDecl>(D2->getPreviousDecl());
10080 testImport(FromD1: D1, FromD2: D2, FromD3: D3, ToExistingD1: nullptr);
10081}
10082
10083TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingClassTemplate) {
10084 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: CodeClass, ToLang: Lang_CXX14);
10085 auto *ToD1 = FirstDeclMatcher<ClassTemplateDecl>().match(
10086 ToTU, classTemplateDecl(hasName(Name: "test")));
10087 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: CodeClass, Lang: Lang_CXX14);
10088 auto *D3 = LastDeclMatcher<ClassTemplateDecl>().match(
10089 FromTU, classTemplateDecl(hasName(Name: "test")));
10090 auto *D2 = dyn_cast<ClassTemplateDecl>(D3->getPreviousDecl());
10091 auto *D1 = dyn_cast<ClassTemplateDecl>(D2->getPreviousDecl());
10092 testImport(FromD1: D1, FromD2: D2, FromD3: D3, ToExistingD1: ToD1);
10093}
10094
10095TEST_P(ImportTemplateParmDeclDefaultValue, ImportVarTemplate) {
10096 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: CodeVar, Lang: Lang_CXX14);
10097 auto *D3 = LastDeclMatcher<VarTemplateDecl>().match(
10098 FromTU, varTemplateDecl(hasName(Name: "test")));
10099 auto *D2 = dyn_cast<VarTemplateDecl>(D3->getPreviousDecl());
10100 auto *D1 = dyn_cast<VarTemplateDecl>(D2->getPreviousDecl());
10101 testImport(FromD1: D1, FromD2: D2, FromD3: D3, ToExistingD1: nullptr);
10102}
10103
10104TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingVarTemplate) {
10105 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: CodeVar, ToLang: Lang_CXX14);
10106 auto *ToD1 = FirstDeclMatcher<VarTemplateDecl>().match(
10107 ToTU, varTemplateDecl(hasName(Name: "test")));
10108 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: CodeVar, Lang: Lang_CXX14);
10109 auto *D3 = LastDeclMatcher<VarTemplateDecl>().match(
10110 FromTU, varTemplateDecl(hasName(Name: "test")));
10111 auto *D2 = dyn_cast<VarTemplateDecl>(D3->getPreviousDecl());
10112 auto *D1 = dyn_cast<VarTemplateDecl>(D2->getPreviousDecl());
10113 testImport(FromD1: D1, FromD2: D2, FromD3: D3, ToExistingD1: ToD1);
10114}
10115
10116TEST_P(ImportTemplateParmDeclDefaultValue,
10117 NonTypeTemplateParmDeclCircularDependency) {
10118 const char *Code =
10119 R"(
10120 struct Z;
10121
10122 struct Y {
10123 Z *z;
10124 static const int x = 1;
10125 };
10126
10127 template <int P1 = Y::x>
10128 struct X;
10129
10130 template <int P2>
10131 struct X {
10132 static const int A = 1;
10133 };
10134
10135 struct Z {
10136 template<int P>
10137 void f(int A = X<P>::A);
10138 };
10139 )";
10140
10141 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX14);
10142 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
10143 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10144 auto *FromDInherited = LastDeclMatcher<ClassTemplateDecl>().match(
10145 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10146
10147 testTemplateParmDeclCircularDependency<NonTypeTemplateParmDecl>(
10148 FromD, FromDInherited);
10149}
10150
10151TEST_P(ImportTemplateParmDeclDefaultValue,
10152 TemplateTypeParmDeclCircularDependency) {
10153 const char *Code =
10154 R"(
10155 struct Z;
10156
10157 struct Y {
10158 Z *z;
10159 };
10160
10161 template <typename T1 = Y>
10162 struct X;
10163
10164 template <typename T2>
10165 struct X {
10166 static const int A = 1;
10167 };
10168
10169 struct Z {
10170 template<typename T>
10171 void f(int A = X<T>::A);
10172 };
10173 )";
10174
10175 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX14);
10176 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
10177 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10178 auto *FromDInherited = LastDeclMatcher<ClassTemplateDecl>().match(
10179 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10180
10181 testTemplateParmDeclCircularDependency<TemplateTypeParmDecl>(FromD,
10182 FromDInherited);
10183}
10184
10185TEST_P(ImportTemplateParmDeclDefaultValue,
10186 TemplateTemplateParmDeclCircularDependency) {
10187 const char *Code =
10188 R"(
10189 struct Z;
10190
10191 template <int>
10192 struct Y {
10193 Z *z;
10194 };
10195
10196 template <template <int> class T1 = Y>
10197 struct X;
10198
10199 template <template <int> class T2>
10200 struct X {
10201 static const int A = 1;
10202 };
10203
10204 struct Z {
10205 template <template <int> class T>
10206 void f(int A = X<T>::A);
10207 };
10208 )";
10209
10210 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX14);
10211 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
10212 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10213 auto *FromDInherited = LastDeclMatcher<ClassTemplateDecl>().match(
10214 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10215
10216 testTemplateParmDeclCircularDependency<TemplateTemplateParmDecl>(
10217 FromD, FromDInherited);
10218}
10219
10220TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceNoMatch1) {
10221 const char *ToCode =
10222 R"(
10223 namespace a {
10224 }
10225 namespace a {
10226 struct X { int A; };
10227 }
10228 )";
10229 getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
10230 const char *Code =
10231 R"(
10232 namespace a {
10233 struct X { char A; };
10234 }
10235 )";
10236 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
10237 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
10238 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
10239 auto *ImportedX = Import(FromX, Lang_CXX11);
10240 EXPECT_FALSE(ImportedX);
10241}
10242
10243TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceNoMatch2) {
10244 const char *ToCode =
10245 R"(
10246 namespace a {
10247 struct X { int A; };
10248 }
10249 namespace a {
10250 }
10251 )";
10252 getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
10253 const char *Code =
10254 R"(
10255 namespace a {
10256 struct X { char A; };
10257 }
10258 )";
10259 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
10260 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
10261 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
10262 auto *ImportedX = Import(FromX, Lang_CXX11);
10263 EXPECT_FALSE(ImportedX);
10264}
10265
10266TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceMatch1) {
10267 const char *ToCode =
10268 R"(
10269 namespace a {
10270 }
10271 namespace a {
10272 struct X { int A; };
10273 }
10274 )";
10275 Decl *ToTU = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
10276 const char *Code =
10277 R"(
10278 namespace a {
10279 struct X { int A; };
10280 }
10281 )";
10282 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
10283 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
10284 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
10285 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(
10286 D: ToTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
10287 auto *ImportedX = Import(FromX, Lang_CXX11);
10288 EXPECT_EQ(ImportedX, ToX);
10289}
10290
10291TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceMatch2) {
10292 const char *ToCode =
10293 R"(
10294 namespace a {
10295 struct X { int A; };
10296 }
10297 namespace a {
10298 }
10299 )";
10300 Decl *ToTU = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
10301 const char *Code =
10302 R"(
10303 namespace a {
10304 struct X { int A; };
10305 }
10306 )";
10307 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
10308 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
10309 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
10310 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(
10311 D: ToTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
10312 auto *ImportedX = Import(FromX, Lang_CXX11);
10313 EXPECT_EQ(ImportedX, ToX);
10314}
10315
10316TEST_P(ASTImporterLookupTableTest, PrimaryDCChangeAtImport) {
10317 const char *ToCode =
10318 R"(
10319 template <class T>
10320 struct X;
10321 )";
10322 Decl *ToTU = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
10323 auto *ToX = FirstDeclMatcher<ClassTemplateDecl>().match(
10324 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10325 NamedDecl *ToParm = ToX->getTemplateParameters()->getParam(0);
10326 DeclContext *OldPrimaryDC = ToX->getTemplatedDecl()->getPrimaryContext();
10327 ASSERT_EQ(ToParm->getDeclContext(), ToX->getTemplatedDecl());
10328 ASSERT_EQ(SharedStatePtr->getLookupTable()
10329 ->lookup(ToX->getTemplatedDecl(), ToParm->getDeclName())
10330 .size(),
10331 1u);
10332 ASSERT_TRUE(SharedStatePtr->getLookupTable()->contains(
10333 ToX->getTemplatedDecl(), ToParm));
10334
10335 const char *Code =
10336 R"(
10337 template <class T>
10338 struct X;
10339 template <class T>
10340 struct X {};
10341 )";
10342 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
10343 auto *FromX = LastDeclMatcher<ClassTemplateDecl>().match(
10344 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10345
10346 auto *ImportedX = Import(FromX, Lang_CXX11);
10347
10348 EXPECT_TRUE(ImportedX);
10349 EXPECT_EQ(ImportedX->getTemplateParameters()->getParam(0)->getDeclContext(),
10350 ImportedX->getTemplatedDecl());
10351
10352 // ToX did not change at the import.
10353 // Verify that primary context has changed after import of class definition.
10354 DeclContext *NewPrimaryDC = ToX->getTemplatedDecl()->getPrimaryContext();
10355 EXPECT_NE(OldPrimaryDC, NewPrimaryDC);
10356 // The lookup table should not be different than it was before.
10357 EXPECT_EQ(SharedStatePtr->getLookupTable()
10358 ->lookup(ToX->getTemplatedDecl(), ToParm->getDeclName())
10359 .size(),
10360 1u);
10361 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
10362 ToX->getTemplatedDecl(), ToParm));
10363}
10364
10365TEST_P(ASTImporterOptionSpecificTestBase,
10366 ExistingUndeclaredImportDeclaredFriend) {
10367 Decl *ToTU = getToTuDecl(
10368 ToSrcCode: R"(
10369 template <class A, A>
10370 struct foo;
10371
10372 template <class A>
10373 struct X {
10374 template <class A1, A1>
10375 friend struct foo;
10376 };
10377 )",
10378 ToLang: Lang_CXX11);
10379 Decl *FromTU = getTuDecl(
10380 SrcCode: R"(
10381 template <class A, A>
10382 struct foo;
10383
10384 template <class A>
10385 struct X {
10386 template <class A1, A1>
10387 friend struct foo;
10388 };
10389
10390 X<int> x;
10391 )",
10392 Lang: Lang_CXX11);
10393
10394 auto *ToFr1 = FirstDeclMatcher<FriendDecl>().match(D: ToTU, AMatcher: friendDecl());
10395 auto *ToFrD1 = ToFr1->getFriendDecl();
10396
10397 auto *FromFr1 = FirstDeclMatcher<FriendDecl>().match(D: FromTU, AMatcher: friendDecl());
10398 auto *FromFr2 = LastDeclMatcher<FriendDecl>().match(D: FromTU, AMatcher: friendDecl());
10399
10400 auto *FromFrD1 = FromFr1->getFriendDecl();
10401 auto *FromFrD2 = FromFr2->getFriendDecl();
10402
10403 auto *Ctx1 = cast<Decl>(FromFrD1->getDeclContext());
10404 auto *Ctx2 = cast<Decl>(FromFrD2->getDeclContext());
10405
10406 ASSERT_EQ(Ctx1, Ctx2);
10407 ASSERT_EQ(ToFrD1->getTemplateDepth(), 1u);
10408 ASSERT_EQ(FromFrD2->getTemplateDepth(), 0u);
10409 ASSERT_EQ(ToFrD1->getFriendObjectKind(), Decl::FOK_Undeclared);
10410 ASSERT_EQ(FromFrD2->getFriendObjectKind(), Decl::FOK_Declared);
10411
10412 auto *ToFr2Imp = Import(FromFr2, Lang_CXX11);
10413
10414 EXPECT_TRUE(ToFr2Imp);
10415}
10416
10417TEST_P(ASTImporterOptionSpecificTestBase,
10418 ExistingDeclaredImportUndeclaredFriend) {
10419 Decl *ToTU = getToTuDecl(
10420 ToSrcCode: R"(
10421 template <class A, A>
10422 struct foo;
10423
10424 template <class A>
10425 struct X {
10426 template <class A1, A1>
10427 friend struct foo;
10428 };
10429
10430 X<int> x;
10431 )",
10432 ToLang: Lang_CXX11);
10433 Decl *FromTU = getTuDecl(
10434 SrcCode: R"(
10435 template <class A, A>
10436 struct foo;
10437
10438 template <class A>
10439 struct X {
10440 template <class A1, A1>
10441 friend struct foo;
10442 };
10443 )",
10444 Lang: Lang_CXX11);
10445
10446 auto *ToFr1 = FirstDeclMatcher<FriendDecl>().match(D: ToTU, AMatcher: friendDecl());
10447 auto *ToFr2 = LastDeclMatcher<FriendDecl>().match(D: ToTU, AMatcher: friendDecl());
10448
10449 auto *ToFrD1 = ToFr1->getFriendDecl();
10450 auto *ToFrD2 = ToFr2->getFriendDecl();
10451
10452 auto *FromFr1 = FirstDeclMatcher<FriendDecl>().match(D: FromTU, AMatcher: friendDecl());
10453 auto *FromFrD1 = FromFr1->getFriendDecl();
10454
10455 auto *Ctx1 = cast<Decl>(ToFrD1->getDeclContext());
10456 auto *Ctx2 = cast<Decl>(ToFrD2->getDeclContext());
10457
10458 ASSERT_EQ(Ctx1, Ctx2);
10459 ASSERT_EQ(FromFrD1->getTemplateDepth(), 1u);
10460 ASSERT_EQ(ToFrD2->getTemplateDepth(), 0u);
10461 ASSERT_EQ(FromFrD1->getFriendObjectKind(), Decl::FOK_Undeclared);
10462 ASSERT_EQ(ToFrD2->getFriendObjectKind(), Decl::FOK_Declared);
10463
10464 auto *ToFr1Imp = Import(FromFr1, Lang_CXX11);
10465
10466 EXPECT_TRUE(ToFr1Imp);
10467 EXPECT_EQ(ToFr1Imp, ToFr1);
10468}
10469
10470struct ImportAndMergeAnonymousNamespace
10471 : public ASTImporterOptionSpecificTestBase {
10472protected:
10473 void test(const char *ToCode, const char *FromCode) {
10474 Decl *ToTU = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
10475 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
10476 auto *FromNS = FirstDeclMatcher<NamespaceDecl>().match(
10477 D: FromTU, AMatcher: namespaceDecl(isAnonymous()));
10478 auto *ToNS = FirstDeclMatcher<NamespaceDecl>().match(
10479 D: ToTU, AMatcher: namespaceDecl(isAnonymous()));
10480 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
10481 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
10482 auto *ImportedF = Import(FromF, Lang_CXX11);
10483 EXPECT_TRUE(ImportedF);
10484 EXPECT_EQ(ImportedF->getDeclContext(), ToNS);
10485 auto *ImportedNS = Import(FromNS, Lang_CXX11);
10486 EXPECT_EQ(ImportedNS, ToNS);
10487 }
10488};
10489
10490TEST_P(ImportAndMergeAnonymousNamespace, NamespaceInTU) {
10491 const char *ToCode =
10492 R"(
10493 namespace {
10494 }
10495 )";
10496 const char *FromCode =
10497 R"(
10498 namespace {
10499 void f();
10500 }
10501 )";
10502 test(ToCode, FromCode);
10503}
10504
10505TEST_P(ImportAndMergeAnonymousNamespace, NamespaceInLinkageSpec) {
10506 const char *ToCode =
10507 R"(
10508 extern "C" {
10509 namespace {
10510 }
10511 }
10512 )";
10513 const char *FromCode =
10514 R"(
10515 extern "C" {
10516 namespace {
10517 void f();
10518 }
10519 }
10520 )";
10521 test(ToCode, FromCode);
10522}
10523
10524TEST_P(ImportAndMergeAnonymousNamespace, NamespaceInNamespace) {
10525 const char *ToCode =
10526 R"(
10527 namespace X {
10528 namespace {
10529 }
10530 }
10531 )";
10532 const char *FromCode =
10533 R"(
10534 namespace X {
10535 namespace {
10536 void f();
10537 }
10538 }
10539 )";
10540 test(ToCode, FromCode);
10541}
10542
10543INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest,
10544 DefaultTestValuesForRunOptions);
10545
10546INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportPath,
10547 ::testing::Values(std::vector<std::string>()));
10548
10549INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportExpr,
10550 DefaultTestValuesForRunOptions);
10551
10552INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFixedPointExpr,
10553 ExtendWithOptions(DefaultTestArrayForRunOptions,
10554 std::vector<std::string>{
10555 "-ffixed-point"}));
10556
10557INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportBlock,
10558 ExtendWithOptions(DefaultTestArrayForRunOptions,
10559 std::vector<std::string>{
10560 "-fblocks"}));
10561
10562INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportType,
10563 DefaultTestValuesForRunOptions);
10564
10565INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportDecl,
10566 DefaultTestValuesForRunOptions);
10567
10568INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
10569 DefaultTestValuesForRunOptions);
10570
10571INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ErrorHandlingTest,
10572 DefaultTestValuesForRunOptions);
10573
10574INSTANTIATE_TEST_SUITE_P(ParameterizedTests, RedirectingImporterTest,
10575 DefaultTestValuesForRunOptions);
10576
10577INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFunctions,
10578 DefaultTestValuesForRunOptions);
10579
10580INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportAutoFunctions,
10581 DefaultTestValuesForRunOptions);
10582
10583INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFunctionTemplates,
10584 DefaultTestValuesForRunOptions);
10585
10586INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFriendFunctionTemplates,
10587 DefaultTestValuesForRunOptions);
10588
10589INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportClasses,
10590 DefaultTestValuesForRunOptions);
10591
10592INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFriendFunctions,
10593 DefaultTestValuesForRunOptions);
10594
10595INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFriendClasses,
10596 DefaultTestValuesForRunOptions);
10597
10598INSTANTIATE_TEST_SUITE_P(ParameterizedTests,
10599 ImportFunctionTemplateSpecializations,
10600 DefaultTestValuesForRunOptions);
10601
10602INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportImplicitMethods,
10603 DefaultTestValuesForRunOptions);
10604
10605INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportVariables,
10606 DefaultTestValuesForRunOptions);
10607
10608INSTANTIATE_TEST_SUITE_P(ParameterizedTests, LLDBLookupTest,
10609 DefaultTestValuesForRunOptions);
10610
10611INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportSourceLocations,
10612 DefaultTestValuesForRunOptions);
10613
10614INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportWithExternalSource,
10615 DefaultTestValuesForRunOptions);
10616
10617INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportAttributes,
10618 DefaultTestValuesForRunOptions);
10619
10620INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportInjectedClassNameType,
10621 DefaultTestValuesForRunOptions);
10622
10623INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportMatrixType,
10624 DefaultTestValuesForRunOptions);
10625
10626INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportTemplateParmDeclDefaultValue,
10627 DefaultTestValuesForRunOptions);
10628
10629INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportAndMergeAnonymousNamespace,
10630 DefaultTestValuesForRunOptions);
10631
10632// FIXME: Make ImportOpenCLPipe test work.
10633// INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportOpenCLPipe,
10634// DefaultTestValuesForRunOptions);
10635GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ImportOpenCLPipe);
10636
10637} // end namespace ast_matchers
10638} // end namespace clang
10639

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang/unittests/AST/ASTImporterTest.cpp