re PR c++/48535 ([C++0x][SFINAE] Hard errors during list-value-initialization)
authorJason Merrill <jason@redhat.com>
Mon, 11 Apr 2011 22:01:04 +0000 (18:01 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 11 Apr 2011 22:01:04 +0000 (18:01 -0400)
PR c++/48535
* decl.c (cp_complete_array_type_or_error): New.
* semantics.c (finish_compound_literal): Use it.
* cp-tree.h: Declare it.

From-SVN: r172287

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/sfinae12.C [new file with mode: 0644]

index d5975fcfbadfc9df602e9a33966058a637981613..bf7113f19030028882862f16c606ed10cf281fff 100644 (file)
@@ -1,5 +1,10 @@
 2011-04-11  Jason Merrill  <jason@redhat.com>
 
+       PR c++/48535
+       * decl.c (cp_complete_array_type_or_error): New.
+       * semantics.c (finish_compound_literal): Use it.
+       * cp-tree.h: Declare it.
+
        PR c++/48535
        * semantics.c (finish_compound_literal): Handle references.
 
index 44a20ead20a2fb2e8b784a74cf32809c24926427..4321d28d4630aaa33e3c2a9ef36236bc6e587b35 100644 (file)
@@ -4791,6 +4791,7 @@ extern void start_decl_1                  (tree, bool);
 extern bool check_array_initializer            (tree, tree, tree);
 extern void cp_finish_decl                     (tree, tree, bool, tree, int);
 extern int cp_complete_array_type              (tree *, tree, bool);
+extern int cp_complete_array_type_or_error     (tree *, tree, bool, tsubst_flags_t);
 extern tree build_ptrmemfunc_type              (tree);
 extern tree build_ptrmem_type                  (tree, tree);
 /* the grokdeclarator prototype is in decl.h */
index a541402ab6642f87ad2e2a183a9caae279cfdcc2..7dea9b7baa556b35105193d424aca092de8dfdf8 100644 (file)
@@ -6689,6 +6689,39 @@ cp_complete_array_type (tree *ptype, tree initial_value, bool do_default)
 
   return failure;
 }
+
+/* As above, but either give an error or reject zero-size arrays, depending
+   on COMPLAIN.  */
+
+int
+cp_complete_array_type_or_error (tree *ptype, tree initial_value,
+                                bool do_default, tsubst_flags_t complain)
+{
+  int failure;
+  bool sfinae = !(complain & tf_error);
+  /* In SFINAE context we can't be lenient about zero-size arrays.  */
+  if (sfinae)
+    ++pedantic;
+  failure = cp_complete_array_type (ptype, initial_value, do_default);
+  if (sfinae)
+    --pedantic;
+  if (failure)
+    {
+      if (sfinae)
+       /* Not an error.  */;
+      else if (failure == 1)
+       error ("initializer fails to determine size of %qT", *ptype);
+      else if (failure == 2)
+       {
+         if (do_default)
+           error ("array size missing in %qT", *ptype);
+       }
+      else if (failure == 3)
+       error ("zero-size array %qT", *ptype);
+      *ptype = error_mark_node;
+    }
+  return failure;
+}
 \f
 /* Return zero if something is declared to be a member of type
    CTYPE when in the context of CUR_TYPE.  STRING is the error
index 461aa0aff3205fa0a0d1b4a11725f1d58ad70af4..61d87beedaaf5a847857659e116860b74f713470 100644 (file)
@@ -2355,8 +2355,14 @@ finish_compound_literal (tree type, tree compound_literal,
       && check_array_initializer (NULL_TREE, type, compound_literal))
     return error_mark_node;
   compound_literal = reshape_init (type, compound_literal);
-  if (TREE_CODE (type) == ARRAY_TYPE)
-    cp_complete_array_type (&type, compound_literal, false);
+  if (TREE_CODE (type) == ARRAY_TYPE
+      && TYPE_DOMAIN (type) == NULL_TREE)
+    {
+      cp_complete_array_type_or_error (&type, compound_literal,
+                                      false, complain);
+      if (type == error_mark_node)
+       return error_mark_node;
+    }
   compound_literal = digest_init (type, compound_literal);
   /* Put static/constant array temporaries in static variables, but always
      represent class temporaries with TARGET_EXPR so we elide copies.  */
index 6612d864613c4d62b204c8cf3450effc16487edf..c5efa1b5e63fd0c152197cb27745e648a54d6656 100644 (file)
@@ -1,5 +1,7 @@
 2011-04-11  Jason Merrill  <jason@redhat.com>
 
+       * g++.dg/cpp0x/sfinae12.C: New.
+
        * g++.dg/cpp0x/enum10.C: New.
 
        * g++.dg/cpp0x/lambda/lambda-this4.C: New.
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae12.C b/gcc/testsuite/g++.dg/cpp0x/sfinae12.C
new file mode 100644 (file)
index 0000000..114f1b4
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/48535
+// { dg-options -std=c++0x }
+
+template<class T,
+ class = decltype(T{})
+>
+char f(int);
+
+template<class>
+char (&f(...))[2];
+
+struct A { virtual ~A() = 0; };
+
+static_assert(sizeof(f<A>(0)) != 1, "Error"); // (a)
+static_assert(sizeof(f<void()>(0)) != 1, "Error"); // (b)
+static_assert(sizeof(f<int&>(0)) != 1, "Error"); // (d)
+static_assert(sizeof(f<const int&>(0)) == 1, "Error"); // (e)
+static_assert(sizeof(f<int[]>(0)) != 1, "Error"); // (f)