OSDN Git Service

* cp-tree.h (cp_id_kind): New type.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 14 Jul 2003 03:04:29 +0000 (03:04 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 14 Jul 2003 03:04:29 +0000 (03:04 +0000)
(unqualified_name_lookup_error): Change prototype.
(unqualified_fn_lookup_error): New function.
(do_identifier): Remove.
(do_scoped_id): Likewise.
(tsubst_copy_and_build): Change prototype.
(reregister_specialization): New function.
(perform_koenig_lookup): Likewise.
(finish_id_expression): Likewise.
* call.c (build_method_call): Adjust call to
unqualified_name_lookup_error.
* decl.c (duplicate_decls): Use reregister_specialization.
* lex.c (is_global): Remove.
(unqualified_name_lookup_error): Return a value.
(do_identifier): Remove.
(do_scoped_id): Likewise.
(identifier_typedecl_value): Remove.
(unqualified_fn_lookup_error): New function.
* parser.c (cp_parser_id_kind): Remove.
(cp_parser_non_constant_id_expression): Remove.
(cp_parser_primary_expression): Use finish_id_expression.
(cp_parser_class_or_namespace_name): Use cp_id_kind, not
cp_parser_id_kind.
(cp_parser_postfix_expression): Use perform_koenig_lookup.
(cp_parser_template_argument): Use cp_id_kind.
(cp_parser_fold_non_dependent_expr): Adjust call to
tsubst_copy_and_build.
* pt.c (unregister_specialization): Rename to ...
(reregister_specialization): This.
(tsubst_friend_function): Use it.
(maybe_fold_nontype_arg): Adjust call to tsubst_copy_and_build.
(tsubst_qualified_id): Likewise.
(tsubst_expr): Likewise.
(tsubst_copy_and_build): Add function_p parameter.  Use
finish_id_expression.  Introduce RECUR macro.
(tsubst_non_call_postfix_expression): New function.
(regenerate_decl_from_template): Use reregister_specialization.
* semantics.c (perform_koenig_lookup): New function.
(finish_id_expression): Likewise.

PR c++/11493
PR c++/11495
* g++.dg/parse/template9.C: Likewise.
* g++.dg/template/crash4.C: New test.
* g++.dg/template/koenig1.C: Likewise.
* g++.old-deja/g++.benjamin/tem03.C: Adjust error markers.
* g++.old-deja/g++.benjamin/tem06.C: Declare "x".
* g++.old-deja/g++.jason/overload33.C: Use this-> when calling
functions.
* g++.old-deja/g++.jason/template36.C: Likewise.
* g++.old-deja/g++.mike/p1989.C: Likewise.
* g++.old-deja/g++.pt/lookup2.C: Use -fpermissive when compiling.
* g++.old-deja/g++.pt/ttp20.C: Use this->.
* g++.old-deja/g++.pt/ttp21.C: Use this->.
* g++.old-deja/g++.pt/typename13.C: Use -fpermissive when
compiling.
* g++.old-deja/g++.pt/union2.C: Use this->.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@69316 138bc75d-0d04-0410-961f-82ee72b054a4

22 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/lex.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/template9.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/crash4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/koenig1.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.benjamin/tem03.C
gcc/testsuite/g++.old-deja/g++.benjamin/tem06.C
gcc/testsuite/g++.old-deja/g++.jason/overload33.C
gcc/testsuite/g++.old-deja/g++.jason/template36.C
gcc/testsuite/g++.old-deja/g++.mike/p1989.C
gcc/testsuite/g++.old-deja/g++.pt/lookup2.C
gcc/testsuite/g++.old-deja/g++.pt/ttp20.C
gcc/testsuite/g++.old-deja/g++.pt/ttp21.C
gcc/testsuite/g++.old-deja/g++.pt/typename13.C
gcc/testsuite/g++.old-deja/g++.pt/union2.C

index b275e80..c096405 100644 (file)
@@ -1,3 +1,45 @@
+2003-07-13  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.h (cp_id_kind): New type.
+       (unqualified_name_lookup_error): Change prototype.
+       (unqualified_fn_lookup_error): New function.
+       (do_identifier): Remove.
+       (do_scoped_id): Likewise.
+       (tsubst_copy_and_build): Change prototype.
+       (reregister_specialization): New function.
+       (perform_koenig_lookup): Likewise.
+       (finish_id_expression): Likewise.
+       * call.c (build_method_call): Adjust call to
+       unqualified_name_lookup_error.
+       * decl.c (duplicate_decls): Use reregister_specialization.
+       * lex.c (is_global): Remove.
+       (unqualified_name_lookup_error): Return a value.
+       (do_identifier): Remove.
+       (do_scoped_id): Likewise.
+       (identifier_typedecl_value): Remove.
+       (unqualified_fn_lookup_error): New function.
+       * parser.c (cp_parser_id_kind): Remove.
+       (cp_parser_non_constant_id_expression): Remove.
+       (cp_parser_primary_expression): Use finish_id_expression.
+       (cp_parser_class_or_namespace_name): Use cp_id_kind, not
+       cp_parser_id_kind.
+       (cp_parser_postfix_expression): Use perform_koenig_lookup.
+       (cp_parser_template_argument): Use cp_id_kind.
+       (cp_parser_fold_non_dependent_expr): Adjust call to
+       tsubst_copy_and_build.
+       * pt.c (unregister_specialization): Rename to ...
+       (reregister_specialization): This.
+       (tsubst_friend_function): Use it.
+       (maybe_fold_nontype_arg): Adjust call to tsubst_copy_and_build.
+       (tsubst_qualified_id): Likewise.
+       (tsubst_expr): Likewise.
+       (tsubst_copy_and_build): Add function_p parameter.  Use
+       finish_id_expression.  Introduce RECUR macro.
+       (tsubst_non_call_postfix_expression): New function.
+       (regenerate_decl_from_template): Use reregister_specialization.
+       * semantics.c (perform_koenig_lookup): New function.
+       (finish_id_expression): Likewise.
+       
 2003-07-13  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
 
        * pt.c (push_access_scope_real): Remove.
index 6659592..39f8221 100644 (file)
@@ -423,10 +423,7 @@ build_method_call (tree instance, tree name, tree parms,
 
   /* If the name could not be found, issue an error.  */
   if (!fn)
-    {
-      unqualified_name_lookup_error (name);
-      return error_mark_node;
-    }
+    return unqualified_name_lookup_error (name);
 
   if (BASELINK_P (fn) && has_template_args)
     BASELINK_FUNCTIONS (fn)
index c713191..24fd278 100644 (file)
@@ -350,6 +350,20 @@ struct tree_wrapper GTY(())
   struct z_candidate *z_c;
 };
 
+/* The different kinds of ids that we ecounter.  */
+
+typedef enum cp_id_kind
+{
+  /* Not an id at all.  */
+  CP_ID_KIND_NONE,
+  /* An unqualified-id that is not a template-id.  */
+  CP_ID_KIND_UNQUALIFIED,
+  /* An unqualified template-id.  */
+  CP_ID_KIND_TEMPLATE_ID,
+  /* A qualified-id.  */
+  CP_ID_KIND_QUALIFIED
+} cp_id_kind;
+
 /* Macros for access to language-specific slots in an identifier.  */
 
 #define IDENTIFIER_NAMESPACE_BINDINGS(NODE)    \
@@ -3883,10 +3897,8 @@ extern void snarf_method                 (tree);
 extern void note_got_semicolon                 (tree);
 extern void note_list_got_semicolon            (tree);
 extern void see_typename                       (void);
-extern void unqualified_name_lookup_error       (tree);
-extern tree do_identifier                      (tree, tree);
-extern tree do_scoped_id                       (tree, tree);
-extern tree identifier_typedecl_value          (tree);
+extern tree unqualified_name_lookup_error       (tree);
+extern tree unqualified_fn_lookup_error         (tree);
 extern tree build_lang_decl                    (enum tree_code, tree, tree);
 extern void retrofit_lang_decl                 (tree);
 extern tree copy_decl                           (tree);
@@ -3963,7 +3975,7 @@ extern tree most_specialized_instantiation      (tree);
 extern void print_candidates                    (tree);
 extern int instantiate_pending_templates        (void);
 extern tree tsubst_default_argument             (tree, tree, tree);
-extern tree tsubst_copy_and_build               (tree, tree, tsubst_flags_t, tree);
+extern tree tsubst_copy_and_build               (tree, tree, tsubst_flags_t, tree, bool);
 extern tree most_general_template              (tree);
 extern tree get_mostly_instantiated_function_type (tree);
 extern int problematic_instantiation_changed    (void);
@@ -3982,6 +3994,7 @@ extern tree resolve_typename_type               (tree, bool);
 extern tree template_for_substitution           (tree);
 extern tree build_non_dependent_expr            (tree);
 extern tree build_non_dependent_args            (tree);
+extern bool reregister_specialization           (tree, tree, tree);
 
 /* in repo.c */
 extern void repo_template_used (tree);
@@ -4111,6 +4124,7 @@ extern tree finish_parenthesized_expr           (tree);
 extern tree finish_non_static_data_member       (tree, tree);
 extern tree begin_stmt_expr                     (void);
 extern tree finish_stmt_expr                    (tree);
+extern tree perform_koenig_lookup               (tree, tree);
 extern tree finish_call_expr                    (tree, tree, bool);
 extern tree finish_increment_expr               (tree, enum tree_code);
 extern tree finish_this_expr                    (void);
@@ -4133,6 +4147,10 @@ extern tree finish_template_type                (tree, tree, int);
 extern tree finish_base_specifier               (tree, tree, bool);
 extern void finish_member_declaration           (tree);
 extern void check_multiple_declarators          (void);
+extern tree finish_id_expression                (tree, tree, tree,
+                                                cp_id_kind *, tree *,
+                                                bool, bool, bool *, 
+                                                const char **);
 extern tree finish_typeof                      (tree);
 extern tree finish_sizeof                      (tree);
 extern tree finish_alignof                     (tree);
index be2846b..d4c212f 100644 (file)
@@ -3558,36 +3558,30 @@ duplicate_decls (tree newdecl, tree olddecl)
              function_size - sizeof (struct tree_common));
 
       if (DECL_TEMPLATE_INSTANTIATION (newdecl))
-       {
-         /* If newdecl is a template instantiation, it is possible that
-            the following sequence of events has occurred:
-
-            o A friend function was declared in a class template.  The
-            class template was instantiated.
-
-            o The instantiation of the friend declaration was
-            recorded on the instantiation list, and is newdecl.
-
-            o Later, however, instantiate_class_template called pushdecl
-            on the newdecl to perform name injection.  But, pushdecl in
-            turn called duplicate_decls when it discovered that another
-            declaration of a global function with the same name already
-            existed.
-
-            o Here, in duplicate_decls, we decided to clobber newdecl.
-
-            If we're going to do that, we'd better make sure that
-            olddecl, and not newdecl, is on the list of
-            instantiations so that if we try to do the instantiation
-            again we won't get the clobbered declaration.  */
-
-         tree tmpl = DECL_TI_TEMPLATE (newdecl);
-         tree decls = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
-
-         for (; decls; decls = TREE_CHAIN (decls))
-           if (TREE_VALUE (decls) == newdecl)
-             TREE_VALUE (decls) = olddecl;
-       }
+       /* If newdecl is a template instantiation, it is possible that
+          the following sequence of events has occurred:
+
+          o A friend function was declared in a class template.  The
+          class template was instantiated.
+
+          o The instantiation of the friend declaration was
+          recorded on the instantiation list, and is newdecl.
+
+          o Later, however, instantiate_class_template called pushdecl
+          on the newdecl to perform name injection.  But, pushdecl in
+          turn called duplicate_decls when it discovered that another
+          declaration of a global function with the same name already
+          existed.
+
+          o Here, in duplicate_decls, we decided to clobber newdecl.
+
+          If we're going to do that, we'd better make sure that
+          olddecl, and not newdecl, is on the list of
+          instantiations so that if we try to do the instantiation
+          again we won't get the clobbered declaration.  */
+       reregister_specialization (newdecl, 
+                                  DECL_TI_TEMPLATE (newdecl), 
+                                  olddecl);
     }
   else
     {
index 7d63e2c..eb0287c 100644 (file)
@@ -49,7 +49,6 @@ static void handle_pragma_interface (cpp_reader *);
 static void handle_pragma_implementation (cpp_reader *);
 static void handle_pragma_java_exceptions (cpp_reader *);
 
-static int is_global (tree);
 static void init_operators (void);
 static void copy_lang_type (tree);
 
@@ -662,30 +661,10 @@ handle_pragma_java_exceptions (cpp_reader* dfile ATTRIBUTE_UNUSED )
   choose_personality_routine (lang_java);
 }
 
-/* Return true if d is in a global scope.  */
-
-static int
-is_global (tree d)
-{
-  while (1)
-    switch (TREE_CODE (d))
-      {
-      case ERROR_MARK:
-       return 1;
-
-      case OVERLOAD: d = OVL_FUNCTION (d); continue;
-      case TREE_LIST: d = TREE_VALUE (d); continue;
-      default:
-        my_friendly_assert (DECL_P (d), 980629);
-
-       return DECL_NAMESPACE_SCOPE_P (d);
-      }
-}
-
 /* Issue an error message indicating that the lookup of NAME (an
-   IDENTIFIER_NODE) failed.  */
+   IDENTIFIER_NODE) failed.  Returns the ERROR_MARK_NODE.  */
 
-void
+tree
 unqualified_name_lookup_error (tree name)
 {
   if (IDENTIFIER_OPNAME_P (name))
@@ -714,164 +693,43 @@ unqualified_name_lookup_error (tree name)
       SET_IDENTIFIER_NAMESPACE_VALUE (name, error_mark_node);
       SET_IDENTIFIER_ERROR_LOCUS (name, current_function_decl);
     }
-}
-
-tree
-do_identifier (register tree token, tree args)
-{
-  register tree id;
-
-  timevar_push (TV_NAME_LOOKUP);
-  id = lookup_name (token, 0);
-
-  /* Do Koenig lookup if appropriate (inside templates we build lookup
-     expressions instead).
-
-     [basic.lookup.koenig]: If the ordinary unqualified lookup of the name
-     finds the declaration of a class member function, the associated
-     namespaces and classes are not considered.  */
-
-  if (args && !current_template_parms && (!id || is_global (id)))
-    id = lookup_arg_dependent (token, id, args);
-
-  if (id == error_mark_node)
-    {
-      /* lookup_name quietly returns error_mark_node if we're parsing,
-        as we don't want to complain about an identifier that ends up
-        being used as a declarator.  So we call it again to get the error
-        message.  */
-      id = lookup_name (token, 0);
-      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
-    }
 
-  if (!id || (TREE_CODE (id) == FUNCTION_DECL
-             && DECL_ANTICIPATED (id)))
-    {
-      if (current_template_parms)
-        POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
-                                build_min_nt (LOOKUP_EXPR, token));
-      else if (IDENTIFIER_TYPENAME_P (token))
-       /* A templated conversion operator might exist.  */
-       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, token);
-      else
-       {
-         unqualified_name_lookup_error (token);
-         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
-       }
-    }
-
-  id = check_for_out_of_scope_variable (id);
-
-  /* TREE_USED is set in `hack_identifier'.  */
-  if (TREE_CODE (id) == CONST_DECL)
-    {
-      /* Check access.  */
-      if (IDENTIFIER_CLASS_VALUE (token) == id)
-       perform_or_defer_access_check (TYPE_BINFO (DECL_CONTEXT (id)), id);
-      if (!processing_template_decl || DECL_TEMPLATE_PARM_P (id))
-       id = DECL_INITIAL (id);
-    }
-  else
-    id = hack_identifier (id, token);
-
-  /* We must look up dependent names when the template is
-     instantiated, not while parsing it.  For now, we don't
-     distinguish between dependent and independent names.  So, for
-     example, we look up all overloaded functions at
-     instantiation-time, even though in some cases we should just use
-     the DECL we have here.  We also use LOOKUP_EXPRs to find things
-     like local variables, rather than creating TEMPLATE_DECLs for the
-     local variables and then finding matching instantiations.  */
-  if (current_template_parms
-      && (is_overloaded_fn (id)
-         || (TREE_CODE (id) == VAR_DECL
-             && CP_DECL_CONTEXT (id)
-             && TREE_CODE (CP_DECL_CONTEXT (id)) == FUNCTION_DECL)
-         || TREE_CODE (id) == PARM_DECL
-         || TREE_CODE (id) == RESULT_DECL
-         || TREE_CODE (id) == USING_DECL))
-    id = build_min_nt (LOOKUP_EXPR, token);
-
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, id);
+  return error_mark_node;
 }
 
+/* Like unqualified_name_lookup_error, but NAME is an unqualified-id
+   used as a function.  Returns an appropriate expression for
+   NAME.  */
+
 tree
-do_scoped_id (tree token, tree id)
+unqualified_fn_lookup_error (tree name)
 {
-  timevar_push (TV_NAME_LOOKUP);
-  if (!id || (TREE_CODE (id) == FUNCTION_DECL
-             && DECL_ANTICIPATED (id)))
-    {
-      if (processing_template_decl)
-       {
-         id = build_min_nt (LOOKUP_EXPR, token);
-         LOOKUP_EXPR_GLOBAL (id) = 1;
-         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, id);
-       }
-      if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node)
-        error ("`::%D' undeclared (first use here)", token);
-      id = error_mark_node;
-      /* Prevent repeated error messages.  */
-      SET_IDENTIFIER_NAMESPACE_VALUE (token, error_mark_node);
-    }
-  else
-    {
-      if (TREE_CODE (id) == ADDR_EXPR)
-       mark_used (TREE_OPERAND (id, 0));
-      else if (TREE_CODE (id) != OVERLOAD)
-       mark_used (id);
-    }
-  if (TREE_CODE (id) == CONST_DECL && ! processing_template_decl)
-    {
-      /* XXX CHS - should we set TREE_USED of the constant? */
-      id = DECL_INITIAL (id);
-      /* This is to prevent an enum whose value is 0
-        from being considered a null pointer constant.  */
-      id = build1 (NOP_EXPR, TREE_TYPE (id), id);
-      TREE_CONSTANT (id) = 1;
-    }
-
   if (processing_template_decl)
     {
-      if (is_overloaded_fn (id))
+      /* In a template, it is invalid to write "f()" or "f(3)" if no
+        declaration of "f" is available.  Historically, G++ and most
+        other compilers accepted that usage; explain to the user what
+        is going wrong.  */
+      (flag_permissive ? warning : error)
+       ("there are no arguments to `%D' that depend on a template "
+        "parameter, so a declaration of `%D' must be available", name,
+        name);
+      
+      if (!flag_permissive)
        {
-         id = build_min_nt (LOOKUP_EXPR, token);
-         LOOKUP_EXPR_GLOBAL (id) = 1;
-         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, id);
+         static bool hint;
+         if (!hint)
+           {
+             error ("(if you use `-fpermissive', G++ will accept your code, "
+                    "but allowing the use of an undeclared name is "
+                    "deprecated)");
+             hint = true;
+           }
        }
-      /* else just use the decl */
+      return build_min_nt (LOOKUP_EXPR, name);
     }
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, convert_from_reference (id));
-}
-
-tree
-identifier_typedecl_value (tree node)
-{
-  tree t, type;
-  type = IDENTIFIER_TYPE_VALUE (node);
-  if (type == NULL_TREE)
-    return NULL_TREE;
-
-  if (IDENTIFIER_BINDING (node))
-    {
-      t = IDENTIFIER_VALUE (node);
-      if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
-       return t;
-    }
-  if (IDENTIFIER_NAMESPACE_VALUE (node))
-    {
-      t = IDENTIFIER_NAMESPACE_VALUE (node);
-      if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
-       return t;
-    }
-
-  /* Will this one ever happen?  */
-  if (TYPE_MAIN_DECL (type))
-    return TYPE_MAIN_DECL (type);
 
-  /* We used to do an internal error of 62 here, but instead we will
-     handle the return of a null appropriately in the callers.  */
-  return NULL_TREE;
+  return unqualified_name_lookup_error (name);
 }
 
 #ifdef GATHER_STATISTICS
