diff options
| author | Alp Toker <alp@nuanti.com> | 2014-01-20 00:24:09 +0000 |
|---|---|---|
| committer | Alp Toker <alp@nuanti.com> | 2014-01-20 00:24:09 +0000 |
| commit | 73287bfe40d4737c27458209d1ef9725b14120bc (patch) | |
| tree | ba8e188ff8145e762b05cef3aebfa1456f45f6b2 /clang/lib/Sema/SemaExprCXX.cpp | |
| parent | b4bca4149184305988d77d41351ef8ec0504c094 (diff) | |
| download | bcm5719-llvm-73287bfe40d4737c27458209d1ef9725b14120bc.tar.gz bcm5719-llvm-73287bfe40d4737c27458209d1ef9725b14120bc.zip | |
MSVC 2013 type trait support
Implement type trait primitives used in the latest edition of the Microsoft
standard C++ library type_traits header.
With this change we can parse much of the Visual Studio 2013 standard headers,
particularly anything that includes <type_traits>.
Fully implemented, available in all language modes:
* __is_constructible()
* __is_nothrow_constructible()
* __is_nothrow_assignable()
Partially implemented, semantic analysis WIP, available as MS extensions:
* __is_destructible()
* __is_nothrow_destructible()
llvm-svn: 199619
Diffstat (limited to 'clang/lib/Sema/SemaExprCXX.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 66 |
1 files changed, 47 insertions, 19 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index f9a3acc93f4..a7723d4b263 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -3156,6 +3156,8 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, case UTT_IsPolymorphic: case UTT_IsAbstract: case UTT_IsInterfaceClass: + case UTT_IsDestructible: + case UTT_IsNothrowDestructible: // Fall-through // These traits require a complete type. @@ -3219,7 +3221,7 @@ static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op, const FunctionProtoType *CPT = Operator->getType()->getAs<FunctionProtoType>(); CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); - if (!CPT || !CPT->isNothrow(Self.Context)) + if (!CPT || !CPT->isNothrow(C)) return false; } } @@ -3421,8 +3423,12 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, return RD->hasTrivialCopyAssignment() && !RD->hasNonTrivialCopyAssignment(); return false; + case UTT_IsDestructible: + case UTT_IsNothrowDestructible: + // FIXME: Implement UTT_IsDestructible and UTT_IsNothrowDestructible. + // For now, let's fall through. case UTT_HasTrivialDestructor: - // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html // If __is_pod (type) is true or type is a reference type // then the trait is true, else if type is a cv class or union // type (or array thereof) with a trivial destructor @@ -3505,7 +3511,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); if (!CPT) return false; - // FIXME: check whether evaluating default arguments can throw. + // TODO: check whether evaluating default arguments can throw. // For now, we'll be conservative and assume that they can throw. if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1) return false; @@ -3605,6 +3611,8 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, Args[1]->getType(), RParenLoc); switch (Kind) { + case clang::TT_IsConstructible: + case clang::TT_IsNothrowConstructible: case clang::TT_IsTriviallyConstructible: { // C++11 [meta.unary.prop]: // is_trivially_constructible is defined as: @@ -3663,20 +3671,31 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, InitializationSequence Init(S, To, InitKind, ArgExprs); if (Init.Failed()) return false; - + ExprResult Result = Init.Perform(S, To, InitKind, ArgExprs); if (Result.isInvalid() || SFINAE.hasErrorOccurred()) return false; - // Under Objective-C ARC, if the destination has non-trivial Objective-C - // lifetime, this is a non-trivial construction. - if (S.getLangOpts().ObjCAutoRefCount && - hasNontrivialObjCLifetime(Args[0]->getType().getNonReferenceType())) - return false; + if (Kind == clang::TT_IsConstructible) + return true; + + if (Kind == clang::TT_IsNothrowConstructible) + return S.canThrow(Result.get()) == CT_Cannot; - // The initialization succeeded; now make sure there are no non-trivial - // calls. - return !Result.get()->hasNonTrivialCall(S.Context); + if (Kind == clang::TT_IsTriviallyConstructible) { + // Under Objective-C ARC, if the destination has non-trivial Objective-C + // lifetime, this is a non-trivial construction. + if (S.getLangOpts().ObjCAutoRefCount && + hasNontrivialObjCLifetime(Args[0]->getType().getNonReferenceType())) + return false; + + // The initialization succeeded; now make sure there are no non-trivial + // calls. + return !Result.get()->hasNonTrivialCall(S.Context); + } + + llvm_unreachable("unhandled type trait"); + return false; } default: llvm_unreachable("not a TT"); } @@ -3831,7 +3850,8 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT, ExprResult Result = Init.Perform(Self, To, Kind, FromPtr); return !Result.isInvalid() && !SFINAE.hasErrorOccurred(); } - + + case BTT_IsNothrowAssignable: case BTT_IsTriviallyAssignable: { // C++11 [meta.unary.prop]p3: // is_trivially_assignable is defined as: @@ -3877,13 +3897,21 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT, if (Result.isInvalid() || SFINAE.hasErrorOccurred()) return false; - // Under Objective-C ARC, if the destination has non-trivial Objective-C - // lifetime, this is a non-trivial assignment. - if (Self.getLangOpts().ObjCAutoRefCount && - hasNontrivialObjCLifetime(LhsT.getNonReferenceType())) - return false; + if (BTT == BTT_IsNothrowAssignable) + return Self.canThrow(Result.get()) == CT_Cannot; - return !Result.get()->hasNonTrivialCall(Self.Context); + if (BTT == BTT_IsTriviallyAssignable) { + // Under Objective-C ARC, if the destination has non-trivial Objective-C + // lifetime, this is a non-trivial assignment. + if (Self.getLangOpts().ObjCAutoRefCount && + hasNontrivialObjCLifetime(LhsT.getNonReferenceType())) + return false; + + return !Result.get()->hasNonTrivialCall(Self.Context); + } + + llvm_unreachable("unhandled type trait"); + return false; } default: llvm_unreachable("not a BTT"); } |

