[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