index 33c88b1..98411a6 100644 (file)
@@ -1047,20 +1047,6 @@ typedef enum cp_parser_flags
   CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2
 } cp_parser_flags;
 
-/* The different kinds of ids that we ecounter.  */
-
-typedef enum cp_parser_id_kind
-{
-  /* Not an id at all.  */
-  CP_PARSER_ID_KIND_NONE,
-  /* An unqualified-id that is not a template-id.  */
-  CP_PARSER_ID_KIND_UNQUALIFIED,
-  /* An unqualified template-id.  */
-  CP_PARSER_ID_KIND_TEMPLATE_ID,
-  /* A qualified-id.  */
-  CP_PARSER_ID_KIND_QUALIFIED
-} cp_parser_id_kind;
-
 /* The different kinds of declarators we want to parse.  */
 
 typedef enum cp_parser_declarator_kind
@@ -1311,7 +1297,7 @@ static bool cp_parser_translation_unit
 /* Expressions [gram.expr]  */
 
 static tree cp_parser_primary_expression
-  (cp_parser *, cp_parser_id_kind *, tree *);
+  (cp_parser *, cp_id_kind *, tree *);
 static tree cp_parser_id_expression
   (cp_parser *, bool, bool, bool *);
 static tree cp_parser_unqualified_id
@@ -1695,8 +1681,6 @@ static void cp_parser_check_type_definition
   (cp_parser *);
 static tree cp_parser_non_constant_expression
   (const char *);
-static tree cp_parser_non_constant_id_expression
-  (tree);
 static bool cp_parser_diagnose_invalid_type_name
   (cp_parser *);
 static int cp_parser_skip_to_closing_parenthesis
@@ -1794,16 +1778,6 @@ cp_parser_non_constant_expression (const char *thing)
   return error_mark_node;
 }
 
-/* Issue an eror message about the fact that DECL appeared in a
-   constant-expression.  Returns ERROR_MARK_NODE.  */
-
-static tree
-cp_parser_non_constant_id_expression (tree decl)
-{
-  error ("`%D' cannot appear in a constant-expression", decl);
-  return error_mark_node;
-}
-
 /* Check for a common situation where a type-name should be present,
    but is not, and issue a sensible error message.  Returns true if an
    invalid type-name was detected.  */
@@ -2215,13 +2189,13 @@ cp_parser_translation_unit (cp_parser* parser)
 
 static tree
 cp_parser_primary_expression (cp_parser *parser, 
-                             cp_parser_id_kind *idk,
+                             cp_id_kind *idk,
                              tree *qualifying_class)
 {
   cp_token *token;
 
   /* Assume the primary expression is not an id-expression.  */
-  *idk = CP_PARSER_ID_KIND_NONE;
+  *idk = CP_ID_KIND_NONE;
   /* And that it cannot be used as pointer-to-member.  */
   *qualifying_class = NULL_TREE;
 
@@ -2397,6 +2371,7 @@ cp_parser_primary_expression (cp_parser *parser,
       {
        tree id_expression;
        tree decl;
+       const char *error_msg;
 
       id_expression:
        /* Parse the id-expression.  */
@@ -2457,281 +2432,16 @@ cp_parser_primary_expression (cp_parser *parser,
                    return error_mark_node;
                  }
              }
-
-           if (decl == error_mark_node)
-             {
-               /* Name lookup failed.  */
-               if (!parser->scope 
-                   && processing_template_decl)
-                 {
-                   /* Unqualified name lookup failed while processing a
-                      template.  */
-                   *idk = CP_PARSER_ID_KIND_UNQUALIFIED;
-                   /* If the next token is a parenthesis, assume that
-                      Koenig lookup will succeed when instantiating the
-                      template.  */
-                   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
-                     return build_min_nt (LOOKUP_EXPR, id_expression);
-                   /* If we're not doing Koenig lookup, issue an error.  */
-                   error ("`%D' has not been declared", id_expression);
-                   return error_mark_node;
-                 }
-               else if (parser->scope
-                        && (!TYPE_P (parser->scope)
-                            || !dependent_type_p (parser->scope)))
-                 {
-                   /* Qualified name lookup failed, and the
-                      qualifying name was not a dependent type.  That
-                      is always an error.  */
-                   if (TYPE_P (parser->scope)
-                       && !COMPLETE_TYPE_P (parser->scope))
-                     error ("incomplete type `%T' used in nested name "
-                            "specifier",
-                            parser->scope);
-                   else if (parser->scope != global_namespace)
-                     error ("`%D' is not a member of `%D'",
-                            id_expression, parser->scope);
-                   else
-                     error ("`::%D' has not been declared", id_expression);
-                   return error_mark_node;
-                 }
-               else if (!parser->scope && !processing_template_decl)
-                 {
-                   /* It may be resolvable as a koenig lookup function
-                      call.  */
-                   *idk = CP_PARSER_ID_KIND_UNQUALIFIED;
-                   return id_expression;
-                 }
-             }
-           /* If DECL is a variable that would be out of scope under
-              ANSI/ISO rules, but in scope in the ARM, name lookup
-              will succeed.  Issue a diagnostic here.  */
-           else
-             decl = check_for_out_of_scope_variable (decl);
-
-           /* Remember that the name was used in the definition of
-              the current class so that we can check later to see if
-              the meaning would have been different after the class
-              was entirely defined.  */
-           if (!parser->scope && decl != error_mark_node)
-             maybe_note_name_used_in_class (id_expression, decl);
-         }
-
-       /* If we didn't find anything, or what we found was a type,
-          then this wasn't really an id-expression.  */
-       if (TREE_CODE (decl) == TEMPLATE_DECL
-           && !DECL_FUNCTION_TEMPLATE_P (decl))
-         {
-           cp_parser_error (parser, "missing template arguments");
-           return error_mark_node;
          }
-       else if (TREE_CODE (decl) == TYPE_DECL
-                || TREE_CODE (decl) == NAMESPACE_DECL)
-         {
-           cp_parser_error (parser, 
-                            "expected primary-expression");
-           return error_mark_node;
-         }
-
-       /* If the name resolved to a template parameter, there is no
-          need to look it up again later.  Similarly, we resolve
-          enumeration constants to their underlying values.  */
-       if (TREE_CODE (decl) == CONST_DECL)
-         {
-           *idk = CP_PARSER_ID_KIND_NONE;
-           if (DECL_TEMPLATE_PARM_P (decl) || !processing_template_decl)
-             return DECL_INITIAL (decl);
-           return decl;
-         }
-       else
-         {
-           bool dependent_p;
-
-           /* If the declaration was explicitly qualified indicate
-              that.  The semantics of `A::f(3)' are different than
-              `f(3)' if `f' is virtual.  */
-           *idk = (parser->scope 
-                   ? CP_PARSER_ID_KIND_QUALIFIED
-                   : (TREE_CODE (decl) == TEMPLATE_ID_EXPR
-                      ? CP_PARSER_ID_KIND_TEMPLATE_ID
-                      : CP_PARSER_ID_KIND_UNQUALIFIED));
-
-
-           /* [temp.dep.expr]
-              
-              An id-expression is type-dependent if it contains an
-              identifier that was declared with a dependent type.
-              
-              As an optimization, we could choose not to create a
-              LOOKUP_EXPR for a name that resolved to a local
-              variable in the template function that we are currently
-              declaring; such a name cannot ever resolve to anything
-              else.  If we did that we would not have to look up
-              these names at instantiation time.
-              
-              The standard is not very specific about an
-              id-expression that names a set of overloaded functions.
-              What if some of them have dependent types and some of
-              them do not?  Presumably, such a name should be treated
-              as a dependent name.  */
-           /* Assume the name is not dependent.  */
-           dependent_p = false;
-           if (!processing_template_decl)
-             /* No names are dependent outside a template.  */
-             ;
-           /* A template-id where the name of the template was not
-              resolved is definitely dependent.  */
-           else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
-                    && (TREE_CODE (TREE_OPERAND (decl, 0)) 
-                        == IDENTIFIER_NODE))
-             dependent_p = true;
-           /* For anything except an overloaded function, just check
-              its type.  */
-           else if (!is_overloaded_fn (decl))
-             dependent_p 
-               = dependent_type_p (TREE_TYPE (decl));
-           /* For a set of overloaded functions, check each of the
-              functions.  */
-           else
-             {
-               tree fns = decl;
-
-               if (BASELINK_P (fns))
-                 fns = BASELINK_FUNCTIONS (fns);
-                 
-               /* For a template-id, check to see if the template
-                  arguments are dependent.  */
-               if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
-                 {
-                   tree args = TREE_OPERAND (fns, 1);
-                   dependent_p = any_dependent_template_arguments_p (args);
-                   /* The functions are those referred to by the
-                      template-id.  */
-                   fns = TREE_OPERAND (fns, 0);
-                 }
-
-               /* If there are no dependent template arguments, go
-                  through the overlaoded functions.  */
-               while (fns && !dependent_p)
-                 {
-                   tree fn = OVL_CURRENT (fns);
-                   
-                   /* Member functions of dependent classes are
-                      dependent.  */
-                   if (TREE_CODE (fn) == FUNCTION_DECL
-                       && type_dependent_expression_p (fn))
-                     dependent_p = true;
-                   else if (TREE_CODE (fn) == TEMPLATE_DECL
-                            && dependent_template_p (fn))
-                     dependent_p = true;
-                   
-                   fns = OVL_NEXT (fns);
-                 }
-             }
-
-           /* If the name was dependent on a template parameter,
-              we will resolve the name at instantiation time.  */
-           if (dependent_p)
-             {
-               /* Create a SCOPE_REF for qualified names, if the
-                  scope is dependent.  */
-               if (parser->scope)
-                 {
-                   if (TYPE_P (parser->scope))
-                     *qualifying_class = parser->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 (parser->constant_expression_p)
-                     parser->non_constant_expression_p = true;
-                   if (TYPE_P (parser->scope)
-                       && dependent_type_p (parser->scope))
-                     return build_nt (SCOPE_REF, 
-                                      parser->scope, 
-                                      id_expression);
-                   else if (TYPE_P (parser->scope)
-                            && DECL_P (decl))
-                     return build (SCOPE_REF,
-                                   TREE_TYPE (decl),
-                                   parser->scope,
-                                   id_expression);
-                   else
-                     return decl;
-                 }
-               /* A TEMPLATE_ID already contains all the information
-                  we need.  */
-               if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR)
-                 return id_expression;
-               /* 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 (parser->constant_expression_p)
-                 parser->non_constant_expression_p = true;
-               /* Create a LOOKUP_EXPR for other unqualified names.  */
-               return build_min_nt (LOOKUP_EXPR, id_expression);
-             }
-
-           /* Only certain kinds of names are allowed in constant
-              expression.  Enumerators have already been handled
-              above.  */
-           if (parser->constant_expression_p)
-             {
-               /* Non-type template parameters of integral or
-                  enumeration type are OK.  */
-               if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX
-                   && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
-                 ;
-               /* Const variables or static data members of integral
-                  or enumeration types initialized with constant
-                   expressions are OK.  We also accept dependent
-                  initializers; they may turn out to be constant at
-                  instantiation-time.  */
-               else if (TREE_CODE (decl) == VAR_DECL
-                        && CP_TYPE_CONST_P (TREE_TYPE (decl))
-                        && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
-                        && DECL_INITIAL (decl)
-                        && (TREE_CONSTANT (DECL_INITIAL (decl))
-                            || type_dependent_expression_p (DECL_INITIAL 
-                                                            (decl))
-                            || value_dependent_expression_p (DECL_INITIAL 
-                                                             (decl))))
-                 ;
-               else
-                 {
-                   if (!parser->allow_non_constant_expression_p)
-                     return cp_parser_non_constant_id_expression (decl);
-                   parser->non_constant_expression_p = true;
-                 }
-             }
-
-           if (parser->scope)
-             {
-               decl = (adjust_result_of_qualified_name_lookup 
-                       (decl, parser->scope, current_class_type));
-               if (TREE_CODE (decl) == FIELD_DECL || BASELINK_P (decl))
-                 *qualifying_class = parser->scope;
-               else if (!processing_template_decl)
-                 decl = convert_from_reference (decl);
-               else if (TYPE_P (parser->scope))
-                 decl = build (SCOPE_REF,
-                               TREE_TYPE (decl),
-                               parser->scope,
-                               decl);
-             }
-           else
-             /* Transform references to non-static data members into
-                COMPONENT_REFs.  */
-             decl = hack_identifier (decl, id_expression);
-
-           /* Resolve references to variables of anonymous unions
-              into COMPONENT_REFs.  */
-           if (TREE_CODE (decl) == ALIAS_DECL)
-             decl = DECL_INITIAL (decl);
-         }
-
-       if (TREE_DEPRECATED (decl))
-         warn_deprecated_use (decl);
-
+       
+       decl = finish_id_expression (id_expression, decl, parser->scope, 
+                                    idk, qualifying_class,
+                                    parser->constant_expression_p,
+                                    parser->allow_non_constant_expression_p,
+                                    &parser->non_constant_expression_p,
+                                    &error_msg);
+       if (error_msg)
+         cp_parser_error (parser, error_msg);
        return decl;
       }
 
@@ -3463,7 +3173,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
 {
   cp_token *token;
   enum rid keyword;
-  cp_parser_id_kind idk = CP_PARSER_ID_KIND_NONE;
+  cp_id_kind idk = CP_ID_KIND_NONE;
   tree postfix_expression = NULL_TREE;
   /* Non-NULL only if the current postfix-expression can be used to
      form a pointer-to-member.  In that case, QUALIFYING_CLASS is the
@@ -3730,11 +3440,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
     {
       if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE
          && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
-       {
-         /* It is not a Koenig lookup function call.  */
-         unqualified_name_lookup_error (postfix_expression);
-         postfix_expression = error_mark_node;
-       }
+       /* It is not a Koenig lookup function call.  */
+       postfix_expression 
+         = unqualified_name_lookup_error (postfix_expression);
       
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
@@ -3756,7 +3464,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
            /* Build the ARRAY_REF.  */
            postfix_expression 
              = grok_array_decl (postfix_expression, index);
-           idk = CP_PARSER_ID_KIND_NONE;
+           idk = CP_ID_KIND_NONE;
          }
          break;
 
@@ -3780,58 +3488,17 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                parser->non_constant_expression_p = true;
              }
 
-           if (idk == CP_PARSER_ID_KIND_UNQUALIFIED
+           if (idk == CP_ID_KIND_UNQUALIFIED
                && (is_overloaded_fn (postfix_expression)
                    || DECL_P (postfix_expression)
                    || TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
                && args)
-             {
-               tree identifier = NULL_TREE;
-               tree functions = NULL_TREE;
-
-               /* Find the name of the overloaded function.  */
-               if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
-                 identifier = postfix_expression;
-               else if (is_overloaded_fn (postfix_expression))
-                 {
-                   functions = postfix_expression;
-                   identifier = DECL_NAME (get_first_fn (functions));
-                 }
-               else if (DECL_P (postfix_expression))
-                 {
-                   functions = postfix_expression;
-                   identifier = DECL_NAME (postfix_expression);
-                 }
-
-               /* A call to a namespace-scope function using an
-                  unqualified name.
-
-                  Do Koenig lookup -- unless any of the arguments are
-                  type-dependent.  */
-               if (!any_type_dependent_arguments_p (args))
-                 {
-                   postfix_expression 
-                     = lookup_arg_dependent (identifier, functions, args);
-                   if (!postfix_expression)
-                     {
-                       /* The unqualified name could not be resolved.  */
-                       unqualified_name_lookup_error (identifier);
-                       postfix_expression = error_mark_node;
-                       break;
-                     }
-                 }
-               else
-                 postfix_expression = build_min_nt (LOOKUP_EXPR,
-                                                    identifier);
-             }
-           else if (idk == CP_PARSER_ID_KIND_UNQUALIFIED 
+             postfix_expression 
+               = perform_koenig_lookup (postfix_expression, args);
+           else if (idk == CP_ID_KIND_UNQUALIFIED 
                     && TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
-             {
-               /* The unqualified name could not be resolved.  */
-               unqualified_name_lookup_error (postfix_expression);
-               postfix_expression = error_mark_node;
-               break;
-             }
+             postfix_expression
+               = unqualified_fn_lookup_error (postfix_expression);
 
            if (TREE_CODE (postfix_expression) == COMPONENT_REF)
              {
@@ -3853,7 +3520,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                postfix_expression
                  = (build_new_method_call 
                     (instance, fn, args, NULL_TREE, 
-                     (idk == CP_PARSER_ID_KIND_QUALIFIED 
+                     (idk == CP_ID_KIND_QUALIFIED 
                       ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
              }
            else if (TREE_CODE (postfix_expression) == OFFSET_REF
@@ -3861,7 +3528,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                     || TREE_CODE (postfix_expression) == DOTSTAR_EXPR)
              postfix_expression = (build_offset_ref_call_from_tree
                                    (postfix_expression, args));
-           else if (idk == CP_PARSER_ID_KIND_QUALIFIED)
+           else if (idk == CP_ID_KIND_QUALIFIED)
              /* A call to a static class member, or a namespace-scope
                 function.  */
              postfix_expression
@@ -3874,7 +3541,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                                    /*disallow_virtual=*/false);
 
            /* The POSTFIX_EXPRESSION is certainly no longer an id.  */
-           idk = CP_PARSER_ID_KIND_NONE;
+           idk = CP_ID_KIND_NONE;
          }
          break;
          
@@ -3901,7 +3568,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
            parser->scope = NULL_TREE;
            parser->qualifying_scope = NULL_TREE;
            parser->object_scope = NULL_TREE;
-           idk = CP_PARSER_ID_KIND_NONE;
+           idk = CP_ID_KIND_NONE;
            /* Enter the scope corresponding to the type of the object
               given by the POSTFIX_EXPRESSION.  */
            if (!dependent_p 
@@ -3969,7 +3636,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                /* But we do need to remember that there was an explicit
                   scope for virtual function calls.  */
                if (parser->scope)
-                 idk = CP_PARSER_ID_KIND_QUALIFIED;
+                 idk = CP_ID_KIND_QUALIFIED;
 
                if (name != error_mark_node 
                    && !BASELINK_P (name)
@@ -4019,7 +3686,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
          postfix_expression 
            = finish_increment_expr (postfix_expression, 
                                     POSTINCREMENT_EXPR);
-         idk = CP_PARSER_ID_KIND_NONE;
+         idk = CP_ID_KIND_NONE;
          break;
 
        case CPP_MINUS_MINUS:
@@ -4037,7 +3704,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
          postfix_expression 
            = finish_increment_expr (postfix_expression, 
                                     POSTDECREMENT_EXPR);
-         idk = CP_PARSER_ID_KIND_NONE;
+         idk = CP_ID_KIND_NONE;
          break;
 
        default:
@@ -8065,7 +7732,7 @@ cp_parser_template_argument (cp_parser* parser)
   bool template_p;
   bool address_p;
   cp_token *token;
-  cp_parser_id_kind idk;
+  cp_id_kind idk;
   tree qualifying_class;
 
   /* There's really no way to know what we're looking at, so we just
@@ -14184,7 +13851,8 @@ cp_parser_fold_non_dependent_expr (tree expr)
       expr = tsubst_copy_and_build (expr,
                                    /*args=*/NULL_TREE,
                                    tf_error,
-                                   /*in_decl=*/NULL_TREE);
+                                   /*in_decl=*/NULL_TREE,
+                                   /*function_p=*/false);
       processing_template_decl = saved_processing_template_decl;
     }
   return expr;
index d7c56a2..37ec868 100644 (file)
@@ -125,7 +125,6 @@ static tree retrieve_specialization (tree, tree);
 static tree retrieve_local_specialization (tree);
 static tree register_specialization (tree, tree, tree);
 static void register_local_specialization (tree, tree);
-static int unregister_specialization (tree, tree);
 static tree reduce_template_parm_level (tree, tree, int);
 static tree build_template_decl (tree, tree);
 static int mark_template_parm (tree, void *);
@@ -987,11 +986,11 @@ register_specialization (tree spec, tree tmpl, tree args)
 }
 
 /* Unregister the specialization SPEC as a specialization of TMPL.
-   Returns nonzero if the SPEC was listed as a specialization of
-   TMPL.  */
+   Replace it with NEW_SPEC, if NEW_SPEC is non-NULL.  Returns true
+   if the SPEC was listed as a specialization of TMPL.  */
 
-static int
-unregister_specialization (tree spec, tree tmpl)
+bool
+reregister_specialization (tree spec, tree tmpl, tree new_spec)
 {
   tree* s;
 
@@ -1000,7 +999,10 @@ unregister_specialization (tree spec, tree tmpl)
        s = &TREE_CHAIN (*s))
     if (TREE_VALUE (*s) == spec)
       {
-       *s = TREE_CHAIN (*s);
+       if (!new_spec)
+         *s = TREE_CHAIN (*s);
+       else
+         TREE_VALUE (*s) == new_spec;
        return 1;
       }
 
@@ -4910,8 +4912,17 @@ tsubst_friend_function (tree decl, tree args)
              DECL_TEMPLATE_INFO (old_decl) = new_friend_template_info;
 
              if (TREE_CODE (old_decl) != TEMPLATE_DECL)
-               /* duplicate_decls will take care of this case.  */
-               ;
+               {
+                 tree t;
+                 tree spec;
+
+                 t = most_general_template (old_decl);
+                 for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t);
+                      spec;
+                      spec = TREE_CHAIN (spec))
+                   if (TREE_VALUE (spec) == new_friend)
+                     TREE_VALUE (spec) = old_decl;
+               }
              else 
                {
                  tree t;
@@ -5503,7 +5514,8 @@ maybe_fold_nontype_arg (tree arg)
          arg = tsubst_copy_and_build (arg,
                                       /*args=*/NULL_TREE,
                                       tf_error,
-                                      /*in_decl=*/NULL_TREE);
+                                      /*in_decl=*/NULL_TREE,
+                                      /*function_p=*/false);
          processing_template_decl = saved_processing_template_decl; 
        }
 
@@ -7071,7 +7083,8 @@ tsubst_baselink (tree baselink, tree object_type,
        template_args = TREE_OPERAND (fns, 1);
        fns = TREE_OPERAND (fns, 0);
        template_args = tsubst_copy_and_build (template_args, args,
-                                              complain, in_decl);
+                                              complain, in_decl,
+                                              /*function_p=*/false);
       }
     name = DECL_NAME (get_first_fn (fns));
     baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1);
