Re: [PATCH 6/6] c++: Consolidate REQUIRES_EXPR evaluation/diagnostic routines

2021-03-03 Thread Patrick Palka via Gcc-patches



On Tue, 2 Mar 2021, Jason Merrill wrote:

> On 3/2/21 11:45 AM, Patrick Palka wrote:
> > On Mon, 1 Mar 2021, Jason Merrill wrote:
> > 
> > > On 2/28/21 12:59 PM, Patrick Palka wrote:
> > > > This folds the diagnose_requires_expr routines into the corresponding
> > > > tsubst_requires_expr ones.  This is achieved by making the latter
> > > > routines take a sat_info instead of a subst_info, and assigning the
> > > > appropriate meanings to the flags sat_info::noisy and
> > > > sat_info::diagnose_unsatisfaction_p during tsubst_requires_expr:
> > > > info.noisy() controls whether to diagnose invalid types and expressions
> > > > inside the requires-expression, and info.diagnose_unsatisfaction_p()
> > > > controls whether to diagnose why the requires-expression evaluates to
> > > > false.
> > > > 
> > > > gcc/cp/ChangeLog:
> > > > 
> > > > * constraint.cc (struct sat_info): Document the different
> > > > meanings of noisy() and diagnose_unsatisfaction_p() during
> > > > satisfaction and requires-expression evaluation.
> > > > (tsubst_valid_expression_requirement): Take a sat_info instead
> > > > of a subst_info.  Perform the substitution quietly first.  Fold
> > > > in error-replaying code from diagnose_valid_expression.
> > > > (tsubst_simple_requirement): Take a sat_info instead of a
> > > > subst_info.
> > > > (tsubst_type_requirement_1): New.  Fold in error-replaying code
> > > > from diagnose_valid_type.
> > > > (tsubst_type_requirement): Use the above.  Take a sat_info
> > > > instead of a subst_info.
> > > > (tsubst_compound_requirement): Likewise.  Fold in
> > > > error-replaying code from diagnose_compound_requirement.
> > > > (tsubst_nested_requirement): Take a sat_info instead of a
> > > > subst_info.  Fold in error-replaying code from
> > > > diagnose_nested_requirement.
> > > > (tsubst_requirement): Take a sat_info instead of a subst_info.
> > > > (tsubst_requires_expr): Split into two versions, one that takes
> > > > a sat_info argument and another that takes a complain and
> > > > in_decl argument.  Remove outdated documentation.  Document the
> > > > effects of the sat_info argument.
> > > > (diagnose_trait_expr): Make static.  Take a template argument
> > > > vector instead of a parameter mapping.
> > > > (diagnose_valid_expression): Remove.
> > > > (diagnose_valid_type): Remove.
> > > > (diagnose_simple_requirement): Remove.
> > > > (diagnose_compound_requirement): Remove.
> > > > (diagnose_type_requirement): Remove.
> > > > (diagnose_nested_requirement): Remove.
> > > > (diagnose_requirement): Remove.
> > > > (diagnose_requires_expr): Remove.
> > > > (diagnose_atomic_constraint): Take a sat_info instead of a
> > > > subst_info.  Adjust call to diagnose_trait_expr.  Call
> > > > tsubst_requires_expr instead of diagnose_requires_expr.
> > > > (diagnose_constraints): Call tsubst_requires_expr instead of
> > > > diagnose_requires_expr.
> > > > 
> > > > gcc/testsuite/ChangeLog:
> > > > 
> > > > * g++.dg/concepts/diagnostic1.C: Adjust expected diagnostics
> > > > now that we diagnose only the first failed requirement of a
> > > > requires-expression.
> > > > ---
> > > >gcc/cp/constraint.cc| 416
> > > > +---
> > > >gcc/testsuite/g++.dg/concepts/diagnostic1.C |   2 +-
> > > >2 files changed, 179 insertions(+), 239 deletions(-)
> > > > 
> > > > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> > > > index cf319b34da0..31f32c25dfe 100644
> > > > --- a/gcc/cp/constraint.cc
> > > > +++ b/gcc/cp/constraint.cc
> > > > @@ -100,17 +100,30 @@ struct subst_info
> > > >  /* Provides additional context for satisfaction.
> > > >-   The flag noisy() controls whether to diagnose ill-formed
> > > > satisfaction,
> > > > -   such as the satisfaction value of an atom being non-bool or
> > > > non-constant.
> > > > -
> > > > -   The flag diagnose_unsatisfaction_p() controls whether to explain why
> > > > -   a constraint is not satisfied.
> > > > -
> > > > -   The entrypoints to satisfaction for which we set noisy+unsat are
> > > > -   diagnose_constraints and diagnose_nested_requirement.  The
> > > > entrypoint
> > > > for
> > > > -   which we set noisy-unsat is the replay inside
> > > > constraint_satisfaction_value.
> > > > -   From constraints_satisfied_p, we enter satisfaction quietly (both
> > > > flags
> > > > -   cleared).  */
> > > > +   During satisfaction:
> > > > +- The flag noisy() controls whether to diagnose ill-formed
> > > > satisfaction,
> > > > +  such as the satisfaction value of an atom being non-bool or
> > > > non-constant.
> > > > +- The flag diagnose_unsatisfaction_p() controls whether to explain

