re PR c++/48500 (Regression: Failing to convert template argument to concrete type...
authorJason Merrill <jason@redhat.com>
Fri, 8 Apr 2011 06:08:31 +0000 (02:08 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 8 Apr 2011 06:08:31 +0000 (02:08 -0400)
PR c++/48500
* semantics.c (potential_constant_expression_1) [CALL_EXPR]: Check
arguments even if we don't know the function.

From-SVN: r172165

gcc/cp/ChangeLog
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/regress/call1.C [new file with mode: 0644]

index 027eac8..1b8f873 100644 (file)
@@ -1,5 +1,9 @@
 2011-04-07  Jason Merrill  <jason@redhat.com>
 
+       PR c++/48500
+       * semantics.c (potential_constant_expression_1) [CALL_EXPR]: Check
+       arguments even if we don't know the function.
+
        PR c++/48481
        * tree.c (build_overload): Allow an unwrapped FUNCTION_DECL
        at the end of the chain.
index 2184a53..0b4d1ec 100644 (file)
@@ -7358,6 +7358,8 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
             class member access expression, including the result of the
             implicit transformation in the body of the non-static
             member function (9.3.1);  */
+      /* FIXME this restriction seems pointless since the standard dropped
+        "potential constant expression".  */
       if (is_this_parameter (t))
         {
           if (flags & tf_error)
@@ -7373,51 +7375,63 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
       {
         tree fun = get_function_named_in_call (t);
         const int nargs = call_expr_nargs (t);
-        if (TREE_CODE (fun) != FUNCTION_DECL)
-          {
-           if (potential_constant_expression_1 (fun, rval, flags))
-             /* Might end up being a constant function pointer.  */
-             return true;
-            if (flags & tf_error)
-              error ("%qE is not a function name", fun);
-            return false;
-          }
-       /* Skip initial arguments to base constructors.  */
-       if (DECL_BASE_CONSTRUCTOR_P (fun))
-         i = num_artificial_parms_for (fun);
+       i = 0;
+
+       if (is_overloaded_fn (fun))
+         {
+           if (TREE_CODE (fun) == FUNCTION_DECL)
+             {
+               if (builtin_valid_in_constant_expr_p (fun))
+                 return true;
+               if (!DECL_DECLARED_CONSTEXPR_P (fun)
+                   && !morally_constexpr_builtin_function_p (fun))
+                 {
+                   if (flags & tf_error)
+                     error ("%qD is not %<constexpr%>", fun);
+                   return false;
+                 }
+               /* A call to a non-static member function takes the address
+                  of the object as the first argument.  But in a constant
+                  expression the address will be folded away, so look
+                  through it now.  */
+               if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun)
+                   && !DECL_CONSTRUCTOR_P (fun))
+                 {
+                   tree x = get_nth_callarg (t, 0);
+                   if (is_this_parameter (x))
+                     /* OK.  */;
+                   else if (!potential_constant_expression_1 (x, rval, flags))
+                     {
+                       if (flags & tf_error)
+                         error ("object argument is not a potential "
+                                "constant expression");
+                       return false;
+                     }
+                   i = 1;
+                 }
+             }
+           else
+             fun = get_first_fn (fun);
+           /* Skip initial arguments to base constructors.  */
+           if (DECL_BASE_CONSTRUCTOR_P (fun))
+             i = num_artificial_parms_for (fun);
+           fun = DECL_ORIGIN (fun);
+         }
        else
-         i = 0;
-       fun = DECL_ORIGIN (fun);
-        if (builtin_valid_in_constant_expr_p (fun))
-          return true;
-        if (!DECL_DECLARED_CONSTEXPR_P (fun)
-            && !morally_constexpr_builtin_function_p (fun))
           {
-            if (flags & tf_error)
-              error ("%qD is not %<constexpr%>", fun);
-            return false;
+           if (potential_constant_expression_1 (fun, rval, flags))
+             /* Might end up being a constant function pointer.  */;
+           else
+             {
+               if (flags & tf_error)
+                 error ("%qE is not a function name", fun);
+               return false;
+             }
           }
         for (; i < nargs; ++i)
           {
             tree x = get_nth_callarg (t, i);
-            /* A call to a non-static member function takes the
-               address of the object as the first argument.
-               But in a constant expression the address will be folded
-              away, so look through it now.  */
-            if (i == 0 && DECL_NONSTATIC_MEMBER_P (fun)
-                && !DECL_CONSTRUCTOR_P (fun))
-             {
-               if (is_this_parameter (x))
-                 /* OK.  */;
-                else if (!potential_constant_expression_1 (x, rval, flags))
-                 {
-                   if (flags & tf_error)
-                     error ("object argument is not a potential constant "
-                            "expression");
-                   return false;
-                 }
-              }
-           else if (!potential_constant_expression_1 (x, rval, flags))
+           if (!potential_constant_expression_1 (x, rval, flags))
              {
                if (flags & tf_error)
                  error ("argument in position %qP is not a "
index 8f52da2..436404b 100644 (file)
@@ -1,5 +1,7 @@
 2011-04-07  Jason Merrill  <jason@redhat.com>
 
+       * g++.dg/cpp0x/regress/call1.C: New.
+
        * g++.dg/cpp0x/variadic107.C: New.
 
        * g++.dg/cpp0x/sfinae11.C: New.
diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/call1.C b/gcc/testsuite/g++.dg/cpp0x/regress/call1.C
new file mode 100644 (file)
index 0000000..833318b
--- /dev/null
@@ -0,0 +1,13 @@
+// PR c++/48500
+// { dg-options -std=c++0x }
+
+struct linked_ptr {
+};
+template <typename T> linked_ptr make_linked_ptr(T* ptr);
+struct Concrete;
+struct NewedClass {
+  NewedClass(const Concrete& req){}
+};
+template<typename ArgT> void AddObjToChange(const ArgT& req) {
+  linked_ptr p = make_linked_ptr(new NewedClass(req));
+}