]> granicus.if.org Git - clang/commitdiff
Implement a new type trait __is_trivially_constructible(T, Args...)
authorDouglas Gregor <dgregor@apple.com>
Fri, 24 Feb 2012 07:38:34 +0000 (07:38 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 24 Feb 2012 07:38:34 +0000 (07:38 +0000)
that provides the behavior of the C++11 library trait
std::is_trivially_constructible<T, Args...>, which can't be
implemented purely as a library.

Since __is_trivially_constructible can have zero or more arguments, I
needed to add Yet Another Type Trait Expression Class, this one
handling arbitrary arguments. The next step will be to migrate
UnaryTypeTrait and BinaryTypeTrait over to this new, more general
TypeTrait class.

Fixes the Clang side of <rdar://problem/10895483> / PR12038.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151352 91177308-0d34-0410-b5e6-96231b3b80d8

33 files changed:
docs/LanguageExtensions.html
include/clang/AST/ExprCXX.h
include/clang/AST/RecursiveASTVisitor.h
include/clang/AST/Stmt.h
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Basic/StmtNodes.td
include/clang/Basic/TokenKinds.def
include/clang/Basic/TypeTraits.h
include/clang/Parse/Parser.h
include/clang/Sema/Sema.h
include/clang/Serialization/ASTBitCodes.h
lib/AST/Expr.cpp
lib/AST/ExprCXX.cpp
lib/AST/ExprClassification.cpp
lib/AST/ExprConstant.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/StmtPrinter.cpp
lib/AST/StmtProfile.cpp
lib/Lex/PPMacroExpansion.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseExprCXX.cpp
lib/Parse/ParseTentative.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterStmt.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
test/Index/annotate-tokens-cxx0x.cpp
test/PCH/cxx-traits.cpp
test/PCH/cxx-traits.h
test/SemaCXX/type-traits.cpp
tools/libclang/CIndex.cpp
tools/libclang/CXCursor.cpp

index d38f5d05ce74ca2263cf2697d4a135f7841ed08c..2471c60776c1d975e0e848df01487dca7b509f69 100644 (file)
@@ -889,6 +889,8 @@ struct is_convertible_to {
   <li><code>__is_literal(type)</code>: Determines whether the given type is a literal type</li>
   <li><code>__is_final</code>: Determines whether the given type is declared with a <code>final</code> class-virt-specifier.</li>
   <li><code>__underlying_type(type)</code>: Retrieves the underlying type for a given <code>enum</code> type. This trait is required to implement the C++11 standard library.</li>
+  <li><code>__is_trivially_assignable(totype, fromtype)</code>: Determines whether a value of type <tt>totype</tt> can be assigned to from a value of type <tt>fromtype</tt> such that no non-trivial functions are called as part of that assignment. This trait is required to implement the C++11 standard library.</li>
+  <li><code>__is_trivially_constructible(type, argtypes...)</code>: Determines whether a value of type <tt>type</tt> can be direct-initialized with arguments of types <tt>argtypes...</tt> such that no non-trivial functions are called as part of that initialization. This trait is required to implement the C++11 standard library.</li>
 </ul>
 
 <!-- ======================================================================= -->
index f21ba1f3b75e8c588bb256f1d6129982c0678ccb..40050c3d2c96f0ecb9302e0e5d776a2933d4905d 100644 (file)
@@ -1926,6 +1926,102 @@ public:
   friend class ASTStmtReader;
 };
 
+/// \brief A type trait used in the implementation of various C++11 and
+/// Library TR1 trait templates.
+///
+/// \code
+///   __is_trivially_constructible(vector<int>, int*, int*)
+/// \endcode
+class TypeTraitExpr : public Expr {
+  /// \brief The location of the type trait keyword.
+  SourceLocation Loc;
+  
+  /// \brief  The location of the closing parenthesis.
+  SourceLocation RParenLoc;
+  
+  // Note: The TypeSourceInfos for the arguments are allocated after the
+  // TypeTraitExpr.
+  
+  TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
+                ArrayRef<TypeSourceInfo *> Args,
+                SourceLocation RParenLoc,
+                bool Value);
+
+  TypeTraitExpr(EmptyShell Empty) : Expr(TypeTraitExprClass, Empty) { }
+
+  /// \brief Retrieve the argument types.
+  TypeSourceInfo **getTypeSourceInfos() {
+    return reinterpret_cast<TypeSourceInfo **>(this+1);
+  }
+  
+  /// \brief Retrieve the argument types.
+  TypeSourceInfo * const *getTypeSourceInfos() const {
+    return reinterpret_cast<TypeSourceInfo * const*>(this+1);
+  }
+  
+public:
+  /// \brief Create a new type trait expression.
+  static TypeTraitExpr *Create(ASTContext &C, QualType T, SourceLocation Loc, 
+                               TypeTrait Kind,
+                               ArrayRef<TypeSourceInfo *> Args,
+                               SourceLocation RParenLoc,
+                               bool Value);
+
+  static TypeTraitExpr *CreateDeserialized(ASTContext &C, unsigned NumArgs);
+  
+  /// \brief Determine which type trait this expression uses.
+  TypeTrait getTrait() const {
+    return static_cast<TypeTrait>(TypeTraitExprBits.Kind);
+  }
+
+  bool getValue() const { 
+    assert(!isValueDependent()); 
+    return TypeTraitExprBits.Value; 
+  }
+  
+  /// \brief Determine the number of arguments to this type trait.
+  unsigned getNumArgs() const { return TypeTraitExprBits.NumArgs; }
+  
+  /// \brief Retrieve the Ith argument.
+  TypeSourceInfo *getArg(unsigned I) const {
+    assert(I < getNumArgs() && "Argument out-of-range");
+    return getArgs()[I];
+  }
+  
+  /// \brief Retrieve the argument types.
+  ArrayRef<TypeSourceInfo *> getArgs() const { 
+    return ArrayRef<TypeSourceInfo *>(getTypeSourceInfos(), getNumArgs());
+  }
+  
+  typedef TypeSourceInfo **arg_iterator;
+  arg_iterator arg_begin() { 
+    return getTypeSourceInfos(); 
+  }
+  arg_iterator arg_end() { 
+    return getTypeSourceInfos() + getNumArgs(); 
+  }
+
+  typedef TypeSourceInfo const * const *arg_const_iterator;
+  arg_const_iterator arg_begin() const { return getTypeSourceInfos(); }
+  arg_const_iterator arg_end() const { 
+    return getTypeSourceInfos() + getNumArgs(); 
+  }
+
+  SourceRange getSourceRange() const { return SourceRange(Loc, RParenLoc); }
+  
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == TypeTraitExprClass;
+  }
+  static bool classof(const TypeTraitExpr *) { return true; }
+  
+  // Iterators
+  child_range children() { return child_range(); }
+  
+  friend class ASTStmtReader;
+  friend class ASTStmtWriter;
+
+};
+  
 /// ArrayTypeTraitExpr - An Embarcadero array type trait, as used in the
 /// implementation of __array_rank and __array_extent.
 /// Example:
index a0f4950a0472abd10b8fb3ee1975ad995aa4adfb..a1214a9d25fc058f86c5ecfe66c96c91f66c19d8 100644 (file)
@@ -1946,6 +1946,11 @@ DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, {
     TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc()));
   })
 
+DEF_TRAVERSE_STMT(TypeTraitExpr, {
+  for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I)
+    TRY_TO(TraverseTypeLoc(S->getArg(I)->getTypeLoc()));
+})
+
 DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, {
     TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
   })
index be2b706fac4e3ac2808f4fcac6c235407028ec09..1bc0c11ef5975c57a77faaf0aa0813f71882268a 100644 (file)
@@ -227,6 +227,24 @@ protected:
     unsigned InitializesStdInitializerList : 1;
   };
 
+  class TypeTraitExprBitfields {
+    friend class TypeTraitExpr;
+    friend class ASTStmtReader;
+    friend class ASTStmtWriter;
+    
+    unsigned : NumExprBits;
+    
+    /// \brief The kind of type trait, which is a value of a TypeTrait enumerator.
+    unsigned Kind : 8;
+    
+    /// \brief If this expression is not value-dependent, this indicates whether
+    /// the trait evaluated true or false.
+    unsigned Value : 1;
+
+    /// \brief The number of arguments to this type trait.
+    unsigned NumArgs : 32 - 8 - 1 - NumExprBits;
+  };
+  
   union {
     // FIXME: this is wasteful on 64-bit platforms.
     void *Aligner;
@@ -241,9 +259,11 @@ protected:
     PseudoObjectExprBitfields PseudoObjectExprBits;
     ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits;
     InitListExprBitfields InitListExprBits;
+    TypeTraitExprBitfields TypeTraitExprBits;
   };
 
   friend class ASTStmtReader;
+  friend class ASTStmtWriter;
 
 public:
   // Only allow allocation of Stmts using the allocator in ASTContext
index 4e60edf37d436d2a5af449555703f0ff23103807..bfece366f14ff853f4164cb29661351d959ed11f 100644 (file)
@@ -4438,6 +4438,10 @@ def note_inequality_comparison_to_or_assign : Note<
 
 def err_incomplete_type_used_in_type_trait_expr : Error<
   "incomplete type %0 used in type trait expression">;
+def err_type_trait_arity : Error<
+  "type trait requires %0%select{| or more}1 argument%select{|s}2; have "
+  "%3 argument%s3">;
+  
 def err_dimension_expr_not_constant_integer : Error<
   "dimension expression does not evaluate to a constant unsigned int">;
 def err_expected_ident_or_lparen : Error<"expected identifier or '('">;
index d728221869d65d0648cac009522e0af8029465e5..07bb227b823dd05dc54c6bd2786dfd66a8675a57 100644 (file)
@@ -107,6 +107,7 @@ def CXXScalarValueInitExpr : DStmt<Expr>;
 def CXXNewExpr : DStmt<Expr>;
 def CXXDeleteExpr : DStmt<Expr>;
 def CXXPseudoDestructorExpr : DStmt<Expr>;
+def TypeTraitExpr : DStmt<Expr>;
 def UnaryTypeTraitExpr : DStmt<Expr>;
 def BinaryTypeTraitExpr : DStmt<Expr>;
 def ArrayTypeTraitExpr : DStmt<Expr>;
index 300db4d8862fc0bc2e96ba53de2772d8754cdb2c..74072ba16a2fae31e4b71a3df0ca02f61d5420d0 100644 (file)
@@ -365,6 +365,7 @@ KEYWORD(__is_trivial                , KEYCXX)
 KEYWORD(__is_union                  , KEYCXX)
 
 // Clang-only C++ Type Traits
+KEYWORD(__is_trivially_constructible, KEYCXX)
 KEYWORD(__is_trivially_copyable     , KEYCXX)
 KEYWORD(__is_trivially_assignable   , KEYCXX)
 KEYWORD(__underlying_type           , KEYCXX)
index 6ed2adfaf5cb6614aa4f7b7b5476e4bb5b5ef067..721f44f40815135023385fd89afa969b436af644 100644 (file)
@@ -84,6 +84,12 @@ namespace clang {
     UETT_AlignOf,
     UETT_VecStep
   };
+  
+  /// \brief Names for type traits that operate specifically on types.
+  enum TypeTrait {
+    TT_IsTriviallyConstructible
+  };
+  
 }
 
 #endif
index 64736118e17b2760c8c2b40fedd200b1e2bb9eb0..e7834edac7bc7c6e196f7ce156396f1a56ade71c 100644 (file)
@@ -2170,7 +2170,8 @@ private:
   // GNU G++: Type Traits [Type-Traits.html in the GCC manual]
   ExprResult ParseUnaryTypeTrait();
   ExprResult ParseBinaryTypeTrait();
-
+  ExprResult ParseTypeTrait();
+  
   //===--------------------------------------------------------------------===//
   // Embarcadero: Arary and Expression Traits
   ExprResult ParseArrayTypeTrait();
