re PR c++/9403 (parse error on template keyword used for disambiguation)

cp:
	PR c++/9403
	* parser.c (cp_parser_class_or_namespace_name): Reject duplicate
	template keyword.
	(cp_parser_base_specifier): Look for and consume a
	TEMPLATE keyword. Replace switch with array index.

	PR c++/795
	* semantics.c (finish_non_static_data_member): Remember the
	field's type even in a template.

	PR c++/9415
	* pt.c (tsubst_copy_and_build, CALL_EXPR): BASELINK exprs are
	already scoped.

	PR c++/8545
	* parser.c (cp_parser_cast_expression): Be more tentative.
testsuite:
	PR c++/9403
	* g++.dg/parse/template3.C: New test.
	* g++.old-deja/g++.pt/memclass5.C: Add needed template keyword.

	PR c++/795
	* g++.dg/parse/template4.C: New test.

	PR c++/9415
	* g++.dg/template/qual2.C: New test.

	PR c++/8545
	* g++.old-deja/g++.brendan/parse3.C: Remove XFAIL.

	* g++.old-deja/g++.ns/bogus1.C: Change expected error.

From-SVN: r61791
This commit is contained in:
Nathan Sidwell 2003-01-25 18:02:43 +00:00 committed by Nathan Sidwell
parent 8324663fcb
commit bbaab9162a
11 changed files with 150 additions and 74 deletions

View File

@ -1,3 +1,22 @@
2003-01-25 Nathan Sidwell <nathan@codesourcery.com>
PR c++/9403
* parser.c (cp_parser_class_or_namespace_name): Reject duplicate
template keyword.
(cp_parser_base_specifier): Look for and consume a
TEMPLATE keyword. Replace switch with array index.
PR c++/795
* semantics.c (finish_non_static_data_member): Remember the
field's type even in a template.
PR c++/9415
* pt.c (tsubst_copy_and_build, CALL_EXPR): BASELINK exprs are
already scoped.
PR c++/8545
* parser.c (cp_parser_cast_expression): Be more tentative.
2003-01-25 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* cp-tree.h (flagged_type_tree_s): Remove.

View File

