[PATCH 16/22] C/C++ frontend: use tree ranges in various diagnostics
David Malcolm
dmalcolm@redhat.com
Thu Sep 10 20:32:00 GMT 2015
Screenshot:
https://dmalcolm.fedorapeople.org/gcc/2015-09-09/tree-ranges.html
This mostly affects the C frontend, but it touches c-common.h so the
C++ frontend needs a slight adjustment.
gcc/c-family/ChangeLog:
* c-common.c: Include gcc-rich-location.h.
(binary_op_error): Add params orig_op0 and orig_op1; use them
to add ranges and captions to the error.
* c-common.h (binary_op_error): Add params orig_op0 and orig_op1.
gcc/c/ChangeLog:
* c-parser.c (c_parser_static_assert_declaration_no_semi):
Convert locals "assert_loc" and "value_loc" from location_t to
source_range, thus using ranges in diagnostics.
* c-typeck.c (inform_declaration): Use DECL_LOCATION_RANGE
of the decl, rather than DECL_SOURCE_LOCATION.
(build_function_call_vec): Use the EXPR_LOCATION_RANGE of
the function when issuing diagnostics, rather than "loc".
(convert_for_assignment): Emit range-based diagnostics, rather
than locations when CAN_HAVE_RANGE_P (rhs).
(c_finish_return): Likewise when CAN_HAVE_RANGE_P (retval).
When issuing warnings about erroneous presence/absence of return
values, show the location of current_function_decl using inform.
(build_binary_op): Pass orig_op0 and orig_op1 to binary_op_error.
gcc/cp/ChangeLog:
* typeck.c (cp_build_binary_op): Pass orig_op0 and orig_op1 to
binary_op_error.
gcc/testsuite/ChangeLog:
* gcc.dg/diagnostic-tree-expr-ranges.c: New file.
---
gcc/c-family/c-common.c | 9 +-
gcc/c-family/c-common.h | 3 +-
gcc/c/c-parser.c | 6 +-
gcc/c/c-typeck.c | 123 ++++++++++------
gcc/cp/typeck.c | 3 +-
gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges.c | 159 +++++++++++++++++++++
6 files changed, 250 insertions(+), 53 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges.c
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index ff6f90f..77962fc 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimplify.h"
#include "wide-int-print.h"
#include "gimple-expr.h"
+#include "gcc-rich-location.h"
cpp_reader *parse_in; /* Declared in c-pragma.h. */
@@ -4340,6 +4341,7 @@ c_register_builtin_type (tree type, const char* name)
void
binary_op_error (location_t location, enum tree_code code,
+ tree orig_op0, tree orig_op1,
tree type0, tree type1)
{
const char *opname;
@@ -4391,7 +4393,12 @@ binary_op_error (location_t location, enum tree_code code,
default:
gcc_unreachable ();
}
- error_at (location,
+ gcc_rich_location richloc (location);
+ richloc.maybe_add_expr_with_caption (orig_op0, global_dc,
+ "%qT", TREE_TYPE (orig_op0));
+ richloc.maybe_add_expr_with_caption (orig_op1, global_dc,
+ "%qT", TREE_TYPE (orig_op1));
+ error_at_rich_loc (&richloc,
"invalid operands to binary %s (have %qT and %qT)", opname,
type0, type1);
}
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index bb17fcc..b9a5d72 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -804,7 +804,8 @@ extern tree c_sizeof_or_alignof_type (location_t, tree, bool, bool, int);
extern tree c_alignof_expr (location_t, tree);
/* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */
-extern void binary_op_error (location_t, enum tree_code, tree, tree);
+extern void binary_op_error (location_t, enum tree_code, tree, tree,
+ tree, tree);
extern tree fix_string_type (tree);
extern void constant_expression_warning (tree);
extern void constant_expression_error (tree);
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 4303496..0c62496 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -2037,12 +2037,12 @@ c_parser_static_assert_declaration (c_parser *parser)
static void
c_parser_static_assert_declaration_no_semi (c_parser *parser)
{
- location_t assert_loc, value_loc;
+ source_range assert_loc, value_loc;
tree value;
tree string;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
- assert_loc = c_parser_peek_token (parser)->location;
+ assert_loc = c_parser_peek_token (parser)->range;
if (flag_isoc99)
pedwarn_c99 (assert_loc, OPT_Wpedantic,
"ISO C99 does not support %<_Static_assert%>");
@@ -2052,8 +2052,8 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
c_parser_consume_token (parser);
if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
return;
- value_loc = c_parser_peek_token (parser)->location;
value = c_parser_expr_no_commas (parser, NULL).value;
+ value_loc = EXPR_LOCATION_RANGE (value);
parser->lex_untranslated_string = true;
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
{
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 4123f11..506abb3 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2851,7 +2851,7 @@ static void
inform_declaration (tree decl)
{
if (decl && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_IS_BUILTIN (decl)))
- inform (DECL_SOURCE_LOCATION (decl), "declared here");
+ inform (DECL_LOCATION_RANGE (decl), "declared here");
}
/* Build a function call to function FUNCTION with parameters PARAMS.
@@ -2873,6 +2873,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
int nargs;
tree *argarray;
+ source_range func_range = EXPR_LOCATION_RANGE (function);
/* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
STRIP_TYPE_NOPS (function);
@@ -2921,13 +2922,13 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
function);
else if (DECL_P (function))
{
- error_at (loc,
+ error_at (func_range,
"called object %qD is not a function or function pointer",
function);
inform_declaration (function);
}
else
- error_at (loc,
+ error_at (func_range,
"called object is not a function or function pointer");
return error_mark_node;
}
@@ -2958,11 +2959,12 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
/* This situation leads to run-time undefined behavior. We can't,
therefore, simply error unless we can prove that all possible
executions of the program must execute the code. */
- warning_at (loc, 0, "function called through a non-compatible type");
+ warning_at (func_range, 0,
+ "function called through a non-compatible type");
if (VOID_TYPE_P (return_type)
&& TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
- pedwarn (loc, 0,
+ pedwarn (func_range, 0,
"function with qualified void return type called");
}
@@ -2999,7 +3001,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
if (VOID_TYPE_P (TREE_TYPE (result)))
{
if (TYPE_QUALS (TREE_TYPE (result)) != TYPE_UNQUALIFIED)
- pedwarn (loc, 0,
+ pedwarn (func_range, 0,
"function with qualified void return type called");
return result;
}
@@ -5734,6 +5736,13 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
tree rname = NULL_TREE;
bool objc_ok = false;
+ source_range rhs_range;
+
+ if (CAN_HAVE_RANGE_P (rhs))
+ rhs_range = EXPR_LOCATION_RANGE (rhs);
+ else
+ rhs_range = source_range::from_location (expr_loc);
+
if (errtype == ic_argpass)
{
tree selector;
@@ -5756,14 +5765,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
/* This macro is used to emit diagnostics to ensure that all format
strings are complete sentences, visible to gettext and checked at
compile time. */
-#define PEDWARN_FOR_ASSIGNMENT(LOCATION, PLOC, OPT, AR, AS, IN, RE) \
+#define PEDWARN_FOR_ASSIGNMENT(LOCATION, RANGE, OPT, AR, AS, IN, RE) \
do { \
switch (errtype) \
{ \
case ic_argpass: \
- if (pedwarn (PLOC, OPT, AR, parmnum, rname)) \
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \
- ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \
+ if (pedwarn (RANGE, OPT, AR, parmnum, rname)) \
+ inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \
+ ? DECL_SOURCE_LOCATION (fundecl) : RANGE.m_start, \
"expected %qT but argument is of type %qT", \
type, rhstype); \
break; \
@@ -5785,14 +5794,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
strings are complete sentences, visible to gettext and checked at
compile time. It is the same as PEDWARN_FOR_ASSIGNMENT but with an
extra parameter to enumerate qualifiers. */
-#define PEDWARN_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \
+#define PEDWARN_FOR_QUALIFIERS(LOCATION, RANGE, OPT, AR, AS, IN, RE, QUALS) \
do { \
switch (errtype) \
{ \
case ic_argpass: \
- if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS)) \
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \
- ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \
+ if (pedwarn (RANGE, OPT, AR, parmnum, rname, QUALS)) \
+ inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \
+ ? DECL_SOURCE_LOCATION (fundecl) : RANGE.m_start, \
"expected %qT but argument is of type %qT", \
type, rhstype); \
break; \
@@ -5814,14 +5823,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
strings are complete sentences, visible to gettext and checked at
compile time. It is the same as PEDWARN_FOR_QUALIFIERS but uses
warning_at instead of pedwarn. */
-#define WARNING_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \
+#define WARNING_FOR_QUALIFIERS(LOCATION, RANGE, OPT, AR, AS, IN, RE, QUALS) \
do { \
switch (errtype) \
{ \
case ic_argpass: \
- if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS)) \
+ if (warning_at (RANGE, OPT, AR, parmnum, rname, QUALS)) \
inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \
- ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \
+ ? DECL_SOURCE_LOCATION (fundecl) : RANGE.m_start, \
"expected %qT but argument is of type %qT", \
type, rhstype); \
break; \
@@ -5881,7 +5890,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
&& TREE_CODE (type) == ENUMERAL_TYPE
&& TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type))
{
- PEDWARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wc___compat,
+ PEDWARN_FOR_ASSIGNMENT (location, rhs_range, OPT_Wc___compat,
G_("enum conversion when passing argument "
"%d of %qE is invalid in C++"),
G_("enum conversion in assignment is "
@@ -6050,7 +6059,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
vice-versa. */
if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
- PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+ PEDWARN_FOR_QUALIFIERS (location, rhs_range,
OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE "
"makes %q#v qualified function "
@@ -6067,7 +6076,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
}
else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
- PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+ PEDWARN_FOR_QUALIFIERS (location, rhs_range,
OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE discards "
"%qv qualifier from pointer target type"),
@@ -6158,7 +6167,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype)
{
case ic_argpass:
- error_at (expr_loc, "passing argument %d of %qE from pointer to "
+ error_at (rhs_range, "passing argument %d of %qE from pointer to "
"non-enclosed address space", parmnum, rname);
break;
case ic_assign:
@@ -6187,7 +6196,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype)
{
case ic_argpass:
- warning_at (expr_loc, OPT_Wsuggest_attribute_format,
+ warning_at (rhs_range, OPT_Wsuggest_attribute_format,
"argument %d of %qE might be "
"a candidate for a format attribute",
parmnum, rname);
@@ -6234,7 +6243,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
& ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
- WARNING_FOR_QUALIFIERS (location, expr_loc,
+ WARNING_FOR_QUALIFIERS (location, rhs_range,
OPT_Wdiscarded_array_qualifiers,
G_("passing argument %d of %qE discards "
"%qv qualifier from pointer target type"),
@@ -6252,7 +6261,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
(VOID_TYPE_P (ttr)
&& !null_pointer_constant
&& TREE_CODE (ttl) == FUNCTION_TYPE)))
- PEDWARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpedantic,
+ PEDWARN_FOR_ASSIGNMENT (location, rhs_range, OPT_Wpedantic,
G_("ISO C forbids passing argument %d of "
"%qE between function pointer "
"and %<void *%>"),
@@ -6277,7 +6286,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
& ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
{
- PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+ PEDWARN_FOR_QUALIFIERS (location, rhs_range,
OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE discards "
"%qv qualifier from pointer target type"),
@@ -6296,7 +6305,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
;
/* If there is a mismatch, do warn. */
else if (warn_pointer_sign)
- PEDWARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpointer_sign,
+ PEDWARN_FOR_ASSIGNMENT (location, rhs_range, OPT_Wpointer_sign,
G_("pointer targets in passing argument "
"%d of %qE differ in signedness"),
G_("pointer targets in assignment "
@@ -6315,7 +6324,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
where an ordinary one is wanted, but not vice-versa. */
if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
- PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+ PEDWARN_FOR_QUALIFIERS (location, rhs_range,
OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE makes "
"%q#v qualified function pointer "
@@ -6332,7 +6341,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
else
/* Avoid warning about the volatile ObjC EH puts on decls. */
if (!objc_ok)
- PEDWARN_FOR_ASSIGNMENT (location, expr_loc,
+ PEDWARN_FOR_ASSIGNMENT (location, rhs_range,
OPT_Wincompatible_pointer_types,
G_("passing argument %d of %qE from "
"incompatible pointer type"),
@@ -6356,7 +6365,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
or one that results from arithmetic, even including
a cast to integer type. */
if (!null_pointer_constant)
- PEDWARN_FOR_ASSIGNMENT (location, expr_loc,
+ PEDWARN_FOR_ASSIGNMENT (location, rhs_range,
OPT_Wint_conversion,
G_("passing argument %d of %qE makes "
"pointer from integer without a cast"),
@@ -6371,7 +6380,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
}
else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
{
- PEDWARN_FOR_ASSIGNMENT (location, expr_loc,
+ PEDWARN_FOR_ASSIGNMENT (location, rhs_range,
OPT_Wint_conversion,
G_("passing argument %d of %qE makes integer "
"from pointer without a cast"),
@@ -6396,7 +6405,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype)
{
case ic_argpass:
- error_at (expr_loc, "incompatible type for argument %d of %qE", parmnum,
+ error_at (rhs_range, "incompatible type for argument %d of %qE", parmnum,
rname);
inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
@@ -9396,8 +9405,14 @@ c_finish_return (location_t loc, tree retval, tree origtype)
bool npc = false;
size_t rank = 0;
+ source_range expr_range;
+ if (retval && CAN_HAVE_RANGE_P (retval))
+ expr_range = EXPR_LOCATION_RANGE (retval);
+ else
+ expr_range = source_range::from_location (loc);
+
if (TREE_THIS_VOLATILE (current_function_decl))
- warning_at (loc, 0,
+ warning_at (expr_range, 0,
"function declared %<noreturn%> has a %<return%> statement");
if (flag_cilkplus && contains_array_notation_expr (retval))
@@ -9408,14 +9423,15 @@ c_finish_return (location_t loc, tree retval, tree origtype)
return error_mark_node;
if (rank >= 1)
{
- error_at (loc, "array notation expression cannot be used as a "
+ error_at (expr_range, "array notation expression cannot be used as a "
"return value");
return error_mark_node;
}
}
if (flag_cilkplus && retval && contains_cilk_spawn_stmt (retval))
{
- error_at (loc, "use of %<_Cilk_spawn%> in a return statement is not "
+ error_at (expr_range,
+ "use of %<_Cilk_spawn%> in a return statement is not "
"allowed");
return error_mark_node;
}
@@ -9439,24 +9455,36 @@ c_finish_return (location_t loc, tree retval, tree origtype)
if ((warn_return_type || flag_isoc99)
&& valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
{
+ bool warned_here;
if (flag_isoc99)
- pedwarn (loc, 0, "%<return%> with no value, in "
- "function returning non-void");
+ warned_here = pedwarn
+ (loc, 0,
+ "%<return%> with no value, in function returning non-void");
else
- warning_at (loc, OPT_Wreturn_type, "%<return%> with no value, "
- "in function returning non-void");
- no_warning = true;
+ warned_here =
+ warning_at (loc, OPT_Wreturn_type,
+ "%<return%> with no value, "
+ "in function returning non-void");
+ if (warned_here)
+ inform (DECL_SOURCE_LOCATION (current_function_decl),
+ "declared here");
}
}
else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
{
current_function_returns_null = 1;
+ bool warned_here;
if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
- pedwarn (loc, 0,
- "%<return%> with a value, in function returning void");
+ warned_here = pedwarn
+ (expr_range, 0,
+ "%<return%> with a value, in function returning void");
else
- pedwarn (loc, OPT_Wpedantic, "ISO C forbids "
- "%<return%> with expression, in function returning void");
+ warned_here = pedwarn
+ (expr_range, OPT_Wpedantic, "ISO C forbids "
+ "%<return%> with expression, in function returning void");
+ if (warned_here)
+ inform (DECL_SOURCE_LOCATION (current_function_decl),
+ "declared here");
}
else
{
@@ -9532,11 +9560,11 @@ c_finish_return (location_t loc, tree retval, tree origtype)
&& DECL_CONTEXT (inner) == current_function_decl)
{
if (TREE_CODE (inner) == LABEL_DECL)
- warning_at (loc, OPT_Wreturn_local_addr,
+ warning_at (expr_range, OPT_Wreturn_local_addr,
"function returns address of label");
else
{
- warning_at (loc, OPT_Wreturn_local_addr,
+ warning_at (expr_range, OPT_Wreturn_local_addr,
"function returns address of local variable");
tree zero = build_zero_cst (TREE_TYPE (res));
t = build2 (COMPOUND_EXPR, TREE_TYPE (res), t, zero);
@@ -11055,7 +11083,7 @@ build_binary_op (location_t location, enum tree_code code,
&& (!tree_int_cst_equal (TYPE_SIZE (type0), TYPE_SIZE (type1))
|| !vector_types_compatible_elements_p (type0, type1)))
{
- binary_op_error (location, code, type0, type1);
+ binary_op_error (location, code, orig_op0, orig_op1, type0, type1);
return error_mark_node;
}
@@ -11294,7 +11322,8 @@ build_binary_op (location_t location, enum tree_code code,
if (!result_type)
{
- binary_op_error (location, code, TREE_TYPE (op0), TREE_TYPE (op1));
+ binary_op_error (location, code, orig_op0, orig_op1,
+ TREE_TYPE (op0), TREE_TYPE (op1));
return error_mark_node;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 388558c..b5a131c 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4841,7 +4841,8 @@ cp_build_binary_op (location_t location,
|| !vector_types_compatible_elements_p (type0, type1))
{
if (complain & tf_error)
- binary_op_error (location, code, type0, type1);
+ binary_op_error (location, code, orig_op0, orig_op1,
+ type0, type1);
return error_mark_node;
}
arithmetic_types_p = 1;
diff --git a/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges.c b/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges.c
new file mode 100644
index 0000000..10ab7db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/diagnostic-tree-expr-ranges.c
@@ -0,0 +1,159 @@
+/* { dg-options "-fdiagnostics-show-caret -Wreturn-local-addr" } */
+
+/* Verify that various diagnostics show source code ranges. */
+
+/* These ones make use of tree ranges. */
+
+void test_nonconst_static_assert (int i)
+{
+ _Static_assert (i > 0, "message"); /* { dg-error "expression in static assertion is not constant" } */
+/*
+{ dg-begin-multiline-output "" }
+ _Static_assert (i > 0, "message");
+ ^~~~~
+{ dg-end-multiline-output "" }
+*/
+}
+
+extern void test_callee (int first, const char *second, int third);
+
+void test_bad_argument_types (int first, int second, int third)
+{
+ test_callee (first, first + second + third, third); /* { dg-warning "passing argument 2 of 'test_callee' makes pointer from integer without a cast" } */
+
+/*
+{ dg-begin-multiline-output "" }
+ test_callee (first, first + second + third, third);
+ ^~~~~~~~~~~~~~~~~~~~~~
+{ dg-end-multiline-output "" }
+{ dg-begin-multiline-output "" }
+ extern void test_callee (int first, const char *second, int third);
+ ^
+{ dg-end-multiline-output "" }
+FIXME: we ought to highlight the specific param in the decl
+*/
+
+ test_callee (first, &first, third); /* { dg-warning "passing argument 2 of 'test_callee' from incompatible pointer type" } */
+
+/*
+{ dg-begin-multiline-output "" }
+ test_callee (first, &first, third);
+ ^~~~~~
+{ dg-end-multiline-output "" }
+{ dg-begin-multiline-output "" }
+ extern void test_callee (int first, const char *second, int third);
+ ^
+{ dg-end-multiline-output "" }
+FIXME: again, we ought to highlight the specific param in the decl
+*/
+
+ test_callee ("hello world", "", third); /* { dg-warning "passing argument 1 of 'test_callee' makes integer from pointer without a cast" } */
+
+/*
+{ dg-begin-multiline-output "" }
+ test_callee ("hello world", "", third);
+ ^~~~~~~~~~~~~
+{ dg-end-multiline-output "" }
+{ dg-begin-multiline-output "" }
+ extern void test_callee (int first, const char *second, int third);
+ ^
+{ dg-end-multiline-output "" }
+FIXME: and again, we ought to highlight the specific param in the decl
+*/
+
+}
+
+/* Adapted from https://gcc.gnu.org/wiki/ClangDiagnosticsComparison */
+
+void call_of_non_function_ptr (char **argP, char **argQ)
+{
+ (argP - argQ)(); /* { dg-error "called object is not a function or function pointer" } */
+
+/* { dg-begin-multiline-output "" }
+ (argP - argQ)();
+ ^~~~~~~~~~~~~
+ { dg-end-multiline-output "" } */
+
+ argP(); /* { dg-error "called object 'argP' is not a function or function pointer" } */
+
+/* { dg-begin-multiline-output "" }
+ argP();
+ ^~~~
+ { dg-end-multiline-output "" }
+ { dg-begin-multiline-output "" }
+ void call_of_non_function_ptr (char **argP, char **argQ)
+ ^
+ { dg-end-multiline-output "" } */
+ /* TODO: underline all of "argP" in the decl above. */
+}
+
+/* Adapted from https://gcc.gnu.org/wiki/ClangDiagnosticsComparison */
+
+typedef float __m128;
+void bad_binary_op ()
+{
+ __m128 myvec[2];
+ int const *ptr;
+ myvec[1]/ptr; /* { dg-error "invalid operands to binary /" } */
+
+/*
+{ dg-begin-multiline-output "" }
+ myvec[1]/ptr;
+ ~~~~~~~~^~~~
+{ dg-end-multiline-output "" } */
+
+}
+
+struct s {};
+struct t {};
+extern struct s some_function (void);
+extern struct t some_other_function (void);
+
+int another_bad_binary_op (void)
+{
+ return (some_function ()
+ + some_other_function ()); /* { dg-error "invalid operands to binary +" } */
+
+/* { dg-begin-multiline-output "" }
+ return (some_function ()|
+ ~~~~~~~~~~~~~~~~+'struct s'
+ + some_other_function ()); |
+ ^ ~~~~~~~~~~~~~~~~~~~~~~ +'struct t'
+ { dg-end-multiline-output "" } */
+}
+
+void surplus_return_when_void (void)
+{
+ return 500; /* { dg-warning "'return' with a value, in function returning void" } */
+/* { dg-begin-multiline-output "" }
+ return 500;
+ ^~~
+ { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+ void surplus_return_when_void (void)
+ ^
+ { dg-end-multiline-output "" } */
+}
+
+int missing_return_value (void)
+{
+ return; /* { dg-warning "'return' with no value, in function returning non-void" } */
+/* { dg-begin-multiline-output "" }
+ return;
+ ^
+ { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+ int missing_return_value (void)
+ ^
+ { dg-end-multiline-output "" } */
+}
+
+int *address_of_local (void)
+{
+ int i;
+ return &i; /* { dg-warning "function returns address of local variable" } */
+/* { dg-begin-multiline-output "" }
+ return &i;
+ ^~
+ { dg-end-multiline-output "" } */
+}
--
1.8.5.3
More information about the Gcc-patches
mailing list