Hi,
in this pretty old issue we crash for this testcase:
namespace N
{
namespace M = N;
namespace M {}// { dg-error "namespace alias" }
}
after the error message, because error recovery after error fails. We
try to do:
error ("namespace alias %qD not allowed here, assuming %qD",
d, DECL_NAMESPACE_ALIAS (d));
d = DECL_NAMESPACE_ALIAS (d);
but then we crash in resume_scope because:
/* Also, resuming a non-directly nested namespace is a no-no. */
gcc_assert (b->level_chain == current_binding_level);
Thus, in the first patch below I changed push_namespace to stay away
from this nasty situation and produce and simpler diagnostics and no
special error recovery in this case: a false is returned, and the
caller, cp_parser_namespace_definition, makes sure to not call a
matching pop_namespace. Diagnostics is good, patch passes testing.
Alternately, the second patch below does the latter unconditionally,
without even trying the "assuming" thing. Same diagnostics for the
testcase at issue, no regressions in this case too. I don't have a
strong personal preference, I suppose the current "assuming" thing may
lead to fewer cascading errors, but I don't know for sure, certainly the
second patch is simpler.
Thanks,
Paolo.
/cp
2012-05-29 Paolo Carlini
PR c++/26155
* name-lookup.c (push_namespace): Simply return false after error
when error recovery is impossible.
* name-lookup.h (push_namespace): Update prototype.
* parser.c (cp_parser_namespace_definition): Chech push_namespace
return value and don't call pop_namespace when false.
/testsuite
2012-05-29 Paolo Carlini
PR c++/26155
* g++.dg/parse/namespace-alias-1.C: New.
Index: testsuite/g++.dg/parse/namespace-alias-1.C
===
--- testsuite/g++.dg/parse/namespace-alias-1.C (revision 0)
+++ testsuite/g++.dg/parse/namespace-alias-1.C (revision 0)
@@ -0,0 +1,7 @@
+// PR c++/26155
+
+namespace N
+{
+ namespace M = N;
+ namespace M {}// { dg-error "namespace alias" }
+}
Index: cp/parser.c
===
--- cp/parser.c (revision 187968)
+++ cp/parser.c (working copy)
@@ -14738,6 +14738,7 @@ cp_parser_namespace_definition (cp_parser* parser)
tree identifier, attribs;
bool has_visibility;
bool is_inline;
+ bool ok;
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_INLINE))
{
@@ -14766,7 +14767,7 @@ cp_parser_namespace_definition (cp_parser* parser)
/* Look for the `{' to start the namespace. */
cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE);
/* Start the namespace. */
- push_namespace (identifier);
+ ok = push_namespace (identifier);
/* "inline namespace" is equivalent to a stub namespace definition
followed by a strong using directive. */
@@ -14792,7 +14793,8 @@ cp_parser_namespace_definition (cp_parser* parser)
pop_visibility (1);
/* Finish the namespace. */
- pop_namespace ();
+ if (ok)
+pop_namespace ();
/* Look for the final `}'. */
cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
}
Index: cp/name-lookup.c
===
--- cp/name-lookup.c(revision 187968)
+++ cp/name-lookup.c(working copy)
@@ -3512,9 +3512,10 @@ handle_namespace_attrs (tree ns, tree attributes)
}
/* Push into the scope of the NAME namespace. If NAME is NULL_TREE, then we
- select a name that is unique to this compilation unit. */
+ select a name that is unique to this compilation unit. Return false if
+ something goes very badly wrong, true otherwise. */
-void
+bool
push_namespace (tree name)
{
tree d = NULL_TREE;
@@ -3544,12 +3545,23 @@ push_namespace (tree name)
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d != NULL_TREE && TREE_CODE (d) == NAMESPACE_DECL)
{
+ tree dna = DECL_NAMESPACE_ALIAS (d);
need_new = 0;
- if (DECL_NAMESPACE_ALIAS (d))
+ if (dna)
{
- error ("namespace alias %qD not allowed here, assuming %qD",
-d, DECL_NAMESPACE_ALIAS (d));
- d = DECL_NAMESPACE_ALIAS (d);
+ if (NAMESPACE_LEVEL (dna)->level_chain
+ == current_binding_level)
+ {
+ error ("namespace alias %qD not allowed here, "
+"assuming %qD", d, dna);
+ d = dna;
+ }
+ else
+ {
+ error ("namespace alias %qD not allowed here", d);
+ timevar_cond_stop (TV_NAME_LOOKUP, subtime);
+ return false;
+ }
}
}
}
@@ -3583,6 +3595,7 @@ push_namespace (tree name)
current_namespace = d;
timevar_cond_stop (TV_NAME_LOOKUP, subtime);
+ return