@@ -1501,6 +1501,7 @@ extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool,
bool);
extern void warn_for_omitted_condop (location_t, tree);
extern void warn_for_restrict (unsigned, tree *, unsigned);
+extern void warn_if_string_plus_char (location_t, tree, tree);
/* Places where an lvalue, or modifiable lvalue, may be required.
Used to select diagnostic messages in lvalue_error and
@@ -2332,6 +2332,28 @@ warn_for_restrict (unsigned param_pos, tree *argarray, unsigned nargs)
arg_positions.length ());
}
+/* Like char_type_p, but check the main variant and filter out
+ char16_t (uint_least16_t) and char32_t (uint_least32_t) in C11. */
+static inline bool
+type_main_variant_is_char (tree type)
+{
+ type = TYPE_MAIN_VARIANT (type);
+ return char_type_p (type)
+ && type != uint_least16_type_node
+ && type != uint_least32_type_node;
+}
+
+void
+warn_if_string_plus_char (location_t loc, tree ptrtype, tree inttype)
+{
+ if (POINTER_TYPE_P (ptrtype)
+ && type_main_variant_is_char (TREE_TYPE (ptrtype))
+ && type_main_variant_is_char (inttype))
+ warning_at (loc, OPT_Wstring_plus_char,
+ "add %qT to string pointer %qT does not append "
+ "to the string", inttype, ptrtype);
+}
+
/* Callback function to determine whether an expression TP or one of its
subexpressions comes from macro expansion. Used to suppress bogus
warnings. */
@@ -732,6 +732,11 @@ C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_stringop_overflow) Ini
Under the control of Object Size type, warn about buffer overflow in string
manipulation functions like memcpy and strcpy.
+Wstring-plus-char
+C ObjC C++ ObjC++ Var(warn_string_plus_char) Warning
+Warn about adding string pointers and characters, which is likely an
+ill-formed attempt to append the string.
+
Wstring-plus-int
C ObjC C++ ObjC++ Var(warn_string_plus_int) Warning
Warn about adding strings and integers, which is likely an ill-formed
@@ -3659,6 +3659,12 @@ parser_build_binary_op (location_t location, enum tree_code code,
arg1.get_start (),
arg2.get_finish ());
+ if (warn_string_plus_char && code == PLUS_EXPR)
+ {
+ warn_if_string_plus_char (location, type1, type2);
+ warn_if_string_plus_char (location, type2, type1);
+ }
+
/* Check for cases such as x+y<<z which users are likely
to misinterpret. */
if (warn_parentheses)
@@ -5788,6 +5794,14 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
newrhs = build_binary_op (location,
modifycode, lhs, newrhs, 1);
+ if (warn_string_plus_char)
+ {
+ tree lt = (lhs_origtype ? lhs_origtype : TREE_TYPE (lhs));
+ tree rt = (rhs_origtype ? rhs_origtype : TREE_TYPE (rhs));
+ warn_if_string_plus_char (location, lt, rt);
+ warn_if_string_plus_char (location, rt, lt);
+ }
+
/* The original type of the right hand side is no longer
meaningful. */
rhs_origtype = NULL_TREE;
@@ -5586,6 +5586,8 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
enum tree_code code2 = NOP_EXPR;
enum tree_code code_orig_arg1 = ERROR_MARK;
enum tree_code code_orig_arg2 = ERROR_MARK;
+ tree orig_type1 = error_mark_node;
+ tree orig_type2 = error_mark_node;
conversion *conv;
void *p;
bool strict_p;
@@ -5642,6 +5644,12 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
/* =, ->, [], () must be non-static member functions. */
case MODIFY_EXPR:
+ if (code2 == PLUS_EXPR)
+ {
+ /* Saved for warn_if_string_plus_char. */
+ orig_type1 = TREE_TYPE (arg1);
+ orig_type2 = TREE_TYPE (arg2);
+ }
if (code2 != NOP_EXPR)
break;
/* FALLTHRU */
@@ -5649,6 +5657,11 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
case ARRAY_REF:
memonly = true;
break;
+ case PLUS_EXPR:
+ /* Saved for warn_if_string_plus_char. */
+ orig_type1 = TREE_TYPE (arg1);
+ orig_type2 = TREE_TYPE (arg2);
+ break;
default:
break;
@@ -5977,6 +5990,13 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
switch (code)
{
case MODIFY_EXPR:
+ if (code2 == PLUS_EXPR
+ && (complain & tf_warning)
+ && warn_string_plus_char)
+ {
+ warn_if_string_plus_char (loc, TREE_TYPE (arg1), orig_type2);
+ warn_if_string_plus_char (loc, TREE_TYPE (arg2), orig_type2);
+ }
return cp_build_modify_expr (loc, arg1, code2, arg2, complain);
case INDIRECT_REF:
@@ -6016,6 +6036,14 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
case BIT_AND_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
+ if ((complain & tf_warning)
+ && warn_string_plus_char
+ && code == PLUS_EXPR)
+ {
+ warn_if_string_plus_char (loc, TREE_TYPE (arg1), orig_type2);
+ warn_if_string_plus_char (loc, TREE_TYPE (arg2), orig_type1);
+ }
+
return cp_build_binary_op (loc, code, arg1, arg2, complain);
case UNARY_PLUS_EXPR:
--
2.7.1