index 7aed347d41079f664f903713c9b92a07d63d0e2b..8131c6372ee4afab66942552dfc912486f19e05a 100644 (file)
@@ -3317,6 +3317,14 @@ public:
                                   TypeSourceInfo *RhsT,
                                   SourceLocation RParen);
 
+  /// \brief Parsed one of the type trait support pseudo-functions.
+  ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
+                            ArrayRef<ParsedType> Args,
+                            SourceLocation RParenLoc);
+  ExprResult BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
+                            ArrayRef<TypeSourceInfo *> Args,
+                            SourceLocation RParenLoc);
+  
   /// ActOnArrayTypeTrait - Parsed one of the bianry type trait support
   /// pseudo-functions.
   ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT,
index 7ec2cac7ff51a8c536829873327a8ec576450db1..7de6b4589a7b0e0a25311b3c4aec9b03318b87a2 100644 (file)
@@ -1156,6 +1156,7 @@ namespace clang {
       EXPR_OPAQUE_VALUE,          // OpaqueValueExpr
       EXPR_BINARY_CONDITIONAL_OPERATOR,  // BinaryConditionalOperator
       EXPR_BINARY_TYPE_TRAIT,     // BinaryTypeTraitExpr
+      EXPR_TYPE_TRAIT,            // TypeTraitExpr
       EXPR_ARRAY_TYPE_TRAIT,      // ArrayTypeTraitIntExpr
       
       EXPR_PACK_EXPANSION,        // PackExpansionExpr
index a1770c915a836d232c679b3e556d073d8065e472..37df90407dce96aa81d00913ab389d9161bb373c 100644 (file)
@@ -2169,6 +2169,7 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const {
   case AddrLabelExprClass:
   case ArrayTypeTraitExprClass:
   case BinaryTypeTraitExprClass:
+  case TypeTraitExprClass:
   case CXXBoolLiteralExprClass:
   case CXXNoexceptExprClass:
   case CXXNullPtrLiteralExprClass:
index 7ef3417e6dc5e0fcaf099e26eda2dc7b90843692..da89bf2798ea432ccf1058d1347869415271499d 100644 (file)
@@ -199,7 +199,6 @@ SourceRange CXXPseudoDestructorExpr::getSourceRange() const {
   return SourceRange(Base->getLocStart(), End);
 }
 
-
 // UnresolvedLookupExpr
 UnresolvedLookupExpr *
 UnresolvedLookupExpr::Create(ASTContext &C, 
@@ -1262,4 +1261,51 @@ TemplateArgument SubstNonTypeTemplateParmPackExpr::getArgumentPack() const {
   return TemplateArgument(Arguments, NumArguments);
 }
 
+TypeTraitExpr::TypeTraitExpr(QualType T, SourceLocation Loc, TypeTrait Kind,
+                             ArrayRef<TypeSourceInfo *> Args,
+                             SourceLocation RParenLoc,
+                             bool Value)
+  : Expr(TypeTraitExprClass, T, VK_RValue, OK_Ordinary,
+         /*TypeDependent=*/false,
+         /*ValueDependent=*/false,
+         /*InstantiationDependent=*/false,
+         /*ContainsUnexpandedParameterPack=*/false),
+    Loc(Loc), RParenLoc(RParenLoc)
+{
+  TypeTraitExprBits.Kind = Kind;
+  TypeTraitExprBits.Value = Value;
+  TypeTraitExprBits.NumArgs = Args.size();
+
+  TypeSourceInfo **ToArgs = getTypeSourceInfos();
+  
+  for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+    if (Args[I]->getType()->isDependentType())
+      setValueDependent(true);
+    if (Args[I]->getType()->isInstantiationDependentType())
+      setInstantiationDependent(true);
+    if (Args[I]->getType()->containsUnexpandedParameterPack())
+      setContainsUnexpandedParameterPack(true);
+    
+    ToArgs[I] = Args[I];
+  }
+}
+
+TypeTraitExpr *TypeTraitExpr::Create(ASTContext &C, QualType T, 
+                                     SourceLocation Loc, 
+                                     TypeTrait Kind,
+                                     ArrayRef<TypeSourceInfo *> Args,
+                                     SourceLocation RParenLoc,
+                                     bool Value) {
+  unsigned Size = sizeof(TypeTraitExpr) + sizeof(TypeSourceInfo*) * Args.size();
+  void *Mem = C.Allocate(Size);
+  return new (Mem) TypeTraitExpr(T, Loc, Kind, Args, RParenLoc, Value);
+}
+
+TypeTraitExpr *TypeTraitExpr::CreateDeserialized(ASTContext &C,
+                                                 unsigned NumArgs) {
+  unsigned Size = sizeof(TypeTraitExpr) + sizeof(TypeSourceInfo*) * NumArgs;
+  void *Mem = C.Allocate(Size);
+  return new (Mem) TypeTraitExpr(EmptyShell());
+}
+
 void ArrayTypeTraitExpr::anchor() { }
index 79d8dc48fe085f24007e35485212ec76ab3815d4..1b04428fae662dd486bac1d55f64f52a79858501 100644 (file)
@@ -151,6 +151,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
   case Expr::CXXScalarValueInitExprClass:
   case Expr::UnaryTypeTraitExprClass:
   case Expr::BinaryTypeTraitExprClass:
+  case Expr::TypeTraitExprClass:
   case Expr::ArrayTypeTraitExprClass:
   case Expr::ExpressionTraitExprClass:
   case Expr::ObjCSelectorExprClass:
index ed64153f853c30d9cd69dc50fe745e1831c4e53a..85aa5ee81efd23b55da11f91d26129c7a5d58cf8 100644 (file)
@@ -4119,6 +4119,10 @@ public:
     return Success(E->getValue(), E);
   }
 
+  bool VisitTypeTraitExpr(const TypeTraitExpr *E) {
+    return Success(E->getValue(), E);
+  }
+
   bool VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) {
     return Success(E->getValue(), E);
   }
@@ -6360,6 +6364,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
   case Expr::CXXScalarValueInitExprClass:
   case Expr::UnaryTypeTraitExprClass:
   case Expr::BinaryTypeTraitExprClass:
