Hi,

one of those cases where we error out in a SFINAE context because the tsubst_flags_t isn't propagated far enough. The straightforward patch works fine mainline and 4_8-branch.

Tested x86_64-linux.

Thanks,
Paolo.

////////////////////////
/cp
2013-04-24  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/56970
        * init.c (build_offset_ref): Add tsubst_flags_t parameter.
        * semantics.c (finish_qualified_id_expr): Likewise.
        (finish_id_expression): Update.
        * typeck.c (cp_build_addr_expr_1): Likewise.
        * pt.c (tsubst_qualified_id, resolve_nondeduced_context): Likewise.
        * cp-tree.h: Update declarations.

/testsuite
2013-04-24  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/56970
        * g++.dg/cpp0x/sfinae45.C: New.
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h        (revision 198220)
+++ cp/cp-tree.h        (working copy)
@@ -5351,7 +5351,8 @@ extern tree get_type_value                        (tree);
 extern tree build_zero_init                    (tree, tree, bool);
 extern tree build_value_init                   (tree, tsubst_flags_t);
 extern tree build_value_init_noctor            (tree, tsubst_flags_t);
-extern tree build_offset_ref                   (tree, tree, bool);
+extern tree build_offset_ref                   (tree, tree, bool,
+                                                tsubst_flags_t);
 extern tree build_new                          (vec<tree, va_gc> **, tree, 
tree,
                                                 vec<tree, va_gc> **, int,
                                                  tsubst_flags_t);
@@ -5748,7 +5749,7 @@ extern void add_typedef_to_current_template_for_ac
                                                              location_t);
 extern void check_accessibility_of_qualified_id (tree, tree, tree);
 extern tree finish_qualified_id_expr           (tree, tree, bool, bool,
-                                                bool, bool);
+                                                bool, bool, tsubst_flags_t);
 extern void simplify_aggr_init_expr            (tree *);
 extern void finalize_nrv                       (tree *, tree, tree);
 extern void note_decl_for_pch                  (tree);
Index: cp/init.c
===================================================================
--- cp/init.c   (revision 198220)
+++ cp/init.c   (working copy)
@@ -1817,7 +1817,8 @@ get_type_value (tree name)
    @@ This function should be rewritten and placed in search.c.  */
 
 tree
-build_offset_ref (tree type, tree member, bool address_p)
+build_offset_ref (tree type, tree member, bool address_p,
+                 tsubst_flags_t complain)
 {
   tree decl;
   tree basebinfo = NULL_TREE;
@@ -1841,7 +1842,8 @@ tree
   type = TYPE_MAIN_VARIANT (type);
   if (!COMPLETE_OR_OPEN_TYPE_P (complete_type (type)))
     {
-      error ("incomplete type %qT does not have member %qD", type, member);
+      if (complain & tf_error)
+       error ("incomplete type %qT does not have member %qD", type, member);
       return error_mark_node;
     }
 
@@ -1854,7 +1856,8 @@ tree
 
   if (TREE_CODE (member) == FIELD_DECL && DECL_C_BIT_FIELD (member))
     {
-      error ("invalid pointer to bit-field %qD", member);
+      if (complain & tf_error)
+       error ("invalid pointer to bit-field %qD", member);
       return error_mark_node;
     }
 
@@ -1883,10 +1886,10 @@ tree
          if (address_p && DECL_P (t)
              && DECL_NONSTATIC_MEMBER_P (t))
            perform_or_defer_access_check (TYPE_BINFO (type), t, t,
-                                          tf_warning_or_error);
+                                          complain);
          else
            perform_or_defer_access_check (basebinfo, t, t,
-                                          tf_warning_or_error);
+                                          complain);
 
          if (DECL_STATIC_FUNCTION_P (t))
            return t;
@@ -1900,7 +1903,7 @@ tree
        check_accessibility_of_qualified_id in case it is
        a pointer to non-static member.  */
     perform_or_defer_access_check (TYPE_BINFO (type), member, member,
-                                  tf_warning_or_error);
+                                  complain);
 
   if (!address_p)
     {
@@ -1932,15 +1935,17 @@ tree
          if (flag_ms_extensions)
            {
              PTRMEM_OK_P (member) = 1;
-             return cp_build_addr_expr (member, tf_warning_or_error);
+             return cp_build_addr_expr (member, complain);
            }
-         error ("invalid use of non-static member function %qD",
-                TREE_OPERAND (member, 1));
+         if (complain & tf_error)
+           error ("invalid use of non-static member function %qD",
+                  TREE_OPERAND (member, 1));
          return error_mark_node;
        }
       else if (TREE_CODE (member) == FIELD_DECL)
        {
-         error ("invalid use of non-static data member %qD", member);
+         if (complain & tf_error)
+           error ("invalid use of non-static data member %qD", member);
          return error_mark_node;
        }
       return member;
