blob: 88543257b75a47d7296a4b92398865d8c43edabb [file] [log] [blame]
Gabor Marton3c72fe12019-05-13 10:06:25 +00001//===- 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
20namespace clang {
21namespace ast_matchers {
22
23using internal::BindableMatcher;
24
25// Type parameters for type-parameterized test fixtures.
26struct GetFunPattern {
27 using DeclTy = FunctionDecl;
28 BindableMatcher<Decl> operator()() { return functionDecl(hasName("f")); }
29};
30struct GetVarPattern {
31 using DeclTy = VarDecl;
32 BindableMatcher<Decl> operator()() { return varDecl(hasName("v")); }
33};
Balazs Keric8272192019-05-27 09:36:00 +000034struct GetClassPattern {
35 using DeclTy = CXXRecordDecl;
36 BindableMatcher<Decl> operator()() { return cxxRecordDecl(hasName("X")); }
37};
Balazs Kerieb79b252019-07-09 11:08:18 +000038struct GetEnumPattern {
39 using DeclTy = EnumDecl;
40 BindableMatcher<Decl> operator()() { return enumDecl(hasName("E")); }
41};
Gabor Marton3c72fe12019-05-13 10:06:25 +000042
43// Values for the value-parameterized test fixtures.
44// FunctionDecl:
45const auto *ExternF = "void f();";
46const auto *StaticF = "static void f();";
47const auto *AnonF = "namespace { void f(); }";
48// VarDecl:
49const auto *ExternV = "extern int v;";
50const auto *StaticV = "static int v;";
51const auto *AnonV = "namespace { extern int v; }";
Balazs Keric8272192019-05-27 09:36:00 +000052// CXXRecordDecl:
53const auto *ExternC = "class X;";
54const auto *AnonC = "namespace { class X; }";
Balazs Kerieb79b252019-07-09 11:08:18 +000055// EnumDecl:
56const auto *ExternE = "enum E {};";
57const auto *AnonE = "namespace { enum E {}; }";
Gabor Marton3c72fe12019-05-13 10:06:25 +000058
59// First value in tuple: Compile options.
60// Second value in tuple: Source code to be used in the test.
61using ImportVisibilityChainParams =
62 ::testing::WithParamInterface<std::tuple<ArgVector, const char *>>;
63// Fixture to test the redecl chain of Decls with the same visibility. Gtest
64// makes it possible to have either value-parameterized or type-parameterized
65// fixtures. However, we cannot have both value- and type-parameterized test
66// fixtures. This is a value-parameterized test fixture in the gtest sense. We
67// intend to mimic gtest's type-parameters via the PatternFactory template
68// parameter. We manually instantiate the different tests with the each types.
69template <typename PatternFactory>
70class ImportVisibilityChain
71 : public ASTImporterTestBase, public ImportVisibilityChainParams {
72protected:
73 using DeclTy = typename PatternFactory::DeclTy;
74 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
75 std::string getCode() const { return std::get<1>(GetParam()); }
76 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
77
78 // Type-parameterized test.
79 void TypedTest_ImportChain() {
80 std::string Code = getCode() + getCode();
81 auto Pattern = getPattern();
82
Balazs Keri14d115f2019-07-15 12:16:30 +000083 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_CXX14, "input0.cc");
Gabor Marton3c72fe12019-05-13 10:06:25 +000084
85 auto *FromD0 = FirstDeclMatcher<DeclTy>().match(FromTu, Pattern);
86 auto *FromD1 = LastDeclMatcher<DeclTy>().match(FromTu, Pattern);
87
Balazs Keri14d115f2019-07-15 12:16:30 +000088 auto *ToD0 = Import(FromD0, Lang_CXX14);
89 auto *ToD1 = Import(FromD1, Lang_CXX14);
Gabor Marton3c72fe12019-05-13 10:06:25 +000090
91 EXPECT_TRUE(ToD0);
92 ASSERT_TRUE(ToD1);
93 EXPECT_NE(ToD0, ToD1);
94 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
95 }
96};
97
98// Manual instantiation of the fixture with each type.
99using ImportFunctionsVisibilityChain = ImportVisibilityChain<GetFunPattern>;
100using ImportVariablesVisibilityChain = ImportVisibilityChain<GetVarPattern>;
Balazs Keric8272192019-05-27 09:36:00 +0000101using ImportClassesVisibilityChain = ImportVisibilityChain<GetClassPattern>;
102// Value-parameterized test for functions.
Gabor Marton3c72fe12019-05-13 10:06:25 +0000103TEST_P(ImportFunctionsVisibilityChain, ImportChain) {
104 TypedTest_ImportChain();
105}
Balazs Keric8272192019-05-27 09:36:00 +0000106// Value-parameterized test for variables.
Gabor Marton3c72fe12019-05-13 10:06:25 +0000107TEST_P(ImportVariablesVisibilityChain, ImportChain) {
108 TypedTest_ImportChain();
109}
Balazs Keric8272192019-05-27 09:36:00 +0000110// Value-parameterized test for classes.
111TEST_P(ImportClassesVisibilityChain, ImportChain) {
112 TypedTest_ImportChain();
113}
Gabor Marton3c72fe12019-05-13 10:06:25 +0000114
115// Automatic instantiation of the value-parameterized tests.
116INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionsVisibilityChain,
117 ::testing::Combine(
118 DefaultTestValuesForRunOptions,
119 ::testing::Values(ExternF, StaticF, AnonF)), );
120INSTANTIATE_TEST_CASE_P(
121 ParameterizedTests, ImportVariablesVisibilityChain,
122 ::testing::Combine(
123 DefaultTestValuesForRunOptions,
124 // There is no point to instantiate with StaticV, because in C++ we can
125 // forward declare a variable only with the 'extern' keyword.
126 // Consequently, each fwd declared variable has external linkage. This
127 // is different in the C language where any declaration without an
128 // initializer is a tentative definition, subsequent definitions may be
129 // provided but they must have the same linkage. See also the test
130 // ImportVariableChainInC which test for this special C Lang case.
131 ::testing::Values(ExternV, AnonV)), );
Balazs Keric8272192019-05-27 09:36:00 +0000132INSTANTIATE_TEST_CASE_P(
133 ParameterizedTests, ImportClassesVisibilityChain,
134 ::testing::Combine(
135 DefaultTestValuesForRunOptions,
136 ::testing::Values(ExternC, AnonC)), );
Gabor Marton3c72fe12019-05-13 10:06:25 +0000137
138// First value in tuple: Compile options.
139// Second value in tuple: Tuple with informations for the test.
140// Code for first import (or initial code), code to import, whether the `f`
141// functions are expected to be linked in a declaration chain.
142// One value of this tuple is combined with every value of compile options.
143// The test can have a single tuple as parameter only.
144using ImportVisibilityParams = ::testing::WithParamInterface<
145 std::tuple<ArgVector, std::tuple<const char *, const char *, bool>>>;
146
147template <typename PatternFactory>
148class ImportVisibility
149 : public ASTImporterTestBase,
150 public ImportVisibilityParams {
151protected:
152 using DeclTy = typename PatternFactory::DeclTy;
153 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
154 std::string getCode0() const { return std::get<0>(std::get<1>(GetParam())); }
155 std::string getCode1() const { return std::get<1>(std::get<1>(GetParam())); }
156 bool shouldBeLinked() const { return std::get<2>(std::get<1>(GetParam())); }
157 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
158
159 void TypedTest_ImportAfter() {
Balazs Keri14d115f2019-07-15 12:16:30 +0000160 TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX14);
161 TranslationUnitDecl *FromTu =
162 getTuDecl(getCode1(), Lang_CXX14, "input1.cc");
Gabor Marton3c72fe12019-05-13 10:06:25 +0000163
164 auto *ToD0 = FirstDeclMatcher<DeclTy>().match(ToTu, getPattern());
165 auto *FromD1 = FirstDeclMatcher<DeclTy>().match(FromTu, getPattern());
166
Balazs Keri14d115f2019-07-15 12:16:30 +0000167 auto *ToD1 = Import(FromD1, Lang_CXX14);
Gabor Marton3c72fe12019-05-13 10:06:25 +0000168
169 ASSERT_TRUE(ToD0);
170 ASSERT_TRUE(ToD1);
171 EXPECT_NE(ToD0, ToD1);
172
173 if (shouldBeLinked())
174 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
175 else
176 EXPECT_FALSE(ToD1->getPreviousDecl());
177 }
178
179 void TypedTest_ImportAfterImport() {
Balazs Keri14d115f2019-07-15 12:16:30 +0000180 TranslationUnitDecl *FromTu0 =
181 getTuDecl(getCode0(), Lang_CXX14, "input0.cc");
182 TranslationUnitDecl *FromTu1 =
183 getTuDecl(getCode1(), Lang_CXX14, "input1.cc");
Gabor Marton3c72fe12019-05-13 10:06:25 +0000184 auto *FromD0 = FirstDeclMatcher<DeclTy>().match(FromTu0, getPattern());
185 auto *FromD1 = FirstDeclMatcher<DeclTy>().match(FromTu1, getPattern());
Balazs Keri14d115f2019-07-15 12:16:30 +0000186 auto *ToD0 = Import(FromD0, Lang_CXX14);
187 auto *ToD1 = Import(FromD1, Lang_CXX14);
Gabor Marton3c72fe12019-05-13 10:06:25 +0000188 ASSERT_TRUE(ToD0);
189 ASSERT_TRUE(ToD1);
190 EXPECT_NE(ToD0, ToD1);
191 if (shouldBeLinked())
192 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
193 else
194 EXPECT_FALSE(ToD1->getPreviousDecl());
195 }
Balazs Kerieb79b252019-07-09 11:08:18 +0000196
197 void TypedTest_ImportAfterWithMerge() {
Balazs Keri14d115f2019-07-15 12:16:30 +0000198 TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX14);
199 TranslationUnitDecl *FromTu =
200 getTuDecl(getCode1(), Lang_CXX14, "input1.cc");
Balazs Kerieb79b252019-07-09 11:08:18 +0000201
202 auto *ToF0 = FirstDeclMatcher<DeclTy>().match(ToTu, getPattern());
203 auto *FromF1 = FirstDeclMatcher<DeclTy>().match(FromTu, getPattern());
204
Balazs Keri14d115f2019-07-15 12:16:30 +0000205 auto *ToF1 = Import(FromF1, Lang_CXX14);
Balazs Kerieb79b252019-07-09 11:08:18 +0000206
207 ASSERT_TRUE(ToF0);
208 ASSERT_TRUE(ToF1);
209
210 if (shouldBeLinked())
211 EXPECT_EQ(ToF0, ToF1);
212 else
213 EXPECT_NE(ToF0, ToF1);
214
215 // We expect no (ODR) warning during the import.
216 EXPECT_EQ(0u, ToTu->getASTContext().getDiagnostics().getNumWarnings());
217 }
218
219 void TypedTest_ImportAfterImportWithMerge() {
Balazs Keri14d115f2019-07-15 12:16:30 +0000220 TranslationUnitDecl *FromTu0 =
221 getTuDecl(getCode0(), Lang_CXX14, "input0.cc");
222 TranslationUnitDecl *FromTu1 =
223 getTuDecl(getCode1(), Lang_CXX14, "input1.cc");
Balazs Kerieb79b252019-07-09 11:08:18 +0000224 auto *FromF0 = FirstDeclMatcher<DeclTy>().match(FromTu0, getPattern());
225 auto *FromF1 = FirstDeclMatcher<DeclTy>().match(FromTu1, getPattern());
Balazs Keri14d115f2019-07-15 12:16:30 +0000226 auto *ToF0 = Import(FromF0, Lang_CXX14);
227 auto *ToF1 = Import(FromF1, Lang_CXX14);
Balazs Kerieb79b252019-07-09 11:08:18 +0000228 ASSERT_TRUE(ToF0);
229 ASSERT_TRUE(ToF1);
230 if (shouldBeLinked())
231 EXPECT_EQ(ToF0, ToF1);
232 else
233 EXPECT_NE(ToF0, ToF1);
234
235 // We expect no (ODR) warning during the import.
236 EXPECT_EQ(0u, ToF0->getTranslationUnitDecl()
237 ->getASTContext()
238 .getDiagnostics()
239 .getNumWarnings());
240 }
Gabor Marton3c72fe12019-05-13 10:06:25 +0000241};
242using ImportFunctionsVisibility = ImportVisibility<GetFunPattern>;
243using ImportVariablesVisibility = ImportVisibility<GetVarPattern>;
Balazs Keric8272192019-05-27 09:36:00 +0000244using ImportClassesVisibility = ImportVisibility<GetClassPattern>;
Balazs Kerieb79b252019-07-09 11:08:18 +0000245using ImportEnumsVisibility = ImportVisibility<GetEnumPattern>;
Gabor Marton3c72fe12019-05-13 10:06:25 +0000246
247// FunctionDecl.
248TEST_P(ImportFunctionsVisibility, ImportAfter) {
249 TypedTest_ImportAfter();
250}
251TEST_P(ImportFunctionsVisibility, ImportAfterImport) {
252 TypedTest_ImportAfterImport();
253}
254// VarDecl.
255TEST_P(ImportVariablesVisibility, ImportAfter) {
256 TypedTest_ImportAfter();
257}
258TEST_P(ImportVariablesVisibility, ImportAfterImport) {
259 TypedTest_ImportAfterImport();
260}
Balazs Keric8272192019-05-27 09:36:00 +0000261// CXXRecordDecl.
262TEST_P(ImportClassesVisibility, ImportAfter) {
263 TypedTest_ImportAfter();
264}
265TEST_P(ImportClassesVisibility, ImportAfterImport) {
266 TypedTest_ImportAfterImport();
267}
Balazs Kerieb79b252019-07-09 11:08:18 +0000268// EnumDecl.
269TEST_P(ImportEnumsVisibility, ImportAfter) {
270 TypedTest_ImportAfterWithMerge();
271}
272TEST_P(ImportEnumsVisibility, ImportAfterImport) {
273 TypedTest_ImportAfterImportWithMerge();
274}
Gabor Marton3c72fe12019-05-13 10:06:25 +0000275
276const bool ExpectLink = true;
277const bool ExpectNotLink = false;
278
279INSTANTIATE_TEST_CASE_P(
280 ParameterizedTests, ImportFunctionsVisibility,
281 ::testing::Combine(
282 DefaultTestValuesForRunOptions,
283 ::testing::Values(std::make_tuple(ExternF, ExternF, ExpectLink),
284 std::make_tuple(ExternF, StaticF, ExpectNotLink),
285 std::make_tuple(ExternF, AnonF, ExpectNotLink),
286 std::make_tuple(StaticF, ExternF, ExpectNotLink),
287 std::make_tuple(StaticF, StaticF, ExpectNotLink),
288 std::make_tuple(StaticF, AnonF, ExpectNotLink),
289 std::make_tuple(AnonF, ExternF, ExpectNotLink),
290 std::make_tuple(AnonF, StaticF, ExpectNotLink),
291 std::make_tuple(AnonF, AnonF, ExpectNotLink))), );
292INSTANTIATE_TEST_CASE_P(
293 ParameterizedTests, ImportVariablesVisibility,
294 ::testing::Combine(
295 DefaultTestValuesForRunOptions,
296 ::testing::Values(std::make_tuple(ExternV, ExternV, ExpectLink),
297 std::make_tuple(ExternV, StaticV, ExpectNotLink),
298 std::make_tuple(ExternV, AnonV, ExpectNotLink),
299 std::make_tuple(StaticV, ExternV, ExpectNotLink),
300 std::make_tuple(StaticV, StaticV, ExpectNotLink),
301 std::make_tuple(StaticV, AnonV, ExpectNotLink),
302 std::make_tuple(AnonV, ExternV, ExpectNotLink),
303 std::make_tuple(AnonV, StaticV, ExpectNotLink),
304 std::make_tuple(AnonV, AnonV, ExpectNotLink))), );
Balazs Keric8272192019-05-27 09:36:00 +0000305INSTANTIATE_TEST_CASE_P(
306 ParameterizedTests, ImportClassesVisibility,
307 ::testing::Combine(
308 DefaultTestValuesForRunOptions,
309 ::testing::Values(std::make_tuple(ExternC, ExternC, ExpectLink),
310 std::make_tuple(ExternC, AnonC, ExpectNotLink),
311 std::make_tuple(AnonC, ExternC, ExpectNotLink),
312 std::make_tuple(AnonC, AnonC, ExpectNotLink))), );
Balazs Kerieb79b252019-07-09 11:08:18 +0000313INSTANTIATE_TEST_CASE_P(
314 ParameterizedTests, ImportEnumsVisibility,
315 ::testing::Combine(
316 DefaultTestValuesForRunOptions,
317 ::testing::Values(std::make_tuple(ExternE, ExternE, ExpectLink),
318 std::make_tuple(ExternE, AnonE, ExpectNotLink),
319 std::make_tuple(AnonE, ExternE, ExpectNotLink),
320 std::make_tuple(AnonE, AnonE, ExpectNotLink))), );
Gabor Marton3c72fe12019-05-13 10:06:25 +0000321
322} // end namespace ast_matchers
323} // end namespace clang