diff options
author | Joao Matos <ripzonetriton@gmail.com> | 2013-03-27 01:34:16 +0000 |
---|---|---|
committer | Joao Matos <ripzonetriton@gmail.com> | 2013-03-27 01:34:16 +0000 |
commit | 9ef9875bbe19dc9f73c6c95b803d9a4945168690 (patch) | |
tree | 7cc545b344a3e003c4d8c7f5c6bc92e4a0e2655d /lib/Sema/SemaExprCXX.cpp | |
parent | 07ffbd74e2188a3a353e9957b9fa0e2f7424e1b4 (diff) |
Implement compiler intrinsics needed for compatibility with MSVC 2012 <type_traits>.
Patch by me and Ryan Molden.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178111 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExprCXX.cpp')
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 107 |
1 files changed, 76 insertions, 31 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 1724624fe3..b586fd70b0 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2975,10 +2975,13 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, // 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: @@ -2997,6 +3000,42 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, llvm_unreachable("Type trait not handled by switch"); } +static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op, + Sema &Self, SourceLocation KeyLoc, ASTContext &C, + bool (CXXRecordDecl::*HasTrivial)() const, + bool (CXXRecordDecl::*HasNonTrivial)() const, + bool (CXXMethodDecl::*IsDesiredOp)() const) +{ + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if ((RD->*HasTrivial)() && !(RD->*HasNonTrivial)()) + return true; + + DeclarationName Name = C.DeclarationNames.getCXXOperatorName(Op); + DeclarationNameInfo NameInfo(Name, KeyLoc); + LookupResult Res(Self, NameInfo, Sema::LookupOrdinaryName); + if (Self.LookupQualifiedName(Res, RD)) { + bool FoundOperator = false; + 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->*IsDesiredOp)()) { + FoundOperator = true; + const FunctionProtoType *CPT = + Operator->getType()->getAs<FunctionProtoType>(); + CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); + if (!CPT || !CPT->isNothrow(Self.Context)) + return false; + } + } + return FoundOperator; + } + return false; +} + static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, SourceLocation KeyLoc, QualType T) { assert(!T->isDependentType() && "Cannot evaluate traits of dependent type"); @@ -3133,6 +3172,15 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, return RD->hasTrivialDefaultConstructor() && !RD->hasNonTrivialDefaultConstructor(); 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::is_trivially_move_constructible (20.9.4.3). + if (T.isPODType(Self.Context)) + return true; + if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) + return RD->hasTrivialMoveConstructor() && !RD->hasNonTrivialMoveConstructor(); + 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 @@ -3145,6 +3193,15 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, return RD->hasTrivialCopyConstructor() && !RD->hasNonTrivialCopyConstructor(); 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 (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) + return RD->hasTrivialMoveAssignment() && !RD->hasNonTrivialMoveAssignment(); + 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 @@ -3198,38 +3255,26 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, if (T->isReferenceType()) return false; if (T.isPODType(Self.Context) || T->isObjCLifetimeType()) - return true; - if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) { - if (RD->hasTrivialCopyAssignment() && !RD->hasNonTrivialCopyAssignment()) - return true; + return true; - bool FoundAssign = false; - DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal); - LookupResult Res(Self, DeclarationNameInfo(Name, KeyLoc), - 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->isCopyAssignmentOperator()) { - 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; - } + if (const RecordType *RT = T->getAs<RecordType>()) + return HasNoThrowOperator(RT, OO_Equal, Self, KeyLoc, C, + &CXXRecordDecl::hasTrivialCopyAssignment, + &CXXRecordDecl::hasNonTrivialCopyAssignment, + &CXXMethodDecl::isCopyAssignmentOperator); + 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>()) + return HasNoThrowOperator(RT, OO_Equal, Self, KeyLoc, C, + &CXXRecordDecl::hasTrivialMoveAssignment, + &CXXRecordDecl::hasNonTrivialMoveAssignment, + &CXXMethodDecl::isMoveAssignmentOperator); return false; case UTT_HasNothrowCopy: // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: |