+  case Expr::TypeTraitExprClass:
   case Expr::ArrayTypeTraitExprClass:
   case Expr::ExpressionTraitExprClass:
   case Expr::CXXNoexceptExprClass:
index 5e167f58dca4277b266a11c0f4add4874c7c1a4d..91e6ee5c970bc1582fb04a121aafd79c093cb7e4 100644 (file)
@@ -2383,6 +2383,7 @@ recurse:
   case Expr::StmtExprClass:
   case Expr::UnaryTypeTraitExprClass:
   case Expr::BinaryTypeTraitExprClass:
+  case Expr::TypeTraitExprClass:
   case Expr::ArrayTypeTraitExprClass:
   case Expr::ExpressionTraitExprClass:
   case Expr::VAArgExprClass:
index 51296ad5f4d3c943c0691fd806f14fdd24599841..6d3e783f221283d01f76454b92ed8bf65f123d9b 100644 (file)
@@ -1555,6 +1555,13 @@ static const char *getTypeTraitName(BinaryTypeTrait BTT) {
   llvm_unreachable("Binary type trait not covered by switch");
 }
 
+static const char *getTypeTraitName(TypeTrait TT) {
+  switch (TT) {
+  case clang::TT_IsTriviallyConstructible:return "__is_trivially_constructible";
+  }
+  llvm_unreachable("Type trait not covered by switch");
+}
+
 static const char *getTypeTraitName(ArrayTypeTrait ATT) {
   switch (ATT) {
   case ATT_ArrayRank:        return "__array_rank";
@@ -1582,6 +1589,16 @@ void StmtPrinter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
      << E->getRhsType().getAsString(Policy) << ")";
 }
 
+void StmtPrinter::VisitTypeTraitExpr(TypeTraitExpr *E) {
+  OS << getTypeTraitName(E->getTrait()) << "(";
+  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) {
+    if (I > 0)
+      OS << ", ";
+    OS << E->getArg(I)->getType().getAsString(Policy);
+  }
+  OS << ")";
+}
+
 void StmtPrinter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
   OS << getTypeTraitName(E->getTrait()) << "("
      << E->getQueriedType().getAsString(Policy) << ")";
index fdd0c8502db5f78b7bf39db96fdda8f594e6c520..643bca817c43ceea3c5e15e6559822b29d6bf073 100644 (file)
@@ -868,6 +868,14 @@ void StmtProfiler::VisitBinaryTypeTraitExpr(const BinaryTypeTraitExpr *S) {
   VisitType(S->getRhsType());
 }
 
+void StmtProfiler::VisitTypeTraitExpr(const TypeTraitExpr *S) {
+  VisitExpr(S);
+  ID.AddInteger(S->getTrait());
+  ID.AddInteger(S->getNumArgs());
+  for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I)
+    VisitType(S->getArg(I)->getType());
+}
+
 void StmtProfiler::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *S) {
   VisitExpr(S);
   ID.AddInteger(S->getTrait());
index 0e00996410297d3ef858c0b8dbb77ec942ade0e1..bc346927027ee2f3b7c6f29d37d8cb45874fcdfe 100644 (file)
@@ -701,6 +701,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
            .Case("is_polymorphic", LangOpts.CPlusPlus)
            .Case("is_trivial", LangOpts.CPlusPlus)
            .Case("is_trivially_assignable", LangOpts.CPlusPlus)
+           .Case("is_trivially_constructible", LangOpts.CPlusPlus)
            .Case("is_trivially_copyable", LangOpts.CPlusPlus)
            .Case("is_union", LangOpts.CPlusPlus)
            .Case("modules", LangOpts.Modules)
index fdf40e877c8f5bd82a088d468965266d159b8bd6..62d1f494beedb8a4f3f7538572e77d4ef45c1353 100644 (file)
@@ -1143,6 +1143,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
   case tok::kw___is_trivially_assignable:
     return ParseBinaryTypeTrait();
 
+  case tok::kw___is_trivially_constructible:
+    return ParseTypeTrait();
+      
   case tok::kw___array_rank:
   case tok::kw___array_extent:
     return ParseArrayTypeTrait();
index 19bc22020cf38adc46e1df1fc547140bdc3b8263..d8663077fdf773188c5db89af7c9dbcc8e405d4e 100644 (file)
@@ -2458,6 +2458,14 @@ static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) {
   }
 }
 
+static TypeTrait TypeTraitFromTokKind(tok::TokenKind kind) {
+  switch (kind) {
+  default: llvm_unreachable("Not a known type trait");
+  case tok::kw___is_trivially_constructible: 
+    return TT_IsTriviallyConstructible;
+  }
+}
+
 static ArrayTypeTrait ArrayTypeTraitFromTokKind(tok::TokenKind kind) {
   switch(kind) {
   default: llvm_unreachable("Not a known binary type trait");
@@ -2540,6 +2548,58 @@ ExprResult Parser::ParseBinaryTypeTrait() {
                                       T.getCloseLocation());
 }
 
+/// \brief Parse the built-in type-trait pseudo-functions that allow 
+/// implementation of the TR1/C++11 type traits templates.
+///
+///       primary-expression:
+///          type-trait '(' type-id-seq ')'
+///
+///       type-id-seq:
+///          type-id ...[opt] type-id-seq[opt]
+///
+ExprResult Parser::ParseTypeTrait() {
+  TypeTrait Kind = TypeTraitFromTokKind(Tok.getKind());
+  SourceLocation Loc = ConsumeToken();
+  
+  BalancedDelimiterTracker Parens(*this, tok::l_paren);
+  if (Parens.expectAndConsume(diag::err_expected_lparen))
+    return ExprError();
+
+  llvm::SmallVector<ParsedType, 2> Args;
+  do {
+    // Parse the next type.
+    TypeResult Ty = ParseTypeName();
+    if (Ty.isInvalid()) {
+      Parens.skipToEnd();
+      return ExprError();
+    }
+
+    // Parse the ellipsis, if present.
+    if (Tok.is(tok::ellipsis)) {
+      Ty = Actions.ActOnPackExpansion(Ty.get(), ConsumeToken());
+      if (Ty.isInvalid()) {
+        Parens.skipToEnd();
+        return ExprError();
+      }
+    }
+    
+    // Add this type to the list of arguments.
+    Args.push_back(Ty.get());
+    
+    if (Tok.is(tok::comma)) {
+      ConsumeToken();
+      continue;
+    }
+    
+    break;
+  } while (true);
+  
+  if (Parens.consumeClose())
+    return ExprError();
+  
+  return Actions.ActOnTypeTrait(Kind, Loc, Args, Parens.getCloseLocation());
+}
+
 /// ParseArrayTypeTrait - Parse the built-in array type-trait
 /// pseudo-functions.
 ///
index 011c28aaf7fa4514148d24a672d391aa803751b0..92ae770fa09fb35e34f834317d0188d9efc4ea94 100644 (file)
@@ -690,6 +690,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) {
   case tok::kw___is_polymorphic:
   case tok::kw___is_trivial:
   case tok::kw___is_trivially_assignable:
+  case tok::kw___is_trivially_constructible:
   case tok::kw___is_trivially_copyable:
   case tok::kw___is_union:
   case tok::kw___uuidof:
index 708db1c9a9cf0b05f29e5bddace239d7746a427b..a4ae9be41b4d39b89962a6136a9c2223f53505d0 100644 (file)
@@ -3212,6 +3212,127 @@ ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait BTT,
   return BuildBinaryTypeTrait(BTT, KWLoc, LhsTSInfo, RhsTSInfo, RParen);
 }
 
+static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
+                              ArrayRef<TypeSourceInfo *> Args,
+                              SourceLocation RParenLoc) {
+  switch (Kind) {
+  case clang::TT_IsTriviallyConstructible: {
+    // C++11 [meta.unary.prop]:
+    //   is_trivially_constructor is defined as:
+    //
+    //     is_constructible<T, Args...>::value is true and the variable 
+    //
+    ///  definition for is_constructible, as defined below, is known to call no
+    //   operation that is not trivial.
+    //
+    //   The predicate condition for a template specialization 
+    //   is_constructible<T, Args...> shall be satisfied if and only if the 
+    //   following variable definition would be well-formed for some invented 
+    //   variable t:
+    //
+    //     T t(create<Args>()...);
+    if (Args.empty()) {
+      S.Diag(KWLoc, diag::err_type_trait_arity)
+        << 1 << 1 << 1 << (int)Args.size();
+      return false;
+    }
+    
+    bool SawVoid = false;
+    for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+      if (Args[I]->getType()->isVoidType()) {
+        SawVoid = true;
+        continue;
+      }
+      
+      if (!Args[I]->getType()->isIncompleteType() &&
+        S.RequireCompleteType(KWLoc, Args[I]->getType(), 
+          diag::err_incomplete_type_used_in_type_trait_expr))
+        return false;
+    }
+    
+    // If any argument was 'void', of course it won't type-check.
+    if (SawVoid)
+      return false;
+    
+    llvm::SmallVector<OpaqueValueExpr, 2> OpaqueArgExprs;
+    llvm::SmallVector<Expr *, 2> ArgExprs;
+    ArgExprs.reserve(Args.size() - 1);
+    for (unsigned I = 1, N = Args.size(); I != N; ++I) {
+      QualType T = Args[I]->getType();
+      if (T->isObjectType() || T->isFunctionType())
+        T = S.Context.getRValueReferenceType(T);
+      OpaqueArgExprs.push_back(
+        OpaqueValueExpr(Args[I]->getTypeLoc().getSourceRange().getBegin(), 
+                        T.getNonLValueExprType(S.Context),
+                        Expr::getValueKindForType(T)));
+      ArgExprs.push_back(&OpaqueArgExprs.back());
+    }
+    
+    // Perform the initialization in an unevaluated context within a SFINAE 
+    // trap at translation unit scope.
+    EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated);
+    Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true);
+    Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());
+    InitializedEntity To(InitializedEntity::InitializeTemporary(Args[0]));
+    InitializationKind InitKind(InitializationKind::CreateDirect(KWLoc, KWLoc,
+                                                                 RParenLoc));
+    InitializationSequence Init(S, To, InitKind, 
+                                ArgExprs.begin(), ArgExprs.size());
+    if (Init.Failed())
+      return false;
+    
+    ExprResult Result = Init.Perform(S, To, InitKind, 
+                                     MultiExprArg(ArgExprs.data(), 
+                                                  ArgExprs.size()));
+    if (Result.isInvalid() || SFINAE.hasErrorOccurred())
+      return false;
+    
+    // The initialization succeeded; not make sure there are no non-trivial 
+    // calls.
+    return !Result.get()->hasNonTrivialCall(S.Context);
+  }
+  }
+  
+  return false;
+}
+
+ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, 
+                                ArrayRef<TypeSourceInfo *> Args, 
+                                SourceLocation RParenLoc) {
+  bool Dependent = false;
+  for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+    if (Args[I]->getType()->isDependentType()) {
+      Dependent = true;
+      break;
+    }
+  }
+  
+  bool Value = false;
+  if (!Dependent)
+    Value = evaluateTypeTrait(*this, Kind, KWLoc, Args, RParenLoc);
+  
+  return TypeTraitExpr::Create(Context, Context.BoolTy, KWLoc, Kind,
+                               Args, RParenLoc, Value);
+}
+
+ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, 
+                                ArrayRef<ParsedType> Args, 
+                                SourceLocation RParenLoc) {
+  llvm::SmallVector<TypeSourceInfo *, 4> ConvertedArgs;
+  ConvertedArgs.reserve(Args.size());
+  
+  for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+    TypeSourceInfo *TInfo;
+    QualType T = GetTypeFromParser(Args[I], &TInfo);
+    if (!TInfo)
+      TInfo = Context.getTrivialTypeSourceInfo(T, KWLoc);
+    
+    ConvertedArgs.push_back(TInfo);    
+  }
+  
+  return BuildTypeTrait(Kind, KWLoc, ConvertedArgs, RParenLoc);
+}
+
 static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT,
                                     QualType LhsT, QualType RhsT,
                                     SourceLocation KeyLoc) {
index 58d6a22a288297966e92cde7b8ce8b578949e76a..f0b5f4e2419fa2cdae8c136bf67521e757513546 100644 (file)
@@ -2022,6 +2022,17 @@ public:
     return getSema().BuildBinaryTypeTrait(Trait, StartLoc, LhsT, RhsT, RParenLoc);
   }
 
