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