diff --git a/clang/lib/Format/NamespaceEndCommentsFixer.cpp b/clang/lib/Format/NamespaceEndCommentsFixer.cpp --- a/clang/lib/Format/NamespaceEndCommentsFixer.cpp +++ b/clang/lib/Format/NamespaceEndCommentsFixer.cpp @@ -205,6 +205,23 @@ const SourceManager &SourceMgr = Env.getSourceManager(); AffectedRangeMgr.computeAffectedLines(AnnotatedLines); tooling::Replacements Fixes; + + // Spin through the lines and ensure we have balanced braces. + int Braces = 0; + for (size_t I = 0, E = AnnotatedLines.size(); I != E; ++I) { + FormatToken *Tok = AnnotatedLines[I]->First; + while (Tok) { + Braces += Tok->is(tok::l_brace) ? 1 : Tok->is(tok::r_brace) ? -1 : 0; + Tok = Tok->Next; + } + } + // Don't attempt to comment unbalanced braces or this can + // lead to comments being placed on the closing brace which isn't + // the matching brace of the namespace. (occurs during incomplete editing). + if (Braces != 0) { + return {Fixes, 0}; + } + std::string AllNamespaceNames = ""; size_t StartLineIndex = SIZE_MAX; StringRef NamespaceTokenText; diff --git a/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp b/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp --- a/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp +++ b/clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp @@ -1089,6 +1089,34 @@ "void d() {\n" "}\n")); } + +TEST_F(NamespaceEndCommentsFixerTest, IgnoreUnbalanced) { + EXPECT_EQ("namespace A {\n" + "class Foo {\n" + "}\n" + "}// namespace A\n", + fixNamespaceEndComments("namespace A {\n" + "class Foo {\n" + "}\n" + "}\n")); + EXPECT_EQ("namespace A {\n" + "class Foo {\n" + "}\n", + fixNamespaceEndComments("namespace A {\n" + "class Foo {\n" + "}\n")); + + EXPECT_EQ("namespace A {\n" + "class Foo {\n" + "}\n" + "}\n" + "}\n", + fixNamespaceEndComments("namespace A {\n" + "class Foo {\n" + "}\n" + "}\n" + "}\n")); +} } // end namespace } // end namespace format } // end namespace clang