r199513 - Fix string-literal to char* conversion in overload resolution for C++11
Chandler Carruth
chandlerc at google.com
Fri Jan 24 00:55:01 PST 2014
Can we revert until a fix is ready? 7 days with msan failures is too many.
On Thu, Jan 23, 2014 at 8:08 PM, Richard Smith <metafoo at gmail.com> wrote:
> Looks like the msan build bot has found a bug here:
>
>
> http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap/builds/1844/steps/annotate/logs/stdio
>
> It appears that some path through the code doesn't initialize Deprecated
> StringLiteralToCharPtr.
>
> On Fri Jan 17 2014 at 1:15:20 PM, Ismail Pazarbasi <
> ismail.pazarbasi at gmail.com> wrote:
>
> Author: ismailp
> Date: Fri Jan 17 15:08:52 2014
> New Revision: 199513
>
> URL: http://llvm.org/viewvc/llvm-project?rev=199513&view=rev
> Log:
> Fix string-literal to char* conversion in overload resolution for C++11
>
> String literal to char* conversion is deprecated in C++03, and is removed
> in
> C++11. We still accept this conversion in C++11 mode as an extension, if
> we find
> it in the best viable function.
>
>
> Modified:
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> cfe/trunk/lib/Sema/SemaExprCXX.cpp
> cfe/trunk/lib/Sema/SemaOverload.cpp
> cfe/trunk/test/SemaCXX/cxx0x-type-convert-construct.cpp
> cfe/trunk/test/SemaCXX/deprecated.cpp
> cfe/trunk/test/SemaCXX/overload-0x.cpp
> cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/
> DiagnosticSemaKinds.td?rev=199513&r1=199512&r2=199513&view=diff
> ============================================================
> ==================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jan 17
> 15:08:52 2014
> @@ -4534,6 +4534,9 @@ def ext_array_init_parens : ExtWarn<
> def warn_deprecated_string_literal_conversion : Warning<
> "conversion from string literal to %0 is deprecated">,
> InGroup<CXX11CompatDeprecatedWritableStr>;
> +def ext_deprecated_string_literal_conversion : ExtWarn<
> + "ISO C++11 does not allow conversion from string literal to %0">,
> + InGroup<CXX11CompatDeprecatedWritableStr>, SFINAEFailure;
> def warn_deprecated_string_literal_conversion_c : Warning<
> "dummy warning to enable -fconst-strings">,
> InGroup<DeprecatedWritableStr>, DefaultIgnore;
> def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">;
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaE
> xprCXX.cpp?rev=199513&r1=199512&r2=199513&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Jan 17 15:08:52 2014
> @@ -3058,9 +3058,12 @@ Sema::PerformImplicitConversion(Expr *Fr
> CK_NoOp, VK, /*BasePath=*/0, CCK).take();
>
> if (SCS.DeprecatedStringLiteralToCharPtr &&
> - !getLangOpts().WritableStrings)
> - Diag(From->getLocStart(), diag::warn_deprecated_string_l
> iteral_conversion)
> + !getLangOpts().WritableStrings) {
> + Diag(From->getLocStart(), getLangOpts().CPlusPlus11
> + ? diag::ext_deprecated_string_literal_conversion
> + : diag::warn_deprecated_string_literal_conversion)
> << ToType.getNonReferenceType();
> + }
>
> break;
> }
>
> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaO
> verload.cpp?rev=199513&r1=199512&r2=199513&view=diff
> ============================================================
> ==================
> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Jan 17 15:08:52 2014
> @@ -1443,7 +1443,6 @@ static bool IsStandardConversion(Sema &S
>
> // Standard conversions (C++ [conv])
> SCS.setAsIdentityConversion();
> - SCS.DeprecatedStringLiteralToCharPtr = false;
> SCS.IncompatibleObjC = false;
> SCS.setFromType(FromType);
> SCS.CopyConstructor = 0;
> @@ -1542,7 +1541,7 @@ static bool IsStandardConversion(Sema &S
> 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,18 +3258,15 @@ Sema::DiagnoseMultipleUserDefinedConvers
> IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined,
> CandidateSet, false, false);
> if (OvResult == OR_Ambiguous)
> - Diag(From->getLocStart(),
> - diag::err_typecheck_ambiguous_condition)
> - << From->getType() << ToType << From->getSourceRange();
> + Diag(From->getLocStart(), diag::err_typecheck_ambiguous_condition)
> + << From->getType() << ToType << From->getSourceRange();
> else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty()) {
> if (!RequireCompleteType(From->getLocStart(), ToType,
> - diag::err_typecheck_nonviable_condition_
> incomplete,
> + diag::err_typecheck_nonviable_
> condition_incomplete,
> From->getType(), From->getSourceRange()))
> - Diag(From->getLocStart(),
> - diag::err_typecheck_nonviable_condition)
> - << From->getType() << From->getSourceRange() << ToType;
> - }
> - else
> + Diag(From->getLocStart(), diag::err_typecheck_nonviable_condition)
> + << From->getType() << From->getSourceRange() << ToType;
> + } else
> return false;
> CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From);
> return true;
> @@ -3280,37 +3276,43 @@ Sema::DiagnoseMultipleUserDefinedConvers
> /// of two user-defined conversion sequences to determine whether any
> ordering
> /// is possible.
> static ImplicitConversionSequence::CompareKind
> -compareConversionFunctions(Sema &S,
> - FunctionDecl *Function1,
> +compareConversionFunctions(Sema &S, FunctionDecl *Function1,
> FunctionDecl *Function2) {
> if (!S.getLangOpts().ObjC1 || !S.getLangOpts().CPlusPlus11)
> return ImplicitConversionSequence::Indistinguishable;
> -
> +
> // Objective-C++:
> // If both conversion functions are implicitly-declared conversions
> from
> - // a lambda closure type to a function pointer and a block pointer,
> + // a lambda closure type to a function pointer and a block pointer,
> // respectively, always prefer the conversion to a function pointer,
> // because the function pointer is more lightweight and is more likely
> // to keep code working.
> CXXConversionDecl *Conv1 = dyn_cast<CXXConversionDecl>(Function1);
> if (!Conv1)
> return ImplicitConversionSequence::Indistinguishable;
> -
> +
> CXXConversionDecl *Conv2 = dyn_cast<CXXConversionDecl>(Function2);
> if (!Conv2)
> return ImplicitConversionSequence::Indistinguishable;
> -
> +
> if (Conv1->getParent()->isLambda() && Conv2->getParent()->isLambda()) {
> bool Block1 = Conv1->getConversionType()->isBlockPointerType();
> bool Block2 = Conv2->getConversionType()->isBlockPointerType();
> if (Block1 != Block2)
> - return Block1? ImplicitConversionSequence::Worse
> - : ImplicitConversionSequence::Better;
> + return Block1 ? ImplicitConversionSequence::Worse
> + : ImplicitConversionSequence::Better;
> }
>
> return ImplicitConversionSequence::Indistinguishable;
> }
> -
> +
> +static bool hasDeprecatedStringLiteralToCharPtrConversion(
> + const ImplicitConversionSequence &ICS) {
> + return (ICS.isStandard() && ICS.Standard.DeprecatedStringLiteralToCharPtr)
> ||
> + (ICS.isUserDefined() &&
> + ICS.UserDefined.Before.DeprecatedStringLiteralToCharPtr);
> +}
> +
> /// 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).
> @@ -3333,6 +3335,32 @@ CompareImplicitConversionSequences(Sema
> // described in 13.3.3.2, the ambiguous conversion sequence is
> // treated as a user-defined sequence that is indistinguishable
> // from any other user-defined conversion sequence.
> +
> + // String literal to 'char *' conversion has been deprecated in C++03.
> It has
> + // been removed from C++11. We still accept this conversion, if it
> happens at
> + // the best viable function. Otherwise, this conversion is considered
> worse
> + // than ellipsis conversion. Consider this as an extension; this is not
> in the
> + // standard. For example:
> + //
> + // int &f(...); // #1
> + // void f(char*); // #2
> + // void g() { int &r = f("foo"); }
> + //
> + // In C++03, we pick #2 as the best viable function.
> + // In C++11, we pick #1 as the best viable function, because ellipsis
> + // conversion is better than string-literal to char* conversion (since
> there
> + // is no such conversion in C++11). If there was no #1 at all or #1
> couldn't
> + // convert arguments, #2 would be the best viable function in C++11.
> + // If the best viable function has this conversion, a warning will be
> issued
> + // in C++03, or an ExtWarn (+SFINAE failure) will be issued in C++11.
> +
> + if (S.getLangOpts().CPlusPlus11 && !S.getLangOpts().WritableStrings &&
> + hasDeprecatedStringLiteralToCharPtrConversion(ICS1) !=
> + hasDeprecatedStringLiteralToCharPtrConversion(ICS2))
> + return hasDeprecatedStringLiteralToCharPtrConversion(ICS1)
> + ? ImplicitConversionSequence::Worse
> + : ImplicitConversionSequence::Better;
> +
> if (ICS1.getKindRank() < ICS2.getKindRank())
> return ImplicitConversionSequence::Better;
> if (ICS2.getKindRank() < ICS1.getKindRank())
> @@ -4244,6 +4272,7 @@ TryReferenceInit(Sema &S, Expr *Init, Qu
> ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier =
> false;
> ICS.Standard.ObjCLifetimeConversionBinding =
> ObjCLifetimeConversion;
> ICS.Standard.CopyConstructor = 0;
> + ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
>
> // Nothing more to do: the inaccessibility/ambiguity check for
> // derived-to-base conversions is suppressed when we're
> @@ -4318,6 +4347,7 @@ TryReferenceInit(Sema &S, Expr *Init, Qu
> ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false;
> ICS.Standard.ObjCLifetimeConversionBinding = ObjCLifetimeConversion;
> ICS.Standard.CopyConstructor = 0;
> + ICS.Standard.DeprecatedStringLiteralToCharPtr = false;
> return ICS;
> }
>
>
> Modified: cfe/trunk/test/SemaCXX/cxx0x-type-convert-construct.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/
> cxx0x-type-convert-construct.cpp?rev=199513&r1=199512&r2=199513&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/SemaCXX/cxx0x-type-convert-construct.cpp (original)
> +++ cfe/trunk/test/SemaCXX/cxx0x-type-convert-construct.cpp Fri Jan 17
> 15:08:52 2014
> @@ -9,9 +9,9 @@ void f() {
> 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{{ISO C++11 does not
> allow conversion from string literal to 'char *'}}
> 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{{ISO C++11
> does not allow conversion from string literal to 'wchar_t *'}}
> 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;
>
> Modified: cfe/trunk/test/SemaCXX/deprecated.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/
> deprecated.cpp?rev=199513&r1=199512&r2=199513&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/SemaCXX/deprecated.cpp (original)
> +++ cfe/trunk/test/SemaCXX/deprecated.cpp Fri Jan 17 15:08:52 2014
> @@ -24,12 +24,15 @@ void stuff() {
> 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 {{ISO C++11 does not allow conversion from
> string literal to 'char *'}}
> +#endif
> }
>
> struct S { int n; };
>
> Modified: cfe/trunk/test/SemaCXX/overload-0x.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/
> overload-0x.cpp?rev=199513&r1=199512&r2=199513&view=diff
> ============================================================
> ==================
> --- cfe/trunk/test/SemaCXX/overload-0x.cpp (original)
> +++ cfe/trunk/test/SemaCXX/overload-0x.cpp Fri Jan 17 15:08:52 2014
> @@ -1,7 +1,11 @@
> -// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
> +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
> +// RUN: %clang_cc1 -fsyntax-only -verify %s
>
> namespace test0 {
> - struct A { // expected-note {{candidate function (the implicit copy
> assignment operator) not viable: 'this' argument has type 'const test0::A',
> but method is not marked const}} expected-note {{candidate function (the
> implicit move assignment operator) not viable: 'this' argument has type
> 'const test0::A', but method is not marked const}}
> + struct A { // expected-note {{candidate function (the implicit copy
> assignment operator) not viable: 'this' argument has type 'const test0::A',
> but method is not marked const}}
> +#if __cplusplus >= 201103L
> + // expected-note at -2 {{candidate function (the implicit move assignment
> operator) not viable: 'this' argument has type 'const test0::A', but method
> is not marked const}}
> +#endif
> A &operator=(void*); // expected-note {{candidate function not
> viable: 'this' argument has type 'const test0::A', but method is not marked
> const}}
> };
>
> @@ -9,3 +13,79 @@ namespace test0 {
> a = "help"; // expected-error {{no viable overloaded '='}}
> }
> }
> +
> +namespace PR16314 {
> + void f(char*);
> + int &f(...);
> + void x()
> + {
> + int &n = f("foo");
> +#if __cplusplus < 201103L
> + // expected-warning at -2 {{conversion from string literal to 'char *'
> is deprecated}}
> + // expected-error at -3 {{non-const lvalue reference to type 'int'
> cannot bind to a temporary of type 'void'}}
> +#endif
> + }
> +}
> +
> +namespace warn_if_best {
> + int f(char *);
> + void f(double);
> + void x()
> + {
> + int n = f("foo");
> +#if __cplusplus < 201103L
> + // expected-warning at -2 {{conversion from string literal to 'char *'
> is deprecated}}
> +#else
> + // expected-warning at -4 {{ISO C++11 does not allow conversion from
> string literal to 'char *'}}
> +#endif
> + }
> +}
> +
> +namespace userdefined_vs_illformed {
> + struct X { X(const char *); };
> +
> + void *f(char *p); // best for C++03
> + double f(X x); // best for C++11
> + void g()
> + {
> + double d = f("foo");
> +#if __cplusplus < 201103L
> + // expected-warning at -2 {{conversion from string literal to 'char *'
> is deprecated}}
> + // expected-error at -3 {{cannot initialize a variable of type 'double'
> with an rvalue of type 'void *'}}
> +#endif
> + }
> +}
> +
> +namespace sfinae_test {
> + int f(int, char*);
> +
> + template<int T>
> + struct S { typedef int type; };
> +
> + template<>
> + struct S<sizeof(int)> { typedef void type; };
> +
> + // C++11: SFINAE failure
> + // C++03: ok
> + template<typename T> int cxx11_ignored(T, typename S<sizeof(f(T(),
> "foo"))>::type *);
> +#if __cplusplus < 201103L
> + // expected-warning at -2 {{conversion from string literal to 'char *' is
> deprecated}}
> +#else
> + // expected-note at -4 {{candidate template ignored: substitution
> failure}}
> +#endif
> +
> + // C++11: better than latter
> + // C++03: worse than latter
> + template<typename T> void g(T, ...);
> + template<typename T> int g(T, typename S<sizeof(f(T(), "foo"))>::type
> *);
> +#if __cplusplus < 201103L
> + // expected-warning at -2 {{conversion from string literal to 'char *' is
> deprecated}}
> +#endif
> +
> + int a = cxx11_ignored(0, 0);
> + int b = g(0, 0);
> +#if __cplusplus >= 201103L
> + // expected-error at -3 {{no matching function for call to
> 'cxx11_ignored'}}
> + // expected-error at -3 {{cannot initialize a variable of type 'int' with
> an rvalue of type 'void'}}
> +#endif
> +}
>
> Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTM
> atchers/ASTMatchersTest.cpp?rev=199513&r1=199512&r2=199513&view=diff
> ============================================================
> ==================
> --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
> +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Fri Jan 17
> 15:08:52 2014
> @@ -2608,13 +2608,13 @@ TEST(ReinterpretCast, DoesNotMatchOtherC
> }
>
> 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 at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140124/d72794c3/attachment.html>
More information about the cfe-commits
mailing list