@@ -7112,7 +7125,8 @@ tsubst_qualified_id (tree qualified_id, tree args,
     {
       is_template = true;
       template_args = tsubst_copy_and_build (TREE_OPERAND (name, 1), 
-                                            args, complain, in_decl);
+                                            args, complain, in_decl,
+                                            /*function_p=*/false);
       name = TREE_OPERAND (name, 0);
     }
   else
@@ -7549,7 +7563,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     return tsubst_copy (t, args, complain, in_decl);
 
   if (!STATEMENT_CODE_P (TREE_CODE (t)))
-    return tsubst_copy_and_build (t, args, complain, in_decl);
+    return tsubst_copy_and_build (t, args, complain, in_decl,
+                                 /*function_p=*/false);
     
   switch (TREE_CODE (t))
     {
@@ -7857,15 +7872,37 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
   return tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
 }
 
+/* T is a postfix-expression that is not being used in a function
+   call.  Return the substituted version of T.  */
+
+static tree
+tsubst_non_call_postfix_expression (tree t, tree args, 
+                                   tsubst_flags_t complain,
+                                   tree in_decl)
+{
+  if (TREE_CODE (t) == SCOPE_REF)
+    t = tsubst_qualified_id (t, args, complain, in_decl,
+                            /*done=*/false, /*address_p=*/false);
+  else
+    t = tsubst_copy_and_build (t, args, complain, in_decl,
+                              /*function_p=*/false);
+
+  return t;
+}
+
 /* Like tsubst but deals with expressions and performs semantic
-   analysis.  */
+   analysis.  FUNCTION_P is true if T is the "F" in "F (ARGS)".  */
 
 tree
 tsubst_copy_and_build (tree t, 
                        tree args, 
                        tsubst_flags_t complain, 
-                       tree in_decl)
+                       tree in_decl,
+                      bool function_p)
 {
+#define RECUR(NODE) \
+  tsubst_copy_and_build (NODE, args, complain, in_decl, /*function_p=*/false)
+
   tree op1;
 
   if (t == NULL_TREE || t == error_mark_node)
@@ -7873,45 +7910,62 @@ tsubst_copy_and_build (tree t,
 
   switch (TREE_CODE (t))
     {
-    case IDENTIFIER_NODE:
-      if (IDENTIFIER_TYPENAME_P (t))
-       {
-         tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
-         return do_identifier (mangle_conv_op_name_for_type (new_type),
-                               NULL_TREE);
-       }
-      else
-       return do_identifier (t, NULL_TREE);
-
     case LOOKUP_EXPR:
+    case IDENTIFIER_NODE:
       {
-       if (LOOKUP_EXPR_GLOBAL (t))
-         {
-           tree token
-             = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl);
-           return do_scoped_id (token, IDENTIFIER_GLOBAL_VALUE (token));
-         }
+       tree decl;
+       tree scope;
+       cp_id_kind idk;
+       tree qualifying_class;
+       bool non_constant_expression_p;
+       const char *error_msg;
+
+       /* Remember whether this identifier was explicitly qualified
+          with "::".  */
+       if (TREE_CODE (t) == LOOKUP_EXPR && LOOKUP_EXPR_GLOBAL (t))
+         scope = global_namespace;
        else
+         scope = NULL_TREE;
+       /* Get at the underlying identifier.  */
+       if (TREE_CODE (t) == LOOKUP_EXPR)
+         t = TREE_OPERAND (t, 0);
+
+       if (IDENTIFIER_TYPENAME_P (t))
          {
-           t = do_identifier
-             (tsubst_copy
-              (TREE_OPERAND (t, 0), args, complain, in_decl),
-              NULL_TREE);
-           if (TREE_CODE (t) == ALIAS_DECL)
-             t = DECL_INITIAL (t);
-           return t;
+           tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+           t = mangle_conv_op_name_for_type (new_type);
          }
+
+       /* Look up the name.  */
+       if (scope == global_namespace)
+         decl = IDENTIFIER_GLOBAL_VALUE (t);
+       else
+         decl = lookup_name (t, 0);
+
+       /* By convention, expressions use ERROR_MARK_NODE to indicate
+          failure, not NULL_TREE.  */
+       if (decl == NULL_TREE)
+         decl = error_mark_node;
+
+       decl = finish_id_expression (t, decl, scope,
+                                    &idk,
+                                    &qualifying_class,
+                                    /*constant_expression_p=*/false,
+                                    /*allow_non_constant_expression_p=*/false,
+                                    &non_constant_expression_p,
+                                    &error_msg);
+       if (error_msg)
+         error (error_msg);
+       if (!function_p && TREE_CODE (decl) == IDENTIFIER_NODE)
+         decl = unqualified_name_lookup_error (decl);
+       return decl;
       }
 
     case TEMPLATE_ID_EXPR:
       {
        tree object;
-       tree template
-         = tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, 
-                                  in_decl);
-       tree targs
-         = tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, 
-                                  in_decl);
+       tree template = RECUR (TREE_OPERAND (t, 0));
+       tree targs = RECUR (TREE_OPERAND (t, 1));
        
        if (TREE_CODE (template) == COMPONENT_REF)
          {
@@ -7930,46 +7984,37 @@ tsubst_copy_and_build (tree t,
       }
 
     case INDIRECT_REF:
-      return build_x_indirect_ref
-       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
-        "unary *");
+      return build_x_indirect_ref (RECUR (TREE_OPERAND (t, 0)), "unary *");
 
     case CAST_EXPR:
       return build_functional_cast
        (tsubst (TREE_TYPE (t), args, complain, in_decl),
-        tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+        RECUR (TREE_OPERAND (t, 0)));
 
     case REINTERPRET_CAST_EXPR:
       return build_reinterpret_cast
        (tsubst (TREE_TYPE (t), args, complain, in_decl),
-        tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+        RECUR (TREE_OPERAND (t, 0)));
 
     case CONST_CAST_EXPR:
       return build_const_cast
        (tsubst (TREE_TYPE (t), args, complain, in_decl),
-        tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+        RECUR (TREE_OPERAND (t, 0)));
 
     case DYNAMIC_CAST_EXPR:
       return build_dynamic_cast
        (tsubst (TREE_TYPE (t), args, complain, in_decl),
-        tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+        RECUR (TREE_OPERAND (t, 0)));
 
     case STATIC_CAST_EXPR:
       return build_static_cast
        (tsubst (TREE_TYPE (t), args, complain, in_decl),
-        tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+        RECUR (TREE_OPERAND (t, 0)));
 
     case POSTDECREMENT_EXPR:
     case POSTINCREMENT_EXPR:
-      op1 = TREE_OPERAND (t, 0);
-      if (TREE_CODE (op1) == SCOPE_REF)
-       op1 = tsubst_qualified_id (TREE_OPERAND (t, 0),
-                                  args, complain, 
-                                  in_decl,
-                                  /*done=*/false,
-                                  /*address_p=*/false);
-      else
-       op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+      op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
+                                               args, complain, in_decl);
       return build_x_unary_op (TREE_CODE (t), op1);
 
     case PREDECREMENT_EXPR:
