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 // Type-parameterized tests for the correct import of Decls with different
10 // visibility.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 // Define this to have ::testing::Combine available.
15 // FIXME: Better solution for this?
16 #define GTEST_HAS_COMBINE 1
17 
18 #include "ASTImporterFixtures.h"
19 
20 namespace clang {
21 namespace ast_matchers {
22 
23 using internal::BindableMatcher;
24 
25 // Type parameters for type-parameterized test fixtures.
26 struct GetFunPattern {
27   using DeclTy = FunctionDecl;
28   BindableMatcher<Decl> operator()() { return functionDecl(hasName("f")); }
29 };
30 struct GetVarPattern {
31   using DeclTy = VarDecl;
32   BindableMatcher<Decl> operator()() { return varDecl(hasName("v")); }
33 };
34 struct GetClassPattern {
35   using DeclTy = CXXRecordDecl;
36   BindableMatcher<Decl> operator()() { return cxxRecordDecl(hasName("X")); }
37 };
38 struct GetEnumPattern {
39   using DeclTy = EnumDecl;
40   BindableMatcher<Decl> operator()() { return enumDecl(hasName("E")); }
41 };
42 struct GetTypedefNamePattern {
43   using DeclTy = TypedefNameDecl;
44   BindableMatcher<Decl> operator()() { return typedefNameDecl(hasName("T")); }
45 };
46 struct GetFunTemplPattern {
47   using DeclTy = FunctionTemplateDecl;
48   BindableMatcher<Decl> operator()() {
49     return functionTemplateDecl(hasName("f"));
50   }
51 };
52 
53 // Values for the value-parameterized test fixtures.
54 // FunctionDecl:
55 const auto *ExternF = "void f();";
56 const auto *StaticF = "static void f();";
57 const auto *AnonF = "namespace { void f(); }";
58 // VarDecl:
59 const auto *ExternV = "extern int v;";
60 const auto *StaticV = "static int v;";
61 const auto *AnonV = "namespace { extern int v; }";
62 // CXXRecordDecl:
63 const auto *ExternC = "class X;";
64 const auto *AnonC = "namespace { class X; }";
65 // EnumDecl:
66 const auto *ExternE = "enum E {};";
67 const auto *AnonE = "namespace { enum E {}; }";
68 // TypedefNameDecl:
69 const auto *ExternTypedef = "typedef int T;";
70 const auto *AnonTypedef = "namespace { typedef int T; }";
71 const auto *ExternUsing = "using T = int;";
72 const auto *AnonUsing = "namespace { using T = int; }";
73 // FunctionTemplateDecl:
74 const auto *ExternFT = "template <class> void f();";
75 const auto *StaticFT = "template <class> static void f();";
76 const auto *AnonFT = "namespace { template <class> void f(); }";
77 
78 // First value in tuple: Compile options.
79 // Second value in tuple: Source code to be used in the test.
80 using ImportVisibilityChainParams =
81     ::testing::WithParamInterface<std::tuple<ArgVector, const char *>>;
82 // Fixture to test the redecl chain of Decls with the same visibility. Gtest
83 // makes it possible to have either value-parameterized or type-parameterized
84 // fixtures. However, we cannot have both value- and type-parameterized test
85 // fixtures. This is a value-parameterized test fixture in the gtest sense. We
86 // intend to mimic gtest's type-parameters via the PatternFactory template
87 // parameter. We manually instantiate the different tests with the each types.
88 template <typename PatternFactory>
89 class ImportVisibilityChain
90     : public ASTImporterTestBase, public ImportVisibilityChainParams {
91 protected:
92   using DeclTy = typename PatternFactory::DeclTy;
93   ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
94   std::string getCode() const { return std::get<1>(GetParam()); }
95   BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
96 
97   // Type-parameterized test.
98   void TypedTest_ImportChain() {
99     std::string Code = getCode() + getCode();
100     auto Pattern = getPattern();
101 
102     TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_CXX14, "input0.cc");
103 
104     auto *FromD0 = FirstDeclMatcher<DeclTy>().match(FromTu, Pattern);
105     auto *FromD1 = LastDeclMatcher<DeclTy>().match(FromTu, Pattern);
106 
107     auto *ToD0 = Import(FromD0, Lang_CXX14);
108     auto *ToD1 = Import(FromD1, Lang_CXX14);
109 
110     EXPECT_TRUE(ToD0);
111     ASSERT_TRUE(ToD1);
112     EXPECT_NE(ToD0, ToD1);
113     EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
114   }
115 };
116 
117 // Manual instantiation of the fixture with each type.
118 using ImportFunctionsVisibilityChain = ImportVisibilityChain<GetFunPattern>;
119 using ImportVariablesVisibilityChain = ImportVisibilityChain<GetVarPattern>;
120 using ImportClassesVisibilityChain = ImportVisibilityChain<GetClassPattern>;
121 using ImportFunctionTemplatesVisibilityChain =
122     ImportVisibilityChain<GetFunTemplPattern>;
123 
124 // Value-parameterized test for functions.
125 TEST_P(ImportFunctionsVisibilityChain, ImportChain) {
126   TypedTest_ImportChain();
127 }
128 // Value-parameterized test for variables.
129 TEST_P(ImportVariablesVisibilityChain, ImportChain) {
130   TypedTest_ImportChain();
131 }
132 // Value-parameterized test for classes.
133 TEST_P(ImportClassesVisibilityChain, ImportChain) {
134   TypedTest_ImportChain();
135 }
136 // Value-parameterized test for function templates.
137 TEST_P(ImportFunctionTemplatesVisibilityChain, ImportChain) {
138   TypedTest_ImportChain();
139 }
140 
141 // Automatic instantiation of the value-parameterized tests.
142 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionsVisibilityChain,
143                         ::testing::Combine(
144                            DefaultTestValuesForRunOptions,
145                            ::testing::Values(ExternF, StaticF, AnonF)), );
146 INSTANTIATE_TEST_CASE_P(
147     ParameterizedTests, ImportVariablesVisibilityChain,
148     ::testing::Combine(
149         DefaultTestValuesForRunOptions,
150         // There is no point to instantiate with StaticV, because in C++ we can
151         // forward declare a variable only with the 'extern' keyword.
152         // Consequently, each fwd declared variable has external linkage.  This
153         // is different in the C language where any declaration without an
154         // initializer is a tentative definition, subsequent definitions may be
155         // provided but they must have the same linkage.  See also the test
156         // ImportVariableChainInC which test for this special C Lang case.
157         ::testing::Values(ExternV, AnonV)), );
158 INSTANTIATE_TEST_CASE_P(
159     ParameterizedTests, ImportClassesVisibilityChain,
160     ::testing::Combine(
161         DefaultTestValuesForRunOptions,
162         ::testing::Values(ExternC, AnonC)), );
163 INSTANTIATE_TEST_CASE_P(ParameterizedTests,
164                         ImportFunctionTemplatesVisibilityChain,
165                         ::testing::Combine(DefaultTestValuesForRunOptions,
166                                            ::testing::Values(ExternFT, StaticFT,
167                                                              AnonFT)), );
168 
169 // First value in tuple: Compile options.
170 // Second value in tuple: Tuple with informations for the test.
171 // Code for first import (or initial code), code to import, whether the `f`
172 // functions are expected to be linked in a declaration chain.
173 // One value of this tuple is combined with every value of compile options.
174 // The test can have a single tuple as parameter only.
175 using ImportVisibilityParams = ::testing::WithParamInterface<
176     std::tuple<ArgVector, std::tuple<const char *, const char *, bool>>>;
177 
178 template <typename PatternFactory>
179 class ImportVisibility
180     : public ASTImporterTestBase,
181       public ImportVisibilityParams {
182 protected:
183   using DeclTy = typename PatternFactory::DeclTy;
184   ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
185   std::string getCode0() const { return std::get<0>(std::get<1>(GetParam())); }
186   std::string getCode1() const { return std::get<1>(std::get<1>(GetParam())); }
187   bool shouldBeLinked() const { return std::get<2>(std::get<1>(GetParam())); }
188   BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
189 
190   void TypedTest_ImportAfter() {
191     TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX14);
192     TranslationUnitDecl *FromTu =
193         getTuDecl(getCode1(), Lang_CXX14, "input1.cc");
194 
195     auto *ToD0 = FirstDeclMatcher<DeclTy>().match(ToTu, getPattern());
196     auto *FromD1 = FirstDeclMatcher<DeclTy>().match(FromTu, getPattern());
197 
198     auto *ToD1 = Import(FromD1, Lang_CXX14);
199 
200     ASSERT_TRUE(ToD0);
201     ASSERT_TRUE(ToD1);
202     EXPECT_NE(ToD0, ToD1);
203 
204     if (shouldBeLinked())
205       EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
206     else
207       EXPECT_FALSE(ToD1->getPreviousDecl());
208   }
209 
210   void TypedTest_ImportAfterImport() {
211     TranslationUnitDecl *FromTu0 =
212         getTuDecl(getCode0(), Lang_CXX14, "input0.cc");
213     TranslationUnitDecl *FromTu1 =
214         getTuDecl(getCode1(), Lang_CXX14, "input1.cc");
215     auto *FromD0 = FirstDeclMatcher<DeclTy>().match(FromTu0, getPattern());
216     auto *FromD1 = FirstDeclMatcher<DeclTy>().match(FromTu1, getPattern());
217     auto *ToD0 = Import(FromD0, Lang_CXX14);
218     auto *ToD1 = Import(FromD1, Lang_CXX14);
219     ASSERT_TRUE(ToD0);
220     ASSERT_TRUE(ToD1);
221     EXPECT_NE(ToD0, ToD1);
222     if (shouldBeLinked())
223       EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
224     else
225       EXPECT_FALSE(ToD1->getPreviousDecl());
226   }
227 
228   void TypedTest_ImportAfterWithMerge() {
229     TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX14);
230     TranslationUnitDecl *FromTu =
231         getTuDecl(getCode1(), Lang_CXX14, "input1.cc");
232 
233     auto *ToF0 = FirstDeclMatcher<DeclTy>().match(ToTu, getPattern());
234     auto *FromF1 = FirstDeclMatcher<DeclTy>().match(FromTu, getPattern());
235 
236     auto *ToF1 = Import(FromF1, Lang_CXX14);
237 
238     ASSERT_TRUE(ToF0);
239     ASSERT_TRUE(ToF1);
240 
241     if (shouldBeLinked())
242       EXPECT_EQ(ToF0, ToF1);
243     else
244       EXPECT_NE(ToF0, ToF1);
245 
246     // We expect no (ODR) warning during the import.
247     EXPECT_EQ(0u, ToTu->getASTContext().getDiagnostics().getNumWarnings());
248   }
249 
250   void TypedTest_ImportAfterImportWithMerge() {
251     TranslationUnitDecl *FromTu0 =
252         getTuDecl(getCode0(), Lang_CXX14, "input0.cc");
253     TranslationUnitDecl *FromTu1 =
254         getTuDecl(getCode1(), Lang_CXX14, "input1.cc");
255     auto *FromF0 = FirstDeclMatcher<DeclTy>().match(FromTu0, getPattern());
256     auto *FromF1 = FirstDeclMatcher<DeclTy>().match(FromTu1, getPattern());
257     auto *ToF0 = Import(FromF0, Lang_CXX14);
258     auto *ToF1 = Import(FromF1, Lang_CXX14);
259     ASSERT_TRUE(ToF0);
260     ASSERT_TRUE(ToF1);
261     if (shouldBeLinked())
262       EXPECT_EQ(ToF0, ToF1);
263     else
264       EXPECT_NE(ToF0, ToF1);
265 
266     // We expect no (ODR) warning during the import.
267     EXPECT_EQ(0u, ToF0->getTranslationUnitDecl()
268                       ->getASTContext()
269                       .getDiagnostics()
270                       .getNumWarnings());
271   }
272 };
273 using ImportFunctionsVisibility = ImportVisibility<GetFunPattern>;
274 using ImportVariablesVisibility = ImportVisibility<GetVarPattern>;
275 using ImportClassesVisibility = ImportVisibility<GetClassPattern>;
276 using ImportEnumsVisibility = ImportVisibility<GetEnumPattern>;
277 using ImportTypedefNameVisibility = ImportVisibility<GetTypedefNamePattern>;
278 using ImportFunctionTemplatesVisibility = ImportVisibility<GetFunTemplPattern>;
279 
280 // FunctionDecl.
281 TEST_P(ImportFunctionsVisibility, ImportAfter) {
282   TypedTest_ImportAfter();
283 }
284 TEST_P(ImportFunctionsVisibility, ImportAfterImport) {
285   TypedTest_ImportAfterImport();
286 }
287 // VarDecl.
288 TEST_P(ImportVariablesVisibility, ImportAfter) {
289   TypedTest_ImportAfter();
290 }
291 TEST_P(ImportVariablesVisibility, ImportAfterImport) {
292   TypedTest_ImportAfterImport();
293 }
294 // CXXRecordDecl.
295 TEST_P(ImportClassesVisibility, ImportAfter) {
296   TypedTest_ImportAfter();
297 }
298 TEST_P(ImportClassesVisibility, ImportAfterImport) {
299   TypedTest_ImportAfterImport();
300 }
301 // EnumDecl.
302 TEST_P(ImportEnumsVisibility, ImportAfter) {
303   TypedTest_ImportAfterWithMerge();
304 }
305 TEST_P(ImportEnumsVisibility, ImportAfterImport) {
306   TypedTest_ImportAfterImportWithMerge();
307 }
308 // TypedefNameDecl.
309 TEST_P(ImportTypedefNameVisibility, ImportAfter) {
310   TypedTest_ImportAfterWithMerge();
311 }
312 TEST_P(ImportTypedefNameVisibility, ImportAfterImport) {
313   TypedTest_ImportAfterImportWithMerge();
314 }
315 // FunctionTemplateDecl.
316 TEST_P(ImportFunctionTemplatesVisibility, ImportAfter) {
317   TypedTest_ImportAfter();
318 }
319 TEST_P(ImportFunctionTemplatesVisibility, ImportAfterImport) {
320   TypedTest_ImportAfterImport();
321 }
322 
323 const bool ExpectLinkedDeclChain = true;
324 const bool ExpectUnlinkedDeclChain = false;
325 
326 INSTANTIATE_TEST_CASE_P(
327     ParameterizedTests, ImportFunctionsVisibility,
328     ::testing::Combine(
329         DefaultTestValuesForRunOptions,
330         ::testing::Values(
331             std::make_tuple(ExternF, ExternF, ExpectLinkedDeclChain),
332             std::make_tuple(ExternF, StaticF, ExpectUnlinkedDeclChain),
333             std::make_tuple(ExternF, AnonF, ExpectUnlinkedDeclChain),
334             std::make_tuple(StaticF, ExternF, ExpectUnlinkedDeclChain),
335             std::make_tuple(StaticF, StaticF, ExpectUnlinkedDeclChain),
336             std::make_tuple(StaticF, AnonF, ExpectUnlinkedDeclChain),
337             std::make_tuple(AnonF, ExternF, ExpectUnlinkedDeclChain),
338             std::make_tuple(AnonF, StaticF, ExpectUnlinkedDeclChain),
339             std::make_tuple(AnonF, AnonF, ExpectUnlinkedDeclChain))), );
340 INSTANTIATE_TEST_CASE_P(
341     ParameterizedTests, ImportVariablesVisibility,
342     ::testing::Combine(
343         DefaultTestValuesForRunOptions,
344         ::testing::Values(
345             std::make_tuple(ExternV, ExternV, ExpectLinkedDeclChain),
346             std::make_tuple(ExternV, StaticV, ExpectUnlinkedDeclChain),
347             std::make_tuple(ExternV, AnonV, ExpectUnlinkedDeclChain),
348             std::make_tuple(StaticV, ExternV, ExpectUnlinkedDeclChain),
349             std::make_tuple(StaticV, StaticV, ExpectUnlinkedDeclChain),
350             std::make_tuple(StaticV, AnonV, ExpectUnlinkedDeclChain),
351             std::make_tuple(AnonV, ExternV, ExpectUnlinkedDeclChain),
352             std::make_tuple(AnonV, StaticV, ExpectUnlinkedDeclChain),
353             std::make_tuple(AnonV, AnonV, ExpectUnlinkedDeclChain))), );
354 INSTANTIATE_TEST_CASE_P(
355     ParameterizedTests, ImportClassesVisibility,
356     ::testing::Combine(
357         DefaultTestValuesForRunOptions,
358         ::testing::Values(
359             std::make_tuple(ExternC, ExternC, ExpectLinkedDeclChain),
360             std::make_tuple(ExternC, AnonC, ExpectUnlinkedDeclChain),
361             std::make_tuple(AnonC, ExternC, ExpectUnlinkedDeclChain),
362             std::make_tuple(AnonC, AnonC, ExpectUnlinkedDeclChain))), );
363 INSTANTIATE_TEST_CASE_P(
364     ParameterizedTests, ImportEnumsVisibility,
365     ::testing::Combine(
366         DefaultTestValuesForRunOptions,
367         ::testing::Values(
368             std::make_tuple(ExternE, ExternE, ExpectLinkedDeclChain),
369             std::make_tuple(ExternE, AnonE, ExpectUnlinkedDeclChain),
370             std::make_tuple(AnonE, ExternE, ExpectUnlinkedDeclChain),
371             std::make_tuple(AnonE, AnonE, ExpectUnlinkedDeclChain))), );
372 INSTANTIATE_TEST_CASE_P(
373     ParameterizedTests, ImportTypedefNameVisibility,
374     ::testing::Combine(
375         DefaultTestValuesForRunOptions,
376         ::testing::Values(
377             std::make_tuple(ExternTypedef, ExternTypedef,
378                             ExpectLinkedDeclChain),
379             std::make_tuple(ExternTypedef, AnonTypedef,
380                             ExpectUnlinkedDeclChain),
381             std::make_tuple(AnonTypedef, ExternTypedef,
382                             ExpectUnlinkedDeclChain),
383             std::make_tuple(AnonTypedef, AnonTypedef, ExpectUnlinkedDeclChain),
384 
385             std::make_tuple(ExternUsing, ExternUsing, ExpectLinkedDeclChain),
386             std::make_tuple(ExternUsing, AnonUsing, ExpectUnlinkedDeclChain),
387             std::make_tuple(AnonUsing, ExternUsing, ExpectUnlinkedDeclChain),
388             std::make_tuple(AnonUsing, AnonUsing, ExpectUnlinkedDeclChain),
389 
390             std::make_tuple(ExternUsing, ExternTypedef, ExpectLinkedDeclChain),
391             std::make_tuple(ExternUsing, AnonTypedef, ExpectUnlinkedDeclChain),
392             std::make_tuple(AnonUsing, ExternTypedef, ExpectUnlinkedDeclChain),
393             std::make_tuple(AnonUsing, AnonTypedef, ExpectUnlinkedDeclChain),
394 
395             std::make_tuple(ExternTypedef, ExternUsing, ExpectLinkedDeclChain),
396             std::make_tuple(ExternTypedef, AnonUsing, ExpectUnlinkedDeclChain),
397             std::make_tuple(AnonTypedef, ExternUsing, ExpectUnlinkedDeclChain),
398             std::make_tuple(AnonTypedef, AnonUsing,
399                             ExpectUnlinkedDeclChain))), );
400 INSTANTIATE_TEST_CASE_P(
401     ParameterizedTests, ImportFunctionTemplatesVisibility,
402     ::testing::Combine(
403         DefaultTestValuesForRunOptions,
404         ::testing::Values(
405             std::make_tuple(ExternFT, ExternFT, ExpectLinkedDeclChain),
406             std::make_tuple(ExternFT, StaticFT, ExpectUnlinkedDeclChain),
407             std::make_tuple(ExternFT, AnonFT, ExpectUnlinkedDeclChain),
408             std::make_tuple(StaticFT, ExternFT, ExpectUnlinkedDeclChain),
409             std::make_tuple(StaticFT, StaticFT, ExpectUnlinkedDeclChain),
410             std::make_tuple(StaticFT, AnonFT, ExpectUnlinkedDeclChain),
411             std::make_tuple(AnonFT, ExternFT, ExpectUnlinkedDeclChain),
412             std::make_tuple(AnonFT, StaticFT, ExpectUnlinkedDeclChain),
413             std::make_tuple(AnonFT, AnonFT, ExpectUnlinkedDeclChain))), );
414 
415 } // end namespace ast_matchers
416 } // end namespace clang
417