Hello Balazs, This commit broke at least one of our builders: http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/10897
. . . Failing Tests (1): Clang-Unit :: AST/./ASTTests.exe/StructuralEquivalenceRecordTest.Name Please have a look? It is not good idea to keep the bot red for too long. This hides new problem which later hard to track down. Thanks Galina On Wed, Jul 11, 2018 at 2:37 AM, Balazs Keri via cfe-commits < cfe-commits@lists.llvm.org> wrote: > Author: balazske > Date: Wed Jul 11 02:37:24 2018 > New Revision: 336776 > > URL: http://llvm.org/viewvc/llvm-project?rev=336776&view=rev > Log: > [AST] Structural equivalence of methods > > Summary: > Added structural equivalence check for C++ methods. > Improved structural equivalence tests. > Added related ASTImporter tests. > > Reviewers: a.sidorin, szepet, xazax.hun, martong, a_sidorin > > Reviewed By: martong, a_sidorin > > Subscribers: a_sidorin, rnkovacs, cfe-commits > > Differential Revision: https://reviews.llvm.org/D48628 > > Modified: > cfe/trunk/lib/AST/ASTImporter.cpp > cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp > cfe/trunk/unittests/AST/ASTImporterTest.cpp > cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp > > Modified: cfe/trunk/lib/AST/ASTImporter.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ > ASTImporter.cpp?rev=336776&r1=336775&r2=336776&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/AST/ASTImporter.cpp (original) > +++ cfe/trunk/lib/AST/ASTImporter.cpp Wed Jul 11 02:37:24 2018 > @@ -230,6 +230,7 @@ namespace clang { > bool IsStructuralMatch(EnumConstantDecl *FromEC, EnumConstantDecl > *ToEC); > bool IsStructuralMatch(FunctionTemplateDecl *From, > FunctionTemplateDecl *To); > + bool IsStructuralMatch(FunctionDecl *From, FunctionDecl *To); > bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl > *To); > bool IsStructuralMatch(VarTemplateDecl *From, VarTemplateDecl *To); > Decl *VisitDecl(Decl *D); > @@ -1525,6 +1526,13 @@ bool ASTNodeImporter::IsStructuralMatch( > return Ctx.IsStructurallyEquivalent(From, To); > } > > +bool ASTNodeImporter::IsStructuralMatch(FunctionDecl *From, FunctionDecl > *To) { > + StructuralEquivalenceContext Ctx( > + Importer.getFromContext(), Importer.getToContext(), > + Importer.getNonEquivalentDecls(), false, false); > + return Ctx.IsStructurallyEquivalent(From, To); > +} > + > bool ASTNodeImporter::IsStructuralMatch(EnumConstantDecl *FromEC, > EnumConstantDecl *ToEC) { > const llvm::APSInt &FromVal = FromEC->getInitVal(); > @@ -2433,13 +2441,15 @@ Decl *ASTNodeImporter::VisitFunctionDecl > if (auto *FoundFunction = dyn_cast<FunctionDecl>(FoundDecl)) { > if (FoundFunction->hasExternalFormalLinkage() && > D->hasExternalFormalLinkage()) { > - if (Importer.IsStructurallyEquivalent(D->getType(), > - > FoundFunction->getType())) { > - if (D->doesThisDeclarationHaveABody() && > - FoundFunction->hasBody()) > - return Importer.Imported(D, FoundFunction); > - FoundByLookup = FoundFunction; > - break; > + if (IsStructuralMatch(D, FoundFunction)) { > + const FunctionDecl *Definition = nullptr; > + if (D->doesThisDeclarationHaveABody() && > + FoundFunction->hasBody(Definition)) { > + return Importer.Imported( > + D, const_cast<FunctionDecl *>(Definition)); > + } > + FoundByLookup = FoundFunction; > + break; > } > > // FIXME: Check for overloading more carefully, e.g., by > boosting > > Modified: cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ > ASTStructuralEquivalence.cpp?rev=336776&r1=336775&r2=336776&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp (original) > +++ cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp Wed Jul 11 02:37:24 > 2018 > @@ -250,6 +250,9 @@ static bool IsStructurallyEquivalent(Str > if (T1.isNull() || T2.isNull()) > return T1.isNull() && T2.isNull(); > > + QualType OrigT1 = T1; > + QualType OrigT2 = T2; > + > if (!Context.StrictTypeSpelling) { > // We aren't being strict about token-to-token equivalence of types, > // so map down to the canonical type. > @@ -422,6 +425,7 @@ static bool IsStructurallyEquivalent(Str > case Type::FunctionProto: { > const auto *Proto1 = cast<FunctionProtoType>(T1); > const auto *Proto2 = cast<FunctionProtoType>(T2); > + > if (Proto1->getNumParams() != Proto2->getNumParams()) > return false; > for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) { > @@ -431,23 +435,33 @@ static bool IsStructurallyEquivalent(Str > } > if (Proto1->isVariadic() != Proto2->isVariadic()) > return false; > - if (Proto1->getExceptionSpecType() != Proto2->getExceptionSpecType()) > + > + if (Proto1->getTypeQuals() != Proto2->getTypeQuals()) > + return false; > + > + // Check exceptions, this information is lost in canonical type. > + const auto *OrigProto1 = > + cast<FunctionProtoType>(OrigT1.getDesugaredType( > Context.FromCtx)); > + const auto *OrigProto2 = > + cast<FunctionProtoType>(OrigT2.getDesugaredType(Context.ToCtx)); > + auto Spec1 = OrigProto1->getExceptionSpecType(); > + auto Spec2 = OrigProto2->getExceptionSpecType(); > + > + if (Spec1 != Spec2) > return false; > - if (Proto1->getExceptionSpecType() == EST_Dynamic) { > - if (Proto1->getNumExceptions() != Proto2->getNumExceptions()) > + if (Spec1 == EST_Dynamic) { > + if (OrigProto1->getNumExceptions() != > OrigProto2->getNumExceptions()) > return false; > - for (unsigned I = 0, N = Proto1->getNumExceptions(); I != N; ++I) { > - if (!IsStructurallyEquivalent(Context, > Proto1->getExceptionType(I), > - Proto2->getExceptionType(I))) > + for (unsigned I = 0, N = OrigProto1->getNumExceptions(); I != N; > ++I) { > + if (!IsStructurallyEquivalent(Context, > OrigProto1->getExceptionType(I), > + OrigProto2->getExceptionType(I))) > return false; > } > - } else if (isComputedNoexcept(Proto1->getExceptionSpecType())) { > - if (!IsStructurallyEquivalent(Context, Proto1->getNoexceptExpr(), > - Proto2->getNoexceptExpr())) > + } else if (isComputedNoexcept(Spec1)) { > + if (!IsStructurallyEquivalent(Context, > OrigProto1->getNoexceptExpr(), > + OrigProto2->getNoexceptExpr())) > return false; > } > - if (Proto1->getTypeQuals() != Proto2->getTypeQuals()) > - return false; > > // Fall through to check the bits common with FunctionNoProtoType. > LLVM_FALLTHROUGH; > @@ -830,6 +844,56 @@ static bool IsStructurallyEquivalent(Str > return true; > } > > +/// Determine structural equivalence of two methodss. > +static bool IsStructurallyEquivalent(StructuralEquivalenceContext > &Context, > + CXXMethodDecl *Method1, > + CXXMethodDecl *Method2) { > + bool PropertiesEqual = > + Method1->getDeclKind() == Method2->getDeclKind() && > + Method1->getRefQualifier() == Method2->getRefQualifier() && > + Method1->getAccess() == Method2->getAccess() && > + Method1->getOverloadedOperator() == Method2->getOverloadedOperator() > && > + Method1->isStatic() == Method2->isStatic() && > + Method1->isConst() == Method2->isConst() && > + Method1->isVolatile() == Method2->isVolatile() && > + Method1->isVirtual() == Method2->isVirtual() && > + Method1->isPure() == Method2->isPure() && > + Method1->isDefaulted() == Method2->isDefaulted() && > + Method1->isDeleted() == Method2->isDeleted(); > + if (!PropertiesEqual) > + return false; > + // FIXME: Check for 'final'. > + > + if (auto *Constructor1 = dyn_cast<CXXConstructorDecl>(Method1)) { > + auto *Constructor2 = cast<CXXConstructorDecl>(Method2); > + if (Constructor1->isExplicit() != Constructor2->isExplicit()) > + return false; > + } > + > + if (auto *Conversion1 = dyn_cast<CXXConversionDecl>(Method1)) { > + auto *Conversion2 = cast<CXXConversionDecl>(Method2); > + if (Conversion1->isExplicit() != Conversion2->isExplicit()) > + return false; > + if (!IsStructurallyEquivalent(Context, Conversion1-> > getConversionType(), > + Conversion2->getConversionType())) > + return false; > + } > + > + const IdentifierInfo *Name1 = Method1->getIdentifier(); > + const IdentifierInfo *Name2 = Method2->getIdentifier(); > + if (!::IsStructurallyEquivalent(Name1, Name2)) { > + return false; > + // TODO: Names do not match, add warning like at check for FieldDecl. > + } > + > + // Check the prototypes. > + if (!::IsStructurallyEquivalent(Context, > + Method1->getType(), Method2->getType())) > + return false; > + > + return true; > +} > + > /// Determine structural equivalence of two records. > static bool IsStructurallyEquivalent(StructuralEquivalenceContext > &Context, > RecordDecl *D1, RecordDecl *D2) { > @@ -1443,6 +1507,14 @@ bool StructuralEquivalenceContext::Finis > Equivalent = false; > } else { > // Kind mismatch. > + Equivalent = false; > + } > + } else if (auto *MD1 = dyn_cast<CXXMethodDecl>(D1)) { > + if (auto *MD2 = dyn_cast<CXXMethodDecl>(D2)) { > + if (!::IsStructurallyEquivalent(*this, MD1, MD2)) > + Equivalent = false; > + } else { > + // Kind mismatch. > Equivalent = false; > } > } else if (FunctionDecl *FD1 = dyn_cast<FunctionDecl>(D1)) { > > Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ > AST/ASTImporterTest.cpp?rev=336776&r1=336775&r2=336776&view=diff > ============================================================ > ================== > --- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original) > +++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Wed Jul 11 02:37:24 2018 > @@ -2243,6 +2243,132 @@ TEST_P(ImportExpr, UnresolvedMemberExpr) > compoundStmt(has(callExpr(has( > unresolvedMemberExpr()))))))))); > } > > +TEST_P(ASTImporterTestBase, ImportOfEquivalentRecord) { > + Decl *ToR1; > + { > + Decl *FromTU = getTuDecl( > + "struct A { };", Lang_CXX, "input0.cc"); > + auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match( > + FromTU, cxxRecordDecl(hasName("A"))); > + > + ToR1 = Import(FromR, Lang_CXX); > + } > + > + Decl *ToR2; > + { > + Decl *FromTU = getTuDecl( > + "struct A { };", Lang_CXX, "input1.cc"); > + auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match( > + FromTU, cxxRecordDecl(hasName("A"))); > + > + ToR2 = Import(FromR, Lang_CXX); > + } > + > + EXPECT_EQ(ToR1, ToR2); > +} > + > +TEST_P(ASTImporterTestBase, ImportOfNonEquivalentRecord) { > + Decl *ToR1; > + { > + Decl *FromTU = getTuDecl( > + "struct A { int x; };", Lang_CXX, "input0.cc"); > + auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match( > + FromTU, cxxRecordDecl(hasName("A"))); > + ToR1 = Import(FromR, Lang_CXX); > + } > + Decl *ToR2; > + { > + Decl *FromTU = getTuDecl( > + "struct A { unsigned x; };", Lang_CXX, "input1.cc"); > + auto *FromR = FirstDeclMatcher<CXXRecordDecl>().match( > + FromTU, cxxRecordDecl(hasName("A"))); > + ToR2 = Import(FromR, Lang_CXX); > + } > + EXPECT_NE(ToR1, ToR2); > +} > + > +TEST_P(ASTImporterTestBase, ImportOfEquivalentField) { > + Decl *ToF1; > + { > + Decl *FromTU = getTuDecl( > + "struct A { int x; };", Lang_CXX, "input0.cc"); > + auto *FromF = FirstDeclMatcher<FieldDecl>().match( > + FromTU, fieldDecl(hasName("x"))); > + ToF1 = Import(FromF, Lang_CXX); > + } > + Decl *ToF2; > + { > + Decl *FromTU = getTuDecl( > + "struct A { int x; };", Lang_CXX, "input1.cc"); > + auto *FromF = FirstDeclMatcher<FieldDecl>().match( > + FromTU, fieldDecl(hasName("x"))); > + ToF2 = Import(FromF, Lang_CXX); > + } > + EXPECT_EQ(ToF1, ToF2); > +} > + > +TEST_P(ASTImporterTestBase, ImportOfNonEquivalentField) { > + Decl *ToF1; > + { > + Decl *FromTU = getTuDecl( > + "struct A { int x; };", Lang_CXX, "input0.cc"); > + auto *FromF = FirstDeclMatcher<FieldDecl>().match( > + FromTU, fieldDecl(hasName("x"))); > + ToF1 = Import(FromF, Lang_CXX); > + } > + Decl *ToF2; > + { > + Decl *FromTU = getTuDecl( > + "struct A { unsigned x; };", Lang_CXX, "input1.cc"); > + auto *FromF = FirstDeclMatcher<FieldDecl>().match( > + FromTU, fieldDecl(hasName("x"))); > + ToF2 = Import(FromF, Lang_CXX); > + } > + EXPECT_NE(ToF1, ToF2); > +} > + > +TEST_P(ASTImporterTestBase, ImportOfEquivalentMethod) { > + Decl *ToM1; > + { > + Decl *FromTU = getTuDecl( > + "struct A { void x(); }; void A::x() { }", Lang_CXX, "input0.cc"); > + auto *FromM = FirstDeclMatcher<FunctionDecl>().match( > + FromTU, functionDecl(hasName("x"), isDefinition())); > + ToM1 = Import(FromM, Lang_CXX); > + } > + Decl *ToM2; > + { > + Decl *FromTU = getTuDecl( > + "struct A { void x(); }; void A::x() { }", Lang_CXX, "input1.cc"); > + auto *FromM = FirstDeclMatcher<FunctionDecl>().match( > + FromTU, functionDecl(hasName("x"), isDefinition())); > + ToM2 = Import(FromM, Lang_CXX); > + } > + EXPECT_EQ(ToM1, ToM2); > +} > + > +TEST_P(ASTImporterTestBase, ImportOfNonEquivalentMethod) { > + Decl *ToM1; > + { > + Decl *FromTU = getTuDecl( > + "struct A { void x(); }; void A::x() { }", > + Lang_CXX, "input0.cc"); > + auto *FromM = FirstDeclMatcher<FunctionDecl>().match( > + FromTU, functionDecl(hasName("x"), isDefinition())); > + ToM1 = Import(FromM, Lang_CXX); > + } > + Decl *ToM2; > + { > + Decl *FromTU = getTuDecl( > + "struct A { void x() const; }; void A::x() const { }", > + Lang_CXX, "input1.cc"); > + auto *FromM = FirstDeclMatcher<FunctionDecl>().match( > + FromTU, functionDecl(hasName("x"), isDefinition())); > + ToM2 = Import(FromM, Lang_CXX); > + } > + EXPECT_NE(ToM1, ToM2); > +} > + > struct DeclContextTest : ASTImporterTestBase {}; > > TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) { > > Modified: cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ > AST/StructuralEquivalenceTest.cpp?rev=336776&r1=336775&r2=336776&view=diff > ============================================================ > ================== > --- cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp (original) > +++ cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp Wed Jul 11 > 02:37:24 2018 > @@ -18,13 +18,13 @@ struct StructuralEquivalenceTest : ::tes > std::unique_ptr<ASTUnit> AST0, AST1; > std::string Code0, Code1; // Buffers for SourceManager > > - // Get a pair of Decl pointers to the synthetised declarations from the > given > - // code snipets. By default we search for the unique Decl with name > 'foo' in > - // both snippets. > - std::tuple<NamedDecl *, NamedDecl *> > - makeNamedDecls(const std::string &SrcCode0, const std::string &SrcCode1, > - Language Lang, const char *const Identifier = "foo") { > - > + // Get a pair of node pointers into the synthesized AST from the given > code > + // snippets. To determine the returned node, a separate matcher is > specified > + // for both snippets. The first matching node is returned. > + template <typename NodeType, typename MatcherType> > + std::tuple<NodeType *, NodeType *> makeDecls( > + const std::string &SrcCode0, const std::string &SrcCode1, Language > Lang, > + const MatcherType &Matcher0, const MatcherType &Matcher1) { > this->Code0 = SrcCode0; > this->Code1 = SrcCode1; > ArgVector Args = getBasicRunOptionsForLanguage(Lang); > @@ -34,30 +34,34 @@ struct StructuralEquivalenceTest : ::tes > AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName); > AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName); > > - ASTContext &Ctx0 = AST0->getASTContext(), &Ctx1 = > AST1->getASTContext(); > + NodeType *D0 = FirstDeclMatcher<NodeType>().match( > + AST0->getASTContext().getTranslationUnitDecl(), Matcher0); > + NodeType *D1 = FirstDeclMatcher<NodeType>().match( > + AST1->getASTContext().getTranslationUnitDecl(), Matcher1); > > - auto getDecl = [](ASTContext &Ctx, const std::string &Name) -> > NamedDecl * { > - IdentifierInfo *SearchedII = &Ctx.Idents.get(Name); > - assert(SearchedII && "Declaration with the identifier " > - "should be specified in test!"); > - DeclarationName SearchDeclName(SearchedII); > - SmallVector<NamedDecl *, 4> FoundDecls; > - Ctx.getTranslationUnitDecl()->localUncachedLookup(SearchDeclName, > - FoundDecls); > - > - // We should find one Decl but one only. > - assert(FoundDecls.size() == 1); > - > - return FoundDecls[0]; > - }; > - > - NamedDecl *D0 = getDecl(Ctx0, Identifier); > - NamedDecl *D1 = getDecl(Ctx1, Identifier); > - assert(D0); > - assert(D1); > return std::make_tuple(D0, D1); > } > > + // Get a pair of node pointers into the synthesized AST from the given > code > + // snippets. The same matcher is used for both snippets. > + template <typename NodeType, typename MatcherType> > + std::tuple<NodeType *, NodeType *> makeDecls( > + const std::string &SrcCode0, const std::string &SrcCode1, Language > Lang, > + const MatcherType &AMatcher) { > + return makeDecls<NodeType, MatcherType>( > + SrcCode0, SrcCode1, Lang, AMatcher, AMatcher); > + } > + > + // Get a pair of Decl pointers to the synthesized declarations from the > given > + // code snippets. We search for the first NamedDecl with given name in > both > + // snippets. > + std::tuple<NamedDecl *, NamedDecl *> makeNamedDecls( > + const std::string &SrcCode0, const std::string &SrcCode1, > + Language Lang, const char *const Identifier = "foo") { > + auto Matcher = namedDecl(hasName(Identifier)); > + return makeDecls<NamedDecl>(SrcCode0, SrcCode1, Lang, Matcher); > + } > + > bool testStructuralMatch(NamedDecl *D0, NamedDecl *D1) { > llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls; > StructuralEquivalenceContext Ctx(D0->getASTContext(), > D1->getASTContext(), > @@ -110,35 +114,29 @@ TEST_F(StructuralEquivalenceTest, CharVs > } > > TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) { > - auto Decls = makeNamedDecls( > - "template <class T> struct foo; template<> struct foo<int>{};", > - "template <class T> struct foo; template<> struct foo<signed > int>{};", > - Lang_CXX); > - ClassTemplateSpecializationDecl *Spec0 = > - *cast<ClassTemplateDecl>(get<0>(Decls))->spec_begin(); > - ClassTemplateSpecializationDecl *Spec1 = > - *cast<ClassTemplateDecl>(get<1>(Decls))->spec_begin(); > - ASSERT_TRUE(Spec0 != nullptr); > - ASSERT_TRUE(Spec1 != nullptr); > + auto Decls = makeDecls<ClassTemplateSpecializationDecl>( > + R"(template <class T> struct foo; template<> struct foo<int>{};)", > + R"(template <class T> struct foo; template<> struct foo<signed > int>{};)", > + Lang_CXX, > + classTemplateSpecializationDecl()); > + auto Spec0 = get<0>(Decls); > + auto Spec1 = get<1>(Decls); > EXPECT_TRUE(testStructuralMatch(Spec0, Spec1)); > } > > TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) { > - auto Decls = makeNamedDecls( > - "template <class T> struct foo; template<> struct foo<char>{};", > - "template <class T> struct foo; template<> struct foo<signed > char>{};", > - Lang_CXX); > - ClassTemplateSpecializationDecl *Spec0 = > - *cast<ClassTemplateDecl>(get<0>(Decls))->spec_begin(); > - ClassTemplateSpecializationDecl *Spec1 = > - *cast<ClassTemplateDecl>(get<1>(Decls))->spec_begin(); > - ASSERT_TRUE(Spec0 != nullptr); > - ASSERT_TRUE(Spec1 != nullptr); > + auto Decls = makeDecls<ClassTemplateSpecializationDecl>( > + R"(template <class T> struct foo; template<> struct foo<char>{};)", > + R"(template <class T> struct foo; template<> struct foo<signed > char>{};)", > + Lang_CXX, > + classTemplateSpecializationDecl()); > + auto Spec0 = get<0>(Decls); > + auto Spec1 = get<1>(Decls); > EXPECT_FALSE(testStructuralMatch(Spec0, Spec1)); > } > > TEST_F(StructuralEquivalenceTest, > CharVsSignedCharTemplateSpecWithInheritance) > { > - auto Decls = makeNamedDecls( > + auto Decls = makeDecls<ClassTemplateSpecializationDecl>( > R"( > struct true_type{}; > template <class T> struct foo; > @@ -149,14 +147,9 @@ TEST_F(StructuralEquivalenceTest, CharVs > template <class T> struct foo; > template<> struct foo<signed char> : true_type {}; > )", > - Lang_CXX); > - ClassTemplateSpecializationDecl *Spec0 = > - *cast<ClassTemplateDecl>(get<0>(Decls))->spec_begin(); > - ClassTemplateSpecializationDecl *Spec1 = > - *cast<ClassTemplateDecl>(get<1>(Decls))->spec_begin(); > - ASSERT_TRUE(Spec0 != nullptr); > - ASSERT_TRUE(Spec1 != nullptr); > - EXPECT_FALSE(testStructuralMatch(Spec0, Spec1)); > + Lang_CXX, > + classTemplateSpecializationDecl()); > + EXPECT_FALSE(testStructuralMatch(Decls)); > } > > // This test is disabled for now. > @@ -203,5 +196,350 @@ TEST_F(StructuralEquivalenceTest, WrongO > EXPECT_FALSE(testStructuralMatch(Decls)); > } > > +struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest { > +}; > + > +TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) { > + auto t = makeNamedDecls("void foo(int&);", > + "void foo(const int&);", Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, ParamConstSimple) { > + auto t = makeNamedDecls("void foo(int);", > + "void foo(const int);", Lang_CXX); > + EXPECT_TRUE(testStructuralMatch(t)); > + // consider this OK > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, Throw) { > + auto t = makeNamedDecls("void foo();", > + "void foo() throw();", Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, Noexcept) { > + auto t = makeNamedDecls("void foo();", > + "void foo() noexcept;", Lang_CXX11); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexcept) { > + auto t = makeNamedDecls("void foo() throw();", > + "void foo() noexcept;", Lang_CXX11); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptFalse) { > + auto t = makeNamedDecls("void foo() throw();", > + "void foo() noexcept(false);", Lang_CXX11); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) { > + auto t = makeNamedDecls("void foo() throw();", > + "void foo() noexcept(true);", Lang_CXX11); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, DISABLED_NoexceptNonMatch) { > + // The expression is not checked yet. > + auto t = makeNamedDecls("void foo() noexcept(false);", > + "void foo() noexcept(true);", Lang_CXX11); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, NoexceptMatch) { > + auto t = makeNamedDecls("void foo() noexcept(false);", > + "void foo() noexcept(false);", Lang_CXX11); > + EXPECT_TRUE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptFalse) { > + auto t = makeNamedDecls("void foo() noexcept;", > + "void foo() noexcept(false);", Lang_CXX11); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptTrue) { > + auto t = makeNamedDecls("void foo() noexcept;", > + "void foo() noexcept(true);", Lang_CXX11); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, ReturnType) { > + auto t = makeNamedDecls("char foo();", > + "int foo();", Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, ReturnConst) { > + auto t = makeNamedDecls("char foo();", > + "const char foo();", Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, ReturnRef) { > + auto t = makeNamedDecls("char &foo();", > + "char &&foo();", Lang_CXX11); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, ParamCount) { > + auto t = makeNamedDecls("void foo(int);", > + "void foo(int, int);", Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, ParamType) { > + auto t = makeNamedDecls("void foo(int);", > + "void foo(char);", Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, ParamName) { > + auto t = makeNamedDecls("void foo(int a);", > + "void foo(int b);", Lang_CXX); > + EXPECT_TRUE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, Variadic) { > + auto t = makeNamedDecls("void foo(int x...);", > + "void foo(int x);", Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, ParamPtr) { > + auto t = makeNamedDecls("void foo(int *);", > + "void foo(int);", Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, NameInParen) { > + auto t = makeNamedDecls( > + "void ((foo))();", > + "void foo();", > + Lang_CXX); > + EXPECT_TRUE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithExceptionSpec) { > + auto t = makeNamedDecls( > + "void (foo)() throw(int);", > + "void (foo)() noexcept;", > + Lang_CXX11); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithConst) { > + auto t = makeNamedDecls( > + "struct A { void (foo)() const; };", > + "struct A { void (foo)(); };", > + Lang_CXX11); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest { > +}; > + > +TEST_F(StructuralEquivalenceCXXMethodTest, Virtual) { > + auto t = makeDecls<CXXMethodDecl>( > + "struct X { void foo(); };", > + "struct X { virtual void foo(); };", Lang_CXX, > + cxxMethodDecl(hasName("foo"))); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, Pure) { > + auto t = makeNamedDecls("struct X { virtual void foo(); };", > + "struct X { virtual void foo() = 0; };", > Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, DISABLED_Final) { > + // The final-ness is not checked yet. > + auto t = makeNamedDecls("struct X { virtual void foo(); };", > + "struct X { virtual void foo() final; };", > Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, Const) { > + auto t = makeNamedDecls("struct X { void foo(); };", > + "struct X { void foo() const; };", Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, Static) { > + auto t = makeNamedDecls("struct X { void foo(); };", > + "struct X { static void foo(); };", Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, Ref1) { > + auto t = makeNamedDecls("struct X { void foo(); };", > + "struct X { void foo() &&; };", Lang_CXX11); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, Ref2) { > + auto t = makeNamedDecls("struct X { void foo() &; };", > + "struct X { void foo() &&; };", Lang_CXX11); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, AccessSpecifier) { > + auto t = makeDecls<CXXMethodDecl>( > + "struct X { public: void foo(); };", > + "struct X { private: void foo(); };", Lang_CXX, > + cxxMethodDecl(hasName("foo"))); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, Delete) { > + auto t = makeNamedDecls("struct X { void foo(); };", > + "struct X { void foo() = delete; };", > Lang_CXX11); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) { > + auto t = makeDecls<FunctionDecl>( > + "void foo();", "struct foo { foo(); };", Lang_CXX, > + functionDecl(), cxxConstructorDecl()); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) { > + auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };", > + "struct X { X(int); };", > Lang_CXX, > + cxxConstructorDecl()); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorExplicit) { > + auto t = makeDecls<CXXConstructorDecl>("struct X { X(int); };", > + "struct X { explicit X(int); };", > + Lang_CXX11, > + cxxConstructorDecl()); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) { > + auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };", > + "struct X { X() = default; };", > + Lang_CXX11, > + cxxConstructorDecl()); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, Conversion) { > + auto t = makeDecls<CXXConversionDecl>("struct X { operator bool(); };", > + "struct X { operator char(); };", > + Lang_CXX11, > + cxxConversionDecl()); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, Operator) { > + auto t = makeDecls<FunctionDecl>( > + "struct X { int operator +(int); };", > + "struct X { int operator -(int); };", Lang_CXX, > + functionDecl(hasOverloadedOperatorName("+")), > + functionDecl(hasOverloadedOperatorName("-"))); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass1) { > + auto t = makeDecls<FunctionDecl>( > + "struct X { virtual void f(); }; void X::f() { }", > + "struct X { virtual void f() { }; };", > + Lang_CXX, > + functionDecl(allOf(hasName("f"), isDefinition()))); > + EXPECT_TRUE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass2) { > + auto t = makeDecls<FunctionDecl>( > + "struct X { virtual void f(); }; void X::f() { }", > + "struct X { void f(); }; void X::f() { }", > + Lang_CXX, > + functionDecl(allOf(hasName("f"), isDefinition()))); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +struct StructuralEquivalenceRecordTest : StructuralEquivalenceTest { > +}; > + > +TEST_F(StructuralEquivalenceRecordTest, Name) { > + auto t = makeDecls<CXXRecordDecl>( > + "struct A{ };", > + "struct B{ };", > + Lang_CXX, > + cxxRecordDecl()); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceRecordTest, Fields) { > + auto t = makeNamedDecls( > + "struct foo{ int x; };", > + "struct foo{ char x; };", > + Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceRecordTest, DISABLED_Methods) { > + // Currently, methods of a class are not checked at class equivalence. > + auto t = makeNamedDecls( > + "struct foo{ int x(); };", > + "struct foo{ char x(); };", > + Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceRecordTest, Bases) { > + auto t = makeNamedDecls( > + "struct A{ }; struct foo: A { };", > + "struct B{ }; struct foo: B { };", > + Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceRecordTest, InheritanceVirtual) { > + auto t = makeNamedDecls( > + "struct A{ }; struct foo: A { };", > + "struct A{ }; struct foo: virtual A { };", > + Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceRecordTest, DISABLED_InheritanceType) { > + // Access specifier in inheritance is not checked yet. > + auto t = makeNamedDecls( > + "struct A{ }; struct foo: public A { };", > + "struct A{ }; struct foo: private A { };", > + Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceRecordTest, Match) { > + auto Code = R"( > + struct A{ }; > + struct B{ }; > + struct foo: A, virtual B { > + void x(); > + int a; > + }; > + )"; > + auto t = makeNamedDecls(Code, Code, Lang_CXX); > + EXPECT_TRUE(testStructuralMatch(t)); > +} > + > +TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) { > + auto t = makeNamedDecls( > + "struct A{ }; struct B{ }; void foo(A a, A b);", > + "struct A{ }; struct B{ }; void foo(A a, B b);", > + Lang_CXX); > + EXPECT_FALSE(testStructuralMatch(t)); > +} > + > } // end namespace ast_matchers > } // end namespace clang > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits