Commit 108e2445 by Jason Merrill Committed by Jason Merrill

re PR c++/42137 (error: expected constructor, destructor, or type conversion before ‘{’ token)

	PR c++/42137
	* parser.c (cp_parser_mem_initializer_id): Pass typename_type to
	cp_parser_class_name.
	(cp_parser_unqualified_id): Same, rather than class_type.

	PR c++/11764
	* parser.c (cp_parser_expression_statement): Give helpful error
	for constructor name used as type.

From-SVN: r154519
parent 3474a3b7
2009-11-24 Jason Merrill <jason@redhat.com>
PR c++/42137
* parser.c (cp_parser_mem_initializer_id): Pass typename_type to
cp_parser_class_name.
(cp_parser_unqualified_id): Same, rather than class_type.
PR c++/11764
* parser.c (cp_parser_expression_statement): Give helpful error
for constructor name used as type.
* pt.c (determine_specialization): Give helpful error about missing
"template<>".
......
......@@ -2401,11 +2401,15 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
error_at (location, "%qE in namespace %qE does not name a type",
id, parser->scope);
else if (CLASS_TYPE_P (parser->scope)
&& constructor_name_p (id, parser->scope)
&& cp_lexer_next_token_is (parser->lexer, CPP_LESS))
/* A<T>::A<T>() */
error_at (location, "invalid use of constructor %<%T::%E%> as "
"template", parser->scope, id);
&& constructor_name_p (id, parser->scope))
{
/* A<T>::A<T>() */
error_at (location, "%<%T::%E%> names the constructor, not"
" the type", parser->scope, id);
if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
error_at (location, "and %qT has no template constructors",
parser->scope);
}
else if (TYPE_P (parser->scope)
&& dependent_scope_p (parser->scope))
error_at (location, "need %<typename%> before %<%T::%E%> because "
......@@ -3906,9 +3910,9 @@ cp_parser_unqualified_id (cp_parser* parser,
/* If there was an explicit qualification (S::~T), first look
in the scope given by the qualification (i.e., S).
Note: in the calls to cp_parser_class_name below we pretend that
the lookup had an explicit 'class' tag so that lookup finds the
injected-class-name rather than the constructor. */
Note: in the calls to cp_parser_class_name below we pass
typename_type so that lookup finds the injected-class-name
rather than the constructor. */
done = false;
type_decl = NULL_TREE;
if (scope)
......@@ -3917,7 +3921,7 @@ cp_parser_unqualified_id (cp_parser* parser,
type_decl = cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
class_type,
typename_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
......@@ -3935,7 +3939,7 @@ cp_parser_unqualified_id (cp_parser* parser,
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
class_type,
typename_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
......@@ -3953,7 +3957,7 @@ cp_parser_unqualified_id (cp_parser* parser,
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
class_type,
typename_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
......@@ -3972,7 +3976,7 @@ cp_parser_unqualified_id (cp_parser* parser,
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
class_type,
typename_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
......@@ -7800,13 +7804,24 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
statement = cp_parser_expression (parser, /*cast_p=*/false, NULL);
/* Give a helpful message for "A<T>::type t;" */
/* Give a helpful message for "A<T>::type t;" and the like. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
&& !cp_parser_uncommitted_to_tentative_parse_p (parser)
&& TREE_CODE (statement) == SCOPE_REF)
error_at (token->location, "need %<typename%> before %qE because "
"%qT is a dependent scope",
statement, TREE_OPERAND (statement, 0));
&& !cp_parser_uncommitted_to_tentative_parse_p (parser))
{
if (TREE_CODE (statement) == SCOPE_REF)
error_at (token->location, "need %<typename%> before %qE because "
"%qT is a dependent scope",
statement, TREE_OPERAND (statement, 0));
else if (is_overloaded_fn (statement)
&& DECL_CONSTRUCTOR_P (get_first_fn (statement)))
{
/* A::A a; */
tree fn = get_first_fn (statement);
error_at (token->location,
"%<%T::%D%> names the constructor, not the type",
DECL_CONTEXT (fn), DECL_NAME (fn));
}
}
/* Consume the final `;'. */
cp_parser_consume_semicolon_at_end_of_statement (parser);
......@@ -10020,7 +10035,7 @@ cp_parser_mem_initializer_id (cp_parser* parser)
return cp_parser_class_name (parser,
/*typename_keyword_p=*/true,
/*template_keyword_p=*/template_p,
none_type,
typename_type,
/*check_dependency_p=*/true,
/*class_head_p=*/false,
/*is_declaration=*/true);
......
2009-11-23 Jason Merrill <jason@redhat.com>
* g++.dg/tc1/dr147.C: Check for helpful messages. Add DR 318 tests.
* g++.old-deja/g++.pt/ctor2.C: Adjust.
* g++.dg/lookup/name-clash4.C: Adjust.
2009-11-23 Jason Merrill <jason@redhat.com>
* g++.dg/template/spec15.C: Check for helpful message.
2009-11-24 Janis Johnson <janis187@us.ibm.com>
......
......@@ -9,4 +9,4 @@ struct A
template<int> struct A {}; // { dg-error "same name" }
};
A::A<0> a; // { dg-error "not a template|invalid use of constructor" }
A::A<0> a; // { dg-error "not a template|constructor" }
......@@ -11,8 +11,12 @@ A::A() { }
B::B() { }
B::A ba;
A::A a; // { dg-error "" "the injected-class-name can never be found through qualified lookup" }
A::A a; // { dg-error "constructor" "the injected-class-name can never be found through qualified lookup" }
void f()
{
A::A a; // { dg-error "constructor" }
} // { dg-error "" "" { target *-*-* } 18 } error cascade
}
namespace N2 {
......@@ -26,6 +30,22 @@ template <class T> struct A {
template <class T2> A(T2);
static A x;
};
template<> template <> A<char>::A<char>(char);
template<> A<int>::A<int>(A<int>::x); // { dg-error "" "this is an invalid declaration of the constructor" }
}
// But DR 318 says that in situations where a type is syntactically
// required, lookup finds it.
struct C
{
C();
typedef int T;
};
struct C::C c;
C::C::T t;
struct D: C::C
{
D(): C::C() { }
};
......@@ -8,6 +8,6 @@ struct A {
};
template <class T>
A<T>::A<T>() // { dg-error "invalid use of constructor|qualified name" }
A<T>::A<T>() // { dg-error "constructor|qualified name" }
{
} // { dg-error "end of input" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment