aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-11-24 15:55:24 -0500
committerJason Merrill <jason@gcc.gnu.org>2009-11-24 15:55:24 -0500
commit108e24453b3463097c8f0a25dd2d21219944b0fe (patch)
treec0ee5b73c59f1d6bab85c25d33794a7d87248d78
parent3474a3b72bf01781f123dc2423bff037ae398fcd (diff)
downloadgcc-108e24453b3463097c8f0a25dd2d21219944b0fe.zip
gcc-108e24453b3463097c8f0a25dd2d21219944b0fe.tar.gz
gcc-108e24453b3463097c8f0a25dd2d21219944b0fe.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/parser.c53
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/lookup/name-clash4.C2
-rw-r--r--gcc/testsuite/g++.dg/tc1/dr147.C22
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/ctor2.C2
6 files changed, 72 insertions, 22 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ba3bbf2..72d7832 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,14 @@
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<>".
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c7560a8..0b6fa01 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index dcf57249..cc5e804 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,11 @@
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>
diff --git a/gcc/testsuite/g++.dg/lookup/name-clash4.C b/gcc/testsuite/g++.dg/lookup/name-clash4.C
index d6c6d97..490f750 100644
--- a/gcc/testsuite/g++.dg/lookup/name-clash4.C
+++ b/gcc/testsuite/g++.dg/lookup/name-clash4.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/tc1/dr147.C b/gcc/testsuite/g++.dg/tc1/dr147.C
index 9c90d98..9006be9 100644
--- a/gcc/testsuite/g++.dg/tc1/dr147.C
+++ b/gcc/testsuite/g++.dg/tc1/dr147.C
@@ -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() { }
+};
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C b/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C
index 802c2a4..eb8f312 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/ctor2.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" }