brintos

brintos / llvm-project-archived public Read only

0
0
Text · 92.5 KiB · 24e20c7 Raw
2766 lines · cpp
1#include "clang/AST/ASTContext.h"2#include "clang/AST/ASTStructuralEquivalence.h"3#include "clang/AST/Decl.h"4#include "clang/AST/DeclTemplate.h"5#include "clang/ASTMatchers/ASTMatchers.h"6#include "clang/Frontend/ASTUnit.h"7#include "clang/Testing/CommandLineArgs.h"8#include "clang/Tooling/Tooling.h"9#include "llvm/TargetParser/Host.h"10 11#include "DeclMatcher.h"12 13#include "gtest/gtest.h"14 15namespace clang {16namespace ast_matchers {17 18using std::get;19 20struct StructuralEquivalenceTest : ::testing::Test {21  std::unique_ptr<ASTUnit> AST0, AST1;22  std::string Code0, Code1; // Buffers for SourceManager23 24  // Parses the source code in the specified language and sets the ASTs of25  // the current test instance to the parse result.26  void makeASTUnits(const std::string &SrcCode0, const std::string &SrcCode1,27                    TestLanguage Lang) {28    this->Code0 = SrcCode0;29    this->Code1 = SrcCode1;30    std::vector<std::string> Args = getCommandLineArgsForTesting(Lang);31 32    const char *const InputFileName = "input.cc";33 34    AST0 = tooling::buildASTFromCodeWithArgs(Code0, Args, InputFileName);35    AST1 = tooling::buildASTFromCodeWithArgs(Code1, Args, InputFileName);36  }37 38  // Get a pair of node pointers into the synthesized AST from the given code39  // snippets. To determine the returned node, a separate matcher is specified40  // for both snippets. The first matching node is returned.41  template <typename NodeType, typename MatcherType>42  std::tuple<NodeType *, NodeType *>43  makeDecls(const std::string &SrcCode0, const std::string &SrcCode1,44            TestLanguage Lang, const MatcherType &Matcher0,45            const MatcherType &Matcher1) {46    makeASTUnits(SrcCode0, SrcCode1, Lang);47 48    NodeType *D0 = FirstDeclMatcher<NodeType>().match(49        AST0->getASTContext().getTranslationUnitDecl(), Matcher0);50    NodeType *D1 = FirstDeclMatcher<NodeType>().match(51        AST1->getASTContext().getTranslationUnitDecl(), Matcher1);52 53    return std::make_tuple(D0, D1);54  }55 56  std::tuple<TranslationUnitDecl *, TranslationUnitDecl *>57  makeTuDecls(const std::string &SrcCode0, const std::string &SrcCode1,58              TestLanguage Lang) {59    makeASTUnits(SrcCode0, SrcCode1, Lang);60 61    return std::make_tuple(AST0->getASTContext().getTranslationUnitDecl(),62                           AST1->getASTContext().getTranslationUnitDecl());63  }64 65  // Get a pair of node pointers into the synthesized AST from the given code66  // snippets. The same matcher is used for both snippets.67  template <typename NodeType, typename MatcherType>68  std::tuple<NodeType *, NodeType *>69  makeDecls(const std::string &SrcCode0, const std::string &SrcCode1,70            TestLanguage Lang, const MatcherType &AMatcher) {71    return makeDecls<NodeType, MatcherType>(72          SrcCode0, SrcCode1, Lang, AMatcher, AMatcher);73  }74 75  // Get a pair of Decl pointers to the synthesized declarations from the given76  // code snippets. We search for the first NamedDecl with given name in both77  // snippets.78  std::tuple<NamedDecl *, NamedDecl *>79  makeNamedDecls(const std::string &SrcCode0, const std::string &SrcCode1,80                 TestLanguage Lang, const char *const Identifier = "foo") {81    auto Matcher = namedDecl(hasName(Identifier));82    return makeDecls<NamedDecl>(SrcCode0, SrcCode1, Lang, Matcher);83  }84 85  // Wraps a Stmt and the ASTContext that contains it.86  struct StmtWithASTContext {87    Stmt *S;88    ASTContext *Context;89    explicit StmtWithASTContext(Stmt &S, ASTContext &Context)90        : S(&S), Context(&Context) {}91    explicit StmtWithASTContext(FunctionDecl *FD)92        : S(FD->getBody()), Context(&FD->getASTContext()) {}93  };94 95  // Get a pair of node pointers into the synthesized AST from the given code96  // snippets. To determine the returned node, a separate matcher is specified97  // for both snippets. The first matching node is returned.98  template <typename MatcherType>99  std::tuple<StmtWithASTContext, StmtWithASTContext>100  makeStmts(const std::string &SrcCode0, const std::string &SrcCode1,101            TestLanguage Lang, const MatcherType &Matcher0,102            const MatcherType &Matcher1) {103    makeASTUnits(SrcCode0, SrcCode1, Lang);104 105    Stmt *S0 = FirstDeclMatcher<Stmt>().match(106        AST0->getASTContext().getTranslationUnitDecl(), Matcher0);107    Stmt *S1 = FirstDeclMatcher<Stmt>().match(108        AST1->getASTContext().getTranslationUnitDecl(), Matcher1);109 110    return std::make_tuple(StmtWithASTContext(*S0, AST0->getASTContext()),111                           StmtWithASTContext(*S1, AST1->getASTContext()));112  }113 114  // Get a pair of node pointers into the synthesized AST from the given code115  // snippets. The same matcher is used for both snippets.116  template <typename MatcherType>117  std::tuple<StmtWithASTContext, StmtWithASTContext>118  makeStmts(const std::string &SrcCode0, const std::string &SrcCode1,119            TestLanguage Lang, const MatcherType &AMatcher) {120    return makeStmts(SrcCode0, SrcCode1, Lang, AMatcher, AMatcher);121  }122 123  // Convenience function for makeStmts that wraps the code inside a function124  // body.125  template <typename MatcherType>126  std::tuple<StmtWithASTContext, StmtWithASTContext>127  makeWrappedStmts(const std::string &SrcCode0, const std::string &SrcCode1,128                   TestLanguage Lang, const MatcherType &AMatcher) {129    auto Wrap = [](const std::string &Src) {130      return "void wrapped() {" + Src + ";}";131    };132    return makeStmts(Wrap(SrcCode0), Wrap(SrcCode1), Lang, AMatcher);133  }134 135  bool testStructuralMatch(Decl *D0, Decl *D1,136                           bool IgnoreTemplateParmDepth = false) {137    StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls01;138    StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls10;139    StructuralEquivalenceContext Ctx01(140        D0->getLangOpts(), D0->getASTContext(), D1->getASTContext(),141        NonEquivalentDecls01, StructuralEquivalenceKind::Default,142        /*StrictTypeSpelling=*/false,143        /*Complain=*/false, /*ErrorOnTagTypeMismatch=*/false,144        IgnoreTemplateParmDepth);145    StructuralEquivalenceContext Ctx10(146        D1->getLangOpts(), D1->getASTContext(), D0->getASTContext(),147        NonEquivalentDecls10, StructuralEquivalenceKind::Default,148        /*StrictTypeSpelling=*/false,149        /*Complain=*/false, /*ErrorOnTagTypeMismatch=*/false,150        IgnoreTemplateParmDepth);151    bool Eq01 = Ctx01.IsEquivalent(D0, D1);152    bool Eq10 = Ctx10.IsEquivalent(D1, D0);153    EXPECT_EQ(Eq01, Eq10);154    return Eq01;155  }156 157  bool testStructuralMatch(StmtWithASTContext S0, StmtWithASTContext S1) {158    StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls01;159    StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls10;160    StructuralEquivalenceContext Ctx01(S0.Context->getLangOpts(), *S0.Context,161                                       *S1.Context, NonEquivalentDecls01,162                                       StructuralEquivalenceKind::Default,163                                       /*StrictTypeSpelling=*/false,164                                       /*Complain=*/false);165    StructuralEquivalenceContext Ctx10(S1.Context->getLangOpts(), *S1.Context,166                                       *S0.Context, NonEquivalentDecls10,167                                       StructuralEquivalenceKind::Default,168                                       /*StrictTypeSpelling=*/false,169                                       /*Complain=*/false);170    bool Eq01 = Ctx01.IsEquivalent(S0.S, S1.S);171    bool Eq10 = Ctx10.IsEquivalent(S1.S, S0.S);172    EXPECT_EQ(Eq01, Eq10);173    return Eq01;174  }175 176  bool177  testStructuralMatch(std::tuple<StmtWithASTContext, StmtWithASTContext> t) {178    return testStructuralMatch(get<0>(t), get<1>(t));179  }180 181  bool testStructuralMatch(std::tuple<Decl *, Decl *> t,182                           bool IgnoreTemplateParmDepth = false) {183    return testStructuralMatch(get<0>(t), get<1>(t), IgnoreTemplateParmDepth);184  }185};186 187TEST_F(StructuralEquivalenceTest, Int) {188  auto Decls = makeNamedDecls("int foo;", "int foo;", Lang_CXX03);189  EXPECT_TRUE(testStructuralMatch(Decls));190}191 192TEST_F(StructuralEquivalenceTest, IntVsSignedInt) {193  auto Decls = makeNamedDecls("int foo;", "signed int foo;", Lang_CXX03);194  EXPECT_TRUE(testStructuralMatch(Decls));195}196 197TEST_F(StructuralEquivalenceTest, Char) {198  auto Decls = makeNamedDecls("char foo;", "char foo;", Lang_CXX03);199  EXPECT_TRUE(testStructuralMatch(Decls));200}201 202// This test is disabled for now.203// FIXME Whether this is equivalent is dependent on the target.204TEST_F(StructuralEquivalenceTest, DISABLED_CharVsSignedChar) {205  auto Decls = makeNamedDecls("char foo;", "signed char foo;", Lang_CXX03);206  EXPECT_FALSE(testStructuralMatch(Decls));207}208 209TEST_F(StructuralEquivalenceTest, ForwardRecordDecl) {210  auto Decls = makeNamedDecls("struct foo;", "struct foo;", Lang_CXX03);211  EXPECT_TRUE(testStructuralMatch(Decls));212}213 214TEST_F(StructuralEquivalenceTest, IntVsSignedIntInStruct) {215  auto Decls = makeNamedDecls("struct foo { int x; };",216                              "struct foo { signed int x; };", Lang_CXX03);217  EXPECT_TRUE(testStructuralMatch(Decls));218}219 220TEST_F(StructuralEquivalenceTest, CharVsSignedCharInStruct) {221  auto Decls = makeNamedDecls("struct foo { char x; };",222                              "struct foo { signed char x; };", Lang_CXX03);223  EXPECT_FALSE(testStructuralMatch(Decls));224}225 226TEST_F(StructuralEquivalenceTest, IntVsSignedIntTemplateSpec) {227  auto Decls = makeDecls<ClassTemplateSpecializationDecl>(228      R"(template <class T> struct foo; template<> struct foo<int>{};)",229      R"(template <class T> struct foo; template<> struct foo<signed int>{};)",230      Lang_CXX03, classTemplateSpecializationDecl());231  auto Spec0 = get<0>(Decls);232  auto Spec1 = get<1>(Decls);233  EXPECT_TRUE(testStructuralMatch(Spec0, Spec1));234}235 236TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpec) {237  auto Decls = makeDecls<ClassTemplateSpecializationDecl>(238      R"(template <class T> struct foo; template<> struct foo<char>{};)",239      R"(template <class T> struct foo; template<> struct foo<signed char>{};)",240      Lang_CXX03, classTemplateSpecializationDecl());241  auto Spec0 = get<0>(Decls);242  auto Spec1 = get<1>(Decls);243  EXPECT_FALSE(testStructuralMatch(Spec0, Spec1));244}245 246TEST_F(StructuralEquivalenceTest, CharVsSignedCharTemplateSpecWithInheritance) {247  auto Decls = makeDecls<ClassTemplateSpecializationDecl>(248      R"(249      struct true_type{};250      template <class T> struct foo;251      template<> struct foo<char> : true_type {};252      )",253      R"(254      struct true_type{};255      template <class T> struct foo;256      template<> struct foo<signed char> : true_type {};257      )",258      Lang_CXX03, classTemplateSpecializationDecl());259  EXPECT_FALSE(testStructuralMatch(Decls));260}261 262// This test is disabled for now.263// FIXME Enable it, once the check is implemented.264TEST_F(StructuralEquivalenceTest, DISABLED_WrongOrderInNamespace) {265  auto Code =266      R"(267      namespace NS {268      template <class T> class Base {269          int a;270      };271      class Derived : Base<Derived> {272      };273      }274      void foo(NS::Derived &);275      )";276  auto Decls = makeNamedDecls(Code, Code, Lang_CXX03);277 278  NamespaceDecl *NS =279      LastDeclMatcher<NamespaceDecl>().match(get<1>(Decls), namespaceDecl());280  ClassTemplateDecl *TD = LastDeclMatcher<ClassTemplateDecl>().match(281      get<1>(Decls), classTemplateDecl(hasName("Base")));282 283  // Reorder the decls, move the TD to the last place in the DC.284  NS->removeDecl(TD);285  NS->addDeclInternal(TD);286 287  EXPECT_FALSE(testStructuralMatch(Decls));288}289 290TEST_F(StructuralEquivalenceTest, WrongOrderOfFieldsInClass) {291  auto Code = "class X { int a; int b; };";292  auto Decls = makeNamedDecls(Code, Code, Lang_CXX03, "X");293 294  CXXRecordDecl *RD = FirstDeclMatcher<CXXRecordDecl>().match(295      get<1>(Decls), cxxRecordDecl(hasName("X")));296  FieldDecl *FD =297      FirstDeclMatcher<FieldDecl>().match(get<1>(Decls), fieldDecl(hasName("a")));298 299  // Reorder the FieldDecls300  RD->removeDecl(FD);301  RD->addDeclInternal(FD);302 303  EXPECT_FALSE(testStructuralMatch(Decls));304}305 306struct StructuralEquivalenceFunctionTest : StructuralEquivalenceTest {307};308 309TEST_F(StructuralEquivalenceFunctionTest, TemplateVsNonTemplate) {310  auto t = makeNamedDecls("void foo();", "template<class T> void foo();",311                          Lang_CXX03);312  EXPECT_FALSE(testStructuralMatch(t));313}314 315TEST_F(StructuralEquivalenceFunctionTest, DifferentOperators) {316  auto t = makeDecls<FunctionDecl>(317      "struct X{}; bool operator<(X, X);", "struct X{}; bool operator==(X, X);",318      Lang_CXX03, functionDecl(hasOverloadedOperatorName("<")),319      functionDecl(hasOverloadedOperatorName("==")));320  EXPECT_FALSE(testStructuralMatch(t));321}322 323TEST_F(StructuralEquivalenceFunctionTest, SameOperators) {324  auto t = makeDecls<FunctionDecl>(325      "struct X{}; bool operator<(X, X);", "struct X{}; bool operator<(X, X);",326      Lang_CXX03, functionDecl(hasOverloadedOperatorName("<")),327      functionDecl(hasOverloadedOperatorName("<")));328  EXPECT_TRUE(testStructuralMatch(t));329}330 331TEST_F(StructuralEquivalenceFunctionTest, CtorVsDtor) {332  auto t = makeDecls<FunctionDecl>("struct X{ X(); };", "struct X{ ~X(); };",333                                   Lang_CXX03, cxxConstructorDecl(),334                                   cxxDestructorDecl());335  EXPECT_FALSE(testStructuralMatch(t));336}337 338TEST_F(StructuralEquivalenceFunctionTest, ParamConstWithRef) {339  auto t =340      makeNamedDecls("void foo(int&);", "void foo(const int&);", Lang_CXX03);341  EXPECT_FALSE(testStructuralMatch(t));342}343 344TEST_F(StructuralEquivalenceFunctionTest, ParamConstSimple) {345  auto t = makeNamedDecls("void foo(int);", "void foo(const int);", Lang_CXX03);346  EXPECT_TRUE(testStructuralMatch(t));347  // consider this OK348}349 350TEST_F(StructuralEquivalenceFunctionTest, Throw) {351  auto t = makeNamedDecls("void foo();", "void foo() throw();", Lang_CXX03);352  EXPECT_FALSE(testStructuralMatch(t));353}354 355TEST_F(StructuralEquivalenceFunctionTest, Noexcept) {356  auto t = makeNamedDecls("void foo();",357                          "void foo() noexcept;", Lang_CXX11);358  EXPECT_FALSE(testStructuralMatch(t));359}360 361TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexcept) {362  auto t = makeNamedDecls("void foo() throw();",363                          "void foo() noexcept;", Lang_CXX11);364  EXPECT_FALSE(testStructuralMatch(t));365}366 367TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptFalse) {368  auto t = makeNamedDecls("void foo() throw();",369                          "void foo() noexcept(false);", Lang_CXX11);370  EXPECT_FALSE(testStructuralMatch(t));371}372 373TEST_F(StructuralEquivalenceFunctionTest, ThrowVsNoexceptTrue) {374  auto t = makeNamedDecls("void foo() throw();",375                          "void foo() noexcept(true);", Lang_CXX11);376  EXPECT_FALSE(testStructuralMatch(t));377}378 379TEST_F(StructuralEquivalenceFunctionTest, NoexceptNonMatch) {380  auto t = makeNamedDecls("void foo() noexcept(false);",381                          "void foo() noexcept(true);", Lang_CXX11);382  EXPECT_FALSE(testStructuralMatch(t));383}384 385TEST_F(StructuralEquivalenceFunctionTest, NoexceptMatch) {386  auto t = makeNamedDecls("void foo() noexcept(false);",387                          "void foo() noexcept(false);", Lang_CXX11);388  EXPECT_TRUE(testStructuralMatch(t));389}390 391TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptFalse) {392  auto t = makeNamedDecls("void foo() noexcept;",393                          "void foo() noexcept(false);", Lang_CXX11);394  EXPECT_FALSE(testStructuralMatch(t));395}396 397TEST_F(StructuralEquivalenceFunctionTest, NoexceptVsNoexceptTrue) {398  auto t = makeNamedDecls("void foo() noexcept;",399                          "void foo() noexcept(true);", Lang_CXX11);400  EXPECT_FALSE(testStructuralMatch(t));401}402 403TEST_F(StructuralEquivalenceFunctionTest, ReturnType) {404  auto t = makeNamedDecls("char foo();", "int foo();", Lang_CXX03);405  EXPECT_FALSE(testStructuralMatch(t));406}407 408TEST_F(StructuralEquivalenceFunctionTest, ReturnConst) {409  auto t = makeNamedDecls("char foo();", "const char foo();", Lang_CXX03);410  EXPECT_FALSE(testStructuralMatch(t));411}412 413TEST_F(StructuralEquivalenceFunctionTest, ReturnRef) {414  auto t = makeNamedDecls("char &foo();",415                          "char &&foo();", Lang_CXX11);416  EXPECT_FALSE(testStructuralMatch(t));417}418 419TEST_F(StructuralEquivalenceFunctionTest, ParamCount) {420  auto t = makeNamedDecls("void foo(int);", "void foo(int, int);", Lang_CXX03);421  EXPECT_FALSE(testStructuralMatch(t));422}423 424TEST_F(StructuralEquivalenceFunctionTest, ParamType) {425  auto t = makeNamedDecls("void foo(int);", "void foo(char);", Lang_CXX03);426  EXPECT_FALSE(testStructuralMatch(t));427}428 429TEST_F(StructuralEquivalenceFunctionTest, ParamName) {430  auto t = makeNamedDecls("void foo(int a);", "void foo(int b);", Lang_CXX03);431  EXPECT_TRUE(testStructuralMatch(t));432}433 434TEST_F(StructuralEquivalenceFunctionTest, Variadic) {435  auto t =436      makeNamedDecls("void foo(int x...);", "void foo(int x);", Lang_CXX03);437  EXPECT_FALSE(testStructuralMatch(t));438}439 440TEST_F(StructuralEquivalenceFunctionTest, ParamPtr) {441  auto t = makeNamedDecls("void foo(int *);", "void foo(int);", Lang_CXX03);442  EXPECT_FALSE(testStructuralMatch(t));443}444 445TEST_F(StructuralEquivalenceFunctionTest, NameInParen) {446  auto t = makeNamedDecls("void ((foo))();", "void foo();", Lang_CXX03);447  EXPECT_TRUE(testStructuralMatch(t));448}449 450TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithExceptionSpec) {451  auto t = makeNamedDecls(452      "void (foo)() throw(int);",453      "void (foo)() noexcept;",454      Lang_CXX11);455  EXPECT_FALSE(testStructuralMatch(t));456}457 458TEST_F(StructuralEquivalenceFunctionTest, NameInParenWithConst) {459  auto t = makeNamedDecls(460      "struct A { void (foo)() const; };",461      "struct A { void (foo)(); };",462      Lang_CXX11);463  EXPECT_FALSE(testStructuralMatch(t));464}465 466TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentNoreturnAttr) {467  auto t = makeNamedDecls("__attribute__((noreturn)) void foo();",468                          "                          void foo();", Lang_C99);469  EXPECT_TRUE(testStructuralMatch(t));470}471 472TEST_F(StructuralEquivalenceFunctionTest,473    FunctionsWithDifferentCallingConventions) {474  // These attributes may not be available on certain platforms.475  if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() !=476      llvm::Triple::x86_64)477    GTEST_SKIP();478  auto t = makeNamedDecls("__attribute__((preserve_all)) void foo();",479                          "__attribute__((ms_abi))   void foo();", Lang_C99);480  EXPECT_FALSE(testStructuralMatch(t));481}482 483TEST_F(StructuralEquivalenceFunctionTest, FunctionsWithDifferentSavedRegsAttr) {484  if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getArch() !=485      llvm::Triple::x86_64)486    GTEST_SKIP();487  auto t = makeNamedDecls(488      "__attribute__((no_caller_saved_registers)) void foo();",489      "                                           void foo();", Lang_C99);490  EXPECT_FALSE(testStructuralMatch(t));491}492 493struct StructuralEquivalenceCXXMethodTest : StructuralEquivalenceTest {494};495 496TEST_F(StructuralEquivalenceCXXMethodTest, Virtual) {497  auto t = makeDecls<CXXMethodDecl>("struct X { void foo(); };",498                                    "struct X { virtual void foo(); };",499                                    Lang_CXX03, cxxMethodDecl(hasName("foo")));500  EXPECT_FALSE(testStructuralMatch(t));501}502 503TEST_F(StructuralEquivalenceCXXMethodTest, Pure) {504  auto t = makeNamedDecls("struct X { virtual void foo(); };",505                          "struct X { virtual void foo() = 0; };", Lang_CXX03);506  EXPECT_FALSE(testStructuralMatch(t));507}508 509TEST_F(StructuralEquivalenceCXXMethodTest, DISABLED_Final) {510  // The final-ness is not checked yet.511  auto t =512      makeNamedDecls("struct X { virtual void foo(); };",513                     "struct X { virtual void foo() final; };", Lang_CXX03);514  EXPECT_FALSE(testStructuralMatch(t));515}516 517TEST_F(StructuralEquivalenceCXXMethodTest, Const) {518  auto t = makeNamedDecls("struct X { void foo(); };",519                          "struct X { void foo() const; };", Lang_CXX03);520  EXPECT_FALSE(testStructuralMatch(t));521}522 523TEST_F(StructuralEquivalenceCXXMethodTest, Static) {524  auto t = makeNamedDecls("struct X { void foo(); };",525                          "struct X { static void foo(); };", Lang_CXX03);526  EXPECT_FALSE(testStructuralMatch(t));527}528 529TEST_F(StructuralEquivalenceCXXMethodTest, Ref1) {530  auto t = makeNamedDecls("struct X { void foo(); };",531                          "struct X { void foo() &&; };", Lang_CXX11);532  EXPECT_FALSE(testStructuralMatch(t));533}534 535TEST_F(StructuralEquivalenceCXXMethodTest, Ref2) {536  auto t = makeNamedDecls("struct X { void foo() &; };",537                          "struct X { void foo() &&; };", Lang_CXX11);538  EXPECT_FALSE(testStructuralMatch(t));539}540 541TEST_F(StructuralEquivalenceCXXMethodTest, AccessSpecifier) {542  auto t = makeDecls<CXXMethodDecl>("struct X { public: void foo(); };",543                                    "struct X { private: void foo(); };",544                                    Lang_CXX03, cxxMethodDecl(hasName("foo")));545  EXPECT_FALSE(testStructuralMatch(t));546}547 548TEST_F(StructuralEquivalenceCXXMethodTest, Delete) {549  auto t = makeNamedDecls("struct X { void foo(); };",550                          "struct X { void foo() = delete; };", Lang_CXX11);551  EXPECT_FALSE(testStructuralMatch(t));552}553 554TEST_F(StructuralEquivalenceCXXMethodTest, Constructor) {555  auto t = makeDecls<FunctionDecl>("void foo();", "struct foo { foo(); };",556                                   Lang_CXX03, functionDecl(hasName("foo")),557                                   cxxConstructorDecl(hasName("foo")));558  EXPECT_FALSE(testStructuralMatch(t));559}560 561TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorParam) {562  auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",563                                         "struct X { X(int); };", Lang_CXX03,564                                         cxxConstructorDecl(hasName("X")));565  EXPECT_FALSE(testStructuralMatch(t));566}567 568TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorExplicit) {569  auto t = makeDecls<CXXConstructorDecl>("struct X { X(int); };",570                                         "struct X { explicit X(int); };",571                                         Lang_CXX11,572                                         cxxConstructorDecl(hasName("X")));573  EXPECT_FALSE(testStructuralMatch(t));574}575 576TEST_F(StructuralEquivalenceCXXMethodTest, ConstructorDefault) {577  auto t = makeDecls<CXXConstructorDecl>("struct X { X(); };",578                                         "struct X { X() = default; };",579                                         Lang_CXX11,580                                         cxxConstructorDecl(hasName("X")));581  EXPECT_FALSE(testStructuralMatch(t));582}583 584TEST_F(StructuralEquivalenceCXXMethodTest, Conversion) {585  auto t = makeDecls<CXXConversionDecl>("struct X { operator bool(); };",586                                        "struct X { operator char(); };",587                                         Lang_CXX11,588                                         cxxConversionDecl());589  EXPECT_FALSE(testStructuralMatch(t));590}591 592TEST_F(StructuralEquivalenceCXXMethodTest, Operator) {593  auto t =594      makeDecls<FunctionDecl>("struct X { int operator +(int); };",595                              "struct X { int operator -(int); };", Lang_CXX03,596                              functionDecl(hasOverloadedOperatorName("+")),597                              functionDecl(hasOverloadedOperatorName("-")));598  EXPECT_FALSE(testStructuralMatch(t));599}600 601TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass1) {602  auto t = makeDecls<FunctionDecl>(603      "struct X { virtual void f(); }; void X::f() { }",604      "struct X { virtual void f() { }; };", Lang_CXX03,605      functionDecl(allOf(hasName("f"), isDefinition())));606  EXPECT_TRUE(testStructuralMatch(t));607}608 609TEST_F(StructuralEquivalenceCXXMethodTest, OutOfClass2) {610  auto t = makeDecls<FunctionDecl>(611      "struct X { virtual void f(); }; void X::f() { }",612      "struct X { void f(); }; void X::f() { }", Lang_CXX03,613      functionDecl(allOf(hasName("f"), isDefinition())));614  EXPECT_FALSE(testStructuralMatch(t));615}616 617struct StructuralEquivalenceRecordTest : StructuralEquivalenceTest {618  // FIXME Use a common getRecordDecl with ASTImporterTest.cpp!619  RecordDecl *getRecordDecl(FieldDecl *FD) {620    return FD->getType()->getAsRecordDecl();621  };622};623 624TEST_F(StructuralEquivalenceRecordTest, Name) {625  auto t = makeDecls<CXXRecordDecl>("struct A{ };", "struct B{ };", Lang_CXX03,626                                    cxxRecordDecl(hasName("A")),627                                    cxxRecordDecl(hasName("B")));628  EXPECT_FALSE(testStructuralMatch(t));629}630 631TEST_F(StructuralEquivalenceRecordTest, Fields) {632  auto t = makeNamedDecls("struct foo{ int x; };", "struct foo{ char x; };",633                          Lang_CXX03);634  EXPECT_FALSE(testStructuralMatch(t));635}636 637TEST_F(StructuralEquivalenceRecordTest, DISABLED_Methods) {638  // Currently, methods of a class are not checked at class equivalence.639  auto t = makeNamedDecls("struct foo{ int x(); };", "struct foo{ char x(); };",640                          Lang_CXX03);641  EXPECT_FALSE(testStructuralMatch(t));642}643 644TEST_F(StructuralEquivalenceRecordTest, Bases) {645  auto t = makeNamedDecls("struct A{ }; struct foo: A { };",646                          "struct B{ }; struct foo: B { };", Lang_CXX03);647  EXPECT_FALSE(testStructuralMatch(t));648}649 650TEST_F(StructuralEquivalenceRecordTest, InheritanceVirtual) {651  auto t =652      makeNamedDecls("struct A{ }; struct foo: A { };",653                     "struct A{ }; struct foo: virtual A { };", Lang_CXX03);654  EXPECT_FALSE(testStructuralMatch(t));655}656 657TEST_F(StructuralEquivalenceRecordTest, DISABLED_InheritanceType) {658  // Access specifier in inheritance is not checked yet.659  auto t =660      makeNamedDecls("struct A{ }; struct foo: public A { };",661                     "struct A{ }; struct foo: private A { };", Lang_CXX03);662  EXPECT_FALSE(testStructuralMatch(t));663}664 665TEST_F(StructuralEquivalenceRecordTest, Match) {666  auto Code = R"(667      struct A{ };668      struct B{ };669      struct foo: A, virtual B {670        void x();671        int a;672      };673      )";674  auto t = makeNamedDecls(Code, Code, Lang_CXX03);675  EXPECT_TRUE(testStructuralMatch(t));676}677 678TEST_F(StructuralEquivalenceRecordTest, UnnamedRecordsShouldBeInequivalent) {679  auto t = makeTuDecls(680      R"(681      struct A {682        struct {683          struct A *next;684        } entry0;685        struct {686          struct A *next;687        } entry1;688      };689      )",690      "", Lang_C99);691  auto *TU = get<0>(t);692  auto *Entry0 =693      FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry0")));694  auto *Entry1 =695      FirstDeclMatcher<FieldDecl>().match(TU, fieldDecl(hasName("entry1")));696  auto *R0 = getRecordDecl(Entry0);697  auto *R1 = getRecordDecl(Entry1);698 699  ASSERT_NE(R0, R1);700  EXPECT_TRUE(testStructuralMatch(R0, R0));701  EXPECT_TRUE(testStructuralMatch(R1, R1));702  EXPECT_FALSE(testStructuralMatch(R0, R1));703}704 705TEST_F(StructuralEquivalenceRecordTest, AnonymousRecordsShouldBeInequivalent) {706  auto t = makeTuDecls(707      R"(708      struct X {709        struct {710          int a;711        };712        struct {713          int b;714        };715      };716      )",717      "", Lang_C99);718  auto *TU = get<0>(t);719  auto *A = FirstDeclMatcher<IndirectFieldDecl>().match(720      TU, indirectFieldDecl(hasName("a")));721  auto *FA = cast<FieldDecl>(A->chain().front());722  RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl();723  auto *B = FirstDeclMatcher<IndirectFieldDecl>().match(724      TU, indirectFieldDecl(hasName("b")));725  auto *FB = cast<FieldDecl>(B->chain().front());726  RecordDecl *RB = cast<RecordType>(FB->getType().getTypePtr())->getDecl();727 728  ASSERT_NE(RA, RB);729  EXPECT_TRUE(testStructuralMatch(RA, RA));730  EXPECT_TRUE(testStructuralMatch(RB, RB));731  EXPECT_FALSE(testStructuralMatch(RA, RB));732}733 734TEST_F(StructuralEquivalenceRecordTest,735       RecordsAreInequivalentIfOrderOfAnonRecordsIsDifferent) {736  auto t = makeTuDecls(737      R"(738      struct X {739        struct { int a; };740        struct { int b; };741      };742      )",743      R"(744      struct X { // The order is reversed.745        struct { int b; };746        struct { int a; };747      };748      )",749      Lang_C99);750 751  auto *TU = get<0>(t);752  auto *A = FirstDeclMatcher<IndirectFieldDecl>().match(753      TU, indirectFieldDecl(hasName("a")));754  auto *FA = cast<FieldDecl>(A->chain().front());755  RecordDecl *RA = cast<RecordType>(FA->getType().getTypePtr())->getDecl();756 757  auto *TU1 = get<1>(t);758  auto *A1 = FirstDeclMatcher<IndirectFieldDecl>().match(759      TU1, indirectFieldDecl(hasName("a")));760  auto *FA1 = cast<FieldDecl>(A1->chain().front());761  RecordDecl *RA1 = cast<RecordType>(FA1->getType().getTypePtr())->getDecl();762 763  RecordDecl *X =764      FirstDeclMatcher<RecordDecl>().match(TU, recordDecl(hasName("X")));765  RecordDecl *X1 =766      FirstDeclMatcher<RecordDecl>().match(TU1, recordDecl(hasName("X")));767  ASSERT_NE(X, X1);768  EXPECT_FALSE(testStructuralMatch(X, X1));769 770  ASSERT_NE(RA, RA1);771  EXPECT_TRUE(testStructuralMatch(RA, RA));772  EXPECT_TRUE(testStructuralMatch(RA1, RA1));773  EXPECT_FALSE(testStructuralMatch(RA1, RA));774}775 776TEST_F(StructuralEquivalenceRecordTest,777       UnnamedRecordsShouldBeInequivalentEvenIfTheSecondIsBeingDefined) {778  auto Code =779      R"(780      struct A {781        struct {782          struct A *next;783        } entry0;784        struct {785          struct A *next;786        } entry1;787      };788      )";789  auto t = makeTuDecls(Code, Code, Lang_C99);790 791  auto *FromTU = get<0>(t);792  auto *Entry1 =793      FirstDeclMatcher<FieldDecl>().match(FromTU, fieldDecl(hasName("entry1")));794 795  auto *ToTU = get<1>(t);796  auto *Entry0 =797      FirstDeclMatcher<FieldDecl>().match(ToTU, fieldDecl(hasName("entry0")));798  auto *A =799      FirstDeclMatcher<RecordDecl>().match(ToTU, recordDecl(hasName("A")));800  A->startDefinition(); // Set isBeingDefined, getDefinition() will return a801                        // nullptr. This may be the case during ASTImport.802 803  auto *R0 = getRecordDecl(Entry0);804  auto *R1 = getRecordDecl(Entry1);805 806  ASSERT_NE(R0, R1);807  EXPECT_TRUE(testStructuralMatch(R0, R0));808  EXPECT_TRUE(testStructuralMatch(R1, R1));809  EXPECT_FALSE(testStructuralMatch(R0, R1));810}811 812TEST_F(StructuralEquivalenceRecordTest, TemplateVsNonTemplate) {813  auto t = makeDecls<CXXRecordDecl>("struct A { };",814                                    "template<class T> struct A { };",815                                    Lang_CXX03, cxxRecordDecl(hasName("A")));816  EXPECT_FALSE(testStructuralMatch(t));817}818 819TEST_F(StructuralEquivalenceRecordTest,820    FwdDeclRecordShouldBeEqualWithFwdDeclRecord) {821  auto t = makeNamedDecls("class foo;", "class foo;", Lang_CXX11);822  EXPECT_TRUE(testStructuralMatch(t));823}824 825TEST_F(StructuralEquivalenceRecordTest,826       FwdDeclRecordShouldBeEqualWithRecordWhichHasDefinition) {827  auto t =828      makeNamedDecls("class foo;", "class foo { int A; };", Lang_CXX11);829  EXPECT_TRUE(testStructuralMatch(t));830}831 832TEST_F(StructuralEquivalenceRecordTest,833       RecordShouldBeEqualWithRecordWhichHasDefinition) {834  auto t = makeNamedDecls("class foo { int A; };", "class foo { int A; };",835                          Lang_CXX11);836  EXPECT_TRUE(testStructuralMatch(t));837}838 839TEST_F(StructuralEquivalenceRecordTest, RecordsWithDifferentBody) {840  auto t = makeNamedDecls("class foo { int B; };", "class foo { int A; };",841                          Lang_CXX11);842  EXPECT_FALSE(testStructuralMatch(t));843}844 845TEST_F(StructuralEquivalenceRecordTest, SameFriendMultipleTimes) {846  auto t = makeNamedDecls("struct foo { friend class X; };",847                          "struct foo { friend class X; friend class X; };",848                          Lang_CXX11);849  EXPECT_FALSE(testStructuralMatch(t));850}851 852TEST_F(StructuralEquivalenceRecordTest, SameFriendsDifferentOrder) {853  auto t = makeNamedDecls("struct foo { friend class X; friend class Y; };",854                          "struct foo { friend class Y; friend class X; };",855                          Lang_CXX11);856  EXPECT_FALSE(testStructuralMatch(t));857}858 859TEST_F(StructuralEquivalenceRecordTest, SameFriendsSameOrder) {860  auto t = makeNamedDecls("struct foo { friend class X; friend class Y; };",861                          "struct foo { friend class X; friend class Y; };",862                          Lang_CXX11);863  EXPECT_TRUE(testStructuralMatch(t));864}865 866struct StructuralEquivalenceLambdaTest : StructuralEquivalenceTest {};867 868TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentMethods) {869  // Get the LambdaExprs, unfortunately we can't match directly the underlying870  // implicit CXXRecordDecl of the Lambda classes.871  auto t = makeDecls<LambdaExpr>(872      "void f() { auto L0 = [](int){}; }",873      "void f() { auto L1 = [](){}; }",874      Lang_CXX11,875      lambdaExpr(),876      lambdaExpr());877  CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();878  CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();879  EXPECT_FALSE(testStructuralMatch(L0, L1));880}881 882TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqMethods) {883  auto t = makeDecls<LambdaExpr>(884      "void f() { auto L0 = [](int){}; }",885      "void f() { auto L1 = [](int){}; }",886      Lang_CXX11,887      lambdaExpr(),888      lambdaExpr());889  CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();890  CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();891  EXPECT_TRUE(testStructuralMatch(L0, L1));892}893 894TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentFields) {895  auto t = makeDecls<LambdaExpr>(896      "void f() { char* X; auto L0 = [X](){}; }",897      "void f() { float X; auto L1 = [X](){}; }",898      Lang_CXX11,899      lambdaExpr(),900      lambdaExpr());901  CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();902  CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();903  EXPECT_FALSE(testStructuralMatch(L0, L1));904}905 906TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqFields) {907  auto t = makeDecls<LambdaExpr>(908      "void f() { float X; auto L0 = [X](){}; }",909      "void f() { float X; auto L1 = [X](){}; }",910      Lang_CXX11,911      lambdaExpr(),912      lambdaExpr());913  CXXRecordDecl *L0 = get<0>(t)->getLambdaClass();914  CXXRecordDecl *L1 = get<1>(t)->getLambdaClass();915  EXPECT_TRUE(testStructuralMatch(L0, L1));916}917 918TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) {919  auto t = makeNamedDecls("struct A{ }; struct B{ }; void foo(A a, A b);",920                          "struct A{ }; struct B{ }; void foo(A a, B b);",921                          Lang_CXX03);922  EXPECT_FALSE(testStructuralMatch(t));923}924 925TEST_F(StructuralEquivalenceTest, ExplicitBoolDifferent) {926  auto Decls = makeNamedDecls("struct foo {explicit(false) foo(int);};",927                              "struct foo {explicit(true) foo(int);};", Lang_CXX20);928  CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(929      get<0>(Decls), cxxConstructorDecl(hasName("foo")));930  CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(931      get<1>(Decls), cxxConstructorDecl(hasName("foo")));932  EXPECT_FALSE(testStructuralMatch(First, Second));933}934 935TEST_F(StructuralEquivalenceTest, ExplicitBoolSame) {936  auto Decls = makeNamedDecls("struct foo {explicit(true) foo(int);};",937                              "struct foo {explicit(true) foo(int);};", Lang_CXX20);938  CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(939      get<0>(Decls), cxxConstructorDecl(hasName("foo")));940  CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(941      get<1>(Decls), cxxConstructorDecl(hasName("foo")));942  EXPECT_TRUE(testStructuralMatch(First, Second));943}944 945struct StructuralEquivalenceRecordContextTest : StructuralEquivalenceTest {};946 947TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNoVsNamed) {948  auto Decls =949      makeNamedDecls("class X;", "namespace N { class X; }", Lang_CXX03, "X");950  EXPECT_FALSE(testStructuralMatch(Decls));951}952 953TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNamedVsNamed) {954  auto Decls = makeNamedDecls("namespace A { class X; }",955                              "namespace B { class X; }", Lang_CXX03, "X");956  EXPECT_FALSE(testStructuralMatch(Decls));957}958 959TEST_F(StructuralEquivalenceRecordContextTest, NamespaceAnonVsNamed) {960  auto Decls = makeNamedDecls("namespace { class X; }",961                              "namespace N { class X; }", Lang_CXX03, "X");962  EXPECT_FALSE(testStructuralMatch(Decls));963}964 965TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNoVsAnon) {966  auto Decls =967      makeNamedDecls("class X;", "namespace { class X; }", Lang_CXX03, "X");968  EXPECT_FALSE(testStructuralMatch(Decls));969}970 971TEST_F(StructuralEquivalenceRecordContextTest, NamespaceAnonVsAnon) {972  auto Decls = makeNamedDecls("namespace { class X; }",973                              "namespace { class X; }", Lang_CXX03, "X");974  EXPECT_TRUE(testStructuralMatch(Decls));975}976 977TEST_F(StructuralEquivalenceRecordContextTest, NamespaceAnonVsAnonAnon) {978  auto Decls =979      makeNamedDecls("namespace { class X; }",980                     "namespace { namespace { class X; } }", Lang_CXX03, "X");981  EXPECT_FALSE(testStructuralMatch(Decls));982}983 984TEST_F(StructuralEquivalenceRecordContextTest,985       NamespaceNamedNamedVsNamedNamed) {986  auto Decls = makeNamedDecls("namespace A { namespace N { class X; } }",987                              "namespace B { namespace N { class X; } }",988                              Lang_CXX03, "X");989  EXPECT_FALSE(testStructuralMatch(Decls));990}991 992TEST_F(StructuralEquivalenceRecordContextTest, NamespaceNamedVsInline) {993  auto Decls = makeNamedDecls("namespace A { namespace A { class X; } }",994                              "namespace A { inline namespace A { class X; } }",995                              Lang_CXX17, "X");996  EXPECT_FALSE(testStructuralMatch(Decls));997}998 999TEST_F(StructuralEquivalenceRecordContextTest, NamespaceInlineVsInline) {1000  auto Decls = makeNamedDecls("namespace A { inline namespace A { class X; } }",1001                              "namespace A { inline namespace B { class X; } }",1002                              Lang_CXX17, "X");1003  EXPECT_TRUE(testStructuralMatch(Decls));1004}1005 1006TEST_F(StructuralEquivalenceRecordContextTest, NamespaceInlineTopLevel) {1007  auto Decls =1008      makeNamedDecls("inline namespace A { class X; }",1009                     "inline namespace B { class X; }", Lang_CXX17, "X");1010  EXPECT_TRUE(testStructuralMatch(Decls));1011}1012 1013TEST_F(StructuralEquivalenceRecordContextTest, TransparentContext) {1014  auto Decls =1015      makeNamedDecls("extern \"C\" { class X; }", "class X;", Lang_CXX03, "X");1016  EXPECT_TRUE(testStructuralMatch(Decls));1017}1018 1019TEST_F(StructuralEquivalenceRecordContextTest, TransparentContextNE) {1020  auto Decls = makeNamedDecls("extern \"C\" { class X; }",1021                              "namespace { class X; }", Lang_CXX03, "X");1022  EXPECT_FALSE(testStructuralMatch(Decls));1023}1024 1025TEST_F(StructuralEquivalenceRecordContextTest, TransparentContextInNamespace) {1026  auto Decls = makeNamedDecls("extern \"C\" { namespace N { class X; } }",1027                              "namespace N { extern \"C\" { class X; } }",1028                              Lang_CXX03, "X");1029  EXPECT_TRUE(testStructuralMatch(Decls));1030}1031 1032TEST_F(StructuralEquivalenceRecordContextTest,1033       ClassTemplateSpecializationContext) {1034  std::string Code =1035      R"(1036      template <typename T> struct O {1037        struct M {};1038      };1039      )";1040  auto t = makeDecls<VarDecl>(Code + R"(1041      typedef O<int>::M MT1;1042      MT1 A;1043      )",1044                              Code + R"(1045      namespace {1046        struct I {};1047      } // namespace1048      typedef O<I>::M MT2;1049      MT2 A;1050      )",1051                              Lang_CXX11, varDecl(hasName("A")));1052  EXPECT_FALSE(testStructuralMatch(t));1053}1054 1055TEST_F(StructuralEquivalenceTest, NamespaceOfRecordMember) {1056  auto Decls = makeNamedDecls(1057      R"(1058      class X;1059      class Y { X* x; };1060      )",1061      R"(1062      namespace N { class X; }1063      class Y { N::X* x; };1064      )",1065      Lang_CXX03, "Y");1066  EXPECT_FALSE(testStructuralMatch(Decls));1067}1068 1069TEST_F(StructuralEquivalenceTest, StructDefinitionInPrototype) {1070  auto Decls =1071      makeNamedDecls("struct Param { int a; }; void foo(struct Param *p);",1072                     "void foo(struct Param { int a; } *p);", Lang_C89);1073  EXPECT_TRUE(testStructuralMatch(Decls));1074}1075 1076TEST_F(StructuralEquivalenceTest, StructDefinitionInPrototypeDifferentName) {1077  auto Decls =1078      makeNamedDecls("struct Param1 { int a; }; void foo(struct Param1 *p);",1079                     "void foo(struct Param2 { int a; } *p);", Lang_C89);1080  EXPECT_FALSE(testStructuralMatch(Decls));1081}1082 1083TEST_F(StructuralEquivalenceRecordContextTest, RecordInsideFunction) {1084  auto Decls = makeNamedDecls("struct Param { int a; };",1085                              "void f() { struct Param { int a; }; }", Lang_C89,1086                              "Param");1087  EXPECT_TRUE(testStructuralMatch(Decls));1088}1089 1090struct StructuralEquivalenceEnumTest : StructuralEquivalenceTest {};1091 1092TEST_F(StructuralEquivalenceEnumTest, FwdDeclEnumShouldBeEqualWithFwdDeclEnum) {1093  auto t = makeNamedDecls("enum class foo;", "enum class foo;", Lang_CXX11);1094  EXPECT_TRUE(testStructuralMatch(t));1095}1096 1097TEST_F(StructuralEquivalenceEnumTest,1098       FwdDeclEnumShouldBeEqualWithEnumWhichHasDefinition) {1099  auto t =1100      makeNamedDecls("enum class foo;", "enum class foo { A };", Lang_CXX11);1101  EXPECT_TRUE(testStructuralMatch(t));1102}1103 1104TEST_F(StructuralEquivalenceEnumTest,1105       EnumShouldBeEqualWithEnumWhichHasDefinition) {1106  auto t = makeNamedDecls("enum class foo { A };", "enum class foo { A };",1107                          Lang_CXX11);1108  EXPECT_TRUE(testStructuralMatch(t));1109}1110 1111TEST_F(StructuralEquivalenceEnumTest, EnumsWithDifferentBody) {1112  auto t = makeNamedDecls("enum class foo { B };", "enum class foo { A };",1113                          Lang_CXX11);1114  EXPECT_FALSE(testStructuralMatch(t));1115}1116 1117TEST_F(StructuralEquivalenceEnumTest, AnonymousEnumsWithSameConsts) {1118  // field x is required to trigger comparison of the anonymous enum1119  auto t = makeNamedDecls("struct foo { enum { A } x; };",1120                          "struct foo { enum { A } x;};", Lang_CXX11);1121  EXPECT_TRUE(testStructuralMatch(t));1122}1123 1124TEST_F(StructuralEquivalenceEnumTest, AnonymousEnumsWithDiffConsts) {1125  // field x is required to trigger comparison of the anonymous enum1126  auto t = makeNamedDecls("struct foo { enum { A } x; };",1127                          "struct foo { enum { B } x;};", Lang_CXX11);1128  EXPECT_FALSE(testStructuralMatch(t));1129}1130 1131struct StructuralEquivalenceEnumConstantTest : StructuralEquivalenceTest {};1132 1133TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithSameValues) {1134  auto t = makeNamedDecls("enum foo { foo = 1 };", "enum foo { foo = 1 };",1135                          Lang_C89);1136  EXPECT_TRUE(testStructuralMatch(t));1137}1138 1139TEST_F(StructuralEquivalenceEnumConstantTest,1140       EnumConstantsWithDifferentValues) {1141  auto t =1142      makeNamedDecls("enum e { foo = 1 };", "enum e { foo = 2 };", Lang_C89);1143  EXPECT_FALSE(testStructuralMatch(t));1144}1145 1146TEST_F(StructuralEquivalenceEnumConstantTest,1147       EnumConstantsWithDifferentExprsButSameValues) {1148  auto t = makeNamedDecls("enum e { foo = 1 + 1 };", "enum e { foo = 2 };",1149                          Lang_CXX11);1150  EXPECT_FALSE(testStructuralMatch(t));1151}1152 1153TEST_F(StructuralEquivalenceEnumConstantTest,1154       EnumConstantsWithDifferentSignedness) {1155  auto t = makeNamedDecls("enum e : unsigned { foo = 1 };",1156                          "enum e : int { foo = 1 };", Lang_CXX11);1157  EXPECT_FALSE(testStructuralMatch(t));1158}1159 1160TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithDifferentWidth) {1161  auto t = makeNamedDecls("enum e : short { foo = 1 };",1162                          "enum e : int { foo = 1 };", Lang_CXX11);1163  EXPECT_FALSE(testStructuralMatch(t));1164}1165 1166TEST_F(StructuralEquivalenceEnumConstantTest, EnumConstantsWithDifferentName) {1167  auto t =1168      makeDecls<EnumConstantDecl>("enum e { foo = 1 };", "enum e { bar = 1 };",1169                                  Lang_CXX11, enumConstantDecl());1170  EXPECT_FALSE(testStructuralMatch(t));1171}1172 1173struct StructuralEquivalenceObjCCategoryTest : StructuralEquivalenceTest {};1174 1175TEST_F(StructuralEquivalenceObjCCategoryTest, MatchinCategoryNames) {1176  auto t = makeDecls<ObjCCategoryDecl>("@interface A @end @interface A(X) @end",1177                                       "@interface A @end @interface A(X) @end",1178                                       Lang_OBJC, objcCategoryDecl());1179  EXPECT_TRUE(testStructuralMatch(t));1180}1181 1182TEST_F(StructuralEquivalenceObjCCategoryTest, CategoriesForDifferentClasses) {1183  auto t = makeDecls<ObjCCategoryDecl>("@interface A @end @interface A(X) @end",1184                                       "@interface B @end @interface B(X) @end",1185                                       Lang_OBJC, objcCategoryDecl());1186  EXPECT_FALSE(testStructuralMatch(t));1187}1188 1189TEST_F(StructuralEquivalenceObjCCategoryTest, CategoriesWithDifferentNames) {1190  auto t = makeDecls<ObjCCategoryDecl>("@interface A @end @interface A(X) @end",1191                                       "@interface A @end @interface A(Y) @end",1192                                       Lang_OBJC, objcCategoryDecl());1193  EXPECT_FALSE(testStructuralMatch(t));1194}1195 1196TEST_F(StructuralEquivalenceObjCCategoryTest, CategoriesWithoutInterfaces) {1197  auto t = makeDecls<ObjCCategoryDecl>("                  @interface A(X) @end",1198                                       "@interface A @end @interface A(X) @end",1199                                       Lang_OBJC, objcCategoryDecl());1200  EXPECT_FALSE(testStructuralMatch(t));1201 1202  auto t2 = makeDecls<ObjCCategoryDecl>("@interface A(X) @end",1203                                        "@interface A(X) @end",1204                                        Lang_OBJC, objcCategoryDecl());1205  EXPECT_TRUE(testStructuralMatch(t2));1206}1207 1208TEST_F(StructuralEquivalenceObjCCategoryTest, CategoryAndExtension) {1209  auto t = makeDecls<ObjCCategoryDecl>("@interface A @end @interface A(X) @end",1210                                       "@interface A @end @interface A() @end",1211                                       Lang_OBJC, objcCategoryDecl());1212  EXPECT_FALSE(testStructuralMatch(t));1213}1214 1215TEST_F(StructuralEquivalenceObjCCategoryTest, MatchingProtocols) {1216  auto t = makeDecls<ObjCCategoryDecl>(1217      "@protocol P @end @interface A @end @interface A(X)<P> @end",1218      "@protocol P @end @interface A @end @interface A(X)<P> @end", Lang_OBJC,1219      objcCategoryDecl());1220  EXPECT_TRUE(testStructuralMatch(t));1221}1222 1223TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentProtocols) {1224  auto t = makeDecls<ObjCCategoryDecl>(1225      "@protocol P @end @interface A @end @interface A(X)<P> @end",1226      "@protocol Q @end @interface A @end @interface A(X)<Q> @end", Lang_OBJC,1227      objcCategoryDecl());1228  EXPECT_FALSE(testStructuralMatch(t));1229}1230 1231TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentProtocolsOrder) {1232  auto t = makeDecls<ObjCCategoryDecl>(1233      "@protocol P @end @protocol Q @end @interface A @end @interface A(X)<P, "1234      "Q> @end",1235      "@protocol P @end @protocol Q @end @interface A @end @interface A(X)<Q, "1236      "P> @end",1237      Lang_OBJC, objcCategoryDecl());1238  EXPECT_FALSE(testStructuralMatch(t));1239}1240 1241TEST_F(StructuralEquivalenceObjCCategoryTest, MatchingIvars) {1242  auto t = makeDecls<ObjCCategoryDecl>(1243      "@interface A @end @interface A() { int x; } @end",1244      "@interface A @end @interface A() { int x; } @end", Lang_OBJC,1245      objcCategoryDecl());1246  EXPECT_TRUE(testStructuralMatch(t));1247}1248 1249TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarName) {1250  auto t = makeDecls<ObjCCategoryDecl>(1251      "@interface A @end @interface A() { int x; } @end",1252      "@interface A @end @interface A() { int y; } @end", Lang_OBJC,1253      objcCategoryDecl());1254  EXPECT_FALSE(testStructuralMatch(t));1255}1256 1257TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarType) {1258  auto t = makeDecls<ObjCCategoryDecl>(1259      "@interface A @end @interface A() { int x; } @end",1260      "@interface A @end @interface A() { float x; } @end", Lang_OBJC,1261      objcCategoryDecl());1262  EXPECT_FALSE(testStructuralMatch(t));1263}1264 1265TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarBitfieldWidth) {1266  auto t = makeDecls<ObjCCategoryDecl>(1267      "@interface A @end @interface A() { int x: 1; } @end",1268      "@interface A @end @interface A() { int x: 2; } @end", Lang_OBJC,1269      objcCategoryDecl());1270  EXPECT_FALSE(testStructuralMatch(t));1271}1272 1273TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarVisibility) {1274  auto t = makeDecls<ObjCCategoryDecl>(1275      "@interface A @end @interface A() { @public int x; } @end",1276      "@interface A @end @interface A() { @protected int x; } @end", Lang_OBJC,1277      objcCategoryDecl());1278  EXPECT_FALSE(testStructuralMatch(t));1279}1280 1281TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarNumber) {1282  auto t = makeDecls<ObjCCategoryDecl>(1283      "@interface A @end @interface A() { int x; } @end",1284      "@interface A @end @interface A() {} @end", Lang_OBJC,1285      objcCategoryDecl());1286  EXPECT_FALSE(testStructuralMatch(t));1287}1288 1289TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentIvarOrder) {1290  auto t = makeDecls<ObjCCategoryDecl>(1291      "@interface A @end @interface A() { int x; int y; } @end",1292      "@interface A @end @interface A() { int y; int x; } @end", Lang_OBJC,1293      objcCategoryDecl());1294  EXPECT_FALSE(testStructuralMatch(t));1295}1296 1297TEST_F(StructuralEquivalenceObjCCategoryTest, MatchingMethods) {1298  auto t = makeDecls<ObjCCategoryDecl>(1299      "@interface A @end @interface A(X) -(void)test; @end",1300      "@interface A @end @interface A(X) -(void)test; @end", Lang_OBJC,1301      objcCategoryDecl());1302  EXPECT_TRUE(testStructuralMatch(t));1303}1304 1305TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodName) {1306  auto t = makeDecls<ObjCCategoryDecl>(1307      "@interface A @end @interface A(X) -(void)test; @end",1308      "@interface A @end @interface A(X) -(void)wasd; @end", Lang_OBJC,1309      objcCategoryDecl());1310  EXPECT_FALSE(testStructuralMatch(t));1311 1312  auto t2 = makeDecls<ObjCCategoryDecl>(1313      "@interface A @end @interface A(X) -(void)test:(int)x more:(int)y; @end",1314      "@interface A @end @interface A(X) -(void)test:(int)x :(int)y; @end",1315      Lang_OBJC, objcCategoryDecl());1316  EXPECT_FALSE(testStructuralMatch(t2));1317}1318 1319TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodClassInstance) {1320  auto t = makeDecls<ObjCCategoryDecl>(1321      "@interface A @end @interface A(X) -(void)test; @end",1322      "@interface A @end @interface A(X) +(void)test; @end", Lang_OBJC,1323      objcCategoryDecl());1324  EXPECT_FALSE(testStructuralMatch(t));1325}1326 1327TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodReturnType) {1328  auto t = makeDecls<ObjCCategoryDecl>(1329      "@interface A @end @interface A(X) -(void)test; @end",1330      "@interface A @end @interface A(X) -(int)test; @end", Lang_OBJC,1331      objcCategoryDecl());1332  EXPECT_FALSE(testStructuralMatch(t));1333}1334 1335TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodParameterType) {1336  auto t = makeDecls<ObjCCategoryDecl>(1337      "@interface A @end @interface A(X) -(void)test:(int)x; @end",1338      "@interface A @end @interface A(X) -(void)test:(float)x; @end", Lang_OBJC,1339      objcCategoryDecl());1340  EXPECT_FALSE(testStructuralMatch(t));1341}1342 1343TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodParameterName) {1344  auto t = makeDecls<ObjCCategoryDecl>(1345      "@interface A @end @interface A(X) -(void)test:(int)x; @end",1346      "@interface A @end @interface A(X) -(void)test:(int)y; @end", Lang_OBJC,1347      objcCategoryDecl());1348  EXPECT_TRUE(testStructuralMatch(t));1349}1350 1351TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodNumber) {1352  auto t = makeDecls<ObjCCategoryDecl>(1353      "@interface A @end @interface A(X) -(void)test; @end",1354      "@interface A @end @interface A(X) @end", Lang_OBJC, objcCategoryDecl());1355  EXPECT_FALSE(testStructuralMatch(t));1356}1357 1358TEST_F(StructuralEquivalenceObjCCategoryTest, DifferentMethodOrder) {1359  auto t = makeDecls<ObjCCategoryDecl>(1360      "@interface A @end @interface A(X) -(void)u; -(void)v; @end",1361      "@interface A @end @interface A(X) -(void)v; -(void)u; @end", Lang_OBJC,1362      objcCategoryDecl());1363  EXPECT_FALSE(testStructuralMatch(t));1364}1365 1366struct StructuralEquivalenceTemplateTest : StructuralEquivalenceTest {};1367 1368TEST_F(StructuralEquivalenceTemplateTest, ExactlySameTemplates) {1369  auto t = makeNamedDecls("template <class T> struct foo;",1370                          "template <class T> struct foo;", Lang_CXX03);1371  EXPECT_TRUE(testStructuralMatch(t));1372}1373 1374TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgName) {1375  auto t = makeNamedDecls("template <class T> struct foo;",1376                          "template <class U> struct foo;", Lang_CXX03);1377  EXPECT_TRUE(testStructuralMatch(t));1378}1379 1380TEST_F(StructuralEquivalenceTemplateTest, DifferentTemplateArgKind) {1381  auto t = makeNamedDecls("template <class T> struct foo;",1382                          "template <int T> struct foo;", Lang_CXX03);1383  EXPECT_FALSE(testStructuralMatch(t));1384}1385 1386TEST_F(StructuralEquivalenceTemplateTest, BitFieldDecl) {1387  const char *Code = "class foo { int a : 2; };";1388  auto t = makeNamedDecls(Code, Code, Lang_CXX03);1389  EXPECT_TRUE(testStructuralMatch(t));1390}1391 1392TEST_F(StructuralEquivalenceTemplateTest, BitFieldDeclDifferentWidth) {1393  auto t = makeNamedDecls("class foo { int a : 2; };",1394                          "class foo { int a : 4; };", Lang_CXX03);1395  EXPECT_FALSE(testStructuralMatch(t));1396}1397 1398TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDecl) {1399  const char *Code = "template <class T> class foo { int a : sizeof(T); };";1400  auto t = makeNamedDecls(Code, Code, Lang_CXX03);1401  EXPECT_TRUE(testStructuralMatch(t));1402}1403 1404TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDeclDifferentVal) {1405  auto t = makeNamedDecls(1406      "template <class A, class B> class foo { int a : sizeof(A); };",1407      "template <class A, class B> class foo { int a : sizeof(B); };",1408      Lang_CXX03);1409  EXPECT_FALSE(testStructuralMatch(t));1410}1411 1412TEST_F(StructuralEquivalenceTemplateTest, DependentBitFieldDeclDifferentVal2) {1413  auto t = makeNamedDecls(1414      "template <class A> class foo { int a : sizeof(A); };",1415      "template <class A> class foo { int a : sizeof(A) + 1; };", Lang_CXX03);1416  EXPECT_FALSE(testStructuralMatch(t));1417}1418 1419TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolSame) {1420  auto Decls = makeNamedDecls(1421      "template <bool b> struct foo {explicit(b) foo(int);};",1422      "template <bool b> struct foo {explicit(b) foo(int);};", Lang_CXX20);1423  CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(1424      get<0>(Decls), cxxConstructorDecl(hasName("foo<b>")));1425  CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(1426      get<1>(Decls), cxxConstructorDecl(hasName("foo<b>")));1427  EXPECT_TRUE(testStructuralMatch(First, Second));1428}1429 1430TEST_F(StructuralEquivalenceTemplateTest, ExplicitBoolDifference) {1431  auto Decls = makeNamedDecls(1432      "template <bool b> struct foo {explicit(b) foo(int);};",1433      "template <bool b> struct foo {explicit(!b) foo(int);};", Lang_CXX20);1434  CXXConstructorDecl *First = FirstDeclMatcher<CXXConstructorDecl>().match(1435      get<0>(Decls), cxxConstructorDecl(hasName("foo<b>")));1436  CXXConstructorDecl *Second = FirstDeclMatcher<CXXConstructorDecl>().match(1437      get<1>(Decls), cxxConstructorDecl(hasName("foo<b>")));1438  EXPECT_FALSE(testStructuralMatch(First, Second));1439}1440 1441TEST_F(StructuralEquivalenceTemplateTest,1442       TemplateVsSubstTemplateTemplateParmInArgEq) {1443  auto t = makeDecls<ClassTemplateSpecializationDecl>(1444      R"(1445template <typename P1> class Arg { };1446template <template <typename PP1> class P1> class Primary { };1447 1448void f() {1449  // Make specialization with simple template.1450  Primary <Arg> A;1451}1452      )",1453      R"(1454template <typename P1> class Arg { };1455template <template <typename PP1> class P1> class Primary { };1456 1457template <template <typename PP1> class P1> class Templ {1458  void f() {1459    // Make specialization with substituted template template param.1460    Primary <P1> A;1461  };1462};1463 1464// Instantiate with substitution Arg into P1.1465template class Templ <Arg>;1466      )",1467      Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));1468  EXPECT_TRUE(testStructuralMatch(t));1469}1470 1471TEST_F(StructuralEquivalenceTemplateTest,1472       TemplateVsSubstTemplateTemplateParmInArgNotEq) {1473  auto t = makeDecls<ClassTemplateSpecializationDecl>(1474      R"(1475template <typename P1> class Arg { };1476template <template <typename PP1> class P1> class Primary { };1477 1478void f() {1479  // Make specialization with simple template.1480  Primary <Arg> A;1481}1482      )",1483      R"(1484// Arg is different from the other, this should cause non-equivalence.1485template <typename P1> class Arg { int X; };1486template <template <typename PP1> class P1> class Primary { };1487 1488template <template <typename PP1> class P1> class Templ {1489  void f() {1490    // Make specialization with substituted template template param.1491    Primary <P1> A;1492  };1493};1494 1495// Instantiate with substitution Arg into P1.1496template class Templ <Arg>;1497      )",1498      Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));1499  EXPECT_FALSE(testStructuralMatch(t));1500}1501 1502struct StructuralEquivalenceDependentTemplateArgsTest1503    : StructuralEquivalenceTemplateTest {};1504 1505TEST_F(StructuralEquivalenceDependentTemplateArgsTest,1506       SameStructsInDependentArgs) {1507  std::string Code =1508      R"(1509      template <typename>1510      struct S1;1511 1512      template <typename>1513      struct enable_if;1514 1515      struct S1516      {1517        template <typename T, typename enable_if<S1<T>>::type>1518        void f();1519      };1520      )";1521  auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11,1522                                           functionTemplateDecl(hasName("f")));1523  EXPECT_TRUE(testStructuralMatch(t));1524}1525 1526TEST_F(StructuralEquivalenceDependentTemplateArgsTest,1527       DifferentStructsInDependentArgs) {1528  std::string Code =1529      R"(1530      template <typename>1531      struct S1;1532 1533      template <typename>1534      struct S2;1535 1536      template <typename>1537      struct enable_if;1538      )";1539  auto t = makeDecls<FunctionTemplateDecl>(Code + R"(1540      struct S1541      {1542        template <typename T, typename enable_if<S1<T>>::type>1543        void f();1544      };1545      )",1546                                           Code + R"(1547      struct S1548      {1549        template <typename T, typename enable_if<S2<T>>::type>1550        void f();1551      };1552      )",1553                                           Lang_CXX11,1554                                           functionTemplateDecl(hasName("f")));1555  EXPECT_FALSE(testStructuralMatch(t));1556}1557 1558TEST_F(StructuralEquivalenceDependentTemplateArgsTest,1559       SameStructsInDependentScopeDeclRefExpr) {1560  std::string Code =1561      R"(1562      template <typename>1563      struct S1;1564 1565      template <bool>1566      struct enable_if;1567 1568      struct S1569      {1570        template <typename T, typename enable_if<S1<T>::value>::type>1571        void f();   // DependentScopeDeclRefExpr:^^^^^^^^^^^^1572      };1573      )";1574  auto t = makeDecls<FunctionTemplateDecl>(Code, Code, Lang_CXX11,1575                                           functionTemplateDecl(hasName("f")));1576  EXPECT_TRUE(testStructuralMatch(t));1577}1578 1579TEST_F(StructuralEquivalenceDependentTemplateArgsTest,1580       DifferentStructsInDependentScopeDeclRefExpr) {1581  std::string Code =1582      R"(1583      template <typename>1584      struct S1;1585 1586      template <typename>1587      struct S2;1588 1589      template <bool>1590      struct enable_if;1591      )";1592  auto t = makeDecls<FunctionTemplateDecl>(Code + R"(1593      struct S1594      {1595        template <typename T, typename enable_if<S1<T>::value>::type>1596        void f();   // DependentScopeDeclRefExpr:^^^^^^^^^^^^1597      };1598      )",1599                                           Code + R"(1600      struct S1601      {1602        template <typename T, typename enable_if<S2<T>::value>::type>1603        void f();1604      };1605      )",1606                                           Lang_CXX03,1607                                           functionTemplateDecl(hasName("f")));1608  EXPECT_FALSE(testStructuralMatch(t));1609}1610 1611TEST_F(StructuralEquivalenceDependentTemplateArgsTest,1612       DifferentValueInDependentScopeDeclRefExpr) {1613  std::string Code =1614      R"(1615      template <typename>1616      struct S1;1617 1618      template <bool>1619      struct enable_if;1620      )";1621  auto t = makeDecls<FunctionTemplateDecl>(Code + R"(1622      struct S1623      {1624        template <typename T, typename enable_if<S1<T>::value1>::type>1625        void f();   // DependentScopeDeclRefExpr:^^^^^^^^^^^^1626      };1627      )",1628                                           Code + R"(1629      struct S1630      {1631        template <typename T, typename enable_if<S1<T>::value2>::type>1632        void f();1633      };1634      )",1635                                           Lang_CXX03,1636                                           functionTemplateDecl(hasName("f")));1637  EXPECT_FALSE(testStructuralMatch(t));1638}1639 1640TEST_F(1641    StructuralEquivalenceTemplateTest,1642    ClassTemplSpecWithQualifiedAndNonQualifiedTypeArgsShouldBeEqual) {1643  auto t = makeDecls<ClassTemplateSpecializationDecl>(1644      R"(1645      template <class T> struct Primary {};1646      namespace N {1647        struct Arg;1648      }1649      // Explicit instantiation with qualified name.1650      template struct Primary<N::Arg>;1651      )",1652      R"(1653      template <class T> struct Primary {};1654      namespace N {1655        struct Arg;1656      }1657      using namespace N;1658      // Explicit instantiation with UNqualified name.1659      template struct Primary<Arg>;1660      )",1661      Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));1662  EXPECT_TRUE(testStructuralMatch(t));1663}1664 1665TEST_F(1666    StructuralEquivalenceTemplateTest,1667    ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTypeArgs) {1668  auto t = makeDecls<ClassTemplateSpecializationDecl>(1669      R"(1670      template <class T> struct Primary {};1671      namespace N {1672        struct Arg { int a; };1673      }1674      // Explicit instantiation with qualified name.1675      template struct Primary<N::Arg>;1676      )",1677      R"(1678      template <class T> struct Primary {};1679      namespace N {1680        // This struct is not equivalent with the other in the prev TU.1681        struct Arg { double b; }; // -- Field mismatch.1682      }1683      using namespace N;1684      // Explicit instantiation with UNqualified name.1685      template struct Primary<Arg>;1686      )",1687      Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));1688  EXPECT_FALSE(testStructuralMatch(t));1689}1690 1691TEST_F(1692    StructuralEquivalenceTemplateTest,1693    ClassTemplSpecWithQualifiedAndNonQualifiedTemplArgsShouldBeEqual) {1694  auto t = makeDecls<ClassTemplateSpecializationDecl>(1695      R"(1696      template <template <class> class T> struct Primary {};1697      namespace N {1698        template <class T> struct Arg;1699      }1700      // Explicit instantiation with qualified name.1701      template struct Primary<N::Arg>;1702      )",1703      R"(1704      template <template <class> class T> struct Primary {};1705      namespace N {1706        template <class T> struct Arg;1707      }1708      using namespace N;1709      // Explicit instantiation with UNqualified name.1710      template struct Primary<Arg>;1711      )",1712      Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));1713  EXPECT_TRUE(testStructuralMatch(t));1714}1715 1716TEST_F(1717    StructuralEquivalenceTemplateTest,1718    ClassTemplSpecWithInequivalentQualifiedAndNonQualifiedTemplArgs) {1719  auto t = makeDecls<ClassTemplateSpecializationDecl>(1720      R"(1721      template <template <class> class T> struct Primary {};1722      namespace N {1723        template <class T> struct Arg { int a; };1724      }1725      // Explicit instantiation with qualified name.1726      template struct Primary<N::Arg>;1727      )",1728      R"(1729      template <template <class> class T> struct Primary {};1730      namespace N {1731        // This template is not equivalent with the other in the prev TU.1732        template <class T> struct Arg { double b; }; // -- Field mismatch.1733      }1734      using namespace N;1735      // Explicit instantiation with UNqualified name.1736      template struct Primary<Arg>;1737      )",1738      Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));1739  EXPECT_FALSE(testStructuralMatch(t));1740}1741 1742TEST_F(StructuralEquivalenceTemplateTest,1743       IgnoreTemplateParmDepthAtTemplateTypeParmDecl) {1744  auto Decls = makeDecls<ClassTemplateDecl>(1745      R"(1746        template<class> struct A;1747      )",1748      R"(1749        template<class> struct S {1750          template<class> friend struct A;1751        };1752      )",1753      Lang_CXX03, classTemplateDecl(hasName("A")),1754      classTemplateDecl(hasName("A")));1755  EXPECT_TRUE(testStructuralMatch(Decls));1756  EXPECT_TRUE(testStructuralMatch(Decls, true));1757}1758 1759TEST_F(StructuralEquivalenceTemplateTest,1760       IgnoreTemplateParmDepthAtNonTypeTemplateParmDecl) {1761  auto Decls = makeDecls<ClassTemplateDecl>(1762      R"(1763        template<class T, T U> struct A;1764      )",1765      R"(1766        template<class T> struct S {1767          template<class P, P Q> friend struct A;1768        };1769      )",1770      Lang_CXX03, classTemplateDecl(hasName("A")),1771      classTemplateDecl(hasName("A")));1772  EXPECT_FALSE(testStructuralMatch(Decls));1773  EXPECT_TRUE(testStructuralMatch(Decls, /*IgnoreTemplateParmDepth=*/true));1774}1775 1776TEST_F(1777    StructuralEquivalenceTemplateTest,1778    ClassTemplSpecWithInequivalentShadowedTemplArg) {1779  auto t = makeDecls<ClassTemplateSpecializationDecl>(1780      R"(1781      template <template <class> class T> struct Primary {};1782      template <class T> struct Arg { int a; };1783      // Explicit instantiation with ::Arg1784      template struct Primary<Arg>;1785      )",1786      R"(1787      template <template <class> class T> struct Primary {};1788      template <class T> struct Arg { int a; };1789      namespace N {1790        // This template is not equivalent with the other in the global scope.1791        template <class T> struct Arg { double b; }; // -- Field mismatch.1792        // Explicit instantiation with N::Arg which shadows ::Arg1793        template struct Primary<Arg>;1794      }1795      )",1796      Lang_CXX03, classTemplateSpecializationDecl(hasName("Primary")));1797  EXPECT_FALSE(testStructuralMatch(t));1798}1799struct StructuralEquivalenceCacheTest : public StructuralEquivalenceTest {1800  StructuralEquivalenceContext::NonEquivalentDeclSet NonEquivalentDecls;1801 1802  template <typename NodeType, typename MatcherType>1803  std::pair<NodeType *, NodeType *>1804  findDeclPair(std::tuple<TranslationUnitDecl *, TranslationUnitDecl *> TU,1805               MatcherType M) {1806    NodeType *D0 = FirstDeclMatcher<NodeType>().match(get<0>(TU), M);1807    NodeType *D1 = FirstDeclMatcher<NodeType>().match(get<1>(TU), M);1808    return {D0, D1};1809  }1810 1811  template <typename NodeType>1812  bool isInNonEqCache(std::pair<NodeType *, NodeType *> D,1813                      bool IgnoreTemplateParmDepth = false) {1814    return NonEquivalentDecls.count(1815               std::make_tuple(D.first, D.second, IgnoreTemplateParmDepth)) > 0;1816  }1817};1818 1819TEST_F(StructuralEquivalenceCacheTest, SimpleNonEq) {1820  auto TU = makeTuDecls(1821      R"(1822      class A {};1823      class B {};1824      void x(A, A);1825      )",1826      R"(1827      class A {};1828      class B {};1829      void x(A, B);1830      )",1831      Lang_CXX03);1832 1833  StructuralEquivalenceContext Ctx(1834      get<0>(TU)->getASTContext().getLangOpts(), get<0>(TU)->getASTContext(),1835      get<1>(TU)->getASTContext(), NonEquivalentDecls,1836      StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,1837      /*Complain=*/false);1838 1839  auto X = findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")));1840  EXPECT_FALSE(Ctx.IsEquivalent(X.first, X.second));1841 1842  EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(1843      TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));1844  EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(1845      TU, cxxRecordDecl(hasName("B"), unless(isImplicit())))));1846}1847 1848TEST_F(StructuralEquivalenceCacheTest, ReturnStmtNonEq) {1849  auto TU = makeTuDecls(1850      R"(1851      bool x() { return true; }1852      )",1853      R"(1854      bool x() { return false; }1855      )",1856      Lang_CXX03);1857 1858  StructuralEquivalenceContext Ctx(1859      get<0>(TU)->getASTContext().getLangOpts(), get<0>(TU)->getASTContext(),1860      get<1>(TU)->getASTContext(), NonEquivalentDecls,1861      StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,1862      /*Complain=*/false);1863 1864  auto X = findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")));1865  EXPECT_FALSE(Ctx.IsEquivalent(X.first->getBody(), X.second->getBody()));1866 1867}1868 1869TEST_F(StructuralEquivalenceCacheTest, VarDeclNoEq) {1870  auto TU = makeTuDecls(1871      R"(1872      int p;1873      )",1874      R"(1875      int q;1876      )",1877      Lang_CXX03);1878 1879  StructuralEquivalenceContext Ctx(1880      get<0>(TU)->getASTContext().getLangOpts(), get<0>(TU)->getASTContext(),1881      get<1>(TU)->getASTContext(), NonEquivalentDecls,1882      StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,1883      /*Complain=*/false);1884 1885  auto Var = findDeclPair<VarDecl>(TU, varDecl());1886  EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second));1887}1888 1889TEST_F(StructuralEquivalenceCacheTest, VarDeclWithDifferentStorageClassNoEq) {1890  auto TU = makeTuDecls(1891      R"(1892      int p;1893      )",1894      R"(1895      static int p;1896      )",1897      Lang_CXX03);1898 1899  StructuralEquivalenceContext Ctx(1900      get<0>(TU)->getASTContext().getLangOpts(), get<0>(TU)->getASTContext(),1901      get<1>(TU)->getASTContext(), NonEquivalentDecls,1902      StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,1903      /*Complain=*/false);1904 1905  auto Var = findDeclPair<VarDecl>(TU, varDecl());1906  EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second));1907}1908 1909TEST_F(StructuralEquivalenceCacheTest,1910       NonTypeTemplateParmWithDifferentPositionNoEq) {1911  auto TU = makeTuDecls(1912      R"(1913      template<int T>1914      struct A {1915        template<int U>1916        void foo() {}1917      };1918      )",1919      R"(1920      template<int U>1921      struct A {1922        template<int V, int T>1923        void foo() {}1924      };1925      )",1926      Lang_CXX03);1927 1928  StructuralEquivalenceContext Ctx(1929      get<0>(TU)->getASTContext().getLangOpts(), get<0>(TU)->getASTContext(),1930      get<1>(TU)->getASTContext(), NonEquivalentDecls,1931      StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,1932      /*Complain=*/false);1933 1934  auto NTTP = findDeclPair<NonTypeTemplateParmDecl>(1935      TU, nonTypeTemplateParmDecl(hasName("T")));1936  EXPECT_FALSE(Ctx.IsEquivalent(NTTP.first, NTTP.second));1937}1938 1939TEST_F(StructuralEquivalenceCacheTest, VarDeclWithInitNoEq) {1940  auto TU = makeTuDecls(1941      R"(1942      int p = 1;1943      )",1944      R"(1945      int p = 2;1946      )",1947      Lang_CXX03);1948 1949  StructuralEquivalenceContext Ctx(1950      get<0>(TU)->getASTContext().getLangOpts(), get<0>(TU)->getASTContext(),1951      get<1>(TU)->getASTContext(), NonEquivalentDecls,1952      StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,1953      /*Complain=*/false);1954 1955  auto Var = findDeclPair<VarDecl>(TU, varDecl());1956  EXPECT_FALSE(Ctx.IsEquivalent(Var.first, Var.second));1957}1958 1959TEST_F(StructuralEquivalenceCacheTest, SpecialNonEq) {1960  auto TU = makeTuDecls(1961      R"(1962      class A {};1963      class B { int i; };1964      void x(A *);1965      void y(A *);1966      class C {1967        friend void x(A *);1968        friend void y(A *);1969      };1970      )",1971      R"(1972      class A {};1973      class B { int i; };1974      void x(A *);1975      void y(B *);1976      class C {1977        friend void x(A *);1978        friend void y(B *);1979      };1980      )",1981      Lang_CXX03);1982 1983  StructuralEquivalenceContext Ctx(1984      get<0>(TU)->getASTContext().getLangOpts(), get<0>(TU)->getASTContext(),1985      get<1>(TU)->getASTContext(), NonEquivalentDecls,1986      StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,1987      /*Complain=*/false);1988 1989  auto C = findDeclPair<CXXRecordDecl>(1990      TU, cxxRecordDecl(hasName("C"), unless(isImplicit())));1991  EXPECT_FALSE(Ctx.IsEquivalent(C.first, C.second));1992 1993  EXPECT_FALSE(isInNonEqCache(C));1994  EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(1995      TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));1996  EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(1997      TU, cxxRecordDecl(hasName("B"), unless(isImplicit())))));1998  EXPECT_FALSE(isInNonEqCache(1999      findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")))));2000  EXPECT_FALSE(isInNonEqCache(2001      findDeclPair<FunctionDecl>(TU, functionDecl(hasName("y")))));2002}2003 2004TEST_F(StructuralEquivalenceCacheTest, Cycle) {2005  auto TU = makeTuDecls(2006      R"(2007      class C;2008      class A { C *c; };2009      void x(A *);2010      class C {2011        friend void x(A *);2012      };2013      )",2014      R"(2015      class C;2016      class A { C *c; };2017      void x(A *);2018      class C {2019        friend void x(A *);2020      };2021      )",2022      Lang_CXX03);2023 2024  StructuralEquivalenceContext Ctx(2025      get<0>(TU)->getASTContext().getLangOpts(), get<0>(TU)->getASTContext(),2026      get<1>(TU)->getASTContext(), NonEquivalentDecls,2027      StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,2028      /*Complain=*/false);2029 2030  auto C = findDeclPair<CXXRecordDecl>(2031      TU, cxxRecordDecl(hasName("C"), unless(isImplicit())));2032  EXPECT_TRUE(Ctx.IsEquivalent(C.first, C.second));2033 2034  EXPECT_FALSE(isInNonEqCache(C));2035  EXPECT_FALSE(isInNonEqCache(findDeclPair<CXXRecordDecl>(2036      TU, cxxRecordDecl(hasName("A"), unless(isImplicit())))));2037  EXPECT_FALSE(isInNonEqCache(2038      findDeclPair<FunctionDecl>(TU, functionDecl(hasName("x")))));2039}2040 2041TEST_F(StructuralEquivalenceCacheTest, TemplateParmDepth) {2042  // In 'friend struct Y' ClassTemplateDecl has the TU as parent context.2043  // This declaration has template depth 1 (it is already inside a template).2044  // It has not a previous declaration and is an "undeclared" friend.2045  //2046  // Second TU has a specialization of 'struct X'.2047  // In this case 'friend struct Y' has the ClassTemplateSpecializationDecl as2048  // parent. It has template depth 0 (it is in the specialization). It has the2049  // first 'struct Y' declaration as previous declaration and canonical2050  // declaration.2051  //2052  // When these two 'friend struct Y' are compared, only the template depth is2053  // different.2054  // FIXME: Structural equivalence checks the depth only in types, not in2055  // TemplateParmDecl. For this reason the second 'A1' argument is needed (as a2056  // type) in the template to make the check fail.2057  auto TU = makeTuDecls(2058      R"(2059      template <class A1, A1>2060      struct Y;2061 2062      template <class A>2063      struct X {2064        template <class A1, A1>2065        friend struct Y;2066      };2067      )",2068      R"(2069      template <class A1, A1>2070      struct Y;2071 2072      template <class A>2073      struct X {2074        template <class A1, A1>2075        friend struct Y;2076      };2077 2078      X<int> x;2079      )",2080      Lang_CXX03);2081 2082  auto *D0 = LastDeclMatcher<ClassTemplateDecl>().match(2083      get<0>(TU), classTemplateDecl(hasName("Y"), unless(isImplicit())));2084  auto *D1 = LastDeclMatcher<ClassTemplateDecl>().match(2085      get<1>(TU), classTemplateDecl(hasName("Y"), unless(isImplicit())));2086  ASSERT_EQ(D0->getTemplateDepth(), 1u);2087  ASSERT_EQ(D1->getTemplateDepth(), 0u);2088 2089  StructuralEquivalenceContext Ctx_NoIgnoreTemplateParmDepth(2090      get<0>(TU)->getASTContext().getLangOpts(), get<0>(TU)->getASTContext(),2091      get<1>(TU)->getASTContext(), NonEquivalentDecls,2092      StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,2093      /*Complain=*/false, /*ErrorOnTagTypeMismatch=*/false,2094      /*IgnoreTemplateParmDepth=*/false);2095 2096  EXPECT_FALSE(Ctx_NoIgnoreTemplateParmDepth.IsEquivalent(D0, D1));2097 2098  Decl *NonEqDecl0 =2099      D0->getCanonicalDecl()->getTemplateParameters()->getParam(1);2100  Decl *NonEqDecl1 =2101      D1->getCanonicalDecl()->getTemplateParameters()->getParam(1);2102  EXPECT_TRUE(isInNonEqCache(std::make_pair(NonEqDecl0, NonEqDecl1), false));2103  EXPECT_FALSE(isInNonEqCache(std::make_pair(NonEqDecl0, NonEqDecl1), true));2104 2105  StructuralEquivalenceContext Ctx_IgnoreTemplateParmDepth(2106      get<0>(TU)->getASTContext().getLangOpts(), get<0>(TU)->getASTContext(),2107      get<1>(TU)->getASTContext(), NonEquivalentDecls,2108      StructuralEquivalenceKind::Default, /*StrictTypeSpelling=*/false,2109      /*Complain=*/false, /*ErrorOnTagTypeMismatch=*/false,2110      /*IgnoreTemplateParmDepth=*/true);2111 2112  EXPECT_TRUE(Ctx_IgnoreTemplateParmDepth.IsEquivalent(D0, D1));2113 2114  EXPECT_FALSE(isInNonEqCache(std::make_pair(NonEqDecl0, NonEqDecl1), true));2115}2116 2117struct StructuralEquivalenceStmtTest : StructuralEquivalenceTest {};2118 2119/// Fallback matcher to be used only when there is no specific matcher for a2120/// Expr subclass. Remove this once all Expr subclasses have their own matcher.2121static auto &fallbackExprMatcher = expr;2122 2123TEST_F(StructuralEquivalenceStmtTest, AddrLabelExpr) {2124  auto t = makeWrappedStmts("lbl: &&lbl;", "lbl: &&lbl;", Lang_CXX03,2125                            addrLabelExpr());2126  EXPECT_TRUE(testStructuralMatch(t));2127}2128 2129TEST_F(StructuralEquivalenceStmtTest, AddrLabelExprDifferentLabel) {2130  auto t = makeWrappedStmts("lbl1: lbl2: &&lbl1;", "lbl1: lbl2: &&lbl2;",2131                            Lang_CXX03, addrLabelExpr());2132  // FIXME: Should be false. LabelDecl are incorrectly matched.2133  EXPECT_TRUE(testStructuralMatch(t));2134}2135 2136static const std::string MemoryOrderSrc = R"(2137enum memory_order {2138  memory_order_relaxed,2139  memory_order_consume,2140  memory_order_acquire,2141  memory_order_release,2142  memory_order_acq_rel,2143  memory_order_seq_cst2144};2145)";2146 2147TEST_F(StructuralEquivalenceStmtTest, AtomicExpr) {2148  std::string Prefix = "char a, b; " + MemoryOrderSrc;2149  auto t = makeStmts(2150      Prefix +2151          "void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }",2152      Prefix +2153          "void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }",2154      Lang_CXX03, atomicExpr());2155  EXPECT_TRUE(testStructuralMatch(t));2156}2157 2158TEST_F(StructuralEquivalenceStmtTest, AtomicExprDifferentOp) {2159  std::string Prefix = "char a, b; " + MemoryOrderSrc;2160  auto t = makeStmts(2161      Prefix +2162          "void wrapped() { __atomic_load(&a, &b, memory_order_seq_cst); }",2163      Prefix +2164          "void wrapped() { __atomic_store(&a, &b, memory_order_seq_cst); }",2165      Lang_CXX03, atomicExpr());2166  EXPECT_FALSE(testStructuralMatch(t));2167}2168 2169TEST_F(StructuralEquivalenceStmtTest, BinaryOperator) {2170  auto t = makeWrappedStmts("1 + 1", "1 + 1", Lang_CXX03, binaryOperator());2171  EXPECT_TRUE(testStructuralMatch(t));2172}2173 2174TEST_F(StructuralEquivalenceStmtTest, BinaryOperatorDifferentOps) {2175  auto t = makeWrappedStmts("1 + 1", "1 - 1", Lang_CXX03, binaryOperator());2176  EXPECT_FALSE(testStructuralMatch(t));2177}2178 2179TEST_F(StructuralEquivalenceStmtTest, CallExpr) {2180  std::string Src = "int call(); int wrapped() { call(); }";2181  auto t = makeStmts(Src, Src, Lang_CXX03, callExpr());2182  EXPECT_TRUE(testStructuralMatch(t));2183}2184 2185TEST_F(StructuralEquivalenceStmtTest, CallExprDifferentCallee) {2186  std::string FunctionSrc = "int func1(); int func2();\n";2187  auto t = makeStmts(FunctionSrc + "void wrapper() { func1(); }",2188                     FunctionSrc + "void wrapper() { func2(); }", Lang_CXX03,2189                     callExpr());2190  EXPECT_FALSE(testStructuralMatch(t));2191}2192 2193TEST_F(StructuralEquivalenceStmtTest, CharacterLiteral) {2194  auto t = makeWrappedStmts("'a'", "'a'", Lang_CXX03, characterLiteral());2195  EXPECT_TRUE(testStructuralMatch(t));2196}2197 2198TEST_F(StructuralEquivalenceStmtTest, CharacterLiteralDifferentValues) {2199  auto t = makeWrappedStmts("'a'", "'b'", Lang_CXX03, characterLiteral());2200  EXPECT_FALSE(testStructuralMatch(t));2201}2202 2203TEST_F(StructuralEquivalenceStmtTest, ExpressionTraitExpr) {2204  auto t = makeWrappedStmts("__is_lvalue_expr(1)", "__is_lvalue_expr(1)",2205                            Lang_CXX03, fallbackExprMatcher());2206  EXPECT_TRUE(testStructuralMatch(t));2207}2208 2209TEST_F(StructuralEquivalenceStmtTest, ExpressionTraitExprDifferentKind) {2210  auto t = makeWrappedStmts("__is_lvalue_expr(1)", "__is_rvalue_expr(1)",2211                            Lang_CXX03, fallbackExprMatcher());2212  EXPECT_FALSE(testStructuralMatch(t));2213}2214 2215TEST_F(StructuralEquivalenceStmtTest, FloatingLiteral) {2216  auto t = makeWrappedStmts("1.0", "1.0", Lang_CXX03, fallbackExprMatcher());2217  EXPECT_TRUE(testStructuralMatch(t));2218}2219 2220TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentSpelling) {2221  auto t = makeWrappedStmts("0x10.1p0", "16.0625", Lang_CXX17,2222                            fallbackExprMatcher());2223  // Same value but with different spelling is equivalent.2224  EXPECT_TRUE(testStructuralMatch(t));2225}2226 2227TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentType) {2228  auto t = makeWrappedStmts("1.0", "1.0f", Lang_CXX03, fallbackExprMatcher());2229  EXPECT_FALSE(testStructuralMatch(t));2230}2231 2232TEST_F(StructuralEquivalenceStmtTest, FloatingLiteralDifferentValue) {2233  auto t = makeWrappedStmts("1.01", "1.0", Lang_CXX03, fallbackExprMatcher());2234  EXPECT_FALSE(testStructuralMatch(t));2235}2236 2237TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprSame) {2238  auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)",2239                            "_Generic(0u, unsigned int: 0, float: 1)", Lang_C99,2240                            genericSelectionExpr());2241  EXPECT_TRUE(testStructuralMatch(t));2242}2243 2244TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprSignsDiffer) {2245  auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)",2246                            "_Generic(0, int: 0, float: 1)", Lang_C99,2247                            genericSelectionExpr());2248  EXPECT_FALSE(testStructuralMatch(t));2249}2250 2251TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprOrderDiffers) {2252  auto t = makeWrappedStmts("_Generic(0u, unsigned int: 0, float: 1)",2253                            "_Generic(0u, float: 1, unsigned int: 0)", Lang_C99,2254                            genericSelectionExpr());2255  EXPECT_FALSE(testStructuralMatch(t));2256}2257 2258TEST_F(StructuralEquivalenceStmtTest, GenericSelectionExprDependentResultSame) {2259  auto t = makeStmts(2260      R"(2261      template <typename T>2262      void f() {2263        T x;2264        (void)_Generic(x, int: 0, float: 1);2265      }2266      void g() { f<int>(); }2267      )",2268      R"(2269      template <typename T>2270      void f() {2271        T x;2272        (void)_Generic(x, int: 0, float: 1);2273      }2274      void g() { f<int>(); }2275      )",2276      Lang_CXX03, genericSelectionExpr());2277  EXPECT_TRUE(testStructuralMatch(t));2278}2279 2280TEST_F(StructuralEquivalenceStmtTest,2281       GenericSelectionExprDependentResultOrderDiffers) {2282  auto t = makeStmts(2283      R"(2284      template <typename T>2285      void f() {2286        T x;2287        (void)_Generic(x, float: 1, int: 0);2288      }2289      void g() { f<int>(); }2290      )",2291      R"(2292      template <typename T>2293      void f() {2294        T x;2295        (void)_Generic(x, int: 0, float: 1);2296      }2297      void g() { f<int>(); }2298      )",2299      Lang_CXX03, genericSelectionExpr());2300 2301  EXPECT_FALSE(testStructuralMatch(t));2302}2303TEST_F(StructuralEquivalenceStmtTest, IntegerLiteral) {2304  auto t = makeWrappedStmts("1", "1", Lang_CXX03, integerLiteral());2305  EXPECT_TRUE(testStructuralMatch(t));2306}2307 2308TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentSpelling) {2309  auto t = makeWrappedStmts("1", "0x1", Lang_CXX03, integerLiteral());2310  // Same value but with different spelling is equivalent.2311  EXPECT_TRUE(testStructuralMatch(t));2312}2313 2314TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentValue) {2315  auto t = makeWrappedStmts("1", "2", Lang_CXX03, integerLiteral());2316  EXPECT_FALSE(testStructuralMatch(t));2317}2318 2319TEST_F(StructuralEquivalenceStmtTest, IntegerLiteralDifferentTypes) {2320  auto t = makeWrappedStmts("1", "1L", Lang_CXX03, integerLiteral());2321  EXPECT_FALSE(testStructuralMatch(t));2322}2323 2324TEST_F(StructuralEquivalenceStmtTest, MemberExpr) {2325  std::string ClassSrc = "struct C { int a; int b; };";2326  auto t = makeStmts(ClassSrc + "int wrapper() { C c; return c.a; }",2327                     ClassSrc + "int wrapper() { C c; return c.a; }",2328                     Lang_CXX03, memberExpr());2329  EXPECT_TRUE(testStructuralMatch(t));2330}2331 2332TEST_F(StructuralEquivalenceStmtTest, MemberExprDifferentMember) {2333  std::string ClassSrc = "struct C { int a; int b; };";2334  auto t = makeStmts(ClassSrc + "int wrapper() { C c; return c.a; }",2335                     ClassSrc + "int wrapper() { C c; return c.b; }",2336                     Lang_CXX03, memberExpr());2337  EXPECT_FALSE(testStructuralMatch(t));2338}2339 2340TEST_F(StructuralEquivalenceStmtTest, ObjCStringLiteral) {2341  auto t =2342      makeWrappedStmts("@\"a\"", "@\"a\"", Lang_OBJCXX, fallbackExprMatcher());2343  EXPECT_TRUE(testStructuralMatch(t));2344}2345 2346TEST_F(StructuralEquivalenceStmtTest, ObjCStringLiteralDifferentContent) {2347  auto t =2348      makeWrappedStmts("@\"a\"", "@\"b\"", Lang_OBJCXX, fallbackExprMatcher());2349  EXPECT_FALSE(testStructuralMatch(t));2350}2351 2352TEST_F(StructuralEquivalenceStmtTest, StringLiteral) {2353  auto t = makeWrappedStmts("\"a\"", "\"a\"", Lang_CXX03, stringLiteral());2354  EXPECT_TRUE(testStructuralMatch(t));2355}2356 2357TEST_F(StructuralEquivalenceStmtTest, StringLiteralDifferentContent) {2358  auto t = makeWrappedStmts("\"a\"", "\"b\"", Lang_CXX03, stringLiteral());2359  EXPECT_FALSE(testStructuralMatch(t));2360}2361 2362TEST_F(StructuralEquivalenceStmtTest, StringLiteralDifferentLength) {2363  auto t = makeWrappedStmts("\"a\"", "\"aa\"", Lang_CXX03, stringLiteral());2364  EXPECT_FALSE(testStructuralMatch(t));2365}2366 2367TEST_F(StructuralEquivalenceStmtTest, TypeTraitExpr) {2368  auto t = makeWrappedStmts("__is_pod(int)", "__is_pod(int)", Lang_CXX03,2369                            fallbackExprMatcher());2370  EXPECT_TRUE(testStructuralMatch(t));2371}2372 2373TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentType) {2374  auto t = makeWrappedStmts("__is_pod(int)", "__is_pod(long)", Lang_CXX03,2375                            fallbackExprMatcher());2376  EXPECT_FALSE(testStructuralMatch(t));2377}2378 2379TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentTrait) {2380  auto t = makeWrappedStmts(2381      "__is_pod(int)", "__is_trivially_constructible(int)", Lang_CXX03, expr());2382  EXPECT_FALSE(testStructuralMatch(t));2383}2384 2385TEST_F(StructuralEquivalenceStmtTest, TypeTraitExprDifferentTraits) {2386  auto t = makeWrappedStmts("__is_constructible(int)",2387                            "__is_constructible(int, int)", Lang_CXX03, expr());2388  EXPECT_FALSE(testStructuralMatch(t));2389}2390 2391TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExpr) {2392  auto t = makeWrappedStmts("sizeof(int)", "sizeof(int)", Lang_CXX03,2393                            unaryExprOrTypeTraitExpr());2394  EXPECT_TRUE(testStructuralMatch(t));2395}2396 2397TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExprDifferentKind) {2398  auto t = makeWrappedStmts("sizeof(int)", "alignof(long)", Lang_CXX11,2399                            unaryExprOrTypeTraitExpr());2400  EXPECT_FALSE(testStructuralMatch(t));2401}2402 2403TEST_F(StructuralEquivalenceStmtTest, UnaryExprOrTypeTraitExprDifferentType) {2404  auto t = makeWrappedStmts("sizeof(int)", "sizeof(long)", Lang_CXX03,2405                            unaryExprOrTypeTraitExpr());2406  EXPECT_FALSE(testStructuralMatch(t));2407}2408 2409TEST_F(StructuralEquivalenceStmtTest, UnaryOperator) {2410  auto t = makeWrappedStmts("+1", "+1", Lang_CXX03, unaryOperator());2411  EXPECT_TRUE(testStructuralMatch(t));2412}2413 2414TEST_F(StructuralEquivalenceStmtTest, UnaryOperatorDifferentOps) {2415  auto t = makeWrappedStmts("+1", "-1", Lang_CXX03, unaryOperator());2416  EXPECT_FALSE(testStructuralMatch(t));2417}2418 2419TEST_F(StructuralEquivalenceStmtTest,2420       CXXOperatorCallExprVsUnaryBinaryOperator) {2421  auto t = makeNamedDecls(2422      R"(2423      template <typename T, T x>2424      class A;2425      template <typename T, T x, T y>2426      void foo(2427        A<T, x + y>,2428        A<T, x - y>,2429        A<T, -x>,2430        A<T, x * y>,2431        A<T, *x>,2432        A<T, x / y>,2433        A<T, x % y>,2434        A<T, x ^ y>,2435        A<T, x & y>,2436        A<T, &x>,2437        A<T, x | y>,2438        A<T, ~x>,2439        A<T, !x>,2440        A<T, x < y>,2441        A<T, (x > y)>,2442        A<T, x << y>,2443        A<T, (x >> y)>,2444        A<T, x == y>,2445        A<T, x != y>,2446        A<T, x <= y>,2447        A<T, x >= y>,2448        A<T, x <=> y>,2449        A<T, x && y>,2450        A<T, x || y>,2451        A<T, ++x>,2452        A<T, --x>,2453        A<T, (x , y)>,2454        A<T, x ->* y>,2455        A<T, x -> y>2456      );2457      )",2458      R"(2459      struct Bar {2460        Bar& operator=(Bar&);2461        Bar& operator->();2462      };2463 2464      Bar& operator+(Bar&, Bar&);2465      Bar& operator+(Bar&);2466      Bar& operator-(Bar&, Bar&);2467      Bar& operator-(Bar&);2468      Bar& operator*(Bar&, Bar&);2469      Bar& operator*(Bar&);2470      Bar& operator/(Bar&, Bar&);2471      Bar& operator%(Bar&, Bar&);2472      Bar& operator^(Bar&, Bar&);2473      Bar& operator&(Bar&, Bar&);2474      Bar& operator&(Bar&);2475      Bar& operator|(Bar&, Bar&);2476      Bar& operator~(Bar&);2477      Bar& operator!(Bar&);2478      Bar& operator<(Bar&, Bar&);2479      Bar& operator>(Bar&, Bar&);2480      Bar& operator+=(Bar&, Bar&);2481      Bar& operator-=(Bar&, Bar&);2482      Bar& operator*=(Bar&, Bar&);2483      Bar& operator/=(Bar&, Bar&);2484      Bar& operator%=(Bar&, Bar&);2485      Bar& operator^=(Bar&, Bar&);2486      Bar& operator&=(Bar&, Bar&);2487      Bar& operator|=(Bar&, Bar&);2488      Bar& operator<<(Bar&, Bar&);2489      Bar& operator>>(Bar&, Bar&);2490      Bar& operator<<=(Bar&, Bar&);2491      Bar& operator>>=(Bar&, Bar&);2492      Bar& operator==(Bar&, Bar&);2493      Bar& operator!=(Bar&, Bar&);2494      Bar& operator<=(Bar&, Bar&);2495      Bar& operator>=(Bar&, Bar&);2496      Bar& operator<=>(Bar&, Bar&);2497      Bar& operator&&(Bar&, Bar&);2498      Bar& operator||(Bar&, Bar&);2499      Bar& operator++(Bar&);2500      Bar& operator--(Bar&);2501      Bar& operator,(Bar&, Bar&);2502      Bar& operator->*(Bar&, Bar&);2503 2504      template <typename T, T x>2505      class A;2506      template <typename T, T x, T y>2507      void foo(2508        A<T, x + y>,2509        A<T, x - y>,2510        A<T, -x>,2511        A<T, x * y>,2512        A<T, *x>,2513        A<T, x / y>,2514        A<T, x % y>,2515        A<T, x ^ y>,2516        A<T, x & y>,2517        A<T, &x>,2518        A<T, x | y>,2519        A<T, ~x>,2520        A<T, !x>,2521        A<T, x < y>,2522        A<T, (x > y)>,2523        A<T, x << y>,2524        A<T, (x >> y)>,2525        A<T, x == y>,2526        A<T, x != y>,2527        A<T, x <= y>,2528        A<T, x >= y>,2529        A<T, x <=> y>,2530        A<T, x && y>,2531        A<T, x || y>,2532        A<T, ++x>,2533        A<T, --x>,2534        A<T, (x , y)>,2535        A<T, x ->* y>,2536        A<T, x -> y>2537      );2538      )",2539      Lang_CXX20);2540  EXPECT_TRUE(testStructuralMatch(t));2541}2542 2543TEST_F(StructuralEquivalenceStmtTest,2544       CXXOperatorCallExprVsUnaryBinaryOperatorNe) {2545  auto t = makeNamedDecls(2546      R"(2547      template <typename T, T x>2548      class A;2549      template <typename T, T x, T y>2550      void foo(2551        A<T, x + y>2552      );2553      )",2554      R"(2555      struct Bar;2556 2557      Bar& operator-(Bar&, Bar&);2558 2559      template <typename T, T x>2560      class A;2561      template <typename T, T x, T y>2562      void foo(2563        A<T, x - y>2564      );2565      )",2566      Lang_CXX11);2567  EXPECT_FALSE(testStructuralMatch(t));2568}2569 2570TEST_F(StructuralEquivalenceStmtTest, NonTypeTemplateParm) {2571  auto t = makeNamedDecls(2572      R"(2573      template <typename T, T x>2574      class A;2575      template <typename T, T x, T y>2576      void foo(A<T, x>);2577      )",2578      R"(2579      template <typename T, T x>2580      class A;2581      template <typename T, T x, T y>2582      void foo(A<T, y>);2583      )",2584      Lang_CXX11);2585  EXPECT_FALSE(testStructuralMatch(t));2586}2587 2588TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookupDifferentName) {2589  auto t = makeStmts(2590      R"(2591      void f1(int);2592      template <typename T>2593      void f(T t) {2594        f1(t);2595      }2596      void g() { f<int>(1); }2597      )",2598      R"(2599      void f2(int);2600      template <typename T>2601      void f(T t) {2602        f2(t);2603      }2604      void g() { f<int>(1); }2605      )",2606      Lang_CXX03, unresolvedLookupExpr());2607  EXPECT_FALSE(testStructuralMatch(t));2608}2609 2610TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookupDifferentQualifier) {2611  auto t = makeStmts(2612      R"(2613      struct X {2614        static void g(int);2615        static void g(char);2616      };2617 2618      template <typename T>2619      void f(T t) {2620        X::g(t);2621      }2622 2623      void g() { f<int>(1); }2624      )",2625      R"(2626      struct Y {2627        static void g(int);2628        static void g(char);2629      };2630 2631      template <typename T>2632      void f(T t) {2633        Y::g(t);2634      }2635 2636      void g() { f<int>(1); }2637      )",2638      Lang_CXX03, unresolvedLookupExpr());2639  EXPECT_FALSE(testStructuralMatch(t));2640}2641 2642TEST_F(StructuralEquivalenceStmtTest,2643       UnresolvedLookupDifferentTemplateArgument) {2644  auto t = makeStmts(2645      R"(2646      struct A {};2647      template<typename T1, typename T2>2648      void g() {}2649 2650      template <typename T>2651      void f() {2652        g<A, T>();2653      }2654 2655      void h() { f<int>(); }2656      )",2657      R"(2658      struct B {};2659      template<typename T1, typename T2>2660      void g() {}2661 2662      template <typename T>2663      void f() {2664        g<B, T>();2665      }2666 2667      void h() { f<int>(); }2668      )",2669      Lang_CXX03, unresolvedLookupExpr());2670  EXPECT_FALSE(testStructuralMatch(t));2671}2672 2673TEST_F(StructuralEquivalenceStmtTest, UnresolvedLookup) {2674  auto t = makeStmts(2675      R"(2676      struct A {};2677      struct B {2678        template<typename T1, typename T2>2679        static void g(int) {};2680        template<typename T1, typename T2>2681        static void g(char) {};2682      };2683 2684      template <typename T1, typename T2>2685      void f(T2 x) {2686        B::g<A, T1>(x);2687      }2688 2689      void g() { f<char, int>(1); }2690      )",2691      R"(2692      struct A {};2693      struct B {2694        template<typename T1, typename T2>2695        static void g(int) {};2696        template<typename T1, typename T2>2697        static void g(char) {};2698      };2699 2700      template <typename T1, typename T2>2701      void f(T2 x) {2702        B::g<A, T1>(x);2703      }2704 2705      void g() { f<char, int>(1); }2706      )",2707      Lang_CXX03, unresolvedLookupExpr());2708  EXPECT_TRUE(testStructuralMatch(t));2709}2710 2711TEST_F(StructuralEquivalenceCacheTest, GotoStmtNoEq) {2712  auto S = makeStmts(2713      R"(2714      void foo() {2715        goto L1;2716        L1: foo();2717      }2718      )",2719      R"(2720      void foo() {2721        goto L2;2722        L2: foo();2723      }2724      )",2725      Lang_CXX03, gotoStmt());2726  EXPECT_FALSE(testStructuralMatch(S));2727}2728 2729TEST_F(StructuralEquivalenceStmtTest, DeclRefExpr) {2730  std::string Prefix = "enum Test { AAA, BBB };";2731  auto t = makeStmts(2732      Prefix + "void foo(int i) {if (i > 0) {i = AAA;} else {i = BBB;}}",2733      Prefix + "void foo(int i) {if (i > 0) {i = BBB;} else {i = AAA;}}",2734      Lang_CXX03, ifStmt());2735  EXPECT_FALSE(testStructuralMatch(t));2736}2737 2738TEST_F(StructuralEquivalenceCacheTest, CXXDependentScopeMemberExprNoEq) {2739  auto S = makeStmts(2740      R"(2741      template <class T>2742      void foo() {2743        (void)T().x;2744      }2745      struct A { int x; };2746      void bar() {2747        foo<A>();2748      }2749      )",2750      R"(2751      template <class T>2752      void foo() {2753        (void)T().y;2754      }2755      struct A { int y; };2756      void bar() {2757        foo<A>();2758      }2759      )",2760      Lang_CXX11, cxxDependentScopeMemberExpr());2761  EXPECT_FALSE(testStructuralMatch(S));2762}2763 2764} // end namespace ast_matchers2765} // end namespace clang2766