[cfe-commits] [Patch] Implement compiler intrinsics for MSVC 2012 type_traits

Aaron Ballman aaron at aaronballman.com
Sun Nov 25 08:11:20 PST 2012


Thanks for working on this!  Comments about the patch below:

On Fri, Nov 23, 2012 at 2:40 PM, Ryan Molden <ryanmolden at gmail.com> wrote:
> Index: lib/Sema/SemaExprCXX.cpp
> ===================================================================
> --- lib/Sema/SemaExprCXX.cpp (revision 168503)
> +++ lib/Sema/SemaExprCXX.cpp (working copy)
> @@ -2920,10 +2920,13 @@
>      // type due to the overarching C++0x type predicates being implemented
>      // requiring the complete type.
>    case UTT_HasNothrowAssign:
> +  case UTT_HasNothrowMoveAssign:
>    case UTT_HasNothrowConstructor:
>    case UTT_HasNothrowCopy:
>    case UTT_HasTrivialAssign:
> +  case UTT_HasTrivialMoveAssign:
>    case UTT_HasTrivialDefaultConstructor:
> +  case UTT_HasTrivialMoveConstructor:
>    case UTT_HasTrivialCopy:
>    case UTT_HasTrivialDestructor:
>    case UTT_HasVirtualDestructor:
> @@ -3071,6 +3074,15 @@
>            C.getBaseElementType(T)->getAs<RecordType>())
>        return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDefaultConstructor();
>      return false;
> +  case UTT_HasTrivialMoveConstructor:
> +    //  This trait is implemented by MSVC 2012 and needed to parse the
> +    //  standard library headers. Specifically this is used as the logic
> +    //  behind std::has_trivial_move_constructor (20.9.4.3).
> +    if (T.isPODType(Self.Context))
> +      return true;
> +    if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>())
> +      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialMoveConstructor();
> +    return false;
>    case UTT_HasTrivialCopy:
>      // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
>      //   If __is_pod (type) is true or type is a reference type then
> @@ -3082,6 +3094,15 @@
>      if (const RecordType *RT = T->getAs<RecordType>())
>        return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyConstructor();
>      return false;
> +  case UTT_HasTrivialMoveAssign:
> +    //  This trait is implemented by MSVC 2012 and needed to parse the
> +    //  standard library headers. Specifically it is used as the logic
> +    //  behind std::is_trivially_move_assignable (20.9.4.3)
> +    if (T.isPODType(Self.Context))
> +      return true;
> +    if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>())
> +      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialMoveAssignment();
> +    return false;
>    case UTT_HasTrivialAssign:
>      // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
>      //   If type is const qualified or is a reference type then the
> @@ -3169,6 +3190,46 @@
>        return FoundAssign;
>      }
>      return false;
> +  case UTT_HasNothrowMoveAssign:
> +    //  This trait is implemented by MSVC 2012 and needed to parse the
> +    //  standard library headers. Specifically this is used as the logic
> +    //  behind std::is_nothrow_move_assignable (20.9.4.3).
> +    if (T.isPODType(Self.Context))
> +      return true;
> +
> +    if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) {
> +      CXXRecordDecl* RD = cast<CXXRecordDecl>(RT->getDecl());
> +      if (RD->hasTrivialMoveAssignment())
> +        return true;
> +
> +      bool FoundAssign = false;
> +      DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal);
> +      DeclarationNameInfo NameInfo(Name, KeyLoc);
> +      LookupResult Res(Self, NameInfo, Sema::LookupOrdinaryName);
> +      if (Self.LookupQualifiedName(Res, RD)) {
> +        Res.suppressDiagnostics();
> +        for (LookupResult::iterator Op = Res.begin(), OpEnd = Res.end();
> +          Op != OpEnd; ++Op) {
> +          if (isa<FunctionTemplateDecl>(*Op))
> +            continue;
> +
> +          CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op);
> +          if (Operator->isMoveAssignmentOperator()) {
> +            FoundAssign = true;
> +            const FunctionProtoType *CPT =
> +              Operator->getType()->getAs<FunctionProtoType>();
> +            CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
> +            if (!CPT)
> +                return false;
> +            if (!CPT->isNothrow(Self.Context))
> +                return false;
> +          }
> +        }
> +      }
> +
> +      return FoundAssign;

Very minor nit: you can move the FoundAssign logic into the
LookupQualifiedName if block.

Given the similarity between the other HasNothrow case statements, I
wonder if there's a way we can consolidate this logic.  For instance,
UTT_HasNothrowAssign looks to be identical with the exception of
calling isCopyAssignmentOperator or isMoveAssignmentOperator.

Otherwise, the patch LGTM.

Thanks!

~Aaron



More information about the cfe-commits mailing list