Re: contracts library support (was Re: [PATCH] PING implement pre-c++20 contracts)

2021-07-16 Thread Andrew Sutton via Gcc-patches
> Is just using std::terminate as the handler viable? Or if we're sure
> contracts in some form will go into the IS eventually, and the
> signature won't change, we could just add it in __cxxabiv1:: as you
> suggested earlier.

No, the handler needs to be configurable (at least quietly) in order
to support experimentation by SG21. No idea if it will stay that way.

Andrew


Re: [PATCH] PING implement pre-c++20 contracts

2021-07-02 Thread Andrew Sutton via Gcc-patches
I think so, yes.

On Fri, Jul 2, 2021 at 11:09 AM Jason Merrill  wrote:
>
> On 7/1/21 12:27 PM, Andrew Sutton wrote:
> >>> I think this version addresses most of your concerns.
> >>
> >> Thanks, looking good.  I'll fuss with it a bit and commit it soon.
>
> Do you agree that this testcase should compile?


Re: [PATCH] PING implement pre-c++20 contracts

2021-07-01 Thread Andrew Sutton via Gcc-patches
> > I think this version addresses most of your concerns.
>
> Thanks, looking good.  I'll fuss with it a bit and commit it soon.

Awesome!

Andrew


Re: [PATCH] implement pre-c++20 contracts

2020-12-03 Thread Andrew Sutton via Gcc-patches
>
>
> > Attached is a new squashed revision of the patch sans ChangeLogs. The
> > current work is now being done on github:
> > https://github.com/lock3/gcc/tree/contracts-jac-alt
>
> I'm starting to review this now, sorry for the delay. Is this still the
> branch you want me to consider for GCC 11?  I notice that the -constexpr
> and -mangled-config branches are newer.


I think so. Jeff can answer more authoritatively. I know we had one set of
changes to the design (how contracts) work aimed at improving the debugging
experience for violated contracts. I'm not sure if that's in the jac-alt
branch though.

The -constexpr branch checks for trivially satisfied contracts (e.g.,
[[assert: true]]) and issues warnings. It also preemptively checks
preconditions against constant function arguments. It's probably worth
reviewing that separately.

I'm not sure the -manged-config branch is worth considering for merging at
this point. It's trying to solve a problem that might not be worth solving.

Out of curiosity, are you concerned that future versions of contracts might
have considerably different syntax or configurability? I'd hope it
wouldn't, but who knows where SG21 is going :)

Andrew


Re: [PATCH] implement pre-c++20 contracts

2020-03-24 Thread Andrew Sutton via Gcc-patches
Hi Jason,

Sorry I haven't been able to get back to this. I've been swamped with
other work, and we haven't had the resources to properly address this.
Jeff Chapman will be working on cleaning this up for when master/trunk
re-opens.


> I find the proposed always_continue semantics kind of nonsensical, as
> somewhat evidenced by the contortions the implementation gets into with
> marking the violation handler as pure.  The trick of assigning the
> result to a local variable won't work with optimization.

We tend to agree and think it's practically non-implementable. IIRC,
later contracts proposals steered away from adding this as a concrete
semantic. I suspect killing this would be fine.

> > +/* Definitions for C++ contract levels
> > +   Copyright (C) 1987-2018 Free Software Foundation, Inc.
>
> Should just be 2019 for a new file.

Probably 2020 now :)

> > +   Contributed by Michael Tiemann (tiem...@cygnus.com)
>
> This seems inaccurate.  :)

Indeed :)


> This change to member function redeclaration seems undesirable; your
> rationale in P1680 is "for generality", but member functions are already
> stricter about redeclaration than non-member functions; I don't see a
> reason to relax this rule just for contracts.  With member functions,
> there *is* always a canonical first declaration, and people expect the
> class definition to have its complete interface, of which contracts are
> a part.

There was a proposal that gave more motivation than just "for
generality". Apparently, I was a co-author -- I think I just helped
write the wording.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1320r2.html


> For non-member functions, we still need to complain if contracts are
> added after we've seen an ODR-use of the function, just like with
> explicit specializations.

We could do that, but it doesn't seem necessary with this model.
Whether the contracts have been seen or not doesn't affect which
function is called.


> > +  /* TODO is there any way to relax this requirement?  */
> > +  if (DECL_VIRTUAL_P (olddecl) && !TYPE_BEING_DEFINED (DECL_CONTEXT 
> > (olddecl)))
>
> Relatedly, I don't think we want to relax this requirement.

Probably. Virtual functions and contracts have complex interactions.
There are going to be more EWG papers about this, I'm sure.


> > +  /* FIXME Is this right for friends? Can a friend refer to a static 
> > member?
> > + Can a friend's contracts refer to our privates? Turning them into
> > + [[assert]]s inside the body of the friend itself certainly lets them 
> > do
> > + so. */
>
> P0542 says contracts are limited to the accessibility of the function
> itself, so a friend cannot refer to private members.

That will almost certainly be changed. This was the proposal:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1289r0.pdf

There was near-unanimous support for removing that (19 for, 1 against).

Andrew


[PATCH] PR C++/92739

2019-12-02 Thread Andrew Sutton
Find attached.

   gcc/cp/
* parser.c (cp_parser_constraint_requires_parens): Exclude
attributes
as postfix expressions.

gcc/testsuite/
* g++.dg/concepts-pr92739.C: New test.

Andrew Sutton


0001-Fix-PR-c-92739.patch
Description: Binary data


Re: [PATCH] Prevent recursive satisfaction (PR c++/88395)

2019-11-27 Thread Andrew Sutton
> > +  if (tmpl)
> > + push_tinst_level (tmpl);
>
> Actually, why not pass 't' here?

I thought it would matter if 't' was a non-template. Turns out it
doesn't. Updated and committed.


[PATCH] PR c++/92439: Improve diagnostics for ill-formed requires-clauses

2019-11-22 Thread Andrew Sutton
This does a much better job identifying when an expression in a
requires-clause needs parentheses.

Andrew Sutton


0001-PR-c-92439.patch
Description: Binary data


[PATCH] PR c++/92236: Improve static assertions of concepts

2019-11-20 Thread Andrew Sutton
This patch builds on https://gcc.gnu.org/ml/gcc-patches/2019-11/msg01034.html.

Tie static assertion diagnostics into constraint diagnostic. For
example, this program:

template
concept iterator =
  requires (I i)
  {
++i;
*i;
  };

static_assert(iterator);

Yields these errors:

x.cpp:11:15: error: static assertion failed
   11 | static_assert(iterator);
  |   ^
x.cpp:11:15: note: constraints not satisfied
x.cpp:4:9:   required by the constraints of ‘template concept iterator’
x.cpp:5:3:   in requirements with ‘int i’
x.cpp:8:5: note: the required expression ‘* i’ is invalid
8 | *i;
  | ^~

Andrew Sutton


0001-Emit-detailed-diagnostics-for-static-assertion-failu.patch
Description: Binary data


Re: [PATCH] Prevent recursive satisfaction (PR c++/88395)

2019-11-18 Thread Andrew Sutton
I forgot to mention a somewhat odd test included in the patch:
concepts-recursive-sat3.C does not recurse. Code follows:

template
concept Fooable = requires(T t) { foo(t); };

template
void foo(T t) { }

void test()
{
  foo(0); // { dg-error "unsatisfied constraints" }
}

It doesn't crash, but it doesn't diagnose also doesn't fail as a
result of recursive instantiation. The recursive-sat2.C test is the
same except that it instantiates foo with a class type. This seems
like it might be related to ADL, but entirely certain.

Andrew Sutton

On Mon, Nov 18, 2019 at 10:13 AM Andrew Sutton
 wrote:
>
> This applies on top of the patch here:
> https://gcc.gnu.org/ml/gcc-patches/2019-11/msg01034.html
>
> Wrap satisfaction with push/pop_tinst_level to force termination on recursion.
>
> Andrew Sutton


[PATCH] Prevent recursive satisfaction (PR c++/88395)

2019-11-18 Thread Andrew Sutton
This applies on top of the patch here:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg01034.html

Wrap satisfaction with push/pop_tinst_level to force termination on recursion.

Andrew Sutton


0001-Prevent-recursive-satisfaction-PR-c-88395.patch
Description: Binary data


[PATCH] Fixes PR c++/89913

2019-11-15 Thread Andrew Sutton
Avoid ICE when the alias is ill-formed.

 gcc/cp/
  * pt.c (get_underlying_template): Exit loop if the original type
of the alias is null.

gcc/testsuite/
  * g++.dg/cpp2a/pr89913.C: New test.

Andrew Sutton


0001-Don-t-segfault-on-error-PR-c-89913.patch
Description: Binary data


[PATCH] PR c++/92078 Add access specifiers to specializations

2019-11-14 Thread Andrew Sutton
Fixes mentioned issue. Tested on bootstrap and cmcsstl2.

gcc/cp/
* pt.c (maybe_new_partial_specialization): Apply access to newly
created partial specializations. Update comment style.

gcc/testsuite/
* g++.dg/cpp2a/concepts-pr92078.C: New.

Andrew


pr92078.patch
Description: Binary data


[PATCH] PR c++/92403

2019-11-13 Thread Andrew Sutton
Suppress diagnostics when substituting into requires-expressions
outside of concept definitions.

This change broke one existing test, which I've updated to match the
behavior of the current patch. Specifically, it changed the case
below:

template
constexpr bool subst = true;

template
constexpr bool test()
{
  if constexpr (requires { requires subst; }) // error?
return true;
  else
return false;
}

static_assert(!test());

Before, the program is ill-formed as a result of substituting void for
U. After applying, the requirement is false. If you replace the
requires-expression with a concept (either before or after the patch),
you get false. So, this seems like the right behavior.

Andrew Sutton


0001-Suppress-diagnostics-substituting-into-a-requires-ex.patch
Description: Binary data


[PATCH] Diagnose hard errors during constraint satisfaction

2019-11-13 Thread Andrew Sutton
This changes the diagnostic of non-boolean constraints and rvalue
conversion failures in constraint satisfaction into hard errors. I
also cleaned up the satisfaction routines to reduce the number of
functions involved.

Jason, this is a squashed version of the patches I sent earlier today.

This patch also fixes the crash PR92439, which was caused by not
building the normalization tree in satisfy_constraint_expression.
However, there are some other problems with that example that cause it
to not compile (e.g., non-boolean atomic constraints).

Andrew Sutton


0001-Diagnose-certain-constraint-errors-as-hard-errors.patch
Description: Binary data


Re: [PATCH] fix constrained auto parsing issue

2019-10-21 Thread Andrew Sutton
In cp_parser_simple_type_specifier:

if (!type && flag_concepts && decl_specs)
{
  /* Try for a type-constraint with template arguments.  We check
 decl_specs here to avoid trying this for a functional cast.  */
 ...

It's subtle.

Andrew Sutton

On Mon, Oct 21, 2019 at 2:22 PM Jason Merrill  wrote:
>
> On 10/17/19 10:36 AM, Andrew Sutton wrote:
> > This fixes a parsing bug with constrained placeholders uses as the
> > first parameter of a constructor.
>
> > +  Parse with an empty set of declaration specifiers since we're
> > +  trying to match a type-specifier of the first parameter.  */
>
> Why does that make a difference?
>
> Jason
>


[PATCH] fix constrained auto parsing issue

2019-10-17 Thread Andrew Sutton
This fixes a parsing bug with constrained placeholders uses as the
first parameter of a constructor.

Andrew Sutton


0001-Fix-a-bug-with-type-constraints-in-constructors.patch
Description: Binary data


[PATCH] diagnose hard errors in concept satisfaction

2019-10-15 Thread Andrew Sutton
Certain errors encountered during constraint satisfaction render the
program ill-formed. Emit those as errors during satisfaction and not
when diagnosing constraint errors.

The errors should include the full context for failure (i.e., when
satisfying X, when satisfying Y, this failed), but we don't build that
information until we know we need to diagnose an error. This patch
does not include that context.

Andrew Sutton


errors.patch
Description: Binary data


[PATCH] concepts cleanups and subsumption caching

2019-10-15 Thread Andrew Sutton
This patch finishes moving concepts-related functionality out of pt.c
and into constraint.cc an logic.cc, and adds logic.cc to gtfiles.

As part of that cleanup, I reimplemented and reenabled the subsumption
caching. It's not clear if this provides any significant performance
benefits, but it will prevent redundant and potentially costly
comparisons of constraints.

Tested on bootstrap and vs. cmcstl2.

Andrew Sutton


cleanup.patch
Description: Binary data


Re: [C++ Patch] PR 71140 ("[concepts] ill-formed nested-requirement lacking a semicolon not rejected")

2018-10-31 Thread Andrew Sutton
Sorry for the slow reply. I've been stuck working on some other projects.


> Can you say a bit about why that was better than continuing to use
> VAR_DECL?
>

I wanted to make sure that we avoid normal VAR_DECL processing routines, so
we don't e.g., slip into a function where we might try to generate an
address for a concept.


Yeah, don't worry about trying to send small patches.  I don't mind
> reviewing what's on the branch, though at least the final patch should
> be sent to the list for archival.
>
> What feedback are you looking for at this point?
>

Mostly anything that would obviously prevent or cause problems merging in
the near future.

I'll try to keep the asutton/gcc fork on github rebased on trunk so there
shouldn't be too many merge issues.


Re: [concepts] Update to match the working draft (and bit more)

2018-10-18 Thread Andrew Sutton
Well,,that's unfortunate. Please forgive the alternative patch submission.

https://github.com/asutton/gcc/blob/master/concepts.patch


> Attached is a rework of the Concepts TS implementation to match the
> Working Draft. It's a big patch -- I'd loved to make it smaller, but
> it didn't work out that way.
>
> Here's a brief summary of changes:
>
> - Make concepts work with -std=c++2a; warn if -fconcepts is also supplied.
> - Add a new flag -fconcepts-ts to enable TS syntax* when -std=c++2a is
used.
> - No more bool for concepts. They are their own kind of declaration.
> - New grammar for requires clauses (unfortunately). This can be
> overriden with -fconcepts-ts.
> - Support "concept bool" with -fconcepts-ts. This includes both
> variable and function concepts.
> - Constraints are instantiated only at the point of use and properly
> interleave substitution and evaluation. This should fix any issues
> with "premature substitution" errors.
> - Implement semantic comparison of atomic constraints (P0717). This
> may be buggy. More testing with complex refinement hierarchies is
> needed.
> - Completely rewrite the subsumption algorithm in logic. The WD broke
> a number of assumptions the previous version relied on, so a simple
> fix wasn't possible. We haven't seen the performance issues related to
> subsumption that showed up in the past. They're still there, but other
> core changes minimize the likelihood of achieving worst case.
> - Declaration matching is syntactic (P0716).
> - Warnings are emitted for the use of TS syntax unless -fconcepts-ts
> is specified. And if you do use -fconcepts, the same-type rule for
> abbreviated function templates is dead.
> - And just because... make template introduction semantics actually
> conform to the TS. We weren't allowing the introduction of a fixed
> series of template parameters for an introduced pack. We do now.
>
> This is not a perfect patch.
>
> - It somehow breaks partial template specializations of variable
> templates (cpp2a/concepts pr80471.C). I have no idea how that
> happened. It almost looks like a GC bug.
> - There's a new regression in cpp2a/concepts-ts2.C)
> - This breaks a lot of concepts TS support (the g++.dg/concepts dir).
> - We've seen other errors in parts of GCC not even remotely related to
> concepts**.
>
> My goals over the next few weeks are to clean up the regressions and
> start working through the backlog of concepts issues. That includes
> fixing new issues as they arise.
>
> * This patch does not preserve the Concepts TS semantics. Anybody
> relying on e.g., subtleties of the partial ordering rules in the TS
> will find themselves with broken code. This was a conscious choice.
> there are serious design issues in the TS.
>
> ** Unfortunately, my testing effort before sending this patch is a bit
> hampered by the fact that a clean bootstrap build ICEs here (bootstrap
> build on Mac OS -- can give more details if needed).
>
> ../../isl/isl_tab_pip.c: In function
‘isl_tab_basic_set_non_trivial_lexmin’:
> ../../isl/isl_tab_pip.c:5087:21: internal compiler error: in check, at
> tree-vrp.c:155
>  5087 | __isl_give isl_vec *isl_tab_basic_set_non_trivial_lexmin(
>   | ^~~~
>
> This one isn't my fault :)
>
> Enjoy,
>

>> Hi. This is the qmail-send program at sourceware.org.
>> I'm afraid I wasn't able to deliver your message to the following
addresses.
>> This is a permanent error; I've given up. Sorry it didn't work out.
>>
>> :
>> ezmlm-reject: fatal: Sorry, I don't accept messages larger than 40
bytes (#5.2.3)


> Andrew Sutton


Re: [C++ Patch] PR 71140 ("[concepts] ill-formed nested-requirement lacking a semicolon not rejected")

2018-10-12 Thread Andrew Sutton
>
> BTW, I would discourage you from messing much with the concepts code
> at this point, as a major overhaul should be coming soon.
>

Major overhaul:

https://github.com/asutton/gcc (branch is concepts; we're about 2 weeks
back from trunk).

Unfortunately, I we haven't been following GCC commit discipline, and
there's a bunch of dead/legacy code that I need to clean up. And of course
some regressions. I wanted to spend the weekend on this and forward a
cleaner version next week. But no time is as good as the present it seems.

This fork reimplements concepts as currently specified in the WD (for the
most part). It also preserves TS syntax (but not behavior), although there
are certainly going to be some new bugs.

-std=c++2a turns on concepts by default (sets -fconcepts)
-fconcepts-ts can be additionally specified to enable TS extensions
(abbreviated fn templates, etc).
-fconcepts on its own gives you (should give you) TS syntax with C++20
semantics and no C++20 features.

Here's what's changed:
- new requires clause syntax as required in the WD (-fconcepts-ts will
change this back to the TS syntax)
- concept bool is now a warning, although (IIRC) disabled with
-fconcepts-ts. Function and variable concepts live on.
- concepts are now their own kind of declaration (CONCEPT_DECL). That was a
big change.
- now only 3 kinds of constraints: conj, disj, and pred (should be
atomic, also needs a dead code cleanup).
- constraints on declarations are represented as expressions -- no
normalization until later
- associated constraints are only instantiated when checked -- no premature
substitution
- new implementaiton of satisfaction, does not require ahead-of-time
normalization
- new implementation of normalization (fewer nodes, smaller impl)
- atomic constraint comparison based on expr identity/parameter mapping
- complete rewrite of subsumption (new comparison model invalidated some
assumptions in the old impl)
- constrained decls differentiated by syntax of constraints (not
equivalence)
- moved the concepts testsuite into c++2a directory as a vetting/curating
process, new 2a tests, new ts-compatability tests

There are some bugs and regressions. I know for a fact that we've broken
partial specialization of variable templats, but I'm really not sure how.
There's also probably a bug in the constraint comparison implementation
that affects partial ordering. More testing is needed. I mostly ignored the
TS support while updating to the WD semantics, so that's been a little
buggy when I brought it back online. Also, sometimes diagnostics aren't
emitted correctly.

I'm not quite sure how to proceed with submitting this patch. Once I made
the decision to make concepts their own kind of declaration, the idea of
sending small patches went right out the window.


Re: [PATCH] Add -std=c++2a

2017-07-20 Thread Andrew Sutton
For now, I think these two are incompatible. There are more features
in -fconcepts than in C++20 (so far). There are also some changes in
syntax and semantics that would be nice to diagnose. A good example
would be 'concept' as a decl-specifier (TS) vs. 'concept' as a
declaration introducer (WD).

I was going to submit a followup that emits a warning when both
-std=c++2a and -fconcepts are both enabled and then disables
-fconcepts.

Andrew Sutton


On Thu, Jul 20, 2017 at 1:04 PM, Markus Trippelsdorf
<mar...@trippelsdorf.de> wrote:
> On 2017.07.20 at 09:33 -0400, Andrew Sutton wrote:
>> This adds a new C++ dialect, enabled by -std=c++2a.
>>
>> libcpp/
>> Add support for C++2a.
>> * include/cpplib.h (c_lang): Add CXX2A and GNUCXX2A.
>> * init.c (lang_defaults): Add rows for CXX2A and GNUCXX2A.
>> (cpp_init_builtins): Set __cplusplus to 201707L for C++2x.
>>
>> gcc/c-family/
>> Add support for -std=c++2a.
>> * c-common.h (cxx_dialect): Add cxx2a as a dialect.
>> * opt.c: Add options for -std=c++2a and -std=gnu++2a.
>> * c-opts.c (set_std_cxx2a): New.
>> (c_common_handle_option): Set options when -std=c++2a is enabled.
>>
>> gcc/testsuite/
>> New test for -std=c++2a.
>> * g++.dg/cpp2a/cplusplus.C: New.
>
> Perhaps you should enable -fconcepts by default?
>
> --
> Markus


[PATCH] Add -std=c++2a

2017-07-20 Thread Andrew Sutton
This adds a new C++ dialect, enabled by -std=c++2a.

libcpp/
Add support for C++2a.
* include/cpplib.h (c_lang): Add CXX2A and GNUCXX2A.
* init.c (lang_defaults): Add rows for CXX2A and GNUCXX2A.
(cpp_init_builtins): Set __cplusplus to 201707L for C++2x.

gcc/c-family/
Add support for -std=c++2a.
* c-common.h (cxx_dialect): Add cxx2a as a dialect.
* opt.c: Add options for -std=c++2a and -std=gnu++2a.
* c-opts.c (set_std_cxx2a): New.
(c_common_handle_option): Set options when -std=c++2a is enabled.

gcc/testsuite/
New test for -std=c++2a.
* g++.dg/cpp2a/cplusplus.C: New.


Andrew Sutton


cxx2a.patch
Description: Binary data


Re: [PATCH] Giant concepts patch

2016-07-10 Thread Andrew Sutton
Ah sure. Jason has been vetting my post-Jacksonville concepts patch in
the branch jason/concepts-rewrite. I just pulled this off the github
GCC mirror this morning to look at an outstanding question. Resulted
in the previous 2 patches.

I tried building a fresh pull of your cmcstl2 and got an off-by const
error. It looks like it's coming from counted_iterator. I'll post the
repro instructions and the error on the bug report.

Andrew


Re: [PATCH] Giant concepts patch

2016-07-10 Thread Andrew Sutton
I just tried building a fresh pull of cmcstl2, and I'm not seeing any
errors as a result of not handling those missing codes in
tsubst_constraint. At one point, I think it was not possible to get
those other constraints in this context because they were nested in a
parm_constr. But that seems obviously untrue now. But still... that
gcc_unreachable isn't being triggered by any code in cmcstl.

I attached a patch that adds tsubsts for the missing constraints.
Unfortunately, I don't have time to test thoroughly today.

I did find another bug building cmcstl2, hence the attached
disable-opt patch. For some reason, the memoization of concept
satisfaction is giving momoized results for concept + args that have
not yet been evaluated. This is exactly the same problem that made me
disable the lookup/memoize_constraint_sat optimizations. Somehow I'm
getting the same hash code for different arguments, and they also
happen to compare equal.

This doesn't seem to affect memoization of concept satisfaction. At
least I haven't seen it yet.

Anyways, disabling that optimization lets me build cmcstl2 with
concepts. Sort of; there's a bug in the library, which is why Casey is
added to the mailing. You're missing a const overload of operator* for
basic_operator. Patch forthcoming.

Changelogs below.

2016-07-10  Andrew Sutton  <andrew.n.sut...@gmail.com>

* constraint.cc (tsubst_type_constr, tsubst_implicit_conversion_constr,
tsubst_argument_deduction_constr, tsubst_exception_constr): New.
(tsubst_constraint): Add cases for missing constraints.

2016-07-10  Andrew Sutton  <andrew.n.sut...@gmail.com>

* pt.c (lookup_concept_satisfaction, memoize_concept_satisfaction):
Disable memoization of concept results.
Andrew Sutton


On Sat, Jul 9, 2016 at 11:24 AM, Andrew Sutton
<andrew.n.sut...@gmail.com> wrote:
> Do we have a smaller test that reproduces this? One reason I didn't make
> much progress was that I could never find a small test that triggers the
> problem. I just pulled your branch and plan to do some digging tomorrow.
>
>
>
> On Fri, Jul 8, 2016 at 6:42 PM Jason Merrill <ja...@redhat.com> wrote:
>>
>> On Wed, Jun 22, 2016 at 2:25 AM, Andrew Sutton
>> <andrew.n.sut...@gmail.com> wrote:
>> >> > I've run into some trouble building cmcstl2: declarator requirements
>> >> > on a function can lead to constraints that tsubst_constraint doesn't
>> >> > handle.  What was your theory of only handling a few _CONSTR codes
>> >> > there?  This is blocking me from checking in the patch.
>> >
>> > I wonder if those were the problems that I was running into, but hadn't
>> > diagnosed. I had thought it shouldn't be possible to get the full set of
>> > constraints in tsubst_constraint. I may have mis-analyzed the problem
>> > for
>> > function constraints.
>>
>> Any further thoughts?
>>
>> Jason
>
> --
> Andrew Sutton
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 145ae1e..745cbbc 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -1625,12 +1625,70 @@ static tree
 tsubst_expr_constr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 {
   cp_unevaluated guard;
-
   tree expr = EXPR_CONSTR_EXPR (t);
-  tree check = tsubst_expr (expr, args, complain, in_decl, false);
-  if (check == error_mark_node)
+  tree ret = tsubst_expr (expr, args, complain, in_decl, false);
+  if (ret == error_mark_node)
+return error_mark_node;
+  return build_nt (EXPR_CONSTR, ret);
+}
+
+static tree
+tsubst_type_constr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
+{
+  tree type = TYPE_CONSTR_TYPE (t);
+  tree ret = tsubst (type, args, complain, in_decl);
+  if (ret == error_mark_node)
 return error_mark_node;
-  return build_nt (EXPR_CONSTR, check);
+  return build_nt (TYPE_CONSTR, ret);
+}
+
+static tree
+tsubst_implicit_conversion_constr (tree t, tree args, tsubst_flags_t complain, 
+   tree in_decl)
+{
+  cp_unevaluated guard;
+  tree expr = ICONV_CONSTR_EXPR (t);
+  tree type = ICONV_CONSTR_TYPE (t);
+  tree new_expr = tsubst_expr (expr, args, complain, in_decl, false);
+  if (new_expr == error_mark_node)
+return error_mark_node;
+  tree new_type = tsubst (type, args, complain, in_decl);
+  if (new_type == error_mark_node)
+return error_mark_node;
+  return build_nt (ICONV_CONSTR, new_expr, new_type);
+}
+
+static tree
+tsubst_argument_deduction_constr (tree t, tree args, tsubst_flags_t complain, 
+  tree in_decl)
+{
+  cp_unevaluated guard;
+  tree expr = DEDUCT_CONSTR_EXPR (t);
+  tree pattern = DEDUCT_CONSTR_PATTERN (t);
+  tree autos = DEDUCT_CONSTR_PLACEHOLDER(t);
+  tree new_expr = tsubst_expr (expr, args, complain, in_decl, false);
+  if (new_expr == error_mark_node)
+

Re: C++ PATCH for non-type constrained-type-specifiers

2015-11-06 Thread Andrew Sutton
> I started looking at allowing non-type constrained-type-specifiers in auto
> deduction and then realized that we didn't handle them in function
> parameters either.  Fixing that brought home to me the oddity of having a
> type-specifier stand in for a non-type.  Mind weighing in on that on the
> core reflector?

That is a little weird. The non-type placeholders should be
id-expressions that name a concept. And template placeholders would be
template-names.

I'll create an issue for it. I need to email Mike Miller and figure
out how issues processing will work. But not until I'm out of the
weeds for the semester.


> I also wonder why we have two different ways of expressing a
> constrained-type-specifier in the implementation: a constrained
> template-parameter (TYPE_DECL, is_constrained_parameter) and a constrained
> auto (TEMPLATE_TYPE_PARM).  Why not represent them the same way?

It's probably a historical distinction. We didn't get concepts as
placeholders until much later in the standardization process.

But with auto template parameters on the horizon, it might be
worthwhile to maintain the distinction. That feature adds a wonderful
little ambiguity:

template struct S;

would declare a non-type template parm whose type is deduced from a
template argument.

template concept bool C = true;
template struct S;

Is C a constrained placeholder (as per a reasonable interpretation of
parameter-declarations), or does it declare a type parameter (as per
the TS)? It's going to end up being the latter.

Combining the representations might make it difficult to tease out
intent later. But that's just me speculating.


Andrew


Re: C++ PATCH to implement fold-expressions

2015-09-17 Thread Andrew Sutton
Fantastic. I've wanted to get back to this, but since school started
back up, I haven't had any time to look at it.

Thanks!

Andrew


On Thu, Sep 17, 2015 at 2:04 PM, Jason Merrill  wrote:
> Back in January Andrew mostly implemented C++1z fold-expressions
> (https://isocpp.org/files/papers/n4295.html), but the patch broke bootstrap.
> I've fixed it up now and am committing it to the trunk.
>
> Andrew: The main change I made was to drop tentative parsing in favor of
> scanning the tokens ahead looking for an ellipsis next to a fold-operator.
> I also tweaked some diagnostics, fixed handling of dependent expressions
> with no TREE_TYPE, and corrected empty fold of modops.
>
> Tested x86_64-pc-linux-gnu, applying to trunk.


concept diagnostics

2015-08-18 Thread Andrew Sutton
This is not a proper patch. I'm missing the usual changelog and I'm
still running the regression tests, but I wanted to get some opinions
before committing more time to it.

This patch extends the diagnostics for concepts to report precise
failures when constraints are not satisfied. It currently reports up
to 7 errors and then elides the rest. That should probably be under
control of a compiler option, but I'd like some suggestions on how to
proceed.

Also, diagnostics are currently emitted as notes against the location
of the concept declaration. It would be better to diagnose the failure
against location of each requirement, but we're not doing a very good
job tracking source locations for those.

Also, in a lot of cases, we probably just want to replay a
substitution with tf_error to generate precise failures. Although that
potentially generates *way* more information (e.g., candidate sets for
failed overload resolution).

I also started try to apply these diagnostics to static_if. The basic
idea being: if you write static_if(CT, ) where C is a concept,
then you should get the full diagnostics for that concept. I suspect
that this will be the most requested feature within a few months time.

Unfortunately, I ran into a little problem that CT is immediately
folded into true/false and the original expression is unrecoverable
from finish_static_if. I tinkered with parsing the condition as a
non-constant expression and then folding it on demand, but that caused
a number of regressions, so I had to back it out. Any thoughts on how
to proceed?

Andrew
Index: cxx-pretty-print.c
===
--- cxx-pretty-print.c	(revision 226937)
+++ cxx-pretty-print.c	(working copy)
@@ -2600,6 +2600,7 @@ pp_cxx_compound_requirement (cxx_pretty_
   pp_cxx_ws_string (pp, -);
   pp-type_id (type);
 }
+  pp_cxx_semicolon (pp);
 }
 
 /* nested requirement:
@@ -2646,7 +2647,7 @@ pp_cxx_implicit_conversion_constraint (c
   pp_left_paren (pp);
   pp-expression (ICONV_CONSTR_EXPR (t));
   pp_cxx_separate_with (pp, ',');
-  pp-expression (ICONV_CONSTR_TYPE (t));
+  pp-type_id (ICONV_CONSTR_TYPE (t));
   pp_right_paren (pp);
 }
 
Index: cp-tree.h
===
--- cp-tree.h	(revision 226937)
+++ cp-tree.h	(working copy)
@@ -6680,6 +6680,8 @@ extern tree tsubst_requires_expr
 extern tree tsubst_constraint   (tree, tree, tsubst_flags_t, tree);
 extern tree tsubst_constraint_info  (tree, tree, tsubst_flags_t, tree);
 extern bool function_concept_check_p(tree);
+extern bool variable_concept_check_p(tree);
+extern bool concept_check_p (tree);
 
 extern tree evaluate_constraints(tree, tree);
 extern tree evaluate_function_concept   (tree, tree);
@@ -6687,6 +6689,7 @@ extern tree evaluate_variable_concept
 extern tree evaluate_constraint_expression  (tree, tree);
 extern bool constraints_satisfied_p (tree);
 extern bool constraints_satisfied_p (tree, tree);
+extern bool constraint_expression_satisfied_p   (tree, tree);
 
 extern bool equivalent_constraints  (tree, tree);
 extern bool equivalently_constrained(tree, tree);
Index: constraint.cc
===
--- constraint.cc	(revision 226937)
+++ constraint.cc	(working copy)
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.
 #include wide-int.h
 #include inchash.h
 #include tree.h
+#include print-tree.h
 #include stringpool.h
 #include attribs.h
 #include intl.h
@@ -113,13 +114,22 @@ conjoin_constraints (tree t)
   return r;
 }
 
-/* Returns true if T is a call expression to a function
-   concept. */
+/* Returns true if T is an expression that would evaluate
+   a variable or function concept. */
+
+bool
+concept_check_p (tree t)
+{
+  return function_concept_check_p (t) || variable_concept_check_p (t);
+}
+
+/* Returns true if T is a call to a function concept. */
 
 bool
 function_concept_check_p (tree t)
 {
-  gcc_assert (TREE_CODE (t) == CALL_EXPR);
+  if (!t || t == error_mark_node || TREE_CODE (t) != CALL_EXPR)
+return false;
   tree fn = CALL_EXPR_FN (t);
   if (TREE_CODE (fn) == TEMPLATE_ID_EXPR
TREE_CODE (TREE_OPERAND (fn, 0)) == OVERLOAD)
@@ -132,6 +142,17 @@ function_concept_check_p (tree t)
   return false;
 }
 
+/* Returns true if T is a template-id referring to a variable concept. */
+
+bool
+variable_concept_check_p (tree t)
+{
+  if (!t || t == error_mark_node || TREE_CODE (t) != TEMPLATE_ID_EXPR)
+return false;
+  return variable_template_p (TREE_OPERAND (t, 0));
+}
+
+
 /*---
 Resolution of qualified concept names
 ---*/
@@ -350,12 +371,12 @@ lift_function_call (tree t)
   

Re: [c++-concepts] code review

2015-05-08 Thread Andrew Sutton
Today is the first day I've had to look at these comments.


if (TEMPLATE_PARM_CONSTRAINTS (current_template_parms))
 -TYPE_CANONICAL (type) = type;
 +SET_TYPE_STRUCTURAL_EQUALITY (type);


 This seems like papering over an underlying issue.  What was the testcase
 that motivated this change?


It almost certainly is, but I haven't been able to find or write a
minimal test case that reproduces the reason for failure. Basically,
we end up with multiple specializations having the same type but
different constraints (since constraints are attached to the
declaration and not the type itself).

I think that I'm running into the same problems with auto a
placeholder in recent commits.


 @@ -11854,7 +11854,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t
 complain)
 -   if (!spec)
 +   if (!spec  DECL_LANG_SPECIFIC (t))
 -   if (!local_p)
 +   if (!local_p  DECL_LANG_SPECIFIC (r))


 What motivated these changes?  From the testcase, it seems that you're
 getting here with the decl for using TD = int, which shouldn't happen.


That's the pretty much it... I suppose we could guard against
substituting into these kinds of declarations from within
tsubst_type_requirement and satisfy_type_constraint. To me it seems
like tsubst should work, but just return the same thing.


 @@ -1159,7 +1159,6 @@ check_noexcept_r (tree *tp, int * /*walk_subtrees*/,
 void * /*data*/)
 -  tree type = TREE_TYPE (TREE_TYPE (fn));
 -  if (!TYPE_NOTHROW_P (type))
 +  if (!TYPE_NOTHROW_P (TREE_TYPE (fn)))


 The old code was incorrectly assuming that CALL_EXPR_FN is always a function
 pointer, but your new code seems to be incorrectly assuming that it's always
 a function or an expression taking the address of a function; I think this
 will break on a call to a function pointer variable.


I will experiment.


 @@ -3481,13 +3481,27 @@ cxx_eval_constant_expression (const constexpr_ctx
 *ctx, tree t,
  case REQUIRES_EXPR:
 +  if (!processing_template_decl)
 +return evaluate_constraint_expression (t, NULL_TREE);
 +  else
 +*non_constant_p = true;
 +return t;


 We shouldn't get here with a dependent REQUIRES_EXPR (or any dependent
 expression), so we shouldn't ever hit the else clause.


IIRC we get here because of build_x_binary_op. It tries to build
non-dependent operands when the operands are not type-dependent.
requires-expressions have type bool, so they get run through the
constexpr evaluator even when processing_template_decl is true.

I've made requires-expressions instantiation dependent, but that
doesn't help in this case.


 +static inline bool
 +pending_expansion_p (tree t)
 +{
 +  return (TREE_CODE (t) == PARM_DECL  CONSTRAINT_VAR_P (t)
 +   PACK_EXPANSION_P (TREE_TYPE (t)));
 +}


 What's the difference between this and function_parameter_pack_p?


Not a lot, except that replacing pending_expansion_p in one of the two
places that it's used causes ICEs :)  This function can almost
certainly be removed.


 +check_implicit_conversion_constraint (tree t, tree args,
 +  tsubst_flags_t complain, tree
 in_decl)
 +{
 +  tree expr = ICONV_CONSTR_EXPR (t);
 +
 +  /* Don't tsubst as if we're processing a template. If we try
 + to we can end up generating template-like expressions
 + (e.g., modop-exprs) that aren't properly typed. */
 +  int saved_template_decl = processing_template_decl;
 +  processing_template_decl = 0;


 Why are we checking constraints when processing_template_decl is true?


IIRC I allow constraints to be evaluated in any context because it
lets us catch these kinds of errors:

templatetypename T
void f()
{
  vectorint v; // error: constraints not satisfied
}


 +  ++processing_template_decl;
 +  tree constr = transform_expression (lift_function_definition (fn,
 args));
 +  --processing_template_decl;


 Why do you need to set processing_template_decl here and in other calls to
 transform_expression?  I don't notice anything that would be helped,
 especially now that you're using separate tree codes for constraints, though
 there is this in check_logical_expr:

 +  /* Resolve the logical operator. Note that template processing is
 + disabled so we get the actual call or target expression back.
 + not_processing_template_sentinel sentinel.


 I guess that isn't needed anymore?


I've had problems in the past where substitution tries a little too
eagerly to fold expressions into constants --- especially type traits.
Those need to be preserved in the text for ordering.

Although I think this really only matters when you're instantiating a
class template whose members are constraints.


Andrew


Re: [c++-concepts] code review

2015-05-01 Thread Andrew Sutton
 It looks like things are coming together pretty well.  What's your feeling
 about readiness to merge into the trunk?  Is the branch down to no
 regressions?

They are coming together pretty well. We have one major unit test
failure involving template introductions (Braden is working on it),
one involving constraint equivalence that I plan to tackle next week.

Other than those issues, which I hope to clear up next week, I think it's ready.

 See you on Monday!

Unfortunately, I won't be attending.

Andrew


 @@ -4146,21 +4146,21 @@ build_new_function_call (tree fn, vectree, va_gc
 **args, bool koenig_p,
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
  {
/* If overload resolution selects a specialization of a
 + function concept for non-dependent template arguments,
 + the expression is true if the constraints are satisfied
 + and false otherwise.

   NOTE: This is an extension of Concepts Lite TS that
   allows constraints to be used in expressions. */
 +  if (flag_concepts  !processing_template_decl)
  {
tree tmpl = DECL_TI_TEMPLATE (cand-fn);
 +  tree targs = DECL_TI_ARGS (cand-fn);
tree decl = DECL_TEMPLATE_RESULT (tmpl);
 +  if (DECL_DECLARED_CONCEPT_P (decl)
 +   !uses_template_parms (targs)) {
 +return evaluate_function_concept (decl, targs);


 If processing_template_decl is false, uses_template_parms should always be
 false as well.

 +function_concept_check_p (tree t)


 +  tree fn = CALL_EXPR_FN (t);
 +  if (TREE_CODE (fn) == TEMPLATE_ID_EXPR
 +   TREE_CODE (TREE_OPERAND (fn, 0)) == OVERLOAD)
 +{
 +  tree f1 = OVL_FUNCTION (TREE_OPERAND (fn, 0));


 I think you want get_first_fn here.

if (TEMPLATE_PARM_CONSTRAINTS (current_template_parms))
 -TYPE_CANONICAL (type) = type;
 +SET_TYPE_STRUCTURAL_EQUALITY (type);


 This seems like papering over an underlying issue.  What was the testcase
 that motivated this change?

 @@ -11854,7 +11854,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t
 complain)
 -   if (!spec)
 +   if (!spec  DECL_LANG_SPECIFIC (t))
 -   if (!local_p)
 +   if (!local_p  DECL_LANG_SPECIFIC (r))


 What motivated these changes?  From the testcase, it seems that you're
 getting here with the decl for using TD = int, which shouldn't happen.

 @@ -1159,7 +1159,6 @@ check_noexcept_r (tree *tp, int * /*walk_subtrees*/,
 void * /*data*/)
 -  tree type = TREE_TYPE (TREE_TYPE (fn));
 -  if (!TYPE_NOTHROW_P (type))
 +  if (!TYPE_NOTHROW_P (TREE_TYPE (fn)))


 The old code was incorrectly assuming that CALL_EXPR_FN is always a function
 pointer, but your new code seems to be incorrectly assuming that it's always
 a function or an expression taking the address of a function; I think this
 will break on a call to a function pointer variable.

 @@ -3481,13 +3481,27 @@ cxx_eval_constant_expression (const constexpr_ctx
 *ctx, tree t,
  case REQUIRES_EXPR:
 +  if (!processing_template_decl)
 +return evaluate_constraint_expression (t, NULL_TREE);
 +  else
 +*non_constant_p = true;
 +return t;


 We shouldn't get here with a dependent REQUIRES_EXPR (or any dependent
 expression), so we shouldn't ever hit the else clause.

 @@ -18063,18 +18063,41 @@ cp_parser_declarator (cp_parser* parser,
 +  /* Function declarations may be followed by a trailing
 + requires-clause. Declarators for function declartions
 + are function declarators wrapping an id-declarator.
 + If the inner declarator is anything else, it does not
 + declare a function. These may also be reference or
 + pointer declarators enclosing such a function declarator.
 + In the declaration :
 +
 +int *f(args)
 +
 + the declarator is *f(args).
 +
 + Abstract declarators cannot have a requires-clauses
 + because they do not declare functions. Here:

  void f() - int requires false

 + The trailing return type contains an abstract declarator,
 + and the requires-clause applies to the function
 + declaration and not the abstract declarator.  */
 +  if (flag_concepts  dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
  {
 +  /* We could have things like *f(args) or f(args).
 + Look inside references and pointers.  */
 +  cp_declarator* p = declarator;
 +  if (p-kind == cdk_reference || p-kind == cdk_pointer)
 +p = p-declarator;
 +
 +  /* Pointers or references with no name, or functions
 + with no name cannot have constraints.  */
 +  if (!p || !p-declarator)
 +return declarator;
 +
 +  /* Look for f(args) but not (*f)(args).  */
 +  if (p  p-kind == cdk_function  p-declarator-kind == cdk_id)


 I think you can use function_declarator_p here.

 +static inline bool
 +pending_expansion_p (tree t)
 +{
 +  return (TREE_CODE (t) == PARM_DECL  

Re: Concepts code review

2014-11-16 Thread Andrew Sutton
 +// Bring the parameters of a function declaration back into
 +// scope without entering the function body. The declarator
 +// must be a function declarator. The caller is responsible
 +// for calling finish_scope.
 +void
 +push_function_parms (cp_declarator *declarator)

 I think if the caller is calling finish_scope, I'd prefer for the
 begin_scope call to be there as well.

 Even though Andrew said that this will change later for other reasons, it's
 a function I wrote so: I actually debated this with Andrew before.  My
 rationale for calling begin_scope in the function was that it feels
 consistent with the semantics of the call. Specifically it can be seen as
 reopening the function parameter scope.  Thus the call is balanced by
 calling finish_scope.  Either way would work of course, but perhaps it just
 needed a better name and/or comment?

In the process of removing constraints from lang_decl nodes, I also
ended up addressing a lot of the other constraint processing comments
-- it made sense to do it at the same time.

One of those was moving a requires-clause into a function declarator.
I had thought that this would prevent me from having to re-open that
scope, but it doesn't. The parameter scope is closed at a lower level
in the parse :/

So this issue is still around.

 +  // Save the current template requirements.
 +  saved_template_reqs = release (current_template_reqs);


 It seems like a lot of places with saved_template_reqs variables could be
 converted to use cp_manage_requirements.

 Probably.  The instance you quoted isn't very trivial though.  The
 requirements are saved in two different branches and need to be restored
 before a certain point in the function.  Might just need to spend more time
 looking over the code.

I got rid of current_template_reqs in my current work. Constraints are
associated directly with a template parameter list or a declarator.

 +  // FIXME: This could be improved. Perhaps the type of the requires
 +  // expression depends on the satisfaction of its constraints. That
 +  // is, its type is bool only if its substitution into its normalized
 +  // constraints succeeds.


 The requires-expression is not type-dependent, but it can be
 instantiation-dependent and value-dependent.

 This is an interesting change.  The REQUIRES_EXPR is currently marked as
 value dependent.  The ChangeLog indicates that Andrew loosened the
 conditions for being value dependent for some cases, but then added it as
 type dependent when something else failed.  May require some time to pin
 down exactly what needs to be done here.

I think something may have changed since I made that change... If I'm
remembering correctly, it used to be the case that build_x_binary_op
would try to fold the resulting expression when the operands weren't
type dependent. That happens in conjoin_constraints.

Now it looks like it's calling build_non_dependent_expr, which does
something a little different.

I agree that requires-expressions are not type-dependent (they have type bool).

Andrew


[c++-concepts] merge from trunk

2014-11-13 Thread Andrew Sutton
I just merged the concepts branch with trunk, after fighting with the
testing framework for the past hour. There was a change to

gcc/testsuite/lib/prune.exp

yesterday that doesn't appear to be compatible with *something* in
this branch. It broke the entire test suite, giving the errors below
for every .exp file.

Using /home/faculty/asutton/local/share/dejagnu/baseboards/unix.exp as
board description file for target.
Using /home/faculty/asutton/local/share/dejagnu/config/unix.exp as
generic interface file for target.
Using 
/home/faculty/asutton/Code/gcc/c++-concepts/gcc/testsuite/config/default.exp
as tool-and-target-specific interface file.
Running 
/home/faculty/asutton/Code/gcc/c++-concepts/gcc/testsuite/gcc.c-torture/compile/compile.exp
...
ERROR: tcl error sourcing
/home/faculty/asutton/Code/gcc/c++-concepts/gcc/testsuite/gcc.c-torture/compile/compile.exp.
ERROR: couldn't compile regular expression pattern: quantifier operand invalid
while executing
regsub -all $srcdir\/ $text  text
(procedure prune_gcc_output line 50)
invoked from within
prune_gcc_output $text
(procedure gcc-dg-prune line 8)
invoked from within
${tool}-dg-prune $target_triplet $comp_output
(procedure saved-dg-test line 183)
invoked from within
saved-dg-test 
/home/faculty/asutton/Code/gcc/c++-concepts/gcc/testsuite/gcc.c-torture/compile/2105-1.c
{  -O0 } -w
(eval body line 1)
invoked from within
eval saved-dg-test $args 
(procedure dg-test line 11)
invoked from within
dg-test $test $flags $flags_t ${default-extra-flags}
(procedure gcc-dg-runtest line 33)
invoked from within
gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]]  -w
(file 
/home/faculty/asutton/Code/gcc/c++-concepts/gcc/testsuite/gcc.c-torture/compile/compile.exp
line 30)
invoked from within
source 
/home/faculty/asutton/Code/gcc/c++-concepts/gcc/testsuite/gcc.c-torture/compile/compile.exp
(uplevel body line 1)
invoked from within
uplevel #0 source
/home/faculty/asutton/Code/gcc/c++-concepts/gcc/testsuite/gcc.c-torture/compile/compile.exp
invoked from within
catch uplevel #0 source $test_file_name

I removed the offending line of code in this branch just to make the tests run.

That change does not affect any other builds on my system, so
something isn't being configured correctly. I just can't find what it
is.

Andrew


Re: Concepts code review

2014-11-12 Thread Andrew Sutton
 +  // The constraint info maintains information about constraints
 +  // associated with the declaration.
 +  tree constraint_info;


 We talked back at the end of June about moving this into a separate
 hashtable; I'm still reluctant to add another pointer to most declarations
 when only a minority will have constraints.  As I was saying in the earlier
 thread, I think the problem you were hitting should be resolved by looking
 through clones with DECL_ORIGIN.  This needs to be fixed before merge, since
 it significantly affects non-concepts compiles.


Agreed. I'll probably start looking at this on Friday morning.


 +  // Zeroth, a constrained function is not viable if its constraints are
 not
 +  // satisfied.

 As I suggested in the document review, I think we want to check this after
 the number of parameters, to avoid unnecessary implicit template
 instantiation in evaluating the constraints.  Patch attached.


Great. I'll apply that after I merge with trunk (which is going on right now).



 +resolve_constraint_check (tree call)
 +{
 +  gcc_assert (TREE_CODE (call) == CALL_EXPR);


 Maybe also assert that the call has no function arguments?


I'll have to look, but we might get regular calls to constexpr
functions through this code path, which are then filtered out during
processing.

It might be better to not take this path if there are function
arguments since that couldn't possibly be a constraint check.


 deduce_concept_introduction (tree expr)
 {
   if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
 {
   // Get the parameters from the template expression.
   tree decl = TREE_OPERAND (expr, 0);
   tree args = TREE_OPERAND (expr, 1);
   tree var = DECL_TEMPLATE_RESULT (decl);
   tree parms = TREE_VALUE (DECL_TEMPLATE_PARMS (decl));

   parms = coerce_template_parms (parms, args, var);


 Do you still need this coerce_template_parms now that I've added a call to
 lookup_template_variable?  Well, once my change is merged onto the branch or
 the branch onto trunk.


Maybe? I'm not sure what the call to lookup_template_variable is going
to do :) I think we still need to instantiate default arguments in
order to perform the match.


 Can you reduce the code duplication between deduce_constrained_parameter and
 deduce_concept_introduction?


Yes.

   // Sometimes a function call results in the creation of clean up
   // points. Allow these to be preserved in the body of the
   // constraint, as we might actually need them for some constexpr
   // evaluations.


 What need are you thinking of?  CLEANUP_POINT_EXPR is ignored in constexpr
 evaluation.

 Also, this function seems like reinventing massage_constexpr_body, can we
 share code?


I didn't know if the forthcoming generalized constexpr evaluator would
act on those or not. We'll have a look at the massage_constexpr_body
function. I wonder if we can apply that to both function and constexpr
variables.


 +  // Normalize the body of the function into the constriants language.
 +  tree body = normalize_constraints (DECL_SAVED_TREE (fn));
 +  if (!body)
 +return error_mark_node;
 ...

 +  // Reduce the initializer of the variable into the constriants
 language.
 +  tree body = normalize_constraints (DECL_INITIAL (decl));


 If we're normalizing before substitution, why wait until the point of use to
 do it?  At least we could cache the result of normalization.


We should be normalizing and caching as soon as we can create a
complete declaration (for some declaration of complete). For functions
and function templates, for example, that's at the top of grokfndecl.

Although, as I think about it, I seem to remember having to
re-normalize a constraint in certain circumstances, but I can't
remember what they are. I'll take a look at this.


   // Modify the declared parameters by removing their context (so they
   // don't refer to the enclosing scope), and marking them constant (so
   // we can actually check constexpr properties).


 We don't check constexpr using these parms anymore, but rather the
 substituted arguments, so we don't need to mark them constant, right? Is the
 other (context) change still relevant?


That will come out.


 +  // TODO: Actually check that the expression can be constexpr
 +  // evaluatd.
 +  //
 +  // return truth_node (potential_constant_expression (expr));
 +  sorry (constexpr requirement);


 Pass it to maybe_constant_value and check whether the result is
 TREE_CONSTANT?  Or do we want to remove the constexpr requirement code now
 that it's out of the proposal?


This should come out. I think we'll get a non-language way of checking
this in the not-so-distant future.


   DECL_INITIAL (decl) = proto;  // Describing parameter
   DECL_SIZE_UNIT (decl) = fn;   // Constraining function declaration
   DECL_SIZE (decl) = args;  // Extra template arguments.


 I'm nervous about misusing these fields this way.  Why is a constrained
 parameter represented as a TYPE_DECL?


I think it was because 

Re: Concepts code review

2014-11-12 Thread Andrew Sutton
 Agreed. I'll probably start looking at this on Friday morning.


 Note that end of stage 1 is Saturday, as I just realized today.  So the
 sooner the better.  :)

Ouch. Good thing my merge with trunk broke in unexpected ways this
morning -- minimally, something in cgraph ended up missing a #include
in the merge and I don't know how to fix it :/

Andrew


[c++-concepts]

2014-10-20 Thread Andrew Sutton
Fixing issues reported by users.

2014-10-20  Andrew Sutton  andrew.n.sut...@gmail.com

Fixing user-reported issues and regressions
* gcc/cp/parser.c (cp_parser_template_declaration_after_exp):
Only pop access checks on failed parsing.
* gcc/cp/pt.cpp (type_dependent_expr_p): Always treat a
requires-expr as if dependently typed. Otherwise, we try to
evaluate these expressions when they have dependent types.
* gcc/cp/constriant.cc (normalize_stmt_list): Remove unused
function.
(normalize_call): Don't fold constraints during normalization.
* gcc/testsuite/g++.dg/concepts/decl-diagnose.C: Update diagnostics.

Andrew Sutton
Index: pt.c
===
--- pt.c	(revision 214991)
+++ pt.c	(working copy)
@@ -21646,6 +21646,16 @@ type_dependent_expression_p (tree expres
 	return dependent_type_p (type);
 }
 
+  // A requires expression has type bool, but is always treated as if
+  // it were a dependent expression.
+  //
+  // FIXME: This could be improved. Perhaps the type of the requires
+  // expression depends on the satisfaction of its constraints. That
+  // is, its type is bool only if its substitution into its normalized
+  // constraints succeeds.
+  if (TREE_CODE (expression) == REQUIRES_EXPR)
+return true;
+
   if (TREE_CODE (expression) == SCOPE_REF)
 {
   tree scope = TREE_OPERAND (expression, 0);
Index: constraint.cc
===
--- constraint.cc	(revision 216159)
+++ constraint.cc	(working copy)
@@ -326,7 +326,6 @@ tree normalize_nested_req (tree);
 tree normalize_var (tree);
 tree normalize_cleanup_point (tree);
 tree normalize_template_id (tree);
-tree normalize_stmt_list (tree);
 tree normalize_atom (tree);
 
 // Reduce the requirement T into a logical formula written in terms of
@@ -559,13 +558,13 @@ normalize_call (tree t)
   tree fn = TREE_VALUE (check);
   tree args = TREE_PURPOSE (check);
 
-  // Reduce the body of the function into the constriants language.
+  // Normalize the body of the function into the constriants language.
   tree body = normalize_constraints (DECL_SAVED_TREE (fn));
   if (!body)
 return error_mark_node;
 
   // Instantiate the reduced results using the deduced args.
-  tree result = tsubst_constraint_expr (body, args, false);
+  tree result = tsubst_constraint_expr (body, args, true);
   if (result == error_mark_node)
 return error_mark_node;
 
Index: testsuite/g++.dg/concepts/decl-diagnose.C
===
--- testsuite/g++.dg/concepts/decl-diagnose.C	(revision 214241)
+++ testsuite/g++.dg/concepts/decl-diagnose.C	(working copy)
@@ -4,12 +4,12 @@ typedef concept int CINT; // { dg-error
 
 void f(concept int); // { dg-error a parameter cannot be declared 'concept' }
 
-concept int f2(); // { dg-error result must be bool }
+concept int f2(); // { dg-error return type }
 concept bool f3();
 
 struct X
 {
-  concept int f4(); // { dg-error result must be bool|declared with function parameters }
+  concept int f4(); // { dg-error return type|function parameters }
   concept bool f5(); // { dg-error declared with function parameters }
   static concept bool f6(); // { dg-error a concept cannot be a static member function }
   static concept bool x; // { dg-error declared 'concept' }
Index: cp/parser.c
===
--- cp/parser.c	(revision 216159)
+++ cp/parser.c	(working copy)
@@ -24422,12 +24422,10 @@ cp_parser_template_declaration_after_exp
 
   push_deferring_access_checks (dk_deferred);
   parameter_list = cp_parser_template_introduction (parser);
-  pop_deferring_access_checks ();
-
   if (parameter_list == error_mark_node)
 {
-	  // Restore template requirements before returning.
 	  current_template_reqs = saved_template_reqs;
+  pop_deferring_access_checks ();
 	  return;
 }
 


[c++-concepts] cleanup expressions

2014-10-13 Thread Andrew Sutton
Sometimes, cleanup_point_exprs are being added to concept definitions.
This patch allows that to happen, but removes the cleanup point during
normalization.

2014-10-13  Andrew Sutton  andrew.n.sut...@gmail.com

Fix bug related to cleanup expressions in concept definitions.
* gcc/cp/constraint.cc (check_function_concept): See through
cleanup handlers when checking the body of a function.
(normalize_cast): Removed. Handled in a default case.
(normalize_cleanup_point): New. Normalize the expression without
the cleanup handler.

Andrew Sutton


Re: [c++-concepts] cleanup expressions

2014-10-13 Thread Andrew Sutton
And here's the patch:


Andrew Sutton


On Mon, Oct 13, 2014 at 3:33 PM, Andrew Sutton
andrew.n.sut...@gmail.com wrote:
 Sometimes, cleanup_point_exprs are being added to concept definitions.
 This patch allows that to happen, but removes the cleanup point during
 normalization.

 2014-10-13  Andrew Sutton  andrew.n.sut...@gmail.com

 Fix bug related to cleanup expressions in concept definitions.
 * gcc/cp/constraint.cc (check_function_concept): See through
 cleanup handlers when checking the body of a function.
 (normalize_cast): Removed. Handled in a default case.
 (normalize_cleanup_point): New. Normalize the expression without
 the cleanup handler.

 Andrew Sutton
Index: constraint.cc
===
--- constraint.cc	(revision 215720)
+++ constraint.cc	(working copy)
@@ -285,6 +285,14 @@ check_function_concept (tree fn)
   tree body = DECL_SAVED_TREE (fn);
   if (TREE_CODE (body) == BIND_EXPR)
 body = BIND_EXPR_BODY (body);
+  
+  // Sometimes a funciton call results the creation of clean up
+  // points. Allow these to be preserved in the body of the 
+  // constraint, as we might actually need them for some constexpr
+  // evaluations.
+  if (TREE_CODE (body) == CLEANUP_POINT_EXPR)
+body = TREE_OPERAND(body, 0);
+
   if (TREE_CODE (body) != RETURN_EXPR)
 error_at (loc, function concept definition %qD has multiple statements, 
   fn);
@@ -316,9 +324,9 @@ tree normalize_expr_req (tree);
 tree normalize_type_req (tree);
 tree normalize_nested_req (tree);
 tree normalize_var (tree);
+tree normalize_cleanup_point (tree);
 tree normalize_template_id (tree);
 tree normalize_stmt_list (tree);
-tree normalize_cast (tree);
 tree normalize_atom (tree);
 
 // Reduce the requirement T into a logical formula written in terms of
@@ -383,12 +391,12 @@ normalize_expr (tree t)
 case TEMPLATE_ID_EXPR: 
   return normalize_template_id (t);
 
-case CAST_EXPR:
-  return normalize_cast (t);
-
 case BIND_EXPR:
   return normalize_node (BIND_EXPR_BODY (t));
 
+case CLEANUP_POINT_EXPR:
+  return normalize_cleanup_point (t);
+
 // Do not recurse.
 case TAG_DEFN: 
   return NULL_TREE;
@@ -655,12 +663,11 @@ normalize_requires (tree t)
   return t;
 }
 
-// Normalize a cast expression.
+// Normalize a cleanup point by normalizing the underlying
+// expression.
 tree
-normalize_cast (tree t) 
-{
-  // return normalize_node (TREE_VALUE (TREE_OPERAND (t, 0)));
-  return normalize_atom (t);
+normalize_cleanup_point (tree t) {
+  return normalize_node (TREE_OPERAND (t, 0));
 }
 
 // Normalize an atomic expression by performing some basic checks.


[c++-concepts] introduction syntax regression

2014-10-13 Thread Andrew Sutton
The original patch for concept introductions was not popping a
deferred access check. This fixes that problem, although I'm not sure
if we need to defer access checks at all.

2014-10-13  Andrew Sutton  andrew.n.sut...@gmail.com

Fix regression related to concept introductions.
* gcc/cp/constraint.cc (cp_parser_template_declaration_after_exp):
Pop deferred access checks afer parsing the introduction.


Andrew Sutton
Index: parser.c
===
--- parser.c	(revision 214991)
+++ parser.c	(working copy)
@@ -24409,19 +24409,21 @@ cp_parser_template_declaration_after_exp
 	= current_template_reqs;
 	}
 }
-  else if(flag_concepts)
+  else if (flag_concepts)
 {
   need_lang_pop = false;
   checks = NULL;
   saved_template_reqs = release (current_template_reqs);
-  push_deferring_access_checks (dk_deferred);
 
   // Scope may be changed by a nested-name-specifier.
   tree saved_scope = parser-scope;
   tree saved_qualifying_scope = parser-qualifying_scope;
   tree saved_object_scope = parser-object_scope;
 
+  push_deferring_access_checks (dk_deferred);
   parameter_list = cp_parser_template_introduction (parser);
+  pop_deferring_access_checks ();
+
   if (parameter_list == error_mark_node)
 {
 	  // Restore template requirements before returning.


[c++-concepts] function concepts with deduced return type

2014-09-30 Thread Andrew Sutton
Do not allow. Return type deduction only happens during instantiation,
and concepts are never instantiated. Therefore, we can't find the
return type of a function concept until you try to normalize the
return expression.

2014-09-25  Andrew Sutton  andrew.n.sut...@gmail.com

Explicitly disallow function concepts with deduced return types.
* gcc/cp/constraint.cc (check_function_concept): Remove check
for deduced return type.
* gcc/cp/decl.c (check_concept_fn): Explicitly check for
deduced return type.
* gcc/testsuite/g++.dg/concepts/fn-concept2.C: New.

Andrew Sutton
Index: testsuite/g++.dg/concepts/fn-concept2.C
===
--- testsuite/g++.dg/concepts/fn-concept2.C	(revision 0)
+++ testsuite/g++.dg/concepts/fn-concept2.C	(revision 0)
@@ -0,0 +1,7 @@
+// { dg-options -std=c++1z }
+
+templatetypename T
+  concept auto C1() { return 0; } // { dg-error deduced return type }
+
+templatetypename T
+  concept int C2() { return 0; } // { dg-error return type }
Index: cp/constraint.cc
===
--- cp/constraint.cc	(revision 215718)
+++ cp/constraint.cc	(working copy)
@@ -280,11 +280,6 @@ 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 %qT and not %qT, 
-  fn, TREE_TYPE (fn), boolean_type_node);
-
   // Check that the function is comprised of only a single
   // return statement.
   tree body = DECL_SAVED_TREE (fn);
Index: cp/decl.c
===
--- cp/decl.c	(revision 215718)
+++ cp/decl.c	(working copy)
@@ -7525,9 +7525,13 @@ check_concept_fn (tree fn)
   if (DECL_ARGUMENTS (fn))
 error (concept %q#D declared with function parameters, fn);
 
-  // The result type must be convertible to bool.
-  if (!same_type_p (TREE_TYPE (TREE_TYPE (fn)), boolean_type_node))
-error (concept %q#D result must be bool, fn);
+  // The declared return type of the concept shall be bool, and
+  // it shall not be deduced from it definition.
+  tree type = TREE_TYPE (TREE_TYPE (fn));
+  if (is_auto (type))
+error (concept %q#D declared with a deduced return type, fn);
+  else if (type != boolean_type_node)
+error (concept %q#D with return type %qT, fn, type);
 }
 
 /* Helper function.  Replace the temporary this parameter injected


[c++-concepts] Check function concept definitions

2014-09-29 Thread Andrew Sutton
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 }
+
+templatetypename T
+  concept bool Tuple() { // { dg-error multiple statements }
+static_assert(T::value, );
+return true;
+  }
+
+  void f(Tuple);


Re: [c++-concepts] Check function concept definitions

2014-09-29 Thread Andrew Sutton
 Hmm, have we actually discussed this in core review?  I'm not seeing it on
 the wiki.  Constexpr started out this way too, and allowing static_assert
 was added pretty fast.  C++11 said

 its function-body shall be = delete, = default, or a compound-statement that
 contains only
 — null statements,
 — static_assert-declarations
 — typedef declarations and alias-declarations that do not define classes or
 enumerations,
 — using-declarations,
 — using-directives,
 — and exactly one return statement;

 Is there a reason we want to be more strict than this for concept functions?


I don't remember much controversy on that particular limitation in
either Rapperswil or the previous telecon review.

The main reason for the restriction is that concept definitions are
normalized into a single constraint-expression. And it's not obvious
how things like using declarations and static-assertions should be
interpreted within the constraint language.

That said, having a static_assert inside a concept kind of defeats the
purpose since it triggers a diagnostic when its condition isn't
satisfied. That's not very SFINAE friendly :)

Maybe the restriction can relaxed when we consider the TS for adoption in 17.

Andrew


Re: [c++-concepts] variable concept fixes

2014-08-21 Thread Andrew Sutton
Ah... thanks for the clarification. Fixed (and committed).

Andrew

On Thu, Aug 21, 2014 at 4:26 AM, Paolo Carlini paolo.carl...@oracle.com wrote:
 Hi Andrew,


 On 08/20/2014 11:08 PM, Andrew Sutton wrote:

 On 08/20/2014 08:56 PM, Andrew Sutton wrote:

 +  return VAR_P (decl)
 +  DECL_LANG_SPECIFIC (decl)
 +  DECL_DECLARED_CONCEPT_P (decl);

 this is brittle from the formatting point of view. Please double check in
 detail what I'm going to say, but I think that in such cases you simply
 want
 to wrap the whole thing in round parentheses.

 Sorry, did you just mean to wrap the entire conjunction in parens? I'm
 trying to find the formatting guidelines to check, but not succeeding
 at the moment.

 Yes, I meant the whole conjunction, sorry about my sloppy language. In terms
 of GNU coding standards:

 http://www.gnu.org/prep/standards/standards.html#Formatting

 toward the end of the section, for example.

 Paolo.
Index: gcc/cp/decl.c
===
--- gcc/cp/decl.c	(revision 214241)
+++ gcc/cp/decl.c	(working copy)
@@ -6264,9 +6264,9 @@ value_dependent_init_p (tree init)
 static inline bool
 is_concept_var (tree decl) 
 {
-  return VAR_P (decl) 
-  DECL_LANG_SPECIFIC (decl)
-  DECL_DECLARED_CONCEPT_P (decl);
+  return (VAR_P (decl) 
+   DECL_LANG_SPECIFIC (decl)
+   DECL_DECLARED_CONCEPT_P (decl));
 }
 
 /* Finish processing of a declaration;


[c++-concepts] constrained friends

2014-08-21 Thread Andrew Sutton
Added tests for constrained friends.  No code, we already to the right thing.

2014-08-15  Andrew Sutton  andrew.n.sut...@gmail.com

Add tests for constrained friends.
* gcc/testsuite/g++.dg/concepts/friend1.C: New.
* gcc/testsuite/g++.dg/concepts/friend2.C: New.

Andrew
Index: gcc/testsuite/g++.dg/concepts/friend2.C
===
--- gcc/testsuite/g++.dg/concepts/friend2.C	(revision 0)
+++ gcc/testsuite/g++.dg/concepts/friend2.C	(revision 0)
@@ -0,0 +1,20 @@
+// { dg-options -std=c++1z }
+
+templatetypename T
+  concept bool Eq() { return requires(T t) { t == t; }; }
+
+templateEq T struct Foo { };
+
+templatetypename T
+  struct S { // { dg-error constraint failure }
+templateEq U friend class Bar;
+
+friend class FooT;
+  };
+
+struct X { };
+
+int main() {
+  Sint si; // OK
+  SX sx;
+}
Index: gcc/testsuite/g++.dg/concepts/friend1.C
===
--- gcc/testsuite/g++.dg/concepts/friend1.C	(revision 0)
+++ gcc/testsuite/g++.dg/concepts/friend1.C	(revision 0)
@@ -0,0 +1,33 @@
+// { dg-options -std=c++1z }
+
+templatetypename T
+  concept bool Eq() { return requires(T t) { t == t; }; }
+
+struct Nt {
+  templateEq T friend void f(T) { }
+} nt;
+
+templatetypename T struct S;
+
+templateEq T
+  void proc(ST*);
+
+templatetypename T
+  struct S {
+friend bool operator==(S, S) requires EqT() { return true; }
+
+friend void proc(S*); // { dg-error does not match any template declaration }
+  };
+
+struct X { } x;
+
+int main() {
+  f(0); // OK
+  f(x); // { dg-error cannot call }
+
+  Sint si;
+  si == si; // OK
+
+  SX sx; 
+  sx == sx; // { dg-error no match }
+}


[c++-concepts] variable concept fixes

2014-08-20 Thread Andrew Sutton
Add more diagnostics for variable concepts. Also fix a regression
where non-template concepts variables were causing ICEs because they
aren't being allocated via build_lang_decl.

2014-08-15  Andrew Sutton  andrew.n.sut...@gmail.com

Additional declaration restrictions on variable concepts.
* gcc/cp/decl.c (is_concept_var): New.
(cp_finish_decl): Check for uninitialized variable
concepts.
(grokvardecl): Don't set the concept flag for non-template variables.
* g++.dg/concepts/decl-diagnose.C: Add tests.

Andrew Sutton
Index: gcc/cp/decl.c
===
--- gcc/cp/decl.c	(revision 214239)
+++ gcc/cp/decl.c	(working copy)
@@ -6259,6 +6259,16 @@ value_dependent_init_p (tree init)
   return false;
 }
 
+// Returns true if a DECL is VAR_DECL with the concept specifier. Note
+// that not all variables are decl-lang-specific.
+static inline bool
+is_concept_var (tree decl) 
+{
+  return VAR_P (decl) 
+  DECL_LANG_SPECIFIC (decl)
+  DECL_DECLARED_CONCEPT_P (decl);
+}
+
 /* Finish processing of a declaration;
install its line number and initial value.
If the length of an array type is not known before,
@@ -6435,6 +6445,8 @@ cp_finish_decl (tree decl, tree init, bo
 	init = NULL_TREE;
 	  release_tree_vector (cleanups);
 	}
+  else if (!init  is_concept_var (decl))
+error (variable concept has no initializer);
   else if (!DECL_PRETTY_FUNCTION_P (decl))
 	{
 	  /* Deduce array size even if the initializer is dependent.  */
@@ -8264,9 +8276,17 @@ grokvardecl (tree type,
   else
 DECL_INTERFACE_KNOWN (decl) = 1;
 
-  // Mark the variable as a concept.
+  // Check that the variable can be safely declared as a concept.
   if (conceptp)
-DECL_DECLARED_CONCEPT_P (decl) = true;
+{
+  if (!processing_template_decl) 
+{
+  error (a non-template variable cannot be %concept%);
+  return NULL_TREE;
+}
+  else
+DECL_DECLARED_CONCEPT_P (decl) = true;
+}
 
   // Handle explicit specializations and instantiations of variable templates.
   if (orig_declarator)


Re: [c++-concepts] variable concept fixes

2014-08-20 Thread Andrew Sutton
 On 08/20/2014 08:56 PM, Andrew Sutton wrote:

 +  return VAR_P (decl)
 +  DECL_LANG_SPECIFIC (decl)
 +  DECL_DECLARED_CONCEPT_P (decl);

 this is brittle from the formatting point of view. Please double check in
 detail what I'm going to say, but I think that in such cases you simply want
 to wrap the whole thing in round parentheses.

Sorry, did you just mean to wrap the entire conjunction in parens? I'm
trying to find the formatting guidelines to check, but not succeeding
at the moment.

Andrew


[c++-concepts] template scoping error

2014-08-20 Thread Andrew Sutton
Fixes a regression in lookup rules involving declarations with
nested-name-specifiers. In particular, we don't actually want to
execute these rules if we absolutely don't have to.

2014-08-15  Andrew Sutton  andrew.n.sut...@gmail.com

Fixing regression in scoping rules for templates.
* gcc/cp/semantics.c (fixup_tmeplate_type): Lift check to
finish_template_type.
(finish_template_type): Only do this when concepts are enabled,
and also when the class is actually a template. For non-dependent
types there are no actions to be taken.

Andrew Sutton
Index: gcc/cp/semantics.c
===
--- gcc/cp/semantics.c	(revision 214228)
+++ gcc/cp/semantics.c	(working copy)
@@ -3004,10 +3004,6 @@ finish_template_decl (tree parms)
 static tree
 fixup_template_type (tree type)
 {
-  // Don't try to fix non-class types.
-  if (!CLASS_TYPE_P (type))
-return type;
-
   // Find the template parameter list at the a depth appropriate to
   // the scope we're trying to enter. 
   tree parms = current_template_parms;
@@ -3055,8 +3051,12 @@ finish_template_type (tree name, tree ar
 NULL_TREE, NULL_TREE, entering_scope,
 tf_warning_or_error | tf_user);
 
-  // If entering a scope, correct the lookup to account for constraints.
-  if (entering_scope)
+  // If entering a scope of a template, correct the lookup to 
+  // account for constraints.
+  if (flag_concepts 
+   entering_scope 
+   CLASS_TYPE_P (type) 
+   CLASSTYPE_IS_TEMPLATE (type))
 type = fixup_template_type (type);
 
   if (type == error_mark_node)


[c++-concepts] normalization checks

2014-08-19 Thread Andrew Sutton
This patch adds checks for user-defined logical operators during
constraint normalization and ensures that all atomics can be converted
to bool.

2014-08-14  Andrew Sutton  andrew.n.sut...@gmail.com

Implement normalization checks.
* gcc/cp/constraint.cc (normalize_expr): Delegate cast and
atomic nodes to a dedicated function.
(check_logical): Check that an  or || does not resolve to a
user-defined function.
(normalize_logical): Check operators and save the locaiton of
the new expression.
(normalize_call, normalize_var): Remove spurios error messages.
(normalize_cast): New, delegates to normalize atom.
(normalize_atom): Check that instantiated expressions can be
converted to bool
(tsubst_constraint_info): Re-normalize the associated constraints
to check for post-substitution restrictions.
* gcc/cp/cp-tree.h (xvalue_result_type): Add to header.


Andrew Sutton
Index: gcc/cp/constraint.cc
===
--- gcc/cp/constraint.cc	(revision 213924)
+++ gcc/cp/constraint.cc	(working copy)
@@ -264,6 +264,8 @@ tree normalize_nested_req (tree);
 tree normalize_var (tree);
 tree normalize_template_id (tree);
 tree normalize_stmt_list (tree);
+tree normalize_cast (tree);
+tree normalize_atom (tree);
 
 // Reduce the requirement T into a logical formula written in terms of
 // atomic propositions.
@@ -328,7 +330,7 @@ normalize_expr (tree t)
   return normalize_template_id (t);
 
 case CAST_EXPR:
-  return normalize_node (TREE_VALUE (TREE_OPERAND (t, 0)));
+  return normalize_cast (t);
 
 case BIND_EXPR:
   return normalize_node (BIND_EXPR_BODY (t));
@@ -339,7 +341,7 @@ normalize_expr (tree t)
 
 // Everything else is atomic.
 default:
-  return t;
+  return normalize_atom (t);
 }
 }
 
@@ -402,6 +404,34 @@ normalize_misc (tree t)
   return NULL_TREE;
 }
 
+// Check that the logical expression is not a user-defined operator.
+bool
+check_logical (tree t) 
+{
+  // We can't do much for type dependent expressions.
+  if (type_dependent_expression_p (t) || value_dependent_expression_p (t))
+return true;
+
+  // Resolve the logical operator. Note that template processing is
+  // disabled so we get the actual call or target expression back.
+  // not_processing_template_sentinel sentinel;
+  tree arg1 = TREE_OPERAND (t, 0);
+  tree arg2 = TREE_OPERAND (t, 1);
+
+  tree ovl = NULL_TREE;
+  tree expr = build_new_op (input_location, TREE_CODE (t), LOOKUP_NORMAL, 
+arg1, arg2, /*arg3*/NULL_TREE, 
+ovl, tf_none);
+  if (TREE_CODE (expr) != TREE_CODE (t))
+{
+  error (user-defined operator %qs in constraint %qE,
+ operator_name_info[TREE_CODE (t)].name, t);
+  ;
+  return false;
+}
+  return true;
+}
+
 // Reduction rules for the binary logical expression T ( and ||).
 //
 // Generate a new expression from the reduced operands. If either operand
@@ -409,14 +439,18 @@ normalize_misc (tree t)
 tree
 normalize_logical (tree t)
 {
+  if (!check_logical (t))
+return NULL_TREE;
+
   tree l = normalize_expr (TREE_OPERAND (t, 0));
   tree r = normalize_expr (TREE_OPERAND (t, 1));
   if (l  r)
 {
-  t = copy_node (t);
-  TREE_OPERAND (t, 0) = l;
-  TREE_OPERAND (t, 1) = r;
-  return t;
+  tree result = copy_node (t);
+  SET_EXPR_LOCATION (result, EXPR_LOCATION (t));
+  TREE_OPERAND (result, 0) = l;
+  TREE_OPERAND (result, 1) = r;
+  return result;
 }
   else
 return NULL_TREE;
@@ -440,18 +474,13 @@ normalize_call (tree t)
   // Reduce the body of the function into the constriants language.
   tree body = normalize_constraints (DECL_SAVED_TREE (fn));
   if (!body)
-{
-  error (could not inline requirements from %qD, fn);
-  return error_mark_node;
-}
+return error_mark_node;
 
   // Instantiate the reduced results using the deduced args.
   tree result = tsubst_constraint_expr (body, args, false);
   if (result == error_mark_node)
-{
-  error (could not instantiate requirements from %qD, fn);
-  return error_mark_node;
-}
+return error_mark_node;
+
   return result;
 }
 
@@ -469,18 +498,12 @@ normalize_var (tree t)
   // Reduce the initializer of the variable into the constriants language.
   tree body = normalize_constraints (DECL_INITIAL (decl));
   if (!body)
-   {
- error (could not inline requirements from %qD, decl);
- return error_mark_node;
-   }
+return error_mark_node;
 
   // Instantiate the reduced results.
   tree result = tsubst_constraint_expr (body, TREE_OPERAND (t, 1), false);
   if (result == error_mark_node)
-{
-  error (could not instantiate requirements from %qD, decl);
-  return error_mark_node;
-}
+return error_mark_node;
 
   return result;
 }
@@ -574,6 +597,29 @@ normalize_stmt_list

[c++-concepts] 2 patches

2014-08-18 Thread Andrew Sutton
The first improves support for shorthand concepts, and includes the
ability to write default arguments. Also, no more ICE when omitting
identifiers for template parameters.

The second adds constraint checks when taking the address of an
overloaded function.

Corresponding change logs follow:

2014-08-13  Andrew Sutton  andrew.n.sut...@gmail.com

* gcc/cp/class.c (resolve_address_of_overloaded_function): Check
constraints.
* gcc/cp/decl.c (grokfndecl): For now, disallow constrained
non-template functions.
* gcc/testsuite/g++.dg/concepts: New tests.

2014-08-13  Andrew Sutton  andrew.n.sut...@gmail.com

* gcc/cp/parser.c (get_id_declarator, get_identifier): New helper
functions.s
(cp_check_constrained_type_parm): Don't fail on null declarators.
(cp_finish_constrained_parameter): Remove redundant processing for
checking declarations.
(cp_maybe_type_parameter, cp_declares_type_parameter,
cp_declares_type_template_parameter,
cp_declares_template_template_parameter): New helper functions for
determining when a parameter declaration is actually a constrained
template parameter.
(cp_parser_default_type_template_argument,
cp_parser_default_template_template_argument): Parsing support
for argument types of default arguments.
(cp_parser_template_parameter): Finish constrained parameters
after all variadic and default arg checks.
(cp_parser_parameter_declaration): Parse default arguments
differently if the parameter actually declares a type parameter.
* gcc/testsuite/g++.dg/concepts: New tests.

Andrew Sutton
Index: gcc/cp/parser.c
===
--- gcc/cp/parser.c	(revision 213909)
+++ gcc/cp/parser.c	(working copy)
@@ -13221,6 +13221,29 @@ cp_parser_template_parameter_list (cp_pa
   return end_template_parm_list (parameter_list);
 }
 
+// Given a declarator, get the declarator-id part, or NULL_TREE if this
+// is an abstract declarator.
+static inline cp_declarator*
+cp_get_id_declarator (cp_declarator *declarator) 
+{
+  cp_declarator *d = declarator;
+  while (d  d-kind != cdk_id)
+d = d-declarator;
+  return d;
+}
+
+// Get the declared name from the DECLARATOR or NULL_TREE if this is
+// DECLARATOR is NULL
+static inline tree
+cp_get_identifier (cp_declarator *declarator)
+{
+  declarator = cp_get_id_declarator (declarator);
+  if (declarator)
+return declarator-u.id.unqualified_name;
+  else
+return NULL_TREE;
+}
+
 // Returns true if PARM declares a constrained-parameter.
 static inline bool
 cp_is_constrained_parameter (cp_parameter_declarator *parm)
@@ -13242,8 +13265,9 @@ bool
 cp_check_constrained_type_parm (cp_parser *parser, 
 cp_parameter_declarator *parm)
 {
-  // Don't ptr, ref, function, or array declarators for a constrained type
-  // or template template parameter.
+  if (!parm-declarator)
+return true;
+  
   if (parm-declarator-kind != cdk_id)
 {
   cp_parser_error (parser, invalid constrained type parameter);
@@ -13320,28 +13344,16 @@ cp_finish_constrained_parameter (cp_pars
  bool *is_parameter_pack)
 {
   tree decl = parmdecl-decl_specifiers.type;
-  tree id = parmdecl-declarator-u.id.unqualified_name;
+  tree id = cp_get_identifier (parmdecl-declarator);
   tree def = parmdecl-default_argument;
   tree proto = DECL_INITIAL (decl);
 
-  // Remember if the user declared this as a parameter pack and
-  // erase that flag on the annotation. Template packs are dealt
-  // with separately.
-  bool is_pack = parmdecl-declarator-parameter_pack_p;
-  if (is_pack)
-parmdecl-declarator-parameter_pack_p = false;
-
-  // Is the prototype a parameter pack? If so, but the declaration
-  // does not include ..., then emit an error.
+  // A templat parameter constrained by a variadic concept shall also
+  // be declared as a template parameter pack.
   bool is_variadic = template_parameter_pack_p (proto);
-  if (is_variadic  !is_pack)
+  if (is_variadic  !*is_parameter_pack)
 cp_parser_error (parser, variadic constraint introduced without %...%);
 
-  // The prototype is a template parameter pack, then the resulting
-  // parameter also needs to be a pack.
-  if (is_pack || is_variadic)
-*is_parameter_pack = true;
-
   // Build the parameter. Return an error if the declarator
   // was invalid.
   tree parm;
@@ -13361,6 +13373,111 @@ cp_finish_constrained_parameter (cp_pars
   return parm;
 }
 
+// Returns the type of the given TYPE may represent the declaration of
+// a template type parameter. This is a helper function for the
+// cp_declares_type* functions below.
+static inline bool
+cp_maybe_type_parameter (tree type)
+{
+  return type
+  TREE_CODE (type) == TYPE_DECL
+  DECL_SIZE_UNIT (type)
+  TREE_TYPE (type);
+}
+
+// Returns true

Re: [c++-concepts] explicit instantiation and specialization

2014-08-15 Thread Andrew Sutton
Just committed this patch, fixing the bootstrap.

2014-08-13  Andrew Sutton  andrew.n.sut...@gmail.com

Fix regression in bootstrap.
  * gcc/cp/call.c (get_temploid): Removed. No longer called.
  (joust): Remove unused variable declarations.

Andrew


On Wed, Aug 13, 2014 at 9:50 PM, Andrew Sutton
andrew.n.sut...@gmail.com wrote:
 Ah... sorry. Leftovers. I didn't have time to run a full bootstrap
 build before heading out for a few days. I'll try to get those out
 tomorrow afternoon-ish.

 Andrew


 On Wed, Aug 13, 2014 at 9:13 PM, Ed Smith-Rowland 3dw...@verizon.net wrote:
 I get build fail:

 ../../gcc_concepts/gcc/cp/call.c:8793:8: error: unused variable ‘m1’
 [-Werror=unused-variable]
tree m1 = get_temploid (cand1);
 ^
 ../../gcc_concepts/gcc/cp/call.c:8794:8: error: unused variable ‘m2’
 [-Werror=unused-variable]
tree m2 = get_temploid (cand2);
 ^
 cc1plus: all warnings being treated as errors

 Commenting the lines let the build finish.

 Ed

Index: gcc/cp/call.c
===
--- gcc/cp/call.c	(revision 213924)
+++ gcc/cp/call.c	(working copy)
@@ -8755,24 +8755,6 @@ add_warning (struct z_candidate *winner,
   winner-warnings = cw;
 }
 
-// When a CANDidate function is a member function of a class template
-// specialization, return the temploid describing that function.
-// Returns NULL_TREE otherwise.
-static inline tree
-get_temploid (struct z_candidate *cand)
-{
-  gcc_assert (cand);
-  tree t = NULL_TREE;
-  if (!cand-template_decl)
-{
-  if (DECL_P (cand-fn)  DECL_USE_TEMPLATE (cand-fn))
-t = DECL_TI_TEMPLATE (cand-fn);
-  if (t  TREE_CODE (t) == TEMPLATE_INFO)
-t = TI_TEMPLATE (t);
-}
-return t;
-}
-
 /* Compare two candidates for overloading as described in
[over.match.best].  Return values:
 
@@ -8789,10 +8771,6 @@ joust (struct z_candidate *cand1, struct
   size_t i;
   size_t len;
 
-  // Try to get a temploid describing each candidate. 
-  tree m1 = get_temploid (cand1);
-  tree m2 = get_temploid (cand2);
-
   /* Candidates that involve bad conversions are always worse than those
  that don't.  */
   if (cand1-viable  cand2-viable)


Re: [c++-concepts] variable concepts

2014-08-13 Thread Andrew Sutton
Committed.

Andrew Sutton


On Wed, Aug 13, 2014 at 3:24 AM, Braden Obrzut ad...@maniacsvault.net wrote:
 This patch adds support for variable concepts.

 There is a known issue that prevents concept variables from having requires
 expressions that have parameters.  This issue is not within the scope of
 this patch as it affects adhoc requires expressions as well.

 2014-08-13  Braden Obrzut ad...@maniacsvault.net

 * gcc/cp/constraint.cc (deduce_constrained_parameter): Deduce concept
 from variable concept template-id expressions.
 (normalize_var): New.
 (normalize_template_id): Identify variable concepts.
 (build_concept_check): Handle variable concepts.
 (finish_shorthand_requirement): Handle variable concepts.
 (diagnose_var): New.
 (diagnose_node): Identify variable concepts.
 * gcc/cp/decl.c (grokvardecl): Pass concept flag through to
 check_explicit_specialization.
 (grokdeclarator): Allow variable concepts and pass concept flag through
 grokvardecl.
 * gcc/cp/parser.c (cp_is_constrained_parameter): Accept variable
 concepts.
 (cp_parser_nonclass_name): Accept variable concepts.
 (get_concept_from_constraint): Handle variable concepts.
 * gcc/cp/pt.c (tsubst_copy_and_build): Lookup variable templates.
 (value_dependent_expression_p): Check requires expressions for value
 dependence.
 * gcc/cp/semantics.c (finish_call_expr): Don't instantiate variable
 templates if processing a template declaration.
 * gcc/testsuite/g++.dg/concepts/decl-diagnose.C: Change expected error
 as variable concepts are now handled.
 * gcc/testsuite/g++.dg/concepts/var-concepts1.C: New test.
 * gcc/testsuite/g++.dg/concepts/var-concepts2.C: New test.



Re: Patch for constexpr variable templates

2014-08-13 Thread Andrew Sutton
 Oohh... I can commit to trunk?

 Yes, you're on the write-after-approval list in MAINTAINERS. :)

True, but it's my first commit to trunk :) Incidentally, that's committed now.

Andrew


[c++-concepts] explicit instantiation and specialization

2014-08-13 Thread Andrew Sutton
This patch re-implements explicit instantiation and specialization.
The latter isn't fully tested just yet, but it's close.

Constraints for explicit instantiations and specializations are
deduced from their candidates, not explicitly specified as part of the
declaration.

2014-08-13  Andrew Sutton  andrew.n.sut...@gmail.com

Implement deduction-based explicit instantiation and specialization.
* gcc/cp/call.c (joust): Allow all non-templates to be ordered by
constraints.
* gcc/cp/pt.c (get_class_bindings): Remove superfluous parameter and
move constraint check into most_specialized_class.
(most_constrained_function): Order functions with the same signatures
by their constraints.
(determine_specialization): Candidates must satisfy constraints. Also,
order non-template candidates by constraints. Improve diagnostics
for instances where candidates are rejected.
(more_specialized_inst): New. Compare function templates.
(most_specialized_instantiation): Refactor to use
more_specialized_inst and order by constraints.
(most_specialized_class): Candidates must satisfy constraints.
* gcc/cp/decl.c (various) Cosmetic fixes.
(adjust_fn_constraints): Rewrite so that class template constraints
are not imposed on member function declarations.
* gcc/testsuite/g++.dg/concepts: New tests.

Andrew Sutton
Index: gcc/cp/decl.c
===
--- gcc/cp/decl.c	(revision 213909)
+++ gcc/cp/decl.c	(working copy)
@@ -991,11 +991,6 @@ decls_match (tree newdecl, tree olddecl)
   if (t1 != t2)
 	return 0;
 
-  // Normal functions can be constraind. Two functions with the
-  // same type and different constraints are different functions.
-  tree c1 = get_constraints (newdecl);
-  tree c2 = get_constraints (olddecl);
-
   if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
 	   ! (DECL_EXTERN_C_P (newdecl)
 		 DECL_EXTERN_C_P (olddecl)))
@@ -1014,6 +1009,11 @@ decls_match (tree newdecl, tree olddecl)
 	 type for declaration matching.  */
   r2 = fndecl_declared_return_type (olddecl);
 
+  // Normal functions can be constraind. Two functions with the
+  // same type and different constraints are different functions.
+  tree c1 = get_constraints (newdecl);
+  tree c2 = get_constraints (olddecl);
+
   if (same_type_p (TREE_TYPE (f1), r2))
 	{
 	  if (!prototype_p (f2)  DECL_EXTERN_C_P (olddecl)
@@ -1041,7 +1041,7 @@ decls_match (tree newdecl, tree olddecl)
 	  TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
 	}
 #endif
-	  else {
+	  else
 	types_match =
 	  compparms (p1, p2)
 	   type_memfn_rqual (f1) == type_memfn_rqual (f2)
@@ -1049,7 +1049,6 @@ decls_match (tree newdecl, tree olddecl)
 	   (TYPE_ATTRIBUTES (TREE_TYPE (newdecl)) == NULL_TREE
 	  || comp_type_attributes (TREE_TYPE (newdecl),
 	   TREE_TYPE (olddecl)) != 0);
-  }
 	}
   else
 	types_match = 0;
@@ -7564,24 +7563,54 @@ get_leading_constraints ()
 // parameter list. The adjustment makes them part of the current
 // template requirements.
 static void
-adjust_out_of_class_fn_requirements (tree ctype)
+adjust_fn_constraints (tree ctype)
 {
+  // When grokking a member function template, we are processing
+  // template decl at a depth greater than that of the member's
+  // enclosing class. That is, this case corresponds to the
+  // following declarations:
+  //
+  //templateC T
+  //struct S {
+  //  templateD U void f(U);
+  //};
+  //
+  //templateC T template D U void ST::f(U) { }
+  //
+  // In both decls, the constraint DU is not the current leading
+  // constraint. Make it so.
+  //
+  // Note that for normal member functions, there are no leading
+  // requirements we need to gather.
   if (ctype  processing_template_decl  template_class_depth (ctype))
 {
   if (tree ci = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms))
 {
+  // TODO: When do I ever have leading requirements for a
+  // member function template?
   tree reqs = CI_LEADING_REQS (ci);
   if (reqs  !get_leading_constraints ())
 current_template_reqs = save_leading_constraints (reqs);
 }
 }
-  else if (current_template_parms)
+
+  // Otherwise, this is just a regular function template. Like so:
+  //
+  //templateC T void f();
+  //
+  // Note that the constraint CT is not the current leading requirement
+  // at this point; it was stashed before the declarator was parsed.
+  // Make it the leading constraint.
+  else if (!ctype  current_template_parms)
   {
 if (tree ci = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms))
   {
 tree r1 = CI_LEADING_REQS (ci);
 if (current_template_reqs)
   {
+// TODO: As with above, when do I ever have leading

Re: [c++-concepts] explicit instantiation and specialization

2014-08-13 Thread Andrew Sutton
Ah... sorry. Leftovers. I didn't have time to run a full bootstrap
build before heading out for a few days. I'll try to get those out
tomorrow afternoon-ish.

Andrew


On Wed, Aug 13, 2014 at 9:13 PM, Ed Smith-Rowland 3dw...@verizon.net wrote:
 I get build fail:

 ../../gcc_concepts/gcc/cp/call.c:8793:8: error: unused variable ‘m1’
 [-Werror=unused-variable]
tree m1 = get_temploid (cand1);
 ^
 ../../gcc_concepts/gcc/cp/call.c:8794:8: error: unused variable ‘m2’
 [-Werror=unused-variable]
tree m2 = get_temploid (cand2);
 ^
 cc1plus: all warnings being treated as errors

 Commenting the lines let the build finish.

 Ed



Re: Patch for constexpr variable templates

2014-08-12 Thread Andrew Sutton
  * pt.c (lookup_template_variable): Make the type unspecified if
  any template arguments are dependent.


 This hunk is OK.

Hi Jason, did you apply this hunk of the patch, or should I just
resend this by itself?

Andrew


Re: Patch for constexpr variable templates

2014-08-12 Thread Andrew Sutton
Oohh... I can commit to trunk? I can do it tomorrow morning.

Andrew Sutton


On Tue, Aug 12, 2014 at 4:59 PM, Jason Merrill ja...@redhat.com wrote:
 On 08/12/2014 04:21 PM, Andrew Sutton wrote:

   * pt.c (lookup_template_variable): Make the type unspecified
 if
   any template arguments are dependent.



 This hunk is OK.


 Hi Jason, did you apply this hunk of the patch, or should I just
 resend this by itself?


 I thought you would apply it, but I can if you'd rather.

 Jason



[c++-concepts] substitution fixes

2014-08-11 Thread Andrew Sutton
Fixing some bugs substituting through constraints. In particular, when
diagnosing an error, make sure that we use the right arguments.

There was also a bug caused by substitution through a decltype-type.
In particular, when folding a non-dependent expression containing a
decltype-type, the inner type is not being resolved (because tsubst
returns early when args == NULL_TREE).

The second patch fixes a regression introduced by the first patch.

2014-08-11  Andrew Sutton  andrew.n.sut...@gmail.com

* gcc/cp/pt.c (tsubst): Don't short circuit substitution into
types when processing constraints.
* gcc/cp/constraint.c (tsubst_constraint_expr): Indicate that
constraint processing is happening.
(tsubst_constraint_info): Just substitute directly into the
normalized constraints instead of re-normalizing.
(diagnose_constraints): Adjust template arguments when
diagnosing template constraint failures.
* gcc/cp/logic.cc (decompose_assumptions): Handle null assumptions.

Andrew Sutton
Index: pt.c
===
--- pt.c	(revision 213758)
+++ pt.c	(working copy)
@@ -11960,6 +11960,8 @@ tsubst_exception_specification (tree fnt
   return new_specs;
 }
 
+extern int processing_constraint;
+
 /* Take the tree structure T and replace template parameters used
therein with the argument vector ARGS.  IN_DECL is an associated
decl for diagnostics.  If an error occurs, returns ERROR_MARK_NODE.
@@ -11994,7 +11996,7 @@ tsubst (tree t, tree args, tsubst_flags_
   if (DECL_P (t))
 return tsubst_decl (t, args, complain);
 
-  if (args == NULL_TREE)
+  if (args == NULL_TREE  !processing_constraint)
 return t;
 
   code = TREE_CODE (t);
Index: semantics.c
===
--- semantics.c	(revision 213758)
+++ semantics.c	(working copy)
@@ -7011,6 +7011,7 @@ finish_decltype_type (tree expr, bool id
   return type;
 }
 
+
   /* The type denoted by decltype(e) is defined as follows:  */
 
   expr = resolve_nondeduced_context (expr);
@@ -7386,7 +7387,7 @@ finish_trait_expr (cp_trait_kind kind, t
 	  || kind == CPTK_IS_LITERAL_TYPE
 	  || kind == CPTK_IS_POD
 	  || kind == CPTK_IS_POLYMORPHIC
-|| kind == CPTK_IS_SAME_AS
+  || kind == CPTK_IS_SAME_AS
 	  || kind == CPTK_IS_STD_LAYOUT
 	  || kind == CPTK_IS_TRIVIAL
 	  || kind == CPTK_IS_UNION);
Index: constraint.cc
===
--- constraint.cc	(revision 213758)
+++ constraint.cc	(working copy)
@@ -241,7 +241,7 @@ tree normalize_stmt (tree);
 tree normalize_decl (tree);
 tree normalize_misc (tree);
 tree normalize_logical (tree);
-tree normalize_call(tree);
+tree normalize_call (tree);
 tree normalize_requires (tree);
 tree normalize_expr_req (tree);
 tree normalize_type_req (tree);
@@ -1114,14 +1114,14 @@ tsubst_local_parms (tree t,
 }
 
 // Substitute ARGS into the requirement body (list of requirements), T.
+// Note that if any substitutions fail, then this is equivalent to 
+// returning false.
 tree
 tsubst_requirement_body (tree t, tree args, tree in_decl)
 {
   tree r = NULL_TREE;
   while (t)
 {
-  // If any substitutions fail, then this is equivalent to
-  // returning false.
   tree e = tsubst_expr (TREE_VALUE (t), args, tf_none, in_decl, false);
   if (e == error_mark_node)
 e = boolean_false_node;
@@ -1142,7 +1142,6 @@ tsubst_requires_expr (tree t, tree args,
   return finish_requires_expr (p, r);
 }
 
-
 // Substitute ARGS into the valid-expr expression T.
 tree
 tsubst_validexpr_expr (tree t, tree args, tree in_decl)
@@ -1197,6 +1196,12 @@ tsubst_nested_req (tree t, tree args, tr
   return tsubst_expr (TREE_OPERAND (t, 0), args, tf_none, in_decl, false);
 }
 
+// Used in various contexts to control substitution. In particular, when
+// non-zero, the substitution of NULL arguments into a type will still
+// process the type as if passing non-NULL arguments, allowing type
+// expressions to be fully elaborated during substitution.
+int processing_constraint;
+
 // Substitute the template arguments ARGS into the requirement
 // expression REQS. Errors resulting from substitution are not
 // diagnosed.
@@ -1208,11 +1213,13 @@ tree
 tsubst_constraint_expr (tree reqs, tree args, bool do_not_fold)
 {
   cp_unevaluated guard;
+  ++processing_constraint;
   if (do_not_fold)
 ++processing_template_decl;
   tree r = tsubst_expr (reqs, args, tf_none, NULL_TREE, false);
   if (do_not_fold)
 --processing_template_decl;
+  --processing_constraint;
   return r;
 }
 
@@ -1230,10 +1237,8 @@ tsubst_constraint_info (tree ci, tree ar
 result-leading_reqs = tsubst_constraint_expr (r, args, true);
   if (tree r = CI_TRAILING_REQS (ci))
 result-trailing_reqs = tsubst_constraint_expr (r, args, true);
-
-  // Build the normalized associated requiremnts.
-  tree r

Re: Patch for constexpr variable templates

2014-08-07 Thread Andrew Sutton
  * decl.c (cp_finish_decl): Don't check the initializer if it is
  value-dependent.


 Why is this needed?

I thought that check_initializer was evaluating the constant
expression, and was resulting in errors because a template-id
referring to a variable template with a concrete type wasn't being
marked as dependent.

Taking a second look, this change doesn't appear to be needed. The
change to lookup_template_variable seems to do enough. I just reran
the tests and it seems to behave correctly without it.

Andrew


[c++-concepts]

2014-08-06 Thread Andrew Sutton
Rewrite the constraint-checking code so that it doesn't instantiate
concept definitions. Instead of doing a simple constexpr evaluation on
the associated constraints, this now iterates over the decomposed
assumptions to determine satisfaction.

2014-08-06  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/constraints.c (tsubst_requires_body, instantiate_requirements):
Lift the unevaluated operand guard to the entire constraint expression.
(check_satisfied, all_constraints_satisfied,
any_conjunctions_satisfied): Rewrite constraint checking to use
atomic constraints. Prevents instantiation of concepts.
(check_diagnostic_constraints): Recursively decompose and check
constraints for fine-grain diagnostics.
(diagnose_*): Use new constraint checking function.

Andrew Sutton
Index: gcc/cp/constraint.cc
===
--- gcc/cp/constraint.cc	(revision 213130)
+++ gcc/cp/constraint.cc	(working copy)
@@ -1117,7 +1117,6 @@ tsubst_local_parms (tree t,
 tree
 tsubst_requirement_body (tree t, tree args, tree in_decl)
 {
-  cp_unevaluated guard;
   tree r = NULL_TREE;
   while (t)
 {
@@ -1143,6 +1142,7 @@ tsubst_requires_expr (tree t, tree args,
   return finish_requires_expr (p, r);
 }
 
+
 // Substitute ARGS into the valid-expr expression T.
 tree
 tsubst_validexpr_expr (tree t, tree args, tree in_decl)
@@ -1207,6 +1207,7 @@ tsubst_nested_req (tree t, tree args, tr
 tree
 instantiate_requirements (tree reqs, tree args, bool do_not_fold)
 {
+  cp_unevaluated guard;
   if (do_not_fold)
 ++processing_template_decl;
   tree r = tsubst_expr (reqs, args, tf_none, NULL_TREE, false);
@@ -1248,22 +1249,55 @@ tsubst_constraint_info (tree ci, tree ar
 // evaluation of constraints.
 
 namespace {
-// Returns true if the requirements expression REQS is satisfied
-// and false otherwise. The requirements are checked by simply 
-// evaluating REQS as a constant expression.
-static inline bool
-check_requirements (tree reqs)
+// Returns true iff the atomic constraint, REQ, is satisfied. This
+// is the case when substitution succeeds and the resulting expression
+// evaluates to true.
+static bool
+check_satisfied (tree req, tree args) 
 {
+  // Instantiate and evaluate the requirements. 
+  req = instantiate_requirements (req, args, false);
+  if (req == error_mark_node)
+return false;
+
   // Reduce any remaining TRAIT_EXPR nodes before evaluating.
-  reqs = fold_non_dependent_expr (reqs);
+  req = fold_non_dependent_expr (req);
 
   // Requirements are satisfied when REQS evaluates to true.
-  return cxx_constant_value (reqs) == boolean_true_node;
+  tree result = cxx_constant_value (req);
+
+  return result == boolean_true_node;
+}
+
+// Returns true iff all atomic constraints in the list are satisfied.
+static bool
+all_constraints_satisfied (tree reqs, tree args)
+{
+  int n = TREE_VEC_LENGTH (reqs);
+  for (int i = 0; i  n; ++i)
+{
+  tree req = TREE_VEC_ELT (reqs, i);
+  if (!check_satisfied (req, args))
+return false;
+}
+  return true;
 }
 
-// Returns true if the requirements expression REQS is satisfied 
-// and false otherwise. The requirements are checked by first
-// instantiating REQS and then evaluating it as a constant expression.
+// Returns true if any conjunction of assumed requirements are satisfied.
+static bool
+any_conjunctions_satisfied (tree reqs, tree args)
+{
+  int n = TREE_VEC_LENGTH (reqs);
+  for (int i = 0; i  n; ++i)
+{
+  tree con = TREE_VEC_ELT (reqs, i);
+  if (all_constraints_satisfied (con, args))
+return true;
+}
+  return false;
+}
+
+// Returns true iff the assumptions in REQS are satisfied.
 static inline bool
 check_requirements (tree reqs, tree args)
 {
@@ -1272,11 +1306,7 @@ check_requirements (tree reqs, tree args
   if (args  uses_template_parms (args))
 return true;
 
-  // Instantiate and evaluate the requirements. 
-  reqs = instantiate_requirements (reqs, args, false);
-  if (reqs == error_mark_node)
-return false;
-  return check_requirements (reqs);
+  return any_conjunctions_satisfied (reqs, args);
 }
 } // namespace
 
@@ -1295,7 +1325,7 @@ check_constraints (tree cinfo)
   // all remaining expressions that are not constant expressions
   // (e.g., template-id expressions).
   else
-return check_requirements (CI_ASSOCIATED_REQS (cinfo), NULL_TREE);
+return check_requirements (CI_ASSUMPTIONS (cinfo), NULL_TREE);
 }
 
 // Check the constraints in CINFO against the given ARGS, returning
@@ -1309,8 +1339,9 @@ check_constraints (tree cinfo, tree args
   // Invlaid requirements cannot be satisfied.
   else if (!valid_requirements_p (cinfo))
 return false;
-  else
-return check_requirements (CI_ASSOCIATED_REQS (cinfo), args);
+  else {
+return check_requirements (CI_ASSUMPTIONS (cinfo), args);
+  }
 }
 
 // Check the constraints of the declaration or type T, against 
@@ -1322,6

Re: [c++-concepts] Allow function parameters to be referenced in trailing requires clauses

2014-07-30 Thread Andrew Sutton
Applied an updated version of this patch.

2014-7-30  Braden Obrzut  ad...@maniacsvault.net
* gcc/cp/parser.c (cp_parser_trailing_requirements): Handle requires
keyword manually so that we can push function parameters back into
scope.
* gcc/cp/decl.c (push_function_parms): New. Recovers and reopens
function parameter scope from declarator.
* gcc/testsuite/g++.dg/concepts/req*.C: New tests.

2014-07-30  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/testsuite/g++.dg/concepts/test.C: Removed.

Andrew Sutton


On Tue, Jun 17, 2014 at 5:06 AM, Braden Obrzut ad...@maniacsvault.net wrote:
 This patch allows function parameters to be referenced by trailing requires
 clauses.  Typically this is used to refer to the type of an implicitly
 generated template.  For example, the following should now be valid (where C
 is some previously defined concept):

 auto f1 (auto x) requires Cdecltype(x) ();

 Note that the test case trailing-requires-overload.C will fail to compile
 unless the previously submitted patch is applied first.

 2014-06-17  Braden Obrzut  ad...@maniacsvault.net
 * gcc/cp/parser.c (cp_parser_trailing_requirements): Handle requires
 keyword manually so that we can push function parameters back into
 scope.
 * gcc/cp/decl.c (push_function_parms): New. Recovers and reopens
 function parameter scope from declarator.
 * gcc/testsuite/g++.dg/concepts/trailing-requires.C: New tests.
 * gcc/testsuite/g++.dg/concepts/trailing-requires-overload.C: New tests.
Index: gcc/testsuite/g++.dg/concepts/traits1.C
===
--- gcc/testsuite/g++.dg/concepts/traits1.C	(revision 212456)
+++ gcc/testsuite/g++.dg/concepts/traits1.C	(working copy)
@@ -79,21 +79,21 @@ void f18() requires Enumvoid();
 
 
 int main() { 
-  f1(); // { dg-error cannot }
-  f2(); // { dg-error cannot }
-  f3(); // { dg-error cannot }
-  f4(); // { dg-error cannot }
-  f5(); // { dg-error cannot }
-  f6(); // { dg-error cannot }
-  f7(); // { dg-error cannot }
-  f8(); // { dg-error cannot }
-  f9(); // { dg-error cannot }
-  f10(); // { dg-error cannot }
-  f11(); // { dg-error cannot }
-  f12(); // { dg-error cannot }
-  f13(); // { dg-error cannot }
-  f14(); // { dg-error cannot }
-  f15(); // { dg-error cannot }
-  f16(); // { dg-error cannot }
-  f17(); // { dg-error cannot }
+  f1(); // { dg-error cannot call }
+  f2(); // { dg-error cannot call }
+  f3(); // { dg-error cannot call }
+  f4(); // { dg-error cannot call }
+  f5(); // { dg-error cannot call }
+  f6(); // { dg-error cannot call }
+  f7(); // { dg-error cannot call }
+  f8(); // { dg-error cannot call }
+  f9(); // { dg-error cannot call }
+  f10(); // { dg-error cannot call }
+  f11(); // { dg-error cannot call }
+  f12(); // { dg-error cannot call }
+  f13(); // { dg-error cannot call }
+  f14(); // { dg-error cannot call }
+  f15(); // { dg-error cannot call }
+  f16(); // { dg-error cannot call }
+  f17(); // { dg-error cannot call }
 }
Index: gcc/testsuite/g++.dg/concepts/req1.C
===
--- gcc/testsuite/g++.dg/concepts/req1.C	(revision 0)
+++ gcc/testsuite/g++.dg/concepts/req1.C	(revision 0)
@@ -0,0 +1,15 @@
+// { dg-do run }
+// { dg-options -std=c++1z }
+
+templatetypename T
+  concept bool Class () { return __is_class(T); }
+
+void f1(auto a) requires Classdecltype(a)() { }
+void f2(auto a) requires requires (decltype(a) x) { -x; } { }
+
+struct S { } s;
+
+int main() {
+  f1(s);
+  f2(0);
+}
Index: gcc/testsuite/g++.dg/concepts/req2.C
===
--- gcc/testsuite/g++.dg/concepts/req2.C	(revision 0)
+++ gcc/testsuite/g++.dg/concepts/req2.C	(revision 0)
@@ -0,0 +1,21 @@
+// { dg-options -std=c++1z }
+
+#include cassert
+
+templatetypename T
+  concept bool Class () { return __is_class(T); }
+
+void f1 (auto a) requires Classdecltype(a)() { }
+
+  // FIXME: This is generating excess errors related to pretty
+  // printing the trailing requires expression.
+void f2(auto a) 
+  requires requires (decltype(a) x) { -x; } 
+{ } 
+
+struct S { } s;
+
+int main() {
+  f1(0); // { dg-error matching }
+  f2((void*)0); // { dg-error matching }
+}
Index: gcc/testsuite/g++.dg/concepts/req3.C
===
--- gcc/testsuite/g++.dg/concepts/req3.C	(revision 0)
+++ gcc/testsuite/g++.dg/concepts/req3.C	(revision 0)
@@ -0,0 +1,18 @@
+// { dg-do run }
+// { dg-options -std=c++1z }
+
+templatetypename T
+  concept bool Class () { return __is_class(T); }
+
+struct Test {
+  void f(auto a) requires Classdecltype(a)();
+} test;
+
+struct S { }s;
+
+int main() {
+  test.f(s);
+}
+
+void Test::f(auto a) requires Classdecltype(a)() { }
+
Index: gcc/testsuite/g++.dg/concepts/test.C
===
--- gcc/testsuite/g++.dg/concepts/test.C

Re: Patch for constexpr variable templates

2014-07-28 Thread Andrew Sutton
 It sounds like GCC's behavior with auto in function parameters
 needs to be changed, but that definitely sounds like a separate
 patch to me.

 I think so.  It's definitely a different patch.

Agreed.

 I've been
 thinking about a simple way for your patch to add to the
 constraints for 'auto_is_implicit_function_template_parm_p' in
 'cp_parser_parameter_declaration_clause' but this is happening
 incrementally at parse time and I can't see how to distinguish
 between the following 'auto' parameters:

  1)  auto f(auto);// generic function 'f'; transformed into
 template by 'auto' in parameter list.
  2)  auto (*f) (auto);// plain variable 'f' (should have an
 initializer for deduction of 'auto's.

  3)  auto (*f (auto)) (auto); // generic function 'f' constrained to
 returning a unary function pointer deduced from the return expression.

Really? I've read the comment and I'm still not sure how to read this
declaration.

 Ultimately, the last two would require the generalized 'auto'
 type deduction behavior.  The difficulty is that there doesn't
 appear to be any existing means for determining, at parse time
 of the first (auto, whether we're forming a function or
 variable declaration.  Maybe such state would fall out of a
 generalized 'auto' solution.

I was wondering about this on the drive to work this morning. Maybe
trying to pin down semantics at parse time isn't the right approach.
That is, always parse declarations like variables, and then build up
template parameters as needed during grorkdecl or grokfndecl. Or maybe
that's too late. I don't know.

Whatever the solution for auto, it will be the same for concepts.
We'll just add constraints to the auto-type whenever we find a
constrained-type-specifier.

Andrew


[c++-concepts] overloading update

2014-07-28 Thread Andrew Sutton
Update the overloading rules for constraints to bring them into line
with the current wording. This handles overloads of member functions
of class template specializations separately from function templates.

Currently, functions that are not specializations of templates (or
temploids) can only be overloaded by type. They are not ordered by
their constraints.

This patch also contains an uncommitted change fixing some small
diagnostic issues. Unfortunately, they got lumped together.

2014-07-28  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/cp-tree.h (more_constraints): Remove
(subsumes_constraints): Renamed from more_constraints
(more_constrained): Repurposed
* gcc/cp/call-c (template_decl_for_candidates): Rename to get_temploid,
only get template info for member functions of a class template
specialization.
(joust): Handle member functions of class template specializations
separately from function templates. This matches the new wording in
the TS.
* gcc/cp/logic.cc (match_terms): Make inline.
(subsumes_constraints): Rename to subsumes_constraints_nonnull.
* gcc/cp/pt.c (is_compatible_template_arg): Use subsumes.
(more_specialized_fn): Use usubsumes_constraints.
(more_specialized_class): Use more_constrained.
* gcc/cp/constraint.cc (more_constraints): Removed.
(more_constrained): New.

2014-07-11  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/typeck.c (cp_build_function_call_vec): Emit diagnostic
at the input location.
* gcc/cp/error.c (dump_template_decl): Constraints are never invalid
in this way. Also fixes brace warning.

Andrew Sutton
Index: error.c
===
--- error.c	(revision 212456)
+++ error.c	(working copy)
@@ -1280,10 +1280,7 @@ dump_template_decl (cxx_pretty_printer *
 
   if (flag_concepts)
 if (tree ci = get_constraints (t))
-if (ci != error_mark_node)
-  pp_cxx_requires_clause (pp, CI_LEADING_REQS (ci));
-else
-  pp_cxx_ws_string (pp, invalid-constraints);
+  pp_cxx_requires_clause (pp, CI_LEADING_REQS (ci));
 
 	  pp_cxx_whitespace (pp);
 	}
Index: typeck.c
===
--- typeck.c	(revision 212456)
+++ typeck.c	(working copy)
@@ -3463,8 +3463,8 @@ cp_build_function_call_vec (tree functio
 if (tree ci = get_constraints (function))
   if (!check_constraints (ci))
 {
+  error (cannot call function %qD, function);
   location_t loc = DECL_SOURCE_LOCATION (function);
-  error_at (loc, cannot call function %qD, function);
   diagnose_constraints (loc, function, NULL_TREE);
   return error_mark_node;
 }
Index: cp-tree.h
===
--- cp-tree.h	(revision 212456)
+++ cp-tree.h	(working copy)
@@ -6423,8 +6423,8 @@ extern bool check_template_constraints
 extern tree subst_template_constraints  (tree, tree);
 extern bool equivalent_constraints  (tree, tree);
 extern bool equivalently_constrained(tree, tree);
-extern bool more_constraints(tree, tree);
-extern bool more_constrained(tree, tree);
+extern bool subsumes_constraints(tree, tree);
+extern int more_constrained (tree, tree);
 
 extern void diagnose_constraints(location_t, tree, tree);
 
Index: call.c
===
--- call.c	(revision 212456)
+++ call.c	(working copy)
@@ -27,6 +27,7 @@ along with GCC; see the file COPYING3.
 #include coretypes.h
 #include tm.h
 #include tree.h
+#include print-tree.h
 #include stor-layout.h
 #include trans-mem.h
 #include stringpool.h
@@ -8731,20 +8732,22 @@ add_warning (struct z_candidate *winner,
   winner-warnings = cw;
 }
 
-// Returns the template declaration associated with the candidate
-// function. For actual templates, this is directly associated
-// with the candidate. For temploids, we return the template
-// associated with the specialization.
+// When a CANDidate function is a member function of a class template
+// specialization, return the temploid describing that function.
+// Returns NULL_TREE otherwise.
 static inline tree
-template_decl_for_candidate (struct z_candidate *cand)
+get_temploid (struct z_candidate *cand)
 {
- tree r = cand-template_decl;
-  tree d = cand-fn;
-  if (!r  DECL_P (d)  DECL_USE_TEMPLATE (d))
-r = DECL_TI_TEMPLATE (d);
-  if (r  TREE_CODE (r) == TEMPLATE_INFO)
-r = TI_TEMPLATE (r);
-  return r;
+  gcc_assert (cand);
+  tree t = NULL_TREE;
+  if (!cand-template_decl)
+{
+  if (DECL_P (cand-fn)  DECL_USE_TEMPLATE (cand-fn))
+t

Re: Patch for constexpr variable templates

2014-07-27 Thread Andrew Sutton
 In the 59638 case, the declarations

   void (*a)(auto);
   void (*b)(auto) = 0;

 are shorthand for

   template typename T void (*a)(T);
   template typename T void (*b)(T) = 0;

 which, unless there's some constraint with variable templates that I'm not
 aware of, ought to define two variable templates 'a' and 'b' to be
 ptr-to-function-taking-T.  So I think it's correct that the variable
 template stuff should be triggering here.

There isn't, but this interpretation isn't consistent with the use of
auto in variable declarations. For example, this:

  const auto x = 0;

does not mean:

  templatetypename T const T x = 0;

So I would be surprised if any of:

  void (*p1)(auto);
  auto (*p2)(int);
  vectorauto x;

did mean create a template instead of deduce the type of x.

Also, if we did have this interpretation of auto for some (but not
all?) variable declarations, we would have to know to write those as
template-ids:

  void (*p)(auto);
  pint = some_f;

since one cannot refer to a template specialization without arguments.

I'm much, much happier if, for variable templates, we always deduce
the type from the initializer.. Besides, that wording (or some
approximation thereof) is already in the TS for concepts. A question
came up during the CWG review as to whether we could declare function
parameters as void (*p)(auto), and EWG said, sure, go for it. We
also have the ability to declare function parameters as, e.g.,
vectorauto or pairconst auto, auto*. I applied that to variable
templates as well, since it would have been a bit inconsistent,
otherwise.

Andrew


Re: Patch for constexpr variable templates

2014-07-23 Thread Andrew Sutton
 But someday we'll want non-constexpr too. I have only seen a sentence
 somewhere stating that non-constexpr variable templates are allowed but have
 seen no paper or wording anywhere.  Does anyone know where such exists?

When variable templates were proposed, EWG decided they wanted
non-constexpr variable templates also. I think that the current draft
reflects that, since I can't find anything that says variable
templates shall be declared constexpr.

There's also an implied requirement for partial specialization of
variable templates (14.3.3p2), but no elaboration of that. Core issue
1711 specifically addresses this. A quick search shows that Clang
already implements it.

Andrew


[c++-concepts] fixes

2014-07-11 Thread Andrew Sutton
Fix a couple of issues causing a test regression and boostrap build errors.

2014-07-11  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/typeck.c (cp_build_function_call_vec): Emit diagnostic
at the input location.
* gcc/cp/error.c (dump_template_decl): Constraints are never invalid
in this way. Also fixes brace warning.

Andrew Sutton
Index: gcc/cp/typeck.c
===
--- gcc/cp/typeck.c	(revision 212456)
+++ gcc/cp/typeck.c	(working copy)
@@ -3463,8 +3463,8 @@ cp_build_function_call_vec (tree functio
 if (tree ci = get_constraints (function))
   if (!check_constraints (ci))
 {
+  error (cannot call function %qD, function);
   location_t loc = DECL_SOURCE_LOCATION (function);
-  error_at (loc, cannot call function %qD, function);
   diagnose_constraints (loc, function, NULL_TREE);
   return error_mark_node;
 }
Index: gcc/cp/error.c
===
--- gcc/cp/error.c	(revision 212456)
+++ gcc/cp/error.c	(working copy)
@@ -1280,10 +1280,7 @@ dump_template_decl (cxx_pretty_printer *
 
   if (flag_concepts)
 if (tree ci = get_constraints (t))
-if (ci != error_mark_node)
-  pp_cxx_requires_clause (pp, CI_LEADING_REQS (ci));
-else
-  pp_cxx_ws_string (pp, invalid-constraints);
+  pp_cxx_requires_clause (pp, CI_LEADING_REQS (ci));
 
 	  pp_cxx_whitespace (pp);
 	}


[c++-concepts] constraint association

2014-06-28 Thread Andrew Sutton
After merging from trunk this morning, I discovered that
DECL_SIZE_UNIT is now being used to store lists of specializations. I
had been using that to store template constraints. Oops.

This patch moves constraints outside the usual tree structures into an
association maintained in a hash table. It also lays the framework for
allowing constraints to be associated with any _*DECL node (templates,
functions, variables, types, etc).

Changelog below; committed as 212103.

2014-06-28  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/cp-tree.h (DECL_CONSTRAINTS): Remove this macro; use
get_constraints instead.
(set_constraints): new.
* gcc/cp/cxx-pretty-print.c (pp_cxx_template_declaration): Use
get_constraints.
* gcc/cp/pt.c (get_specialization_constraints): Use get_constraints.
(build_template_decl): Use get_constraints.
(process_partial_specialization): Use get_constraints.
(add_inherited_template_parms): Use get_constraints.
(redeclare_class_template): Use get_constraints.
(is_compatible_template_arg): Use get_constraints.
(tsubst_friend_class): Use get_constraints.
(tsubst_decl): Uset get_constraints.
* gcc/cp/semantics.c (finish_template_template_parm): Use
get_constraints.
(fixup_template_type): Use get_constraints.
* gcc/cp/constraint.cc (constraints): New global association
of declarations to constraints.
(get_constraints): Return the associated constraints from the
hash table.
(set_constraints): New. Associate constraints with a declaration.
(check_template_constraints): Use get_constraints.
(equivalently_constrained): Use get_constraints.
(more_constrained): Use get_constraints.
(diagnose_constraints): Use get_constraints.
* gcc/testsuite/g++.dg/concepts/partial-spec.C: New.

Andrew
Index: gcc/cp/cxx-pretty-print.c
===
--- gcc/cp/cxx-pretty-print.c	(revision 212100)
+++ gcc/cp/cxx-pretty-print.c	(working copy)
@@ -2220,7 +2220,7 @@ pp_cxx_template_declaration (cxx_pretty_
   pp_newline_and_indent (pp, 3);
 }
 
-  if (tree c = DECL_CONSTRAINTS (t))
+  if (tree c = get_constraints (t))
 {
   pp_cxx_ws_string (pp, requires);
   pp-expression (CI_REQUIREMENTS (c));
Index: gcc/cp/pt.c
===
--- gcc/cp/pt.c	(revision 212101)
+++ gcc/cp/pt.c	(working copy)
@@ -846,7 +846,7 @@ get_specialization_constraints (tree typ
   // that type. If it is an explicit specialization, return null since
   // non-templates cannot be constrained.
   if (tree d = get_specializing_template_decl (type))
-return DECL_CONSTRAINTS (d);
+return get_constraints (d);
   else
 return NULL_TREE;
 }
@@ -4147,10 +4147,10 @@ build_template_decl (tree decl, tree par
 {
   tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
   DECL_TEMPLATE_PARMS (tmpl) = parms;
-  DECL_CONSTRAINTS (tmpl) = constr;
   DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
   DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
   DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p;
+  set_constraints (tmpl, constr);
 
   return tmpl;
 }
@@ -4319,7 +4319,7 @@ process_partial_specialization (tree dec
  arguments but different constraints. */
   tree main_type = TREE_TYPE (maintmpl);
   tree main_args = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (main_type));
-  tree main_constr = DECL_CONSTRAINTS (maintmpl);
+  tree main_constr = get_constraints (maintmpl);
   if (comp_template_args (inner_args, main_args)
equivalent_constraints (current_template_reqs, main_constr))
 error (partial specialization %qT does not specialize any 
@@ -5229,13 +5229,13 @@ add_inherited_template_parms (tree fn, t
   // If the inherited constructor was constrained, then also
   // propagate the constraints to the new declaration by
   // rewriting them in terms of the local template parameters.
-  tree cons = DECL_CONSTRAINTS (inherited);
+  tree cons = get_constraints (inherited);
   if (cons)
 {
   ++processing_template_decl;
   tree reqs = instantiate_requirements (CI_REQUIREMENTS (cons), args);
   --processing_template_decl;
-  DECL_CONSTRAINTS (tmpl) = make_constraints (reqs);
+  set_constraints (tmpl, make_constraints (reqs));
 }
 
   DECL_TEMPLATE_INFO (fn) = build_template_info (tmpl, args);
@@ -5354,7 +5354,7 @@ redeclare_class_template (tree type, tre
 }
 
   // Cannot redeclare a class template with a different set of constraints. 
-  if (!equivalent_constraints (DECL_CONSTRAINTS (tmpl), cons))
+  if (!equivalent_constraints (get_constraints (tmpl), cons))
 {
   error_at (input_location, redeclaration %q#D with different 
 constraints, tmpl);
@@ -6586,8 +6586,8 @@ is_compatible_template_arg (tree parm, t

[c++-concepts] Compiler options/bootstrap

2014-06-28 Thread Andrew Sutton
This patch restores C++98 as the default language in this branch and
disables -fconcepts by default. Using -std=c++1z will enable
-fconcepts.

I wanted to give an error if -fconcepts is used with dialect = cxx11,
but I didn't find the right place to put the check.

This also adds a new format specifier (Z) to the cxxdiag flags. That
warning was turning into an error in the bootstrap build. FYI: The
bootstrap builds cleanly for me now.

Committed in r212105.

2014-06-28  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/c-family/c.opt (flag_concepts): Don't enable by default.
* gcc/c-family/c-opts.c (set_std_cxx1z): Enable concepts if
-std=cxx1z is selected.
* gcc/c-family/c-format.c (gcc_cxxdia): Add Z as format specifier.
* gcc/cp/c-common.c (cxx_dialect): Make -std=c++98 the default
language again.
* gcc/cp/lex.c (cxx_init): Don't set flag_concepts explicitly.
* gcc/testsuite/g++.dg/concepts/*.C: Updat build flags.

Andrew


Re: [c++-concepts] Change constraint equivalence

2014-06-27 Thread Andrew Sutton
 Please drop gcc/ and gcc/testsuite/ prefixes (the former goes to
 cp/ChangeLog, the latter to testsuite/ChangeLog).

This is the format (and file) that Gaby requested when we started the
project. We can certainly distribute the entries, but I don't know if
its worthwhile right now.

Andrew


Re: Re: [c++-concepts] Fix assertion failure with cp_maybe_constrained_type_specifier

2014-06-25 Thread Andrew Sutton
 I did a full 3-stage bootstrap which is the default these days.
 I'll try --disable-bootstrap and see what happens.

I just did a full bootstrap build and got the same errors. The errors
are correct for C++11, which was enabled by default in this branch.
IIRC, aggregate initialization requires the initializer-clause to
match the structure exactly (or at least not omit any const
initializers?)

I think this was something Gaby wanted when we created the branch, but
I'm not sure it's worth keeping because of the bootstrapping errors. I
could reset the default dialect to 98 and turn on concepts iff 1y is
enabled, or I could turn on 1y if -fconcepts is enabled.

Thoughts?

Andrew


Re: [c++-concepts] Fix assertion failure with cp_maybe_constrained_type_specifier

2014-06-24 Thread Andrew Sutton
Braden,

Did you have a specific test case that causes this breakage? I have a
feeling that if we're missing base-link nodes in one place, we'll miss
them in others too.

Andrew


On Tue, Jun 17, 2014 at 4:54 AM, Braden Obrzut ad...@maniacsvault.net wrote:
 cp_maybe_constrained_type_specifier asserted that the decl passed in would
 be of type OVERLOAD, however a clean build of the compiler was broken since
 it could also be a BASELINK.  I'm not entirely sure when this is the case,
 except that it seems to happen with class member templates as it also caused
 a test case in my next patch to fail.  The solution is to check for a
 BASELINK and extract the functions from it.

 The possibility of decl being a BASELINK is asserted near the call in
 cp_parser_template_id (cp_maybe_partial_concept_id just calls the function
 in question at this time).

 2014-06-17  Braden Obrzut  ad...@maniacsvault.net
 * gcc/cp/parser.c (cp_maybe_constrained_type_specifier): Fix assertion
 failure if baselink was passed in as decl.



Re: [c++-concepts] Fix assertion failure with cp_maybe_constrained_type_specifier

2014-06-24 Thread Andrew Sutton
Committed as r211935. I updated the patch to add a more appropriate
comment and changelog entry.

Andrew

On Tue, Jun 24, 2014 at 8:07 AM, Ed Smith-Rowland 3dw...@verizon.net wrote:
 I saw this during bootstrap.  I've verified that the patch works (I was
 working on similar).

 Ed

Index: parser.c
===
--- parser.c	(revision 211591)
+++ parser.c	(working copy)
@@ -15175,9 +15175,15 @@ cp_parser_allows_constrained_type_specif
 static tree
 cp_maybe_constrained_type_specifier (cp_parser *parser, tree decl, tree args)
 {
-  gcc_assert (TREE_CODE (decl) == OVERLOAD);
   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))


[c++-concepts] small pretty printing fix

2014-06-24 Thread Andrew Sutton
This helps improve debug output. When pretty printing template args
including a placeholder, show placeholder instead of a dump_expr
error.

2014-06-24  Andrew Sutton  andrew.n.sut...@gmail.com
  * gcc/cp/error.C (dump_expr): Pretty print placeholder to improve
  debug output.

Committed as r211942.

Andrew
Index: gcc/cp/error.c
===
--- gcc/cp/error.c	(revision 211415)
+++ gcc/cp/error.c	(working copy)
@@ -2656,6 +2656,10 @@ dump_expr (cxx_pretty_printer *pp, tree
 case CONSTEXPR_EXPR:
   pp_cxx_constexpr_expr (cxx_pp, t);
 
+case PLACEHOLDER_EXPR:
+  pp_cxx_ws_string (cxx_pp, placeholder);
+  break;
+
   /*  This list is incomplete, but should suffice for now.
 	  It is very important that `sorry' does not call
 	  `report_error_function'.  That could cause an infinite loop.  */


[c++-concepts] member concepts

2014-06-24 Thread Andrew Sutton
Actually allow member concepts in using shorthand notation.

2014-06-24  Andrew Sutton  andrew.n.sut...@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 {
+  templatetypename T
+static concept bool D() { return __is_same_as(T, int); }
+
+  templatetypename T, typename U
+static concept bool E() { return __is_same_as(T, U); }
+};
+
+void f1(Base::D) { }
+void f2(Base::Edouble x) { }
+
+templatetypename T
+  struct S : Base {
+void f1(Base::D) { }
+void f2(Base::ET x) { }
+  };
+
+int main() { 
+  f1(0);
+
+  f2(0.0);
+
+  Sint 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 {
+  templatetypename T, typename U
+bool C() const { return false; } // Not a concept!
+
+  templatetypename T
+static concept bool D() { return __is_same_as(T, int); }
+
+  templatetypename T, typename U
+static concept bool E() { return __is_same_as(T, U); }
+};
+
+void f1(Base::D) { }
+void f2(Base::Edouble x) { }
+
+templatetypename T
+  struct S : Base {
+void f0(Base::Cfloat x) { } // { dg-error expected|type }
+void f1(Base::D) { }
+void f2(Base::ET x) { }
+  };
+
+int main() { 
+  f1('a'); // { dg-error matching }
+  f2(0);   // { dg-error matching }
+
+  Sint 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

Re: [c++-concepts] Fix assertion failure with cp_maybe_constrained_type_specifier

2014-06-24 Thread Andrew Sutton
Weird.  Any chance you're doing a bootstrap build?

There was an earlier bootstrapping issue with this branch. We had
turned on -std=c++1y by default, and it was causing some conversion
errors with lvalue references to bitfields in libasan.

This doesn't *look* like a regression caused by concepts -- I don't
think I'm touching the initializer code at all.

Andrew Sutton


On Tue, Jun 24, 2014 at 11:42 AM, Ed Smith-Rowland 3dw...@verizon.net wrote:
 I'm not sure the warning is correct in any case...

 In i386.h
 
 struct stringop_algs
 {
   const enum stringop_alg unknown_size;
   const struct stringop_strategy {
 const int max;
 const enum stringop_alg alg;
 int noalign;
   } size [MAX_STRINGOP_ALGS];
 };

 in i386.c
 ---
 static stringop_algs ix86_size_memcpy[2] = {
   {rep_prefix_1_byte, {{-1, rep_prefix_1_byte, false}}},
   {rep_prefix_1_byte, {{-1, rep_prefix_1_byte, false;
 static stringop_algs ix86_size_memset[2] = {
   {rep_prefix_1_byte, {{-1, rep_prefix_1_byte, false}}},
   {rep_prefix_1_byte, {{-1, rep_prefix_1_byte, false;



terse notation diagnostics

2014-06-12 Thread Andrew Sutton
Adds additional checks and tests for ill-formed programs.

2014-06-12  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/parser.c (cp_check_type_concept): New.
(cp_check_concept_name): Remove redundant condition from check.
Diagnose misuse of non-type concepts in constrained type specifiers.
* gcc/testuite/g++.dg/concepts/generic-fn.C: Add tests for
non-simple constrained-type-specifiers and nested-name-specifiers
in concept names.
* gcc/testuite/g++.dg/concepts/generic-fn-err.C: New tests for
diagnosing ill-formed programs.

Committed in r211585.

Andrew Sutton
Index: parser.c
===
--- parser.c	(revision 211476)
+++ parser.c	(working copy)
@@ -15132,11 +15132,22 @@ cp_parser_type_name (cp_parser* parser)
   return type_decl;
 }
 
-
+/// Returns true if proto is a type parameter, but not a template template
+/// parameter.
+static bool
+cp_check_type_concept (tree proto, tree fn) 
+{
+  if (TREE_CODE (proto) != TYPE_DECL) 
+{
+  error (invalid use of non-type concept %qD, fn);
+  return false;
+}
+  return true;
+}
 
 // If DECL refers to a concept, return a TYPE_DECL representing the result
 // of using the constrained type specifier in the current context. 
-
+//
 // DECL refers to a concept if
 //   - it is an overload set containing a function concept taking a single
 // type argument, or
@@ -15173,9 +15184,13 @@ cp_check_concept_name (cp_parser* parser
 
   // In template paramteer scope, this results in a constrained parameter.
   // Return a descriptor of that parm.
-  if (template_parm_scope_p ()  processing_template_parmlist)
+  if (processing_template_parmlist)
 return build_constrained_parameter (proto, fn);
 
+  // In any other context, a concept must be a type concept.
+  if (!cp_check_type_concept (proto, fn))
+return error_mark_node;
+
   // In a parameter-declaration-clause, constrained-type specifiers
   // result in invented template parameters.
   if (parser-auto_is_implicit_function_template_parm_p)
Index: generic-fn.C
===
--- generic-fn.C	(revision 211476)
+++ generic-fn.C	(working copy)
@@ -1,11 +1,16 @@
+// { dg-do run }
 // { dg-options -std=c++1y }
 
 #include cassert
+#include type_traits
 
 templatetypename T
   concept bool C() { return __is_class(T); }
 
-struct S { } s;
+templatetypename T
+  concept bool Type() { return true; }
+
+struct S { };
 
 int called;
 
@@ -50,7 +55,43 @@ templateC T
   };
 
 
+void ptr(C*) { called = 1; }
+void ptr(const C*) { called = 2; }
+
+void ref(C) { called = 1; }
+void ref(const C) { called = 2; }
+
+void 
+fwd_lvalue_ref(Type x) {
+  using T = decltype(x);
+  static_assert(std::is_lvalue_referenceT::value, not an lvlaue reference);
+}
+
+void 
+fwd_const_lvalue_ref(Type x) {
+  using T = decltype(x);
+  static_assert(std::is_lvalue_referenceT::value, not an lvalue reference);
+  using U = typename std::remove_referenceT::type;
+  static_assert(std::is_constU::value, not const-qualified);
+}
+
+void fwd_rvalue_ref(Type x) {
+  using T = decltype(x);
+  static_assert(std::is_rvalue_referenceT::value, not an rvalue reference);
+}
+
+// Make sure we can use nested names speicifers for concept names.
+namespace N {
+  templatetypename T
+concept bool C() { return true; }
+} // namesspace N
+
+void foo(N::C x) { }
+
 int main() {
+  S s;
+  const S cs;
+
   f(0); assert(called == 1);
   g(s); assert(called == 2);
 
@@ -60,7 +101,6 @@ int main() {
   S1 s1;
   s1.f1(0); assert(called == 1);
   s1.f2(s); assert(called == 2);
-  // s1.f2(0); // Error
 
   s1.f3(0); assert(called == 1);
   s1.f3(s); assert(called == 2);
@@ -68,26 +108,35 @@ int main() {
   S2S s2;
   s2.f1(0); assert(called == 1);
   s2.f2(s); assert(called == 2);
-  // s2.f2(0); // Error
 
   s2.f3(0); assert(called == 1);
   s2.f3(s); assert(called == 2);
 
   s2.h1(0); assert(called == 1);
   s2.h2(s); assert(called == 2);
-  // s2.h2(0); // Error
 
   s2.h3(0); assert(called == 1);
   s2.h3(s); assert(called == 2);
 
   s2.g1(s, s); assert(called == 1); 
-  // s2.g(s, 0); // Error
-  // s2.g(0, s); // Error
-
   s2.g2(s, s); assert(called == 2);
-  // s2.g(s, 0); // Error
+
+  ptr(s); assert(called == 1);
+  ptr(cs); assert(called == 2);
+
+  ref(s); assert(called == 1);
+  ref(cs); assert(called == 2);
+
+  // Check forwarding problems
+  fwd_lvalue_ref(s);
+  fwd_const_lvalue_ref(cs);
+  fwd_rvalue_ref(S());
+
+  foo(0);
 }
 
+// Test that decl/def matching works.
+
 void p(auto x) { called = 1; }
 void p(C x) { called = 2; }
 
Index: generic-fn-err.C
===
--- generic-fn-err.C	(revision 0)
+++ generic-fn-err.C	(revision 0)
@@ -0,0 +1,51 @@
+// { dg-options -std=c++1y }
+
+#include cassert
+
+templatetypename T
+  concept bool C() { return __is_class(T); }
+
+templateint N
+  concept bool Int

partial-concept-ids

2014-06-12 Thread Andrew Sutton
Add support for partial concept ids. Mostly this just refactors the
basic support for concept names to also allow a template and extra
arguments.

Also added the missing .exp file for the test suite.

2014-06-12  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/constraint.cc (deduce_constrained_parameter): Refactor
common deduction framework into separate function.
(build_call_check): New.
(build_concept_check): Take additional arguments to support the
creation of constrained-type-specifiers from partial-concept-ids.
(build_constrained_parameter): Take arguments from a partial-concept-id.
* gcc/cp/cp-tree.h (build_concept_check, biuld_constrained_parameter):
Take a template argument list, defaulting to NULL_TREE.
* gcc/cp/parser.c (cp_parser_template_id): Check to see if a
template-id is a concept check.
(cp_check_type_concept): Reorder arguments
(cp_parser_allows_constrained_type_specifier): New. Check contexts
where a constrained-type-specifier is allowed.
(cp_maybe_constrained_type_specifier): New. Refactored common rules
for concept name checks.
(cp_maybe_partial_concept_id): New. Check for
constrained-type-specifiers.
* gcc/testuite/g++.dg/concepts/partial.C: New tests.
* gcc/testuite/g++.dg/concepts/partial-err.C: New tests.
* gcc/testuite/g++.dg/concepts/concepts.exp: Add missing test driver.

Andrew Sutton
Index: parser.c
===
--- parser.c	(revision 211585)
+++ parser.c	(working copy)
@@ -2523,7 +2523,10 @@ static tree cp_parser_make_typename_type
 static cp_declarator * cp_parser_make_indirect_declarator
  (enum tree_code, tree, cp_cv_quals, cp_declarator *, tree);
 
+/* Concept-related syntactic transformations */
 
+static tree cp_maybe_concept_name   (cp_parser *, tree);
+static tree cp_maybe_partial_concept_id (cp_parser *, tree, tree);
 
 // -- //
 // Unevaluated Operand Guard
@@ -13775,6 +13778,11 @@ cp_parser_template_id (cp_parser *parser
 		   || TREE_CODE (templ) == OVERLOAD
 		   || BASELINK_P (templ)));
 
+  // If the template + args designate a concept, then return
+  // something else.
+  if (tree id = cp_maybe_partial_concept_id (parser, templ, arguments))
+return id;
+
   template_id = lookup_template_function (templ, arguments);
 }
 
@@ -14995,7 +15003,8 @@ cp_parser_simple_type_specifier (cp_pars
 	}
   /* Otherwise, look for a type-name.  */
   else
-	type = cp_parser_type_name (parser);
+type = cp_parser_type_name (parser);
+  
   /* Keep track of all name-lookups performed in class scopes.  */
   if (type
 	   !global_p
@@ -15071,6 +15080,7 @@ cp_parser_simple_type_specifier (cp_pars

type-name:
  concept-name
+ partial-concept-id
 
concept-name:
  identifier
@@ -15092,6 +15102,7 @@ cp_parser_type_name (cp_parser* parser)
 /*check_dependency_p=*/true,
 /*class_head_p=*/false,
 /*is_declaration=*/false);
+
   /* If it's not a class-name, keep looking.  */
   if (!cp_parser_parse_definitely (parser))
 {
@@ -15107,6 +15118,7 @@ cp_parser_type_name (cp_parser* parser)
 	 /*check_dependency_p=*/true,
 	 none_type,
 	 /*is_declaration=*/false);
+
   /* Note that this must be an instantiation of an alias template
 	 because [temp.names]/6 says:
 	 
@@ -15135,7 +15147,7 @@ cp_parser_type_name (cp_parser* parser)
 /// Returns true if proto is a type parameter, but not a template template
 /// parameter.
 static bool
-cp_check_type_concept (tree proto, tree fn) 
+cp_check_type_concept (tree fn, tree proto) 
 {
   if (TREE_CODE (proto) != TYPE_DECL) 
 {
@@ -15145,57 +15157,58 @@ cp_check_type_concept (tree proto, tree
   return true;
 }
 
-// If DECL refers to a concept, return a TYPE_DECL representing the result
-// of using the constrained type specifier in the current context. 
-//
-// DECL refers to a concept if
-//   - it is an overload set containing a function concept taking a single
-// type argument, or
-//   - it is a variable concept taking a single type argument
-//
-//
-// TODO: DECL could be a variable concept.
+/// Returns true if the parser is in a context that allows the
+/// use of a constrained type specifier.
+static inline bool
+cp_parser_allows_constrained_type_specifier (cp_parser *parser)
+{
+  return flag_concepts 
+ (processing_template_parmlist
+|| parser-auto_is_implicit_function_template_parm_p
+|| 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
+// is NULL, then we try to form a concept check

[c++-concepts] Terse notation

2014-06-11 Thread Andrew Sutton
Sorry if you receive multiple versions of this. The original message
bounced (formatting).

Attached is a patch that greatly improves terse notation support for
generic functions and the use of concept names in
constrained-type-specifiers. There are actually 2 patches. The second
includes unit tests. Mostly, this is just cleaning up a previous
(hacky) commit. Most of the work is done in the parser, since terse
notation is largely syntactic.

Generic functions can be declared with auto and concept names in
namespace and class scope. Definitions can be matched to declarations,
and overloading is supported.

Various restrictions are put in place to prevent things like this:

  templateconst C // C constrains a type argument!

That holds when C constrains a template template argument also.

The patch also includes the initial parsing and semantic hooks for
handling constrained-type-specifiers in compound requirements:

  {expr} - const auto; // unnamed result type must form a valid type
  {expr} - C; // unnamed result type satisfies the concept C

Semantics will come later.

Changelog:

2014-06-11  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/cp-tree.h (build_constrained_parameter): Renamed fro
describe_tempalte_parm.
* gcc/cp/parser.c (cp_check_constrained_type_parm): New. Prevent
declaration of cv-qualifed or non-id types.
(cp_constrained_type_template_parm): Renamed, check for invalid
specifiers.
(cp_constrained_template_template_parm): Renamed, check for invalid
specifiers.
(cp_constrained_non_type_tmeplate_parm): Renamed.
(cp_finish_constrained-parameter): Support checking of decarlarations.
(cp_check_concept_name): Renamed. Add initial support for auto
and constrained-type-specifiers in compound requirements.
(cp_parser_nonclass_name): Only check for concept names if -fconcepts
is on.
(cp_manage_requirements): New RAII guard for managinging the
current_template_reqs variable during declaration parsing.
(cp_paresr_trailing_requirements): Refactored common parsing
requirements from cp_parser_init_declarator and
cp_parser_member_declarator. Take terse constraints from implicit
parameter declarations.
(cp_parser_init_declarator): Cleanup, refactor requirement logic.
(cp_parser_type_id_1): Allow auto in compound requirements.
(cp_parser_member_declaration): Cleanup, refactor requirement logic.
(cp_parser_compound_requirement): Note parsing state for the
trailing-type-id so we can get auto and constrained-type-specifiers.
(cp_parser_function_definition_after_decl): Remove broken constraint
association.
* gcc/cp/parser.h (cp_parser): New member.
* gcc/cp/constraint.cc (finish_validtype_expr): Initial (non-)handling
of auto in type requirements.
(finish_concept_name): Moved to cp_check_concept_name.
* gcc/testuite/g++.dg/concepts/constrained-parm.C: New test.
* gcc/testuite/g++.dg/concepts/generic-fn.C: New test.

Andrew Sutton
Index: constrained-parm.C
===
--- constrained-parm.C	(revision 0)
+++ constrained-parm.C	(revision 0)
@@ -0,0 +1,13 @@
+// { dg-options -std=c++1y }
+
+templatetypename T
+  concept bool C() { return __is_class(T); }
+
+templateconst C T struct S1 { };// { dg-error cv-qualified }
+templatevolatile C T struct S2 { }; // { dg-error cv-qualified }
+templateC* T struct S3 { }; // { dg-error invalid }
+templateC const* T struct S3a { };  // { dg-error invalid }
+templateC* const T struct S3b { };  // { dg-error invalid }
+templateC T struct S4 { }; // { dg-error invalid }
+templateC[3] T struct S4 { };   // { dg-error invalid|expected } 
+templateC(*T)() struct S5 { };  // { dg-error invalid }
Index: generic-fn.C
===
--- generic-fn.C	(revision 0)
+++ generic-fn.C	(revision 0)
@@ -0,0 +1,108 @@
+// { dg-options -std=c++1y }
+
+#include cassert
+
+templatetypename T
+  concept bool C() { return __is_class(T); }
+
+struct S { } s;
+
+int called;
+
+// Basic terse notation
+void f(auto x) { called = 1; }
+void g(C x) { called = 2; }
+
+// Overloading generic functions
+void h(auto x) { called = 1; }
+void h(C x) { called = 2; }
+
+void p(auto x);
+void p(C x);
+
+struct S1 {
+  void f1(auto x) { called = 1; }
+  void f2(C x) { called = 2; }
+
+  void f3(auto x) { called = 1; }
+  void f3(C x) { called = 2; }
+};
+
+templateC T
+  struct S2 {
+void f1(auto x) { called = 1; }
+void f2(C x) { called = 2; }
+
+void f3(auto x) { called = 1; }
+void f3(C x) { called = 2; }
+
+void h1(auto x);
+void h2(C x);
+
+void h3(auto x);
+void h3(C x);
+
+templateC U
+  void g1(T t, U u) { called = 1; }
+
+templateC U
+  void g2(T t, U u

Re: [PATCH] [C++ RFC] Support named type capture for generic lambdas and generic functions as proposed by N3878

2014-03-25 Thread Andrew Sutton
It's not clear that this feature will be part of concepts. It will not
be included in the initial working paper, so the proposal will need to
be re-evaluated.

Andrew


On Tue, Mar 25, 2014 at 3:03 AM, Adam Butcher a...@jessamine.co.uk wrote:
 * parser.c (cp_parser_simple_type_specifier): Lookahead for a braced
 identifier after a generic type ('auto') parameter and, if present, 
 use
 that as the type identifier name.  Otherwise generate one with
 make_generic_type_name.  Pass the resulting identifier as the new 
 second
 parameter ...
 (synthesize_implicit_template_parm): ... here.  Synthesize the 
 template
 type parm with the provided name rather than generating one.

 * g++.dg/cpp1y/generic-fn-typeid.C: New testcase.
 ---
  gcc/cp/parser.c| 55 
 +-
  gcc/testsuite/g++.dg/cpp1y/generic-fn-typeid.C | 42 
  2 files changed, 88 insertions(+), 9 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/generic-fn-typeid.C

 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
 index 49fb731..4d6f8fe 100644
 --- a/gcc/cp/parser.c
 +++ b/gcc/cp/parser.c
 @@ -2128,8 +2128,10 @@ static tree cp_parser_late_parsing_omp_declare_simd
  static tree cp_parser_late_parsing_cilk_simd_fn_info
(cp_parser *, tree);

 +static tree make_generic_type_name
 +  ();
  static tree synthesize_implicit_template_parm
 -  (cp_parser *);
 +  (cp_parser *, tree);
  static tree finish_fully_implicit_template
(cp_parser *, tree);

 @@ -14530,23 +14532,58 @@ cp_parser_simple_type_specifier (cp_parser* parser,
maybe_warn_cpp0x (CPP0X_AUTO);
if (parser-auto_is_implicit_function_template_parm_p)
 {
 - type = synthesize_implicit_template_parm (parser);
 + /* Synthesize an implicit template parameter named as specified by
 +the IDENTIFIER_NODE of a braced identifier (as proposed by 
 section
 +2.2 of N3878).  If no braced identifier is present then a name is
 +generated a via make_generic_type_name.  */
 +
 + if (cp_lexer_peek_nth_token
 + (parser-lexer, 2)-type == CPP_OPEN_BRACE)
 +   {
 + /* The 'auto' has only been peeked and is expected to be 
 consumed
 +later; parse the braced identifier leaving the closing brace 
 as
 +the next token.  */
 +
 + cp_lexer_consume_token (parser-lexer); /* RID_AUTO */
 + cp_lexer_consume_token (parser-lexer); /* CPP_OPEN_BRACE */
 +
 + tree synth_id = cp_parser_identifier (parser);
 + if (synth_id != error_mark_node)
 +   type = synthesize_implicit_template_parm (parser, synth_id);
 +
 + if (cp_parser_require
 + (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE) == 0
 + || synth_id == error_mark_node)
 +   {
 + error_at (input_location,
 +expected braced identifier for generic type capture);
 + return error_mark_node;
 +   }
 +
 + /* Roll-back one token to allow for consume below.  */
 + cp_lexer_set_token_position (parser-lexer,
 +  cp_lexer_previous_token_position
 +  (parser-lexer));
 +   }
 + else
 +   type = synthesize_implicit_template_parm
 + (parser, make_generic_type_name ());

   if (current_class_type  LAMBDA_TYPE_P (current_class_type))
 {
   if (cxx_dialect  cxx1y)
 -   pedwarn (location_of (type), 0,
 +   pedwarn (token-location, 0,
  use of %auto% in lambda parameter declaration 
  only available with 
  -std=c++1y or -std=gnu++1y);
 }
   else if (cxx_dialect  cxx1y)
 -   pedwarn (location_of (type), 0,
 +   pedwarn (token-location, 0,
  use of %auto% in parameter declaration 
  only available with 
  -std=c++1y or -std=gnu++1y);
   else
 -   pedwarn (location_of (type), OPT_Wpedantic,
 +   pedwarn (token-location, OPT_Wpedantic,
  ISO C++ forbids use of %auto% in parameter 
  declaration);
 }
 @@ -31957,11 +31994,12 @@ tree_type_is_auto_or_concept (const_tree t)
  }

  /* Add an implicit template type parameter to the CURRENT_TEMPLATE_PARMS
 -   (creating a new template parameter list if necessary).  Returns the newly
 -   created template type parm.  */
 +   (creating a new template parameter list if necessary).  The template type
 +   parameter is given the id SYNTH_ID.  Returns the newly created template 
 type
 +   parm.  */

  tree
 -synthesize_implicit_template_parm  (cp_parser *parser)
 

Fwd: [c++-concepts] Shorthand notation

2014-03-06 Thread Andrew Sutton
I'm resending this patch for constrained template parameters for
review. It's been languishing for a while without review and it has
some interesting features in the implementation (namely, resolution
mechanism or constrained template parameters).

Andrew

-- Forwarded message --
From: Andrew Sutton andrew.n.sut...@gmail.com
Date: Wed, Oct 16, 2013 at 9:59 AM
Subject: [c++-concepts] Shorthand notation
To: gcc-patches@gcc.gnu.org, Jason Merrill ja...@redhat.com


I've committed initial support for shorthand constraints. This patch
adds support for parsing a concept-names as non-class names. When
introducing a template parameter, the concept name is transformed into
a constraint on the template parameter. Constrained parameters can
introduce type, non-type and template template parameters.

This has initial support for variadic constraints, but it's not well tested.

This patch does not yet support default arguments for constrained
template parameters, nor does it support the use of concept ids of
this form:

  templatetypename T, FunctionT F
void f();

There are a couple of interesting things in the patch. I'm using a
PLACEHOLDER_EXPR as a template argument in order to resolve constraint
names. Effectively, I deduce concepts by creating an expression like:

  Equality_comparable?()

where ? is a placeholder, and after coerce_template_arguments
completes, I can extract the matched parameter from the placeholder.
This works nicely when concepts are overloaded or have default
arguments (although I'm not sure I'm testing that very thoroughly
right now).

With variadic constraints, I've had to add functionality to expand a
pack as a conjunction of requirements. For example, if you declare:

  templateClass... Ts // ClassT() must be true for each T in Ts
void f();

The transformation is:

  templatetypename... Ts
requires ClassTs()...
  void f();

Where ClassTs()... expands to ClassT1()  ClassT2()  ... etc.
I feel like the current implementation is a bit hacky, and I'm
wondering if I should introduce a new node for a pack conjunction.

Change log follows.

2013-10-16  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/constraint.cc (conjoin_requiremens): New.
(resolve_constraint_check): Filter non-concept candidates before
coercing arguments. Perform deduction in a template-decl processing
context to prevent errors during diagnosis.
(finish_concept_name), (finish_shorthand_requirement),
(get_shorthand_requirements): New.
* gcc/cp/pt.c (template_parm_to_arg): Make non-static.
(process_templat_parm): Build shorthand requirements from the
parameter description.
(end_templat_parm_list): New.
(convert_placeholder_argument): New.
(convert_template_argument): Match placeholder arguments against
any template parameter.
(tsubst_pack_conjuction):  New.
(tsubst_expr): Expand a pack as a conjunction.
(type_dependent_expression_p): Placeholders are always type
dependent.
* gcc/cp/parser.c (cp_is_constrained_parameter),
(cp_finish_template_type_parm), (cp_finish_template_template_parm)
(cp_finish_non_type_template_parm), (cp_finish_constrined_parameter):
New.
(cp_parser_template_parameter): Handle constrained parameters.
(cp_parser_nonclass_name): An identifier naming an overload set
may declare a constrained parameter.
(cp_parser_type_parameter), (cp_parser_template_declaration_after_exp):
Get shorthand requirements from the tmeplate parameter list.
* gcc/cp/cp-tree.h (TEMPLATE_PARM_CONSTRAINTS): New.

Committed in 203704.

Andrew Sutton


[c++-concepts] Constrained scope bugfix

2013-10-30 Thread Andrew Sutton
Partially fixing a bug that caused lookup errors in valid programs. For example:

templateInt T, Float U
  pairT, U::type void f(T, U); // Error, no such pair

When entering a template scope, we tried to match the template to one
having the same constraints. Obviously pair doesn't have Int and Float
constraints, and it probably doesn't have a partial specialization
with those constraints either.

I relaxed the fixup_template_type function so that it would just
return the looked-up type without emitting a diagnostic. This fix
makes the following a legal, however:

templatetypename T
  struct S { void f(); }

templateInt T
  void ST::f() { } // Should be an error

The right solution seems to be to diagnose the error only when
defining an out-of-class member by verifying that each template scope
in the qualified name matches a declaration with the same constraints.

2013-10-30  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/semantics.c (fixup_template_type): Don't emit errors when
no templates can be found with matching constraints.
Index: gcc/cp/semantics.c
===
--- gcc/cp/semantics.c	(revision 203626)
+++ gcc/cp/semantics.c	(working copy)
@@ -2847,8 +2847,35 @@ finish_template_decl (tree parms)
 
 // Returns the template type of the class scope being entered. If we're
 // entering a constrained class scope. TYPE is the class template
-// scope being entered. If TYPE is not a class-type (e.g. a typename type),
-// then no fixup is needed.
+// scope being entered and we may need to match the intended type with
+// a constrained specialization. For example:
+//
+//templateObject T
+//  struct S { void f(); }; #1
+//
+//templateObject T
+//  void ST::f() { }  #2
+//
+// We check, in #2, that ST refers precisely to the type declared by
+// #1 (i.e., that the constraints match). Note that the following should
+// be an error since there is no specialization of ST that is 
+// unconstrained, but this is not diagnosed here.
+//
+//templatetypename T
+//  void ST::f() { }
+//
+// We cannot diagnose this problem here since this function also matches
+// qualified template names that are not part of a definition. For example:
+//
+//templateIntegral T, Floating_point U
+//  typename pairT, U::first_type void f(T, U);
+//
+// Here, it is unlikely that there is a partial specialization of
+// pair constrained for for Integral and Floating_point arguments.
+//
+// The general rule is: if a constrained specialization with matching
+// constraints is found return that type. Alos note that if TYPE is not a 
+// class-type (e.g. a typename type), then no fixup is needed.
 static tree
 fixup_template_type (tree type)
 {
@@ -2866,14 +2893,8 @@ fixup_template_type (tree type)
 return type;
   tree cur_constr = TEMPLATE_PARMS_CONSTRAINTS (parms);
 
-  // Do the constraints match those of the most general template? 
-  // If the constraints are NULL_TREE, this will match the most general
-  // template iff it is unconstrained.
+  // Search for a specialization whose constraints match.
   tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
-  if (equivalent_constraints (cur_constr, DECL_CONSTRAINTS (tmpl)))
-return type;
-
-  // Can we find a specialization that matches?
   tree specs = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
   while (specs)
 {
@@ -2883,10 +2904,8 @@ fixup_template_type (tree type)
   specs = TREE_CHAIN (specs);
 }
 
-  // Emit an error, but return the type to allow processing to continue.
-  // TODO: We should emit candidates since we've just scanned the 
-  // list of template constraints.
-  error (type %qT does not match any declarations, type);
+  // If no specialization matches, then must return the type
+  // previously found.
   return type;
 }
 
@@ -2904,7 +2923,7 @@ finish_template_type (tree name, tree ar
   type = lookup_template_class (name, args,
 NULL_TREE, NULL_TREE, entering_scope,
 tf_warning_or_error | tf_user);
-  
+
   // If entering a scope, correct the lookup to account for constraints.
   if (entering_scope)
 type = fixup_template_type (type);


[c++-concepts] Diagnostics patch

2013-10-30 Thread Andrew Sutton
Applying a patch from Ville that adds diagnostics for the concept
specifier. Thanks Ville!

2013-10-30  Ville Voutilainen  ville.voutilai...@gmail.com
* gcc/cp/decl.c (grokdeclarator): Reject concept keyword
in typedefs, function parameters, data members, non-static
member functions and variables. Allow static member functions
to be concepts.

Andrew Sutton
Index: gcc/cp/decl.c
===
--- gcc/cp/decl.c	(revision 204092)
+++ gcc/cp/decl.c	(working copy)
@@ -9074,6 +9074,12 @@
   if (name == NULL)
 name = decl_context == PARM ? parameter : type name;
 
+  if (concept_p  typedef_p)
+{
+  error (%concept% cannot appear in a typedef declaration);
+  return error_mark_node;
+}
+
   if (constexpr_p  typedef_p)
 {
   error (%constexpr% cannot appear in a typedef declaration);
@@ -9387,9 +9393,12 @@
 	   || thread_p)
 	error (storage class specifiers invalid in parameter declarations);
 
+  /* Function parameters cannot be concept. */
+  if (concept_p)
+  error (a parameter cannot be declared %concept%);
   /* Function parameters cannot be constexpr.  If we saw one, moan
  and pretend it wasn't there.  */
-  if (constexpr_p)
+  else if (constexpr_p)
 {
   error (a parameter cannot be declared %constexpr%);
   constexpr_p = 0;
@@ -10619,6 +10628,11 @@
 			   uqname, ctype);
 		return error_mark_node;
 		  }
+if (concept_p)
+  {
+error (a destructor cannot be %concept%);
+return error_mark_node;
+  }
 if (constexpr_p)
   {
 error (a destructor cannot be %constexpr%);
@@ -10632,6 +10646,12 @@
 		   id_declarator-u.id.unqualified_name);
 		return error_mark_node;
 	  }
+	if (sfk == sfk_constructor)
+if (concept_p)
+  {
+error (a constructor cannot be %concept%);
+return error_mark_node;
+  }
 
 	/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node.  */
 	function_context = (ctype != NULL_TREE) ?
@@ -10645,7 +10665,7 @@
 			   unqualified_id,
 			   virtualp, flags, memfn_quals, rqual, raises,
 			   friendp ? -1 : 0, friendp, publicp,
-   inlinep | (2 * constexpr_p),
+   inlinep | (2 * constexpr_p) | (4 * concept_p),
 			   sfk,
 			   funcdef_flag, template_count, in_namespace,
 			   attrlist, declarator-id_loc);
@@ -10739,8 +10759,12 @@
 		if (declspecs-gnu_thread_keyword_p)
 		  DECL_GNU_TLS_P (decl) = true;
 		  }
-
-		if (constexpr_p  !initialized)
+		if (concept_p)
+		  // TODO: This needs to be revisited once variable
+		  // templates are supported
+		error (static data member %qE declared %concept%,
+			   unqualified_id);
+		else if (constexpr_p  !initialized)
 		  {
 		error (constexpr static data member %qD must have an 
 			   initializer, decl);
@@ -10749,7 +10773,10 @@
 	  }
 	else
 	  {
-if (constexpr_p)
+		if (concept_p)
+		  error (non-static data member %qE declared %concept%,
+			 unqualified_id);
+else if (constexpr_p)
 		  {
 		error (non-static data member %qE declared %constexpr%,
 			   unqualified_id);
@@ -10897,6 +10924,15 @@
   {
 	/* It's a variable.  */
 
+	// TODO: This needs to be revisited once variable
+	// templates are supported
+	if (concept_p)
+	  {
+	error (variable %qE declared %concept%,
+		   unqualified_id);
+	return error_mark_node;
+	  }
+	
 	/* An uninitialized decl with `extern' is a reference.  */
 	decl = grokvardecl (type, unqualified_id,
 			declspecs,
Index: gcc/testsuite/g++.dg/concepts/decl-diagnose.C
===
--- gcc/testsuite/g++.dg/concepts/decl-diagnose.C	(revision 0)
+++ gcc/testsuite/g++.dg/concepts/decl-diagnose.C	(working copy)
@@ -0,0 +1,20 @@
+// { dg-options -std=c++11 }
+typedef concept int CINT; // { dg-error 'concept' cannot appear in a typedef declaration }
+
+void f(concept int); // { dg-error a parameter cannot be declared 'concept' }
+
+concept int f2(); // { dg-error result must be bool }
+concept bool f3();
+
+struct X
+{
+  concept int f4(); // { dg-error result must be bool|declared with function parameters }
+  concept bool f5(); // { dg-error declared with function parameters }
+  static concept bool f6();
+  static concept bool x; // { dg-error declared 'concept' }
+  concept int x2; // { dg-error declared 'concept' }
+  concept ~X(); // { dg-error a destructor cannot be 'concept' }
+  concept X(); // { dg-error a constructor cannot be 'concept' }
+};
+
+concept bool X2; // { dg-error declared 'concept' }


[c++-concepts] Requires expr in non-templte

2013-10-25 Thread Andrew Sutton
This patch prevents the use of requires expressions in non-template
scopes. This restriction was relaxed in the most recent version of
concepts lite, but the implementation requires some thought. For now,
I am marking it an error to make it consistent with previous versions
of the spec.

2013-10-25  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/parsre.c (cp_parser_requires_expression): Gracefully
fail when parsing a requires expr outside a template.

Andrew Sutton


template-requires.patch
Description: Binary data


Re: [c++-concepts] small tidbits to get it to build

2013-10-24 Thread Andrew Sutton
Hi Ed,

I committed half of your patch (the unused variable part) in r204011
and removed the unused keywords as a resolution for the other half in
r204012.

Changelog/patch follow:

2013-10-24  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/c-common.c (c_common_r): Remove unused keywords assume,
axiom, and forall.
* gcc/cp/c-common.h (rid): Removed unused reserved word ids.

Andrew


On Wed, Oct 23, 2013 at 8:05 PM, Ed Smith-Rowland 3dw...@verizon.net wrote:
 On 10/23/2013 08:36 AM, Andrew Sutton wrote:

 Hi Ed,

 It looks like we did reserve assume as a keyword, but it's not being
 used... By any chance, did you configure without --disable-bootstrap?

 I think it would be a better solution to remove the unused keywords --
 there were a couple of others that we grabbed for some other
 concepts-related work, but which aren't included in Concepts Lite.

 I'll apply the typeck fix.

 Andrew Sutton


 On Tue, Oct 22, 2013 at 10:02 PM, Ed Smith-Rowland 3dw...@verizon.net
 wrote:

 I had to get past two small bugs to get c++-concepts to build.
 Take a good look because I'm not sure if they're right.  The solutions
 should be harmless though.

 Ed

 I did this:
 $ ../gcc_concepts/configure --prefix=/home/ed/bin_concepts
 --enable-languages=c,c++,lto

 This is pretty base bones - no special treatment configure and the branch
 worked pretty well.

 Ed



keyword.patch
Description: Binary data


Re: [c++-concepts] small tidbits to get it to build

2013-10-23 Thread Andrew Sutton
Hi Ed,

It looks like we did reserve assume as a keyword, but it's not being
used... By any chance, did you configure without --disable-bootstrap?

I think it would be a better solution to remove the unused keywords --
there were a couple of others that we grabbed for some other
concepts-related work, but which aren't included in Concepts Lite.

I'll apply the typeck fix.

Andrew Sutton


On Tue, Oct 22, 2013 at 10:02 PM, Ed Smith-Rowland 3dw...@verizon.net wrote:
 I had to get past two small bugs to get c++-concepts to build.
 Take a good look because I'm not sure if they're right.  The solutions
 should be harmless though.

 Ed



[c++-concepts] Specialization of concepts

2013-10-23 Thread Andrew Sutton
This patch disallows the explicit specialization of concepts, as
required by the specification. It also fixes an ICE when comparing
overloads of non-template members.

2013-10-23  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/class.c (get_member_fntemplate): New.
(are_constrained_member_overloads): Only get a template declaration
if the member function is, in fact, a template or temploid.
* gcc/cp/pt.c (check_explicit_specialization): Do not allow
explicit specializations to be declared 'concept', and do not allow
an explicit specialization of a concept.
* gcc/cp/decl.c (grokfndecl): Propagate the concept flag to
check_explicit_specialization.

Committed in r203970.

Andrew


bugfix-3.patch
Description: Binary data


[c++-concepts] bitfield reference bugfix

2013-10-22 Thread Andrew Sutton
This fixes the longstanding problem with bitfield references. The
default dialect was set to cxx1y, which was resulting different
conversions for bitfield references. I'm not sure if there's a change
in semantics for 1y or if that's a separate bug, but it's not related
to concepts.

Also prevent an ICE for invalid constrained friends.

2013-10-16  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/c-family/c-common.c (cxx_dialect): Make the default
language C++11.
* gcc/cp/constraint.cc (check_constrained_friend): Don't assert
on error_mark_node.

Andrew


bugfix-2.patch
Description: Binary data


Re: [c++-concepts] Shorthand notation

2013-10-18 Thread Andrew Sutton
A small follow up change. This removes the sorry from concept name
resolution. Committed in r203815.

2013-10-16  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/constraint.cc (finish_concept_name): Allow functions with
the same name as concepts to resolve as call expressions in the
usual way.

Andrew Sutton


On Wed, Oct 16, 2013 at 9:59 AM, Andrew Sutton
andrew.n.sut...@gmail.com wrote:
 I've committed initial support for shorthand constraints. This patch
 adds support for parsing a concept-names as non-class names. When
 introducing a template parameter, the concept name is transformed into
 a constraint on the template parameter. Constrained parameters can
 introduce type, non-type and template template parameters.

 This has initial support for variadic constraints, but it's not well tested.

 This patch does not yet support default arguments for constrained
 template parameters, nor does it support the use of concept ids of
 this form:

   templatetypename T, FunctionT F
 void f();

 There are a couple of interesting things in the patch. I'm using a
 PLACEHOLDER_EXPR as a template argument in order to resolve constraint
 names. Effectively, I deduce concepts by creating an expression like:

   Equality_comparable?()

 where ? is a placeholder, and after coerce_template_arguments
 completes, I can extract the matched parameter from the placeholder.
 This works nicely when concepts are overloaded or have default
 arguments (although I'm not sure I'm testing that very thoroughly
 right now).

 With variadic constraints, I've had to add functionality to expand a
 pack as a conjunction of requirements. For example, if you declare:

   templateClass... Ts // ClassT() must be true for each T in Ts
 void f();

 The transformation is:

   templatetypename... Ts
 requires ClassTs()...
   void f();

 Where ClassTs()... expands to ClassT1()  ClassT2()  ... etc.
 I feel like the current implementation is a bit hacky, and I'm
 wondering if I should introduce a new node for a pack conjunction.

 Change log follows.

 2013-10-16  Andrew Sutton  andrew.n.sut...@gmail.com
 * gcc/cp/constraint.cc (conjoin_requiremens): New.
 (resolve_constraint_check): Filter non-concept candidates before
 coercing arguments. Perform deduction in a template-decl processing
 context to prevent errors during diagnosis.
 (finish_concept_name), (finish_shorthand_requirement),
 (get_shorthand_requirements): New.
 * gcc/cp/pt.c (template_parm_to_arg): Make non-static.
 (process_templat_parm): Build shorthand requirements from the
 parameter description.
 (end_templat_parm_list): New.
 (convert_placeholder_argument): New.
 (convert_template_argument): Match placeholder arguments against
 any template parameter.
 (tsubst_pack_conjuction):  New.
 (tsubst_expr): Expand a pack as a conjunction.
 (type_dependent_expression_p): Placeholders are always type
 dependent.
 * gcc/cp/parser.c (cp_is_constrained_parameter),
 (cp_finish_template_type_parm), (cp_finish_template_template_parm)
 (cp_finish_non_type_template_parm), (cp_finish_constrined_parameter):
 New.
 (cp_parser_template_parameter): Handle constrained parameters.
 (cp_parser_nonclass_name): An identifier naming an overload set
 may declare a constrained parameter.
 (cp_parser_type_parameter), 
 (cp_parser_template_declaration_after_exp):
 Get shorthand requirements from the tmeplate parameter list.
 * gcc/cp/cp-tree.h (TEMPLATE_PARM_CONSTRAINTS): New.

 Committed in 203704.

 Andrew Sutton


short-2.patch
Description: Binary data


Re: [c++-concepts] Shorthand notation

2013-10-18 Thread Andrew Sutton
I know. When I started working on the project, Gaby asked that I keep
all concept-related changes in the top-level Changelog.concepts with
full paths for the file names.

Andrew Sutton


On Fri, Oct 18, 2013 at 8:53 AM, Paolo Carlini paolo.carl...@oracle.com wrote:
 Hi,


 On 10/18/2013 02:23 PM, Andrew Sutton wrote:

 A small follow up change. This removes the sorry from concept name
 resolution. Committed in r203815.

 2013-10-16  Andrew Sutton  andrew.n.sut...@gmail.com
  * gcc/cp/constraint.cc (finish_concept_name): Allow functions
 with
  the same name as concepts to resolve as call expressions in the
  usual way.

 Nit: normally this would be just * constraint.cc, because the paths are
 relative to the location of the corresponding ChangeLog file (which is under
 gcc/cp)

 Thanks!
 Paolo.


[c++-concepts] Bugfix

2013-10-18 Thread Andrew Sutton
Fixing 2 issues. A test for __is_convertible_to was missing in
diagnose_trait, and *somehow* the logic for determining constraint
ordering w.r.t. requires expressions was missing.

Committed in 203826.

2013-10-16  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/logic.cc (left_requires), (decompose_left): Add
decomposition rules for requires expressions.
(subsumes_requires), (subsumes_prop): Add subsumption rules for
requires expressions.
* gcc/cp/constraint.cc (diagnose_trait): Diagnose failed conversion
requirements.

Andrew


[c++-concepts] Shorthand notation

2013-10-16 Thread Andrew Sutton
I've committed initial support for shorthand constraints. This patch
adds support for parsing a concept-names as non-class names. When
introducing a template parameter, the concept name is transformed into
a constraint on the template parameter. Constrained parameters can
introduce type, non-type and template template parameters.

This has initial support for variadic constraints, but it's not well tested.

This patch does not yet support default arguments for constrained
template parameters, nor does it support the use of concept ids of
this form:

  templatetypename T, FunctionT F
void f();

There are a couple of interesting things in the patch. I'm using a
PLACEHOLDER_EXPR as a template argument in order to resolve constraint
names. Effectively, I deduce concepts by creating an expression like:

  Equality_comparable?()

where ? is a placeholder, and after coerce_template_arguments
completes, I can extract the matched parameter from the placeholder.
This works nicely when concepts are overloaded or have default
arguments (although I'm not sure I'm testing that very thoroughly
right now).

With variadic constraints, I've had to add functionality to expand a
pack as a conjunction of requirements. For example, if you declare:

  templateClass... Ts // ClassT() must be true for each T in Ts
void f();

The transformation is:

  templatetypename... Ts
requires ClassTs()...
  void f();

Where ClassTs()... expands to ClassT1()  ClassT2()  ... etc.
I feel like the current implementation is a bit hacky, and I'm
wondering if I should introduce a new node for a pack conjunction.

Change log follows.

2013-10-16  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/constraint.cc (conjoin_requiremens): New.
(resolve_constraint_check): Filter non-concept candidates before
coercing arguments. Perform deduction in a template-decl processing
context to prevent errors during diagnosis.
(finish_concept_name), (finish_shorthand_requirement),
(get_shorthand_requirements): New.
* gcc/cp/pt.c (template_parm_to_arg): Make non-static.
(process_templat_parm): Build shorthand requirements from the
parameter description.
(end_templat_parm_list): New.
(convert_placeholder_argument): New.
(convert_template_argument): Match placeholder arguments against
any template parameter.
(tsubst_pack_conjuction):  New.
(tsubst_expr): Expand a pack as a conjunction.
(type_dependent_expression_p): Placeholders are always type
dependent.
* gcc/cp/parser.c (cp_is_constrained_parameter),
(cp_finish_template_type_parm), (cp_finish_template_template_parm)
(cp_finish_non_type_template_parm), (cp_finish_constrined_parameter):
New.
(cp_parser_template_parameter): Handle constrained parameters.
(cp_parser_nonclass_name): An identifier naming an overload set
may declare a constrained parameter.
(cp_parser_type_parameter), (cp_parser_template_declaration_after_exp):
Get shorthand requirements from the tmeplate parameter list.
* gcc/cp/cp-tree.h (TEMPLATE_PARM_CONSTRAINTS): New.

Committed in 203704.

Andrew Sutton


Re: [c++-concepts] friends regression

2013-10-08 Thread Andrew Sutton
No, any current_template_reqs are reset (set to null) before parsing
any trailing requirements and restored after the fact.

Andrew Sutton


On Mon, Oct 7, 2013 at 3:05 PM, Jason Merrill ja...@redhat.com wrote:
 OK.

 If we have a friend declaration inside a constrained partial specialization,
 will that still get a false positive?

 Jason


[c++-concepts] friends regression

2013-10-07 Thread Andrew Sutton
The last patch introduced a regression. This ensures that we don't
generate false positives diagnosing errors in non-template contexts.

2013-10-07  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/cp-tree.h (check_constrained_friend): Take requirements as
an argument.
* gcc/cp/constraints.cc (check_constrained_friend): Do not diagnose
errors in unconstrained friend declarations.
* gcc/cp/parser.cc (cp_parser_member_declaration): Pass current
requirements to check_constrained_friend.

Andrew Sutton


friends-4.patch
Description: Binary data


Re: [c++-concepts] constrained friends redux

2013-10-04 Thread Andrew Sutton
 +  // Do not permit the declaration of constrained friend
 +  // function declarations. They cannot be instantiated since
 +  // the resulting declaration would never match the definition,
 +  // which must be a non-template and cannot be constrained.


 You're in the template-id code here, so must be a non-template is
 confusing:

 template class T void f();

 struct A {
   friend void fint(); // matches a template
 };

 Perhaps you mean that it must match a fully-instantiated function, so any
 constraints on the templates were considered during
 determine_specialization.

This seems like a simple comment fix, but there's a longer explanation
of what I want (see below). Would this be more appropriate?

  // Do not allow constrained friend template specializations.

The intent is stronger than to say it must match something. I don't
want to allow any declarations of the form

templatetypename T
struct X {
  friend void f(T x) requires CT; // Error.
};

This should never even get to determine_specialization since the
original declaration is never actually pushed.

We could use those constraints to match the specialization to one of
several constrained overloads, as you mentioned earlier, but I'd
rather avoid that for now. Solving that problem in general would
require that we allow constrained (explicit) specializations and
define a method of matching instantiated constraints to dependent
constraints, and that we do so as an alternative to the usual
constraint checking during template argument deduction.

Maybe it's a useful feature, but it's really hard to gauge how much
use it would actually get. We can always revisit that in the future.
Somebody else can write that paper :)

Andrew


Re: [c++-concepts] constrained friends redux

2013-10-04 Thread Andrew Sutton
 Perhaps you mean that it must match a fully-instantiated function, so
  any
 constraints on the templates were considered during
 determine_specialization.


 This seems like a simple comment fix, but there's a longer explanation
 of what I want (see below). Would this be more appropriate?

// Do not allow constrained friend template specializations.

 The intent is stronger than to say it must match something.


 By must I meant that whatever it matches could only be a
 fully-instantiated function.


I see what you mean. I was caught up in the wrong part of the
sentence.. But yes, that's right.

 But I guess the main reason for disallowing constraints here is the same as
 for explicit specializations and non-template functions; non-dependent
 constraints don't really make any sense.

That's the intent.

Okay to commit?

Andrew


friends-3.patch
Description: Binary data


[c++-concepts] constrained friends redux

2013-10-02 Thread Andrew Sutton
This patch implements constrained friends and disallows declarations
of constrained friend template specialization.

There was a previous question about whether I was doing the right
thing in determine_specialization. I'm looking at that issue
separately.

2013-10-01  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/parser.c (cp_parser_member_declaration): Check that
a constrained friend definition is valid.
* gcc/cp/decl.c (grokfndecl): Disallow constrained friend template
specializations.
* gcc/cp/constraints.cc (check_constrained_friend): New.
* gcc/cp/typeck.c (cp_build_function_call_vec): Diagnose constraints
in the presence of the failure of a single candidate.
* gcc/cp/cp-tree.h (check_constrained_friend): New.
* gcc/cp/call.c (is_non_template_member_fn): Make inline.
(is_non_template_friend), (is_constrainable_non_template_fn): New.
(add_function_candidate): Predicate check on
is_constrainable_non_template_fn.

Andrew Sutton


friends-2.patch
Description: Binary data


Re: [c++-concepts] Constrained friends

2013-09-21 Thread Andrew Sutton
I'm going to rewrite this patch tomorrow morning. The semantics aren't
quite right --- they should be simpler.

 Previously, if constraints were not
 satisfied, we would not record the template as a candidate. However,
 this causes errors in class template instantiation if there are
 constrained friend declarations whose constraints are not satisfied
 (no matching template declaration).

 Is that wrong?  We normally give errors about friend declarations that don't
 match any template.  Why don't we want this error when the friend
 declaration is looking for a constrained template?

It is wrong, but not for the reasons I gave. This only happens when
you try to constrain a friend function that declares a specialization,
which happens to be completely separate from the previously declared
template.

I'm going to disallow the ability to declare constrained friend
specializations. They don't really make sense.

 +  if (is_non_template_member_fn (fn) || is_non_template_friend (fn))


 Let's have one predicate instead of two; the condition here is a temploid
 that is not a specialization of a primary template.

Agreed.


 +  if (!check_template_constraints (tmpl, args)  (complain 
 tf_error))
  {
reason = template_constraint_failure (tmpl, args);
viable = false;


 Why add the complain check?  A constraint failure should make a candidate
 non-viable even in SFINAE context.

What have I done? That's awful...


 +  // If we're not instantiating a friend function, then we need to
 +  // ensure the specialization of the best template satisfies its
 +  // constraints.


 Surely we need to check constraints in the earlier loop, so that we don't
 treat as a candidate a template that doesn't satisfy the constraints;
 otherwise if we have two templates

 template class T T f(T) requires Thing;
 template class T T* f(T*);

 and our specialization requires Thing, we would select the second (because
 it is otherwise more specialized) and then give an error about constraint
 mismatch; I would think we want to select the first.

I believe that's what the previous version did, and we'll go back to
that. This change was part of the semantics that I didn't get right.

 +// If there is an overload with the same type and
 +// constraints, then this is a good declaration.
 +if (same_type_p (TREE_TYPE (fn), TREE_TYPE (f)))
 +  if (equivalent_constraints (constr, get_constraints (f)))
 +return;


 It seems that this will only allow friend declarations that match the
 template exactly, not friend declarations that are more specialized than the
 matching template.  It looks like you're trying to implement a subset of
 determine_specialization here, which I think is a mistake.

I agree. It's a mistake. This is also related to the semantics that I got wrong.

Effectively, the only changes needed for constrained friends are that:

a) you can't constrain non-dependent friends
b) you can't constraint non-template friend functions that declare a
specialization
and c) that we check non-template friends the same way as non-template
member fns

There should be no changes to any of the rules for determining specializations.

Andrew


[c++-concepts] Constrained friends

2013-09-13 Thread Andrew Sutton
This patch implements semantics for constrained friend templates and
classes. The only significant changes are in determine_specializaiton
and check_constrained_friend.

Unless a friend function is defined, a constraints on friend
declarations are never actually checked. The checking happens during
overload resolution against the actual (non-friend) declarations.

The change to determine_specialization is interesting. We have cases
where a programmer has written an explicit specialization and it's
being matched to a template. Previously, if constraints were not
satisfied, we would not record the template as a candidate. However,
this causes errors in class template instantiation if there are
constrained friend declarations whose constraints are not satisfied
(no matching template declaration).

With this patch, we defer constraints checks until we've selected the
best template for the specialization. And then we only check the
constraints if the declaration is a non-friend.

2013-09-13  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/cp-tree.h (check_constrained_friend): New.
* gcc/cp/pt.c (determine_specialization): Only check constraints
after determining which template the declaraiton is a specialization
of. Don't check constraints for friends during class template
instantiation.
(fn_type_unification): New parameter to determine if constraints
should be checked.
(more_specialized_class): Update for interface change.
(get_bindings): New parameter to determine if constraints should
be checked during fn_type_unification. New overload that checks
constraints by default.
* gcc/cp/parser.c (cp_parser_member_declaration): Check constrained
friends after parsing.
* gcc/cp/class.c (resolve_address_of_overloaded_function): Update
for interface change.
* gcc/cp/call.c (is_non_template_friend): New.
(add_function_candidate): Check constraints on constrained friend
templates.
(add_template_candidate_real): Update for interface change.
* gcc/cp/constraint.c (check_constrained_friend): New.


Andrew Sutton


friends.patch
Description: Binary data


[c++-concepts] template parameter constraints

2013-09-10 Thread Andrew Sutton
I added a new macro to replace the use of TREE_TYPE to get
constraints. It's called TEMPLATE_PARMS_CONSTRAINTS. Patch attached:

2013-09-10  Andrew Sutton  andrew.n.sut...@gmail.com
* gcc/cp/cp-tree.h (TEMPLATE_PARMS_CONSTRAINTS): New.
* gcc/cp/parser.c (cp_parser_template_declaration_after_export),
(cp_parser_type_parameter): Use TEMPLATE_PARMS_CONSTRAINTS.
* gcc/cp/semantics.c (fixup_template_scope): Use
 TEMPLATE_PARMS_CONSTRAINTS.


Andrew Sutton


template-parms.patch
Description: Binary data


Re: [c++-concepts] template parameter constraints

2013-09-10 Thread Andrew Sutton
Will amend and commit tomorrow morning!

Andrew
Andrew Sutton


On Tue, Sep 10, 2013 at 7:54 PM, Gabriel Dos Reis g...@axiomatics.org wrote:
 Andrew Sutton andrew.n.sut...@gmail.com writes:

 | I added a new macro to replace the use of TREE_TYPE to get
 | constraints. It's called TEMPLATE_PARMS_CONSTRAINTS. Patch attached:
 |
 | 2013-09-10  Andrew Sutton  andrew.n.sut...@gmail.com
 | * gcc/cp/cp-tree.h (TEMPLATE_PARMS_CONSTRAINTS): New.
 | * gcc/cp/parser.c (cp_parser_template_declaration_after_export),
 | (cp_parser_type_parameter): Use TEMPLATE_PARMS_CONSTRAINTS.
 | * gcc/cp/semantics.c (fixup_template_scope): Use
 |  TEMPLATE_PARMS_CONSTRAINTS.

 | +// Access template constraints associated with the template
 | +// parameter lists. Template parameter constraints are stored in
 | +// the TREE_TYPE of list.

 Hmm, we can have several levels of template parameter list.  What about:

   // Logical constraints on the template parameters introduced at a
   // given template parameter list level indicated by NODE.

 Patch OK with that change.

 Thanks,

 -- Gaby


Re: [c++-concepts] Class template constraints

2013-09-09 Thread Andrew Sutton
Ok to commit? Attached is the doc fix patch. I'll send the TREE_TYPE
patch shortly.

Andrew
Andrew Sutton


On Sat, Sep 7, 2013 at 1:00 PM, Jason Merrill ja...@redhat.com wrote:
 On 09/06/2013 12:03 PM, Andrew Sutton wrote:

 +// Returns the template type of the class scope being entered. If we're
 +// entering a constrained class scope. TMPL is the most general template
 +// of the scope being entered, and TYPE is its type.


 TMPL is not part of the interface of fixup_template_type, so it should be
 documented when it is declared rather than before the function.

 OK with that tweak.

 +  tree cur_constr = TREE_TYPE (parms);


 In a separate patch, I'd like to use a different macro name for getting
 constraints from template parms.

 Jason



templates-2.patch
Description: Binary data


  1   2   >