+  /// \brief Build a new type trait expression.
+  ///
+  /// By default, performs semantic analysis to build the new expression.
+  /// Subclasses may override this routine to provide different behavior.
+  ExprResult RebuildTypeTrait(TypeTrait Trait,
+                              SourceLocation StartLoc,
+                              ArrayRef<TypeSourceInfo *> Args,
+                              SourceLocation RParenLoc) {
+    return getSema().BuildTypeTrait(Trait, StartLoc, Args, RParenLoc);
+  }
+  
   /// \brief Build a new array type trait expression.
   ///
   /// By default, performs semantic analysis to build the new expression.
@@ -7434,6 +7445,128 @@ TreeTransform<Derived>::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
                                             E->getLocEnd());
 }
 
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) {
+  bool ArgChanged = false;
+  llvm::SmallVector<TypeSourceInfo *, 4> Args;
+  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) {
+    TypeSourceInfo *From = E->getArg(I);
+    TypeLoc FromTL = From->getTypeLoc();
+    if (!isa<PackExpansionTypeLoc>(FromTL)) {
+      TypeLocBuilder TLB;
+      TLB.reserve(FromTL.getFullDataSize());
+      QualType To = getDerived().TransformType(TLB, FromTL);
+      if (To.isNull())
+        return ExprError();
+      
+      if (To == From->getType())
+        Args.push_back(From);
+      else {
+        Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To));
+        ArgChanged = true;
+      }
+      continue;
+    }
+    
+    ArgChanged = true;
+    
+    // We have a pack expansion. Instantiate it.
+    PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(FromTL);      
+    TypeLoc PatternTL = ExpansionTL.getPatternLoc();
+    SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+    SemaRef.collectUnexpandedParameterPacks(PatternTL, Unexpanded);
+    
+    // Determine whether the set of unexpanded parameter packs can and should
+    // be expanded.
+    bool Expand = true;
+    bool RetainExpansion = false;
+    llvm::Optional<unsigned> OrigNumExpansions
+      = ExpansionTL.getTypePtr()->getNumExpansions();
+    llvm::Optional<unsigned> NumExpansions = OrigNumExpansions;
+    if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(),
+                                             PatternTL.getSourceRange(),
+                                             Unexpanded,
+                                             Expand, RetainExpansion,
+                                             NumExpansions))
+      return ExprError();
+    
+    if (!Expand) {
+      // The transform has determined that we should perform a simple
+      // transformation on the pack expansion, producing another pack 
+      // expansion.
+      Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
+      
+      TypeLocBuilder TLB;
+      TLB.reserve(From->getTypeLoc().getFullDataSize());
+
+      QualType To = getDerived().TransformType(TLB, PatternTL);
+      if (To.isNull())
+        return ExprError();
+
+      To = getDerived().RebuildPackExpansionType(To, 
+                                                 PatternTL.getSourceRange(),
+                                                 ExpansionTL.getEllipsisLoc(),
+                                                 NumExpansions);
+      if (To.isNull())
+        return ExprError();
+      
+      PackExpansionTypeLoc ToExpansionTL
+        = TLB.push<PackExpansionTypeLoc>(To);
+      ToExpansionTL.setEllipsisLoc(ExpansionTL.getEllipsisLoc());
+      Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To));
+      continue;
+    }
+
+    // Expand the pack expansion by substituting for each argument in the
+    // pack(s).
+    for (unsigned I = 0; I != *NumExpansions; ++I) {
+      Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I);
+      TypeLocBuilder TLB;
+      TLB.reserve(PatternTL.getFullDataSize());
+      QualType To = getDerived().TransformType(TLB, PatternTL);
+      if (To.isNull())
+        return ExprError();
+
+      Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To));
+    }
+    
+    if (!RetainExpansion)
+      continue;
+    
+    // If we're supposed to retain a pack expansion, do so by temporarily
+    // forgetting the partially-substituted parameter pack.
+    ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+
+    TypeLocBuilder TLB;
+    TLB.reserve(From->getTypeLoc().getFullDataSize());
+    
+    QualType To = getDerived().TransformType(TLB, PatternTL);
+    if (To.isNull())
+      return ExprError();
+    
+    To = getDerived().RebuildPackExpansionType(To, 
+                                               PatternTL.getSourceRange(),
+                                               ExpansionTL.getEllipsisLoc(),
+                                               NumExpansions);
+    if (To.isNull())
+      return ExprError();
+    
+    PackExpansionTypeLoc ToExpansionTL
+      = TLB.push<PackExpansionTypeLoc>(To);
+    ToExpansionTL.setEllipsisLoc(ExpansionTL.getEllipsisLoc());
+    Args.push_back(TLB.getTypeSourceInfo(SemaRef.Context, To));
+  }
+  
+  if (!getDerived().AlwaysRebuild() && !ArgChanged)
+    return SemaRef.Owned(E);
+
+  return getDerived().RebuildTypeTrait(E->getTrait(),
+                                       E->getLocStart(),
+                                       Args,
+                                       E->getLocEnd());
+}
+
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
index 77e45416694fed597b0506a3eb2f6c949215df43..2d308fb030a58b72075a4ef323aaba08c4d2b6ab 100644 (file)
@@ -1327,6 +1327,17 @@ void ASTStmtReader::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
   E->RhsType = GetTypeSourceInfo(Record, Idx);
 }
 
