Hi,
On 05/01/2012 11:01 PM, Paolo Carlini wrote:
Well, not really. The first time walk_template_parms_r is called, t is a
SIZEOF_EXPR which remains unhandled, the function returns NULL_TREE. The
second time, t is a COMPONENT_REF, thus !TYPE_P (t) is true, TREE_TYPE
is NULL, the function immediately returns error_mark_node and the
iteration ends (with the correct result that the expression is
instantiation-dependent).

Ah, I guess we can't get to a FIELD_DECL without going through an expression with null type. OK, can leave out the FIELD_DECL case then with a comment.
Ok.
I also booted and tested a variant, attached, which changes finish_static_assert to also use instantiation_dependent_expression_p and also passes testing: nice, between front-end and library we stress the new function quite a bit more.

Great. Let's also use it for sizeof/alignof, controlled with abi_version_at_least (7), since it affects mangling.
Ok. I'm attaching what I booted and tested successfully.

Is it now good enough to go in to resolve PR51222? Otherwise, if we aren't still not completely sure about bits outside PR51222 proper, maybe we could split the work in two parts?
And then figure out what we're going to to about ABI transition in 4.8...
This reminds me that maybe it's finally time to break the library ABI. I guess we may want to discuss the issue at the Cauldron too.

Paolo.

////////////////////
/cp
2012-05-02  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/51222
        * pt.c (for_each_template_parm): Rename to walk_template_parms,
        add check_types bool parameter.
        (mark_template_parm, uses_template_parms_level): Adjust.
        (instantiation_dependent_expression_p): New.
        (finish_decltype_type, finish_static_assert): Use it.
        * typeck.c (cxx_sizeof_expr, cxx_alignof_expr): Likewise.
        * cp-tree.h: Update declarations.

/testsuite
2012-05-02  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/51222
        * g++.dg/cpp0x/decltype37.C: New.