@ -3392,16 +3392,6 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
tree scope;
bool only_class_p;
/* If the next token is the `template' keyword, we know that we are
looking at a class-name. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
return cp_parser_class_name (parser,
typename_keyword_p,
template_keyword_p,
type_p,
/*check_access_p=*/true,
check_dependency_p,
/*class_head_p=*/false);
/* Before we try to parse the class-name, we must save away the
current PARSER->SCOPE since cp_parser_class_name will destroy
it. */
@ -3410,7 +3400,7 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
saved_object_scope = parser->object_scope;
/* Try for a class-name first. If the SAVED_SCOPE is a type, then
there is no need to look for a namespace-name. */
only_class_p = saved_scope && TYPE_P (saved_scope);
only_class_p = template_keyword_p || (saved_scope && TYPE_P (saved_scope));
if (!only_class_p)
cp_parser_parse_tentatively (parser);
scope = cp_parser_class_name (parser,
@ -3931,7 +3921,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
postfix_expression = build_x_arrow (postfix_expression);
/* Check to see whether or not the expression is
type-dependent. */
dependent_p = (type_dependent_expression_p (postfix_expression));
dependent_p = type_dependent_expression_p (postfix_expression);
/* The identifier following the `->' or `.' is not
qualified. */
parser->scope = NULL_TREE;
@ -4761,23 +4751,26 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
/* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message;
/* If all went well, this is a cast. */
/* If ok so far, parse the dependent expression. We cannot be
sure it is a cast. Consider `(T ())'. It is a parenthesized
ctor of T, but looks like a cast to function returning T
without a dependent expression. */
if (!cp_parser_error_occurred (parser))
expr = cp_parser_cast_expression (parser, /*address_p=*/false);
if (cp_parser_parse_definitely (parser))
{
/* Parse the dependent expression. */
expr = cp_parser_cast_expression (parser, /*address_p=*/false);
/* Warn about old-style casts, if so requested. */
if (warn_old_style_cast
&& !in_system_header
&& !VOID_TYPE_P (type)
&& current_lang_name != lang_name_c)
warning ("use of old-style cast");
/* Perform the cast. */
expr = build_c_cast (type, expr);
return expr;
}
if (expr)
return expr;
}
/* If we get here, then it's not a cast, so it must be a
@ -12175,12 +12168,20 @@ cp_parser_base_clause (cp_parser* parser)
static tree
cp_parser_base_specifier (cp_parser* parser)
{
static const tree *const access_nodes[][2] =
{
/* This ordering must match the access_kind enumeration. */
{&access_default_node, &access_default_virtual_node},
{&access_public_node, &access_public_virtual_node},
{&access_protected_node, &access_protected_virtual_node},
{&access_private_node, &access_private_virtual_node}
};
cp_token *token;
bool done = false;
bool virtual_p = false;
bool duplicate_virtual_error_issued_p = false;
bool duplicate_access_error_issued_p = false;
bool class_scope_p;
bool class_scope_p, template_p;
access_kind access = ak_none;
tree access_node;
tree type;
@ -12236,45 +12237,9 @@ cp_parser_base_specifier (cp_parser* parser)
}
}
/* Map `virtual_p' and `access' onto one of the access
tree-nodes. */
if (!virtual_p)
switch (access)
{
case ak_none:
access_node = access_default_node;
break;
case ak_public:
access_node = access_public_node;
break;
case ak_protected:
access_node = access_protected_node;
break;
case ak_private:
access_node = access_private_node;
break;
default:
abort ();
}
else
switch (access)
{
case ak_none:
access_node = access_default_virtual_node;
break;
case ak_public:
access_node = access_public_virtual_node;
break;
case ak_protected:
access_node = access_protected_virtual_node;
break;
case ak_private:
access_node = access_private_virtual_node;
break;
default:
abort ();
}
/* Map `virtual_p' and `access' onto one of the access tree-nodes. */
access_node = *access_nodes[access][virtual_p];
/* Look for the optional `::' operator. */
cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
/* Look for the nested-name-specifier. The simplest way to
@ -12296,10 +12261,12 @@ cp_parser_base_specifier (cp_parser* parser)
/* If the base class is given by a qualified name, assume that names
we see are type names or templates, as appropriate. */
class_scope_p = (parser->scope && TYPE_P (parser->scope));
template_p = class_scope_p && cp_parser_optional_template_keyword (parser);
/* Finally, look for the class-name. */
type = cp_parser_class_name (parser,
class_scope_p,
class_scope_p,
template_p,
/*type_p=*/true,
/*check_access=*/true,
/*check_dependency_p=*/true,

View File

@ -8129,28 +8129,32 @@ tsubst_copy_and_build (t, args, complain, in_decl)
case CALL_EXPR:
{
tree function
= tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
if (TREE_CODE (function) == SCOPE_REF)
tree function, copy_args;
function = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
copy_args = tsubst_copy_and_build (TREE_OPERAND (t, 1), args,
complain, in_decl);
if (BASELINK_P (function))
return build_call_from_tree (function, copy_args, 1);
else if (TREE_CODE (function) == SCOPE_REF)
{
tree name = TREE_OPERAND (function, 1);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = build_nt (TEMPLATE_ID_EXPR,
TREE_OPERAND (name, 0),
TREE_OPERAND (name, 1));
return build_call_from_tree
(resolve_scoped_fn_name (TREE_OPERAND (function, 0), name),
tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
in_decl),
1);
function = resolve_scoped_fn_name (TREE_OPERAND (function, 0),
name);
return build_call_from_tree (function, copy_args, 1);
}
else
{
tree name = function;
tree id;
tree copy_args = tsubst_copy_and_build
(TREE_OPERAND (t, 1), args, complain, in_decl);
if (copy_args != NULL_TREE && TREE_CODE (name) == LOOKUP_EXPR
&& !LOOKUP_EXPR_GLOBAL (name)
&& (TREE_CODE ((id = TREE_OPERAND (name, 0)))

View File

@ -1214,7 +1214,8 @@ finish_non_static_data_member (tree decl, tree qualifying_scope)
}
TREE_USED (current_class_ptr) = 1;
if (processing_template_decl)
return build_min_nt (COMPONENT_REF, current_class_ref, DECL_NAME (decl));
return build_min (COMPONENT_REF, TREE_TYPE (decl),
current_class_ref, DECL_NAME (decl));
else
{
tree access_type = current_class_type;

View File

@ -1,3 +1,20 @@
2003-01-25 Nathan Sidwell <nathan@codesourcery.com>
PR c++/9403
* g++.dg/parse/template3.C: New test.
* g++.old-deja/g++.pt/memclass5.C: Add needed template keyword.
PR c++/795
* g++.dg/parse/template4.C: New test.
PR c++/9415
* g++.dg/template/qual2.C: New test.
PR c++/8545
* g++.old-deja/g++.brendan/parse3.C: Remove XFAIL.
* g++.old-deja/g++.ns/bogus1.C: Change expected error.
2003-01-25 Roger Sayle <roger@eyesopen.com>
* gcc.c-torture/execute/switch-1.c: New test case.

View File

@ -0,0 +1,17 @@
// { dg-do compile }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 24 Jan 2003 <nathan@codesourcery.com>
// PR 9403. We failed to parse template keyword, and we accepted code
// which required one.
template<bool> struct Outer;
template <bool b, typename T>
struct X : Outer<b>::template Inner<T>
{};
template <bool b, typename T>
struct Y : Outer<b>::Inner<T> {}; // { dg-error "" "" }

View File

@ -0,0 +1,21 @@
// { dg-do compile }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 32 Jan 2003 <nathan@codesourcery.com>
// PR 795. fields are not necessarily a dependent type.
struct V
{
template<typename T> T get ();
};
struct L
{
V v;
template<typename T> T at (int i)
{
return v.get<T> ();
}
};

View File

@ -0,0 +1,29 @@
// { dg-do run }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 23 Jan 2003 <nathan@codesourcery.com>
// PR9415. Forgot a lookup was scoped
int here;
int there;
struct B
{
virtual int activate() {return !here++;}
};
template <class K>
struct TPL : public B
{
int activate()
{
return !there++ && B::activate();
}
};
int main ()
{
TPL<int> i;
return !i.activate ();
}

View File

@ -6,6 +6,7 @@
// when the parser's been cleaned up or rewritten, these two error
// markers can go away, since they'll no longer occur.
// Fixed. PR 8545, 2001 01 23
class A
{
public:
@ -19,5 +20,5 @@ A A::operator+(const A in)
if (high==0)
return A(); // this works
else
return (A()); // this works not // gets bogus error - XFAIL *-*-*
return (A()); // this works not
}

View File

@ -2,7 +2,7 @@
namespace N {}
void f(int N::k); // ERROR - cannot use `::' in parameter declaration
void f(int N::k); // ERROR -
class Foo
{

View File

@ -14,7 +14,7 @@ void f ()
b.A<T>::template B<U>::~B();
}
template <class T> struct C: public A<T>::B<T> { };
template <class T> struct C: public A<T>::template B<T> { };
int main ()
{