+void ASTStmtReader::VisitTypeTraitExpr(TypeTraitExpr *E) {
+  VisitExpr(E);
+  E->TypeTraitExprBits.NumArgs = Record[Idx++];
+  E->TypeTraitExprBits.Kind = Record[Idx++];
+  E->TypeTraitExprBits.Value = Record[Idx++];
+  
+  TypeSourceInfo **Args = E->getTypeSourceInfos();
+  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
+    Args[I] = GetTypeSourceInfo(Record, Idx);
+}
+
 void ASTStmtReader::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
   VisitExpr(E);
   E->ATT = (ArrayTypeTrait)Record[Idx++];
@@ -2046,6 +2057,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
       S = new (Context) BinaryTypeTraitExpr(Empty);
       break;
 
+    case EXPR_TYPE_TRAIT:
+      S = TypeTraitExpr::CreateDeserialized(Context, 
+            Record[ASTStmtReader::NumExprFields]);
+      break;
+        
     case EXPR_ARRAY_TYPE_TRAIT:
       S = new (Context) ArrayTypeTraitExpr(Empty);
       break;
index 0ba413df7224d5b6ba7ce459e152059db5e0fda1..f9c3c5de43b87f14bccd55cf8acc70d99eed1ff5 100644 (file)
@@ -1341,6 +1341,16 @@ void ASTStmtWriter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
   Code = serialization::EXPR_BINARY_TYPE_TRAIT;
 }
 
+void ASTStmtWriter::VisitTypeTraitExpr(TypeTraitExpr *E) {
+  VisitExpr(E);
+  Record.push_back(E->TypeTraitExprBits.NumArgs);
+  Record.push_back(E->TypeTraitExprBits.Kind); // FIXME: Stable encoding
+  Record.push_back(E->TypeTraitExprBits.Value);
+  for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
+    Writer.AddTypeSourceInfo(E->getArg(I), Record);
+  Code = serialization::EXPR_TYPE_TRAIT;
+}
+
 void ASTStmtWriter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
   VisitExpr(E);
   Record.push_back(E->getTrait());
index 34ad23a429edd2c62a99ec95622f2febfeba063c..a61c0272b532f9d14b629165c7a6fcf0cc7261bb 100644 (file)
@@ -478,6 +478,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::DependentScopeDeclRefExprClass:
     case Stmt::UnaryTypeTraitExprClass:
     case Stmt::BinaryTypeTraitExprClass:
+    case Stmt::TypeTraitExprClass:
     case Stmt::ArrayTypeTraitExprClass:
     case Stmt::ExpressionTraitExprClass:
     case Stmt::UnresolvedLookupExprClass:
index 89876b28eab378770486c09c85c231a34b70d931..a126b8512775cd0c1f105758860c62cf3adb366a 100644 (file)
@@ -6,6 +6,11 @@ int f(Args ...args) {
 void test() {
   int a;
   decltype(a) b;
+
+  typedef int Integer;
+  typedef float Float;
+  typedef bool Bool;
+  bool b2 = __is_trivially_constructible(Integer, Float, Bool);
 }
 
 // RUN: c-index-test -test-annotate-tokens=%s:1:1:5:1 -fno-delayed-template-parsing -std=c++11 %s | FileCheck %s
@@ -14,3 +19,9 @@ void test() {
 
 // RUN: c-index-test -test-annotate-tokens=%s:8:1:9:1 -std=c++11 %s | FileCheck -check-prefix=CHECK-DECLTYPE %s
 // CHECK-DECLTYPE: Identifier: "a" [8:12 - 8:13] DeclRefExpr=a:7:7
+
+// RUN: c-index-test -test-annotate-tokens=%s:13:1:14:1 -std=c++11 %s | FileCheck -check-prefix=CHECK-TRAIT %s
+// CHECK-TRAIT: Identifier: "Integer" [13:42 - 13:49] TypeRef=Integer:10:15
+// CHECK-TRAIT: Identifier: "Float" [13:51 - 13:56] TypeRef=Float:11:17
+// CHECK-TRAIT: Identifier: "Bool" [13:58 - 13:62] TypeRef=Bool:12:16
+
index 69c64758aea69a2bfdc989e483acfd0dcf643152..3df34794f2e231535fd5e596ff61c5f5aef008ec 100644 (file)
@@ -1,8 +1,11 @@
 // Test this without pch.
-// RUN: %clang_cc1 -include %S/cxx-traits.h -fsyntax-only -verify %s
+// RUN: %clang_cc1 -include %S/cxx-traits.h -std=c++11 -fsyntax-only -verify %s
 
-// RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx-traits.h
-// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s
+// RUN: %clang_cc1 -x c++-header -std=c++11 -emit-pch -o %t %S/cxx-traits.h
+// RUN: %clang_cc1 -std=c++11 -include-pch %t -fsyntax-only -verify %s
 
 bool _Is_pod_comparator = __is_pod<int>::__value;
 bool _Is_empty_check = __is_empty<int>::__value;
+
+bool default_construct_int = is_trivially_constructible<int>::value;
+bool copy_construct_int = is_trivially_constructible<int, const int&>::value;
index 62722ab1793abbec409b27154b7a8217e90ae534..8b62002789d6f829294534f14ad2ded9c97c1b69 100644 (file)
@@ -9,3 +9,8 @@ template<typename _Tp>
 struct __is_empty {
   enum { __value };
 };
+
+template<typename T, typename ...Args>
+struct is_trivially_constructible {
+  static const bool value = __is_trivially_constructible(T, Args...);
+};
index 50c135d0b7ad517ea92ba2ac53802695871732ba..fd41c17ab2768436046f85f2ac2f88c41ab6cc0e 100644 (file)
@@ -47,6 +47,10 @@ struct TrivialMoveButNotCopy {
   TrivialMoveButNotCopy &operator=(TrivialMoveButNotCopy&&) = default;
   TrivialMoveButNotCopy &operator=(const TrivialMoveButNotCopy&);
 };
+struct NonTrivialDefault {
+  NonTrivialDefault();
+};
+
 struct HasDest { ~HasDest(); };
 class  HasPriv { int priv; };
 class  HasProt { protected: int prot; };
@@ -104,6 +108,10 @@ class AllPrivate {
   ~AllPrivate() throw();
 };
 
+struct ThreeArgCtor {
+  ThreeArgCtor(int*, char*, int);
+};
+
 void is_pod()
 {
   { int arr[T(__is_pod(int))]; }
@@ -1602,7 +1610,7 @@ void is_trivial()
   { int arr[F(__is_trivial(cvoid))]; }
 }
 
-void is_trivially_copyable()
+void trivial_checks()
 {
   { int arr[T(__is_trivially_copyable(int))]; }
   { int arr[T(__is_trivially_copyable(Enum))]; }
@@ -1646,6 +1654,25 @@ void is_trivially_copyable()
   { int arr[F(__is_trivially_copyable(void))]; }
   { int arr[F(__is_trivially_copyable(cvoid))]; }
 
+  { int arr[T((__is_trivially_constructible(int)))]; }
+  { int arr[T((__is_trivially_constructible(int, int)))]; }
+  { int arr[T((__is_trivially_constructible(int, float)))]; }
+  { int arr[T((__is_trivially_constructible(int, int&)))]; }
+  { int arr[T((__is_trivially_constructible(int, const int&)))]; }
+  { int arr[T((__is_trivially_constructible(int, int)))]; }
+  { int arr[T((__is_trivially_constructible(HasCopyAssign, HasCopyAssign)))]; }
+  { int arr[T((__is_trivially_constructible(HasCopyAssign, const HasCopyAssign&)))]; }
+  { int arr[T((__is_trivially_constructible(HasCopyAssign, HasCopyAssign&&)))]; }
+  { int arr[T((__is_trivially_constructible(HasCopyAssign)))]; }
+  { int arr[T((__is_trivially_constructible(NonTrivialDefault,
+                                            const NonTrivialDefault&)))]; }
+  { int arr[T((__is_trivially_constructible(NonTrivialDefault,
+                                            NonTrivialDefault&&)))]; }
+
+  { int arr[F((__is_trivially_constructible(int, int*)))]; }
+  { int arr[F((__is_trivially_constructible(NonTrivialDefault)))]; }
+  { int arr[F((__is_trivially_constructible(ThreeArgCtor, int*, char*, int&)))]; }
+
   { int arr[T((__is_trivially_assignable(int&, int)))]; }
   { int arr[T((__is_trivially_assignable(int&, int&)))]; }
   { int arr[T((__is_trivially_assignable(int&, int&&)))]; }
@@ -1680,6 +1707,33 @@ void is_trivially_copyable()
                                          TrivialMoveButNotCopy&&)))]; }
 }
 
