Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -4485,6 +4485,8 @@ InGroup>, DefaultError; def warn_deprecated_string_literal_conversion : Warning< "conversion from string literal to %0 is deprecated">, InGroup; +def ext_warn_deprecated_string_literal_conversion : ExtWarn< + "conversion from string literal to %0 is ill-formed in C++11">, InGroup; 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@-2 {{conversion from string literal to 'char *' is deprecated}} +#else + // expected-warning@-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()));