Hi, I am aware of the problem, there should be already a commit to (hopefully) correct the failure.
Balázs Kéri Galina Kistanova <gkistan...@gmail.com> ezt írta (időpont: 2018. júl. 11., Sze, 20:01): > 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