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