From: Zoe Carver Date: Mon, 23 Sep 2019 15:41:20 +0000 (+0000) Subject: Fix __is_signed builtin X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2e9f804150df090d8a7155ac7aaec29ac8e94aa8;p=clang Fix __is_signed builtin Summary: This patch fixes the __is_signed builtin type trait to work with floating point types and enums. Now, the builtin will return true if it is passed a floating point type and false for an enum type. Reviewers: EricWF, rsmith, erichkeane, craig.topper, efriedma Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D67897 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@372621 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst index 23c8778113..903d450059 100644 --- a/docs/LanguageExtensions.rst +++ b/docs/LanguageExtensions.rst @@ -1161,10 +1161,7 @@ The following type trait primitives are supported by Clang. Those traits marked * ``__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. Note, before Clang 10, returned true for enumeration types if the underlying type was signed, and returned false 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/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 1018035192..a9efbbc9e5 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -4605,7 +4605,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, 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/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index 9bc238e678..e190844533 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -12,6 +12,7 @@ typedef NonPOD NonPODArMB[10][2]; // 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 HasInheritedCons : HasDefaultCons { using HasDefaultCons::HasDefaultCons; 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 HasThrowMoveAssign { }; -struct HasNoExceptFalseMoveAssign { +struct HasNoExceptFalseMoveAssign { HasNoExceptFalseMoveAssign& operator=( const HasNoExceptFalseMoveAssign&&) noexcept(false); }; struct HasMoveCtor { HasMoveCtor(const HasMoveCtor&&); }; @@ -82,17 +83,17 @@ struct HasMemberMoveAssign { HasMoveAssign member; }; 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 @@ void is_enum() struct FinalClass final { }; -template +template struct PotentiallyFinal { }; template @@ -1419,12 +1420,12 @@ void is_signed() 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 @@ void is_signed() 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 @@ class PrivateCopy { }; template -struct X0 { +struct X0 { template X0(const X0&); }; @@ -2766,7 +2768,7 @@ struct CanBeUniqueIfNoPadding : NotUniqueBecauseTailPadding { 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.