On 02/22/2017 04:01 AM, Xi Ruoyao wrote:
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)
Needs a comment describing what the function does.


+{
+  return char_type_p (build_qualified_type (type, TYPE_UNQUALIFIED));
+}
Can you use TYPE_MAIN_VARIANT (type) here rather than building a new type?


+
+/* 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.  */
s/about/for/  I think

+  if (type2 == uint_least16_type_node ||
+         type2 == uint_least32_type_node)
+       arg2_is_char = false;
Formatting.  Operator goes on the next line.

+
+  if (code1 == STRING_CST && TREE_CODE (type2) == INTEGER_TYPE &&
+      (code2 != INTEGER_CST || arg2_is_char))
Formatting.

+    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)
Formatting.


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 */
Formatting problems should be obvious :-)

I think Jason probably needs to chime in on this patch. I'm not keen on the way we stash away the arguments into orig_argX. Perhaps he's got a better suggestion.

Jeff

Reply via email to