blob: 66c967e8460b93e554cb633fc63ced29e5a2ce65 [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
83 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_CXX, "input0.cc");
84
85 auto *FromD0 = FirstDeclMatcher<DeclTy>().match(FromTu, Pattern);
86 auto *FromD1 = LastDeclMatcher<DeclTy>().match(FromTu, Pattern);
87
88 auto *ToD0 = Import(FromD0, Lang_CXX);
89 auto *ToD1 = Import(FromD1, Lang_CXX);
90
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() {
160 TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX);
161 TranslationUnitDecl *FromTu = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
162
163 auto *ToD0 = FirstDeclMatcher<DeclTy>().match(ToTu, getPattern());
164 auto *FromD1 = FirstDeclMatcher<DeclTy>().match(FromTu, getPattern());
165
166 auto *ToD1 = Import(FromD1, Lang_CXX);
167
168 ASSERT_TRUE(ToD0);
169 ASSERT_TRUE(ToD1);
170 EXPECT_NE(ToD0, ToD1);
171
172 if (shouldBeLinked())
173 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
174 else
175 EXPECT_FALSE(ToD1->getPreviousDecl());
176 }
177
178 void TypedTest_ImportAfterImport() {
179 TranslationUnitDecl *FromTu0 = getTuDecl(getCode0(), Lang_CXX, "input0.cc");
180 TranslationUnitDecl *FromTu1 = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
181 auto *FromD0 = FirstDeclMatcher<DeclTy>().match(FromTu0, getPattern());
182 auto *FromD1 = FirstDeclMatcher<DeclTy>().match(FromTu1, getPattern());
183 auto *ToD0 = Import(FromD0, Lang_CXX);
184 auto *ToD1 = Import(FromD1, Lang_CXX);
185 ASSERT_TRUE(ToD0);
186 ASSERT_TRUE(ToD1);
187 EXPECT_NE(ToD0, ToD1);
188 if (shouldBeLinked())
189 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
190 else
191 EXPECT_FALSE(ToD1->getPreviousDecl());
192 }
Balazs Kerieb79b252019-07-09 11:08:18 +0000193
194 void TypedTest_ImportAfterWithMerge() {
195 TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX);
196 TranslationUnitDecl *FromTu = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
197
198 auto *ToF0 = FirstDeclMatcher<DeclTy>().match(ToTu, getPattern());
199 auto *FromF1 = FirstDeclMatcher<DeclTy>().match(FromTu, getPattern());
200
201 auto *ToF1 = Import(FromF1, Lang_CXX);
202
203 ASSERT_TRUE(ToF0);
204 ASSERT_TRUE(ToF1);
205
206 if (shouldBeLinked())
207 EXPECT_EQ(ToF0, ToF1);
208 else
209 EXPECT_NE(ToF0, ToF1);
210
211 // We expect no (ODR) warning during the import.
212 EXPECT_EQ(0u, ToTu->getASTContext().getDiagnostics().getNumWarnings());
213 }
214
215 void TypedTest_ImportAfterImportWithMerge() {
216 TranslationUnitDecl *FromTu0 = getTuDecl(getCode0(), Lang_CXX, "input0.cc");
217 TranslationUnitDecl *FromTu1 = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
218 auto *FromF0 = FirstDeclMatcher<DeclTy>().match(FromTu0, getPattern());
219 auto *FromF1 = FirstDeclMatcher<DeclTy>().match(FromTu1, getPattern());
220 auto *ToF0 = Import(FromF0, Lang_CXX);
221 auto *ToF1 = Import(FromF1, Lang_CXX);
222 ASSERT_TRUE(ToF0);
223 ASSERT_TRUE(ToF1);
224 if (shouldBeLinked())
225 EXPECT_EQ(ToF0, ToF1);
226 else
227 EXPECT_NE(ToF0, ToF1);
228
229 // We expect no (ODR) warning during the import.
230 EXPECT_EQ(0u, ToF0->getTranslationUnitDecl()
231 ->getASTContext()
232 .getDiagnostics()
233 .getNumWarnings());
234 }
Gabor Marton3c72fe12019-05-13 10:06:25 +0000235};
236using ImportFunctionsVisibility = ImportVisibility<GetFunPattern>;
237using ImportVariablesVisibility = ImportVisibility<GetVarPattern>;
Balazs Keric8272192019-05-27 09:36:00 +0000238using ImportClassesVisibility = ImportVisibility<GetClassPattern>;
Balazs Kerieb79b252019-07-09 11:08:18 +0000239using ImportEnumsVisibility = ImportVisibility<GetEnumPattern>;
Gabor Marton3c72fe12019-05-13 10:06:25 +0000240
241// FunctionDecl.
242TEST_P(ImportFunctionsVisibility, ImportAfter) {
243 TypedTest_ImportAfter();
244}
245TEST_P(ImportFunctionsVisibility, ImportAfterImport) {
246 TypedTest_ImportAfterImport();
247}
248// VarDecl.
249TEST_P(ImportVariablesVisibility, ImportAfter) {
250 TypedTest_ImportAfter();
251}
252TEST_P(ImportVariablesVisibility, ImportAfterImport) {
253 TypedTest_ImportAfterImport();
254}
Balazs Keric8272192019-05-27 09:36:00 +0000255// CXXRecordDecl.
256TEST_P(ImportClassesVisibility, ImportAfter) {
257 TypedTest_ImportAfter();
258}
259TEST_P(ImportClassesVisibility, ImportAfterImport) {
260 TypedTest_ImportAfterImport();
261}
Balazs Kerieb79b252019-07-09 11:08:18 +0000262// EnumDecl.
263TEST_P(ImportEnumsVisibility, ImportAfter) {
264 TypedTest_ImportAfterWithMerge();
265}
266TEST_P(ImportEnumsVisibility, ImportAfterImport) {
267 TypedTest_ImportAfterImportWithMerge();
268}
Gabor Marton3c72fe12019-05-13 10:06:25 +0000269
270const bool ExpectLink = true;
271const bool ExpectNotLink = false;
272
273INSTANTIATE_TEST_CASE_P(
274 ParameterizedTests, ImportFunctionsVisibility,
275 ::testing::Combine(
276 DefaultTestValuesForRunOptions,
277 ::testing::Values(std::make_tuple(ExternF, ExternF, ExpectLink),
278 std::make_tuple(ExternF, StaticF, ExpectNotLink),
279 std::make_tuple(ExternF, AnonF, ExpectNotLink),
280 std::make_tuple(StaticF, ExternF, ExpectNotLink),
281 std::make_tuple(StaticF, StaticF, ExpectNotLink),
282 std::make_tuple(StaticF, AnonF, ExpectNotLink),
283 std::make_tuple(AnonF, ExternF, ExpectNotLink),
284 std::make_tuple(AnonF, StaticF, ExpectNotLink),
285 std::make_tuple(AnonF, AnonF, ExpectNotLink))), );
286INSTANTIATE_TEST_CASE_P(
287 ParameterizedTests, ImportVariablesVisibility,
288 ::testing::Combine(
289 DefaultTestValuesForRunOptions,
290 ::testing::Values(std::make_tuple(ExternV, ExternV, ExpectLink),
291 std::make_tuple(ExternV, StaticV, ExpectNotLink),
292 std::make_tuple(ExternV, AnonV, ExpectNotLink),
293 std::make_tuple(StaticV, ExternV, ExpectNotLink),
294 std::make_tuple(StaticV, StaticV, ExpectNotLink),
295 std::make_tuple(StaticV, AnonV, ExpectNotLink),
296 std::make_tuple(AnonV, ExternV, ExpectNotLink),
297 std::make_tuple(AnonV, StaticV, ExpectNotLink),
298 std::make_tuple(AnonV, AnonV, ExpectNotLink))), );
Balazs Keric8272192019-05-27 09:36:00 +0000299INSTANTIATE_TEST_CASE_P(
300 ParameterizedTests, ImportClassesVisibility,
301 ::testing::Combine(
302 DefaultTestValuesForRunOptions,
303 ::testing::Values(std::make_tuple(ExternC, ExternC, ExpectLink),
304 std::make_tuple(ExternC, AnonC, ExpectNotLink),
305 std::make_tuple(AnonC, ExternC, ExpectNotLink),
306 std::make_tuple(AnonC, AnonC, ExpectNotLink))), );
Balazs Kerieb79b252019-07-09 11:08:18 +0000307INSTANTIATE_TEST_CASE_P(
308 ParameterizedTests, ImportEnumsVisibility,
309 ::testing::Combine(
310 DefaultTestValuesForRunOptions,
311 ::testing::Values(std::make_tuple(ExternE, ExternE, ExpectLink),
312 std::make_tuple(ExternE, AnonE, ExpectNotLink),
313 std::make_tuple(AnonE, ExternE, ExpectNotLink),
314 std::make_tuple(AnonE, AnonE, ExpectNotLink))), );
Gabor Marton3c72fe12019-05-13 10:06:25 +0000315
316} // end namespace ast_matchers
317} // end namespace clang