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/ExprConcepts.h"
14#include "clang/AST/RecordLayout.h"
15#include "clang/ASTMatchers/ASTMatchers.h"
16#include "clang/Testing/CommandLineArgs.h"
17#include "llvm/Support/SmallVectorMemoryBuffer.h"
18
19#include "clang/AST/DeclContextInternals.h"
20#include "gtest/gtest.h"
21
22#include "ASTImporterFixtures.h"
23#include <optional>
24
25namespace clang {
26namespace ast_matchers {
27
28using internal::Matcher;
29
30static const RecordDecl *getRecordDeclOfFriend(FriendDecl *FD) {
31 QualType Ty = FD->getFriendType()->getType().getCanonicalType();
32 return cast<RecordType>(Val&: Ty)->getDecl();
33}
34
35struct ImportExpr : TestImportBase {};
36struct ImportType : TestImportBase {};
37struct ImportDecl : TestImportBase {};
38struct ImportFixedPointExpr : ImportExpr {};
39
40struct CanonicalRedeclChain : ASTImporterOptionSpecificTestBase {};
41
42TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers) {
43 Decl *FromTU = getTuDecl(SrcCode: "void f();", Lang: Lang_CXX03);
44 auto Pattern = functionDecl(hasName(Name: "f"));
45 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
46
47 auto Redecls = getCanonicalForwardRedeclChain(D: D0);
48 ASSERT_EQ(Redecls.size(), 1u);
49 EXPECT_EQ(D0, Redecls[0]);
50}
51
52TEST_P(CanonicalRedeclChain, ShouldBeConsequentWithMatchers2) {
53 Decl *FromTU = getTuDecl(SrcCode: "void f(); void f(); void f();", Lang: Lang_CXX03);
54 auto Pattern = functionDecl(hasName(Name: "f"));
55 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
56 auto *D2 = LastDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
57 FunctionDecl *D1 = D2->getPreviousDecl();
58
59 auto Redecls = getCanonicalForwardRedeclChain(D: D0);
60 ASSERT_EQ(Redecls.size(), 3u);
61 EXPECT_EQ(D0, Redecls[0]);
62 EXPECT_EQ(D1, Redecls[1]);
63 EXPECT_EQ(D2, Redecls[2]);
64}
65
66TEST_P(CanonicalRedeclChain, ShouldBeSameForAllDeclInTheChain) {
67 Decl *FromTU = getTuDecl(SrcCode: "void f(); void f(); void f();", Lang: Lang_CXX03);
68 auto Pattern = functionDecl(hasName(Name: "f"));
69 auto *D0 = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
70 auto *D2 = LastDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
71 FunctionDecl *D1 = D2->getPreviousDecl();
72
73 auto RedeclsD0 = getCanonicalForwardRedeclChain(D: D0);
74 auto RedeclsD1 = getCanonicalForwardRedeclChain(D: D1);
75 auto RedeclsD2 = getCanonicalForwardRedeclChain(D: D2);
76
77 EXPECT_THAT(RedeclsD0, ::testing::ContainerEq(RedeclsD1));
78 EXPECT_THAT(RedeclsD1, ::testing::ContainerEq(RedeclsD2));
79}
80
81namespace {
82struct RedirectingImporter : public ASTImporter {
83 using ASTImporter::ASTImporter;
84
85protected:
86 llvm::Expected<Decl *> ImportImpl(Decl *FromD) override {
87 auto *ND = dyn_cast<NamedDecl>(Val: FromD);
88 if (!ND || ND->getName() != "shouldNotBeImported")
89 return ASTImporter::ImportImpl(From: FromD);
90 for (Decl *D : getToContext().getTranslationUnitDecl()->decls()) {
91 if (auto *ND = dyn_cast<NamedDecl>(Val: D))
92 if (ND->getName() == "realDecl") {
93 RegisterImportedDecl(FromD, ToD: ND);
94 return ND;
95 }
96 }
97 return ASTImporter::ImportImpl(From: FromD);
98 }
99};
100
101} // namespace
102
103struct RedirectingImporterTest : ASTImporterOptionSpecificTestBase {
104 RedirectingImporterTest() {
105 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
106 ASTContext &FromContext, FileManager &FromFileManager,
107 bool MinimalImport,
108 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
109 return new RedirectingImporter(ToContext, ToFileManager, FromContext,
110 FromFileManager, MinimalImport,
111 SharedState);
112 };
113 }
114};
115
116// Test that an ASTImporter subclass can intercept an import call.
117TEST_P(RedirectingImporterTest, InterceptImport) {
118 Decl *From, *To;
119 std::tie(args&: From, args&: To) =
120 getImportedDecl(FromSrcCode: "class shouldNotBeImported {};", FromLang: Lang_CXX03,
121 ToSrcCode: "class realDecl {};", ToLang: Lang_CXX03, Identifier: "shouldNotBeImported");
122 auto *Imported = cast<CXXRecordDecl>(Val: To);
123 EXPECT_EQ(Imported->getQualifiedNameAsString(), "realDecl");
124
125 // Make sure our importer prevented the importing of the decl.
126 auto *ToTU = Imported->getTranslationUnitDecl();
127 auto Pattern = functionDecl(hasName(Name: "shouldNotBeImported"));
128 unsigned count =
129 DeclCounterWithPredicate<CXXRecordDecl>().match(D: ToTU, AMatcher: Pattern);
130 EXPECT_EQ(0U, count);
131}
132
133// Test that when we indirectly import a declaration the custom ASTImporter
134// is still intercepting the import.
135TEST_P(RedirectingImporterTest, InterceptIndirectImport) {
136 Decl *From, *To;
137 std::tie(args&: From, args&: To) =
138 getImportedDecl(FromSrcCode: "class shouldNotBeImported {};"
139 "class F { shouldNotBeImported f; };",
140 FromLang: Lang_CXX03, ToSrcCode: "class realDecl {};", ToLang: Lang_CXX03, Identifier: "F");
141
142 // Make sure our ASTImporter prevented the importing of the decl.
143 auto *ToTU = To->getTranslationUnitDecl();
144 auto Pattern = functionDecl(hasName(Name: "shouldNotBeImported"));
145 unsigned count =
146 DeclCounterWithPredicate<CXXRecordDecl>().match(D: ToTU, AMatcher: Pattern);
147 EXPECT_EQ(0U, count);
148}
149
150struct ImportPath : ASTImporterOptionSpecificTestBase {
151 Decl *FromTU;
152 FunctionDecl *D0, *D1, *D2;
153 ImportPath() {
154 FromTU = getTuDecl(SrcCode: "void f(); void f(); void f();", Lang: Lang_CXX03);
155 auto Pattern = functionDecl(hasName(Name: "f"));
156 D0 = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
157 D2 = LastDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
158 D1 = D2->getPreviousDecl();
159 }
160};
161
162TEST_P(ImportPath, Push) {
163 ASTImporter::ImportPathTy path;
164 path.push(D: D0);
165 EXPECT_FALSE(path.hasCycleAtBack());
166}
167
168TEST_P(ImportPath, SmallCycle) {
169 ASTImporter::ImportPathTy path;
170 path.push(D: D0);
171 path.push(D: D0);
172 EXPECT_TRUE(path.hasCycleAtBack());
173 path.pop();
174 EXPECT_FALSE(path.hasCycleAtBack());
175 path.push(D: D0);
176 EXPECT_TRUE(path.hasCycleAtBack());
177}
178
179TEST_P(ImportPath, GetSmallCycle) {
180 ASTImporter::ImportPathTy path;
181 path.push(D: D0);
182 path.push(D: D0);
183 EXPECT_TRUE(path.hasCycleAtBack());
184 std::array<Decl* ,2> Res;
185 int i = 0;
186 for (Decl *Di : path.getCycleAtBack()) {
187 Res[i++] = Di;
188 }
189 ASSERT_EQ(i, 2);
190 EXPECT_EQ(Res[0], D0);
191 EXPECT_EQ(Res[1], D0);
192}
193
194TEST_P(ImportPath, GetCycle) {
195 ASTImporter::ImportPathTy path;
196 path.push(D: D0);
197 path.push(D: D1);
198 path.push(D: D2);
199 path.push(D: D0);
200 EXPECT_TRUE(path.hasCycleAtBack());
201 std::array<Decl* ,4> Res;
202 int i = 0;
203 for (Decl *Di : path.getCycleAtBack()) {
204 Res[i++] = Di;
205 }
206 ASSERT_EQ(i, 4);
207 EXPECT_EQ(Res[0], D0);
208 EXPECT_EQ(Res[1], D2);
209 EXPECT_EQ(Res[2], D1);
210 EXPECT_EQ(Res[3], D0);
211}
212
213TEST_P(ImportPath, CycleAfterCycle) {
214 ASTImporter::ImportPathTy path;
215 path.push(D: D0);
216 path.push(D: D1);
217 path.push(D: D0);
218 path.push(D: D1);
219 path.push(D: D2);
220 path.push(D: D0);
221 EXPECT_TRUE(path.hasCycleAtBack());
222 std::array<Decl* ,4> Res;
223 int i = 0;
224 for (Decl *Di : path.getCycleAtBack()) {
225 Res[i++] = Di;
226 }
227 ASSERT_EQ(i, 4);
228 EXPECT_EQ(Res[0], D0);
229 EXPECT_EQ(Res[1], D2);
230 EXPECT_EQ(Res[2], D1);
231 EXPECT_EQ(Res[3], D0);
232
233 path.pop();
234 path.pop();
235 path.pop();
236 EXPECT_TRUE(path.hasCycleAtBack());
237 i = 0;
238 for (Decl *Di : path.getCycleAtBack()) {
239 Res[i++] = Di;
240 }
241 ASSERT_EQ(i, 3);
242 EXPECT_EQ(Res[0], D0);
243 EXPECT_EQ(Res[1], D1);
244 EXPECT_EQ(Res[2], D0);
245
246 path.pop();
247 EXPECT_FALSE(path.hasCycleAtBack());
248}
249
250const internal::VariadicDynCastAllOfMatcher<Stmt, SourceLocExpr> sourceLocExpr;
251
252AST_MATCHER_P(SourceLocExpr, hasBuiltinStr, StringRef, Str) {
253 return Node.getBuiltinStr() == Str;
254}
255
256TEST_P(ImportExpr, ImportSourceLocExpr) {
257 MatchVerifier<Decl> Verifier;
258 testImport(FromCode: "void declToImport() { (void)__builtin_FILE(); }", FromLang: Lang_CXX03, ToCode: "",
259 ToLang: Lang_CXX03, Verifier,
260 AMatcher: functionDecl(hasDescendant(
261 sourceLocExpr(hasBuiltinStr(Str: "__builtin_FILE")))));
262 testImport(FromCode: "void declToImport() { (void)__builtin_FILE_NAME(); }", FromLang: Lang_CXX03,
263 ToCode: "", ToLang: Lang_CXX03, Verifier,
264 AMatcher: functionDecl(hasDescendant(
265 sourceLocExpr(hasBuiltinStr(Str: "__builtin_FILE_NAME")))));
266 testImport(FromCode: "void declToImport() { (void)__builtin_COLUMN(); }", FromLang: Lang_CXX03,
267 ToCode: "", ToLang: Lang_CXX03, Verifier,
268 AMatcher: functionDecl(hasDescendant(
269 sourceLocExpr(hasBuiltinStr(Str: "__builtin_COLUMN")))));
270}
271
272TEST_P(ImportExpr, ImportStringLiteral) {
273 MatchVerifier<Decl> Verifier;
274 testImport(FromCode: "void declToImport() { (void)\"foo\"; }", FromLang: Lang_CXX03, ToCode: "",
275 ToLang: Lang_CXX03, Verifier,
276 AMatcher: functionDecl(hasDescendant(
277 stringLiteral(hasType(InnerMatcher: asString(Name: "const char[4]"))))));
278 testImport(FromCode: "void declToImport() { (void)L\"foo\"; }", FromLang: Lang_CXX03, ToCode: "",
279 ToLang: Lang_CXX03, Verifier,
280 AMatcher: functionDecl(hasDescendant(
281 stringLiteral(hasType(InnerMatcher: asString(Name: "const wchar_t[4]"))))));
282 testImport(FromCode: "void declToImport() { (void) \"foo\" \"bar\"; }", FromLang: Lang_CXX03, ToCode: "",
283 ToLang: Lang_CXX03, Verifier,
284 AMatcher: functionDecl(hasDescendant(
285 stringLiteral(hasType(InnerMatcher: asString(Name: "const char[7]"))))));
286}
287
288TEST_P(ImportExpr, ImportChooseExpr) {
289 MatchVerifier<Decl> Verifier;
290
291 // This case tests C code that is not condition-dependent and has a true
292 // condition.
293 testImport(FromCode: "void declToImport() { (void)__builtin_choose_expr(1, 2, 3); }",
294 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
295 AMatcher: functionDecl(hasDescendant(chooseExpr())));
296}
297
298const internal::VariadicDynCastAllOfMatcher<Stmt, ShuffleVectorExpr>
299 shuffleVectorExpr;
300
301TEST_P(ImportExpr, ImportShuffleVectorExpr) {
302 MatchVerifier<Decl> Verifier;
303 constexpr auto Code = R"code(
304 typedef double vector4double __attribute__((__vector_size__(32)));
305 vector4double declToImport(vector4double a, vector4double b) {
306 return __builtin_shufflevector(a, b, 0, 1, 2, 3);
307 }
308 )code";
309 const auto Pattern = functionDecl(hasDescendant(shuffleVectorExpr(
310 allOf(has(declRefExpr(to(InnerMatcher: parmVarDecl(hasName(Name: "a"))))),
311 has(declRefExpr(to(InnerMatcher: parmVarDecl(hasName(Name: "b"))))),
312 has(constantExpr(has(integerLiteral(equals(Value: 0))))),
313 has(constantExpr(has(integerLiteral(equals(Value: 1))))),
314 has(constantExpr(has(integerLiteral(equals(Value: 2))))),
315 has(constantExpr(has(integerLiteral(equals(Value: 3)))))))));
316 testImport(FromCode: Code, FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier, AMatcher: Pattern);
317}
318
319TEST_P(ImportExpr, ImportGNUNullExpr) {
320 MatchVerifier<Decl> Verifier;
321 testImport(FromCode: "void declToImport() { (void)__null; }", FromLang: Lang_CXX03, ToCode: "",
322 ToLang: Lang_CXX03, Verifier,
323 AMatcher: functionDecl(hasDescendant(gnuNullExpr(hasType(InnerMatcher: isInteger())))));
324}
325
326TEST_P(ImportExpr, ImportGenericSelectionExpr) {
327 MatchVerifier<Decl> Verifier;
328
329 testImport(
330 FromCode: "void declToImport() { int x; (void)_Generic(x, int: 0, float: 1); }",
331 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
332 AMatcher: functionDecl(hasDescendant(genericSelectionExpr())));
333}
334
335TEST_P(ImportExpr, ImportCXXNullPtrLiteralExpr) {
336 MatchVerifier<Decl> Verifier;
337 testImport(
338 FromCode: "void declToImport() { (void)nullptr; }",
339 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
340 AMatcher: functionDecl(hasDescendant(cxxNullPtrLiteralExpr())));
341}
342
343
344TEST_P(ImportExpr, ImportFloatinglLiteralExpr) {
345 MatchVerifier<Decl> Verifier;
346 testImport(FromCode: "void declToImport() { (void)1.0; }", FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99,
347 Verifier,
348 AMatcher: functionDecl(hasDescendant(
349 floatLiteral(equals(Value: 1.0), hasType(InnerMatcher: asString(Name: "double"))))));
350 testImport(FromCode: "void declToImport() { (void)1.0e-5f; }", FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99,
351 Verifier,
352 AMatcher: functionDecl(hasDescendant(
353 floatLiteral(equals(Value: 1.0e-5f), hasType(InnerMatcher: asString(Name: "float"))))));
354}
355
356TEST_P(ImportFixedPointExpr, ImportFixedPointerLiteralExpr) {
357 MatchVerifier<Decl> Verifier;
358 testImport(FromCode: "void declToImport() { (void)1.0k; }", FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99,
359 Verifier, AMatcher: functionDecl(hasDescendant(fixedPointLiteral())));
360 testImport(FromCode: "void declToImport() { (void)0.75r; }", FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99,
361 Verifier, AMatcher: functionDecl(hasDescendant(fixedPointLiteral())));
362}
363
364TEST_P(ImportExpr, ImportImaginaryLiteralExpr) {
365 MatchVerifier<Decl> Verifier;
366 testImport(
367 FromCode: "void declToImport() { (void)1.0i; }",
368 FromLang: Lang_CXX14, ToCode: "", ToLang: Lang_CXX14, Verifier,
369 AMatcher: functionDecl(hasDescendant(imaginaryLiteral())));
370}
371
372TEST_P(ImportExpr, ImportCompoundLiteralExpr) {
373 MatchVerifier<Decl> Verifier;
374 testImport(FromCode: "void declToImport() {"
375 " struct s { int x; long y; unsigned z; }; "
376 " (void)(struct s){ 42, 0L, 1U }; }",
377 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
378 AMatcher: functionDecl(hasDescendant(compoundLiteralExpr(
379 hasType(InnerMatcher: asString(Name: "struct s")),
380 has(initListExpr(
381 hasType(InnerMatcher: asString(Name: "struct s")),
382 has(integerLiteral(equals(Value: 42), hasType(InnerMatcher: asString(Name: "int")))),
383 has(integerLiteral(equals(Value: 0), hasType(InnerMatcher: asString(Name: "long")))),
384 has(integerLiteral(
385 equals(Value: 1), hasType(InnerMatcher: asString(Name: "unsigned int"))))))))));
386}
387
388TEST_P(ImportExpr, ImportCXXThisExpr) {
389 MatchVerifier<Decl> Verifier;
390 testImport(FromCode: "class declToImport { void f() { (void)this; } };", FromLang: Lang_CXX03, ToCode: "",
391 ToLang: Lang_CXX03, Verifier,
392 AMatcher: cxxRecordDecl(hasMethod(InnerMatcher: hasDescendant(
393 cxxThisExpr(hasType(InnerMatcher: asString(Name: "class declToImport *")))))));
394}
395
396TEST_P(ImportExpr, ImportAtomicExpr) {
397 MatchVerifier<Decl> Verifier;
398 testImport(FromCode: "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
399 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
400 AMatcher: functionDecl(hasDescendant(atomicExpr(
401 has(ignoringParenImpCasts(
402 InnerMatcher: declRefExpr(hasDeclaration(InnerMatcher: varDecl(hasName(Name: "ptr"))),
403 hasType(InnerMatcher: asString(Name: "int *"))))),
404 has(integerLiteral(equals(Value: 1), hasType(InnerMatcher: asString(Name: "int"))))))));
405}
406
407TEST_P(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
408 MatchVerifier<Decl> Verifier;
409 testImport(FromCode: "void declToImport() { loop: goto loop; (void)&&loop; }", FromLang: Lang_C99,
410 ToCode: "", ToLang: Lang_C99, Verifier,
411 AMatcher: functionDecl(hasDescendant(labelStmt(
412 hasDeclaration(InnerMatcher: labelDecl(hasName(Name: "loop"))))),
413 hasDescendant(addrLabelExpr(
414 hasDeclaration(InnerMatcher: labelDecl(hasName(Name: "loop")))))));
415}
416
417AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
418 internal::Matcher<NamedDecl>, InnerMatcher) {
419 const NamedDecl *Template = Node.getTemplatedDecl();
420 return Template && InnerMatcher.matches(Node: *Template, Finder, Builder);
421}
422
423TEST_P(ImportExpr, ImportParenListExpr) {
424 MatchVerifier<Decl> Verifier;
425 testImport(
426 FromCode: "template<typename T> class dummy { void f() { dummy X(*this); } };"
427 "typedef dummy<int> declToImport;"
428 "template class dummy<int>;",
429 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
430 AMatcher: typedefDecl(hasType(InnerMatcher: elaboratedType(namesType(InnerMatcher: templateSpecializationType(
431 hasDeclaration(InnerMatcher: classTemplateSpecializationDecl(hasSpecializedTemplate(
432 InnerMatcher: classTemplateDecl(hasTemplateDecl(InnerMatcher: cxxRecordDecl(hasMethod(
433 InnerMatcher: allOf(hasName(Name: "f"),
434 hasBody(InnerMatcher: compoundStmt(has(declStmt(hasSingleDecl(InnerMatcher: varDecl(
435 hasInitializer(InnerMatcher: parenListExpr(has(unaryOperator(
436 hasOperatorName(Name: "*"),
437 hasUnaryOperand(
438 InnerMatcher: cxxThisExpr())))))))))))))))))))))))));
439}
440
441TEST_P(ImportExpr, ImportSwitch) {
442 MatchVerifier<Decl> Verifier;
443 testImport(FromCode: "void declToImport() { int b; switch (b) { case 1: break; } }",
444 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
445 AMatcher: functionDecl(hasDescendant(
446 switchStmt(has(compoundStmt(has(caseStmt())))))));
447}
448
449TEST_P(ImportExpr, ImportStmtExpr) {
450 MatchVerifier<Decl> Verifier;
451 testImport(
452 FromCode: "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
453 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
454 AMatcher: traverse(TK: TK_AsIs,
455 InnerMatcher: functionDecl(hasDescendant(varDecl(
456 hasName(Name: "C"), hasType(InnerMatcher: asString(Name: "int")),
457 hasInitializer(InnerMatcher: stmtExpr(
458 hasAnySubstatement(InnerMatcher: declStmt(hasSingleDecl(InnerMatcher: varDecl(
459 hasName(Name: "X"), hasType(InnerMatcher: asString(Name: "int")),
460 hasInitializer(InnerMatcher: integerLiteral(equals(Value: 4))))))),
461 hasDescendant(implicitCastExpr()))))))));
462}
463
464TEST_P(ImportExpr, ImportConditionalOperator) {
465 MatchVerifier<Decl> Verifier;
466 testImport(FromCode: "void declToImport() { (void)(true ? 1 : -5); }", FromLang: Lang_CXX03, ToCode: "",
467 ToLang: Lang_CXX03, Verifier,
468 AMatcher: functionDecl(hasDescendant(conditionalOperator(
469 hasCondition(InnerMatcher: cxxBoolLiteral(equals(Value: true))),
470 hasTrueExpression(InnerMatcher: integerLiteral(equals(Value: 1))),
471 hasFalseExpression(InnerMatcher: unaryOperator(
472 hasUnaryOperand(InnerMatcher: integerLiteral(equals(Value: 5)))))))));
473}
474
475TEST_P(ImportExpr, ImportBinaryConditionalOperator) {
476 MatchVerifier<Decl> Verifier;
477 testImport(
478 FromCode: "void declToImport() { (void)(1 ?: -5); }", FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03,
479 Verifier,
480 AMatcher: traverse(TK: TK_AsIs,
481 InnerMatcher: functionDecl(hasDescendant(binaryConditionalOperator(
482 hasCondition(InnerMatcher: implicitCastExpr(
483 hasSourceExpression(InnerMatcher: opaqueValueExpr(
484 hasSourceExpression(InnerMatcher: integerLiteral(equals(Value: 1))))),
485 hasType(InnerMatcher: booleanType()))),
486 hasTrueExpression(InnerMatcher: opaqueValueExpr(
487 hasSourceExpression(InnerMatcher: integerLiteral(equals(Value: 1))))),
488 hasFalseExpression(InnerMatcher: unaryOperator(
489 hasOperatorName(Name: "-"),
490 hasUnaryOperand(InnerMatcher: integerLiteral(equals(Value: 5))))))))));
491}
492
493TEST_P(ImportExpr, ImportDesignatedInitExpr) {
494 MatchVerifier<Decl> Verifier;
495 testImport(
496 FromCode: "void declToImport() {"
497 " struct point { double x; double y; };"
498 " struct point ptarray[10] = "
499 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
500 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
501 AMatcher: functionDecl(hasDescendant(initListExpr(
502 has(designatedInitExpr(designatorCountIs(N: 2),
503 hasDescendant(floatLiteral(equals(Value: 1.0))),
504 hasDescendant(integerLiteral(equals(Value: 2))))),
505 has(designatedInitExpr(designatorCountIs(N: 2),
506 hasDescendant(floatLiteral(equals(Value: 2.0))),
507 hasDescendant(integerLiteral(equals(Value: 2))))),
508 has(designatedInitExpr(designatorCountIs(N: 2),
509 hasDescendant(floatLiteral(equals(Value: 1.0))),
510 hasDescendant(integerLiteral(equals(Value: 0)))))))));
511}
512
513TEST_P(ImportExpr, ImportPredefinedExpr) {
514 MatchVerifier<Decl> Verifier;
515 // __func__ expands as StringLiteral("declToImport")
516 testImport(FromCode: "void declToImport() { (void)__func__; }", FromLang: Lang_CXX03, ToCode: "",
517 ToLang: Lang_CXX03, Verifier,
518 AMatcher: functionDecl(hasDescendant(predefinedExpr(
519 hasType(InnerMatcher: asString(Name: "const char[13]")),
520 has(stringLiteral(hasType(InnerMatcher: asString(Name: "const char[13]"))))))));
521}
522
523TEST_P(ImportExpr, ImportInitListExpr) {
524 MatchVerifier<Decl> Verifier;
525 testImport(FromCode: "void declToImport() {"
526 " struct point { double x; double y; };"
527 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
528 " [0].x = 1.0 }; }",
529 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
530 AMatcher: functionDecl(hasDescendant(initListExpr(
531 has(cxxConstructExpr(requiresZeroInitialization())),
532 has(initListExpr(
533 hasType(InnerMatcher: asString(Name: "point")), has(floatLiteral(equals(Value: 1.0))),
534 has(implicitValueInitExpr(hasType(InnerMatcher: asString(Name: "double")))))),
535 has(initListExpr(hasType(InnerMatcher: asString(Name: "point")),
536 has(floatLiteral(equals(Value: 2.0))),
537 has(floatLiteral(equals(Value: 1.0)))))))));
538}
539
540const internal::VariadicDynCastAllOfMatcher<Expr, CXXDefaultInitExpr>
541 cxxDefaultInitExpr;
542
543TEST_P(ImportExpr, ImportCXXDefaultInitExpr) {
544 MatchVerifier<Decl> Verifier;
545 testImport(FromCode: "class declToImport { int DefInit = 5; }; declToImport X;",
546 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
547 AMatcher: cxxRecordDecl(hasDescendant(cxxConstructorDecl(
548 hasAnyConstructorInitializer(InnerMatcher: cxxCtorInitializer(
549 withInitializer(InnerMatcher: cxxDefaultInitExpr())))))));
550 testImport(
551 FromCode: "struct X { int A = 5; }; X declToImport{};", FromLang: Lang_CXX17, ToCode: "", ToLang: Lang_CXX17,
552 Verifier,
553 AMatcher: varDecl(hasInitializer(InnerMatcher: initListExpr(hasInit(N: 0, InnerMatcher: cxxDefaultInitExpr())))));
554}
555
556const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
557
558TEST_P(ImportExpr, ImportVAArgExpr) {
559 MatchVerifier<Decl> Verifier;
560 testImport(FromCode: "void declToImport(__builtin_va_list list, ...) {"
561 " (void)__builtin_va_arg(list, int); }",
562 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
563 AMatcher: functionDecl(hasDescendant(
564 cStyleCastExpr(hasSourceExpression(InnerMatcher: vaArgExpr())))));
565}
566
567const internal::VariadicDynCastAllOfMatcher<Stmt, BuiltinBitCastExpr>
568 builtinBitCastExpr;
569
570TEST_P(ImportExpr, ImportBuiltinBitCastExpr) {
571 MatchVerifier<Decl> Verifier;
572 testImport(FromCode: "void declToImport(int X) {"
573 " (void)__builtin_bit_cast(float, X); }",
574 FromLang: Lang_CXX20, ToCode: "", ToLang: Lang_CXX20, Verifier,
575 AMatcher: functionDecl(hasDescendant(
576 cStyleCastExpr(hasSourceExpression(InnerMatcher: builtinBitCastExpr())))));
577}
578
579TEST_P(ImportExpr, CXXTemporaryObjectExpr) {
580 MatchVerifier<Decl> Verifier;
581 testImport(
582 FromCode: "struct C {};"
583 "void declToImport() { C c = C(); }",
584 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
585 AMatcher: traverse(TK: TK_AsIs,
586 InnerMatcher: functionDecl(hasDescendant(exprWithCleanups(has(cxxConstructExpr(
587 has(materializeTemporaryExpr(has(implicitCastExpr(
588 has(cxxTemporaryObjectExpr()))))))))))));
589}
590
591TEST_P(ImportType, ImportAtomicType) {
592 MatchVerifier<Decl> Verifier;
593 testImport(
594 FromCode: "void declToImport() { typedef _Atomic(int) a_int; }",
595 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
596 AMatcher: functionDecl(hasDescendant(typedefDecl(has(atomicType())))));
597}
598
599TEST_P(ImportType, ImportBitIntType) {
600 const AstTypeMatcher<BitIntType> bitIntType;
601 MatchVerifier<Decl> Verifier;
602 testImport(FromCode: "_BitInt(10) declToImport;", FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
603 AMatcher: varDecl(hasType(InnerMatcher: bitIntType())));
604}
605
606TEST_P(ImportType, ImportDependentBitIntType) {
607 const AstTypeMatcher<DependentBitIntType> dependentBitIntType;
608 MatchVerifier<Decl> Verifier;
609 testImport(FromCode: "template<int Width> using declToImport = _BitInt(Width);",
610 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
611 AMatcher: typeAliasTemplateDecl(
612 has(typeAliasDecl(hasType(InnerMatcher: dependentBitIntType())))));
613}
614
615TEST_P(ImportType, ImportDependentAddressSpaceType) {
616 const AstTypeMatcher<DependentAddressSpaceType> dependentAddressSpaceType;
617 MatchVerifier<Decl> Verifier;
618 testImport(
619 FromCode: R"(
620 template<typename T, int AddrSpace>
621 using declToImport = T __attribute__((address_space(AddrSpace)));
622 )",
623 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
624 AMatcher: typeAliasTemplateDecl(
625 has(typeAliasDecl(hasType(InnerMatcher: dependentAddressSpaceType())))));
626}
627
628TEST_P(ImportType, ImportVectorType) {
629 const AstTypeMatcher<VectorType> vectorType;
630 MatchVerifier<Decl> Verifier;
631 testImport(FromCode: "typedef int __attribute__((vector_size(12))) declToImport;",
632 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
633 AMatcher: typedefDecl(hasType(InnerMatcher: vectorType())));
634}
635
636TEST_P(ImportType, ImportDependentVectorType) {
637 const AstTypeMatcher<DependentVectorType> dependentVectorType;
638 MatchVerifier<Decl> Verifier;
639 testImport(
640 FromCode: R"(
641 template<typename T, int Size>
642 using declToImport = T __attribute__((vector_size(Size)));
643 )",
644 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
645 AMatcher: typeAliasTemplateDecl(
646 has(typeAliasDecl(hasType(InnerMatcher: dependentVectorType())))));
647}
648
649struct ImportOpenCLPipe : ImportType {
650 std::vector<std::string> getExtraArgs() const override {
651 return {"-x", "cl", "-cl-no-stdinc", "-cl-std=CL2.0"};
652 }
653};
654
655TEST_P(ImportOpenCLPipe, ImportPipeType) {
656 const AstTypeMatcher<PipeType> pipeType;
657 MatchVerifier<Decl> Verifier;
658 testImport(FromCode: "typedef pipe int declToImport;", FromLang: Lang_OpenCL, ToCode: "", ToLang: Lang_OpenCL,
659 Verifier, AMatcher: typedefDecl(hasType(InnerMatcher: pipeType())));
660}
661
662struct ImportMatrixType : ImportType {
663 std::vector<std::string> getExtraArgs() const override {
664 return {"-fenable-matrix"};
665 }
666};
667
668TEST_P(ImportMatrixType, ImportConstantMatrixType) {
669 const AstTypeMatcher<ConstantMatrixType> constantMatrixType;
670 MatchVerifier<Decl> Verifier;
671 testImport(FromCode: "typedef int __attribute__((matrix_type(5, 5))) declToImport;",
672 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
673 AMatcher: typedefDecl(hasType(InnerMatcher: constantMatrixType())));
674}
675
676TEST_P(ImportMatrixType, ImportDependentSizedMatrixType) {
677 const AstTypeMatcher<DependentSizedMatrixType> dependentSizedMatrixType;
678 MatchVerifier<Decl> Verifier;
679 testImport(
680 FromCode: R"(
681 template<typename T, int Rows, int Cols>
682 using declToImport = T __attribute__((matrix_type(Rows, Cols)));
683 )",
684 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
685 AMatcher: typeAliasTemplateDecl(
686 has(typeAliasDecl(hasType(InnerMatcher: dependentSizedMatrixType())))));
687}
688
689TEST_P(ImportType, ImportUsingType) {
690 MatchVerifier<Decl> Verifier;
691 testImport(FromCode: "struct C {};"
692 "void declToImport() { using ::C; new C{}; }",
693 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
694 AMatcher: functionDecl(hasDescendant(cxxNewExpr(hasType(InnerMatcher: pointerType(
695 pointee(elaboratedType(namesType(InnerMatcher: usingType())))))))));
696}
697
698TEST_P(ImportDecl, ImportFunctionTemplateDecl) {
699 MatchVerifier<Decl> Verifier;
700 testImport(FromCode: "template <typename T> void declToImport() { };", FromLang: Lang_CXX03, ToCode: "",
701 ToLang: Lang_CXX03, Verifier, AMatcher: functionTemplateDecl());
702}
703
704TEST_P(ImportExpr, ImportCXXDependentScopeMemberExpr) {
705 MatchVerifier<Decl> Verifier;
706 testImport(FromCode: "template <typename T> struct C { T t; };"
707 "template <typename T> void declToImport() {"
708 " C<T> d;"
709 " (void)d.t;"
710 "}"
711 "void instantiate() { declToImport<int>(); }",
712 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
713 AMatcher: functionTemplateDecl(hasDescendant(
714 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
715 testImport(FromCode: "template <typename T> struct C { T t; };"
716 "template <typename T> void declToImport() {"
717 " C<T> d;"
718 " (void)(&d)->t;"
719 "}"
720 "void instantiate() { declToImport<int>(); }",
721 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
722 AMatcher: functionTemplateDecl(hasDescendant(
723 cStyleCastExpr(has(cxxDependentScopeMemberExpr())))));
724}
725
726TEST_P(ImportType, ImportTypeAliasTemplate) {
727 MatchVerifier<Decl> Verifier;
728 testImport(
729 FromCode: "template <int K>"
730 "struct dummy { static const int i = K; };"
731 "template <int K> using dummy2 = dummy<K>;"
732 "int declToImport() { return dummy2<3>::i; }",
733 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
734 AMatcher: traverse(TK: TK_AsIs,
735 InnerMatcher: functionDecl(hasDescendant(implicitCastExpr(has(declRefExpr()))),
736 unless(hasAncestor(
737 translationUnitDecl(has(typeAliasDecl())))))));
738}
739
740const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
741 varTemplateSpecializationDecl;
742
743TEST_P(ImportDecl, ImportVarTemplate) {
744 MatchVerifier<Decl> Verifier;
745 testImport(
746 FromCode: "template <typename T>"
747 "T pi = T(3.1415926535897932385L);"
748 "void declToImport() { (void)pi<int>; }",
749 FromLang: Lang_CXX14, ToCode: "", ToLang: Lang_CXX14, Verifier,
750 AMatcher: functionDecl(
751 hasDescendant(declRefExpr(to(InnerMatcher: varTemplateSpecializationDecl()))),
752 unless(hasAncestor(translationUnitDecl(has(varDecl(
753 hasName(Name: "pi"), unless(varTemplateSpecializationDecl()))))))));
754}
755
756TEST_P(ImportType, ImportPackExpansion) {
757 MatchVerifier<Decl> Verifier;
758 testImport(FromCode: "template <typename... Args>"
759 "struct dummy {"
760 " dummy(Args... args) {}"
761 " static const int i = 4;"
762 "};"
763 "int declToImport() { return dummy<int>::i; }",
764 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
765 AMatcher: traverse(TK: TK_AsIs, InnerMatcher: functionDecl(hasDescendant(returnStmt(has(
766 implicitCastExpr(has(declRefExpr()))))))));
767}
768
769TEST_P(ImportType, ImportDependentTemplateSpecialization) {
770 MatchVerifier<Decl> Verifier;
771 testImport(FromCode: "template<typename T>"
772 "struct A;"
773 "template<typename T>"
774 "struct declToImport {"
775 " typename A<T>::template B<T> a;"
776 "};",
777 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
778 AMatcher: classTemplateDecl(has(cxxRecordDecl(has(
779 fieldDecl(hasType(InnerMatcher: dependentTemplateSpecializationType())))))));
780}
781
782TEST_P(ImportType, ImportDeducedTemplateSpecialization) {
783 MatchVerifier<Decl> Verifier;
784 testImport(FromCode: "template <typename T>"
785 "class C { public: C(T); };"
786 "C declToImport(123);",
787 FromLang: Lang_CXX17, ToCode: "", ToLang: Lang_CXX17, Verifier,
788 AMatcher: varDecl(hasType(InnerMatcher: elaboratedType(
789 namesType(InnerMatcher: deducedTemplateSpecializationType())))));
790}
791
792const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
793 sizeOfPackExpr;
794
795TEST_P(ImportExpr, ImportSizeOfPackExpr) {
796 MatchVerifier<Decl> Verifier;
797 testImport(
798 FromCode: "template <typename... Ts>"
799 "void declToImport() {"
800 " const int i = sizeof...(Ts);"
801 "};"
802 "void g() { declToImport<int>(); }",
803 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
804 AMatcher: functionTemplateDecl(hasDescendant(sizeOfPackExpr())));
805 testImport(
806 FromCode: "template <typename... Ts>"
807 "using X = int[sizeof...(Ts)];"
808 "template <typename... Us>"
809 "struct Y {"
810 " X<Us..., int, double, int, Us...> f;"
811 "};"
812 "Y<float, int> declToImport;",
813 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
814 AMatcher: varDecl(hasType(InnerMatcher: classTemplateSpecializationDecl(has(fieldDecl(hasType(
815 InnerMatcher: hasUnqualifiedDesugaredType(InnerMatcher: constantArrayType(hasSize(N: 7))))))))));
816}
817
818TEST_P(ImportExpr, ImportCXXFoldExpr) {
819 auto Match1 = cxxFoldExpr(hasOperatorName(Name: "+"), isLeftFold(),
820 unless(hasFoldInit(InnerMacher: expr())));
821 auto Match2 =
822 cxxFoldExpr(hasOperatorName(Name: "-"), isLeftFold(), hasFoldInit(InnerMacher: expr()));
823 auto Match3 = cxxFoldExpr(hasOperatorName(Name: "*"), isRightFold(),
824 unless(hasFoldInit(InnerMacher: expr())));
825 auto Match4 =
826 cxxFoldExpr(hasOperatorName(Name: "/"), isRightFold(), hasFoldInit(InnerMacher: expr()));
827
828 MatchVerifier<Decl> Verifier;
829 testImport(FromCode: "template <typename... Ts>"
830 "void declToImport(Ts... args) {"
831 " const int i1 = (... + args);"
832 " const int i2 = (1 - ... - args);"
833 " const int i3 = (args * ...);"
834 " const int i4 = (args / ... / 1);"
835 "};"
836 "void g() { declToImport(1, 2, 3, 4, 5); }",
837 FromLang: Lang_CXX17, ToCode: "", ToLang: Lang_CXX17, Verifier,
838 AMatcher: functionTemplateDecl(hasDescendant(Match1), hasDescendant(Match2),
839 hasDescendant(Match3),
840 hasDescendant(Match4)));
841}
842
843/// \brief Matches __builtin_types_compatible_p:
844/// GNU extension to check equivalent types
845/// Given
846/// \code
847/// __builtin_types_compatible_p(int, int)
848/// \endcode
849// will generate TypeTraitExpr <...> 'int'
850const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
851
852TEST_P(ImportExpr, ImportTypeTraitExpr) {
853 MatchVerifier<Decl> Verifier;
854 testImport(
855 FromCode: "void declToImport() { "
856 " (void)__builtin_types_compatible_p(int, int);"
857 "}",
858 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
859 AMatcher: functionDecl(hasDescendant(typeTraitExpr(hasType(InnerMatcher: asString(Name: "int"))))));
860}
861
862const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
863
864TEST_P(ImportExpr, ImportCXXTypeidExpr) {
865 MatchVerifier<Decl> Verifier;
866 testImport(
867 FromCode: "namespace std { class type_info {}; }"
868 "void declToImport() {"
869 " int x;"
870 " auto a = typeid(int); auto b = typeid(x);"
871 "}",
872 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
873 AMatcher: traverse(
874 TK: TK_AsIs,
875 InnerMatcher: functionDecl(
876 hasDescendant(varDecl(hasName(Name: "a"), hasInitializer(InnerMatcher: hasDescendant(
877 cxxTypeidExpr())))),
878 hasDescendant(varDecl(hasName(Name: "b"), hasInitializer(InnerMatcher: hasDescendant(
879 cxxTypeidExpr())))))));
880}
881
882TEST_P(ImportExpr, ImportTypeTraitExprValDep) {
883 MatchVerifier<Decl> Verifier;
884 testImport(
885 FromCode: "template<typename T> struct declToImport {"
886 " void m() { (void)__is_pod(T); }"
887 "};"
888 "void f() { declToImport<int>().m(); }",
889 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
890 AMatcher: classTemplateDecl(has(cxxRecordDecl(has(
891 functionDecl(hasDescendant(
892 typeTraitExpr(hasType(InnerMatcher: booleanType())))))))));
893}
894
895TEST_P(ImportDecl, ImportRecordDeclInFunc) {
896 MatchVerifier<Decl> Verifier;
897 testImport(FromCode: "int declToImport() { "
898 " struct data_t {int a;int b;};"
899 " struct data_t d;"
900 " return 0;"
901 "}",
902 FromLang: Lang_C99, ToCode: "", ToLang: Lang_C99, Verifier,
903 AMatcher: functionDecl(hasBody(InnerMatcher: compoundStmt(
904 has(declStmt(hasSingleDecl(InnerMatcher: varDecl(hasName(Name: "d")))))))));
905}
906
907TEST_P(ImportDecl, ImportedVarDeclPreservesThreadLocalStorage) {
908 MatchVerifier<Decl> Verifier;
909 testImport(FromCode: "thread_local int declToImport;", FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11,
910 Verifier, AMatcher: varDecl(hasThreadStorageDuration()));
911}
912
913TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordTypeInFunc) {
914 Decl *FromTU = getTuDecl(SrcCode: "int declToImport() { "
915 " struct data_t {int a;int b;};"
916 " struct data_t d;"
917 " return 0;"
918 "}",
919 Lang: Lang_C99, FileName: "input.c");
920 auto *FromVar =
921 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "d")));
922 ASSERT_TRUE(FromVar);
923 auto ToType =
924 ImportType(FromType: FromVar->getType().getCanonicalType(), TUDecl: FromVar, ToLang: Lang_C99);
925 EXPECT_FALSE(ToType.isNull());
926}
927
928TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncParams) {
929 // This construct is not supported by ASTImporter.
930 Decl *FromTU = getTuDecl(
931 SrcCode: "int declToImport(struct data_t{int a;int b;} ***d){ return 0; }",
932 Lang: Lang_C99, FileName: "input.c");
933 auto *From = FirstDeclMatcher<FunctionDecl>().match(
934 D: FromTU, AMatcher: functionDecl(hasName(Name: "declToImport")));
935 ASSERT_TRUE(From);
936 auto *To = Import(From, Lang: Lang_C99);
937 EXPECT_EQ(To, nullptr);
938}
939
940TEST_P(ASTImporterOptionSpecificTestBase, ImportRecordDeclInFuncFromMacro) {
941 Decl *FromTU =
942 getTuDecl(SrcCode: "#define NONAME_SIZEOF(type) sizeof(struct{type *dummy;}) \n"
943 "int declToImport(){ return NONAME_SIZEOF(int); }",
944 Lang: Lang_C99, FileName: "input.c");
945 auto *From = FirstDeclMatcher<FunctionDecl>().match(
946 D: FromTU, AMatcher: functionDecl(hasName(Name: "declToImport")));
947 ASSERT_TRUE(From);
948 auto *To = Import(From, Lang: Lang_C99);
949 ASSERT_TRUE(To);
950 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
951 To, functionDecl(hasName("declToImport"),
952 hasDescendant(unaryExprOrTypeTraitExpr()))));
953}
954
955TEST_P(ASTImporterOptionSpecificTestBase,
956 ImportRecordDeclInFuncParamsFromMacro) {
957 // This construct is not supported by ASTImporter.
958 Decl *FromTU =
959 getTuDecl(SrcCode: "#define PAIR_STRUCT(type) struct data_t{type a;type b;} \n"
960 "int declToImport(PAIR_STRUCT(int) ***d){ return 0; }",
961 Lang: Lang_C99, FileName: "input.c");
962 auto *From = FirstDeclMatcher<FunctionDecl>().match(
963 D: FromTU, AMatcher: functionDecl(hasName(Name: "declToImport")));
964 ASSERT_TRUE(From);
965 auto *To = Import(From, Lang: Lang_C99);
966 EXPECT_EQ(To, nullptr);
967}
968
969const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
970 cxxPseudoDestructorExpr;
971
972TEST_P(ImportExpr, ImportCXXPseudoDestructorExpr) {
973 MatchVerifier<Decl> Verifier;
974 testImport(
975 FromCode: "typedef int T;"
976 "void declToImport(int *p) {"
977 " T t;"
978 " p->T::~T();"
979 "}",
980 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
981 AMatcher: functionDecl(hasDescendant(callExpr(has(cxxPseudoDestructorExpr())))));
982}
983
984TEST_P(ImportDecl, ImportUsingDecl) {
985 MatchVerifier<Decl> Verifier;
986 testImport(FromCode: "namespace foo { int bar; }"
987 "void declToImport() { using foo::bar; }",
988 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
989 AMatcher: functionDecl(hasDescendant(usingDecl(hasName(Name: "bar")))));
990}
991
992TEST_P(ImportDecl, ImportUsingTemplate) {
993 MatchVerifier<Decl> Verifier;
994 testImport(FromCode: "namespace ns { template <typename T> struct S {}; }"
995 "template <template <typename> class T> class X {};"
996 "void declToImport() {"
997 "using ns::S; X<S> xi; }",
998 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
999 AMatcher: functionDecl(hasDescendant(varDecl(hasTypeLoc(Inner: elaboratedTypeLoc(
1000 hasNamedTypeLoc(InnerMatcher: templateSpecializationTypeLoc(
1001 hasAnyTemplateArgumentLoc(InnerMatcher: templateArgumentLoc())))))))));
1002}
1003
1004TEST_P(ImportDecl, ImportUsingEnumDecl) {
1005 MatchVerifier<Decl> Verifier;
1006 testImport(FromCode: "namespace foo { enum bar { baz, toto, quux }; }"
1007 "void declToImport() { using enum foo::bar; }",
1008 FromLang: Lang_CXX20, ToCode: "", ToLang: Lang_CXX20, Verifier,
1009 AMatcher: functionDecl(hasDescendant(usingEnumDecl(hasName(Name: "bar")))));
1010}
1011
1012const internal::VariadicDynCastAllOfMatcher<Decl, UsingPackDecl> usingPackDecl;
1013
1014TEST_P(ImportDecl, ImportUsingPackDecl) {
1015 MatchVerifier<Decl> Verifier;
1016 testImport(
1017 FromCode: "struct A { int operator()() { return 1; } };"
1018 "struct B { int operator()() { return 2; } };"
1019 "template<typename ...T> struct C : T... { using T::operator()...; };"
1020 "C<A, B> declToImport;",
1021 FromLang: Lang_CXX20, ToCode: "", ToLang: Lang_CXX20, Verifier,
1022 AMatcher: varDecl(hasType(InnerMatcher: elaboratedType(namesType(InnerMatcher: templateSpecializationType(
1023 hasDeclaration(InnerMatcher: classTemplateSpecializationDecl(
1024 hasDescendant(usingPackDecl())))))))));
1025}
1026
1027/// \brief Matches shadow declarations introduced into a scope by a
1028/// (resolved) using declaration.
1029///
1030/// Given
1031/// \code
1032/// namespace n { int f; }
1033/// namespace declToImport { using n::f; }
1034/// \endcode
1035/// usingShadowDecl()
1036/// matches \code f \endcode
1037const internal::VariadicDynCastAllOfMatcher<Decl,
1038 UsingShadowDecl> usingShadowDecl;
1039
1040TEST_P(ImportDecl, ImportUsingShadowDecl) {
1041 MatchVerifier<Decl> Verifier;
1042 // from using-decl
1043 testImport(FromCode: "namespace foo { int bar; }"
1044 "namespace declToImport { using foo::bar; }",
1045 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1046 AMatcher: namespaceDecl(has(usingShadowDecl(hasName(Name: "bar")))));
1047 // from using-enum-decl
1048 testImport(FromCode: "namespace foo { enum bar {baz, toto, quux }; }"
1049 "namespace declToImport { using enum foo::bar; }",
1050 FromLang: Lang_CXX20, ToCode: "", ToLang: Lang_CXX20, Verifier,
1051 AMatcher: namespaceDecl(has(usingShadowDecl(hasName(Name: "baz")))));
1052}
1053
1054TEST_P(ImportExpr, ImportUnresolvedLookupExpr) {
1055 MatchVerifier<Decl> Verifier;
1056 testImport(FromCode: "template<typename T> int foo();"
1057 "template <typename T> void declToImport() {"
1058 " (void)::foo<T>;"
1059 " (void)::template foo<T>;"
1060 "}"
1061 "void instantiate() { declToImport<int>(); }",
1062 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1063 AMatcher: functionTemplateDecl(hasDescendant(unresolvedLookupExpr())));
1064}
1065
1066TEST_P(ImportExpr, ImportCXXUnresolvedConstructExpr) {
1067 MatchVerifier<Decl> Verifier;
1068 testImport(FromCode: "template <typename T> struct C { T t; };"
1069 "template <typename T> void declToImport() {"
1070 " C<T> d;"
1071 " d.t = T();"
1072 "}"
1073 "void instantiate() { declToImport<int>(); }",
1074 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1075 AMatcher: functionTemplateDecl(hasDescendant(
1076 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1077 testImport(FromCode: "template <typename T> struct C { T t; };"
1078 "template <typename T> void declToImport() {"
1079 " C<T> d;"
1080 " (&d)->t = T();"
1081 "}"
1082 "void instantiate() { declToImport<int>(); }",
1083 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1084 AMatcher: functionTemplateDecl(hasDescendant(
1085 binaryOperator(has(cxxUnresolvedConstructExpr())))));
1086}
1087
1088/// Check that function "declToImport()" (which is the templated function
1089/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
1090/// Same for class template declarations.
1091TEST_P(ImportDecl, ImportTemplatedDeclForTemplate) {
1092 MatchVerifier<Decl> Verifier;
1093 testImport(FromCode: "template <typename T> void declToImport() { T a = 1; }"
1094 "void instantiate() { declToImport<int>(); }",
1095 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1096 AMatcher: functionTemplateDecl(hasAncestor(translationUnitDecl(
1097 unless(has(functionDecl(hasName(Name: "declToImport"))))))));
1098 testImport(FromCode: "template <typename T> struct declToImport { T t; };"
1099 "void instantiate() { declToImport<int>(); }",
1100 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1101 AMatcher: classTemplateDecl(hasAncestor(translationUnitDecl(
1102 unless(has(cxxRecordDecl(hasName(Name: "declToImport"))))))));
1103}
1104
1105TEST_P(ImportDecl, ImportClassTemplatePartialSpecialization) {
1106 MatchVerifier<Decl> Verifier;
1107 auto Code =
1108 R"s(
1109 struct declToImport {
1110 template <typename T0> struct X;
1111 template <typename T0> struct X<T0 *> {};
1112 };
1113 )s";
1114 testImport(FromCode: Code, FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1115 AMatcher: recordDecl(has(classTemplateDecl()),
1116 has(classTemplateSpecializationDecl())));
1117}
1118
1119TEST_P(ImportExpr, CXXOperatorCallExpr) {
1120 MatchVerifier<Decl> Verifier;
1121 testImport(
1122 FromCode: "class declToImport {"
1123 " void f() { *this = declToImport(); }"
1124 "};",
1125 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1126 AMatcher: cxxRecordDecl(has(cxxMethodDecl(hasDescendant(cxxOperatorCallExpr())))));
1127}
1128
1129TEST_P(ImportExpr, DependentSizedArrayType) {
1130 MatchVerifier<Decl> Verifier;
1131 testImport(FromCode: "template<typename T, int Size> class declToImport {"
1132 " T data[Size];"
1133 "};",
1134 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1135 AMatcher: classTemplateDecl(has(cxxRecordDecl(
1136 has(fieldDecl(hasType(InnerMatcher: dependentSizedArrayType())))))));
1137}
1138
1139TEST_P(ImportExpr, DependentSizedExtVectorType) {
1140 MatchVerifier<Decl> Verifier;
1141 testImport(FromCode: "template<typename T, int Size>"
1142 "class declToImport {"
1143 " typedef T __attribute__((ext_vector_type(Size))) type;"
1144 "};",
1145 FromLang: Lang_CXX03, ToCode: "", ToLang: Lang_CXX03, Verifier,
1146 AMatcher: classTemplateDecl(has(cxxRecordDecl(
1147 has(typedefDecl(hasType(InnerMatcher: dependentSizedExtVectorType())))))));
1148}
1149
1150TEST_P(ASTImporterOptionSpecificTestBase, ImportUsingPackDecl) {
1151 Decl *FromTU = getTuDecl(
1152 SrcCode: "struct A { int operator()() { return 1; } };"
1153 "struct B { int operator()() { return 2; } };"
1154 "template<typename ...T> struct C : T... { using T::operator()...; };"
1155 "C<A, B> Var;",
1156 Lang: Lang_CXX20);
1157
1158 auto From = FirstDeclMatcher<UsingPackDecl>().match(D: FromTU, AMatcher: usingPackDecl());
1159 ASSERT_TRUE(From);
1160 auto To = cast<UsingPackDecl>(Val: Import(From, Lang: Lang_CXX20));
1161 ASSERT_TRUE(To);
1162
1163 ArrayRef<NamedDecl *> FromExpansions = From->expansions();
1164 ArrayRef<NamedDecl *> ToExpansions = To->expansions();
1165 ASSERT_EQ(FromExpansions.size(), ToExpansions.size());
1166 for (unsigned int I = 0; I < FromExpansions.size(); ++I) {
1167 auto ImportedExpansion = Import(From: FromExpansions[I], Lang: Lang_CXX20);
1168 EXPECT_EQ(ImportedExpansion, ToExpansions[I]);
1169 }
1170
1171 auto ImportedDC = cast<Decl>(Val: Import(From: From->getDeclContext(), Lang: Lang_CXX20));
1172 EXPECT_EQ(ImportedDC, cast<Decl>(To->getDeclContext()));
1173}
1174
1175TEST_P(ASTImporterOptionSpecificTestBase, TemplateTypeParmDeclNoDefaultArg) {
1176 Decl *FromTU = getTuDecl(SrcCode: "template<typename T> struct X {};", Lang: Lang_CXX03);
1177 auto From = FirstDeclMatcher<TemplateTypeParmDecl>().match(
1178 D: FromTU, AMatcher: templateTypeParmDecl(hasName(Name: "T")));
1179 TemplateTypeParmDecl *To = Import(From, Lang: Lang_CXX03);
1180 ASSERT_FALSE(To->hasDefaultArgument());
1181}
1182
1183TEST_P(ASTImporterOptionSpecificTestBase, TemplateTypeParmDeclDefaultArg) {
1184 Decl *FromTU =
1185 getTuDecl(SrcCode: "template<typename T = int> struct X {};", Lang: Lang_CXX03);
1186 auto From = FirstDeclMatcher<TemplateTypeParmDecl>().match(
1187 D: FromTU, AMatcher: templateTypeParmDecl(hasName(Name: "T")));
1188 TemplateTypeParmDecl *To = Import(From, Lang: Lang_CXX03);
1189 ASSERT_TRUE(To->hasDefaultArgument());
1190 QualType ToArg = To->getDefaultArgument().getArgument().getAsType();
1191 ASSERT_EQ(ToArg, QualType(To->getASTContext().IntTy));
1192}
1193
1194TEST_P(ASTImporterOptionSpecificTestBase, ImportBeginLocOfDeclRefExpr) {
1195 Decl *FromTU =
1196 getTuDecl(SrcCode: "class A { public: static int X; }; void f() { (void)A::X; }",
1197 Lang: Lang_CXX03);
1198 auto From = FirstDeclMatcher<FunctionDecl>().match(
1199 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
1200 ASSERT_TRUE(From);
1201 ASSERT_TRUE(
1202 cast<CStyleCastExpr>(cast<CompoundStmt>(From->getBody())->body_front())
1203 ->getSubExpr()
1204 ->getBeginLoc()
1205 .isValid());
1206 FunctionDecl *To = Import(From, Lang: Lang_CXX03);
1207 ASSERT_TRUE(To);
1208 ASSERT_TRUE(
1209 cast<CStyleCastExpr>(cast<CompoundStmt>(To->getBody())->body_front())
1210 ->getSubExpr()
1211 ->getBeginLoc()
1212 .isValid());
1213}
1214
1215TEST_P(ASTImporterOptionSpecificTestBase,
1216 TemplateTemplateParmDeclNoDefaultArg) {
1217 Decl *FromTU = getTuDecl(SrcCode: R"(
1218 template<template<typename> typename TT> struct Y {};
1219 )",
1220 Lang: Lang_CXX17);
1221 auto From = FirstDeclMatcher<TemplateTemplateParmDecl>().match(
1222 D: FromTU, AMatcher: templateTemplateParmDecl(hasName(Name: "TT")));
1223 TemplateTemplateParmDecl *To = Import(From, Lang: Lang_CXX17);
1224 ASSERT_FALSE(To->hasDefaultArgument());
1225}
1226
1227TEST_P(ASTImporterOptionSpecificTestBase, TemplateTemplateParmDeclDefaultArg) {
1228 Decl *FromTU = getTuDecl(SrcCode: R"(
1229 template<typename T> struct X {};
1230 template<template<typename> typename TT = X> struct Y {};
1231 )",
1232 Lang: Lang_CXX17);
1233 auto From = FirstDeclMatcher<TemplateTemplateParmDecl>().match(
1234 D: FromTU, AMatcher: templateTemplateParmDecl(hasName(Name: "TT")));
1235 TemplateTemplateParmDecl *To = Import(From, Lang: Lang_CXX17);
1236 ASSERT_TRUE(To->hasDefaultArgument());
1237 const TemplateArgument &ToDefaultArg = To->getDefaultArgument().getArgument();
1238 ASSERT_TRUE(To->isTemplateDecl());
1239 TemplateDecl *ToTemplate = ToDefaultArg.getAsTemplate().getAsTemplateDecl();
1240
1241 // Find the default argument template 'X' in the AST and compare it against
1242 // the default argument we got.
1243 auto ToExpectedDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
1244 D: To->getTranslationUnitDecl(), AMatcher: classTemplateDecl(hasName(Name: "X")));
1245 ASSERT_EQ(ToTemplate, ToExpectedDecl);
1246}
1247
1248TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclNoDefaultArg) {
1249 Decl *FromTU = getTuDecl(SrcCode: "template<int N> struct X {};", Lang: Lang_CXX03);
1250 auto From = FirstDeclMatcher<NonTypeTemplateParmDecl>().match(
1251 D: FromTU, AMatcher: nonTypeTemplateParmDecl(hasName(Name: "N")));
1252 NonTypeTemplateParmDecl *To = Import(From, Lang: Lang_CXX03);
1253 ASSERT_FALSE(To->hasDefaultArgument());
1254}
1255
1256TEST_P(ASTImporterOptionSpecificTestBase, NonTypeTemplateParmDeclDefaultArg) {
1257 Decl *FromTU = getTuDecl(SrcCode: "template<int S = 1> struct X {};", Lang: Lang_CXX03);
1258 auto From = FirstDeclMatcher<NonTypeTemplateParmDecl>().match(
1259 D: FromTU, AMatcher: nonTypeTemplateParmDecl(hasName(Name: "S")));
1260 NonTypeTemplateParmDecl *To = Import(From, Lang: Lang_CXX03);
1261 ASSERT_TRUE(To->hasDefaultArgument());
1262 Stmt *ToArg = To->getDefaultArgument().getArgument().getAsExpr();
1263 ASSERT_TRUE(isa<IntegerLiteral>(ToArg));
1264 ASSERT_EQ(cast<IntegerLiteral>(ToArg)->getValue().getLimitedValue(), 1U);
1265}
1266
1267TEST_P(ASTImporterOptionSpecificTestBase, TemplateArgumentsDefaulted) {
1268 Decl *FromTU = getTuDecl(SrcCode: R"(
1269 template<typename T> struct X {};
1270 template<typename TP = double,
1271 int NTTP = 50,
1272 template<typename> typename TT = X> struct S {};
1273 S<> s;
1274 )",
1275 Lang: Lang_CXX17);
1276 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
1277 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "S")));
1278 ASSERT_TRUE(FromSpec);
1279 auto *ToSpec = Import(From: FromSpec, Lang: Lang_CXX03);
1280 ASSERT_TRUE(ToSpec);
1281 auto const &TList = ToSpec->getTemplateArgs();
1282 for (auto const &Arg : TList.asArray()) {
1283 ASSERT_TRUE(Arg.getIsDefaulted());
1284 }
1285}
1286
1287TEST_P(ASTImporterOptionSpecificTestBase,
1288 ImportOfTemplatedDeclOfClassTemplateDecl) {
1289 Decl *FromTU = getTuDecl(SrcCode: "template<class X> struct S{};", Lang: Lang_CXX03);
1290 auto From =
1291 FirstDeclMatcher<ClassTemplateDecl>().match(D: FromTU, AMatcher: classTemplateDecl());
1292 ASSERT_TRUE(From);
1293 auto To = cast<ClassTemplateDecl>(Val: Import(From, Lang: Lang_CXX03));
1294 ASSERT_TRUE(To);
1295 Decl *ToTemplated = To->getTemplatedDecl();
1296 Decl *ToTemplated1 = Import(From: From->getTemplatedDecl(), Lang: Lang_CXX03);
1297 EXPECT_TRUE(ToTemplated1);
1298 EXPECT_EQ(ToTemplated1, ToTemplated);
1299}
1300
1301TEST_P(ASTImporterOptionSpecificTestBase,
1302 ImportOfTemplatedDeclOfFunctionTemplateDecl) {
1303 Decl *FromTU = getTuDecl(SrcCode: "template<class X> void f(){}", Lang: Lang_CXX03);
1304 auto From = FirstDeclMatcher<FunctionTemplateDecl>().match(
1305 D: FromTU, AMatcher: functionTemplateDecl());
1306 ASSERT_TRUE(From);
1307 auto To = cast<FunctionTemplateDecl>(Val: Import(From, Lang: Lang_CXX03));
1308 ASSERT_TRUE(To);
1309 Decl *ToTemplated = To->getTemplatedDecl();
1310 Decl *ToTemplated1 = Import(From: From->getTemplatedDecl(), Lang: Lang_CXX03);
1311 EXPECT_TRUE(ToTemplated1);
1312 EXPECT_EQ(ToTemplated1, ToTemplated);
1313}
1314
1315TEST_P(ASTImporterOptionSpecificTestBase,
1316 ImportOfTemplatedDeclShouldImportTheClassTemplateDecl) {
1317 Decl *FromTU = getTuDecl(SrcCode: "template<class X> struct S{};", Lang: Lang_CXX03);
1318 auto FromFT =
1319 FirstDeclMatcher<ClassTemplateDecl>().match(D: FromTU, AMatcher: classTemplateDecl());
1320 ASSERT_TRUE(FromFT);
1321
1322 auto ToTemplated =
1323 cast<CXXRecordDecl>(Val: Import(From: FromFT->getTemplatedDecl(), Lang: Lang_CXX03));
1324 EXPECT_TRUE(ToTemplated);
1325 auto ToTU = ToTemplated->getTranslationUnitDecl();
1326 auto ToFT =
1327 FirstDeclMatcher<ClassTemplateDecl>().match(D: ToTU, AMatcher: classTemplateDecl());
1328 EXPECT_TRUE(ToFT);
1329}
1330
1331TEST_P(ASTImporterOptionSpecificTestBase,
1332 ImportOfTemplatedDeclShouldImportTheFunctionTemplateDecl) {
1333 Decl *FromTU = getTuDecl(SrcCode: "template<class X> void f(){}", Lang: Lang_CXX03);
1334 auto FromFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1335 D: FromTU, AMatcher: functionTemplateDecl());
1336 ASSERT_TRUE(FromFT);
1337
1338 auto ToTemplated =
1339 cast<FunctionDecl>(Val: Import(From: FromFT->getTemplatedDecl(), Lang: Lang_CXX03));
1340 EXPECT_TRUE(ToTemplated);
1341 auto ToTU = ToTemplated->getTranslationUnitDecl();
1342 auto ToFT = FirstDeclMatcher<FunctionTemplateDecl>().match(
1343 D: ToTU, AMatcher: functionTemplateDecl());
1344 EXPECT_TRUE(ToFT);
1345}
1346
1347TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplatedDecl) {
1348 auto Code =
1349 R"(
1350 namespace x {
1351 template<class X> struct S1{};
1352 template<class X> struct S2{};
1353 template<class X> struct S3{};
1354 }
1355 )";
1356 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
1357 auto FromNs =
1358 FirstDeclMatcher<NamespaceDecl>().match(D: FromTU, AMatcher: namespaceDecl());
1359 auto ToNs = cast<NamespaceDecl>(Val: Import(From: FromNs, Lang: Lang_CXX03));
1360 ASSERT_TRUE(ToNs);
1361 auto From =
1362 FirstDeclMatcher<ClassTemplateDecl>().match(D: FromTU,
1363 AMatcher: classTemplateDecl(
1364 hasName(Name: "S2")));
1365 auto To =
1366 FirstDeclMatcher<ClassTemplateDecl>().match(D: ToNs,
1367 AMatcher: classTemplateDecl(
1368 hasName(Name: "S2")));
1369 ASSERT_TRUE(From);
1370 ASSERT_TRUE(To);
1371 auto ToTemplated = To->getTemplatedDecl();
1372 auto ToTemplated1 =
1373 cast<CXXRecordDecl>(Val: Import(From: From->getTemplatedDecl(), Lang: Lang_CXX03));
1374 EXPECT_TRUE(ToTemplated1);
1375 ASSERT_EQ(ToTemplated1, ToTemplated);
1376}
1377
1378TEST_P(ASTImporterOptionSpecificTestBase,
1379 ImportTemplateSpecializationStaticMember) {
1380 auto FromCode =
1381 R"(
1382 template <typename H> class Test{
1383 public:
1384 static const unsigned int length;
1385 };
1386
1387 template<> const unsigned int Test<int>::length;
1388 template<> const unsigned int Test<int>::length = 0;
1389 )";
1390 auto ToCode =
1391 R"(
1392 template <typename H> class Test {
1393 public:
1394 static const unsigned int length;
1395 };
1396
1397 template <> const unsigned int Test<int>::length;
1398
1399 void foo() { int i = 1 / Test<int>::length; }
1400 )";
1401 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX14);
1402 auto FromDecl = FirstDeclMatcher<VarDecl>().match(
1403 D: FromTU, AMatcher: varDecl(hasName(Name: "length"), isDefinition()));
1404 Decl *ToTu = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX14);
1405 auto ToX = Import(From: FromDecl, Lang: Lang_CXX03);
1406 auto ToDecl = FirstDeclMatcher<VarDecl>().match(
1407 D: ToTu, AMatcher: varDecl(hasName(Name: "length"), isDefinition()));
1408 EXPECT_TRUE(ToX);
1409 EXPECT_EQ(ToX, ToDecl);
1410}
1411
1412TEST_P(ASTImporterOptionSpecificTestBase, ImportChooseExpr) {
1413 // This tests the import of isConditionTrue directly to make sure the importer
1414 // gets it right.
1415 Decl *From, *To;
1416 std::tie(args&: From, args&: To) = getImportedDecl(
1417 FromSrcCode: "void declToImport() { (void)__builtin_choose_expr(1, 0, 1); }", FromLang: Lang_C99,
1418 ToSrcCode: "", ToLang: Lang_C99);
1419
1420 auto ToResults = match(Matcher: chooseExpr().bind(ID: "choose"), Context&: To->getASTContext());
1421 auto FromResults = match(Matcher: chooseExpr().bind(ID: "choose"), Context&: From->getASTContext());
1422
1423 const ChooseExpr *FromChooseExpr =
1424 selectFirst<ChooseExpr>(BoundTo: "choose", Results: FromResults);
1425 ASSERT_TRUE(FromChooseExpr);
1426
1427 const ChooseExpr *ToChooseExpr = selectFirst<ChooseExpr>(BoundTo: "choose", Results: ToResults);
1428 ASSERT_TRUE(ToChooseExpr);
1429
1430 EXPECT_EQ(FromChooseExpr->isConditionTrue(), ToChooseExpr->isConditionTrue());
1431 EXPECT_EQ(FromChooseExpr->isConditionDependent(),
1432 ToChooseExpr->isConditionDependent());
1433}
1434
1435TEST_P(ASTImporterOptionSpecificTestBase, ImportConvertVectorExpr) {
1436 Decl *From, *To;
1437 std::tie(args&: From, args&: To) = getImportedDecl(
1438 FromSrcCode: "typedef double v4double __attribute__((__vector_size__(32)));"
1439 "typedef float v4float __attribute__((__vector_size__(16)));"
1440 "v4float vf;"
1441 "void declToImport() { (void)__builtin_convertvector(vf, v4double); }",
1442 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1443
1444 auto ToResults =
1445 match(Matcher: convertVectorExpr().bind(ID: "convert"), Context&: To->getASTContext());
1446 auto FromResults =
1447 match(Matcher: convertVectorExpr().bind(ID: "convert"), Context&: From->getASTContext());
1448
1449 const ConvertVectorExpr *FromConvertVectorExpr =
1450 selectFirst<ConvertVectorExpr>(BoundTo: "convert", Results: FromResults);
1451 ASSERT_TRUE(FromConvertVectorExpr);
1452
1453 const ConvertVectorExpr *ToConvertVectorExpr =
1454 selectFirst<ConvertVectorExpr>(BoundTo: "convert", Results: ToResults);
1455 ASSERT_TRUE(ToConvertVectorExpr);
1456}
1457
1458TEST_P(ASTImporterOptionSpecificTestBase, ImportGenericSelectionExpr) {
1459 Decl *From, *To;
1460 std::tie(args&: From, args&: To) = getImportedDecl(
1461 FromSrcCode: R"(
1462 int declToImport() {
1463 int x;
1464 return _Generic(x, int: 0, default: 1);
1465 }
1466 )",
1467 FromLang: Lang_C99, ToSrcCode: "", ToLang: Lang_C99);
1468
1469 auto ToResults =
1470 match(Matcher: genericSelectionExpr().bind(ID: "expr"), Context&: To->getASTContext());
1471 auto FromResults =
1472 match(Matcher: genericSelectionExpr().bind(ID: "expr"), Context&: From->getASTContext());
1473
1474 const GenericSelectionExpr *FromGenericSelectionExpr =
1475 selectFirst<GenericSelectionExpr>(BoundTo: "expr", Results: FromResults);
1476 ASSERT_TRUE(FromGenericSelectionExpr);
1477
1478 const GenericSelectionExpr *ToGenericSelectionExpr =
1479 selectFirst<GenericSelectionExpr>(BoundTo: "expr", Results: ToResults);
1480 ASSERT_TRUE(ToGenericSelectionExpr);
1481
1482 EXPECT_EQ(FromGenericSelectionExpr->isResultDependent(),
1483 ToGenericSelectionExpr->isResultDependent());
1484 EXPECT_EQ(FromGenericSelectionExpr->getResultIndex(),
1485 ToGenericSelectionExpr->getResultIndex());
1486}
1487
1488TEST_P(ASTImporterOptionSpecificTestBase,
1489 ImportFunctionWithBackReferringParameter) {
1490 Decl *From, *To;
1491 std::tie(args&: From, args&: To) = getImportedDecl(
1492 FromSrcCode: R"(
1493 template <typename T> struct X {};
1494
1495 void declToImport(int y, X<int> &x) {}
1496
1497 template <> struct X<int> {
1498 void g() {
1499 X<int> x;
1500 declToImport(0, x);
1501 }
1502 };
1503 )",
1504 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1505
1506 MatchVerifier<Decl> Verifier;
1507 auto Matcher = functionDecl(hasName(Name: "declToImport"),
1508 parameterCountIs(N: 2),
1509 hasParameter(N: 0, InnerMatcher: hasName(Name: "y")),
1510 hasParameter(N: 1, InnerMatcher: hasName(Name: "x")),
1511 hasParameter(N: 1, InnerMatcher: hasType(InnerMatcher: asString(Name: "X<int> &"))));
1512 ASSERT_TRUE(Verifier.match(From, Matcher));
1513 EXPECT_TRUE(Verifier.match(To, Matcher));
1514}
1515
1516TEST_P(ASTImporterOptionSpecificTestBase,
1517 TUshouldNotContainTemplatedDeclOfFunctionTemplates) {
1518 Decl *From, *To;
1519 std::tie(args&: From, args&: To) =
1520 getImportedDecl(FromSrcCode: "template <typename T> void declToImport() { T a = 1; }"
1521 "void instantiate() { declToImport<int>(); }",
1522 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1523
1524 auto Check = [](Decl *D) -> bool {
1525 auto TU = D->getTranslationUnitDecl();
1526 for (auto Child : TU->decls()) {
1527 if (auto *FD = dyn_cast<FunctionDecl>(Val: Child)) {
1528 if (FD->getNameAsString() == "declToImport") {
1529 GTEST_NONFATAL_FAILURE_(
1530 "TU should not contain any FunctionDecl with name declToImport");
1531 return false;
1532 }
1533 }
1534 }
1535 return true;
1536 };
1537
1538 ASSERT_TRUE(Check(From));
1539 EXPECT_TRUE(Check(To));
1540}
1541
1542TEST_P(ASTImporterOptionSpecificTestBase,
1543 TUshouldNotContainTemplatedDeclOfClassTemplates) {
1544 Decl *From, *To;
1545 std::tie(args&: From, args&: To) =
1546 getImportedDecl(FromSrcCode: "template <typename T> struct declToImport { T t; };"
1547 "void instantiate() { declToImport<int>(); }",
1548 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1549
1550 auto Check = [](Decl *D) -> bool {
1551 auto TU = D->getTranslationUnitDecl();
1552 for (auto Child : TU->decls()) {
1553 if (auto *RD = dyn_cast<CXXRecordDecl>(Val: Child)) {
1554 if (RD->getNameAsString() == "declToImport") {
1555 GTEST_NONFATAL_FAILURE_(
1556 "TU should not contain any CXXRecordDecl with name declToImport");
1557 return false;
1558 }
1559 }
1560 }
1561 return true;
1562 };
1563
1564 ASSERT_TRUE(Check(From));
1565 EXPECT_TRUE(Check(To));
1566}
1567
1568TEST_P(ASTImporterOptionSpecificTestBase,
1569 TUshouldNotContainTemplatedDeclOfTypeAlias) {
1570 Decl *From, *To;
1571 std::tie(args&: From, args&: To) =
1572 getImportedDecl(
1573 FromSrcCode: "template <typename T> struct X {};"
1574 "template <typename T> using declToImport = X<T>;"
1575 "void instantiate() { declToImport<int> a; }",
1576 FromLang: Lang_CXX11, ToSrcCode: "", ToLang: Lang_CXX11);
1577
1578 auto Check = [](Decl *D) -> bool {
1579 auto TU = D->getTranslationUnitDecl();
1580 for (auto Child : TU->decls()) {
1581 if (auto *AD = dyn_cast<TypeAliasDecl>(Val: Child)) {
1582 if (AD->getNameAsString() == "declToImport") {
1583 GTEST_NONFATAL_FAILURE_(
1584 "TU should not contain any TypeAliasDecl with name declToImport");
1585 return false;
1586 }
1587 }
1588 }
1589 return true;
1590 };
1591
1592 ASSERT_TRUE(Check(From));
1593 EXPECT_TRUE(Check(To));
1594}
1595
1596TEST_P(ASTImporterOptionSpecificTestBase,
1597 TUshouldNotContainClassTemplateSpecializationOfImplicitInstantiation) {
1598
1599 Decl *From, *To;
1600 std::tie(args&: From, args&: To) = getImportedDecl(
1601 FromSrcCode: R"(
1602 template<class T>
1603 class Base {};
1604 class declToImport : public Base<declToImport> {};
1605 )",
1606 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1607
1608 // Check that the ClassTemplateSpecializationDecl is NOT the child of the TU.
1609 auto Pattern =
1610 translationUnitDecl(unless(has(classTemplateSpecializationDecl())));
1611 ASSERT_TRUE(
1612 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1613 EXPECT_TRUE(
1614 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1615
1616 // Check that the ClassTemplateSpecializationDecl is the child of the
1617 // ClassTemplateDecl.
1618 Pattern = translationUnitDecl(has(classTemplateDecl(
1619 hasName(Name: "Base"), has(classTemplateSpecializationDecl()))));
1620 ASSERT_TRUE(
1621 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1622 EXPECT_TRUE(
1623 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1624}
1625
1626AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector<StringRef>, Order) {
1627 size_t Index = 0;
1628 for (Decl *D : Node.decls()) {
1629 if (isa<FieldDecl>(Val: D) || isa<IndirectFieldDecl>(Val: D)) {
1630 auto *ND = cast<NamedDecl>(Val: D);
1631 if (Index == Order.size())
1632 return false;
1633 if (ND->getName() != Order[Index])
1634 return false;
1635 ++Index;
1636 }
1637 }
1638 return Index == Order.size();
1639}
1640
1641TEST_P(ASTImporterOptionSpecificTestBase,
1642 TUshouldContainClassTemplateSpecializationOfExplicitInstantiation) {
1643 Decl *From, *To;
1644 std::tie(args&: From, args&: To) = getImportedDecl(
1645 FromSrcCode: R"(
1646 namespace NS {
1647 template<class T>
1648 class X {};
1649 template class X<int>;
1650 }
1651 )",
1652 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03, Identifier: "NS");
1653
1654 // Check that the ClassTemplateSpecializationDecl is NOT the child of the
1655 // ClassTemplateDecl.
1656 auto Pattern = namespaceDecl(has(classTemplateDecl(
1657 hasName(Name: "X"), unless(has(classTemplateSpecializationDecl())))));
1658 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1659 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1660
1661 // Check that the ClassTemplateSpecializationDecl is the child of the
1662 // NamespaceDecl.
1663 Pattern = namespaceDecl(has(classTemplateSpecializationDecl(hasName(Name: "X"))));
1664 ASSERT_TRUE(MatchVerifier<Decl>{}.match(From, Pattern));
1665 EXPECT_TRUE(MatchVerifier<Decl>{}.match(To, Pattern));
1666}
1667
1668TEST_P(ASTImporterOptionSpecificTestBase,
1669 CXXRecordDeclFieldsShouldBeInCorrectOrder) {
1670 Decl *From, *To;
1671 std::tie(args&: From, args&: To) =
1672 getImportedDecl(
1673 FromSrcCode: "struct declToImport { int a; int b; };",
1674 FromLang: Lang_CXX11, ToSrcCode: "", ToLang: Lang_CXX11);
1675
1676 MatchVerifier<Decl> Verifier;
1677 ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1678 EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"}))));
1679}
1680
1681TEST_P(ASTImporterOptionSpecificTestBase,
1682 CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
1683 Decl *From, *To;
1684 std::tie(args&: From, args&: To) = getImportedDecl(
1685 // The original recursive algorithm of ASTImporter first imports 'c' then
1686 // 'b' and lastly 'a'. Therefore we must restore the order somehow.
1687 FromSrcCode: R"s(
1688 struct declToImport {
1689 int a = c + b;
1690 int b = 1;
1691 int c = 2;
1692 };
1693 )s",
1694 FromLang: Lang_CXX11, ToSrcCode: "", ToLang: Lang_CXX11);
1695
1696 MatchVerifier<Decl> Verifier;
1697 ASSERT_TRUE(
1698 Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1699 EXPECT_TRUE(
1700 Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"}))));
1701}
1702
1703TEST_P(ASTImporterOptionSpecificTestBase,
1704 CXXRecordDeclFieldAndIndirectFieldOrder) {
1705 Decl *From, *To;
1706 std::tie(args&: From, args&: To) = getImportedDecl(
1707 // First field is "a", then the field for unnamed union, then "b" and "c"
1708 // from it (indirect fields), then "d".
1709 FromSrcCode: R"s(
1710 struct declToImport {
1711 int a = d;
1712 union {
1713 int b;
1714 int c;
1715 };
1716 int d;
1717 };
1718 )s",
1719 FromLang: Lang_CXX11, ToSrcCode: "", ToLang: Lang_CXX11);
1720
1721 MatchVerifier<Decl> Verifier;
1722 ASSERT_TRUE(Verifier.match(
1723 From, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1724 EXPECT_TRUE(Verifier.match(
1725 To, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"}))));
1726}
1727
1728TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) {
1729 Decl *From, *To;
1730 std::tie(args&: From, args&: To) = getImportedDecl(
1731 FromSrcCode: R"(
1732 struct declToImport {
1733 };
1734 )",
1735 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1736
1737 MatchVerifier<Decl> Verifier;
1738 // Match the implicit Decl.
1739 auto Matcher = cxxRecordDecl(has(cxxRecordDecl()));
1740 ASSERT_TRUE(Verifier.match(From, Matcher));
1741 EXPECT_TRUE(Verifier.match(To, Matcher));
1742}
1743
1744TEST_P(ASTImporterOptionSpecificTestBase,
1745 ShouldImportImplicitCXXRecordDeclOfClassTemplate) {
1746 Decl *From, *To;
1747 std::tie(args&: From, args&: To) = getImportedDecl(
1748 FromSrcCode: R"(
1749 template <typename U>
1750 struct declToImport {
1751 };
1752 )",
1753 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1754
1755 MatchVerifier<Decl> Verifier;
1756 // Match the implicit Decl.
1757 auto Matcher = classTemplateDecl(has(cxxRecordDecl(has(cxxRecordDecl()))));
1758 ASSERT_TRUE(Verifier.match(From, Matcher));
1759 EXPECT_TRUE(Verifier.match(To, Matcher));
1760}
1761
1762TEST_P(ASTImporterOptionSpecificTestBase,
1763 ShouldImportImplicitCXXRecordDeclOfClassTemplateSpecializationDecl) {
1764 Decl *From, *To;
1765 std::tie(args&: From, args&: To) = getImportedDecl(
1766 FromSrcCode: R"(
1767 template<class T>
1768 class Base {};
1769 class declToImport : public Base<declToImport> {};
1770 )",
1771 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1772
1773 auto hasImplicitClass = has(cxxRecordDecl());
1774 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1775 hasName(Name: "Base"),
1776 has(classTemplateSpecializationDecl(hasImplicitClass)))));
1777 ASSERT_TRUE(
1778 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1779 EXPECT_TRUE(
1780 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1781}
1782
1783TEST_P(ASTImporterOptionSpecificTestBase, IDNSOrdinary) {
1784 Decl *From, *To;
1785 std::tie(args&: From, args&: To) =
1786 getImportedDecl(FromSrcCode: "void declToImport() {}", FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1787
1788 MatchVerifier<Decl> Verifier;
1789 auto Matcher = functionDecl();
1790 ASSERT_TRUE(Verifier.match(From, Matcher));
1791 EXPECT_TRUE(Verifier.match(To, Matcher));
1792 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1793}
1794
1795TEST_P(ASTImporterOptionSpecificTestBase, IDNSOfNonmemberOperator) {
1796 Decl *FromTU = getTuDecl(
1797 SrcCode: R"(
1798 struct X {};
1799 void operator<<(int, X);
1800 )",
1801 Lang: Lang_CXX03);
1802 Decl *From = LastDeclMatcher<Decl>{}.match(D: FromTU, AMatcher: functionDecl());
1803 const Decl *To = Import(From, ToLang: Lang_CXX03);
1804 EXPECT_EQ(From->getIdentifierNamespace(), To->getIdentifierNamespace());
1805}
1806
1807TEST_P(ASTImporterOptionSpecificTestBase,
1808 ShouldImportMembersOfClassTemplateSpecializationDecl) {
1809 Decl *From, *To;
1810 std::tie(args&: From, args&: To) = getImportedDecl(
1811 FromSrcCode: R"(
1812 template<class T>
1813 class Base { int a; };
1814 class declToImport : Base<declToImport> {};
1815 )",
1816 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03);
1817
1818 auto Pattern = translationUnitDecl(has(classTemplateDecl(
1819 hasName(Name: "Base"),
1820 has(classTemplateSpecializationDecl(has(fieldDecl(hasName(Name: "a"))))))));
1821 ASSERT_TRUE(
1822 MatchVerifier<Decl>{}.match(From->getTranslationUnitDecl(), Pattern));
1823 EXPECT_TRUE(
1824 MatchVerifier<Decl>{}.match(To->getTranslationUnitDecl(), Pattern));
1825}
1826
1827TEST_P(ASTImporterOptionSpecificTestBase,
1828 ImportDefinitionOfClassTemplateAfterFwdDecl) {
1829 {
1830 Decl *FromTU = getTuDecl(
1831 SrcCode: R"(
1832 template <typename T>
1833 struct B;
1834 )",
1835 Lang: Lang_CXX03, FileName: "input0.cc");
1836 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1837 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "B")));
1838
1839 Import(From: FromD, Lang: Lang_CXX03);
1840 }
1841
1842 {
1843 Decl *FromTU = getTuDecl(
1844 SrcCode: R"(
1845 template <typename T>
1846 struct B {
1847 void f();
1848 };
1849 )",
1850 Lang: Lang_CXX03, FileName: "input1.cc");
1851 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
1852 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
1853 Import(From: FromD, Lang: Lang_CXX03);
1854 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
1855 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "B")));
1856 auto *ToCTD = cast<ClassTemplateDecl>(Val: Import(From: FromCTD, Lang: Lang_CXX03));
1857 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
1858 }
1859}
1860
1861TEST_P(ASTImporterOptionSpecificTestBase,
1862 ImportDefinitionOfClassTemplateIfThereIsAnExistingFwdDeclAndDefinition) {
1863 Decl *ToTU = getToTuDecl(
1864 ToSrcCode: R"(
1865 template <typename T>
1866 struct B {
1867 void f();
1868 };
1869
1870 template <typename T>
1871 struct B;
1872 )",
1873 ToLang: Lang_CXX03);
1874 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1875 [](const ClassTemplateDecl *T) {
1876 return T->isThisDeclarationADefinition();
1877 })
1878 .match(ToTU, classTemplateDecl()));
1879
1880 Decl *FromTU = getTuDecl(
1881 SrcCode: R"(
1882 template <typename T>
1883 struct B {
1884 void f();
1885 };
1886 )",
1887 Lang: Lang_CXX03, FileName: "input1.cc");
1888 ClassTemplateDecl *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
1889 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "B")));
1890
1891 Import(From: FromD, Lang: Lang_CXX03);
1892
1893 // We should have only one definition.
1894 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateDecl>(
1895 [](const ClassTemplateDecl *T) {
1896 return T->isThisDeclarationADefinition();
1897 })
1898 .match(ToTU, classTemplateDecl()));
1899}
1900
1901TEST_P(ASTImporterOptionSpecificTestBase,
1902 ImportDefinitionOfClassIfThereIsAnExistingFwdDeclAndDefinition) {
1903 Decl *ToTU = getToTuDecl(
1904 ToSrcCode: R"(
1905 struct B {
1906 void f();
1907 };
1908
1909 struct B;
1910 )",
1911 ToLang: Lang_CXX03);
1912 ASSERT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
1913 ToTU, cxxRecordDecl(unless(isImplicit()))));
1914
1915 Decl *FromTU = getTuDecl(
1916 SrcCode: R"(
1917 struct B {
1918 void f();
1919 };
1920 )",
1921 Lang: Lang_CXX03, FileName: "input1.cc");
1922 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
1923 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "B")));
1924
1925 Import(From: FromD, Lang: Lang_CXX03);
1926
1927 EXPECT_EQ(2u, DeclCounter<CXXRecordDecl>().match(
1928 ToTU, cxxRecordDecl(unless(isImplicit()))));
1929}
1930
1931static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
1932 EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
1933 EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
1934 EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
1935 EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
1936}
1937static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
1938 SourceManager &SM1, SourceManager &SM2) {
1939 CompareSourceLocs(Loc1: FullSourceLoc{ Range1.getBegin(), SM1 },
1940 Loc2: FullSourceLoc{ Range2.getBegin(), SM2 });
1941 CompareSourceLocs(Loc1: FullSourceLoc{ Range1.getEnd(), SM1 },
1942 Loc2: FullSourceLoc{ Range2.getEnd(), SM2 });
1943}
1944TEST_P(ASTImporterOptionSpecificTestBase, ImportSourceLocs) {
1945 Decl *FromTU = getTuDecl(
1946 SrcCode: R"(
1947 #define MFOO(arg) arg = arg + 1
1948
1949 void foo() {
1950 int a = 5;
1951 MFOO(a);
1952 }
1953 )",
1954 Lang: Lang_CXX03);
1955 auto FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: functionDecl());
1956 auto ToD = Import(From: FromD, Lang: Lang_CXX03);
1957
1958 auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(D: ToD, AMatcher: declRefExpr());
1959 auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(D: FromTU, AMatcher: declRefExpr());
1960 auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(D: ToD, AMatcher: integerLiteral());
1961 auto FromRHS =
1962 LastDeclMatcher<IntegerLiteral>().match(D: FromTU, AMatcher: integerLiteral());
1963
1964 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1965 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1966 CompareSourceRanges(Range1: ToD->getSourceRange(), Range2: FromD->getSourceRange(), SM1&: ToSM,
1967 SM2&: FromSM);
1968 CompareSourceRanges(Range1: ToLHS->getSourceRange(), Range2: FromLHS->getSourceRange(), SM1&: ToSM,
1969 SM2&: FromSM);
1970 CompareSourceRanges(Range1: ToRHS->getSourceRange(), Range2: FromRHS->getSourceRange(), SM1&: ToSM,
1971 SM2&: FromSM);
1972}
1973
1974TEST_P(ASTImporterOptionSpecificTestBase, ImportNestedMacro) {
1975 Decl *FromTU = getTuDecl(
1976 SrcCode: R"(
1977 #define FUNC_INT void declToImport
1978 #define FUNC FUNC_INT
1979 FUNC(int a);
1980 )",
1981 Lang: Lang_CXX03);
1982 auto FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: functionDecl());
1983 auto ToD = Import(From: FromD, Lang: Lang_CXX03);
1984
1985 SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
1986 SourceManager &FromSM = FromD->getASTContext().getSourceManager();
1987 CompareSourceRanges(Range1: ToD->getSourceRange(), Range2: FromD->getSourceRange(), SM1&: ToSM,
1988 SM2&: FromSM);
1989}
1990
1991TEST_P(
1992 ASTImporterOptionSpecificTestBase,
1993 ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition) {
1994 Decl *ToTU = getToTuDecl(
1995 ToSrcCode: R"(
1996 template <typename T>
1997 struct B;
1998
1999 template <>
2000 struct B<int> {};
2001
2002 template <>
2003 struct B<int>;
2004 )",
2005 ToLang: Lang_CXX03);
2006 // We should have only one definition.
2007 ASSERT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
2008 [](const ClassTemplateSpecializationDecl *T) {
2009 return T->isThisDeclarationADefinition();
2010 })
2011 .match(ToTU, classTemplateSpecializationDecl()));
2012
2013 Decl *FromTU = getTuDecl(
2014 SrcCode: R"(
2015 template <typename T>
2016 struct B;
2017
2018 template <>
2019 struct B<int> {};
2020 )",
2021 Lang: Lang_CXX03, FileName: "input1.cc");
2022 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
2023 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "B")));
2024
2025 Import(From: FromD, Lang: Lang_CXX03);
2026
2027 // We should have only one definition.
2028 EXPECT_EQ(1u, DeclCounterWithPredicate<ClassTemplateSpecializationDecl>(
2029 [](const ClassTemplateSpecializationDecl *T) {
2030 return T->isThisDeclarationADefinition();
2031 })
2032 .match(ToTU, classTemplateSpecializationDecl()));
2033}
2034
2035TEST_P(ASTImporterOptionSpecificTestBase, ObjectsWithUnnamedStructType) {
2036 Decl *FromTU = getTuDecl(
2037 SrcCode: R"(
2038 struct { int a; int b; } object0 = { 2, 3 };
2039 struct { int x; int y; int z; } object1;
2040 )",
2041 Lang: Lang_CXX03, FileName: "input0.cc");
2042
2043 auto *Obj0 =
2044 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "object0")));
2045 auto *From0 = getRecordDecl(D: Obj0);
2046 auto *Obj1 =
2047 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "object1")));
2048 auto *From1 = getRecordDecl(D: Obj1);
2049
2050 auto *To0 = Import(From: From0, Lang: Lang_CXX03);
2051 auto *To1 = Import(From: From1, Lang: Lang_CXX03);
2052
2053 EXPECT_TRUE(To0);
2054 EXPECT_TRUE(To1);
2055 EXPECT_NE(To0, To1);
2056 EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl());
2057}
2058
2059TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecords) {
2060 auto *Code =
2061 R"(
2062 struct X {
2063 struct { int a; };
2064 struct { int b; };
2065 };
2066 )";
2067 Decl *FromTU0 = getTuDecl(SrcCode: Code, Lang: Lang_C99, FileName: "input0.c");
2068
2069 Decl *FromTU1 = getTuDecl(SrcCode: Code, Lang: Lang_C99, FileName: "input1.c");
2070
2071 auto *X0 =
2072 FirstDeclMatcher<RecordDecl>().match(D: FromTU0, AMatcher: recordDecl(hasName(Name: "X")));
2073 auto *X1 =
2074 FirstDeclMatcher<RecordDecl>().match(D: FromTU1, AMatcher: recordDecl(hasName(Name: "X")));
2075 Import(From: X0, Lang: Lang_C99);
2076 Import(From: X1, Lang: Lang_C99);
2077
2078 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2079 // We expect no (ODR) warning during the import.
2080 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
2081 EXPECT_EQ(1u,
2082 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
2083}
2084
2085TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
2086 Decl *FromTU0 = getTuDecl(
2087 SrcCode: R"(
2088 struct X {
2089 struct { int a; };
2090 struct { int b; };
2091 };
2092 )",
2093 Lang: Lang_C99, FileName: "input0.c");
2094
2095 Decl *FromTU1 = getTuDecl(
2096 SrcCode: R"(
2097 struct X { // reversed order
2098 struct { int b; };
2099 struct { int a; };
2100 };
2101 )",
2102 Lang: Lang_C99, FileName: "input1.c");
2103
2104 auto *X0 =
2105 FirstDeclMatcher<RecordDecl>().match(D: FromTU0, AMatcher: recordDecl(hasName(Name: "X")));
2106 auto *X1 =
2107 FirstDeclMatcher<RecordDecl>().match(D: FromTU1, AMatcher: recordDecl(hasName(Name: "X")));
2108 Import(From: X0, Lang: Lang_C99);
2109 Import(From: X1, Lang: Lang_C99);
2110
2111 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2112 // We expect one (ODR) warning during the import.
2113 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
2114 EXPECT_EQ(1u,
2115 DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
2116}
2117
2118TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag) {
2119 auto Pattern = varDecl(hasName(Name: "x"));
2120 VarDecl *Imported1;
2121 {
2122 Decl *FromTU = getTuDecl(SrcCode: "extern int x;", Lang: Lang_CXX03, FileName: "input0.cc");
2123 auto *FromD = FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: Pattern);
2124 Imported1 = cast<VarDecl>(Val: Import(From: FromD, Lang: Lang_CXX03));
2125 }
2126 VarDecl *Imported2;
2127 {
2128 Decl *FromTU = getTuDecl(SrcCode: "int x;", Lang: Lang_CXX03, FileName: "input1.cc");
2129 auto *FromD = FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: Pattern);
2130 Imported2 = cast<VarDecl>(Val: Import(From: FromD, Lang: Lang_CXX03));
2131 }
2132 EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl());
2133 EXPECT_FALSE(Imported2->isUsed(false));
2134 {
2135 Decl *FromTU = getTuDecl(SrcCode: "extern int x; int f() { return x; }", Lang: Lang_CXX03,
2136 FileName: "input2.cc");
2137 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2138 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
2139 Import(From: FromD, Lang: Lang_CXX03);
2140 }
2141 EXPECT_TRUE(Imported2->isUsed(false));
2142}
2143
2144TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag2) {
2145 auto Pattern = varDecl(hasName(Name: "x"));
2146 VarDecl *ExistingD;
2147 {
2148 Decl *ToTU = getToTuDecl(ToSrcCode: "int x = 1;", ToLang: Lang_CXX03);
2149 ExistingD = FirstDeclMatcher<VarDecl>().match(D: ToTU, AMatcher: Pattern);
2150 }
2151 EXPECT_FALSE(ExistingD->isUsed(false));
2152 {
2153 Decl *FromTU =
2154 getTuDecl(SrcCode: "int x = 1; int f() { return x; }", Lang: Lang_CXX03, FileName: "input1.cc");
2155 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2156 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
2157 Import(From: FromD, Lang: Lang_CXX03);
2158 }
2159 EXPECT_TRUE(ExistingD->isUsed(false));
2160}
2161
2162TEST_P(ASTImporterOptionSpecificTestBase, ImportDoesUpdateUsedFlag3) {
2163 auto Pattern = varDecl(hasName(Name: "a"));
2164 VarDecl *ExistingD;
2165 {
2166 Decl *ToTU = getToTuDecl(
2167 ToSrcCode: R"(
2168 struct A {
2169 static const int a = 1;
2170 };
2171 )",
2172 ToLang: Lang_CXX03);
2173 ExistingD = FirstDeclMatcher<VarDecl>().match(D: ToTU, AMatcher: Pattern);
2174 }
2175 EXPECT_FALSE(ExistingD->isUsed(false));
2176 {
2177 Decl *FromTU = getTuDecl(
2178 SrcCode: R"(
2179 struct A {
2180 static const int a = 1;
2181 };
2182 const int *f() { return &A::a; } // requires storage,
2183 // thus used flag will be set
2184 )",
2185 Lang: Lang_CXX03, FileName: "input1.cc");
2186 auto *FromFunD = FirstDeclMatcher<FunctionDecl>().match(
2187 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
2188 auto *FromD = FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: Pattern);
2189 ASSERT_TRUE(FromD->isUsed(false));
2190 Import(From: FromFunD, Lang: Lang_CXX03);
2191 }
2192 EXPECT_TRUE(ExistingD->isUsed(false));
2193}
2194
2195TEST_P(ASTImporterOptionSpecificTestBase, ReimportWithUsedFlag) {
2196 auto Pattern = varDecl(hasName(Name: "x"));
2197
2198 Decl *FromTU = getTuDecl(SrcCode: "int x;", Lang: Lang_CXX03, FileName: "input0.cc");
2199 auto *FromD = FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: Pattern);
2200
2201 auto *Imported1 = cast<VarDecl>(Val: Import(From: FromD, Lang: Lang_CXX03));
2202
2203 ASSERT_FALSE(Imported1->isUsed(false));
2204
2205 FromD->setIsUsed();
2206 auto *Imported2 = cast<VarDecl>(Val: Import(From: FromD, Lang: Lang_CXX03));
2207
2208 EXPECT_EQ(Imported1, Imported2);
2209 EXPECT_TRUE(Imported2->isUsed(false));
2210}
2211
2212struct ImportFunctions : ASTImporterOptionSpecificTestBase {};
2213
2214TEST_P(ImportFunctions, ImportPrototypeOfRecursiveFunction) {
2215 Decl *FromTU = getTuDecl(SrcCode: "void f(); void f() { f(); }", Lang: Lang_CXX03);
2216 auto Pattern = functionDecl(hasName(Name: "f"));
2217 auto *From =
2218 FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern); // Proto
2219
2220 Decl *ImportedD = Import(From, Lang: Lang_CXX03);
2221 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2222
2223 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2224 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2225 auto *To1 = LastDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2226 EXPECT_TRUE(ImportedD == To0);
2227 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2228 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2229 EXPECT_EQ(To1->getPreviousDecl(), To0);
2230}
2231
2232TEST_P(ImportFunctions, ImportDefinitionOfRecursiveFunction) {
2233 Decl *FromTU = getTuDecl(SrcCode: "void f(); void f() { f(); }", Lang: Lang_CXX03);
2234 auto Pattern = functionDecl(hasName(Name: "f"));
2235 auto *From =
2236 LastDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern); // Def
2237
2238 Decl *ImportedD = Import(From, Lang: Lang_CXX03);
2239 Decl *ToTU = ImportedD->getTranslationUnitDecl();
2240
2241 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2242 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2243 auto *To1 = LastDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2244 EXPECT_TRUE(ImportedD == To1);
2245 EXPECT_FALSE(To0->doesThisDeclarationHaveABody());
2246 EXPECT_TRUE(To1->doesThisDeclarationHaveABody());
2247 EXPECT_EQ(To1->getPreviousDecl(), To0);
2248}
2249
2250TEST_P(ImportFunctions, OverriddenMethodsShouldBeImported) {
2251 auto Code =
2252 R"(
2253 struct B { virtual void f(); };
2254 void B::f() {}
2255 struct D : B { void f(); };
2256 )";
2257 auto Pattern =
2258 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "D"))));
2259 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
2260 CXXMethodDecl *Proto =
2261 FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU, AMatcher: Pattern);
2262
2263 ASSERT_EQ(Proto->size_overridden_methods(), 1u);
2264 CXXMethodDecl *To = cast<CXXMethodDecl>(Val: Import(From: Proto, Lang: Lang_CXX03));
2265 EXPECT_EQ(To->size_overridden_methods(), 1u);
2266}
2267
2268TEST_P(ImportFunctions, VirtualFlagShouldBePreservedWhenImportingPrototype) {
2269 auto Code =
2270 R"(
2271 struct B { virtual void f(); };
2272 void B::f() {}
2273 )";
2274 auto Pattern =
2275 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))));
2276 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
2277 CXXMethodDecl *Proto =
2278 FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU, AMatcher: Pattern);
2279 CXXMethodDecl *Def = LastDeclMatcher<CXXMethodDecl>().match(D: FromTU, AMatcher: Pattern);
2280
2281 ASSERT_TRUE(Proto->isVirtual());
2282 ASSERT_TRUE(Def->isVirtual());
2283 CXXMethodDecl *To = cast<CXXMethodDecl>(Val: Import(From: Proto, Lang: Lang_CXX03));
2284 EXPECT_TRUE(To->isVirtual());
2285}
2286
2287TEST_P(ImportFunctions,
2288 ImportDefinitionIfThereIsAnExistingDefinitionAndFwdDecl) {
2289 Decl *ToTU = getToTuDecl(
2290 ToSrcCode: R"(
2291 void f() {}
2292 void f();
2293 )",
2294 ToLang: Lang_CXX03);
2295 ASSERT_EQ(1u,
2296 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2297 return FD->doesThisDeclarationHaveABody();
2298 }).match(ToTU, functionDecl()));
2299
2300 Decl *FromTU = getTuDecl(SrcCode: "void f() {}", Lang: Lang_CXX03, FileName: "input0.cc");
2301 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: functionDecl());
2302
2303 Import(From: FromD, Lang: Lang_CXX03);
2304
2305 EXPECT_EQ(1u,
2306 DeclCounterWithPredicate<FunctionDecl>([](const FunctionDecl *FD) {
2307 return FD->doesThisDeclarationHaveABody();
2308 }).match(ToTU, functionDecl()));
2309}
2310
2311TEST_P(ImportFunctions, ImportOverriddenMethodTwice) {
2312 auto Code =
2313 R"(
2314 struct B { virtual void f(); };
2315 struct D:B { void f(); };
2316 )";
2317 auto BFP =
2318 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))));
2319 auto DFP =
2320 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "D"))));
2321
2322 Decl *FromTU0 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
2323 auto *DF = FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU0, AMatcher: DFP);
2324 Import(From: DF, Lang: Lang_CXX03);
2325
2326 Decl *FromTU1 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input1.cc");
2327 auto *BF = FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU1, AMatcher: BFP);
2328 Import(From: BF, Lang: Lang_CXX03);
2329
2330 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2331
2332 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2333 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2334}
2335
2336TEST_P(ImportFunctions, ImportOverriddenMethodTwiceDefinitionFirst) {
2337 auto CodeWithoutDef =
2338 R"(
2339 struct B { virtual void f(); };
2340 struct D:B { void f(); };
2341 )";
2342 auto CodeWithDef =
2343 R"(
2344 struct B { virtual void f(){}; };
2345 struct D:B { void f(){}; };
2346 )";
2347 auto BFP =
2348 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))));
2349 auto DFP =
2350 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "D"))));
2351 auto BFDefP = cxxMethodDecl(
2352 hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))), isDefinition());
2353 auto DFDefP = cxxMethodDecl(
2354 hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "D"))), isDefinition());
2355 auto FDefAllP = cxxMethodDecl(hasName(Name: "f"), isDefinition());
2356
2357 {
2358 Decl *FromTU = getTuDecl(SrcCode: CodeWithDef, Lang: Lang_CXX03, FileName: "input0.cc");
2359 auto *FromD = FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU, AMatcher: DFP);
2360 Import(From: FromD, Lang: Lang_CXX03);
2361 }
2362 {
2363 Decl *FromTU = getTuDecl(SrcCode: CodeWithoutDef, Lang: Lang_CXX03, FileName: "input1.cc");
2364 auto *FromB = FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU, AMatcher: BFP);
2365 Import(From: FromB, Lang: Lang_CXX03);
2366 }
2367
2368 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2369
2370 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2371 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2372 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 1u);
2373 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 1u);
2374 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FDefAllP), 2u);
2375}
2376
2377TEST_P(ImportFunctions, ImportOverriddenMethodTwiceOutOfClassDef) {
2378 auto Code =
2379 R"(
2380 struct B { virtual void f(); };
2381 struct D:B { void f(); };
2382 void B::f(){};
2383 )";
2384
2385 auto BFP =
2386 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))));
2387 auto BFDefP = cxxMethodDecl(
2388 hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))), isDefinition());
2389 auto DFP = cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "D"))),
2390 unless(isDefinition()));
2391
2392 Decl *FromTU0 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
2393 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU0, AMatcher: DFP);
2394 Import(From: D, Lang: Lang_CXX03);
2395
2396 Decl *FromTU1 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input1.cc");
2397 auto *B = FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU1, AMatcher: BFP);
2398 Import(From: B, Lang: Lang_CXX03);
2399
2400 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2401
2402 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2403 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2404
2405 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2406 D: ToTU, AMatcher: cxxRecordDecl(hasName(Name: "B")));
2407 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(D: ToTU, AMatcher: BFP);
2408 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2409 D: ToTU, AMatcher: cxxMethodDecl(hasName(Name: "f"), isDefinition()));
2410
2411 // The definition should be out-of-class.
2412 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2413 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2414 ToBFOutOfClass->getLexicalDeclContext());
2415 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2416 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2417
2418 // Check that the redecl chain is intact.
2419 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2420}
2421
2422TEST_P(ImportFunctions,
2423 ImportOverriddenMethodTwiceOutOfClassDefInSeparateCode) {
2424 auto CodeTU0 =
2425 R"(
2426 struct B { virtual void f(); };
2427 struct D:B { void f(); };
2428 )";
2429 auto CodeTU1 =
2430 R"(
2431 struct B { virtual void f(); };
2432 struct D:B { void f(); };
2433 void B::f(){}
2434 void D::f(){}
2435 void foo(B &b, D &d) { b.f(); d.f(); }
2436 )";
2437
2438 auto BFP =
2439 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))));
2440 auto BFDefP = cxxMethodDecl(
2441 hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "B"))), isDefinition());
2442 auto DFP =
2443 cxxMethodDecl(hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "D"))));
2444 auto DFDefP = cxxMethodDecl(
2445 hasName(Name: "f"), hasParent(cxxRecordDecl(hasName(Name: "D"))), isDefinition());
2446 auto FooDef = functionDecl(hasName(Name: "foo"));
2447
2448 {
2449 Decl *FromTU0 = getTuDecl(SrcCode: CodeTU0, Lang: Lang_CXX03, FileName: "input0.cc");
2450 auto *D = FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU0, AMatcher: DFP);
2451 Import(From: D, Lang: Lang_CXX03);
2452 }
2453
2454 {
2455 Decl *FromTU1 = getTuDecl(SrcCode: CodeTU1, Lang: Lang_CXX03, FileName: "input1.cc");
2456 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(D: FromTU1, AMatcher: FooDef);
2457 Import(From: Foo, Lang: Lang_CXX03);
2458 }
2459
2460 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2461
2462 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFP), 1u);
2463 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFP), 1u);
2464 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, BFDefP), 0u);
2465 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, DFDefP), 0u);
2466
2467 auto *ToB = FirstDeclMatcher<CXXRecordDecl>().match(
2468 D: ToTU, AMatcher: cxxRecordDecl(hasName(Name: "B")));
2469 auto *ToD = FirstDeclMatcher<CXXRecordDecl>().match(
2470 D: ToTU, AMatcher: cxxRecordDecl(hasName(Name: "D")));
2471 auto *ToBFInClass = FirstDeclMatcher<CXXMethodDecl>().match(D: ToTU, AMatcher: BFP);
2472 auto *ToBFOutOfClass = FirstDeclMatcher<CXXMethodDecl>().match(
2473 D: ToTU, AMatcher: cxxMethodDecl(hasName(Name: "f"), isDefinition()));
2474 auto *ToDFInClass = FirstDeclMatcher<CXXMethodDecl>().match(D: ToTU, AMatcher: DFP);
2475 auto *ToDFOutOfClass = LastDeclMatcher<CXXMethodDecl>().match(
2476 D: ToTU, AMatcher: cxxMethodDecl(hasName(Name: "f"), isDefinition()));
2477
2478 // The definition should be out-of-class.
2479 EXPECT_NE(ToBFInClass, ToBFOutOfClass);
2480 EXPECT_NE(ToBFInClass->getLexicalDeclContext(),
2481 ToBFOutOfClass->getLexicalDeclContext());
2482 EXPECT_EQ(ToBFOutOfClass->getDeclContext(), ToB);
2483 EXPECT_EQ(ToBFOutOfClass->getLexicalDeclContext(), ToTU);
2484
2485 EXPECT_NE(ToDFInClass, ToDFOutOfClass);
2486 EXPECT_NE(ToDFInClass->getLexicalDeclContext(),
2487 ToDFOutOfClass->getLexicalDeclContext());
2488 EXPECT_EQ(ToDFOutOfClass->getDeclContext(), ToD);
2489 EXPECT_EQ(ToDFOutOfClass->getLexicalDeclContext(), ToTU);
2490
2491 // Check that the redecl chain is intact.
2492 EXPECT_EQ(ToBFOutOfClass->getPreviousDecl(), ToBFInClass);
2493 EXPECT_EQ(ToDFOutOfClass->getPreviousDecl(), ToDFInClass);
2494}
2495
2496TEST_P(ASTImporterOptionSpecificTestBase,
2497 ImportVirtualOverriddenMethodOnALoop) {
2498 // B::f() calls => f1() ==> C ==> C::f()
2499 // \
2500 // \---- A::f()
2501 //
2502 // C::f()'s ImportOverriddenMethods() asserts B::isVirtual(), so B::f()'s
2503 // ImportOverriddenMethods() should be completed before B::f()'s body
2504 const char *Code =
2505 R"(
2506 void f1();
2507 class A {
2508 virtual void f(){}
2509 };
2510 class B: public A {
2511 void f() override {
2512 f1();
2513 }
2514 };
2515 class C: public B {
2516 void f() override {}
2517 };
2518 void f1() { C c; }
2519 )";
2520 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
2521
2522 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
2523 D: FromTU, AMatcher: cxxMethodDecl(hasName(Name: "B::f")));
2524
2525 auto *ToBF = Import(From: FromF, Lang: Lang_CXX11);
2526 EXPECT_TRUE(ToBF->isVirtual());
2527
2528 auto *ToCF = FirstDeclMatcher<CXXMethodDecl>().match(
2529 D: ToBF->getTranslationUnitDecl(), AMatcher: cxxMethodDecl(hasName(Name: "C::f")));
2530 EXPECT_TRUE(ToCF->isVirtual());
2531}
2532
2533TEST_P(ASTImporterOptionSpecificTestBase, ImportVariableChainInC) {
2534 std::string Code = "static int v; static int v = 0;";
2535 auto Pattern = varDecl(hasName(Name: "v"));
2536
2537 TranslationUnitDecl *FromTu = getTuDecl(SrcCode: Code, Lang: Lang_C99, FileName: "input0.c");
2538
2539 auto *From0 = FirstDeclMatcher<VarDecl>().match(D: FromTu, AMatcher: Pattern);
2540 auto *From1 = LastDeclMatcher<VarDecl>().match(D: FromTu, AMatcher: Pattern);
2541
2542 auto *To0 = Import(From: From0, Lang: Lang_C99);
2543 auto *To1 = Import(From: From1, Lang: Lang_C99);
2544
2545 EXPECT_TRUE(To0);
2546 ASSERT_TRUE(To1);
2547 EXPECT_NE(To0, To1);
2548 EXPECT_EQ(To1->getPreviousDecl(), To0);
2549}
2550
2551TEST_P(ImportFunctions, ImportFromDifferentScopedAnonNamespace) {
2552 TranslationUnitDecl *FromTu =
2553 getTuDecl(SrcCode: "namespace NS0 { namespace { void f(); } }"
2554 "namespace NS1 { namespace { void f(); } }",
2555 Lang: Lang_CXX03, FileName: "input0.cc");
2556 auto Pattern = functionDecl(hasName(Name: "f"));
2557
2558 auto *FromF0 = FirstDeclMatcher<FunctionDecl>().match(D: FromTu, AMatcher: Pattern);
2559 auto *FromF1 = LastDeclMatcher<FunctionDecl>().match(D: FromTu, AMatcher: Pattern);
2560
2561 auto *ToF0 = Import(From: FromF0, Lang: Lang_CXX03);
2562 auto *ToF1 = Import(From: FromF1, Lang: Lang_CXX03);
2563
2564 EXPECT_TRUE(ToF0);
2565 ASSERT_TRUE(ToF1);
2566 EXPECT_NE(ToF0, ToF1);
2567 EXPECT_FALSE(ToF1->getPreviousDecl());
2568}
2569
2570TEST_P(ImportFunctions, ImportFunctionFromUnnamedNamespace) {
2571 {
2572 Decl *FromTU = getTuDecl(SrcCode: "namespace { void f() {} } void g0() { f(); }",
2573 Lang: Lang_CXX03, FileName: "input0.cc");
2574 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2575 D: FromTU, AMatcher: functionDecl(hasName(Name: "g0")));
2576
2577 Import(From: FromD, Lang: Lang_CXX03);
2578 }
2579 {
2580 Decl *FromTU =
2581 getTuDecl(SrcCode: "namespace { void f() { int a; } } void g1() { f(); }",
2582 Lang: Lang_CXX03, FileName: "input1.cc");
2583 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2584 D: FromTU, AMatcher: functionDecl(hasName(Name: "g1")));
2585 Import(From: FromD, Lang: Lang_CXX03);
2586 }
2587
2588 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2589 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
2590 2u);
2591}
2592
2593TEST_P(ImportFunctions, ImportImplicitFunctionsInLambda) {
2594 Decl *FromTU = getTuDecl(
2595 SrcCode: R"(
2596 void foo() {
2597 (void)[]() { ; };
2598 }
2599 )",
2600 Lang: Lang_CXX11);
2601 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2602 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo")));
2603 auto *ToD = Import(From: FromD, Lang: Lang_CXX03);
2604 EXPECT_TRUE(ToD);
2605 CXXRecordDecl *LambdaRec =
2606 cast<LambdaExpr>(Val: cast<CStyleCastExpr>(
2607 Val: *cast<CompoundStmt>(Val: ToD->getBody())->body_begin())
2608 ->getSubExpr())
2609 ->getLambdaClass();
2610 EXPECT_TRUE(LambdaRec->getDestructor());
2611}
2612
2613TEST_P(ImportFunctions,
2614 CallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2615 Decl *FromTU = getTuDecl(
2616 SrcCode: R"(
2617 struct X {
2618 template <typename T>
2619 void foo(){}
2620 };
2621 void f() {
2622 X x;
2623 x.foo<int>();
2624 }
2625 )",
2626 Lang: Lang_CXX03);
2627 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2628 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
2629 auto *ToD = Import(From: FromD, Lang: Lang_CXX03);
2630 EXPECT_TRUE(ToD);
2631 EXPECT_TRUE(MatchVerifier<FunctionDecl>().match(
2632 ToD, functionDecl(hasName("f"), hasDescendant(declRefExpr()))));
2633}
2634
2635TEST_P(ImportFunctions,
2636 DependentCallExprOfMemberFunctionTemplateWithExplicitTemplateArgs) {
2637 Decl *FromTU = getTuDecl(
2638 SrcCode: R"(
2639 struct X {
2640 template <typename T>
2641 void foo(){}
2642 };
2643 template <typename T>
2644 void f() {
2645 X x;
2646 x.foo<T>();
2647 }
2648 void g() {
2649 f<int>();
2650 }
2651 )",
2652 Lang: Lang_CXX03);
2653 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2654 D: FromTU, AMatcher: functionDecl(hasName(Name: "g")));
2655 auto *ToD = Import(From: FromD, Lang: Lang_CXX03);
2656 EXPECT_TRUE(ToD);
2657 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2658 EXPECT_TRUE(MatchVerifier<TranslationUnitDecl>().match(
2659 ToTU, translationUnitDecl(hasDescendant(
2660 functionDecl(hasName("f"), hasDescendant(declRefExpr()))))));
2661}
2662
2663struct ImportFunctionTemplates : ASTImporterOptionSpecificTestBase {};
2664
2665TEST_P(ImportFunctionTemplates, ImportFunctionTemplateInRecordDeclTwice) {
2666 auto Code =
2667 R"(
2668 class X {
2669 template <class T>
2670 void f(T t);
2671 };
2672 )";
2673 Decl *FromTU1 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input1.cc");
2674 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2675 D: FromTU1, AMatcher: functionTemplateDecl(hasName(Name: "f")));
2676 auto *ToD1 = Import(From: FromD1, Lang: Lang_CXX03);
2677 Decl *FromTU2 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input2.cc");
2678 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2679 D: FromTU2, AMatcher: functionTemplateDecl(hasName(Name: "f")));
2680 auto *ToD2 = Import(From: FromD2, Lang: Lang_CXX03);
2681 EXPECT_EQ(ToD1, ToD2);
2682}
2683
2684TEST_P(ImportFunctionTemplates,
2685 ImportFunctionTemplateWithDefInRecordDeclTwice) {
2686 auto Code =
2687 R"(
2688 class X {
2689 template <class T>
2690 void f(T t);
2691 };
2692 template <class T>
2693 void X::f(T t) {};
2694 )";
2695 Decl *FromTU1 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input1.cc");
2696 auto *FromD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2697 D: FromTU1, AMatcher: functionTemplateDecl(hasName(Name: "f")));
2698 auto *ToD1 = Import(From: FromD1, Lang: Lang_CXX03);
2699 Decl *FromTU2 = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input2.cc");
2700 auto *FromD2 = FirstDeclMatcher<FunctionTemplateDecl>().match(
2701 D: FromTU2, AMatcher: functionTemplateDecl(hasName(Name: "f")));
2702 auto *ToD2 = Import(From: FromD2, Lang: Lang_CXX03);
2703 EXPECT_EQ(ToD1, ToD2);
2704}
2705
2706TEST_P(ImportFunctionTemplates,
2707 ImportFunctionWhenThereIsAFunTemplateWithSameName) {
2708 getToTuDecl(
2709 ToSrcCode: R"(
2710 template <typename T>
2711 void foo(T) {}
2712 void foo();
2713 )",
2714 ToLang: Lang_CXX03);
2715 Decl *FromTU = getTuDecl(SrcCode: "void foo();", Lang: Lang_CXX03);
2716 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
2717 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo")));
2718 auto *ImportedD = Import(From: FromD, Lang: Lang_CXX03);
2719 EXPECT_TRUE(ImportedD);
2720}
2721
2722TEST_P(ImportFunctionTemplates,
2723 ImportConstructorWhenThereIsAFunTemplateWithSameName) {
2724 auto Code =
2725 R"(
2726 struct Foo {
2727 template <typename T>
2728 Foo(T) {}
2729 Foo();
2730 };
2731 )";
2732 getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX03);
2733 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
2734 auto *FromD =
2735 LastDeclMatcher<CXXConstructorDecl>().match(D: FromTU, AMatcher: cxxConstructorDecl());
2736 auto *ImportedD = Import(From: FromD, Lang: Lang_CXX03);
2737 EXPECT_TRUE(ImportedD);
2738}
2739
2740TEST_P(ImportFunctionTemplates,
2741 ImportOperatorWhenThereIsAFunTemplateWithSameName) {
2742 getToTuDecl(
2743 ToSrcCode: R"(
2744 template <typename T>
2745 void operator<(T,T) {}
2746 struct X{};
2747 void operator<(X, X);
2748 )",
2749 ToLang: Lang_CXX03);
2750 Decl *FromTU = getTuDecl(
2751 SrcCode: R"(
2752 struct X{};
2753 void operator<(X, X);
2754 )",
2755 Lang: Lang_CXX03);
2756 auto *FromD = LastDeclMatcher<FunctionDecl>().match(
2757 D: FromTU, AMatcher: functionDecl(hasOverloadedOperatorName(Name: "<")));
2758 auto *ImportedD = Import(From: FromD, Lang: Lang_CXX03);
2759 EXPECT_TRUE(ImportedD);
2760}
2761
2762struct ImportFriendFunctions : ImportFunctions {};
2763
2764TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
2765 auto Pattern = functionDecl(hasName(Name: "f"));
2766
2767 Decl *FromTU = getTuDecl(SrcCode: "struct X { friend void f(); };"
2768 "void f();",
2769 Lang: Lang_CXX03, FileName: "input0.cc");
2770 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2771
2772 auto *ImportedD = cast<FunctionDecl>(Val: Import(From: FromD, Lang: Lang_CXX03));
2773 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2774 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2775 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2776 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2777 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2778 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2779}
2780
2781TEST_P(ImportFriendFunctions,
2782 ImportFriendFunctionRedeclChainProto_OutOfClassProtoFirst) {
2783 auto Pattern = functionDecl(hasName(Name: "f"));
2784
2785 Decl *FromTU = getTuDecl(SrcCode: "void f();"
2786 "struct X { friend void f(); };",
2787 Lang: Lang_CXX03, FileName: "input0.cc");
2788 auto FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2789
2790 auto *ImportedD = cast<FunctionDecl>(Val: Import(From: FromD, Lang: Lang_CXX03));
2791 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2792 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2793 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2794 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2795 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2796 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2797}
2798
2799TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDef) {
2800 auto Pattern = functionDecl(hasName(Name: "f"));
2801
2802 Decl *FromTU = getTuDecl(SrcCode: "struct X { friend void f(){} };"
2803 "void f();",
2804 Lang: Lang_CXX03, FileName: "input0.cc");
2805 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2806
2807 auto *ImportedD = cast<FunctionDecl>(Val: Import(From: FromD, Lang: Lang_CXX03));
2808 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2809 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2810 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2811 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2812 EXPECT_FALSE(ToFD->doesThisDeclarationHaveABody());
2813 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2814}
2815
2816TEST_P(ImportFriendFunctions,
2817 ImportFriendFunctionRedeclChainDef_OutOfClassDef) {
2818 auto Pattern = functionDecl(hasName(Name: "f"));
2819
2820 Decl *FromTU = getTuDecl(SrcCode: "struct X { friend void f(); };"
2821 "void f(){}",
2822 Lang: Lang_CXX03, FileName: "input0.cc");
2823 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2824
2825 auto *ImportedD = cast<FunctionDecl>(Val: Import(From: FromD, Lang: Lang_CXX03));
2826 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2827 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2828 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2829 auto *ToFD = LastDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: Pattern);
2830 EXPECT_TRUE(ToFD->doesThisDeclarationHaveABody());
2831 EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD);
2832}
2833
2834TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainDefWithClass) {
2835 auto Pattern = functionDecl(hasName(Name: "f"));
2836
2837 Decl *FromTU = getTuDecl(
2838 SrcCode: R"(
2839 class X;
2840 void f(X *x){}
2841 class X{
2842 friend void f(X *x);
2843 };
2844 )",
2845 Lang: Lang_CXX03, FileName: "input0.cc");
2846 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2847
2848 auto *ImportedD = cast<FunctionDecl>(Val: Import(From: FromD, Lang: Lang_CXX03));
2849 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2850 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2851 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2852 auto *InClassFD = cast<FunctionDecl>(Val: FirstDeclMatcher<FriendDecl>()
2853 .match(D: ToTU, AMatcher: friendDecl())
2854 ->getFriendDecl());
2855 EXPECT_FALSE(InClassFD->doesThisDeclarationHaveABody());
2856 EXPECT_EQ(InClassFD->getPreviousDecl(), ImportedD);
2857 // The parameters must refer the same type
2858 EXPECT_EQ((*InClassFD->param_begin())->getOriginalType(),
2859 (*ImportedD->param_begin())->getOriginalType());
2860}
2861
2862TEST_P(ImportFriendFunctions,
2863 ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) {
2864 auto Pattern = functionDecl(hasName(Name: "f"));
2865
2866 Decl *FromTU = getTuDecl(
2867 SrcCode: R"(
2868 class X;
2869 void f(X *x){}
2870 class X{
2871 friend void f(X *x);
2872 };
2873 )",
2874 Lang: Lang_CXX03, FileName: "input0.cc");
2875 auto *FromD = LastDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2876
2877 auto *ImportedD = cast<FunctionDecl>(Val: Import(From: FromD, Lang: Lang_CXX03));
2878 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2879 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2880 EXPECT_FALSE(ImportedD->doesThisDeclarationHaveABody());
2881 auto *OutOfClassFD = FirstDeclMatcher<FunctionDecl>().match(
2882 D: ToTU, AMatcher: functionDecl(unless(hasParent(friendDecl()))));
2883
2884 EXPECT_TRUE(OutOfClassFD->doesThisDeclarationHaveABody());
2885 EXPECT_EQ(ImportedD->getPreviousDecl(), OutOfClassFD);
2886 // The parameters must refer the same type
2887 EXPECT_EQ((*OutOfClassFD->param_begin())->getOriginalType(),
2888 (*ImportedD->param_begin())->getOriginalType());
2889}
2890
2891TEST_P(ImportFriendFunctions, ImportFriendFunctionFromMultipleTU) {
2892 auto Pattern = functionDecl(hasName(Name: "f"));
2893
2894 FunctionDecl *ImportedD;
2895 {
2896 Decl *FromTU =
2897 getTuDecl(SrcCode: "struct X { friend void f(){} };", Lang: Lang_CXX03, FileName: "input0.cc");
2898 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2899 ImportedD = cast<FunctionDecl>(Val: Import(From: FromD, Lang: Lang_CXX03));
2900 }
2901 FunctionDecl *ImportedD1;
2902 {
2903 Decl *FromTU = getTuDecl(SrcCode: "void f();", Lang: Lang_CXX03, FileName: "input1.cc");
2904 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: Pattern);
2905 ImportedD1 = cast<FunctionDecl>(Val: Import(From: FromD, Lang: Lang_CXX03));
2906 }
2907
2908 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2909 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
2910 EXPECT_TRUE(ImportedD->doesThisDeclarationHaveABody());
2911 EXPECT_FALSE(ImportedD1->doesThisDeclarationHaveABody());
2912 EXPECT_EQ(ImportedD1->getPreviousDecl(), ImportedD);
2913}
2914
2915TEST_P(ImportFriendFunctions, Lookup) {
2916 auto FunctionPattern = functionDecl(hasName(Name: "f"));
2917 auto ClassPattern = cxxRecordDecl(hasName(Name: "X"));
2918
2919 TranslationUnitDecl *FromTU =
2920 getTuDecl(SrcCode: "struct X { friend void f(); };", Lang: Lang_CXX03, FileName: "input0.cc");
2921 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: FunctionPattern);
2922 ASSERT_TRUE(FromD->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2923 ASSERT_FALSE(FromD->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2924 {
2925 auto FromName = FromD->getDeclName();
2926 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(D: FromTU, AMatcher: ClassPattern);
2927 auto LookupRes = Class->noload_lookup(Name: FromName);
2928 ASSERT_TRUE(LookupRes.empty());
2929 LookupRes = FromTU->noload_lookup(Name: FromName);
2930 ASSERT_TRUE(LookupRes.isSingleResult());
2931 }
2932
2933 auto *ToD = cast<FunctionDecl>(Val: Import(From: FromD, Lang: Lang_CXX03));
2934 auto ToName = ToD->getDeclName();
2935
2936 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2937 auto *Class = FirstDeclMatcher<CXXRecordDecl>().match(D: ToTU, AMatcher: ClassPattern);
2938 auto LookupRes = Class->noload_lookup(Name: ToName);
2939 EXPECT_TRUE(LookupRes.empty());
2940 LookupRes = ToTU->noload_lookup(Name: ToName);
2941 EXPECT_TRUE(LookupRes.isSingleResult());
2942
2943 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 1u);
2944 auto *To0 = FirstDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: FunctionPattern);
2945 EXPECT_TRUE(To0->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2946 EXPECT_FALSE(To0->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2947}
2948
2949TEST_P(ImportFriendFunctions, LookupWithProtoAfter) {
2950 auto FunctionPattern = functionDecl(hasName(Name: "f"));
2951 auto ClassPattern = cxxRecordDecl(hasName(Name: "X"));
2952
2953 TranslationUnitDecl *FromTU =
2954 getTuDecl(SrcCode: "struct X { friend void f(); };"
2955 // This proto decl makes f available to normal
2956 // lookup, otherwise it is hidden.
2957 // Normal C++ lookup (implemented in
2958 // `clang::Sema::CppLookupName()` and in `LookupDirect()`)
2959 // returns the found `NamedDecl` only if the set IDNS is matched
2960 "void f();",
2961 Lang: Lang_CXX03, FileName: "input0.cc");
2962 auto *FromFriend =
2963 FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: FunctionPattern);
2964 auto *FromNormal =
2965 LastDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: FunctionPattern);
2966 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2967 ASSERT_FALSE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2968 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2969 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2970
2971 auto FromName = FromFriend->getDeclName();
2972 auto *FromClass =
2973 FirstDeclMatcher<CXXRecordDecl>().match(D: FromTU, AMatcher: ClassPattern);
2974 auto LookupRes = FromClass->noload_lookup(Name: FromName);
2975 ASSERT_TRUE(LookupRes.empty());
2976 LookupRes = FromTU->noload_lookup(Name: FromName);
2977 ASSERT_TRUE(LookupRes.isSingleResult());
2978
2979 auto *ToFriend = cast<FunctionDecl>(Val: Import(From: FromFriend, Lang: Lang_CXX03));
2980 auto ToName = ToFriend->getDeclName();
2981
2982 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
2983 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(D: ToTU, AMatcher: ClassPattern);
2984 LookupRes = ToClass->noload_lookup(Name: ToName);
2985 EXPECT_TRUE(LookupRes.empty());
2986 LookupRes = ToTU->noload_lookup(Name: ToName);
2987 // Test is disabled because this result is 2.
2988 EXPECT_TRUE(LookupRes.isSingleResult());
2989
2990 ASSERT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
2991 ToFriend = FirstDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: FunctionPattern);
2992 auto *ToNormal = LastDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: FunctionPattern);
2993 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2994 EXPECT_FALSE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2995 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
2996 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
2997}
2998
2999TEST_P(ImportFriendFunctions, LookupWithProtoBefore) {
3000 auto FunctionPattern = functionDecl(hasName(Name: "f"));
3001 auto ClassPattern = cxxRecordDecl(hasName(Name: "X"));
3002
3003 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: "void f();"
3004 "struct X { friend void f(); };",
3005 Lang: Lang_CXX03, FileName: "input0.cc");
3006 auto *FromNormal =
3007 FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: FunctionPattern);
3008 auto *FromFriend =
3009 LastDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: FunctionPattern);
3010 ASSERT_FALSE(FromNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3011 ASSERT_TRUE(FromNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3012 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3013 ASSERT_TRUE(FromFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3014
3015 auto FromName = FromNormal->getDeclName();
3016 auto *FromClass =
3017 FirstDeclMatcher<CXXRecordDecl>().match(D: FromTU, AMatcher: ClassPattern);
3018 auto LookupRes = FromClass->noload_lookup(Name: FromName);
3019 ASSERT_TRUE(LookupRes.empty());
3020 LookupRes = FromTU->noload_lookup(Name: FromName);
3021 ASSERT_TRUE(LookupRes.isSingleResult());
3022
3023 auto *ToNormal = cast<FunctionDecl>(Val: Import(From: FromNormal, Lang: Lang_CXX03));
3024 auto ToName = ToNormal->getDeclName();
3025 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3026
3027 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(D: ToTU, AMatcher: ClassPattern);
3028 LookupRes = ToClass->noload_lookup(Name: ToName);
3029 EXPECT_TRUE(LookupRes.empty());
3030 LookupRes = ToTU->noload_lookup(Name: ToName);
3031 EXPECT_TRUE(LookupRes.isSingleResult());
3032
3033 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, FunctionPattern), 2u);
3034 ToNormal = FirstDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: FunctionPattern);
3035 auto *ToFriend = LastDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: FunctionPattern);
3036 EXPECT_FALSE(ToNormal->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3037 EXPECT_TRUE(ToNormal->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3038 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3039 EXPECT_TRUE(ToFriend->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3040}
3041
3042TEST_P(ImportFriendFunctions, ImportFriendChangesLookup) {
3043 auto Pattern = functionDecl(hasName(Name: "f"));
3044
3045 TranslationUnitDecl *FromNormalTU =
3046 getTuDecl(SrcCode: "void f();", Lang: Lang_CXX03, FileName: "input0.cc");
3047 auto *FromNormalF =
3048 FirstDeclMatcher<FunctionDecl>().match(D: FromNormalTU, AMatcher: Pattern);
3049 TranslationUnitDecl *FromFriendTU =
3050 getTuDecl(SrcCode: "class X { friend void f(); };", Lang: Lang_CXX03, FileName: "input1.cc");
3051 auto *FromFriendF =
3052 FirstDeclMatcher<FunctionDecl>().match(D: FromFriendTU, AMatcher: Pattern);
3053 auto FromNormalName = FromNormalF->getDeclName();
3054 auto FromFriendName = FromFriendF->getDeclName();
3055
3056 ASSERT_TRUE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3057 ASSERT_FALSE(FromNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3058 ASSERT_FALSE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3059 ASSERT_TRUE(FromFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3060 auto LookupRes = FromNormalTU->noload_lookup(Name: FromNormalName);
3061 ASSERT_TRUE(LookupRes.isSingleResult());
3062 LookupRes = FromFriendTU->noload_lookup(Name: FromFriendName);
3063 ASSERT_TRUE(LookupRes.isSingleResult());
3064
3065 auto *ToNormalF = cast<FunctionDecl>(Val: Import(From: FromNormalF, Lang: Lang_CXX03));
3066 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3067 auto ToName = ToNormalF->getDeclName();
3068 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3069 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3070 LookupRes = ToTU->noload_lookup(Name: ToName);
3071 EXPECT_TRUE(LookupRes.isSingleResult());
3072 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 1u);
3073
3074 auto *ToFriendF = cast<FunctionDecl>(Val: Import(From: FromFriendF, Lang: Lang_CXX03));
3075 LookupRes = ToTU->noload_lookup(Name: ToName);
3076 EXPECT_TRUE(LookupRes.isSingleResult());
3077 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, Pattern), 2u);
3078
3079 EXPECT_TRUE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3080 EXPECT_FALSE(ToNormalF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3081
3082 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_Ordinary));
3083 EXPECT_TRUE(ToFriendF->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend));
3084}
3085
3086TEST_P(ImportFriendFunctions, ImportFriendList) {
3087 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: "struct X { friend void f(); };"
3088 "void f();",
3089 Lang: Lang_CXX03, FileName: "input0.cc");
3090 auto *FromFriendF = FirstDeclMatcher<FunctionDecl>().match(
3091 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
3092
3093 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3094 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
3095 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(D: FromTU, AMatcher: friendDecl());
3096 auto FromFriends = FromClass->friends();
3097 unsigned int FrN = 0;
3098 for (auto Fr : FromFriends) {
3099 ASSERT_EQ(Fr, FromFriend);
3100 ++FrN;
3101 }
3102 ASSERT_EQ(FrN, 1u);
3103
3104 Import(From: FromFriendF, Lang: Lang_CXX03);
3105 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3106 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3107 D: ToTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
3108 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(D: ToTU, AMatcher: friendDecl());
3109 auto ToFriends = ToClass->friends();
3110 FrN = 0;
3111 for (auto Fr : ToFriends) {
3112 EXPECT_EQ(Fr, ToFriend);
3113 ++FrN;
3114 }
3115 EXPECT_EQ(FrN, 1u);
3116}
3117
3118AST_MATCHER_P(TagDecl, hasTypedefForAnonDecl, Matcher<TypedefNameDecl>,
3119 InnerMatcher) {
3120 if (auto *Typedef = Node.getTypedefNameForAnonDecl())
3121 return InnerMatcher.matches(Node: *Typedef, Finder, Builder);
3122 return false;
3123}
3124
3125TEST_P(ImportDecl, ImportEnumSequential) {
3126 CodeFiles Samples{{"main.c",
3127 {.CodeSample: "void foo();"
3128 "void moo();"
3129 "int main() { foo(); moo(); }",
3130 .Lang: Lang_C99}},
3131
3132 {"foo.c",
3133 {.CodeSample: "typedef enum { THING_VALUE } thing_t;"
3134 "void conflict(thing_t type);"
3135 "void foo() { (void)THING_VALUE; }"
3136 "void conflict(thing_t type) {}",
3137 .Lang: Lang_C99}},
3138
3139 {"moo.c",
3140 {.CodeSample: "typedef enum { THING_VALUE } thing_t;"
3141 "void conflict(thing_t type);"
3142 "void moo() { conflict(THING_VALUE); }",
3143 .Lang: Lang_C99}}};
3144
3145 auto VerificationMatcher =
3146 enumDecl(has(enumConstantDecl(hasName(Name: "THING_VALUE"))),
3147 hasTypedefForAnonDecl(InnerMatcher: hasName(Name: "thing_t")));
3148
3149 ImportAction ImportFoo{"foo.c", "main.c", functionDecl(hasName(Name: "foo"))},
3150 ImportMoo{"moo.c", "main.c", functionDecl(hasName(Name: "moo"))};
3151
3152 testImportSequence(
3153 CodeSamples: Samples, ImportActions: {ImportFoo, ImportMoo}, // "foo", them "moo".
3154 // Just check that there is only one enum decl in the result AST.
3155 FileForFinalCheck: "main.c", FinalSelectPredicate: enumDecl(), VerificationMatcher);
3156
3157 // For different import order, result should be the same.
3158 testImportSequence(
3159 CodeSamples: Samples, ImportActions: {ImportMoo, ImportFoo}, // "moo", them "foo".
3160 // Check that there is only one enum decl in the result AST.
3161 FileForFinalCheck: "main.c", FinalSelectPredicate: enumDecl(), VerificationMatcher);
3162}
3163
3164TEST_P(ImportDecl, ImportFieldOrder) {
3165 MatchVerifier<Decl> Verifier;
3166 testImport(FromCode: "struct declToImport {"
3167 " int b = a + 2;"
3168 " int a = 5;"
3169 "};",
3170 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
3171 AMatcher: recordDecl(hasFieldOrder(Order: {"b", "a"})));
3172}
3173
3174TEST_P(ImportExpr, DependentScopeDeclRefExpr) {
3175 MatchVerifier<Decl> Verifier;
3176 testImport(FromCode: "template <typename T> struct S { static T foo; };"
3177 "template <typename T> void declToImport() {"
3178 " (void) S<T>::foo;"
3179 "}"
3180 "void instantiate() { declToImport<int>(); }"
3181 "template <typename T> T S<T>::foo;",
3182 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
3183 AMatcher: functionTemplateDecl(has(functionDecl(has(compoundStmt(
3184 has(cStyleCastExpr(has(dependentScopeDeclRefExpr())))))))));
3185
3186 testImport(FromCode: "template <typename T> struct S {"
3187 "template<typename S> static void foo(){};"
3188 "};"
3189 "template <typename T> void declToImport() {"
3190 " S<T>::template foo<T>();"
3191 "}"
3192 "void instantiate() { declToImport<int>(); }",
3193 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
3194 AMatcher: functionTemplateDecl(has(functionDecl(has(compoundStmt(
3195 has(callExpr(has(dependentScopeDeclRefExpr())))))))));
3196}
3197
3198TEST_P(ImportExpr, DependentNameType) {
3199 MatchVerifier<Decl> Verifier;
3200 testImport(FromCode: "template <typename T> struct declToImport {"
3201 " typedef typename T::type dependent_name;"
3202 "};",
3203 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
3204 AMatcher: classTemplateDecl(has(
3205 cxxRecordDecl(has(typedefDecl(has(dependentNameType())))))));
3206}
3207
3208TEST_P(ImportExpr, UnresolvedMemberExpr) {
3209 MatchVerifier<Decl> Verifier;
3210 testImport(FromCode: "struct S { template <typename T> void mem(); };"
3211 "template <typename U> void declToImport() {"
3212 " S s;"
3213 " s.mem<U>();"
3214 "}"
3215 "void instantiate() { declToImport<int>(); }",
3216 FromLang: Lang_CXX11, ToCode: "", ToLang: Lang_CXX11, Verifier,
3217 AMatcher: functionTemplateDecl(has(functionDecl(has(
3218 compoundStmt(has(callExpr(has(unresolvedMemberExpr())))))))));
3219}
3220
3221TEST_P(ImportExpr, ConceptNoRequirement) {
3222 MatchVerifier<Decl> Verifier;
3223 const char *Code = R"(
3224 template<typename T>
3225 struct is_int { static const bool value = false; };
3226 template<> struct is_int<int> { static const bool value = true; };
3227 template<typename T>
3228 concept declToImport = is_int<T>::value;
3229 )";
3230 testImport(FromCode: Code, FromLang: Lang_CXX20, ToCode: "", ToLang: Lang_CXX20, Verifier,
3231 AMatcher: conceptDecl(unless(has(requiresExpr()))));
3232}
3233
3234TEST_P(ImportExpr, ConceptSimpleRequirement) {
3235 MatchVerifier<Decl> Verifier;
3236 const char *Code = R"(
3237 template <class T1, class T2>
3238 concept declToImport = requires(T1 i, T2 j) {
3239 i + j;
3240 };
3241 )";
3242 testImport(FromCode: Code, FromLang: Lang_CXX20, ToCode: "", ToLang: Lang_CXX20, Verifier,
3243 AMatcher: conceptDecl(has(requiresExpr(has(requiresExprBodyDecl())))));
3244}
3245
3246TEST_P(ImportExpr, ConceptCompoundNonTypeRequirement) {
3247 MatchVerifier<Decl> Verifier;
3248 const char *Code = R"(
3249 template <class T1, class T2>
3250 concept declToImport = requires(T1 i, T2 j) {
3251 {i + j};
3252 };
3253 )";
3254 testImport(FromCode: Code, FromLang: Lang_CXX20, ToCode: "", ToLang: Lang_CXX20, Verifier,
3255 AMatcher: conceptDecl(has(requiresExpr(has(requiresExprBodyDecl())))));
3256}
3257
3258TEST_P(ImportExpr, ConceptCompoundTypeRequirement) {
3259 MatchVerifier<Decl> Verifier;
3260 const char *Code = R"(
3261 template<typename T>
3262 struct is_int { static const bool value = false; };
3263 template<> struct is_int<int> { static const bool value = true; };
3264
3265 template<typename T>
3266 concept type_is_int = is_int<T>::value;
3267
3268 template<typename T>
3269 concept declToImport = requires(T x) {
3270 {x * 1} -> type_is_int;
3271 };
3272 )";
3273 testImport(FromCode: Code, FromLang: Lang_CXX20, ToCode: "", ToLang: Lang_CXX20, Verifier,
3274 AMatcher: conceptDecl(has(requiresExpr(has(requiresExprBodyDecl())))));
3275}
3276
3277TEST_P(ImportExpr, ConceptTypeRequirement) {
3278 MatchVerifier<Decl> Verifier;
3279 const char *Code = R"(
3280 template <class T>
3281 concept declToImport = requires {
3282 typename T::value;
3283 };
3284 )";
3285 testImport(FromCode: Code, FromLang: Lang_CXX20, ToCode: "", ToLang: Lang_CXX20, Verifier,
3286 AMatcher: conceptDecl(has(requiresExpr(has(requiresExprBodyDecl())))));
3287}
3288
3289TEST_P(ImportExpr, ConceptNestedRequirement) {
3290 MatchVerifier<Decl> Verifier;
3291 const char *Code = R"(
3292 template<typename T>
3293 struct is_int { static const bool value = false; };
3294 template<> struct is_int<int> { static const bool value = true; };
3295
3296 template<typename T>
3297 concept declToImport = requires(T x) {
3298 requires is_int<T>::value;
3299 };
3300 )";
3301 testImport(FromCode: Code, FromLang: Lang_CXX20, ToCode: "", ToLang: Lang_CXX20, Verifier,
3302 AMatcher: conceptDecl(has(requiresExpr(has(requiresExprBodyDecl())))));
3303}
3304
3305TEST_P(ImportExpr, ConceptNestedNonInstantiationDependentRequirement) {
3306 MatchVerifier<Decl> Verifier;
3307 const char *Code = R"(
3308 template<typename T>
3309 concept declToImport = requires {
3310 requires sizeof(long) == sizeof(int);
3311 };
3312 )";
3313 testImport(FromCode: Code, FromLang: Lang_CXX20, ToCode: "", ToLang: Lang_CXX20, Verifier,
3314 AMatcher: conceptDecl(has(requiresExpr(has(requiresExprBodyDecl())))));
3315}
3316
3317class ImportImplicitMethods : public ASTImporterOptionSpecificTestBase {
3318public:
3319 static constexpr auto DefaultCode = R"(
3320 struct A { int x; };
3321 void f() {
3322 A a;
3323 A a1(a);
3324 A a2(A{});
3325 a = a1;
3326 a = A{};
3327 a.~A();
3328 })";
3329
3330 template <typename MatcherType>
3331 void testImportOf(
3332 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3333 test(MethodMatcher, Code, /*ExpectedCount=*/1u);
3334 }
3335
3336 template <typename MatcherType>
3337 void testNoImportOf(
3338 const MatcherType &MethodMatcher, const char *Code = DefaultCode) {
3339 test(MethodMatcher, Code, /*ExpectedCount=*/0u);
3340 }
3341
3342private:
3343 template <typename MatcherType>
3344 void test(const MatcherType &MethodMatcher,
3345 const char *Code, unsigned int ExpectedCount) {
3346 auto ClassMatcher = cxxRecordDecl(unless(isImplicit()));
3347
3348 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX11);
3349 auto *ToClass = FirstDeclMatcher<CXXRecordDecl>().match(
3350 D: ToTU, AMatcher: ClassMatcher);
3351
3352 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 1u);
3353
3354 {
3355 CXXMethodDecl *Method =
3356 FirstDeclMatcher<CXXMethodDecl>().match(ToClass, MethodMatcher);
3357 ToClass->removeDecl(D: Method);
3358 SharedStatePtr->getLookupTable()->remove(ND: Method);
3359 }
3360
3361 ASSERT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher), 0u);
3362
3363 Decl *ImportedClass = nullptr;
3364 {
3365 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11, FileName: "input1.cc");
3366 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
3367 D: FromTU, AMatcher: ClassMatcher);
3368 ImportedClass = Import(From: FromClass, Lang: Lang_CXX11);
3369 }
3370
3371 EXPECT_EQ(ToClass, ImportedClass);
3372 EXPECT_EQ(DeclCounter<CXXMethodDecl>().match(ToClass, MethodMatcher),
3373 ExpectedCount);
3374 }
3375};
3376
3377TEST_P(ImportImplicitMethods, DefaultConstructor) {
3378 testImportOf(MethodMatcher: cxxConstructorDecl(isDefaultConstructor()));
3379}
3380
3381TEST_P(ImportImplicitMethods, CopyConstructor) {
3382 testImportOf(MethodMatcher: cxxConstructorDecl(isCopyConstructor()));
3383}
3384
3385TEST_P(ImportImplicitMethods, MoveConstructor) {
3386 testImportOf(MethodMatcher: cxxConstructorDecl(isMoveConstructor()));
3387}
3388
3389TEST_P(ImportImplicitMethods, Destructor) {
3390 testImportOf(MethodMatcher: cxxDestructorDecl());
3391}
3392
3393TEST_P(ImportImplicitMethods, CopyAssignment) {
3394 testImportOf(MethodMatcher: cxxMethodDecl(isCopyAssignmentOperator()));
3395}
3396
3397TEST_P(ImportImplicitMethods, MoveAssignment) {
3398 testImportOf(MethodMatcher: cxxMethodDecl(isMoveAssignmentOperator()));
3399}
3400
3401TEST_P(ImportImplicitMethods, DoNotImportUserProvided) {
3402 auto Code = R"(
3403 struct A { A() { int x; } };
3404 )";
3405 testNoImportOf(MethodMatcher: cxxConstructorDecl(isDefaultConstructor()), Code);
3406}
3407
3408TEST_P(ImportImplicitMethods, DoNotImportDefault) {
3409 auto Code = R"(
3410 struct A { A() = default; };
3411 )";
3412 testNoImportOf(MethodMatcher: cxxConstructorDecl(isDefaultConstructor()), Code);
3413}
3414
3415TEST_P(ImportImplicitMethods, DoNotImportDeleted) {
3416 auto Code = R"(
3417 struct A { A() = delete; };
3418 )";
3419 testNoImportOf(MethodMatcher: cxxConstructorDecl(isDefaultConstructor()), Code);
3420}
3421
3422TEST_P(ImportImplicitMethods, DoNotImportOtherMethod) {
3423 auto Code = R"(
3424 struct A { void f() { } };
3425 )";
3426 testNoImportOf(MethodMatcher: cxxMethodDecl(hasName(Name: "f")), Code);
3427}
3428
3429TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentRecord) {
3430 Decl *ToR1;
3431 {
3432 Decl *FromTU = getTuDecl(SrcCode: "struct A { };", Lang: Lang_CXX03, FileName: "input0.cc");
3433 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3434 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
3435
3436 ToR1 = Import(From: FromR, Lang: Lang_CXX03);
3437 }
3438
3439 Decl *ToR2;
3440 {
3441 Decl *FromTU = getTuDecl(SrcCode: "struct A { };", Lang: Lang_CXX03, FileName: "input1.cc");
3442 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3443 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
3444
3445 ToR2 = Import(From: FromR, Lang: Lang_CXX03);
3446 }
3447
3448 EXPECT_EQ(ToR1, ToR2);
3449}
3450
3451TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentRecord) {
3452 Decl *ToR1;
3453 {
3454 Decl *FromTU = getTuDecl(SrcCode: "struct A { int x; };", Lang: Lang_CXX03, FileName: "input0.cc");
3455 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3456 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
3457 ToR1 = Import(From: FromR, Lang: Lang_CXX03);
3458 }
3459 Decl *ToR2;
3460 {
3461 Decl *FromTU =
3462 getTuDecl(SrcCode: "struct A { unsigned x; };", Lang: Lang_CXX03, FileName: "input1.cc");
3463 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
3464 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
3465 ToR2 = Import(From: FromR, Lang: Lang_CXX03);
3466 }
3467 EXPECT_NE(ToR1, ToR2);
3468}
3469
3470TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentField) {
3471 Decl *ToF1;
3472 {
3473 Decl *FromTU = getTuDecl(SrcCode: "struct A { int x; };", Lang: Lang_CXX03, FileName: "input0.cc");
3474 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3475 D: FromTU, AMatcher: fieldDecl(hasName(Name: "x")));
3476 ToF1 = Import(From: FromF, Lang: Lang_CXX03);
3477 }
3478 Decl *ToF2;
3479 {
3480 Decl *FromTU = getTuDecl(SrcCode: "struct A { int x; };", Lang: Lang_CXX03, FileName: "input1.cc");
3481 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3482 D: FromTU, AMatcher: fieldDecl(hasName(Name: "x")));
3483 ToF2 = Import(From: FromF, Lang: Lang_CXX03);
3484 }
3485 EXPECT_EQ(ToF1, ToF2);
3486}
3487
3488TEST_P(ASTImporterOptionSpecificTestBase, ImportBitfields) {
3489 Decl *FromTU = getTuDecl(SrcCode: "struct A { unsigned x : 3; };", Lang: Lang_CXX03);
3490 auto *FromF =
3491 FirstDeclMatcher<FieldDecl>().match(D: FromTU, AMatcher: fieldDecl(hasName(Name: "x")));
3492
3493 ASSERT_TRUE(FromF->isBitField());
3494 ASSERT_EQ(3u, FromF->getBitWidthValue());
3495 auto *ToField = Import(From: FromF, Lang: Lang_CXX03);
3496
3497 EXPECT_TRUE(ToField->isBitField());
3498 EXPECT_EQ(3u, ToField->getBitWidthValue());
3499
3500 const auto *FromBT = FromF->getBitWidth()->getType()->getAs<BuiltinType>();
3501 const auto *ToBT = ToField->getBitWidth()->getType()->getAs<BuiltinType>();
3502 ASSERT_TRUE(FromBT);
3503 ASSERT_EQ(BuiltinType::Int, FromBT->getKind());
3504 EXPECT_TRUE(ToBT);
3505 EXPECT_EQ(BuiltinType::Int, ToBT->getKind());
3506}
3507
3508struct ImportBlock : ASTImporterOptionSpecificTestBase {};
3509TEST_P(ImportBlock, ImportBlocksAreUnsupported) {
3510 const auto *Code = R"(
3511 void test_block__capture_null() {
3512 int *p = 0;
3513 ^(){
3514 *p = 1;
3515 }();
3516 })";
3517 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
3518 auto *FromBlock = FirstDeclMatcher<BlockDecl>().match(D: FromTU, AMatcher: blockDecl());
3519 ASSERT_TRUE(FromBlock);
3520
3521 auto ToBlockOrError = importOrError(From: FromBlock, ToLang: Lang_CXX03);
3522
3523 const auto ExpectUnsupportedConstructError = [](const ASTImportError &Error) {
3524 EXPECT_EQ(ASTImportError::UnsupportedConstruct, Error.Error);
3525 };
3526 llvm::handleAllErrors(E: ToBlockOrError.takeError(),
3527 Handlers: ExpectUnsupportedConstructError);
3528}
3529
3530TEST_P(ASTImporterOptionSpecificTestBase, ImportParmVarDecl) {
3531 const auto *Code = R"(
3532 template <typename T> struct Wrapper {
3533 Wrapper(T Value = {}) {}
3534 };
3535 template class Wrapper<int>;
3536 )";
3537 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
3538 auto *FromVar = FirstDeclMatcher<ParmVarDecl>().match(
3539 D: FromTU, AMatcher: parmVarDecl(hasType(InnerMatcher: asString(Name: "int"))));
3540 ASSERT_TRUE(FromVar);
3541 ASSERT_TRUE(FromVar->hasUninstantiatedDefaultArg());
3542 ASSERT_TRUE(FromVar->getUninstantiatedDefaultArg());
3543 ASSERT_FALSE(FromVar->isExplicitObjectParameter());
3544
3545 const auto *ToVar = Import(From: FromVar, Lang: Lang_CXX11);
3546 EXPECT_TRUE(ToVar);
3547 EXPECT_TRUE(ToVar->hasUninstantiatedDefaultArg());
3548 EXPECT_TRUE(ToVar->getUninstantiatedDefaultArg());
3549 EXPECT_NE(FromVar->getUninstantiatedDefaultArg(),
3550 ToVar->getUninstantiatedDefaultArg());
3551 EXPECT_FALSE(ToVar->isExplicitObjectParameter());
3552}
3553
3554TEST_P(ASTImporterOptionSpecificTestBase, ImportParmVarDecl_Explicit) {
3555 const auto *Code = R"(
3556 struct Wrapper {
3557 void func(this Wrapper) {}
3558 };
3559 )";
3560 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX23);
3561 auto *FromVar = FirstDeclMatcher<ParmVarDecl>().match(D: FromTU, AMatcher: parmVarDecl());
3562 ASSERT_TRUE(FromVar);
3563 ASSERT_TRUE(FromVar->isExplicitObjectParameter());
3564
3565 const auto *ToVar = Import(From: FromVar, Lang: Lang_CXX23);
3566 EXPECT_TRUE(ToVar);
3567 EXPECT_TRUE(ToVar->isExplicitObjectParameter());
3568 EXPECT_NE(ToVar->getExplicitObjectParamThisLoc(),
3569 FromVar->getExplicitObjectParamThisLoc());
3570}
3571
3572TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentField) {
3573 Decl *ToF1;
3574 {
3575 Decl *FromTU = getTuDecl(SrcCode: "struct A { int x; };", Lang: Lang_CXX03, FileName: "input0.cc");
3576 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3577 D: FromTU, AMatcher: fieldDecl(hasName(Name: "x")));
3578 ToF1 = Import(From: FromF, Lang: Lang_CXX03);
3579 }
3580 Decl *ToF2;
3581 {
3582 Decl *FromTU =
3583 getTuDecl(SrcCode: "struct A { unsigned x; };", Lang: Lang_CXX03, FileName: "input1.cc");
3584 auto *FromF = FirstDeclMatcher<FieldDecl>().match(
3585 D: FromTU, AMatcher: fieldDecl(hasName(Name: "x")));
3586 ToF2 = Import(From: FromF, Lang: Lang_CXX03);
3587 }
3588 EXPECT_NE(ToF1, ToF2);
3589}
3590
3591TEST_P(ASTImporterOptionSpecificTestBase, ImportOfEquivalentMethod) {
3592 Decl *ToM1;
3593 {
3594 Decl *FromTU = getTuDecl(SrcCode: "struct A { void x(); }; void A::x() { }",
3595 Lang: Lang_CXX03, FileName: "input0.cc");
3596 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3597 D: FromTU, AMatcher: functionDecl(hasName(Name: "x"), isDefinition()));
3598 ToM1 = Import(From: FromM, Lang: Lang_CXX03);
3599 }
3600 Decl *ToM2;
3601 {
3602 Decl *FromTU = getTuDecl(SrcCode: "struct A { void x(); }; void A::x() { }",
3603 Lang: Lang_CXX03, FileName: "input1.cc");
3604 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3605 D: FromTU, AMatcher: functionDecl(hasName(Name: "x"), isDefinition()));
3606 ToM2 = Import(From: FromM, Lang: Lang_CXX03);
3607 }
3608 EXPECT_EQ(ToM1, ToM2);
3609}
3610
3611TEST_P(ASTImporterOptionSpecificTestBase, ImportOfNonEquivalentMethod) {
3612 Decl *ToM1;
3613 {
3614 Decl *FromTU = getTuDecl(SrcCode: "struct A { void x(); }; void A::x() { }",
3615 Lang: Lang_CXX03, FileName: "input0.cc");
3616 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3617 D: FromTU, AMatcher: functionDecl(hasName(Name: "x"), isDefinition()));
3618 ToM1 = Import(From: FromM, Lang: Lang_CXX03);
3619 }
3620 Decl *ToM2;
3621 {
3622 Decl *FromTU =
3623 getTuDecl(SrcCode: "struct A { void x() const; }; void A::x() const { }",
3624 Lang: Lang_CXX03, FileName: "input1.cc");
3625 auto *FromM = FirstDeclMatcher<FunctionDecl>().match(
3626 D: FromTU, AMatcher: functionDecl(hasName(Name: "x"), isDefinition()));
3627 ToM2 = Import(From: FromM, Lang: Lang_CXX03);
3628 }
3629 EXPECT_NE(ToM1, ToM2);
3630}
3631
3632TEST_P(ASTImporterOptionSpecificTestBase,
3633 ImportUnnamedStructsWithRecursingField) {
3634 Decl *FromTU = getTuDecl(
3635 SrcCode: R"(
3636 struct A {
3637 struct {
3638 struct A *next;
3639 } entry0;
3640 struct {
3641 struct A *next;
3642 } entry1;
3643 };
3644 )",
3645 Lang: Lang_C99, FileName: "input0.cc");
3646 auto *From =
3647 FirstDeclMatcher<RecordDecl>().match(D: FromTU, AMatcher: recordDecl(hasName(Name: "A")));
3648
3649 Import(From, Lang: Lang_C99);
3650
3651 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
3652 auto *Entry0 =
3653 FirstDeclMatcher<FieldDecl>().match(D: ToTU, AMatcher: fieldDecl(hasName(Name: "entry0")));
3654 auto *Entry1 =
3655 FirstDeclMatcher<FieldDecl>().match(D: ToTU, AMatcher: fieldDecl(hasName(Name: "entry1")));
3656 auto *R0 = getRecordDecl(D: Entry0);
3657 auto *R1 = getRecordDecl(D: Entry1);
3658 EXPECT_NE(R0, R1);
3659 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3660 R0, recordDecl(has(fieldDecl(hasName("next"))))));
3661 EXPECT_TRUE(MatchVerifier<RecordDecl>().match(
3662 R1, recordDecl(has(fieldDecl(hasName("next"))))));
3663}
3664
3665TEST_P(ASTImporterOptionSpecificTestBase, ImportUnnamedFieldsInCorrectOrder) {
3666 Decl *FromTU = getTuDecl(
3667 SrcCode: R"(
3668 void f(int X, int Y, bool Z) {
3669 (void)[X, Y, Z] { (void)Z; };
3670 }
3671 )",
3672 Lang: Lang_CXX11, FileName: "input0.cc");
3673 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
3674 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
3675 auto *ToF = cast_or_null<FunctionDecl>(Val: Import(From: FromF, Lang: Lang_CXX11));
3676 EXPECT_TRUE(ToF);
3677
3678 CXXRecordDecl *FromLambda =
3679 cast<LambdaExpr>(Val: cast<CStyleCastExpr>(Val: cast<CompoundStmt>(
3680 Val: FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
3681
3682 auto *ToLambda = cast_or_null<CXXRecordDecl>(Val: Import(From: FromLambda, Lang: Lang_CXX11));
3683 EXPECT_TRUE(ToLambda);
3684
3685 // Check if the fields of the lambda class are imported in correct order.
3686 unsigned FromIndex = 0u;
3687 for (auto *FromField : FromLambda->fields()) {
3688 ASSERT_FALSE(FromField->getDeclName());
3689 auto *ToField = cast_or_null<FieldDecl>(Val: Import(From: FromField, Lang: Lang_CXX11));
3690 EXPECT_TRUE(ToField);
3691 UnsignedOrNone ToIndex = ASTImporter::getFieldIndex(F: ToField);
3692 EXPECT_TRUE(ToIndex);
3693 EXPECT_EQ(*ToIndex, FromIndex);
3694 ++FromIndex;
3695 }
3696
3697 EXPECT_EQ(FromIndex, 3u);
3698}
3699
3700TEST_P(ASTImporterOptionSpecificTestBase,
3701 MergeFieldDeclsOfClassTemplateSpecialization) {
3702 std::string ClassTemplate =
3703 R"(
3704 template <typename T>
3705 struct X {
3706 int a{0}; // FieldDecl with InitListExpr
3707 X(char) : a(3) {} // (1)
3708 X(int) {} // (2)
3709 };
3710 )";
3711 Decl *ToTU = getToTuDecl(ToSrcCode: ClassTemplate +
3712 R"(
3713 void foo() {
3714 // ClassTemplateSpec with ctor (1): FieldDecl without InitlistExpr
3715 X<char> xc('c');
3716 }
3717 )", ToLang: Lang_CXX11);
3718 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3719 D: ToTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
3720 // FieldDecl without InitlistExpr:
3721 auto *ToField = *ToSpec->field_begin();
3722 ASSERT_TRUE(ToField);
3723 ASSERT_FALSE(ToField->getInClassInitializer());
3724 Decl *FromTU = getTuDecl(SrcCode: ClassTemplate +
3725 R"(
3726 void bar() {
3727 // ClassTemplateSpec with ctor (2): FieldDecl WITH InitlistExpr
3728 X<char> xc(1);
3729 }
3730 )", Lang: Lang_CXX11);
3731 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3732 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
3733 // FieldDecl with InitlistExpr:
3734 auto *FromField = *FromSpec->field_begin();
3735 ASSERT_TRUE(FromField);
3736 ASSERT_TRUE(FromField->getInClassInitializer());
3737
3738 auto *ImportedSpec = Import(From: FromSpec, Lang: Lang_CXX11);
3739 ASSERT_TRUE(ImportedSpec);
3740 EXPECT_EQ(ImportedSpec, ToSpec);
3741 // After the import, the FieldDecl has to be merged, thus it should have the
3742 // InitListExpr.
3743 EXPECT_TRUE(ToField->getInClassInitializer());
3744}
3745
3746TEST_P(ASTImporterOptionSpecificTestBase,
3747 MergeFunctionOfClassTemplateSpecialization) {
3748 std::string ClassTemplate =
3749 R"(
3750 template <typename T>
3751 struct X {
3752 void f() {}
3753 void g() {}
3754 };
3755 )";
3756 Decl *ToTU = getToTuDecl(ToSrcCode: ClassTemplate +
3757 R"(
3758 void foo() {
3759 X<char> x;
3760 x.f();
3761 }
3762 )", ToLang: Lang_CXX11);
3763 Decl *FromTU = getTuDecl(SrcCode: ClassTemplate +
3764 R"(
3765 void bar() {
3766 X<char> x;
3767 x.g();
3768 }
3769 )", Lang: Lang_CXX11);
3770 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3771 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
3772 auto FunPattern = functionDecl(hasName(Name: "g"),
3773 hasParent(classTemplateSpecializationDecl()));
3774 auto *FromFun =
3775 FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: FunPattern);
3776 auto *ToFun =
3777 FirstDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: FunPattern);
3778 ASSERT_TRUE(FromFun->hasBody());
3779 ASSERT_FALSE(ToFun->hasBody());
3780 auto *ImportedSpec = Import(From: FromSpec, Lang: Lang_CXX11);
3781 ASSERT_TRUE(ImportedSpec);
3782 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3783 D: ToTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
3784 EXPECT_EQ(ImportedSpec, ToSpec);
3785 EXPECT_TRUE(ToFun->hasBody());
3786}
3787
3788TEST_P(ASTImporterOptionSpecificTestBase, MergeTemplateSpecWithForwardDecl) {
3789 std::string ClassTemplate =
3790 R"(
3791 template<typename T>
3792 struct X { int m; };
3793 template<>
3794 struct X<int> { int m; };
3795 )";
3796 // Append a forward decl for our template specialization.
3797 getToTuDecl(ToSrcCode: ClassTemplate + "template<> struct X<int>;", ToLang: Lang_CXX11);
3798 Decl *FromTU = getTuDecl(SrcCode: ClassTemplate, Lang: Lang_CXX11);
3799 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3800 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X"), isDefinition()));
3801 auto *ImportedSpec = Import(From: FromSpec, Lang: Lang_CXX11);
3802 // Check that our definition got merged with the existing definition.
3803 EXPECT_TRUE(FromSpec->isThisDeclarationADefinition());
3804 EXPECT_TRUE(ImportedSpec->isThisDeclarationADefinition());
3805}
3806
3807TEST_P(ASTImporterOptionSpecificTestBase,
3808 ODRViolationOfClassTemplateSpecializationsShouldBeReported) {
3809 std::string ClassTemplate =
3810 R"(
3811 template <typename T>
3812 struct X {};
3813 )";
3814 Decl *ToTU = getToTuDecl(ToSrcCode: ClassTemplate +
3815 R"(
3816 template <>
3817 struct X<char> {
3818 int a;
3819 };
3820 void foo() {
3821 X<char> x;
3822 }
3823 )",
3824 ToLang: Lang_CXX11);
3825 Decl *FromTU = getTuDecl(SrcCode: ClassTemplate +
3826 R"(
3827 template <>
3828 struct X<char> {
3829 int b;
3830 };
3831 void foo() {
3832 X<char> x;
3833 }
3834 )",
3835 Lang: Lang_CXX11);
3836 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3837 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
3838 auto *ImportedSpec = Import(From: FromSpec, Lang: Lang_CXX11);
3839
3840 // We expect one (ODR) warning during the import.
3841 EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
3842
3843 // The second specialization is different from the first, thus it violates
3844 // ODR, consequently we expect to keep the first specialization only, which is
3845 // already in the "To" context.
3846 EXPECT_FALSE(ImportedSpec);
3847 EXPECT_EQ(1u,
3848 DeclCounter<ClassTemplateSpecializationDecl>().match(
3849 ToTU, classTemplateSpecializationDecl(hasName("X"))));
3850}
3851
3852TEST_P(ASTImporterOptionSpecificTestBase,
3853 MergeCtorOfClassTemplateSpecialization) {
3854 std::string ClassTemplate =
3855 R"(
3856 template <typename T>
3857 struct X {
3858 X(char) {}
3859 X(int) {}
3860 };
3861 )";
3862 Decl *ToTU = getToTuDecl(ToSrcCode: ClassTemplate +
3863 R"(
3864 void foo() {
3865 X<char> x('c');
3866 }
3867 )", ToLang: Lang_CXX11);
3868 Decl *FromTU = getTuDecl(SrcCode: ClassTemplate +
3869 R"(
3870 void bar() {
3871 X<char> x(1);
3872 }
3873 )", Lang: Lang_CXX11);
3874 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3875 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
3876 // Match the void(int) ctor.
3877 auto CtorPattern =
3878 cxxConstructorDecl(hasParameter(N: 0, InnerMatcher: varDecl(hasType(InnerMatcher: asString(Name: "int")))),
3879 hasParent(classTemplateSpecializationDecl()));
3880 auto *FromCtor =
3881 FirstDeclMatcher<CXXConstructorDecl>().match(D: FromTU, AMatcher: CtorPattern);
3882 auto *ToCtor =
3883 FirstDeclMatcher<CXXConstructorDecl>().match(D: ToTU, AMatcher: CtorPattern);
3884 ASSERT_TRUE(FromCtor->hasBody());
3885 ASSERT_FALSE(ToCtor->hasBody());
3886 auto *ImportedSpec = Import(From: FromSpec, Lang: Lang_CXX11);
3887 ASSERT_TRUE(ImportedSpec);
3888 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3889 D: ToTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
3890 EXPECT_EQ(ImportedSpec, ToSpec);
3891 EXPECT_TRUE(ToCtor->hasBody());
3892}
3893
3894TEST_P(ASTImporterOptionSpecificTestBase, ClassTemplateFriendDecl) {
3895 const auto *Code =
3896 R"(
3897 template <class T> class X { friend T; };
3898 struct Y {};
3899 template class X<Y>;
3900 )";
3901 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX11);
3902 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
3903 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3904 D: FromTU, AMatcher: classTemplateSpecializationDecl());
3905 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3906 D: ToTU, AMatcher: classTemplateSpecializationDecl());
3907
3908 auto *ImportedSpec = Import(From: FromSpec, Lang: Lang_CXX11);
3909 EXPECT_EQ(ImportedSpec, ToSpec);
3910 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3911 ToTU, classTemplateSpecializationDecl()));
3912}
3913
3914TEST_P(ASTImporterOptionSpecificTestBase,
3915 ClassTemplatePartialSpecializationsShouldNotBeDuplicated) {
3916 auto Code =
3917 R"(
3918 // primary template
3919 template<class T1, class T2, int I>
3920 class A {};
3921
3922 // partial specialization
3923 template<class T, int I>
3924 class A<T, T*, I> {};
3925 )";
3926 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX11);
3927 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
3928 auto *FromSpec =
3929 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3930 D: FromTU, AMatcher: classTemplatePartialSpecializationDecl());
3931 auto *ToSpec =
3932 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
3933 D: ToTU, AMatcher: classTemplatePartialSpecializationDecl());
3934
3935 auto *ImportedSpec = Import(From: FromSpec, Lang: Lang_CXX11);
3936 EXPECT_EQ(ImportedSpec, ToSpec);
3937 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3938 ToTU, classTemplatePartialSpecializationDecl()));
3939}
3940
3941TEST_P(ASTImporterOptionSpecificTestBase,
3942 ClassTemplateSpecializationsShouldNotBeDuplicated) {
3943 auto Code =
3944 R"(
3945 // primary template
3946 template<class T1, class T2, int I>
3947 class A {};
3948
3949 // full specialization
3950 template<>
3951 class A<int, int, 1> {};
3952 )";
3953 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX11);
3954 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
3955 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3956 D: FromTU, AMatcher: classTemplateSpecializationDecl());
3957 auto *ToSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3958 D: ToTU, AMatcher: classTemplateSpecializationDecl());
3959
3960 auto *ImportedSpec = Import(From: FromSpec, Lang: Lang_CXX11);
3961 EXPECT_EQ(ImportedSpec, ToSpec);
3962 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3963 ToTU, classTemplateSpecializationDecl()));
3964}
3965
3966TEST_P(ASTImporterOptionSpecificTestBase,
3967 ClassTemplateFullAndPartialSpecsShouldNotBeMixed) {
3968 std::string PrimaryTemplate =
3969 R"(
3970 template<class T1, class T2, int I>
3971 class A {};
3972 )";
3973 auto PartialSpec =
3974 R"(
3975 template<class T, int I>
3976 class A<T, T*, I> {};
3977 )";
3978 auto FullSpec =
3979 R"(
3980 template<>
3981 class A<int, int, 1> {};
3982 )";
3983 Decl *ToTU = getToTuDecl(ToSrcCode: PrimaryTemplate + FullSpec, ToLang: Lang_CXX11);
3984 Decl *FromTU = getTuDecl(SrcCode: PrimaryTemplate + PartialSpec, Lang: Lang_CXX11);
3985 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
3986 D: FromTU, AMatcher: classTemplateSpecializationDecl());
3987
3988 auto *ImportedSpec = Import(From: FromSpec, Lang: Lang_CXX11);
3989 EXPECT_TRUE(ImportedSpec);
3990 // Check the number of partial specializations.
3991 EXPECT_EQ(1u, DeclCounter<ClassTemplatePartialSpecializationDecl>().match(
3992 ToTU, classTemplatePartialSpecializationDecl()));
3993 // Check the number of full specializations.
3994 EXPECT_EQ(1u, DeclCounter<ClassTemplateSpecializationDecl>().match(
3995 ToTU, classTemplateSpecializationDecl(
3996 unless(classTemplatePartialSpecializationDecl()))));
3997}
3998
3999TEST_P(ASTImporterOptionSpecificTestBase,
4000 InitListExprValueKindShouldBeImported) {
4001 Decl *TU = getTuDecl(
4002 SrcCode: R"(
4003 const int &init();
4004 void foo() { const int &a{init()}; }
4005 )", Lang: Lang_CXX11, FileName: "input0.cc");
4006 auto *FromD = FirstDeclMatcher<VarDecl>().match(D: TU, AMatcher: varDecl(hasName(Name: "a")));
4007 ASSERT_TRUE(FromD->getAnyInitializer());
4008 auto *InitExpr = FromD->getAnyInitializer();
4009 ASSERT_TRUE(InitExpr);
4010 ASSERT_TRUE(InitExpr->isGLValue());
4011
4012 auto *ToD = Import(From: FromD, Lang: Lang_CXX11);
4013 EXPECT_TRUE(ToD);
4014 auto *ToInitExpr = cast<VarDecl>(Val: ToD)->getAnyInitializer();
4015 EXPECT_TRUE(ToInitExpr);
4016 EXPECT_TRUE(ToInitExpr->isGLValue());
4017}
4018
4019struct ImportVariables : ASTImporterOptionSpecificTestBase {};
4020
4021TEST_P(ImportVariables, ImportOfOneDeclBringsInTheWholeChain) {
4022 Decl *FromTU = getTuDecl(
4023 SrcCode: R"(
4024 struct A {
4025 static const int a = 1 + 2;
4026 };
4027 const int A::a;
4028 )",
4029 Lang: Lang_CXX03, FileName: "input1.cc");
4030
4031 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
4032 D: FromTU, AMatcher: varDecl(hasName(Name: "a"))); // Decl with init
4033 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
4034 D: FromTU, AMatcher: varDecl(hasName(Name: "a"))); // Decl with definition
4035 ASSERT_NE(FromDWithInit, FromDWithDef);
4036 ASSERT_EQ(FromDWithDef->getPreviousDecl(), FromDWithInit);
4037
4038 auto *ToD0 = cast<VarDecl>(Val: Import(From: FromDWithInit, Lang: Lang_CXX11));
4039 auto *ToD1 = cast<VarDecl>(Val: Import(From: FromDWithDef, Lang: Lang_CXX11));
4040 ASSERT_TRUE(ToD0);
4041 ASSERT_TRUE(ToD1);
4042 EXPECT_NE(ToD0, ToD1);
4043 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
4044}
4045
4046TEST_P(ImportVariables, InitAndDefinitionAreInDifferentTUs) {
4047 auto StructA =
4048 R"(
4049 struct A {
4050 static const int a = 1 + 2;
4051 };
4052 )";
4053 Decl *ToTU = getToTuDecl(ToSrcCode: StructA, ToLang: Lang_CXX03);
4054 Decl *FromTU = getTuDecl(SrcCode: std::string(StructA) + "const int A::a;", Lang: Lang_CXX03,
4055 FileName: "input1.cc");
4056
4057 auto *FromDWithInit = FirstDeclMatcher<VarDecl>().match(
4058 D: FromTU, AMatcher: varDecl(hasName(Name: "a"))); // Decl with init
4059 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
4060 D: FromTU, AMatcher: varDecl(hasName(Name: "a"))); // Decl with definition
4061 ASSERT_EQ(FromDWithInit, FromDWithDef->getPreviousDecl());
4062 ASSERT_TRUE(FromDWithInit->getInit());
4063 ASSERT_FALSE(FromDWithInit->isThisDeclarationADefinition());
4064 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
4065 ASSERT_FALSE(FromDWithDef->getInit());
4066
4067 auto *ToD = FirstDeclMatcher<VarDecl>().match(
4068 D: ToTU, AMatcher: varDecl(hasName(Name: "a"))); // Decl with init
4069 ASSERT_TRUE(ToD->getInit());
4070 ASSERT_FALSE(ToD->getDefinition());
4071
4072 auto *ImportedD = cast<VarDecl>(Val: Import(From: FromDWithDef, Lang: Lang_CXX11));
4073 EXPECT_TRUE(ImportedD->getAnyInitializer());
4074 EXPECT_TRUE(ImportedD->getDefinition());
4075}
4076
4077TEST_P(ImportVariables, InitAndDefinitionAreInTheFromContext) {
4078 auto StructA =
4079 R"(
4080 struct A {
4081 static const int a;
4082 };
4083 )";
4084 Decl *ToTU = getToTuDecl(ToSrcCode: StructA, ToLang: Lang_CXX03);
4085 Decl *FromTU = getTuDecl(SrcCode: std::string(StructA) + "const int A::a = 1 + 2;",
4086 Lang: Lang_CXX03, FileName: "input1.cc");
4087
4088 auto *FromDDeclarationOnly = FirstDeclMatcher<VarDecl>().match(
4089 D: FromTU, AMatcher: varDecl(hasName(Name: "a")));
4090 auto *FromDWithDef = LastDeclMatcher<VarDecl>().match(
4091 D: FromTU, AMatcher: varDecl(hasName(Name: "a"))); // Decl with definition and with init.
4092 ASSERT_EQ(FromDDeclarationOnly, FromDWithDef->getPreviousDecl());
4093 ASSERT_FALSE(FromDDeclarationOnly->getInit());
4094 ASSERT_FALSE(FromDDeclarationOnly->isThisDeclarationADefinition());
4095 ASSERT_TRUE(FromDWithDef->isThisDeclarationADefinition());
4096 ASSERT_TRUE(FromDWithDef->getInit());
4097
4098 auto *ToD = FirstDeclMatcher<VarDecl>().match(
4099 D: ToTU, AMatcher: varDecl(hasName(Name: "a")));
4100 ASSERT_FALSE(ToD->getInit());
4101 ASSERT_FALSE(ToD->getDefinition());
4102
4103 auto *ImportedD = cast<VarDecl>(Val: Import(From: FromDWithDef, Lang: Lang_CXX11));
4104 EXPECT_TRUE(ImportedD->getAnyInitializer());
4105 EXPECT_TRUE(ImportedD->getDefinition());
4106}
4107
4108TEST_P(ImportVariables, ImportBindingDecl) {
4109 Decl *From, *To;
4110 std::tie(args&: From, args&: To) = getImportedDecl(
4111 FromSrcCode: R"(
4112 void declToImport() {
4113 int a[2] = {1,2};
4114 auto [x1,y1] = a;
4115 auto& [x2,y2] = a;
4116
4117 struct S {
4118 mutable int x1 : 2;
4119 volatile double y1;
4120 };
4121 S b;
4122 const auto [x3, y3] = b;
4123 };
4124 )",
4125 FromLang: Lang_CXX17, ToSrcCode: "", ToLang: Lang_CXX17);
4126
4127 TranslationUnitDecl *FromTU = From->getTranslationUnitDecl();
4128 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
4129 D: FromTU, AMatcher: functionDecl(hasName(Name: "declToImport")));
4130 auto *ToF = Import(From: FromF, Lang: Lang_CXX17);
4131 EXPECT_TRUE(ToF);
4132
4133 auto VerifyImport = [&](llvm::StringRef BindName) {
4134 auto *FromB = FirstDeclMatcher<BindingDecl>().match(
4135 D: FromF, AMatcher: bindingDecl(hasName(Name: BindName)));
4136 ASSERT_TRUE(FromB);
4137 auto *ToB = Import(From: FromB, Lang: Lang_CXX17);
4138 EXPECT_TRUE(ToB);
4139 EXPECT_EQ(FromB->getBinding() != nullptr, ToB->getBinding() != nullptr);
4140 EXPECT_EQ(FromB->getDecomposedDecl() != nullptr,
4141 ToB->getDecomposedDecl() != nullptr);
4142 EXPECT_EQ(FromB->getHoldingVar() != nullptr,
4143 ToB->getHoldingVar() != nullptr);
4144 };
4145
4146 VerifyImport("x1");
4147 VerifyImport("y1");
4148 VerifyImport("x2");
4149 VerifyImport("y2");
4150 VerifyImport("x3");
4151 VerifyImport("y3");
4152}
4153
4154TEST_P(ImportVariables, ImportDecompositionDeclArray) {
4155 Decl *From, *To;
4156 std::tie(args&: From, args&: To) = getImportedDecl(
4157 FromSrcCode: R"(
4158 void declToImport() {
4159 int a[2] = {1,2};
4160 auto [x1,y1] = a;
4161 };
4162 )",
4163 FromLang: Lang_CXX17, ToSrcCode: "", ToLang: Lang_CXX17);
4164
4165 TranslationUnitDecl *FromTU = From->getTranslationUnitDecl();
4166 auto *FromDecomp =
4167 FirstDeclMatcher<DecompositionDecl>().match(D: FromTU, AMatcher: decompositionDecl());
4168 auto *ToDecomp = Import(From: FromDecomp, Lang: Lang_CXX17);
4169 EXPECT_TRUE(ToDecomp);
4170
4171 ArrayRef<BindingDecl *> FromB = FromDecomp->bindings();
4172 ArrayRef<BindingDecl *> ToB = ToDecomp->bindings();
4173 EXPECT_EQ(FromB.size(), ToB.size());
4174 for (unsigned int I = 0; I < FromB.size(); ++I) {
4175 auto *ToBI = Import(From: FromB[I], Lang: Lang_CXX17);
4176 EXPECT_EQ(ToBI, ToB[I]);
4177 }
4178}
4179
4180struct ImportClasses : ASTImporterOptionSpecificTestBase {};
4181
4182TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContext) {
4183 Decl *ToTU = getToTuDecl(ToSrcCode: "struct A { struct X *Xp; };", ToLang: Lang_C99);
4184 Decl *FromTU1 = getTuDecl(SrcCode: "struct X {};", Lang: Lang_C99, FileName: "input1.cc");
4185 auto Pattern = recordDecl(hasName(Name: "X"), unless(isImplicit()));
4186 auto ToProto = FirstDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: Pattern);
4187 auto FromDef = FirstDeclMatcher<RecordDecl>().match(D: FromTU1, AMatcher: Pattern);
4188
4189 Decl *ImportedDef = Import(From: FromDef, Lang: Lang_C99);
4190
4191 EXPECT_NE(ImportedDef, ToProto);
4192 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
4193 auto ToDef = LastDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: Pattern);
4194 EXPECT_TRUE(ImportedDef == ToDef);
4195 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4196 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4197 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
4198}
4199
4200TEST_P(ImportClasses, ImportDefinitionWhenProtoIsInNestedToContextCXX) {
4201 Decl *ToTU = getToTuDecl(ToSrcCode: "struct A { struct X *Xp; };", ToLang: Lang_CXX03);
4202 Decl *FromTU1 = getTuDecl(SrcCode: "struct X {};", Lang: Lang_CXX03, FileName: "input1.cc");
4203 auto Pattern = recordDecl(hasName(Name: "X"), unless(isImplicit()));
4204 auto ToProto = FirstDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: Pattern);
4205 auto FromDef = FirstDeclMatcher<RecordDecl>().match(D: FromTU1, AMatcher: Pattern);
4206
4207 Decl *ImportedDef = Import(From: FromDef, Lang: Lang_CXX03);
4208
4209 EXPECT_NE(ImportedDef, ToProto);
4210 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
4211 auto ToDef = LastDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: Pattern);
4212 EXPECT_TRUE(ImportedDef == ToDef);
4213 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4214 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4215 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
4216}
4217
4218TEST_P(ImportClasses, ImportNestedPrototypeThenDefinition) {
4219 Decl *FromTU0 =
4220 getTuDecl(SrcCode: "struct A { struct X *Xp; };", Lang: Lang_C99, FileName: "input0.cc");
4221 Decl *FromTU1 = getTuDecl(SrcCode: "struct X {};", Lang: Lang_C99, FileName: "input1.cc");
4222 auto Pattern = recordDecl(hasName(Name: "X"), unless(isImplicit()));
4223 auto FromProto = FirstDeclMatcher<RecordDecl>().match(D: FromTU0, AMatcher: Pattern);
4224 auto FromDef = FirstDeclMatcher<RecordDecl>().match(D: FromTU1, AMatcher: Pattern);
4225
4226 Decl *ImportedProto = Import(From: FromProto, Lang: Lang_C99);
4227 Decl *ImportedDef = Import(From: FromDef, Lang: Lang_C99);
4228 Decl *ToTU = ImportedDef->getTranslationUnitDecl();
4229
4230 EXPECT_NE(ImportedDef, ImportedProto);
4231 EXPECT_EQ(DeclCounter<RecordDecl>().match(ToTU, Pattern), 2u);
4232 auto ToProto = FirstDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: Pattern);
4233 auto ToDef = LastDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: Pattern);
4234 EXPECT_TRUE(ImportedDef == ToDef);
4235 EXPECT_TRUE(ImportedProto == ToProto);
4236 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
4237 EXPECT_FALSE(ToProto->isThisDeclarationADefinition());
4238 EXPECT_EQ(ToDef->getPreviousDecl(), ToProto);
4239}
4240
4241struct ImportFriendClasses : ASTImporterOptionSpecificTestBase {
4242 void testRecursiveFriendClassTemplate(Decl *FromTu) {
4243 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
4244 D: FromTu, AMatcher: classTemplateDecl());
4245
4246 auto Pattern = classTemplateDecl(
4247 has(cxxRecordDecl(has(friendDecl(has(classTemplateDecl()))))));
4248 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4249
4250 auto *FromFriend =
4251 FirstDeclMatcher<FriendDecl>().match(D: FromD, AMatcher: friendDecl());
4252 auto *FromRecordOfFriend =
4253 cast<ClassTemplateDecl>(Val: FromFriend->getFriendDecl())
4254 ->getTemplatedDecl();
4255 EXPECT_NE(FromRecordOfFriend, FromD->getTemplatedDecl());
4256 EXPECT_TRUE(FromRecordOfFriend->getPreviousDecl() == nullptr);
4257
4258 auto *FromDC = FromRecordOfFriend->getDeclContext();
4259 auto *FromLexicalDC = FromRecordOfFriend->getLexicalDeclContext();
4260 ASSERT_EQ(FromDC, cast<DeclContext>(FromTu));
4261 ASSERT_EQ(FromLexicalDC, cast<DeclContext>(FromD->getTemplatedDecl()));
4262
4263 ASSERT_FALSE(FromDC->containsDecl(FromRecordOfFriend));
4264 ASSERT_FALSE(FromLexicalDC->containsDecl(FromRecordOfFriend));
4265 ASSERT_FALSE(cast<RecordDecl>(FromRecordOfFriend)
4266 ->getLookupParent()
4267 ->lookup(FromRecordOfFriend->getDeclName())
4268 .empty());
4269
4270 auto *ToD = Import(From: FromD, Lang: Lang_CXX03);
4271 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4272
4273 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(D: ToD, AMatcher: friendDecl());
4274 auto *ToRecordOfFriend =
4275 cast<ClassTemplateDecl>(Val: ToFriend->getFriendDecl())->getTemplatedDecl();
4276
4277 EXPECT_NE(ToRecordOfFriend, ToD->getTemplatedDecl());
4278 EXPECT_TRUE(ToRecordOfFriend->getPreviousDecl() == nullptr);
4279
4280 auto *ToDC = ToRecordOfFriend->getDeclContext();
4281 auto *ToLexicalDC = ToRecordOfFriend->getLexicalDeclContext();
4282 ASSERT_EQ(ToDC, cast<DeclContext>(ToD->getTranslationUnitDecl()));
4283 ASSERT_EQ(ToLexicalDC, cast<DeclContext>(ToD->getTemplatedDecl()));
4284
4285 ASSERT_FALSE(ToDC->containsDecl(ToRecordOfFriend));
4286 ASSERT_FALSE(ToLexicalDC->containsDecl(ToRecordOfFriend));
4287 ASSERT_FALSE(cast<RecordDecl>(ToRecordOfFriend)
4288 ->getLookupParent()
4289 ->lookup(ToRecordOfFriend->getDeclName())
4290 .empty());
4291 }
4292
4293 void testRepeatedFriendImport(const char *Code) {
4294 Decl *ToTu = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX03);
4295 Decl *FromTu = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "from.cc");
4296
4297 auto *ToFriend1 = FirstDeclMatcher<FriendDecl>().match(D: ToTu, AMatcher: friendDecl());
4298 auto *ToFriend2 = LastDeclMatcher<FriendDecl>().match(D: ToTu, AMatcher: friendDecl());
4299 auto *FromFriend1 =
4300 FirstDeclMatcher<FriendDecl>().match(D: FromTu, AMatcher: friendDecl());
4301 auto *FromFriend2 =
4302 LastDeclMatcher<FriendDecl>().match(D: FromTu, AMatcher: friendDecl());
4303
4304 FriendDecl *ToImportedFriend1 = Import(From: FromFriend1, Lang: Lang_CXX03);
4305 FriendDecl *ToImportedFriend2 = Import(From: FromFriend2, Lang: Lang_CXX03);
4306
4307 EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
4308 EXPECT_EQ(ToFriend1, ToImportedFriend1);
4309 EXPECT_EQ(ToFriend2, ToImportedFriend2);
4310 }
4311};
4312
4313TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
4314 Decl *FromTU = getTuDecl(
4315 SrcCode: R"(
4316 class A {
4317 template <int I> class F {};
4318 class X {
4319 template <int I> friend class F;
4320 };
4321 };
4322 )",
4323 Lang: Lang_CXX03, FileName: "input0.cc");
4324
4325 auto *FromClass = FirstDeclMatcher<CXXRecordDecl>().match(
4326 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "F"), isDefinition()));
4327 auto *FromFriendClass = LastDeclMatcher<CXXRecordDecl>().match(
4328 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "F")));
4329
4330 ASSERT_TRUE(FromClass);
4331 ASSERT_TRUE(FromFriendClass);
4332 ASSERT_NE(FromClass, FromFriendClass);
4333 ASSERT_EQ(FromFriendClass->getDefinition(), FromClass);
4334 ASSERT_EQ(FromFriendClass->getPreviousDecl(), FromClass);
4335 ASSERT_EQ(FromFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4336 FromClass->getDescribedClassTemplate());
4337
4338 auto *ToClass = cast<CXXRecordDecl>(Val: Import(From: FromClass, Lang: Lang_CXX03));
4339 auto *ToFriendClass =
4340 cast<CXXRecordDecl>(Val: Import(From: FromFriendClass, Lang: Lang_CXX03));
4341
4342 EXPECT_TRUE(ToClass);
4343 EXPECT_TRUE(ToFriendClass);
4344 EXPECT_NE(ToClass, ToFriendClass);
4345 EXPECT_EQ(ToFriendClass->getDefinition(), ToClass);
4346 EXPECT_EQ(ToFriendClass->getPreviousDecl(), ToClass);
4347 EXPECT_EQ(ToFriendClass->getDescribedClassTemplate()->getPreviousDecl(),
4348 ToClass->getDescribedClassTemplate());
4349}
4350
4351TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClass) {
4352 Decl *FromTu = getTuDecl(
4353 SrcCode: R"(
4354 class declToImport {
4355 friend class declToImport;
4356 };
4357 )",
4358 Lang: Lang_CXX03, FileName: "input.cc");
4359
4360 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
4361 D: FromTu, AMatcher: cxxRecordDecl(hasName(Name: "declToImport")));
4362 auto *ToD = Import(From: FromD, Lang: Lang_CXX03);
4363 auto Pattern = cxxRecordDecl(has(friendDecl()));
4364 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromD, Pattern));
4365 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToD, Pattern));
4366}
4367
4368TEST_P(ImportFriendClasses, UndeclaredFriendClassShouldNotBeVisible) {
4369 Decl *FromTu =
4370 getTuDecl(SrcCode: "class X { friend class Y; };", Lang: Lang_CXX03, FileName: "from.cc");
4371 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
4372 D: FromTu, AMatcher: cxxRecordDecl(hasName(Name: "X")));
4373 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(D: FromTu, AMatcher: friendDecl());
4374 RecordDecl *FromRecordOfFriend =
4375 const_cast<RecordDecl *>(getRecordDeclOfFriend(FD: FromFriend));
4376
4377 ASSERT_EQ(FromRecordOfFriend->getDeclContext(), cast<DeclContext>(FromTu));
4378 ASSERT_EQ(FromRecordOfFriend->getLexicalDeclContext(),
4379 cast<DeclContext>(FromX));
4380 ASSERT_FALSE(
4381 FromRecordOfFriend->getDeclContext()->containsDecl(FromRecordOfFriend));
4382 ASSERT_FALSE(FromRecordOfFriend->getLexicalDeclContext()->containsDecl(
4383 FromRecordOfFriend));
4384 ASSERT_FALSE(FromRecordOfFriend->getLookupParent()
4385 ->lookup(FromRecordOfFriend->getDeclName())
4386 .empty());
4387
4388 auto *ToX = Import(From: FromX, Lang: Lang_CXX03);
4389 ASSERT_TRUE(ToX);
4390
4391 Decl *ToTu = ToX->getTranslationUnitDecl();
4392 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(D: ToTu, AMatcher: friendDecl());
4393 RecordDecl *ToRecordOfFriend =
4394 const_cast<RecordDecl *>(getRecordDeclOfFriend(FD: ToFriend));
4395
4396 ASSERT_EQ(ToRecordOfFriend->getDeclContext(), cast<DeclContext>(ToTu));
4397 ASSERT_EQ(ToRecordOfFriend->getLexicalDeclContext(), cast<DeclContext>(ToX));
4398 EXPECT_FALSE(
4399 ToRecordOfFriend->getDeclContext()->containsDecl(ToRecordOfFriend));
4400 EXPECT_FALSE(ToRecordOfFriend->getLexicalDeclContext()->containsDecl(
4401 ToRecordOfFriend));
4402 EXPECT_FALSE(ToRecordOfFriend->getLookupParent()
4403 ->lookup(ToRecordOfFriend->getDeclName())
4404 .empty());
4405}
4406
4407TEST_P(ImportFriendClasses, ImportOfRecursiveFriendClassTemplate) {
4408 Decl *FromTu = getTuDecl(
4409 SrcCode: R"(
4410 template<class A> class declToImport {
4411 template<class A1> friend class declToImport;
4412 };
4413 )",
4414 Lang: Lang_CXX03, FileName: "input.cc");
4415
4416 testRecursiveFriendClassTemplate(FromTu);
4417}
4418
4419TEST_P(ImportFriendClasses,
4420 ImportOfRecursiveFriendClassTemplateWithNonTypeParm) {
4421 Decl *FromTu = getTuDecl(
4422 SrcCode: R"(
4423 template<class A1, A1 A> class declToImport {
4424 template<class B1, B1> friend class declToImport;
4425 };
4426 )",
4427 Lang: Lang_CXX03, FileName: "input.cc");
4428 testRecursiveFriendClassTemplate(FromTu);
4429}
4430
4431TEST_P(ImportFriendClasses, ProperPrevDeclForClassTemplateDecls) {
4432 auto Pattern = classTemplateSpecializationDecl(hasName(Name: "X"));
4433
4434 ClassTemplateSpecializationDecl *Imported1;
4435 {
4436 Decl *FromTU = getTuDecl(SrcCode: "template<class T> class X;"
4437 "struct Y { friend class X<int>; };",
4438 Lang: Lang_CXX03, FileName: "input0.cc");
4439 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4440 D: FromTU, AMatcher: Pattern);
4441
4442 Imported1 =
4443 cast<ClassTemplateSpecializationDecl>(Val: Import(From: FromD, Lang: Lang_CXX03));
4444 }
4445 ClassTemplateSpecializationDecl *Imported2;
4446 {
4447 Decl *FromTU = getTuDecl(SrcCode: "template<class T> class X;"
4448 "template<> class X<int>{};"
4449 "struct Z { friend class X<int>; };",
4450 Lang: Lang_CXX03, FileName: "input1.cc");
4451 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4452 D: FromTU, AMatcher: Pattern);
4453
4454 Imported2 =
4455 cast<ClassTemplateSpecializationDecl>(Val: Import(From: FromD, Lang: Lang_CXX03));
4456 }
4457
4458 Decl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4459 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(ToTU, Pattern),
4460 2u);
4461 ASSERT_TRUE(Imported2->getPreviousDecl());
4462 EXPECT_EQ(Imported2->getPreviousDecl(), Imported1);
4463}
4464
4465TEST_P(ImportFriendClasses, TypeForDeclShouldBeSetInTemplated) {
4466 Decl *FromTU0 = getTuDecl(
4467 SrcCode: R"(
4468 class X {
4469 class Y;
4470 };
4471 class X::Y {
4472 template <typename T>
4473 friend class F; // The decl context of F is the global namespace.
4474 };
4475 )",
4476 Lang: Lang_CXX03, FileName: "input0.cc");
4477 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4478 D: FromTU0, AMatcher: classTemplateDecl(hasName(Name: "F")));
4479 auto *Imported0 = cast<ClassTemplateDecl>(Val: Import(From: Fwd, Lang: Lang_CXX03));
4480 Decl *FromTU1 = getTuDecl(
4481 SrcCode: R"(
4482 template <typename T>
4483 class F {};
4484 )",
4485 Lang: Lang_CXX03, FileName: "input1.cc");
4486 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4487 D: FromTU1, AMatcher: classTemplateDecl(hasName(Name: "F")));
4488 auto *Imported1 = cast<ClassTemplateDecl>(Val: Import(From: Definition, Lang: Lang_CXX03));
4489 EXPECT_EQ(Imported0->getTemplatedDecl()->getTypeForDecl(),
4490 Imported1->getTemplatedDecl()->getTypeForDecl());
4491}
4492
4493TEST_P(ImportFriendClasses, DeclsFromFriendsShouldBeInRedeclChains) {
4494 Decl *From, *To;
4495 std::tie(args&: From, args&: To) =
4496 getImportedDecl(FromSrcCode: "class declToImport {};", FromLang: Lang_CXX03,
4497 ToSrcCode: "class Y { friend class declToImport; };", ToLang: Lang_CXX03);
4498 auto *Imported = cast<CXXRecordDecl>(Val: To);
4499
4500 EXPECT_TRUE(Imported->getPreviousDecl());
4501}
4502
4503TEST_P(ImportFriendClasses, SkipComparingFriendTemplateDepth) {
4504 Decl *ToTU = getToTuDecl(
4505 ToSrcCode: R"(
4506 template <class T, T U>
4507 class A;
4508
4509 template <class T, T U>
4510 class A {
4511 public:
4512 template <class P, P Q>
4513 friend class A;
4514
4515 A(T x) :x(x) {}
4516
4517 private:
4518 T x;
4519 };
4520 )",
4521 ToLang: Lang_CXX11);
4522
4523 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4524 D: ToTU,
4525 AMatcher: classTemplateDecl(has(cxxRecordDecl(hasDefinition(), hasName(Name: "A")))));
4526 Decl *FromTU = getTuDecl(
4527 SrcCode: R"(
4528 template <class T, T U>
4529 class A;
4530
4531 template <class T, T U>
4532 class A {
4533 public:
4534 template <class P, P Q>
4535 friend class A;
4536
4537 A(T x) : x(x) {}
4538
4539 private:
4540 T x;
4541 };
4542
4543 A<int,3> a1(0);
4544 )",
4545 Lang: Lang_CXX11, FileName: "input1.cc");
4546 auto *FromA = FirstDeclMatcher<ClassTemplateDecl>().match(
4547 D: FromTU,
4548 AMatcher: classTemplateDecl(has(cxxRecordDecl(hasDefinition(), hasName(Name: "A")))));
4549 auto *ToA = Import(From: FromA, Lang: Lang_CXX11);
4550 EXPECT_TRUE(ToA);
4551 EXPECT_EQ(Fwd->getTemplatedDecl()->getTypeForDecl(),
4552 ToA->getTemplatedDecl()->getTypeForDecl());
4553}
4554
4555TEST_P(ImportFriendClasses,
4556 ImportOfClassTemplateDefinitionShouldConnectToFwdFriend) {
4557 Decl *ToTU = getToTuDecl(
4558 ToSrcCode: R"(
4559 class X {
4560 class Y;
4561 };
4562 class X::Y {
4563 template <typename T>
4564 friend class F; // The decl context of F is the global namespace.
4565 };
4566 )",
4567 ToLang: Lang_CXX03);
4568 auto *ToDecl = FirstDeclMatcher<ClassTemplateDecl>().match(
4569 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "F")));
4570 Decl *FromTU = getTuDecl(
4571 SrcCode: R"(
4572 template <typename T>
4573 class F {};
4574 )",
4575 Lang: Lang_CXX03, FileName: "input0.cc");
4576 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4577 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "F")));
4578 auto *ImportedDef = cast<ClassTemplateDecl>(Val: Import(From: Definition, Lang: Lang_CXX03));
4579 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4580 EXPECT_EQ(ToDecl, ImportedDef->getPreviousDecl());
4581 EXPECT_EQ(ToDecl->getTemplatedDecl(),
4582 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4583}
4584
4585TEST_P(ImportFriendClasses,
4586 ImportOfClassTemplateDefinitionAndFwdFriendShouldBeLinked) {
4587 Decl *FromTU0 = getTuDecl(
4588 SrcCode: R"(
4589 class X {
4590 class Y;
4591 };
4592 class X::Y {
4593 template <typename T>
4594 friend class F; // The decl context of F is the global namespace.
4595 };
4596 )",
4597 Lang: Lang_CXX03, FileName: "input0.cc");
4598 auto *Fwd = FirstDeclMatcher<ClassTemplateDecl>().match(
4599 D: FromTU0, AMatcher: classTemplateDecl(hasName(Name: "F")));
4600 auto *ImportedFwd = cast<ClassTemplateDecl>(Val: Import(From: Fwd, Lang: Lang_CXX03));
4601 Decl *FromTU1 = getTuDecl(
4602 SrcCode: R"(
4603 template <typename T>
4604 class F {};
4605 )",
4606 Lang: Lang_CXX03, FileName: "input1.cc");
4607 auto *Definition = FirstDeclMatcher<ClassTemplateDecl>().match(
4608 D: FromTU1, AMatcher: classTemplateDecl(hasName(Name: "F")));
4609 auto *ImportedDef = cast<ClassTemplateDecl>(Val: Import(From: Definition, Lang: Lang_CXX03));
4610 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4611 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4612 EXPECT_EQ(ImportedFwd->getTemplatedDecl(),
4613 ImportedDef->getTemplatedDecl()->getPreviousDecl());
4614}
4615
4616TEST_P(ImportFriendClasses, ImportOfClassDefinitionAndFwdFriendShouldBeLinked) {
4617 Decl *FromTU0 = getTuDecl(
4618 SrcCode: R"(
4619 class X {
4620 class Y;
4621 };
4622 class X::Y {
4623 friend class F; // The decl context of F is the global namespace.
4624 };
4625 )",
4626 Lang: Lang_CXX03, FileName: "input0.cc");
4627 auto *Friend = FirstDeclMatcher<FriendDecl>().match(D: FromTU0, AMatcher: friendDecl());
4628 QualType FT = Friend->getFriendType()->getType();
4629 FT = FromTU0->getASTContext().getCanonicalType(T: FT);
4630 auto *Fwd = cast<TagType>(Val&: FT)->getDecl();
4631 auto *ImportedFwd = Import(From: Fwd, Lang: Lang_CXX03);
4632 Decl *FromTU1 = getTuDecl(
4633 SrcCode: R"(
4634 class F {};
4635 )",
4636 Lang: Lang_CXX03, FileName: "input1.cc");
4637 auto *Definition = FirstDeclMatcher<CXXRecordDecl>().match(
4638 D: FromTU1, AMatcher: cxxRecordDecl(hasName(Name: "F")));
4639 auto *ImportedDef = Import(From: Definition, Lang: Lang_CXX03);
4640 EXPECT_TRUE(ImportedDef->getPreviousDecl());
4641 EXPECT_EQ(ImportedFwd, ImportedDef->getPreviousDecl());
4642}
4643
4644TEST_P(ImportFriendClasses,
4645 ImportFriendTemplatesInDependentContext_DefToFriend) {
4646 Decl *ToTU = getToTuDecl(
4647 ToSrcCode: R"(
4648 template<class T1>
4649 struct X {
4650 template<class T2>
4651 friend struct Y;
4652 };
4653 )",
4654 ToLang: Lang_CXX03);
4655 auto *ToYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4656 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4657 Decl *FromTU = getTuDecl(
4658 SrcCode: R"(
4659 template<class T1>
4660 struct Y {};
4661 )",
4662 Lang: Lang_CXX03, FileName: "input0.cc");
4663 auto *FromYDef = FirstDeclMatcher<ClassTemplateDecl>().match(
4664 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4665 auto *ImportedYDef = Import(From: FromYDef, Lang: Lang_CXX03);
4666 EXPECT_TRUE(ImportedYDef);
4667 EXPECT_FALSE(ImportedYDef->getPreviousDecl());
4668 EXPECT_NE(ImportedYDef, ToYFriend);
4669}
4670
4671TEST_P(ImportFriendClasses,
4672 ImportFriendTemplatesInDependentContext_DefToFriend_NE) {
4673 getToTuDecl(
4674 ToSrcCode: R"(
4675 template<class T1>
4676 struct X {
4677 template<class T2>
4678 friend struct Y;
4679 };
4680 )",
4681 ToLang: Lang_CXX03);
4682 Decl *FromTU = getTuDecl(
4683 SrcCode: R"(
4684 template<class T1, class T2>
4685 struct Y {};
4686 )",
4687 Lang: Lang_CXX03, FileName: "input0.cc");
4688 auto *FromYDef = FirstDeclMatcher<ClassTemplateDecl>().match(
4689 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4690 auto *ImportedYDef = Import(From: FromYDef, Lang: Lang_CXX03);
4691 EXPECT_FALSE(ImportedYDef);
4692}
4693
4694TEST_P(ImportFriendClasses,
4695 ImportFriendTemplatesInDependentContext_FriendToFriend) {
4696 Decl *ToTU = getToTuDecl(
4697 ToSrcCode: R"(
4698 template<class T1>
4699 struct X {
4700 template<class T2>
4701 friend struct Y;
4702 };
4703 )",
4704 ToLang: Lang_CXX03);
4705 auto *ToYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4706 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4707 Decl *FromTU = getTuDecl(
4708 SrcCode: R"(
4709 template<class T1>
4710 struct X {
4711 template<class T2>
4712 friend struct Y;
4713 };
4714 )",
4715 Lang: Lang_CXX03, FileName: "input0.cc");
4716 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4717 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4718 auto *ImportedYFriend = Import(From: FromYFriend, Lang: Lang_CXX03);
4719 EXPECT_TRUE(ImportedYFriend);
4720 EXPECT_FALSE(ImportedYFriend->getPreviousDecl());
4721 EXPECT_NE(ImportedYFriend, ToYFriend);
4722}
4723
4724TEST_P(ImportFriendClasses,
4725 ImportFriendTemplatesInDependentContext_FriendToFriend_NE) {
4726 getToTuDecl(
4727 ToSrcCode: R"(
4728 template<class T1>
4729 struct X {
4730 template<class T2>
4731 friend struct Y;
4732 };
4733 )",
4734 ToLang: Lang_CXX03);
4735 Decl *FromTU = getTuDecl(
4736 SrcCode: R"(
4737 template<class T1>
4738 struct X {
4739 template<class T2, class T3>
4740 friend struct Y;
4741 };
4742 )",
4743 Lang: Lang_CXX03, FileName: "input0.cc");
4744 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4745 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4746 auto *ImportedYFriend = Import(From: FromYFriend, Lang: Lang_CXX03);
4747 EXPECT_FALSE(ImportedYFriend);
4748}
4749
4750TEST_P(ImportFriendClasses,
4751 ImportFriendTemplatesInDependentContext_FriendToDef) {
4752 Decl *ToTU = getToTuDecl(
4753 ToSrcCode: R"(
4754 template<class T1>
4755 struct Y {};
4756 )",
4757 ToLang: Lang_CXX03);
4758 auto *ToYDef = FirstDeclMatcher<ClassTemplateDecl>().match(
4759 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4760 Decl *FromTU = getTuDecl(
4761 SrcCode: R"(
4762 template<class T1>
4763 struct X {
4764 template<class T2>
4765 friend struct Y;
4766 };
4767 )",
4768 Lang: Lang_CXX03, FileName: "input0.cc");
4769 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4770 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4771 auto *ImportedYFriend = Import(From: FromYFriend, Lang: Lang_CXX03);
4772 EXPECT_TRUE(ImportedYFriend);
4773 EXPECT_FALSE(ImportedYFriend->getPreviousDecl());
4774 EXPECT_NE(ImportedYFriend, ToYDef);
4775}
4776
4777TEST_P(ImportFriendClasses,
4778 ImportFriendTemplatesInDependentContext_FriendToDef_NE) {
4779 getToTuDecl(
4780 ToSrcCode: R"(
4781 template<class T1>
4782 struct Y {};
4783 )",
4784 ToLang: Lang_CXX03);
4785 Decl *FromTU = getTuDecl(
4786 SrcCode: R"(
4787 template<class T1>
4788 struct X {
4789 template<class T2, class T3>
4790 friend struct Y;
4791 };
4792 )",
4793 Lang: Lang_CXX03, FileName: "input0.cc");
4794 auto *FromYFriend = FirstDeclMatcher<ClassTemplateDecl>().match(
4795 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "Y")));
4796 auto *ImportedYFriend = Import(From: FromYFriend, Lang: Lang_CXX03);
4797 EXPECT_FALSE(ImportedYFriend);
4798}
4799
4800TEST_P(ImportFriendClasses, ImportOfRepeatedFriendType) {
4801 const char *Code =
4802 R"(
4803 class Container {
4804 friend class X;
4805 friend class X;
4806 };
4807 )";
4808 testRepeatedFriendImport(Code);
4809}
4810
4811TEST_P(ImportFriendClasses, ImportOfRepeatedFriendDecl) {
4812 const char *Code =
4813 R"(
4814 class Container {
4815 friend void f();
4816 friend void f();
4817 };
4818 )";
4819 testRepeatedFriendImport(Code);
4820}
4821
4822TEST_P(ImportFriendClasses, ImportOfRepeatedFriendFunctionTemplateDecl) {
4823 const char *Code =
4824 R"(
4825 template <class T>
4826 class Container {
4827 template <class U> friend void m();
4828 template <class U> friend void m();
4829 };
4830 )";
4831 testRepeatedFriendImport(Code);
4832}
4833
4834TEST_P(ImportFriendClasses, ImportOfRepeatedFriendClassTemplateDecl) {
4835 const char *Code =
4836 R"(
4837 template <class T>
4838 class Container {
4839 template <class U> friend class X;
4840 template <class U> friend class X;
4841 };
4842 )";
4843 testRepeatedFriendImport(Code);
4844}
4845
4846TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
4847 auto *Code = R"(
4848 template <class T>
4849 struct X {
4850 friend void foo(){}
4851 };
4852 )";
4853 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX03);
4854 auto *ToFoo = FirstDeclMatcher<FunctionDecl>().match(
4855 D: ToTU, AMatcher: functionDecl(hasName(Name: "foo")));
4856
4857 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input.cc");
4858 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
4859 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo")));
4860 auto *ImportedFoo = Import(From: FromFoo, Lang: Lang_CXX03);
4861 EXPECT_EQ(ImportedFoo, ToFoo);
4862}
4863
4864struct DeclContextTest : ASTImporterOptionSpecificTestBase {};
4865
4866TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
4867 Decl *TU = getTuDecl(
4868 SrcCode: R"(
4869 namespace NS {
4870
4871 template <typename T>
4872 struct S {};
4873 template struct S<int>;
4874
4875 inline namespace INS {
4876 template <typename T>
4877 struct S {};
4878 template struct S<int>;
4879 }
4880
4881 }
4882 )", Lang: Lang_CXX11, FileName: "input0.cc");
4883 auto *NS = FirstDeclMatcher<NamespaceDecl>().match(
4884 D: TU, AMatcher: namespaceDecl());
4885 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
4886 D: TU, AMatcher: classTemplateSpecializationDecl());
4887 ASSERT_TRUE(NS->containsDecl(Spec));
4888
4889 NS->removeDecl(D: Spec);
4890 EXPECT_FALSE(NS->containsDecl(Spec));
4891}
4892
4893TEST_P(DeclContextTest,
4894 removeDeclShouldNotFailEvenIfWeHaveExternalVisibleStorage) {
4895 Decl *TU = getTuDecl(SrcCode: "extern int A; int A;", Lang: Lang_CXX03);
4896 auto *A0 = FirstDeclMatcher<VarDecl>().match(D: TU, AMatcher: varDecl(hasName(Name: "A")));
4897 auto *A1 = LastDeclMatcher<VarDecl>().match(D: TU, AMatcher: varDecl(hasName(Name: "A")));
4898
4899 // Investigate the list.
4900 auto *DC = A0->getDeclContext();
4901 ASSERT_TRUE(DC->containsDecl(A0));
4902 ASSERT_TRUE(DC->containsDecl(A1));
4903
4904 // Investigate the lookup table.
4905 auto *Map = DC->getLookupPtr();
4906 ASSERT_TRUE(Map);
4907 auto I = Map->find(Val: A0->getDeclName());
4908 ASSERT_NE(I, Map->end());
4909 StoredDeclsList &L = I->second;
4910 // The lookup table contains the most recent decl of A.
4911 ASSERT_NE(L.getAsDecl(), A0);
4912 ASSERT_EQ(L.getAsDecl(), A1);
4913
4914 ASSERT_TRUE(L.getAsDecl());
4915 // Simulate the private function DeclContext::reconcileExternalVisibleStorage.
4916 // We do not have a list with one element.
4917 L.setHasExternalDecls();
4918 ASSERT_FALSE(L.getAsList());
4919 auto Results = L.getLookupResult();
4920 ASSERT_EQ(1u, std::distance(Results.begin(), Results.end()));
4921
4922 // This asserts in the old implementation.
4923 DC->removeDecl(D: A0);
4924 EXPECT_FALSE(DC->containsDecl(A0));
4925
4926 // Make sure we do not leave a StoredDeclsList with no entries.
4927 DC->removeDecl(D: A1);
4928 ASSERT_EQ(Map->find(A1->getDeclName()), Map->end());
4929}
4930
4931struct ImportFunctionTemplateSpecializations
4932 : ASTImporterOptionSpecificTestBase {};
4933
4934TEST_P(ImportFunctionTemplateSpecializations,
4935 TUshouldNotContainFunctionTemplateImplicitInstantiation) {
4936
4937 Decl *FromTU = getTuDecl(
4938 SrcCode: R"(
4939 template<class T>
4940 int f() { return 0; }
4941 void foo() { f<int>(); }
4942 )",
4943 Lang: Lang_CXX03, FileName: "input0.cc");
4944
4945 // Check that the function template instantiation is NOT the child of the TU.
4946 auto Pattern = translationUnitDecl(
4947 unless(has(functionDecl(hasName(Name: "f"), isTemplateInstantiation()))));
4948 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4949
4950 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
4951 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo")));
4952 ASSERT_TRUE(Import(Foo, Lang_CXX03));
4953
4954 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4955 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4956}
4957
4958TEST_P(ImportFunctionTemplateSpecializations,
4959 TUshouldNotContainFunctionTemplateExplicitInstantiation) {
4960
4961 Decl *FromTU = getTuDecl(
4962 SrcCode: R"(
4963 template<class T>
4964 int f() { return 0; }
4965 template int f<int>();
4966 )",
4967 Lang: Lang_CXX03, FileName: "input0.cc");
4968
4969 // Check that the function template instantiation is NOT the child of the TU.
4970 auto Instantiation = functionDecl(hasName(Name: "f"), isTemplateInstantiation());
4971 auto Pattern = translationUnitDecl(unless(has(Instantiation)));
4972 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4973
4974 ASSERT_TRUE(Import(FirstDeclMatcher<Decl>().match(FromTU, Instantiation),
4975 Lang_CXX03));
4976
4977 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
4978 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
4979}
4980
4981TEST_P(ImportFunctionTemplateSpecializations,
4982 TUshouldContainFunctionTemplateSpecialization) {
4983
4984 Decl *FromTU = getTuDecl(
4985 SrcCode: R"(
4986 template<class T>
4987 int f() { return 0; }
4988 template <> int f<int>() { return 4; }
4989 )",
4990 Lang: Lang_CXX03, FileName: "input0.cc");
4991
4992 // Check that the function template specialization is the child of the TU.
4993 auto Specialization =
4994 functionDecl(hasName(Name: "f"), isExplicitTemplateSpecialization());
4995 auto Pattern = translationUnitDecl(has(Specialization));
4996 ASSERT_TRUE(MatchVerifier<Decl>{}.match(FromTU, Pattern));
4997
4998 ASSERT_TRUE(Import(FirstDeclMatcher<Decl>().match(FromTU, Specialization),
4999 Lang_CXX03));
5000
5001 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5002 EXPECT_TRUE(MatchVerifier<Decl>{}.match(ToTU, Pattern));
5003}
5004
5005TEST_P(ImportFunctionTemplateSpecializations,
5006 FunctionTemplateSpecializationRedeclChain) {
5007
5008 Decl *FromTU = getTuDecl(
5009 SrcCode: R"(
5010 template<class T>
5011 int f() { return 0; }
5012 template <> int f<int>() { return 4; }
5013 )",
5014 Lang: Lang_CXX03, FileName: "input0.cc");
5015
5016 auto Spec = functionDecl(hasName(Name: "f"), isExplicitTemplateSpecialization(),
5017 hasParent(translationUnitDecl()));
5018 auto *FromSpecD = FirstDeclMatcher<Decl>().match(D: FromTU, AMatcher: Spec);
5019 {
5020 auto *TU = FromTU;
5021 auto *SpecD = FromSpecD;
5022 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
5023 D: TU, AMatcher: functionTemplateDecl());
5024 auto *FirstSpecD = *(TemplateD->spec_begin());
5025 ASSERT_EQ(SpecD, FirstSpecD);
5026 ASSERT_TRUE(SpecD->getPreviousDecl());
5027 ASSERT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
5028 ->doesThisDeclarationHaveABody());
5029 }
5030
5031 ASSERT_TRUE(Import(FromSpecD, Lang_CXX03));
5032
5033 {
5034 auto *TU = ToAST->getASTContext().getTranslationUnitDecl();
5035 auto *SpecD = FirstDeclMatcher<Decl>().match(D: TU, AMatcher: Spec);
5036 auto *TemplateD = FirstDeclMatcher<FunctionTemplateDecl>().match(
5037 D: TU, AMatcher: functionTemplateDecl());
5038 auto *FirstSpecD = *(TemplateD->spec_begin());
5039 EXPECT_EQ(SpecD, FirstSpecD);
5040 ASSERT_TRUE(SpecD->getPreviousDecl());
5041 EXPECT_FALSE(cast<FunctionDecl>(SpecD->getPreviousDecl())
5042 ->doesThisDeclarationHaveABody());
5043 }
5044}
5045
5046TEST_P(ImportFunctionTemplateSpecializations,
5047 MatchNumberOfFunctionTemplateSpecializations) {
5048
5049 Decl *FromTU = getTuDecl(
5050 SrcCode: R"(
5051 template <typename T> constexpr int f() { return 0; }
5052 template <> constexpr int f<int>() { return 4; }
5053 void foo() {
5054 static_assert(f<char>() == 0, "");
5055 static_assert(f<int>() == 4, "");
5056 }
5057 )",
5058 Lang: Lang_CXX11, FileName: "input0.cc");
5059 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
5060 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo")));
5061
5062 Import(From: FromD, Lang: Lang_CXX11);
5063 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5064 EXPECT_EQ(
5065 DeclCounter<FunctionDecl>().match(FromTU, functionDecl(hasName("f"))),
5066 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))));
5067}
5068
5069TEST_P(ASTImporterOptionSpecificTestBase,
5070 ImportShouldNotReportFalseODRErrorWhenRecordIsBeingDefined) {
5071 {
5072 Decl *FromTU = getTuDecl(
5073 SrcCode: R"(
5074 template <typename T>
5075 struct B;
5076 )",
5077 Lang: Lang_CXX03, FileName: "input0.cc");
5078 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
5079 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "B")));
5080
5081 Import(From: FromD, Lang: Lang_CXX03);
5082 }
5083
5084 {
5085 Decl *FromTU = getTuDecl(
5086 SrcCode: R"(
5087 template <typename T>
5088 struct B {
5089 void f();
5090 B* b;
5091 };
5092 )",
5093 Lang: Lang_CXX03, FileName: "input1.cc");
5094 FunctionDecl *FromD = FirstDeclMatcher<FunctionDecl>().match(
5095 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
5096 Import(From: FromD, Lang: Lang_CXX03);
5097 auto *FromCTD = FirstDeclMatcher<ClassTemplateDecl>().match(
5098 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "B")));
5099 auto *ToCTD = cast<ClassTemplateDecl>(Val: Import(From: FromCTD, Lang: Lang_CXX03));
5100 EXPECT_TRUE(ToCTD->isThisDeclarationADefinition());
5101
5102 // We expect no (ODR) warning during the import.
5103 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
5104 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
5105 }
5106}
5107
5108TEST_P(ASTImporterOptionSpecificTestBase,
5109 ImportingTypedefShouldImportTheCompleteType) {
5110 // We already have an incomplete underlying type in the "To" context.
5111 auto Code =
5112 R"(
5113 template <typename T>
5114 struct S {
5115 void foo();
5116 };
5117 using U = S<int>;
5118 )";
5119 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX11);
5120 auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(D: ToTU,
5121 AMatcher: typedefNameDecl(hasName(Name: "U")));
5122 ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
5123
5124 // The "From" context has the same typedef, but the underlying type is
5125 // complete this time.
5126 Decl *FromTU = getTuDecl(SrcCode: std::string(Code) +
5127 R"(
5128 void foo(U* u) {
5129 u->foo();
5130 }
5131 )", Lang: Lang_CXX11);
5132 auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(D: FromTU,
5133 AMatcher: typedefNameDecl(hasName(Name: "U")));
5134 ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
5135
5136 // The imported type should be complete.
5137 auto *ImportedD = cast<TypedefNameDecl>(Val: Import(From: FromD, Lang: Lang_CXX11));
5138 EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
5139}
5140
5141TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) {
5142 auto Code =
5143 R"(
5144 template<class T>
5145 int f() { return 0; }
5146 template <> int f<int>() { return 4; }
5147 )";
5148
5149 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03);
5150 auto *FromD = FirstDeclMatcher<FunctionDecl>().match(D: FromTU,
5151 AMatcher: functionDecl(hasName(Name: "f"), isExplicitTemplateSpecialization()));
5152 ASSERT_EQ(FromD->getNumTemplateParameterLists(), 1u);
5153
5154 auto *ToD = Import(From: FromD, Lang: Lang_CXX03);
5155 // The template parameter list should exist.
5156 EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u);
5157}
5158
5159const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateDecl>
5160 varTemplateDecl;
5161
5162const internal::VariadicDynCastAllOfMatcher<
5163 Decl, VarTemplatePartialSpecializationDecl>
5164 varTemplatePartialSpecializationDecl;
5165
5166TEST_P(ASTImporterOptionSpecificTestBase,
5167 FunctionTemplateParameterDeclContext) {
5168 constexpr auto Code =
5169 R"(
5170 template<class T>
5171 void f() {};
5172 )";
5173
5174 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
5175
5176 auto *FromD = FirstDeclMatcher<FunctionTemplateDecl>().match(
5177 D: FromTU, AMatcher: functionTemplateDecl(hasName(Name: "f")));
5178
5179 ASSERT_EQ(FromD->getTemplateParameters()->getParam(0)->getDeclContext(),
5180 FromD->getTemplatedDecl());
5181
5182 auto *ToD = Import(From: FromD, Lang: Lang_CXX11);
5183 EXPECT_EQ(ToD->getTemplateParameters()->getParam(0)->getDeclContext(),
5184 ToD->getTemplatedDecl());
5185 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5186 ToD->getTemplatedDecl(), ToD->getTemplateParameters()->getParam(0)));
5187}
5188
5189TEST_P(ASTImporterOptionSpecificTestBase, ClassTemplateParameterDeclContext) {
5190 constexpr auto Code =
5191 R"(
5192 template<class T1, class T2>
5193 struct S {};
5194 template<class T2>
5195 struct S<int, T2> {};
5196 )";
5197
5198 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
5199
5200 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
5201 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "S")));
5202 auto *FromDPart =
5203 FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match(
5204 D: FromTU, AMatcher: classTemplatePartialSpecializationDecl(hasName(Name: "S")));
5205
5206 ASSERT_EQ(FromD->getTemplateParameters()->getParam(0)->getDeclContext(),
5207 FromD->getTemplatedDecl());
5208 ASSERT_EQ(FromDPart->getTemplateParameters()->getParam(0)->getDeclContext(),
5209 FromDPart);
5210
5211 auto *ToD = Import(From: FromD, Lang: Lang_CXX11);
5212 auto *ToDPart = Import(From: FromDPart, Lang: Lang_CXX11);
5213
5214 EXPECT_EQ(ToD->getTemplateParameters()->getParam(0)->getDeclContext(),
5215 ToD->getTemplatedDecl());
5216 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5217 ToD->getTemplatedDecl(), ToD->getTemplateParameters()->getParam(0)));
5218
5219 EXPECT_EQ(ToDPart->getTemplateParameters()->getParam(0)->getDeclContext(),
5220 ToDPart);
5221 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5222 ToDPart, ToDPart->getTemplateParameters()->getParam(0)));
5223}
5224
5225TEST_P(ASTImporterOptionSpecificTestBase,
5226 CXXDeductionGuideTemplateParameterDeclContext) {
5227 Decl *FromTU = getTuDecl(
5228 SrcCode: R"(
5229 template <typename T> struct A {
5230 A(T);
5231 };
5232 A a{(int)0};
5233 )",
5234 Lang: Lang_CXX17, FileName: "input.cc");
5235// clang-format off
5236/*
5237|-ClassTemplateDecl 0x1fe5000 <input.cc:2:7, line:4:7> line:2:36 A
5238| |-TemplateTypeParmDecl 0x1fe4eb0 <col:17, col:26> col:26 referenced typename depth 0 index 0 T
5239| |-CXXRecordDecl 0x1fe4f70 <col:29, line:4:7> line:2:36 struct A definition
5240
5241|-FunctionTemplateDecl 0x1fe5860 <line:2:7, line:3:12> col:9 implicit <deduction guide for A>
5242| |-TemplateTypeParmDecl 0x1fe4eb0 <line:2:17, col:26> col:26 referenced typename depth 0 index 0 T
5243| |-CXXDeductionGuideDecl 0x1fe57a8 <line:3:9, col:12> col:9 implicit <deduction guide for A> 'auto (T) -> A<T>'
5244| | `-ParmVarDecl 0x1fe56b0 <col:11> col:12 'T'
5245| `-CXXDeductionGuideDecl 0x20515d8 <col:9, col:12> col:9 implicit used <deduction guide for A> 'auto (int) -> A<int>'
5246| |-TemplateArgument type 'int'
5247| | `-BuiltinType 0x20587e0 'int'
5248| `-ParmVarDecl 0x2051388 <col:11> col:12 'int'
5249`-FunctionTemplateDecl 0x1fe5a78 <line:2:7, col:36> col:36 implicit <deduction guide for A>
5250 |-TemplateTypeParmDecl 0x1fe4eb0 <col:17, col:26> col:26 referenced typename depth 0 index 0 T
5251 `-CXXDeductionGuideDecl 0x1fe59c0 <col:36> col:36 implicit <deduction guide for A> 'auto (A<T>) -> A<T>'
5252 `-ParmVarDecl 0x1fe5958 <col:36> col:36 'A<T>'
5253*/
5254// clang-format on
5255 auto *FromD1 = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
5256 D: FromTU, AMatcher: cxxDeductionGuideDecl());
5257 auto *FromD2 = LastDeclMatcher<CXXDeductionGuideDecl>().match(
5258 D: FromTU, AMatcher: cxxDeductionGuideDecl());
5259
5260 NamedDecl *P1 =
5261 FromD1->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(
5262 Idx: 0);
5263 NamedDecl *P2 =
5264 FromD2->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(
5265 Idx: 0);
5266 DeclContext *DC = P1->getDeclContext();
5267
5268 ASSERT_EQ(P1, P2);
5269 ASSERT_TRUE(DC == FromD1 || DC == FromD2);
5270
5271 auto *ToD1 = Import(From: FromD1, Lang: Lang_CXX17);
5272 auto *ToD2 = Import(From: FromD2, Lang: Lang_CXX17);
5273 ASSERT_TRUE(ToD1 && ToD2);
5274
5275 P1 = ToD1->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(
5276 Idx: 0);
5277 P2 = ToD2->getDescribedFunctionTemplate()->getTemplateParameters()->getParam(
5278 Idx: 0);
5279 DC = P1->getDeclContext();
5280
5281 EXPECT_EQ(P1, P2);
5282 EXPECT_TRUE(DC == ToD1 || DC == ToD2);
5283
5284 ASTImporterLookupTable *Tbl = SharedStatePtr->getLookupTable();
5285 if (Tbl->contains(DC: ToD1, ND: P1)) {
5286 EXPECT_FALSE(Tbl->contains(ToD2, P1));
5287 } else {
5288 EXPECT_TRUE(Tbl->contains(ToD2, P1));
5289 }
5290}
5291
5292TEST_P(ASTImporterOptionSpecificTestBase, RecordVarTemplateDecl) {
5293 Decl *ToTU = getToTuDecl(
5294 ToSrcCode: R"(
5295 template <class T>
5296 class A {
5297 public:
5298 template <class U>
5299 static constexpr bool X = true;
5300 };
5301 )",
5302 ToLang: Lang_CXX14);
5303
5304 auto *ToTUX = FirstDeclMatcher<VarTemplateDecl>().match(
5305 D: ToTU, AMatcher: varTemplateDecl(hasName(Name: "X")));
5306 Decl *FromTU = getTuDecl(
5307 SrcCode: R"(
5308 template <class T>
5309 class A {
5310 public:
5311 template <class U>
5312 static constexpr bool X = true;
5313 };
5314 )",
5315 Lang: Lang_CXX14, FileName: "input1.cc");
5316 auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match(
5317 D: FromTU, AMatcher: varTemplateDecl(hasName(Name: "X")));
5318 auto *ToX = Import(From: FromX, Lang: Lang_CXX11);
5319 EXPECT_TRUE(ToX);
5320 EXPECT_EQ(ToTUX, ToX);
5321}
5322
5323TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateDeclConflict) {
5324 getToTuDecl(
5325 ToSrcCode: R"(
5326 template <class U>
5327 constexpr int X = 1;
5328 )",
5329 ToLang: Lang_CXX14);
5330
5331 Decl *FromTU = getTuDecl(
5332 SrcCode: R"(
5333 template <class U>
5334 constexpr int X = 2;
5335 )",
5336 Lang: Lang_CXX14, FileName: "input1.cc");
5337 auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match(
5338 D: FromTU, AMatcher: varTemplateDecl(hasName(Name: "X")));
5339 auto *ToX = Import(From: FromX, Lang: Lang_CXX11);
5340 // FIXME: This import should fail.
5341 EXPECT_TRUE(ToX);
5342}
5343
5344TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateStaticDefinition) {
5345 Decl *ToTU = getToTuDecl(
5346 ToSrcCode: R"(
5347 struct A {
5348 template <class U>
5349 static int X;
5350 };
5351 )",
5352 ToLang: Lang_CXX14);
5353 auto *ToX = FirstDeclMatcher<VarTemplateDecl>().match(
5354 D: ToTU, AMatcher: varTemplateDecl(hasName(Name: "X")));
5355 ASSERT_FALSE(ToX->isThisDeclarationADefinition());
5356
5357 Decl *FromTU = getTuDecl(
5358 SrcCode: R"(
5359 struct A {
5360 template <class U>
5361 static int X;
5362 };
5363 template <class U>
5364 int A::X = 2;
5365 )",
5366 Lang: Lang_CXX14, FileName: "input1.cc");
5367 auto *FromXDef = LastDeclMatcher<VarTemplateDecl>().match(
5368 D: FromTU, AMatcher: varTemplateDecl(hasName(Name: "X")));
5369 ASSERT_TRUE(FromXDef->isThisDeclarationADefinition());
5370 auto *ToXDef = Import(From: FromXDef, Lang: Lang_CXX14);
5371 EXPECT_TRUE(ToXDef);
5372 EXPECT_TRUE(ToXDef->isThisDeclarationADefinition());
5373 EXPECT_EQ(ToXDef->getPreviousDecl(), ToX);
5374}
5375
5376TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateSpecializationDeclValue) {
5377 Decl *ToTU = getToTuDecl(
5378 ToSrcCode: R"(
5379 template <class U>
5380 constexpr int X = U::Value;
5381 struct A { static constexpr int Value = 1; };
5382 constexpr int Y = X<A>;
5383 )",
5384 ToLang: Lang_CXX14);
5385
5386 auto *ToTUX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(
5387 D: ToTU, AMatcher: varTemplateSpecializationDecl(hasName(Name: "X")));
5388 Decl *FromTU = getTuDecl(
5389 SrcCode: R"(
5390 template <class U>
5391 constexpr int X = U::Value;
5392 struct A { static constexpr int Value = 1; };
5393 constexpr int Y = X<A>;
5394 )",
5395 Lang: Lang_CXX14, FileName: "input1.cc");
5396 auto *FromX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(
5397 D: FromTU, AMatcher: varTemplateSpecializationDecl(hasName(Name: "X")));
5398 auto *ToX = Import(From: FromX, Lang: Lang_CXX14);
5399 EXPECT_TRUE(ToX);
5400 EXPECT_EQ(ToTUX, ToX);
5401}
5402
5403TEST_P(ASTImporterOptionSpecificTestBase,
5404 VarTemplateSpecializationDeclValueConflict) {
5405 getToTuDecl(
5406 ToSrcCode: R"(
5407 template <class U>
5408 constexpr int X = U::Value;
5409 struct A { static constexpr int Value = 1; };
5410 constexpr int Y = X<A>;
5411 )",
5412 ToLang: Lang_CXX14);
5413
5414 Decl *FromTU = getTuDecl(
5415 SrcCode: R"(
5416 template <class U>
5417 constexpr int X = U::Value;
5418 struct A { static constexpr int Value = 2; };
5419 constexpr int Y = X<A>;
5420 )",
5421 Lang: Lang_CXX14, FileName: "input1.cc");
5422 auto *FromX = FirstDeclMatcher<VarTemplateSpecializationDecl>().match(
5423 D: FromTU, AMatcher: varTemplateSpecializationDecl(hasName(Name: "X")));
5424 auto *ToX = Import(From: FromX, Lang: Lang_CXX14);
5425 EXPECT_FALSE(ToX);
5426}
5427
5428TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateDeclInlineWithCXX17) {
5429 Decl *FromTU = getTuDecl(
5430 SrcCode: R"(
5431 struct S {
5432 template <unsigned> static constexpr bool X = true;
5433 };
5434 )",
5435 Lang: Lang_CXX17, FileName: "input1.cc");
5436 Decl *FromTU2 = getTuDecl(
5437 SrcCode: R"(
5438 struct S {
5439 template <unsigned> static constexpr bool X = true;
5440 template <typename T> void get() { X<sizeof(T)>; }
5441 };
5442 template <typename U> U qvariant_cast(const S &v) { return v.get; }
5443 )",
5444 Lang: Lang_CXX17, FileName: "input2.cc");
5445 auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match(
5446 D: FromTU, AMatcher: varTemplateDecl(hasName(Name: "X")));
5447 auto *ToX = Import(From: FromX, Lang: Lang_CXX17);
5448 ASSERT_TRUE(ToX);
5449 auto *FromX2 = FirstDeclMatcher<VarTemplateDecl>().match(
5450 D: FromTU2, AMatcher: varTemplateDecl(hasName(Name: "X")));
5451 auto *ToX2 = Import(From: FromX2, Lang: Lang_CXX17);
5452 EXPECT_TRUE(ToX2);
5453 EXPECT_EQ(ToX, ToX2);
5454}
5455
5456TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateParameterDeclContext) {
5457 constexpr auto Code =
5458 R"(
5459 template<class T1, class T2>
5460 int X1;
5461 template<class T2>
5462 int X1<int, T2>;
5463
5464 namespace Ns {
5465 template<class T1, class T2>
5466 int X2;
5467 template<class T2>
5468 int X2<int, T2>;
5469 }
5470 )";
5471
5472 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX14);
5473
5474 auto *FromD1 = FirstDeclMatcher<VarTemplateDecl>().match(
5475 D: FromTU, AMatcher: varTemplateDecl(hasName(Name: "X1")));
5476 auto *FromD1Part =
5477 FirstDeclMatcher<VarTemplatePartialSpecializationDecl>().match(
5478 D: FromTU, AMatcher: varTemplatePartialSpecializationDecl(hasName(Name: "X1")));
5479 auto *FromD2 = FirstDeclMatcher<VarTemplateDecl>().match(
5480 D: FromTU, AMatcher: varTemplateDecl(hasName(Name: "X2")));
5481 auto *FromD2Part =
5482 FirstDeclMatcher<VarTemplatePartialSpecializationDecl>().match(
5483 D: FromTU, AMatcher: varTemplatePartialSpecializationDecl(hasName(Name: "X2")));
5484
5485 ASSERT_EQ(FromD1->getTemplateParameters()->getParam(0)->getDeclContext(),
5486 FromD1->getDeclContext());
5487 ASSERT_EQ(FromD2->getTemplateParameters()->getParam(0)->getDeclContext(),
5488 FromD2->getDeclContext());
5489
5490 ASSERT_EQ(FromD1Part->getTemplateParameters()->getParam(0)->getDeclContext(),
5491 FromD1Part->getDeclContext());
5492 // FIXME: VarTemplatePartialSpecializationDecl does not update ("adopt")
5493 // template parameter decl context
5494 // ASSERT_EQ(FromD2Part->getTemplateParameters()->getParam(0)->getDeclContext(),
5495 // FromD2Part->getDeclContext());
5496
5497 auto *ToD1 = Import(From: FromD1, Lang: Lang_CXX14);
5498 auto *ToD2 = Import(From: FromD2, Lang: Lang_CXX14);
5499
5500 auto *ToD1Part = Import(From: FromD1Part, Lang: Lang_CXX14);
5501 auto *ToD2Part = Import(From: FromD2Part, Lang: Lang_CXX14);
5502
5503 EXPECT_EQ(ToD1->getTemplateParameters()->getParam(0)->getDeclContext(),
5504 ToD1->getDeclContext());
5505 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5506 ToD1->getDeclContext(), ToD1->getTemplateParameters()->getParam(0)));
5507 EXPECT_EQ(ToD2->getTemplateParameters()->getParam(0)->getDeclContext(),
5508 ToD2->getDeclContext());
5509 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5510 ToD2->getDeclContext(), ToD2->getTemplateParameters()->getParam(0)));
5511
5512 EXPECT_EQ(ToD1Part->getTemplateParameters()->getParam(0)->getDeclContext(),
5513 ToD1Part->getDeclContext());
5514 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5515 ToD1Part->getDeclContext(),
5516 ToD1Part->getTemplateParameters()->getParam(0)));
5517 // EXPECT_EQ(ToD2Part->getTemplateParameters()->getParam(0)->getDeclContext(),
5518 // ToD2Part->getDeclContext());
5519 // EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5520 // ToD2Part->getDeclContext(),
5521 // ToD2Part->getTemplateParameters()->getParam(0)));
5522 (void)ToD2Part;
5523}
5524
5525TEST_P(ASTImporterOptionSpecificTestBase,
5526 TypeAliasTemplateParameterDeclContext) {
5527 constexpr auto Code =
5528 R"(
5529 template<class T1, class T2>
5530 struct S {};
5531 template<class T> using S1 = S<T, int>;
5532 namespace Ns {
5533 template<class T> using S2 = S<T, int>;
5534 }
5535 )";
5536
5537 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
5538
5539 auto *FromD1 = FirstDeclMatcher<TypeAliasTemplateDecl>().match(
5540 D: FromTU, AMatcher: typeAliasTemplateDecl(hasName(Name: "S1")));
5541 auto *FromD2 = FirstDeclMatcher<TypeAliasTemplateDecl>().match(
5542 D: FromTU, AMatcher: typeAliasTemplateDecl(hasName(Name: "S2")));
5543
5544 ASSERT_EQ(FromD1->getTemplateParameters()->getParam(0)->getDeclContext(),
5545 FromD1->getDeclContext());
5546 ASSERT_EQ(FromD2->getTemplateParameters()->getParam(0)->getDeclContext(),
5547 FromD2->getDeclContext());
5548
5549 auto *ToD1 = Import(From: FromD1, Lang: Lang_CXX11);
5550 auto *ToD2 = Import(From: FromD2, Lang: Lang_CXX11);
5551
5552 EXPECT_EQ(ToD1->getTemplateParameters()->getParam(0)->getDeclContext(),
5553 ToD1->getDeclContext());
5554 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5555 ToD1->getDeclContext(), ToD1->getTemplateParameters()->getParam(0)));
5556 EXPECT_EQ(ToD2->getTemplateParameters()->getParam(0)->getDeclContext(),
5557 ToD2->getDeclContext());
5558 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
5559 ToD2->getDeclContext(), ToD2->getTemplateParameters()->getParam(0)));
5560}
5561
5562TEST_P(ASTImporterOptionSpecificTestBase, ImportSubstTemplateTypeParmType) {
5563 constexpr auto Code = R"(
5564 template <class A1, class... A2> struct A {
5565 using B = A1(A2...);
5566 };
5567 template struct A<void, char, float, int, short>;
5568 )";
5569 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11, FileName: "input.cpp");
5570 auto *FromClass = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
5571 D: FromTU, AMatcher: classTemplateSpecializationDecl());
5572
5573 auto testType = [&](ASTContext &Ctx, const char *Name,
5574 UnsignedOrNone PackIndex) {
5575 const auto *Subst = selectFirst<SubstTemplateTypeParmType>(
5576 BoundTo: "sttp", Results: match(Matcher: substTemplateTypeParmType(
5577 hasReplacementType(hasCanonicalType(InnerMatcher: asString(Name))))
5578 .bind(ID: "sttp"),
5579 Context&: Ctx));
5580 const char *ExpectedTemplateParamName = PackIndex ? "A2" : "A1";
5581 ASSERT_TRUE(Subst);
5582 ASSERT_EQ(Subst->getReplacedParameter()->getIdentifier()->getName(),
5583 ExpectedTemplateParamName);
5584 ASSERT_EQ(Subst->getPackIndex(), PackIndex);
5585 };
5586 auto tests = [&](ASTContext &Ctx) {
5587 testType(Ctx, "void", std::nullopt);
5588 testType(Ctx, "char", 3u);
5589 testType(Ctx, "float", 2u);
5590 testType(Ctx, "int", 1u);
5591 testType(Ctx, "short", 0u);
5592 };
5593
5594 tests(FromTU->getASTContext());
5595
5596 ClassTemplateSpecializationDecl *ToClass = Import(From: FromClass, Lang: Lang_CXX11);
5597 tests(ToClass->getASTContext());
5598}
5599
5600const AstTypeMatcher<SubstTemplateTypeParmPackType>
5601 substTemplateTypeParmPackType;
5602
5603TEST_P(ASTImporterOptionSpecificTestBase, ImportSubstTemplateTypeParmPackType) {
5604 constexpr auto Code = R"(
5605 template<typename ...T> struct D {
5606 template<typename... U> using B = int(int (*...p)(T, U));
5607 template<typename U1, typename U2> D(B<U1, U2>*);
5608 };
5609 int f(int(int, int), int(int, int));
5610
5611 using asd = D<float, double, float>::B<int, long, int>;
5612 )";
5613 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11, FileName: "input.cpp");
5614 auto *FromClass = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
5615 D: FromTU, AMatcher: classTemplateSpecializationDecl());
5616
5617 {
5618 ASTContext &FromCtx = FromTU->getASTContext();
5619 const auto *FromSubstPack = selectFirst<SubstTemplateTypeParmPackType>(
5620 BoundTo: "pack", Results: match(Matcher: substTemplateTypeParmPackType().bind(ID: "pack"), Context&: FromCtx));
5621
5622 ASSERT_TRUE(FromSubstPack);
5623 ASSERT_EQ(FromSubstPack->getIdentifier()->getName(), "T");
5624 ArrayRef<TemplateArgument> FromArgPack =
5625 FromSubstPack->getArgumentPack().pack_elements();
5626 ASSERT_EQ(FromArgPack.size(), 3u);
5627 ASSERT_EQ(FromArgPack[0].getAsType(), FromCtx.FloatTy);
5628 ASSERT_EQ(FromArgPack[1].getAsType(), FromCtx.DoubleTy);
5629 ASSERT_EQ(FromArgPack[2].getAsType(), FromCtx.FloatTy);
5630 }
5631 {
5632 // Let's do the import.
5633 ClassTemplateSpecializationDecl *ToClass = Import(From: FromClass, Lang: Lang_CXX11);
5634 ASTContext &ToCtx = ToClass->getASTContext();
5635
5636 const auto *ToSubstPack = selectFirst<SubstTemplateTypeParmPackType>(
5637 BoundTo: "pack", Results: match(Matcher: substTemplateTypeParmPackType().bind(ID: "pack"), Context&: ToCtx));
5638
5639 // Check if it meets the requirements.
5640 ASSERT_TRUE(ToSubstPack);
5641 ASSERT_EQ(ToSubstPack->getIdentifier()->getName(), "T");
5642 ArrayRef<TemplateArgument> ToArgPack =
5643 ToSubstPack->getArgumentPack().pack_elements();
5644 ASSERT_EQ(ToArgPack.size(), 3u);
5645 ASSERT_EQ(ToArgPack[0].getAsType(), ToCtx.FloatTy);
5646 ASSERT_EQ(ToArgPack[1].getAsType(), ToCtx.DoubleTy);
5647 ASSERT_EQ(ToArgPack[2].getAsType(), ToCtx.FloatTy);
5648 }
5649}
5650
5651struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {};
5652
5653TEST_P(ASTImporterLookupTableTest, OneDecl) {
5654 auto *ToTU = getToTuDecl(ToSrcCode: "int a;", ToLang: Lang_CXX03);
5655 auto *D = FirstDeclMatcher<VarDecl>().match(D: ToTU, AMatcher: varDecl(hasName(Name: "a")));
5656 ASTImporterLookupTable LT(*ToTU);
5657 auto Res = LT.lookup(DC: ToTU, Name: D->getDeclName());
5658 ASSERT_EQ(Res.size(), 1u);
5659 EXPECT_EQ(*Res.begin(), D);
5660}
5661
5662static Decl *findInDeclListOfDC(DeclContext *DC, DeclarationName Name) {
5663 for (Decl *D : DC->decls()) {
5664 if (auto *ND = dyn_cast<NamedDecl>(Val: D))
5665 if (ND->getDeclName() == Name)
5666 return ND;
5667 }
5668 return nullptr;
5669}
5670
5671TEST_P(ASTImporterLookupTableTest,
5672 FriendWhichIsnotFoundByNormalLookupShouldBeFoundByImporterSpecificLookup) {
5673 auto *Code = R"(
5674 template <class T>
5675 struct X {
5676 friend void foo(){}
5677 };
5678 )";
5679 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX03);
5680 auto *X = FirstDeclMatcher<ClassTemplateDecl>().match(
5681 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
5682 auto *Foo = FirstDeclMatcher<FunctionDecl>().match(
5683 D: ToTU, AMatcher: functionDecl(hasName(Name: "foo")));
5684 DeclContext *FooDC = Foo->getDeclContext();
5685 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
5686 ASSERT_EQ(cast<Decl>(FooLexicalDC), X->getTemplatedDecl());
5687 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
5688 DeclarationName FooName = Foo->getDeclName();
5689
5690 // Cannot find in the LookupTable of its DC (TUDecl)
5691 SmallVector<NamedDecl *, 2> FoundDecls;
5692 FooDC->getRedeclContext()->localUncachedLookup(Name: FooName, Results&: FoundDecls);
5693 EXPECT_EQ(FoundDecls.size(), 0u);
5694
5695 // Cannot find in the LookupTable of its LexicalDC (X)
5696 FooLexicalDC->getRedeclContext()->localUncachedLookup(Name: FooName, Results&: FoundDecls);
5697 EXPECT_EQ(FoundDecls.size(), 0u);
5698
5699 // Can't find in the list of Decls of the DC.
5700 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
5701
5702 // Can't find in the list of Decls of the LexicalDC
5703 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), nullptr);
5704
5705 // ASTImporter specific lookup finds it.
5706 ASTImporterLookupTable LT(*ToTU);
5707 auto Res = LT.lookup(DC: FooDC, Name: Foo->getDeclName());
5708 ASSERT_EQ(Res.size(), 1u);
5709 EXPECT_EQ(*Res.begin(), Foo);
5710}
5711
5712TEST_P(ASTImporterLookupTableTest,
5713 FwdDeclStructShouldBeFoundByImporterSpecificLookup) {
5714 TranslationUnitDecl *ToTU =
5715 getToTuDecl(ToSrcCode: "struct A { struct Foo *p; };", ToLang: Lang_C99);
5716 auto *Foo =
5717 FirstDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: recordDecl(hasName(Name: "Foo")));
5718 auto *A =
5719 FirstDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: recordDecl(hasName(Name: "A")));
5720 DeclContext *FooDC = Foo->getDeclContext();
5721 DeclContext *FooLexicalDC = Foo->getLexicalDeclContext();
5722 ASSERT_EQ(cast<Decl>(FooLexicalDC), A);
5723 ASSERT_EQ(cast<Decl>(FooDC), ToTU);
5724 DeclarationName FooName = Foo->getDeclName();
5725
5726 // Cannot find in the LookupTable of its DC (TUDecl).
5727 SmallVector<NamedDecl *, 2> FoundDecls;
5728 FooDC->getRedeclContext()->localUncachedLookup(Name: FooName, Results&: FoundDecls);
5729 EXPECT_EQ(FoundDecls.size(), 0u);
5730
5731 // Finds via linear search of its LexicalDC (A).
5732 FooLexicalDC->getRedeclContext()->localUncachedLookup(Name: FooName, Results&: FoundDecls);
5733 EXPECT_EQ(FoundDecls.size(), 1u);
5734
5735 // Can't find in the list of Decls of the DC.
5736 EXPECT_EQ(findInDeclListOfDC(FooDC, FooName), nullptr);
5737
5738 // Can find in the list of Decls of the LexicalDC.
5739 EXPECT_EQ(findInDeclListOfDC(FooLexicalDC, FooName), Foo);
5740
5741 // ASTImporter specific lookup finds it.
5742 ASTImporterLookupTable LT(*ToTU);
5743 auto Res = LT.lookup(DC: FooDC, Name: Foo->getDeclName());
5744 ASSERT_EQ(Res.size(), 1u);
5745 EXPECT_EQ(*Res.begin(), Foo);
5746}
5747
5748TEST_P(ASTImporterLookupTableTest, LookupFindsNamesInDifferentDC) {
5749 TranslationUnitDecl *ToTU =
5750 getToTuDecl(ToSrcCode: "int V; struct A { int V; }; struct B { int V; };", ToLang: Lang_C99);
5751 DeclarationName VName = FirstDeclMatcher<VarDecl>()
5752 .match(D: ToTU, AMatcher: varDecl(hasName(Name: "V")))
5753 ->getDeclName();
5754 auto *A =
5755 FirstDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: recordDecl(hasName(Name: "A")));
5756 auto *B =
5757 FirstDeclMatcher<RecordDecl>().match(D: ToTU, AMatcher: recordDecl(hasName(Name: "B")));
5758
5759 ASTImporterLookupTable LT(*ToTU);
5760
5761 auto Res = LT.lookup(DC: cast<DeclContext>(Val: A), Name: VName);
5762 ASSERT_EQ(Res.size(), 1u);
5763 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5764 ToTU, fieldDecl(hasName("V"),
5765 hasParent(recordDecl(hasName("A"))))));
5766 Res = LT.lookup(DC: cast<DeclContext>(Val: B), Name: VName);
5767 ASSERT_EQ(Res.size(), 1u);
5768 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<FieldDecl>().match(
5769 ToTU, fieldDecl(hasName("V"),
5770 hasParent(recordDecl(hasName("B"))))));
5771 Res = LT.lookup(DC: ToTU, Name: VName);
5772 ASSERT_EQ(Res.size(), 1u);
5773 EXPECT_EQ(*Res.begin(), FirstDeclMatcher<VarDecl>().match(
5774 ToTU, varDecl(hasName("V"),
5775 hasParent(translationUnitDecl()))));
5776}
5777
5778TEST_P(ASTImporterLookupTableTest, LookupFindsOverloadedNames) {
5779 TranslationUnitDecl *ToTU = getToTuDecl(
5780 ToSrcCode: R"(
5781 void foo();
5782 void foo(int);
5783 void foo(int, int);
5784 )",
5785 ToLang: Lang_CXX03);
5786
5787 ASTImporterLookupTable LT(*ToTU);
5788 auto *F0 = FirstDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: functionDecl());
5789 auto *F2 = LastDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: functionDecl());
5790 DeclarationName Name = F0->getDeclName();
5791 auto Res = LT.lookup(DC: ToTU, Name);
5792 EXPECT_EQ(Res.size(), 3u);
5793 EXPECT_EQ(Res.count(F0), 1u);
5794 EXPECT_EQ(Res.count(F2), 1u);
5795}
5796
5797TEST_P(ASTImporterLookupTableTest,
5798 DifferentOperatorsShouldHaveDifferentResultSet) {
5799 TranslationUnitDecl *ToTU = getToTuDecl(
5800 ToSrcCode: R"(
5801 struct X{};
5802 void operator+(X, X);
5803 void operator-(X, X);
5804 )",
5805 ToLang: Lang_CXX03);
5806
5807 ASTImporterLookupTable LT(*ToTU);
5808 auto *FPlus = FirstDeclMatcher<FunctionDecl>().match(
5809 D: ToTU, AMatcher: functionDecl(hasOverloadedOperatorName(Name: "+")));
5810 auto *FMinus = FirstDeclMatcher<FunctionDecl>().match(
5811 D: ToTU, AMatcher: functionDecl(hasOverloadedOperatorName(Name: "-")));
5812 DeclarationName NamePlus = FPlus->getDeclName();
5813 auto ResPlus = LT.lookup(DC: ToTU, Name: NamePlus);
5814 EXPECT_EQ(ResPlus.size(), 1u);
5815 EXPECT_EQ(ResPlus.count(FPlus), 1u);
5816 EXPECT_EQ(ResPlus.count(FMinus), 0u);
5817 DeclarationName NameMinus = FMinus->getDeclName();
5818 auto ResMinus = LT.lookup(DC: ToTU, Name: NameMinus);
5819 EXPECT_EQ(ResMinus.size(), 1u);
5820 EXPECT_EQ(ResMinus.count(FMinus), 1u);
5821 EXPECT_EQ(ResMinus.count(FPlus), 0u);
5822 EXPECT_NE(*ResMinus.begin(), *ResPlus.begin());
5823}
5824
5825TEST_P(ASTImporterLookupTableTest, LookupDeclNamesFromDifferentTUs) {
5826 TranslationUnitDecl *ToTU = getToTuDecl(
5827 ToSrcCode: R"(
5828 struct X {};
5829 void operator+(X, X);
5830 )",
5831 ToLang: Lang_CXX03);
5832 auto *ToPlus = FirstDeclMatcher<FunctionDecl>().match(
5833 D: ToTU, AMatcher: functionDecl(hasOverloadedOperatorName(Name: "+")));
5834
5835 Decl *FromTU = getTuDecl(
5836 SrcCode: R"(
5837 struct X {};
5838 void operator+(X, X);
5839 )",
5840 Lang: Lang_CXX03);
5841 auto *FromPlus = FirstDeclMatcher<FunctionDecl>().match(
5842 D: FromTU, AMatcher: functionDecl(hasOverloadedOperatorName(Name: "+")));
5843
5844 // FromPlus have a different TU, thus its DeclarationName is different too.
5845 ASSERT_NE(ToPlus->getDeclName(), FromPlus->getDeclName());
5846
5847 ASTImporterLookupTable LT(*ToTU);
5848 auto Res = LT.lookup(DC: ToTU, Name: ToPlus->getDeclName());
5849 ASSERT_EQ(Res.size(), 1u);
5850 EXPECT_EQ(*Res.begin(), ToPlus);
5851
5852 // FromPlus have a different TU, thus its DeclarationName is different too.
5853 Res = LT.lookup(DC: ToTU, Name: FromPlus->getDeclName());
5854 ASSERT_EQ(Res.size(), 0u);
5855}
5856
5857TEST_P(ASTImporterLookupTableTest,
5858 LookupFindsFwdFriendClassDeclWithElaboratedType) {
5859 TranslationUnitDecl *ToTU = getToTuDecl(
5860 ToSrcCode: R"(
5861 class Y { friend class F; };
5862 )",
5863 ToLang: Lang_CXX03);
5864
5865 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
5866 // So we must dig up the underlying CXXRecordDecl.
5867 ASTImporterLookupTable LT(*ToTU);
5868 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(D: ToTU, AMatcher: friendDecl());
5869 const RecordDecl *RD = getRecordDeclOfFriend(FD: FriendD);
5870 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(
5871 D: ToTU, AMatcher: cxxRecordDecl(hasName(Name: "Y")));
5872
5873 DeclarationName Name = RD->getDeclName();
5874 auto Res = LT.lookup(DC: ToTU, Name);
5875 EXPECT_EQ(Res.size(), 1u);
5876 EXPECT_EQ(*Res.begin(), RD);
5877
5878 Res = LT.lookup(DC: Y, Name);
5879 EXPECT_EQ(Res.size(), 0u);
5880}
5881
5882TEST_P(ASTImporterLookupTableTest,
5883 LookupFindsFwdFriendClassDeclWithUnelaboratedType) {
5884 TranslationUnitDecl *ToTU = getToTuDecl(
5885 ToSrcCode: R"(
5886 class F;
5887 class Y { friend F; };
5888 )",
5889 ToLang: Lang_CXX11);
5890
5891 // In this case, the CXXRecordDecl is hidden, the FriendDecl is not a parent.
5892 // So we must dig up the underlying CXXRecordDecl.
5893 ASTImporterLookupTable LT(*ToTU);
5894 auto *FriendD = FirstDeclMatcher<FriendDecl>().match(D: ToTU, AMatcher: friendDecl());
5895 const RecordDecl *RD = getRecordDeclOfFriend(FD: FriendD);
5896 auto *Y = FirstDeclMatcher<CXXRecordDecl>().match(D: ToTU, AMatcher: cxxRecordDecl(hasName(Name: "Y")));
5897
5898 DeclarationName Name = RD->getDeclName();
5899 auto Res = LT.lookup(DC: ToTU, Name);
5900 EXPECT_EQ(Res.size(), 1u);
5901 EXPECT_EQ(*Res.begin(), RD);
5902
5903 Res = LT.lookup(DC: Y, Name);
5904 EXPECT_EQ(Res.size(), 0u);
5905}
5906
5907TEST_P(ASTImporterLookupTableTest,
5908 LookupFindsFriendClassDeclWithTypeAliasDoesNotAssert) {
5909 TranslationUnitDecl *ToTU = getToTuDecl(
5910 ToSrcCode: R"(
5911 class F;
5912 using alias_of_f = F;
5913 class Y { friend alias_of_f; };
5914 )",
5915 ToLang: Lang_CXX11);
5916
5917 // ASTImporterLookupTable constructor handles using declarations correctly,
5918 // no assert is expected.
5919 ASTImporterLookupTable LT(*ToTU);
5920
5921 auto *Alias = FirstDeclMatcher<TypeAliasDecl>().match(
5922 D: ToTU, AMatcher: typeAliasDecl(hasName(Name: "alias_of_f")));
5923 DeclarationName Name = Alias->getDeclName();
5924 auto Res = LT.lookup(DC: ToTU, Name);
5925 EXPECT_EQ(Res.count(Alias), 1u);
5926}
5927
5928TEST_P(ASTImporterLookupTableTest,
5929 LookupFindsFriendClassDeclWithUsingTypeDoesNotAssert) {
5930 TranslationUnitDecl *ToTU = getToTuDecl(
5931 ToSrcCode: R"(
5932 namespace a {
5933 namespace b { class InnerClass; }
5934 using b::InnerClass;
5935 }
5936 class B {
5937 friend a::InnerClass;
5938 };
5939 )",
5940 ToLang: Lang_CXX11);
5941
5942 // ASTImporterLookupTable constructor handles friend with using-type without
5943 // asserts.
5944 ASTImporterLookupTable LT(*ToTU);
5945
5946 auto *Using = FirstDeclMatcher<UsingDecl>().match(
5947 D: ToTU, AMatcher: usingDecl(hasName(Name: "InnerClass")));
5948 DeclarationName Name = Using->getDeclName();
5949 auto Res = LT.lookup(DC: ToTU, Name);
5950 EXPECT_EQ(Res.size(), 0u);
5951 auto *NsA = FirstDeclMatcher<NamespaceDecl>().match(
5952 D: ToTU, AMatcher: namespaceDecl(hasName(Name: "a")));
5953 auto *RecordB = FirstDeclMatcher<CXXRecordDecl>().match(
5954 D: ToTU, AMatcher: cxxRecordDecl(hasName(Name: "B")));
5955 auto Res1 = LT.lookup(DC: NsA, Name);
5956 EXPECT_EQ(Res1.count(Using), 1u);
5957 auto Res2 = LT.lookup(DC: RecordB, Name);
5958 EXPECT_EQ(Res2.size(), 0u);
5959}
5960
5961TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendClassTemplateDecl) {
5962 TranslationUnitDecl *ToTU = getToTuDecl(
5963 ToSrcCode: R"(
5964 class Y { template <class T> friend class F; };
5965 )",
5966 ToLang: Lang_CXX03);
5967
5968 ASTImporterLookupTable LT(*ToTU);
5969 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5970 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "F")));
5971 DeclarationName Name = F->getDeclName();
5972 auto Res = LT.lookup(DC: ToTU, Name);
5973 EXPECT_EQ(Res.size(), 2u);
5974 EXPECT_EQ(Res.count(F), 1u);
5975 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5976}
5977
5978TEST_P(ASTImporterLookupTableTest, DependentFriendClass) {
5979 TranslationUnitDecl *ToTU = getToTuDecl(
5980 ToSrcCode: R"(
5981 template <typename T>
5982 class F;
5983
5984 template <typename T>
5985 class Y {
5986 friend class F<T>;
5987 };
5988 )",
5989 ToLang: Lang_CXX03);
5990
5991 ASTImporterLookupTable LT(*ToTU);
5992 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
5993 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "F")));
5994 DeclarationName Name = F->getDeclName();
5995 auto Res = LT.lookup(DC: ToTU, Name);
5996 EXPECT_EQ(Res.size(), 2u);
5997 EXPECT_EQ(Res.count(F), 1u);
5998 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
5999}
6000
6001TEST_P(ASTImporterLookupTableTest, FriendClassTemplateSpecialization) {
6002 TranslationUnitDecl *ToTU = getToTuDecl(
6003 ToSrcCode: R"(
6004 template <typename T>
6005 class F;
6006
6007 class Y {
6008 friend class F<int>;
6009 };
6010 )",
6011 ToLang: Lang_CXX03);
6012
6013 ASTImporterLookupTable LT(*ToTU);
6014 auto *F = FirstDeclMatcher<ClassTemplateDecl>().match(
6015 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "F")));
6016 DeclarationName Name = F->getDeclName();
6017 auto Res = LT.lookup(DC: ToTU, Name);
6018 ASSERT_EQ(Res.size(), 3u);
6019 EXPECT_EQ(Res.count(F), 1u);
6020 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
6021 EXPECT_EQ(Res.count(*F->spec_begin()), 1u);
6022}
6023
6024TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionDecl) {
6025 TranslationUnitDecl *ToTU = getToTuDecl(
6026 ToSrcCode: R"(
6027 class Y { friend void F(); };
6028 )",
6029 ToLang: Lang_CXX03);
6030
6031 ASTImporterLookupTable LT(*ToTU);
6032 auto *F =
6033 FirstDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: functionDecl(hasName(Name: "F")));
6034 DeclarationName Name = F->getDeclName();
6035 auto Res = LT.lookup(DC: ToTU, Name);
6036 EXPECT_EQ(Res.size(), 1u);
6037 EXPECT_EQ(*Res.begin(), F);
6038}
6039
6040TEST_P(ASTImporterLookupTableTest,
6041 LookupFindsDeclsInClassTemplateSpecialization) {
6042 TranslationUnitDecl *ToTU = getToTuDecl(
6043 ToSrcCode: R"(
6044 template <typename T>
6045 struct X {
6046 int F;
6047 };
6048 void foo() {
6049 X<char> xc;
6050 }
6051 )",
6052 ToLang: Lang_CXX03);
6053
6054 ASTImporterLookupTable LT(*ToTU);
6055
6056 auto *Template = FirstDeclMatcher<ClassTemplateDecl>().match(
6057 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
6058 auto *FieldInTemplate = FirstDeclMatcher<FieldDecl>().match(
6059 D: ToTU,
6060 AMatcher: fieldDecl(hasParent(cxxRecordDecl(hasParent(classTemplateDecl())))));
6061
6062 auto *Spec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
6063 D: ToTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
6064 FieldDecl *FieldInSpec = *Spec->field_begin();
6065 ASSERT_TRUE(FieldInSpec);
6066
6067 DeclarationName Name = FieldInSpec->getDeclName();
6068 auto TemplateDC = cast<DeclContext>(Val: Template->getTemplatedDecl());
6069
6070 SmallVector<NamedDecl *, 2> FoundDecls;
6071 TemplateDC->getRedeclContext()->localUncachedLookup(Name, Results&: FoundDecls);
6072 EXPECT_EQ(FoundDecls.size(), 1u);
6073 EXPECT_EQ(FoundDecls[0], FieldInTemplate);
6074
6075 auto Res = LT.lookup(DC: TemplateDC, Name);
6076 ASSERT_EQ(Res.size(), 1u);
6077 EXPECT_EQ(*Res.begin(), FieldInTemplate);
6078
6079 cast<DeclContext>(Val: Spec)->getRedeclContext()->localUncachedLookup(Name,
6080 Results&: FoundDecls);
6081 EXPECT_EQ(FoundDecls.size(), 1u);
6082 EXPECT_EQ(FoundDecls[0], FieldInSpec);
6083
6084 Res = LT.lookup(DC: cast<DeclContext>(Val: Spec), Name);
6085 ASSERT_EQ(Res.size(), 1u);
6086 EXPECT_EQ(*Res.begin(), FieldInSpec);
6087}
6088
6089TEST_P(ASTImporterLookupTableTest, LookupFindsFwdFriendFunctionTemplateDecl) {
6090 TranslationUnitDecl *ToTU = getToTuDecl(
6091 ToSrcCode: R"(
6092 class Y { template <class T> friend void F(); };
6093 )",
6094 ToLang: Lang_CXX03);
6095
6096 ASTImporterLookupTable LT(*ToTU);
6097 auto *F = FirstDeclMatcher<FunctionTemplateDecl>().match(
6098 D: ToTU, AMatcher: functionTemplateDecl(hasName(Name: "F")));
6099 DeclarationName Name = F->getDeclName();
6100 auto Res = LT.lookup(DC: ToTU, Name);
6101 EXPECT_EQ(Res.size(), 2u);
6102 EXPECT_EQ(Res.count(F), 1u);
6103 EXPECT_EQ(Res.count(F->getTemplatedDecl()), 1u);
6104}
6105
6106TEST_P(ASTImporterLookupTableTest, MultipleBefriendingClasses) {
6107 TranslationUnitDecl *ToTU = getToTuDecl(
6108 ToSrcCode: R"(
6109 struct X;
6110 struct A {
6111 friend struct X;
6112 };
6113 struct B {
6114 friend struct X;
6115 };
6116 )",
6117 ToLang: Lang_CXX03);
6118
6119 ASTImporterLookupTable LT(*ToTU);
6120 auto *X = FirstDeclMatcher<CXXRecordDecl>().match(
6121 D: ToTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
6122 auto *FriendD0 = FirstDeclMatcher<FriendDecl>().match(D: ToTU, AMatcher: friendDecl());
6123 auto *FriendD1 = LastDeclMatcher<FriendDecl>().match(D: ToTU, AMatcher: friendDecl());
6124 const RecordDecl *RD0 = getRecordDeclOfFriend(FD: FriendD0);
6125 const RecordDecl *RD1 = getRecordDeclOfFriend(FD: FriendD1);
6126 ASSERT_EQ(RD0, RD1);
6127 ASSERT_EQ(RD1, X);
6128
6129 DeclarationName Name = X->getDeclName();
6130 auto Res = LT.lookup(DC: ToTU, Name);
6131 EXPECT_EQ(Res.size(), 1u);
6132 EXPECT_EQ(*Res.begin(), X);
6133}
6134
6135TEST_P(ASTImporterLookupTableTest, EnumConstantDecl) {
6136 TranslationUnitDecl *ToTU = getToTuDecl(
6137 ToSrcCode: R"(
6138 enum E {
6139 A,
6140 B
6141 };
6142 )",
6143 ToLang: Lang_C99);
6144
6145 ASTImporterLookupTable LT(*ToTU);
6146 auto *E = FirstDeclMatcher<EnumDecl>().match(D: ToTU, AMatcher: enumDecl(hasName(Name: "E")));
6147 auto *A = FirstDeclMatcher<EnumConstantDecl>().match(
6148 D: ToTU, AMatcher: enumConstantDecl(hasName(Name: "A")));
6149
6150 DeclarationName Name = A->getDeclName();
6151 // Redecl context is the TU.
6152 ASSERT_EQ(E->getRedeclContext(), ToTU);
6153
6154 SmallVector<NamedDecl *, 2> FoundDecls;
6155 // Normal lookup finds in the DC.
6156 E->localUncachedLookup(Name, Results&: FoundDecls);
6157 EXPECT_EQ(FoundDecls.size(), 1u);
6158
6159 // Normal lookup finds in the Redecl context.
6160 ToTU->localUncachedLookup(Name, Results&: FoundDecls);
6161 EXPECT_EQ(FoundDecls.size(), 1u);
6162
6163 // Import specific lookup finds in the DC.
6164 auto Res = LT.lookup(DC: E, Name);
6165 ASSERT_EQ(Res.size(), 1u);
6166 EXPECT_EQ(*Res.begin(), A);
6167
6168 // Import specific lookup finds in the Redecl context.
6169 Res = LT.lookup(DC: ToTU, Name);
6170 ASSERT_EQ(Res.size(), 1u);
6171 EXPECT_EQ(*Res.begin(), A);
6172}
6173
6174TEST_P(ASTImporterLookupTableTest, LookupSearchesInActualNamespaceOnly) {
6175 TranslationUnitDecl *ToTU = getToTuDecl(
6176 ToSrcCode: R"(
6177 namespace N {
6178 int A;
6179 }
6180 namespace N {
6181 }
6182 )",
6183 ToLang: Lang_CXX03);
6184 auto *N1 = FirstDeclMatcher<NamespaceDecl>().match(
6185 D: ToTU, AMatcher: namespaceDecl(hasName(Name: "N")));
6186 auto *N2 =
6187 LastDeclMatcher<NamespaceDecl>().match(D: ToTU, AMatcher: namespaceDecl(hasName(Name: "N")));
6188 auto *A = FirstDeclMatcher<VarDecl>().match(D: ToTU, AMatcher: varDecl(hasName(Name: "A")));
6189 DeclarationName Name = A->getDeclName();
6190
6191 ASTImporterLookupTable LT(*ToTU);
6192 auto Res = LT.lookup(DC: N1, Name);
6193 ASSERT_EQ(Res.size(), 1u);
6194 EXPECT_EQ(*Res.begin(), A);
6195 EXPECT_TRUE(LT.lookup(N2, Name).empty());
6196}
6197
6198TEST_P(ASTImporterOptionSpecificTestBase,
6199 RedeclChainShouldBeCorrectAmongstNamespaces) {
6200 Decl *FromTU = getTuDecl(
6201 SrcCode: R"(
6202 namespace NS {
6203 struct X;
6204 struct Y {
6205 static const int I = 3;
6206 };
6207 }
6208 namespace NS {
6209 struct X { // <--- To be imported
6210 void method(int i = Y::I) {}
6211 int f;
6212 };
6213 }
6214 )",
6215 Lang: Lang_CXX03);
6216 auto *FromFwd = FirstDeclMatcher<CXXRecordDecl>().match(
6217 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X"), unless(isImplicit())));
6218 auto *FromDef = LastDeclMatcher<CXXRecordDecl>().match(
6219 D: FromTU,
6220 AMatcher: cxxRecordDecl(hasName(Name: "X"), isDefinition(), unless(isImplicit())));
6221 ASSERT_NE(FromFwd, FromDef);
6222 ASSERT_FALSE(FromFwd->isThisDeclarationADefinition());
6223 ASSERT_TRUE(FromDef->isThisDeclarationADefinition());
6224 ASSERT_EQ(FromFwd->getCanonicalDecl(), FromDef->getCanonicalDecl());
6225
6226 auto *ToDef = cast_or_null<CXXRecordDecl>(Val: Import(From: FromDef, Lang: Lang_CXX03));
6227 auto *ToFwd = cast_or_null<CXXRecordDecl>(Val: Import(From: FromFwd, Lang: Lang_CXX03));
6228 EXPECT_NE(ToFwd, ToDef);
6229 EXPECT_FALSE(ToFwd->isThisDeclarationADefinition());
6230 EXPECT_TRUE(ToDef->isThisDeclarationADefinition());
6231 EXPECT_EQ(ToFwd->getCanonicalDecl(), ToDef->getCanonicalDecl());
6232 auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
6233 // We expect no (ODR) warning during the import.
6234 EXPECT_EQ(0u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
6235}
6236
6237struct ImportFriendFunctionTemplates : ASTImporterOptionSpecificTestBase {};
6238
6239TEST_P(ImportFriendFunctionTemplates, LookupShouldFindPreviousFriend) {
6240 Decl *ToTU = getToTuDecl(
6241 ToSrcCode: R"(
6242 class X {
6243 template <typename T> friend void foo();
6244 };
6245 )",
6246 ToLang: Lang_CXX03);
6247 auto *Friend = FirstDeclMatcher<FunctionTemplateDecl>().match(
6248 D: ToTU, AMatcher: functionTemplateDecl(hasName(Name: "foo")));
6249
6250 Decl *FromTU = getTuDecl(
6251 SrcCode: R"(
6252 template <typename T> void foo();
6253 )",
6254 Lang: Lang_CXX03);
6255 auto *FromFoo = FirstDeclMatcher<FunctionTemplateDecl>().match(
6256 D: FromTU, AMatcher: functionTemplateDecl(hasName(Name: "foo")));
6257 auto *Imported = Import(From: FromFoo, Lang: Lang_CXX03);
6258
6259 EXPECT_EQ(Imported->getPreviousDecl(), Friend);
6260}
6261
6262TEST_P(ImportFriendFunctionTemplates, ImportFriendFunctionInsideClassTemplate) {
6263 Decl *From, *To;
6264 std::tie(args&: From, args&: To) = getImportedDecl(
6265 FromSrcCode: R"(
6266 template <typename T> struct X {
6267 template <typename U> friend void f();
6268 };
6269 )",
6270 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03, Identifier: "X");
6271
6272 auto *FromFriend = FirstDeclMatcher<FriendDecl>().match(D: From, AMatcher: friendDecl());
6273 auto *ToFriend = FirstDeclMatcher<FriendDecl>().match(D: To, AMatcher: friendDecl());
6274
6275 EXPECT_TRUE(FromFriend ==
6276 LastDeclMatcher<FriendDecl>().match(From, friendDecl()));
6277 EXPECT_TRUE(ToFriend ==
6278 LastDeclMatcher<FriendDecl>().match(To, friendDecl()));
6279
6280 auto *FromDecl = FromFriend->getFriendDecl();
6281 auto *FromDC = FromFriend->getDeclContext();
6282 auto *FromLexicalDC = FromFriend->getLexicalDeclContext();
6283
6284 EXPECT_TRUE(FromDC->containsDecl(FromFriend));
6285 EXPECT_FALSE(FromDC->containsDecl(FromDecl));
6286 EXPECT_TRUE(FromLexicalDC->containsDecl(FromFriend));
6287 EXPECT_FALSE(FromLexicalDC->containsDecl(FromDecl));
6288
6289 auto *ToDecl = ToFriend->getFriendDecl();
6290 auto *ToDC = ToFriend->getDeclContext();
6291 auto *ToLexicalDC = ToFriend->getLexicalDeclContext();
6292
6293 EXPECT_TRUE(ToDC->containsDecl(ToFriend));
6294 EXPECT_FALSE(ToDC->containsDecl(ToDecl));
6295 EXPECT_TRUE(ToLexicalDC->containsDecl(ToFriend));
6296 EXPECT_FALSE(ToLexicalDC->containsDecl(ToDecl));
6297}
6298
6299struct ASTImporterWithFakeErrors : ASTImporter {
6300 using ASTImporter::ASTImporter;
6301 bool returnWithErrorInTest() override { return true; }
6302};
6303
6304struct ErrorHandlingTest : ASTImporterOptionSpecificTestBase {
6305 ErrorHandlingTest() {
6306 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
6307 ASTContext &FromContext, FileManager &FromFileManager,
6308 bool MinimalImport,
6309 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
6310 return new ASTImporterWithFakeErrors(ToContext, ToFileManager,
6311 FromContext, FromFileManager,
6312 MinimalImport, SharedState);
6313 };
6314 }
6315 // In this test we purposely report an error (UnsupportedConstruct) when
6316 // importing the below stmt.
6317 static constexpr auto* ErroneousStmt = R"( asm(""); )";
6318};
6319
6320// Check a case when no new AST node is created in the AST before encountering
6321// the error.
6322TEST_P(ErrorHandlingTest, ErrorHappensBeforeCreatingANewNode) {
6323 TranslationUnitDecl *ToTU = getToTuDecl(
6324 ToSrcCode: R"(
6325 template <typename T>
6326 class X {};
6327 template <>
6328 class X<int> { int a; };
6329 )",
6330 ToLang: Lang_CXX03);
6331 TranslationUnitDecl *FromTU = getTuDecl(
6332 SrcCode: R"(
6333 template <typename T>
6334 class X {};
6335 template <>
6336 class X<int> { double b; };
6337 )",
6338 Lang: Lang_CXX03);
6339 auto *FromSpec = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
6340 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
6341 ClassTemplateSpecializationDecl *ImportedSpec = Import(From: FromSpec, Lang: Lang_CXX03);
6342 EXPECT_FALSE(ImportedSpec);
6343
6344 // The original Decl is kept, no new decl is created.
6345 EXPECT_EQ(DeclCounter<ClassTemplateSpecializationDecl>().match(
6346 ToTU, classTemplateSpecializationDecl(hasName("X"))),
6347 1u);
6348
6349 // But an error is set to the counterpart in the "from" context.
6350 ASTImporter *Importer = findFromTU(From: FromSpec)->Importer.get();
6351 std::optional<ASTImportError> OptErr =
6352 Importer->getImportDeclErrorIfAny(FromD: FromSpec);
6353 ASSERT_TRUE(OptErr);
6354 EXPECT_EQ(OptErr->Error, ASTImportError::NameConflict);
6355}
6356
6357// Check a case when a new AST node is created but not linked to the AST before
6358// encountering the error.
6359TEST_P(ErrorHandlingTest,
6360 ErrorHappensAfterCreatingTheNodeButBeforeLinkingThatToTheAST) {
6361 TranslationUnitDecl *FromTU = getTuDecl(
6362 SrcCode: std::string("void foo() { ") + ErroneousStmt + " }", Lang: Lang_CXX03);
6363 auto *FromFoo = FirstDeclMatcher<FunctionDecl>().match(
6364 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo")));
6365
6366 FunctionDecl *ImportedFoo = Import(From: FromFoo, Lang: Lang_CXX03);
6367 EXPECT_FALSE(ImportedFoo);
6368
6369 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
6370 // Created, but not linked.
6371 EXPECT_EQ(
6372 DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("foo"))),
6373 0u);
6374
6375 ASTImporter *Importer = findFromTU(From: FromFoo)->Importer.get();
6376 std::optional<ASTImportError> OptErr =
6377 Importer->getImportDeclErrorIfAny(FromD: FromFoo);
6378 ASSERT_TRUE(OptErr);
6379 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6380}
6381
6382// Check a case when a new AST node is created and linked to the AST before
6383// encountering the error. The error is set for the counterpart of the nodes in
6384// the "from" context.
6385TEST_P(ErrorHandlingTest, ErrorHappensAfterNodeIsCreatedAndLinked) {
6386 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: std::string(R"(
6387 void f();
6388 void f() { )") + ErroneousStmt + R"( }
6389 )",
6390 Lang: Lang_CXX03);
6391 auto *FromProto = FirstDeclMatcher<FunctionDecl>().match(
6392 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
6393 auto *FromDef =
6394 LastDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
6395 FunctionDecl *ImportedProto = Import(From: FromProto, Lang: Lang_CXX03);
6396 EXPECT_FALSE(ImportedProto); // Could not import.
6397 // However, we created two nodes in the AST. 1) the fwd decl 2) the
6398 // definition. The definition is not added to its DC, but the fwd decl is
6399 // there.
6400 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
6401 EXPECT_EQ(DeclCounter<FunctionDecl>().match(ToTU, functionDecl(hasName("f"))),
6402 1u);
6403 // Match the fwd decl.
6404 auto *ToProto =
6405 FirstDeclMatcher<FunctionDecl>().match(D: ToTU, AMatcher: functionDecl(hasName(Name: "f")));
6406 EXPECT_TRUE(ToProto);
6407 // An error is set to the counterpart in the "from" context both for the fwd
6408 // decl and the definition.
6409 ASTImporter *Importer = findFromTU(From: FromProto)->Importer.get();
6410 std::optional<ASTImportError> OptErr =
6411 Importer->getImportDeclErrorIfAny(FromD: FromProto);
6412 ASSERT_TRUE(OptErr);
6413 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6414 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromDef);
6415 ASSERT_TRUE(OptErr);
6416 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6417}
6418
6419// An error should be set for a class if we cannot import one member.
6420TEST_P(ErrorHandlingTest, ErrorIsPropagatedFromMemberToClass) {
6421 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: std::string(R"(
6422 class X {
6423 void f() { )") + ErroneousStmt + R"( } // This member has the error
6424 // during import.
6425 void ok(); // The error should not prevent importing this.
6426 }; // An error will be set for X too.
6427 )",
6428 Lang: Lang_CXX03);
6429 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
6430 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
6431 CXXRecordDecl *ImportedX = Import(From: FromX, Lang: Lang_CXX03);
6432
6433 // An error is set for X.
6434 EXPECT_FALSE(ImportedX);
6435 ASTImporter *Importer = findFromTU(From: FromX)->Importer.get();
6436 std::optional<ASTImportError> OptErr =
6437 Importer->getImportDeclErrorIfAny(FromD: FromX);
6438 ASSERT_TRUE(OptErr);
6439 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6440
6441 // An error is set for f().
6442 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
6443 D: FromTU, AMatcher: cxxMethodDecl(hasName(Name: "f")));
6444 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromF);
6445 ASSERT_TRUE(OptErr);
6446 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6447 // And any subsequent import should fail.
6448 CXXMethodDecl *ImportedF = Import(From: FromF, Lang: Lang_CXX03);
6449 EXPECT_FALSE(ImportedF);
6450
6451 // There is an error set for the other member too.
6452 auto *FromOK = FirstDeclMatcher<CXXMethodDecl>().match(
6453 D: FromTU, AMatcher: cxxMethodDecl(hasName(Name: "ok")));
6454 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromOK);
6455 EXPECT_TRUE(OptErr);
6456 // Cannot import the other member.
6457 CXXMethodDecl *ImportedOK = Import(From: FromOK, Lang: Lang_CXX03);
6458 EXPECT_FALSE(ImportedOK);
6459}
6460
6461// Check that an error propagates to the dependent AST nodes.
6462// In the below code it means that an error in X should propagate to A.
6463// And even to F since the containing A is erroneous.
6464// And to all AST nodes which we visit during the import process which finally
6465// ends up in a failure (in the error() function).
6466TEST_P(ErrorHandlingTest, ErrorPropagatesThroughImportCycles) {
6467 Decl *FromTU = getTuDecl(SrcCode: std::string(R"(
6468 namespace NS {
6469 class A {
6470 template <int I> class F {};
6471 class X {
6472 template <int I> friend class F;
6473 void error() { )") +
6474 ErroneousStmt + R"( }
6475 };
6476 };
6477
6478 class B {};
6479 } // NS
6480 )",
6481 Lang: Lang_CXX03, FileName: "input0.cc");
6482
6483 auto *FromFRD = FirstDeclMatcher<CXXRecordDecl>().match(
6484 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "F"), isDefinition()));
6485 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
6486 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A"), isDefinition()));
6487 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(
6488 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "B"), isDefinition()));
6489 auto *FromNS = FirstDeclMatcher<NamespaceDecl>().match(
6490 D: FromTU, AMatcher: namespaceDecl(hasName(Name: "NS")));
6491
6492 // Start by importing the templated CXXRecordDecl of F.
6493 // Import fails for that.
6494 EXPECT_FALSE(Import(FromFRD, Lang_CXX03));
6495 // Import fails for A.
6496 EXPECT_FALSE(Import(FromA, Lang_CXX03));
6497 // But we should be able to import the independent B.
6498 EXPECT_TRUE(Import(FromB, Lang_CXX03));
6499 // And the namespace.
6500 EXPECT_TRUE(Import(FromNS, Lang_CXX03));
6501
6502 // An error is set to the templated CXXRecordDecl of F.
6503 ASTImporter *Importer = findFromTU(From: FromFRD)->Importer.get();
6504 std::optional<ASTImportError> OptErr =
6505 Importer->getImportDeclErrorIfAny(FromD: FromFRD);
6506 EXPECT_TRUE(OptErr);
6507
6508 // An error is set to A.
6509 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromA);
6510 EXPECT_TRUE(OptErr);
6511
6512 // There is no error set to B.
6513 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromB);
6514 EXPECT_FALSE(OptErr);
6515
6516 // There is no error set to NS.
6517 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromNS);
6518 EXPECT_FALSE(OptErr);
6519
6520 // Check some of those decls whose ancestor is X, they all should have an
6521 // error set if we visited them during an import process which finally failed.
6522 // These decls are part of a cycle in an ImportPath.
6523 // There would not be any error set for these decls if we hadn't follow the
6524 // ImportPaths and the cycles.
6525 OptErr = Importer->getImportDeclErrorIfAny(
6526 FromD: FirstDeclMatcher<ClassTemplateDecl>().match(
6527 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "F"))));
6528 // An error is set to the 'F' ClassTemplateDecl.
6529 EXPECT_TRUE(OptErr);
6530 // An error is set to the FriendDecl.
6531 OptErr = Importer->getImportDeclErrorIfAny(
6532 FromD: FirstDeclMatcher<FriendDecl>().match(
6533 D: FromTU, AMatcher: friendDecl()));
6534 EXPECT_TRUE(OptErr);
6535 // An error is set to the implicit class of A.
6536 OptErr =
6537 Importer->getImportDeclErrorIfAny(FromD: FirstDeclMatcher<CXXRecordDecl>().match(
6538 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A"), isImplicit())));
6539 EXPECT_TRUE(OptErr);
6540 // An error is set to the implicit class of X.
6541 OptErr =
6542 Importer->getImportDeclErrorIfAny(FromD: FirstDeclMatcher<CXXRecordDecl>().match(
6543 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X"), isImplicit())));
6544 EXPECT_TRUE(OptErr);
6545}
6546
6547TEST_P(ErrorHandlingTest, ErrorIsNotPropagatedFromMemberToNamespace) {
6548 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: std::string(R"(
6549 namespace X {
6550 void f() { )") + ErroneousStmt + R"( } // This member has the error
6551 // during import.
6552 void ok(); // The error should not prevent importing this.
6553 }; // An error will be set for X too.
6554 )",
6555 Lang: Lang_CXX03);
6556 auto *FromX = FirstDeclMatcher<NamespaceDecl>().match(
6557 D: FromTU, AMatcher: namespaceDecl(hasName(Name: "X")));
6558 NamespaceDecl *ImportedX = Import(From: FromX, Lang: Lang_CXX03);
6559
6560 // There is no error set for X.
6561 EXPECT_TRUE(ImportedX);
6562 ASTImporter *Importer = findFromTU(From: FromX)->Importer.get();
6563 std::optional<ASTImportError> OptErr =
6564 Importer->getImportDeclErrorIfAny(FromD: FromX);
6565 ASSERT_FALSE(OptErr);
6566
6567 // An error is set for f().
6568 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
6569 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
6570 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromF);
6571 ASSERT_TRUE(OptErr);
6572 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6573 // And any subsequent import should fail.
6574 FunctionDecl *ImportedF = Import(From: FromF, Lang: Lang_CXX03);
6575 EXPECT_FALSE(ImportedF);
6576
6577 // There is no error set for ok().
6578 auto *FromOK = FirstDeclMatcher<FunctionDecl>().match(
6579 D: FromTU, AMatcher: functionDecl(hasName(Name: "ok")));
6580 OptErr = Importer->getImportDeclErrorIfAny(FromD: FromOK);
6581 EXPECT_FALSE(OptErr);
6582 // And we should be able to import.
6583 FunctionDecl *ImportedOK = Import(From: FromOK, Lang: Lang_CXX03);
6584 EXPECT_TRUE(ImportedOK);
6585}
6586
6587TEST_P(ErrorHandlingTest, ODRViolationWithinTypedefDecls) {
6588 // Importing `z` should fail - instead of crashing - due to an ODR violation.
6589 // The `bar::e` typedef sets it's DeclContext after the import is done.
6590 // However, if the importation fails, it will be left as a nullptr.
6591 // During the cleanup of the failed import, we should check whether the
6592 // DeclContext is null or not - instead of dereferencing that unconditionally.
6593 constexpr auto ToTUCode = R"(
6594 namespace X {
6595 struct bar {
6596 int odr_violation;
6597 };
6598 })";
6599 constexpr auto FromTUCode = R"(
6600 namespace X {
6601 enum b {};
6602 struct bar {
6603 typedef b e;
6604 static e d;
6605 };
6606 }
6607 int z = X::bar::d;
6608 )";
6609 Decl *ToTU = getToTuDecl(ToSrcCode: ToTUCode, ToLang: Lang_CXX11);
6610 static_cast<void>(ToTU);
6611 Decl *FromTU = getTuDecl(SrcCode: FromTUCode, Lang: Lang_CXX11);
6612 auto *FromZ =
6613 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "z")));
6614 ASSERT_TRUE(FromZ);
6615 ASSERT_TRUE(FromZ->hasInit());
6616
6617 auto *ImportedZ = Import(From: FromZ, Lang: Lang_CXX11);
6618 EXPECT_FALSE(ImportedZ);
6619}
6620
6621// An error should be set for a class if it had a previous import with an error
6622// from another TU.
6623TEST_P(ErrorHandlingTest,
6624 ImportedDeclWithErrorShouldFailTheImportOfDeclWhichMapToIt) {
6625 // We already have a fwd decl.
6626 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: "class X;", ToLang: Lang_CXX03);
6627 // Then we import a definition.
6628 {
6629 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: std::string(R"(
6630 class X {
6631 void f() { )") + ErroneousStmt + R"( }
6632 void ok();
6633 };
6634 )",
6635 Lang: Lang_CXX03);
6636 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
6637 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
6638 CXXRecordDecl *ImportedX = Import(From: FromX, Lang: Lang_CXX03);
6639
6640 // An error is set for X ...
6641 EXPECT_FALSE(ImportedX);
6642 ASTImporter *Importer = findFromTU(From: FromX)->Importer.get();
6643 std::optional<ASTImportError> OptErr =
6644 Importer->getImportDeclErrorIfAny(FromD: FromX);
6645 ASSERT_TRUE(OptErr);
6646 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6647 }
6648 // ... but the node had been created.
6649 auto *ToXDef = FirstDeclMatcher<CXXRecordDecl>().match(
6650 D: ToTU, AMatcher: cxxRecordDecl(hasName(Name: "X"), isDefinition()));
6651 // An error is set for "ToXDef" in the shared state.
6652 std::optional<ASTImportError> OptErr =
6653 SharedStatePtr->getImportDeclErrorIfAny(ToD: ToXDef);
6654 ASSERT_TRUE(OptErr);
6655 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6656
6657 auto *ToXFwd = FirstDeclMatcher<CXXRecordDecl>().match(
6658 D: ToTU, AMatcher: cxxRecordDecl(hasName(Name: "X"), unless(isDefinition())));
6659 // An error is NOT set for the fwd Decl of X in the shared state.
6660 OptErr = SharedStatePtr->getImportDeclErrorIfAny(ToD: ToXFwd);
6661 ASSERT_FALSE(OptErr);
6662
6663 // Try to import X again but from another TU.
6664 {
6665 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: std::string(R"(
6666 class X {
6667 void f() { )") + ErroneousStmt + R"( }
6668 void ok();
6669 };
6670 )",
6671 Lang: Lang_CXX03, FileName: "input1.cc");
6672
6673 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
6674 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
6675 CXXRecordDecl *ImportedX = Import(From: FromX, Lang: Lang_CXX03);
6676
6677 // If we did not save the errors for the "to" context then the below checks
6678 // would fail, because the lookup finds the fwd Decl of the existing
6679 // definition in the "to" context. We can reach the existing definition via
6680 // the found fwd Decl. That existing definition is structurally equivalent
6681 // (we check only the fields) with this one we want to import, so we return
6682 // with the existing definition, which is erroneous (one method is missing).
6683
6684 // The import should fail.
6685 EXPECT_FALSE(ImportedX);
6686 ASTImporter *Importer = findFromTU(From: FromX)->Importer.get();
6687 std::optional<ASTImportError> OptErr =
6688 Importer->getImportDeclErrorIfAny(FromD: FromX);
6689 // And an error is set for this new X in the "from" ctx.
6690 ASSERT_TRUE(OptErr);
6691 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6692 }
6693}
6694
6695TEST_P(ErrorHandlingTest, ImportOfOverriddenMethods) {
6696 auto MatchFooA =
6697 functionDecl(hasName(Name: "foo"), hasAncestor(cxxRecordDecl(hasName(Name: "A"))));
6698 auto MatchFooB =
6699 functionDecl(hasName(Name: "foo"), hasAncestor(cxxRecordDecl(hasName(Name: "B"))));
6700 auto MatchFooC =
6701 functionDecl(hasName(Name: "foo"), hasAncestor(cxxRecordDecl(hasName(Name: "C"))));
6702
6703 // Provoke import of a method that has overridden methods with import error.
6704 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: std::string(R"(
6705 struct C;
6706 struct A {
6707 virtual void foo();
6708 void f1(C *);
6709 };
6710 void A::foo() {
6711 )") + ErroneousStmt + R"(
6712 }
6713 struct B : public A {
6714 void foo() override;
6715 };
6716 struct C : public B {
6717 void foo() override;
6718 };
6719 )",
6720 Lang: Lang_CXX11);
6721 auto *FromFooA = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: MatchFooA);
6722 auto *FromFooB = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: MatchFooB);
6723 auto *FromFooC = FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: MatchFooC);
6724
6725 EXPECT_FALSE(Import(FromFooA, Lang_CXX11));
6726 ASTImporter *Importer = findFromTU(From: FromFooA)->Importer.get();
6727 auto CheckError = [&Importer](Decl *FromD) {
6728 std::optional<ASTImportError> OptErr =
6729 Importer->getImportDeclErrorIfAny(FromD);
6730 ASSERT_TRUE(OptErr);
6731 EXPECT_EQ(OptErr->Error, ASTImportError::UnsupportedConstruct);
6732 };
6733 CheckError(FromFooA);
6734 EXPECT_FALSE(Import(FromFooB, Lang_CXX11));
6735 CheckError(FromFooB);
6736 EXPECT_FALSE(Import(FromFooC, Lang_CXX11));
6737 CheckError(FromFooC);
6738}
6739
6740TEST_P(ErrorHandlingTest, ODRViolationWithinParmVarDecls) {
6741 // Importing of 'f' and parameter 'P' should cause an ODR error.
6742 // The error happens after the ParmVarDecl for 'P' was already created.
6743 // This is a special case because the ParmVarDecl has a temporary DeclContext.
6744 // Expected is no crash at error handling of ASTImporter.
6745 constexpr auto ToTUCode = R"(
6746 struct X {
6747 char A;
6748 };
6749 )";
6750 constexpr auto FromTUCode = R"(
6751 struct X {
6752 enum Y { Z };
6753 };
6754 void f(int P = X::Z);
6755 )";
6756 Decl *ToTU = getToTuDecl(ToSrcCode: ToTUCode, ToLang: Lang_CXX11);
6757 static_cast<void>(ToTU);
6758 Decl *FromTU = getTuDecl(SrcCode: FromTUCode, Lang: Lang_CXX11);
6759 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
6760 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
6761 ASSERT_TRUE(FromF);
6762
6763 auto *ImportedF = Import(From: FromF, Lang: Lang_CXX11);
6764 EXPECT_FALSE(ImportedF);
6765}
6766
6767TEST_P(ErrorHandlingTest, DoNotInheritErrorFromNonDependentChild) {
6768 // Declarations should not inherit an import error from a child object
6769 // if the declaration has no direct dependence to such a child.
6770 // For example a namespace should not get import error if one of the
6771 // declarations inside it fails to import.
6772 // There was a special case in error handling (when "import path circles" are
6773 // encountered) when this property was not held. This case is provoked by the
6774 // following code.
6775 constexpr auto ToTUCode = R"(
6776 namespace ns {
6777 struct Err {
6778 char A;
6779 };
6780 }
6781 )";
6782 constexpr auto FromTUCode = R"(
6783 namespace ns {
6784 struct A {
6785 using U = struct Err;
6786 };
6787 }
6788 namespace ns {
6789 struct Err {}; // ODR violation
6790 void f(A) {}
6791 }
6792 )";
6793
6794 Decl *ToTU = getToTuDecl(ToSrcCode: ToTUCode, ToLang: Lang_CXX11);
6795 static_cast<void>(ToTU);
6796 Decl *FromTU = getTuDecl(SrcCode: FromTUCode, Lang: Lang_CXX11);
6797 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
6798 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A"), hasDefinition()));
6799 ASSERT_TRUE(FromA);
6800 auto *ImportedA = Import(From: FromA, Lang: Lang_CXX11);
6801 // 'A' can not be imported: ODR error at 'Err'
6802 EXPECT_FALSE(ImportedA);
6803 // When import of 'A' failed there was a "saved import path circle" that
6804 // contained namespace 'ns' (A - U - Err - ns - f - A). This should not mean
6805 // that every object in this path fails to import.
6806
6807 Decl *FromNS = FirstDeclMatcher<NamespaceDecl>().match(
6808 D: FromTU, AMatcher: namespaceDecl(hasName(Name: "ns")));
6809 EXPECT_TRUE(FromNS);
6810 auto *ImportedNS = Import(From: FromNS, ToLang: Lang_CXX11);
6811 EXPECT_TRUE(ImportedNS);
6812}
6813
6814TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) {
6815 Decl *FromTU = getTuDecl(
6816 SrcCode: R"(
6817 void f() {
6818 auto L = [](){};
6819 }
6820 )",
6821 Lang: Lang_CXX11, FileName: "input0.cc");
6822 auto Pattern = lambdaExpr();
6823 CXXRecordDecl *FromL =
6824 FirstDeclMatcher<LambdaExpr>().match(D: FromTU, AMatcher: Pattern)->getLambdaClass();
6825
6826 auto ToL = Import(From: FromL, Lang: Lang_CXX11);
6827 unsigned ToLSize = std::distance(first: ToL->decls().begin(), last: ToL->decls().end());
6828 unsigned FromLSize =
6829 std::distance(first: FromL->decls().begin(), last: FromL->decls().end());
6830 EXPECT_NE(ToLSize, 0u);
6831 EXPECT_EQ(ToLSize, FromLSize);
6832 EXPECT_FALSE(FromL->isDependentLambda());
6833}
6834
6835TEST_P(ASTImporterOptionSpecificTestBase,
6836 ReturnTypeDeclaredInsideOfCXX11LambdaWithoutTrailingReturn) {
6837 Decl *From, *To;
6838 std::tie(args&: From, args&: To) = getImportedDecl(
6839 FromSrcCode: R"(
6840 void foo() {
6841 (void) []() {
6842 struct X {};
6843 return X();
6844 };
6845 }
6846 )",
6847 FromLang: Lang_CXX11, ToSrcCode: "", ToLang: Lang_CXX11, Identifier: "foo"); // c++11 only
6848 auto *ToLambda = FirstDeclMatcher<LambdaExpr>().match(D: To, AMatcher: lambdaExpr());
6849 EXPECT_TRUE(ToLambda);
6850}
6851
6852TEST_P(ASTImporterOptionSpecificTestBase,
6853 ReturnTypeDeclaredInsideOfCXX11LambdaWithTrailingReturn) {
6854 Decl *From, *To;
6855 std::tie(args&: From, args&: To) = getImportedDecl(
6856 FromSrcCode: R"(
6857 void foo() {
6858 (void) [] {
6859 struct X {};
6860 return X();
6861 };
6862 }
6863 )",
6864 FromLang: Lang_CXX11, ToSrcCode: "", ToLang: Lang_CXX11, Identifier: "foo"); // c++11 only
6865 auto *ToLambda = FirstDeclMatcher<LambdaExpr>().match(D: To, AMatcher: lambdaExpr());
6866 EXPECT_TRUE(ToLambda);
6867}
6868
6869TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
6870 Decl *FromTU = getTuDecl(
6871 SrcCode: R"(
6872 template <typename F>
6873 void f(F L = [](){}) {}
6874 )",
6875 Lang: Lang_CXX11, FileName: "input0.cc");
6876 auto Pattern = lambdaExpr();
6877 CXXRecordDecl *FromL =
6878 FirstDeclMatcher<LambdaExpr>().match(D: FromTU, AMatcher: Pattern)->getLambdaClass();
6879
6880 auto ToL = Import(From: FromL, Lang: Lang_CXX11);
6881 unsigned ToLSize = std::distance(first: ToL->decls().begin(), last: ToL->decls().end());
6882 unsigned FromLSize =
6883 std::distance(first: FromL->decls().begin(), last: FromL->decls().end());
6884 EXPECT_NE(ToLSize, 0u);
6885 EXPECT_EQ(ToLSize, FromLSize);
6886 EXPECT_TRUE(FromL->isDependentLambda());
6887}
6888
6889TEST_P(ASTImporterOptionSpecificTestBase, LambdaInGlobalScope) {
6890 Decl *FromTU = getTuDecl(
6891 SrcCode: R"(
6892 auto l1 = [](unsigned lp) { return 1; };
6893 auto l2 = [](int lp) { return 2; };
6894 int f(int p) {
6895 return l1(p) + l2(p);
6896 }
6897 )",
6898 Lang: Lang_CXX11, FileName: "input0.cc");
6899 FunctionDecl *FromF = FirstDeclMatcher<FunctionDecl>().match(
6900 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
6901 FunctionDecl *ToF = Import(From: FromF, Lang: Lang_CXX11);
6902 EXPECT_TRUE(ToF);
6903}
6904
6905TEST_P(ASTImporterOptionSpecificTestBase,
6906 ImportExistingFriendClassTemplateDef) {
6907 auto Code =
6908 R"(
6909 template <class T1, class T2>
6910 struct Base {
6911 template <class U1, class U2>
6912 friend struct Class;
6913 };
6914 template <class T1, class T2>
6915 struct Class { };
6916 )";
6917
6918 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_CXX03);
6919 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX03, FileName: "input.cc");
6920
6921 auto *ToClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
6922 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "Class")));
6923 auto *ToClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
6924 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "Class")));
6925 ASSERT_FALSE(ToClassProto->isThisDeclarationADefinition());
6926 ASSERT_TRUE(ToClassDef->isThisDeclarationADefinition());
6927 // Previous friend decl is not linked to it!
6928 ASSERT_FALSE(ToClassDef->getPreviousDecl());
6929 ASSERT_EQ(ToClassDef->getMostRecentDecl(), ToClassDef);
6930 ASSERT_EQ(ToClassProto->getMostRecentDecl(), ToClassProto);
6931
6932 auto *FromClassProto = FirstDeclMatcher<ClassTemplateDecl>().match(
6933 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "Class")));
6934 auto *FromClassDef = LastDeclMatcher<ClassTemplateDecl>().match(
6935 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "Class")));
6936 ASSERT_FALSE(FromClassProto->isThisDeclarationADefinition());
6937 ASSERT_TRUE(FromClassDef->isThisDeclarationADefinition());
6938 ASSERT_FALSE(FromClassDef->getPreviousDecl());
6939 ASSERT_EQ(FromClassDef->getMostRecentDecl(), FromClassDef);
6940 ASSERT_EQ(FromClassProto->getMostRecentDecl(), FromClassProto);
6941
6942 auto *ImportedDef = Import(From: FromClassDef, Lang: Lang_CXX03);
6943 // At import we should find the definition for 'Class' even if the
6944 // prototype (inside 'friend') for it comes first in the AST and is not
6945 // linked to the definition.
6946 EXPECT_EQ(ImportedDef, ToClassDef);
6947}
6948
6949struct LLDBLookupTest : ASTImporterOptionSpecificTestBase {
6950 LLDBLookupTest() {
6951 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
6952 ASTContext &FromContext, FileManager &FromFileManager,
6953 bool MinimalImport,
6954 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
6955 return new ASTImporter(ToContext, ToFileManager, FromContext,
6956 FromFileManager, MinimalImport,
6957 // We use the regular lookup.
6958 /*SharedState=*/nullptr);
6959 };
6960 }
6961};
6962
6963TEST_P(LLDBLookupTest, ImporterShouldFindInTransparentContext) {
6964 TranslationUnitDecl *ToTU = getToTuDecl(
6965 ToSrcCode: R"(
6966 extern "C" {
6967 class X{};
6968 };
6969 )",
6970 ToLang: Lang_CXX03);
6971 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(
6972 D: ToTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
6973
6974 // Set up a stub external storage.
6975 ToTU->setHasExternalLexicalStorage(true);
6976 // Set up DeclContextBits.HasLazyExternalLexicalLookups to true.
6977 ToTU->setMustBuildLookupTable();
6978 struct TestExternalASTSource : ExternalASTSource {};
6979 ToTU->getASTContext().setExternalSource(new TestExternalASTSource());
6980
6981 Decl *FromTU = getTuDecl(
6982 SrcCode: R"(
6983 class X;
6984 )",
6985 Lang: Lang_CXX03);
6986 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
6987 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
6988 auto *ImportedX = Import(From: FromX, Lang: Lang_CXX03);
6989 // The lookup must find the existing class definition in the LinkageSpecDecl.
6990 // Then the importer renders the existing and the new decl into one chain.
6991 EXPECT_EQ(ImportedX->getCanonicalDecl(), ToX->getCanonicalDecl());
6992}
6993
6994struct SVEBuiltins : ASTImporterOptionSpecificTestBase {};
6995
6996TEST_P(SVEBuiltins, ImportTypes) {
6997 static const char *const TypeNames[] = {
6998 "__SVInt8_t", "__SVInt16_t", "__SVInt32_t", "__SVInt64_t",
6999 "__SVUint8_t", "__SVUint16_t", "__SVUint32_t", "__SVUint64_t",
7000 "__SVFloat16_t", "__SVBfloat16_t", "__SVFloat32_t", "__SVFloat64_t",
7001 "__SVBool_t"};
7002
7003 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: "", ToLang: Lang_CXX03);
7004 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: "", Lang: Lang_CXX03, FileName: "input.cc");
7005 for (auto *TypeName : TypeNames) {
7006 auto *ToTypedef = FirstDeclMatcher<TypedefDecl>().match(
7007 D: ToTU, AMatcher: typedefDecl(hasName(Name: TypeName)));
7008 QualType ToType = ToTypedef->getUnderlyingType();
7009
7010 auto *FromTypedef = FirstDeclMatcher<TypedefDecl>().match(
7011 D: FromTU, AMatcher: typedefDecl(hasName(Name: TypeName)));
7012 QualType FromType = FromTypedef->getUnderlyingType();
7013
7014 QualType ImportedType = ImportType(FromType, TUDecl: FromTypedef, ToLang: Lang_CXX03);
7015 EXPECT_EQ(ImportedType, ToType);
7016 }
7017}
7018
7019TEST_P(ASTImporterOptionSpecificTestBase, ImportOfDefaultImplicitFunctions) {
7020 // Test that import of implicit functions works and the functions
7021 // are merged into one chain.
7022 auto GetDeclToImport = [this](StringRef File) {
7023 Decl *FromTU = getTuDecl(
7024 SrcCode: R"(
7025 struct X { };
7026 // Force generating some implicit operator definitions for X.
7027 void f() { X x1, x2; x1 = x2; X *x3 = new X; delete x3; }
7028 )",
7029 Lang: Lang_CXX11, FileName: File);
7030 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
7031 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X"), unless(isImplicit())));
7032 // Destructor is picked as one example of implicit function.
7033 return FromD->getDestructor();
7034 };
7035
7036 auto *ToD1 = Import(From: GetDeclToImport("input1.cc"), Lang: Lang_CXX11);
7037 ASSERT_TRUE(ToD1);
7038
7039 auto *ToD2 = Import(From: GetDeclToImport("input2.cc"), Lang: Lang_CXX11);
7040 ASSERT_TRUE(ToD2);
7041
7042 EXPECT_EQ(ToD1->getCanonicalDecl(), ToD2->getCanonicalDecl());
7043}
7044
7045TEST_P(ASTImporterOptionSpecificTestBase,
7046 ImportOfExplicitlyDefaultedOrDeleted) {
7047 Decl *FromTU = getTuDecl(
7048 SrcCode: R"(
7049 struct X { X() = default; X(const X&) = delete; };
7050 )",
7051 Lang: Lang_CXX11);
7052 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
7053 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
7054 auto *ImportedX = Import(From: FromX, Lang: Lang_CXX11);
7055 auto *Constr1 = FirstDeclMatcher<CXXConstructorDecl>().match(
7056 D: ImportedX, AMatcher: cxxConstructorDecl(hasName(Name: "X"), unless(isImplicit())));
7057 auto *Constr2 = LastDeclMatcher<CXXConstructorDecl>().match(
7058 D: ImportedX, AMatcher: cxxConstructorDecl(hasName(Name: "X"), unless(isImplicit())));
7059
7060 ASSERT_TRUE(ImportedX);
7061 EXPECT_TRUE(Constr1->isDefaulted());
7062 EXPECT_TRUE(Constr1->isExplicitlyDefaulted());
7063 EXPECT_TRUE(Constr2->isDeletedAsWritten());
7064 EXPECT_EQ(ImportedX->isAggregate(), FromX->isAggregate());
7065}
7066
7067INSTANTIATE_TEST_SUITE_P(ParameterizedTests, SVEBuiltins,
7068 ::testing::Values(std::vector<std::string>{
7069 "-target", "aarch64-linux-gnu"}));
7070
7071INSTANTIATE_TEST_SUITE_P(ParameterizedTests, DeclContextTest,
7072 ::testing::Values(std::vector<std::string>()));
7073
7074INSTANTIATE_TEST_SUITE_P(ParameterizedTests, CanonicalRedeclChain,
7075 ::testing::Values(std::vector<std::string>()));
7076
7077TEST_P(ASTImporterOptionSpecificTestBase, LambdasAreDifferentiated) {
7078 Decl *FromTU = getTuDecl(
7079 SrcCode: R"(
7080 void f() {
7081 auto L0 = [](){};
7082 auto L1 = [](){};
7083 }
7084 )",
7085 Lang: Lang_CXX11, FileName: "input0.cc");
7086 auto Pattern = lambdaExpr();
7087 CXXRecordDecl *FromL0 =
7088 FirstDeclMatcher<LambdaExpr>().match(D: FromTU, AMatcher: Pattern)->getLambdaClass();
7089 CXXRecordDecl *FromL1 =
7090 LastDeclMatcher<LambdaExpr>().match(D: FromTU, AMatcher: Pattern)->getLambdaClass();
7091 ASSERT_NE(FromL0, FromL1);
7092
7093 CXXRecordDecl *ToL0 = Import(From: FromL0, Lang: Lang_CXX11);
7094 CXXRecordDecl *ToL1 = Import(From: FromL1, Lang: Lang_CXX11);
7095 EXPECT_NE(ToL0, ToL1);
7096}
7097
7098TEST_P(ASTImporterOptionSpecificTestBase,
7099 LambdasInFunctionParamsAreDifferentiated) {
7100 Decl *FromTU = getTuDecl(
7101 SrcCode: R"(
7102 template <typename F0, typename F1>
7103 void f(F0 L0 = [](){}, F1 L1 = [](){}) {}
7104 )",
7105 Lang: Lang_CXX11, FileName: "input0.cc");
7106 auto Pattern = cxxRecordDecl(isLambda());
7107 CXXRecordDecl *FromL0 =
7108 FirstDeclMatcher<CXXRecordDecl>().match(D: FromTU, AMatcher: Pattern);
7109 CXXRecordDecl *FromL1 =
7110 LastDeclMatcher<CXXRecordDecl>().match(D: FromTU, AMatcher: Pattern);
7111 ASSERT_NE(FromL0, FromL1);
7112
7113 CXXRecordDecl *ToL0 = Import(From: FromL0, Lang: Lang_CXX11);
7114 CXXRecordDecl *ToL1 = Import(From: FromL1, Lang: Lang_CXX11);
7115 ASSERT_NE(ToL0, ToL1);
7116}
7117
7118TEST_P(ASTImporterOptionSpecificTestBase,
7119 LambdasInFunctionParamsAreDifferentiatedWhenMacroIsUsed) {
7120 Decl *FromTU = getTuDecl(
7121 SrcCode: R"(
7122 #define LAMBDA [](){}
7123 template <typename F0, typename F1>
7124 void f(F0 L0 = LAMBDA, F1 L1 = LAMBDA) {}
7125 )",
7126 Lang: Lang_CXX11, FileName: "input0.cc");
7127 auto Pattern = cxxRecordDecl(isLambda());
7128 CXXRecordDecl *FromL0 =
7129 FirstDeclMatcher<CXXRecordDecl>().match(D: FromTU, AMatcher: Pattern);
7130 CXXRecordDecl *FromL1 =
7131 LastDeclMatcher<CXXRecordDecl>().match(D: FromTU, AMatcher: Pattern);
7132 ASSERT_NE(FromL0, FromL1);
7133
7134 Import(From: FromL0, Lang: Lang_CXX11);
7135 Import(From: FromL1, Lang: Lang_CXX11);
7136 CXXRecordDecl *ToL0 = Import(From: FromL0, Lang: Lang_CXX11);
7137 CXXRecordDecl *ToL1 = Import(From: FromL1, Lang: Lang_CXX11);
7138 ASSERT_NE(ToL0, ToL1);
7139}
7140
7141TEST_P(ASTImporterOptionSpecificTestBase, ImportAssignedLambda) {
7142 Decl *FromTU = getTuDecl(
7143 SrcCode: R"(
7144 void f() {
7145 auto x = []{} = {}; auto x2 = x;
7146 }
7147 )",
7148 Lang: Lang_CXX20, FileName: "input0.cc");
7149 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
7150 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
7151 // We have only one lambda class.
7152 ASSERT_EQ(
7153 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
7154 1u);
7155
7156 FunctionDecl *ToF = Import(From: FromF, Lang: Lang_CXX20);
7157 EXPECT_TRUE(ToF);
7158 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
7159 // We have only one lambda class after the import.
7160 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
7161 1u);
7162}
7163
7164TEST_P(ASTImporterOptionSpecificTestBase, ImportDefaultConstructibleLambdas) {
7165 Decl *FromTU = getTuDecl(
7166 SrcCode: R"(
7167 void f() {
7168 auto x = []{} = {};
7169 auto xb = []{} = {};
7170 }
7171 )",
7172 Lang: Lang_CXX20, FileName: "input0.cc");
7173 auto FromF = FirstDeclMatcher<FunctionDecl>().match(
7174 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
7175 // We have two lambda classes.
7176 ASSERT_EQ(
7177 DeclCounter<CXXRecordDecl>().match(FromTU, cxxRecordDecl(isLambda())),
7178 2u);
7179
7180 FunctionDecl *ToF = Import(From: FromF, Lang: Lang_CXX20);
7181 EXPECT_TRUE(ToF);
7182 TranslationUnitDecl *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
7183 // We have two lambda classes after the import.
7184 EXPECT_EQ(DeclCounter<CXXRecordDecl>().match(ToTU, cxxRecordDecl(isLambda())),
7185 2u);
7186}
7187
7188TEST_P(ASTImporterOptionSpecificTestBase,
7189 ImportFunctionDeclWithTypeSourceInfoWithSourceDecl) {
7190 // This code results in a lambda with implicit constructor.
7191 // The constructor's TypeSourceInfo points out the function prototype.
7192 // This prototype has an EST_Unevaluated in its exception information and a
7193 // SourceDecl that is the function declaration itself.
7194 // The test verifies that AST import of such AST does not crash.
7195 // (Here the function's TypeSourceInfo references the function itself.)
7196 Decl *FromTU = getTuDecl(
7197 SrcCode: R"(
7198 template<typename T> void f(T) { auto X = [](){}; }
7199 void g() { f(10); }
7200 )",
7201 Lang: Lang_CXX11, FileName: "input0.cc");
7202
7203 // Use LastDeclMatcher to find the LambdaExpr in the template specialization.
7204 CXXRecordDecl *FromL = LastDeclMatcher<LambdaExpr>()
7205 .match(D: FromTU, AMatcher: lambdaExpr())
7206 ->getLambdaClass();
7207
7208 CXXConstructorDecl *FromCtor = *FromL->ctor_begin();
7209 ASSERT_TRUE(FromCtor->isCopyConstructor());
7210 ASSERT_TRUE(FromCtor->getTypeSourceInfo());
7211 const auto *FromFPT = FromCtor->getType()->getAs<FunctionProtoType>();
7212 ASSERT_TRUE(FromFPT);
7213 EXPECT_EQ(FromCtor->getTypeSourceInfo()->getType().getTypePtr(), FromFPT);
7214 FunctionProtoType::ExtProtoInfo FromEPI = FromFPT->getExtProtoInfo();
7215 // If type is EST_Unevaluated, SourceDecl should be set to the parent Decl.
7216 EXPECT_EQ(FromEPI.ExceptionSpec.Type, EST_Unevaluated);
7217 EXPECT_EQ(FromEPI.ExceptionSpec.SourceDecl, FromCtor);
7218
7219 auto ToL = Import(From: FromL, Lang: Lang_CXX11);
7220
7221 // Check if the import was correct.
7222 CXXConstructorDecl *ToCtor = *ToL->ctor_begin();
7223 EXPECT_TRUE(ToCtor->getTypeSourceInfo());
7224 const auto *ToFPT = ToCtor->getType()->getAs<FunctionProtoType>();
7225 ASSERT_TRUE(ToFPT);
7226 EXPECT_EQ(ToCtor->getTypeSourceInfo()->getType().getTypePtr(), ToFPT);
7227 FunctionProtoType::ExtProtoInfo ToEPI = ToFPT->getExtProtoInfo();
7228 EXPECT_EQ(ToEPI.ExceptionSpec.Type, EST_Unevaluated);
7229 EXPECT_EQ(ToEPI.ExceptionSpec.SourceDecl, ToCtor);
7230}
7231
7232struct ImportAutoFunctions : ASTImporterOptionSpecificTestBase {
7233 void testImport(llvm::StringRef Code, clang::TestLanguage Lang = Lang_CXX14,
7234 bool FindLast = false) {
7235 Decl *FromTU = getTuDecl(SrcCode: Code, Lang, FileName: "input0.cc");
7236 FunctionDecl *From = FindLast ? LastDeclMatcher<FunctionDecl>().match(
7237 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo")))
7238 : FirstDeclMatcher<FunctionDecl>().match(
7239 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo")));
7240
7241 FunctionDecl *To = Import(From, Lang);
7242 EXPECT_TRUE(To);
7243 // We check here only that the type is auto type.
7244 // These tests are to verify that no crash happens.
7245 // The crash possibility is the presence of a reference to a declaration
7246 // in the function's body from the return type, if the function has auto
7247 // return type.
7248 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
7249 }
7250};
7251
7252TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate1) {
7253 testImport(
7254 Code: R"(
7255 template<class C>
7256 C f1() { return C(); }
7257 auto foo() {
7258 struct B {};
7259 return f1<B>();
7260 }
7261 )");
7262}
7263
7264TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate2) {
7265 testImport(
7266 Code: R"(
7267 template<class T>
7268 int f1(T t) { return 1; }
7269 auto foo() {
7270 struct B {};
7271 return f1(B());
7272 }
7273 )");
7274}
7275
7276TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate3) {
7277 testImport(
7278 Code: R"(
7279 template<class A> struct S1 {};
7280 template<class A> struct S2 {};
7281 template<class C>
7282 S1<C> f1() { return S1<C>(); }
7283 auto foo() {
7284 struct B {};
7285 return f1<S2<B *>>();
7286 }
7287 )");
7288}
7289
7290TEST_P(ImportAutoFunctions, ReturnWithFunctionTemplate4) {
7291 testImport(
7292 Code: R"(
7293 template<class... A> struct S1 {};
7294 template<class... A> struct S2 {};
7295 template<class... C>
7296 S1<C...> f1() { return S1<C...>(); }
7297 auto foo() {
7298 struct B {};
7299 return f1<S2<int, B *>, bool>();
7300 }
7301 )");
7302}
7303
7304TEST_P(ImportAutoFunctions, ReturnWithVarTemplate1) {
7305 testImport(
7306 Code: R"(
7307 template<class T> T X;
7308 auto foo() {
7309 struct A {};
7310 return X<A>;
7311 }
7312 )");
7313}
7314
7315TEST_P(ImportAutoFunctions, ReturnWithVarTemplate2) {
7316 testImport(
7317 Code: R"(
7318 template<class A> struct S1 {};
7319 template<class T> S1<T> X;
7320 auto foo() {
7321 struct A {};
7322 return X<S1<A>>;
7323 }
7324 )");
7325}
7326
7327TEST_P(ImportAutoFunctions, ReturnWithVarTemplate3) {
7328 testImport(
7329 Code: R"(
7330 template<class... A> struct S1 {};
7331 template<class... T> S1<T...> X;
7332 auto foo() {
7333 struct A {};
7334 return X<bool, S1<A, int>>;
7335 }
7336 )");
7337}
7338
7339TEST_P(ImportAutoFunctions, ReturnWithAutoUnresolvedArg) {
7340 testImport(
7341 Code: R"(
7342 template<int A>
7343 auto foo() {
7344 return 22;
7345 }
7346 )");
7347}
7348
7349TEST_P(ImportAutoFunctions, ReturnWithTemplateWithTemplateTemplateArg) {
7350 // FIXME: Is it possible to have the template arg inside the function?
7351 testImport(
7352 Code: R"(
7353 template<int> struct Tmpl {};
7354 template<template<int> class> struct TmplTmpl {};
7355 auto foo() {
7356 return TmplTmpl<Tmpl>();
7357 }
7358 )");
7359}
7360
7361TEST_P(ImportAutoFunctions, ReturnWithTemplateWithDeclarationTemplateArg) {
7362 // FIXME: Is it possible to have the template arg inside the function?
7363 testImport(
7364 Code: R"(
7365 template<const int *> struct Tmpl {};
7366 int A[10];
7367 auto foo() {
7368 return Tmpl<A>();
7369 }
7370 )");
7371}
7372
7373TEST_P(ImportAutoFunctions, ReturnWithTemplateWithNullPtrTemplateArg) {
7374 testImport(
7375 Code: R"(
7376 template<int *> struct Tmpl {};
7377 auto foo() {
7378 constexpr int* A = nullptr;
7379 return Tmpl<A>();
7380 }
7381 )");
7382}
7383
7384TEST_P(ImportAutoFunctions, ReturnWithTemplateWithIntegralTemplateArg) {
7385 testImport(
7386 Code: R"(
7387 template<int> struct Tmpl {};
7388 auto foo() {
7389 using Int = int;
7390 constexpr Int A = 7;
7391 return Tmpl<A>();
7392 }
7393 )");
7394}
7395
7396TEST_P(ImportAutoFunctions, ReturnWithTemplateWithDecltypeTypeDeclaredInside) {
7397 testImport(
7398 Code: R"(
7399 template<class> struct Tmpl {};
7400 auto foo() {
7401 struct X {};
7402 X x;
7403 return Tmpl<decltype(x)>();
7404 }
7405 )");
7406}
7407
7408TEST_P(ImportAutoFunctions, ReturnWithTemplateWithUsingTypeDeclaredInside) {
7409 testImport(
7410 Code: R"(
7411 template<class> struct Tmpl {};
7412 namespace A { struct X {}; }
7413 auto foo() {
7414 using A::X;
7415 return Tmpl<X>();
7416 }
7417 )");
7418}
7419
7420TEST_P(ImportAutoFunctions, ReturnWithTemplateWithArrayTypeDeclaredInside) {
7421 testImport(
7422 Code: R"(
7423 template<class> struct Tmpl {};
7424 auto foo() {
7425 struct X {};
7426 return Tmpl<X[10]>();
7427 }
7428 )");
7429}
7430
7431TEST_P(ImportAutoFunctions, ReturnWithTemplateWithArraySizeExprDeclaredInside) {
7432 testImport(
7433 Code: R"(
7434 template<class> struct Tmpl {};
7435 auto foo() {
7436 constexpr int S = 10;
7437 return Tmpl<int[S]>();
7438 }
7439 )");
7440}
7441
7442TEST_P(ImportAutoFunctions, ReturnWithTemplateWithPackArgDeclaredInside) {
7443 testImport(
7444 Code: R"(
7445 template<class ...> struct Tmpl {};
7446 auto foo() {
7447 using X = bool;
7448 return Tmpl<int, X>();
7449 }
7450 )");
7451}
7452
7453TEST_P(ImportAutoFunctions, ReturnWithTemplateWithIntegerArgDeclaredInside) {
7454 testImport(
7455 Code: R"(
7456 template<int> struct Tmpl {};
7457 auto foo() {
7458 constexpr int X = 1;
7459 return Tmpl<X>();
7460 }
7461 )");
7462}
7463
7464TEST_P(ImportAutoFunctions, ReturnWithTemplateWithPtrToStructDeclaredInside) {
7465 testImport(
7466 Code: R"(
7467 template<class> struct Tmpl {};
7468 auto foo() {
7469 struct X {};
7470 return Tmpl<X *>();
7471 }
7472 )");
7473}
7474
7475TEST_P(ImportAutoFunctions, ReturnWithTemplateWithRefToStructDeclaredInside) {
7476 testImport(
7477 Code: R"(
7478 template<class> struct Tmpl {};
7479 struct X {};
7480 auto foo() {
7481 using Y = X;
7482 return Tmpl<Y &>();
7483 }
7484 )");
7485}
7486
7487TEST_P(ImportAutoFunctions, ReturnWithTemplateWithStructDeclaredInside1) {
7488 testImport(
7489 Code: R"(
7490 template<class> struct Tmpl {};
7491 auto foo() {
7492 struct X {};
7493 return Tmpl<X>();
7494 }
7495 )");
7496}
7497
7498TEST_P(ImportAutoFunctions, ReturnWithTemplateWithStructDeclaredInside2) {
7499 testImport(
7500 Code: R"(
7501 template<class> struct Tmpl {};
7502 auto foo() {
7503 struct X {};
7504 return Tmpl<Tmpl<X>>();
7505 }
7506 )");
7507}
7508
7509TEST_P(ImportAutoFunctions, ReturnWithTemplateWithTypedefDeclaredInside) {
7510 testImport(
7511 Code: R"(
7512 template<class> struct Tmpl {};
7513 auto foo() {
7514 struct X {};
7515 using x_type = X;
7516 return Tmpl<x_type>();
7517 }
7518 )");
7519}
7520
7521TEST_P(ImportAutoFunctions, ReturnWithTypedefDeclaredInside) {
7522 Decl *FromTU = getTuDecl(
7523 SrcCode: R"(
7524 auto X = [](long l) {
7525 using int_type = long;
7526 auto dur = 13;
7527 return static_cast<int_type>(dur);
7528 };
7529 )",
7530 Lang: Lang_CXX14, FileName: "input0.cc");
7531 CXXMethodDecl *From =
7532 FirstDeclMatcher<CXXMethodDecl>().match(D: FromTU, AMatcher: cxxMethodDecl());
7533
7534 // Explicitly set the return type of the lambda's operator() to the TypeAlias.
7535 // Normally the return type would be the built-in 'long' type. However, there
7536 // are cases when Clang does not use the canonical type and the TypeAlias is
7537 // used. I could not create such an AST from regular source code, it requires
7538 // some special state in the preprocessor. I've found such an AST when Clang
7539 // parsed libcxx/src/filesystem/directory_iterator.cpp, but could not reduce
7540 // that with creduce, because after preprocessing, the AST no longer
7541 // contained the TypeAlias as a return type of the lambda.
7542 ASTContext &Ctx = From->getASTContext();
7543 TypeAliasDecl *FromTA =
7544 FirstDeclMatcher<TypeAliasDecl>().match(D: FromTU, AMatcher: typeAliasDecl());
7545 QualType TT = Ctx.getTypedefType(Decl: FromTA);
7546 const FunctionProtoType *FPT = cast<FunctionProtoType>(Val: From->getType());
7547 QualType NewFunType =
7548 Ctx.getFunctionType(ResultTy: TT, Args: FPT->getParamTypes(), EPI: FPT->getExtProtoInfo());
7549 From->setType(NewFunType);
7550
7551 CXXMethodDecl *To = Import(From, Lang: Lang_CXX14);
7552 EXPECT_TRUE(To);
7553 EXPECT_TRUE(isa<TypedefType>(To->getReturnType()));
7554}
7555
7556TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside) {
7557 testImport(
7558 Code: R"(
7559 auto foo() {
7560 struct X {};
7561 return X();
7562 }
7563 )");
7564}
7565
7566TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside2) {
7567 Decl *FromTU = getTuDecl(
7568 SrcCode: R"(
7569 auto foo() {
7570 struct X {};
7571 return X();
7572 }
7573 )",
7574 Lang: Lang_CXX14, FileName: "input0.cc");
7575 FunctionDecl *From =
7576 FirstDeclMatcher<FunctionDecl>().match(D: FromTU, AMatcher: functionDecl());
7577
7578 // This time import the type directly.
7579 QualType ToT = ImportType(FromType: From->getType(), TUDecl: From, ToLang: Lang_CXX14);
7580 const FunctionProtoType *FPT = cast<FunctionProtoType>(Val&: ToT);
7581 EXPECT_TRUE(isa<AutoType>(FPT->getReturnType()));
7582}
7583
7584TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredInside3) {
7585 Decl *FromTU = getTuDecl(
7586 SrcCode: R"(
7587 struct S {
7588 constexpr auto foo();
7589 };
7590 constexpr auto S::foo() {
7591 struct X {};
7592 return X();
7593 }
7594 )",
7595 Lang: Lang_CXX14, FileName: "input0.cc");
7596 FunctionDecl *From = FirstDeclMatcher<FunctionDecl>().match(
7597 D: FromTU, AMatcher: functionDecl(hasName(Name: "foo"), unless(hasBody(InnerMatcher: stmt()))));
7598 ASSERT_FALSE(From->isThisDeclarationADefinition());
7599
7600 FunctionDecl *To = Import(From, Lang: Lang_CXX17);
7601 EXPECT_TRUE(To);
7602 EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
7603 EXPECT_FALSE(To->isThisDeclarationADefinition());
7604}
7605
7606TEST_P(ImportAutoFunctions, ReturnWithTypedefToStructDeclaredInside) {
7607 testImport(
7608 Code: R"(
7609 auto foo() {
7610 struct X {};
7611 using Y = X;
7612 return Y();
7613 }
7614 )");
7615}
7616
7617TEST_P(ImportAutoFunctions, ReturnWithStructDeclaredNestedInside) {
7618 testImport(
7619 Code: R"(
7620 auto foo() {
7621 struct X { struct Y{}; };
7622 return X::Y();
7623 }
7624 )");
7625}
7626
7627TEST_P(ImportAutoFunctions, ReturnWithInternalLambdaType) {
7628 testImport(
7629 Code: R"(
7630 auto foo() {
7631 auto l = []() {
7632 struct X {};
7633 return X();
7634 };
7635 return l();
7636 }
7637 )",
7638 Lang: Lang_CXX17);
7639}
7640
7641TEST_P(ImportAutoFunctions, ReturnWithTypeInIf) {
7642 testImport(
7643 Code: R"(
7644 auto foo() {
7645 if (struct X {} x; true)
7646 return X();
7647 else
7648 return X();
7649 }
7650 )",
7651 Lang: Lang_CXX17);
7652}
7653
7654TEST_P(ImportAutoFunctions, ReturnWithTypeInFor) {
7655 testImport(
7656 Code: R"(
7657 auto foo() {
7658 for (struct X {} x;;)
7659 return X();
7660 }
7661 )",
7662 Lang: Lang_CXX17);
7663}
7664
7665TEST_P(ImportAutoFunctions, ReturnWithTypeInSwitch) {
7666 testImport(
7667 Code: R"(
7668 auto foo() {
7669 switch (struct X {} x; 10) {
7670 case 10:
7671 return X();
7672 }
7673 }
7674 )",
7675 Lang: Lang_CXX17);
7676}
7677
7678TEST_P(ImportAutoFunctions, ReturnWithAutoTemplateType) {
7679 testImport(
7680 Code: R"(
7681 template<class T>
7682 struct S {};
7683 template<class T>
7684 auto foo() {
7685 return S<T>{};
7686 }
7687 auto a = foo<int>();
7688 )",
7689 Lang: Lang_CXX14, /*FindLast=*/true);
7690}
7691
7692TEST_P(ImportAutoFunctions, ReturnWithSubstNonTypeTemplateParmExpr) {
7693 const char *Code =
7694 R"(
7695 template<int>
7696 struct array {};
7697
7698 template <int N>
7699 auto foo() { return array<N>(); }
7700
7701 void bar() { foo<0>(); }
7702 )";
7703 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX17);
7704
7705 auto *FromBar = FirstDeclMatcher<FunctionDecl>().match(
7706 D: FromTU, AMatcher: functionDecl(hasName(Name: "bar")));
7707
7708 auto *ToBar = Import(From: FromBar, Lang: Lang_CXX17);
7709 EXPECT_TRUE(ToBar);
7710}
7711
7712TEST_P(ImportAutoFunctions, ReturnWithUnaryTransformType) {
7713 const char *Code =
7714 R"(
7715 enum E { E1 };
7716
7717 template<typename T>
7718 auto foo(T v) { return static_cast<__underlying_type(T)>(v); }
7719
7720 bool bar() { return foo(E1); }
7721 )";
7722 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX17);
7723
7724 auto *FromBar = FirstDeclMatcher<FunctionDecl>().match(
7725 D: FromTU, AMatcher: functionDecl(hasName(Name: "bar")));
7726
7727 auto *ToBar = Import(From: FromBar, Lang: Lang_CXX17);
7728 EXPECT_TRUE(ToBar);
7729}
7730
7731struct ImportSourceLocations : ASTImporterOptionSpecificTestBase {};
7732
7733TEST_P(ImportSourceLocations, PreserveFileIDTreeStructure) {
7734 // Tests that the FileID tree structure (with the links being the include
7735 // chains) is preserved while importing other files (which need to be
7736 // added to this structure with fake include locations.
7737
7738 SourceLocation Location1;
7739 {
7740 auto Pattern = varDecl(hasName(Name: "X"));
7741 Decl *FromTU = getTuDecl(SrcCode: "int X;", Lang: Lang_C99, FileName: "input0.c");
7742 auto *FromD = FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: Pattern);
7743
7744 Location1 = Import(From: FromD, Lang: Lang_C99)->getLocation();
7745 }
7746 SourceLocation Location2;
7747 {
7748 auto Pattern = varDecl(hasName(Name: "Y"));
7749 Decl *FromTU = getTuDecl(SrcCode: "int Y;", Lang: Lang_C99, FileName: "input1.c");
7750 auto *FromD = FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: Pattern);
7751
7752 Location2 = Import(From: FromD, Lang: Lang_C99)->getLocation();
7753 }
7754
7755 SourceManager &ToSM = ToAST->getSourceManager();
7756 FileID FileID1 = ToSM.getFileID(SpellingLoc: Location1);
7757 FileID FileID2 = ToSM.getFileID(SpellingLoc: Location2);
7758
7759 // Check that the imported files look like as if they were included from the
7760 // start of the main file.
7761 SourceLocation FileStart = ToSM.getLocForStartOfFile(FID: ToSM.getMainFileID());
7762 EXPECT_NE(FileID1, ToSM.getMainFileID());
7763 EXPECT_NE(FileID2, ToSM.getMainFileID());
7764 EXPECT_EQ(ToSM.getIncludeLoc(FileID1), FileStart);
7765 EXPECT_EQ(ToSM.getIncludeLoc(FileID2), FileStart);
7766
7767 // Let the SourceManager check the order of the locations. The order should
7768 // be the order in which the declarations are imported.
7769 EXPECT_TRUE(ToSM.isBeforeInTranslationUnit(Location1, Location2));
7770 EXPECT_FALSE(ToSM.isBeforeInTranslationUnit(Location2, Location1));
7771}
7772
7773TEST_P(ImportSourceLocations, NormalFileBuffer) {
7774 // Test importing normal file buffers.
7775
7776 std::string Path = "input0.c";
7777 std::string Source = "int X;";
7778 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: Source, Lang: Lang_C99, FileName: Path);
7779
7780 SourceLocation ImportedLoc;
7781 {
7782 // Import the VarDecl to trigger the importing of the FileID.
7783 auto Pattern = varDecl(hasName(Name: "X"));
7784 VarDecl *FromD = FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: Pattern);
7785 ImportedLoc = Import(From: FromD, Lang: Lang_C99)->getLocation();
7786 }
7787
7788 // Make sure the imported buffer has the original contents.
7789 SourceManager &ToSM = ToAST->getSourceManager();
7790 FileID ImportedID = ToSM.getFileID(SpellingLoc: ImportedLoc);
7791 EXPECT_EQ(Source,
7792 ToSM.getBufferOrFake(ImportedID, SourceLocation()).getBuffer());
7793}
7794
7795TEST_P(ImportSourceLocations, OverwrittenFileBuffer) {
7796 // Test importing overwritten file buffers.
7797
7798 std::string Path = "input0.c";
7799 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: "int X;", Lang: Lang_C99, FileName: Path);
7800
7801 // Overwrite the file buffer for our input file with new content.
7802 const std::string Contents = "overwritten contents";
7803 SourceLocation ImportedLoc;
7804 {
7805 SourceManager &FromSM = FromTU->getASTContext().getSourceManager();
7806 clang::FileManager &FM = FromSM.getFileManager();
7807 clang::FileEntryRef FE =
7808 FM.getVirtualFileRef(Filename: Path, Size: static_cast<off_t>(Contents.size()), ModificationTime: 0);
7809
7810 llvm::SmallVector<char, 64> Buffer;
7811 Buffer.append(in_start: Contents.begin(), in_end: Contents.end());
7812 auto FileContents = std::make_unique<llvm::SmallVectorMemoryBuffer>(
7813 args: std::move(Buffer), args&: Path, /*RequiresNullTerminator=*/args: false);
7814 FromSM.overrideFileContents(SourceFile: FE, Buffer: std::move(FileContents));
7815
7816 // Import the VarDecl to trigger the importing of the FileID.
7817 auto Pattern = varDecl(hasName(Name: "X"));
7818 VarDecl *FromD = FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: Pattern);
7819 ImportedLoc = Import(From: FromD, Lang: Lang_C99)->getLocation();
7820 }
7821
7822 // Make sure the imported buffer has the overwritten contents.
7823 SourceManager &ToSM = ToAST->getSourceManager();
7824 FileID ImportedID = ToSM.getFileID(SpellingLoc: ImportedLoc);
7825 EXPECT_EQ(Contents,
7826 ToSM.getBufferOrFake(ImportedID, SourceLocation()).getBuffer());
7827}
7828
7829struct ImportAttributes : public ASTImporterOptionSpecificTestBase {
7830 void checkAttrImportCommon(const Attr *From, const Attr *To,
7831 const Decl *ToD) {
7832
7833 // Verify that dump does not crash because invalid data.
7834 ToD->dump(Out&: llvm::nulls());
7835
7836 EXPECT_EQ(From->getParsedKind(), To->getParsedKind());
7837 EXPECT_EQ(From->getSyntax(), To->getSyntax());
7838 if (From->getAttrName()) {
7839 EXPECT_TRUE(To->getAttrName());
7840 EXPECT_STREQ(From->getAttrName()->getNameStart(),
7841 To->getAttrName()->getNameStart());
7842 } else {
7843 EXPECT_FALSE(To->getAttrName());
7844 }
7845 if (From->getScopeName()) {
7846 EXPECT_TRUE(To->getScopeName());
7847 EXPECT_STREQ(From->getScopeName()->getNameStart(),
7848 To->getScopeName()->getNameStart());
7849 } else {
7850 EXPECT_FALSE(To->getScopeName());
7851 }
7852 EXPECT_EQ(From->getSpellingListIndex(), To->getSpellingListIndex());
7853 EXPECT_STREQ(From->getSpelling(), To->getSpelling());
7854 EXPECT_EQ(From->isInherited(), To->isInherited());
7855 EXPECT_EQ(From->isImplicit(), To->isImplicit());
7856 EXPECT_EQ(From->isPackExpansion(), To->isPackExpansion());
7857 EXPECT_EQ(From->isLateParsed(), To->isLateParsed());
7858 }
7859
7860 template <class DT, class AT>
7861 void importAttr(const char *Code, AT *&FromAttr, AT *&ToAttr,
7862 TestLanguage Lang = Lang_CXX11) {
7863 static_assert(std::is_base_of<Attr, AT>::value, "AT should be an Attr");
7864 static_assert(std::is_base_of<Decl, DT>::value, "DT should be a Decl");
7865
7866 Decl *FromTU = getTuDecl(SrcCode: Code, Lang, FileName: "input.cc");
7867 DT *FromD =
7868 FirstDeclMatcher<DT>().match(FromTU, namedDecl(hasName(Name: "test")));
7869 ASSERT_TRUE(FromD);
7870
7871 DT *ToD = Import(FromD, Lang_CXX11);
7872 ASSERT_TRUE(ToD);
7873
7874 FromAttr = FromD->template getAttr<AT>();
7875 ToAttr = ToD->template getAttr<AT>();
7876 ASSERT_TRUE(FromAttr);
7877 EXPECT_TRUE(ToAttr);
7878
7879 checkAttrImportCommon(From: FromAttr, To: ToAttr, ToD);
7880 }
7881
7882 template <class T> void checkImported(const T *From, const T *To) {
7883 EXPECT_TRUE(To);
7884 EXPECT_NE(From, To);
7885 }
7886
7887 template <class T>
7888 void checkImportVariadicArg(const llvm::iterator_range<T **> &From,
7889 const llvm::iterator_range<T **> &To) {
7890 for (auto FromI = From.begin(), ToI = To.begin(); FromI != From.end();
7891 ++FromI, ++ToI) {
7892 ASSERT_NE(ToI, To.end());
7893 checkImported(*FromI, *ToI);
7894 }
7895 }
7896};
7897
7898template <>
7899void ImportAttributes::checkImported<Decl>(const Decl *From, const Decl *To) {
7900 EXPECT_TRUE(To);
7901 EXPECT_NE(From, To);
7902 EXPECT_EQ(To->getTranslationUnitDecl(),
7903 ToAST->getASTContext().getTranslationUnitDecl());
7904}
7905
7906TEST_P(ImportAttributes, ImportAligned) {
7907 AlignedAttr *FromAttr, *ToAttr;
7908 importAttr<RecordDecl>(
7909 Code: R"(
7910 struct __attribute__((packed)) A { int __attribute__((aligned(8))) X; };
7911 struct alignas(alignof(A)) test {};
7912 )",
7913 FromAttr, ToAttr);
7914 checkImported(From: FromAttr->getAlignmentExpr(), To: ToAttr->getAlignmentExpr());
7915
7916 auto *ToA = FirstDeclMatcher<CXXRecordDecl>().match(
7917 D: ToAST->getASTContext().getTranslationUnitDecl(),
7918 AMatcher: cxxRecordDecl(hasName(Name: "A"), unless(isImplicit())));
7919 // Ensure that 'struct A' was imported (through reference from attribute of
7920 // struct 'test').
7921 EXPECT_TRUE(ToA);
7922}
7923
7924TEST_P(ImportAttributes, ImportAlignValue) {
7925 AlignValueAttr *FromAttr, *ToAttr;
7926 importAttr<VarDecl>(
7927 Code: R"(
7928 void *test __attribute__((align_value(64)));
7929 )",
7930 FromAttr, ToAttr);
7931 checkImported(From: FromAttr->getAlignment(), To: ToAttr->getAlignment());
7932}
7933
7934TEST_P(ImportAttributes, ImportFormat) {
7935 FormatAttr *FromAttr, *ToAttr;
7936 importAttr<FunctionDecl>(
7937 Code: R"(
7938 int test(const char * fmt, ...)
7939 __attribute__ ((__format__ (__scanf__, 1, 2)));
7940 )",
7941 FromAttr, ToAttr);
7942
7943 EXPECT_EQ(FromAttr->getType()->getName(), ToAttr->getType()->getName());
7944 EXPECT_EQ(FromAttr->getFirstArg(), ToAttr->getFirstArg());
7945 EXPECT_EQ(FromAttr->getFormatIdx(), ToAttr->getFormatIdx());
7946}
7947
7948TEST_P(ImportAttributes, ImportEnableIf) {
7949 EnableIfAttr *FromAttr, *ToAttr;
7950 importAttr<FunctionDecl>(
7951 Code: "void test(int A) __attribute__((enable_if(A == 1, \"message\")));",
7952 FromAttr, ToAttr);
7953 checkImported(From: FromAttr->getCond(), To: ToAttr->getCond());
7954 EXPECT_EQ(FromAttr->getMessage(), ToAttr->getMessage());
7955}
7956
7957TEST_P(ImportAttributes, ImportGuardedVar) {
7958 GuardedVarAttr *FromAttr, *ToAttr;
7959 importAttr<VarDecl>(Code: "int test __attribute__((guarded_var));", FromAttr,
7960 ToAttr);
7961}
7962
7963TEST_P(ImportAttributes, ImportPtGuardedVar) {
7964 PtGuardedVarAttr *FromAttr, *ToAttr;
7965 importAttr<VarDecl>(Code: "int *test __attribute__((pt_guarded_var));", FromAttr,
7966 ToAttr);
7967}
7968
7969TEST_P(ImportAttributes, ImportScopedLockable) {
7970 ScopedLockableAttr *FromAttr, *ToAttr;
7971 importAttr<CXXRecordDecl>(Code: "struct __attribute__((scoped_lockable)) test {};",
7972 FromAttr, ToAttr);
7973}
7974
7975TEST_P(ImportAttributes, ImportCapability) {
7976 CapabilityAttr *FromAttr, *ToAttr;
7977 importAttr<CXXRecordDecl>(
7978 Code: "struct __attribute__((capability(\"cap\"))) test {};", FromAttr, ToAttr);
7979 EXPECT_EQ(FromAttr->getName(), ToAttr->getName());
7980}
7981
7982TEST_P(ImportAttributes, ImportAssertCapability) {
7983 AssertCapabilityAttr *FromAttr, *ToAttr;
7984 importAttr<FunctionDecl>(
7985 Code: "void test(int A1, int A2) __attribute__((assert_capability(A1, A2)));",
7986 FromAttr, ToAttr);
7987 checkImportVariadicArg(From: FromAttr->args(), To: ToAttr->args());
7988}
7989
7990TEST_P(ImportAttributes, ImportAcquireCapability) {
7991 AcquireCapabilityAttr *FromAttr, *ToAttr;
7992 importAttr<FunctionDecl>(
7993 Code: "void test(int A1, int A2) __attribute__((acquire_capability(A1, A2)));",
7994 FromAttr, ToAttr);
7995 checkImportVariadicArg(From: FromAttr->args(), To: ToAttr->args());
7996}
7997
7998TEST_P(ImportAttributes, ImportTryAcquireCapability) {
7999 TryAcquireCapabilityAttr *FromAttr, *ToAttr;
8000 importAttr<FunctionDecl>(
8001 Code: "void test(int A1, int A2) __attribute__((try_acquire_capability(1, A1, "
8002 "A2)));",
8003 FromAttr, ToAttr);
8004 checkImported(From: FromAttr->getSuccessValue(), To: ToAttr->getSuccessValue());
8005 checkImportVariadicArg(From: FromAttr->args(), To: ToAttr->args());
8006}
8007
8008TEST_P(ImportAttributes, ImportReleaseCapability) {
8009 ReleaseCapabilityAttr *FromAttr, *ToAttr;
8010 importAttr<FunctionDecl>(
8011 Code: "void test(int A1, int A2) __attribute__((release_capability(A1, A2)));",
8012 FromAttr, ToAttr);
8013 checkImportVariadicArg(From: FromAttr->args(), To: ToAttr->args());
8014}
8015
8016TEST_P(ImportAttributes, ImportRequiresCapability) {
8017 RequiresCapabilityAttr *FromAttr, *ToAttr;
8018 importAttr<FunctionDecl>(
8019 Code: "void test(int A1, int A2) __attribute__((requires_capability(A1, A2)));",
8020 FromAttr, ToAttr);
8021 checkImportVariadicArg(From: FromAttr->args(), To: ToAttr->args());
8022}
8023
8024TEST_P(ImportAttributes, ImportNoThreadSafetyAnalysis) {
8025 NoThreadSafetyAnalysisAttr *FromAttr, *ToAttr;
8026 importAttr<FunctionDecl>(
8027 Code: "void test() __attribute__((no_thread_safety_analysis));", FromAttr,
8028 ToAttr);
8029}
8030
8031TEST_P(ImportAttributes, ImportGuardedBy) {
8032 GuardedByAttr *FromAttr, *ToAttr;
8033 importAttr<VarDecl>(
8034 Code: R"(
8035 int G;
8036 int test __attribute__((guarded_by(G)));
8037 )",
8038 FromAttr, ToAttr);
8039 checkImported(From: FromAttr->getArg(), To: ToAttr->getArg());
8040}
8041
8042TEST_P(ImportAttributes, ImportPtGuardedBy) {
8043 PtGuardedByAttr *FromAttr, *ToAttr;
8044 importAttr<VarDecl>(
8045 Code: R"(
8046 int G;
8047 int *test __attribute__((pt_guarded_by(G)));
8048 )",
8049 FromAttr, ToAttr);
8050 checkImported(From: FromAttr->getArg(), To: ToAttr->getArg());
8051}
8052
8053TEST_P(ImportAttributes, ImportAcquiredAfter) {
8054 AcquiredAfterAttr *FromAttr, *ToAttr;
8055 importAttr<VarDecl>(
8056 Code: R"(
8057 struct __attribute__((lockable)) L {};
8058 L A1;
8059 L A2;
8060 L test __attribute__((acquired_after(A1, A2)));
8061 )",
8062 FromAttr, ToAttr);
8063 checkImportVariadicArg(From: FromAttr->args(), To: ToAttr->args());
8064}
8065
8066TEST_P(ImportAttributes, ImportAcquiredBefore) {
8067 AcquiredBeforeAttr *FromAttr, *ToAttr;
8068 importAttr<VarDecl>(
8069 Code: R"(
8070 struct __attribute__((lockable)) L {};
8071 L A1;
8072 L A2;
8073 L test __attribute__((acquired_before(A1, A2)));
8074 )",
8075 FromAttr, ToAttr);
8076 checkImportVariadicArg(From: FromAttr->args(), To: ToAttr->args());
8077}
8078
8079TEST_P(ImportAttributes, ImportLockReturned) {
8080 LockReturnedAttr *FromAttr, *ToAttr;
8081 importAttr<FunctionDecl>(
8082 Code: "void test(int A1) __attribute__((lock_returned(A1)));", FromAttr,
8083 ToAttr);
8084 checkImported(From: FromAttr->getArg(), To: ToAttr->getArg());
8085}
8086
8087TEST_P(ImportAttributes, ImportLocksExcluded) {
8088 LocksExcludedAttr *FromAttr, *ToAttr;
8089 importAttr<FunctionDecl>(
8090 Code: "void test(int A1, int A2) __attribute__((locks_excluded(A1, A2)));",
8091 FromAttr, ToAttr);
8092 checkImportVariadicArg(From: FromAttr->args(), To: ToAttr->args());
8093}
8094
8095TEST_P(ImportAttributes, ImportReentrantCapability) {
8096 ReentrantCapabilityAttr *FromAttr, *ToAttr;
8097 importAttr<CXXRecordDecl>(
8098 Code: R"(
8099 struct __attribute__((capability("x"), reentrant_capability)) test {};
8100 )",
8101 FromAttr, ToAttr);
8102}
8103
8104TEST_P(ImportAttributes, ImportC99NoThrowAttr) {
8105 NoThrowAttr *FromAttr, *ToAttr;
8106 importAttr<FunctionDecl>(Code: "void test () __attribute__ ((__nothrow__));",
8107 FromAttr, ToAttr, Lang: Lang_C99);
8108 checkImported(From: FromAttr->getAttrName(), To: ToAttr->getAttrName());
8109}
8110
8111template <typename T>
8112auto ExtendWithOptions(const T &Values, const std::vector<std::string> &Args) {
8113 auto Copy = Values;
8114 for (std::vector<std::string> &ArgV : Copy) {
8115 for (const std::string &Arg : Args) {
8116 ArgV.push_back(x: Arg);
8117 }
8118 }
8119 return ::testing::ValuesIn(Copy);
8120}
8121
8122struct ImportWithExternalSource : ASTImporterOptionSpecificTestBase {
8123 ImportWithExternalSource() {
8124 Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
8125 ASTContext &FromContext, FileManager &FromFileManager,
8126 bool MinimalImport,
8127 const std::shared_ptr<ASTImporterSharedState> &SharedState) {
8128 return new ASTImporter(ToContext, ToFileManager, FromContext,
8129 // Use minimal import for these tests.
8130 FromFileManager, /*MinimalImport=*/true,
8131 // We use the regular lookup.
8132 /*SharedState=*/nullptr);
8133 };
8134 }
8135};
8136
8137/// An ExternalASTSource that keeps track of the tags is completed.
8138struct SourceWithCompletedTagList : clang::ExternalASTSource {
8139 std::vector<clang::TagDecl *> &CompletedTags;
8140 SourceWithCompletedTagList(std::vector<clang::TagDecl *> &CompletedTags)
8141 : CompletedTags(CompletedTags) {}
8142 void CompleteType(TagDecl *Tag) override {
8143 auto *Record = cast<CXXRecordDecl>(Val: Tag);
8144 Record->startDefinition();
8145 Record->completeDefinition();
8146 CompletedTags.push_back(x: Tag);
8147 }
8148 using clang::ExternalASTSource::CompleteType;
8149};
8150
8151TEST_P(ImportWithExternalSource, CompleteRecordBeforeImporting) {
8152 // Create an empty TU.
8153 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: "", Lang: Lang_CXX03, FileName: "input.cpp");
8154
8155 // Create and add the test ExternalASTSource.
8156 std::vector<clang::TagDecl *> CompletedTags;
8157 IntrusiveRefCntPtr<ExternalASTSource> source =
8158 new SourceWithCompletedTagList(CompletedTags);
8159 clang::ASTContext &Context = FromTU->getASTContext();
8160 Context.setExternalSource(std::move(source));
8161
8162 // Create a dummy class by hand with external lexical storage.
8163 IdentifierInfo &Ident = Context.Idents.get(Name: "test_class");
8164 auto *Record =
8165 CXXRecordDecl::Create(C: Context, TK: TagTypeKind::Class, DC: FromTU,
8166 StartLoc: SourceLocation(), IdLoc: SourceLocation(), Id: &Ident);
8167 Record->setHasExternalLexicalStorage();
8168 FromTU->addDecl(D: Record);
8169
8170 // Do a minimal import of the created class.
8171 EXPECT_EQ(0U, CompletedTags.size());
8172 Import(From: Record, Lang: Lang_CXX03);
8173 EXPECT_EQ(0U, CompletedTags.size());
8174
8175 // Import the definition of the created class.
8176 llvm::Error Err = findFromTU(From: Record)->Importer->ImportDefinition(From: Record);
8177 EXPECT_FALSE((bool)Err);
8178 consumeError(Err: std::move(Err));
8179
8180 // Make sure the class was completed once.
8181 EXPECT_EQ(1U, CompletedTags.size());
8182 EXPECT_EQ(Record, CompletedTags.front());
8183}
8184
8185TEST_P(ImportFunctions, CTADImplicit) {
8186 Decl *FromTU = getTuDecl(
8187 SrcCode: R"(
8188 template <typename T> struct A {
8189 A(T);
8190 };
8191 A a{(int)0};
8192 )",
8193 Lang: Lang_CXX17, FileName: "input.cc");
8194 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8195 D: FromTU,
8196 AMatcher: cxxDeductionGuideDecl(hasParameter(N: 0, InnerMatcher: hasType(InnerMatcher: asString(Name: "A<T>")))));
8197 auto *ToD = Import(From: FromD, Lang: Lang_CXX17);
8198 ASSERT_TRUE(ToD);
8199 EXPECT_EQ(ToD->getDeductionCandidateKind(), DeductionCandidate::Copy);
8200 EXPECT_EQ(ToD->getSourceDeductionGuide(), nullptr);
8201 EXPECT_EQ(ToD->getSourceDeductionGuideKind(),
8202 CXXDeductionGuideDecl::SourceDeductionGuideKind::None);
8203 // Check that the deduced class template is also imported.
8204 EXPECT_TRUE(findFromTU(FromD)->Importer->GetAlreadyImportedOrNull(
8205 FromD->getDeducedTemplate()));
8206}
8207
8208TEST_P(ImportFunctions, CTADUserDefinedExplicit) {
8209 Decl *FromTU = getTuDecl(
8210 SrcCode: R"(
8211 template <typename T> struct A {
8212 A(T);
8213 };
8214 template <typename T> explicit A(T) -> A<float>;
8215 A a{(int)0}; // calls A<float>::A(float)
8216 )",
8217 Lang: Lang_CXX17, FileName: "input.cc");
8218 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8219 D: FromTU, AMatcher: cxxDeductionGuideDecl(unless(isImplicit())));
8220 // Not-implicit: i.e. not compiler-generated, user defined.
8221 ASSERT_FALSE(FromD->isImplicit());
8222 ASSERT_TRUE(FromD->isExplicit()); // Has the explicit keyword.
8223 auto *ToD = Import(From: FromD, Lang: Lang_CXX17);
8224 ASSERT_TRUE(ToD);
8225 EXPECT_FALSE(FromD->isImplicit());
8226 EXPECT_TRUE(ToD->isExplicit());
8227 EXPECT_EQ(ToD->getSourceDeductionGuide(), nullptr);
8228 EXPECT_EQ(ToD->getSourceDeductionGuideKind(),
8229 CXXDeductionGuideDecl::SourceDeductionGuideKind::None);
8230}
8231
8232TEST_P(ImportFunctions, CTADWithLocalTypedef) {
8233 Decl *TU = getTuDecl(
8234 SrcCode: R"(
8235 template <typename T> struct A {
8236 typedef T U;
8237 A(U);
8238 };
8239 A a{(int)0};
8240 )",
8241 Lang: Lang_CXX17, FileName: "input.cc");
8242 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8243 D: TU, AMatcher: cxxDeductionGuideDecl());
8244 auto *ToD = Import(From: FromD, Lang: Lang_CXX17);
8245 ASSERT_TRUE(ToD);
8246}
8247
8248TEST_P(ImportFunctions, CTADAliasTemplate) {
8249 Decl *TU = getTuDecl(
8250 SrcCode: R"(
8251 template <typename T> struct A {
8252 A(T);
8253 };
8254 template<typename T>
8255 using B = A<T>;
8256 B b{(int)0};
8257 )",
8258 Lang: Lang_CXX20, FileName: "input.cc");
8259 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8260 D: TU, AMatcher: cxxDeductionGuideDecl(hasParameter(N: 0, InnerMatcher: hasType(InnerMatcher: asString(Name: "int")))));
8261 auto *ToD = Import(From: FromD, Lang: Lang_CXX20);
8262 ASSERT_TRUE(ToD);
8263 EXPECT_TRUE(ToD->getSourceDeductionGuideKind() ==
8264 CXXDeductionGuideDecl::SourceDeductionGuideKind::Alias);
8265 EXPECT_TRUE(ToD->getSourceDeductionGuide());
8266}
8267
8268TEST_P(ImportFunctions, CTADAliasTemplateWithExplicitSourceDeductionGuide) {
8269 Decl *TU = getTuDecl(
8270 SrcCode: R"(
8271 template <typename T> struct A {
8272 A(T);
8273 };
8274 template<typename T>
8275 using B = A<T>;
8276 A(int) -> A<double>; // explicit
8277 B b{(int)0};
8278 )",
8279 Lang: Lang_CXX20, FileName: "input.cc");
8280 auto *FromD = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8281 D: TU, AMatcher: cxxDeductionGuideDecl(hasParameter(N: 0, InnerMatcher: hasType(InnerMatcher: asString(Name: "int"))),
8282 hasName(Name: "<deduction guide for B>"),
8283 hasReturnTypeLoc(ReturnMatcher: loc(InnerMatcher: asString(Name: "A<double>")))));
8284 auto *ToD = Import(From: FromD, Lang: Lang_CXX20);
8285 ASSERT_TRUE(ToD);
8286 EXPECT_TRUE(ToD->getSourceDeductionGuideKind() ==
8287 CXXDeductionGuideDecl::SourceDeductionGuideKind::Alias);
8288 EXPECT_TRUE(ToD->getSourceDeductionGuide());
8289}
8290
8291TEST_P(ImportFunctions, ParmVarDeclDeclContext) {
8292 constexpr auto FromTUCode = R"(
8293 void f(int P);
8294 )";
8295 Decl *FromTU = getTuDecl(SrcCode: FromTUCode, Lang: Lang_CXX11);
8296 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
8297 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
8298 ASSERT_TRUE(FromF);
8299
8300 auto *ImportedF = Import(From: FromF, Lang: Lang_CXX11);
8301 EXPECT_TRUE(ImportedF);
8302 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
8303 ImportedF, ImportedF->getParamDecl(0)));
8304}
8305
8306// FIXME Move these tests out of ASTImporterTest. For that we need to factor
8307// out the ASTImporter specific pars from ASTImporterOptionSpecificTestBase
8308// into a new test Fixture. Then we should lift up this Fixture to its own
8309// implementation file and only then could we reuse the Fixture in other AST
8310// unitttests.
8311struct CTAD : ASTImporterOptionSpecificTestBase {};
8312
8313TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedef) {
8314 Decl *TU = getTuDecl(
8315 SrcCode: R"(
8316 typedef int U;
8317 template <typename T> struct A {
8318 A(U, T);
8319 };
8320 A a{(int)0, (int)0};
8321 )",
8322 Lang: Lang_CXX17, FileName: "input.cc");
8323 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8324 D: TU, AMatcher: cxxDeductionGuideDecl());
8325 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
8326 D: TU, AMatcher: typedefNameDecl(hasName(Name: "U")));
8327 ParmVarDecl *Param = Guide->getParamDecl(i: 0);
8328 // The type of the first param (which is a typedef) should match the typedef
8329 // in the global scope.
8330 EXPECT_EQ(Param->getType()->getAs<TypedefType>()->getDecl(), Typedef);
8331}
8332
8333TEST_P(CTAD, DeductionGuideShouldReferToANonLocalTypedefInParamPtr) {
8334 Decl *TU = getTuDecl(
8335 SrcCode: R"(
8336 typedef int U;
8337 template <typename T> struct A {
8338 A(U*, T);
8339 };
8340 A a{(int*)0, (int)0};
8341 )",
8342 Lang: Lang_CXX17, FileName: "input.cc");
8343 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8344 D: TU, AMatcher: cxxDeductionGuideDecl());
8345 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
8346 D: TU, AMatcher: typedefNameDecl(hasName(Name: "U")));
8347 ParmVarDecl *Param = Guide->getParamDecl(i: 0);
8348 EXPECT_EQ(Param->getType()
8349 ->getAs<PointerType>()
8350 ->getPointeeType()
8351 ->getAs<TypedefType>()
8352 ->getDecl(),
8353 Typedef);
8354}
8355
8356TEST_P(CTAD, DeductionGuideShouldCopyALocalTypedef) {
8357 Decl *TU = getTuDecl(
8358 SrcCode: R"(
8359 template <typename T> struct A {
8360 typedef T U;
8361 A(U, T);
8362 };
8363 A a{(int)0, (int)0};
8364 )",
8365 Lang: Lang_CXX17, FileName: "input.cc");
8366 auto *Guide = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8367 D: TU, AMatcher: cxxDeductionGuideDecl());
8368 auto *Typedef = FirstDeclMatcher<TypedefNameDecl>().match(
8369 D: TU, AMatcher: typedefNameDecl(hasName(Name: "U")));
8370 ParmVarDecl *Param = Guide->getParamDecl(i: 0);
8371 EXPECT_NE(Param->getType()->getAs<TypedefType>()->getDecl(), Typedef);
8372}
8373
8374INSTANTIATE_TEST_SUITE_P(ParameterizedTests, CTAD,
8375 DefaultTestValuesForRunOptions);
8376
8377TEST_P(ASTImporterOptionSpecificTestBase, TypedefWithAttribute) {
8378 Decl *TU = getTuDecl(
8379 SrcCode: R"(
8380 namespace N {
8381 typedef int X __attribute__((annotate("A")));
8382 }
8383 )",
8384 Lang: Lang_CXX17, FileName: "input.cc");
8385 auto *FromD =
8386 FirstDeclMatcher<TypedefDecl>().match(D: TU, AMatcher: typedefDecl(hasName(Name: "X")));
8387 auto *ToD = Import(From: FromD, Lang: Lang_CXX17);
8388 ASSERT_TRUE(ToD);
8389 ASSERT_EQ(ToD->getAttrs().size(), 1U);
8390 auto *ToAttr = dyn_cast<AnnotateAttr>(Val: ToD->getAttrs()[0]);
8391 ASSERT_TRUE(ToAttr);
8392 EXPECT_EQ(ToAttr->getAnnotation(), "A");
8393}
8394
8395TEST_P(ASTImporterOptionSpecificTestBase,
8396 ImportOfTemplatedDeclWhenPreviousDeclHasNoDescribedTemplateSet) {
8397 Decl *FromTU = getTuDecl(
8398 SrcCode: R"(
8399
8400 namespace std {
8401 template<typename T>
8402 class basic_stringbuf;
8403 }
8404 namespace std {
8405 class char_traits;
8406 template<typename T = char_traits>
8407 class basic_stringbuf;
8408 }
8409 namespace std {
8410 template<typename T>
8411 class basic_stringbuf {};
8412 }
8413
8414 )",
8415 Lang: Lang_CXX11);
8416
8417 auto *From1 = FirstDeclMatcher<ClassTemplateDecl>().match(
8418 D: FromTU,
8419 AMatcher: classTemplateDecl(hasName(Name: "basic_stringbuf"), unless(isImplicit())));
8420 auto *To1 = cast_or_null<ClassTemplateDecl>(Val: Import(From: From1, Lang: Lang_CXX11));
8421 EXPECT_TRUE(To1);
8422
8423 auto *From2 = LastDeclMatcher<ClassTemplateDecl>().match(
8424 D: FromTU,
8425 AMatcher: classTemplateDecl(hasName(Name: "basic_stringbuf"), unless(isImplicit())));
8426 auto *To2 = cast_or_null<ClassTemplateDecl>(Val: Import(From: From2, Lang: Lang_CXX11));
8427 EXPECT_TRUE(To2);
8428}
8429
8430TEST_P(ASTImporterOptionSpecificTestBase, ImportOfCapturedVLAType) {
8431 Decl *FromTU = getTuDecl(
8432 SrcCode: R"(
8433 void declToImport(int N) {
8434 int VLA[N];
8435 [&VLA] {}; // FieldDecl inside the lambda.
8436 }
8437 )",
8438 Lang: Lang_CXX14);
8439 auto *FromFD = FirstDeclMatcher<FieldDecl>().match(D: FromTU, AMatcher: fieldDecl());
8440 ASSERT_TRUE(FromFD);
8441 ASSERT_TRUE(FromFD->hasCapturedVLAType());
8442
8443 auto *ToFD = Import(From: FromFD, Lang: Lang_CXX14);
8444 EXPECT_TRUE(ToFD);
8445 EXPECT_TRUE(ToFD->hasCapturedVLAType());
8446 EXPECT_NE(FromFD->getCapturedVLAType(), ToFD->getCapturedVLAType());
8447}
8448
8449TEST_P(ASTImporterOptionSpecificTestBase, ImportEnumMemberSpecialization) {
8450 Decl *FromTU = getTuDecl(
8451 SrcCode: R"(
8452 template <class T> struct A {
8453 enum tagname { enumerator };
8454 };
8455 template struct A<int>;
8456 )",
8457 Lang: Lang_CXX03);
8458 auto *FromD = FirstDeclMatcher<EnumDecl>().match(
8459 D: FromTU, AMatcher: enumDecl(hasName(Name: "tagname"),
8460 hasParent(classTemplateSpecializationDecl())));
8461 ASSERT_TRUE(FromD);
8462 ASSERT_TRUE(FromD->getMemberSpecializationInfo());
8463
8464 auto *ToD = Import(From: FromD, Lang: Lang_CXX03);
8465 EXPECT_TRUE(ToD);
8466 EXPECT_TRUE(ToD->getMemberSpecializationInfo());
8467 EXPECT_EQ(FromD->getTemplateSpecializationKind(),
8468 ToD->getTemplateSpecializationKind());
8469}
8470
8471TEST_P(ASTImporterOptionSpecificTestBase, ImportIsInheritingConstructorBit) {
8472 Decl *FromTU = getTuDecl(
8473 SrcCode: R"(
8474 struct A {
8475 A(int);
8476 };
8477 struct B : A {
8478 using A::A; // Inherited ctor.
8479 };
8480 void f() {
8481 (B(0));
8482 }
8483 )",
8484 Lang: Lang_CXX11);
8485 auto *FromD = FirstDeclMatcher<CXXConstructorDecl>().match(
8486 D: FromTU, AMatcher: cxxConstructorDecl(isInheritingConstructor()));
8487 ASSERT_TRUE(FromD);
8488 ASSERT_TRUE(FromD->isInheritingConstructor());
8489
8490 auto *ToD = Import(From: FromD, Lang: Lang_CXX11);
8491 ASSERT_TRUE(ToD);
8492 EXPECT_TRUE(ToD->isInheritingConstructor());
8493}
8494
8495TEST_P(ASTImporterOptionSpecificTestBase, ImportConstructorUsingShadow) {
8496 TranslationUnitDecl *FromTU = getTuDecl(
8497 SrcCode: R"(
8498 struct A {
8499 A(int, int);
8500 };
8501 struct B : A {
8502 using A::A;
8503 };
8504 struct C : B {
8505 using B::B;
8506 };
8507 )",
8508 Lang: Lang_CXX11);
8509
8510 auto CheckAST = [](TranslationUnitDecl *TU, CXXRecordDecl *RecordC) {
8511 auto *RecordA = FirstDeclMatcher<CXXRecordDecl>().match(
8512 D: TU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
8513 auto *RecordB = FirstDeclMatcher<CXXRecordDecl>().match(
8514 D: TU, AMatcher: cxxRecordDecl(hasName(Name: "B")));
8515 auto *ConstrA = FirstDeclMatcher<CXXConstructorDecl>().match(
8516 D: TU, AMatcher: cxxConstructorDecl(hasParent(equalsNode(Other: RecordA)),
8517 parameterCountIs(N: 2)));
8518 auto *ShadowBA = cast<ConstructorUsingShadowDecl>(
8519 Val: FirstDeclMatcher<UsingShadowDecl>().match(
8520 D: TU, AMatcher: usingShadowDecl(hasParent(equalsNode(Other: RecordB)),
8521 hasTargetDecl(InnerMatcher: equalsNode(Other: ConstrA)))));
8522 auto *ShadowCA = cast<ConstructorUsingShadowDecl>(
8523 Val: FirstDeclMatcher<UsingShadowDecl>().match(
8524 D: TU, AMatcher: usingShadowDecl(hasParent(equalsNode(Other: RecordC)),
8525 hasTargetDecl(InnerMatcher: equalsNode(Other: ConstrA)))));
8526 EXPECT_EQ(ShadowBA->getTargetDecl(), ConstrA);
8527 EXPECT_EQ(ShadowBA->getNominatedBaseClass(), RecordA);
8528 EXPECT_EQ(ShadowBA->getConstructedBaseClass(), RecordA);
8529 EXPECT_EQ(ShadowBA->getNominatedBaseClassShadowDecl(), nullptr);
8530 EXPECT_EQ(ShadowBA->getConstructedBaseClassShadowDecl(), nullptr);
8531 EXPECT_FALSE(ShadowBA->constructsVirtualBase());
8532 EXPECT_EQ(ShadowCA->getTargetDecl(), ConstrA);
8533 EXPECT_EQ(ShadowCA->getNominatedBaseClass(), RecordB);
8534 EXPECT_EQ(ShadowCA->getConstructedBaseClass(), RecordB);
8535 EXPECT_EQ(ShadowCA->getNominatedBaseClassShadowDecl(), ShadowBA);
8536 EXPECT_EQ(ShadowCA->getConstructedBaseClassShadowDecl(), ShadowBA);
8537 EXPECT_FALSE(ShadowCA->constructsVirtualBase());
8538 };
8539
8540 auto *FromC = FirstDeclMatcher<CXXRecordDecl>().match(
8541 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "C")));
8542
8543 auto *ToC = Import(From: FromC, Lang: Lang_CXX11);
8544 TranslationUnitDecl *ToTU = ToC->getTranslationUnitDecl();
8545
8546 CheckAST(FromTU, FromC);
8547 CheckAST(ToTU, ToC);
8548}
8549
8550TEST_P(ASTImporterOptionSpecificTestBase,
8551 ImportFunctionDeclBitShouldNotOverwriteCtorDeclBits) {
8552 Decl *From, *To;
8553 std::tie(args&: From, args&: To) = getImportedDecl(
8554 FromSrcCode: R"s(
8555 struct A {
8556 A() : m() {}
8557 int m;
8558 };
8559
8560 A foo() { A a; return a; }
8561 A bar() { return {}; }
8562 )s",
8563 FromLang: Lang_CXX17,
8564 ToSrcCode: R"s(
8565 struct A {
8566 A() : m() {}
8567 int m;
8568 };
8569 A baz() { return {}; }
8570 )s",
8571 ToLang: Lang_CXX17, Identifier: "A");
8572
8573 auto HasCtorInit =
8574 hasAnyConstructorInitializer(InnerMatcher: cxxCtorInitializer(isMemberInitializer()));
8575 auto ImpMoveCtor =
8576 cxxConstructorDecl(isMoveConstructor(), isImplicit(), HasCtorInit);
8577
8578 auto *FromImpMoveCtor = FirstDeclMatcher<CXXConstructorDecl>().match(
8579 D: From, AMatcher: ImpMoveCtor);
8580 auto *ToImpMoveCtor = FirstDeclMatcher<CXXConstructorDecl>().match(
8581 D: To, AMatcher: ImpMoveCtor);
8582
8583 EXPECT_TRUE(FromImpMoveCtor->getNumCtorInitializers() == 1);
8584 EXPECT_FALSE(FromImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
8585
8586 EXPECT_TRUE(ToImpMoveCtor->getNumCtorInitializers() == 1);
8587 EXPECT_FALSE(ToImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
8588 EXPECT_TRUE(*ToImpMoveCtor->init_begin());
8589}
8590
8591AST_MATCHER_P(UsingShadowDecl, hasIntroducerDecl, internal::Matcher<NamedDecl>,
8592 InnerMatcher) {
8593 return InnerMatcher.matches(Node: *Node.getIntroducer(), Finder, Builder);
8594}
8595
8596TEST_P(ASTImporterOptionSpecificTestBase,
8597 ImportConstructorUsingShadowVirtualBase) {
8598 TranslationUnitDecl *FromTU = getTuDecl(
8599 SrcCode: R"(
8600 struct A { A(int, int); };
8601 struct B : A { using A::A; };
8602
8603 struct V1 : virtual B { using B::B; };
8604 struct V2 : virtual B { using B::B; };
8605
8606 struct D2 : V1, V2 {
8607 using V1::V1;
8608 using V2::V2;
8609 };
8610 )",
8611 Lang: Lang_CXX11);
8612
8613 auto CheckAST = [](TranslationUnitDecl *TU, CXXRecordDecl *RecordD2) {
8614 auto *RecordA = FirstDeclMatcher<CXXRecordDecl>().match(
8615 D: TU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
8616 auto *RecordB = FirstDeclMatcher<CXXRecordDecl>().match(
8617 D: TU, AMatcher: cxxRecordDecl(hasName(Name: "B")));
8618 auto *RecordV1 = FirstDeclMatcher<CXXRecordDecl>().match(
8619 D: TU, AMatcher: cxxRecordDecl(hasName(Name: "V1")));
8620 auto *RecordV2 = FirstDeclMatcher<CXXRecordDecl>().match(
8621 D: TU, AMatcher: cxxRecordDecl(hasName(Name: "V2")));
8622 auto *ConstrA = FirstDeclMatcher<CXXConstructorDecl>().match(
8623 D: TU, AMatcher: cxxConstructorDecl(hasParent(equalsNode(Other: RecordA)),
8624 parameterCountIs(N: 2)));
8625 auto *ConstrB = FirstDeclMatcher<CXXConstructorDecl>().match(
8626 D: TU, AMatcher: cxxConstructorDecl(hasParent(equalsNode(Other: RecordB)),
8627 isCopyConstructor()));
8628 auto *UsingD2V1 = FirstDeclMatcher<UsingDecl>().match(
8629 D: TU, AMatcher: usingDecl(hasParent(equalsNode(Other: RecordD2))));
8630 auto *UsingD2V2 = LastDeclMatcher<UsingDecl>().match(
8631 D: TU, AMatcher: usingDecl(hasParent(equalsNode(Other: RecordD2))));
8632 auto *ShadowBA = cast<ConstructorUsingShadowDecl>(
8633 Val: FirstDeclMatcher<UsingShadowDecl>().match(
8634 D: TU, AMatcher: usingShadowDecl(hasParent(equalsNode(Other: RecordB)),
8635 hasTargetDecl(InnerMatcher: equalsNode(Other: ConstrA)))));
8636 auto *ShadowV1A = cast<ConstructorUsingShadowDecl>(
8637 Val: FirstDeclMatcher<UsingShadowDecl>().match(
8638 D: TU, AMatcher: usingShadowDecl(hasParent(equalsNode(Other: RecordV1)),
8639 hasTargetDecl(InnerMatcher: equalsNode(Other: ConstrA)))));
8640 auto *ShadowV1B = cast<ConstructorUsingShadowDecl>(
8641 Val: FirstDeclMatcher<UsingShadowDecl>().match(
8642 D: TU, AMatcher: usingShadowDecl(hasParent(equalsNode(Other: RecordV1)),
8643 hasTargetDecl(InnerMatcher: equalsNode(Other: ConstrB)))));
8644 auto *ShadowV2A = cast<ConstructorUsingShadowDecl>(
8645 Val: FirstDeclMatcher<UsingShadowDecl>().match(
8646 D: TU, AMatcher: usingShadowDecl(hasParent(equalsNode(Other: RecordV2)),
8647 hasTargetDecl(InnerMatcher: equalsNode(Other: ConstrA)))));
8648 auto *ShadowV2B = cast<ConstructorUsingShadowDecl>(
8649 Val: FirstDeclMatcher<UsingShadowDecl>().match(
8650 D: TU, AMatcher: usingShadowDecl(hasParent(equalsNode(Other: RecordV2)),
8651 hasTargetDecl(InnerMatcher: equalsNode(Other: ConstrB)))));
8652 auto *ShadowD2V1A = cast<ConstructorUsingShadowDecl>(
8653 Val: FirstDeclMatcher<UsingShadowDecl>().match(
8654 D: TU, AMatcher: usingShadowDecl(hasParent(equalsNode(Other: RecordD2)),
8655 hasIntroducerDecl(InnerMatcher: equalsNode(Other: UsingD2V1)),
8656 hasTargetDecl(InnerMatcher: equalsNode(Other: ConstrA)))));
8657 auto *ShadowD2V1B = cast<ConstructorUsingShadowDecl>(
8658 Val: FirstDeclMatcher<UsingShadowDecl>().match(
8659 D: TU, AMatcher: usingShadowDecl(hasParent(equalsNode(Other: RecordD2)),
8660 hasIntroducerDecl(InnerMatcher: equalsNode(Other: UsingD2V1)),
8661 hasTargetDecl(InnerMatcher: equalsNode(Other: ConstrB)))));
8662 auto *ShadowD2V2A = cast<ConstructorUsingShadowDecl>(
8663 Val: FirstDeclMatcher<UsingShadowDecl>().match(
8664 D: TU, AMatcher: usingShadowDecl(hasParent(equalsNode(Other: RecordD2)),
8665 hasIntroducerDecl(InnerMatcher: equalsNode(Other: UsingD2V2)),
8666 hasTargetDecl(InnerMatcher: equalsNode(Other: ConstrA)))));
8667 auto *ShadowD2V2B = cast<ConstructorUsingShadowDecl>(
8668 Val: FirstDeclMatcher<UsingShadowDecl>().match(
8669 D: TU, AMatcher: usingShadowDecl(hasParent(equalsNode(Other: RecordD2)),
8670 hasIntroducerDecl(InnerMatcher: equalsNode(Other: UsingD2V2)),
8671 hasTargetDecl(InnerMatcher: equalsNode(Other: ConstrB)))));
8672
8673 EXPECT_EQ(ShadowD2V1A->getTargetDecl(), ConstrA);
8674 EXPECT_EQ(ShadowD2V1A->getNominatedBaseClassShadowDecl(), ShadowV1A);
8675 EXPECT_EQ(ShadowD2V1A->getNominatedBaseClass(), RecordV1);
8676 EXPECT_EQ(ShadowD2V1A->getConstructedBaseClassShadowDecl(), ShadowBA);
8677 EXPECT_EQ(ShadowD2V1A->getConstructedBaseClass(), RecordB);
8678 EXPECT_TRUE(ShadowD2V1A->constructsVirtualBase());
8679 EXPECT_EQ(ShadowD2V1B->getTargetDecl(), ConstrB);
8680 EXPECT_EQ(ShadowD2V1B->getNominatedBaseClassShadowDecl(), ShadowV1B);
8681 EXPECT_EQ(ShadowD2V1B->getNominatedBaseClass(), RecordV1);
8682 EXPECT_EQ(ShadowD2V1B->getConstructedBaseClassShadowDecl(), nullptr);
8683 EXPECT_EQ(ShadowD2V1B->getConstructedBaseClass(), RecordB);
8684 EXPECT_TRUE(ShadowD2V1B->constructsVirtualBase());
8685 EXPECT_EQ(ShadowD2V2A->getTargetDecl(), ConstrA);
8686 EXPECT_EQ(ShadowD2V2A->getNominatedBaseClassShadowDecl(), ShadowV2A);
8687 EXPECT_EQ(ShadowD2V2A->getNominatedBaseClass(), RecordV2);
8688 EXPECT_EQ(ShadowD2V2A->getConstructedBaseClassShadowDecl(), ShadowBA);
8689 EXPECT_EQ(ShadowD2V2A->getConstructedBaseClass(), RecordB);
8690 EXPECT_TRUE(ShadowD2V2A->constructsVirtualBase());
8691 EXPECT_EQ(ShadowD2V2B->getTargetDecl(), ConstrB);
8692 EXPECT_EQ(ShadowD2V2B->getNominatedBaseClassShadowDecl(), ShadowV2B);
8693 EXPECT_EQ(ShadowD2V2B->getNominatedBaseClass(), RecordV2);
8694 EXPECT_EQ(ShadowD2V2B->getConstructedBaseClassShadowDecl(), nullptr);
8695 EXPECT_EQ(ShadowD2V2B->getConstructedBaseClass(), RecordB);
8696 EXPECT_TRUE(ShadowD2V2B->constructsVirtualBase());
8697
8698 EXPECT_TRUE(ShadowV1A->constructsVirtualBase());
8699 EXPECT_TRUE(ShadowV1B->constructsVirtualBase());
8700 EXPECT_TRUE(ShadowV2A->constructsVirtualBase());
8701 EXPECT_TRUE(ShadowV2B->constructsVirtualBase());
8702 EXPECT_FALSE(ShadowBA->constructsVirtualBase());
8703 };
8704
8705 auto *FromD2 = FirstDeclMatcher<CXXRecordDecl>().match(
8706 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "D2")));
8707
8708 auto *ToD2 = Import(From: FromD2, Lang: Lang_CXX11);
8709 TranslationUnitDecl *ToTU = ToD2->getTranslationUnitDecl();
8710
8711 CheckAST(FromTU, FromD2);
8712 CheckAST(ToTU, ToD2);
8713}
8714
8715TEST_P(ASTImporterOptionSpecificTestBase, ImportUsingShadowList) {
8716 TranslationUnitDecl *FromTU = getTuDecl(
8717 SrcCode: R"(
8718 struct A {
8719 void f();
8720 void f(int);
8721 };
8722 struct B : A {
8723 using A::f;
8724 };
8725 )",
8726 Lang: Lang_CXX11);
8727
8728 auto *FromB = FirstDeclMatcher<CXXRecordDecl>().match(
8729 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "B")));
8730
8731 auto *ToB = Import(From: FromB, Lang: Lang_CXX11);
8732 TranslationUnitDecl *ToTU = ToB->getTranslationUnitDecl();
8733
8734 auto *ToUsing = FirstDeclMatcher<UsingDecl>().match(
8735 D: ToTU, AMatcher: usingDecl(hasParent(equalsNode(Other: ToB))));
8736 auto *ToUsingShadowF1 = FirstDeclMatcher<UsingShadowDecl>().match(
8737 D: ToTU, AMatcher: usingShadowDecl(hasTargetDecl(
8738 InnerMatcher: functionDecl(hasName(Name: "f"), parameterCountIs(N: 0)))));
8739 auto *ToUsingShadowF2 = FirstDeclMatcher<UsingShadowDecl>().match(
8740 D: ToTU, AMatcher: usingShadowDecl(hasTargetDecl(
8741 InnerMatcher: functionDecl(hasName(Name: "f"), parameterCountIs(N: 1)))));
8742
8743 EXPECT_EQ(ToUsing->shadow_size(), 2u);
8744 auto ShadowI = ToUsing->shadow_begin();
8745 EXPECT_EQ(*ShadowI, ToUsingShadowF1);
8746 ++ShadowI;
8747 EXPECT_EQ(*ShadowI, ToUsingShadowF2);
8748}
8749
8750AST_MATCHER_P(FunctionTemplateDecl, templateParameterCountIs, unsigned, Cnt) {
8751 return Node.getTemplateParameters()->size() == Cnt;
8752}
8753
8754TEST_P(ASTImporterOptionSpecificTestBase, ImportDeductionGuide) {
8755 TranslationUnitDecl *FromTU = getTuDecl(
8756 SrcCode: R"(
8757 template<class> class A { };
8758 template<class T> class B {
8759 template<class T1, typename = A<T>> B(T1);
8760 };
8761 template<class T>
8762 B(T, T) -> B<int>;
8763 )",
8764 Lang: Lang_CXX17);
8765
8766 // Get the implicit deduction guide for (non-default) constructor of 'B'.
8767 auto *FromDGCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(
8768 D: FromTU, AMatcher: functionTemplateDecl(templateParameterCountIs(Cnt: 3)));
8769 // Implicit deduction guide for copy constructor of 'B'.
8770 auto *FromDGCopyCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(
8771 D: FromTU, AMatcher: functionTemplateDecl(templateParameterCountIs(Cnt: 1), isImplicit()));
8772 // User defined deduction guide.
8773 auto *FromDGOther = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8774 D: FromTU, AMatcher: cxxDeductionGuideDecl(unless(isImplicit())));
8775
8776 TemplateParameterList *FromDGCtorTP = FromDGCtor->getTemplateParameters();
8777 // Don't know why exactly but this is the DeclContext here.
8778 EXPECT_EQ(FromDGCtorTP->getParam(0)->getDeclContext(),
8779 FromDGCopyCtor->getTemplatedDecl());
8780 EXPECT_EQ(FromDGCtorTP->getParam(1)->getDeclContext(),
8781 FromDGCtor->getTemplatedDecl());
8782 EXPECT_EQ(FromDGCtorTP->getParam(2)->getDeclContext(),
8783 FromDGCtor->getTemplatedDecl());
8784 EXPECT_EQ(
8785 FromDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),
8786 FromDGCopyCtor->getTemplatedDecl());
8787 EXPECT_EQ(FromDGOther->getDescribedTemplate()
8788 ->getTemplateParameters()
8789 ->getParam(0)
8790 ->getDeclContext(),
8791 FromDGOther);
8792
8793 auto *ToDGCtor = Import(From: FromDGCtor, Lang: Lang_CXX17);
8794 auto *ToDGCopyCtor = Import(From: FromDGCopyCtor, Lang: Lang_CXX17);
8795 auto *ToDGOther = Import(From: FromDGOther, Lang: Lang_CXX17);
8796 ASSERT_TRUE(ToDGCtor);
8797 ASSERT_TRUE(ToDGCopyCtor);
8798 ASSERT_TRUE(ToDGOther);
8799
8800 TemplateParameterList *ToDGCtorTP = ToDGCtor->getTemplateParameters();
8801 EXPECT_EQ(ToDGCtorTP->getParam(0)->getDeclContext(),
8802 ToDGCopyCtor->getTemplatedDecl());
8803 EXPECT_EQ(ToDGCtorTP->getParam(1)->getDeclContext(),
8804 ToDGCtor->getTemplatedDecl());
8805 EXPECT_EQ(ToDGCtorTP->getParam(2)->getDeclContext(),
8806 ToDGCtor->getTemplatedDecl());
8807 EXPECT_EQ(
8808 ToDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),
8809 ToDGCopyCtor->getTemplatedDecl());
8810 EXPECT_EQ(ToDGOther->getDescribedTemplate()
8811 ->getTemplateParameters()
8812 ->getParam(0)
8813 ->getDeclContext(),
8814 ToDGOther);
8815}
8816
8817TEST_P(ASTImporterOptionSpecificTestBase, ImportDeductionGuideDifferentOrder) {
8818 // This test demonstrates that the DeclContext of the imported object is
8819 // dependent on the order of import. The test is an exact copy of the previous
8820 // one except at the indicated locations.
8821 TranslationUnitDecl *FromTU = getTuDecl(
8822 SrcCode: R"(
8823 template<class> class A { };
8824 template<class T> class B {
8825 template<class T1, typename = A<T>> B(T1);
8826 };
8827 template<class T>
8828 B(T, T) -> B<int>;
8829 )",
8830 Lang: Lang_CXX17);
8831
8832 // Get the implicit deduction guide for (non-default) constructor of 'B'.
8833 auto *FromDGCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(
8834 D: FromTU, AMatcher: functionTemplateDecl(templateParameterCountIs(Cnt: 3)));
8835 // Implicit deduction guide for copy constructor of 'B'.
8836 auto *FromDGCopyCtor = FirstDeclMatcher<FunctionTemplateDecl>().match(
8837 D: FromTU, AMatcher: functionTemplateDecl(templateParameterCountIs(Cnt: 1), isImplicit()));
8838 // User defined deduction guide.
8839 auto *FromDGOther = FirstDeclMatcher<CXXDeductionGuideDecl>().match(
8840 D: FromTU, AMatcher: cxxDeductionGuideDecl(unless(isImplicit())));
8841
8842 TemplateParameterList *FromDGCtorTP = FromDGCtor->getTemplateParameters();
8843 // Don't know why exactly but this is the DeclContext here.
8844 EXPECT_EQ(FromDGCtorTP->getParam(0)->getDeclContext(),
8845 FromDGCopyCtor->getTemplatedDecl());
8846 EXPECT_EQ(FromDGCtorTP->getParam(1)->getDeclContext(),
8847 FromDGCtor->getTemplatedDecl());
8848 EXPECT_EQ(FromDGCtorTP->getParam(2)->getDeclContext(),
8849 FromDGCtor->getTemplatedDecl());
8850 EXPECT_EQ(
8851 FromDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),
8852 FromDGCopyCtor->getTemplatedDecl());
8853 EXPECT_EQ(FromDGOther->getDescribedTemplate()
8854 ->getTemplateParameters()
8855 ->getParam(0)
8856 ->getDeclContext(),
8857 FromDGOther);
8858
8859 // Here the import of 'ToDGCopyCtor' and 'ToDGCtor' is reversed relative to
8860 // the previous test.
8861 auto *ToDGCopyCtor = Import(From: FromDGCopyCtor, Lang: Lang_CXX17);
8862 auto *ToDGCtor = Import(From: FromDGCtor, Lang: Lang_CXX17);
8863 auto *ToDGOther = Import(From: FromDGOther, Lang: Lang_CXX17);
8864 ASSERT_TRUE(ToDGCtor);
8865 ASSERT_TRUE(ToDGCopyCtor);
8866 ASSERT_TRUE(ToDGOther);
8867
8868 TemplateParameterList *ToDGCtorTP = ToDGCtor->getTemplateParameters();
8869 // Next line: DeclContext is different relative to the previous test.
8870 EXPECT_EQ(ToDGCtorTP->getParam(0)->getDeclContext(),
8871 ToDGCtor->getTemplatedDecl());
8872 EXPECT_EQ(ToDGCtorTP->getParam(1)->getDeclContext(),
8873 ToDGCtor->getTemplatedDecl());
8874 EXPECT_EQ(ToDGCtorTP->getParam(2)->getDeclContext(),
8875 ToDGCtor->getTemplatedDecl());
8876 // Next line: DeclContext is different relative to the previous test.
8877 EXPECT_EQ(
8878 ToDGCopyCtor->getTemplateParameters()->getParam(0)->getDeclContext(),
8879 ToDGCtor->getTemplatedDecl());
8880 EXPECT_EQ(ToDGOther->getDescribedTemplate()
8881 ->getTemplateParameters()
8882 ->getParam(0)
8883 ->getDeclContext(),
8884 ToDGOther);
8885}
8886
8887TEST_P(ASTImporterOptionSpecificTestBase,
8888 ImportFieldsFirstForCorrectRecordLayout) {
8889 // UnaryOperator(&) triggers RecordLayout computation, which relies on
8890 // correctly imported fields.
8891 auto Code =
8892 R"(
8893 class A {
8894 int m() {
8895 return &((A *)0)->f1 - &((A *)0)->f2;
8896 }
8897 int f1;
8898 int f2;
8899 };
8900 )";
8901 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
8902
8903 auto *FromF = FirstDeclMatcher<CXXMethodDecl>().match(
8904 D: FromTU, AMatcher: cxxMethodDecl(hasName(Name: "A::m")));
8905 Import(From: FromF, Lang: Lang_CXX11);
8906}
8907
8908TEST_P(ASTImporterOptionSpecificTestBase,
8909 ImportCirularRefFieldsWithoutCorruptedRecordLayoutCache) {
8910 // Import sequence: A => A.b => B => B.f() => ... => UnaryOperator(&) => ...
8911 //
8912 // UnaryOperator(&) should not introduce invalid RecordLayout since 'A' is
8913 // still not completely imported.
8914 auto Code =
8915 R"(
8916 class B;
8917 class A {
8918 B* b;
8919 int c;
8920 };
8921 class B {
8922 A *f() { return &((B *)0)->a; }
8923 A a;
8924 };
8925 )";
8926
8927 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
8928 D: getTuDecl(SrcCode: Code, Lang: Lang_CXX11), AMatcher: cxxRecordDecl(hasName(Name: "A")));
8929 FromR = FromR->getDefinition();
8930 auto &FromAST = FromR->getASTContext();
8931 auto *ToR = Import(From: FromR, Lang: Lang_CXX11);
8932 auto &ToAST = ToR->getASTContext();
8933
8934 uint64_t SecondFieldOffset = FromAST.getTypeSize(T: FromAST.VoidPtrTy);
8935
8936 EXPECT_TRUE(FromR->isCompleteDefinition());
8937 const auto &FromLayout = FromAST.getASTRecordLayout(D: FromR);
8938 EXPECT_TRUE(FromLayout.getFieldOffset(0) == 0);
8939 EXPECT_TRUE(FromLayout.getFieldOffset(1) == SecondFieldOffset);
8940
8941 EXPECT_TRUE(ToR->isCompleteDefinition());
8942 const auto &ToLayout = ToAST.getASTRecordLayout(D: ToR);
8943 EXPECT_TRUE(ToLayout.getFieldOffset(0) == 0);
8944 EXPECT_TRUE(ToLayout.getFieldOffset(1) == SecondFieldOffset);
8945}
8946
8947TEST_P(ASTImporterOptionSpecificTestBase,
8948 ImportRecordWithLayoutRequestingExpr) {
8949 TranslationUnitDecl *FromTU = getTuDecl(
8950 SrcCode: R"(
8951 struct A {
8952 int idx;
8953 static void foo(A x) {
8954 (void)&"text"[x.idx];
8955 }
8956 };
8957 )",
8958 Lang: Lang_CXX11);
8959
8960 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
8961 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
8962
8963 // Test that during import of 'foo' the record layout can be obtained without
8964 // crash.
8965 auto *ToA = Import(From: FromA, Lang: Lang_CXX11);
8966 EXPECT_TRUE(ToA);
8967 EXPECT_TRUE(ToA->isCompleteDefinition());
8968}
8969
8970TEST_P(ASTImporterOptionSpecificTestBase,
8971 ImportRecordWithLayoutRequestingExprDifferentRecord) {
8972 TranslationUnitDecl *FromTU = getTuDecl(
8973 SrcCode: R"(
8974 struct B;
8975 struct A {
8976 int idx;
8977 B *b;
8978 };
8979 struct B {
8980 static void foo(A x) {
8981 (void)&"text"[x.idx];
8982 }
8983 };
8984 )",
8985 Lang: Lang_CXX11);
8986
8987 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
8988 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
8989
8990 // Test that during import of 'foo' the record layout (of 'A') can be obtained
8991 // without crash. It is not possible to have all of the fields of 'A' imported
8992 // at that time (without big code changes).
8993 auto *ToA = Import(From: FromA, Lang: Lang_CXX11);
8994 EXPECT_TRUE(ToA);
8995 EXPECT_TRUE(ToA->isCompleteDefinition());
8996}
8997
8998TEST_P(ASTImporterOptionSpecificTestBase, ImportInClassInitializerFromField) {
8999 // Encounter import of a field when the field already exists but has the
9000 // in-class initializer expression not yet set. Such case can occur in the AST
9001 // of generated template specializations.
9002 // The first code forces to create a template specialization of
9003 // `A<int>` but without implicit constructors.
9004 // The second ("From") code contains a variable of type `A<int>`, this
9005 // results in a template specialization that has constructors and
9006 // CXXDefaultInitExpr nodes.
9007 Decl *ToTU = getToTuDecl(
9008 ToSrcCode: R"(
9009 void f();
9010 template<typename> struct A { int X = 1; };
9011 struct B { A<int> Y; };
9012 )",
9013 ToLang: Lang_CXX11);
9014 auto *ToX = FirstDeclMatcher<FieldDecl>().match(
9015 D: ToTU,
9016 AMatcher: fieldDecl(hasName(Name: "X"), hasParent(classTemplateSpecializationDecl())));
9017 ASSERT_TRUE(ToX->hasInClassInitializer());
9018 ASSERT_FALSE(ToX->getInClassInitializer());
9019
9020 Decl *FromTU = getTuDecl(
9021 SrcCode: R"(
9022 void f();
9023 template<typename> struct A { int X = 1; };
9024 struct B { A<int> Y; };
9025 //
9026 A<int> Z;
9027 )",
9028 Lang: Lang_CXX11, FileName: "input1.cc");
9029 auto *FromX = FirstDeclMatcher<FieldDecl>().match(
9030 D: FromTU,
9031 AMatcher: fieldDecl(hasName(Name: "X"), hasParent(classTemplateSpecializationDecl())));
9032
9033 auto *ToXImported = Import(From: FromX, Lang: Lang_CXX11);
9034 EXPECT_EQ(ToXImported, ToX);
9035 EXPECT_TRUE(ToX->getInClassInitializer());
9036}
9037
9038TEST_P(ASTImporterOptionSpecificTestBase,
9039 ImportInClassInitializerFromCXXDefaultInitExpr) {
9040 // Encounter AST import of a CXXDefaultInitExpr where the "to-field"
9041 // of it exists but has the in-class initializer not set yet.
9042 Decl *ToTU = getToTuDecl(
9043 ToSrcCode: R"(
9044 namespace N {
9045 template<typename> int b;
9046 struct X;
9047 }
9048 template<typename> struct A { N::X *X = nullptr; };
9049 struct B { A<int> Y; };
9050 )",
9051 ToLang: Lang_CXX14);
9052 auto *ToX = FirstDeclMatcher<FieldDecl>().match(
9053 D: ToTU,
9054 AMatcher: fieldDecl(hasName(Name: "X"), hasParent(classTemplateSpecializationDecl())));
9055 ASSERT_TRUE(ToX->hasInClassInitializer());
9056 ASSERT_FALSE(ToX->getInClassInitializer());
9057
9058 Decl *FromTU = getTuDecl(
9059 SrcCode: R"(
9060 namespace N {
9061 template<typename> int b;
9062 struct X;
9063 }
9064 template<typename> struct A { N::X *X = nullptr; };
9065 struct B { A<int> Y; };
9066 //
9067 void f() {
9068 (void)A<int>{};
9069 }
9070 struct C {
9071 C(): attr(new A<int>{}){}
9072 A<int> *attr;
9073 const int value = N::b<C>;
9074 };
9075 )",
9076 Lang: Lang_CXX14, FileName: "input1.cc");
9077 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
9078 D: FromTU, AMatcher: functionDecl(hasName(Name: "f"), isDefinition()));
9079 auto *ToF = Import(From: FromF, Lang: Lang_CXX11);
9080 EXPECT_TRUE(ToF);
9081 EXPECT_TRUE(ToX->getInClassInitializer());
9082}
9083
9084TEST_P(ASTImporterOptionSpecificTestBase, ImportRecursiveFieldInitializer) {
9085 const char *Code =
9086 R"(
9087 struct AP_TECS;
9088
9089 struct AP_Landing {
9090 AP_TECS *TECS_controller;
9091 };
9092
9093 struct AP_TECS {
9094 AP_Landing landing;
9095 };
9096
9097 class Plane {
9098 AP_TECS TECS_controller{landing};
9099 AP_Landing landing{&TECS_controller};
9100 };
9101 )";
9102 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9103
9104 auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match(
9105 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "Plane")));
9106 for (FieldDecl *F : FromR->fields())
9107 EXPECT_TRUE(F->getInClassInitializer());
9108 auto *ToR = Import(From: FromR, Lang: Lang_CXX11);
9109 for (FieldDecl *F : ToR->fields())
9110 EXPECT_TRUE(F->getInClassInitializer());
9111}
9112
9113TEST_P(ASTImporterOptionSpecificTestBase, ImportFieldInitializerWithItself) {
9114 const char *Code =
9115 R"(
9116 class A {
9117 int a{a};
9118 };
9119 )";
9120 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9121 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9122 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
9123 EXPECT_TRUE(FromA->field_begin()->getInClassInitializer());
9124 auto *ToA = Import(From: FromA, Lang: Lang_CXX11);
9125 EXPECT_TRUE(ToA->field_begin()->getInClassInitializer());
9126}
9127
9128TEST_P(ASTImporterOptionSpecificTestBase, ImportRecursiveFieldInitializer1) {
9129 // FIXME: This is a example of recursive field initialization that is not
9130 // supported.
9131 // The following import chain occurs (not complete):
9132 // import of A => A.a => in-class initializer of A.a => ref_B() => B => B.b
9133 // => in-class initializer of B.b => ref_A() => CXXConstructExpr for A =>
9134 // CXXDefaultInitExpr for A.a => in-class initializer of A.a
9135 // in-class initializer of A.a is created in two different instances in this
9136 // case (import of FieldDecl and CXXDefaultInitExpr). Probably not a big
9137 // problem because it is an Expr (the second construction can be ignored
9138 // instead of assert). But such recursive init code should not occur in
9139 // practice.
9140 const char *Code =
9141 R"(
9142 static int ref_A();
9143 static int ref_B();
9144 struct A {
9145 int a = ref_B();
9146 };
9147 struct B {
9148 int b = ref_A();
9149 };
9150 int ref_B() { B b; return b.b; }
9151 int ref_A() { A a; return a.a; }
9152 )";
9153 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9154 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9155 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
9156 EXPECT_TRUE(FromA->field_begin()->getInClassInitializer());
9157 // auto *ToA = Import(FromA, Lang_CXX11);
9158 // EXPECT_TRUE(ToA->field_begin()->getInClassInitializer());
9159}
9160
9161TEST_P(ASTImporterOptionSpecificTestBase, isNewDecl) {
9162 Decl *FromTU = getTuDecl(
9163 SrcCode: R"(
9164 int bar() {
9165 return 0;
9166 }
9167 void other() {
9168 bar();
9169 }
9170 )",
9171 Lang: Lang_CXX11);
9172 Decl *ToTU = getToTuDecl(
9173 ToSrcCode: R"(
9174 int bar() {
9175 return 0;
9176 }
9177 )",
9178 ToLang: Lang_CXX11);
9179 auto *FromOther = FirstDeclMatcher<FunctionDecl>().match(
9180 D: FromTU, AMatcher: functionDecl(hasName(Name: "other")));
9181 ASSERT_TRUE(FromOther);
9182
9183 auto *ToOther = Import(From: FromOther, Lang: Lang_CXX11);
9184 ASSERT_TRUE(ToOther);
9185
9186 auto *ToBar = FirstDeclMatcher<FunctionDecl>().match(
9187 D: ToTU, AMatcher: functionDecl(hasName(Name: "bar")));
9188
9189 EXPECT_TRUE(SharedStatePtr->isNewDecl(ToOther));
9190 EXPECT_FALSE(SharedStatePtr->isNewDecl(ToBar));
9191}
9192
9193struct ImportInjectedClassNameType : public ASTImporterOptionSpecificTestBase {
9194protected:
9195 const CXXRecordDecl *findInjected(const CXXRecordDecl *Parent) {
9196 for (Decl *Found : Parent->decls()) {
9197 const auto *Record = dyn_cast<CXXRecordDecl>(Val: Found);
9198 if (Record && Record->isInjectedClassName())
9199 return Record;
9200 }
9201 return nullptr;
9202 }
9203
9204 void checkInjType(const CXXRecordDecl *D) {
9205 // The whole redecl chain should have the same InjectedClassNameType
9206 // instance. The injected record declaration is a separate chain, this
9207 // should contain the same type too.
9208 const Type *Ty = nullptr;
9209 for (const Decl *ReD : D->redecls()) {
9210 const auto *ReRD = cast<CXXRecordDecl>(Val: ReD);
9211 EXPECT_TRUE(ReRD->getTypeForDecl());
9212 EXPECT_TRUE(!Ty || Ty == ReRD->getTypeForDecl());
9213 Ty = ReRD->getTypeForDecl();
9214 }
9215 ASSERT_TRUE(Ty);
9216 const auto *InjTy = Ty->castAs<InjectedClassNameType>();
9217 EXPECT_TRUE(InjTy);
9218 if (CXXRecordDecl *Def = D->getDefinition()) {
9219 const CXXRecordDecl *InjRD = findInjected(Parent: Def);
9220 EXPECT_TRUE(InjRD);
9221 EXPECT_EQ(InjRD->getTypeForDecl(), InjTy);
9222 }
9223 }
9224
9225 void testImport(Decl *ToTU, Decl *FromTU, Decl *FromD) {
9226 checkInjType(D: cast<CXXRecordDecl>(Val: FromD));
9227 Decl *ToD = Import(From: FromD, ToLang: Lang_CXX11);
9228 if (auto *ToRD = dyn_cast<CXXRecordDecl>(Val: ToD))
9229 checkInjType(D: ToRD);
9230 }
9231
9232 const char *ToCodeA =
9233 R"(
9234 template <class T>
9235 struct A;
9236 )";
9237 const char *ToCodeADef =
9238 R"(
9239 template <class T>
9240 struct A {
9241 typedef A T1;
9242 };
9243 )";
9244 const char *ToCodeC =
9245 R"(
9246 template <class T>
9247 struct C;
9248 )";
9249 const char *ToCodeCDef =
9250 R"(
9251 template <class T>
9252 struct A {
9253 typedef A T1;
9254 };
9255
9256 template <class T1, class T2>
9257 struct B {};
9258
9259 template<class T>
9260 struct C {
9261 typedef typename A<T>::T1 T1;
9262 typedef B<T1, T> T2;
9263 typedef B<T1, C> T3;
9264 };
9265 )";
9266 const char *FromCode =
9267 R"(
9268 template <class T>
9269 struct A;
9270 template <class T>
9271 struct A {
9272 typedef A T1;
9273 };
9274 template <class T>
9275 struct A;
9276
9277 template <class T1, class T2>
9278 struct B {};
9279
9280 template <class T>
9281 struct C;
9282 template <class T>
9283 struct C {
9284 typedef typename A<T>::T1 T1;
9285 typedef B<T1, T> T2;
9286 typedef B<T1, C> T3;
9287 };
9288 template <class T>
9289 struct C;
9290
9291 template <class T>
9292 struct D {
9293 void f(typename C<T>::T3 *);
9294 };
9295 )";
9296};
9297
9298TEST_P(ImportInjectedClassNameType, ImportADef) {
9299 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeA, ToLang: Lang_CXX11);
9300 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9301 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9302 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A"), isDefinition()));
9303 testImport(ToTU, FromTU, FromD: FromA);
9304}
9305
9306TEST_P(ImportInjectedClassNameType, ImportAFirst) {
9307 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeA, ToLang: Lang_CXX11);
9308 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9309 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9310 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
9311 testImport(ToTU, FromTU, FromD: FromA);
9312}
9313
9314TEST_P(ImportInjectedClassNameType, ImportALast) {
9315 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeA, ToLang: Lang_CXX11);
9316 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9317 auto *FromA = LastDeclMatcher<CXXRecordDecl>().match(
9318 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
9319 testImport(ToTU, FromTU, FromD: FromA);
9320}
9321
9322TEST_P(ImportInjectedClassNameType, ImportADefToDef) {
9323 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeADef, ToLang: Lang_CXX11);
9324 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9325 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9326 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A"), isDefinition()));
9327 testImport(ToTU, FromTU, FromD: FromA);
9328}
9329
9330TEST_P(ImportInjectedClassNameType, ImportAFirstToDef) {
9331 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeADef, ToLang: Lang_CXX11);
9332 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9333 auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
9334 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
9335 testImport(ToTU, FromTU, FromD: FromA);
9336}
9337
9338TEST_P(ImportInjectedClassNameType, ImportALastToDef) {
9339 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeADef, ToLang: Lang_CXX11);
9340 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9341 auto *FromA = LastDeclMatcher<CXXRecordDecl>().match(
9342 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "A")));
9343 testImport(ToTU, FromTU, FromD: FromA);
9344}
9345
9346TEST_P(ImportInjectedClassNameType, ImportCDef) {
9347 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeC, ToLang: Lang_CXX11);
9348 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9349 auto *FromC = FirstDeclMatcher<CXXRecordDecl>().match(
9350 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "C"), isDefinition()));
9351 testImport(ToTU, FromTU, FromD: FromC);
9352}
9353
9354TEST_P(ImportInjectedClassNameType, ImportCLast) {
9355 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeC, ToLang: Lang_CXX11);
9356 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9357 auto *FromC = LastDeclMatcher<CXXRecordDecl>().match(
9358 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "C")));
9359 testImport(ToTU, FromTU, FromD: FromC);
9360}
9361
9362TEST_P(ImportInjectedClassNameType, ImportCDefToDef) {
9363 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeCDef, ToLang: Lang_CXX11);
9364 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9365 auto *FromC = FirstDeclMatcher<CXXRecordDecl>().match(
9366 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "C"), isDefinition()));
9367 testImport(ToTU, FromTU, FromD: FromC);
9368}
9369
9370TEST_P(ImportInjectedClassNameType, ImportCLastToDef) {
9371 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeCDef, ToLang: Lang_CXX11);
9372 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9373 auto *FromC = LastDeclMatcher<CXXRecordDecl>().match(
9374 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "C")));
9375 testImport(ToTU, FromTU, FromD: FromC);
9376}
9377
9378TEST_P(ImportInjectedClassNameType, ImportD) {
9379 Decl *ToTU = getToTuDecl(ToSrcCode: "", ToLang: Lang_CXX11);
9380 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9381 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
9382 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "D"), isDefinition()));
9383 testImport(ToTU, FromTU, FromD);
9384}
9385
9386TEST_P(ImportInjectedClassNameType, ImportDToDef) {
9387 Decl *ToTU = getToTuDecl(ToSrcCode: ToCodeCDef, ToLang: Lang_CXX11);
9388 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
9389 auto *FromD = FirstDeclMatcher<CXXRecordDecl>().match(
9390 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "D"), isDefinition()));
9391 testImport(ToTU, FromTU, FromD);
9392}
9393
9394TEST_P(ImportInjectedClassNameType, ImportTypedefType) {
9395 Decl *ToTU = getToTuDecl(
9396 ToSrcCode: R"(
9397 template <class T>
9398 struct A {
9399 typedef A A1;
9400 void f(A1 *);
9401 };
9402 )",
9403 ToLang: Lang_CXX11);
9404 Decl *FromTU = getTuDecl(
9405 SrcCode: R"(
9406 template <class T>
9407 struct A {
9408 typedef A A1;
9409 void f(A1 *);
9410 };
9411 template<class T>
9412 void A<T>::f(A::A1 *) {}
9413 )",
9414 Lang: Lang_CXX11);
9415
9416 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
9417 D: FromTU, AMatcher: functionDecl(hasName(Name: "f"), isDefinition()));
9418 auto *ToF = Import(From: FromF, Lang: Lang_CXX11);
9419 EXPECT_TRUE(ToF);
9420 ASTContext &ToCtx = ToF->getDeclContext()->getParentASTContext();
9421
9422 auto *ToA1 =
9423 FirstDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "A1")));
9424 QualType ToInjTypedef = ToA1->getUnderlyingType().getCanonicalType();
9425 QualType ToInjParmVar =
9426 ToF->parameters()[0]->getType().getDesugaredType(Context: ToCtx);
9427 ToInjParmVar =
9428 ToInjParmVar->getAs<PointerType>()->getPointeeType().getCanonicalType();
9429 EXPECT_TRUE(isa<InjectedClassNameType>(ToInjTypedef));
9430 EXPECT_TRUE(isa<InjectedClassNameType>(ToInjParmVar));
9431 EXPECT_TRUE(ToCtx.hasSameType(ToInjTypedef, ToInjParmVar));
9432}
9433
9434TEST_P(ASTImporterOptionSpecificTestBase, ImportMacroQualifiedType) {
9435 Decl *From, *To;
9436 std::tie(args&: From, args&: To) = getImportedDecl(
9437 FromSrcCode: R"(
9438 #define CDECL __attribute__((cdecl))
9439 typedef void (CDECL *X)();
9440 )",
9441 FromLang: Lang_CXX03, ToSrcCode: "", ToLang: Lang_CXX03, Identifier: "X");
9442
9443 auto *FromTy =
9444 FirstDeclMatcher<MacroQualifiedType>().match(D: From, AMatcher: macroQualifiedType());
9445 auto *ToTy =
9446 FirstDeclMatcher<MacroQualifiedType>().match(D: To, AMatcher: macroQualifiedType());
9447
9448 EXPECT_TRUE(isa<AttributedType>(FromTy->getUnderlyingType()));
9449 EXPECT_TRUE(isa<AttributedType>(ToTy->getUnderlyingType()));
9450}
9451
9452TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplateName) {
9453 constexpr auto TestCode = R"(
9454 template <class T>
9455 struct A;
9456 template <class T>
9457 struct A {};
9458 template <template<class> class T = A>
9459 struct B {};
9460 using C = B<>;
9461 )";
9462 Decl *ToTU = getToTuDecl(ToSrcCode: TestCode, ToLang: Lang_CXX11);
9463 Decl *FromTU = getTuDecl(SrcCode: TestCode, Lang: Lang_CXX11);
9464
9465 auto *ToUsingFirst = FirstDeclMatcher<TypeAliasDecl>().match(
9466 D: ToTU, AMatcher: typeAliasDecl(hasName(Name: "C")));
9467
9468 auto *FromUsing = FirstDeclMatcher<TypeAliasDecl>().match(
9469 D: FromTU, AMatcher: typeAliasDecl(hasName(Name: "C")));
9470 auto *ToUsing = Import(From: FromUsing, Lang: Lang_CXX11);
9471 EXPECT_TRUE(ToUsing);
9472
9473 auto *ToB = FirstDeclMatcher<ClassTemplateDecl>().match(
9474 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "B")));
9475 auto *ToB1 = LastDeclMatcher<ClassTemplateDecl>().match(
9476 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "B")));
9477 // One template definition of 'B' should exist.
9478 EXPECT_EQ(ToB, ToB1);
9479
9480 // These declarations are imported separately.
9481 EXPECT_NE(ToUsingFirst, ToUsing);
9482
9483 auto SpB = ToB->spec_begin();
9484 auto SpE = ToB->spec_end();
9485 EXPECT_TRUE(SpB != SpE);
9486 ClassTemplateSpecializationDecl *Spec1 = *SpB;
9487 ++SpB;
9488 // The template 'B' should have one specialization (with default argument).
9489 EXPECT_TRUE(SpB == SpE);
9490
9491 // Even if 'B' has one specialization with the default arguments, the AST
9492 // contains after the import two specializations that are linked in the
9493 // declaration chain. The 'spec_begin' iteration does not find these because
9494 // the template arguments are the same. But the imported type alias has the
9495 // link to the second specialization. The template name object in these
9496 // specializations must point to the same (and one) instance of definition of
9497 // 'B'.
9498 auto *Spec2 = cast<ClassTemplateSpecializationDecl>(
9499 Val: ToUsing->getUnderlyingType()
9500 ->getAs<TemplateSpecializationType>()
9501 ->getAsRecordDecl());
9502 EXPECT_NE(Spec1, Spec2);
9503 EXPECT_TRUE(Spec1->getPreviousDecl() == Spec2 ||
9504 Spec2->getPreviousDecl() == Spec1);
9505 TemplateDecl *Templ1 =
9506 Spec1->getTemplateArgs()[0].getAsTemplate().getAsTemplateDecl();
9507 TemplateDecl *Templ2 =
9508 Spec2->getTemplateArgs()[0].getAsTemplate().getAsTemplateDecl();
9509 EXPECT_EQ(Templ1, Templ2);
9510}
9511
9512TEST_P(ASTImporterOptionSpecificTestBase, VaListC) {
9513 Decl *FromTU = getTuDecl(SrcCode: R"(typedef __builtin_va_list va_list;)", Lang: Lang_C99);
9514
9515 auto *FromVaList = FirstDeclMatcher<TypedefDecl>().match(
9516 D: FromTU, AMatcher: typedefDecl(hasName(Name: "va_list")));
9517 ASSERT_TRUE(FromVaList);
9518
9519 auto *ToVaList = Import(From: FromVaList, Lang: Lang_C99);
9520 ASSERT_TRUE(ToVaList);
9521
9522 auto *ToBuiltinVaList = FirstDeclMatcher<TypedefDecl>().match(
9523 D: ToAST->getASTContext().getTranslationUnitDecl(),
9524 AMatcher: typedefDecl(hasName(Name: "__builtin_va_list")));
9525
9526 ASSERT_TRUE(ToAST->getASTContext().hasSameType(
9527 ToVaList->getUnderlyingType(), ToBuiltinVaList->getUnderlyingType()));
9528}
9529
9530TEST_P(ASTImporterOptionSpecificTestBase, VaListCpp) {
9531 Decl *FromTU = getTuDecl(SrcCode: R"(typedef __builtin_va_list va_list;)", Lang: Lang_CXX03);
9532
9533 auto *FromVaList = FirstDeclMatcher<TypedefDecl>().match(
9534 D: FromTU, AMatcher: typedefDecl(hasName(Name: "va_list")));
9535 ASSERT_TRUE(FromVaList);
9536
9537 auto *ToVaList = Import(From: FromVaList, Lang: Lang_CXX03);
9538 ASSERT_TRUE(ToVaList);
9539
9540 auto *ToBuiltinVaList = FirstDeclMatcher<TypedefDecl>().match(
9541 D: ToAST->getASTContext().getTranslationUnitDecl(),
9542 AMatcher: typedefDecl(hasName(Name: "__builtin_va_list")));
9543
9544 ASSERT_TRUE(ToAST->getASTContext().hasSameType(
9545 ToVaList->getUnderlyingType(), ToBuiltinVaList->getUnderlyingType()));
9546}
9547
9548TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingTypedefToRecord) {
9549 const char *Code =
9550 R"(
9551 struct S { int i; };
9552 typedef struct S T;
9553 extern T x;
9554 )";
9555 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_C99);
9556 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_C99);
9557
9558 auto *FromX =
9559 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "x")));
9560 auto *ToX = Import(From: FromX, Lang: Lang_C99);
9561 EXPECT_TRUE(ToX);
9562
9563 auto *Typedef1 =
9564 FirstDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T")));
9565 auto *Typedef2 =
9566 LastDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T")));
9567 EXPECT_EQ(Typedef1, Typedef2);
9568}
9569
9570TEST_P(ASTImporterOptionSpecificTestBase,
9571 ImportExistingTypedefToUnnamedRecord) {
9572 const char *Code =
9573 R"(
9574 typedef const struct { int f; } T;
9575 extern T x;
9576 )";
9577 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_C99);
9578 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_C99);
9579
9580 auto *FromX =
9581 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "x")));
9582 auto *ToX = Import(From: FromX, Lang: Lang_C99);
9583 EXPECT_TRUE(ToX);
9584
9585 auto *Typedef1 =
9586 FirstDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T")));
9587 auto *Typedef2 =
9588 LastDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T")));
9589 EXPECT_NE(Typedef1, Typedef2);
9590 EXPECT_NE(Typedef1->getUnderlyingType().getTypePtr(),
9591 Typedef2->getUnderlyingType().getTypePtr());
9592 EXPECT_EQ(ToX->getType()->getAs<TypedefType>()->getDecl(), Typedef2);
9593}
9594
9595TEST_P(ASTImporterOptionSpecificTestBase, ImportTwoTypedefsToUnnamedRecord) {
9596 const char *Code =
9597 R"(
9598 typedef struct { int f; } T1;
9599 typedef struct { int f; } T2;
9600 extern T1 x1;
9601 extern T2 x2;
9602 )";
9603 Decl *ToTU = getToTuDecl(ToSrcCode: "", ToLang: Lang_C99);
9604 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_C99);
9605
9606 auto *FromX1 =
9607 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "x1")));
9608 auto *FromX2 =
9609 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "x2")));
9610 auto *ToX1 = Import(From: FromX1, Lang: Lang_C99);
9611 EXPECT_TRUE(ToX1);
9612 auto *ToX2 = Import(From: FromX2, Lang: Lang_C99);
9613 EXPECT_TRUE(ToX2);
9614
9615 auto *Typedef1 =
9616 FirstDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T1")));
9617 auto *Typedef2 =
9618 FirstDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T2")));
9619 EXPECT_NE(Typedef1->getUnderlyingType().getTypePtr(),
9620 Typedef2->getUnderlyingType().getTypePtr());
9621}
9622
9623TEST_P(ASTImporterOptionSpecificTestBase,
9624 ImportExistingTypedefToUnnamedRecordPtr) {
9625 const char *Code =
9626 R"(
9627 typedef const struct { int fff; } * const T;
9628 extern T x;
9629 )";
9630 Decl *ToTU = getToTuDecl(ToSrcCode: Code, ToLang: Lang_C99);
9631 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_C99);
9632
9633 auto *FromX =
9634 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "x")));
9635 auto *ToX = Import(From: FromX, Lang: Lang_C99);
9636 EXPECT_TRUE(ToX);
9637
9638 auto *Typedef1 =
9639 FirstDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T")));
9640 auto *Typedef2 =
9641 LastDeclMatcher<TypedefDecl>().match(D: ToTU, AMatcher: typedefDecl(hasName(Name: "T")));
9642 // FIXME: These should be imported separately, like in the test above.
9643 // Or: In the test above these should be merged too.
9644 EXPECT_EQ(Typedef1, Typedef2);
9645
9646 auto *FromR = FirstDeclMatcher<RecordDecl>().match(
9647 D: FromTU, AMatcher: recordDecl(hasDescendant(fieldDecl(hasName(Name: "fff")))));
9648 auto *ToRExisting = FirstDeclMatcher<RecordDecl>().match(
9649 D: ToTU, AMatcher: recordDecl(hasDescendant(fieldDecl(hasName(Name: "fff")))));
9650 ASSERT_TRUE(FromR);
9651 auto *ToRImported = Import(From: FromR, Lang: Lang_C99);
9652 // FIXME: If typedefs are not imported separately, do not import ToRImported
9653 // separately.
9654 EXPECT_NE(ToRExisting, ToRImported);
9655}
9656
9657TEST_P(ASTImporterOptionSpecificTestBase,
9658 ImportTypedefWithDifferentUnderlyingType) {
9659 const char *Code =
9660 R"(
9661 using X1 = int;
9662 using Y1 = int;
9663
9664 using RPB1 = X1*;
9665 typedef RPB1 RPX1;
9666 using RPB1 = Y1*; // redeclared
9667 typedef RPB1 RPY1;
9668
9669 auto X = 0 ? (RPX1){} : (RPY1){};
9670 )";
9671 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9672
9673 auto *FromX =
9674 FirstDeclMatcher<VarDecl>().match(D: FromTU, AMatcher: varDecl(hasName(Name: "X")));
9675
9676 auto *FromXType = FromX->getType()->getAs<TypedefType>();
9677 EXPECT_FALSE(FromXType->typeMatchesDecl());
9678
9679 auto *ToX = Import(From: FromX, Lang: Lang_CXX11);
9680 auto *ToXType = ToX->getType()->getAs<TypedefType>();
9681 // FIXME: This should be false.
9682 EXPECT_TRUE(ToXType->typeMatchesDecl());
9683}
9684
9685TEST_P(ASTImporterOptionSpecificTestBase,
9686 ImportTemplateArgumentWithPointerToDifferentInstantiation) {
9687 const char *CodeTo =
9688 R"(
9689 template<class A>
9690 A f1() {
9691 return A();
9692 }
9693 template<class A, A (B)()>
9694 class X {};
9695
9696 X<int, f1<int>> x;
9697 )";
9698 const char *CodeFrom =
9699 R"(
9700 template<class A>
9701 A f1();
9702 template<class A, A (B)()>
9703 class X {};
9704
9705 X<int, f1<int>> x;
9706 )";
9707 Decl *ToTU = getToTuDecl(ToSrcCode: CodeTo, ToLang: Lang_CXX11);
9708 Decl *FromTU = getTuDecl(SrcCode: CodeFrom, Lang: Lang_CXX11);
9709
9710 auto *ToF1 = FirstDeclMatcher<FunctionDecl>().match(
9711 D: ToTU, AMatcher: functionDecl(hasName(Name: "f1"), isInstantiated()));
9712 auto *FromF1 = FirstDeclMatcher<FunctionDecl>().match(
9713 D: FromTU, AMatcher: functionDecl(hasName(Name: "f1"), isInstantiated()));
9714 EXPECT_TRUE(ToF1->isThisDeclarationADefinition());
9715 EXPECT_FALSE(FromF1->isThisDeclarationADefinition());
9716
9717 auto *ToX = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
9718 D: ToTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
9719 auto *FromX = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
9720 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "X")));
9721
9722 Decl *ToTArgF = ToX->getTemplateArgs().get(Idx: 1).getAsDecl();
9723 Decl *FromTArgF = FromX->getTemplateArgs().get(Idx: 1).getAsDecl();
9724 EXPECT_EQ(ToTArgF, ToF1);
9725 EXPECT_EQ(FromTArgF, FromF1);
9726
9727 auto *ToXImported = Import(From: FromX, Lang: Lang_CXX11);
9728 // The template argument 1 of 'X' in the "From" code points to a function
9729 // that has no definition. The import must ensure that this template argument
9730 // is imported in a way that it will point to the existing 'f1' function, not
9731 // to the 'f1' that is imported. In this way when specialization of 'X' is
9732 // imported it will have the same template arguments as the existing one.
9733 EXPECT_EQ(ToXImported, ToX);
9734 // FIXME: This matcher causes a crash "Tried to match orphan node".
9735 // The code is removed until the problem is fixed.
9736 // auto *ToF1Imported =
9737 // LastDeclMatcher<FunctionDecl>().match(ToTU,
9738 // functionDecl(hasName("f1"),isInstantiated()));
9739 // EXPECT_NE(ToF1Imported, ToF1);
9740 // EXPECT_EQ(ToF1Imported->getPreviousDecl(), ToF1);
9741}
9742
9743TEST_P(ASTImporterOptionSpecificTestBase,
9744 ImportTypeAliasTemplateAfterSimilarCalledTemplateTypeParm) {
9745 const char *Code =
9746 R"(
9747 struct S;
9748 template <typename>
9749 using Callable = S;
9750 template <typename Callable>
9751 int bindingFunctionVTable;
9752 )";
9753 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX17);
9754
9755 auto *FromCallable = FirstDeclMatcher<TypeAliasTemplateDecl>().match(
9756 D: FromTU, AMatcher: typeAliasTemplateDecl(hasName(Name: "Callable")));
9757
9758 auto *FromCallableParm = FirstDeclMatcher<TemplateTypeParmDecl>().match(
9759 D: FromTU, AMatcher: templateTypeParmDecl(hasName(Name: "Callable")));
9760
9761 auto *ToFromCallableParm = Import(From: FromCallableParm, Lang: Lang_CXX17);
9762 auto *ToCallable = Import(From: FromCallable, Lang: Lang_CXX17);
9763 EXPECT_TRUE(ToFromCallableParm);
9764 EXPECT_TRUE(ToCallable);
9765}
9766
9767TEST_P(ASTImporterOptionSpecificTestBase, ImportConflictTypeAliasTemplate) {
9768 const char *ToCode =
9769 R"(
9770 struct S;
9771 template <typename, typename>
9772 using Callable = S;
9773 )";
9774 const char *Code =
9775 R"(
9776 struct S;
9777 template <typename>
9778 using Callable = S;
9779 )";
9780 (void)getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX17);
9781 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX17);
9782
9783 auto *FromCallable = FirstDeclMatcher<TypeAliasTemplateDecl>().match(
9784 D: FromTU, AMatcher: typeAliasTemplateDecl(hasName(Name: "Callable")));
9785
9786 auto *ImportedCallable = Import(From: FromCallable, Lang: Lang_CXX17);
9787 EXPECT_FALSE(ImportedCallable);
9788}
9789
9790AST_MATCHER(ClassTemplateSpecializationDecl, hasInstantiatedFromMember) {
9791 if (auto Instantiate = Node.getInstantiatedFrom()) {
9792 if (auto *FromPartialSpecialization =
9793 cast<ClassTemplatePartialSpecializationDecl *>(Val&: Instantiate)) {
9794 return nullptr != FromPartialSpecialization->getInstantiatedFromMember();
9795 }
9796 }
9797 return false;
9798}
9799
9800TEST_P(ASTImporterOptionSpecificTestBase, ImportInstantiatedFromMember) {
9801 const char *Code =
9802 R"(
9803 template <typename> struct B {
9804 template <typename, bool = false> union D;
9805 template <typename T> union D<T> {};
9806 D<int> d;
9807 };
9808 B<int> b;
9809 )";
9810 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9811 auto *FromD = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match(
9812 D: FromTU, AMatcher: classTemplateSpecializationDecl(hasName(Name: "D"),
9813 hasInstantiatedFromMember()));
9814 auto *FromPartialSpecialization =
9815 cast<ClassTemplatePartialSpecializationDecl *>(
9816 Val: FromD->getInstantiatedFrom());
9817 ASSERT_TRUE(FromPartialSpecialization->getInstantiatedFromMember());
9818 auto *ImportedPartialSpecialization =
9819 Import(From: FromPartialSpecialization, Lang: Lang_CXX11);
9820 EXPECT_TRUE(ImportedPartialSpecialization->getInstantiatedFromMember());
9821}
9822
9823AST_MATCHER_P(EnumDecl, hasEnumConstName, StringRef, ConstName) {
9824 for (EnumConstantDecl *D : Node.enumerators())
9825 if (D->getName() == ConstName)
9826 return true;
9827 return false;
9828}
9829
9830TEST_P(ASTImporterOptionSpecificTestBase, ImportAnonymousEnums) {
9831 const char *Code =
9832 R"(
9833 struct A {
9834 enum { E1, E2 } x;
9835 enum { E3, E4 } y;
9836 };
9837 )";
9838 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9839 auto *FromEnumE1 = FirstDeclMatcher<EnumDecl>().match(
9840 D: FromTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E1")));
9841 auto *ImportedEnumE1 = Import(From: FromEnumE1, Lang: Lang_CXX11);
9842 EXPECT_TRUE(ImportedEnumE1);
9843 auto *FromEnumE3 = FirstDeclMatcher<EnumDecl>().match(
9844 D: FromTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E3")));
9845 auto *ImportedEnumE3 = Import(From: FromEnumE3, Lang: Lang_CXX11);
9846 EXPECT_TRUE(ImportedEnumE3);
9847 EXPECT_NE(ImportedEnumE1, ImportedEnumE3);
9848}
9849
9850TEST_P(ASTImporterOptionSpecificTestBase, ImportFreeStandingAnonymousEnums) {
9851 const char *Code =
9852 R"(
9853 struct A {
9854 enum { E1, E2 };
9855 enum { E3, E4 };
9856 };
9857 )";
9858 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9859 auto *FromEnumE1 = FirstDeclMatcher<EnumDecl>().match(
9860 D: FromTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E1")));
9861 auto *ImportedEnumE1 = Import(From: FromEnumE1, Lang: Lang_CXX11);
9862 EXPECT_TRUE(ImportedEnumE1);
9863 auto *FromEnumE3 = FirstDeclMatcher<EnumDecl>().match(
9864 D: FromTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E3")));
9865 auto *ImportedEnumE3 = Import(From: FromEnumE3, Lang: Lang_CXX11);
9866 EXPECT_TRUE(ImportedEnumE3);
9867 EXPECT_NE(ImportedEnumE1, ImportedEnumE3);
9868}
9869
9870TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingAnonymousEnums) {
9871 const char *ToCode =
9872 R"(
9873 struct A {
9874 enum { E1, E2 } x;
9875 enum { E3, E4 } y;
9876 };
9877 )";
9878 Decl *ToTU = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
9879 auto *ToEnumE1 = FirstDeclMatcher<EnumDecl>().match(
9880 D: ToTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E1")));
9881 auto *ToEnumE3 = FirstDeclMatcher<EnumDecl>().match(
9882 D: ToTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E3")));
9883 const char *Code =
9884 R"(
9885 struct A {
9886 enum { E1, E2 } x;
9887 enum { E3, E4 } y;
9888 };
9889 )";
9890 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9891 auto *FromEnumE1 = FirstDeclMatcher<EnumDecl>().match(
9892 D: FromTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E1")));
9893 auto *ImportedEnumE1 = Import(From: FromEnumE1, Lang: Lang_CXX11);
9894 ASSERT_TRUE(ImportedEnumE1);
9895 EXPECT_EQ(ImportedEnumE1, ToEnumE1);
9896 auto *FromEnumE3 = FirstDeclMatcher<EnumDecl>().match(
9897 D: FromTU, AMatcher: enumDecl(hasEnumConstName(ConstName: "E3")));
9898 auto *ImportedEnumE3 = Import(From: FromEnumE3, Lang: Lang_CXX11);
9899 ASSERT_TRUE(ImportedEnumE3);
9900 EXPECT_EQ(ImportedEnumE3, ToEnumE3);
9901}
9902
9903TEST_P(ASTImporterOptionSpecificTestBase, ImportExistingEmptyAnonymousEnums) {
9904 const char *ToCode =
9905 R"(
9906 struct A {
9907 enum {};
9908 };
9909 )";
9910 Decl *ToTU = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
9911 auto *ToE1 = FirstDeclMatcher<EnumDecl>().match(D: ToTU, AMatcher: enumDecl());
9912 const char *Code =
9913 R"(
9914 struct A {
9915 enum {};
9916 enum {};
9917 };
9918 )";
9919 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
9920 auto *FromE1 = FirstDeclMatcher<EnumDecl>().match(D: FromTU, AMatcher: enumDecl());
9921 auto *ImportedE1 = Import(From: FromE1, Lang: Lang_CXX11);
9922 ASSERT_TRUE(ImportedE1);
9923 EXPECT_EQ(ImportedE1, ToE1);
9924 auto *FromE2 = LastDeclMatcher<EnumDecl>().match(D: FromTU, AMatcher: enumDecl());
9925 ASSERT_NE(FromE1, FromE2);
9926 auto *ImportedE2 = Import(From: FromE2, Lang: Lang_CXX11);
9927 ASSERT_TRUE(ImportedE2);
9928 // FIXME: These should not be equal, or the import should fail.
9929 EXPECT_EQ(ImportedE2, ToE1);
9930}
9931
9932TEST_P(ASTImporterOptionSpecificTestBase, ImportMultipleAnonymousEnumDecls) {
9933 Decl *ToTU = getToTuDecl(ToSrcCode: "", ToLang: Lang_CXX03);
9934 Decl *FromTU = getTuDecl(
9935 SrcCode: R"(
9936 struct foo {
9937 enum { A };
9938 enum { B };
9939 };
9940 )",
9941 Lang: Lang_CXX03);
9942
9943 auto EnumConstA = enumConstantDecl(hasName(Name: "A"));
9944 auto EnumConstB = enumConstantDecl(hasName(Name: "B"));
9945
9946 auto *FromA = FirstDeclMatcher<EnumConstantDecl>().match(D: FromTU, AMatcher: EnumConstA);
9947 auto *FromB = FirstDeclMatcher<EnumConstantDecl>().match(D: FromTU, AMatcher: EnumConstB);
9948
9949 auto *ToA = Import(From: FromA, Lang: Lang_CXX03);
9950 auto *ToB = Import(From: FromB, Lang: Lang_CXX03);
9951
9952 ASSERT_TRUE(ToA);
9953 ASSERT_TRUE(ToB);
9954
9955 auto *ToFooA = FirstDeclMatcher<CXXRecordDecl>().match(
9956 D: ToTU, AMatcher: tagDecl(has(enumDecl(has(EnumConstA)))));
9957 auto *ToFooB = FirstDeclMatcher<CXXRecordDecl>().match(
9958 D: ToTU, AMatcher: tagDecl(has(enumDecl(has(EnumConstB)))));
9959 ASSERT_EQ(ToFooA, ToFooB);
9960
9961 // different EnumDecl
9962 auto *ToEnumDeclA =
9963 FirstDeclMatcher<EnumDecl>().match(D: ToTU, AMatcher: enumDecl(has(EnumConstA)));
9964 auto *ToEnumDeclB =
9965 FirstDeclMatcher<EnumDecl>().match(D: ToTU, AMatcher: enumDecl(has(EnumConstB)));
9966 ASSERT_NE(ToEnumDeclA, ToEnumDeclB);
9967}
9968
9969struct ImportTemplateParmDeclDefaultValue
9970 : public ASTImporterOptionSpecificTestBase {
9971protected:
9972 void checkTemplateParams(RedeclarableTemplateDecl *D,
9973 RedeclarableTemplateDecl *InheritedFromD) {
9974 auto *NonTypeP =
9975 cast<NonTypeTemplateParmDecl>(Val: D->getTemplateParameters()->getParam(Idx: 0));
9976 auto *TypeP =
9977 cast<TemplateTypeParmDecl>(Val: D->getTemplateParameters()->getParam(Idx: 1));
9978 auto *TemplateP =
9979 cast<TemplateTemplateParmDecl>(Val: D->getTemplateParameters()->getParam(Idx: 2));
9980 if (InheritedFromD) {
9981 EXPECT_TRUE(NonTypeP->getDefaultArgStorage().isInherited());
9982 EXPECT_TRUE(TypeP->getDefaultArgStorage().isInherited());
9983 EXPECT_TRUE(TemplateP->getDefaultArgStorage().isInherited());
9984 EXPECT_EQ(NonTypeP->getDefaultArgStorage().getInheritedFrom(),
9985 InheritedFromD->getTemplateParameters()->getParam(0));
9986 EXPECT_EQ(TypeP->getDefaultArgStorage().getInheritedFrom(),
9987 InheritedFromD->getTemplateParameters()->getParam(1));
9988 EXPECT_EQ(TemplateP->getDefaultArgStorage().getInheritedFrom(),
9989 InheritedFromD->getTemplateParameters()->getParam(2));
9990 } else {
9991 EXPECT_FALSE(NonTypeP->getDefaultArgStorage().isInherited());
9992 EXPECT_FALSE(TypeP->getDefaultArgStorage().isInherited());
9993 EXPECT_FALSE(TemplateP->getDefaultArgStorage().isInherited());
9994 }
9995 }
9996
9997 void testImport(RedeclarableTemplateDecl *FromD1,
9998 RedeclarableTemplateDecl *FromD2,
9999 RedeclarableTemplateDecl *FromD3,
10000 RedeclarableTemplateDecl *ToExistingD1) {
10001 auto *ToD1 = Import(From: FromD1, Lang: Lang_CXX14);
10002 auto *ToD2 = Import(From: FromD2, Lang: Lang_CXX14);
10003 auto *ToD3 = Import(From: FromD3, Lang: Lang_CXX14);
10004 checkTemplateParams(D: ToD1, InheritedFromD: nullptr);
10005 checkTemplateParams(D: ToD2, InheritedFromD: ToD1);
10006 checkTemplateParams(D: ToD3, InheritedFromD: ToExistingD1 ? ToExistingD1 : ToD1);
10007 }
10008
10009 // In these tests a circular dependency is created between the template
10010 // parameter default value and the template declaration (with the same
10011 // template parameter).
10012 template <class TemplateParmDeclT>
10013 void
10014 testTemplateParmDeclCircularDependency(ClassTemplateDecl *FromD,
10015 ClassTemplateDecl *FromDInherited) {
10016 auto GetTemplateParm =
10017 [](ClassTemplateDecl *D) -> const TemplateParmDeclT * {
10018 return dyn_cast<TemplateParmDeclT>(
10019 D->getTemplateParameters()->getParam(Idx: 0));
10020 };
10021
10022 ASSERT_FALSE(GetTemplateParm(FromD)->getDefaultArgStorage().isInherited());
10023 ASSERT_TRUE(
10024 GetTemplateParm(FromDInherited)->getDefaultArgStorage().isInherited());
10025
10026 auto *ToD = Import(From: FromD, Lang: Lang_CXX14);
10027 EXPECT_TRUE(ToD);
10028
10029 auto *ToDInherited = Import(From: FromDInherited, Lang: Lang_CXX14);
10030 EXPECT_TRUE(ToDInherited);
10031
10032 EXPECT_FALSE(GetTemplateParm(ToD)->getDefaultArgStorage().isInherited());
10033 EXPECT_TRUE(
10034 GetTemplateParm(ToDInherited)->getDefaultArgStorage().isInherited());
10035 EXPECT_EQ(GetTemplateParm(ToDInherited)
10036 ->getDefaultArgStorage()
10037 .getInheritedFrom(),
10038 GetTemplateParm(ToD));
10039
10040 EXPECT_EQ(ToD->getPreviousDecl(), ToDInherited);
10041 }
10042
10043 const char *CodeFunction =
10044 R"(
10045 template <class> struct X;
10046
10047 template <int A = 2, typename B = int, template<class> class C = X>
10048 void test();
10049 template <int A, typename B, template<class> class C>
10050 void test();
10051 template <int A, typename B, template<class> class C>
10052 void test() {}
10053 )";
10054
10055 const char *CodeClass =
10056 R"(
10057 namespace N {
10058 template <class> struct X;
10059
10060 template <int A = 2, typename B = int, template<class> class C = X>
10061 struct test;
10062 template <int A, typename B, template<class> class C>
10063 struct test;
10064 template <int A, typename B, template<class> class C>
10065 struct test {};
10066 }
10067 )";
10068
10069 const char *CodeVar =
10070 R"(
10071 namespace N {
10072 template <class> struct X;
10073
10074 template <int A = 2, typename B = int, template<class> class C = X>
10075 extern int test;
10076 template <int A, typename B, template<class> class C>
10077 extern int test;
10078 template <int A, typename B, template<class> class C>
10079 int test = A;
10080 }
10081 )";
10082};
10083
10084TEST_P(ImportTemplateParmDeclDefaultValue, InvisibleInheritedFrom) {
10085 const char *ToCode =
10086 R"(
10087 template <int P = 1>
10088 void f() {}
10089 )";
10090 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX14);
10091 auto *ToFDef = FirstDeclMatcher<FunctionTemplateDecl>().match(
10092 D: ToTU, AMatcher: functionTemplateDecl(hasName(Name: "f")));
10093
10094 const char *FromCode =
10095 R"(
10096 template <int P = 1>
10097 void f() {}
10098 template <int P>
10099 void f();
10100 )";
10101 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX14);
10102 auto *FromFDef = FirstDeclMatcher<FunctionTemplateDecl>().match(
10103 D: FromTU, AMatcher: functionTemplateDecl(hasName(Name: "f")));
10104 auto *FromF = LastDeclMatcher<FunctionTemplateDecl>().match(
10105 D: FromTU, AMatcher: functionTemplateDecl(hasName(Name: "f")));
10106
10107 auto *ToFDefImported = Import(From: FromFDef, Lang: Lang_CXX14);
10108 EXPECT_EQ(ToFDefImported, ToFDef);
10109 auto *ToF = Import(From: FromF, Lang: Lang_CXX14);
10110 EXPECT_NE(ToF, ToFDef);
10111 const auto *Parm = dyn_cast<NonTypeTemplateParmDecl>(
10112 Val: ToF->getTemplateParameters()->getParam(Idx: 0));
10113 EXPECT_TRUE(Parm->defaultArgumentWasInherited());
10114 // FIXME: This behavior may be confusing:
10115 // Default value is not inherited from the existing declaration, instead a new
10116 // is created at import that is similar to the existing but not reachable from
10117 // the AST.
10118 EXPECT_NE(Parm->getDefaultArgStorage().getInheritedFrom(),
10119 ToFDef->getTemplateParameters()->getParam(0));
10120}
10121
10122TEST_P(ImportTemplateParmDeclDefaultValue, DefValImportError) {
10123 const char *ToCode =
10124 R"(
10125 class X {
10126 int A;
10127 };
10128 )";
10129 getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX14);
10130
10131 const char *FromCode =
10132 R"(
10133 class X;
10134
10135 template <typename P = X>
10136 void f() {}
10137
10138 class X {
10139 char A;
10140 };
10141 )";
10142 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX14);
10143 auto *FromF = FirstDeclMatcher<FunctionTemplateDecl>().match(
10144 D: FromTU, AMatcher: functionTemplateDecl(hasName(Name: "f")));
10145
10146 auto *ToFImported = Import(From: FromF, Lang: Lang_CXX14);
10147 EXPECT_FALSE(ToFImported);
10148}
10149
10150TEST_P(ImportTemplateParmDeclDefaultValue, ImportFunctionTemplate) {
10151 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: CodeFunction, Lang: Lang_CXX14);
10152 auto *D3 = LastDeclMatcher<FunctionTemplateDecl>().match(
10153 D: FromTU, AMatcher: functionTemplateDecl(hasName(Name: "test") /*, hasBody(stmt())*/));
10154 auto *D2 = dyn_cast<FunctionTemplateDecl>(Val: D3->getPreviousDecl());
10155 auto *D1 = dyn_cast<FunctionTemplateDecl>(Val: D2->getPreviousDecl());
10156 testImport(FromD1: D1, FromD2: D2, FromD3: D3, ToExistingD1: nullptr);
10157}
10158
10159TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingFunctionTemplate) {
10160 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: CodeFunction, ToLang: Lang_CXX14);
10161 auto *ToD1 = FirstDeclMatcher<FunctionTemplateDecl>().match(
10162 D: ToTU, AMatcher: functionTemplateDecl(hasName(Name: "test")));
10163 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: CodeFunction, Lang: Lang_CXX14);
10164 auto *D3 = LastDeclMatcher<FunctionTemplateDecl>().match(
10165 D: FromTU, AMatcher: functionTemplateDecl(hasName(Name: "test")));
10166 auto *D2 = dyn_cast<FunctionTemplateDecl>(Val: D3->getPreviousDecl());
10167 auto *D1 = dyn_cast<FunctionTemplateDecl>(Val: D2->getPreviousDecl());
10168 testImport(FromD1: D1, FromD2: D2, FromD3: D3, ToExistingD1: ToD1);
10169}
10170
10171TEST_P(ImportTemplateParmDeclDefaultValue, ImportClassTemplate) {
10172 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: CodeClass, Lang: Lang_CXX14);
10173 auto *D3 = LastDeclMatcher<ClassTemplateDecl>().match(
10174 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "test")));
10175 auto *D2 = dyn_cast<ClassTemplateDecl>(Val: D3->getPreviousDecl());
10176 auto *D1 = dyn_cast<ClassTemplateDecl>(Val: D2->getPreviousDecl());
10177 testImport(FromD1: D1, FromD2: D2, FromD3: D3, ToExistingD1: nullptr);
10178}
10179
10180TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingClassTemplate) {
10181 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: CodeClass, ToLang: Lang_CXX14);
10182 auto *ToD1 = FirstDeclMatcher<ClassTemplateDecl>().match(
10183 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "test")));
10184 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: CodeClass, Lang: Lang_CXX14);
10185 auto *D3 = LastDeclMatcher<ClassTemplateDecl>().match(
10186 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "test")));
10187 auto *D2 = dyn_cast<ClassTemplateDecl>(Val: D3->getPreviousDecl());
10188 auto *D1 = dyn_cast<ClassTemplateDecl>(Val: D2->getPreviousDecl());
10189 testImport(FromD1: D1, FromD2: D2, FromD3: D3, ToExistingD1: ToD1);
10190}
10191
10192TEST_P(ImportTemplateParmDeclDefaultValue, ImportVarTemplate) {
10193 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: CodeVar, Lang: Lang_CXX14);
10194 auto *D3 = LastDeclMatcher<VarTemplateDecl>().match(
10195 D: FromTU, AMatcher: varTemplateDecl(hasName(Name: "test")));
10196 auto *D2 = dyn_cast<VarTemplateDecl>(Val: D3->getPreviousDecl());
10197 auto *D1 = dyn_cast<VarTemplateDecl>(Val: D2->getPreviousDecl());
10198 testImport(FromD1: D1, FromD2: D2, FromD3: D3, ToExistingD1: nullptr);
10199}
10200
10201TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingVarTemplate) {
10202 TranslationUnitDecl *ToTU = getToTuDecl(ToSrcCode: CodeVar, ToLang: Lang_CXX14);
10203 auto *ToD1 = FirstDeclMatcher<VarTemplateDecl>().match(
10204 D: ToTU, AMatcher: varTemplateDecl(hasName(Name: "test")));
10205 TranslationUnitDecl *FromTU = getTuDecl(SrcCode: CodeVar, Lang: Lang_CXX14);
10206 auto *D3 = LastDeclMatcher<VarTemplateDecl>().match(
10207 D: FromTU, AMatcher: varTemplateDecl(hasName(Name: "test")));
10208 auto *D2 = dyn_cast<VarTemplateDecl>(Val: D3->getPreviousDecl());
10209 auto *D1 = dyn_cast<VarTemplateDecl>(Val: D2->getPreviousDecl());
10210 testImport(FromD1: D1, FromD2: D2, FromD3: D3, ToExistingD1: ToD1);
10211}
10212
10213TEST_P(ImportTemplateParmDeclDefaultValue,
10214 NonTypeTemplateParmDeclCircularDependency) {
10215 const char *Code =
10216 R"(
10217 struct Z;
10218
10219 struct Y {
10220 Z *z;
10221 static const int x = 1;
10222 };
10223
10224 template <int P1 = Y::x>
10225 struct X;
10226
10227 template <int P2>
10228 struct X {
10229 static const int A = 1;
10230 };
10231
10232 struct Z {
10233 template<int P>
10234 void f(int A = X<P>::A);
10235 };
10236 )";
10237
10238 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX14);
10239 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
10240 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10241 auto *FromDInherited = LastDeclMatcher<ClassTemplateDecl>().match(
10242 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10243
10244 testTemplateParmDeclCircularDependency<NonTypeTemplateParmDecl>(
10245 FromD, FromDInherited);
10246}
10247
10248TEST_P(ImportTemplateParmDeclDefaultValue,
10249 TemplateTypeParmDeclCircularDependency) {
10250 const char *Code =
10251 R"(
10252 struct Z;
10253
10254 struct Y {
10255 Z *z;
10256 };
10257
10258 template <typename T1 = Y>
10259 struct X;
10260
10261 template <typename T2>
10262 struct X {
10263 static const int A = 1;
10264 };
10265
10266 struct Z {
10267 template<typename T>
10268 void f(int A = X<T>::A);
10269 };
10270 )";
10271
10272 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX14);
10273 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
10274 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10275 auto *FromDInherited = LastDeclMatcher<ClassTemplateDecl>().match(
10276 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10277
10278 testTemplateParmDeclCircularDependency<TemplateTypeParmDecl>(FromD,
10279 FromDInherited);
10280}
10281
10282TEST_P(ImportTemplateParmDeclDefaultValue,
10283 TemplateTemplateParmDeclCircularDependency) {
10284 const char *Code =
10285 R"(
10286 struct Z;
10287
10288 template <int>
10289 struct Y {
10290 Z *z;
10291 };
10292
10293 template <template <int> class T1 = Y>
10294 struct X;
10295
10296 template <template <int> class T2>
10297 struct X {
10298 static const int A = 1;
10299 };
10300
10301 struct Z {
10302 template <template <int> class T>
10303 void f(int A = X<T>::A);
10304 };
10305 )";
10306
10307 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX14);
10308 auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match(
10309 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10310 auto *FromDInherited = LastDeclMatcher<ClassTemplateDecl>().match(
10311 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10312
10313 testTemplateParmDeclCircularDependency<TemplateTemplateParmDecl>(
10314 FromD, FromDInherited);
10315}
10316
10317TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceNoMatch1) {
10318 const char *ToCode =
10319 R"(
10320 namespace a {
10321 }
10322 namespace a {
10323 struct X { int A; };
10324 }
10325 )";
10326 getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
10327 const char *Code =
10328 R"(
10329 namespace a {
10330 struct X { char A; };
10331 }
10332 )";
10333 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
10334 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
10335 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
10336 auto *ImportedX = Import(From: FromX, Lang: Lang_CXX11);
10337 EXPECT_FALSE(ImportedX);
10338}
10339
10340TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceNoMatch2) {
10341 const char *ToCode =
10342 R"(
10343 namespace a {
10344 struct X { int A; };
10345 }
10346 namespace a {
10347 }
10348 )";
10349 getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
10350 const char *Code =
10351 R"(
10352 namespace a {
10353 struct X { char A; };
10354 }
10355 )";
10356 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
10357 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
10358 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
10359 auto *ImportedX = Import(From: FromX, Lang: Lang_CXX11);
10360 EXPECT_FALSE(ImportedX);
10361}
10362
10363TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceMatch1) {
10364 const char *ToCode =
10365 R"(
10366 namespace a {
10367 }
10368 namespace a {
10369 struct X { int A; };
10370 }
10371 )";
10372 Decl *ToTU = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
10373 const char *Code =
10374 R"(
10375 namespace a {
10376 struct X { int A; };
10377 }
10378 )";
10379 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
10380 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
10381 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
10382 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(
10383 D: ToTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
10384 auto *ImportedX = Import(From: FromX, Lang: Lang_CXX11);
10385 EXPECT_EQ(ImportedX, ToX);
10386}
10387
10388TEST_P(ASTImporterOptionSpecificTestBase, ImportIntoReopenedNamespaceMatch2) {
10389 const char *ToCode =
10390 R"(
10391 namespace a {
10392 struct X { int A; };
10393 }
10394 namespace a {
10395 }
10396 )";
10397 Decl *ToTU = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
10398 const char *Code =
10399 R"(
10400 namespace a {
10401 struct X { int A; };
10402 }
10403 )";
10404 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
10405 auto *FromX = FirstDeclMatcher<CXXRecordDecl>().match(
10406 D: FromTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
10407 auto *ToX = FirstDeclMatcher<CXXRecordDecl>().match(
10408 D: ToTU, AMatcher: cxxRecordDecl(hasName(Name: "X")));
10409 auto *ImportedX = Import(From: FromX, Lang: Lang_CXX11);
10410 EXPECT_EQ(ImportedX, ToX);
10411}
10412
10413TEST_P(ASTImporterLookupTableTest, PrimaryDCChangeAtImport) {
10414 const char *ToCode =
10415 R"(
10416 template <class T>
10417 struct X;
10418 )";
10419 Decl *ToTU = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
10420 auto *ToX = FirstDeclMatcher<ClassTemplateDecl>().match(
10421 D: ToTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10422 NamedDecl *ToParm = ToX->getTemplateParameters()->getParam(Idx: 0);
10423 DeclContext *OldPrimaryDC = ToX->getTemplatedDecl()->getPrimaryContext();
10424 ASSERT_EQ(ToParm->getDeclContext(), ToX->getTemplatedDecl());
10425 ASSERT_EQ(SharedStatePtr->getLookupTable()
10426 ->lookup(ToX->getTemplatedDecl(), ToParm->getDeclName())
10427 .size(),
10428 1u);
10429 ASSERT_TRUE(SharedStatePtr->getLookupTable()->contains(
10430 ToX->getTemplatedDecl(), ToParm));
10431
10432 const char *Code =
10433 R"(
10434 template <class T>
10435 struct X;
10436 template <class T>
10437 struct X {};
10438 )";
10439 Decl *FromTU = getTuDecl(SrcCode: Code, Lang: Lang_CXX11);
10440 auto *FromX = LastDeclMatcher<ClassTemplateDecl>().match(
10441 D: FromTU, AMatcher: classTemplateDecl(hasName(Name: "X")));
10442
10443 auto *ImportedX = Import(From: FromX, Lang: Lang_CXX11);
10444
10445 EXPECT_TRUE(ImportedX);
10446 EXPECT_EQ(ImportedX->getTemplateParameters()->getParam(0)->getDeclContext(),
10447 ImportedX->getTemplatedDecl());
10448
10449 // ToX did not change at the import.
10450 // Verify that primary context has changed after import of class definition.
10451 DeclContext *NewPrimaryDC = ToX->getTemplatedDecl()->getPrimaryContext();
10452 EXPECT_NE(OldPrimaryDC, NewPrimaryDC);
10453 // The lookup table should not be different than it was before.
10454 EXPECT_EQ(SharedStatePtr->getLookupTable()
10455 ->lookup(ToX->getTemplatedDecl(), ToParm->getDeclName())
10456 .size(),
10457 1u);
10458 EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains(
10459 ToX->getTemplatedDecl(), ToParm));
10460}
10461
10462TEST_P(ASTImporterOptionSpecificTestBase,
10463 ExistingUndeclaredImportDeclaredFriend) {
10464 Decl *ToTU = getToTuDecl(
10465 ToSrcCode: R"(
10466 template <class A, A>
10467 struct foo;
10468
10469 template <class A>
10470 struct X {
10471 template <class A1, A1>
10472 friend struct foo;
10473 };
10474 )",
10475 ToLang: Lang_CXX11);
10476 Decl *FromTU = getTuDecl(
10477 SrcCode: R"(
10478 template <class A, A>
10479 struct foo;
10480
10481 template <class A>
10482 struct X {
10483 template <class A1, A1>
10484 friend struct foo;
10485 };
10486
10487 X<int> x;
10488 )",
10489 Lang: Lang_CXX11);
10490
10491 auto *ToFr1 = FirstDeclMatcher<FriendDecl>().match(D: ToTU, AMatcher: friendDecl());
10492 auto *ToFrD1 = ToFr1->getFriendDecl();
10493
10494 auto *FromFr1 = FirstDeclMatcher<FriendDecl>().match(D: FromTU, AMatcher: friendDecl());
10495 auto *FromFr2 = LastDeclMatcher<FriendDecl>().match(D: FromTU, AMatcher: friendDecl());
10496
10497 auto *FromFrD1 = FromFr1->getFriendDecl();
10498 auto *FromFrD2 = FromFr2->getFriendDecl();
10499
10500 auto *Ctx1 = cast<Decl>(Val: FromFrD1->getDeclContext());
10501 auto *Ctx2 = cast<Decl>(Val: FromFrD2->getDeclContext());
10502
10503 ASSERT_EQ(Ctx1, Ctx2);
10504 ASSERT_EQ(ToFrD1->getTemplateDepth(), 1u);
10505 ASSERT_EQ(FromFrD2->getTemplateDepth(), 0u);
10506 ASSERT_EQ(ToFrD1->getFriendObjectKind(), Decl::FOK_Undeclared);
10507 ASSERT_EQ(FromFrD2->getFriendObjectKind(), Decl::FOK_Declared);
10508
10509 auto *ToFr2Imp = Import(From: FromFr2, Lang: Lang_CXX11);
10510
10511 EXPECT_TRUE(ToFr2Imp);
10512}
10513
10514TEST_P(ASTImporterOptionSpecificTestBase,
10515 ExistingDeclaredImportUndeclaredFriend) {
10516 Decl *ToTU = getToTuDecl(
10517 ToSrcCode: R"(
10518 template <class A, A>
10519 struct foo;
10520
10521 template <class A>
10522 struct X {
10523 template <class A1, A1>
10524 friend struct foo;
10525 };
10526
10527 X<int> x;
10528 )",
10529 ToLang: Lang_CXX11);
10530 Decl *FromTU = getTuDecl(
10531 SrcCode: R"(
10532 template <class A, A>
10533 struct foo;
10534
10535 template <class A>
10536 struct X {
10537 template <class A1, A1>
10538 friend struct foo;
10539 };
10540 )",
10541 Lang: Lang_CXX11);
10542
10543 auto *ToFr1 = FirstDeclMatcher<FriendDecl>().match(D: ToTU, AMatcher: friendDecl());
10544 auto *ToFr2 = LastDeclMatcher<FriendDecl>().match(D: ToTU, AMatcher: friendDecl());
10545
10546 auto *ToFrD1 = ToFr1->getFriendDecl();
10547 auto *ToFrD2 = ToFr2->getFriendDecl();
10548
10549 auto *FromFr1 = FirstDeclMatcher<FriendDecl>().match(D: FromTU, AMatcher: friendDecl());
10550 auto *FromFrD1 = FromFr1->getFriendDecl();
10551
10552 auto *Ctx1 = cast<Decl>(Val: ToFrD1->getDeclContext());
10553 auto *Ctx2 = cast<Decl>(Val: ToFrD2->getDeclContext());
10554
10555 ASSERT_EQ(Ctx1, Ctx2);
10556 ASSERT_EQ(FromFrD1->getTemplateDepth(), 1u);
10557 ASSERT_EQ(ToFrD2->getTemplateDepth(), 0u);
10558 ASSERT_EQ(FromFrD1->getFriendObjectKind(), Decl::FOK_Undeclared);
10559 ASSERT_EQ(ToFrD2->getFriendObjectKind(), Decl::FOK_Declared);
10560
10561 auto *ToFr1Imp = Import(From: FromFr1, Lang: Lang_CXX11);
10562
10563 EXPECT_TRUE(ToFr1Imp);
10564 EXPECT_EQ(ToFr1Imp, ToFr1);
10565}
10566
10567struct ImportAndMergeAnonymousNamespace
10568 : public ASTImporterOptionSpecificTestBase {
10569protected:
10570 void test(const char *ToCode, const char *FromCode) {
10571 Decl *ToTU = getToTuDecl(ToSrcCode: ToCode, ToLang: Lang_CXX11);
10572 Decl *FromTU = getTuDecl(SrcCode: FromCode, Lang: Lang_CXX11);
10573 auto *FromNS = FirstDeclMatcher<NamespaceDecl>().match(
10574 D: FromTU, AMatcher: namespaceDecl(isAnonymous()));
10575 auto *ToNS = FirstDeclMatcher<NamespaceDecl>().match(
10576 D: ToTU, AMatcher: namespaceDecl(isAnonymous()));
10577 auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
10578 D: FromTU, AMatcher: functionDecl(hasName(Name: "f")));
10579 auto *ImportedF = Import(From: FromF, Lang: Lang_CXX11);
10580 EXPECT_TRUE(ImportedF);
10581 EXPECT_EQ(ImportedF->getDeclContext(), ToNS);
10582 auto *ImportedNS = Import(From: FromNS, Lang: Lang_CXX11);
10583 EXPECT_EQ(ImportedNS, ToNS);
10584 }
10585};
10586
10587TEST_P(ImportAndMergeAnonymousNamespace, NamespaceInTU) {
10588 const char *ToCode =
10589 R"(
10590 namespace {
10591 }
10592 )";
10593 const char *FromCode =
10594 R"(
10595 namespace {
10596 void f();
10597 }
10598 )";
10599 test(ToCode, FromCode);
10600}
10601
10602TEST_P(ImportAndMergeAnonymousNamespace, NamespaceInLinkageSpec) {
10603 const char *ToCode =
10604 R"(
10605 extern "C" {
10606 namespace {
10607 }
10608 }
10609 )";
10610 const char *FromCode =
10611 R"(
10612 extern "C" {
10613 namespace {
10614 void f();
10615 }
10616 }
10617 )";
10618 test(ToCode, FromCode);
10619}
10620
10621TEST_P(ImportAndMergeAnonymousNamespace, NamespaceInNamespace) {
10622 const char *ToCode =
10623 R"(
10624 namespace X {
10625 namespace {
10626 }
10627 }
10628 )";
10629 const char *FromCode =
10630 R"(
10631 namespace X {
10632 namespace {
10633 void f();
10634 }
10635 }
10636 )";
10637 test(ToCode, FromCode);
10638}
10639
10640INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest,
10641 DefaultTestValuesForRunOptions);
10642
10643INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportPath,
10644 ::testing::Values(std::vector<std::string>()));
10645
10646INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportExpr,
10647 DefaultTestValuesForRunOptions);
10648
10649INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFixedPointExpr,
10650 ExtendWithOptions(DefaultTestArrayForRunOptions,
10651 std::vector<std::string>{
10652 "-ffixed-point"}));
10653
10654INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportBlock,
10655 ExtendWithOptions(DefaultTestArrayForRunOptions,
10656 std::vector<std::string>{
10657 "-fblocks"}));
10658
10659INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportType,
10660 DefaultTestValuesForRunOptions);
10661
10662INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportDecl,
10663 DefaultTestValuesForRunOptions);
10664
10665INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
10666 DefaultTestValuesForRunOptions);
10667
10668INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ErrorHandlingTest,
10669 DefaultTestValuesForRunOptions);
10670
10671INSTANTIATE_TEST_SUITE_P(ParameterizedTests, RedirectingImporterTest,
10672 DefaultTestValuesForRunOptions);
10673
10674INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFunctions,
10675 DefaultTestValuesForRunOptions);
10676
10677INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportAutoFunctions,
10678 DefaultTestValuesForRunOptions);
10679
10680INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFunctionTemplates,
10681 DefaultTestValuesForRunOptions);
10682
10683INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFriendFunctionTemplates,
10684 DefaultTestValuesForRunOptions);
10685
10686INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportClasses,
10687 DefaultTestValuesForRunOptions);
10688
10689INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFriendFunctions,
10690 DefaultTestValuesForRunOptions);
10691
10692INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportFriendClasses,
10693 DefaultTestValuesForRunOptions);
10694
10695INSTANTIATE_TEST_SUITE_P(ParameterizedTests,
10696 ImportFunctionTemplateSpecializations,
10697 DefaultTestValuesForRunOptions);
10698
10699INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportImplicitMethods,
10700 DefaultTestValuesForRunOptions);
10701
10702INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportVariables,
10703 DefaultTestValuesForRunOptions);
10704
10705INSTANTIATE_TEST_SUITE_P(ParameterizedTests, LLDBLookupTest,
10706 DefaultTestValuesForRunOptions);
10707
10708INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportSourceLocations,
10709 DefaultTestValuesForRunOptions);
10710
10711INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportWithExternalSource,
10712 DefaultTestValuesForRunOptions);
10713
10714INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportAttributes,
10715 DefaultTestValuesForRunOptions);
10716
10717INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportInjectedClassNameType,
10718 DefaultTestValuesForRunOptions);
10719
10720INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportMatrixType,
10721 DefaultTestValuesForRunOptions);
10722
10723INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportTemplateParmDeclDefaultValue,
10724 DefaultTestValuesForRunOptions);
10725
10726INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportAndMergeAnonymousNamespace,
10727 DefaultTestValuesForRunOptions);
10728
10729// FIXME: Make ImportOpenCLPipe test work.
10730// INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ImportOpenCLPipe,
10731// DefaultTestValuesForRunOptions);
10732GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ImportOpenCLPipe);
10733
10734} // end namespace ast_matchers
10735} // end namespace clang
10736

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