aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2003-01-25 18:02:43 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2003-01-25 18:02:43 +0000
commitbbaab9162a854dd2225f38cb42e0c3666a9462ec (patch)
treebbea47d7b8e0183a5f7884bf430c0c75e59768f9 /gcc
parent8324663fcbeb40a837e46fa65d1252124345d565 (diff)
downloadgcc-bbaab9162a854dd2225f38cb42e0c3666a9462ec.zip
gcc-bbaab9162a854dd2225f38cb42e0c3666a9462ec.tar.gz
gcc-bbaab9162a854dd2225f38cb42e0c3666a9462ec.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog19
-rw-r--r--gcc/cp/parser.c85
-rw-r--r--gcc/cp/pt.c26
-rw-r--r--gcc/cp/semantics.c3
-rw-r--r--gcc/testsuite/ChangeLog17
-rw-r--r--gcc/testsuite/g++.dg/parse/template3.C17
-rw-r--r--gcc/testsuite/g++.dg/parse/template4.C21
-rw-r--r--gcc/testsuite/g++.dg/template/qual2.C29
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/parse3.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.ns/bogus1.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/memclass5.C2
11 files changed, 150 insertions, 74 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 336370f..fe8898f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4d809b8..7e172ab 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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,
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ca75cb0..bbfec14 100644
--- a/gcc/cp/pt.c
+++ b/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)))
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 19808e6..fb6f25d 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f6a8dff..7c331f1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.dg/parse/template3.C b/gcc/testsuite/g++.dg/parse/template3.C
new file mode 100644
index 0000000..290721e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/template3.C
@@ -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 "" "" }
+
diff --git a/gcc/testsuite/g++.dg/parse/template4.C b/gcc/testsuite/g++.dg/parse/template4.C
new file mode 100644
index 0000000..11f11d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/template4.C
@@ -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> ();
+ }
+};
diff --git a/gcc/testsuite/g++.dg/template/qual2.C b/gcc/testsuite/g++.dg/template/qual2.C
new file mode 100644
index 0000000..aa6b10e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/qual2.C
@@ -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 ();
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/parse3.C b/gcc/testsuite/g++.old-deja/g++.brendan/parse3.C
index 8941356..ffe72d2 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/parse3.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/parse3.C
@@ -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
}
diff --git a/gcc/testsuite/g++.old-deja/g++.ns/bogus1.C b/gcc/testsuite/g++.old-deja/g++.ns/bogus1.C
index c61dea8..373688a 100644
--- a/gcc/testsuite/g++.old-deja/g++.ns/bogus1.C
+++ b/gcc/testsuite/g++.old-deja/g++.ns/bogus1.C
@@ -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
{
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memclass5.C b/gcc/testsuite/g++.old-deja/g++.pt/memclass5.C
index 6fc7219..5a0c037 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/memclass5.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/memclass5.C
@@ -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 ()
{