[PATCH] C++11: Reject string literal to non-const char * conversion

Ismail Pazarbasi ismail.pazarbasi at gmail.com
Tue Nov 5 10:31:58 PST 2013


  Compared to the previous revision, this revision issues a new ExtWarn instead of the existing Warning.

Hi rsmith,

http://llvm-reviews.chandlerc.com/D1965

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D1965?vs=5328&id=5351#toc

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaExprCXX.cpp
  lib/Sema/SemaOverload.cpp
  test/SemaCXX/cxx0x-type-convert-construct.cpp
  test/SemaCXX/deprecated.cpp
  test/SemaCXX/overload-0x.cpp
  unittests/ASTMatchers/ASTMatchersTest.cpp

Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -4485,6 +4485,8 @@
   InGroup<DiagGroup<"gnu-array-member-paren-init">>, DefaultError;
 def warn_deprecated_string_literal_conversion : Warning<
   "conversion from string literal to %0 is deprecated">, InGroup<DeprecatedWritableStr>;
+def ext_warn_deprecated_string_literal_conversion : ExtWarn<
+  "conversion from string literal to %0 is ill-formed in C++11">, InGroup<DeprecatedWritableStr>;
 def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">;
 def err_typecheck_sclass_fscope : Error<
   "illegal storage class on file-scoped variable">;
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -3020,9 +3020,13 @@
                              CK_NoOp, VK, /*BasePath=*/0, CCK).take();
 
     if (SCS.DeprecatedStringLiteralToCharPtr &&
-        !getLangOpts().WritableStrings)
-      Diag(From->getLocStart(), diag::warn_deprecated_string_literal_conversion)
-        << ToType.getNonReferenceType();
+        !getLangOpts().WritableStrings) {
+      Diag(From->getLocStart(),
+           getLangOpts().CPlusPlus11
+               ? diag::ext_warn_deprecated_string_literal_conversion
+               : diag::warn_deprecated_string_literal_conversion)
+          << ToType.getNonReferenceType();
+    }
 
     break;
   }
Index: lib/Sema/SemaOverload.cpp
===================================================================
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -1172,6 +1172,18 @@
   return ICS;
 }
 
+/// Checks whether conversion sequence is string literal to (non-const) char *
+/// in C++11 mode. -fwritable-strings still enables the conversion.
+static inline bool
+isIllFormedStringLiteralConversion(Sema &S,
+                                   const ImplicitConversionSequence &ICS) {
+  return (ICS.isStandard() && ICS.Standard.First == ICK_Array_To_Pointer &&
+          ICS.Standard.Second == ICK_Identity &&
+          ICS.Standard.Third == ICK_Qualification &&
+          ICS.Standard.DeprecatedStringLiteralToCharPtr &&
+          !S.getLangOpts().WritableStrings && S.getLangOpts().CPlusPlus11);
+}
+
 /// TryImplicitConversion - Attempt to perform an implicit conversion
 /// from the given expression (Expr) to the given type (ToType). This
 /// function returns an implicit conversion sequence that can be used
@@ -1513,7 +1525,7 @@
     FromType = S.Context.getArrayDecayedType(FromType);
 
     if (S.IsStringLiteralToNonConstPointerConversion(From, ToType)) {
-      // This conversion is deprecated. (C++ D.4).
+      // This conversion is deprecated in C++03 (D.4)
       SCS.DeprecatedStringLiteralToCharPtr = true;
 
       // For the purpose of ranking in overload resolution
@@ -3259,7 +3271,7 @@
 
   return ImplicitConversionSequence::Indistinguishable;
 }
-  
+
 /// CompareImplicitConversionSequences - Compare two implicit
 /// conversion sequences to determine whether one is better than the
 /// other or if they are indistinguishable (C++ 13.3.3.2).
@@ -3283,9 +3295,14 @@
   //   treated as a user-defined sequence that is indistinguishable
   //   from any other user-defined conversion sequence.
   if (ICS1.getKindRank() < ICS2.getKindRank())
-    return ImplicitConversionSequence::Better;
+    return isIllFormedStringLiteralConversion(S, ICS1)
+               ? ImplicitConversionSequence::Worse
+               : ImplicitConversionSequence::Better;
+
   if (ICS2.getKindRank() < ICS1.getKindRank())
-    return ImplicitConversionSequence::Worse;
+    return isIllFormedStringLiteralConversion(S, ICS2)
+               ? ImplicitConversionSequence::Better
+               : ImplicitConversionSequence::Worse;
 
   // The following checks require both conversion sequences to be of
   // the same kind.
Index: test/SemaCXX/cxx0x-type-convert-construct.cpp
===================================================================
--- test/SemaCXX/cxx0x-type-convert-construct.cpp
+++ test/SemaCXX/cxx0x-type-convert-construct.cpp
@@ -9,9 +9,9 @@
   Ustr = U"a UTF-32 string"; // expected-error {{assigning to 'char32_t *' from incompatible type 'const char32_t [16]'}}
 
   char *Rstr;
-  Rstr = R"foo(a raw string)foo"; // expected-warning{{conversion from string literal to 'char *' is deprecated}}
+  Rstr = R"foo(a raw string)foo"; // expected-warning{{conversion from string literal to 'char *' is ill-formed in C++11}}
   wchar_t *LRstr;
-  LRstr = LR"foo(a wide raw string)foo"; // expected-warning{{conversion from string literal to 'wchar_t *' is deprecated}}
+  LRstr = LR"foo(a wide raw string)foo"; // expected-warning{{conversion from string literal to 'wchar_t *' is ill-formed in C++11}}
   char *u8Rstr;
   u8Rstr = u8R"foo(a UTF-8 raw string)foo"; // expected-error {{assigning to 'char *' from incompatible type 'const char [19]'}}
   char16_t *uRstr;
Index: test/SemaCXX/deprecated.cpp
===================================================================
--- test/SemaCXX/deprecated.cpp
+++ test/SemaCXX/deprecated.cpp
@@ -24,12 +24,15 @@
   register int m asm("rbx"); // no-warning
 
   int k = to_int(n); // no-warning
-
   bool b;
   ++b; // expected-warning {{incrementing expression of type bool is deprecated}}
 
-  // FIXME: This is ill-formed in C++11.
-  char *p = "foo"; // expected-warning {{conversion from string literal to 'char *' is deprecated}}
+  char *p = "foo";
+#if __cplusplus < 201103L
+  // expected-warning at -2 {{conversion from string literal to 'char *' is deprecated}}
+#else
+  // expected-warning at -4 {{conversion from string literal to 'char *' is ill-formed in C++11}}
+#endif
 }
 
 struct S { int n; };
Index: test/SemaCXX/overload-0x.cpp
===================================================================
--- test/SemaCXX/overload-0x.cpp
+++ test/SemaCXX/overload-0x.cpp
@@ -9,3 +9,22 @@
     a = "help"; // expected-error {{no viable overloaded '='}}
   }
 }
+
+namespace PR16314 {
+  void f(char*);
+  int &f(...);
+  void x()
+  {
+    int &r = f("foo");
+  }
+}
+
+namespace warn_if_best {
+  void f(char *);
+  void f(double);
+  void x()
+  {
+    f("foo");  // expected-warning {{conversion from string literal to 'char *' is ill-formed in C++11}}
+  }
+}
+
Index: unittests/ASTMatchers/ASTMatchersTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersTest.cpp
+++ unittests/ASTMatchers/ASTMatchersTest.cpp
@@ -2583,13 +2583,13 @@
 }
 
 TEST(FunctionalCast, MatchesSimpleCase) {
-  std::string foo_class = "class Foo { public: Foo(char*); };";
+  std::string foo_class = "class Foo { public: Foo(const char*); };";
   EXPECT_TRUE(matches(foo_class + "void r() { Foo f = Foo(\"hello world\"); }",
                       functionalCastExpr()));
 }
 
 TEST(FunctionalCast, DoesNotMatchOtherCasts) {
-  std::string FooClass = "class Foo { public: Foo(char*); };";
+  std::string FooClass = "class Foo { public: Foo(const char*); };";
   EXPECT_TRUE(
       notMatches(FooClass + "void r() { Foo f = (Foo) \"hello world\"; }",
                  functionalCastExpr()));
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1965.3.patch
Type: text/x-patch
Size: 7289 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131105/d123109c/attachment.bin>


More information about the cfe-commits mailing list