Re: [PATCH 6/6] c++: Consolidate REQUIRES_EXPR evaluation/diagnostic routines

2021-03-02 Thread Jason Merrill via Gcc-patches

On 3/2/21 11:45 AM, Patrick Palka wrote:

On Mon, 1 Mar 2021, Jason Merrill wrote:


On 2/28/21 12:59 PM, Patrick Palka wrote:

This folds the diagnose_requires_expr routines into the corresponding
tsubst_requires_expr ones.  This is achieved by making the latter
routines take a sat_info instead of a subst_info, and assigning the
appropriate meanings to the flags sat_info::noisy and
sat_info::diagnose_unsatisfaction_p during tsubst_requires_expr:
info.noisy() controls whether to diagnose invalid types and expressions
inside the requires-expression, and info.diagnose_unsatisfaction_p()
controls whether to diagnose why the requires-expression evaluates to
false.

gcc/cp/ChangeLog:

* constraint.cc (struct sat_info): Document the different
meanings of noisy() and diagnose_unsatisfaction_p() during
satisfaction and requires-expression evaluation.
(tsubst_valid_expression_requirement): Take a sat_info instead
of a subst_info.  Perform the substitution quietly first.  Fold
in error-replaying code from diagnose_valid_expression.
(tsubst_simple_requirement): Take a sat_info instead of a
subst_info.
(tsubst_type_requirement_1): New.  Fold in error-replaying code
from diagnose_valid_type.
(tsubst_type_requirement): Use the above.  Take a sat_info
instead of a subst_info.
(tsubst_compound_requirement): Likewise.  Fold in
error-replaying code from diagnose_compound_requirement.
(tsubst_nested_requirement): Take a sat_info instead of a
subst_info.  Fold in error-replaying code from
diagnose_nested_requirement.
(tsubst_requirement): Take a sat_info instead of a subst_info.
(tsubst_requires_expr): Split into two versions, one that takes
a sat_info argument and another that takes a complain and
in_decl argument.  Remove outdated documentation.  Document the
effects of the sat_info argument.
(diagnose_trait_expr): Make static.  Take a template argument
vector instead of a parameter mapping.
(diagnose_valid_expression): Remove.
(diagnose_valid_type): Remove.
(diagnose_simple_requirement): Remove.
(diagnose_compound_requirement): Remove.
(diagnose_type_requirement): Remove.
(diagnose_nested_requirement): Remove.
(diagnose_requirement): Remove.
(diagnose_requires_expr): Remove.
(diagnose_atomic_constraint): Take a sat_info instead of a
subst_info.  Adjust call to diagnose_trait_expr.  Call
tsubst_requires_expr instead of diagnose_requires_expr.
(diagnose_constraints): Call tsubst_requires_expr instead of
diagnose_requires_expr.

gcc/testsuite/ChangeLog:

* g++.dg/concepts/diagnostic1.C: Adjust expected diagnostics
now that we diagnose only the first failed requirement of a
requires-expression.
---
   gcc/cp/constraint.cc| 416 +---
   gcc/testsuite/g++.dg/concepts/diagnostic1.C |   2 +-
   2 files changed, 179 insertions(+), 239 deletions(-)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index cf319b34da0..31f32c25dfe 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -100,17 +100,30 @@ struct subst_info
 /* Provides additional context for satisfaction.
   -   The flag noisy() controls whether to diagnose ill-formed satisfaction,
-   such as the satisfaction value of an atom being non-bool or
non-constant.
-
-   The flag diagnose_unsatisfaction_p() controls whether to explain why
-   a constraint is not satisfied.
-
-   The entrypoints to satisfaction for which we set noisy+unsat are
-   diagnose_constraints and diagnose_nested_requirement.  The entrypoint
for
-   which we set noisy-unsat is the replay inside
constraint_satisfaction_value.
-   From constraints_satisfied_p, we enter satisfaction quietly (both flags
-   cleared).  */
+   During satisfaction:
+- The flag noisy() controls whether to diagnose ill-formed
satisfaction,
+  such as the satisfaction value of an atom being non-bool or
non-constant.
+- The flag diagnose_unsatisfaction_p() controls whether to explain why
+  a constraint is not satisfied.
+- We enter satisfaction with noisy+unsat from diagnose_constraints.
+- We enter satisfaction with noisy-unsat from the replay inside
+  constraint_satisfaction_value.
+- We enter satisfaction quietly (both flags cleared) from
+  constraints_satisfied_p.
+
+   During evaluation of a requires-expression:
+- The flag noisy() controls whether to diagnose ill-formed types and
+  expressions inside its requirements.
+- The flag diagnose_unsatisfaction_p() controls whether to explain why
+  the requires-expression evaluates to false.
+- We enter tsubst_requires_expr with noisy+unsat from
diagnose_constraints
+  and from diagnose_atomic_constraint.
+- We enter tsubst_requires_expr 

Re: [PATCH 6/6] c++: Consolidate REQUIRES_EXPR evaluation/diagnostic routines

2021-03-02 Thread Patrick Palka via Gcc-patches
On Mon, 1 Mar 2021, Jason Merrill wrote:

> On 2/28/21 12:59 PM, Patrick Palka wrote:
> > This folds the diagnose_requires_expr routines into the corresponding
> > tsubst_requires_expr ones.  This is achieved by making the latter
> > routines take a sat_info instead of a subst_info, and assigning the
> > appropriate meanings to the flags sat_info::noisy and
> > sat_info::diagnose_unsatisfaction_p during tsubst_requires_expr:
> > info.noisy() controls whether to diagnose invalid types and expressions
> > inside the requires-expression, and info.diagnose_unsatisfaction_p()
> > controls whether to diagnose why the requires-expression evaluates to
> > false.
> > 
> > gcc/cp/ChangeLog:
> > 
> > * constraint.cc (struct sat_info): Document the different
> > meanings of noisy() and diagnose_unsatisfaction_p() during
> > satisfaction and requires-expression evaluation.
> > (tsubst_valid_expression_requirement): Take a sat_info instead
> > of a subst_info.  Perform the substitution quietly first.  Fold
> > in error-replaying code from diagnose_valid_expression.
> > (tsubst_simple_requirement): Take a sat_info instead of a
> > subst_info.
> > (tsubst_type_requirement_1): New.  Fold in error-replaying code
> > from diagnose_valid_type.
> > (tsubst_type_requirement): Use the above.  Take a sat_info
> > instead of a subst_info.
> > (tsubst_compound_requirement): Likewise.  Fold in
> > error-replaying code from diagnose_compound_requirement.
> > (tsubst_nested_requirement): Take a sat_info instead of a
> > subst_info.  Fold in error-replaying code from
> > diagnose_nested_requirement.
> > (tsubst_requirement): Take a sat_info instead of a subst_info.
> > (tsubst_requires_expr): Split into two versions, one that takes
> > a sat_info argument and another that takes a complain and
> > in_decl argument.  Remove outdated documentation.  Document the
> > effects of the sat_info argument.
> > (diagnose_trait_expr): Make static.  Take a template argument
> > vector instead of a parameter mapping.
> > (diagnose_valid_expression): Remove.
> > (diagnose_valid_type): Remove.
> > (diagnose_simple_requirement): Remove.
> > (diagnose_compound_requirement): Remove.
> > (diagnose_type_requirement): Remove.
> > (diagnose_nested_requirement): Remove.
> > (diagnose_requirement): Remove.
> > (diagnose_requires_expr): Remove.
> > (diagnose_atomic_constraint): Take a sat_info instead of a
> > subst_info.  Adjust call to diagnose_trait_expr.  Call
> > tsubst_requires_expr instead of diagnose_requires_expr.
> > (diagnose_constraints): Call tsubst_requires_expr instead of
> > diagnose_requires_expr.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/concepts/diagnostic1.C: Adjust expected diagnostics
> > now that we diagnose only the first failed requirement of a
> > requires-expression.
> > ---
> >   gcc/cp/constraint.cc| 416 +---
> >   gcc/testsuite/g++.dg/concepts/diagnostic1.C |   2 +-
> >   2 files changed, 179 insertions(+), 239 deletions(-)
> > 
> > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> > index cf319b34da0..31f32c25dfe 100644
> > --- a/gcc/cp/constraint.cc
> > +++ b/gcc/cp/constraint.cc
> > @@ -100,17 +100,30 @@ struct subst_info
> > /* Provides additional context for satisfaction.
> >   -   The flag noisy() controls whether to diagnose ill-formed satisfaction,
> > -   such as the satisfaction value of an atom being non-bool or
> > non-constant.
> > -
> > -   The flag diagnose_unsatisfaction_p() controls whether to explain why
> > -   a constraint is not satisfied.
> > -
> > -   The entrypoints to satisfaction for which we set noisy+unsat are
> > -   diagnose_constraints and diagnose_nested_requirement.  The entrypoint
> > for
> > -   which we set noisy-unsat is the replay inside
> > constraint_satisfaction_value.
> > -   From constraints_satisfied_p, we enter satisfaction quietly (both flags
> > -   cleared).  */
> > +   During satisfaction:
> > +- The flag noisy() controls whether to diagnose ill-formed
> > satisfaction,
> > +  such as the satisfaction value of an atom being non-bool or
> > non-constant.
> > +- The flag diagnose_unsatisfaction_p() controls whether to explain why
> > +  a constraint is not satisfied.
> > +- We enter satisfaction with noisy+unsat from diagnose_constraints.
> > +- We enter satisfaction with noisy-unsat from the replay inside
> > +  constraint_satisfaction_value.
> > +- We enter satisfaction quietly (both flags cleared) from
> > +  constraints_satisfied_p.
> > +
> > +   During evaluation of a requires-expression:
> > +- The flag noisy() controls whether to diagnose ill-formed types and
> > +  expressions inside its requirements.
> > +- The flag diagnose_unsatisfaction_p() controls whether to explain why
> > +  the requires-expression 

Re: [PATCH 6/6] c++: Consolidate REQUIRES_EXPR evaluation/diagnostic routines

2021-03-01 Thread Jason Merrill via Gcc-patches

On 2/28/21 12:59 PM, Patrick Palka wrote:

This folds the diagnose_requires_expr routines into the corresponding
tsubst_requires_expr ones.  This is achieved by making the latter
routines take a sat_info instead of a subst_info, and assigning the
appropriate meanings to the flags sat_info::noisy and
sat_info::diagnose_unsatisfaction_p during tsubst_requires_expr:
info.noisy() controls whether to diagnose invalid types and expressions
inside the requires-expression, and info.diagnose_unsatisfaction_p()
controls whether to diagnose why the requires-expression evaluates to
false.

gcc/cp/ChangeLog:

* constraint.cc (struct sat_info): Document the different
meanings of noisy() and diagnose_unsatisfaction_p() during
satisfaction and requires-expression evaluation.
(tsubst_valid_expression_requirement): Take a sat_info instead
of a subst_info.  Perform the substitution quietly first.  Fold
in error-replaying code from diagnose_valid_expression.
(tsubst_simple_requirement): Take a sat_info instead of a
subst_info.
(tsubst_type_requirement_1): New.  Fold in error-replaying code
from diagnose_valid_type.
(tsubst_type_requirement): Use the above.  Take a sat_info
instead of a subst_info.
(tsubst_compound_requirement): Likewise.  Fold in
error-replaying code from diagnose_compound_requirement.
(tsubst_nested_requirement): Take a sat_info instead of a
subst_info.  Fold in error-replaying code from
diagnose_nested_requirement.
(tsubst_requirement): Take a sat_info instead of a subst_info.
(tsubst_requires_expr): Split into two versions, one that takes
a sat_info argument and another that takes a complain and
in_decl argument.  Remove outdated documentation.  Document the
effects of the sat_info argument.
(diagnose_trait_expr): Make static.  Take a template argument
vector instead of a parameter mapping.
(diagnose_valid_expression): Remove.
(diagnose_valid_type): Remove.
(diagnose_simple_requirement): Remove.
(diagnose_compound_requirement): Remove.
(diagnose_type_requirement): Remove.
(diagnose_nested_requirement): Remove.
(diagnose_requirement): Remove.
(diagnose_requires_expr): Remove.
(diagnose_atomic_constraint): Take a sat_info instead of a
subst_info.  Adjust call to diagnose_trait_expr.  Call
tsubst_requires_expr instead of diagnose_requires_expr.
(diagnose_constraints): Call tsubst_requires_expr instead of
diagnose_requires_expr.

gcc/testsuite/ChangeLog:

* g++.dg/concepts/diagnostic1.C: Adjust expected diagnostics
now that we diagnose only the first failed requirement of a
requires-expression.
---
  gcc/cp/constraint.cc| 416 +---
  gcc/testsuite/g++.dg/concepts/diagnostic1.C |   2 +-
  2 files changed, 179 insertions(+), 239 deletions(-)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index cf319b34da0..31f32c25dfe 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -100,17 +100,30 @@ struct subst_info
  
  /* Provides additional context for satisfaction.
  
-   The flag noisy() controls whether to diagnose ill-formed satisfaction,

-   such as the satisfaction value of an atom being non-bool or non-constant.
-
-   The flag diagnose_unsatisfaction_p() controls whether to explain why
-   a constraint is not satisfied.
-
-   The entrypoints to satisfaction for which we set noisy+unsat are
-   diagnose_constraints and diagnose_nested_requirement.  The entrypoint for
-   which we set noisy-unsat is the replay inside constraint_satisfaction_value.
-   From constraints_satisfied_p, we enter satisfaction quietly (both flags
-   cleared).  */
+   During satisfaction:
+- The flag noisy() controls whether to diagnose ill-formed satisfaction,
+  such as the satisfaction value of an atom being non-bool or non-constant.
+- The flag diagnose_unsatisfaction_p() controls whether to explain why
+  a constraint is not satisfied.
+- We enter satisfaction with noisy+unsat from diagnose_constraints.
+- We enter satisfaction with noisy-unsat from the replay inside
+  constraint_satisfaction_value.
+- We enter satisfaction quietly (both flags cleared) from
+  constraints_satisfied_p.
+
+   During evaluation of a requires-expression:
+- The flag noisy() controls whether to diagnose ill-formed types and
+  expressions inside its requirements.
+- The flag diagnose_unsatisfaction_p() controls whether to explain why
+  the requires-expression evaluates to false.
+- We enter tsubst_requires_expr with noisy+unsat from diagnose_constraints
+  and from diagnose_atomic_constraint.
+- We enter tsubst_requires_expr with noisy-unsat from
+  cp_parser_requires_expression when processing a 

[PATCH 6/6] c++: Consolidate REQUIRES_EXPR evaluation/diagnostic routines

2021-02-28 Thread Patrick Palka via Gcc-patches
This folds the diagnose_requires_expr routines into the corresponding
tsubst_requires_expr ones.  This is achieved by making the latter
routines take a sat_info instead of a subst_info, and assigning the
appropriate meanings to the flags sat_info::noisy and
sat_info::diagnose_unsatisfaction_p during tsubst_requires_expr:
info.noisy() controls whether to diagnose invalid types and expressions
inside the requires-expression, and info.diagnose_unsatisfaction_p()
controls whether to diagnose why the requires-expression evaluates to
false.

