aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExprCXX.cpp
diff options
context:
space:
mode:
authorJoao Matos <ripzonetriton@gmail.com>2013-03-27 01:34:16 +0000
committerJoao Matos <ripzonetriton@gmail.com>2013-03-27 01:34:16 +0000
commit9ef9875bbe19dc9f73c6c95b803d9a4945168690 (patch)
tree7cc545b344a3e003c4d8c7f5c6bc92e4a0e2655d /lib/Sema/SemaExprCXX.cpp
parent07ffbd74e2188a3a353e9957b9fa0e2f7424e1b4 (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.cpp107
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: