This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[c++-concepts] member concepts
- From: Andrew Sutton <andrew dot n dot sutton at gmail dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 24 Jun 2014 11:01:07 -0400
- Subject: [c++-concepts] member concepts
- Authentication-results: sourceware.org; auth=none
Actually allow member concepts in using shorthand notation.
2014-06-24 Andrew Sutton <andrew.n.sutton@gmail.com>
* gcc/cp/parser.c (cp_maybe_constrained_type_specifier): Defer
handling the BASELINK check until concept-resolution in order to
allow member conceps.
(cp_parser_nonclass_name): Also Check for concept-names when the
lookup finds a BASELINk.
* gcc/cp/constraint.cc: (resolve_constraint_check) If the call
target is a base-link, resolve against its overload set.
(build_concept_check): Update comments and variable names to
reflect actual processing.
* gcc/testuite/g++.dg/concepts/mem-concept.C: New test.
* gcc/testuite/g++.dg/concepts/mem-concept-err.C: New test.
Committed as r211946.
Andrew Sutton
Index: mem-concept.C
===================================================================
--- mem-concept.C (revision 0)
+++ mem-concept.C (revision 0)
@@ -0,0 +1,28 @@
+// { dg-options "-std=c++1y" }
+
+struct Base {
+ template<typename T>
+ static concept bool D() { return __is_same_as(T, int); }
+
+ template<typename T, typename U>
+ static concept bool E() { return __is_same_as(T, U); }
+};
+
+void f1(Base::D) { }
+void f2(Base::E<double> x) { }
+
+template<typename T>
+ struct S : Base {
+ void f1(Base::D) { }
+ void f2(Base::E<T> x) { }
+ };
+
+int main() {
+ f1(0);
+
+ f2(0.0);
+
+ S<int> s;
+ s.f1(0);
+ s.f2(0);
+}
Index: mem-concept-err.C
===================================================================
--- mem-concept-err.C (revision 0)
+++ mem-concept-err.C (revision 0)
@@ -0,0 +1,40 @@
+// { dg-options "-std=c++1y" }
+
+
+// The following error is emitted without context. I'm not
+// certain why that would be the case. It comes as a result
+// of failing the declaration of S::f0().
+//
+// cc1plus: error: expected ';' at end of member declaration
+
+
+struct Base {
+ template<typename T, typename U>
+ bool C() const { return false; } // Not a concept!
+
+ template<typename T>
+ static concept bool D() { return __is_same_as(T, int); }
+
+ template<typename T, typename U>
+ static concept bool E() { return __is_same_as(T, U); }
+};
+
+void f1(Base::D) { }
+void f2(Base::E<double> x) { }
+
+template<typename T>
+ struct S : Base {
+ void f0(Base::C<float> x) { } // { dg-error "expected|type" }
+ void f1(Base::D) { }
+ void f2(Base::E<T> x) { }
+ };
+
+int main() {
+ f1('a'); // { dg-error "matching" }
+ f2(0); // { dg-error "matching" }
+
+ S<int> s;
+ s.f1('a'); // { dg-error "matching" }
+ s.f2('a'); // { dg-error "matching" }
+}
+
Index: pt.c
===================================================================
--- pt.c (revision 211415)
+++ pt.c (working copy)
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "print-tree.h"
#include "stringpool.h"
#include "varasm.h"
#include "attribs.h"
Index: parser.c
===================================================================
--- parser.c (revision 211935)
+++ parser.c (working copy)
@@ -15168,6 +15168,7 @@ cp_parser_allows_constrained_type_specif
|| parser->in_result_type_constraint_p);
}
+
// Check if DECL and ARGS can form a constrained-type-specifier. If ARGS
// is non-null, we try to form a concept check of the form DECL<?, ARGS>
// where ? is a placeholder for any kind of template argument. If ARGS
@@ -15177,13 +15178,6 @@ cp_maybe_constrained_type_specifier (cp_
{
gcc_assert (args ? TREE_CODE (args) == TREE_VEC : true);
- // If we get a reference to a member function, allow the referenced
- // functions to participate in this resolution: the baselink may refer
- // to a static member concept.
- if (BASELINK_P (decl))
- decl = BASELINK_FUNCTIONS (decl);
- gcc_assert (TREE_CODE (decl) == OVERLOAD);
-
// Don't do any heavy lifting if we know we're not in a context
// where it could succeed.
if (!cp_parser_allows_constrained_type_specifier (parser))
@@ -15191,7 +15185,8 @@ cp_maybe_constrained_type_specifier (cp_
// Try to build a call expression that evaluates the concept. This
// can fail if the overload set refers only to non-templates.
- tree call = build_concept_check (decl, build_nt(PLACEHOLDER_EXPR), args);
+ tree placeholder = build_nt(PLACEHOLDER_EXPR);
+ tree call = build_concept_check (decl, placeholder, args);
if (call == error_mark_node)
return NULL_TREE;
@@ -15291,7 +15286,8 @@ cp_parser_nonclass_name (cp_parser* pars
//
// TODO: The name could also refer to a variable template or an
// introduction (if followed by '{').
- if (flag_concepts && TREE_CODE (type_decl) == OVERLOAD)
+ if (flag_concepts &&
+ (TREE_CODE (type_decl) == OVERLOAD || BASELINK_P (type_decl)))
{
// Determine whether the overload refers to a concept.
if (tree decl = cp_maybe_concept_name (parser, type_decl))
Index: constraint.cc
===================================================================
--- constraint.cc (revision 211591)
+++ constraint.cc (working copy)
@@ -181,8 +181,13 @@ resolve_constraint_check (tree call)
{
gcc_assert (TREE_CODE (call) == CALL_EXPR);
- // A constraint check must be only be a template-id expression.
+ // A constraint check must be only a template-id expression. If
+ // it's a call to a base-link, its function(s) should be a
+ // template-id expressson. If this is not a template-id, then it
+ // cannot be a concept-check.
tree target = CALL_EXPR_FN (call);
+ if (BASELINK_P (target))
+ target = BASELINK_FUNCTIONS (target);
if (TREE_CODE (target) != TEMPLATE_ID_EXPR)
return NULL_TREE;
@@ -850,19 +855,20 @@ build_call_check (tree id)
}
} // namespace
-// Construct a concept check for the overloaded function, where the
-// template arguments are the list given by ARG and REST. That is, it
-// build the call expression OVL<ARG, REST>(). If REST is null, then
-// the resulting constraint is OVL<ARG>().
+// Construct a concept check for the given TARGET. The target may be
+// an overload set or a baselink referring to an overload set. Template
+// arguments to the target are given by ARG and REST. If the target is
+// a function (overload set or baselink reffering to an overload set),
+// then ths builds the call expression TARGET<ARG, REST>(). If REST is
+// NULL_TREE, then the resulting check is just TARGET<ARG>().
//
-// TODO: Extend this to take a variable concept also.
+// TODO: Allow TARGET to be a variable concept.
tree
-build_concept_check (tree ovl, tree arg, tree rest)
+build_concept_check (tree target, tree arg, tree rest)
{
- gcc_assert (TREE_CODE (ovl) == OVERLOAD);
gcc_assert (rest ? TREE_CODE (rest) == TREE_VEC : true);
- // Build a template-id that acts as the call target using OVL as
+ // Build a template-id that acts as the call target using TARGET as
// the template and ARG as the only explicit argument.
int n = rest ? TREE_VEC_LENGTH (rest) : 0;
tree targs = make_tree_vec (n + 1);
@@ -871,7 +877,7 @@ build_concept_check (tree ovl, tree arg,
for (int i = 0; i < n; ++i)
TREE_VEC_ELT (targs, i + 1) = TREE_VEC_ELT (rest, i);
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, n + 1);
- tree id = lookup_template_function (ovl, targs);
+ tree id = lookup_template_function (target, targs);
return build_call_check (id);
}