This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[c++-concepts] member concepts


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);
 }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]