This patch adds warning option -Wstring-plus-int for C++. gcc/ChangeLog:
2017-02-22 Xi Ruoyao <r...@stu.xidian.edu.cn> * c-family/c-common.h (maybe_warn_string_plus_int): new prototype * c-family/c-warn.h (maybe_warn_string_plus_int): new function * c-family/c-opt: new option -Wstring-plus-int * cp/call.c (build_new_op_1): Checking for -Wstring-plus-int --- gcc/c-family/c-common.h | 2 ++ gcc/c-family/c-warn.c | 34 ++++++++++++++++++++++++++++++++++ gcc/c-family/c.opt | 5 +++++ gcc/cp/call.c | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+) diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 72fba56..8c748e9 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1503,6 +1503,8 @@ 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, vec<tree, va_gc> *); +extern void maybe_warn_string_plus_int (location_t, tree, tree, + enum tree_code, enum tree_code); /* Places where an lvalue, or modifiable lvalue, may be required. Used to select diagnostic messages in lvalue_error and diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index 09c5760..0b038a7 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -2290,3 +2290,37 @@ do_warn_duplicated_branches_r (tree *tp, int *, void *) do_warn_duplicated_branches (*tp); return NULL_TREE; } + +static inline bool +char_type_cv_p (tree type) +{ + return char_type_p (build_qualified_type (type, TYPE_UNQUALIFIED)); +} + +/* Warn about adding string literals/pointers and chars. + Produce a warning when: + 1) arg1 is a string literal, and arg2 is a non-literal integer; + 2) arg1 is a string pointer, and arg2 is a character. */ + +void +maybe_warn_string_plus_int (location_t loc, tree type1, tree type2, + enum tree_code code1, enum tree_code code2) +{ + bool arg2_is_char = char_type_cv_p (type2); + /* In C11, char16_t and char32_t are typedefs. Prevent false positives + about uint_least16_t and uint_least32_t. */ + if (type2 == uint_least16_type_node || + type2 == uint_least32_type_node) + arg2_is_char = false; + + if (code1 == STRING_CST && TREE_CODE (type2) == INTEGER_TYPE && + (code2 != INTEGER_CST || arg2_is_char)) + warning_at (loc, OPT_Wstring_plus_int, + "adding %qT to string literal does not append to " + "the string", type2); + else if (TREE_CODE (type1) == POINTER_TYPE && + char_type_cv_p (TREE_TYPE (type1)) && arg2_is_char) + warning_at (loc, OPT_Wstring_plus_int, + "adding %qT to string pointer %qT does not append " + "to the string", type2, type1); +} diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index a1b3ae5..f0b482f 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -716,6 +716,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-int +C ObjC C++ ObjC++ Var(warn_string_plus_int) Warning +Warn about adding string pointers and integers, which is likely an ill-formed attempt +to append the string. + Wsuggest-attribute=format C ObjC C++ ObjC++ Var(warn_suggest_attribute_format) Warning Warn about functions which might be candidates for format attributes. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 93fae0d..95bda1b 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5555,6 +5555,8 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, void *p; bool strict_p; bool any_viable_p; + tree orig_arg1 = error_mark_node; + tree orig_arg2 = error_mark_node; if (error_operand_p (arg1) || error_operand_p (arg2) @@ -5605,8 +5607,20 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, code_orig_arg2 = TREE_CODE (TREE_TYPE (arg2)); break; + case PLUS_EXPR: + /* These are saved for the sake of warn_string_plus_int. */ + orig_arg1 = arg1; + orig_arg2 = arg2; + break; + /* =, ->, [], () must be non-static member functions. */ case MODIFY_EXPR: + if (code2 == PLUS_EXPR) + { + /* Like PLUS_EXPR. */ + orig_arg1 = arg1; + orig_arg2 = arg2; + } if (code2 != NOP_EXPR) break; /* FALLTHRU */ @@ -5937,9 +5951,30 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, return result; builtin: + /* Warn about adding string literals/pointers and chars. */ + if (code == PLUS_EXPR && (complain & tf_warning) && + warn_string_plus_int) + { + maybe_warn_string_plus_int (loc, TREE_TYPE (arg1), + TREE_TYPE (orig_arg2), + TREE_CODE (arg1), + TREE_CODE (orig_arg2)); + maybe_warn_string_plus_int (loc, TREE_TYPE (arg2), + TREE_TYPE (orig_arg1), + TREE_CODE (arg2), + TREE_CODE (orig_arg1)); + } + switch (code) { case MODIFY_EXPR: + /* Warn about adding string literals/pointers and chars. */ + if (code2 == PLUS_EXPR && (complain & tf_warning) && + warn_string_plus_int) + maybe_warn_string_plus_int (loc, TREE_TYPE (arg1), + TREE_TYPE (orig_arg2), + TREE_CODE (arg1), + TREE_CODE (orig_arg2)); return cp_build_modify_expr (loc, arg1, code2, arg2, complain); case INDIRECT_REF: -- Xi Ruoyao <r...@stu.xidian.edu.cn> School of Aerospace Science and Technology, Xidian University