[cfe-commits] [patch] Implement MSVC 2012 type traits

Aaron Ballman aaron at aaronballman.com
Tue Sep 4 14:17:27 PDT 2012


> From e8799f8d23ee863feb2557942321e5d466fc8f95 Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Jo=C3=A3o=20Matos?= <ripzonetriton at gmail.com>
> Date: Sat, 25 Aug 2012 20:41:44 +0100
> Subject: [PATCH] Added support for MSVC 2012 type traits used in standard
>  library.
> ---
>  include/clang/Basic/TokenKinds.def |  3 ++
>  include/clang/Basic/TypeTraits.h   |  3 ++
>  lib/AST/StmtPrinter.cpp            |  3 ++
>  lib/Parse/ParseExpr.cpp            |  3 ++
>  lib/Parse/ParseExprCXX.cpp         |  4 +++
>  lib/Sema/SemaExprCXX.cpp           | 59 ++++++++++++++++++++++++++++++++++++++
>  6 files changed, 75 insertions(+)
> diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
> index fc03191..c5623ff 100644
> --- a/include/clang/Basic/TokenKinds.def
> +++ b/include/clang/Basic/TokenKinds.def
> @@ -350,11 +350,14 @@ KEYWORD(L__FUNCTION__               , KEYMS)
>
>  // GNU and MS Type Traits
>  KEYWORD(__has_nothrow_assign        , KEYCXX)
> +KEYWORD(__has_nothrow_move_assign   , KEYCXX)
>  KEYWORD(__has_nothrow_copy          , KEYCXX)
>  KEYWORD(__has_nothrow_constructor   , KEYCXX)
>  KEYWORD(__has_trivial_assign        , KEYCXX)
> +KEYWORD(__has_trivial_move_assign   , KEYCXX)
>  KEYWORD(__has_trivial_copy          , KEYCXX)
>  KEYWORD(__has_trivial_constructor   , KEYCXX)
> +KEYWORD(__has_trivial_move_constructor, KEYCXX)
>  KEYWORD(__has_trivial_destructor    , KEYCXX)
>  KEYWORD(__has_virtual_destructor    , KEYCXX)
>  KEYWORD(__is_abstract               , KEYCXX)

If it is explicit to MSVC, do we also want to OR in KEYMS?

> diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h
> index 0a5a864..9f27fa0 100644
> --- a/include/clang/Basic/TypeTraits.h
> +++ b/include/clang/Basic/TypeTraits.h
> @@ -20,11 +20,14 @@ namespace clang {
>    /// \brief Names for the unary type traits.
>    enum UnaryTypeTrait {
>      UTT_HasNothrowAssign,
> +    UTT_HasNothrowMoveAssign,
>      UTT_HasNothrowCopy,
>      UTT_HasNothrowConstructor,
>      UTT_HasTrivialAssign,
> +    UTT_HasTrivialMoveAssign,
>      UTT_HasTrivialCopy,
>      UTT_HasTrivialDefaultConstructor,
> +    UTT_HasTrivialMoveConstructor,
>      UTT_HasTrivialDestructor,
>      UTT_HasVirtualDestructor,
>      UTT_IsAbstract,
> diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
> index 9a31416..badb46e 100644
> --- a/lib/AST/StmtPrinter.cpp
> +++ b/lib/AST/StmtPrinter.cpp
> @@ -1510,9 +1510,12 @@ void StmtPrinter::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *Node) {
>  static const char *getTypeTraitName(UnaryTypeTrait UTT) {
>    switch (UTT) {
>    case UTT_HasNothrowAssign:      return "__has_nothrow_assign";
> +  case UTT_HasNothrowMoveAssign:  return "__has_nothrow_move_assign";
>    case UTT_HasNothrowConstructor: return "__has_nothrow_constructor";
>    case UTT_HasNothrowCopy:          return "__has_nothrow_copy";
>    case UTT_HasTrivialAssign:      return "__has_trivial_assign";
> +  case UTT_HasTrivialMoveAssign:      return "__has_trivial_move_assign";
> +  case UTT_HasTrivialMoveConstructor: return "__has_trivial_move_constructor";
>    case UTT_HasTrivialDefaultConstructor: return "__has_trivial_constructor";
>    case UTT_HasTrivialCopy:          return "__has_trivial_copy";
>    case UTT_HasTrivialDestructor:  return "__has_trivial_destructor";
> diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
> index 8df08b8..728a3d5 100644
> --- a/lib/Parse/ParseExpr.cpp
> +++ b/lib/Parse/ParseExpr.cpp
> @@ -1171,10 +1171,13 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
>    case tok::kw___is_union:
>    case tok::kw___is_final:
>    case tok::kw___has_trivial_constructor:
> +  case tok::kw___has_trivial_move_constructor:
>    case tok::kw___has_trivial_copy:
>    case tok::kw___has_trivial_assign:
> +  case tok::kw___has_trivial_move_assign:
>    case tok::kw___has_trivial_destructor:
>    case tok::kw___has_nothrow_assign:
> +  case tok::kw___has_nothrow_move_assign:
>    case tok::kw___has_nothrow_copy:
>    case tok::kw___has_nothrow_constructor:
>    case tok::kw___has_virtual_destructor:
> diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
> index e02cb7a..93cc182 100644
> --- a/lib/Parse/ParseExprCXX.cpp
> +++ b/lib/Parse/ParseExprCXX.cpp
> @@ -2435,11 +2435,15 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
>    switch(kind) {
>    default: llvm_unreachable("Not a known unary type trait.");
>    case tok::kw___has_nothrow_assign:      return UTT_HasNothrowAssign;
> +  case tok::kw___has_nothrow_move_assign: return UTT_HasNothrowMoveAssign;
>    case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
>    case tok::kw___has_nothrow_copy:           return UTT_HasNothrowCopy;
>    case tok::kw___has_trivial_assign:      return UTT_HasTrivialAssign;
> +  case tok::kw___has_trivial_move_assign: return UTT_HasTrivialMoveAssign;
>    case tok::kw___has_trivial_constructor:
>                                      return UTT_HasTrivialDefaultConstructor;
> +  case tok::kw___has_trivial_move_constructor:
> +                                    return UTT_HasTrivialMoveConstructor;
>    case tok::kw___has_trivial_copy:           return UTT_HasTrivialCopy;
>    case tok::kw___has_trivial_destructor:  return UTT_HasTrivialDestructor;
>    case tok::kw___has_virtual_destructor:  return UTT_HasVirtualDestructor;
> diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
> index 4fc9abd..9501af8 100644
> --- a/lib/Sema/SemaExprCXX.cpp
> +++ b/lib/Sema/SemaExprCXX.cpp
> @@ -2945,10 +2945,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:
> @@ -3092,6 +3095,15 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
>            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.
> +    if (T.isPODType(Self.Context))
> +      return true;

I think this is redundant with the hasTrivialMoveConstructor call
since that defaults to true and is only set to false when we know it's
non-trivial.

> +    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
> @@ -3123,6 +3135,15 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
>      if (const RecordType *RT = T->getAs<RecordType>())
>        return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyAssignment();
>      return false;
> +  case UTT_HasTrivialMoveAssign:
> +    // This trait is implemented by MSVC 2012 and needed to parse the
> +    // standard library headers.
> +    if (T.isPODType(Self.Context))
> +      return true;

Same is true of this POD check.

> +    if (const RecordType *RT =
> +          C.getBaseElementType(T)->getAs<RecordType>())
> +      return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialMoveAssignment();
> +    return false;
>    case UTT_HasTrivialDestructor:
>      // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
>      //   If __is_pod (type) is true or type is a reference type
> @@ -3190,6 +3211,44 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
>        return FoundAssign;
>      }
>      return false;
> +  case UTT_HasNothrowMoveAssign:
> +    // This trait is implemented by MSVC 2012 and needed to parse the
> +    // standard library headers.
> +    if (T.isPODType(Self.Context))
> +      return true;

Same here

> +    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);
> +      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->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;
> +    }
> +    return false;
>    case UTT_HasNothrowCopy:
>      // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
>      //   If __has_trivial_copy (type) is true then the trait is true, else
> --
> 1.7.11
>
> From fec722607d7daab121dbd319b9017f8c40abc15c Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Jo=C3=A3o=20Matos?= <ripzonetriton at gmail.com>
> Date: Sat, 25 Aug 2012 22:00:10 +0100
> Subject: [PATCH] Added has_ type traits feature macros for MSVC 2012
>  extensions.
> ---
>  lib/Lex/PPMacroExpansion.cpp | 3 +++
>  1 file changed, 3 insertions(+)
> diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
> index 96d6b2c..eb4da22 100644
> --- a/lib/Lex/PPMacroExpansion.cpp
> +++ b/lib/Lex/PPMacroExpansion.cpp
> @@ -700,11 +700,14 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
>             .Case("cxx_variadic_templates", LangOpts.CPlusPlus0x)
>             // Type traits
>             .Case("has_nothrow_assign", LangOpts.CPlusPlus)
> +           .Case("has_nothrow_move_assign", LangOpts.CPlusPlus)
>             .Case("has_nothrow_copy", LangOpts.CPlusPlus)
>             .Case("has_nothrow_constructor", LangOpts.CPlusPlus)
>             .Case("has_trivial_assign", LangOpts.CPlusPlus)
> +           .Case("has_trivial_move_assign", LangOpts.CPlusPlus)
>             .Case("has_trivial_copy", LangOpts.CPlusPlus)
>             .Case("has_trivial_constructor", LangOpts.CPlusPlus)
> +           .Case("has_trivial_move_constructor", LangOpts.CPlusPlus)
>             .Case("has_trivial_destructor", LangOpts.CPlusPlus)
>             .Case("has_virtual_destructor", LangOpts.CPlusPlus)
>             .Case("is_abstract", LangOpts.CPlusPlus)
> --
> 1.7.11

~Aaron



More information about the cfe-commits mailing list