Index: cp/pt.c
===================================================================
--- cp/pt.c     (revision 198220)
+++ cp/pt.c     (working copy)
@@ -12053,7 +12053,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
       expr = (finish_qualified_id_expr
              (scope, expr, done, address_p && PTRMEM_OK_P (qualified_id),
               QUALIFIED_NAME_IS_TEMPLATE (qualified_id),
-              /*template_arg_p=*/false));
+              /*template_arg_p=*/false, complain));
     }
 
   /* Expressions do not generally have reference type.  */
@@ -16040,7 +16040,7 @@ resolve_nondeduced_context (tree orig_expr)
            {
              tree base
                = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (offset, 0)));
-             expr = build_offset_ref (base, expr, addr);
+             expr = build_offset_ref (base, expr, addr, tf_warning_or_error);
            }
          if (addr)
            expr = cp_build_addr_expr (expr, tf_warning_or_error);
Index: cp/semantics.c
===================================================================
--- cp/semantics.c      (revision 198220)
+++ cp/semantics.c      (working copy)
@@ -1772,7 +1772,8 @@ finish_qualified_id_expr (tree qualifying_class,
                          bool done,
                          bool address_p,
                          bool template_p,
-                         bool template_arg_p)
+                         bool template_arg_p,
+                         tsubst_flags_t complain)
 {
   gcc_assert (TYPE_P (qualifying_class));
 
@@ -1792,7 +1793,7 @@ finish_qualified_id_expr (tree qualifying_class,
       if (TREE_CODE (expr) == SCOPE_REF)
        expr = TREE_OPERAND (expr, 1);
       expr = build_offset_ref (qualifying_class, expr,
-                              /*address_p=*/true);
+                              /*address_p=*/true, complain);
       return expr;
     }
 
@@ -1826,11 +1827,12 @@ finish_qualified_id_expr (tree qualifying_class,
                 expr,
                 BASELINK_ACCESS_BINFO (expr),
                 /*preserve_reference=*/false,
-                tf_warning_or_error));
+                complain));
       else if (done)
        /* The expression is a qualified name whose address is not
           being taken.  */
-       expr = build_offset_ref (qualifying_class, expr, /*address_p=*/false);
+       expr = build_offset_ref (qualifying_class, expr, /*address_p=*/false,
+                                complain);
     }
   else if (BASELINK_P (expr))
     ;
@@ -3278,7 +3280,8 @@ finish_id_expression (tree id_expression,
                    decl = finish_qualified_id_expr (scope, decl,
                                                     done, address_p,
                                                     template_p,
-                                                    template_arg_p);
+                                                    template_arg_p,
+                                                    tf_warning_or_error);
                  else
                    {
                      tree type = NULL_TREE;
@@ -3394,7 +3397,8 @@ finish_id_expression (tree id_expression,
                                             done,
                                             address_p,
                                             template_p,
-                                            template_arg_p);
+                                            template_arg_p,
+                                            tf_warning_or_error);
          else
            decl = convert_from_reference (decl);
        }
Index: cp/typeck.c
===================================================================
--- cp/typeck.c (revision 198220)
+++ cp/typeck.c (working copy)
@@ -5164,7 +5164,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
                       "  Say %<&%T::%D%>",
                       base, name);
        }
-      arg = build_offset_ref (base, fn, /*address_p=*/true);
+      arg = build_offset_ref (base, fn, /*address_p=*/true, complain);
     }
 
   /* Uninstantiated types are all functions.  Taking the
Index: testsuite/g++.dg/cpp0x/sfinae45.C
===================================================================
--- testsuite/g++.dg/cpp0x/sfinae45.C   (revision 0)
+++ testsuite/g++.dg/cpp0x/sfinae45.C   (working copy)
@@ -0,0 +1,35 @@
+// PR c++/56970
+// { dg-do compile { target c++11 } }
+
+template <typename T>
+struct has
+{
+  template <typename>
+  constexpr static int test(...) {
+    return 0;
+  }
+  
+  template <typename C>
+  constexpr static int test(decltype(sizeof(C::x))) {  // Doesn't compile.
+    return 1;   // Is a member variable.
+  }
+  
+  template <typename C, int c = sizeof(decltype(((C*)nullptr)->x()))>
+  constexpr static int test(int) {
+    return 2;   // Is a member function.
+  }
+
+  static const int value = test<T>(0);
+};
+
+struct foo {
+  int x;
+};
+
+struct bar {
+  int x();
+};
+
+static_assert(has<int>::value == 0, "");
+static_assert(has<foo>::value == 1, "");
+static_assert(has<bar>::value == 2, "");

Reply via email to