+// Instantiation of __is_trivially_constructible
+template<typename T, typename ...Args>
+struct is_trivially_constructible {
+  static const bool value = __is_trivially_constructible(T, Args...);
+};
+
+void is_trivially_constructible_test() {
+  { int arr[T((is_trivially_constructible<int>::value))]; }
+  { int arr[T((is_trivially_constructible<int, int>::value))]; }
+  { int arr[T((is_trivially_constructible<int, float>::value))]; }
+  { int arr[T((is_trivially_constructible<int, int&>::value))]; }
+  { int arr[T((is_trivially_constructible<int, const int&>::value))]; }
+  { int arr[T((is_trivially_constructible<int, int>::value))]; }
+  { int arr[T((is_trivially_constructible<HasCopyAssign, HasCopyAssign>::value))]; }
+  { int arr[T((is_trivially_constructible<HasCopyAssign, const HasCopyAssign&>::value))]; }
+  { int arr[T((is_trivially_constructible<HasCopyAssign, HasCopyAssign&&>::value))]; }
+  { int arr[T((is_trivially_constructible<HasCopyAssign>::value))]; }
+  { int arr[T((is_trivially_constructible<NonTrivialDefault,
+                                            const NonTrivialDefault&>::value))]; }
+  { int arr[T((is_trivially_constructible<NonTrivialDefault,
+                                            NonTrivialDefault&&>::value))]; }
+
+  { int arr[F((is_trivially_constructible<int, int*>::value))]; }
+  { int arr[F((is_trivially_constructible<NonTrivialDefault>::value))]; }
+  { int arr[F((is_trivially_constructible<ThreeArgCtor, int*, char*, int&>::value))]; }
+}
+
 void array_rank() {
   int t01[T(__array_rank(IntAr) == 1)];
   int t02[T(__array_rank(ConstIntArAr) == 2)];
index 8d0f5fa76f1c6f3b5277b9e28cca09bf35af334c..53c7634d46e9471e11ae16a357b755b6775a61e4 100644 (file)
@@ -1755,6 +1755,7 @@ public:
   void VisitWhileStmt(WhileStmt *W);
   void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
   void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
+  void VisitTypeTraitExpr(TypeTraitExpr *E);
   void VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E);
   void VisitExpressionTraitExpr(ExpressionTraitExpr *E);
   void VisitUnresolvedMemberExpr(UnresolvedMemberExpr *U);
@@ -2056,6 +2057,11 @@ void EnqueueVisitor::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
   AddTypeLoc(E->getLhsTypeSourceInfo());
 }
 
+void EnqueueVisitor::VisitTypeTraitExpr(TypeTraitExpr *E) {
+  for (unsigned I = E->getNumArgs(); I > 0; --I)
+    AddTypeLoc(E->getArg(I-1));
+}
+
 void EnqueueVisitor::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
   AddTypeLoc(E->getQueriedTypeSourceInfo());
 }
index 531e70e17ada8e9d11ef16aa1736f90a2b5902e3..1adf552683dc993dc50649f8346f8a0f0b0d3f51 100644 (file)
@@ -206,6 +206,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, CXTranslationUnit TU,
   case Stmt::AtomicExprClass:
   case Stmt::BinaryConditionalOperatorClass:
   case Stmt::BinaryTypeTraitExprClass:
+  case Stmt::TypeTraitExprClass:
   case Stmt::CXXBindTemporaryExprClass:
   case Stmt::CXXDefaultArgExprClass:
   case Stmt::CXXScalarValueInitExprClass: