diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 99 |
1 files changed, 76 insertions, 23 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index d87752081b..85a65a43a3 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2628,34 +2628,87 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, QualType T, } } +/// \brief Check the completeness of a type in a unary type trait. +/// +/// If the particular type trait requires a complete type, tries to complete +/// it. If completing the type fails, a diagnostic is emitted and false +/// returned. If completing the type succeeds or no completion was required, +/// returns true. +static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, + UnaryTypeTrait UTT, + SourceLocation Loc, + QualType ArgTy) { + // C++0x [meta.unary.prop]p3: + // For all of the class templates X declared in this Clause, instantiating + // that template with a template argument that is a class template + // specialization may result in the implicit instantiation of the template + // argument if and only if the semantics of X require that the argument + // must be a complete type. + // We apply this rule to all the type trait expressions used to implement + // these class templates. We also try to follow any GCC documented behavior + // in these expressions to ensure portability of standard libraries. + switch (UTT) { + // is_complete_type somewhat obviously cannot require a complete type. + case UTT_IsCompleteType: + return true; + + // According to http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html + // all traits except __is_class, __is_enum and __is_union require a the type + // to be complete, an array of unknown bound, or void. + case UTT_IsClass: + case UTT_IsEnum: + case UTT_IsUnion: + return true; + + default: + // Apprantely Borland only wants the explicitly listed traits to complete + // the type. + if (S.LangOpts.Borland) return true; + + // C++0x [meta.unary.prop] Table 49 requires the following traits to be + // applied to a complete type, so we enumerate theme here even though the + // default for non-Borland compilers is to require completeness for any + // other traits than the ones specifically allowed to work on incomplete + // types. + // FIXME: C++0x: This list is incomplete, and the names don't always + // correspond clearly to entries in the standard's table. + case UTT_HasNothrowAssign: + case UTT_HasNothrowConstructor: + case UTT_HasNothrowCopy: + case UTT_HasTrivialAssign: + case UTT_HasTrivialConstructor: + case UTT_HasTrivialCopy: + case UTT_HasTrivialDestructor: + case UTT_HasVirtualDestructor: + case UTT_IsAbstract: + case UTT_IsEmpty: + case UTT_IsLiteral: + case UTT_IsPOD: + case UTT_IsPolymorphic: + case UTT_IsStandardLayout: + case UTT_IsTrivial: + // Arrays of unknown bound are expressly allowed. + QualType ElTy = ArgTy; + if (ArgTy->isIncompleteArrayType()) + ElTy = S.Context.getAsArrayType(ArgTy)->getElementType(); + + // The void type is expressly allowed. + if (ElTy->isVoidType()) + return true; + + return !S.RequireCompleteType( + Loc, ElTy, diag::err_incomplete_type_used_in_type_trait_expr); + } +} + + ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT, SourceLocation KWLoc, TypeSourceInfo *TSInfo, SourceLocation RParen) { QualType T = TSInfo->getType(); - - // According to http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html - // all traits except __is_class, __is_enum and __is_union require a the type - // to be complete, an array of unknown bound, or void. - if (UTT != UTT_IsClass && UTT != UTT_IsEnum && UTT != UTT_IsUnion && - UTT != UTT_IsCompleteType) { - QualType E = T; - if (T->isIncompleteArrayType()) - E = Context.getAsArrayType(T)->getElementType(); - if (!T->isVoidType() && - (! LangOpts.Borland || - UTT == UTT_HasNothrowAssign || - UTT == UTT_HasNothrowCopy || - UTT == UTT_HasNothrowConstructor || - UTT == UTT_HasTrivialAssign || - UTT == UTT_HasTrivialCopy || - UTT == UTT_HasTrivialConstructor || - UTT == UTT_HasTrivialDestructor || - UTT == UTT_HasVirtualDestructor) && - RequireCompleteType(KWLoc, E, - diag::err_incomplete_type_used_in_type_trait_expr)) - return ExprError(); - } + if (!CheckUnaryTypeTraitTypeCompleteness(*this, UTT, KWLoc, T)) + return ExprError(); bool Value = false; if (!T->isDependentType()) |