@@ -7981,10 +8026,7 @@ tsubst_copy_and_build (tree t,
     case CONVERT_EXPR:  /* Unary + */
     case REALPART_EXPR:
     case IMAGPART_EXPR:
-      return (build_x_unary_op
-             (TREE_CODE (t),
-              tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
-                                     in_decl)));
+      return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)));
 
     case ADDR_EXPR:
       op1 = TREE_OPERAND (t, 0);
@@ -7992,7 +8034,8 @@ tsubst_copy_and_build (tree t,
        op1 = tsubst_qualified_id (op1, args, complain, in_decl, 
                                   /*done=*/true, /*address_p=*/true);
       else
-       op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+       op1 = tsubst_non_call_postfix_expression (op1, args, complain, 
+                                                 in_decl);
       return build_x_unary_op (ADDR_EXPR, op1);
 
     case PLUS_EXPR:
@@ -8026,15 +8069,11 @@ tsubst_copy_and_build (tree t,
     case LT_EXPR:
     case GT_EXPR:
     case MEMBER_REF:
+    case DOTSTAR_EXPR:
       return build_x_binary_op
        (TREE_CODE (t), 
-        tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
-        tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl));
-
-    case DOTSTAR_EXPR:
-      return build_m_component_ref
-       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
-        tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl));
+        RECUR (TREE_OPERAND (t, 0)),
+        RECUR (TREE_OPERAND (t, 1)));
 
     case SCOPE_REF:
       return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true,
@@ -8044,24 +8083,14 @@ tsubst_copy_and_build (tree t,
       if (tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl)
          == NULL_TREE)
        /* new-type-id */
-       return build_nt
-         (ARRAY_REF, NULL_TREE,
-          tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain,
-                                 in_decl));
+       return build_nt (ARRAY_REF, NULL_TREE, RECUR (TREE_OPERAND (t, 1)));
 
-      op1 = TREE_OPERAND (t, 0);
-      if (TREE_CODE (op1) == SCOPE_REF)
-       op1 = tsubst_qualified_id (op1, args, complain, in_decl,
-                                  /*done=*/false, /*address_p=*/false);
-      else
-       op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+      op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
+                                               args, complain, in_decl);
       /* Remember that there was a reference to this entity.  */
       if (DECL_P (op1))
        mark_used (op1);
-      return grok_array_decl (op1, 
-                             tsubst_copy_and_build (TREE_OPERAND (t, 1), 
-                                                    args, complain,
-                                                    in_decl));
+      return grok_array_decl (op1, RECUR (TREE_OPERAND (t, 1)));
 
     case SIZEOF_EXPR:
     case ALIGNOF_EXPR:
@@ -8077,7 +8106,7 @@ tsubst_copy_and_build (tree t,
       else
        {
          ++skip_evaluation;
-         op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+         op1 = RECUR (op1);
          --skip_evaluation;
        }
       if (TREE_CODE (t) == SIZEOF_EXPR)
@@ -8087,17 +8116,13 @@ tsubst_copy_and_build (tree t,
 
     case MODOP_EXPR:
       return build_x_modify_expr
-       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
+       (RECUR (TREE_OPERAND (t, 0)),
         TREE_CODE (TREE_OPERAND (t, 1)),
-        tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
+        RECUR (TREE_OPERAND (t, 2)));
 
     case ARROW_EXPR:
-      op1 = TREE_OPERAND (t, 0);
-      if (TREE_CODE (op1) == SCOPE_REF)
-       op1 = tsubst_qualified_id (op1, args, complain, in_decl,
-                                  /*done=*/false, /*address_p=*/false);
-      else
-       op1 = tsubst_copy_and_build (op1, args, complain, in_decl);
+      op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
+                                               args, complain, in_decl);
       /* Remember that there was a reference to this entity.  */
       if (DECL_P (op1))
        mark_used (op1);
@@ -8105,38 +8130,29 @@ tsubst_copy_and_build (tree t,
 
     case NEW_EXPR:
       return build_new
-       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
-        tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
-        tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl),
+       (RECUR (TREE_OPERAND (t, 0)),
+        RECUR (TREE_OPERAND (t, 1)),
+        RECUR (TREE_OPERAND (t, 2)),
         NEW_EXPR_USE_GLOBAL (t));
 
     case DELETE_EXPR:
      return delete_sanity
-       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
-       tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
+       (RECUR (TREE_OPERAND (t, 0)),
+       RECUR (TREE_OPERAND (t, 1)),
        DELETE_EXPR_USE_VEC (t),
        DELETE_EXPR_USE_GLOBAL (t));
 
     case COMPOUND_EXPR:
-      return (build_x_compound_expr
-             (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, 
-                                     in_decl),
-              tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, 
-                                     in_decl)));
+      return build_x_compound_expr (RECUR (TREE_OPERAND (t, 0)),
+                                   RECUR (TREE_OPERAND (t, 1)));
 
     case CALL_EXPR:
       {
        tree function;
        tree call_args;
-       tree koenig_name;
        bool qualified_p;
 
        function = TREE_OPERAND (t, 0);
-       if (TREE_CODE (function) == LOOKUP_EXPR
-           && !LOOKUP_EXPR_GLOBAL (function))
-         koenig_name = TREE_OPERAND (function, 0);
-       else
-         koenig_name = NULL_TREE;
        if (TREE_CODE (function) == SCOPE_REF)
          {
            qualified_p = true;
@@ -8150,24 +8166,32 @@ tsubst_copy_and_build (tree t,
                           && (TREE_CODE (TREE_OPERAND (function, 1))
                               == SCOPE_REF));
            function = tsubst_copy_and_build (function, args, complain, 
-                                             in_decl);
-           function = convert_from_reference (function);
+                                             in_decl,
+                                             !qualified_p);
          }
 
-       /* Remember that there was a reference to this entity.  */
-       if (DECL_P (function))
-         mark_used (function);
-
-       call_args = tsubst_copy_and_build (TREE_OPERAND (t, 1), args,
-                                          complain, in_decl);
+       call_args = RECUR (TREE_OPERAND (t, 1));
          
        if (BASELINK_P (function))
          qualified_p = 1;
 
-       if (call_args != NULL_TREE && koenig_name)
-         function = lookup_arg_dependent (koenig_name,
-                                          function, 
-                                          call_args);
+       if (!qualified_p
+           && TREE_CODE (function) != TEMPLATE_ID_EXPR
+           && (is_overloaded_fn (function)
+               || DECL_P (function)
+               || TREE_CODE (function) == IDENTIFIER_NODE))
+         {
+           if (call_args)
+             function = perform_koenig_lookup (function, call_args);
+           else if (TREE_CODE (function) == IDENTIFIER_NODE)
+             function = unqualified_name_lookup_error (function);
+         }
+
+       /* Remember that there was a reference to this entity.  */
+       if (DECL_P (function))
+         mark_used (function);
+
+       function = convert_from_reference (function);
 
        if (TREE_CODE (function) == OFFSET_REF)
          return build_offset_ref_call_from_tree (function, call_args);
@@ -8183,15 +8207,15 @@ tsubst_copy_and_build (tree t,
 
     case COND_EXPR:
       return build_x_conditional_expr
-       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
-        tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
-        tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
+       (RECUR (TREE_OPERAND (t, 0)),
+        RECUR (TREE_OPERAND (t, 1)),
+        RECUR (TREE_OPERAND (t, 2)));
 
     case PSEUDO_DTOR_EXPR:
       return finish_pseudo_destructor_expr 
-       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl),
-        tsubst_copy_and_build (TREE_OPERAND (t, 1), args, complain, in_decl),
-        tsubst_copy_and_build (TREE_OPERAND (t, 2), args, complain, in_decl));
+       (RECUR (TREE_OPERAND (t, 0)),
+        RECUR (TREE_OPERAND (t, 1)),
+        RECUR (TREE_OPERAND (t, 2)));
 
     case TREE_LIST:
       {
@@ -8202,13 +8226,13 @@ tsubst_copy_and_build (tree t,
 
        purpose = TREE_PURPOSE (t);
        if (purpose)
-         purpose = tsubst_copy_and_build (purpose, args, complain, in_decl);
+         purpose = RECUR (purpose);
        value = TREE_VALUE (t);
        if (value)
-         value = tsubst_copy_and_build (value, args, complain, in_decl);
+         value = RECUR (value);
        chain = TREE_CHAIN (t);
        if (chain && chain != void_type_node)
-         chain = tsubst_copy_and_build (chain, args, complain, in_decl);
+         chain = RECUR (chain);
        if (purpose == TREE_PURPOSE (t)
            && value == TREE_VALUE (t)
            && chain == TREE_CHAIN (t))
@@ -8221,13 +8245,8 @@ tsubst_copy_and_build (tree t,
        tree object;
        tree member;
 
-       object = TREE_OPERAND (t, 0);
-       if (TREE_CODE (object) == SCOPE_REF)
-         object = tsubst_qualified_id (object, args, complain, in_decl,
-                                       /*done=*/false, /*address_p=*/false);
-       else
-         object = tsubst_copy_and_build (object, args, complain, in_decl);
-
+       object = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0),
+                                                    args, complain, in_decl);
        /* Remember that there was a reference to this entity.  */
        if (DECL_P (object))
          mark_used (object);
@@ -8282,7 +8301,7 @@ tsubst_copy_and_build (tree t,
 
     case THROW_EXPR:
       return build_throw
-       (tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain, in_decl));
+       (RECUR (TREE_OPERAND (t, 0)));
 
     case CONSTRUCTOR:
       {
@@ -8308,9 +8327,8 @@ tsubst_copy_and_build (tree t,
            tree value = TREE_VALUE (elts);
            
            if (purpose && purpose_p)
-             purpose
-               = tsubst_copy_and_build (purpose, args, complain, in_decl);
-           value = tsubst_copy_and_build (value, args, complain, in_decl);
+             purpose = RECUR (purpose);
+           value = RECUR (value);
            r = tree_cons (purpose, value, r);
          }
        
@@ -8324,10 +8342,7 @@ tsubst_copy_and_build (tree t,
 
     case TYPEID_EXPR:
       {
-       tree operand_0
-         = tsubst_copy_and_build (TREE_OPERAND (t, 0), args, complain,
-                                  in_decl);
-       
+       tree operand_0 = RECUR (TREE_OPERAND (t, 0));
        if (TYPE_P (operand_0))
          return get_typeid (operand_0);
        return build_typeid (operand_0);
@@ -8347,14 +8362,15 @@ tsubst_copy_and_build (tree t,
       return convert_from_reference (t);
 
     case VA_ARG_EXPR:
-       return build_x_va_arg
-         (tsubst_copy_and_build
-          (TREE_OPERAND (t, 0), args, complain, in_decl),
-          tsubst_copy (TREE_TYPE (t), args, complain, in_decl));
+      return build_x_va_arg (RECUR (TREE_OPERAND (t, 0)),
+                            tsubst_copy (TREE_TYPE (t), args, complain, 
+                                         in_decl));
 
     default:
       return tsubst_copy (t, args, complain, in_decl);
     }
+
+#undef RECUR
 }
 
 /* Verify that the instantiated ARGS are valid. For type arguments,
@@ -10576,7 +10592,7 @@ regenerate_decl_from_template (tree decl, tree tmpl)
   tree args;
   tree code_pattern;
   tree new_decl;
-  int unregistered;
+  bool unregistered;
 
   args = DECL_TI_ARGS (decl);
   code_pattern = DECL_TEMPLATE_RESULT (tmpl);
@@ -10587,7 +10603,8 @@ regenerate_decl_from_template (tree decl, tree tmpl)
      instantiation of a specialization, which it isn't: it's a full
      instantiation.  */
   gen_tmpl = most_general_template (tmpl);
-  unregistered = unregister_specialization (decl, gen_tmpl);
+  unregistered = reregister_specialization (decl, gen_tmpl,
+                                           /*new_spec=*/NULL_TREE);
 
   /* If the DECL was not unregistered then something peculiar is
      happening: we created a specialization but did not call
index db9e4d2..ab9376b 100644 (file)
@@ -1473,6 +1473,47 @@ finish_stmt_expr (tree rtl_expr)
   return result;
 }
 
+/* Perform Koenig lookup.  FN is the postfix-expression representing
+   the call; ARGS are the arguments to the call.  Returns the
+   functions to be considered by overload resolution.  */
+
+tree
+perform_koenig_lookup (tree fn, tree args)
+{
+  tree identifier = NULL_TREE;
+  tree functions = NULL_TREE;
+
+  /* Find the name of the overloaded function.  */
+  if (TREE_CODE (fn) == IDENTIFIER_NODE)
+    identifier = fn;
+  else if (is_overloaded_fn (fn))
+    {
+      functions = fn;
+      identifier = DECL_NAME (get_first_fn (functions));
+    }
+  else if (DECL_P (fn))
+    {
+      functions = fn;
+      identifier = DECL_NAME (fn);
+    }
+
+  /* A call to a namespace-scope function using an unqualified name.
+
+     Do Koenig lookup -- unless any of the arguments are
+     type-dependent.  */
+  if (!any_type_dependent_arguments_p (args))
+    {
+      fn = lookup_arg_dependent (identifier, functions, args);
+      if (!fn)
+       /* The unqualified name could not be resolved.  */
+       fn = unqualified_fn_lookup_error (identifier);
+    }
+  else
+    fn = build_min_nt (LOOKUP_EXPR, identifier);
+
+  return fn;
+}
+
 /* Generate an expression for `FN (ARGS)'.
 
    If DISALLOW_VIRTUAL is true, the call to FN will be not generated
@@ -2191,6 +2232,306 @@ check_multiple_declarators (void)
     error ("multiple declarators in template declaration");
 }
 
+/* ID_EXPRESSION is a representation of parsed, but unprocessed,
+   id-expression.  (See cp_parser_id_expression for details.)  SCOPE,
+   if non-NULL, is the type or namespace used to explicitly qualify
+   ID_EXPRESSION.  DECL is the entity to which that name has been
+   resolved.  
+
+   *CONSTANT_EXPRESSION_P is true if we are presently parsing a
+   constant-expression.  In that case, *NON_CONSTANT_EXPRESSION_P will
+   be set to true if this expression isn't permitted in a
+   constant-expression, but it is otherwise not set by this function.
+   *ALLOW_NON_CONSTANT_EXPRESSION_P is true if we are parsing a
+   constant-expression, but a non-constant expression is also
+   permissible.
+
+   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
+   will be a string with static storage duration, so the caller need
+   not "free" it.
+
+   Return an expression for the entity, after issuing appropriate
+   diagnostics.  This function is also responsible for transforming a
+   reference to a non-static member into a COMPONENT_REF that makes
+   the use of "this" explicit.  
+
+   Upon return, *IDK will be filled in appropriately.  */
+
+tree
+finish_id_expression (tree id_expression, 
+                     tree decl,
+                     tree scope,
+                     cp_id_kind *idk,
+                     tree *qualifying_class,
+                     bool constant_expression_p,
+                     bool allow_non_constant_expression_p,
+                     bool *non_constant_expression_p,
+                     const char **error_msg)
+{
+  /* Initialize the output parameters.  */
+  *idk = CP_ID_KIND_NONE;
+  *error_msg = NULL;
+
+  if (id_expression == error_mark_node)
+    return error_mark_node;
+  /* If we have a template-id, then no further lookup is
+     required.  If the template-id was for a template-class, we
+     will sometimes have a TYPE_DECL at this point.  */
+  else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
+      || TREE_CODE (decl) == TYPE_DECL)
+    ;
+  /* Look up the name.  */
+  else 
+    {
+      if (decl == error_mark_node)
+       {
+         /* Name lookup failed.  */
+         if (scope && (!TYPE_P (scope) || !dependent_type_p (scope)))
+           {
+             /* Qualified name lookup failed, and the qualifying name
+                was not a dependent type.  That is always an
+                error.  */
+             if (TYPE_P (scope) && !COMPLETE_TYPE_P (scope))
+               error ("incomplete type `%T' used in nested name "
+                      "specifier",
+                      scope);
+             else if (scope != global_namespace)
+               error ("`%D' is not a member of `%D'",
+                      id_expression, scope);
+             else
+               error ("`::%D' has not been declared", id_expression);
+             return error_mark_node;
+           }
+         else if (!scope)
+           {
+             /* It may be resolved via Koenig lookup.  */
+             *idk = CP_ID_KIND_UNQUALIFIED;
+             return id_expression;
+           }
+       }
+      /* If DECL is a variable that would be out of scope under
+        ANSI/ISO rules, but in scope in the ARM, name lookup
+        will succeed.  Issue a diagnostic here.  */
+      else
+       decl = check_for_out_of_scope_variable (decl);
+
+      /* Remember that the name was used in the definition of
+        the current class so that we can check later to see if
+        the meaning would have been different after the class
+        was entirely defined.  */
+      if (!scope && decl != error_mark_node)
+       maybe_note_name_used_in_class (id_expression, decl);
+    }
+
+  /* If we didn't find anything, or what we found was a type,
+     then this wasn't really an id-expression.  */
+  if (TREE_CODE (decl) == TEMPLATE_DECL
+      && !DECL_FUNCTION_TEMPLATE_P (decl))
+    {
+      *error_msg = "missing template arguments";
+      return error_mark_node;
+    }
+  else if (TREE_CODE (decl) == TYPE_DECL
+          || TREE_CODE (decl) == NAMESPACE_DECL)
+    {
+      *error_msg = "expected primary-expression";
+      return error_mark_node;
+    }
+
+  /* If the name resolved to a template parameter, there is no
+     need to look it up again later.  Similarly, we resolve
+     enumeration constants to their underlying values.  */
+  if (TREE_CODE (decl) == CONST_DECL)
+    {
+      *idk = CP_ID_KIND_NONE;
+      if (DECL_TEMPLATE_PARM_P (decl) || !processing_template_decl)
+       return DECL_INITIAL (decl);
+      return decl;
+    }
+  else
+    {
+      bool dependent_p;
+
+      /* If the declaration was explicitly qualified indicate
+        that.  The semantics of `A::f(3)' are different than
+        `f(3)' if `f' is virtual.  */
+      *idk = (scope 
+             ? CP_ID_KIND_QUALIFIED
+             : (TREE_CODE (decl) == TEMPLATE_ID_EXPR
+                ? CP_ID_KIND_TEMPLATE_ID
+                : CP_ID_KIND_UNQUALIFIED));
+
+
+      /* [temp.dep.expr]
+
+        An id-expression is type-dependent if it contains an
+        identifier that was declared with a dependent type.
+
+        As an optimization, we could choose not to create a
+        LOOKUP_EXPR for a name that resolved to a local variable in
+        the template function that we are currently declaring; such a
+        name cannot ever resolve to anything else.  If we did that we
+        would not have to look up these names at instantiation time.
+
+        The standard is not very specific about an id-expression that
+        names a set of overloaded functions.  What if some of them
+        have dependent types and some of them do not?  Presumably,
+        such a name should be treated as a dependent name.  */
+      /* Assume the name is not dependent.  */
+      dependent_p = false;
+      if (!processing_template_decl)
+       /* No names are dependent outside a template.  */
+       ;
+      /* A template-id where the name of the template was not resolved
+        is definitely dependent.  */
+      else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
+              && (TREE_CODE (TREE_OPERAND (decl, 0)) 
+                  == IDENTIFIER_NODE))
+       dependent_p = true;
+      /* For anything except an overloaded function, just check its
+        type.  */
+      else if (!is_overloaded_fn (decl))
+       dependent_p 
+         = dependent_type_p (TREE_TYPE (decl));
+      /* For a set of overloaded functions, check each of the
+        functions.  */
+      else
+       {
+         tree fns = decl;
+
+         if (BASELINK_P (fns))
+           fns = BASELINK_FUNCTIONS (fns);
+
+         /* For a template-id, check to see if the template
+            arguments are dependent.  */
+         if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
+           {
+             tree args = TREE_OPERAND (fns, 1);
+             dependent_p = any_dependent_template_arguments_p (args);
+             /* The functions are those referred to by the
+                template-id.  */
+             fns = TREE_OPERAND (fns, 0);
+           }
+
+         /* If there are no dependent template arguments, go through
+            the overlaoded functions.  */
+         while (fns && !dependent_p)
+           {
+             tree fn = OVL_CURRENT (fns);
+
+             /* Member functions of dependent classes are
+                dependent.  */
+             if (TREE_CODE (fn) == FUNCTION_DECL
+                 && type_dependent_expression_p (fn))
+               dependent_p = true;
+             else if (TREE_CODE (fn) == TEMPLATE_DECL
+                      && dependent_template_p (fn))
+               dependent_p = true;
+
+             fns = OVL_NEXT (fns);
+           }
+       }
+
+      /* If the name was dependent on a template parameter, we will
+        resolve the name at instantiation time.  */
+      if (dependent_p)
+       {
+         /* Create a SCOPE_REF for qualified names, if the scope is
+            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 (constant_expression_p)
+               *non_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 build (SCOPE_REF, TREE_TYPE (decl), scope,
+                             id_expression);
+             else
+               return decl;
+           }
+         /* A TEMPLATE_ID already contains all the information we
+            need.  */
+         if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR)
+           return id_expression;
+         /* 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 (constant_expression_p)
+           *non_constant_expression_p = true;
+         /* Create a LOOKUP_EXPR for other unqualified names.  */
+         return build_min_nt (LOOKUP_EXPR, id_expression);
+       }
+
+      /* Only certain kinds of names are allowed in constant
+        expression.  Enumerators have already been handled above.  */
+      if (constant_expression_p)
+       {
+         /* Non-type template parameters of integral or enumeration
+            type are OK.  */
+         if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX
+             && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
+         ;
+         /* Const variables or static data members of integral or
+            enumeration types initialized with constant expressions
+            are OK.  We also accept dependent initializers; they may
+            turn out to be constant at instantiation-time.  */
+         else if (TREE_CODE (decl) == VAR_DECL
+                  && CP_TYPE_CONST_P (TREE_TYPE (decl))
+                  && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
+                  && DECL_INITIAL (decl)
+                  && (TREE_CONSTANT (DECL_INITIAL (decl))
+                      || type_dependent_expression_p (DECL_INITIAL 
+                                                      (decl))
+                      || value_dependent_expression_p (DECL_INITIAL 
+                                                       (decl))))
+           ;
+         else
+           {
+             if (!allow_non_constant_expression_p)
+               {
+                 error ("`%D' cannot appear in a constant-expression", decl);
+                 return error_mark_node;
+               }
+             *non_constant_expression_p = true;
+           }
+       }
+
+      if (scope)
+       {
+         decl = (adjust_result_of_qualified_name_lookup 
+                 (decl, scope, current_class_type));
+         if (TREE_CODE (decl) == FIELD_DECL || BASELINK_P (decl))
+           *qualifying_class = scope;
+         else if (!processing_template_decl)
+           decl = convert_from_reference (decl);
+         else if (TYPE_P (scope))
+           decl = build (SCOPE_REF, TREE_TYPE (decl), scope, decl);
+       }
+      else
+       /* Transform references to non-static data members into
+          COMPONENT_REFs.  */
+       decl = hack_identifier (decl, id_expression);
+
+      /* Resolve references to variables of anonymous unions
+        into COMPONENT_REFs.  */
+      if (TREE_CODE (decl) == ALIAS_DECL)
+       decl = DECL_INITIAL (decl);
+    }
+
+  if (TREE_DEPRECATED (decl))
+    warn_deprecated_use (decl);
+
+  return decl;
+}
+
 /* Implement the __typeof keyword: Return the type of EXPR, suitable for
    use as a type-specifier.  */
 