gcc/cp/ChangeLog:

* constraint.cc (struct sat_info): Document the different
meanings of noisy() and diagnose_unsatisfaction_p() during
satisfaction and requires-expression evaluation.
(tsubst_valid_expression_requirement): Take a sat_info instead
of a subst_info.  Perform the substitution quietly first.  Fold
in error-replaying code from diagnose_valid_expression.
(tsubst_simple_requirement): Take a sat_info instead of a
subst_info.
(tsubst_type_requirement_1): New.  Fold in error-replaying code
from diagnose_valid_type.
(tsubst_type_requirement): Use the above.  Take a sat_info
instead of a subst_info.
(tsubst_compound_requirement): Likewise.  Fold in
error-replaying code from diagnose_compound_requirement.
(tsubst_nested_requirement): Take a sat_info instead of a
subst_info.  Fold in error-replaying code from
diagnose_nested_requirement.
(tsubst_requirement): Take a sat_info instead of a subst_info.
(tsubst_requires_expr): Split into two versions, one that takes
a sat_info argument and another that takes a complain and
in_decl argument.  Remove outdated documentation.  Document the
effects of the sat_info argument.
(diagnose_trait_expr): Make static.  Take a template argument
vector instead of a parameter mapping.
(diagnose_valid_expression): Remove.
(diagnose_valid_type): Remove.
(diagnose_simple_requirement): Remove.
(diagnose_compound_requirement): Remove.
(diagnose_type_requirement): Remove.
(diagnose_nested_requirement): Remove.
(diagnose_requirement): Remove.
(diagnose_requires_expr): Remove.
(diagnose_atomic_constraint): Take a sat_info instead of a
subst_info.  Adjust call to diagnose_trait_expr.  Call
tsubst_requires_expr instead of diagnose_requires_expr.
(diagnose_constraints): Call tsubst_requires_expr instead of
diagnose_requires_expr.

gcc/testsuite/ChangeLog:

* g++.dg/concepts/diagnostic1.C: Adjust expected diagnostics
now that we diagnose only the first failed requirement of a
requires-expression.
---
 gcc/cp/constraint.cc| 416 +---
 gcc/testsuite/g++.dg/concepts/diagnostic1.C |   2 +-
 2 files changed, 179 insertions(+), 239 deletions(-)

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index cf319b34da0..31f32c25dfe 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -100,17 +100,30 @@ struct subst_info
 
 /* Provides additional context for satisfaction.
 
-   The flag noisy() controls whether to diagnose ill-formed satisfaction,
-   such as the satisfaction value of an atom being non-bool or non-constant.
-
-   The flag diagnose_unsatisfaction_p() controls whether to explain why
-   a constraint is not satisfied.
-
-   The entrypoints to satisfaction for which we set noisy+unsat are
-   diagnose_constraints and diagnose_nested_requirement.  The entrypoint for
-   which we set noisy-unsat is the replay inside constraint_satisfaction_value.
-   From constraints_satisfied_p, we enter satisfaction quietly (both flags
-   cleared).  */
+   During satisfaction:
+- The flag noisy() controls whether to diagnose ill-formed satisfaction,
+  such as the satisfaction value of an atom being non-bool or non-constant.
+- The flag diagnose_unsatisfaction_p() controls whether to explain why
+  a constraint is not satisfied.
+- We enter satisfaction with noisy+unsat from diagnose_constraints.
+- We enter satisfaction with noisy-unsat from the replay inside
+  constraint_satisfaction_value.
+- We enter satisfaction quietly (both flags cleared) from
+  constraints_satisfied_p.
+
+   During evaluation of a requires-expression:
+- The flag noisy() controls whether to diagnose ill-formed types and
+  expressions inside its requirements.
+- The flag diagnose_unsatisfaction_p() controls whether to explain why
+  the requires-expression evaluates to false.
+- We enter tsubst_requires_expr with noisy+unsat from diagnose_constraints
+  and from diagnose_atomic_constraint.
+- We enter tsubst_requires_expr with noisy-unsat from
+  cp_parser_requires_expression when processing a requires-expression that
+  appears outside a template.
+