aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/semantics.c
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2005-10-16 19:38:57 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2005-10-16 19:38:57 +0000
commit02ed62dd463d55d9d9810b9c8829691e7814743d (patch)
tree76f4797c33c693120da1fa591e01740f0bef605d /gcc/cp/semantics.c
parentc2b27658fe406ae890354dd825e4060d65df7e0a (diff)
downloadgcc-02ed62dd463d55d9d9810b9c8829691e7814743d.zip
gcc-02ed62dd463d55d9d9810b9c8829691e7814743d.tar.gz
gcc-02ed62dd463d55d9d9810b9c8829691e7814743d.tar.bz2
re PR c++/22137 (Internal error: Segmentation fault (program cc1plus))
PR c++/22137 * cp-tree.h (QUALIFIED_NAME_IS_TEMPLATE): New macro. (check_template_keyword): New function. (finish_id_expression): Change prototoype. (finish_qualified_id_expr): Change prototype. (build_qualified_name): New function. (finish_class_member_access_expr): Change prototype. * init.c (build_offset_ref): Use build_qualified_name. * mangle.c (write_expression): Likewise. * parser.c (cp_parser_primary_expression): Remove qualifying_class parameter. Add address_p and template_arg_p. Use build_qualified_name. (cp_parser_id_expression): Default *template_p to template_keyword_p. Check for invalid uses of the template keyword. (cp_parser_postfix_expression): Eliminate special handling for qualified names. Adjust call to cp_parser_primary_expression. (cp_parser_postfix_dot_deref_expression): Adjust call to cp_parser_id_expression and finish_class_member_access_expr. (cp_parser_template_argument_list): Add comment. (cp_parser_template_argument): Adjust use of cp_parser_primary_expression. Remove call to finish_qualified_id_expr. (cp_parser_lookup_name): Use build_qualified_name. * pt.c (tsubst): Use build_qualified_name. (tsubst_qualified_id): Likewise. Adjust call to finish_qualified_id_expr. (tsubst_copy): Use build_qualified_name. (tsubst_copy_and_build): Adjusts call to finish_id_expression and finish_class_member_access_expr. * semantics.c (finish_non_static_data_member): Use build_qualified_name. (finish_qualified_id_expr): Add template_p and template_arg_p parameters. (finish_id_expression): Remove qualifiying_class parameter. Add template_p, done, address_p, and template_arg_p. Use build_qualified_name. Adjust calls to finish_class_member_acess_expr. * tree.c (build_qualified_name): New function. * typeck.c (check_template_keyword): New function. (finish_class_member_access_expr): Add template_p argument. Check for invalid uses of the template keyword. PR c++/22137 * g++.dg/parse/template18.C: New test. * g++.dg/template/nontype15.C: Likewise. From-SVN: r105463
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r--gcc/cp/semantics.c91
1 files changed, 69 insertions, 22 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index d870fda..5ccc7c7 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1407,8 +1407,10 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
QUALIFYING_SCOPE is also non-null. Wrap this in a SCOPE_REF
for now. */
if (processing_template_decl)
- return build_min (SCOPE_REF, TREE_TYPE (decl),
- qualifying_scope, DECL_NAME (decl));
+ return build_qualified_name (TREE_TYPE (decl),
+ qualifying_scope,
+ DECL_NAME (decl),
+ /*template_p=*/false);
perform_or_defer_access_check (TYPE_BINFO (access_type), decl);
@@ -1494,15 +1496,24 @@ check_accessibility_of_qualified_id (tree decl,
class named to the left of the "::" operator. DONE is true if this
expression is a complete postfix-expression; it is false if this
expression is followed by '->', '[', '(', etc. ADDRESS_P is true
- iff this expression is the operand of '&'. */
+ iff this expression is the operand of '&'. TEMPLATE_P is true iff
+ the qualified-id was of the form "A::template B". TEMPLATE_ARG_P
+ is true iff this qualified name appears as a template argument. */
tree
-finish_qualified_id_expr (tree qualifying_class, tree expr, bool done,
- bool address_p)
+finish_qualified_id_expr (tree qualifying_class,
+ tree expr,
+ bool done,
+ bool address_p,
+ bool template_p,
+ bool template_arg_p)
{
if (error_operand_p (expr))
return error_mark_node;
+ if (template_p)
+ check_template_keyword (expr);
+
/* If EXPR occurs as the operand of '&', use special handling that
permits a pointer-to-member. */
if (address_p && done)
@@ -1514,7 +1525,13 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done,
return expr;
}
- if (TREE_CODE (expr) == FIELD_DECL)
+ /* Within the scope of a class, turn references to non-static
+ members into expression of the form "this->...". */
+ if (template_arg_p)
+ /* But, within a template argument, we do not want make the
+ transformation, as there is no "this" pointer. */
+ ;
+ else if (TREE_CODE (expr) == FIELD_DECL)
expr = finish_non_static_data_member (expr, current_class_ref,
qualifying_class);
else if (BASELINK_P (expr) && !processing_template_decl)
@@ -2383,6 +2400,13 @@ qualified_name_lookup_error (tree scope, tree name, tree decl)
constant-expression, but a non-constant expression is also
permissible.
+ DONE is true if this expression is a complete postfix-expression;
+ it is false if this expression is followed by '->', '[', '(', etc.
+ ADDRESS_P is true iff this expression is the operand of '&'.
+ TEMPLATE_P is true iff the qualified-id was of the form
+ "A::template B". TEMPLATE_ARG_P is true iff this qualified name
+ appears as a template argument.
+
If an error occurs, and it is the kind of error that might cause
the parser to abort a tentative parse, *ERROR_MSG is filled in. It
is the caller's responsibility to issue the message. *ERROR_MSG
@@ -2401,10 +2425,13 @@ finish_id_expression (tree id_expression,
tree decl,
tree scope,
cp_id_kind *idk,
- tree *qualifying_class,
bool integral_constant_expression_p,
bool allow_non_integral_constant_expression_p,
bool *non_integral_constant_expression_p,
+ bool template_p,
+ bool done,
+ bool address_p,
+ bool template_arg_p,
const char **error_msg)
{
/* Initialize the output parameters. */
@@ -2610,20 +2637,32 @@ finish_id_expression (tree id_expression,
dependent. */
if (scope)
{
- if (TYPE_P (scope))
- *qualifying_class = scope;
/* Since this name was dependent, the expression isn't
constant -- yet. No error is issued because it might
be constant when things are instantiated. */
if (integral_constant_expression_p)
*non_integral_constant_expression_p = true;
- if (TYPE_P (scope) && dependent_type_p (scope))
- return build_nt (SCOPE_REF, scope, id_expression);
- else if (TYPE_P (scope) && DECL_P (decl))
- return convert_from_reference
- (build2 (SCOPE_REF, TREE_TYPE (decl), scope, id_expression));
- else
- return convert_from_reference (decl);
+ if (TYPE_P (scope))
+ {
+ if (address_p && done)
+ decl = finish_qualified_id_expr (scope, decl,
+ done, address_p,
+ template_p,
+ template_arg_p);
+ else if (dependent_type_p (scope))
+ decl = build_qualified_name (/*type=*/NULL_TREE,
+ scope,
+ id_expression,
+ template_p);
+ else if (DECL_P (decl))
+ decl = build_qualified_name (TREE_TYPE (decl),
+ scope,
+ id_expression,
+ template_p);
+ }
+ if (TREE_TYPE (decl))
+ decl = convert_from_reference (decl);
+ return decl;
}
/* A TEMPLATE_ID already contains all the information we
need. */
@@ -2703,14 +2742,20 @@ finish_id_expression (tree id_expression,
mark_used (decl);
if (TREE_CODE (decl) == FIELD_DECL || BASELINK_P (decl))
- *qualifying_class = scope;
+ decl = finish_qualified_id_expr (scope,
+ decl,
+ done,
+ address_p,
+ template_p,
+ template_arg_p);
else
{
tree r = convert_from_reference (decl);
- if (processing_template_decl
- && TYPE_P (scope))
- r = build2 (SCOPE_REF, TREE_TYPE (r), scope, decl);
+ if (processing_template_decl && TYPE_P (scope))
+ r = build_qualified_name (TREE_TYPE (r),
+ scope, decl,
+ template_p);
decl = r;
}
}
@@ -2734,13 +2779,15 @@ finish_id_expression (tree id_expression,
if (!really_overloaded_fn (decl))
mark_used (first_fn);
- if (TREE_CODE (first_fn) == FUNCTION_DECL
+ if (!template_arg_p
+ && TREE_CODE (first_fn) == FUNCTION_DECL
&& DECL_FUNCTION_MEMBER_P (first_fn)
&& !shared_member_p (decl))
{
/* A set of member functions. */
decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0);
- return finish_class_member_access_expr (decl, id_expression);
+ return finish_class_member_access_expr (decl, id_expression,
+ /*template_p=*/false);
}
}
else