Moved fix-its from the notes to the error message.

On Fri, May 6, 2011 at 2:20 PM, Richard Trieu <[email protected]> wrote:

> When improperly using "::" to nest namespaces, give a fix-it to correct it.
>  Parsing will also recover as if they were properly nested.
>
> namespace foo::bar {
> }
>
> Will result in a fix-it at "::" to change to " { namespace " and an
> additional right bracket at the end.
>
> Patch attached and available through Code Review:
> http://codereview.appspot.com/4452052/
>
Index: test/Parser/nested-namespaces-recovery.cpp
===================================================================
--- test/Parser/nested-namespaces-recovery.cpp	(revision 0)
+++ test/Parser/nested-namespaces-recovery.cpp	(revision 0)
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+namespace foo1::foo2::foo3 { // expected-error 2{{nested namespace definition must define each namespace separately}}
+  int foo(int x) { return x; }
+}
+
+int foo(int x) {
+  return foo1::foo2::foo3::foo(x);
+}
+
+namespace bar1 {
+  namespace bar2 {
+    namespace bar3 {
+      int bar(int x) { return x; }
+    }
+  }
+}
+
+int bar(int x) {
+  return bar1::bar2::bar3::bar(x);
+}
+
Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td	(revision 130254)
+++ include/clang/Basic/DiagnosticParseKinds.td	(working copy)
@@ -161,6 +161,8 @@
 def err_inline_namespace_alias : Error<"namespace alias cannot be inline">;
 def err_namespace_nonnamespace_scope : Error<
   "namespaces can only be defined in global or namespace scope">;
+def err_nested_namespaces_with_double_colon : Error<
+  "nested namespace definition must define each namespace separately">;
 def err_expected_semi_after_attribute_list : Error<
   "expected ';' after attribute list">;
 def err_expected_semi_after_static_assert : Error<
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp	(revision 130254)
+++ lib/Parse/ParseDeclCXX.cpp	(working copy)
@@ -85,10 +85,33 @@
     return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
   }
 
+  bool FixNestedNamespace = false;
+
   if (Tok.isNot(tok::l_brace)) {
-    Diag(Tok, Ident ? diag::err_expected_lbrace :
-         diag::err_expected_ident_lbrace);
-    return 0;
+    // Unless we have "namepsace foo::bar {", just complain about a lack of '{'.
+    if (!Tok.is(tok::coloncolon) || !NextToken().is(tok::identifier)) {
+      Diag(Tok, Ident ? diag::err_expected_lbrace :
+           diag::err_expected_ident_lbrace);
+      return 0;
+    }
+    // Otherwise, recover parsing as if the user had typed
+    // "namespace foo { namespace bar {".
+    TentativeParsingAction TPA(*this);
+    SkipUntil(tok::l_brace, /*StopAtSemi*/false);
+    SkipUntil(tok::r_brace, /*StopAtSemi*/false, /*DontConsume*/true);
+    Token rBraceToken = Tok;
+    rBraceToken.setKind(tok::r_brace);
+    PP.EnterToken(rBraceToken);
+    TPA.Revert();
+
+    Diag(Tok, diag::err_nested_namespaces_with_double_colon)
+        << FixItHint::CreateReplacement(Tok.getLocation(), " { namespace ")
+        << FixItHint::CreateInsertion(rBraceToken.getLocation(), "}");
+
+    Tok.setKind(tok::kw_namespace);
+    PP.EnterToken(Tok);
+    Tok.setKind(tok::l_brace);
+    FixNestedNamespace = true;
   }
 
   SourceLocation LBrace = ConsumeBrace();
@@ -114,12 +137,16 @@
 
   PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc,
                                       "parsing namespace");
-
-  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
-    ParsedAttributesWithRange attrs(AttrFactory);
-    MaybeParseCXX0XAttributes(attrs);
-    MaybeParseMicrosoftAttributes(attrs);
-    ParseExternalDeclaration(attrs);
+  if (FixNestedNamespace) {
+    // Only have an inner namespace to parse.
+    ParseNamespace(Context, DeclEnd);
+  } else {
+    while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
+      ParsedAttributesWithRange attrs(AttrFactory);
+      MaybeParseCXX0XAttributes(attrs);
+      MaybeParseMicrosoftAttributes(attrs);
+      ParseExternalDeclaration(attrs);
+    }
   }
 
   // Leave the namespace scope.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to