Index: testsuite/g++.dg/cpp0x/decltype37.C
===================================================================
--- testsuite/g++.dg/cpp0x/decltype37.C (revision 0)
+++ testsuite/g++.dg/cpp0x/decltype37.C (revision 0)
@@ -0,0 +1,101 @@
+// PR c++/51222
+// { dg-options -std=c++11 }
+
+template<class T>
+struct add_rref {
+  typedef T&& type;
+};
+
+template<>
+struct add_rref<void> {
+  typedef void type;
+};
+
+template<class T>
+typename add_rref<T>::type declval();
+
+template<class T, class U, class =
+  decltype(::delete ::new T(declval<U>()))
+>
+auto f(int) -> char;
+
+template<class, class>
+auto f(...) -> char(&)[2];
+
+template<class T, class =
+  decltype(::delete ::new T())
+>
+auto g(int) -> char;
+
+template<class>
+auto g(...) -> char(&)[2];
+
+template<class T, class U>
+auto f2(int) -> decltype(::delete ::new T(declval<U>()), char());
+
+template<class, class>
+auto f2(...) -> char(&)[2];
+
+template<class T>
+auto g2(int) -> decltype(::delete ::new T(), char());
+
+template<class>
+auto g2(...) -> char(&)[2];
+
+struct C { };
+
+struct A {
+  virtual ~A() = 0;
+};
+
+struct D1 {
+  D1() = delete;
+};
+
+struct D2 {
+  ~D2() = delete;
+};
+
+static_assert(sizeof(g<void>(0)) == 2, "Ouch");
+static_assert(sizeof(g<void()>(0)) == 2, "Ouch");
+static_assert(sizeof(g<void() const>(0)) == 2, "Ouch");
+static_assert(sizeof(g<A>(0)) == 2, "Ouch");
+static_assert(sizeof(g<D1>(0)) == 2, "Ouch");
+static_assert(sizeof(g<D2>(0)) == 2, "Ouch");
+static_assert(sizeof(g<int&>(0)) == 2, "Ouch");
+static_assert(sizeof(g<int&&>(0)) == 2, "Ouch");
+static_assert(sizeof(g<void(&)()>(0)) == 2, "Ouch");
+static_assert(sizeof(g<void(&&)()>(0)) == 2, "Ouch");
+static_assert(sizeof(f<void, void>(0)) == 2, "Ouch");
+static_assert(sizeof(f<void(), void()>(0)) == 2, "Ouch");
+static_assert(sizeof(f<void() const, void() const>(0)) == 2, "Ouch");
+static_assert(sizeof(f<int, void>(0)) == 2, "Ouch");
+static_assert(sizeof(f<void, int>(0)) == 2, "Ouch");
+static_assert(sizeof(f<C, void>(0)) == 2, "Ouch");
+static_assert(sizeof(f<C, int>(0)) == 2, "Ouch");
+static_assert(sizeof(f<int&, int&>(0)) == 2, "Ouch");
+static_assert(sizeof(f<int&&, int&&>(0)) == 2, "Ouch");
+static_assert(sizeof(f<void(&)(), void(&)()>(0)) == 2, "Ouch");
+static_assert(sizeof(f<void(&&)(), void(&&)()>(0)) == 2, "Ouch");
+
+static_assert(sizeof(g2<void>(0)) == 2, "Ouch");
+static_assert(sizeof(g2<void()>(0)) == 2, "Ouch");
+static_assert(sizeof(g2<void() const>(0)) == 2, "Ouch");
+static_assert(sizeof(g2<A>(0)) == 2, "Ouch");
+static_assert(sizeof(g2<D1>(0)) == 2, "Ouch");
+static_assert(sizeof(g2<D2>(0)) == 2, "Ouch");
+static_assert(sizeof(g2<int&>(0)) == 2, "Ouch");
+static_assert(sizeof(g2<int&&>(0)) == 2, "Ouch");
+static_assert(sizeof(g2<void(&)()>(0)) == 2, "Ouch");
+static_assert(sizeof(g2<void(&&)()>(0)) == 2, "Ouch");
+static_assert(sizeof(f2<void, void>(0)) == 2, "Ouch");
+static_assert(sizeof(f2<void(), void()>(0)) == 2, "Ouch");
+static_assert(sizeof(f2<void() const, void() const>(0)) == 2, "Ouch");
+static_assert(sizeof(f2<int, void>(0)) == 2, "Ouch");
+static_assert(sizeof(f2<void, int>(0)) == 2, "Ouch");
+static_assert(sizeof(f2<C, void>(0)) == 2, "Ouch");
+static_assert(sizeof(f2<C, int>(0)) == 2, "Ouch");
+static_assert(sizeof(f2<int&, int&>(0)) == 2, "Ouch");
+static_assert(sizeof(f2<int&&, int&&>(0)) == 2, "Ouch");
+static_assert(sizeof(f2<void(&)(), void(&)()>(0)) == 2, "Ouch");
+static_assert(sizeof(f2<void(&&)(), void(&&)()>(0)) == 2, "Ouch");
Index: cp/typeck.c
===================================================================
--- cp/typeck.c (revision 187058)
+++ cp/typeck.c (working copy)
@@ -1581,7 +1581,9 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain)
   if (e == error_mark_node)
     return error_mark_node;
 
-  if (processing_template_decl)
+  if (abi_version_at_least (7)
+      ? instantiation_dependent_expression_p (e)
+      : processing_template_decl)
     {
       e = build_min (SIZEOF_EXPR, size_type_node, e);
       TREE_SIDE_EFFECTS (e) = 0;
@@ -1645,7 +1647,9 @@ cxx_alignof_expr (tree e, tsubst_flags_t complain)
   if (e == error_mark_node)
     return error_mark_node;
 
-  if (processing_template_decl)
+  if (abi_version_at_least (7)
+      ? instantiation_dependent_expression_p (e)
+      : processing_template_decl)
     {
       e = build_min (ALIGNOF_EXPR, size_type_node, e);
       TREE_SIDE_EFFECTS (e) = 0;
Index: cp/pt.c
===================================================================
--- cp/pt.c     (revision 187058)
+++ cp/pt.c     (working copy)
@@ -145,8 +145,8 @@ static tree convert_nontype_argument_function (tre
 static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
 static tree convert_template_argument (tree, tree, tree,
                                       tsubst_flags_t, int, tree);
-static int for_each_template_parm (tree, tree_fn_t, void*,
-                                  struct pointer_set_t*, bool);
+static int walk_template_parms (tree, tree_fn_t, void*,
+                               struct pointer_set_t*, bool, bool);
 static tree expand_template_argument_pack (tree);
 static tree build_template_parm_index (int, int, int, int, tree, tree);
 static bool inline_needs_template_parms (tree);
@@ -185,7 +185,7 @@ static int coerce_template_template_parms (tree, t
 static bool template_template_parm_bindings_ok_p (tree, tree);
 static int template_args_equal (tree, tree);
 static void tsubst_default_arguments (tree);
-static tree for_each_template_parm_r (tree *, int *, void *);
+static tree walk_template_parms_r (tree *, int *, void *);
 static tree copy_default_args_to_explicit_spec_1 (tree, tree);
 static void copy_default_args_to_explicit_spec (tree);
 static int invalid_nontype_parm_type_p (tree, tsubst_flags_t);
@@ -4276,8 +4276,8 @@ mark_template_parm (tree t, void* data)
       tpd->arg_uses_template_parms[tpd->current_arg] = 1;
     }
 
-  /* Return zero so that for_each_template_parm will continue the
-     traversal of the tree; we want to mark *every* template parm.  */
+  /* Return zero so that walk_template_parms will continue the traversal
+     of the tree; we want to mark *every* template parm.  */
   return 0;
 }
 
@@ -4344,11 +4344,12 @@ process_partial_specialization (tree decl)
   for (i = 0; i < nargs; ++i)
     {
       tpd.current_arg = i;
-      for_each_template_parm (TREE_VEC_ELT (inner_args, i),
-                             &mark_template_parm,
-                             &tpd,
-                             NULL,
-                             /*include_nondeduced_p=*/false);
+      walk_template_parms (TREE_VEC_ELT (inner_args, i),
+                          &mark_template_parm,
+                          &tpd,
+                          NULL,
+                          /*check_types=*/false,
+                          /*include_nondeduced_p=*/false);
     }
   for (i = 0; i < ntparms; ++i)
     if (tpd.parms[i] == 0)
@@ -4481,11 +4482,12 @@ process_partial_specialization (tree decl)
                   tpd2.current_arg = i;
                   tpd2.arg_uses_template_parms[i] = 0;
                   memset (tpd2.parms, 0, sizeof (int) * nargs);
-                  for_each_template_parm (type,
-                                          &mark_template_parm,
-                                          &tpd2,
-                                          NULL,
-                                         /*include_nondeduced_p=*/false);
+                  walk_template_parms (type,
+                                      &mark_template_parm,
+                                      &tpd2,
+                                      NULL,
+                                      /*check_types=*/false,
+                                      /*include_nondeduced_p=*/false);
 
                   if (tpd2.arg_uses_template_parms [i])
                     {
@@ -4755,7 +4757,7 @@ check_default_tmpl_args (tree decl, tree parms, in
 }
 
 /* Worker for push_template_decl_real, called via
-   for_each_template_parm.  DATA is really an int, indicating the
+   walk_template_parms.  DATA is really an int, indicating the
    level of the parameters we are interested in.  If T is a template
    parameter of that level, return nonzero.  */
 
@@ -7750,26 +7752,34 @@ struct pair_fn_data
 {
   tree_fn_t fn;
   void *data;
+  bool check_types;
   /* True when we should also visit template parameters that occur in
      non-deduced contexts.  */
   bool include_nondeduced_p;
   struct pointer_set_t *visited;
 };
 
-/* Called from for_each_template_parm via walk_tree.  */
+/* Called from walk_template_parms via walk_tree.  */
 
 static tree
-for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
+walk_template_parms_r (tree *tp, int *walk_subtrees, void *d)
 {
   tree t = *tp;
   struct pair_fn_data *pfd = (struct pair_fn_data *) d;
   tree_fn_t fn = pfd->fn;
   void *data = pfd->data;
 
+  /* If the type is null, this is a type-dependent expression, and if
+     we're checking types, we would find the relevant template parameters.
+     And fn must be null, so we can just return.  */ 
+  if (pfd->check_types && !TYPE_P (t) && TREE_TYPE (t) == NULL_TREE)
+    return error_mark_node;
+
   if (TYPE_P (t)
       && (pfd->include_nondeduced_p || TREE_CODE (t) != TYPENAME_TYPE)
-      && for_each_template_parm (TYPE_CONTEXT (t), fn, data, pfd->visited,
-                                pfd->include_nondeduced_p))
+      && walk_template_parms (TYPE_CONTEXT (t), fn, data,
+                             pfd->visited, pfd->check_types,
+                             pfd->include_nondeduced_p))
     return error_mark_node;
 
   switch (TREE_CODE (t))
@@ -7783,34 +7793,39 @@ static tree
     case ENUMERAL_TYPE:
       if (!TYPE_TEMPLATE_INFO (t))
        *walk_subtrees = 0;
-      else if (for_each_template_parm (TI_ARGS (TYPE_TEMPLATE_INFO (t)),
-                                      fn, data, pfd->visited, 
-                                      pfd->include_nondeduced_p))
+      else if (walk_template_parms (TI_ARGS (TYPE_TEMPLATE_INFO (t)),
+                                   fn, data, pfd->visited,
+                                   pfd->check_types,
+                                   pfd->include_nondeduced_p))
        return error_mark_node;
       break;
 
     case INTEGER_TYPE:
-      if (for_each_template_parm (TYPE_MIN_VALUE (t),
-                                 fn, data, pfd->visited, 
-                                 pfd->include_nondeduced_p)
-         || for_each_template_parm (TYPE_MAX_VALUE (t),
-                                    fn, data, pfd->visited,
-                                    pfd->include_nondeduced_p))
+      if (walk_template_parms (TYPE_MIN_VALUE (t),
+                              fn, data, pfd->visited,
+                              pfd->check_types,
+                              pfd->include_nondeduced_p)
+         || walk_template_parms (TYPE_MAX_VALUE (t),
+                                 fn, data, pfd->visited,
+                                 pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
       break;
 
     case METHOD_TYPE:
       /* Since we're not going to walk subtrees, we have to do this
         explicitly here.  */
-      if (for_each_template_parm (TYPE_METHOD_BASETYPE (t), fn, data,
-                                 pfd->visited, pfd->include_nondeduced_p))
+      if (walk_template_parms (TYPE_METHOD_BASETYPE (t), fn, data,
+                              pfd->visited, pfd->check_types,
+                              pfd->include_nondeduced_p))
        return error_mark_node;
       /* Fall through.  */
 
     case FUNCTION_TYPE:
       /* Check the return type.  */
-      if (for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited,
-                                 pfd->include_nondeduced_p))
+      if (walk_template_parms (TREE_TYPE (t), fn, data,
+                              pfd->visited, pfd->check_types,
+                              pfd->include_nondeduced_p))
        return error_mark_node;
 
       /* Check the parameter types.  Since default arguments are not
@@ -7823,8 +7838,9 @@ static tree
        tree parm;
 
        for (parm = TYPE_ARG_TYPES (t); parm; parm = TREE_CHAIN (parm))
-         if (for_each_template_parm (TREE_VALUE (parm), fn, data,
-                                     pfd->visited, pfd->include_nondeduced_p))
+         if (walk_template_parms (TREE_VALUE (parm), fn, data,
+                                  pfd->visited, pfd->check_types,
+                                  pfd->include_nondeduced_p))
            return error_mark_node;
 
        /* Since we've already handled the TYPE_ARG_TYPES, we don't
@@ -7836,37 +7852,48 @@ static tree
     case TYPEOF_TYPE:
     case UNDERLYING_TYPE:
       if (pfd->include_nondeduced_p
-         && for_each_template_parm (TYPE_FIELDS (t), fn, data,
-                                    pfd->visited, 
-                                    pfd->include_nondeduced_p))
+         && walk_template_parms (TYPE_FIELDS (t), fn, data,
+                                 pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
       break;
 
     case FUNCTION_DECL:
     case VAR_DECL:
+      /* We can leave out the FIELD_DECL case: we can't get to such
+        a decl without going through an expression with null type.  */
       if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
-         && for_each_template_parm (DECL_TI_ARGS (t), fn, data,
-                                    pfd->visited, pfd->include_nondeduced_p))
+         && walk_template_parms (DECL_TI_ARGS (t), fn, data,
+                                 pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
       /* Fall through.  */
 
     case PARM_DECL:
     case CONST_DECL:
       if (TREE_CODE (t) == CONST_DECL && DECL_TEMPLATE_PARM_P (t)
-         && for_each_template_parm (DECL_INITIAL (t), fn, data,
-                                    pfd->visited, pfd->include_nondeduced_p))
+         && walk_template_parms (DECL_INITIAL (t), fn, data,
+                                 pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
       if (DECL_CONTEXT (t)
          && pfd->include_nondeduced_p
-         && for_each_template_parm (DECL_CONTEXT (t), fn, data,
-                                    pfd->visited, pfd->include_nondeduced_p))
+         && walk_template_parms (DECL_CONTEXT (t), fn, data,
+                                 pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
+      if (pfd->check_types && TREE_TYPE (t)
+         && walk_template_parms (TREE_TYPE(t), fn, data,
+                                 pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
+       return error_mark_node;
       break;
 
     case BOUND_TEMPLATE_TEMPLATE_PARM:
       /* Record template parameters such as `T' inside `TT<T>'.  */
-      if (for_each_template_parm (TYPE_TI_ARGS (t), fn, data, pfd->visited,
-                                 pfd->include_nondeduced_p))
+      if (walk_template_parms (TYPE_TI_ARGS (t), fn, data,
+                              pfd->visited, pfd->check_types,
+                              pfd->include_nondeduced_p))
        return error_mark_node;
       /* Fall through.  */
 
@@ -7882,8 +7909,9 @@ static tree
     case TEMPLATE_DECL:
       /* A template template parameter is encountered.  */
       if (DECL_TEMPLATE_TEMPLATE_PARM_P (t)
-         && for_each_template_parm (TREE_TYPE (t), fn, data, pfd->visited,
-                                    pfd->include_nondeduced_p))
+         && walk_template_parms (TREE_TYPE (t), fn, data,
+                                 pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
 
       /* Already substituted template template parameter */
@@ -7892,44 +7920,27 @@ static tree
 
     case TYPENAME_TYPE:
       if (!fn
-         || for_each_template_parm (TYPENAME_TYPE_FULLNAME (t), fn,
-                                    data, pfd->visited, 
-                                    pfd->include_nondeduced_p))
+         || walk_template_parms (TYPENAME_TYPE_FULLNAME (t), fn,
+                                 data, pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
       break;
 
     case CONSTRUCTOR:
       if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))
          && pfd->include_nondeduced_p
-         && for_each_template_parm (TYPE_PTRMEMFUNC_FN_TYPE
-                                    (TREE_TYPE (t)), fn, data,
-                                    pfd->visited, pfd->include_nondeduced_p))
+         && walk_template_parms (TYPE_PTRMEMFUNC_FN_TYPE
+                                 (TREE_TYPE (t)), fn, data,
+                                 pfd->visited, pfd->check_types,
+                                 pfd->include_nondeduced_p))
        return error_mark_node;
-      break;
-
-    case INDIRECT_REF:
-    case COMPONENT_REF:
-      /* If there's no type, then this thing must be some expression
-        involving template parameters.  */
-      if (!fn && !TREE_TYPE (t))
+      else if (pfd->check_types && TREE_TYPE (t)
+              && walk_template_parms (TREE_TYPE (t), fn, data,
+                                      pfd->visited, pfd->check_types,
+                                      pfd->include_nondeduced_p))
        return error_mark_node;
       break;
 
-    case MODOP_EXPR:
-    case CAST_EXPR:
-    case IMPLICIT_CONV_EXPR:
-    case REINTERPRET_CAST_EXPR:
-    case CONST_CAST_EXPR:
-    case STATIC_CAST_EXPR:
-    case DYNAMIC_CAST_EXPR:
-    case ARROW_EXPR:
-    case DOTSTAR_EXPR:
-    case TYPEID_EXPR:
-    case PSEUDO_DTOR_EXPR:
-      if (!fn)
-       return error_mark_node;
-      break;
-
     default:
       break;
     }
@@ -7938,35 +7949,41 @@ static tree
   return NULL_TREE;
 }
 
-/* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM,
-   BOUND_TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX in T,
-   call FN with the parameter and the DATA.
-   If FN returns nonzero, the iteration is terminated, and
-   for_each_template_parm returns 1.  Otherwise, the iteration
-   continues.  If FN never returns a nonzero value, the value
-   returned by for_each_template_parm is 0.  If FN is NULL, it is
-   considered to be the function which always returns 1.
+/* Walk T looking for TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM,
+   BOUND_TEMPLATE_TEMPLATE_PARM or TEMPLATE_PARM_INDEX.
 
+   If CHECK_TYPES, return 1 if any, 0 otherwise.
+
+   If FN is non-null, for each the iteration calls FN with the parameter
+   and the DATA.  If FN returns nonzero, the iteration is terminated,
+   and walk_template_parms returns 1.  Otherwise, the iteration continues.
+   If FN never returns a nonzero value, the value returned by
+   walk_template_parms is 0.  If FN is NULL, it is considered to be the
+   function which always returns 1.
+
    If INCLUDE_NONDEDUCED_P, then this routine will also visit template
    parameters that occur in non-deduced contexts.  When false, only
    visits those template parameters that can be deduced.  */
 
 static int
-for_each_template_parm (tree t, tree_fn_t fn, void* data,
-                       struct pointer_set_t *visited,
-                       bool include_nondeduced_p)
+walk_template_parms (tree t, tree_fn_t fn, void* data,
+                    struct pointer_set_t *visited,
+                    bool check_types, bool include_nondeduced_p)
 {
   struct pair_fn_data pfd;
   int result;
 
+  gcc_assert (!check_types || !fn);
+
   /* Set up.  */
   pfd.fn = fn;
   pfd.data = data;
+  pfd.check_types = check_types;
   pfd.include_nondeduced_p = include_nondeduced_p;
 
   /* Walk the tree.  (Conceptually, we would like to walk without
-     duplicates, but for_each_template_parm_r recursively calls
-     for_each_template_parm, so we would need to reorganize a fair
+     duplicates, but walk_template_parms_r recursively calls
+     walk_template_parms, so we would need to reorganize a fair
      bit to use walk_tree_without_duplicates, so we keep our own
      visited list.)  */
   if (visited)
@@ -7974,7 +7991,7 @@ static int
   else
     pfd.visited = pointer_set_create ();
   result = cp_walk_tree (&t,
-                        for_each_template_parm_r,
+                        walk_template_parms_r,
                         &pfd,
                         pfd.visited) != NULL_TREE;
 
@@ -8035,8 +8052,9 @@ uses_template_parms (tree t)
 int
 uses_template_parms_level (tree t, int level)
 {
-  return for_each_template_parm (t, template_parm_this_level_p, &level, NULL,
-                                /*include_nondeduced_p=*/true);
+  return walk_template_parms (t, template_parm_this_level_p, &level, NULL,
+                             /*check_types=*/false,
+                             /*include_nondeduced_p=*/true);
 }
 
 /* Returns TRUE iff INST is an instantiation we don't need to do in an
@@ -19744,6 +19762,27 @@ type_dependent_expression_p (tree expression)
   return (dependent_type_p (TREE_TYPE (expression)));
 }
 
+/* Returns TRUE if the EXPRESSION is instantiation-dependent, in the
+   sense defined by the ABI:
+
+   "An expression is instantiation-dependent if it is type-dependent
+   or value-dependent, or it has a subexpression that is type-dependent
+   or value-dependent."  */
+
+bool
+instantiation_dependent_expression_p (tree expression)
+{
+  if (!processing_template_decl)
+    return false;
+
+  if (expression == error_mark_node)
+    return false;
+
+  return walk_template_parms (expression, /*fn=*/NULL, NULL, NULL,
+                             /*check_types=*/true,
+                             /*include_nondeduced_p=*/true);
+}
+
 /* Like type_dependent_expression_p, but it also works while not processing
    a template definition, i.e. during substitution or mangling.  */
 
Index: cp/semantics.c
===================================================================
--- cp/semantics.c      (revision 187058)
+++ cp/semantics.c      (working copy)
@@ -5094,8 +5094,7 @@ finish_static_assert (tree condition, tree message
   if (check_for_bare_parameter_packs (condition))
     condition = error_mark_node;
 
-  if (type_dependent_expression_p (condition) 
-      || value_dependent_expression_p (condition))
+  if (instantiation_dependent_expression_p (condition))
     {
       /* We're in a template; build a STATIC_ASSERT and put it in
          the right place. */
@@ -5168,8 +5167,7 @@ finish_decltype_type (tree expr, bool id_expressio
       return error_mark_node;
     }
 
-  /* FIXME instantiation-dependent  */
-  if (type_dependent_expression_p (expr)
+  if (instantiation_dependent_expression_p (expr)
       /* In a template, a COMPONENT_REF has an IDENTIFIER_NODE for op1 even
         if it isn't dependent, so that we can check access control at
         instantiation time, so defer the decltype as well (PR 42277).  */
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h        (revision 187058)
+++ cp/cp-tree.h        (working copy)
@@ -5363,6 +5363,7 @@ extern bool any_type_dependent_arguments_p      (c
 extern bool any_type_dependent_elements_p       (const_tree);
 extern bool type_dependent_expression_p_push   (tree);
 extern bool value_dependent_expression_p       (tree);
+extern bool instantiation_dependent_expression_p(tree);
 extern bool any_value_dependent_elements_p      (const_tree);
 extern bool dependent_omp_for_p                        (tree, tree, tree, 
tree);
 extern tree resolve_typename_type              (tree, bool);

Reply via email to