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

Ryan Molden ryanmolden at gmail.com
Sun Nov 25 16:54:23 PST 2012


On Sun, Nov 25, 2012 at 8:11 AM, Aaron Ballman <aaron at aaronballman.com>wrote:

> 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
>

Something more like this? It isn't ultimately generic, but it does allow
for re-use of the general logic between UTT_HasNoThrowAssign and
UTT_HasNoThrowMoveAssign.

Ryan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20121125/43e03351/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Support-For-MSVC-2012-Type-Traits-For-STL.patch
Type: application/octet-stream
Size: 20026 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20121125/43e03351/attachment.obj>


More information about the cfe-commits mailing list