index 9550b62..1dedd65 100644 (file)
@@ -1,3 +1,23 @@
+2003-07-13  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/11493
+       PR c++/11495
+       * g++.dg/parse/template9.C: Likewise.
+       * g++.dg/template/crash4.C: New test.
+       * g++.dg/template/koenig1.C: Likewise.
+       * g++.old-deja/g++.benjamin/tem03.C: Adjust error markers.
+       * g++.old-deja/g++.benjamin/tem06.C: Declare "x".
+       * g++.old-deja/g++.jason/overload33.C: Use this-> when calling
+       functions.
+       * g++.old-deja/g++.jason/template36.C: Likewise.
+       * g++.old-deja/g++.mike/p1989.C: Likewise.
+       * g++.old-deja/g++.pt/lookup2.C: Use -fpermissive when compiling.
+       * g++.old-deja/g++.pt/ttp20.C: Use this->.
+       * g++.old-deja/g++.pt/ttp21.C: Use this->.
+       * g++.old-deja/g++.pt/typename13.C: Use -fpermissive when
+       compiling.
+       * g++.old-deja/g++.pt/union2.C: Use this->.
+
 2003-07-11  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.dg/20030711-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/parse/template9.C b/gcc/testsuite/g++.dg/parse/template9.C
new file mode 100644 (file)
index 0000000..90ce9fe
--- /dev/null
@@ -0,0 +1,5 @@
+template <typename T> 
+void f() {
+  g(); // { dg-error "" }
+  h(3); // { dg-error "" }
+}
diff --git a/gcc/testsuite/g++.dg/template/crash4.C b/gcc/testsuite/g++.dg/template/crash4.C
new file mode 100644 (file)
index 0000000..72b2bb1
--- /dev/null
@@ -0,0 +1,12 @@
+namespace NS {
+    struct C {};
+    void foo();
+}
+
+template <class T> struct X {};
+
+template <class T> struct A {
+    A() { foo (X<T>()); }
+    void foo(X<T>);
+};
+template struct A<NS::C>;
diff --git a/gcc/testsuite/g++.dg/template/koenig1.C b/gcc/testsuite/g++.dg/template/koenig1.C
new file mode 100644 (file)
index 0000000..850d388
--- /dev/null
@@ -0,0 +1,8 @@
+namespace NS {
+    struct C {};
+    void foo(C);
+}
+
+template <class T> void bar() { T t; foo (t); }
+
+template void bar<NS::C> ();
index 2fc599f..73b9965 100644 (file)
@@ -195,7 +195,7 @@ struct Xthirteen {
     if (local_value > value) // { dg-error "" } .*
       return local_value;
     else
-      return value; // { dg-error "" } .*
+      return value;
   }
 };
 
index b56425e..3233e0e 100644 (file)
@@ -14,6 +14,8 @@ public:
   friend void x (const T &) { }
 };
 
+void x(const int &);
+
 template<class T>
 void blah (const T &) {
   T y;
index 19b4a2e..2cc34c6 100644 (file)
@@ -58,10 +58,10 @@ class SmartPtr : public ConstSmartPtr<T>
                          : ConstSmartPtr<T>(theItem) {}
 
     T*                 item() const
-                               { return _item(); }
+                               { return this->_item(); }
 
                        operator T*() const
-                               { return _item(); }
+                               { return this->_item(); }
 };
 
 /* ------------------------------------------------------------ */
index a8a9d16..23cdb00 100644 (file)
@@ -33,7 +33,7 @@ public:
     int base::* g ();
 
     int zowee() const
-    { return bar(); }  
+    { return this->bar(); }  
 };
 
 template <class T>
index 30c7e51..bbecdd8 100644 (file)
@@ -195,8 +195,8 @@ template<class T>
 Pix
 List_DLS<T>::search(const T& item) const
 {
-    for (Pix x=first(); 0 != x; next(x)) {
-       if (item == operator()(x)) // { dg-error "" } const subversion
+    for (Pix x=this->first(); 0 != x; this->next(x)) {
+       if (item == this->operator()(x)) // { dg-error "" } const subversion
            return x;
     }
     return 0;
@@ -223,8 +223,8 @@ template<class T>
 bool
 List_DLSp<T>::contains(const T& item) const
 {
-    for (Pix x=first(); 0 != x; next(x)) {
-       if (*item == *operator()(x))
+    for (Pix x=this->first(); 0 != x; this->next(x)) {
+        if (*item == *(this->operator()(x)))
            return TRUE;
     }
     return FALSE;
index 73c2bbb..3d9f060 100644 (file)
@@ -1,5 +1,5 @@
 // { dg-do assemble  }
-// { dg-options "" }
+// { dg-options "-fpermissive" }
 
 class A
 {
@@ -15,6 +15,6 @@ protected:
 template <class T> class D : private B<T>
 {
 public:
-  void f2() { f1(); };
+  void f2() { f1(); }; // { dg-warning "" }
 };
 
index c9f7912..c54119e 100644 (file)
@@ -18,7 +18,7 @@ template<template<class> class D,class E> class C : D<E>
 
 template<template<class> class D,class E> int C<D,E>::g()
 {
-       return f();
+       return this->f();
 }
 
 int main()
index c1a4fd0..f0b41bf 100644 (file)
@@ -18,13 +18,13 @@ template<template<class> class D,class E> class C : D<E>
 
 template<template<class> class D,class E> int C<D,E>::g()
 {
-       return f();
+       return this->f();
 }
 
 class E : C<D,int>
 {
        public:
-               int h() { return g(); }
+               int h() { return this->g(); }
 };
 
 int main()
index b0d4b47..385834b 100644 (file)
@@ -1,5 +1,5 @@
 // { dg-do assemble  }
-// { dg-options "" }
+// { dg-options "-fpermissive" }
 
 template <class T>
 struct B 
@@ -18,7 +18,7 @@ struct D : public B<T>
 template <class T>
 void D<T>::f()
 {
-  I();
+  I(); // { dg-warning "" }
 }
 
 
index 9eb4a87..fdb038f 100644 (file)
@@ -12,7 +12,7 @@ protected:
 };
 
 template<class T> struct vector : public vector_base<T> {
-  vector () { def_basep (); }
+  vector () { this->def_basep (); }
 };
 
 vector<int> iv;