summaryrefslogtreecommitdiffstats
path: root/clang/unittests/AST/ASTImporterTest.cpp
diff options
context:
space:
mode:
authorGabor Marton <gabor.marton@ericsson.com>2019-08-27 11:36:10 +0000
committerGabor Marton <gabor.marton@ericsson.com>2019-08-27 11:36:10 +0000
commitf035b75d8f079a7b3c8d5c163e2ab0596ac59d17 (patch)
tree728488b68992c3688630151ee4ed9e29361066cb /clang/unittests/AST/ASTImporterTest.cpp
parentc397a266f01d7907e45a1f5c54bd9be219e94ea3 (diff)
downloadbcm5719-llvm-f035b75d8f079a7b3c8d5c163e2ab0596ac59d17.tar.gz
bcm5719-llvm-f035b75d8f079a7b3c8d5c163e2ab0596ac59d17.zip
[ASTImporter] Fix name conflict handling with different strategies
There are numorous flaws about the name conflict handling, this patch attempts fixes them. Changes in details: * HandleNameConflict return with a false DeclarationName Hitherto we effectively never returned with a NameConflict error, even if the preceding StructuralMatch indicated a conflict. Because we just simply returned with the parameter `Name` in HandleNameConflict and that name is almost always `true` when converted to `bool`. * Add tests which indicate wrong NameConflict handling * Add to ConflictingDecls only if decl kind is different Note, we might not indicate an ODR error when there is an existing record decl and a enum is imported with same name. But there are other cases. E.g. think about the case when we import a FunctionTemplateDecl with name f and we found a simple FunctionDecl with name f. They overload. Or in case of a ClassTemplateDecl and CXXRecordDecl, the CXXRecordDecl could be the 'templated' class, so it would be false to report error. So I think we should report a name conflict error only when we are 100% sure of that. That is why I think it should be a general pattern to report the error only if the kind is the same. * Fix failing ctu test with EnumConstandDecl In ctu-main.c we have the enum class 'A' which brings in the enum constant 'x' with value 0 into the global namespace. In ctu-other.c we had the enum class 'B' which brought in the same name ('x') as an enum constant but with a different enum value (42). This is clearly an ODR violation in the global namespace. The solution was to rename the second enum constant. * Introduce ODR handling strategies Reviewers: a_sidorin, shafik Differential Revision: https://reviews.llvm.org/D59692 llvm-svn: 370045
Diffstat (limited to 'clang/unittests/AST/ASTImporterTest.cpp')
-rw-r--r--clang/unittests/AST/ASTImporterTest.cpp269
1 files changed, 254 insertions, 15 deletions
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index 78b67d836b9..2038e3a28a3 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -1879,7 +1879,7 @@ TEST_P(ASTImporterOptionSpecificTestBase, AnonymousRecordsReversed) {
auto *ToTU = ToAST->getASTContext().getTranslationUnitDecl();
// We expect one (ODR) warning during the import.
EXPECT_EQ(1u, ToTU->getASTContext().getDiagnostics().getNumWarnings());
- EXPECT_EQ(2u,
+ EXPECT_EQ(1u,
DeclCounter<RecordDecl>().match(ToTU, recordDecl(hasName("X"))));
}
@@ -2432,6 +2432,62 @@ TEST_P(ImportFunctionTemplates,
EXPECT_EQ(ToD1, ToD2);
}
+TEST_P(ImportFunctionTemplates,
+ ImportFunctionWhenThereIsAFunTemplateWithSameName) {
+ getToTuDecl(
+ R"(
+ template <typename T>
+ void foo(T) {}
+ void foo();
+ )",
+ Lang_CXX);
+ Decl *FromTU = getTuDecl("void foo();", Lang_CXX);
+ auto *FromD = FirstDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("foo")));
+ auto *ImportedD = Import(FromD, Lang_CXX);
+ EXPECT_TRUE(ImportedD);
+}
+
+TEST_P(ImportFunctionTemplates,
+ ImportConstructorWhenThereIsAFunTemplateWithSameName) {
+ auto Code =
+ R"(
+ struct Foo {
+ template <typename T>
+ Foo(T) {}
+ Foo();
+ };
+ )";
+ getToTuDecl(Code, Lang_CXX);
+ Decl *FromTU = getTuDecl(Code, Lang_CXX);
+ auto *FromD =
+ LastDeclMatcher<CXXConstructorDecl>().match(FromTU, cxxConstructorDecl());
+ auto *ImportedD = Import(FromD, Lang_CXX);
+ EXPECT_TRUE(ImportedD);
+}
+
+TEST_P(ImportFunctionTemplates,
+ ImportOperatorWhenThereIsAFunTemplateWithSameName) {
+ getToTuDecl(
+ R"(
+ template <typename T>
+ void operator<(T,T) {}
+ struct X{};
+ void operator<(X, X);
+ )",
+ Lang_CXX);
+ Decl *FromTU = getTuDecl(
+ R"(
+ struct X{};
+ void operator<(X, X);
+ )",
+ Lang_CXX);
+ auto *FromD = LastDeclMatcher<FunctionDecl>().match(
+ FromTU, functionDecl(hasOverloadedOperatorName("<")));
+ auto *ImportedD = Import(FromD, Lang_CXX);
+ EXPECT_TRUE(ImportedD);
+}
+
struct ImportFriendFunctions : ImportFunctions {};
TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) {
@@ -5127,15 +5183,6 @@ TEST_P(ErrorHandlingTest,
}
}
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ErrorHandlingTest,
- DefaultTestValuesForRunOptions, );
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
- ::testing::Values(ArgVector()), );
-
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, CanonicalRedeclChain,
- ::testing::Values(ArgVector()), );
-
TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) {
Decl *FromTU = getTuDecl(
R"(
@@ -5233,8 +5280,8 @@ TEST_P(ASTImporterOptionSpecificTestBase,
// prototype (inside 'friend') for it comes first in the AST and is not
// linked to the definition.
EXPECT_EQ(ImportedDef, ToClassDef);
-}
-
+}
+
struct LLDBLookupTest : ASTImporterOptionSpecificTestBase {
LLDBLookupTest() {
Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
@@ -5362,10 +5409,197 @@ TEST_P(ASTImporterOptionSpecificTestBase,
EXPECT_EQ(ImportedX->isAggregate(), FromX->isAggregate());
}
+struct ConflictingDeclsWithLiberalStrategy : ASTImporterOptionSpecificTestBase {
+ ConflictingDeclsWithLiberalStrategy() {
+ this->ODRHandling = ASTImporter::ODRHandlingType::Liberal;
+ }
+};
+
+// Check that a Decl has been successfully imported into a standalone redecl
+// chain.
+template <typename DeclTy, typename PatternTy>
+static void CheckImportedAsNew(llvm::Expected<Decl *> &Result, Decl *ToTU,
+ PatternTy Pattern) {
+ ASSERT_TRUE(isSuccess(Result));
+ Decl *ImportedD = *Result;
+ ASSERT_TRUE(ImportedD);
+ auto *ToD = FirstDeclMatcher<DeclTy>().match(ToTU, Pattern);
+ EXPECT_NE(ImportedD, ToD);
+ EXPECT_FALSE(ImportedD->getPreviousDecl());
+ EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, Pattern), 2u);
+}
+
+TEST_P(ConflictingDeclsWithLiberalStrategy, Typedef) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ typedef int X;
+ )",
+ Lang_CXX11);
+ Decl *FromTU = getTuDecl(
+ R"(
+ typedef double X;
+ )",
+ Lang_CXX11);
+ auto Pattern = typedefNameDecl(hasName("X"));
+ auto *FromX = FirstDeclMatcher<TypedefNameDecl>().match(FromTU, Pattern);
+
+ Expected<Decl *> Result = importOrError(FromX, Lang_CXX11);
+ CheckImportedAsNew<TypedefNameDecl>(Result, ToTU, Pattern);
+}
+
+TEST_P(ConflictingDeclsWithLiberalStrategy, TypeAlias) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ using X = int;
+ )",
+ Lang_CXX11);
+ Decl *FromTU = getTuDecl(
+ R"(
+ using X = double;
+ )",
+ Lang_CXX11);
+ auto Pattern = typedefNameDecl(hasName("X"));
+ auto *FromX = FirstDeclMatcher<TypedefNameDecl>().match(FromTU, Pattern);
+ Expected<Decl *> Result = importOrError(FromX, Lang_CXX11);
+ CheckImportedAsNew<TypedefNameDecl>(Result, ToTU, Pattern);
+}
+
+TEST_P(ConflictingDeclsWithLiberalStrategy, EnumDecl) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ enum X { a, b };
+ )",
+ Lang_CXX11);
+ Decl *FromTU = getTuDecl(
+ R"(
+ enum X { a, b, c };
+ )",
+ Lang_CXX11);
+ auto Pattern = enumDecl(hasName("X"));
+ auto *FromX = FirstDeclMatcher<EnumDecl>().match(FromTU, Pattern);
+ Expected<Decl *> Result = importOrError(FromX, Lang_CXX11);
+ CheckImportedAsNew<EnumDecl>(Result, ToTU, Pattern);
+}
+
+TEST_P(ConflictingDeclsWithLiberalStrategy, EnumConstantDecl) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ enum E { X = 0 };
+ )",
+ Lang_CXX11);
+ Decl *FromTU = getTuDecl(
+ R"(
+ enum E { X = 1 };
+ )",
+ Lang_CXX11);
+ auto Pattern = enumConstantDecl(hasName("X"));
+ auto *FromX = FirstDeclMatcher<EnumConstantDecl>().match(FromTU, Pattern);
+ Expected<Decl *> Result = importOrError(FromX, Lang_CXX11);
+ CheckImportedAsNew<EnumConstantDecl>(Result, ToTU, Pattern);
+}
+
+TEST_P(ConflictingDeclsWithLiberalStrategy, RecordDecl) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ class X { int a; };
+ )",
+ Lang_CXX11);
+ Decl *FromTU = getTuDecl(
+ R"(
+ class X { int b; };
+ )",
+ Lang_CXX11);
+ auto Pattern = cxxRecordDecl(hasName("X"), unless(isImplicit()));
+ auto *FromX = FirstDeclMatcher<RecordDecl>().match(FromTU, Pattern);
+ Expected<Decl *> Result = importOrError(FromX, Lang_CXX11);
+ CheckImportedAsNew<RecordDecl>(Result, ToTU, Pattern);
+}
+
+TEST_P(ConflictingDeclsWithLiberalStrategy, VarDecl) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ int X;
+ )",
+ Lang_CXX11);
+ Decl *FromTU = getTuDecl(
+ R"(
+ double X;
+ )",
+ Lang_CXX11);
+ auto Pattern = varDecl(hasName("X"));
+ auto *FromX = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
+ Expected<Decl *> Result = importOrError(FromX, Lang_CXX11);
+ CheckImportedAsNew<VarDecl>(Result, ToTU, Pattern);
+}
+
+TEST_P(ConflictingDeclsWithLiberalStrategy, FunctionDecl) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ void X(int);
+ )",
+ Lang_C); // C, no overloading!
+ Decl *FromTU = getTuDecl(
+ R"(
+ void X(double);
+ )",
+ Lang_C);
+ auto Pattern = functionDecl(hasName("X"));
+ auto *FromX = FirstDeclMatcher<FunctionDecl>().match(FromTU, Pattern);
+ Expected<Decl *> Result = importOrError(FromX, Lang_CXX11);
+ CheckImportedAsNew<FunctionDecl>(Result, ToTU, Pattern);
+}
+
+TEST_P(ConflictingDeclsWithLiberalStrategy, ClassTemplateDecl) {
+ Decl *ToTU = getToTuDecl(
+ R"(
+ template <class>
+ struct X;
+ )",
+ Lang_CXX11);
+ Decl *FromTU = getTuDecl(
+ R"(
+ template <int>
+ struct X;
+ )",
+ Lang_CXX11);
+ auto Pattern = classTemplateDecl(hasName("X"));
+ auto *FromX = FirstDeclMatcher<ClassTemplateDecl>().match(FromTU, Pattern);
+ Expected<Decl *> Result = importOrError(FromX, Lang_CXX11);
+ CheckImportedAsNew<ClassTemplateDecl>(Result, ToTU, Pattern);
+}
+
+TEST_P(ConflictingDeclsWithLiberalStrategy, DISABLED_VarTemplateDecl) {
+ const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateDecl>
+ varTemplateDecl;
+ Decl *ToTU = getToTuDecl(
+ R"(
+ template <class T>
+ constexpr T X;
+ )",
+ Lang_CXX14);
+ Decl *FromTU = getTuDecl(
+ R"(
+ template <int>
+ constexpr int X = 0;
+ )",
+ Lang_CXX14);
+ auto Pattern = varTemplateDecl(hasName("X"));
+ auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match(
+ FromTU, varTemplateDecl(hasName("X")));
+ Expected<Decl *> Result = importOrError(FromX, Lang_CXX11);
+ CheckImportedAsNew<VarTemplateDecl>(Result, ToTU, Pattern);
+}
+
INSTANTIATE_TEST_CASE_P(ParameterizedTests, SVEBuiltins,
::testing::Values(ArgVector{"-target",
"aarch64-linux-gnu"}), );
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
+ ::testing::Values(ArgVector()), );
+
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, CanonicalRedeclChain,
+ ::testing::Values(ArgVector()), );
+
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
DefaultTestValuesForRunOptions, );
@@ -5384,19 +5618,22 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportDecl,
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterOptionSpecificTestBase,
DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ErrorHandlingTest,
+ DefaultTestValuesForRunOptions, );
+
INSTANTIATE_TEST_CASE_P(ParameterizedTests, RedirectingImporterTest,
DefaultTestValuesForRunOptions, );
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctions,
DefaultTestValuesForRunOptions, );
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionTemplates,
DefaultTestValuesForRunOptions, );
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates,
DefaultTestValuesForRunOptions, );
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionTemplates,
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses,
DefaultTestValuesForRunOptions, );
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions,
@@ -5418,6 +5655,8 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
INSTANTIATE_TEST_CASE_P(ParameterizedTests, LLDBLookupTest,
DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(ParameterizedTests, ConflictingDeclsWithLiberalStrategy,
+ DefaultTestValuesForRunOptions, );
} // end namespace ast_matchers
} // end namespace clang
OpenPOWER on IntegriCloud