We decided to limit this patch to overload resolution, addressing only PR16314.
When comparing candidate functions, this conversion is considered worse than other conversions to prevent the candidate function to be the best. If this conversion happens in the best viable function, we will accept it with a warning (current behavior). Hi rsmith, http://llvm-reviews.chandlerc.com/D1965 CHANGE SINCE LAST DIFF http://llvm-reviews.chandlerc.com/D1965?vs=5010&id=5328#toc Files: lib/Sema/SemaOverload.cpp test/SemaCXX/overload-0x.cpp unittests/ASTMatchers/ASTMatchersTest.cpp 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/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 deprecated}} + } +} + 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()));
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/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 deprecated}} + } +} + 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()));
_______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits