diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1161,10 +1161,7 @@ * ``__is_sealed`` (Microsoft): Synonym for ``__is_final``. * ``__is_signed`` (C++, Embarcadero): - Note that this currently returns true for enumeration types if the underlying - type is signed, and returns false for floating-point types, in violation of - the requirements for ``std::is_signed``. This behavior is likely to change in - a future version of Clang. + Returns false for enumeration types, and returns true for floating-point types. * ``__is_standard_layout`` (C++, GNU, Microsoft, Embarcadero) * ``__is_trivial`` (C++, GNU, Microsoft, Embarcadero) * ``__is_trivially_assignable`` (C++, GNU, Microsoft) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -4605,7 +4605,9 @@ return RD->hasAttr(); return false; case UTT_IsSigned: - return T->isSignedIntegerType(); + // Enum types should always return false. + // Floating points should always return true. + return !T->isEnumeralType() && (T->isFloatingType() || T->isSignedIntegerType()); case UTT_IsUnsigned: return T->isUnsignedIntegerType(); diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -12,6 +12,7 @@ // PODs enum Enum { EV }; +enum SignedEnum : signed int { }; struct POD { Enum e; int i; float f; NonPOD* p; }; struct Empty {}; struct IncompleteStruct; @@ -56,14 +57,14 @@ struct HasNoInheritedCons : HasCons {}; struct HasCopyAssign { HasCopyAssign operator =(const HasCopyAssign&); }; struct HasMoveAssign { HasMoveAssign operator =(const HasMoveAssign&&); }; -struct HasNoThrowMoveAssign { +struct HasNoThrowMoveAssign { HasNoThrowMoveAssign& operator=( const HasNoThrowMoveAssign&&) throw(); }; -struct HasNoExceptNoThrowMoveAssign { +struct HasNoExceptNoThrowMoveAssign { HasNoExceptNoThrowMoveAssign& operator=( - const HasNoExceptNoThrowMoveAssign&&) noexcept; + const HasNoExceptNoThrowMoveAssign&&) noexcept; }; -struct HasThrowMoveAssign { +struct HasThrowMoveAssign { HasThrowMoveAssign& operator=(const HasThrowMoveAssign&&) #if __cplusplus <= 201402L throw(POD); @@ -73,7 +74,7 @@ }; -struct HasNoExceptFalseMoveAssign { +struct HasNoExceptFalseMoveAssign { HasNoExceptFalseMoveAssign& operator=( const HasNoExceptFalseMoveAssign&&) noexcept(false); }; struct HasMoveCtor { HasMoveCtor(const HasMoveCtor&&); }; @@ -82,17 +83,17 @@ struct HasStaticMemberMoveCtor { static HasMoveCtor member; }; struct HasStaticMemberMoveAssign { static HasMoveAssign member; }; struct HasMemberThrowMoveAssign { HasThrowMoveAssign member; }; -struct HasMemberNoExceptFalseMoveAssign { +struct HasMemberNoExceptFalseMoveAssign { HasNoExceptFalseMoveAssign member; }; struct HasMemberNoThrowMoveAssign { HasNoThrowMoveAssign member; }; -struct HasMemberNoExceptNoThrowMoveAssign { +struct HasMemberNoExceptNoThrowMoveAssign { HasNoExceptNoThrowMoveAssign member; }; -struct HasDefaultTrivialCopyAssign { +struct HasDefaultTrivialCopyAssign { HasDefaultTrivialCopyAssign &operator=( - const HasDefaultTrivialCopyAssign&) = default; + const HasDefaultTrivialCopyAssign&) = default; }; -struct TrivialMoveButNotCopy { +struct TrivialMoveButNotCopy { TrivialMoveButNotCopy &operator=(TrivialMoveButNotCopy&&) = default; TrivialMoveButNotCopy &operator=(const TrivialMoveButNotCopy&); }; @@ -361,7 +362,7 @@ struct FinalClass final { }; -template +template struct PotentiallyFinal { }; template @@ -1419,12 +1420,12 @@ int t04[T(__is_signed(short))]; int t05[T(__is_signed(signed char))]; int t06[T(__is_signed(wchar_t))]; + int t07[T(__is_signed(float))]; + int t08[T(__is_signed(double))]; + int t09[T(__is_signed(long double))]; - int t10[F(__is_signed(bool))]; - int t11[F(__is_signed(cvoid))]; - int t12[F(__is_signed(float))]; - int t13[F(__is_signed(double))]; - int t14[F(__is_signed(long double))]; + int t13[F(__is_signed(bool))]; + int t14[F(__is_signed(cvoid))]; int t15[F(__is_signed(unsigned char))]; int t16[F(__is_signed(unsigned int))]; int t17[F(__is_signed(unsigned long long))]; @@ -1434,9 +1435,10 @@ int t21[F(__is_signed(ClassType))]; int t22[F(__is_signed(Derives))]; int t23[F(__is_signed(Enum))]; - int t24[F(__is_signed(IntArNB))]; - int t25[F(__is_signed(Union))]; - int t26[F(__is_signed(UnionAr))]; + int t24[F(__is_signed(SignedEnum))]; + int t25[F(__is_signed(IntArNB))]; + int t26[F(__is_signed(Union))]; + int t27[F(__is_signed(UnionAr))]; } void is_unsigned() @@ -2005,7 +2007,7 @@ }; template -struct X0 { +struct X0 { template X0(const X0&); }; @@ -2766,7 +2768,7 @@ char b[7]; }; -static_assert(!has_unique_object_representations::value, +static_assert(!has_unique_object_representations::value, "non trivial"); // Can be unique on Itanium, since the is child class' data is 'folded' into the // parent's tail padding.