blob: 95b7c4c920abb497e7b9b666a80fdcfa062ac859 [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};
Gabor Marton3c72fe12019-05-13 10:06:25 +000038
39// Values for the value-parameterized test fixtures.
40// FunctionDecl:
41const auto *ExternF = "void f();";
42const auto *StaticF = "static void f();";
43const auto *AnonF = "namespace { void f(); }";
44// VarDecl:
45const auto *ExternV = "extern int v;";
46const auto *StaticV = "static int v;";
47const auto *AnonV = "namespace { extern int v; }";
Balazs Keric8272192019-05-27 09:36:00 +000048// CXXRecordDecl:
49const auto *ExternC = "class X;";
50const auto *AnonC = "namespace { class X; }";
Gabor Marton3c72fe12019-05-13 10:06:25 +000051
52// First value in tuple: Compile options.
53// Second value in tuple: Source code to be used in the test.
54using ImportVisibilityChainParams =
55 ::testing::WithParamInterface<std::tuple<ArgVector, const char *>>;
56// Fixture to test the redecl chain of Decls with the same visibility. Gtest
57// makes it possible to have either value-parameterized or type-parameterized
58// fixtures. However, we cannot have both value- and type-parameterized test
59// fixtures. This is a value-parameterized test fixture in the gtest sense. We
60// intend to mimic gtest's type-parameters via the PatternFactory template
61// parameter. We manually instantiate the different tests with the each types.
62template <typename PatternFactory>
63class ImportVisibilityChain
64 : public ASTImporterTestBase, public ImportVisibilityChainParams {
65protected:
66 using DeclTy = typename PatternFactory::DeclTy;
67 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
68 std::string getCode() const { return std::get<1>(GetParam()); }
69 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
70
71 // Type-parameterized test.
72 void TypedTest_ImportChain() {
73 std::string Code = getCode() + getCode();
74 auto Pattern = getPattern();
75
76 TranslationUnitDecl *FromTu = getTuDecl(Code, Lang_CXX, "input0.cc");
77
78 auto *FromD0 = FirstDeclMatcher<DeclTy>().match(FromTu, Pattern);
79 auto *FromD1 = LastDeclMatcher<DeclTy>().match(FromTu, Pattern);
80
81 auto *ToD0 = Import(FromD0, Lang_CXX);
82 auto *ToD1 = Import(FromD1, Lang_CXX);
83
84 EXPECT_TRUE(ToD0);
85 ASSERT_TRUE(ToD1);
86 EXPECT_NE(ToD0, ToD1);
87 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
88 }
89};
90
91// Manual instantiation of the fixture with each type.
92using ImportFunctionsVisibilityChain = ImportVisibilityChain<GetFunPattern>;
93using ImportVariablesVisibilityChain = ImportVisibilityChain<GetVarPattern>;
Balazs Keric8272192019-05-27 09:36:00 +000094using ImportClassesVisibilityChain = ImportVisibilityChain<GetClassPattern>;
95// Value-parameterized test for functions.
Gabor Marton3c72fe12019-05-13 10:06:25 +000096TEST_P(ImportFunctionsVisibilityChain, ImportChain) {
97 TypedTest_ImportChain();
98}
Balazs Keric8272192019-05-27 09:36:00 +000099// Value-parameterized test for variables.
Gabor Marton3c72fe12019-05-13 10:06:25 +0000100TEST_P(ImportVariablesVisibilityChain, ImportChain) {
101 TypedTest_ImportChain();
102}
Balazs Keric8272192019-05-27 09:36:00 +0000103// Value-parameterized test for classes.
104TEST_P(ImportClassesVisibilityChain, ImportChain) {
105 TypedTest_ImportChain();
106}
Gabor Marton3c72fe12019-05-13 10:06:25 +0000107
108// Automatic instantiation of the value-parameterized tests.
109INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionsVisibilityChain,
110 ::testing::Combine(
111 DefaultTestValuesForRunOptions,
112 ::testing::Values(ExternF, StaticF, AnonF)), );
113INSTANTIATE_TEST_CASE_P(
114 ParameterizedTests, ImportVariablesVisibilityChain,
115 ::testing::Combine(
116 DefaultTestValuesForRunOptions,
117 // There is no point to instantiate with StaticV, because in C++ we can
118 // forward declare a variable only with the 'extern' keyword.
119 // Consequently, each fwd declared variable has external linkage. This
120 // is different in the C language where any declaration without an
121 // initializer is a tentative definition, subsequent definitions may be
122 // provided but they must have the same linkage. See also the test
123 // ImportVariableChainInC which test for this special C Lang case.
124 ::testing::Values(ExternV, AnonV)), );
Balazs Keric8272192019-05-27 09:36:00 +0000125INSTANTIATE_TEST_CASE_P(
126 ParameterizedTests, ImportClassesVisibilityChain,
127 ::testing::Combine(
128 DefaultTestValuesForRunOptions,
129 ::testing::Values(ExternC, AnonC)), );
Gabor Marton3c72fe12019-05-13 10:06:25 +0000130
131// First value in tuple: Compile options.
132// Second value in tuple: Tuple with informations for the test.
133// Code for first import (or initial code), code to import, whether the `f`
134// functions are expected to be linked in a declaration chain.
135// One value of this tuple is combined with every value of compile options.
136// The test can have a single tuple as parameter only.
137using ImportVisibilityParams = ::testing::WithParamInterface<
138 std::tuple<ArgVector, std::tuple<const char *, const char *, bool>>>;
139
140template <typename PatternFactory>
141class ImportVisibility
142 : public ASTImporterTestBase,
143 public ImportVisibilityParams {
144protected:
145 using DeclTy = typename PatternFactory::DeclTy;
146 ArgVector getExtraArgs() const override { return std::get<0>(GetParam()); }
147 std::string getCode0() const { return std::get<0>(std::get<1>(GetParam())); }
148 std::string getCode1() const { return std::get<1>(std::get<1>(GetParam())); }
149 bool shouldBeLinked() const { return std::get<2>(std::get<1>(GetParam())); }
150 BindableMatcher<Decl> getPattern() const { return PatternFactory()(); }
151
152 void TypedTest_ImportAfter() {
153 TranslationUnitDecl *ToTu = getToTuDecl(getCode0(), Lang_CXX);
154 TranslationUnitDecl *FromTu = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
155
156 auto *ToD0 = FirstDeclMatcher<DeclTy>().match(ToTu, getPattern());
157 auto *FromD1 = FirstDeclMatcher<DeclTy>().match(FromTu, getPattern());
158
159 auto *ToD1 = Import(FromD1, Lang_CXX);
160
161 ASSERT_TRUE(ToD0);
162 ASSERT_TRUE(ToD1);
163 EXPECT_NE(ToD0, ToD1);
164
165 if (shouldBeLinked())
166 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
167 else
168 EXPECT_FALSE(ToD1->getPreviousDecl());
169 }
170
171 void TypedTest_ImportAfterImport() {
172 TranslationUnitDecl *FromTu0 = getTuDecl(getCode0(), Lang_CXX, "input0.cc");
173 TranslationUnitDecl *FromTu1 = getTuDecl(getCode1(), Lang_CXX, "input1.cc");
174 auto *FromD0 = FirstDeclMatcher<DeclTy>().match(FromTu0, getPattern());
175 auto *FromD1 = FirstDeclMatcher<DeclTy>().match(FromTu1, getPattern());
176 auto *ToD0 = Import(FromD0, Lang_CXX);
177 auto *ToD1 = Import(FromD1, Lang_CXX);
178 ASSERT_TRUE(ToD0);
179 ASSERT_TRUE(ToD1);
180 EXPECT_NE(ToD0, ToD1);
181 if (shouldBeLinked())
182 EXPECT_EQ(ToD1->getPreviousDecl(), ToD0);
183 else
184 EXPECT_FALSE(ToD1->getPreviousDecl());
185 }
186};
187using ImportFunctionsVisibility = ImportVisibility<GetFunPattern>;
188using ImportVariablesVisibility = ImportVisibility<GetVarPattern>;
Balazs Keric8272192019-05-27 09:36:00 +0000189using ImportClassesVisibility = ImportVisibility<GetClassPattern>;
Gabor Marton3c72fe12019-05-13 10:06:25 +0000190
191// FunctionDecl.
192TEST_P(ImportFunctionsVisibility, ImportAfter) {
193 TypedTest_ImportAfter();
194}
195TEST_P(ImportFunctionsVisibility, ImportAfterImport) {
196 TypedTest_ImportAfterImport();
197}
198// VarDecl.
199TEST_P(ImportVariablesVisibility, ImportAfter) {
200 TypedTest_ImportAfter();
201}
202TEST_P(ImportVariablesVisibility, ImportAfterImport) {
203 TypedTest_ImportAfterImport();
204}
Balazs Keric8272192019-05-27 09:36:00 +0000205// CXXRecordDecl.
206TEST_P(ImportClassesVisibility, ImportAfter) {
207 TypedTest_ImportAfter();
208}
209TEST_P(ImportClassesVisibility, ImportAfterImport) {
210 TypedTest_ImportAfterImport();
211}
Gabor Marton3c72fe12019-05-13 10:06:25 +0000212
213const bool ExpectLink = true;
214const bool ExpectNotLink = false;
215
216INSTANTIATE_TEST_CASE_P(
217 ParameterizedTests, ImportFunctionsVisibility,
218 ::testing::Combine(
219 DefaultTestValuesForRunOptions,
220 ::testing::Values(std::make_tuple(ExternF, ExternF, ExpectLink),
221 std::make_tuple(ExternF, StaticF, ExpectNotLink),
222 std::make_tuple(ExternF, AnonF, ExpectNotLink),
223 std::make_tuple(StaticF, ExternF, ExpectNotLink),
224 std::make_tuple(StaticF, StaticF, ExpectNotLink),
225 std::make_tuple(StaticF, AnonF, ExpectNotLink),
226 std::make_tuple(AnonF, ExternF, ExpectNotLink),
227 std::make_tuple(AnonF, StaticF, ExpectNotLink),
228 std::make_tuple(AnonF, AnonF, ExpectNotLink))), );
229INSTANTIATE_TEST_CASE_P(
230 ParameterizedTests, ImportVariablesVisibility,
231 ::testing::Combine(
232 DefaultTestValuesForRunOptions,
233 ::testing::Values(std::make_tuple(ExternV, ExternV, ExpectLink),
234 std::make_tuple(ExternV, StaticV, ExpectNotLink),
235 std::make_tuple(ExternV, AnonV, ExpectNotLink),
236 std::make_tuple(StaticV, ExternV, ExpectNotLink),
237 std::make_tuple(StaticV, StaticV, ExpectNotLink),
238 std::make_tuple(StaticV, AnonV, ExpectNotLink),
239 std::make_tuple(AnonV, ExternV, ExpectNotLink),
240 std::make_tuple(AnonV, StaticV, ExpectNotLink),
241 std::make_tuple(AnonV, AnonV, ExpectNotLink))), );
Balazs Keric8272192019-05-27 09:36:00 +0000242INSTANTIATE_TEST_CASE_P(
243 ParameterizedTests, ImportClassesVisibility,
244 ::testing::Combine(
245 DefaultTestValuesForRunOptions,
246 ::testing::Values(std::make_tuple(ExternC, ExternC, ExpectLink),
247 std::make_tuple(ExternC, AnonC, ExpectNotLink),
248 std::make_tuple(AnonC, ExternC, ExpectNotLink),
249 std::make_tuple(AnonC, AnonC, ExpectNotLink))), );
Gabor Marton3c72fe12019-05-13 10:06:25 +0000250
251} // end namespace ast_matchers
252} // end namespace clang