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 <[email protected]>
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&);