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:
parent
8324663fcb
commit
bbaab9162a
@ -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.
|
||||
|
@ -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,
|
||||
|
26
gcc/cp/pt.c
26
gcc/cp/pt.c
@ -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)))
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
17
gcc/testsuite/g++.dg/parse/template3.C
Normal file
17
gcc/testsuite/g++.dg/parse/template3.C
Normal 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 "" "" }
|
||||
|
21
gcc/testsuite/g++.dg/parse/template4.C
Normal file
21
gcc/testsuite/g++.dg/parse/template4.C
Normal 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> ();
|
||||
}
|
||||
};
|
29
gcc/testsuite/g++.dg/template/qual2.C
Normal file
29
gcc/testsuite/g++.dg/template/qual2.C
Normal 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 ();
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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 ()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user