[C++ Patch] PR 94034 ("[10 Regression] Broken diagnostic: 'result_decl' not supported by dump_expr")

2020-03-06 Thread Paolo Carlini

Hi,

in this apparently simple regression we end up producing garbled 
diagnostic because dump_expr (called via verify_constant) doesn't handle 
RESULT_DECL. I think it makes sense to add the tree code together with 
all the other *_DECL. Tested x86_64-linux.


Thanks, Paolo.

/



Re: [C++ Patch] PR 94034 ("[10 Regression] Broken diagnostic: 'result_decl' not supported by dump_expr")

2020-03-06 Thread Paolo Carlini

... the patch ;)

Paolo.

Fix "PR c++/94034 Broken diagnostic: 'result_decl' not supported by dump_expr"

A rather simple diagnostic issue where we failed to handle RESULT_DECL in
dump_expr.

Tested x86_64-linux.

   /cp
   PR c++/94034
   * error.c (dump_expr): Handle RESULT_DECL like the other *_DECL.

   /testsuite
   PR c++/94034
   * g++.dg/cpp0x/pr94034.C: New.

diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index cc51b6ffe13..c1392bcbb25 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -2102,6 +2102,7 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
 case OVERLOAD:
 case TYPE_DECL:
 case IDENTIFIER_NODE:
+case RESULT_DECL:
   dump_decl (pp, t, ((flags & ~(TFF_DECL_SPECIFIERS|TFF_RETURN_TYPE
 |TFF_TEMPLATE_HEADER))
 | TFF_NO_TEMPLATE_BINDINGS
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr94034.C 
b/gcc/testsuite/g++.dg/cpp0x/pr94034.C
new file mode 100644
index 000..0a828c1e263
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr94034.C
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++11 } }
+
+struct A { A *ap = this; };
+constexpr A foo() {
+  return {};
+}
+void g() {
+  constexpr A a = foo();  // { dg-bogus "not supported by" }
+  // { dg-error "not a constant expression" "" { target c++11 } .-1 }
+}


Re: [C++ Patch] PR 90915 [9/10 Regression] ICE in has_attribute, at c-family/c-attribs.c:4221

2020-01-29 Thread Paolo Carlini

Hi,

On 29/01/20 19:00, Jason Merrill wrote:

On 1/29/20 4:31 AM, Paolo Carlini wrote:

Hi,

in this regression we issue a diagnostic about an incomplete type 
(only a warning by default) and then we crash when we try to query 
has_attribute on a member of the type because in such cases the 
member remains an IDENTIFIER_NODE which of course doesn't have a 
TREE_TYPE neither a DECL_ATTRIBUTES... Simply recognizing 
IDENTIFIER_NODEs and returning false works fine, not sure if we want 
to do something more sophisticated. Tested x86_64-linux.


Why are we getting to has_attribute at all for a type-dependent argument?


Because the implementation of __builtin_has_attribute, largely shared 
with the C front-end, doesn't know about templates at all? :-/


Not sure it's the best time to complete it, but shouldn't be too difficult.

Paolo.




[C++ Patch] PR 90915 [9/10 Regression] ICE in has_attribute, at c-family/c-attribs.c:4221

2020-01-29 Thread Paolo Carlini

Hi,

in this regression we issue a diagnostic about an incomplete type (only 
a warning by default) and then we crash when we try to query 
has_attribute on a member of the type because in such cases the member 
remains an IDENTIFIER_NODE which of course doesn't have a TREE_TYPE 
neither a DECL_ATTRIBUTES... Simply recognizing IDENTIFIER_NODEs and 
returning false works fine, not sure if we want to do something more 
sophisticated. Tested x86_64-linux.


Thanks, Paolo.



Fix "PR c++/90915 ICE in has_attribute, at c-family/c-attribs.c:4221"

A rather simple ICE where we didn't properly recover upon diagnosing
an incomplete type.

Tested x86_64-linux.

   /c-family
   PR c++/90915
   * c-attribs.c (has_attribute): Handle correctly IDENTIFIER_NODEs.

   /testsuite
   PR c++/90915
   * g++.dg/ext/builtin-has-attribute-1.C: New.
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index dc9579c5c60..97590a19c0f 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -4759,6 +4759,10 @@ has_attribute (location_t atloc, tree t, tree attr, tree 
(*convert)(tree))
  expr = NULL_TREE;
  done = true;
}
+  else if (TREE_CODE (expr) == IDENTIFIER_NODE)
+   /* Can happen during error-recovery when querying a member of
+  an incomplete type (c++/90915).  */
+   return false;
   else if (DECL_P (expr))
{
  /* Set TYPE to the DECL's type to process it on the next
diff --git a/gcc/testsuite/g++.dg/ext/builtin-has-attribute-1.C 
b/gcc/testsuite/g++.dg/ext/builtin-has-attribute-1.C
new file mode 100644
index 000..3d81a078159
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/builtin-has-attribute-1.C
@@ -0,0 +1,7 @@
+// { dg-do compile { target c++11 } }
+
+struct S;
+template struct T
+{
+  static_assert (!__builtin_has_attribute (((S *) 0) -> a, packed), "");  // { 
dg-error "invalid use of incomplete type" }
+};


Re: [C++ Patch] PR 92804 [10 Regression] ICE trying to use concept as a nested-name-specifier

2020-01-23 Thread Paolo Carlini

Hi,

On 22/01/20 22:32, Jason Merrill wrote:

On 1/22/20 3:31 PM, Paolo Carlini wrote:

Hi,

On 22/01/20 17:27, Jason Merrill wrote:

On 1/22/20 10:22 AM, Paolo Carlini wrote:

Hi,

in this simple issue we either wrongly talked about variable 
template-id in c++17 mode or ICEd in c++2a. I think we simply want 
to handle concept-ids first, both as represented in c++17 mode and 
as represented in c++2a mode. Tested x86_64-linux.
What happens if you try to use a function template/function concept 
name?


AFAICS no ICEs, no regressions but indeed we can do better, tell 
concepts from function templates. The below does that and passes 
testing but I'm not sure if the wording is optimal, whether we always 
want to talk about concept-id.


I think it's fine either way.


+// { dg-do compile { target c++17 } }
+// { dg-options "-w -fconcepts" }


Does it work to use -fconcepts-ts instead of -w -fconcepts?


Sure, it does. Attached what I tested.

Thanks, Paolo.

//

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index caafbefda8e..85a4ea5be82 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6467,16 +6467,27 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
  tree fns = get_fns (tid);
  if (OVL_SINGLE_P (fns))
tmpl = OVL_FIRST (fns);
- error_at (token->location, "function template-id %qD "
-   "in nested-name-specifier", tid);
+ if (function_concept_p (fns))
+   error_at (token->location, "concept-id %qD "
+ "in nested-name-specifier", tid);
+ else
+   error_at (token->location, "function template-id "
+ "%qD in nested-name-specifier", tid);
}
  else
{
- /* Variable template.  */
  tmpl = TREE_OPERAND (tid, 0);
- gcc_assert (variable_template_p (tmpl));
- error_at (token->location, "variable template-id %qD "
-   "in nested-name-specifier", tid);
+ if (variable_concept_p (tmpl)
+ || standard_concept_p (tmpl))
+   error_at (token->location, "concept-id %qD "
+ "in nested-name-specifier", tid);
+ else
+   {
+ /* Variable template.  */
+ gcc_assert (variable_template_p (tmpl));
+ error_at (token->location, "variable template-id "
+   "%qD in nested-name-specifier", tid);
+   }
}
  if (tmpl)
inform (DECL_SOURCE_LOCATION (tmpl),
diff --git a/gcc/testsuite/g++.dg/concepts/pr92804-1.C 
b/gcc/testsuite/g++.dg/concepts/pr92804-1.C
new file mode 100644
index 000..cc21426bb9e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr92804-1.C
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++17 } }
+// { dg-options "-fconcepts" }
+
+template
+concept foo = true;  // { dg-message "declared here" }
+
+template
+void bar(T t)
+{
+  if constexpr (foo::value)  // { dg-error "17:concept-id .foo. in 
nested-name-specifier" }
+  // { dg-error "expected|value" "" { target c++17 } .-1 }
+  {
+  }
+}
+
+int main()
+{
+  bar(1);
+}
diff --git a/gcc/testsuite/g++.dg/concepts/pr92804-2.C 
b/gcc/testsuite/g++.dg/concepts/pr92804-2.C
new file mode 100644
index 000..32a15543310
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr92804-2.C
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++17 } }
+// { dg-options "-fconcepts-ts" }
+
+template
+concept bool foo() { return true; };  // { dg-message "declared here" }
+
+template
+void bar(T t)
+{
+  if constexpr (foo::value)  // { dg-error "17:concept-id .foo. in 
nested-name-specifier" }
+  // { dg-error "expected|value" "" { target *-*-* } .-1 }
+  {
+  }
+}
+
+int main()
+{
+  bar(1);
+}


Re: [C++ Patch] PR 92804 [10 Regression] ICE trying to use concept as a nested-name-specifier

2020-01-22 Thread Paolo Carlini

Hi,

On 22/01/20 17:27, Jason Merrill wrote:

On 1/22/20 10:22 AM, Paolo Carlini wrote:

Hi,

in this simple issue we either wrongly talked about variable 
template-id in c++17 mode or ICEd in c++2a. I think we simply want to 
handle concept-ids first, both as represented in c++17 mode and as 
represented in c++2a mode. Tested x86_64-linux.

What happens if you try to use a function template/function concept name?


AFAICS no ICEs, no regressions but indeed we can do better, tell 
concepts from function templates. The below does that and passes testing 
but I'm not sure if the wording is optimal, whether we always want to 
talk about concept-id.


Thanks! Paolo.

///


diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index caafbefda8e..85a4ea5be82 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6467,16 +6467,27 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
  tree fns = get_fns (tid);
  if (OVL_SINGLE_P (fns))
tmpl = OVL_FIRST (fns);
- error_at (token->location, "function template-id %qD "
-   "in nested-name-specifier", tid);
+ if (function_concept_p (fns))
+   error_at (token->location, "concept-id %qD "
+ "in nested-name-specifier", tid);
+ else
+   error_at (token->location, "function template-id "
+ "%qD in nested-name-specifier", tid);
}
  else
{
- /* Variable template.  */
  tmpl = TREE_OPERAND (tid, 0);
- gcc_assert (variable_template_p (tmpl));
- error_at (token->location, "variable template-id %qD "
-   "in nested-name-specifier", tid);
+ if (variable_concept_p (tmpl)
+ || standard_concept_p (tmpl))
+   error_at (token->location, "concept-id %qD "
+ "in nested-name-specifier", tid);
+ else
+   {
+ /* Variable template.  */
+ gcc_assert (variable_template_p (tmpl));
+ error_at (token->location, "variable template-id "
+   "%qD in nested-name-specifier", tid);
+   }
}
  if (tmpl)
inform (DECL_SOURCE_LOCATION (tmpl),
diff --git a/gcc/testsuite/g++.dg/concepts/pr92804-1.C 
b/gcc/testsuite/g++.dg/concepts/pr92804-1.C
new file mode 100644
index 000..cc21426bb9e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr92804-1.C
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++17 } }
+// { dg-options "-fconcepts" }
+
+template
+concept foo = true;  // { dg-message "declared here" }
+
+template
+void bar(T t)
+{
+  if constexpr (foo::value)  // { dg-error "17:concept-id .foo. in 
nested-name-specifier" }
+  // { dg-error "expected|value" "" { target c++17 } .-1 }
+  {
+  }
+}
+
+int main()
+{
+  bar(1);
+}
diff --git a/gcc/testsuite/g++.dg/concepts/pr92804-2.C 
b/gcc/testsuite/g++.dg/concepts/pr92804-2.C
new file mode 100644
index 000..98ec4ae598e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr92804-2.C
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++17 } }
+// { dg-options "-w -fconcepts" }
+
+template
+concept bool foo() { return true; };  // { dg-message "declared here" }
+
+template
+void bar(T t)
+{
+  if constexpr (foo::value)  // { dg-error "17:concept-id .foo. in 
nested-name-specifier" }
+  // { dg-error "expected|value" "" { target *-*-* } .-1 }
+  {
+  }
+}
+
+int main()
+{
+  bar(1);
+}


[C++ Patch] PR 92804 [10 Regression] ICE trying to use concept as a nested-name-specifier

2020-01-22 Thread Paolo Carlini

Hi,

in this simple issue we either wrongly talked about variable template-id 
in c++17 mode or ICEd in c++2a. I think we simply want to handle 
concept-ids first, both as represented in c++17 mode and as represented 
in c++2a mode. Tested x86_64-linux.


Thanks, Paolo.

///

Fix "PR c++/92804 ICE trying to use concept as a nested-name-specifier"

A rather simple ICE where we failed to properly check for concept-ids
uses in nested-name-specifiers.

Tested x86_64-linux.

   /cp
   PR c++/92804
   * parser.c (cp_parser_nested_name_specifier_opt): Properly
   diagnose concept-ids.

   /testsuite
   PR c++/92804
   * g++.dg/concepts/pr92804.C: New.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index caafbefda8e..fe490d4a69f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6472,11 +6472,18 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
}
  else
{
- /* Variable template.  */
  tmpl = TREE_OPERAND (tid, 0);
- gcc_assert (variable_template_p (tmpl));
- error_at (token->location, "variable template-id %qD "
-   "in nested-name-specifier", tid);
+ if (variable_concept_p (tmpl)
+ || standard_concept_p (tmpl))
+   error_at (token->location, "concept-id %qD "
+ "in nested-name-specifier", tid);
+ else
+   {
+ /* Variable template.  */
+ gcc_assert (variable_template_p (tmpl));
+ error_at (token->location, "variable template-id "
+   "%qD in nested-name-specifier", tid);
+   }
}
  if (tmpl)
inform (DECL_SOURCE_LOCATION (tmpl),
diff --git a/gcc/testsuite/g++.dg/concepts/pr92804.C 
b/gcc/testsuite/g++.dg/concepts/pr92804.C
new file mode 100644
index 000..cc21426bb9e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/pr92804.C
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++17 } }
+// { dg-options "-fconcepts" }
+
+template
+concept foo = true;  // { dg-message "declared here" }
+
+template
+void bar(T t)
+{
+  if constexpr (foo::value)  // { dg-error "17:concept-id .foo. in 
nested-name-specifier" }
+  // { dg-error "expected|value" "" { target c++17 } .-1 }
+  {
+  }
+}
+
+int main()
+{
+  bar(1);
+}


Re: [C++ Patch] Improve build_new locations

2020-01-07 Thread Paolo Carlini

Hi,

On 06/01/20 21:47, Jason Merrill wrote:

On 1/2/20 4:23 AM, Paolo Carlini wrote:

@@ -19320,8 +19320,8 @@ tsubst_copy_and_build (tree t,
    tree op1 = tsubst (TREE_OPERAND (t, 1), args, complain, 
in_decl);

  tree op2 = RECUR (TREE_OPERAND (t, 2));
-    ret = build_new (_vec, op1, op2, _vec,
- NEW_EXPR_USE_GLOBAL (t),
+    ret = build_new (input_location, _vec, op1, op2,


Hmm, using input_location bothers me even though it does have the 
right value in this function.  Let's use a local variable instead; 
maybe change the existing loc variable to save_loc and use the name 
loc for the location we want to use.


I see, I wondered about that myself: when I started working on these 
location issues I forwarded simple EXPR_LOCATION (t) in a few places, 
which worked just fine. Then I noticed that in many existing places we 
were exploiting the fact that input_location is changed on top and 
started using it myself too. I suppose some of those places too could be 
changed to simple EXPR_LOCATION (t), I can experiment with that.


Anyway, the below implements the save_loc bit and regtests fine on 
x86_64-linux, as usual.


Thanks, Paolo.

/

Index: gcc/cp/cp-tree.h
===
--- gcc/cp/cp-tree.h(revision 279829)
+++ gcc/cp/cp-tree.h(working copy)
@@ -6720,9 +6720,10 @@ extern tree throw_bad_array_new_length   (void);
 extern bool type_has_new_extended_alignment(tree);
 extern unsigned malloc_alignment   (void);
 extern tree build_new_constexpr_heap_type  (tree, tree, tree);
-extern tree build_new  (vec **, tree, 
tree,
-vec **, int,
- tsubst_flags_t);
+extern tree build_new  (location_t,
+vec **, tree,
+tree, vec **,
+int, tsubst_flags_t);
 extern tree get_temp_regvar(tree, tree);
 extern tree build_vec_init (tree, tree, tree, bool, int,
  tsubst_flags_t);
Index: gcc/cp/init.c
===
--- gcc/cp/init.c   (revision 279829)
+++ gcc/cp/init.c   (working copy)
@@ -2396,8 +2396,8 @@ decl_constant_value (tree decl)
creates and returns a NEW_EXPR.  */
 
 static tree
-build_raw_new_expr (vec *placement, tree type, tree nelts,
-   vec *init, int use_global_new)
+build_raw_new_expr (location_t loc, vec *placement, tree type,
+   tree nelts, vec *init, int use_global_new)
 {
   tree init_list;
   tree new_expr;
@@ -2413,9 +2413,9 @@ static tree
   else
 init_list = build_tree_list_vec (init);
 
-  new_expr = build4 (NEW_EXPR, build_pointer_type (type),
-build_tree_list_vec (placement), type, nelts,
-init_list);
+  new_expr = build4_loc (loc, NEW_EXPR, build_pointer_type (type),
+build_tree_list_vec (placement), type, nelts,
+init_list);
   NEW_EXPR_USE_GLOBAL (new_expr) = use_global_new;
   TREE_SIDE_EFFECTS (new_expr) = 1;
 
@@ -3775,8 +3775,9 @@ build_new_1 (vec **placement, tree ty
rather than just "new".  This may change PLACEMENT and INIT.  */
 
 tree
-build_new (vec **placement, tree type, tree nelts,
-  vec **init, int use_global_new, tsubst_flags_t complain)
+build_new (location_t loc, vec **placement, tree type,
+  tree nelts, vec **init, int use_global_new,
+  tsubst_flags_t complain)
 {
   tree rval;
   vec *orig_placement = NULL;
@@ -3826,7 +3827,7 @@ tree
  || (nelts && type_dependent_expression_p (nelts))
  || (nelts && *init)
  || any_type_dependent_arguments_p (*init))
-   return build_raw_new_expr (*placement, type, nelts, *init,
+   return build_raw_new_expr (loc, *placement, type, nelts, *init,
   use_global_new);
 
   orig_placement = make_tree_vector_copy (*placement);
@@ -3852,10 +3853,11 @@ tree
 
   if (nelts)
 {
+  location_t nelts_loc = cp_expr_loc_or_loc (nelts, loc);
   if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false))
 {
   if (complain & tf_error)
-   permerror (cp_expr_loc_or_input_loc (nelts),
+   permerror (nelts_loc,
   "size in array new must have integral type");
   else
 return error_mark_node;
@@ -3871,8 +3873,7 @@ tree
 less than zero. ... If the expression is a constant expression,
 the program is ill-fomed.  */
   if (TREE_CODE (cst_nelts) == INTEGER_CST
- && !val

[C++ Patch] Improve build_new locations

2020-01-02 Thread Paolo Carlini

Hi,

some rather straightforward bits for build_new / 
cp_parser_new_expression, almost a clean-up. It would be nice to do 
better for the diagnostic issued from build_new_1 too but having 
consistent locations for all the valid_array_size_p and 
invalid_array_size_error calls isn't trivial, I'd rather work on that at 
a later time. Tested x86_64-linux.


Thanks, Paolo.

///

/gcc/cp
2020-01-02  Paolo Carlini  

* init.c (build_new): Add location_t parameter and use it throughout.
(build_raw_new_expr): Likewise.
* parser.c (cp_parser_new_expression): Pass the combined_loc.
* pt.c (tsubst_copy_and_build): Adjust call.
* cp-tree.h: Update declarations.

/libcc1
2020-01-02  Paolo Carlini  

* libcp1plugin.cc (plugin_build_new_expr): Update build_new call.

/gcc/testsuite
2020-01-02  Paolo Carlini  

* g++.old-deja/g++.bugs/900208_03.C: Check locations too.
* g++.old-deja/g++.bugs/900519_06.C: Likewise.
Index: gcc/cp/cp-tree.h
===
--- gcc/cp/cp-tree.h(revision 279768)
+++ gcc/cp/cp-tree.h(working copy)
@@ -6720,9 +6720,10 @@ extern tree throw_bad_array_new_length   (void);
 extern bool type_has_new_extended_alignment(tree);
 extern unsigned malloc_alignment   (void);
 extern tree build_new_constexpr_heap_type  (tree, tree, tree);
-extern tree build_new  (vec **, tree, 
tree,
-vec **, int,
- tsubst_flags_t);
+extern tree build_new  (location_t,
+vec **, tree,
+tree, vec **,
+int, tsubst_flags_t);
 extern tree get_temp_regvar(tree, tree);
 extern tree build_vec_init (tree, tree, tree, bool, int,
  tsubst_flags_t);
Index: gcc/cp/init.c
===
--- gcc/cp/init.c   (revision 279768)
+++ gcc/cp/init.c   (working copy)
@@ -2396,8 +2396,8 @@ decl_constant_value (tree decl)
creates and returns a NEW_EXPR.  */
 
 static tree
-build_raw_new_expr (vec *placement, tree type, tree nelts,
-   vec *init, int use_global_new)
+build_raw_new_expr (location_t loc, vec *placement, tree type,
+   tree nelts, vec *init, int use_global_new)
 {
   tree init_list;
   tree new_expr;
@@ -2413,9 +2413,9 @@ static tree
   else
 init_list = build_tree_list_vec (init);
 
-  new_expr = build4 (NEW_EXPR, build_pointer_type (type),
-build_tree_list_vec (placement), type, nelts,
-init_list);
+  new_expr = build4_loc (loc, NEW_EXPR, build_pointer_type (type),
+build_tree_list_vec (placement), type, nelts,
+init_list);
   NEW_EXPR_USE_GLOBAL (new_expr) = use_global_new;
   TREE_SIDE_EFFECTS (new_expr) = 1;
 
@@ -3775,8 +3775,9 @@ build_new_1 (vec **placement, tree ty
rather than just "new".  This may change PLACEMENT and INIT.  */
 
 tree
-build_new (vec **placement, tree type, tree nelts,
-  vec **init, int use_global_new, tsubst_flags_t complain)
+build_new (location_t loc, vec **placement, tree type,
+  tree nelts, vec **init, int use_global_new,
+  tsubst_flags_t complain)
 {
   tree rval;
   vec *orig_placement = NULL;
@@ -3826,7 +3827,7 @@ tree
  || (nelts && type_dependent_expression_p (nelts))
  || (nelts && *init)
  || any_type_dependent_arguments_p (*init))
-   return build_raw_new_expr (*placement, type, nelts, *init,
+   return build_raw_new_expr (loc, *placement, type, nelts, *init,
   use_global_new);
 
   orig_placement = make_tree_vector_copy (*placement);
@@ -3852,10 +3853,11 @@ tree
 
   if (nelts)
 {
+  location_t nelts_loc = cp_expr_loc_or_loc (nelts, loc);
   if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false))
 {
   if (complain & tf_error)
-   permerror (cp_expr_loc_or_input_loc (nelts),
+   permerror (nelts_loc,
   "size in array new must have integral type");
   else
 return error_mark_node;
@@ -3871,8 +3873,7 @@ tree
 less than zero. ... If the expression is a constant expression,
 the program is ill-fomed.  */
   if (TREE_CODE (cst_nelts) == INTEGER_CST
- && !valid_array_size_p (cp_expr_loc_or_input_loc (nelts),
- cst_nelts, NULL_TREE,
+ && !valid_array_size_p (nelts_loc, cst_nelts, NULL_TREE,
  complain & tf_error))

[C++ Patch] Improve delete expressions locations

2019-12-20 Thread Paolo Carlini

Hi,

more of the last idea, this time applied to cp_parser_delete_expression 
/ delete_sanity (thus build_delete and build_vec_delete which provide 
tests). Nothing particularly remarkable in this case. Tested x86_64-linux.


Thanks, Paolo.

///

/gcc/cp
2019-12-20  Paolo Carlini  

* decl2.c (delete_sanity): Add location_t parameter and use
it throughout.
* init.c (build_vec_delete_1): Likewise.
(build_delete): Likewise.
(build_vec_delete): Likewise.
(perform_target_ctor): Adjust call.
(perform_member_init): Likewise.
(build_vec_init): Likewise.
* decl.c (cxx_maybe_build_cleanup): Likewise.
* pt.c (tsubst_copy_and_build): Likewise.
* parser.c (cp_parser_delete_expression): Likewise, pass the
combined_loc.
* cp-tree.h: Update declarations.

/libcc1
2019-12-20  Paolo Carlini  

* libcp1plugin.cc (plugin_build_unary_expr): Update delete_sanity
call.

/gcc/testsuite
2019-12-18  Paolo Carlini  

* g++.dg/init/delete1.C: Check locations too.
* g++.dg/ipa/pr85607.C: Likewise.
* g++.dg/warn/Wdelete-incomplete-1.C: Likewise.
* g++.dg/warn/delete-non-virtual-dtor.C: Likewise.
* g++.dg/warn/incomplete1.C: Likewise.
Index: gcc/cp/cp-tree.h
===
--- gcc/cp/cp-tree.h(revision 279563)
+++ gcc/cp/cp-tree.h(working copy)
@@ -6583,7 +6583,8 @@ extern bool vague_linkage_p   (tree);
 extern void grokclassfn(tree, tree,
 enum overload_flags);
 extern tree grok_array_decl(location_t, tree, tree, bool);
-extern tree delete_sanity  (tree, tree, bool, int, 
tsubst_flags_t);
+extern tree delete_sanity  (location_t, tree, tree, bool,
+int, tsubst_flags_t);
 extern tree check_classfn  (tree, tree, tree);
 extern void check_member_template  (tree);
 extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *,
@@ -6725,11 +6726,11 @@ extern tree build_new   
(vec **, tre
 extern tree get_temp_regvar(tree, tree);
 extern tree build_vec_init (tree, tree, tree, bool, int,
  tsubst_flags_t);
-extern tree build_delete   (tree, tree,
+extern tree build_delete   (location_t, tree, tree,
 special_function_kind,
 int, int, tsubst_flags_t);
 extern void push_base_cleanups (void);
-extern tree build_vec_delete   (tree, tree,
+extern tree build_vec_delete   (location_t, tree, tree,
 special_function_kind, int,
 tsubst_flags_t);
 extern tree create_temporary_var   (tree);
Index: gcc/cp/decl.c
===
--- gcc/cp/decl.c   (revision 279563)
+++ gcc/cp/decl.c   (working copy)
@@ -17311,7 +17311,7 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t
   else
addr = build_address (decl);
 
-  call = build_delete (TREE_TYPE (addr), addr,
+  call = build_delete (input_location, TREE_TYPE (addr), addr,
   sfk_complete_destructor, flags, 0, complain);
   if (call == error_mark_node)
cleanup = error_mark_node;
Index: gcc/cp/decl2.c
===
--- gcc/cp/decl2.c  (revision 279563)
+++ gcc/cp/decl2.c  (working copy)
@@ -475,8 +475,8 @@ grok_array_decl (location_t loc, tree array_expr,
Implements ARM $5.3.4.  This is called from the parser.  */
 
 tree
-delete_sanity (tree exp, tree size, bool doing_vec, int use_global_delete,
-  tsubst_flags_t complain)
+delete_sanity (location_t loc, tree exp, tree size, bool doing_vec,
+  int use_global_delete, tsubst_flags_t complain)
 {
   tree t, type;
 
@@ -489,14 +489,16 @@ tree
   DELETE_EXPR_USE_GLOBAL (t) = use_global_delete;
   DELETE_EXPR_USE_VEC (t) = doing_vec;
   TREE_SIDE_EFFECTS (t) = 1;
+  SET_EXPR_LOCATION (t, loc);
   return t;
 }
 
+  location_t exp_loc = cp_expr_loc_or_loc (exp, loc);
+
   /* An array can't have been allocated by new, so complain.  */
   if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
   && (complain & tf_warning))
-warning_at (cp_expr_loc_or_input_loc (exp), 0,
-   "deleting array %q#E", exp);
+warning_at (exp_loc, 0, "deleting array %q#E", exp);
 
   t = build_expr_type_conversion (WANT_POINTER

[C++ Patch] Improve throw, sizeof, and alignof locations & more

2019-12-16 Thread Paolo Carlini

Hi,

another batch of work. Primarily, more of the idea of moving up the 
construction of the compound location thus passing it to the 
cxx_sizeof_or_alignof* and build_throw functions to obtain better 
locations for all the diagnostics issued by the latter. During the work 
a few mildly interesting nits (eg, for sizeof and alignof we want to set 
whenever possible the location inside the cxx_* functions and that 
allows to avoid set_location in cp_parser_unary_expression, but 
minimally we have to pass it to the cp_expr constructor, otherwise 
plugin testcases badly fail; noticed that in cxx_sizeof_expr and 
cxx_alignof_expr having a single cp_expr_loc_or_input_loc on top 
actually implies better locations (4 testcases) because below, before 
the diagnostic calls, we have STRIP_ANY_LOCATION_WRAPPER uses; in fact I 
changed those cp_expr_loc_or_input_loc to cp_expr_loc_or_loc because for 
expressions we still want to try fetching the locations but we do have a 
meaningful fallback in the location argument of the function; in 
build_throw, an error should be an inform, because in such cases we 
already issued an error (tested in ctor1.C)) but nothing major. The 
below includes a few other minor changes, like two additional uses of 
DECL_SOURCE_LOCATION, cp_expr_loc_or_input_loc, removal of an unused 
function.


Tested x86_64-linux.

Thanks, Paolo.

//

/gcc/cp
2019-12-16  Paolo Carlini  

* typeck.c (cxx_sizeof_or_alignof_type): Add location_t parameter
and use it throughout.
(cxx_sizeof_expr): Likewise.
(cxx_alignof_expr): Likewise.
(cxx_sizeof_or_alignof_expr): Likewise.
(cxx_alignas_expr): Update call.
* decl.c (fold_sizeof_expr): Likewise.
* pt.c (tsubst_copy): Likewise.
(tsubst_copy_and_build): Likewise.
* except.c (build_throw): Add location_t parameter and use it.
(expand_end_catch_block): Update call.
* parser.c (cp_parser_unary_expression): Update
cxx_sizeof_or_alignof_type and cxx_sizeof_or_alignof_expr calls,
pass the compound location.
(cp_parser_throw_expression): Likewise pass the combined location
to build_throw.
* cp-tree.h: Update declarations.

* semantics.c (finish_handler_parms): Use DECL_SOURCE_LOCATION.
* decl2.c (check_classfn): Likewise.

* except.c (is_admissible_throw_operand_or_catch_parameter):
Exploit cp_expr_loc_or_input_loc in one place.

* except.c (create_try_catch_expr): Remove, unused.

/libcc1
2019-12-16  Paolo Carlini  

* libcp1plugin.cc (plugin_build_unary_expr): Update build_throw
and cxx_sizeof_or_alignof_expr calls.
(plugin_build_unary_type_expr): Likewise for
cxx_sizeof_or_alignof_type.

/gcc/testsuite
2019-12-16  Paolo Carlini  

* g++.dg/diagnostic/alignof2.C: New.
* g++.dg/diagnostic/alignof3.C: Likewise.
* g++.dg/diagnostic/incomplete-type-1.C: Likewise.
* g++.dg/warn/Wcatch-value-3b.C: Likewise.
* g++.dg/cpp0x/alignof3.C: Check location(s) too.
* g++.dg/cpp1z/decomp-bitfield1.C: Likewise.
* g++.dg/cpp1z/has-unique-obj-representations2.C: Likewise.
* g++.dg/expr/sizeof3.C: Likewise.
* g++.dg/ext/flexary6.C: Likewise.
* g++.dg/ext/vla4.C: Likewise.
* g++.dg/template/sizeof11.C: Likewise.
* g++.dg/warn/Wcatch-value-1.C: Likewise.
* g++.dg/warn/Wcatch-value-2.C: Likewise.
* g++.dg/warn/Wcatch-value-3.C: Likewise.
* g++.old-deja/g++.brendan/sizeof1.C: Likewise.
* g++.old-deja/g++.brendan/sizeof3.C: Likewise.
* g++.old-deja/g++.brendan/sizeof4.C: Likewise.
* g++.old-deja/g++.eh/ctor1.C: Likewise.
* g++.old-deja/g++.jason/ambig1.C: Likewise.
* g++.old-deja/g++.other/sizeof4.C: Likewise.
Index: gcc/cp/cp-tree.h
===
--- gcc/cp/cp-tree.h(revision 279371)
+++ gcc/cp/cp-tree.h(working copy)
@@ -6657,7 +6657,7 @@ extern void init_exception_processing (void);
 extern tree expand_start_catch_block   (tree);
 extern void expand_end_catch_block (void);
 extern tree build_exc_ptr  (void);
-extern tree build_throw(tree);
+extern tree build_throw(location_t, tree);
 extern int nothrow_libfn_p (const_tree);
 extern void check_handlers (tree);
 extern tree finish_noexcept_expr   (tree, tsubst_flags_t);
@@ -6674,7 +6674,6 @@ extern tree begin_eh_spec_block   (void);
 extern void finish_eh_spec_block   (tree, tree);
 extern tree build_eh_type_type (tree);
 extern tree cp_protect_cleanup_actions (void);
-extern tree create_try_catch_expr   (tree, tree);
 extern tree template_parms_to_args

Re: [C++ Patch] Improve build_*_cast locations

2019-12-09 Thread Paolo Carlini

Hi,

On 08/12/19 18:51, Jason Merrill wrote:
Hmm, is the change to cp_expr really necessary vs. using 
protected_set_expr_location?


Yes, using protected_set_expr_location works fine in this case, I 
suppose because we are dealing with expressions anyway plus the cp_expr 
constructor from a tree copies the location too. In the below I also 
added the thin build_functional_case wrapper, this way consistently all 
the build_*_cast functions called by the parser do not use set_location 
afterwards. Note, at some point we should also do something about the 
build_x_* functions which have been doing that for a while...


Anyway, the below passed testing.

Thanks, Paolo.



Index: gcc/cp/cp-tree.h
===
--- gcc/cp/cp-tree.h(revision 279041)
+++ gcc/cp/cp-tree.h(working copy)
@@ -6998,7 +6998,8 @@ extern tree build_typeid  (tree, 
tsubst_flags_t);
 extern tree get_tinfo_decl (tree);
 extern tree get_typeid (tree, tsubst_flags_t);
 extern tree build_headof   (tree);
-extern tree build_dynamic_cast (tree, tree, tsubst_flags_t);
+extern tree build_dynamic_cast (location_t, tree, tree,
+tsubst_flags_t);
 extern void emit_support_tinfos(void);
 extern bool emit_tinfo_decl(tree);
 
@@ -7547,13 +7548,17 @@ extern tree build_x_compound_expr   
(location_t, tr
 tsubst_flags_t);
 extern tree build_compound_expr (location_t, tree, tree);
 extern tree cp_build_compound_expr (tree, tree, tsubst_flags_t);
-extern tree build_static_cast  (tree, tree, tsubst_flags_t);
-extern tree build_reinterpret_cast (tree, tree, tsubst_flags_t);
-extern tree build_const_cast   (tree, tree, tsubst_flags_t);
+extern tree build_static_cast  (location_t, tree, tree,
+tsubst_flags_t);
+extern tree build_reinterpret_cast (location_t, tree, tree,
+tsubst_flags_t);
+extern tree build_const_cast   (location_t, tree, tree,
+tsubst_flags_t);
 extern tree build_c_cast   (location_t, tree, tree);
 extern cp_expr build_c_cast(location_t loc, tree type,
 cp_expr expr);
-extern tree cp_build_c_cast(tree, tree, tsubst_flags_t);
+extern tree cp_build_c_cast(location_t, tree, tree,
+tsubst_flags_t);
 extern cp_expr build_x_modify_expr (location_t, tree,
 enum tree_code, tree,
 tsubst_flags_t);
@@ -7613,7 +7618,8 @@ extern int lvalue_or_else (tree, enum 
lvalue_use
 extern void check_template_keyword (tree);
 extern bool check_raw_literal_operator (const_tree decl);
 extern bool check_literal_operator_args(const_tree, bool *, 
bool *);
-extern void maybe_warn_about_useless_cast   (tree, tree, tsubst_flags_t);
+extern void maybe_warn_about_useless_cast   (location_t, tree, tree,
+tsubst_flags_t);
 extern tree cp_perform_integral_promotions  (tree, tsubst_flags_t);
 
 extern tree finish_left_unary_fold_expr  (tree, int);
Index: gcc/cp/decl.c
===
--- gcc/cp/decl.c   (revision 279041)
+++ gcc/cp/decl.c   (working copy)
@@ -6483,7 +6483,8 @@ reshape_init (tree type, tree init, tsubst_flags_t
{
  warning_sentinel w (warn_useless_cast);
  warning_sentinel w2 (warn_ignored_qualifiers);
- return cp_build_c_cast (type, elt, tf_warning_or_error);
+ return cp_build_c_cast (input_location, type, elt,
+ tf_warning_or_error);
}
   else
return error_mark_node;
Index: gcc/cp/method.c
===
--- gcc/cp/method.c (revision 279041)
+++ gcc/cp/method.c (working copy)
@@ -474,7 +474,8 @@ forward_parm (tree parm)
   if (!TYPE_REF_P (type))
 type = cp_build_reference_type (type, /*rval=*/true);
   warning_sentinel w (warn_useless_cast);
-  exp = build_static_cast (type, exp, tf_warning_or_error);
+  exp = build_static_cast (input_location, type, exp,
+  tf_warning_or_error);
   if (DECL_PACK_P (parm))
 exp = make_pack_expansion (exp);
   return exp;
@@ -1361,7 +1362,8 @@ build_comparison_op (tree fndecl, 

Re: [C++ Patch] Improve build_*_cast locations

2019-12-06 Thread Paolo Carlini

Hi,

On 06/12/19 18:53, Jason Merrill wrote:

On 12/6/19 11:14 AM, Paolo Carlini wrote:

Hi,

as promised, the below takes care of the various remaining casts. 
It's mostly mechanical, follows the same approach used for 
build_functional_cast. Tested x86_64-linux.


It occurs to me that once we're passing the location into the build_* 
functions, we can apply it to the expression there rather than in the 
parser.


In fact that occurred to me too ;) but at first I didn't like the idea 
of multiplying the set_location calls... Anyway, in practice for the 
casts of this last patch the idea works reasonably well, because most of 
the complexity is encapsulated in the *_1 versions of the functions and 
the build_* functions proper have only a couple of returns. I wanted to 
send those changes... But then my build failed in the libcp1plugin.cc 
bits because the switch also includes c_cast and all the functions must 
return the same type. And then for consistency we want also to adjust 
functional_cast (which allows to remove the set_location in the parser 
which also remained after my previous patch). Those two cast however are 
more annoying, because there aren't *_1 counterparts and the functions 
have *lots* of returns, are complicated. Thus for those I'm proposing to 
create ad hoc *_1 identical to the current functions in order to have 
single set_location in cp_build_c_cast and build_functional_cast. All in 
all, I don't have better ideas... I'm finishing testing the below.


Thanks, Paolo.

//

Index: gcc/cp/cp-tree.h
===
--- gcc/cp/cp-tree.h(revision 279041)
+++ gcc/cp/cp-tree.h(working copy)
@@ -6998,7 +6998,8 @@ extern tree build_typeid  (tree, 
tsubst_flags_t);
 extern tree get_tinfo_decl (tree);
 extern tree get_typeid (tree, tsubst_flags_t);
 extern tree build_headof   (tree);
-extern tree build_dynamic_cast (tree, tree, tsubst_flags_t);
+extern cp_expr build_dynamic_cast  (location_t, tree, tree,
+tsubst_flags_t);
 extern void emit_support_tinfos(void);
 extern bool emit_tinfo_decl(tree);
 
@@ -7547,13 +7548,17 @@ extern tree build_x_compound_expr   
(location_t, tr
 tsubst_flags_t);
 extern tree build_compound_expr (location_t, tree, tree);
 extern tree cp_build_compound_expr (tree, tree, tsubst_flags_t);
-extern tree build_static_cast  (tree, tree, tsubst_flags_t);
-extern tree build_reinterpret_cast (tree, tree, tsubst_flags_t);
-extern tree build_const_cast   (tree, tree, tsubst_flags_t);
+extern cp_expr build_static_cast   (location_t, tree, tree,
+tsubst_flags_t);
+extern cp_expr build_reinterpret_cast  (location_t, tree, tree,
+tsubst_flags_t);
+extern cp_expr build_const_cast(location_t, tree, tree,
+tsubst_flags_t);
 extern tree build_c_cast   (location_t, tree, tree);
 extern cp_expr build_c_cast(location_t loc, tree type,
 cp_expr expr);
-extern tree cp_build_c_cast(tree, tree, tsubst_flags_t);
+extern cp_expr cp_build_c_cast (location_t, tree, tree,
+tsubst_flags_t);
 extern cp_expr build_x_modify_expr (location_t, tree,
 enum tree_code, tree,
 tsubst_flags_t);
@@ -7613,7 +7618,8 @@ extern int lvalue_or_else (tree, enum 
lvalue_use
 extern void check_template_keyword (tree);
 extern bool check_raw_literal_operator (const_tree decl);
 extern bool check_literal_operator_args(const_tree, bool *, 
bool *);
-extern void maybe_warn_about_useless_cast   (tree, tree, tsubst_flags_t);
+extern void maybe_warn_about_useless_cast   (location_t, tree, tree,
+tsubst_flags_t);
 extern tree cp_perform_integral_promotions  (tree, tsubst_flags_t);
 
 extern tree finish_left_unary_fold_expr  (tree, int);
@@ -7681,7 +7687,7 @@ extern tree build_scoped_ref  (tree, 
tree, tree *
 extern tree build_x_arrow  (location_t, tree,
 tsubst_flags_t);
 extern tree build_m_component_ref  (tree, tree, tsubst_flags_t);
-extern tree build_functional_cast  (location_t, tree, tree,
+extern cp_expr build_functional_cast

[C++ Patch] Improve build_*_cast locations

2019-12-06 Thread Paolo Carlini

Hi,

as promised, the below takes care of the various remaining casts. It's 
mostly mechanical, follows the same approach used for 
build_functional_cast. Tested x86_64-linux.


Thanks, Paolo.



gcc/cp
2019-12-06  Paolo Carlini  

* typeck.c (check_for_casting_away_constness): Add location_t
parameter and use it.
(maybe_warn_about_useless_cast): Likewise.
(maybe_warn_about_cast_ignoring_quals): Likewise.
(build_static_cast_1): Likewise.
(build_static_cast): Likewise.
(build_reinterpret_cast_1): Likewise.
(build_reinterpret_cast): Likewise.
(build_const_cast_1): Likewise.
(build_const_cast): Likewise.
(cp_build_c_cast): Likewise.
(build_c_cast): Adjust.
(build_ptrmemfunc): Adjust calls.
(cp_build_unary_op): Pass the location to invert_truthvalue_loc.
* rtti.c (build_dynamic_cast_1): Add location_t parameter and
use it.
(build_dynamic_cast): Likewise.
* cp-tree.h: Adjust declarations.
* parser.c (cp_parser_postfix_expression): Pass cp_cast_loc to
the various build_*_cast functions.
(get_cast_suggestion): Adjust calls.
(cp_parser_builtin_offsetof): Likewise.
* decl.c (reshape_init): Adjust call.
* method.c (forward_parm): Likewise.
(build_comparison_op): Likewise.
* pt.c (tsubst_copy_and_build): Likewise.
* semantics.c (finish_omp_reduction_clause): Likewise.
(cp_omp_finish_iterators): Likewise.
* tree.c (cp_stabilize_reference): Likewise.
(move): Likewise.
* typeck2.c (build_functional_cast): Likewise.

/libcc1
2019-12-06  Paolo Carlini  

* libcp1plugin.cc (plugin_build_cast_expr): Adjust build_cast
declaration.

gcc/testsuite
2019-12-06  Paolo Carlini  

* c-c++-common/Wcast-align.c: Check location(s) too.
* c-c++-common/Wcast-function-type.c: Likewise.
* c-c++-common/Wint-to-pointer-cast-1.c: Likewise.
* c-c++-common/Wint-to-pointer-cast-2.c: Likewise.
* c-c++-common/Wint-to-pointer-cast-3.c: Likewise.
* g++.dg/Wcast-function-type.C: Likewise.
* g++.dg/addr_builtin-1.C: Likewise.
* g++.dg/conversion/const2.C: Likewise.
* g++.dg/conversion/dynamic1.C: Likewise.
* g++.dg/conversion/ptrmem2.C: Likewise.
* g++.dg/conversion/ptrmem3.C: Likewise.
* g++.dg/conversion/qual3.C: Likewise.
* g++.dg/conversion/reinterpret3.C: Likewise.
* g++.dg/cpp0x/lambda/lambda-conv11.C: Likewise.
* g++.dg/cpp0x/nullptr04.C: Likewise.
* g++.dg/cpp0x/reinterpret_cast2.C: Likewise.
* g++.dg/cpp0x/rv-cast2.C: Likewise.
* g++.dg/cpp1y/lambda-conv1.C: Likewise.
* g++.dg/cpp1z/noexcept-type7.C: Likewise.
* g++.dg/cpp2a/array-conv9.C: Likewise.
* g++.dg/expr/cast11.C: Likewise.
* g++.dg/expr/static_cast8.C: Likewise.
* g++.dg/ext/vector6.C: Likewise.
* g++.dg/other/conversion1.C: Likewise.
* g++.dg/parse/pr26997.C: Likewise.
* g++.dg/rtti/no-rtti.C: Likewise.
* g++.dg/tc1/dr137.C: Likewise.
* g++.dg/template/cast4.C: Likewise.
* g++.dg/warn/Wcast-qual1.C: Likewise.
* g++.dg/warn/Wcast-qual2.C: Likewise.
* g++.dg/warn/Wconditionally-supported-1.C: Likewise.
* g++.dg/warn/Wuseless-cast.C: Likewise.
* g++.dg/warn/pr35711.C: Likewise.
* g++.old-deja/g++.bugs/900227_01.C: Likewise.
* g++.old-deja/g++.bugs/900404_07.C: Likewise.
* g++.old-deja/g++.jason/overload1.C: Likewise.
* g++.old-deja/g++.jason/rfg26.C: Likewise.
* g++.old-deja/g++.jason/rvalue3.C: Likewise.
* g++.old-deja/g++.jason/warning2.C: Likewise.
* g++.old-deja/g++.mike/dyncast4.C: Likewise.
* g++.old-deja/g++.mike/dyncast6.C: Likewise.
* g++.old-deja/g++.mike/p11482.C: Likewise.
* g++.old-deja/g++.mike/p2573.C: Likewise.
* g++.old-deja/g++.mike/p2855.C: Likewise.
* g++.old-deja/g++.mike/p7476.C: Likewise.
* g++.old-deja/g++.mike/p8039.C: Likewise.
* g++.old-deja/g++.other/cast2.C: Likewise.
* g++.old-deja/g++.other/cast3.C: Likewise.
* g++.old-deja/g++.other/dcast1.C: Likewise.
* g++.old-deja/g++.other/dcast2.C: Likewise.

Index: gcc/cp/cp-tree.h
===
--- gcc/cp/cp-tree.h(revision 279041)
+++ gcc/cp/cp-tree.h(working copy)
@@ -6998,7 +6998,8 @@ extern tree build_typeid  (tree, 
tsubst_flags_t);
 extern tree get_tinfo_decl (tree);
 extern tree get_typeid (tree, tsubst_flags_t);
 extern tree build_headof   (tree);
-extern tree build_dynamic_cast (tree, tree, tsubst_flags_t);
+extern tree build_dynamic_cast (location_t, tree

[C++ Patch] Improve build_functional_cast locations

2019-12-04 Thread Paolo Carlini

Hi,

this exemplifies in a compact way the kind of change we can implement 
for the other casts too: near the end of cp_parser_functional_cast 
instead of using the combined_loc only for the returned cp_expr we can 
also pass it to build_functional_cast. Tested x86_64-linux.


Thanks, Paolo.

///

/gcc/cp
2019-12-04  Paolo Carlini  

* typeck2.c (build_functional_cast): Add location_t parameter
and use it.
* cp-tree.h: Update declaration.
* parser.c (cp_parser_functional_cast): Adjust call.
* call.c (build_op_delete_call): Likewise.
(build_new_method_call_1): Likewise.
* decl.c (check_initializer): Likewise.
* pt.c (tsubst_copy_and_build): Likewise.
* semantics.c (finish_compound_literal): Likewise.

/libcc1
2019-12-04  Paolo Carlini  

* libcp1plugin.cc (plugin_build_expression_list_expr): Adjust
build_functional_cast call.

/testsuite
2019-12-04  Paolo Carlini  

* g++.dg/diagnostic/functional-cast-to-array-type-1.C: New.
* g++.dg/cpp0x/auto25.C: Check location(s) too.
* g++.dg/cpp0x/auto28.C: Likewise.
* g++.dg/init/reference2.C: Likewise.
* g++.dg/parse/template2.C: Likewise.
* g++.dg/template/error8.C: Likewise.
* g++.old-deja/g++.ns/crash3.C: Likewise.
* g++.old-deja/g++.ns/template7.C: Likewise.
* g++.old-deja/g++.pt/crash8.C: Likewise.
Index: gcc/cp/call.c
===
--- gcc/cp/call.c   (revision 278959)
+++ gcc/cp/call.c   (working copy)
@@ -6933,7 +6933,8 @@ build_op_delete_call (enum tree_code code, tree ad
  rtype = cv_unqualified (rtype);
  rtype = TYPE_POINTER_TO (rtype);
  addr = cp_convert (rtype, oaddr, complain);
- destroying = build_functional_cast (destroying, NULL_TREE,
+ destroying = build_functional_cast (input_location,
+ destroying, NULL_TREE,
  complain);
}
 
@@ -9997,7 +9998,8 @@ build_new_method_call_1 (tree instance, tree fns,
 basetype, name))
inform (input_location, "for a function-style cast, remove the "
"redundant %<::%D%>", name);
-  call = build_functional_cast (basetype, build_tree_list_vec (user_args),
+  call = build_functional_cast (input_location, basetype,
+   build_tree_list_vec (user_args),
complain);
   return call;
 }
Index: gcc/cp/cp-tree.h
===
--- gcc/cp/cp-tree.h(revision 278959)
+++ gcc/cp/cp-tree.h(working copy)
@@ -7681,7 +7681,8 @@ extern tree build_scoped_ref  (tree, 
tree, tree *
 extern tree build_x_arrow  (location_t, tree,
 tsubst_flags_t);
 extern tree build_m_component_ref  (tree, tree, tsubst_flags_t);
-extern tree build_functional_cast  (tree, tree, tsubst_flags_t);
+extern tree build_functional_cast  (location_t, tree, tree,
+tsubst_flags_t);
 extern tree add_exception_specifier(tree, tree, tsubst_flags_t);
 extern tree merge_exception_specifiers (tree, tree);
 
Index: gcc/cp/decl.c
===
--- gcc/cp/decl.c   (revision 278959)
+++ gcc/cp/decl.c   (working copy)
@@ -6764,7 +6764,8 @@ check_initializer (tree decl, tree init, int flags
  if (CLASS_TYPE_P (type)
  && (!init || TREE_CODE (init) == TREE_LIST))
{
- init = build_functional_cast (type, init, tf_none);
+ init = build_functional_cast (input_location, type,
+   init, tf_none);
  if (TREE_CODE (init) == TARGET_EXPR)
TARGET_EXPR_DIRECT_INIT_P (init) = true;
}
Index: gcc/cp/parser.c
===
--- gcc/cp/parser.c (revision 278959)
+++ gcc/cp/parser.c (working copy)
@@ -29268,8 +29268,17 @@ cp_parser_functional_cast (cp_parser* parser, tree
   release_tree_vector (vec);
 }
 
-  cast = build_functional_cast (type, expression_list,
+  /* Create a location of the form:
+   float(i)
+   ^~~~
+ with caret == start at the start of the type name,
+ finishing at the closing paren.  */
+  location_t combined_loc = make_location (start_loc, start_loc,
+  parser->lexer);
+  cast = build_functional_cast (combined_loc, type, expression_list,
 tf_warning_or_error

Re: [C++ Patch] A few more cp_expr_loc_or_input_loc and a diagnostic regression fix

2019-12-02 Thread Paolo Carlini

Hi,

On 02/12/19 19:58, Jason Merrill wrote:

On 11/29/19 8:08 AM, Paolo Carlini wrote:

Hi,

a few more rather straightforward uses for cp_expr_loc_or_input_loc.

Additionally, while working on the latter, I noticed that, compared 
to say, gcc-7, lately the code we have in cp_build_addr_expr_1 to 
diagnose taking the address of 'main' often doesn't work anymore, 
when the argument is wrapped in a location_wrapper. The below fixes 
that by using tree_strip_any_location_wrapper in the DECL_MAIN_P 
check, which works fine, but I can imagine various other ways to 
solve the issue...


Maybe

location_t loc = cp_expr_loc_or_input_loc (arg);
STRIP_ANY_LOCATION_WRAPPER (arg);

at the top?  In general I prefer the local variable to writing 
cp_expr_loc_or_input_loc in lots of places, whether or not we then 
strip wrappers.


Sure. In a few circumstances I hesitated because 
cp_expr_loc_or_input_loc isn't really trivial, boils down to quite a few 
conditionals, and adds a bit to the complexity of simple functions when 
in fact no errors nor warnings are issued. But certainly calling it at 
the top is often much cleaner. I changed both the functions.


However, using STRIP_ANY_LOCATION_WRAPPER at the beginning of 
cp_build_addr_expr_1 doesn't seem straightforward, causes a few 
regressions (wrong location for conversion/Wwrite-strings.C; even an ICE 
for cpp1z/constexpr-lambda23.C; cpp1z/decomp48.C). The function doesn't 
seem trivial from this point of view, there is already a localized 
tree_strip_any_location_wrapper near the end, for 
processing_template_decl. I would rather further investigate that kind 
of simplification in a separate patch, beyond the regression fix. 
(before I would like to improve the locations for all the various kinds 
of cast, quite a few changes)


Thanks, Paolo.

///


Index: cp/typeck.c
===
--- cp/typeck.c (revision 278911)
+++ cp/typeck.c (working copy)
@@ -6061,6 +6061,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
 {
   tree argtype;
   tree val;
+  location_t loc;
 
   if (!arg || error_operand_p (arg))
 return error_mark_node;
@@ -6070,6 +6071,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
 return error_mark_node;
 
   argtype = lvalue_type (arg);
+  loc = cp_expr_loc_or_input_loc (arg);
 
   gcc_assert (!(identifier_p (arg) && IDENTIFIER_ANY_OP_P (arg)));
 
@@ -6103,12 +6105,14 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
  else if (current_class_type
   && TREE_OPERAND (arg, 0) == current_class_ref)
/* An expression like   */
-   permerror (input_location, "ISO C++ forbids taking the address of 
an unqualified"
+   permerror (loc,
+  "ISO C++ forbids taking the address of an unqualified"
   " or parenthesized non-static member function to form"
   " a pointer to member function.  Say %<&%T::%D%>",
   base, name);
  else
-   permerror (input_location, "ISO C++ forbids taking the address of a 
bound member"
+   permerror (loc,
+  "ISO C++ forbids taking the address of a bound member"
   " function to form a pointer to member function."
   "  Say %<&%T::%D%>",
   base, name);
@@ -6135,7 +6139,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
   if (kind == clk_none)
{
  if (complain & tf_error)
-   lvalue_error (cp_expr_loc_or_input_loc (arg), lv_addressof);
+   lvalue_error (loc, lv_addressof);
  return error_mark_node;
}
   if (strict_lvalue && (kind & (clk_rvalueref|clk_class)))
@@ -6143,8 +6147,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
  if (!(complain & tf_error))
return error_mark_node;
  /* Make this a permerror because we used to accept it.  */
- permerror (cp_expr_loc_or_input_loc (arg),
-"taking address of rvalue");
+ permerror (loc, "taking address of rvalue");
}
 }
 
@@ -6154,13 +6157,13 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
   arg = build1 (CONVERT_EXPR, type, arg);
   return arg;
 }
-  else if (pedantic && DECL_MAIN_P (arg))
+  else if (pedantic && DECL_MAIN_P (tree_strip_any_location_wrapper (arg)))
 {
   /* ARM $3.4 */
   /* Apparently a lot of autoconf scripts for C++ packages do this,
 so only complain if -Wpedantic.  */
   if (complain & (flag_pedantic_errors ? tf_error : tf_warning))
-   pedwarn (input_location, OPT_Wpedantic,
+   pedwarn (loc, OPT_Wpedantic,
 "ISO C++ forbids taking address of functio

[C++ Patch] A few more cp_expr_loc_or_input_loc and a diagnostic regression fix

2019-11-29 Thread Paolo Carlini

Hi,

a few more rather straightforward uses for cp_expr_loc_or_input_loc.

Additionally, while working on the latter, I noticed that, compared to 
say, gcc-7, lately the code we have in cp_build_addr_expr_1 to diagnose 
taking the address of 'main' often doesn't work anymore, when the 
argument is wrapped in a location_wrapper. The below fixes that by using 
tree_strip_any_location_wrapper in the DECL_MAIN_P check, which works 
fine, but I can imagine various other ways to solve the issue... Tested 
x86_64-linux.


Thanks, Paolo.

//

/cp
2019-11-29  Paolo Carlini  

* typeck.c (cp_build_addr_expr_1): Use cp_expr_loc_or_input_loc in a
few additional places.
(check_return_expr): Likewise.

* typeck.c (cp_build_addr_expr_1): Use tree_strip_any_location_wrapper
for address of main pedwarn.

/testsuite
2019-11-29  Paolo Carlini  

* g++.dg/diagnostic/inconsistent-deduction-1.C: New.
* g++.dg/diagnostic/returning-a-value-1.C: Likewise.
* g++.dg/cpp0x/decltype3.C: Check location(s) too.
* g++.dg/cpp0x/decltype4.C: Likewise.
* g++.dg/cpp0x/lambda/lambda-deduce-ext-neg.C: Likewise.
* g++.dg/cpp2a/consteval13.C: Likewise.
* g++.dg/expr/pmf-1.C: Likewise.
* g++.dg/other/ptrmem2.C: Likewise.
* g++.dg/template/ptrmem17.C: Likewise.
* g++.old-deja/g++.bugs/900213_03.C: Likewise.
* g++.old-deja/g++.other/pmf7.C: Likewise.
* g++.old-deja/g++.other/ptrmem7.C: Likewise.

* g++.dg/diagnostic/main2.C: New.
Index: cp/typeck.c
===
--- cp/typeck.c (revision 278834)
+++ cp/typeck.c (working copy)
@@ -6103,12 +6103,14 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
  else if (current_class_type
   && TREE_OPERAND (arg, 0) == current_class_ref)
/* An expression like   */
-   permerror (input_location, "ISO C++ forbids taking the address of 
an unqualified"
+   permerror (cp_expr_loc_or_input_loc (arg),
+  "ISO C++ forbids taking the address of an unqualified"
   " or parenthesized non-static member function to form"
   " a pointer to member function.  Say %<&%T::%D%>",
   base, name);
  else
-   permerror (input_location, "ISO C++ forbids taking the address of a 
bound member"
+   permerror (cp_expr_loc_or_input_loc (arg),
+  "ISO C++ forbids taking the address of a bound member"
   " function to form a pointer to member function."
   "  Say %<&%T::%D%>",
   base, name);
@@ -6154,13 +6156,13 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
   arg = build1 (CONVERT_EXPR, type, arg);
   return arg;
 }
-  else if (pedantic && DECL_MAIN_P (arg))
+  else if (pedantic && DECL_MAIN_P (tree_strip_any_location_wrapper (arg)))
 {
   /* ARM $3.4 */
   /* Apparently a lot of autoconf scripts for C++ packages do this,
 so only complain if -Wpedantic.  */
   if (complain & (flag_pedantic_errors ? tf_error : tf_warning))
-   pedwarn (input_location, OPT_Wpedantic,
+   pedwarn (cp_expr_loc_or_input_loc (arg), OPT_Wpedantic,
 "ISO C++ forbids taking address of function %<::main%>");
   else if (flag_pedantic_errors)
return error_mark_node;
@@ -6218,7 +6220,8 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
if (TYPE_REF_P (TREE_TYPE (t)))
  {
if (complain & tf_error)
- error ("cannot create pointer to reference member %qD", t);
+ error_at (cp_expr_loc_or_input_loc (arg),
+   "cannot create pointer to reference member %qD", t);
return error_mark_node;
  }
 
@@ -6254,8 +6257,9 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
  || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl)))
{
  if (complain & tf_error)
-   error ("taking address of an immediate function %qD",
-  stripped_arg);
+   error_at (cp_expr_loc_or_input_loc (arg),
+ "taking address of an immediate function %qD",
+ stripped_arg);
  return error_mark_node;
}
   if (TREE_CODE (stripped_arg) == FUNCTION_DECL
@@ -9689,7 +9693,8 @@ check_return_expr (tree retval, bool *no_warning)
   if (DECL_DESTRUCTOR_P (current_function_decl))
 {
   if (retval)
-   error ("returning a value from a destructor");
+   error_at (cp_expr_loc_or_input_loc (retval),
+ "returning a value from a destructor");
  

[C++ Patch] More accurate locations in cp_build_unary_op and cp_build_compound_expr

2019-11-25 Thread Paolo Carlini

Hi,

a bunch of straightforward tweaks: let's use the available location in 
some additional places. Tested x86_64-linux, as usual.


Thanks, Paolo.

///

/cp
2019-11-15  Paolo Carlini  

* typeck.c (cp_build_unary_op): Consistently use the accurate
location in seven additional diagnostic messages.
(cp_build_compound_expr): Use cp_expr_loc_or_input_loc in one place.

/testsuite
2019-11-15  Paolo Carlini  

* g++.dg/cpp1z/bool-increment1.C: Test location(s) too.
* g++.dg/expr/bitfield3.C: Likewise.
* g++.dg/expr/bitfield4.C: Likewise.
* g++.dg/expr/bitfield5.C: Likewise.
* g++.dg/expr/bitfield6.C: Likewise.
* g++.dg/expr/bool1.C: Likewise.
* g++.dg/expr/bool2.C: Likewise.
* g++.dg/expr/bool3.C: Likewise.
* g++.dg/expr/bool4.C: Likewise.
* g++.dg/expr/lval3.C: Likewise.
* g++.dg/other/error18.C: Likewise.
* g++.dg/warn/Wpointer-arith-1.C: Likewise.
* g++.old-deja/g++.bugs/900212_01.C: Likewise.
* g++.old-deja/g++.bugs/900428_02.C: Likewise.
* g++.old-deja/g++.jason/rfg14.C: Likewise.
* g++.old-deja/g++.other/overload11.C: Likewise.
Index: cp/typeck.c
===
--- cp/typeck.c (revision 278692)
+++ cp/typeck.c (working copy)
@@ -6520,7 +6520,8 @@ cp_build_unary_op (enum tree_code code, tree xarg,
if (TREE_CODE (argtype) == ENUMERAL_TYPE)
   {
 if (complain & tf_error)
-  permerror (input_location, (code == PREINCREMENT_EXPR || code == 
POSTINCREMENT_EXPR)
+  permerror (location, (code == PREINCREMENT_EXPR
+   || code == POSTINCREMENT_EXPR)
  ? G_("ISO C++ forbids incrementing an enum")
  : G_("ISO C++ forbids decrementing an enum"));
 else
@@ -6536,11 +6537,13 @@ cp_build_unary_op (enum tree_code code, tree xarg,
if (!COMPLETE_OR_VOID_TYPE_P (type))
   {
 if (complain & tf_error)
-  error (((code == PREINCREMENT_EXPR
-   || code == POSTINCREMENT_EXPR))
- ? G_("cannot increment a pointer to incomplete type 
%qT")
- : G_("cannot decrement a pointer to incomplete type 
%qT"),
- TREE_TYPE (argtype));
+  error_at (location, ((code == PREINCREMENT_EXPR
+   || code == POSTINCREMENT_EXPR))
+   ? G_("cannot increment a pointer to incomplete "
+"type %qT")
+   : G_("cannot decrement a pointer to incomplete "
+"type %qT"),
+   TREE_TYPE (argtype));
 else
   return error_mark_node;
   }
@@ -6547,11 +6550,13 @@ cp_build_unary_op (enum tree_code code, tree xarg,
else if (!TYPE_PTROB_P (argtype)) 
   {
 if (complain & tf_error)
-  pedwarn (input_location, OPT_Wpointer_arith,
+  pedwarn (location, OPT_Wpointer_arith,
   (code == PREINCREMENT_EXPR
   || code == POSTINCREMENT_EXPR)
-  ? G_("ISO C++ forbids incrementing a pointer of type 
%qT")
-  : G_("ISO C++ forbids decrementing a pointer of type 
%qT"),
+  ? G_("ISO C++ forbids incrementing a pointer "
+   "of type %qT")
+  : G_("ISO C++ forbids decrementing a pointer "
+   "of type %qT"),
   argtype);
 else
   return error_mark_node;
@@ -6597,8 +6602,9 @@ cp_build_unary_op (enum tree_code code, tree xarg,
if (code == POSTDECREMENT_EXPR || code == PREDECREMENT_EXPR)
  {
 if (complain & tf_error)
- error ("use of an operand of type %qT in % "
-"is forbidden", boolean_type_node);
+ error_at (location,
+   "use of an operand of type %qT in % "
+   "is forbidden", boolean_type_node);
return error_mark_node;
  }
else
@@ -6606,16 +6612,18 @@ cp_build_unary_op (enum tree_code code, tree xarg,
if (cxx_dialect >= cxx17)
  {
if (complain & tf_error)
- error ("use of an operand of type %qT in "
-"% is forbidden in C++17

[C++ Patch] Improve build_new_op_1, cp_build_indirect_ref_1, and cp_build_modify_expr locations

2019-11-22 Thread Paolo Carlini

Hi,

I would say most of the changes are straightforward or mechanical. 
Essentially, for build_new_op_1 and cp_build_modify_expr I'm simply 
consistently using the available location argument; for 
cp_build_indirect_ref_1 I'm adding the parameter but then using it in a 
completely straightforward way. Minor nit: I wondered for a while if 
cp_build_modify_expr should use cp_expr_loc_or_loc more - normally the 
passed loc points to the '=' - but eventually, given the actual texts of 
the messages, I used it only in one place, for "void value not ignored 
as it ought to be" which is mostly about the type of 'rhs'. All the 
other messages in one way or the other talk about both sides (the 
primary clang caret appears to agree).


Tested x86_64-linux.

Thanks, Paolo.

//

/gcc
2019-11-20  Paolo Carlini  

* typeck.c (cp_build_indirect_ref_1): Add location_t parameter
and use it in error messages.
(build_x_indirect_ref): Adjust call.
(build_indirect_ref): Likewise.
(cp_build_fold_indirect_ref): Likewise.
(cp_build_array_ref): Likewise.
* call.c (build_new_op_1): Likewise.
* semantics.c (finish_omp_clauses): Likewise.
(finish_omp_depobj): Likewise.
* typeck2.c (build_x_arrow): Likewise.
* cp-tree.h (cp_build_indirect_ref): Update declaration.

* call.c (build_new_op_1): Use location argument in warning_at.

* typeck.c (cp_build_modify_expr): Consistently use the
location_t argument.

/libcc1
2019-11-20  Paolo Carlini  

* libcp1plugin.cc (plugin_pragma_push_user_expression): Update
cp_build_indirect_ref call.

/testsuite
2019-11-20  Paolo Carlini  

* g++.dg/diagnostic/base-operand-non-pointer-1.C: New.
* g++.dg/pr53055.C: Check location too.
* g++.old-deja/g++.bugs/900213_02.C: Likewise.
* g++.old-deja/g++.bugs/900215_02.C: Likewise.
* g++.old-deja/g++.other/badarrow.C: Likewise.
* g++.old-deja/g++.other/deref1.C: Likewise.

* g++.dg/warn/Wenum-compare.C: Check location too.

* g++.dg/cpp0x/initlist26.C: Check location too.
* g++.dg/cpp0x/initlist28.C: Likewise.
* g++.dg/cpp0x/initlist29.C: Likewise.
* g++.dg/cpp0x/initlist33.C: Likewise.
* g++.dg/expr/string-2.C: Likewise.
* g++.dg/other/ptrmem5.C: Likewise.
* g++.old-deja/g++.benjamin/14664-1.C: Likewise.
* g++.old-deja/g++.benjamin/14664-2.C: Likewise.
* g++.old-deja/g++.brendan/init12.C: Likewise.
* g++.old-deja/g++.bugs/900324_04.C: Likewise.
* g++.old-deja/g++.ext/array1.C: Likewise.
* g++.old-deja/g++.jason/rfg17.C: Likewise.
Index: cp/call.c
===
--- cp/call.c   (revision 278549)
+++ cp/call.c   (working copy)
@@ -6354,11 +6354,9 @@ build_new_op_1 (const op_location_t , enum tre
  && (TYPE_MAIN_VARIANT (arg1_type)
  != TYPE_MAIN_VARIANT (arg2_type))
  && (complain & tf_warning))
-   {
- warning (OPT_Wenum_compare,
-  "comparison between %q#T and %q#T",
-  arg1_type, arg2_type);
-   }
+   warning_at (loc, OPT_Wenum_compare,
+   "comparison between %q#T and %q#T",
+   arg1_type, arg2_type);
  break;
default:
  break;
@@ -6416,7 +6414,7 @@ build_new_op_1 (const op_location_t , enum tre
   return cp_build_modify_expr (loc, arg1, code2, arg2, complain);
 
 case INDIRECT_REF:
-  return cp_build_indirect_ref (arg1, RO_UNARY_STAR, complain);
+  return cp_build_indirect_ref (loc, arg1, RO_UNARY_STAR, complain);
 
 case TRUTH_ANDIF_EXPR:
 case TRUTH_ORIF_EXPR:
@@ -6472,8 +6470,9 @@ build_new_op_1 (const op_location_t , enum tre
   return cp_build_array_ref (input_location, arg1, arg2, complain);
 
 case MEMBER_REF:
-  return build_m_component_ref (cp_build_indirect_ref (arg1, 
RO_ARROW_STAR, 
-   complain), 
+  return build_m_component_ref (cp_build_indirect_ref (loc, arg1,
+  RO_ARROW_STAR,
+   complain),
 arg2, complain);
 
   /* The caller will deal with these.  */
Index: cp/cp-tree.h
===
--- cp/cp-tree.h(revision 278549)
+++ cp/cp-tree.h(working copy)
@@ -7482,9 +7482,11 @@ extern tree build_class_member_access_expr  (c
 extern tree finish_class_member_access_expr (cp_expr, tree, bool,
 tsubst_flags_t);
 extern tree bu

[C++ Patch] Avoid redundant error messages from build_x_arrow

2019-11-20 Thread Paolo Carlini

Hi,

while working on improving the locations of cp_build_indirect_ref_1 & 
co, I noticed this nit which seems a separate issue.


In a nutshell, at variance with many other cases, in build_x_arrow we 
don't immediately check for error_mark_node the return value of 
decay_conversion. Then, for the testcase, after a sensible:


error: invalid use of member function ‘C* C::f()’ (did you forget the 
‘()’ ?)


we also issue:

error: base operand of ‘->’ is not a pointer

which is certainly redundant and a bit misleading, is talking about the 
'f' mentioned in the first message. The amended behavior is also 
consistent with EDG and CLANG.


Tested x86_64-linux, as usual.

Thanks, Paolo.

//

/gcc
2019-11-20  Paolo Carlini  

* typeck2.c (build_x_arrow): Early return if decay_conversion
returns error_mark_node.

/testsuite
2019-11-20  Paolo Carlini  

* g++.dg/parse/error43.C: Adjust expected error.
Index: cp/typeck2.c
===
--- cp/typeck2.c(revision 278499)
+++ cp/typeck2.c(working copy)
@@ -2044,7 +2044,11 @@ build_x_arrow (location_t loc, tree expr, tsubst_f
last_rval = convert_from_reference (last_rval);
 }
   else
-last_rval = decay_conversion (expr, complain);
+{
+  last_rval = decay_conversion (expr, complain);
+  if (last_rval == error_mark_node)
+   return error_mark_node;
+}
 
   if (TYPE_PTR_P (TREE_TYPE (last_rval)))
 {
Index: testsuite/g++.dg/parse/error43.C
===
--- testsuite/g++.dg/parse/error43.C(revision 278499)
+++ testsuite/g++.dg/parse/error43.C(working copy)
@@ -2,4 +2,4 @@
 // { dg-options "" }
 
 class C { public: C* f(); int get(); };
-int f(C* p) { return p->f->get(); }  // { dg-error "forget the '\\(\\)'|base 
operand" }
+int f(C* p) { return p->f->get(); }  // { dg-error "25:invalid use of member 
function" }


[C++ Patch] Avoid duplicate warning

2019-11-18 Thread Paolo Carlini

Hi,

functions like c_common_truthvalue_conversion are shared with the C 
front-end thus don't get a tsubst_flags_t argument. It seems clear that 
long term we have to do something about those but in the meanwhile we 
have been using warning sentinels which, along the paths which certainly 
must have all the warnings suppressed, work well for now and cannot 
cause regressions. Here I propose to add (at least) one more to 
ocp_convert since I have a straightforward testcase. Note sue if we want 
to proactively add, say, one for warn_parentheses too.


Tested x86_64-linux.

Thanks, Paolo.

///

/cp
2019-11-18  Paolo Carlini  

* cvt.c (ocp_convert): Use additional warning sentinel.

/testsuite
2019-11-18  Paolo Carlini  

* g++.dg/warn/multiple-sign-compare-warn-1.C: New.
Index: cp/cvt.c
===
--- cp/cvt.c(revision 278407)
+++ cp/cvt.c(working copy)
@@ -847,6 +847,7 @@ ocp_convert (tree type, tree expr, int convtype, i
  /* Prevent bogus -Wint-in-bool-context warnings coming
 from c_common_truthvalue_conversion down the line.  */
  warning_sentinel w (warn_int_in_bool_context);
+ warning_sentinel c (warn_sign_compare);
  return cp_truthvalue_conversion (e, complain);
}
}
Index: testsuite/g++.dg/warn/multiple-sign-compare-warn-1.C
===
--- testsuite/g++.dg/warn/multiple-sign-compare-warn-1.C(nonexistent)
+++ testsuite/g++.dg/warn/multiple-sign-compare-warn-1.C(working copy)
@@ -0,0 +1,11 @@
+// { dg-options "-Wsign-compare" }
+
+int foo()
+{
+  unsigned char b = '1';
+
+  bool x = ~b; // { dg-bogus "promoted bitwise complement of an unsigned value 
is always nonzero.*promoted bitwise complement of an unsigned value is always 
nonzero" }
+ // { dg-warning "promoted bitwise complement of an unsigned value is always 
nonzero" "" { target *-*-* } .-1 }
+
+  return 0;
+}


Re: [C++ Patch] Use cp_expr_loc_or_input_loc in a few additional typeck.c places

2019-11-14 Thread Paolo Carlini

Hi again,

On 14/11/19 12:09, Paolo Carlini wrote:

Hi,

tested x86_64-linux.


Instead of sending a separate patch, the below has two additional uses. 
Tested as usual.


Thanks, Paolo.

///

/cp
2019-11-14  Paolo Carlini  

* typeck.c (cp_build_addr_expr_1): Use cp_expr_loc_or_input_loc
in three places.
(cxx_sizeof_expr): Use it in one additional place.
(cxx_alignof_expr): Likewise.
(lvalue_or_else): Likewise.

/testsuite
2019-11-14  Paolo Carlini  

* g++.dg/cpp0x/addressof2.C: Test locations too.
* g++.dg/cpp0x/rv-lvalue-req.C: Likewise.
* g++.dg/expr/crash2.C: Likewise.
* g++.dg/expr/lval1.C: Likewise.
* g++.dg/expr/unary2.C: Likewise.
* g++.dg/ext/lvaddr.C: Likewise.
* g++.dg/ext/lvalue1.C: Likewise.
* g++.dg/tree-ssa/pr20280.C: Likewise.
* g++.dg/warn/Wplacement-new-size.C: Likewise.
* g++.old-deja/g++.brendan/alignof.C: Likewise.
* g++.old-deja/g++.brendan/sizeof2.C: Likewise.
* g++.old-deja/g++.law/temps1.C: Likewise.
Index: cp/typeck.c
===
--- cp/typeck.c (revision 278253)
+++ cp/typeck.c (working copy)
@@ -1765,7 +1765,8 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain)
   if (bitfield_p (e))
 {
   if (complain & tf_error)
-error ("invalid application of % to a bit-field");
+   error_at (cp_expr_loc_or_input_loc (e),
+ "invalid application of % to a bit-field");
   else
 return error_mark_node;
   e = char_type_node;
@@ -1825,7 +1826,8 @@ cxx_alignof_expr (tree e, tsubst_flags_t complain)
   else if (bitfield_p (e))
 {
   if (complain & tf_error)
-error ("invalid application of %<__alignof%> to a bit-field");
+   error_at (cp_expr_loc_or_input_loc (e),
+ "invalid application of %<__alignof%> to a bit-field");
   else
 return error_mark_node;
   t = size_one_node;
@@ -6126,7 +6128,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
   if (kind == clk_none)
{
  if (complain & tf_error)
-   lvalue_error (input_location, lv_addressof);
+   lvalue_error (cp_expr_loc_or_input_loc (arg), lv_addressof);
  return error_mark_node;
}
   if (strict_lvalue && (kind & (clk_rvalueref|clk_class)))
@@ -6134,7 +6136,8 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
  if (!(complain & tf_error))
return error_mark_node;
  /* Make this a permerror because we used to accept it.  */
- permerror (input_location, "taking address of rvalue");
+ permerror (cp_expr_loc_or_input_loc (arg),
+"taking address of rvalue");
}
 }
 
@@ -6228,7 +6231,8 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
   if (bitfield_p (arg))
 {
   if (complain & tf_error)
-   error ("attempt to take address of bit-field");
+   error_at (cp_expr_loc_or_input_loc (arg),
+ "attempt to take address of bit-field");
   return error_mark_node;
 }
 
@@ -10431,7 +10435,7 @@ lvalue_or_else (tree ref, enum lvalue_use use, tsu
   if (kind == clk_none)
 {
   if (complain & tf_error)
-   lvalue_error (input_location, use);
+   lvalue_error (cp_expr_loc_or_input_loc (ref), use);
   return 0;
 }
   else if (kind & (clk_rvalueref|clk_class))
Index: testsuite/g++.dg/cpp0x/addressof2.C
===
--- testsuite/g++.dg/cpp0x/addressof2.C (revision 278253)
+++ testsuite/g++.dg/cpp0x/addressof2.C (working copy)
@@ -8,19 +8,19 @@ addressof (T ) noexcept
   return __builtin_addressof (x);
 }
 
-auto a = __builtin_addressof (1);  // { dg-error "lvalue required 
as unary" }
-auto b = addressof (1);// { dg-error "cannot 
bind non-const lvalue reference of type" }
+auto a = __builtin_addressof (1);  // { dg-error "31:lvalue 
required as unary" }
+auto b = addressof (1);// { dg-error 
"21:cannot bind non-const lvalue reference of type" }
 
 struct S { int s : 5; int t; void foo (); } s;
 
 auto c = __builtin_addressof (s);
 auto d = addressof (s);
-auto e = __builtin_addressof (s.s);// { dg-error "attempt to take 
address of bit-field" }
-auto f = addressof (s.s);  // { dg-error "cannot bind 
bit-field" }
-auto g = __builtin_addressof (S{});// { dg-error "taking address 
of rvalue" }
-auto h = addressof (S{});  // { dg-error "cannot bind 
non-const lvalue reference of type" }
-auto i = __builtin_addressof (S::t);   // { dg-error &

[C++ Patch] Use cp_expr_loc_or_input_loc in a few additional typeck.c places

2019-11-14 Thread Paolo Carlini

Hi,

tested x86_64-linux.

Thanks, Paolo.

///

/cp
2019-11-14  Paolo Carlini  

* typeck.c (cp_build_addr_expr_1): Use cp_expr_loc_or_input_loc
in three places.
(lvalue_or_else): Use it in one place.

/testsuite
2019-11-14  Paolo Carlini  

* g++.dg/cpp0x/addressof2.C: Test locations too.
* g++.dg/cpp0x/rv-lvalue-req.C: Likewise.
* g++.dg/expr/crash2.C: Likewise.
* g++.dg/expr/lval1.C: Likewise.
* g++.dg/expr/unary2.C: Likewise.
* g++.dg/ext/lvaddr.C: Likewise.
* g++.dg/ext/lvalue1.C: Likewise.
* g++.dg/tree-ssa/pr20280.C: Likewise.
* g++.dg/warn/Wplacement-new-size.C: Likewise.
* g++.old-deja/g++.law/temps1.C: Likewise.
Index: cp/typeck.c
===
--- cp/typeck.c (revision 278216)
+++ cp/typeck.c (working copy)
@@ -6126,7 +6126,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
   if (kind == clk_none)
{
  if (complain & tf_error)
-   lvalue_error (input_location, lv_addressof);
+   lvalue_error (cp_expr_loc_or_input_loc (arg), lv_addressof);
  return error_mark_node;
}
   if (strict_lvalue && (kind & (clk_rvalueref|clk_class)))
@@ -6134,7 +6134,8 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
  if (!(complain & tf_error))
return error_mark_node;
  /* Make this a permerror because we used to accept it.  */
- permerror (input_location, "taking address of rvalue");
+ permerror (cp_expr_loc_or_input_loc (arg),
+"taking address of rvalue");
}
 }
 
@@ -6228,7 +6229,8 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
   if (bitfield_p (arg))
 {
   if (complain & tf_error)
-   error ("attempt to take address of bit-field");
+   error_at (cp_expr_loc_or_input_loc (arg),
+ "attempt to take address of bit-field");
   return error_mark_node;
 }
 
@@ -10431,7 +10433,7 @@ lvalue_or_else (tree ref, enum lvalue_use use, tsu
   if (kind == clk_none)
 {
   if (complain & tf_error)
-   lvalue_error (input_location, use);
+   lvalue_error (cp_expr_loc_or_input_loc (ref), use);
   return 0;
 }
   else if (kind & (clk_rvalueref|clk_class))
Index: testsuite/g++.dg/cpp0x/addressof2.C
===
--- testsuite/g++.dg/cpp0x/addressof2.C (revision 278216)
+++ testsuite/g++.dg/cpp0x/addressof2.C (working copy)
@@ -8,19 +8,19 @@ addressof (T ) noexcept
   return __builtin_addressof (x);
 }
 
-auto a = __builtin_addressof (1);  // { dg-error "lvalue required 
as unary" }
-auto b = addressof (1);// { dg-error "cannot 
bind non-const lvalue reference of type" }
+auto a = __builtin_addressof (1);  // { dg-error "31:lvalue 
required as unary" }
+auto b = addressof (1);// { dg-error 
"21:cannot bind non-const lvalue reference of type" }
 
 struct S { int s : 5; int t; void foo (); } s;
 
 auto c = __builtin_addressof (s);
 auto d = addressof (s);
-auto e = __builtin_addressof (s.s);// { dg-error "attempt to take 
address of bit-field" }
-auto f = addressof (s.s);  // { dg-error "cannot bind 
bit-field" }
-auto g = __builtin_addressof (S{});// { dg-error "taking address 
of rvalue" }
-auto h = addressof (S{});  // { dg-error "cannot bind 
non-const lvalue reference of type" }
-auto i = __builtin_addressof (S::t);   // { dg-error "invalid use of 
non-static data member" }
-auto j = __builtin_addressof (S::foo); // { dg-error "invalid use of 
non-static member function" }
+auto e = __builtin_addressof (s.s);// { dg-error "33:attempt to 
take address of bit-field" }
+auto f = addressof (s.s);  // { dg-error "23:cannot bind 
bit-field" }
+auto g = __builtin_addressof (S{});// { dg-error "31:taking 
address of rvalue" }
+auto h = addressof (S{});  // { dg-error "21:cannot bind 
non-const lvalue reference of type" }
+auto i = __builtin_addressof (S::t);   // { dg-error "34:invalid use 
of non-static data member" }
+auto j = __builtin_addressof (S::foo); // { dg-error "34:invalid use 
of non-static member function" }
 
 void
 foo (bool b)
@@ -28,6 +28,6 @@ foo (bool b)
   lab:;
   char c;
   long long int d;
-  auto k = __builtin_addressof (lab);  // { dg-error "was not declared 
in this scope" }
-  auto l = __builtin_addressof (b ? c : d);// { dg-error "lvalue required 
as unary" 

[C++ Patch] Improve cp_truthvalue_conversion locations and more

2019-11-12 Thread Paolo Carlini

Hi,

a few days ago I noticed that we weren't doing the right thing 
location-wise for the first test of g++.dg/warn/Waddress-1.C: it seems 
clear that the ultimate reason is that we didn't pass an accurate 
location to build_binary_op called from cp_truthvalue_conversion. When I 
fixed that, I noticed that for testcases like warn/Walways-true-3.C we 
were issuing many duplicate warnings and I traced that to ocp_convert 
not using its tsubst_flags_t argument - which can come from 
cp_convert_and_check as tf_none - when calling cp_truthvalue_conversion. 
Thus I also added a tusbst_flags_t parameter to the latter and 
everything looks finally good for these testcases.


Tested x86_64-linux.

Thanks, Paolo.



/cp
2019-11-12  Paolo Carlini  

* typeck.c (cp_truthvalue_conversion): Add tsubst_flags_t parameter
and use it in calls; also pass the location_t of the expression to
cp_build_binary_op and c_common_truthvalue_conversion.
* rtti.c (build_dynamic_cast_1): Adjust call.
* cvt.c (ocp_convert): Likewise.
* cp-gimplify.c (cp_fold): Likewise.
* cp-tree.h (cp_truthvalue_conversion): Update declaration.

/testsuite
2019-11-12  Paolo Carlini  

* g++.dg/warn/Walways-true-1.C: Check locations too.
* g++.dg/warn/Walways-true-2.C: Likewise.
* g++.dg/warn/Walways-true-3.C: Likewise.
* g++.dg/warn/Waddress-1.C: Check additional location.
Index: cp/cp-gimplify.c
===
--- cp/cp-gimplify.c(revision 278059)
+++ cp/cp-gimplify.c(working copy)
@@ -2573,9 +2573,9 @@ cp_fold (tree x)
{
  warning_sentinel s (warn_int_in_bool_context);
  if (!VOID_TYPE_P (TREE_TYPE (op1)))
-   op1 = cp_truthvalue_conversion (op1);
+   op1 = cp_truthvalue_conversion (op1, tf_warning_or_error);
  if (!VOID_TYPE_P (TREE_TYPE (op2)))
-   op2 = cp_truthvalue_conversion (op2);
+   op2 = cp_truthvalue_conversion (op2, tf_warning_or_error);
}
   else if (VOID_TYPE_P (TREE_TYPE (x)))
{
Index: cp/cp-tree.h
===
--- cp/cp-tree.h(revision 278059)
+++ cp/cp-tree.h(working copy)
@@ -7445,7 +7445,7 @@ enum compare_bounds_t { bounds_none, bounds_either
 
 extern bool cxx_mark_addressable   (tree, bool = false);
 extern int string_conv_p   (const_tree, const_tree, int);
-extern tree cp_truthvalue_conversion   (tree);
+extern tree cp_truthvalue_conversion   (tree, tsubst_flags_t);
 extern tree contextual_conv_bool   (tree, tsubst_flags_t);
 extern tree condition_conversion   (tree);
 extern tree require_complete_type  (tree);
Index: cp/cvt.c
===
--- cp/cvt.c(revision 278059)
+++ cp/cvt.c(working copy)
@@ -841,13 +841,13 @@ ocp_convert (tree type, tree expr, int convtype, i
  if (SCOPED_ENUM_P (intype) && (convtype & CONV_STATIC))
e = build_nop (ENUM_UNDERLYING_TYPE (intype), e);
  if (complain & tf_warning)
-   return cp_truthvalue_conversion (e);
+   return cp_truthvalue_conversion (e, complain);
  else
{
  /* Prevent bogus -Wint-in-bool-context warnings coming
 from c_common_truthvalue_conversion down the line.  */
  warning_sentinel w (warn_int_in_bool_context);
- return cp_truthvalue_conversion (e);
+ return cp_truthvalue_conversion (e, complain);
}
}
 
Index: cp/rtti.c
===
--- cp/rtti.c   (revision 278059)
+++ cp/rtti.c   (working copy)
@@ -782,7 +782,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst
  tree neq;
 
  result = save_expr (result);
- neq = cp_truthvalue_conversion (result);
+ neq = cp_truthvalue_conversion (result, complain);
  return cp_convert (type,
 build3 (COND_EXPR, TREE_TYPE (result),
 neq, result, bad), complain);
Index: cp/typeck.c
===
--- cp/typeck.c (revision 278059)
+++ cp/typeck.c (working copy)
@@ -5975,15 +5975,16 @@ cp_build_addressof (location_t loc, tree arg, tsub
-1.  */
 
 tree
-cp_truthvalue_conversion (tree expr)
+cp_truthvalue_conversion (tree expr, tsubst_flags_t complain)
 {
   tree type = TREE_TYPE (expr);
+  location_t loc = cp_expr_loc_or_input_loc (expr);
   if (TYPE_PTR_OR_PTRMEM_P (type)
   /* Avoid ICE on invalid use of non-static member function.  */
   || TREE_CODE (expr) == FUNCTION_DECL)
-return build_binary_op (input_location, NE_EXPR, expr, nullptr_node, tr

Re: [C++ Patch] Add location parameter to composite_pointer_type and use it

2019-11-01 Thread Paolo Carlini

Hi again,

On 31/10/19 16:56, Paolo Carlini wrote:

Hi,

yesterday I noticed that we want to forward the location parameter of 
cp_build_binary_op to composite_pointer_type and then 
composite_pointer_error. Note, for the time being at least, this is 
always for CPO_COMPARISON, the other two composite_pointer_operation 
cases aren't involved - and the various functions (eg, 
common_pointer_type) forward input_location - but I'm consistently 
changing all the pedwarn, emit_diagnostic, and error_at anyway to use 
the location.


In fact, build_conditional_expr_1, which passes CPO_CONDITIONAL_EXPR, 
has available a suitable location, thus we can extend my previous patch 
and forward that too instead of input_location. Tested as usual 
x86_64-linux.


Thanks, Paolo.

/

/cp
2019-11-01  Paolo Carlini  

* typeck.c (composite_pointer_type): Add a const op_location_t&
parameter and use it in diagnostics.
(composite_pointer_error): Likewise.
(composite_pointer_type_r): Add a const op_location_t&
parameter and forward it.
(cp_build_binary_op): Adjust calls.
(common_pointer_type): Likewise.
* call.c (add_builtin_candidate): Likewise.
(build_conditional_expr_1): Likewise.
* cp-tree.h (composite_pointer_type): Update declaration.

* typeck.c (cxx_sizeof_expr): Use cp_expr_loc_or_input_loc
in permerror.
(cxx_alignof_expr): Likewise.
(lvalue_or_else): Likewise.

/testsuite
2019-11-01  Paolo Carlini  

* g++.dg/conversion/ptrmem9.C: Check location.
* g++.dg/expr/cond2.C: Likewise.
* g++.dg/warn/Waddress-1.C: Check locations.
* g++.old-deja/g++.bugs/900324_02.C: Check location.
* g++.old-deja/g++.jason/rfg20.C: Likewise.
* g++.old-deja/g++.law/typeck1.C: Likewise.
* g++.old-deja/g++.rfg/00321_01-.C: Likewise.
* g++.old-deja/g++.rfg/00324_02-.C: Likewise.

* g++.dg/diagnostic/alignof1.C: New.
* g++.dg/expr/sizeof1.C: Check location.
* g++.dg/cpp0x/rv-lvalue-req.C: Check locations.
Index: cp/call.c
===
--- cp/call.c   (revision 277705)
+++ cp/call.c   (working copy)
@@ -3029,7 +3029,8 @@ add_builtin_candidate (struct z_candidate **candid
 {
   if (TYPE_PTR_OR_PTRMEM_P (type1))
{
- tree cptype = composite_pointer_type (type1, type2,
+ tree cptype = composite_pointer_type (input_location,
+   type1, type2,
error_mark_node,
error_mark_node,
CPO_CONVERSION,
@@ -5553,7 +5554,8 @@ build_conditional_expr_1 (const op_location_t 
   || (TYPE_PTRDATAMEM_P (arg2_type) && TYPE_PTRDATAMEM_P (arg3_type))
   || (TYPE_PTRMEMFUNC_P (arg2_type) && TYPE_PTRMEMFUNC_P (arg3_type)))
 {
-  result_type = composite_pointer_type (arg2_type, arg3_type, arg2,
+  result_type = composite_pointer_type (loc,
+   arg2_type, arg3_type, arg2,
arg3, CPO_CONDITIONAL_EXPR,
complain);
   if (result_type == error_mark_node)
Index: cp/cp-tree.h
===
--- cp/cp-tree.h(revision 277705)
+++ cp/cp-tree.h(working copy)
@@ -7509,7 +7509,8 @@ extern tree build_ptrmemfunc1 (tree, 
tree, tree)
 extern void expand_ptrmemfunc_cst  (tree, tree *, tree *);
 extern tree type_after_usual_arithmetic_conversions (tree, tree);
 extern tree common_pointer_type (tree, tree);
-extern tree composite_pointer_type (tree, tree, tree, tree,
+extern tree composite_pointer_type (const op_location_t &,
+tree, tree, tree, tree,
 composite_pointer_operation,
 tsubst_flags_t);
 extern tree merge_types(tree, tree);
Index: cp/typeck.c
===
--- cp/typeck.c (revision 277705)
+++ cp/typeck.c (working copy)
@@ -450,25 +450,26 @@ type_after_usual_arithmetic_conversions (tree t1,
 }
 
 static void
-composite_pointer_error (diagnostic_t kind, tree t1, tree t2,
+composite_pointer_error (const op_location_t ,
+diagnostic_t kind, tree t1, tree t2,
 composite_pointer_operation operation)
 {
   switch (operation)
 {
 case CPO_COMPARISON:
-  emit_diagnostic (kind, input_location, 0,
+  emit_diagnostic (kind, location, 0,
   "comparison between "

[C++ Patch] Add location parameter to composite_pointer_type and use it

2019-10-31 Thread Paolo Carlini

Hi,

yesterday I noticed that we want to forward the location parameter of 
cp_build_binary_op to composite_pointer_type and then 
composite_pointer_error. Note, for the time being at least, this is 
always for CPO_COMPARISON, the other two composite_pointer_operation 
cases aren't involved - and the various functions (eg, 
common_pointer_type) forward input_location - but I'm consistently 
changing all the pedwarn, emit_diagnostic, and error_at anyway to use 
the location. Additionally, I had in my tree some additional uses for 
cp_expr_loc_or_input_loc.


Tested x86_64-linux.

Thanks, Paolo.



/cp
2019-10-31  Paolo Carlini  

* typeck.c (composite_pointer_type): Add a const op_location_t&
parameter and use it in diagnostics.
(composite_pointer_error): Likewise.
(composite_pointer_type_r): Add a const op_location_t&
parameter and forward it.
(cp_build_binary_op): Adjust calls.
(common_pointer_type): Likewise.
* call.c (add_builtin_candidate): Likewise.
(build_conditional_expr_1): Likewise.
* cp-tree.h (composite_pointer_type): Update declaration.

* typeck.c (cxx_sizeof_expr): Use cp_expr_loc_or_input_loc
in permerror.
(cxx_alignof_expr): Likewise.
(lvalue_or_else): Likewise.

/testsuite
2019-10-31  Paolo Carlini  

* g++.dg/conversion/ptrmem9.C: Check location.
* g++.dg/warn/Waddress-1.C: Check locations.
* g++.old-deja/g++.jason/rfg20.C: Likewise.
* g++.old-deja/g++.law/typeck1.C: Likewise.
* g++.old-deja/g++.rfg/00321_01-.C: Likewise.

* g++.dg/diagnostic/alignof1.C: New.
* g++.dg/expr/sizeof1.C: Check location.
* g++.dg/cpp0x/rv-lvalue-req.C: Check locations.
Index: cp/call.c
===
--- cp/call.c   (revision 277657)
+++ cp/call.c   (working copy)
@@ -3029,7 +3029,8 @@ add_builtin_candidate (struct z_candidate **candid
 {
   if (TYPE_PTR_OR_PTRMEM_P (type1))
{
- tree cptype = composite_pointer_type (type1, type2,
+ tree cptype = composite_pointer_type (input_location,
+   type1, type2,
error_mark_node,
error_mark_node,
CPO_CONVERSION,
@@ -5553,7 +5554,8 @@ build_conditional_expr_1 (const op_location_t 
   || (TYPE_PTRDATAMEM_P (arg2_type) && TYPE_PTRDATAMEM_P (arg3_type))
   || (TYPE_PTRMEMFUNC_P (arg2_type) && TYPE_PTRMEMFUNC_P (arg3_type)))
 {
-  result_type = composite_pointer_type (arg2_type, arg3_type, arg2,
+  result_type = composite_pointer_type (input_location,
+   arg2_type, arg3_type, arg2,
arg3, CPO_CONDITIONAL_EXPR,
complain);
   if (result_type == error_mark_node)
Index: cp/cp-tree.h
===
--- cp/cp-tree.h(revision 277657)
+++ cp/cp-tree.h(working copy)
@@ -7509,7 +7509,8 @@ extern tree build_ptrmemfunc1 (tree, 
tree, tree)
 extern void expand_ptrmemfunc_cst  (tree, tree *, tree *);
 extern tree type_after_usual_arithmetic_conversions (tree, tree);
 extern tree common_pointer_type (tree, tree);
-extern tree composite_pointer_type (tree, tree, tree, tree,
+extern tree composite_pointer_type (const op_location_t &,
+tree, tree, tree, tree,
 composite_pointer_operation,
 tsubst_flags_t);
 extern tree merge_types(tree, tree);
Index: cp/typeck.c
===
--- cp/typeck.c (revision 277657)
+++ cp/typeck.c (working copy)
@@ -450,25 +450,26 @@ type_after_usual_arithmetic_conversions (tree t1,
 }
 
 static void
-composite_pointer_error (diagnostic_t kind, tree t1, tree t2,
+composite_pointer_error (const op_location_t ,
+diagnostic_t kind, tree t1, tree t2,
 composite_pointer_operation operation)
 {
   switch (operation)
 {
 case CPO_COMPARISON:
-  emit_diagnostic (kind, input_location, 0,
+  emit_diagnostic (kind, location, 0,
   "comparison between "
   "distinct pointer types %qT and %qT lacks a cast",
   t1, t2);
   break;
 case CPO_CONVERSION:
-  emit_diagnostic (kind, input_location, 0,
+  emit_diagnostic (kind, location, 0,
   "conversion between "
 

[C++ Patch] Prefer error + inform in four typeck.c places

2019-10-24 Thread Paolo Carlini

Hi,

some additional straightforward bits in typeck.c, which I noticed when I 
went through the cp_build_binary_op callers. Tested x86_64-linux.


Thanks, Paolo.

//

/cp
2019-10-24  Paolo Carlini  

* typeck.c (cp_build_modify_expr): Prefer error + inform to
error + error in one place.
(get_delta_difference_1): Likewise.
(get_delta_difference): Likewise, in two places.

/testsuite
2019-10-24  Paolo Carlini  

* g++.dg/conversion/ptrmem2.C: Adjust for error + inform.
* g++.dg/gomp/tpl-atomic-2.C: Likewise.
Index: cp/typeck.c
===
--- cp/typeck.c (revision 277366)
+++ cp/typeck.c (working copy)
@@ -8358,8 +8358,8 @@ cp_build_modify_expr (location_t loc, tree lhs, en
  if (newrhs == error_mark_node)
{
  if (complain & tf_error)
-   error ("  in evaluation of %<%Q(%#T, %#T)%>", modifycode,
-  TREE_TYPE (lhs), TREE_TYPE (rhs));
+   inform (loc, "  in evaluation of %<%Q(%#T, %#T)%>",
+   modifycode, TREE_TYPE (lhs), TREE_TYPE (rhs));
  return error_mark_node;
}
 
@@ -8594,7 +8594,7 @@ get_delta_difference_1 (tree from, tree to, bool c
   if (!(complain & tf_error))
return error_mark_node;
 
-  error ("   in pointer to member function conversion");
+  inform (input_location, "   in pointer to member function conversion");
   return size_zero_node;
 }
   else if (binfo)
@@ -8655,7 +8655,7 @@ get_delta_difference (tree from, tree to,
  return error_mark_node;
 
error_not_base_type (from, to);
-   error ("   in pointer to member conversion");
+   inform (input_location, "   in pointer to member conversion");
result = size_zero_node;
   }
 else
@@ -8674,7 +8674,7 @@ get_delta_difference (tree from, tree to,
  return error_mark_node;
 
error_not_base_type (from, to);
-   error ("   in pointer to member conversion");
+   inform (input_location, "   in pointer to member conversion");
result = size_zero_node;
  }
   }
Index: testsuite/g++.dg/conversion/ptrmem2.C
===
--- testsuite/g++.dg/conversion/ptrmem2.C   (revision 277366)
+++ testsuite/g++.dg/conversion/ptrmem2.C   (working copy)
@@ -15,16 +15,20 @@ int B::*p1 = static_cast(::x);
 int D::*p2 = static_cast(::x);
 
 // Virtual base class.
-int V::*p3 = static_cast(::x);  // { dg-error "" }
-int D::*p4 = static_cast(::x);  // { dg-error "" }
+int V::*p3 = static_cast(::x);  // { dg-error "virtual base" }
+int D::*p4 = static_cast(::x);  // { dg-error "virtual base" }
 
 // Inaccessible base class.
-int P::*p5 = static_cast(::x);  // { dg-error "" }
-int D::*p6 = static_cast(::x);  // { dg-error "" }
+int P::*p5 = static_cast(::x);  // { dg-error "inaccessible base" }
+// { dg-message "pointer to member function" "" { target *-*-* } .-1 }
+int D::*p6 = static_cast(::x);  // { dg-error "inaccessible base" }
+// { dg-message "pointer to member function" "" { target *-*-* } .-1 }
 
 // Ambiguous base class.
-int A::*p7 = static_cast(::x);  // { dg-error "" }
-int D::*p8 = static_cast(::x);  // { dg-error "" }
+int A::*p7 = static_cast(::x);  // { dg-error "ambiguous base" }
+// { dg-message "pointer to member function" "" { target *-*-* } .-1 }
+int D::*p8 = static_cast(::x);  // { dg-error "ambiguous base" }
+// { dg-message "pointer to member function" "" { target *-*-* } .-1 }
 
 // Valid conversions which increase cv-qualification.
 const int B::*p9 = static_cast(::x);
@@ -35,5 +39,5 @@ int B::*p11 = static_cast(p10); // { dg-
 int D::*p12 = static_cast(p9);  // { dg-error "casts away 
qualifiers" }
 
 // Attempts to change member type.
-float B::*p13 = static_cast(::x); // { dg-error "" }
-float D::*p14 = static_cast(::x); // { dg-error "" }
+float B::*p13 = static_cast(::x); // { dg-error "invalid 
.static_cast." }
+float D::*p14 = static_cast(::x); // { dg-error "invalid 
.static_cast." }
Index: testsuite/g++.dg/gomp/tpl-atomic-2.C
===
--- testsuite/g++.dg/gomp/tpl-atomic-2.C(revision 277374)
+++ testsuite/g++.dg/gomp/tpl-atomic-2.C(working copy)
@@ -13,7 +13,7 @@ template void f1()
 template void f2(float *f)
 {
   #pragma omp atomic   // { dg-error "invalid" }
-  *f |= 1; // { dg-error "evaluation" }
+  *f |= 1; // { dg-message "evaluation"

[C++ Patch] Improve build_x_unary_op locations

2019-10-22 Thread Paolo Carlini

Hi,

at the moment I'm going through more typeck.c and typeck2.c functions: 
the below are some straightforward changes for build_x_unary_op (fwiw, 
the resulting locations are also consistent with clang)


Tested x86_64-linux.

Thanks, Paolo.



/cp
2019-10-22  Paolo Carlini  

* typeck.c (build_x_unary_op): Use the location_t argument in
three error_at.

/testsuite
2019-10-22  Paolo Carlini  

* g++.dg/other/ptrmem8.C: Test locations too.
* g++.dg/template/dtor6.C: Likewise.
Index: cp/typeck.c
===
--- cp/typeck.c (revision 277268)
+++ cp/typeck.c (working copy)
@@ -5829,10 +5831,10 @@ build_x_unary_op (location_t loc, enum tree_code c
  if (DECL_CONSTRUCTOR_P (fn) || DECL_DESTRUCTOR_P (fn))
{
  if (complain & tf_error)
-   error (DECL_CONSTRUCTOR_P (fn)
-  ? G_("taking address of constructor %qD")
-  : G_("taking address of destructor %qD"),
-  fn);
+   error_at (loc, DECL_CONSTRUCTOR_P (fn)
+ ? G_("taking address of constructor %qD")
+ : G_("taking address of destructor %qD"),
+ fn);
  return error_mark_node;
}
}
@@ -5847,10 +5849,10 @@ build_x_unary_op (location_t loc, enum tree_code c
{
  if (complain & tf_error)
{
- error ("invalid use of %qE to form a "
-"pointer-to-member-function", xarg.get_value ());
+ error_at (loc, "invalid use of %qE to form a "
+   "pointer-to-member-function", xarg.get_value ());
  if (TREE_CODE (xarg) != OFFSET_REF)
-   inform (input_location, "  a qualified-id is required");
+   inform (loc, "  a qualified-id is required");
}
  return error_mark_node;
}
@@ -5857,9 +5859,9 @@ build_x_unary_op (location_t loc, enum tree_code c
  else
{
  if (complain & tf_error)
-   error ("parentheses around %qE cannot be used to form a"
-  " pointer-to-member-function",
-  xarg.get_value ());
+   error_at (loc, "parentheses around %qE cannot be used to "
+ "form a pointer-to-member-function",
+ xarg.get_value ());
  else
return error_mark_node;
  PTRMEM_OK_P (xarg) = 1;
Index: testsuite/g++.dg/other/ptrmem8.C
===
--- testsuite/g++.dg/other/ptrmem8.C(revision 277268)
+++ testsuite/g++.dg/other/ptrmem8.C(working copy)
@@ -6,11 +6,11 @@ struct A {};
 template void foo(void (A::* f)())
 {
   A a;
-  &(a.*f); // { dg-error "invalid use of\[^\n\]*\\.\\*\[^\n\]*to 
form|qualified-id is required" }
+  &(a.*f); // { dg-error "3:invalid use of\[^\n\]*\\.\\*\[^\n\]*to 
form|qualified-id is required" }
 }
 
 template void bar(void (A::* f)())
 {
   A *p;
-  &(p->*f);// { dg-error "invalid use of\[^\n\]*->\\*\[^\n\]*to 
form|qualified-id is required" }
+  &(p->*f);// { dg-error "3:invalid use of\[^\n\]*->\\*\[^\n\]*to 
form|qualified-id is required" }
 }
Index: testsuite/g++.dg/template/dtor6.C
===
--- testsuite/g++.dg/template/dtor6.C   (revision 277268)
+++ testsuite/g++.dg/template/dtor6.C   (working copy)
@@ -5,12 +5,12 @@ template struct A
   static int i;
 };
 
-template int A::i = { A::~A }; // { dg-error "non-static member 
function" }
+template int A::i = { A::~A }; // { dg-error "36:invalid use of 
non-static member function" }
 
 template class A<0>;
 
 struct X { };
 
-int i1 = X::~X;// { dg-error "non-static member 
function" }
-int i2 = ::~X;   // { dg-error "address of destructor" }
-int i3 = <0>::~A;// { dg-error "address of destructor" }
+int i1 = X::~X;// { dg-error "13:invalid use of 
non-static member function" }
+int i2 = ::~X;   // { dg-error "10:taking address of destructor" 
}
+int i3 = <0>::~A;// { dg-error "10:taking address of destructor" 
}


[C++ Patch] Improve cp_parser_class_head error recovery

2019-10-18 Thread Paolo Carlini

Hi,

a few days ago I noticed that for, say, g++.dg/parse/qualified2.C we 
were issuing two additional misleading errors after the first one, 
mentioning in particular a certain "unnamed class" (I'm reproducing only 
the error messages proper):


namespace Glib {
  template  class Value {};
  template <> class Glib::Value {}; // { dg-error "" }
}

qualified2.C:3:29: error: extra qualification not allowed [\-fpermissive\]
qualified2.C:3:46: error: explicit specialization of non-template 
‘Glib::’
qualified2.C:3:47: error: abstract declarator ‘Glib::’ 
used as declaration


Let's see if I can explain clearly enough what I think it's going on.

In cp_parser_class_head, upon the permerror about the extra 
qualification, we try to do error recovery, which is particularly 
tricky, because we are dealing with a permerror thus we have to make 
sure that in case of -fpermissive everything remains internally 
consistent anyway. In this context, clearing 'nested_name_specifier' and 
'num_templates' doesn't seem a good idea because it does *not* give us 
an internal state similar to the one normally obtained when the nested 
name specifier is not there, the reason being that, earlier in the 
function, when a nested name specifier really isn't there we try 
cp_parser_template_id or in case cp_parser_identifier, which set the 
locale 'id' and possibly 'template_id' and 'num_templates', whereas 
during error recovery we remain so to speak completely empty handed. 
Thus, what about not clearing anything? That seems to work at least for 
the two testcases below and doesn't cause regressions.


Thanks, Paolo.

/////



/cp
2019-10-18  Paolo Carlini  

* parser.c (cp_parser_class_head): Improve error recovery upon
extra qualification error.

/testsuite
2019-10-18  Paolo Carlini  

* g++.dg/parse/qualified2.C: Tighten dg-error directive.
* g++.old-deja/g++.other/decl5.C: Don't expect redundant error.
Index: cp/parser.c
===
--- cp/parser.c (revision 277149)
+++ cp/parser.c (working copy)
@@ -24178,12 +24178,8 @@ cp_parser_class_head (cp_parser* parser,
 ... [or] the definition or explicit instantiation of a
 class member of a namespace outside of its namespace.  */
   if (scope == nested_name_specifier)
-   {
- permerror (nested_name_specifier_token_start->location,
-"extra qualification not allowed");
- nested_name_specifier = NULL_TREE;
- num_templates = 0;
-   }
+   permerror (nested_name_specifier_token_start->location,
+  "extra qualification not allowed");
 }
   /* An explicit-specialization must be preceded by "template <>".  If
  it is not, try to recover gracefully.  */
Index: testsuite/g++.dg/parse/qualified2.C
===
--- testsuite/g++.dg/parse/qualified2.C (revision 277144)
+++ testsuite/g++.dg/parse/qualified2.C (working copy)
@@ -1,4 +1,4 @@
 namespace Glib {
   template  class Value {};
-  template <> class Glib::Value {}; // { dg-error "" }
+  template <> class Glib::Value {}; // { dg-error "29:extra 
qualification" }
 }
Index: testsuite/g++.old-deja/g++.other/decl5.C
===
--- testsuite/g++.old-deja/g++.other/decl5.C(revision 277144)
+++ testsuite/g++.old-deja/g++.other/decl5.C(working copy)
@@ -12,7 +12,6 @@ struct A {
   int A::m;   // { dg-error "extra qualification" } 
   struct e;
   struct A::e {int i;}; // { dg-error "extra qualification" "qual" } 
-  // { dg-error "anonymous struct" "anon" { target *-*-* } .-1 }
   struct A::expand {  // { dg-error "qualified name" } 
   int m;
   };


Re: [C++ Patch] Remove most uses of in_system_header_at

2019-10-17 Thread Paolo Carlini

.. hi again.

We have an issue with this idea which I didn't notice earlier today: 
there are some libstdc++ *_neg testcases which rely on permerrors being 
emitted for code in library headers. For example 
20_util/ratio/cons/cons_overflow_neg.cc relies on a permerror for the 
"overflow in constant expression" in constexpr.c. Or, 
20_util/variant/visit_neg.cc relies on the permerror for "invalid 
conversion from .. to .." emitted by convert_like_real.


Something seems a little fishy here but I'm not sure which way we want 
to go: I don't think we want to audit that right here, right now all the 
permerrors in the front-end which could potentially be involved in this 
kind of issue. Even if we, say, promote to plain errors the above two, 
that seems brittle, we got many permerrors which in principle should be 
real errors.


Paolo.



Re: [C++ Patch] Remove most uses of in_system_header_at

2019-10-17 Thread Paolo Carlini

Hi,

On 17/10/19 05:15, Jason Merrill wrote:

On 10/16/19 11:59 AM, Paolo Carlini wrote:
... the below, slightly extended patch: 1- Makes sure the 
in_system_header_at calls surviving in decl.c get the same location 
used for the corresponding diagnostic
Hmm, we probably want to change permerror to respect 
warn_system_headers like warning and pedwarn.


I see. Certainly it enables cleaning up those two remaining usages in 
decl.c.


Which is the right place to implement this? The beginning of 
diagnostic_impl figures out if a given permerror boils down to an actual 
error or a warning: if we use in_system_header_at at that level, part of 
the permissive_error_kind macro, then the warning is handled as any 
other other warning, thus by default suppressed in system headers, etc. 
Makes sense? Tested x86_64-linux.


Thanks, Paolo.



Index: cp/decl.c
===
--- cp/decl.c   (revision 277097)
+++ cp/decl.c   (working copy)
@@ -4933,10 +4933,9 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
  "multiple types in one declaration");
   else if (declspecs->redefined_builtin_type)
 {
-  if (!in_system_header_at (input_location))
-   permerror (declspecs->locations[ds_redefined_builtin_type_spec],
-  "redeclaration of C++ built-in type %qT",
-  declspecs->redefined_builtin_type);
+  permerror (declspecs->locations[ds_redefined_builtin_type_spec],
+"redeclaration of C++ built-in type %qT",
+declspecs->redefined_builtin_type);
   return NULL_TREE;
 }
 
@@ -4984,7 +4983,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
 --end example]  */
   if (saw_typedef)
{
- error ("missing type-name in typedef-declaration");
+ error_at (declspecs->locations[ds_typedef],
+   "missing type-name in typedef-declaration");
  return NULL_TREE;
}
   /* Anonymous unions are objects, so they can have specifiers.  */;
@@ -9328,7 +9328,6 @@ grokfndecl (tree ctype,
}
  /* 17.6.3.3.5  */
  if (suffix[0] != '_'
- && !in_system_header_at (location)
  && !current_function_decl && !(friendp && !funcdef_flag))
warning_at (location, OPT_Wliteral_suffix,
"literal operator suffixes not preceded by %<_%>"
@@ -10036,8 +10035,6 @@ compute_array_index_type_loc (location_t name_loc,
   indicated by the state of complain), so that
   another substitution can be found.  */
return error_mark_node;
- else if (in_system_header_at (input_location))
-   /* Allow them in system headers because glibc uses them.  */;
  else if (name)
pedwarn (loc, OPT_Wpedantic,
 "ISO C++ forbids zero-size array %qD", name);
@@ -11004,7 +11001,7 @@ grokdeclarator (const cp_declarator *declarator,
 
   if (type_was_error_mark_node)
/* We've already issued an error, don't complain more.  */;
-  else if (in_system_header_at (input_location) || flag_ms_extensions)
+  else if (flag_ms_extensions)
/* Allow it, sigh.  */;
   else if (! is_main)
permerror (id_loc, "ISO C++ forbids declaration of %qs with no type",
@@ -11037,7 +11034,7 @@ grokdeclarator (const cp_declarator *declarator,
}
   /* Don't pedwarn if the alternate "__intN__" form has been used instead
 of "__intN".  */
-  else if (!int_n_alt && pedantic && ! in_system_header_at 
(input_location))
+  else if (!int_n_alt && pedantic)
pedwarn (declspecs->locations[ds_type_spec], OPT_Wpedantic,
 "ISO C++ does not support %<__int%d%> for %qs",
 int_n_data[declspecs->int_n_idx].bitsize, name);
@@ -12695,10 +12692,7 @@ grokdeclarator (const cp_declarator *declarator,
else
  {
/* Array is a flexible member.  */
-   if (in_system_header_at (input_location))
- /* Do not warn on flexible array members in system
-headers because glibc uses them.  */;
-   else if (name)
+   if (name)
  pedwarn (id_loc, OPT_Wpedantic,
   "ISO C++ forbids flexible array member %qs", name);
else
Index: cp/error.c
===
--- cp/error.c  (revision 277097)
+++ cp/error.c  (working copy)
@@ -4317,10 +4317,7 @@ cp_printer (pretty_printer *pp, text_info *text, c
 void
 maybe_warn_cpp0x (cpp0x_warn_str str)
 {
-  if ((cxx_dialect == cxx98) && !in_system_header_at (input

Re: [C++ Patch] Remove most uses of in_system_header_at

2019-10-16 Thread Paolo Carlini
... the below, slightly extended patch: 1- Makes sure the 
in_system_header_at calls surviving in decl.c get the same location used 
for the corresponding diagnostic; exploit locations[ds_typedef] in an 
error_at in grokdeclarator.


Tested, as usual, on x86_64-linux.

Thanks, Paolo.

/

/cp
2019-10-16  Paolo Carlini  

* decl.c (grokfndecl): Remove redundant use of in_system_header_at.
(compute_array_index_type_loc): Likewise.
(grokdeclarator): Likewise.
* error.c (cp_printer): Likewise.
* lambda.c (add_default_capture): Likewise.
* parser.c (cp_parser_primary_expression): Likewise.
(cp_parser_selection_statement): Likewise.
(cp_parser_toplevel_declaration): Likewise.
(cp_parser_enumerator_list): Likewise.
(cp_parser_using_declaration): Likewise.
(cp_parser_member_declaration): Likewise.
(cp_parser_exception_specification_opt): Likewise.
(cp_parser_std_attribute_spec): Likewise.
* pt.c (do_decl_instantiation): Likewise.
(do_type_instantiation): Likewise.
* typeck.c (cp_build_unary_op): Likewise.

* decl.c (check_tag_decl): Pass to in_system_header_at the same
location used for the permerror.
(grokdeclarator): Likewise.

* decl.c (check_tag_decl): Use locations[ds_typedef] in error_at.

/testsuite
2019-10-16  Paolo Carlini  

* g++.old-deja/g++.other/decl9.C: Check locations too.
Index: cp/decl.c
===
--- cp/decl.c   (revision 276984)
+++ cp/decl.c   (working copy)
@@ -4933,9 +4933,9 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
  "multiple types in one declaration");
   else if (declspecs->redefined_builtin_type)
 {
-  if (!in_system_header_at (input_location))
-   permerror (declspecs->locations[ds_redefined_builtin_type_spec],
-  "redeclaration of C++ built-in type %qT",
+  location_t loc = declspecs->locations[ds_redefined_builtin_type_spec];
+  if (!in_system_header_at (loc))
+   permerror (loc, "redeclaration of C++ built-in type %qT",
   declspecs->redefined_builtin_type);
   return NULL_TREE;
 }
@@ -4984,7 +4984,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
 --end example]  */
   if (saw_typedef)
{
- error ("missing type-name in typedef-declaration");
+ error_at (declspecs->locations[ds_typedef],
+   "missing type-name in typedef-declaration");
  return NULL_TREE;
}
   /* Anonymous unions are objects, so they can have specifiers.  */;
@@ -9328,7 +9329,6 @@ grokfndecl (tree ctype,
}
  /* 17.6.3.3.5  */
  if (suffix[0] != '_'
- && !in_system_header_at (location)
  && !current_function_decl && !(friendp && !funcdef_flag))
warning_at (location, OPT_Wliteral_suffix,
"literal operator suffixes not preceded by %<_%>"
@@ -10036,8 +10036,6 @@ compute_array_index_type_loc (location_t name_loc,
   indicated by the state of complain), so that
   another substitution can be found.  */
return error_mark_node;
- else if (in_system_header_at (input_location))
-   /* Allow them in system headers because glibc uses them.  */;
  else if (name)
pedwarn (loc, OPT_Wpedantic,
 "ISO C++ forbids zero-size array %qD", name);
@@ -11004,7 +11002,7 @@ grokdeclarator (const cp_declarator *declarator,
 
   if (type_was_error_mark_node)
/* We've already issued an error, don't complain more.  */;
-  else if (in_system_header_at (input_location) || flag_ms_extensions)
+  else if (in_system_header_at (id_loc) || flag_ms_extensions)
/* Allow it, sigh.  */;
   else if (! is_main)
permerror (id_loc, "ISO C++ forbids declaration of %qs with no type",
@@ -11037,7 +11035,7 @@ grokdeclarator (const cp_declarator *declarator,
}
   /* Don't pedwarn if the alternate "__intN__" form has been used instead
 of "__intN".  */
-  else if (!int_n_alt && pedantic && ! in_system_header_at 
(input_location))
+  else if (!int_n_alt && pedantic)
pedwarn (declspecs->locations[ds_type_spec], OPT_Wpedantic,
 "ISO C++ does not support %<__int%d%> for %qs",
 int_n_data[declspecs->int_n_idx].bitsize, name);
@@ -12695,10 +12693,7 @@ grokdeclarator (const cp_declarator *declarator,
else
  {
/* Array is a flexible member.  */
-   if (in_system_header_at (input_location))
- /* Do not warn o

Re: [C++ Patch] Remove most uses of in_system_header_at

2019-10-14 Thread Paolo Carlini

Hi,

On 12/10/19 00:28, Jakub Jelinek wrote:

@@ -10036,8 +10035,6 @@ compute_array_index_type_loc (location_t name_loc,
   indicated by the state of complain), so that
   another substitution can be found.  */
return error_mark_node;
- else if (in_system_header_at (input_location))
-   /* Allow them in system headers because glibc uses them.  */;
  else if (name)
pedwarn (loc, OPT_Wpedantic,
 "ISO C++ forbids zero-size array %qD", name);

But this one is unclear, in_system_header_at is testing a different location
from what will be used by pedwarn, so if input_location is in system header
and loc is not, it didn't pedwarn before and now it will.
Similarly various other spots in the patch.  I haven't tried to check in
detail what exactly we want in each case, all I want to say is that some
cases are obvious, other cases are not.


Thanks for noticiing. We already discussed that a bit with Marek: we 
believe it should not make a difference, in practice, because the 
difference should only be quite small and if the first location is in 
the header the second one is supposed to be there too. More importantly, 
as far as I know, the difference is just an historical artifact and many 
actually I created myself ;) when I started changing decl.c, decl2.c, 
etc, to pass locations more consistently: I simply left the 
in_system_header bits alone for simplicity (as discussed with Marek).


Thanks, Paolo.



[C++ Patch] Remove most uses of in_system_header_at

2019-10-11 Thread Paolo Carlini

Hi,

as promised, this removes most uses of the predicate. I left alone the 
two occurrences in decl.c which guard permerrors, not warnings, and two 
more in parser.c which should be a (minor) optimization (particularly 
that in cp_parser_cast_expression).


Tested x86_64-linux.

Thanks, Paolo.

///

2019-10-11  Paolo Carlini  

* decl.c (grokfndecl): Remove redundant use of in_system_header_at.
(compute_array_index_type_loc): Likewise.
(grokdeclarator): Likewise.
* error.c (cp_printer): Likewise.
* lambda.c (add_default_capture): Likewise.
* parser.c (cp_parser_primary_expression): Likewise.
(cp_parser_selection_statement): Likewise.
(cp_parser_toplevel_declaration): Likewise.
(cp_parser_enumerator_list): Likewise.
(cp_parser_using_declaration): Likewise.
(cp_parser_member_declaration): Likewise.
(cp_parser_exception_specification_opt): Likewise.
(cp_parser_std_attribute_spec): Likewise.
* pt.c (do_decl_instantiation): Likewise.
(do_type_instantiation): Likewise.
* typeck.c (cp_build_unary_op): Likewise.
Index: decl.c
===
--- decl.c  (revision 276903)
+++ decl.c  (working copy)
@@ -9328,7 +9328,6 @@ grokfndecl (tree ctype,
}
  /* 17.6.3.3.5  */
  if (suffix[0] != '_'
- && !in_system_header_at (location)
  && !current_function_decl && !(friendp && !funcdef_flag))
warning_at (location, OPT_Wliteral_suffix,
"literal operator suffixes not preceded by %<_%>"
@@ -10036,8 +10035,6 @@ compute_array_index_type_loc (location_t name_loc,
   indicated by the state of complain), so that
   another substitution can be found.  */
return error_mark_node;
- else if (in_system_header_at (input_location))
-   /* Allow them in system headers because glibc uses them.  */;
  else if (name)
pedwarn (loc, OPT_Wpedantic,
 "ISO C++ forbids zero-size array %qD", name);
@@ -11037,7 +11034,7 @@ grokdeclarator (const cp_declarator *declarator,
}
   /* Don't pedwarn if the alternate "__intN__" form has been used instead
 of "__intN".  */
-  else if (!int_n_alt && pedantic && ! in_system_header_at 
(input_location))
+  else if (!int_n_alt && pedantic)
pedwarn (declspecs->locations[ds_type_spec], OPT_Wpedantic,
 "ISO C++ does not support %<__int%d%> for %qs",
 int_n_data[declspecs->int_n_idx].bitsize, name);
@@ -12695,10 +12692,7 @@ grokdeclarator (const cp_declarator *declarator,
else
  {
/* Array is a flexible member.  */
-   if (in_system_header_at (input_location))
- /* Do not warn on flexible array members in system
-headers because glibc uses them.  */;
-   else if (name)
+   if (name)
  pedwarn (id_loc, OPT_Wpedantic,
   "ISO C++ forbids flexible array member %qs", name);
else
Index: error.c
===
--- error.c (revision 276903)
+++ error.c (working copy)
@@ -4317,10 +4317,7 @@ cp_printer (pretty_printer *pp, text_info *text, c
 void
 maybe_warn_cpp0x (cpp0x_warn_str str)
 {
-  if ((cxx_dialect == cxx98) && !in_system_header_at (input_location))
-/* We really want to suppress this warning in system headers,
-   because libstdc++ uses variadic templates even when we aren't
-   in C++0x mode. */
+  if (cxx_dialect == cxx98)
 switch (str)
   {
   case CPP0X_INITIALIZER_LISTS:
Index: lambda.c
===
--- lambda.c(revision 276903)
+++ lambda.c(working copy)
@@ -697,8 +697,7 @@ add_default_capture (tree lambda_stack, tree id, t
   /* Warn about deprecated implicit capture of this via [=].  */
   if (cxx_dialect >= cxx2a
  && this_capture_p
- && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) == CPLD_COPY
- && !in_system_header_at (LAMBDA_EXPR_LOCATION (lambda)))
+ && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) == CPLD_COPY)
{
  if (warning_at (LAMBDA_EXPR_LOCATION (lambda), OPT_Wdeprecated,
  "implicit capture of %qE via %<[=]%> is deprecated "
Index: parser.c
===
--- parser.c(revision 276903)
+++ parser.c(working copy)
@@ -5364,8 +5364,7 @@ cp_parser_primary_expression (cp_parser *parser,
  {
  

Re: [C++ Patch] Remove RROTATE_EXPR and LROTATE_EXPR handling

2019-10-11 Thread Paolo Carlini

Hi,

On 11/10/19 18:25, Jason Merrill wrote:

On 10/10/19 2:33 PM, Paolo Carlini wrote:

Hi,

On 10/10/19 19:57, Jason Merrill wrote:

On 10/10/19 1:53 PM, Jakub Jelinek wrote:

On Thu, Oct 10, 2019 at 06:12:02PM +0200, Paolo Carlini wrote:
while working on cp_build_binary_op I noticed that the testsuite 
wasn't
exercising the warnings in case RROTATE_EXPR / LROTATE_EXPR, even 
more the
code handling those tree codes seemed completely unused. Turned 
out that the

C front-end doesn't handle those tree codes at all: I'm coming to the
conclusion that the C++ front-end bits too are now obsolete and 
may be
removed, because only the middle-end generates those codes in 
order to
implement optimizations. Anything I'm missing? Any additional 
testing?


I guess it depends on where.
fold_binary_loc certainly has code to create {L,R}ROTATE_EXPR,
just look at
unsigned foo (unsigned x)
{
   return (x << 3) + (x >> (__SIZEOF_INT__ * __CHAR_BIT__ - 3));
}

unsigned bar (unsigned x, unsigned y)
{
   return (x << y) | (x >> (__SIZEOF_INT__ * __CHAR_BIT__ - y));
}
and the *.original dump.
The cp_build_binary_op case is unlikely to ever trigger, unless 
we'd rerun

it on cp_folded trees.
cxx_eval_constant_expression is unlikely, because recently we've 
switched to
performing constexpr evaluation on pre-cp_folded bodies, not sure 
if we

never encounter folded trees though.
cp_fold itself depends on whether we ever reprocess the already folded
trees, I'd be afraid we could.


True, and the failure mode there is silent.  Let's leave the codes 
in that switch.


Ok, thanks Jason and Jakub for the additional information.

While I give this more thought and maybe manage to come up with a 
testcase triggering the warning, shall we simply pass the location to 
those two warnings too - cannot hurt, AFAICS?


I meant let's omit the changes to cp_fold, the rest of the patch is 
still OK.


Nice, thanks, I'll do that.

Paolo.



Re: [C++ Patch] One more DECL_SOURCE_LOCATION

2019-10-11 Thread Paolo Carlini

Hi,

On 11/10/19 17:52, Jakub Jelinek wrote:

On Fri, Oct 11, 2019 at 05:34:16PM +0200, Paolo Carlini wrote:

Hi again...

On 11/10/19 17:30, Paolo Carlini wrote:

Oh nice, I wasn't aware of that, to be honest, probably we should audit
the front-end for more such redundant uses.

... and I can confirm that we have *many*. If we agree that removing all of
them is the way to go I can do that in a follow up patch.

If they just guard a pedwarn/warning/warning_at etc., that's fine, if they
guard also some code that needs to compute something for the diagnostics,
it might not be redundant.


Indeed. We got many of the very straightforward ones ;)

Paolo.



Re: [C++ Patch] One more DECL_SOURCE_LOCATION

2019-10-11 Thread Paolo Carlini

Hi again...

On 11/10/19 17:30, Paolo Carlini wrote:
Oh nice, I wasn't aware of that, to be honest, probably we should 
audit the front-end for more such redundant uses.


... and I can confirm that we have *many*. If we agree that removing all 
of them is the way to go I can do that in a follow up patch.


Thanks, Paolo.



Re: [C++ Patch] One more DECL_SOURCE_LOCATION

2019-10-11 Thread Paolo Carlini

Hi,

On 11/10/19 17:23, Marek Polacek wrote:

I mean the latter; pedwarn will check for diagnostic_report_warnings_p so
the pedwarn will not trigger in a system header unless -Wsystem-headers
even without that check.


Oh nice, I wasn't aware of that, to be honest, probably we should audit 
the front-end for more such redundant uses. Anyway, consider it dropped 
in this case, I'm re-running the testsuite to be safe.


Thanks, Paolo.



Re: [C++ Patch] One more DECL_SOURCE_LOCATION

2019-10-11 Thread Paolo Carlini

Hi,

On 11/10/19 15:37, Marek Polacek wrote:



Index: cp/decl.c
===
--- cp/decl.c   (revision 276845)
+++ cp/decl.c   (working copy)
@@ -4992,7 +4992,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
  
if (TREE_CODE (declared_type) != UNION_TYPE

  && !in_system_header_at (input_location))
-   pedwarn (input_location, OPT_Wpedantic, "ISO C++ prohibits anonymous 
structs");
+   pedwarn (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (declared_type)),
+OPT_Wpedantic, "ISO C++ prohibits anonymous structs");

The change looks fine but the in_system_header_at line can be dropped, right?


What do you mean, exactly? Do you mean that, more correctly, we should 
use DECL_SOURCE_LOCATION for it too or that in fact is and was already 
completely redundant? I agree with the former, I didn't bother changing 
it (likely in a couple of other places too) because in practice 
input_location should work fine anyway as far as noticing that we are in 
system header is concerned and is simpler. If you mean the latter, I'm 
not sure, I don't really see why...


Paolo.



[C++ Patch] One more DECL_SOURCE_LOCATION

2019-10-11 Thread Paolo Carlini

Hi,

another straightforward DECL_SOURCE_LOCATION (TYPE_MAIN_DECL consistent 
with the one I used in build_anon_union_vars. Tested x86_64-linux.


Thanks, Paolo.

/
/cp
2019-10-11  Paolo Carlini  

* decl.c (check_tag_decl): Use DECL_SOURCE_LOCATION.

/testsuite
2019-10-11  Paolo Carlini  

* g++.dg/cpp0x/constexpr-union5.C: Test location(s) too.
* g++.dg/diagnostic/bitfld2.C: Likewise.
* g++.dg/ext/anon-struct1.C: Likewise.
* g++.dg/ext/anon-struct6.C: Likewise.
* g++.dg/ext/flexary19.C: Likewise.
* g++.dg/ext/flexary9.C: Likewise.
* g++.dg/template/error17.C: Likewise.
Index: cp/decl.c
===
--- cp/decl.c   (revision 276845)
+++ cp/decl.c   (working copy)
@@ -4992,7 +4992,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
 
   if (TREE_CODE (declared_type) != UNION_TYPE
  && !in_system_header_at (input_location))
-   pedwarn (input_location, OPT_Wpedantic, "ISO C++ prohibits anonymous 
structs");
+   pedwarn (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (declared_type)),
+OPT_Wpedantic, "ISO C++ prohibits anonymous structs");
 }
 
   else
Index: testsuite/g++.dg/cpp0x/constexpr-union5.C
===
--- testsuite/g++.dg/cpp0x/constexpr-union5.C   (revision 276845)
+++ testsuite/g++.dg/cpp0x/constexpr-union5.C   (working copy)
@@ -23,16 +23,16 @@ SA((a.i == 42));
 
 struct B
 {
-  struct {
+  struct { // { dg-warning "10:ISO C\\+\\+ prohibits 
anonymous struct" }
 int h;
-struct {
+struct {   // { dg-warning "12:ISO C\\+\\+ prohibits 
anonymous struct" }
   union {
unsigned char i;
int j;
   };
   int k;
-}; // { dg-warning "anonymous struct" }
-  };   // { dg-warning "anonymous struct" }
+};
+  };
   int l;
 
   constexpr B(): h(1), i(2), k(3), l(4) {}
Index: testsuite/g++.dg/diagnostic/bitfld2.C
===
--- testsuite/g++.dg/diagnostic/bitfld2.C   (revision 276845)
+++ testsuite/g++.dg/diagnostic/bitfld2.C   (working copy)
@@ -6,4 +6,4 @@ template struct A
   struct {} : 2;   // { dg-error "expected ';' after struct" "expected" }
 };
 // { dg-error "ISO C.. forbids declaration" "declaration" { target *-*-* } 6 }
-// { dg-error "ISO C.. prohibits anonymous" "anonymous" { target *-*-* } 6 }
+// { dg-error "10:ISO C.. prohibits anonymous" "anonymous" { target *-*-* } 6 }
Index: testsuite/g++.dg/ext/anon-struct1.C
===
--- testsuite/g++.dg/ext/anon-struct1.C (revision 276845)
+++ testsuite/g++.dg/ext/anon-struct1.C (working copy)
@@ -19,7 +19,7 @@ char testD[sizeof(C::D) == sizeof(A) ? 1 : -1];
 
 /* GNU extension.  */
 struct E {
-  struct { char z; };  /* { dg-error "prohibits anonymous structs" } */
+  struct { char z; };  /* { dg-error "10:ISO C\\+\\+ prohibits 
anonymous structs" } */
   char e;
 };
 
@@ -45,6 +45,6 @@ char testH[sizeof(H) == 2 * sizeof(A) ? 1 : -1];
 
 /* Make sure __extension__ gets turned back off.  */
 struct I {
-  struct { char z; };  /* { dg-error "prohibits anonymous structs" } */
+  struct { char z; };  /* { dg-error "10:ISO C\\+\\+ prohibits 
anonymous structs" } */
   char i;
 };
Index: testsuite/g++.dg/ext/anon-struct6.C
===
--- testsuite/g++.dg/ext/anon-struct6.C (revision 276845)
+++ testsuite/g++.dg/ext/anon-struct6.C (working copy)
@@ -3,8 +3,8 @@
 struct A
 {
   struct
-  {
+  { // { dg-error "3:ISO C\\+\\+ prohibits anonymous structs" }
 struct { static int i; }; // { dg-error "prohibits anonymous 
structs|non-static data members|unnamed class" }
 void foo() { i; } // { dg-error "public non-static data" }
-  }; // { dg-error "prohibits anonymous structs" }
+  };
 };
Index: testsuite/g++.dg/ext/flexary19.C
===
--- testsuite/g++.dg/ext/flexary19.C(revision 276845)
+++ testsuite/g++.dg/ext/flexary19.C(working copy)
@@ -146,13 +146,13 @@ struct S16
 {
   int i;
 
-  struct {  // { dg-warning "invalid use" }
+  struct {  // { dg-warning "10:ISO C\\+\\+ prohibits anonymous 
struct|invalid use" }
 // A flexible array as a sole member of an anonymous struct is
 // rejected with an error in C mode but emits just a pedantic
 // warning in C++.  Other than excessive pedantry there is no
 // reason to reject it.
 int a[];
-  };

Re: [C++ Patch] Remove RROTATE_EXPR and LROTATE_EXPR handling

2019-10-10 Thread Paolo Carlini

Hi,

On 10/10/19 19:57, Jason Merrill wrote:

On 10/10/19 1:53 PM, Jakub Jelinek wrote:

On Thu, Oct 10, 2019 at 06:12:02PM +0200, Paolo Carlini wrote:

while working on cp_build_binary_op I noticed that the testsuite wasn't
exercising the warnings in case RROTATE_EXPR / LROTATE_EXPR, even 
more the
code handling those tree codes seemed completely unused. Turned out 
that the

C front-end doesn't handle those tree codes at all: I'm coming to the
conclusion that the C++ front-end bits too are now obsolete and may be
removed, because only the middle-end generates those codes in order to
implement optimizations. Anything I'm missing? Any additional testing?


I guess it depends on where.
fold_binary_loc certainly has code to create {L,R}ROTATE_EXPR,
just look at
unsigned foo (unsigned x)
{
   return (x << 3) + (x >> (__SIZEOF_INT__ * __CHAR_BIT__ - 3));
}

unsigned bar (unsigned x, unsigned y)
{
   return (x << y) | (x >> (__SIZEOF_INT__ * __CHAR_BIT__ - y));
}
and the *.original dump.
The cp_build_binary_op case is unlikely to ever trigger, unless we'd 
rerun

it on cp_folded trees.
cxx_eval_constant_expression is unlikely, because recently we've 
switched to

performing constexpr evaluation on pre-cp_folded bodies, not sure if we
never encounter folded trees though.
cp_fold itself depends on whether we ever reprocess the already folded
trees, I'd be afraid we could.


True, and the failure mode there is silent.  Let's leave the codes in 
that switch.


Ok, thanks Jason and Jakub for the additional information.

While I give this more thought and maybe manage to come up with a 
testcase triggering the warning, shall we simply pass the location to 
those two warnings too - cannot hurt, AFAICS?


Thanks, Paolo.





Index: typeck.c
===
--- typeck.c(revision 276845)
+++ typeck.c(working copy)
@@ -4906,16 +4906,16 @@ cp_build_binary_op (const op_location_t ,
  if (tree_int_cst_lt (op1, integer_zero_node))
{
  if (complain & tf_warning)
-   warning (0, (code == LROTATE_EXPR)
- ? G_("left rotate count is negative")
- : G_("right rotate count is negative"));
+   warning_at (location, 0, (code == LROTATE_EXPR)
+   ? G_("left rotate count is negative")
+   : G_("right rotate count is negative"));
}
  else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
{
  if (complain & tf_warning)
-   warning (0, (code == LROTATE_EXPR) 
-  ? G_("left rotate count >= width of type")
-  : G_("right rotate count >= width of type"));
+   warning_at (location, 0, (code == LROTATE_EXPR) 
+   ? G_("left rotate count >= width of type")
+   : G_("right rotate count >= width of type"));
}
}
  /* Convert the shift-count to an integer, regardless of


[C++ Patch] Remove RROTATE_EXPR and LROTATE_EXPR handling

2019-10-10 Thread Paolo Carlini

Hi,

while working on cp_build_binary_op I noticed that the testsuite wasn't 
exercising the warnings in case RROTATE_EXPR / LROTATE_EXPR, even more 
the code handling those tree codes seemed completely unused. Turned out 
that the C front-end doesn't handle those tree codes at all: I'm coming 
to the conclusion that the C++ front-end bits too are now obsolete and 
may be removed, because only the middle-end generates those codes in 
order to implement optimizations. Anything I'm missing? Any additional 
testing? Tested x86_64-linux.


Thanks, Paolo.

///

2019-10-10  Paolo Carlini  

* typeck.c (cp_build_binary_op): Do not handle RROTATE_EXPR and
LROTATE_EXPR.
* constexpr.c (cxx_eval_constant_expression): Likewise.
(potential_constant_expression_1): Likewise.
* cp-gimplify.c (cp_fold): Likewise.
* pt.c (tsubst_copy): Likewise.
Index: constexpr.c
===
--- constexpr.c (revision 276805)
+++ constexpr.c (working copy)
@@ -5115,8 +5115,6 @@ cxx_eval_constant_expression (const constexpr_ctx
 case MAX_EXPR:
 case LSHIFT_EXPR:
 case RSHIFT_EXPR:
-case LROTATE_EXPR:
-case RROTATE_EXPR:
 case BIT_IOR_EXPR:
 case BIT_XOR_EXPR:
 case BIT_AND_EXPR:
@@ -7103,8 +7101,6 @@ potential_constant_expression_1 (tree t, bool want
 case MAX_EXPR:
 case LSHIFT_EXPR:
 case RSHIFT_EXPR:
-case LROTATE_EXPR:
-case RROTATE_EXPR:
 case BIT_IOR_EXPR:
 case BIT_XOR_EXPR:
 case BIT_AND_EXPR:
Index: cp-gimplify.c
===
--- cp-gimplify.c   (revision 276805)
+++ cp-gimplify.c   (working copy)
@@ -2468,8 +2468,6 @@ cp_fold (tree x)
 case MAX_EXPR:
 case LSHIFT_EXPR:
 case RSHIFT_EXPR:
-case LROTATE_EXPR:
-case RROTATE_EXPR:
 case BIT_AND_EXPR:
 case BIT_IOR_EXPR:
 case BIT_XOR_EXPR:
Index: pt.c
===
--- pt.c(revision 276805)
+++ pt.c(working copy)
@@ -16308,8 +16308,6 @@ tsubst_copy (tree t, tree args, tsubst_flags_t com
 case TRUTH_OR_EXPR:
 case RSHIFT_EXPR:
 case LSHIFT_EXPR:
-case RROTATE_EXPR:
-case LROTATE_EXPR:
 case EQ_EXPR:
 case NE_EXPR:
 case MAX_EXPR:
@@ -18913,8 +18911,6 @@ tsubst_copy_and_build (tree t,
 case TRUTH_OR_EXPR:
 case RSHIFT_EXPR:
 case LSHIFT_EXPR:
-case RROTATE_EXPR:
-case LROTATE_EXPR:
 case EQ_EXPR:
 case NE_EXPR:
 case MAX_EXPR:
Index: typeck.c
===
--- typeck.c(revision 276805)
+++ typeck.c(working copy)
@@ -4896,35 +4896,6 @@ cp_build_binary_op (const op_location_t ,
}
   break;
 
-case RROTATE_EXPR:
-case LROTATE_EXPR:
-  if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
-   {
- result_type = type0;
- if (TREE_CODE (op1) == INTEGER_CST)
-   {
- if (tree_int_cst_lt (op1, integer_zero_node))
-   {
- if (complain & tf_warning)
-   warning (0, (code == LROTATE_EXPR)
- ? G_("left rotate count is negative")
- : G_("right rotate count is negative"));
-   }
- else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
-   {
- if (complain & tf_warning)
-   warning (0, (code == LROTATE_EXPR) 
-  ? G_("left rotate count >= width of type")
-  : G_("right rotate count >= width of type"));
-   }
-   }
- /* Convert the shift-count to an integer, regardless of
-size of value being shifted.  */
- if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
-   op1 = cp_convert (integer_type_node, op1, complain);
-   }
-  break;
-
 case EQ_EXPR:
 case NE_EXPR:
   if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)


[C++ Patch] Fix cp_build_binary_op locations

2019-10-09 Thread Paolo Carlini

Hi,

this largely mechanical patch fixes those errors in cp_build_binary_op 
which weren't exploiting yet the op_location_t argument, thus aligning 
the locations to those of the C front-end. Plus an additional use for 
DECL_SOURCE_LOCATION in decl.c. Tested x86_64-linux.


Thanks, Paolo.

///

/cp
2019-10-09  Paolo Carlini  

* decl.c (grok_ctor_properties): Use DECL_SOURCE_LOCATION.
* typeck.c (cp_build_binary_op): Use the op_location_t argument
in many error messages.

/testsuite
2019-10-09  Paolo Carlini  

* c-c++-common/Waddress-1.c: Test locations too.
* c-c++-common/Wpointer-compare-1.c: Likewise.
* c-c++-common/Wshift-count-negative-1.c: Likewise.
* c-c++-common/Wshift-count-overflow-1.c: Likewise.
* c-c++-common/Wshift-negative-value-1.c: Likewise.
* c-c++-common/Wshift-negative-value-2.c: Likewise.
* c-c++-common/Wshift-negative-value-5.c: Likewise.
* c-c++-common/pr48418.c: Likewise.
* c-c++-common/pr65830.c: Likewise.
* c-c++-common/pr69764.c: Likewise.
* g++.dg/cpp0x/constexpr-array-ptr10.C: Likewise.
* g++.dg/cpp0x/nullptr37.C: Likewise.
* g++.dg/template/crash126.C: Likewise.
* g++.dg/template/crash129.C: Likewise.
* g++.dg/warn/Wextra-3.C: Likewise.
* g++.dg/warn/Wfloat-equal-1.C: Likewise.
* g++.dg/warn/Wstring-literal-comparison-1.C: Likewise.
* g++.dg/warn/Wstring-literal-comparison-2.C: Likewise.
* g++.dg/warn/pointer-integer-comparison.C: Likewise.
* g++.old-deja/g++.jason/crash8.C: Likewise.
Index: cp/decl.c
===
--- cp/decl.c   (revision 276756)
+++ cp/decl.c   (working copy)
@@ -13738,7 +13738,8 @@ grok_ctor_properties (const_tree ctype, const_tree
 or implicitly defined), there's no need to worry about their
 existence.  Theoretically, they should never even be
 instantiated, but that's hard to forestall.  */
-  error ("invalid constructor; you probably meant %<%T (const %T&)%>",
+  error_at (DECL_SOURCE_LOCATION (decl),
+   "invalid constructor; you probably meant %<%T (const %T&)%>",
ctype, ctype);
   return false;
 }
Index: cp/typeck.c
===
--- cp/typeck.c (revision 276756)
+++ cp/typeck.c (working copy)
@@ -4475,7 +4475,8 @@ cp_build_binary_op (const op_location_t ,
   if (t != error_mark_node)
{
  if (complain & tf_error)
-   permerror (input_location, "assuming cast to type %qT from 
overloaded function",
+   permerror (location,
+  "assuming cast to type %qT from overloaded function",
   TREE_TYPE (t));
  op0 = t;
}
@@ -4486,7 +4487,8 @@ cp_build_binary_op (const op_location_t ,
   if (t != error_mark_node)
{
  if (complain & tf_error)
-   permerror (input_location, "assuming cast to type %qT from 
overloaded function",
+   permerror (location,
+  "assuming cast to type %qT from overloaded function",
   TREE_TYPE (t));
  op1 = t;
}
@@ -4809,8 +4811,8 @@ cp_build_binary_op (const op_location_t ,
{
  if ((complain & tf_warning)
  && c_inhibit_evaluation_warnings == 0)
-   warning (OPT_Wshift_count_negative,
-"right shift count is negative");
+   warning_at (location, OPT_Wshift_count_negative,
+   "right shift count is negative");
}
  else
{
@@ -4817,8 +4819,8 @@ cp_build_binary_op (const op_location_t ,
  if (compare_tree_int (const_op1, TYPE_PRECISION (type0)) >= 0
  && (complain & tf_warning)
  && c_inhibit_evaluation_warnings == 0)
-   warning (OPT_Wshift_count_overflow,
-"right shift count >= width of type");
+   warning_at (location, OPT_Wshift_count_overflow,
+   "right shift count >= width of type");
}
}
  /* Avoid converting op1 to result_type later.  */
@@ -4856,8 +4858,8 @@ cp_build_binary_op (const op_location_t ,
  && tree_int_cst_sgn (const_op0) < 0
  && (complain & tf_warning)
  && c_inhibit_evaluation_warnings == 0)
-   warning (OPT_Wshift_negative_value,
-"left shift of negative value");
+   warning_at (location, OPT_Wshift_negative_valu

[C++ Patch] Fix cp_parser_delete_expression and cp_parser_throw_expression locations and more

2019-10-07 Thread Paolo Carlini

Hi,

the below fixes those two functions consistently with 
cp_parser_new_expression. Additionally, a few rather straightforward 
tweaks along the usual lines, more DECL_SOURCE_LOCATION and id_loc. 
Tested x86_64-linux.


Thanks, Paolo.

/

/cp
2019-10-07  Paolo Carlini  

* call.c (resolve_args): Use cp_expr_loc_or_input_loc in one place.
* decl.c (grokdeclarator): Use id_loc in one place.
* decl2.c (build_anon_union_vars): Use DECL_SOURCE_LOCATION.
* parser.c (cp_parser_delete_expression): Fix the location of the
returned expression.
(cp_parser_throw_expression): Likewise.
* pt.c (determine_specialization): Use DECL_SOURCE_LOCATION.

/testsuite
2019-10-07  Paolo Carlini  

* g++.dg/diagnostic/not-a-function-template-1.C: New.
* g++.dg/template/crash107.C: Adjust expected location.
* g++.dg/template/dependent-expr1.C: Check locations.
* g++.dg/template/error17.C: Check location.
Index: cp/call.c
===
--- cp/call.c   (revision 276646)
+++ cp/call.c   (working copy)
@@ -4381,7 +4381,8 @@ resolve_args (vec *args, tsubst_flags
   else if (VOID_TYPE_P (TREE_TYPE (arg)))
{
  if (complain & tf_error)
-   error ("invalid use of void expression");
+   error_at (cp_expr_loc_or_input_loc (arg),
+ "invalid use of void expression");
  return NULL;
}
   else if (invalid_nonstatic_memfn_p (EXPR_LOCATION (arg), arg, complain))
Index: cp/decl.c
===
--- cp/decl.c   (revision 276646)
+++ cp/decl.c   (working copy)
@@ -12754,8 +12754,8 @@ grokdeclarator (const cp_declarator *declarator,
tree tmpl = TREE_OPERAND (unqualified_id, 0);
if (variable_template_p (tmpl))
  {
-   error ("specialization of variable template %qD "
-  "declared as function", tmpl);
+   error_at (id_loc, "specialization of variable template "
+ "%qD declared as function", tmpl);
inform (DECL_SOURCE_LOCATION (tmpl),
"variable template declared here");
return error_mark_node;
Index: cp/decl2.c
===
--- cp/decl2.c  (revision 276646)
+++ cp/decl2.c  (working copy)
@@ -1608,7 +1608,8 @@ build_anon_union_vars (tree type, tree object)
  just give an error.  */
   if (TREE_CODE (type) != UNION_TYPE)
 {
-  error ("anonymous struct not inside named type");
+  error_at (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
+   "anonymous struct not inside named type");
   return error_mark_node;
 }
 
Index: cp/parser.c
===
--- cp/parser.c (revision 276646)
+++ cp/parser.c (working copy)
@@ -9014,6 +9014,7 @@ cp_parser_delete_expression (cp_parser* parser)
   bool global_scope_p;
   bool array_p;
   tree expression;
+  location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
 
   /* Look for the optional `::' operator.  */
   global_scope_p
@@ -9043,8 +9044,18 @@ cp_parser_delete_expression (cp_parser* parser)
   if (cp_parser_non_integral_constant_expression (parser, NIC_DEL))
 return error_mark_node;
 
-  return delete_sanity (expression, NULL_TREE, array_p, global_scope_p,
-   tf_warning_or_error);
+  /* Construct a location e.g.:
+   delete [ ] ptr
+   ^~
+ with caret == start at the start of the "delete" token, and
+ the end at the end of the final token we consumed.  */
+  location_t combined_loc = make_location (start_loc, start_loc,
+  parser->lexer);
+  expression = delete_sanity (expression, NULL_TREE, array_p,
+ global_scope_p, tf_warning_or_error);
+  protected_set_expr_location (expression, combined_loc);
+
+  return expression;
 }
 
 /* Returns 1 if TOKEN may start a cast-expression and isn't '++', '--',
@@ -25827,6 +25838,7 @@ cp_parser_throw_expression (cp_parser* parser)
 {
   tree expression;
   cp_token* token;
+  location_t start_loc = cp_lexer_peek_token (parser->lexer)->location;
 
   cp_parser_require_keyword (parser, RID_THROW, RT_THROW);
   token = cp_lexer_peek_token (parser->lexer);
@@ -25842,7 +25854,17 @@ cp_parser_throw_expression (cp_parser* parser)
   else
 expression = cp_parser_assignment_expression (parser);
 
-  return build_throw (expression);
+  /* Construct a location e.g.:
+   throw x
+   ^~~
+ with caret == start at the start of the "throw" toke

Re: [C++ Patch] Improve grokdeclarator error

2019-09-30 Thread Paolo Carlini

Hi,

On 30/09/19 20:46, Jason Merrill wrote:

On Mon, Sep 30, 2019 at 6:54 AM Paolo Carlini  wrote:

On 28/09/19 04:05, Jason Merrill wrote:

On 9/26/19 3:39 PM, Paolo Carlini wrote:

+template void foo(  // { dg-error "15:template-id .foo.
used as a declarator" }

That's a strange diagnostic message; there's nothing wrong with using
a template-id as a declarator.  Why are we even calling grokdeclarator
when we hit EOF in the middle of the declarator?

It's indeed a weird situation. Note, by the way, that for

template void foo;

we end up giving the same diagnostic, only, the location was already fine.

Anyway, to explain why I say weird, clang believes it's dealing with an
explicit instantiation:

explicit instantiation of 'foo' does not refer to a function template,
variable template, member function, member class, or static data member

whereas EDG gives:

declaration is incompatible with function template "void foo<>()"

I *think* what we are issuing is closer in spirit to the latter, we
don't get fooled into thinking it's an instantiation and we say that as
a declaration doesn't work either. See what I mean?

Well, it is an explicit instantiation, the problem (as EDG says) is
that the instantiation declaration doesn't match the template.


Definitely it doesn't.




Removing completely
the diagnostic code doesn't seem fine either because we end up with very
confusing wordings like

variable or field declared void

or worse we mention variable templates, depending on the type (I already
mentioned this).

Any thought about my question about why we're calling grokdeclarator
in the first place?


Yes. If you look at cp_parser_explicit_instantiation, clearly 
cp_parser_declarator doesn't return a cp_error_declarator and in such 
cases we always call grokdeclarator. Do you think we should error out 
here instead, much earlier? Currently grokdeclarator does quite a bit of 
work before the diagnostic.


Paolo..



[C++ Patch] More cp_expr_loc_or_input_loc and DECL_SOURCE_LOCATION uses

2019-09-30 Thread Paolo Carlini

Hi,

a few more in init.c and name-lookup.c, respectively. Tested 
x86_64-linux, as usual.


Thanks, Paolo.

///

/cp
2019-09-30  Paolo Carlini  

* init.c (build_new): Use cp_expr_loc_or_input_loc in two places.
* name-lookup.c (do_pushdecl): Use DECL_SOURCE_LOCATION.
(push_class_level_binding_1): Likewise.
(set_decl_namespace): Likewise.

/testsuite
2019-09-30  Paolo Carlini  

* g++.dg/diagnostic/integral-array-size-1.C: New.
* g++.dg/cpp0x/alias-decl-1.C: Test location(s) too.
* g++.dg/init/new43.C: Likewise.
* g++.dg/lookup/friend12.C: Likewise.
* g++.dg/lookup/pr79766.C: Likewise.
* g++.dg/lookup/pr84375.C: Likewise.
* g++.dg/other/new-size-type.C: Likewise.
Index: cp/init.c
===
--- cp/init.c   (revision 276151)
+++ cp/init.c   (working copy)
@@ -3759,7 +3759,8 @@ build_new (vec **placement, tree type
   if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false))
 {
   if (complain & tf_error)
-permerror (input_location, "size in array new must have integral 
type");
+   permerror (cp_expr_loc_or_input_loc (nelts),
+  "size in array new must have integral type");
   else
 return error_mark_node;
 }
@@ -3774,7 +3775,8 @@ build_new (vec **placement, tree type
 less than zero. ... If the expression is a constant expression,
 the program is ill-fomed.  */
   if (TREE_CODE (cst_nelts) == INTEGER_CST
- && !valid_array_size_p (input_location, cst_nelts, NULL_TREE,
+ && !valid_array_size_p (cp_expr_loc_or_input_loc (nelts),
+ cst_nelts, NULL_TREE,
  complain & tf_error))
return error_mark_node;
 
Index: cp/name-lookup.c
===
--- cp/name-lookup.c(revision 276151)
+++ cp/name-lookup.c(working copy)
@@ -3080,8 +3080,9 @@ do_pushdecl (tree decl, bool is_friend)
  /* In a local class, a friend function declaration must
 find a matching decl in the innermost non-class scope.
 [class.friend/11] */
- error ("friend declaration %qD in local class without "
-"prior local declaration", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+   "friend declaration %qD in local class without "
+   "prior local declaration", decl);
  /* Don't attempt to push it.  */
  return error_mark_node;
}
@@ -4451,9 +4452,9 @@ push_class_level_binding_1 (tree name, tree x)
   tree scope = context_for_name_lookup (x);
   if (TYPE_P (scope) && same_type_p (scope, current_class_type))
{
- error ("%qD has the same name as the class in which it is "
-"declared",
-x);
+ error_at (DECL_SOURCE_LOCATION (x),
+   "%qD has the same name as the class in which it is "
+   "declared", x);
  return false;
}
 }
@@ -4757,7 +4758,8 @@ set_decl_namespace (tree decl, tree scope, bool fr
   /* Writing "N::i" to declare something directly in "N" is invalid.  */
   if (CP_DECL_CONTEXT (decl) == current_namespace
  && at_namespace_scope_p ())
-   error ("explicit qualification in declaration of %qD", decl);
+   error_at (DECL_SOURCE_LOCATION (decl),
+ "explicit qualification in declaration of %qD", decl);
   return;
 }
 
Index: testsuite/g++.dg/cpp0x/alias-decl-1.C
===
--- testsuite/g++.dg/cpp0x/alias-decl-1.C   (revision 276151)
+++ testsuite/g++.dg/cpp0x/alias-decl-1.C   (working copy)
@@ -12,5 +12,5 @@ template struct Ptr {}; // { dg-error
 
 struct A {
 using A = int;  // { dg-error "11:ISO C\\+\\+ forbids nested type .A." }
-// { dg-error "same name as" "" { target c++11 } .-1 }  
+// { dg-error "11:.using A = int. has the same name as" "" { target c++11 } 
.-1 }  
 };
Index: testsuite/g++.dg/diagnostic/integral-array-size-1.C
===
--- testsuite/g++.dg/diagnostic/integral-array-size-1.C (nonexistent)
+++ testsuite/g++.dg/diagnostic/integral-array-size-1.C (working copy)
@@ -0,0 +1,7 @@
+template
+void foo(T a)
+{
+  new int[a];  // { dg-error "11:size in array new must have integral type" }
+}
+
+template void foo(float);
Index: testsuite/g++.dg/init/new43.C

Re: [C++ Patch] Improve grokdeclarator error

2019-09-30 Thread Paolo Carlini

Hi,

On 28/09/19 04:05, Jason Merrill wrote:

On 9/26/19 3:39 PM, Paolo Carlini wrote:
+template void foo(  // { dg-error "15:template-id .foo. 
used as a declarator" }


That's a strange diagnostic message; there's nothing wrong with using 
a template-id as a declarator.  Why are we even calling grokdeclarator 
when we hit EOF in the middle of the declarator?


It's indeed a weird situation. Note, by the way, that for

template void foo;

we end up giving the same diagnostic, only, the location was already fine.

Anyway, to explain why I say weird, clang believes it's dealing with an 
explicit instantiation:


explicit instantiation of 'foo' does not refer to a function template, 
variable template, member function, member class, or static data member


whereas EDG gives:

declaration is incompatible with function template "void foo<>()"

I *think* what we are issuing is closer in spirit to the latter, we 
don't get fooled into thinking it's an instantiation and we say that as 
a declaration doesn't work either. See what I mean? Removing completely 
the diagnostic code doesn't seem fine either because we end up with very 
confusing wordings like


variable or field declared void

or worse we mention variable templates, depending on the type (I already 
mentioned this).


Thus, all in all, would it make sense to simply issue something closer 
to EDG?


Thanks, Paolo.



[C++ Patch] Improve grokdeclarator error

2019-09-26 Thread Paolo Carlini

Hi,

over the last weeks, while working on various batches of location 
improvements (a new one is forthcoming, in case you are wondering ;) I 
noticed this grokdeclarator diagnostic, one of those not exercised by 
our testsuite. While constructing a testcase I realized that probably 
it's better to immediately return error_mark_node, and avoid an 
additional redundant error about variable or field declared void or even 
about "fancy" variable templates, depending on the return type of the 
function template. Tested x86_64-linux.


Thanks, Paolo.

//

/cp
2019-09-26  Paolo Carlini  

* decl.c (grokdeclarator): Immediately return error_mark_node
upon error about template-id used as a declarator.

/testsuite
2019-09-26  Paolo Carlini  

* g++.dg/diagnostic/template-id-as-declarator-1.C: New.
Index: testsuite/g++.dg/diagnostic/template-id-as-declarator-1.C
===
--- testsuite/g++.dg/diagnostic/template-id-as-declarator-1.C   (nonexistent)
+++ testsuite/g++.dg/diagnostic/template-id-as-declarator-1.C   (working copy)
@@ -0,0 +1,5 @@
+template
+void foo() {}
+
+template void foo(  // { dg-error "15:template-id .foo. used as a 
declarator" }
+// { dg-error "expected" "" { target *-*-* } .-1 }
Index: cp/decl.c
===
--- cp/decl.c   (revision 276151)
+++ cp/decl.c   (working copy)
@@ -12078,9 +12078,9 @@ grokdeclarator (const cp_declarator *declarator,
   && !FUNC_OR_METHOD_TYPE_P (type)
   && !variable_template_p (TREE_OPERAND (unqualified_id, 0)))
 {
-  error ("template-id %qD used as a declarator",
-unqualified_id);
-  unqualified_id = dname;
+  error_at (id_loc, "template-id %qD used as a declarator",
+   unqualified_id);
+  return error_mark_node;
 }
 
   /* If TYPE is a FUNCTION_TYPE, but the function name was explicitly


[C++ Patch] Use DECL_SOURCE_LOCATION more in name-lookup.c

2019-09-24 Thread Paolo Carlini

Hi,

Marek's recent fix prompted an audit of name-lookup.c and I found a few 
additional straightforward places where we should use a more accurate 
location. Tested x86_64-linux.


Thanks, Paolo.

///

/cp
2019-09-24  Paolo Carlini  

* name-lookup.c (check_extern_c_conflict): Use DECL_SOURCE_LOCATION.
(check_local_shadow): Use it in three additional places.

/testsuite
2019-09-24  Paolo Carlini  

* g++.dg/diagnostic/redeclaration-1.C: New.
* g++.dg/lookup/extern-c-hidden.C: Test location(s) too.
* g++.dg/lookup/extern-c-redecl.C: Likewise.
* g++.dg/lookup/extern-c-redecl6.C: Likewise.
* g++.old-deja/g++.other/using9.C: Likewise.
Index: cp/name-lookup.c
===
--- cp/name-lookup.c(revision 276104)
+++ cp/name-lookup.c(working copy)
@@ -2549,12 +2549,12 @@ check_extern_c_conflict (tree decl)
   if (mismatch)
{
  auto_diagnostic_group d;
- pedwarn (input_location, 0,
+ pedwarn (DECL_SOURCE_LOCATION (decl), 0,
   "conflicting C language linkage declaration %q#D", decl);
  inform (DECL_SOURCE_LOCATION (old),
  "previous declaration %q#D", old);
  if (mismatch < 0)
-   inform (input_location,
+   inform (DECL_SOURCE_LOCATION (decl),
"due to different exception specifications");
}
   else
@@ -2674,7 +2674,8 @@ check_local_shadow (tree decl)
  /* ARM $8.3 */
  if (b->kind == sk_function_parms)
{
- error ("declaration of %q#D shadows a parameter", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+   "declaration of %q#D shadows a parameter", decl);
  return;
}
}
@@ -2700,7 +2701,8 @@ check_local_shadow (tree decl)
   && (old_scope->kind == sk_cond || old_scope->kind == sk_for))
{
  auto_diagnostic_group d;
- error ("redeclaration of %q#D", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+   "redeclaration of %q#D", decl);
  inform (DECL_SOURCE_LOCATION (old),
  "%q#D previously declared here", old);
  return;
@@ -2723,7 +2725,8 @@ check_local_shadow (tree decl)
   && in_function_try_handler))
{
  auto_diagnostic_group d;
- if (permerror (input_location, "redeclaration of %q#D", decl))
+ if (permerror (DECL_SOURCE_LOCATION (decl),
+"redeclaration of %q#D", decl))
inform (DECL_SOURCE_LOCATION (old),
"%q#D previously declared here", old);
  return;
Index: testsuite/g++.dg/diagnostic/redeclaration-1.C
===
--- testsuite/g++.dg/diagnostic/redeclaration-1.C   (nonexistent)
+++ testsuite/g++.dg/diagnostic/redeclaration-1.C   (working copy)
@@ -0,0 +1,20 @@
+void
+foo (int i)
+{
+  int i  // { dg-error "7:declaration of .int i. shadows a parameter" }
+(0);
+  
+  for (int j ;;)
+int j  // { dg-error "9:redeclaration of .int j." }
+  (0);
+}
+
+void
+bar (int i)
+  try
+{ }
+  catch (...)
+{
+  int i  // { dg-error "11:redeclaration of .int i." }
+   (0);
+}
Index: testsuite/g++.dg/lookup/extern-c-hidden.C
===
--- testsuite/g++.dg/lookup/extern-c-hidden.C   (revision 276104)
+++ testsuite/g++.dg/lookup/extern-c-hidden.C   (working copy)
@@ -4,8 +4,8 @@ extern "C" float fabsf (float);  // { dg-message "
 
 namespace Bob 
 {
-  extern "C" float fabsf (float, float); // { dg-error "C language" }
+  extern "C" float fabsf (float, float); // { dg-error "20:conflicting C 
language" }
   extern "C" double fabs (double, double); // { dg-message "previous 
declaration" }
 }
 
-extern "C" double fabs (double); // { dg-error "C language" }
+extern "C" double fabs (double); // { dg-error "19:conflicting C language" }
Index: testsuite/g++.dg/lookup/extern-c-redecl.C
===
--- testsuite/g++.dg/lookup/extern-c-redecl.C   (revision 276104)
+++ testsuite/g++.dg/lookup/extern-c-redecl.C   (working copy)
@@ -8,4 +8,4 @@ namespace A {
 // next line should trigger an error because
 // it conflicts with previous declaration of foo_func (), due to
 // different exception specifications.
-extern "C" void foo_func (); // { dg-error "C language linkage|exception 
specifications" }
+extern "C" void foo_func (); // { dg-error "17:confl

[C++ Patch] Use cp_expr_loc_or_input_loc in a few places in pt.c

2019-09-23 Thread Paolo Carlini

Hi,

simply a few new uses, in the places where we are dealing with 
expressions: we are able to do the right thing in a pretty large number 
of additional cases - the below could even include more testcases, most 
however are rather tangled (eg, we finally get the locations completely 
right only for the c++17 errors, there are additional errors on the same 
line, a few redundant ones, etc).


Tested x86_64-linux, as usual.

Thanks, Paolo.



/cp
2019-09-23  Paolo Carlini  

* pt.c (check_explicit_specialization): Use cp_expr_loc_or_input_loc.
(process_partial_specialization): Likewise.
(convert_nontype_argument_function): Likewise.
(invalid_tparm_referent_p): Likewise.
(convert_template_argument): Likewise.
(check_valid_ptrmem_cst_expr): Tidy.

/testsuite
2019-09-23  Paolo Carlini  

* g++.dg/cpp0x/pr68724.C: Check location(s) too.
* g++.dg/cpp0x/variadic38.C: Likewise.
* g++.dg/cpp1z/nontype2.C: Likewise.
* g++.dg/parse/explicit1.C: Likewise.
* g++.dg/template/crash11.C: Likewise.
* g++.dg/template/non-dependent8.C: Likewise.
* g++.dg/template/nontype-array1.C: Likewise.
* g++.dg/template/nontype3.C: Likewise.
* g++.dg/template/nontype8.C: Likewise.
* g++.dg/template/partial5.C: Likewise.
* g++.dg/template/spec33.C: Likewise.
* g++.old-deja/g++.pt/memtemp64.C: Likewise.
* g++.old-deja/g++.pt/spec20.C: Likewise.
* g++.old-deja/g++.pt/spec21.C: Likewise.
* g++.old-deja/g++.robertl/eb103.C: Likewise.
Index: cp/pt.c
===
--- cp/pt.c (revision 276015)
+++ cp/pt.c (working copy)
@@ -2808,8 +2808,9 @@ check_explicit_specialization (tree declarator,
  /* This case handles bogus declarations like template <>
 template  void f(); */
 
- error ("template-id %qD in declaration of primary template",
-declarator);
+ error_at (cp_expr_loc_or_input_loc (declarator),
+   "template-id %qE in declaration of primary template",
+   declarator);
  return decl;
}
}
@@ -2867,8 +2868,9 @@ check_explicit_specialization (tree declarator,
 template  void f(); */
 
  if (!uses_template_parms (TREE_OPERAND (declarator, 1)))
-   error ("template-id %qD in declaration of primary template",
-  declarator);
+   error_at (cp_expr_loc_or_input_loc (declarator),
+ "template-id %qE in declaration of primary template",
+ declarator);
  else if (variable_template_p (TREE_OPERAND (declarator, 0)))
{
  /* Partial specialization of variable template.  */
@@ -2877,11 +2879,13 @@ check_explicit_specialization (tree declarator,
  goto ok;
}
  else if (cxx_dialect < cxx14)
-   error ("non-type partial specialization %qD "
-  "is not allowed", declarator);
+   error_at (cp_expr_loc_or_input_loc (declarator),
+ "non-type partial specialization %qE "
+ "is not allowed", declarator);
  else
-   error ("non-class, non-variable partial specialization %qD "
-  "is not allowed", declarator);
+   error_at (cp_expr_loc_or_input_loc (declarator),
+ "non-class, non-variable partial specialization %qE "
+ "is not allowed", declarator);
  return decl;
ok:;
}
@@ -4958,8 +4962,9 @@ process_partial_specialization (tree decl)
 {
   if ((!packed_args && tpd.arg_uses_template_parms[i])
   || (packed_args && uses_template_parms (arg)))
-error ("template argument %qE involves template parameter(s)",
-   arg);
+   error_at (cp_expr_loc_or_input_loc (arg),
+ "template argument %qE involves template "
+ "parameter(s)", arg);
   else 
 {
   /* Look at the corresponding template parameter,
@@ -6258,13 +6263,14 @@ convert_nontype_argument_function (tree type, tree
 {
   if (complain & tf_error)
{
- error ("%qE is not a valid template argument for type %qT",
-expr, type);
+ location_t loc = cp_expr_loc_or_input_loc (expr);
+ error_at (loc, "%qE is not a valid template argument for type %qT",
+   expr, type);
  if (TYPE_PTR_P (type))
-   inform (input_location, "it must be the ad

Re: [C++ Patch] Another bunch of location fixes

2019-09-16 Thread Paolo Carlini

Hi,

On 15/09/19 16:22, Jason Merrill wrote:

On 9/12/19 9:41 AM, Paolo Carlini wrote:

+  if (!valid_array_size_p (dname
+   ? declarator->id_loc : input_location,


Use the id_loc local variable?


This diagnostic is inside the loop over declarator->declarator. 
Eventually, outside the loop, the id_loc local is updated to the final 
declarator->id_loc or input_location. Norrmally in the loop we use the 
current declarator->id_loc: what I tested seems more correct to me (we 
have to account for input_location too because valid_array_size_p, 
shared with the C front-end, wants a sound location)


Paolo.



[C++ Patch] Another bunch of location fixes

2019-09-12 Thread Paolo Carlini

Hi,

nothing special here, various bits I missed so far or in the past meant 
to test more thoroughly.


Thanks, Paolo.

//

/cp
2019-09-12  Paolo Carlini  

* decl.c (grokdeclarator): Use declspecs->locations and
declarator->id_loc in a few error messages.
* pt.c (finish_member_template_decl): Use DECL_SOURCE_LOCATION.
(push_template_decl_real): Likewise.

/testsuite
2019-09-12  Paolo Carlini  

* g++.dg/ext/int128-6.C: New.
* c-c++-common/pr68107.c: Test location(s).
* g++.dg/other/large-size-array.C: Likewise.
* g++.dg/template/dtor2.C: Likewise.
* g++.dg/template/error9.C: Likewise.
* g++.dg/tls/diag-2.C: Likewise.
* g++.dg/tls/diag-4.C: Likewise.
* g++.dg/tls/diag-5.C: Likewise.
* g++.old-deja/g++.pt/memtemp71.C: Likewise.
Index: cp/decl.c
===
--- cp/decl.c   (revision 275681)
+++ cp/decl.c   (working copy)
@@ -10948,14 +10948,15 @@ grokdeclarator (const cp_declarator *declarator,
 {
   if (! int_n_enabled_p[declspecs->int_n_idx])
{
- error ("%<__int%d%> is not supported by this target",
-int_n_data[declspecs->int_n_idx].bitsize);
+ error_at (declspecs->locations[ds_type_spec],
+   "%<__int%d%> is not supported by this target",
+   int_n_data[declspecs->int_n_idx].bitsize);
  explicit_intN = false;
}
   /* Don't pedwarn if the alternate "__intN__" form has been used instead
 of "__intN".  */
   else if (!int_n_alt && pedantic && ! in_system_header_at 
(input_location))
-   pedwarn (input_location, OPT_Wpedantic,
+   pedwarn (declspecs->locations[ds_type_spec], OPT_Wpedantic,
 "ISO C++ does not support %<__int%d%> for %qs",
 int_n_data[declspecs->int_n_idx].bitsize, name);
 }
@@ -11330,7 +11331,10 @@ grokdeclarator (const cp_declarator *declarator,
   && storage_class != sc_static)
  || typedef_p))
 {
-  error ("multiple storage classes in declaration of %qs", name);
+  location_t loc
+   = min_location (declspecs->locations[ds_thread],
+   declspecs->locations[ds_storage_class]);
+  error_at (loc, "multiple storage classes in declaration of %qs", name);
   thread_p = false;
 }
   if (decl_context != NORMAL
@@ -11489,7 +11493,9 @@ grokdeclarator (const cp_declarator *declarator,
  type = create_array_type_for_decl (dname, type,
 declarator->u.array.bounds,
 declarator->id_loc);
- if (!valid_array_size_p (input_location, type, dname))
+ if (!valid_array_size_p (dname
+  ? declarator->id_loc : input_location,
+  type, dname))
type = error_mark_node;
 
  if (declarator->std_attributes)
Index: cp/pt.c
===
--- cp/pt.c (revision 275681)
+++ cp/pt.c (working copy)
@@ -298,7 +298,8 @@ finish_member_template_decl (tree decl)
   return NULL_TREE;
 }
   else if (TREE_CODE (decl) == FIELD_DECL)
-error ("data member %qD cannot be a member template", decl);
+error_at (DECL_SOURCE_LOCATION (decl),
+ "data member %qD cannot be a member template", decl);
   else if (DECL_TEMPLATE_INFO (decl))
 {
   if (!DECL_TEMPLATE_SPECIALIZATION (decl))
@@ -310,7 +311,8 @@ finish_member_template_decl (tree decl)
return decl;
 }
   else
-error ("invalid member template declaration %qD", decl);
+error_at (DECL_SOURCE_LOCATION (decl),
+ "invalid member template declaration %qD", decl);
 
   return error_mark_node;
 }
@@ -5515,7 +5517,8 @@ push_template_decl_real (tree decl, bool is_friend
  /* [temp.mem]
 
 A destructor shall not be a member template.  */
- error ("destructor %qD declared as member template", decl);
+ error_at (DECL_SOURCE_LOCATION (decl),
+   "destructor %qD declared as member template", decl);
  return error_mark_node;
}
  if (IDENTIFIER_NEWDEL_OP_P (DECL_NAME (decl))
Index: testsuite/c-c++-common/pr68107.c
===
--- testsuite/c-c++-common/pr68107.c(revision 275681)
+++ testsuite/c-c++-common/pr68107.c(working copy)
@@ -3,34 +3,34 @@
 
 #define N ((__SIZE_MAX__ / sizeof (int)) / 2 + 1)
 
-typedef int (*T1)[N]; /* { dg-error "exceeds maximum object size" } */
+typedef int (*T1)[N]; /* { d

Re: C++ PATCH for c++/91740 - ICE with constexpr call and ?: in ARRAY_REF

2019-09-12 Thread Paolo Carlini

Hi again,

On 12/09/19 11:03, Paolo Carlini wrote:

Hi,

On 11/09/19 23:15, Marek Polacek wrote:

--- gcc/cp/pt.c
+++ gcc/cp/pt.c
@@ -26709,7 +26709,7 @@ build_non_dependent_expr (tree expr)
    if (TREE_CODE (expr) == COND_EXPR)
  return build3 (COND_EXPR,
 TREE_TYPE (expr),
-   TREE_OPERAND (expr, 0),
+   build_non_dependent_expr (TREE_OPERAND (expr, 0)),
 (TREE_OPERAND (expr, 1)
  ? build_non_dependent_expr (TREE_OPERAND (expr, 1))
  : build_non_dependent_expr (TREE_OPERAND (expr, 0))),


Looks like we would end up unnecessarily calling 
build_non_dependent_expr three times instead of two: probably is very 
cheap, probably the code is cleaner this way but I'm a little annoyed 
at this anyway, for the record ;)


Sorry, I misread the code: normally TREE_OPERAND (expr, 1) isn't 
NULL_TREE thus we are fine.


Paolo.



Re: C++ PATCH for c++/91740 - ICE with constexpr call and ?: in ARRAY_REF

2019-09-12 Thread Paolo Carlini

Hi,

On 11/09/19 23:15, Marek Polacek wrote:

--- gcc/cp/pt.c
+++ gcc/cp/pt.c
@@ -26709,7 +26709,7 @@ build_non_dependent_expr (tree expr)
if (TREE_CODE (expr) == COND_EXPR)
  return build3 (COND_EXPR,
   TREE_TYPE (expr),
-  TREE_OPERAND (expr, 0),
+  build_non_dependent_expr (TREE_OPERAND (expr, 0)),
   (TREE_OPERAND (expr, 1)
? build_non_dependent_expr (TREE_OPERAND (expr, 1))
: build_non_dependent_expr (TREE_OPERAND (expr, 0))),


Looks like we would end up unnecessarily calling 
build_non_dependent_expr three times instead of two: probably is very 
cheap, probably the code is cleaner this way but I'm a little annoyed at 
this anyway, for the record ;)


Cheers, Paolo.



[C++ Patch ping] Bunch of location improvements

2019-09-09 Thread Paolo Carlini

Hi,

On 02/09/19 16:28, Paolo Carlini wrote:

Hi,

all should be more or less straightforward. I also propose to use an 
additional range for that error message about constinit && constexpr 
mentioned to Marek a few days ago. Tested x86_64-linux.


I'm gently piniging this very early because the first time I forgot to 
add the C++ Patch tag.


    https://gcc.gnu.org/ml/gcc-patches/2019-09/msg00063.html

Cheers, Paolo.



Bunch of location improvements

2019-09-02 Thread Paolo Carlini

Hi,

all should be more or less straightforward. I also propose to use an 
additional range for that error message about constinit && constexpr 
mentioned to Marek a few days ago. Tested x86_64-linux.


Thanks, Paolo.

/

/cp
2019-09-02  Paolo Carlini  

* decl.c (has_designator_problem): Use cp_expr_loc_or_input_loc
in error_at.
(build_enumerator): Likewise.
(cp_finish_decl): Use DECL_SOURCE_LOCATION.
(grokdeclarator): Use id_loc in two error_at; change errror
message about constinit together constexpr to use two ranges.

/testsuite
2019-09-02  Paolo Carlini  

* g++.dg/cpp0x/enum29.C: Test location(s) too.
* g++.dg/cpp0x/lambda/lambda-ice10.C: Likewise.
* g++.dg/cpp2a/constinit3.C: Likewise.
* g++.dg/ext/desig4.C: Likewise.
* g++.dg/ext/label10.C: Likewise.
* g++.old-deja/g++.other/dtor3.C: Likewise.
Index: cp/decl.c
===
--- cp/decl.c   (revision 275318)
+++ cp/decl.c   (working copy)
@@ -6108,8 +6108,9 @@ has_designator_problem (reshape_iter *d, tsubst_fl
   if (d->cur->index)
 {
   if (complain & tf_error)
-   error ("C99 designator %qE outside aggregate initializer",
-  d->cur->index);
+   error_at (cp_expr_loc_or_input_loc (d->cur->index),
+ "C99 designator %qE outside aggregate initializer",
+ d->cur->index);
   else
return true;
 }
@@ -7282,8 +7283,9 @@ cp_finish_decl (tree decl, tree init, bool init_co
   if ((flags & LOOKUP_CONSTINIT)
  && !(dk == dk_thread || dk == dk_static))
{
- error ("% can only be applied to a variable with static "
-"or thread storage duration");
+ error_at (DECL_SOURCE_LOCATION (decl),
+   "% can only be applied to a variable with "
+   "static or thread storage duration");
  return;
}
 
@@ -10622,8 +10624,9 @@ grokdeclarator (const cp_declarator *declarator,
 && !uniquely_derived_from_p (ctype,
  current_class_type))
  {
-   error ("invalid use of qualified-name %<%T::%D%>",
-  qualifying_scope, decl);
+   error_at (id_declarator->id_loc,
+ "invalid use of qualified-name %<%T::%D%>",
+ qualifying_scope, decl);
return error_mark_node;
  }
  }
@@ -10810,8 +10813,9 @@ grokdeclarator (const cp_declarator *declarator,
  keywords shall appear in a decl-specifier-seq."  */
   if (constinit_p && constexpr_p)
 {
-  error_at (min_location (declspecs->locations[ds_constinit],
- declspecs->locations[ds_constexpr]),
+  gcc_rich_location richloc (declspecs->locations[ds_constinit]);
+  richloc.add_range (declspecs->locations[ds_constexpr]);
+  error_at (,
"can use at most one of the % and % "
"specifiers");
   return error_mark_node;
@@ -11815,7 +11819,8 @@ grokdeclarator (const cp_declarator *declarator,
&& inner_declarator->u.id.sfk == sfk_destructor
&& arg_types != void_list_node)
  {
-   error ("destructors may not have parameters");
+   error_at (declarator->id_loc,
+ "destructors may not have parameters");
arg_types = void_list_node;
parms = NULL_TREE;
  }
@@ -15155,8 +15160,9 @@ build_enumerator (tree name, tree value, tree enum
  if (! INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P
  (TREE_TYPE (value)))
{
- error ("enumerator value for %qD must have integral or "
-"unscoped enumeration type", name);
+ error_at (cp_expr_loc_or_input_loc (value),
+   "enumerator value for %qD must have integral or "
+   "unscoped enumeration type", name);
  value = NULL_TREE;
}
  else
Index: testsuite/g++.dg/cpp0x/enum29.C
===
--- testsuite/g++.dg/cpp0x/enum29.C (revision 275318)
+++ testsuite/g++.dg/cpp0x/enum29.C (working copy)
@@ -38,7 +38,7 @@ enum E0 { e0 = X0() };
 enum E1 { e1 = X1() };
 enum E2 { e2 = X2() };
 enum E3 { e3 = X3() };
-e

Re: C++ PATCH to implement C++20 P1143R2, constinit (PR c++/91360)

2019-08-27 Thread Paolo Carlini

Hi,

On 14/08/19 23:22, Marek Polacek wrote:

+  /* [dcl.spec]/2 "At most one of the constexpr, consteval, and constinit
+ keywords shall appear in a decl-specifier-seq."  */
+  if (constinit_p && constexpr_p)
+{
+  error_at (min_location (declspecs->locations[ds_constinit],
+ declspecs->locations[ds_constexpr]),
+   "can use at most one of the % and % "
+   "specifiers");


For this error we also have the option of using a gcc_rich_location, and 
add_range, etc, like for signed_p && unsigned_p, for example. Just 
saying, since we have the infrastructure ready...


Paolo.



[C++ Patch] Improve check_var_type locations

2019-08-27 Thread Paolo Carlini

Hi,

by adding a location_t parameter we can improve the locations of the 
error messages. At the moment the locations of the first and third 
message end up being input_location anyway, but we can imagine improving 
those later (this a much more general issue, the locations we use when 
unnamed entities are involved, see for example all the 'if (name)' in 
grokdeclarator and elsewhere: input_location is very rarely the best 
location).


Testex x86_64-linux.

Thanks, Paolo.

/

/cp
2019-08-27  Paolo Carlini  

* decl.c (check_var_type): Add location_t parameter and use it.
(grokdeclarator): Adjust call.
* pt.c (tsubst_decl): Likewise.
* cp-tree.h: Adjust declaration.

/testsuite
2019-08-27  Paolo Carlini  

* g++.dg/spellcheck-typenames.C: Adjust expected locations.
* g++.dg/cpp0x/pr84676.C: Check locations.
* g++.dg/other/pr88187.C: Likewise.
* g++.dg/parse/crash13.C: Likewise.
* g++.dg/parse/crash46.C: Likewise.
* g++.dg/parse/template28.C: Likewise.
* g++.dg/parse/typename4.C: Likewise.
Index: cp/cp-tree.h
===
--- cp/cp-tree.h(revision 274945)
+++ cp/cp-tree.h(working copy)
@@ -6469,7 +6469,7 @@ extern tree cxx_comdat_group  (tree);
 extern bool cp_missing_noreturn_ok_p   (tree);
 extern bool is_direct_enum_init(tree, tree);
 extern void initialize_artificial_var  (tree, vec *);
-extern tree check_var_type (tree, tree);
+extern tree check_var_type (tree, tree, location_t);
 extern tree reshape_init(tree, tree, tsubst_flags_t);
 extern tree next_initializable_field (tree);
 extern tree fndecl_declared_return_type(tree);
Index: cp/decl.c
===
--- cp/decl.c   (revision 274945)
+++ cp/decl.c   (working copy)
@@ -10278,19 +10278,20 @@ check_special_function_return_type (special_functi
error-recovery purposes.  */
 
 tree
-check_var_type (tree identifier, tree type)
+check_var_type (tree identifier, tree type, location_t loc)
 {
   if (VOID_TYPE_P (type))
 {
   if (!identifier)
-   error ("unnamed variable or field declared void");
+   error_at (loc, "unnamed variable or field declared void");
   else if (identifier_p (identifier))
{
  gcc_assert (!IDENTIFIER_ANY_OP_P (identifier));
- error ("variable or field %qE declared void", identifier);
+ error_at (loc, "variable or field %qE declared void",
+   identifier);
}
   else
-   error ("variable or field declared void");
+   error_at (loc, "variable or field declared void");
   type = error_mark_node;
 }
 
@@ -12407,7 +12408,7 @@ grokdeclarator (const cp_declarator *declarator,
  error message later.  */
   if (decl_context != PARM)
 {
-  type = check_var_type (unqualified_id, type);
+  type = check_var_type (unqualified_id, type, id_loc);
   if (type == error_mark_node)
 return error_mark_node;
 }
Index: cp/pt.c
===
--- cp/pt.c (revision 274945)
+++ cp/pt.c (working copy)
@@ -13894,7 +13895,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t com
/* Wait until cp_finish_decl to set this again, to handle
   circular dependency (template/instantiate6.C). */
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r) = 0;
-   type = check_var_type (DECL_NAME (r), type);
+   type = check_var_type (DECL_NAME (r), type,
+  DECL_SOURCE_LOCATION (r));
 
if (DECL_HAS_VALUE_EXPR_P (t))
  {
Index: testsuite/g++.dg/cpp0x/pr84676.C
===
--- testsuite/g++.dg/cpp0x/pr84676.C(revision 274945)
+++ testsuite/g++.dg/cpp0x/pr84676.C(working copy)
@@ -1,4 +1,5 @@
 // { dg-do compile { target c++11 } }
 
 int a;
-void b(__attribute__((c([](int *) {} (a == (0 = auto));  // { dg-error "" }
+void b(__attribute__((c([](int *) {} (a == (0 = auto));  // { dg-error 
"6:variable or field .b. declared void" }
+// { dg-error "expected" "" { target c++11 } .-1 }
Index: testsuite/g++.dg/other/pr88187.C
===
--- testsuite/g++.dg/other/pr88187.C(revision 274945)
+++ testsuite/g++.dg/other/pr88187.C(working copy)
@@ -2,6 +2,6 @@
 // { dg-do compile }
 
 template  struct A;
-void f (A ()); // { dg-error "variable or field 'f' declared void" "" { target 
c++14_down } }
+void f (A ()); // { dg-error "6:variable or field 'f' declared v

[C++ Patch] Fix finish_switch_cond location

2019-08-23 Thread Paolo Carlini

Hi,

a rather straightforward tweak. We could imagine much more heavily 
reworking the code to avoid saving the original condition 
(build_expr_type_conversion return NULL_TREE upon error), I'm not sure 
if it's worth it. Tested x86_64-linux.


Thanks, Paolo.



/cp
2019-08-23  Paolo Carlini  

* semantics.c (finish_switch_cond): Improve error message location.

/testsuite
2019-08-23  Paolo Carlini  

* g++.dg/conversion/simd4.C: Test all the locations.
Index: cp/semantics.c
===
--- cp/semantics.c  (revision 274845)
+++ cp/semantics.c  (working copy)
@@ -1185,10 +1185,12 @@ finish_switch_cond (tree cond, tree switch_stmt)
   if (!processing_template_decl)
 {
   /* Convert the condition to an integer or enumeration type.  */
+  tree orig_cond = cond;
   cond = build_expr_type_conversion (WANT_INT | WANT_ENUM, cond, true);
   if (cond == NULL_TREE)
{
- error ("switch quantity not an integer");
+ error_at (cp_expr_loc_or_input_loc (orig_cond),
+   "switch quantity not an integer");
  cond = error_mark_node;
}
   /* We want unlowered type here to handle enum bit-fields.  */
Index: testsuite/g++.dg/conversion/simd4.C
===
--- testsuite/g++.dg/conversion/simd4.C (revision 274845)
+++ testsuite/g++.dg/conversion/simd4.C (working copy)
@@ -20,15 +20,15 @@ foo ()
   v[b];// { dg-error "4:invalid types" }
   w[b];// { dg-error "4:invalid types" }
   new int[t];
-  new int[u];  // { dg-error "new-declarator must have integral" }
-  new int[v];  // { dg-error "new-declarator must have integral" }
-  new int[w];  // { dg-error "new-declarator must have integral" }
+  new int[u];  // { dg-error "11:expression in new-declarator must have 
integral" }
+  new int[v];  // { dg-error "11:expression in new-declarator must have 
integral" }
+  new int[w];  // { dg-error "11:expression in new-declarator must have 
integral" }
   switch (t) { default: break; }
-  switch (u) { default: break; }   // { dg-error "switch quantity not an 
integer" }
-  switch (v) { default: break; }   // { dg-error "switch quantity not an 
integer" }
-  switch (w) { default: break; }   // { dg-error "switch quantity not an 
integer" }
+  switch (u) { default: break; }   // { dg-error "11:switch quantity not 
an integer" }
+  switch (v) { default: break; }   // { dg-error "11:switch quantity not 
an integer" }
+  switch (w) { default: break; }   // { dg-error "11:switch quantity not 
an integer" }
   t = ~t;
-  u = ~u;  // { dg-error "wrong type argument to bit-complement" }
+  u = ~u;  // { dg-error "8:wrong type argument to bit-complement" }
   v = ~v;
-  w = ~w;  // { dg-error "wrong type argument to bit-complement" }
+  w = ~w;  // { dg-error "8:wrong type argument to bit-complement" }
 }


[C++ Patch] Improve grok_array_decl location

2019-08-13 Thread Paolo Carlini

Hi,

for this error message about the types involved in array subscripting I 
think we can exploit the available location argument and point to the 
open square bracket instead of simply using input_location. Tested 
x86_64-linux.


Thanks, Paolo Carlini.



/cp
2019-08-13  Paolo Carlini  

* decl2.c (grok_array_decl): Use the location of the open square
bracket in error message about invalid types.

/testsuite
2019-08-13  Paolo Carlini  

* g++.dg/conversion/simd4.C: Test locations.
Index: cp/decl2.c
===
--- cp/decl2.c  (revision 274330)
+++ cp/decl2.c  (working copy)
@@ -434,8 +434,8 @@ grok_array_decl (location_t loc, tree array_expr,
array_expr = p2, index_exp = i1;
   else
{
- error ("invalid types %<%T[%T]%> for array subscript",
-type, TREE_TYPE (index_exp));
+ error_at (loc, "invalid types %<%T[%T]%> for array subscript",
+   type, TREE_TYPE (index_exp));
  return error_mark_node;
}
 
Index: testsuite/g++.dg/conversion/simd4.C
===
--- testsuite/g++.dg/conversion/simd4.C (revision 274330)
+++ testsuite/g++.dg/conversion/simd4.C (working copy)
@@ -12,13 +12,13 @@ void
 foo ()
 {
   b[t];
-  b[u];// { dg-error "invalid types" }
-  b[v];// { dg-error "invalid types" }
-  b[w];// { dg-error "invalid types" }
+  b[u];// { dg-error "4:invalid types" }
+  b[v];// { dg-error "4:invalid types" }
+  b[w];// { dg-error "4:invalid types" }
   t[b];
-  u[b];// { dg-error "invalid types" }
-  v[b];// { dg-error "invalid types" }
-  w[b];// { dg-error "invalid types" }
+  u[b];// { dg-error "4:invalid types" }
+  v[b];// { dg-error "4:invalid types" }
+  w[b];// { dg-error "4:invalid types" }
   new int[t];
   new int[u];  // { dg-error "new-declarator must have integral" }
   new int[v];  // { dg-error "new-declarator must have integral" }


Re: [C++ Patch] Improve start_function and grokmethod locations

2019-08-09 Thread Paolo Carlini

Hi,

On 08/08/19 16:51, Jason Merrill wrote:

On 8/6/19 8:28 AM, Paolo Carlini wrote:
apparently this is now easy to do, likely because a while ago I made 
sure that we consistently have meaningful locations for TYPE_DECLs too.


(I went through grokdeclarator and confirmed that when the third 
argument is FUNCDEF or MEMFUNCDEF it cannot return NULL_TREE)


-typedef void foo () {}    // { dg-error "invalid function 
declaration" }
+typedef void foo () {}    // { dg-error "14:invalid function 
declaration" }

 struct S
 {
-  typedef int bar (void) { return 0; } // { dg-error "invalid member 
function declaration" }
+  typedef int bar (void) { return 0; }  // { dg-error "15:invalid 
member function declaration" }


Maybe we could give a more specific diagnostic in grokdeclarator; 
perhaps under



  if (typedef_p && decl_context != TYPENAME)


complain and return error_mark_node in FUNCDEF or MEMFUNCDEF context.


Yes, I briefly considered that myself, I only stopped because 
grokdeclarator seemed big enough already ;)


Anyway, I tested on x86_64-linux the below. Not 100% sure about the 
wording, but we have something similar a few lines below. Also, probably 
a single error_at both for functions and member functions would be good 
enough (but it would be a specificity regression).


Thanks, Paolo.



Index: cp/decl.c
===
--- cp/decl.c   (revision 274220)
+++ cp/decl.c   (working copy)
@@ -12165,6 +12165,17 @@ grokdeclarator (const cp_declarator *declarator,
   bool alias_p = decl_spec_seq_has_spec_p (declspecs, ds_alias);
   tree decl;
 
+  if (funcdef_flag)
+   {
+ if (decl_context == NORMAL)
+   error_at (id_loc,
+ "typedef may not be a function definition");
+ else
+   error_at (id_loc,
+ "typedef may not be a member function definition");
+ return error_mark_node;
+   }
+
   /* This declaration:
 
   typedef void f(int) const;
@@ -15775,13 +15786,6 @@ start_function (cp_decl_specifier_seq *declspecs,
   invoke_plugin_callbacks (PLUGIN_START_PARSE_FUNCTION, decl1);
   if (decl1 == error_mark_node)
 return false;
-  /* If the declarator is not suitable for a function definition,
- cause a syntax error.  */
-  if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
-{
-  error ("invalid function declaration");
-  return false;
-}
 
   if (DECL_MAIN_P (decl1))
 /* main must return int.  grokfndecl should have corrected it
@@ -16436,12 +16440,6 @@ grokmethod (cp_decl_specifier_seq *declspecs,
   if (fndecl == error_mark_node)
 return error_mark_node;
 
-  if (fndecl == NULL || TREE_CODE (fndecl) != FUNCTION_DECL)
-{
-  error ("invalid member function declaration");
-  return error_mark_node;
-}
-
   if (attrlist)
 cplus_decl_attributes (, attrlist, 0);
 
Index: testsuite/g++.dg/parse/typedef9.C
===
--- testsuite/g++.dg/parse/typedef9.C   (revision 274218)
+++ testsuite/g++.dg/parse/typedef9.C   (working copy)
@@ -1,8 +1,8 @@
 // PR c++/38794
 // { dg-do compile }
 
-typedef void foo () {} // { dg-error "invalid function declaration" }
+typedef void foo () {} // { dg-error "14:typedef may not be a function 
definition" }
 struct S
 {
-  typedef int bar (void) { return 0; } // { dg-error "invalid member function 
declaration" }
+  typedef int bar (void) { return 0; } // { dg-error "15:typedef may not be a 
member function definition" }
 };


[C++ Patch] More grokdeclarator locations fixes

2019-08-08 Thread Paolo Carlini

Hi,

these are all more or less straightforward, exploit the existing 
infrastructure. Nits: the first change also removes an 'a' in the 
wording because all the other error messages - a few - mentioning class 
or namespace don't have it; the fixes using EXPR_LOCATION also change 
%qD to %qE because we are dealing with BIT_NOT_EXPRs.


Thanks, Paolo.

///

/cp
2019-08-08  Paolo Carlini  

* decl.c (grokdeclarator): Use id_loc and EXPR_LOCATION in
a few error messages.

/testsuite
2019-08-08  Paolo Carlini  

* g++.dg/cpp0x/enum20.C: Test location(s) too.
* g++.dg/other/friend3.C: Likewise.
* g++.dg/parse/dtor5.C: Likewise.
* g++.dg/parse/friend7.C: Likewise.
* g++.dg/template/error22.C: Likewise.
* g++.old-deja/g++.brendan/err-msg5.C: Likewise.
Index: cp/decl.c
===
--- cp/decl.c   (revision 274195)
+++ cp/decl.c   (working copy)
@@ -10579,7 +10579,8 @@ grokdeclarator (const cp_declarator *declarator,
ctype = qualifying_scope;
if (!MAYBE_CLASS_TYPE_P (ctype))
  {
-   error ("%q#T is not a class or a namespace", ctype);
+   error_at (id_declarator->id_loc,
+ "%q#T is not a class or namespace", ctype);
ctype = NULL_TREE;
  }
else if (innermost_code != cdk_function
@@ -10601,13 +10602,15 @@ grokdeclarator (const cp_declarator *declarator,
{
  if (innermost_code != cdk_function)
{
- error ("declaration of %qD as non-function", decl);
+ error_at (EXPR_LOCATION (decl),
+   "declaration of %qE as non-function", decl);
  return error_mark_node;
}
  else if (!qualifying_scope
   && !(current_class_type && at_class_scope_p ()))
{
- error ("declaration of %qD as non-member", decl);
+ error_at (EXPR_LOCATION (decl),
+   "declaration of %qE as non-member", decl);
  return error_mark_node;
}
 
@@ -12510,7 +12513,7 @@ grokdeclarator (const cp_declarator *declarator,
else if (in_namespace && !friendp)
  {
/* Something like struct S { int N::j; };  */
-   error ("invalid use of %<::%>");
+   error_at (id_loc, "invalid use of %<::%>");
return error_mark_node;
  }
else if (FUNC_OR_METHOD_TYPE_P (type) && unqualified_id)
@@ -12565,15 +12568,15 @@ grokdeclarator (const cp_declarator *declarator,
if (!ctype)
  {
gcc_assert (friendp);
-   error ("expected qualified name in friend declaration "
-  "for destructor %qD", uqname);
+   error_at (id_loc, "expected qualified name in friend "
+ "declaration for destructor %qD", uqname);
return error_mark_node;
  }
 
if (!check_dtor_name (ctype, TREE_OPERAND (uqname, 0)))
  {
-   error ("declaration of %qD as member of %qT",
-  uqname, ctype);
+   error_at (id_loc, "declaration of %qD as member of %qT",
+ uqname, ctype);
return error_mark_node;
  }
 if (concept_p)
Index: testsuite/g++.dg/cpp0x/enum20.C
===
--- testsuite/g++.dg/cpp0x/enum20.C (revision 274195)
+++ testsuite/g++.dg/cpp0x/enum20.C (working copy)
@@ -2,4 +2,4 @@
 // { dg-do compile { target c++11 } }
 
 enum A { };
-void A::f() { }// { dg-error "not a class" }
+void A::f() { }// { dg-error "6:.enum A. is not a 
class" }
Index: testsuite/g++.dg/other/friend3.C
===
--- testsuite/g++.dg/other/friend3.C(revision 274195)
+++ testsuite/g++.dg/other/friend3.C(working copy)
@@ -4,10 +4,10 @@
 
 struct A
 {
-  friend ~A();  // { dg-error "qualified name" }
+  friend ~A();  // { dg-error "10:expected qualified name" }
 };
 
 struct B
 {
-  friend ~A();  // { dg-error "qualified name" }
+  friend ~A();  // { dg-error "10:expected qualified name" }
 };
Index: testsuite/g++.dg/parse/dtor5.C
==

Re: C++ PATCH for c++/91264 - detect modifying const objects in constexpr

2019-08-06 Thread Paolo Carlini

Hi,

On 31/07/19 21:26, Marek Polacek wrote:

+static void
+modifying_const_object_error (tree expr, tree obj)
+{
+  location_t loc = cp_expr_loc_or_loc (expr, input_location);


Nit: now we have cp_expr_loc_input_loc

Paolo.



[C++ Patch] Improve start_function and grokmethod locations

2019-08-06 Thread Paolo Carlini

Hi,

apparently this is now easy to do, likely because a while ago I made 
sure that we consistently have meaningful locations for TYPE_DECLs too.


(I went through grokdeclarator and confirmed that when the third 
argument is FUNCDEF or MEMFUNCDEF it cannot return NULL_TREE)


Tested x86_64-linux.

Thanks, Paolo.




/cp
2019-08-06  Paolo Carlini  

* decl.c (start_function): Use DECL_SOURCE_LOCATION.
(grokmethod): Likewise.

/testsuite
2019-08-06  Paolo Carlini  

* g++.dg/parse/typedef9.C: Test locations too.
Index: cp/decl.c
===
--- cp/decl.c   (revision 274141)
+++ cp/decl.c   (working copy)
@@ -15774,9 +15774,10 @@ start_function (cp_decl_specifier_seq *declspecs,
 return false;
   /* If the declarator is not suitable for a function definition,
  cause a syntax error.  */
-  if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
+  if (TREE_CODE (decl1) != FUNCTION_DECL)
 {
-  error ("invalid function declaration");
+  error_at (DECL_SOURCE_LOCATION (decl1),
+   "invalid function declaration");
   return false;
 }
 
@@ -16433,9 +16434,10 @@ grokmethod (cp_decl_specifier_seq *declspecs,
   if (fndecl == error_mark_node)
 return error_mark_node;
 
-  if (fndecl == NULL || TREE_CODE (fndecl) != FUNCTION_DECL)
+  if (TREE_CODE (fndecl) != FUNCTION_DECL)
 {
-  error ("invalid member function declaration");
+  error_at (DECL_SOURCE_LOCATION (fndecl),
+   "invalid member function declaration");
   return error_mark_node;
 }
 
Index: testsuite/g++.dg/parse/typedef9.C
===
--- testsuite/g++.dg/parse/typedef9.C   (revision 274140)
+++ testsuite/g++.dg/parse/typedef9.C   (working copy)
@@ -1,8 +1,8 @@
 // PR c++/38794
 // { dg-do compile }
 
-typedef void foo () {} // { dg-error "invalid function declaration" }
+typedef void foo () {} // { dg-error "14:invalid function declaration" }
 struct S
 {
-  typedef int bar (void) { return 0; } // { dg-error "invalid member function 
declaration" }
+  typedef int bar (void) { return 0; }  // { dg-error "15:invalid member 
function declaration" }
 };


[C++ Patch] One more cp_expr_loc_or_input_loc

2019-08-05 Thread Paolo Carlini

Hi,

just spotted an additional error which can benefit from 
cp_expr_loc_or_input_loc. Tested x86_64-linux.


Thanks, Paolo.



/cp
2019-08-05  Paolo Carlini  

* decl.c (check_array_designated_initializer): Use
cp_expr_loc_or_input_loc in one place.

/testsuite
2019-08-05  Paolo Carlini  

* g++.dg/cpp0x/desig1.C: Check location too.
Index: cp/decl.c
===
--- cp/decl.c   (revision 274124)
+++ cp/decl.c   (working copy)
@@ -5520,8 +5520,9 @@ check_array_designated_initializer (constructor_el
sorry ("non-trivial designated initializers not supported");
}
   else
-   error ("C99 designator %qE is not an integral constant-expression",
-  ce->index);
+   error_at (cp_expr_loc_or_input_loc (ce->index),
+ "C99 designator %qE is not an integral constant-expression",
+ ce->index);
 
   return false;
 }
Index: testsuite/g++.dg/cpp0x/desig1.C
===
--- testsuite/g++.dg/cpp0x/desig1.C (revision 274123)
+++ testsuite/g++.dg/cpp0x/desig1.C (working copy)
@@ -25,5 +25,5 @@ struct C
   constexpr operator SE() const { return SE::se0; }
 };
 
-int c[] = { [C()] = 0 }; // { dg-error "integral constant-expression" }
+int c[] = { [C()] = 0 }; // { dg-error "14:C99 designator .C\\\(\\\). is not 
an integral constant-expression" }
 // { dg-warning "does not allow C99 designated 
initializers" "" { target *-*-* } .-1 }


Re: [C++ Patch] Improve delete_sanity locations

2019-08-02 Thread Paolo Carlini

Hi,

On 31/07/19 21:39, David Malcolm wrote:

[snip]

I don't care for "cp_expr_loc_or_loc".

By "_or_here" do you mean "or input_location"?

Calling it "cp_expr_loc_or_input_location" would spell out what it
does, but would be rather long.


Thanks for your feedback. At this point I don't feel very strongly about 
the issue, and, well, hopefully it's just temporary material, but I 
tested the below which proposes the name cp_expr_loc_or_input_loc. Seems 
a good balance to me. What do you think?


Cheers, Paolo.

/

Index: call.c
===
--- call.c  (revision 274001)
+++ call.c  (working copy)
@@ -4184,7 +4184,7 @@ build_converted_constant_expr_internal (tree type,
   conversion *conv;
   void *p;
   tree t;
-  location_t loc = cp_expr_loc_or_loc (expr, input_location);
+  location_t loc = cp_expr_loc_or_input_loc (expr);
 
   if (error_operand_p (expr))
 return error_mark_node;
@@ -6961,7 +6961,7 @@ convert_like_real (conversion *convs, tree expr, t
   tree totype = convs->type;
   diagnostic_t diag_kind;
   int flags;
-  location_t loc = cp_expr_loc_or_loc (expr, input_location);
+  location_t loc = cp_expr_loc_or_input_loc (expr);
 
   if (convs->bad_p && !(complain & tf_error))
 return error_mark_node;
@@ -7481,7 +7481,7 @@ tree
 convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
 {
   tree arg_type;
-  location_t loc = cp_expr_loc_or_loc (arg, input_location);
+  location_t loc = cp_expr_loc_or_input_loc (arg);
 
   /* [expr.call]
 
@@ -7789,7 +7789,7 @@ convert_for_arg_passing (tree type, tree val, tsub
 "argument of function call might be a candidate "
 "for a format attribute");
}
-  maybe_warn_parm_abi (type, cp_expr_loc_or_loc (val, input_location));
+  maybe_warn_parm_abi (type, cp_expr_loc_or_input_loc (val));
 }
 
   if (complain & tf_warning)
@@ -8595,7 +8595,7 @@ build_over_call (struct z_candidate *cand, int fla
   tree type = TREE_TYPE (to);
   tree as_base = CLASSTYPE_AS_BASE (type);
   tree arg = argarray[1];
-  location_t loc = cp_expr_loc_or_loc (arg, input_location);
+  location_t loc = cp_expr_loc_or_input_loc (arg);
 
   if (is_really_empty_class (type, /*ignore_vptr*/true))
{
@@ -9143,7 +9143,7 @@ build_cxx_call (tree fn, int nargs, tree *argarray
   tree fndecl;
 
   /* Remember roughly where this call is.  */
-  location_t loc = cp_expr_loc_or_loc (fn, input_location);
+  location_t loc = cp_expr_loc_or_input_loc (fn);
   fn = build_call_a (fn, nargs, argarray);
   SET_EXPR_LOCATION (fn, loc);
 
@@ -11183,7 +11183,7 @@ perform_implicit_conversion_flags (tree type, tree
 {
   conversion *conv;
   void *p;
-  location_t loc = cp_expr_loc_or_loc (expr, input_location);
+  location_t loc = cp_expr_loc_or_input_loc (expr);
 
   if (TYPE_REF_P (type))
 expr = mark_lvalue_use (expr);
@@ -11532,7 +11532,7 @@ initialize_reference (tree type, tree expr,
 {
   conversion *conv;
   void *p;
-  location_t loc = cp_expr_loc_or_loc (expr, input_location);
+  location_t loc = cp_expr_loc_or_input_loc (expr);
 
   if (type == error_mark_node || error_operand_p (expr))
 return error_mark_node;
Index: constexpr.c
===
--- constexpr.c (revision 274001)
+++ constexpr.c (working copy)
@@ -1527,7 +1527,7 @@ cxx_eval_internal_function (const constexpr_ctx *c
 
 default:
   if (!ctx->quiet)
-   error_at (cp_expr_loc_or_loc (t, input_location),
+   error_at (cp_expr_loc_or_input_loc (t),
  "call to internal function %qE", t);
   *non_constant_p = true;
   return t;
@@ -1542,7 +1542,7 @@ cxx_eval_internal_function (const constexpr_ctx *c
 
   if (TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST)
 {
-  location_t loc = cp_expr_loc_or_loc (t, input_location);
+  location_t loc = cp_expr_loc_or_input_loc (t);
   tree type = TREE_TYPE (TREE_TYPE (t));
   tree result = fold_binary_loc (loc, opcode, type,
 fold_convert_loc (loc, type, arg0),
@@ -1584,7 +1584,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx
  bool lval,
  bool *non_constant_p, bool *overflow_p)
 {
-  location_t loc = cp_expr_loc_or_loc (t, input_location);
+  location_t loc = cp_expr_loc_or_input_loc (t);
   tree fun = get_function_named_in_call (t);
   constexpr_call new_call
 = { NULL, NULL, NULL, 0, ctx->manifestly_const_eval };
@@ -2580,7 +2580,7 @@ eval_and_check_array_index (const constexpr_ctx *c
tree t, bool allow_one_past,
bool *non_constant_p, bool *overflow_p)
 {
-  location_t loc = cp_expr_loc_or_loc (t, input_location);
+  location_t loc = cp_expr_loc_or_input_loc (t);
   tree ary = TREE_OPERAND (t, 0);
   t = TREE_OPERAND (t, 1);
   tree index = 

[C++ Patch] Do not warn about [[nodiscard]] applied to a constructor

2019-08-01 Thread Paolo Carlini

Hi,

in Cologne, during the presentation of P1771R0, Per Sommerlad pointed 
out that apparently GCC was already almost doing the right thing - it 
accepts [[nodiscard]] on a constructor and then a warning is emitted in 
the relevant potentially dangerous situations - but it does first emit a 
warning when it encounters the [[nodiscard]] itself. Avoiding the latter 
seems easy to me - the below passes testing. Something else?


Thanks, Paolo.

///

/cp
2019-08-01  Paolo Carlini  

* tree.c (handle_nodiscard_attribute): Do not warn about nodiscard
applied to a constructor.

/testsuite
2019-08-01  Paolo Carlini  

* g++.dg/cpp1z/nodiscard6.C: New.
Index: cp/tree.c
===
--- cp/tree.c   (revision 273951)
+++ cp/tree.c   (working copy)
@@ -4361,7 +4361,8 @@ handle_nodiscard_attribute (tree *node, tree name,
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
 {
-  if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (*node
+  if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (*node)))
+ && !DECL_CONSTRUCTOR_P (*node))
warning_at (DECL_SOURCE_LOCATION (*node),
OPT_Wattributes, "%qE attribute applied to %qD with void "
"return type", name, *node);
Index: testsuite/g++.dg/cpp1z/nodiscard6.C
===
--- testsuite/g++.dg/cpp1z/nodiscard6.C (nonexistent)
+++ testsuite/g++.dg/cpp1z/nodiscard6.C (working copy)
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+  [[nodiscard]] A();
+};
+
+void foo()
+{
+  A();  // { dg-warning "ignoring return value" }
+}


[C++ Patch] Improve delete_sanity locations

2019-07-24 Thread Paolo Carlini

Hi,

this takes care of the four locations, two warnings and two errors. I'm 
also adding the missing complain & tf_warning or tf_error guards, I 
don't have a SFINAE testcase failing but since the function takes a 
tsubst_flags_t argument I think it's the right thing to do. Tested 
x86_64-linux.


By the way, shall we add to cp-tree.h, at least temporarily, a:

inline location_t
cp_expr_loc_or_loc (const_tree t)
{
  return cp_expr_loc_or_loc (t, input_location);
}

overload? We could use it in a ton of places.

Thanks, Paolo.

//

/cp
2019-07-24  Paolo Carlini  

* decl2.c (delete_sanity): Improve diagnostic locations, use
cp_expr_loc_or_loc in four places.

/testsuite
2019-07-24  Paolo Carlini  

* g++.dg/diagnostic/delete1.C: New.
Index: cp/decl2.c
===
--- cp/decl2.c  (revision 273767)
+++ cp/decl2.c  (working copy)
@@ -487,15 +487,19 @@ delete_sanity (tree exp, tree size, bool doing_vec
 }
 
   /* An array can't have been allocated by new, so complain.  */
-  if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
-warning (0, "deleting array %q#E", exp);
+  if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
+  && (complain & tf_warning))
+warning_at (cp_expr_loc_or_loc (exp, input_location), 0,
+   "deleting array %q#E", exp);
 
   t = build_expr_type_conversion (WANT_POINTER, exp, true);
 
   if (t == NULL_TREE || t == error_mark_node)
 {
-  error ("type %q#T argument given to %, expected pointer",
-TREE_TYPE (exp));
+  if (complain & tf_error)
+   error_at (cp_expr_loc_or_loc (exp, input_location),
+ "type %q#T argument given to %, expected pointer",
+ TREE_TYPE (exp));
   return error_mark_node;
 }
 
@@ -506,8 +510,10 @@ delete_sanity (tree exp, tree size, bool doing_vec
   /* You can't delete functions.  */
   if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
 {
-  error ("cannot delete a function.  Only pointer-to-objects are "
-"valid arguments to %");
+  if (complain & tf_error)
+   error_at (cp_expr_loc_or_loc (exp, input_location),
+ "cannot delete a function.  Only pointer-to-objects are "
+ "valid arguments to %");
   return error_mark_node;
 }
 
@@ -514,7 +520,10 @@ delete_sanity (tree exp, tree size, bool doing_vec
   /* Deleting ptr to void is undefined behavior [expr.delete/3].  */
   if (VOID_TYPE_P (TREE_TYPE (type)))
 {
-  warning (OPT_Wdelete_incomplete, "deleting %qT is undefined", type);
+  if (complain & tf_warning)
+   warning_at (cp_expr_loc_or_loc (exp, input_location),
+   OPT_Wdelete_incomplete,
+   "deleting %qT is undefined", type);
   doing_vec = 0;
 }
 
Index: testsuite/g++.dg/diagnostic/delete1.C
===
--- testsuite/g++.dg/diagnostic/delete1.C   (nonexistent)
+++ testsuite/g++.dg/diagnostic/delete1.C   (working copy)
@@ -0,0 +1,14 @@
+void f ()
+{
+  int a[1];
+  delete (a);  // { dg-warning "11:deleting array" }
+
+  bool b;
+  delete (b);  // { dg-error "11:type .bool. argument" }
+
+  void g ();
+  delete (g);  // { dg-error "11:cannot delete a function" }
+
+  void* p;
+  delete (p);  // { dg-warning "11:deleting .void*." }
+}


Re: [C++ Patch] A few additional location improvements to grokdeclarator and check_tag_decl

2019-07-09 Thread Paolo Carlini

Hi,

On 08/07/19 23:44, Jason Merrill wrote:

On 6/23/19 7:58 AM, Paolo Carlini wrote:

+    error_at (smallest_type_location (get_type_quals (declspecs),
+  declspecs->locations),
How about adding a smallest_type_location overload that just takes 
declspecs?


Sure. The below has an additional location fixlet which I noticed over 
the last days, for "complex invalid for". Tested x86_64-linux, as usual.


Thanks, Paolo.



/cp
2019-07-09  Paolo Carlini  

* decl.c (get_type_quals,
smallest_type_location (const cp_decl_specifier_seq*)): New.
(check_tag_decl): Use smallest_type_location in error_at about
multiple types in one declaration.
(grokdeclarator): Use locations[ds_complex] in error_at about
complex invalid; use locations[ds_storage_class] in error_at
about static cdtor; use id_loc in error_at about flexible
array member in union; use get_type_quals.

/testsuite
2019-07-09  Paolo Carlini  

* g++.dg/diagnostic/complex-invalid-1.C: New.
* g++.dg/diagnostic/static-cdtor-1.C: Likewise.
* g++.dg/cpp1z/has-unique-obj-representations2.C: Test location
too.
* g++.dg/other/anon-union3.C: Adjust expected location.
* g++.dg/parse/error8.C: Likewise.
Index: cp/decl.c
===
--- cp/decl.c   (revision 273227)
+++ cp/decl.c   (working copy)
@@ -100,6 +100,7 @@ static tree build_cp_library_fn (tree, enum tree_c
 static void store_parm_decls (tree);
 static void initialize_local_var (tree, tree);
 static void expand_static_init (tree, tree);
+static location_t smallest_type_location (const cp_decl_specifier_seq*);
 
 /* The following symbols are subsumed in the cp_global_trees array, and
listed here individually for documentation purposes.
@@ -4802,6 +4803,24 @@ warn_misplaced_attr_for_class_type (location_t loc
class_type, class_key_or_enum_as_string (class_type));
 }
 
+/* Returns the cv-qualifiers that apply to the type specified
+   by the DECLSPECS.  */
+
+static int
+get_type_quals (const cp_decl_specifier_seq *declspecs)
+{
+  int type_quals = TYPE_UNQUALIFIED;
+
+  if (decl_spec_seq_has_spec_p (declspecs, ds_const))
+type_quals |= TYPE_QUAL_CONST;
+  if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
+type_quals |= TYPE_QUAL_VOLATILE;
+  if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
+type_quals |= TYPE_QUAL_RESTRICT;
+
+  return type_quals;
+}
+
 /* Make sure that a declaration with no declarator is well-formed, i.e.
just declares a tagged type or anonymous union.
 
@@ -4821,7 +4840,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
   bool error_p = false;
 
   if (declspecs->multiple_types_p)
-error ("multiple types in one declaration");
+error_at (smallest_type_location (declspecs),
+ "multiple types in one declaration");
   else if (declspecs->redefined_builtin_type)
 {
   if (!in_system_header_at (input_location))
@@ -10142,6 +10162,13 @@ smallest_type_location (int type_quals, const loca
   return min_location (loc, locations[ds_type_spec]);
 }
 
+static location_t
+smallest_type_location (const cp_decl_specifier_seq *declspecs)
+{
+  int type_quals = get_type_quals (declspecs);
+  return smallest_type_location (type_quals, declspecs->locations);
+}
+
 /* Check that it's OK to declare a function with the indicated TYPE
and TYPE_QUALS.  SFK indicates the kind of special function (if any)
that this function is.  OPTYPE is the type given in a conversion
@@ -10407,7 +10434,7 @@ grokdeclarator (const cp_declarator *declarator,
  a member function.  */
   cp_ref_qualifier rqual = REF_QUAL_NONE;
   /* cv-qualifiers that apply to the type specified by the DECLSPECS.  */
-  int type_quals = TYPE_UNQUALIFIED;
+  int type_quals = get_type_quals (declspecs);
   tree raises = NULL_TREE;
   int template_count = 0;
   tree returned_attrs = NULL_TREE;
@@ -10454,13 +10481,6 @@ grokdeclarator (const cp_declarator *declarator,
   if (concept_p)
 constexpr_p = true;
 
-  if (decl_spec_seq_has_spec_p (declspecs, ds_const))
-type_quals |= TYPE_QUAL_CONST;
-  if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
-type_quals |= TYPE_QUAL_VOLATILE;
-  if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
-type_quals |= TYPE_QUAL_RESTRICT;
-
   if (decl_context == FUNCDEF)
 funcdef_flag = true, decl_context = NORMAL;
   else if (decl_context == MEMFUNCDEF)
@@ -10999,7 +11019,8 @@ grokdeclarator (const cp_declarator *declarator,
   if (decl_spec_seq_has_spec_p (declspecs, ds_complex))
 {
   if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
-   error ("complex invalid for %qs", name);
+   error_at (declspecs->locations[ds_complex],
+ "complex invalid for %qs", name);
   /* If a modifier

[C++ Patch PING] Re: [C++ Patch] A few additional location improvements to grokdeclarator and check_tag_decl

2019-07-05 Thread Paolo Carlini

Hi,

On 23/06/19 13:58, Paolo Carlini wrote:

Hi,

here there are a couple of rather straightforward improvements in the 
second half of grokdeclarator plus a check_tag_decl change consistent 
with the other existing case of multiple_types_p diagnostic. Tested 
x86_64-linux.


Gently pinging this...

    https://gcc.gnu.org/ml/gcc-patches/2019-06/msg01391.html

Thanks, Paolo.



Re: [C++ Patch] PR 90909 ("[10 Regression] call devirtualized to pure virtual")

2019-07-04 Thread Paolo Carlini

Hi,

On 27/06/19 23:19, Jason Merrill wrote:
Ah, thanks.  Then perhaps we want to change the CLASSTYPE_FINAL in 
build_over_call to resolves_to_fixed_type_p (arg), to also handle the 
other reasons we might know the dynamic type of the argument, and 
remove the related code from build_new_method_call_1?


You could avoid needing to move the conditional lower by comparing 
DECL_CONTEXT (fn) and BINFO_TYPE (cand->conversion_path) rather than 
parmtype and TREE_TYPE (converted_arg).


Sorry for late replying, a few days off.

Anyway, great, it looks like we are reaching a nice synthesis. I must 
admit that until yesterday I hadn't noticed that Fabien dealt precisely 
with using declarations in order to fix c++/11750, thus the existing 
check in build_new_method_call_1 is exactly what we need. The below does 
that and passes testing, in it I didn't keep the checks of DECL_VINDEX 
(fn) && ! (flags & LOOKUP_NONVIRTUAL) which don't seem necessary, might 
avoid function calls, though. Let me know...


Thanks, Paolo.




Index: cp/call.c
===
--- cp/call.c   (revision 273076)
+++ cp/call.c   (working copy)
@@ -8241,10 +8241,17 @@ build_over_call (struct z_candidate *cand, int fla
return error_mark_node;
}
 
-  /* See if the function member or the whole class type is declared
-final and the call can be devirtualized.  */
+  /* Optimize away vtable lookup if we know that this
+function can't be overridden.  We need to check if
+the context and the type where we found fn are the same,
+actually FN might be defined in a different class
+type because of a using-declaration. In this case, we
+do not want to perform a non-virtual call.  Note that
+resolves_to_fixed_type_p checks CLASSTYPE_FINAL too.  */
   if (DECL_FINAL_P (fn)
- || CLASSTYPE_FINAL (TYPE_METHOD_BASETYPE (TREE_TYPE (fn
+ || (resolves_to_fixed_type_p (arg, 0)
+ && same_type_ignoring_top_level_qualifiers_p
+ (DECL_CONTEXT (fn), BINFO_TYPE (cand->conversion_path 
flags |= LOOKUP_NONVIRTUAL;
 
   /* [class.mfct.nonstatic]: If a nonstatic member function of a class
@@ -9845,17 +9852,6 @@ build_new_method_call_1 (tree instance, tree fns,
 
  if (call != error_mark_node)
{
- /* Optimize away vtable lookup if we know that this
-function can't be overridden.  We need to check if
-the context and the type where we found fn are the same,
-actually FN might be defined in a different class
-type because of a using-declaration. In this case, we
-do not want to perform a non-virtual call.  */
- if (DECL_VINDEX (fn) && ! (flags & LOOKUP_NONVIRTUAL)
- && same_type_ignoring_top_level_qualifiers_p
- (DECL_CONTEXT (fn), BINFO_TYPE (binfo))
- && resolves_to_fixed_type_p (instance, 0))
-   flags |= LOOKUP_NONVIRTUAL;
   if (explicit_targs)
 flags |= LOOKUP_EXPLICIT_TMPL_ARGS;
  /* Now we know what function is being called.  */
Index: testsuite/g++.dg/other/final4.C
===
--- testsuite/g++.dg/other/final4.C (nonexistent)
+++ testsuite/g++.dg/other/final4.C (working copy)
@@ -0,0 +1,16 @@
+// PR c++/67184
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdump-tree-original"  }
+
+struct B
+{
+  virtual void operator()();
+  virtual operator int();
+  virtual int operator++();
+};
+
+struct D final : B { };
+
+void foo(D& d) { d(); int t = d; ++d; }
+
+// { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "original" } }


Re: [C++ Patch] PR 90909 ("[10 Regression] call devirtualized to pure virtual")

2019-06-24 Thread Paolo Carlini

Hi,

On 23/06/19 19:45, Jason Merrill wrote:

On 6/23/19 7:53 AM, Paolo Carlini wrote:

... hi again ;)

The other day I was having a look at using declarations for this 
issue and noticed that only a few lines below the de-virtualization 
check we have to handle functions found by a using declaration, for 
various reasons. In particular, we know whether we found a function 
fn where has been declared or in a derived class. Thus the idea: for 
the purpose of making some progress, in particular all the cases in 
c++/67184 & co, would it make sense for the time being to simply add 
a check to the de-virtualization condition restricting it to 
non-using declarations? See the below (it also moves the conditional 
a few lines below only for clarity and consistency with the code 
handling using declarations, no functional impact) What do you think?


Hmm, perhaps we should check CLASSTYPE_FINAL in 
resolves_to_fixed_type_p rather than in build_over_call at all; then 
the code in build_new_method_call ought to set LOOKUP_NONVIRTUAL when 
appropriate.


I think your suggestion has to do with the initial implementation of 
this optimization, as contributed by my friend Roberto Agostino: we had 
the issue that it didn't handle at all user-defined operators and 
Vincenzo filed c++/53186. Thus, upon your suggestion, we moved the code 
to build_over_call, the current place:


    https://gcc.gnu.org/ml/gcc-patches/2012-05/msg00246.html

where it catched both member functions and operators. Now - before we 
get to the details - if I move the CLASSTYPE_FINAL check to 
resolves_to_fixed_type_p we exactly regress on c++/53186, that is 
other/final2.C, because resolves_to_fixed_type_p is *never* called. The 
pending final4.C, also involving operators (I constructed it exactly 
because I knew operators could be tricky) is also not fixed, but in that 
case at least resolves_to_fixed_type_p *is* called, only, too late (I 
think, I more details later, if you like).


All the other existing and pending testcases - involving member 
functions - appear to be Ok, even with a draft implementation of your 
suggestion (I slapped a 'if (CLASS_TYPE_P (t) && CLASSTYPE_FINAL (t)) 
return true;' in the middle of resolves_to_fixed_type_p.


Thanks, Paolo.




[C++ Patch] A few additional location improvements to grokdeclarator and check_tag_decl

2019-06-23 Thread Paolo Carlini

Hi,

here there are a couple of rather straightforward improvements in the 
second half of grokdeclarator plus a check_tag_decl change consistent 
with the other existing case of multiple_types_p diagnostic. Tested 
x86_64-linux.


Thanks, Paolo.

/

/cp
2019-06-23  Paolo Carlini  

* decl.c (get_type_quals): New.
(check_tag_decl): Use smallest_type_location and the latter in
error_at about multiple types in one declaration.
(grokdeclarator): Use locations[ds_storage_class] in error_at
about static cdtor; use id_loc in error_at about flexible
array member in union; use get_type_quals.

/testsuite
2019-06-23  Paolo Carlini  

* g++.dg/diagnostic/static-cdtor-1.C: New.
* g++.dg/cpp1z/has-unique-obj-representations2.C: Test location
too.
* g++.dg/other/anon-union3.C: Adjust expected location.
* g++.dg/parse/error8.C: Likewise.
Index: cp/decl.c
===
--- cp/decl.c   (revision 272584)
+++ cp/decl.c   (working copy)
@@ -100,6 +100,7 @@ static tree build_cp_library_fn (tree, enum tree_c
 static void store_parm_decls (tree);
 static void initialize_local_var (tree, tree);
 static void expand_static_init (tree, tree);
+static location_t smallest_type_location (int, const location_t*);
 
 /* The following symbols are subsumed in the cp_global_trees array, and
listed here individually for documentation purposes.
@@ -4802,6 +4803,24 @@ warn_misplaced_attr_for_class_type (location_t loc
class_type, class_key_or_enum_as_string (class_type));
 }
 
+/* Returns the cv-qualifiers that apply to the type specified
+   by the DECLSPECS.  */
+
+static int
+get_type_quals (const cp_decl_specifier_seq *declspecs)
+{
+  int type_quals = TYPE_UNQUALIFIED;
+
+  if (decl_spec_seq_has_spec_p (declspecs, ds_const))
+type_quals |= TYPE_QUAL_CONST;
+  if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
+type_quals |= TYPE_QUAL_VOLATILE;
+  if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
+type_quals |= TYPE_QUAL_RESTRICT;
+
+  return type_quals;
+}
+
 /* Make sure that a declaration with no declarator is well-formed, i.e.
just declares a tagged type or anonymous union.
 
@@ -4821,7 +4840,9 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
   bool error_p = false;
 
   if (declspecs->multiple_types_p)
-error ("multiple types in one declaration");
+error_at (smallest_type_location (get_type_quals (declspecs),
+ declspecs->locations),
+ "multiple types in one declaration");
   else if (declspecs->redefined_builtin_type)
 {
   if (!in_system_header_at (input_location))
@@ -10403,7 +10424,7 @@ grokdeclarator (const cp_declarator *declarator,
  a member function.  */
   cp_ref_qualifier rqual = REF_QUAL_NONE;
   /* cv-qualifiers that apply to the type specified by the DECLSPECS.  */
-  int type_quals = TYPE_UNQUALIFIED;
+  int type_quals = get_type_quals (declspecs);
   tree raises = NULL_TREE;
   int template_count = 0;
   tree returned_attrs = NULL_TREE;
@@ -10449,13 +10470,6 @@ grokdeclarator (const cp_declarator *declarator,
   if (concept_p)
 constexpr_p = true;
 
-  if (decl_spec_seq_has_spec_p (declspecs, ds_const))
-type_quals |= TYPE_QUAL_CONST;
-  if (decl_spec_seq_has_spec_p (declspecs, ds_volatile))
-type_quals |= TYPE_QUAL_VOLATILE;
-  if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
-type_quals |= TYPE_QUAL_RESTRICT;
-
   if (decl_context == FUNCDEF)
 funcdef_flag = true, decl_context = NORMAL;
   else if (decl_context == MEMFUNCDEF)
@@ -11571,9 +11585,12 @@ grokdeclarator (const cp_declarator *declarator,
   virtual.  A constructor may not be static.
   A constructor may not be declared with ref-qualifier. */
if (staticp == 2)
- error ((flags == DTOR_FLAG)
-? G_("destructor cannot be static member function")
-: G_("constructor cannot be static member function"));
+ error_at (declspecs->locations[ds_storage_class],
+   (flags == DTOR_FLAG)
+   ? G_("destructor cannot be static member "
+"function")
+   : G_("constructor cannot be static member "
+"function"));
if (memfn_quals)
  {
error ((flags == DTOR_FLAG)
@@ -12431,7 +12448,7 @@ grokdeclarator (const cp_declarator *declarator,
&& (TREE_CODE (ctype) == UNION_TYPE
|| TREE_CODE (ctype) == QUAL_UNION_TYPE))
  {
-   error ("flexible array member in union");
+   error_at (id_loc, &qu

Re: [C++ Patch] PR 90909 ("[10 Regression] call devirtualized to pure virtual")

2019-06-23 Thread Paolo Carlini

... hi again ;)

The other day I was having a look at using declarations for this issue 
and noticed that only a few lines below the de-virtualization check we 
have to handle functions found by a using declaration, for various 
reasons. In particular, we know whether we found a function fn where has 
been declared or in a derived class. Thus the idea: for the purpose of 
making some progress, in particular all the cases in c++/67184 & co, 
would it make sense for the time being to simply add a check to the 
de-virtualization condition restricting it to non-using declarations? 
See the below (it also moves the conditional a few lines below only for 
clarity and consistency with the code handling using declarations, no 
functional impact) What do you think?


Thanks, Paolo.

///

Index: cp/call.c
===
--- cp/call.c   (revision 272583)
+++ cp/call.c   (working copy)
@@ -8241,12 +8241,6 @@ build_over_call (struct z_candidate *cand, int fla
return error_mark_node;
}
 
-  /* See if the function member or the whole class type is declared
-final and the call can be devirtualized.  */
-  if (DECL_FINAL_P (fn)
- || CLASSTYPE_FINAL (TYPE_METHOD_BASETYPE (TREE_TYPE (fn
-   flags |= LOOKUP_NONVIRTUAL;
-
   /* [class.mfct.nonstatic]: If a nonstatic member function of a class
 X is called for an object that is not of type X, or of a type
 derived from X, the behavior is undefined.
@@ -8271,6 +8265,17 @@ build_over_call (struct z_candidate *cand, int fla
  else
return error_mark_node;
}
+
+  /* See if the function member or the whole class type is declared
+final and the call can be devirtualized.  */
+  if (DECL_FINAL_P (fn)
+ || (CLASSTYPE_FINAL (TREE_TYPE (argtype))
+ /* Give up for now if fn was found by a using declaration,
+the complex case, see c++/90909.  */
+ && (TREE_TYPE (TREE_TYPE (converted_arg))
+ == TREE_TYPE (parmtype
+   flags |= LOOKUP_NONVIRTUAL;
+
   /* If fn was found by a using declaration, the conversion path
 will be to the derived class, not the base declaring fn. We
 must convert from derived to base.  */
Index: testsuite/g++.dg/other/final3.C
===
--- testsuite/g++.dg/other/final3.C (nonexistent)
+++ testsuite/g++.dg/other/final3.C (working copy)
@@ -0,0 +1,28 @@
+// PR c++/67184
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdump-tree-original"  }
+
+struct V {
+ virtual void foo(); 
+};
+
+struct wV final : V {
+};
+
+struct oV final : V {
+  void foo();
+};
+
+void call(wV& x)
+{
+  x.foo();
+  x.V::foo();
+}
+
+void call(oV& x)
+{
+  x.foo();
+  x.V::foo();
+}
+
+// { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "original" } }
Index: testsuite/g++.dg/other/final4.C
===
--- testsuite/g++.dg/other/final4.C (nonexistent)
+++ testsuite/g++.dg/other/final4.C (working copy)
@@ -0,0 +1,16 @@
+// PR c++/67184
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdump-tree-original"  }
+
+struct B
+{
+  virtual void operator()();
+  virtual operator int();
+  virtual int operator++();
+};
+
+struct D final : B { };
+
+void foo(D& d) { d(); int t = d; ++d; }
+
+// { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "original" } }
Index: testsuite/g++.dg/other/final5.C
===
--- testsuite/g++.dg/other/final5.C (nonexistent)
+++ testsuite/g++.dg/other/final5.C (working copy)
@@ -0,0 +1,19 @@
+// PR c++/69445
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdump-tree-original"  }
+
+struct Base {
+  virtual void foo() const = 0;
+  virtual void bar() const {}
+};
+
+struct C final : Base {
+  void foo() const { }
+};
+
+void func(const C & c) {
+  c.bar();
+  c.foo();
+}
+
+// { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "original" } }


Re: [C++ Patch] PR 90909 ("[10 Regression] call devirtualized to pure virtual")

2019-06-21 Thread Paolo Carlini
... so, now that I see the issue more clearly, I'm adding to the 
testsuite the below too.


Thanks, Paolo.




Index: final7.C
===
--- final7.C(nonexistent)
+++ final7.C(working copy)
@@ -0,0 +1,11 @@
+// PR c++/90909
+// { dg-do run { target c++11 } }
+
+#include 
+
+struct S1 { virtual bool f() { return false; } };
+struct S2: S1 { virtual bool f() { return true; } };
+struct S3: S2 { using S1::f; };
+struct S4 final: S3 { void g(); };
+void S4::g() { assert (f() == true); }
+int main() { S4().g(); }


Re: [C++ Patch] PR 90909 ("[10 Regression] call devirtualized to pure virtual")

2019-06-21 Thread Paolo Carlini

and...
By the way, if S1:.f is not pure virtual, just a virtual declaration - 
all the rest being the same - the code doesn't link: undefined 
references to vtable and typeinfo for S1. The same happens with 
current clang and icc. I don't know if this detail helps us in the 
short term


... the same happens without final too.

Paolo.



Re: [C++ Patch] PR 90909 ("[10 Regression] call devirtualized to pure virtual")

2019-06-21 Thread Paolo Carlini

Hi,

On 21/06/19 21:27, Paolo Carlini wrote:

Hi,

On 21/06/19 20:50, Jason Merrill wrote:

On 6/20/19 12:24 AM, Paolo Carlini wrote:

Hi,

this bug notices that the more aggressive de-virtualization check 
that we have now in place (fixed c++/67184) doesn't work correctly 
for the below reproducer, which involves a pure virtual: we 
de-virtualize and the build fails at link-time. To cure this I 
believe we simply want an additional DECL_PURE_VIRTUAL_P in the 
condition.


I don't see why this bug would be specific to pure virtual functions, 
so the fix also should not be.  If S1::f is not pure virtual, I'd 
expect that we wrongly devirtualize to it in the same way.


By the way, if S1:.f is not pure virtual, just a virtual declaration - 
all the rest being the same - the code doesn't link: undefined 
references to vtable and typeinfo for S1. The same happens with current 
clang and icc. I don't know if this detail helps us in the short term


Paolo.



Re: [C++ Patch] PR 90909 ("[10 Regression] call devirtualized to pure virtual")

2019-06-21 Thread Paolo Carlini

Hi,

On 21/06/19 20:50, Jason Merrill wrote:

On 6/20/19 12:24 AM, Paolo Carlini wrote:

Hi,

this bug notices that the more aggressive de-virtualization check 
that we have now in place (fixed c++/67184) doesn't work correctly 
for the below reproducer, which involves a pure virtual: we 
de-virtualize and the build fails at link-time. To cure this I 
believe we simply want an additional DECL_PURE_VIRTUAL_P in the 
condition.


I don't see why this bug would be specific to pure virtual functions, 
so the fix also should not be.  If S1::f is not pure virtual, I'd 
expect that we wrongly devirtualize to it in the same way.


Devirtualizing the call in S4 is a good optimization, we're just 
selecting the wrong function.


It seems like the issue here is that the using-declaration hides the 
final overrider from lookup.  So we need to work harder to find the 
actual final overrider, perhaps by looking into the argtype vtable.


I see, thanks for the suggestion.

The issue seems rather tricky, then. For the time being I'm going to 
revert the recent improvements. Probably I'm also going to unassign 
myself, because I don't want to prevent somebody else more knowledgeable 
than me in the area from contributing a good solution.


Thanks, Paolo.



[C++ Patch] PR 90909 ("[10 Regression] call devirtualized to pure virtual")

2019-06-19 Thread Paolo Carlini

Hi,

this bug notices that the more aggressive de-virtualization check that 
we have now in place (fixed c++/67184) doesn't work correctly for the 
below reproducer, which involves a pure virtual: we de-virtualize and 
the build fails at link-time. To cure this I believe we simply want an 
additional DECL_PURE_VIRTUAL_P in the condition. I also checked that the 
other compilers I have at hand appear to do the same, that is, they 
compile the reproducer both as-is and without the final specifier to the 
same assembly.


Note, in principle we have the option of not doing the additional 
DECL_PURE_VIRTUAL_P check when the final overrider comes from the class 
itself, not from a base, that is in the cases that we were already 
de-virtualizing pre-67184. That is, for something like:


struct A final
{
  virtual void foo () = 0;
};

void fun(A* a, B* b)
{
  a->foo();
}

devirtualize anyway (which then doesn't link). We could add back an '|| 
CLASSTYPE_FINAL (TYPE_METHOD_BASETYPE (TREE_TYPE (fn)))' for that. ICC 
appears to behave this way.


Tested x86_64-linux.

Thanks, Paolo.





/cp
2019-06-20  Paolo Carlini  

PR c++/90909
* call.c (build_over_call): Do not try to devirtualize when
then function is pure virtual.

/testsuite
2019-06-20  Paolo Carlini  

PR c++/90909
* g++.dg/other/final6.C: New.
Index: testsuite/g++.dg/other/final6.C
===
--- testsuite/g++.dg/other/final6.C (nonexistent)
+++ testsuite/g++.dg/other/final6.C (working copy)
@@ -0,0 +1,9 @@
+// PR c++/90909
+// { dg-do link { target c++11 } }
+
+struct S1 { virtual void f() = 0; };
+struct S2: S1 { virtual void f() {} };
+struct S3: S2 { using S1::f; };
+struct S4 final: S3 { void g(); };
+void S4::g() { f(); }
+int main() { S4().g(); }
Index: cp/call.c
===
--- cp/call.c   (revision 272410)
+++ cp/call.c   (working copy)
@@ -8244,7 +8244,8 @@ build_over_call (struct z_candidate *cand, int fla
   /* See if the function member or the whole class type is declared
 final and the call can be devirtualized.  */
   if (DECL_FINAL_P (fn)
- || CLASSTYPE_FINAL (TREE_TYPE (argtype)))
+ || (CLASSTYPE_FINAL (TREE_TYPE (argtype))
+ && !DECL_PURE_VIRTUAL_P (fn)))
flags |= LOOKUP_NONVIRTUAL;
 
   /* [class.mfct.nonstatic]: If a nonstatic member function of a class


[C++ Patch] More grokdeclarator locations

2019-06-13 Thread Paolo Carlini

Hi,

should all be rather straightforward but I spent quite a bit of time on 
the testsuite changes... Tested x86_64-linux, as usual.


Thanks, Paolo.

PS: at some point we should start talking about all the error, error_at, 
etc, which are *never* exercised by our testsuite. I'm coming to the 
conclusion that some should really go. Any general procedural suggestions?


///


/cp
2019-06-14  Paolo Carlini  

* decl.c (grokdeclarator): Use id_loc, typespec_loc, and
locations[ds_storage_class] in a few additional places.

/testsuite
2019-06-14  Paolo Carlini  

* g++.dg/diagnostic/auto-storage-1.C: New.
* g++.dg/diagnostic/no-type-1.C: Likewise.
* g++.dg/diagnostic/no-type-2.C: Likewise.
* g++.dg/diagnostic/top-level-auto-1.C: Likewise.
* g++.dg/cpp0x/auto9.C: Test some locations too.
* g++.dg/cpp1z/register1.C: Likewise.
* g++.dg/cpp1z/register2.C: Likewise.
* g++.dg/cpp1z/register3.C: Likewise.
* g++.dg/other/error34.C: Likewise.
Index: cp/decl.c
===
--- cp/decl.c   (revision 272259)
+++ cp/decl.c   (working copy)
@@ -10797,13 +10797,14 @@ grokdeclarator (const cp_declarator *declarator,
   else if (in_system_header_at (input_location) || flag_ms_extensions)
/* Allow it, sigh.  */;
   else if (! is_main)
-   permerror (input_location, "ISO C++ forbids declaration of %qs with no 
type", name);
+   permerror (id_loc, "ISO C++ forbids declaration of %qs with no type",
+  name);
   else if (pedantic)
-   pedwarn (input_location, OPT_Wpedantic,
+   pedwarn (id_loc, OPT_Wpedantic,
 "ISO C++ forbids declaration of %qs with no type", name);
   else
-   warning (OPT_Wreturn_type,
-"ISO C++ forbids declaration of %qs with no type", name);
+   warning_at (id_loc, OPT_Wreturn_type,
+   "ISO C++ forbids declaration of %qs with no type", name);
 
   if (type_was_error_mark_node && template_parm_flag)
/* FIXME we should be able to propagate the error_mark_node as is
@@ -11232,7 +11233,8 @@ grokdeclarator (const cp_declarator *declarator,
   else if (toplevel_bindings_p ())
 {
   if (storage_class == sc_auto)
-   error ("top-level declaration of %qs specifies %", name);
+   error_at (declspecs->locations[ds_storage_class],
+ "top-level declaration of %qs specifies %", name);
 }
   else if (thread_p
   && storage_class != sc_extern
@@ -12323,9 +12325,10 @@ grokdeclarator (const cp_declarator *declarator,
  && !(cxx_dialect >= cxx17 && template_parm_flag))
{
  if (cxx_dialect >= cxx14)
-   error ("% parameter not permitted in this context");
+   error_at (typespec_loc,
+ "% parameter not permitted in this context");
  else
-   error ("parameter declared %");
+   error_at (typespec_loc, "parameter declared %");
  type = error_mark_node;
}
 
@@ -12746,9 +12749,12 @@ grokdeclarator (const cp_declarator *declarator,
// FIXME:gcc_assert (original_name == dname);
 
if (storage_class == sc_auto)
- error ("storage class % invalid for function %qs", name);
+ error_at (declspecs->locations[ds_storage_class],
+   "storage class % invalid for function %qs", name);
else if (storage_class == sc_register)
- error ("storage class % invalid for function %qs", name);
+ error_at (declspecs->locations[ds_storage_class],
+   "storage class % invalid for function %qs",
+   name);
else if (thread_p)
  {
if (declspecs->gnu_thread_keyword_p)
Index: testsuite/g++.dg/cpp0x/auto9.C
===
--- testsuite/g++.dg/cpp0x/auto9.C  (revision 272259)
+++ testsuite/g++.dg/cpp0x/auto9.C  (working copy)
@@ -78,10 +78,10 @@ enum struct D : auto * { FF = 0 };  // { dg-error
 void
 bar ()
 {
-  try { } catch (auto i) { }   // { dg-error "parameter" }
-  try { } catch (auto) { } // { dg-error "parameter" }
-  try { } catch (auto *i) { }  // { dg-error "parameter" }
-  try { } catch (auto *) { }   // { dg-error "parameter" }
+  try { } catch (auto i) { }   // { dg-error "18:parameter" }
+  try { } catch (auto) { } // { dg-error "18:parameter" }
+  try { } catch (auto *i) { }  // { dg-error "18:parameter" }
+  try { } catch (auto *) 

Re: [C++ Patch] Further grokdeclarator locations work

2019-06-12 Thread Paolo Carlini

Hi,

On 12/06/19 22:24, Jason Merrill wrote:

On 6/6/19 9:00 AM, Paolo Carlini wrote:

Hi,

only minor functional changes here - more precise locations for two 
error messages  - but I think it's a step in the right direction: it 
moves the declaration of id_loc way up, near typespec_loc and as such 
id_loc is immediately used. Then its value is updated upon the loop 
over declarator in the middle of the function and used again in the 
final part of the function. That also "frees" the simple name loc for 
other local uses, allows to simplify those checks changed rather 
recently over (name && declarator). and (unqualified_id && 
declarator). Tested x86_64-linux.


Mostly OK, except:


   if (declspecs->multiple_types_p)
 {
-  error ("two or more data types in declaration of %qs", name);
+  error_at (id_loc, "two or more data types in declaration of 
%qs", name);

   return error_mark_node;
 }


declspecs->locations[ds_type_spec]?


   if (declspecs->conflicting_specifiers_p)
 {
-  error ("conflicting specifiers in declaration of %qs", name);
+  error_at (id_loc, "conflicting specifiers in declaration of 
%qs", name);

   return error_mark_node;
 }


ds_storage_class/ds_typedef?


Ok.

Ideally, it would be nice to have available locations for the two 
leftmost data types and, for the second error, the locations of 
conflicting storage classes (eg, static and register). Other compilers 
then point to the second one, where the issue shows up. I think we 
already briefly discussed that kind of logic in the past, but in those 
cases we had available all the locations we needed and we ended up using 
gcc_rich_location and add_range, etc..


Anyway, we can certainly use typespec_loc and the minimum of 
ds_storage_class and ds_typedef, respectively, like in the below, which 
passes testing.


Thanks! Paolo.

///


Index: cp/decl.c
===
--- cp/decl.c   (revision 272213)
+++ cp/decl.c   (working copy)
@@ -10456,6 +10456,8 @@ grokdeclarator (const cp_declarator *declarator,
   if (typespec_loc == UNKNOWN_LOCATION)
 typespec_loc = input_location;
 
+  location_t id_loc = declarator ? declarator->id_loc : input_location;
+
   /* Look inside a declarator for the name being declared
  and get it as a string, for an error message.  */
   for (id_declarator = declarator;
@@ -10620,8 +10622,7 @@ grokdeclarator (const cp_declarator *declarator,
  D1 ( parameter-declaration-clause) ...  */
   if (funcdef_flag && innermost_code != cdk_function)
 {
-  error_at (declarator->id_loc,
-   "function definition does not declare parameters");
+  error_at (id_loc, "function definition does not declare parameters");
   return error_mark_node;
 }
 
@@ -10629,8 +10630,7 @@ grokdeclarator (const cp_declarator *declarator,
   && innermost_code != cdk_function
   && ! (ctype && !declspecs->any_specifiers_p))
 {
-  error_at (declarator->id_loc,
-   "declaration of %qD as non-function", dname);
+  error_at (id_loc, "declaration of %qD as non-function", dname);
   return error_mark_node;
 }
 
@@ -10639,8 +10639,7 @@ grokdeclarator (const cp_declarator *declarator,
   if (UDLIT_OPER_P (dname)
  && innermost_code != cdk_function)
{
- error_at (declarator->id_loc,
-   "declaration of %qD as non-function", dname);
+ error_at (id_loc, "declaration of %qD as non-function", dname);
  return error_mark_node;
}
 
@@ -10648,14 +10647,12 @@ grokdeclarator (const cp_declarator *declarator,
{
  if (typedef_p)
{
- error_at (declarator->id_loc,
-   "declaration of %qD as %", dname);
+ error_at (id_loc, "declaration of %qD as %", dname);
  return error_mark_node;
}
  else if (decl_context == PARM || decl_context == CATCHPARM)
{
- error_at (declarator->id_loc,
-   "declaration of %qD as parameter", dname);
+ error_at (id_loc, "declaration of %qD as parameter", dname);
  return error_mark_node;
}
}
@@ -10705,13 +10702,16 @@ grokdeclarator (const cp_declarator *declarator,
  issue an error message.  */
   if (declspecs->multiple_types_p)
 {
-  error ("two or more data types in declaration of %qs", name);
+  error_at (typespec_loc,
+   "two or more data types in declaration of %qs", name);
   return error_mark_node;
 }
 
   if (declspecs->conflicting_specifiers_p)
 {
-  error ("conflicting specifiers 

[C++ Patch] More grokdeclarator locations fixes

2019-06-10 Thread Paolo Carlini

Hi,

this one requires my last patch, uses id_loc in a few additional places 
in the last part of the function.


Most of the changes should be straightforward, I only want to mention 
the "typedef name may not be a nested-name-specifier" change, where, not 
using input_location means that for a test like 
g++.old-deja/g++.jason/crash10.C:


struct A {
  enum foo { bar };
};

typedef A::foo A::foo;

the location is under the 'A' of the second 'A::foo'. The EDG front-end 
does exactly the same; clang points to the 'f' but then has the wavy 
thing reaching back to 'A' (a while ago I already mentioned that we 
don't have that option). Tested x86_64-linux.


Thanks, Paolo.

/

/cp
2019-06-10  Paolo Carlini  

* decl.c (grokdeclarator): Use id_loc in five additional places
in the last part of the function.

/testsuite
2019-06-10  Paolo Carlini  

* g++.dg/diagnostic/variably-modified-type-1.C: New.
* g++.dg/cpp0x/alias-decl-1.C: Test the location too.
* g++.dg/other/pr84792-1.C: Likewise.
* g++.dg/other/pr84792-2.C: Likewise.
* g++.dg/parse/error24.C: Likewise.
* g++.dg/parse/error32.C: Likewise.
* g++.dg/parse/error33.C: Likewise.
* g++.dg/parse/saved1.C: Likewise.
* g++.dg/template/operator6.C: Likewise.
* g++.dg/template/pr61745.C: Likewise.
* g++.dg/template/typedef41.C: Likewise.
* g++.old-deja/g++.jason/crash10.C: Likewise.
Index: cp/decl.c
===
--- cp/decl.c   (revision 272105)
+++ cp/decl.c   (working copy)
@@ -12000,9 +12000,11 @@ grokdeclarator (const cp_declarator *declarator,
   && variably_modified_type_p (type, NULL_TREE))
 {
   if (decl_context == FIELD)
-   error ("data member may not have variably modified type %qT", type);
+   error_at (id_loc,
+ "data member may not have variably modified type %qT", type);
   else
-   error ("parameter may not have variably modified type %qT", type);
+   error_at (id_loc,
+ "parameter may not have variably modified type %qT", type);
   type = error_mark_node;
 }
 
@@ -12106,7 +12108,7 @@ grokdeclarator (const cp_declarator *declarator,
 
   if (id_declarator && declarator->u.id.qualifying_scope)
{
- error ("typedef name may not be a nested-name-specifier");
+ error_at (id_loc, "typedef name may not be a nested-name-specifier");
  type = error_mark_node;
}
 
@@ -12130,7 +12132,7 @@ grokdeclarator (const cp_declarator *declarator,
}
   else if (current_class_type
   && constructor_name_p (unqualified_id, current_class_type))
-   permerror (input_location, "ISO C++ forbids nested type %qD with same 
name "
+   permerror (id_loc, "ISO C++ forbids nested type %qD with same name "
   "as enclosing class",
   unqualified_id);
 
@@ -12288,7 +12290,7 @@ grokdeclarator (const cp_declarator *declarator,
   /* Only functions may be declared using an operator-function-id.  */
   if (dname && IDENTIFIER_ANY_OP_P (dname))
{
- error ("declaration of %qD as non-function", dname);
+ error_at (id_loc, "declaration of %qD as non-function", dname);
  return error_mark_node;
}
 
Index: testsuite/g++.dg/cpp0x/alias-decl-1.C
===
--- testsuite/g++.dg/cpp0x/alias-decl-1.C   (revision 272105)
+++ testsuite/g++.dg/cpp0x/alias-decl-1.C   (working copy)
@@ -11,5 +11,6 @@ template  using Ptr = U*;
 template struct Ptr {}; // { dg-error "specialization" }
 
 struct A {
-using A = int;//{ dg-error "nested|has|same name as|class|in 
which|declared" }
+using A = int;  // { dg-error "11:ISO C\\+\\+ forbids nested type .A." }
+// { dg-error "same name as" "" { target c++11 } .-1 }  
 };
Index: testsuite/g++.dg/diagnostic/variably-modified-type-1.C
===
--- testsuite/g++.dg/diagnostic/variably-modified-type-1.C  (nonexistent)
+++ testsuite/g++.dg/diagnostic/variably-modified-type-1.C  (working copy)
@@ -0,0 +1,12 @@
+// { dg-options "" }
+
+void foo ()
+{
+  int n;
+  typedef int X[n];
+  struct Z
+  {
+X x __attribute__((unused)); // { dg-error "7:data member may not have 
variably modified type" }
+void bar (X x __attribute__((unused))); // { dg-error "17:parameter may 
not have variably modified type" }
+  };
+}
Index: testsuite/g++.dg/other/pr84792-1.C
===
--- testsuite/g++.dg/other/pr84792-1.C  (revision 272105)
+++ test

Re: [C++ PATCH] PR c++/90449 - add -Winaccessible-base option.

2019-06-07 Thread Paolo Carlini

Hi,

On 07/06/19 22:31, Marek Polacek wrote:

On Fri, Jun 07, 2019 at 10:20:02PM +0200, Paolo Carlini wrote:

Hi,

On 07/06/19 22:10, Matthew Beliveau wrote:

@@ -6025,6 +6025,10 @@ warn_about_ambiguous_bases (tree t)

Just a nit, but it seems weird to me that the function implementing
warn_inaccessible_base is named warn_about_ambiguous_bases.

Maybe, but we want to keep the warning's name in sync with clang, and
renaming the function seems like unnecessary noise.  I could go either
way.


It's definitely a minor issue. But, given that we have a rationale for 
inaccessible_base - I didn't know that - I vote for renaming the 
function. A maybe_* name would be appropriate in that case, because the 
function doesn't always warn.


Paolo.



Re: [C++ PATCH] PR c++/90449 - add -Winaccessible-base option.

2019-06-07 Thread Paolo Carlini

Hi,

On 07/06/19 22:10, Matthew Beliveau wrote:

@@ -6025,6 +6025,10 @@ warn_about_ambiguous_bases (tree t)


Just a nit, but it seems weird to me that the function implementing 
warn_inaccessible_base is named warn_about_ambiguous_bases.


Paolo.




[C++ Patch] Further grokdeclarator locations work

2019-06-06 Thread Paolo Carlini

Hi,

only minor functional changes here - more precise locations for two 
error messages  - but I think it's a step in the right direction: it 
moves the declaration of id_loc way up, near typespec_loc and as such 
id_loc is immediately used. Then its value is updated upon the loop over 
declarator in the middle of the function and used again in the final 
part of the function. That also "frees" the simple name loc for other 
local uses, allows to simplify those checks changed rather recently over 
(name && declarator). and (unqualified_id && declarator). Tested 
x86_64-linux.


Thanks, Paolo.

//////

/cp
2019-06-06  Paolo Carlini  

* decl.c (grokdeclarator): Move further up the declaration of
id_loc, use it immediately, update its value after the loop
over declarator, use it again in the final part of function;
use id_loc in error messages about multiple data types and
conflicting specifiers.

/testsuite
2019-06-06  Paolo Carlini  

* g++.dg/diagnostic/conflicting-specifiers-1.C: New.
* g++.dg/diagnostic/two-or-more-data-types-1.C: Likewise.
Index: cp/decl.c
===
--- cp/decl.c   (revision 271974)
+++ cp/decl.c   (working copy)
@@ -10456,6 +10456,8 @@ grokdeclarator (const cp_declarator *declarator,
   if (typespec_loc == UNKNOWN_LOCATION)
 typespec_loc = input_location;
 
+  location_t id_loc = declarator ? declarator->id_loc : input_location;
+
   /* Look inside a declarator for the name being declared
  and get it as a string, for an error message.  */
   for (id_declarator = declarator;
@@ -10620,8 +10622,7 @@ grokdeclarator (const cp_declarator *declarator,
  D1 ( parameter-declaration-clause) ...  */
   if (funcdef_flag && innermost_code != cdk_function)
 {
-  error_at (declarator->id_loc,
-   "function definition does not declare parameters");
+  error_at (id_loc, "function definition does not declare parameters");
   return error_mark_node;
 }
 
@@ -10629,8 +10630,7 @@ grokdeclarator (const cp_declarator *declarator,
   && innermost_code != cdk_function
   && ! (ctype && !declspecs->any_specifiers_p))
 {
-  error_at (declarator->id_loc,
-   "declaration of %qD as non-function", dname);
+  error_at (id_loc, "declaration of %qD as non-function", dname);
   return error_mark_node;
 }
 
@@ -10639,8 +10639,7 @@ grokdeclarator (const cp_declarator *declarator,
   if (UDLIT_OPER_P (dname)
  && innermost_code != cdk_function)
{
- error_at (declarator->id_loc,
-   "declaration of %qD as non-function", dname);
+ error_at (id_loc, "declaration of %qD as non-function", dname);
  return error_mark_node;
}
 
@@ -10648,14 +10647,12 @@ grokdeclarator (const cp_declarator *declarator,
{
  if (typedef_p)
{
- error_at (declarator->id_loc,
-   "declaration of %qD as %", dname);
+ error_at (id_loc, "declaration of %qD as %", dname);
  return error_mark_node;
}
  else if (decl_context == PARM || decl_context == CATCHPARM)
{
- error_at (declarator->id_loc,
-   "declaration of %qD as parameter", dname);
+ error_at (id_loc, "declaration of %qD as parameter", dname);
  return error_mark_node;
}
}
@@ -10705,13 +10702,13 @@ grokdeclarator (const cp_declarator *declarator,
  issue an error message.  */
   if (declspecs->multiple_types_p)
 {
-  error ("two or more data types in declaration of %qs", name);
+  error_at (id_loc, "two or more data types in declaration of %qs", name);
   return error_mark_node;
 }
 
   if (declspecs->conflicting_specifiers_p)
 {
-  error ("conflicting specifiers in declaration of %qs", name);
+  error_at (id_loc, "conflicting specifiers in declaration of %qs", name);
   return error_mark_node;
 }
 
@@ -11861,6 +11858,8 @@ grokdeclarator (const cp_declarator *declarator,
}
 }
 
+  id_loc = declarator ? declarator->id_loc : input_location;
+
   /* A `constexpr' specifier used in an object declaration declares
  the object as `const'.  */
   if (constexpr_p && innermost_code != cdk_function)
@@ -11884,8 +11883,6 @@ grokdeclarator (const cp_declarator *declarator,
   unqualified_id = dname;
 }
 
-  location_t loc = declarator ? declarator->id_loc : input_location;
-
   /* If TYPE is a FUNCTION_TYPE, but the function name was explicitly
  qualified with a class-name, turn it into a METHOD_TYPE, unless
 

Re: [C++ Patch] Use declarator->id_loc in three additional places

2019-06-05 Thread Paolo Carlini

Hi,

On 05/06/19 19:45, Jason Merrill wrote:

On 6/4/19 11:57 AM, Paolo Carlini wrote:

Hi,

On 04/06/19 16:50, Jason Merrill wrote:

On 6/4/19 10:31 AM, Paolo Carlini wrote:

+  permerror (loc, "member functions are implicitly "
+ "friends of their class");


Wouldn't it be better to use the location of "friend" in this 
diagnostic?


Yes, however doing that fully correctly seems a bit tricky


Why tricky?  Doesn't declspecs->locations[ds_friend] work?


To be honest, here I wasn't considering ds_friend at all. Indeed it 
gives us the location of 'friend', but, say, for a testcase like 
parse/friend4.C:


struct A
{
  friend void A::foo();  // { dg-error "implicitly friends" }
  friend A::~A();    // { dg-error "implicitly friends" }
};

I thought we wanted a precise caret under the 'f' of 'foo' and the '~' 
of the destructor - both clang and icc do that - I wasn't even 
considering pointing at 'friend'. If you think that would be an 
improvement wrt the current closed parenthesis - I agreee it would! - I 
can do that!


Paolo.




[C++ Patch] Improve check_special_function_return_type locations

2019-06-05 Thread Paolo Carlini

Hi,

here certainly we can do better than using input_location. In principle 
we could also pass the location of the entity (constructor, destructor, 
etc) itself or something else but I think it makes a lot of sense to 
simply include locations[ds_type_spec] in the computation, seems 
consistent with the existing case of spurious qualifiers (ICC does 
something similar AFAICS). Tested x86_64-linux.


Thanks, Paolo.

//

/cp
2019-06-05  Paolo Carlini  

* decl.c (smallest_type_location): Add.
(check_special_function_return_type): Use it.
(grokdeclarator): Lkewise.

/testsuite
2019-06-05  Paolo Carlini  

* g++.dg/diagnostic/return-type-invalid-1.C: New.
* g++.old-deja/g++.brendan/crash16.C: Adjust.
* g++.old-deja/g++.law/ctors5.C: Likewise.
Index: cp/decl.c
===
--- cp/decl.c   (revision 271949)
+++ cp/decl.c   (working copy)
@@ -10111,6 +10111,15 @@ smallest_type_quals_location (int type_quals, cons
   return loc;
 }
 
+/* Returns the smallest among the latter and locations[ds_type_spec].  */
+
+static location_t
+smallest_type_location (int type_quals, const location_t* locations)
+{
+  location_t loc = smallest_type_quals_location (type_quals, locations);
+  return min_location (loc, locations[ds_type_spec]);
+}
+
 /* Check that it's OK to declare a function with the indicated TYPE
and TYPE_QUALS.  SFK indicates the kind of special function (if any)
that this function is.  OPTYPE is the type given in a conversion
@@ -10129,7 +10138,8 @@ check_special_function_return_type (special_functi
 {
 case sfk_constructor:
   if (type)
-   error ("return type specification for constructor invalid");
+   error_at (smallest_type_location (type_quals, locations),
+ "return type specification for constructor invalid");
   else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
  "qualifiers are not allowed on constructor declaration");
@@ -10142,7 +10152,8 @@ check_special_function_return_type (special_functi
 
 case sfk_destructor:
   if (type)
-   error ("return type specification for destructor invalid");
+   error_at (smallest_type_location (type_quals, locations),
+ "return type specification for destructor invalid");
   else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
  "qualifiers are not allowed on destructor declaration");
@@ -10157,7 +10168,8 @@ check_special_function_return_type (special_functi
 
 case sfk_conversion:
   if (type)
-   error ("return type specified for %", optype);
+   error_at (smallest_type_location (type_quals, locations),
+ "return type specified for %", optype);
   else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
  "qualifiers are not allowed on declaration of "
@@ -10168,7 +10180,8 @@ check_special_function_return_type (special_functi
 
 case sfk_deduction_guide:
   if (type)
-   error ("return type specified for deduction guide");
+   error_at (smallest_type_location (type_quals, locations),
+ "return type specified for deduction guide");
   else if (type_quals != TYPE_UNQUALIFIED)
error_at (smallest_type_quals_location (type_quals, locations),
  "qualifiers are not allowed on declaration of "
@@ -10438,10 +10451,8 @@ grokdeclarator (const cp_declarator *declarator,
   if (initialized > 1)
 funcdef_flag = true;
 
-  location_t typespec_loc = smallest_type_quals_location (type_quals,
- declspecs->locations);
-  typespec_loc = min_location (typespec_loc,
-  declspecs->locations[ds_type_spec]);
+  location_t typespec_loc = smallest_type_location (type_quals,
+   declspecs->locations);
   if (typespec_loc == UNKNOWN_LOCATION)
 typespec_loc = input_location;
 
Index: testsuite/g++.dg/diagnostic/return-type-invalid-1.C
===
--- testsuite/g++.dg/diagnostic/return-type-invalid-1.C (nonexistent)
+++ testsuite/g++.dg/diagnostic/return-type-invalid-1.C (working copy)
@@ -0,0 +1,27 @@
+struct S1
+{
+  int S1();  // { dg-error "3:return type" }
+  int ~S1();  // { dg-error "3:return type" }
+  int operator int();  // { dg-error "3:return type" }
+};
+
+struct S2
+{
+  const int S2();  // { dg-error "3:return type" }
+  const int ~S2();  // { dg-error "3:return type" }
+  cons

Re: PR C++/63149

2019-06-04 Thread Paolo Carlini

Hi,

On 04/06/19 21:26, Nina Dinka Ranns wrote:

Good point, dg-do compile is sufficient to demonstrate the issue.


I agree.

A couple of additional nits, sorry for mentioning only now.



C++63149_2.diff

Index: gcc/cp/pt.c
===
--- gcc/cp/pt.c (revision 271709)
+++ gcc/cp/pt.c (working copy)
@@ -26836,7 +26836,7 @@
  static tree
  listify_autos (tree type, tree auto_node)
  {
-  tree init_auto = listify (auto_node);
+  tree init_auto = listify (strip_top_quals(auto_node));


You want a space after strip_top_quals.


tree argvec = make_tree_vec (1);
TREE_VEC_ELT (argvec, 0) = init_auto;
if (processing_template_decl)
Index: gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C
===
--- gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C   (nonexistent)
+++ gcc/testsuite/g++.dg/cpp0x/initlist-deduce2.C   (working copy)
@@ -0,0 +1,12 @@
+// Test for PR63149
+// { dg-do compile { target c++11 } }
+
+#include 
+
+const auto r = { 1, 2, 3 };
+using X = decltype(r);
+using X = const std::initializer_list;
+
+int main()
+{
+}


With dg-do compile you don't need a main anymore.

I seem to remember also a couple of minor formatting issues in the 
ChangeLog entry: just harmonize the format with everything else you find 
in the ChangeLog, in terms of the usual trivial details: upper cases, 
line lenghts and line wraps, etc.


Paolo.



Re: PR C++/63149

2019-06-04 Thread Paolo Carlini

Hi,

On 04/06/19 18:36, Nina Dinka Ranns wrote:

+// Test for PR63149
+// { dg-do run { target c++11 } }


Are you sure you want a dg-do run?

Paolo.




Re: [C++ Patch] Use declarator->id_loc in three additional places

2019-06-04 Thread Paolo Carlini

Hi,

On 04/06/19 16:50, Jason Merrill wrote:

On 6/4/19 10:31 AM, Paolo Carlini wrote:

+  permerror (loc, "member functions are implicitly "
+ "friends of their class");


Wouldn't it be better to use the location of "friend" in this diagnostic?


Yes, however doing that fully correctly seems a bit tricky, I thought 
that pointing to the id_loc it's still better than a rather meaningless 
place near the end of the line, eg, before the semicolon. Note this is a 
more general issue, I'll give it some thought... I'm leaving those 
friends alone for the time being.


Thanks, Paolo.



[C++ Patch] Use declarator->id_loc in three additional places

2019-06-04 Thread Paolo Carlini

Hi,

tested x86_64-linux, as usual.

Thanks, Paolo.

///

/cp
2019-06-04  Paolo Carlini  

* decl.c (grokdeclarator): Use declarator->id_loc in three
additional places.

/testsuite
2019-06-04  Paolo Carlini  

* g++.dg/concepts/pr60573.C: Test locations too.
* g++.dg/cpp0x/deleted13.C: Likewise.
* g++.dg/other/friend4.C: Likewise.
* g++.dg/other/friend5.C: Likewise.
* g++.dg/other/friend7.C: Likewise.
* g++.dg/parse/error29.C: Likewise.
* g++.dg/parse/friend7.C: Likewise.
* g++.dg/parse/qualified4.C: Likewise.
* g++.dg/template/crash96.C Likewise.
* g++.old-deja/g++.brendan/crash22.C Likewise.
* g++.old-deja/g++.brendan/crash23.C Likewise.
* g++.old-deja/g++.law/visibility10.C Likewise.
* g++.old-deja/g++.other/decl5.C: Likewise.
Index: cp/decl.c
===
--- cp/decl.c   (revision 271899)
+++ cp/decl.c   (working copy)
@@ -11873,6 +11873,8 @@ grokdeclarator (const cp_declarator *declarator,
   unqualified_id = dname;
 }
 
+  location_t loc = declarator ? declarator->id_loc : input_location;
+
   /* If TYPE is a FUNCTION_TYPE, but the function name was explicitly
  qualified with a class-name, turn it into a METHOD_TYPE, unless
  we know that the function is static.  We take advantage of this
@@ -11893,13 +11895,12 @@ grokdeclarator (const cp_declarator *declarator,
{
  if (friendp)
{
- permerror (input_location, "member functions are implicitly "
-"friends of their class");
+ permerror (loc, "member functions are implicitly "
+"friends of their class");
  friendp = 0;
}
  else
-   permerror (declarator->id_loc, 
-  "extra qualification %<%T::%> on member %qs",
+   permerror (loc, "extra qualification %<%T::%> on member %qs",
   ctype, name);
}
   else if (/* If the qualifying type is already complete, then we
@@ -11928,19 +11929,19 @@ grokdeclarator (const cp_declarator *declarator,
  if (current_class_type
  && (!friendp || funcdef_flag || initialized))
{
- error (funcdef_flag || initialized
-? G_("cannot define member function %<%T::%s%> "
- "within %qT")
-: G_("cannot declare member function %<%T::%s%> "
- "within %qT"),
-ctype, name, current_class_type);
+ error_at (loc, funcdef_flag || initialized
+   ? G_("cannot define member function %<%T::%s%> "
+"within %qT")
+   : G_("cannot declare member function %<%T::%s%> "
+"within %qT"),
+   ctype, name, current_class_type);
  return error_mark_node;
}
}
   else if (typedef_p && current_class_type)
{
- error ("cannot declare member %<%T::%s%> within %qT",
-ctype, name, current_class_type);
+ error_at (loc, "cannot declare member %<%T::%s%> within %qT",
+   ctype, name, current_class_type);
  return error_mark_node;
}
 }
@@ -12053,8 +12054,6 @@ grokdeclarator (const cp_declarator *declarator,
}
 }
 
-  location_t loc = declarator ? declarator->id_loc : input_location;
-
   /* If this is declaring a typedef name, return a TYPE_DECL.  */
   if (typedef_p && decl_context != TYPENAME)
 {
Index: testsuite/g++.dg/concepts/pr60573.C
===
--- testsuite/g++.dg/concepts/pr60573.C (revision 271899)
+++ testsuite/g++.dg/concepts/pr60573.C (working copy)
@@ -9,7 +9,7 @@ struct A
 void foo(auto);
   };
 
-  void B::foo(auto) {}  // { dg-error "cannot define" }
+  void B::foo(auto) {}  // { dg-error "8:cannot define" }
 
   struct X
   {
@@ -21,8 +21,8 @@ struct A
   };
 };
 
-void Y::Z::foo(auto) {}  // { dg-error "cannot define" }
+void Y::Z::foo(auto) {}  // { dg-error "10:cannot define" }
   };
 
-  void X::Y::Z::foo(auto) {}  // { dg-error "cannot define" }
+  void X::Y::Z::foo(auto) {}  // { dg-error "8:cannot define" }
 };
Index: testsuite/g++.dg/cpp0x/deleted13.C
===
--- testsuite/g++.dg/cpp0x/deleted13.C  (revision 271899)
+++ testsuite/g++.dg/cpp0x/deleted13.C  (working copy)
@@ -8,5 +8,5 @@

Re: [PATCH][Preprocessor][Version 2]patch to fix PR 90581

2019-06-03 Thread Paolo Carlini

Hi,

a few minor comments.

On 03/06/19 16:49, Qing Zhao wrote:

+fmax-include-depth=
+C ObjC C++ ObjC++ Joined RejectNegative UInteger
+fmax-include-depth= Set the maximum number of depth of nested #include.


I think you want something like "Set the maximum depth of nested #include".


+@item -fmax-include-depth=@var{depth}
+@opindex fmax-include-depth
+Set the maximum number of depth of the nested include. The default is 200.


Likewise, plus include or #include?

In any case the wording should be consistent with the actual cpp_error 
message below in your attachment, thus, in particular, no "number".



+  /* the maximum depths for nested #include.  */


Upper case "The". "for" or "of"? Again, consistency.

Paolo.




[C++ Patch] Fix cp_parser_unqualified_id typo

2019-05-31 Thread Paolo Carlini

Hi,

noticed this typo: we are passing the location to build_nt as third 
argument instead of passing it to cp_expr as second argument. Tested 
x86_64-linux.


By the way, we have the option of using build_min_nt_loc instead of 
build_nt in all these places for BIT_NOT_EXPR in 
cp_parser_unqualified_id, Certainly it has the advantage that the 
location information survives in the tree node when cp_expr is 
eventually converted to a plain tree... (below tests fine) What do you 
think?


Thanks, Paolo.



2019-05-31  Paolo Carlini  

  * parser.c (cp_parser_unqualified_id): Fix typo, properly call
  build_nt.
Index: parser.c
===
--- parser.c(revision 271785)
+++ parser.c(working copy)
@@ -6063,7 +6063,7 @@ cp_parser_unqualified_id (cp_parser* parser,
   "%<~auto%> only available with "
   "%<-std=c++14%> or %<-std=gnu++14%>");
cp_lexer_consume_token (parser->lexer);
-   return cp_expr (build_nt (BIT_NOT_EXPR, make_auto (), loc));
+   return cp_expr (build_nt (BIT_NOT_EXPR, make_auto ()), loc);
  }
 
/* If there was an explicit qualification (S::~T), first look
Index: parser.c
===
--- parser.c(revision 271761)
+++ parser.c(working copy)
@@ -6052,7 +6052,7 @@ cp_parser_unqualified_id (cp_parser* parser,
&& constructor_name_p (token->u.value, scope
  {
cp_lexer_consume_token (parser->lexer);
-   return cp_expr (build_nt (BIT_NOT_EXPR, scope), loc);
+   return build_min_nt_loc (loc, BIT_NOT_EXPR, scope);
  }
 
/* ~auto means the destructor of whatever the object is.  */
@@ -6063,7 +6063,7 @@ cp_parser_unqualified_id (cp_parser* parser,
   "%<~auto%> only available with "
   "%<-std=c++14%> or %<-std=gnu++14%>");
cp_lexer_consume_token (parser->lexer);
-   return cp_expr (build_nt (BIT_NOT_EXPR, make_auto (), loc));
+   return build_min_nt_loc (loc, BIT_NOT_EXPR, make_auto ());
  }
 
/* If there was an explicit qualification (S::~T), first look
@@ -6153,8 +6153,8 @@ cp_parser_unqualified_id (cp_parser* parser,
   time.  */
type_decl = cp_parser_identifier (parser);
if (type_decl != error_mark_node)
- type_decl = build_nt (BIT_NOT_EXPR, type_decl);
-   return cp_expr (type_decl, loc);
+ type_decl = build_min_nt_loc (loc, BIT_NOT_EXPR, type_decl);
+   return type_decl;
  }
  }
/* If an error occurred, assume that the name of the
@@ -6162,7 +6162,7 @@ cp_parser_unqualified_id (cp_parser* parser,
   class.  That allows us to keep parsing after running
   into ill-formed destructor names.  */
if (type_decl == error_mark_node && scope)
- return build_nt (BIT_NOT_EXPR, scope);
+ return build_min_nt_loc (loc, BIT_NOT_EXPR, scope);
else if (type_decl == error_mark_node)
  return error_mark_node;
 
@@ -6189,7 +6189,7 @@ cp_parser_unqualified_id (cp_parser* parser,
"typedef-name %qD used as destructor declarator",
type_decl);
 
-   return cp_expr (build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl), loc));
+   return build_min_nt_loc (loc, BIT_NOT_EXPR, TREE_TYPE (type_decl));
   }
 
 case CPP_KEYWORD:


Re: [C++ Patch] PR 89875 ("[7/8/9/10 Regression] invalid typeof reference to a member of an incomplete struct accepted at function scope")

2019-05-28 Thread Paolo Carlini

Hi,

On 28/05/19 16:47, Jason Merrill wrote:

On 5/10/19 10:29 AM, Paolo Carlini wrote:

Hi,

a while ago Martin noticed that an unintended consequence of an old 
tweak of mine - which avoided redundant error messages emitted from 
cp_parser_init_declarator - is that, in some cases, we started 
accepting ill-formed typeofs. Luckily, decltype isn't affected and 
that points to the real issue: by the time that place in 
cp_parser_init_declarator is reached, for a decltype version we 
already emitted a correct error message. Thus I think the right way 
to fix the problem is simply committing to tentative parse when, 
toward the end of cp_parser_sizeof_operand we know that we must be 
looking at a (possibly ill-formed) expression. Tested x86_64-linux.


The problem with calling cp_parser_commit_to_tentative_parse here is 
that the tentative parse you're committing to is for the enclosing 
scope, which is trying to decide whether e.g. we're parsing a 
declaration or expression.  If the operand of typeof is a well-formed 
expression, and the larger context is an expression, this will break.


Better, I think, to commit and re-parse only if you actually encounter 
an error.


Alternately, cp_parser_decltype_expr deals with this by using a 
tentative firewall and CPP_DECLTYPE; cp_parser_sizeof_operand could do 
the same, but that seems like a bigger hammer.


Today I spent quite a bit of time on this and eventually decided to 
follow the example of decltype as closely as possible. Then I started 
tweaking those drafts which laready passed the testsuite and after a 
while ended up with the below, rather close to the current code, in 
fact. Testing !cp_parser_error_occurred and in case calling 
cp_parser_abort_tentative_parse by hand (closer to the decltype example) 
also works. What do you think? Thanks, Paolo.


///


Index: cp/parser.c
===
--- cp/parser.c (revision 271692)
+++ cp/parser.c (working copy)
@@ -28942,6 +28942,8 @@ cp_parser_sizeof_operand (cp_parser* parser, enum
 {
   tree type = NULL_TREE;
 
+  tentative_firewall firewall (parser);
+
   /* We can't be sure yet whether we're looking at a type-id or an
 expression.  */
   cp_parser_parse_tentatively (parser);
@@ -28969,11 +28971,15 @@ cp_parser_sizeof_operand (cp_parser* parser, enum
   /* If all went well, then we're done.  */
   if (cp_parser_parse_definitely (parser))
expr = type;
+  else
+   {
+ /* Commit to the tentative_firewall so we get syntax errors.  */
+ cp_parser_commit_to_tentative_parse (parser);
+
+ expr = cp_parser_unary_expression (parser);
+   }
 }
-
-  /* If the type-id production did not work out, then we must be
- looking at the unary-expression production.  */
-  if (!expr)
+  else
 expr = cp_parser_unary_expression (parser);
 
   /* Go back to evaluating expressions.  */
Index: testsuite/g++.dg/cpp0x/decltype-pr66548.C
===
--- testsuite/g++.dg/cpp0x/decltype-pr66548.C   (revision 271692)
+++ testsuite/g++.dg/cpp0x/decltype-pr66548.C   (working copy)
@@ -11,7 +11,7 @@ struct Meow {};
 
 void f ()
 {
-  decltype (Meow.purr ()) d;   // { dg-error "expected primary-expression" 
"pr89875" { xfail c++98_only } }
+  decltype (Meow.purr ()) d;   // { dg-error "expected primary-expression" }
   (void)
 }
 
Index: testsuite/g++.dg/template/sizeof-template-argument.C
===
--- testsuite/g++.dg/template/sizeof-template-argument.C(revision 
271692)
+++ testsuite/g++.dg/template/sizeof-template-argument.C(working copy)
@@ -3,9 +3,9 @@
 
 template struct A {};
 
-template struct B : A  {}; /* { dg-error "template 
argument" } */
+template struct B : A  {}; /* { dg-error "expected 
primary-expression" } */
 
-template struct C : A  {}; /* { dg-error "template 
argument" } */
+template struct C : A  {}; /* { dg-error "expected 
primary-expression" } */
 
 int a;
 


Re: [C++ Patch] PR 89875 ("[7/8/9/10 Regression] invalid typeof reference to a member of an incomplete struct accepted at function scope")

2019-05-24 Thread Paolo Carlini

Hi,

gently pinging this...

On 10/05/19 16:29, Paolo Carlini wrote:

Hi,

a while ago Martin noticed that an unintended consequence of an old 
tweak of mine - which avoided redundant error messages emitted from 
cp_parser_init_declarator - is that, in some cases, we started 
accepting ill-formed typeofs. Luckily, decltype isn't affected and 
that points to the real issue: by the time that place in 
cp_parser_init_declarator is reached, for a decltype version we 
already emitted a correct error message. Thus I think the right way to 
fix the problem is simply committing to tentative parse when, toward 
the end of cp_parser_sizeof_operand we know that we must be looking at 
a (possibly ill-formed) expression. Tested x86_64-linux.


    https://gcc.gnu.org/ml/gcc-patches/2019-05/msg00501.html

Thanks, Paolo.

PS: To be honest, not knowing the exact rules, I would not consider this 
issue a P2 - in particular considering that typeof is legacy and is 
affected but all sorts of weird issues - but that's what it is ;)





[C++ Patch] A few more grokdeclarator locations fixes

2019-05-23 Thread Paolo Carlini

Hi,

one more, rather straightforward, simply use the location stored in the 
declarator. Tested x86_64-linux.


Thanks, Paolo.



/cp
2019-05-23  Paolo Carlini  

* decl.c (grokdeclarator): Use declarator->id_loc in five error
error_at calls.

/testsuite
2019-05-23  Paolo Carlini  

* g++.dg/cpp0x/alias-decl-18.C: Test location too.
* g++.dg/cpp0x/udlit-nofunc-neg.C: Likewise.
* g++.dg/parse/crash59.C: Likewise.
* g++.dg/parse/error38.C: Likewise.
* g++.dg/parse/error39.C: Likewise.
* g++.dg/template/crash31.C: Likewise.
* g++.dg/template/operator8.C: Likewise.
* g++.dg/template/operator9.C: Likewise.
Index: cp/decl.c
===
--- cp/decl.c   (revision 271542)
+++ cp/decl.c   (working copy)
@@ -10592,7 +10592,8 @@ grokdeclarator (const cp_declarator *declarator,
  D1 ( parameter-declaration-clause) ...  */
   if (funcdef_flag && innermost_code != cdk_function)
 {
-  error ("function definition does not declare parameters");
+  error_at (declarator->id_loc,
+   "function definition does not declare parameters");
   return error_mark_node;
 }
 
@@ -10600,7 +10601,8 @@ grokdeclarator (const cp_declarator *declarator,
   && innermost_code != cdk_function
   && ! (ctype && !declspecs->any_specifiers_p))
 {
-  error ("declaration of %qD as non-function", dname);
+  error_at (declarator->id_loc,
+   "declaration of %qD as non-function", dname);
   return error_mark_node;
 }
 
@@ -10609,7 +10611,8 @@ grokdeclarator (const cp_declarator *declarator,
   if (UDLIT_OPER_P (dname)
  && innermost_code != cdk_function)
{
- error ("declaration of %qD as non-function", dname);
+ error_at (declarator->id_loc,
+   "declaration of %qD as non-function", dname);
  return error_mark_node;
}
 
@@ -10617,12 +10620,14 @@ grokdeclarator (const cp_declarator *declarator,
{
  if (typedef_p)
{
- error ("declaration of %qD as %", dname);
+ error_at (declarator->id_loc,
+   "declaration of %qD as %", dname);
  return error_mark_node;
}
  else if (decl_context == PARM || decl_context == CATCHPARM)
{
- error ("declaration of %qD as parameter", dname);
+ error_at (declarator->id_loc,
+   "declaration of %qD as parameter", dname);
  return error_mark_node;
}
}
Index: testsuite/g++.dg/cpp0x/alias-decl-18.C
===
--- testsuite/g++.dg/cpp0x/alias-decl-18.C  (revision 271542)
+++ testsuite/g++.dg/cpp0x/alias-decl-18.C  (working copy)
@@ -5,5 +5,6 @@ template using ::T = void(int n); // {
 template using operator int = void(int n); // { dg-error "" }
 template using typename U = void; // { dg-error "" }
 template using typename ::V = void(int n); // { dg-error "" }
-template using typename ::operator bool = void(int n); // { 
dg-error "" }
+template using typename ::operator bool = void(int n); // { 
dg-error "39:declaration" }
+// { dg-error "expected" "" { target *-*-* } .-1 }
 using foo __attribute__((aligned(4)) = int; // { dg-error "" }
Index: testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C
===
--- testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C   (revision 271542)
+++ testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C   (working copy)
@@ -3,7 +3,7 @@
 // Test user-defined literals.
 // Test error on non-function declaration.
 
-double operator"" _baddecl; // { dg-error "as non-function" }
+double operator"" _baddecl; // { dg-error "8:declaration of 
.operator\"\"_baddecl. as non-function" }
 
 template
-  int operator"" _badtmpldecl; // { dg-error "as non-function" }
+  int operator"" _badtmpldecl; // { dg-error "7:declaration of 
.operator\"\"_badtmpldecl. as non-function" }
Index: testsuite/g++.dg/parse/crash59.C
===
--- testsuite/g++.dg/parse/crash59.C(revision 271542)
+++ testsuite/g++.dg/parse/crash59.C(working copy)
@@ -1,3 +1,4 @@
 // PR c++/53003
 
-struct A{ void a{} return b  // { dg-error "function definition|expected" }
+struct A{ void a{} return b  // { dg-error "16:function definition" }
+// { dg-error "expected" "" { target *-*-* } .-1 }
Index: testsuite/g++.dg/parse/e

Re: [C++ PATCH] Fix udlit-char-template-neg.C test

2019-05-22 Thread Paolo Carlini

Hi,

On 23/05/19 00:04, Marek Polacek wrote:

On Thu, May 23, 2019 at 12:00:22AM +0200, Paolo Carlini wrote:

Hi,

On 22/05/19 23:45, Marek Polacek wrote:

I noticed this test fails since r271492.  Probably obvious, but...

Tested on x86_64-linux, ok for trunk?

I was wondering why I didn't notice it... It's because it only fails with
check-c++-all not with check-c++. Anyway, it seems obvious to me too and the
right line is the current one, good ;)

I'll go ahead and check it in, thanks for confirming!


Actually, Marek, there is a vey weird issue with our DejaGNU 
infrastructure which I noticed already in the past: dg-error "3:literal 
operator template|has invalid parameter list" is unexpectedly very weak: 
the column information, the 3, due to the | is mysteriously ignored. I 
think you want to shorten the string literal to simply "3:literal 
operator template", or alternately specify everything up to the "has 
invalid parameter list" (ie, see what I did for that patch and many other).


Paolo.



Re: [C++ PATCH] Fix udlit-char-template-neg.C test

2019-05-22 Thread Paolo Carlini

Hi,

On 22/05/19 23:45, Marek Polacek wrote:

I noticed this test fails since r271492.  Probably obvious, but...

Tested on x86_64-linux, ok for trunk?


I was wondering why I didn't notice it... It's because it only fails 
with check-c++-all not with check-c++. Anyway, it seems obvious to me 
too and the right line is the current one, good ;)


Paolo.



Re: [C++ Patch] Two literal operator template location fixes

2019-05-22 Thread Paolo Carlini

On 22/05/19 10:28, Christophe Lyon wrote:

On Tue, 21 May 2019 at 13:03, Paolo Carlini  wrote:

Hi,

also in my back queue a few more location fixes (of course ;) Tested
x86_64-linux.

Thanks, Paolo.




Hi,

I think you incorrectly committed an additional chunk:


I fixed that earlier today, sorry.

Paolo.




Re: [C++ Patch] PR 67184 ("Missed optimization with C++11 final specifier")

2019-05-21 Thread Paolo Carlini

Hi,

On 21/05/19 16:57, Jason Merrill wrote:

On 5/16/19 7:12 PM, Paolo Carlini wrote:

Hi,

when Roberto Agostino and I implemented the front-end 
devirtualization of final overriders we missed this case, where it 
comes from the base. It seems to me that by way of access_path the 
existing approach can be neatly extended. Tested x86_64-linux.



+  || CLASSTYPE_FINAL (TREE_TYPE (cand->access_path)))


This will give the wrong type when the function is called with an 
explicit scope; you probably want to look at argtype instead.


Yes, thanks, that works fine and is even neater. I'm finishing testing 
the below. As you can see, I also added a line to final3.C where the two 
versions of the call..c conditional give different answers. Note, 
however, that in practice, in terms, say, of dumps, the difference is 
difficult to emphasize because the call would not be virtual anyway (if 
I'm not horribly mistaken ;)


Thanks, Paolo.

/


Index: cp/call.c
===
--- cp/call.c   (revision 271459)
+++ cp/call.c   (working copy)
@@ -8244,7 +8244,7 @@ build_over_call (struct z_candidate *cand, int fla
   /* See if the function member or the whole class type is declared
 final and the call can be devirtualized.  */
   if (DECL_FINAL_P (fn)
- || CLASSTYPE_FINAL (TYPE_METHOD_BASETYPE (TREE_TYPE (fn
+ || CLASSTYPE_FINAL (TREE_TYPE (argtype)))
flags |= LOOKUP_NONVIRTUAL;
 
   /* [class.mfct.nonstatic]: If a nonstatic member function of a class
Index: testsuite/g++.dg/other/final3.C
===
--- testsuite/g++.dg/other/final3.C (nonexistent)
+++ testsuite/g++.dg/other/final3.C (working copy)
@@ -0,0 +1,27 @@
+// PR c++/67184
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdump-tree-original"  }
+
+struct V {
+ virtual void foo(); 
+};
+
+struct wV final : V {
+};
+
+struct oV final : V {
+  void foo();
+};
+
+void call(wV& x)
+{
+  x.foo();
+  x.V::foo();
+}
+
+void call(oV& x)
+{
+  x.foo();
+}
+
+// { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "original" } }
Index: testsuite/g++.dg/other/final4.C
===
--- testsuite/g++.dg/other/final4.C (nonexistent)
+++ testsuite/g++.dg/other/final4.C (working copy)
@@ -0,0 +1,16 @@
+// PR c++/67184
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdump-tree-original"  }
+
+struct B
+{
+  virtual void operator()();
+  virtual operator int();
+  virtual int operator++();
+};
+
+struct D final : B { };
+
+void foo(D& d) { d(); int t = d; ++d; }
+
+// { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "original" } }
Index: testsuite/g++.dg/other/final5.C
===
--- testsuite/g++.dg/other/final5.C (nonexistent)
+++ testsuite/g++.dg/other/final5.C (working copy)
@@ -0,0 +1,19 @@
+// PR c++/69445
+// { dg-do compile { target c++11 } }
+// { dg-options "-fdump-tree-original"  }
+
+struct Base {
+  virtual void foo() const = 0;
+  virtual void bar() const {}
+};
+
+struct C final : Base {
+  void foo() const { }
+};
+
+void func(const C & c) {
+  c.bar();
+  c.foo();
+}
+
+// { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "original" } }


  1   2   3   4   5   6   7   8   9   10   >