xbolva00 updated this revision to Diff 284043.
xbolva00 marked 2 inline comments as done.
xbolva00 added a comment.

New testcases.
Emit note to tell user how to supress warning - extra parentheses.
Emit fixit with comma.
Addressed review notes.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D85545/new/

https://reviews.llvm.org/D85545

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaExpr.cpp
  clang/test/Sema/string-concat.c

Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -6907,6 +6907,19 @@
         << DIE->getSourceRange();
       Diag(InitArgList[I]->getBeginLoc(), diag::note_designated_init_mixed)
         << InitArgList[I]->getSourceRange();
+    } else if (const auto *SL = dyn_cast<StringLiteral>(InitArgList[I])) {
+      unsigned numConcat = SL->getNumConcatenated();
+      // Diagnose missing comma in string array initialization.
+      if (numConcat > 1 && !SL->getBeginLoc().isMacroID()) {
+        SmallVector<FixItHint, 1> Hints;
+        for (unsigned i = 0; i < numConcat - 1; ++i)
+          Hints.push_back(FixItHint::CreateInsertion(
+              PP.getLocForEndOfToken(SL->getStrTokenLoc(i)), ", "));
+
+        Diag(SL->getStrTokenLoc(1), diag::warn_concatenated_literal_array_init)
+            << Hints;
+        Diag(SL->getBeginLoc(), diag::note_concatenated_string_literal_silence);
+      }
     }
   }
 
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2999,6 +2999,10 @@
 def warn_objc_string_literal_comparison : Warning<
   "direct comparison of a string literal has undefined behavior">,
   InGroup<ObjCStringComparison>;
+def warn_concatenated_literal_array_init : Warning<
+  "concatenated literal in a string array initialization - "
+  "possibly missing a comma">,
+  InGroup<DiagGroup<"string-concatenation">>;
 def warn_concatenated_nsarray_literal : Warning<
   "concatenated NSString literal for an NSArray expression - "
   "possibly missing a comma">,
@@ -6139,6 +6143,9 @@
 def note_evaluate_comparison_first :Note<
   "place parentheses around comparison expression to evaluate it first">;
 
+def note_concatenated_string_literal_silence :Note<
+  "place parentheses around string literal to silence warning">;
+
 def warn_addition_in_bitshift : Warning<
   "operator '%0' has lower precedence than '%1'; "
   "'%1' will be evaluated first">, InGroup<ShiftOpParentheses>;
Index: clang/test/Sema/string-concat.c
===================================================================
--- /dev/null
+++ clang/test/Sema/string-concat.c
@@ -2,40 +2,84 @@
 // RUN: %clang_cc1 -x c -fsyntax-only -verify %s
 // RUN: %clang_cc1 -x c++ -fsyntax-only -verify %s
 
-const char *test1[] = {
+const char *missing_comma[] = {
     "basic_filebuf",
     "basic_ios",
     "future",
     "optional",
-    "packaged_task" // expected-warning{{concatenated literal in a string array initialization - possibly missing a comma}}
-    "promise",
-    "shared_future",
-    "shared_lock",
-    "shared_ptr",
-    "thread",
-    "unique_ptr",
-    "unique_lock",
-    "weak_ptr",
+    "packaged_task" // expected-note{{place parentheses around string literal to silence warning}}
+    "promise",      // expected-warning{{concatenated literal in a string array initialization - possibly missing a comma}}
+    "promise",      
+    "shared_future"
 };
 
-const char *test2[] = {"basic_filebuf",
-                       "basic_ios" // expected-warning{{concatenated literal in a string array initialization - possibly missing a comma}}
-                       "future"
+const char *missing_two_commas[] = {"basic_filebuf",
+                       "basic_ios" // expected-note{{place parentheses around string literal to silence warning}}
+                       "future"    // expected-warning{{concatenated literal in a string array initialization - possibly missing a comma}}
                        "optional",
                        "packaged_task"};
 
-const char *test3[] = {"basic_filebuf", "basic_ios",
-                       "future" "optional", // expected-warning{{concatenated literal in a string array initialization - possibly missing a comma}}
-                       "packaged_task", "promise"};
+const char *missing_comma_same_line[] = {"basic_filebuf", "basic_ios",
+                       "future" "optional",         // expected-note{{place parentheses around string literal to silence warning}}
+                       "packaged_task", "promise"}; // expected-warning@-1{{concatenated literal in a string array initialization - possibly missing a comma}}
 
-const char *test4[] = {"basic_filebuf", "basic_ios" // expected-warning{{concatenated literal in a string array initialization - possibly missing a comma}}
-                       "future", "optional",
+const char *missing_comma_different_lines[] = {"basic_filebuf", "basic_ios" // expected-note{{place parentheses around string literal to silence warning}}
+                       "future", "optional",        // expected-warning{{concatenated literal in a string array initialization - possibly missing a comma}}
                        "packaged_task", "promise"};
 
+const char *missing_comma_same_line_all_literals[] = {"basic_filebuf", "future" "optional", "packaged_task"}; // expected-note{{place parentheses around string literal to silence warning}}
+                                                                               // expected-warning@-1{{concatenated literal in a string array initialization - possibly missing a comma}}
+
+char missing_comma_inner[][4] = {
+    "a",
+    "b" // expected-note{{place parentheses around string literal to silence warning}}
+    "c" // expected-warning{{concatenated literal in a string array initialization - possibly missing a comma}}
+};
+
+
+#define ONE(x) x
+#define TWO "foo"
+const char *macro_test[] = { ONE("foo") "bar", 
+                             TWO "bar", 
+                             "foo" TWO // expected-note{{place parentheses around string literal to silence warning}}
+                           };          // expected-warning@-1{{concatenated literal in a string array initialization - possibly missing a comma}}
+
+// Do not warn for macros.
+
 #define BASIC_IOS "basic_ios"
 #define FUTURE "future"
-const char *test5[] = {"basic_filebuf", BASIC_IOS // expected-warning{{concatenated literal in a string array initialization - possibly missing a comma}}
+const char *macro_test2[] = {"basic_filebuf", BASIC_IOS
                         FUTURE, "optional",
                        "packaged_task", "promise"};
 
-const char *test6[] = {"basic_filebuf", "future" "optional", "packaged_task"}; // expected-warning{{concatenated literal in a string array initialization - possibly missing a comma}}
+#define FOO(xx) xx "_normal", \
+                xx "_movable",
+
+const char *macro_test3[] = {"basic_filebuf",
+                       "basic_ios",
+                       FOO("future")
+                       "optional",
+                       "packaged_task"};
+
+#define BAR(name) #name "_normal"
+
+const char *macro_test4[] = {"basic_filebuf",
+                       "basic_ios",
+                       BAR(future),
+                       "optional",
+                       "packaged_task"};
+
+#define SUPPRESS(x) x
+const char *macro_test5[] = { SUPPRESS("foo" "bar"), "baz" };
+
+// Warning can be supressed also by extra parentheses.
+
+const char *extra_parens_to_suppress_warning[] = {
+    "basic_filebuf",
+    "basic_ios",
+    "future",
+    "optional",
+    ("packaged_task"
+    "promise"),
+    "shared_future"
+};
\ No newline at end of file
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to