This fixes an ICE trying to normalize a function concept with multiple
statements. That error will now be diagnosed at the point of
definition.

Jason, do you want to review this before I commit? This is a pretty small patch.

2014-09-01  Andrew Sutton  <andrew.n.sut...@gmail.com>

        Check requirements on function concept definitions.
        * gcc/cp/decl.c (finish_function): Check properties of a function
        concept definition.
        * gcc/cp/constraint.cc (check_function_concept): New. Check
        for deduced return type and multiple statements.
        (normalize_misc): Don't normalize multiple statements.
        (normalize_stmt_list): Removed.
        * gcc/cp/cp-tree.h (check_function_concept): New.
        * gcc/testsuite/g++.dg/concepts/fn-concept1.C: New.

Andrew
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 214991)
+++ cp/cp-tree.h	(working copy)
@@ -6444,6 +6444,7 @@ extern tree build_concept_check
 extern tree build_constrained_parameter         (tree, tree, tree = NULL_TREE);
 extern bool deduce_constrained_parameter        (tree, tree&, tree&);
 extern tree resolve_constraint_check            (tree);
+extern tree check_function_concept              (tree);
 
 extern tree finish_concept_introduction         (tree, tree);
 extern tree finish_template_constraints         (tree);
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 214268)
+++ cp/decl.c	(working copy)
@@ -14360,6 +14360,10 @@ finish_function (int flags)
       fntype = TREE_TYPE (fndecl);
     }
 
+  // If this is a concept, check that the definition is reasonable.
+  if (DECL_DECLARED_CONCEPT_P (fndecl))
+    check_function_concept (fndecl);
+
   /* Save constexpr function body before it gets munged by
      the NRV transformation.   */
   maybe_save_function_definition (fndecl);
Index: cp/constraint.cc
===================================================================
--- cp/constraint.cc	(revision 214991)
+++ cp/constraint.cc	(working copy)
@@ -269,6 +269,35 @@ deduce_concept_introduction (tree expr)
     gcc_unreachable ();
 }
 
+
+// -------------------------------------------------------------------------- //
+// Declarations
+
+// Check that FN satisfies the structural requirements of a
+// function concept definition.
+tree 
+check_function_concept (tree fn)
+{
+  location_t loc = DECL_SOURCE_LOCATION (fn);
+
+  // If fn was declared with auto, make sure the result type is bool.
+  if (FNDECL_USED_AUTO (fn) && TREE_TYPE (fn) != boolean_type_node) 
+    error_at (loc, "deduced type of concept definition %qD is not %qT", 
+              fn, boolean_type_node);
+
+  // Check that the function is comprised of only a single
+  // return statements.
+  tree body = DECL_SAVED_TREE (fn);
+  if (TREE_CODE (body) == BIND_EXPR)
+    body = BIND_EXPR_BODY (body);
+  if (TREE_CODE (body) != RETURN_EXPR)
+    error_at (loc, "function concept definition %qD has multiple statements", 
+              fn);
+  
+  return NULL_TREE;
+}
+
+
 // -------------------------------------------------------------------------- //
 // Normalization
 //
@@ -425,9 +454,10 @@ normalize_misc (tree t)
     case CONSTRUCTOR:
       return t;
 
-    case STATEMENT_LIST:
-      return normalize_stmt_list (t);
-    
+    // This should have been caught as an error.
+    case STATEMENT_LIST: 
+      return NULL_TREE;
+
     default:
       gcc_unreachable ();
     }
@@ -630,28 +660,6 @@ normalize_requires (tree t)
   return t;
 }
 
-// Reduction rules for the statement list STMTS.
-//
-// Recursively reduce each statement in the list, concatenating each
-// reduced result into a conjunction of requirements. 
-//
-// A constexpr function may include statements other than a return
-// statement. The primary purpose of these rules is to filter those
-// non-return statements from the constraints language.
-tree
-normalize_stmt_list (tree stmts)
-{
-  tree lhs = NULL_TREE;
-  tree_stmt_iterator i = tsi_start (stmts);
-  while (!tsi_end_p (i))
-    {
-      if (tree rhs = normalize_node (tsi_stmt (i)))
-        lhs = conjoin_constraints (lhs, rhs);
-      tsi_next (&i);
-    }
-  return lhs;
-}
-
 // Normalize a cast expression.
 tree
 normalize_cast (tree t) 
@@ -686,6 +694,7 @@ normalize_constraints (tree reqs)
   ++processing_template_decl;
   tree expr = normalize_node (reqs);
   --processing_template_decl;
+
   return expr;
 }
 
Index: testsuite/g++.dg/concepts/fn-concept1.C
===================================================================
--- testsuite/g++.dg/concepts/fn-concept1.C	(revision 0)
+++ testsuite/g++.dg/concepts/fn-concept1.C	(revision 0)
@@ -0,0 +1,9 @@
+// { dg-options "-std=c++1z" }
+
+template<typename T>
+  concept bool Tuple() { // { dg-error "multiple statements" }
+    static_assert(T::value, "");
+    return true;
+  }
+
+  void f(Tuple&);

Reply via email to