constexpr fallout. In fold_non_dependent_expr, we determined that the expression is not type-dependent, is potentially constant, and is not value-dependent, so we try to fold it. But it isn't potentially constant. So this patch fixes that determination.

Tested x86_64-pc-linux-gnu, applying to trunk and 4.6 (regression).
commit e49c0a722ad7226f7dabfc4a2fea9e47f8fc235f
Author: Jason Merrill <ja...@redhat.com>
Date:   Thu Apr 7 14:52:08 2011 -0400

        PR c++/48500
        * semantics.c (potential_constant_expression_1) [CALL_EXPR]: Check
        arguments even if we don't know the function.

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 2184a53..0b4d1ec 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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)
+       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
           {
            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);
-       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;
+             /* 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 "
diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/call1.C 
b/gcc/testsuite/g++.dg/cpp0x/regress/call1.C
new file mode 100644
index 0000000..833318b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/regress/call1.C
@@ -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));
+}

Reply via email to