r372564 - [ASTImporter][NFC] Add comprehensive tests for ODR violation handling strategies
Gabor Marton via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 23 02:32:07 PDT 2019
Author: martong
Date: Mon Sep 23 02:32:07 2019
New Revision: 372564
URL: http://llvm.org/viewvc/llvm-project?rev=372564&view=rev
Log:
[ASTImporter][NFC] Add comprehensive tests for ODR violation handling strategies
Summary:
In this patch we provide additional and comprehensive tests for the ODR
handling strategies. This is the continuation of
https://reviews.llvm.org/D59692.
Reviewers: shafik, a_sidorin, balazske, a.sidorin
Subscribers: mgorny, rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66951
Added:
cfe/trunk/unittests/AST/ASTImporterODRStrategiesTest.cpp
Modified:
cfe/trunk/unittests/AST/ASTImporterTest.cpp
cfe/trunk/unittests/AST/CMakeLists.txt
Added: cfe/trunk/unittests/AST/ASTImporterODRStrategiesTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterODRStrategiesTest.cpp?rev=372564&view=auto
==============================================================================
--- cfe/trunk/unittests/AST/ASTImporterODRStrategiesTest.cpp (added)
+++ cfe/trunk/unittests/AST/ASTImporterODRStrategiesTest.cpp Mon Sep 23 02:32:07 2019
@@ -0,0 +1,670 @@
+//===- unittest/AST/ASTImporterODRStrategiesTest.cpp -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Type-parameterized tests to verify the import behaviour in case of ODR
+// violation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ASTImporterFixtures.h"
+
+namespace clang {
+namespace ast_matchers {
+
+using internal::BindableMatcher;
+
+// DeclTy: Type of the Decl to check.
+// Prototype: "Prototype" (forward declaration) of the Decl.
+// Definition: A definition for the Prototype.
+// ConflictingPrototype: A prototype with the same name but different
+// declaration.
+// ConflictingDefinition: A different definition for Prototype.
+// ConflictingProtoDef: A definition for ConflictingPrototype.
+// getPattern: Return a matcher that matches any of Prototype, Definition,
+// ConflictingPrototype, ConflictingDefinition, ConflictingProtoDef.
+
+struct Function {
+ using DeclTy = FunctionDecl;
+ static constexpr auto *Prototype = "void X(int);";
+ static constexpr auto *ConflictingPrototype = "void X(double);";
+ static constexpr auto *Definition = "void X(int a) {}";
+ static constexpr auto *ConflictingDefinition = "void X(double a) {}";
+ BindableMatcher<Decl> getPattern() {
+ return functionDecl(hasName("X"), unless(isImplicit()));
+ }
+ Language getLang() { return Lang_C; }
+};
+
+struct Typedef {
+ using DeclTy = TypedefNameDecl;
+ static constexpr auto *Definition = "typedef int X;";
+ static constexpr auto *ConflictingDefinition = "typedef double X;";
+ BindableMatcher<Decl> getPattern() { return typedefNameDecl(hasName("X")); }
+ Language getLang() { return Lang_CXX; }
+};
+
+struct TypedefAlias {
+ using DeclTy = TypedefNameDecl;
+ static constexpr auto *Definition = "using X = int;";
+ static constexpr auto *ConflictingDefinition = "using X = double;";
+ BindableMatcher<Decl> getPattern() { return typedefNameDecl(hasName("X")); }
+ Language getLang() { return Lang_CXX11; }
+};
+
+struct Enum {
+ using DeclTy = EnumDecl;
+ static constexpr auto *Definition = "enum X { a, b };";
+ static constexpr auto *ConflictingDefinition = "enum X { a, b, c };";
+ BindableMatcher<Decl> getPattern() { return enumDecl(hasName("X")); }
+ Language getLang() { return Lang_CXX; }
+};
+
+struct EnumConstant {
+ using DeclTy = EnumConstantDecl;
+ static constexpr auto *Definition = "enum E { X = 0 };";
+ static constexpr auto *ConflictingDefinition = "enum E { X = 1 };";
+ BindableMatcher<Decl> getPattern() { return enumConstantDecl(hasName("X")); }
+ Language getLang() { return Lang_CXX; }
+};
+
+struct Class {
+ using DeclTy = CXXRecordDecl;
+ static constexpr auto *Prototype = "class X;";
+ static constexpr auto *Definition = "class X {};";
+ static constexpr auto *ConflictingDefinition = "class X { int A; };";
+ BindableMatcher<Decl> getPattern() {
+ return cxxRecordDecl(hasName("X"), unless(isImplicit()));
+ }
+ Language getLang() { return Lang_CXX; }
+};
+
+struct Variable {
+ using DeclTy = VarDecl;
+ static constexpr auto *Prototype = "extern int X;";
+ static constexpr auto *ConflictingPrototype = "extern float X;";
+ static constexpr auto *Definition = "int X;";
+ static constexpr auto *ConflictingDefinition = "float X;";
+ BindableMatcher<Decl> getPattern() { return varDecl(hasName("X")); }
+ Language getLang() { return Lang_CXX; }
+};
+
+struct ClassTemplate {
+ using DeclTy = ClassTemplateDecl;
+ static constexpr auto *Prototype = "template <class> class X;";
+ static constexpr auto *ConflictingPrototype = "template <int> class X;";
+ static constexpr auto *Definition = "template <class> class X {};";
+ static constexpr auto *ConflictingDefinition =
+ "template <class> class X { int A; };";
+ static constexpr auto *ConflictingProtoDef = "template <int> class X { };";
+ BindableMatcher<Decl> getPattern() {
+ return classTemplateDecl(hasName("X"), unless(isImplicit()));
+ }
+ Language getLang() { return Lang_CXX; }
+};
+
+struct FunctionTemplate {
+ using DeclTy = FunctionTemplateDecl;
+ static constexpr auto *Definition0 =
+ R"(
+ template <class T>
+ void X(T a) {};
+ )";
+ // This is actually not a conflicting definition, but another primary template.
+ static constexpr auto *Definition1 =
+ R"(
+ template <class T>
+ void X(T* a) {};
+ )";
+ BindableMatcher<Decl> getPattern() {
+ return functionTemplateDecl(hasName("X"), unless(isImplicit()));
+ }
+ static std::string getDef0() { return Definition0; }
+ static std::string getDef1() { return Definition1; }
+ Language getLang() { return Lang_CXX; }
+};
+
+static const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateDecl>
+ varTemplateDecl;
+
+struct VarTemplate {
+ using DeclTy = VarTemplateDecl;
+ static constexpr auto *Definition =
+ R"(
+ template <class T>
+ constexpr T X = 0;
+ )";
+ static constexpr auto *ConflictingDefinition =
+ R"(
+ template <int>
+ constexpr int X = 0;
+ )";
+ BindableMatcher<Decl> getPattern() { return varTemplateDecl(hasName("X")); }
+ Language getLang() { return Lang_CXX14; }
+};
+
+struct ClassTemplateSpec {
+ using DeclTy = ClassTemplateSpecializationDecl;
+ static constexpr auto *Prototype =
+ R"(
+ template <class T> class X;
+ template <> class X<int>;
+ )";
+ static constexpr auto *Definition =
+ R"(
+ template <class T> class X;
+ template <> class X<int> {};
+ )";
+ static constexpr auto *ConflictingDefinition =
+ R"(
+ template <class T> class X;
+ template <> class X<int> { int A; };
+ )";
+ BindableMatcher<Decl> getPattern() {
+ return classTemplateSpecializationDecl(hasName("X"), unless(isImplicit()));
+ }
+ Language getLang() { return Lang_CXX; }
+};
+
+// Function template specializations are all "full" specializations.
+// Structural equivalency does not check the body of functions, so we cannot
+// create conflicting function template specializations.
+struct FunctionTemplateSpec {
+ using DeclTy = FunctionDecl;
+
+ static constexpr auto *Definition0 =
+ R"(
+ template <class T>
+ void X(T a);
+ template <> void X(int a) {};
+ )";
+
+ // This is actually not a conflicting definition, but another full
+ // specialization.
+ // Thus, during the import we would create a new specialization with a
+ // different type argument.
+ static constexpr auto *Definition1 =
+ R"(
+ template <class T>
+ void X(T a);
+ template <> void X(double a) {};
+ )";
+
+ BindableMatcher<Decl> getPattern() {
+ return functionDecl(hasName("X"), isExplicitTemplateSpecialization(),
+ unless(isImplicit()));
+ }
+ static std::string getDef0() { return Definition0; }
+ static std::string getDef1() { return Definition1; }
+ Language getLang() { return Lang_CXX; }
+};
+
+static const internal::VariadicDynCastAllOfMatcher<
+ Decl, VarTemplateSpecializationDecl>
+ varTemplateSpecializationDecl;
+
+struct VarTemplateSpec {
+ using DeclTy = VarTemplateSpecializationDecl;
+ static constexpr auto *Definition =
+ R"(
+ template <class T> T X = 0;
+ template <> int X<int> = 0;
+ )";
+ static constexpr auto *ConflictingDefinition =
+ R"(
+ template <class T> T X = 0;
+ template <> float X<int> = 1.0;
+ )";
+ BindableMatcher<Decl> getPattern() {
+ return varTemplateSpecializationDecl(hasName("X"), unless(isImplicit()));
+ }
+ Language getLang() { return Lang_CXX14; }
+};
+
+template <typename TypeParam, ASTImporter::ODRHandlingType ODRHandlingParam>
+struct ODRViolation : ASTImporterOptionSpecificTestBase {
+
+ using DeclTy = typename TypeParam::DeclTy;
+
+ ODRViolation() { ODRHandling = ODRHandlingParam; }
+
+ static std::string getPrototype() { return TypeParam::Prototype; }
+ static std::string getConflictingPrototype() {
+ return TypeParam::ConflictingPrototype;
+ }
+ static std::string getDefinition() { return TypeParam::Definition; }
+ static std::string getConflictingDefinition() {
+ return TypeParam::ConflictingDefinition;
+ }
+ static std::string getConflictingProtoDef() {
+ return TypeParam::ConflictingProtoDef;
+ }
+ static BindableMatcher<Decl> getPattern() { return TypeParam().getPattern(); }
+ static Language getLang() { return TypeParam().getLang(); }
+
+ template <std::string (*ToTUContent)(), std::string (*FromTUContent)(),
+ void (*ResultChecker)(llvm::Expected<Decl *> &, Decl *, Decl *)>
+ void TypedTest_ImportAfter() {
+ Decl *ToTU = getToTuDecl(ToTUContent(), getLang());
+ auto *ToD = FirstDeclMatcher<DeclTy>().match(ToTU, getPattern());
+
+ Decl *FromTU = getTuDecl(FromTUContent(), getLang());
+ auto *FromD = FirstDeclMatcher<DeclTy>().match(FromTU, getPattern());
+
+ auto Result = importOrError(FromD, getLang());
+
+ ResultChecker(Result, ToTU, ToD);
+ }
+
+ // Check that a Decl has been successfully imported into a standalone redecl
+ // chain.
+ static void CheckImportedAsNew(llvm::Expected<Decl *> &Result, Decl *ToTU,
+ Decl *ToD) {
+ ASSERT_TRUE(isSuccess(Result));
+ Decl *ImportedD = *Result;
+ ASSERT_TRUE(ImportedD);
+ EXPECT_NE(ImportedD, ToD);
+ EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 2u);
+
+ // There may be a hidden fwd spec decl before a function spec decl.
+ if (auto *ImportedF = dyn_cast<FunctionDecl>(ImportedD))
+ if (ImportedF->getTemplatedKind() ==
+ FunctionDecl::TK_FunctionTemplateSpecialization)
+ return;
+
+ EXPECT_FALSE(ImportedD->getPreviousDecl());
+ }
+
+ // Check that a Decl was not imported because of NameConflict.
+ static void CheckImportNameConflict(llvm::Expected<Decl *> &Result,
+ Decl *ToTU, Decl *ToD) {
+ EXPECT_TRUE(isImportError(Result, ImportError::NameConflict));
+ EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
+ }
+
+ // Check that a Decl was not imported because lookup found the same decl.
+ static void CheckImportFoundExisting(llvm::Expected<Decl *> &Result,
+ Decl *ToTU, Decl *ToD) {
+ ASSERT_TRUE(isSuccess(Result));
+ EXPECT_EQ(DeclCounter<DeclTy>().match(ToTU, getPattern()), 1u);
+ }
+
+ void TypedTest_ImportConflictingDefAfterDef() {
+ TypedTest_ImportAfter<getDefinition, getConflictingDefinition,
+ CheckImportedAsNew>();
+ }
+ void TypedTest_ImportConflictingProtoAfterProto() {
+ TypedTest_ImportAfter<getPrototype, getConflictingPrototype,
+ CheckImportedAsNew>();
+ }
+ void TypedTest_ImportConflictingProtoAfterDef() {
+ TypedTest_ImportAfter<getDefinition, getConflictingPrototype,
+ CheckImportedAsNew>();
+ }
+ void TypedTest_ImportConflictingDefAfterProto() {
+ TypedTest_ImportAfter<getConflictingPrototype, getDefinition,
+ CheckImportedAsNew>();
+ }
+ void TypedTest_ImportConflictingProtoDefAfterProto() {
+ TypedTest_ImportAfter<getPrototype, getConflictingProtoDef,
+ CheckImportedAsNew>();
+ }
+ void TypedTest_ImportConflictingProtoAfterProtoDef() {
+ TypedTest_ImportAfter<getConflictingProtoDef, getPrototype,
+ CheckImportedAsNew>();
+ }
+ void TypedTest_ImportConflictingProtoDefAfterDef() {
+ TypedTest_ImportAfter<getDefinition, getConflictingProtoDef,
+ CheckImportedAsNew>();
+ }
+ void TypedTest_ImportConflictingDefAfterProtoDef() {
+ TypedTest_ImportAfter<getConflictingProtoDef, getDefinition,
+ CheckImportedAsNew>();
+ }
+
+ void TypedTest_DontImportConflictingProtoAfterProto() {
+ TypedTest_ImportAfter<getPrototype, getConflictingPrototype,
+ CheckImportNameConflict>();
+ }
+ void TypedTest_DontImportConflictingDefAfterDef() {
+ TypedTest_ImportAfter<getDefinition, getConflictingDefinition,
+ CheckImportNameConflict>();
+ }
+ void TypedTest_DontImportConflictingProtoAfterDef() {
+ TypedTest_ImportAfter<getDefinition, getConflictingPrototype,
+ CheckImportNameConflict>();
+ }
+ void TypedTest_DontImportConflictingDefAfterProto() {
+ TypedTest_ImportAfter<getConflictingPrototype, getDefinition,
+ CheckImportNameConflict>();
+ }
+ void TypedTest_DontImportConflictingProtoDefAfterProto() {
+ TypedTest_ImportAfter<getPrototype, getConflictingProtoDef,
+ CheckImportNameConflict>();
+ }
+ void TypedTest_DontImportConflictingProtoAfterProtoDef() {
+ TypedTest_ImportAfter<getConflictingProtoDef, getPrototype,
+ CheckImportNameConflict>();
+ }
+ void TypedTest_DontImportConflictingProtoDefAfterDef() {
+ TypedTest_ImportAfter<getDefinition, getConflictingProtoDef,
+ CheckImportNameConflict>();
+ }
+ void TypedTest_DontImportConflictingDefAfterProtoDef() {
+ TypedTest_ImportAfter<getConflictingProtoDef, getDefinition,
+ CheckImportNameConflict>();
+ }
+
+ // Used for function templates and function template specializations.
+ void TypedTest_ImportDifferentDefAfterDef() {
+ TypedTest_ImportAfter<TypeParam::getDef0, TypeParam::getDef1,
+ CheckImportedAsNew>();
+ }
+ void TypedTest_DontImportSameDefAfterDef() {
+ TypedTest_ImportAfter<TypeParam::getDef0, TypeParam::getDef0,
+ CheckImportFoundExisting>();
+ }
+};
+
+// ==============================
+// Define the parametrized tests.
+// ==============================
+
+#define ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE( \
+ TypeParam, ODRHandlingParam, NamePrefix, TestCase) \
+ using TypeParam##ODRHandlingParam = \
+ ODRViolation<TypeParam, ASTImporter::ODRHandlingType::ODRHandlingParam>; \
+ TEST_P(TypeParam##ODRHandlingParam, NamePrefix##TestCase) { \
+ TypedTest_##TestCase(); \
+ }
+
+// clang-format off
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Function, Liberal, ,
+ ImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Typedef, Liberal, ,
+ ImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ TypedefAlias, Liberal, ,
+ ImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Enum, Liberal, ,
+ ImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ EnumConstant, Liberal, ,
+ ImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Class, Liberal, ,
+ ImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Variable, Liberal, ,
+ ImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Liberal, ,
+ ImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ VarTemplate, Liberal, ,
+ ImportConflictingDefAfterDef)
+// Class and variable template specializations/instantiatons are always
+// imported conservatively, because the AST holds the specializations in a set,
+// and the key within the set is a hash calculated from the arguments of the
+// specialization.
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplateSpec, Liberal, ,
+ DontImportConflictingDefAfterDef) // Don't import !!!
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ VarTemplateSpec, Liberal, ,
+ DontImportConflictingDefAfterDef) // Don't import !!!
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Function, Conservative, ,
+ DontImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Typedef, Conservative, ,
+ DontImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ TypedefAlias, Conservative, ,
+ DontImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Enum, Conservative, ,
+ DontImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ EnumConstant, Conservative, ,
+ DontImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Class, Conservative, ,
+ DontImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Variable, Conservative, ,
+ DontImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Conservative, ,
+ DontImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ VarTemplate, Conservative, ,
+ DontImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplateSpec, Conservative, ,
+ DontImportConflictingDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ VarTemplateSpec, Conservative, ,
+ DontImportConflictingDefAfterDef)
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Function, Liberal, ,
+ ImportConflictingProtoAfterProto)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Variable, Liberal, ,
+ ImportConflictingProtoAfterProto)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Liberal, ,
+ ImportConflictingProtoAfterProto)
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Function, Conservative, ,
+ DontImportConflictingProtoAfterProto)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Variable, Conservative, ,
+ DontImportConflictingProtoAfterProto)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Conservative, ,
+ DontImportConflictingProtoAfterProto)
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Variable, Liberal, ,
+ ImportConflictingProtoAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Liberal, ,
+ ImportConflictingProtoAfterDef)
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Variable, Conservative, ,
+ DontImportConflictingProtoAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Conservative, ,
+ DontImportConflictingProtoAfterDef)
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Function, Liberal, ,
+ ImportConflictingDefAfterProto)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Variable, Liberal, ,
+ ImportConflictingDefAfterProto)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Liberal, ,
+ ImportConflictingDefAfterProto)
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Function, Conservative, ,
+ DontImportConflictingDefAfterProto)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ Variable, Conservative, ,
+ DontImportConflictingDefAfterProto)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Conservative, ,
+ DontImportConflictingDefAfterProto)
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Liberal, ,
+ ImportConflictingProtoDefAfterProto)
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Conservative, ,
+ DontImportConflictingProtoDefAfterProto)
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Liberal, ,
+ ImportConflictingProtoAfterProtoDef)
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Conservative, ,
+ DontImportConflictingProtoAfterProtoDef)
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Liberal, ,
+ ImportConflictingProtoDefAfterDef)
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Conservative, ,
+ DontImportConflictingProtoDefAfterDef)
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Liberal, ,
+ ImportConflictingDefAfterProtoDef)
+
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ ClassTemplate, Conservative, ,
+ DontImportConflictingDefAfterProtoDef)
+
+// FunctionTemplate decls overload with each other. Thus, they are imported
+// always as a new node, independently from any ODRHandling strategy.
+//
+// Function template specializations are "full" specializations. Structural
+// equivalency does not check the body of functions, so we cannot create
+// conflicting function template specializations. Thus, ODR handling strategies
+// has nothing to do with function template specializations. Fully specialized
+// function templates are imported as new nodes if their template arguments are
+// different.
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ FunctionTemplate, Liberal, ,
+ ImportDifferentDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ FunctionTemplateSpec, Liberal, ,
+ ImportDifferentDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ FunctionTemplate, Conservative, ,
+ ImportDifferentDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ FunctionTemplateSpec, Conservative, ,
+ ImportDifferentDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ FunctionTemplate, Liberal, ,
+ DontImportSameDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ FunctionTemplateSpec, Liberal, ,
+ DontImportSameDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ FunctionTemplate, Conservative, ,
+ DontImportSameDefAfterDef)
+ASTIMPORTER_ODR_INSTANTIATE_TYPED_TEST_CASE(
+ FunctionTemplateSpec, Conservative, ,
+ DontImportSameDefAfterDef)
+
+// ======================
+// Instantiate the tests.
+// ======================
+
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, FunctionConservative,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, TypedefConservative,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, TypedefAliasConservative,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, EnumConservative,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, EnumConstantConservative,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, ClassConservative,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, VariableConservative,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, ClassTemplateConservative,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, FunctionTemplateConservative,
+ DefaultTestValuesForRunOptions, );
+// FIXME: Make VarTemplate tests work.
+//INSTANTIATE_TEST_CASE_P(
+ //ODRViolationTests, VarTemplateConservative,
+ //DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, FunctionTemplateSpecConservative,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, ClassTemplateSpecConservative,
+ DefaultTestValuesForRunOptions, );
+// FIXME: Make VarTemplateSpec tests work.
+//INSTANTIATE_TEST_CASE_P(
+ //ODRViolationTests, VarTemplateSpecConservative,
+ //DefaultTestValuesForRunOptions, );
+
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, FunctionLiberal,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, TypedefLiberal,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, TypedefAliasLiberal,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, EnumLiberal,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, EnumConstantLiberal,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, ClassLiberal,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, VariableLiberal,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, ClassTemplateLiberal,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, FunctionTemplateLiberal,
+ DefaultTestValuesForRunOptions, );
+// FIXME: Make VarTemplate tests work.
+// INSTANTIATE_TEST_CASE_P(
+// ODRViolationTests, VarTemplateLiberal,
+// DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, ClassTemplateSpecLiberal,
+ DefaultTestValuesForRunOptions, );
+INSTANTIATE_TEST_CASE_P(
+ ODRViolationTests, FunctionTemplateSpecLiberal,
+ DefaultTestValuesForRunOptions, );
+// FIXME: Make VarTemplateSpec tests work.
+//INSTANTIATE_TEST_CASE_P(
+ //ODRViolationTests, VarTemplateSpecLiberal,
+ //DefaultTestValuesForRunOptions, );
+
+// clang-format on
+
+} // end namespace ast_matchers
+} // end namespace clang
Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=372564&r1=372563&r2=372564&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original)
+++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Mon Sep 23 02:32:07 2019
@@ -5481,187 +5481,6 @@ 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"}), );
@@ -5838,8 +5657,5 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTes
INSTANTIATE_TEST_CASE_P(ParameterizedTests, LLDBLookupTest,
DefaultTestValuesForRunOptions, );
-INSTANTIATE_TEST_CASE_P(ParameterizedTests, ConflictingDeclsWithLiberalStrategy,
- DefaultTestValuesForRunOptions, );
-
} // end namespace ast_matchers
} // end namespace clang
Modified: cfe/trunk/unittests/AST/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/CMakeLists.txt?rev=372564&r1=372563&r2=372564&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/CMakeLists.txt (original)
+++ cfe/trunk/unittests/AST/CMakeLists.txt Mon Sep 23 02:32:07 2019
@@ -11,6 +11,7 @@ add_clang_unittest(ASTTests
ASTImporterFixtures.cpp
ASTImporterTest.cpp
ASTImporterGenericRedeclTest.cpp
+ ASTImporterODRStrategiesTest.cpp
ASTImporterVisibilityTest.cpp
ASTTraverserTest.cpp
ASTTypeTraitsTest.cpp
More information about the cfe-commits
mailing list