This is breaking build bots, and I am trying to fix it. Feel free to revert the change if this blocks you.
On Thu, Feb 2, 2017 at 6:51 PM Eric Liu via cfe-commits < cfe-commits@lists.llvm.org> wrote: > Author: ioeric > Date: Thu Feb 2 11:40:38 2017 > New Revision: 293909 > > URL: http://llvm.org/viewvc/llvm-project?rev=293909&view=rev > Log: > [change-namespace] fix unscoped enum constant references. > > Reviewers: bkramer > > Subscribers: cfe-commits > > Differential Revision: https://reviews.llvm.org/D29460 > > Modified: > clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp > > clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp > > Modified: clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp?rev=293909&r1=293908&r2=293909&view=diff > > ============================================================================== > --- clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp (original) > +++ clang-tools-extra/trunk/change-namespace/ChangeNamespace.cpp Thu Feb > 2 11:40:38 2017 > @@ -282,6 +282,10 @@ bool isDeclVisibleAtLocation(const Sourc > isNestedDeclContext(DeclCtx, D->getDeclContext())); > } > > +AST_MATCHER(EnumDecl, isScoped) { > + return Node.isScoped(); > +} > + > } // anonymous namespace > > ChangeNamespaceTool::ChangeNamespaceTool( > @@ -454,6 +458,17 @@ void ChangeNamespaceTool::registerMatche > to(GlobalVarMatcher.bind("var_decl"))) > .bind("var_ref"), > this); > + > + // Handle unscoped enum constant. > + auto UnscopedEnumMatcher = enumConstantDecl(hasParent(enumDecl( > + hasParent(namespaceDecl()), > + unless(anyOf(isScoped(), IsInMovedNs, hasAncestor(cxxRecordDecl()), > + hasAncestor(namespaceDecl(isAnonymous()))))))); > + Finder->addMatcher( > + declRefExpr(IsInMovedNs, hasAncestor(decl().bind("dc")), > + to(UnscopedEnumMatcher.bind("enum_const_decl"))) > + .bind("enum_const_ref"), > + this); > } > > void ChangeNamespaceTool::run( > @@ -518,6 +533,21 @@ void ChangeNamespaceTool::run( > assert(Context && "Empty decl context."); > fixDeclRefExpr(Result, Context->getDeclContext(), > llvm::cast<NamedDecl>(Var), VarRef); > + } else if (const auto *EnumConstRef = > + Result.Nodes.getNodeAs<DeclRefExpr>("enum_const_ref")) { > + // Do not rename the reference if it is already scoped by the > EnumDecl name. > + if (EnumConstRef->hasQualifier() && > + EnumConstRef->getQualifier()->getAsType()->isEnumeralType()) > + return; > + const auto *EnumConstDecl = > + Result.Nodes.getNodeAs<EnumConstantDecl>("enum_const_decl"); > + assert(EnumConstDecl); > + const auto *Context = Result.Nodes.getNodeAs<Decl>("dc"); > + assert(Context && "Empty decl context."); > + // FIXME: this would qualify "ns::VALUE" as "ns::EnumValue::VALUE". > Fix it > + // if it turns out to be an issue. > + fixDeclRefExpr(Result, Context->getDeclContext(), > + llvm::cast<NamedDecl>(EnumConstDecl), EnumConstRef); > } else if (const auto *FuncRef = > Result.Nodes.getNodeAs<DeclRefExpr>("func_ref")) { > // If this reference has been processed as a function call, we do not > > Modified: > clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp > URL: > http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp?rev=293909&r1=293908&r2=293909&view=diff > > ============================================================================== > --- > clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp > (original) > +++ > clang-tools-extra/trunk/unittests/change-namespace/ChangeNamespaceTests.cpp > Thu Feb 2 11:40:38 2017 > @@ -1774,6 +1774,207 @@ TEST_F(ChangeNamespaceTest, ShortenNames > EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); > } > > +TEST_F(ChangeNamespaceTest, SimpleMoveEnum) { > + std::string Code = "namespace na {\n" > + "namespace nb {\n" > + "enum class X { X1, X2 };\n" > + "enum Y { Y1, Y2 };\n" > + "} // namespace nb\n" > + "} // namespace na\n"; > + std::string Expected = "\n\nnamespace x {\n" > + "namespace y {\n" > + "enum class X { X1, X2 };\n" > + "enum Y { Y1, Y2 };\n" > + "} // namespace y\n" > + "} // namespace x\n"; > + > + EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); > +} > + > +TEST_F(ChangeNamespaceTest, ReferencesToEnums) { > + std::string Code = "enum Glob { G1, G2 };\n" > + "namespace na {\n" > + "enum class X { X1 };\n" > + "enum Y { Y1, Y2 };\n" > + "namespace nb {\n" > + "void f() {\n" > + " Glob g1 = Glob::G1;\n" > + " Glob g2 = G2;\n" > + " X x1 = X::X1;\n" > + " Y y1 = Y::Y1;\n" > + " Y y2 = Y2;\n" > + "}\n" > + "} // namespace nb\n" > + "} // namespace na\n"; > + std::string Expected = "enum Glob { G1, G2 };\n" > + "namespace na {\n" > + "enum class X { X1 };\n" > + "enum Y { Y1, Y2 };\n" > + "\n" > + "} // namespace na\n" > + "namespace x {\n" > + "namespace y {\n" > + "void f() {\n" > + " Glob g1 = Glob::G1;\n" > + " Glob g2 = G2;\n" > + " ::na::X x1 = ::na::X::X1;\n" > + " ::na::Y y1 = ::na::Y::Y1;\n" > + " ::na::Y y2 = ::na::Y::Y2;\n" > + "}\n" > + "} // namespace y\n" > + "} // namespace x\n"; > + > + EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); > +} > + > +TEST_F(ChangeNamespaceTest, NoRedundantEnumUpdate) { > + std::string Code = "namespace ns {\n" > + "enum class X { X1 };\n" > + "enum Y { Y1, Y2 };\n" > + "} // namespace ns\n" > + "namespace na {\n" > + "namespace nb {\n" > + "void f() {\n" > + " ns::X x1 = ns::X::X1;\n" > + " ns::Y y1 = ns::Y::Y1;\n" > + " ns::Y y2 = ns::Y2;\n" > + "}\n" > + "} // namespace nb\n" > + "} // namespace na\n"; > + std::string Expected = "namespace ns {\n" > + "enum class X { X1 };\n" > + "enum Y { Y1, Y2 };\n" > + "} // namespace ns\n" > + "\n" > + "namespace x {\n" > + "namespace y {\n" > + "void f() {\n" > + " ns::X x1 = ns::X::X1;\n" > + " ns::Y y1 = ns::Y::Y1;\n" > + // FIXME: this is redundant > + " ns::Y y2 = ::ns::Y::Y2;\n" > + "}\n" > + "} // namespace y\n" > + "} // namespace x\n"; > + ; > + > + EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); > +} > + > +TEST_F(ChangeNamespaceTest, EnumsAndUsingShadows) { > + std::string Code = "namespace ns {\n" > + "enum class X { X1 };\n" > + "enum Y { Y1, Y2, Y3 };\n" > + "} // namespace ns\n" > + "using ns::X;\n" > + "using ns::Y;\n" > + "using ns::Y::Y2;\n" > + "using ns::Y::Y3;\n" > + "namespace na {\n" > + "namespace nb {\n" > + "void f() {\n" > + " X x1 = X::X1;\n" > + " Y y1 = Y::Y1;\n" > + " Y y2 = Y2;\n" > + " Y y3 = Y3;\n" > + "}\n" > + "} // namespace nb\n" > + "} // namespace na\n"; > + std::string Expected = "namespace ns {\n" > + "enum class X { X1 };\n" > + "enum Y { Y1, Y2, Y3 };\n" > + "} // namespace ns\n" > + "using ns::X;\n" > + "using ns::Y;\n" > + "using ns::Y::Y2;\n" > + "using ns::Y::Y3;\n" > + "\n" > + "namespace x {\n" > + "namespace y {\n" > + "void f() {\n" > + " X x1 = X::X1;\n" > + " Y y1 = Y::Y1;\n" > + " Y y2 = Y2;\n" > + " Y y3 = Y3;\n" > + "}\n" > + "} // namespace y\n" > + "} // namespace x\n"; > + > + EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); > +} > + > +TEST_F(ChangeNamespaceTest, EnumsAndAliases) { > + std::string Code = "namespace ns {\n" > + "enum class X { X1 };\n" > + "enum Y { Y1, Y2, Y3 };\n" > + "} // namespace ns\n" > + "typedef ns::X TX;\n" > + "typedef ns::Y TY;\n" > + "using UX = ns::X;\n" > + "using UY = ns::Y;\n" > + "namespace na {\n" > + "namespace nb {\n" > + "void f() {\n" > + " ns::X x1 = ns::X::X1;\n" > + " TX tx1 = TX::X1;\n" > + " UX ux1 = UX::X1;\n" > + " ns::Y y1 = ns::Y::Y1;\n" > + " TY ty1 = TY::Y1;\n" > + " UY uy1 = UY::Y1;\n" > + "}\n" > + "} // namespace nb\n" > + "} // namespace na\n"; > + std::string Expected = "namespace ns {\n" > + "enum class X { X1 };\n" > + "enum Y { Y1, Y2, Y3 };\n" > + "} // namespace ns\n" > + "typedef ns::X TX;\n" > + "typedef ns::Y TY;\n" > + "using UX = ns::X;\n" > + "using UY = ns::Y;\n" > + "\n" > + "namespace x {\n" > + "namespace y {\n" > + "void f() {\n" > + " ns::X x1 = ns::X::X1;\n" > + " TX tx1 = TX::X1;\n" > + " UX ux1 = UX::X1;\n" > + " ns::Y y1 = ns::Y::Y1;\n" > + " TY ty1 = TY::Y1;\n" > + " UY uy1 = UY::Y1;\n" > + "}\n" > + "} // namespace y\n" > + "} // namespace x\n"; > + > + EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); > +} > + > +TEST_F(ChangeNamespaceTest, EnumInClass) { > + std::string Code = "namespace na {\n" > + "struct X { enum E { E1 }; };\n" > + "namespace nb {\n" > + "void f() {\n" > + " X::E e = X::E1;\n" > + " X::E ee = X::E::E1;\n" > + "}\n" > + "} // namespace nb\n" > + "} // namespace na\n"; > + std::string Expected = "namespace na {\n" > + "struct X { enum E { E1 }; };\n" > + "\n" > + "} // namespace na\n" > + "namespace x {\n" > + "namespace y {\n" > + "void f() {\n" > + " ::na::X::E e = ::na::X::E1;\n" > + " ::na::X::E ee = ::na::X::E::E1;\n" > + "}\n" > + "} // namespace y\n" > + "} // namespace x\n"; > + > + EXPECT_EQ(format(Expected), runChangeNamespaceOnCode(Code)); > +} > + > } // anonymous namespace > } // namespace change_namespace > } // namespace clang > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits