AMDG
The attached patch implements __is_base_of and __is_convertible_to.
These are the last intrinsics required to compile the <type_traits> header
that ships with MSVC 10.0.
In Christ,
Steven Watanabe
Index: tools/clang/test/SemaCXX/type-traits.cpp
===================================================================
--- tools/clang/test/SemaCXX/type-traits.cpp (revision 114230)
+++ tools/clang/test/SemaCXX/type-traits.cpp (working copy)
@@ -434,3 +434,66 @@
int t22[F(__has_virtual_destructor(void))];
int t23[F(__has_virtual_destructor(cvoid))];
}
+
+struct Base {};
+struct VirtualBase {};
+struct VirtDerived : virtual VirtualBase {};
+struct PrivateDerived : private Base {};
+
+struct D1 : Base {};
+struct D2 : Base {};
+struct AmbiguousDerived : D1, D2 {};
+struct MultipleDerived : AmbiguousDerived, private VirtDerived {};
+
+// Make sure that type-traits work in a dependent context,
+// since they're evaluated eagerly.
+template<class T1, class T2>
+struct test_is_base_of {
+ static const bool value = __is_base_of(T1, T2);
+};
+
+void is_base_of() {
+ int t01[F(__is_base_of(Int, Int))];
+ int t02[T(__is_base_of(POD, Derives))];
+ int t03[T(__is_base_of(POD, POD))];
+ int t04[T(__is_base_of(const POD, volatile POD))];
+ int t05[T(__is_base_of(VirtualBase, VirtDerived))];
+ int t06[T(__is_base_of(Base, PrivateDerived))];
+ int t07[T(__is_base_of(Base, D1))];
+ int t08[T(__is_base_of(Base, AmbiguousDerived))];
+ int t09[T(__is_base_of(VirtualBase, MultipleDerived))];
+ int t10[T(__is_base_of(POD, const Derives))];
+ int t11[T(__is_base_of(const POD, Derives))];
+ int t12[F(__is_base_of(POD&, Derives&))];
+ int t13[F(__is_base_of(POD*, Derives*))];
+ int t14[F(__is_base_of(Union, Union))];
+ int t15[T((test_is_base_of<Base, D1>::value))];
+}
+
+struct FromInt { FromInt(int); };
+struct ToInt { operator int(); };
+typedef void Function();
+
+void is_convertible_to() {
+ int t01[T(__is_convertible_to(Int, Int))];
+ int t02[F(__is_convertible_to(Int, IntAr))];
+ int t03[F(__is_convertible_to(IntAr, IntAr))];
+ int t04[T(__is_convertible_to(void, void))];
+ int t05[T(__is_convertible_to(cvoid, void))];
+ int t06[T(__is_convertible_to(void, cvoid))];
+ int t07[T(__is_convertible_to(cvoid, cvoid))];
+ int t08[T(__is_convertible_to(int, FromInt))];
+ int t09[T(__is_convertible_to(long, FromInt))];
+ int t10[T(__is_convertible_to(double, FromInt))];
+ int t11[T(__is_convertible_to(const int, FromInt))];
+ int t12[T(__is_convertible_to(const int&, FromInt))];
+ int t13[T(__is_convertible_to(ToInt, int))];
+ int t14[T(__is_convertible_to(ToInt, const int&))];
+ int t15[T(__is_convertible_to(ToInt, long))];
+ int t16[F(__is_convertible_to(ToInt, int&))];
+ int t17[F(__is_convertible_to(ToInt, FromInt))];
+ int t18[T(__is_convertible_to(IntAr&, IntAr&))];
+ int t19[T(__is_convertible_to(IntAr&, const IntAr&))];
+ int t20[F(__is_convertible_to(const IntAr&, IntAr&))];
+ int t21[T(__is_convertible_to(Function, Function))];
+}
Index: tools/clang/include/clang/Basic/StmtNodes.td
===================================================================
--- tools/clang/include/clang/Basic/StmtNodes.td (revision 114230)
+++ tools/clang/include/clang/Basic/StmtNodes.td (working copy)
@@ -100,6 +100,7 @@
def CXXDeleteExpr : DStmt<Expr>;
def CXXPseudoDestructorExpr : DStmt<Expr>;
def UnaryTypeTraitExpr : DStmt<Expr>;
+def BinaryTypeTraitExpr : DStmt<Expr>;
def DependentScopeDeclRefExpr : DStmt<Expr>;
def CXXConstructExpr : DStmt<Expr>;
def CXXBindTemporaryExpr : DStmt<Expr>;
@@ -132,3 +133,5 @@
// Microsoft Extensions.
def CXXUuidofExpr : DStmt<Expr>;
+// Internal Helper.
+def DummyExpr : DStmt<Expr>;
Index: tools/clang/include/clang/Basic/TypeTraits.h
===================================================================
--- tools/clang/include/clang/Basic/TypeTraits.h (revision 114230)
+++ tools/clang/include/clang/Basic/TypeTraits.h (working copy)
@@ -36,6 +36,12 @@
UTT_IsLiteral
};
+ /// BinaryTypeTrait - Names for the binary type traits
+ enum BinaryTypeTrait {
+ BTT_IsBaseOf,
+ BTT_IsConvertibleTo
+ };
+
}
#endif
Index: tools/clang/include/clang/Basic/TokenKinds.def
===================================================================
--- tools/clang/include/clang/Basic/TokenKinds.def (revision 114230)
+++ tools/clang/include/clang/Basic/TokenKinds.def (working copy)
@@ -322,6 +322,7 @@
KEYWORD(__is_pod , KEYCXX)
KEYWORD(__is_polymorphic , KEYCXX)
KEYWORD(__is_union , KEYCXX)
+KEYWORD(__is_convertible_to , KEYCXX)
// Tentative name - there's no implementation of std::is_literal_type yet.
KEYWORD(__is_literal , KEYCXX)
// FIXME: Add MS's traits, too.
Index: tools/clang/include/clang/Sema/Sema.h
===================================================================
--- tools/clang/include/clang/Sema/Sema.h (revision 114230)
+++ tools/clang/include/clang/Sema/Sema.h (working copy)
@@ -2276,6 +2276,18 @@
TypeSourceInfo *T,
SourceLocation RParen);
+ ExprResult ActOnBinaryTypeTrait(BinaryTypeTrait OTT,
+ SourceLocation KWLoc,
+ ParsedType Ty1,
+ ParsedType Ty2,
+ SourceLocation RParen);
+
+ ExprResult BuildBinaryTypeTrait(BinaryTypeTrait OTT,
+ SourceLocation KWLoc,
+ TypeSourceInfo *T1,
+ TypeSourceInfo *T2,
+ SourceLocation RParen);
+
ExprResult ActOnStartCXXMemberReference(Scope *S,
Expr *Base,
SourceLocation OpLoc,
Index: tools/clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- tools/clang/include/clang/AST/RecursiveASTVisitor.h (revision 114230)
+++ tools/clang/include/clang/AST/RecursiveASTVisitor.h (working copy)
@@ -1785,6 +1785,11 @@
TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
})
+DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, {
+ TRY_TO(TraverseType(S->getQueriedType(0)));
+ TRY_TO(TraverseType(S->getQueriedType(1)));
+ })
+
// These exprs (most of them), do not need any action except iterating
// over the children.
DEF_TRAVERSE_STMT(AddrLabelExpr, { })
@@ -1854,6 +1859,8 @@
DEF_TRAVERSE_STMT(StringLiteral, { })
DEF_TRAVERSE_STMT(ObjCStringLiteral, { })
+DEF_TRAVERSE_STMT(DummyExpr, { })
+
// FIXME: look at the following tricky-seeming exprs to see if we
// need to recurse on anything. These are ones that have methods
// returning decls or qualtypes or nestednamespecifier -- though I'm
Index: tools/clang/include/clang/AST/Expr.h
===================================================================
--- tools/clang/include/clang/AST/Expr.h (revision 114230)
+++ tools/clang/include/clang/AST/Expr.h (working copy)
@@ -3500,6 +3500,28 @@
virtual child_iterator child_end();
};
+class DummyExpr : public Expr {
+
+ Classification::Kinds Kind;
+
+public:
+ DummyExpr(QualType T, Classification::Kinds kind)
+ : Expr(DummyExprClass, T, false, false), Kind(kind) {}
+
+ virtual SourceRange getSourceRange() const { return SourceRange(); }
+
+ Classification::Kinds getKind() const { return Kind; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == DummyExprClass;
+ }
+ static bool classof(const DummyExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+};
+
} // end namespace clang
#endif
Index: tools/clang/include/clang/AST/ExprCXX.h
===================================================================
--- tools/clang/include/clang/AST/ExprCXX.h (revision 114230)
+++ tools/clang/include/clang/AST/ExprCXX.h (working copy)
@@ -1421,6 +1421,63 @@
friend class ASTStmtReader;
};
+/// BinaryTypeTraitExpr - A GCC or MS unary type trait, as used in the
+/// implementation of TR1/C++0x type trait templates.
+/// Example:
+class BinaryTypeTraitExpr : public Expr {
+ /// BTT - The trait.
+ unsigned BTT : 31;
+
+ /// The value of the type trait. Unspecified if dependent.
+ unsigned Value : 1;
+
+ /// Loc - The location of the type trait keyword.
+ SourceLocation Loc;
+
+ /// RParen - The location of the closing paren.
+ SourceLocation RParen;
+
+ TypeSourceInfo *QueriedTypes[2];
+
+public:
+ BinaryTypeTraitExpr(SourceLocation loc, BinaryTypeTrait btt,
+ TypeSourceInfo *queried1, TypeSourceInfo *queried2,
+ bool value, SourceLocation rparen, QualType ty)
+ : Expr(BinaryTypeTraitExprClass, ty, false,
+ queried1->getType()->isDependentType() ||
+ queried2->getType()->isDependentType()),
+ BTT(btt), Value(value), Loc(loc), RParen(rparen) {
+ QueriedTypes[0] = queried1;
+ QueriedTypes[1] = queried2;
+ }
+
+ explicit BinaryTypeTraitExpr(EmptyShell Empty)
+ : Expr(BinaryTypeTraitExprClass, Empty), BTT(0), Value(false) { }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen);}
+
+ BinaryTypeTrait getTrait() const { return static_cast<BinaryTypeTrait>(BTT); }
+
+ QualType getQueriedType(int n) const { return QueriedTypes[n]->getType(); }
+ TypeSourceInfo *getQueriedTypeSourceInfo(int n) const {
+ return QueriedTypes[n];
+ }
+
+ bool getValue() const { return Value; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BinaryTypeTraitExprClass;
+ }
+ static bool classof(const BinaryTypeTraitExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+
+ friend class ASTStmtReader;
+};
+
+
/// \brief A reference to an overloaded function set, either an
/// \t UnresolvedLookupExpr or an \t UnresolvedMemberExpr.
class OverloadExpr : public Expr {
Index: tools/clang/include/clang/Parse/Parser.h
===================================================================
--- tools/clang/include/clang/Parse/Parser.h (revision 114230)
+++ tools/clang/include/clang/Parse/Parser.h (working copy)
@@ -1566,6 +1566,7 @@
//===--------------------------------------------------------------------===//
// GNU G++: Type Traits [Type-Traits.html in the GCC manual]
ExprResult ParseUnaryTypeTrait();
+ ExprResult ParseBinaryTypeTrait();
//===--------------------------------------------------------------------===//
// Preprocessor code-completion pass-through
Index: tools/clang/include/clang/Serialization/ASTBitCodes.h
===================================================================
--- tools/clang/include/clang/Serialization/ASTBitCodes.h (revision 114230)
+++ tools/clang/include/clang/Serialization/ASTBitCodes.h (working copy)
@@ -899,6 +899,7 @@
EXPR_CXX_UNRESOLVED_LOOKUP, // UnresolvedLookupExpr
EXPR_CXX_UNARY_TYPE_TRAIT, // UnaryTypeTraitExpr
+ EXPR_CXX_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr
EXPR_CXX_NOEXCEPT // CXXNoexceptExpr
};
Index: tools/clang/tools/libclang/CXCursor.cpp
===================================================================
--- tools/clang/tools/libclang/CXCursor.cpp (revision 114230)
+++ tools/clang/tools/libclang/CXCursor.cpp (working copy)
@@ -141,6 +141,7 @@
case Stmt::CXXPseudoDestructorExprClass:
case Stmt::UnresolvedLookupExprClass:
case Stmt::UnaryTypeTraitExprClass:
+ case Stmt::BinaryTypeTraitExprClass:
case Stmt::DependentScopeDeclRefExprClass:
case Stmt::CXXBindTemporaryExprClass:
case Stmt::CXXExprWithTemporariesClass:
Index: tools/clang/tools/libclang/CIndex.cpp
===================================================================
--- tools/clang/tools/libclang/CIndex.cpp (revision 114230)
+++ tools/clang/tools/libclang/CIndex.cpp (working copy)
@@ -390,6 +390,7 @@
bool VisitCXXNewExpr(CXXNewExpr *E);
bool VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
bool VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
+ bool VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
bool VisitOverloadExpr(OverloadExpr *E);
bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
bool VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E);
@@ -1787,6 +1788,11 @@
return Visit(E->getQueriedTypeSourceInfo()->getTypeLoc());
}
+bool CursorVisitor::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+ return Visit(E->getQueriedTypeSourceInfo(0)->getTypeLoc());
+ return Visit(E->getQueriedTypeSourceInfo(1)->getTypeLoc());
+}
+
bool CursorVisitor::VisitOverloadExpr(OverloadExpr *E) {
// Visit the nested-name-specifier.
if (NestedNameSpecifier *Qualifier = E->getQualifier())
Index: tools/clang/lib/Sema/TreeTransform.h
===================================================================
--- tools/clang/lib/Sema/TreeTransform.h (revision 114230)
+++ tools/clang/lib/Sema/TreeTransform.h (working copy)
@@ -1646,6 +1646,19 @@
return getSema().BuildUnaryTypeTrait(Trait, StartLoc, T, RParenLoc);
}
+ /// \brief Build a new binary type trait expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildBinaryTypeTrait(BinaryTypeTrait Trait,
+ SourceLocation StartLoc,
+ TypeSourceInfo *T1,
+ TypeSourceInfo *T2,
+ SourceLocation RParenLoc) {
+ return getSema().BuildBinaryTypeTrait(Trait, StartLoc,
+ T1, T2, RParenLoc);
+ }
+
/// \brief Build a new (previously unresolved) declaration reference
/// expression.
///
@@ -5595,6 +5608,28 @@
template<typename Derived>
ExprResult
+TreeTransform<Derived>::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+ TypeSourceInfo *T1 =
+ getDerived().TransformType(E->getQueriedTypeSourceInfo(0));
+ TypeSourceInfo *T2 =
+ getDerived().TransformType(E->getQueriedTypeSourceInfo(1));
+ if (!T1 || !T2)
+ return ExprError();
+
+ if (!getDerived().AlwaysRebuild() &&
+ T1 == E->getQueriedTypeSourceInfo(0) &&
+ T2 == E->getQueriedTypeSourceInfo(1))
+ return SemaRef.Owned(E->Retain());
+
+ return getDerived().RebuildBinaryTypeTrait(E->getTrait(),
+ E->getLocStart(),
+ T1,
+ T2,
+ E->getLocEnd());
+}
+
+template<typename Derived>
+ExprResult
TreeTransform<Derived>::TransformDependentScopeDeclRefExpr(
DependentScopeDeclRefExpr *E) {
NestedNameSpecifier *NNS
@@ -6292,6 +6327,12 @@
ND, NameInfo, 0);
}
+template<typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformDummyExpr(DummyExpr *E) {
+ return SemaRef.Owned(E->Retain());
+}
+
//===----------------------------------------------------------------------===//
// Type reconstruction
//===----------------------------------------------------------------------===//
Index: tools/clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- tools/clang/lib/Sema/SemaExprCXX.cpp (revision 114230)
+++ tools/clang/lib/Sema/SemaExprCXX.cpp (working copy)
@@ -1996,6 +1996,15 @@
return false;
}
+static bool CheckTypeTraitArgument(Sema& S, QualType T, SourceLocation KWLoc) {
+ QualType E = T;
+ if (T->isIncompleteArrayType())
+ E = S.getASTContext().getAsArrayType(T)->getElementType();
+ return !T->isVoidType() &&
+ S.RequireCompleteType(KWLoc, E,
+ diag::err_incomplete_type_used_in_type_trait_expr);
+}
+
ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT,
SourceLocation KWLoc,
ParsedType Ty,
@@ -2234,12 +2243,7 @@
// 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) {
- QualType E = T;
- if (T->isIncompleteArrayType())
- E = Context.getAsArrayType(T)->getElementType();
- if (!T->isVoidType() &&
- RequireCompleteType(KWLoc, E,
- diag::err_incomplete_type_used_in_type_trait_expr))
+ if (CheckTypeTraitArgument(*this, T, KWLoc))
return ExprError();
}
@@ -2251,6 +2255,82 @@
RParen, Context.BoolTy));
}
+static bool EvaluateBinaryTypeTrait(Sema& S,
+ BinaryTypeTrait BTT,
+ QualType T1,
+ QualType T2) {
+ assert(!T1->isDependentType() && !T2->isDependentType() &&
+ "Cannot evaluate traits for dependent types.");
+ switch(BTT) {
+ default: assert(false && "Unknown type trait or not implemented");
+ case BTT_IsBaseOf:
+ if (const RecordType *Base = T1->getAs<RecordType>()) {
+ if (const RecordType *Derived = T2->getAs<RecordType>()) {
+ CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(Base->getDecl());
+ CXXRecordDecl *DerivedDecl = cast<CXXRecordDecl>(Derived->getDecl());
+ return DerivedDecl->isDerivedFrom(BaseDecl) ||
+ (!DerivedDecl->isUnion() && DerivedDecl == BaseDecl);
+ }
+ }
+ return false;
+ case BTT_IsConvertibleTo:
+ InitializedEntity To(InitializedEntity::InitializeTemporary(T2));
+ Expr::Classification::Kinds Classification = T1->isLValueReferenceType()?
+ Expr::Classification::CL_LValue :
+ Expr::Classification::CL_PRValue;
+ DummyExpr From(T1.getNonReferenceType(), Classification);
+ Expr *FromPtr = &From;
+ InitializationKind Kind(
+ InitializationKind::CreateCopy(SourceLocation(), SourceLocation()));
+ InitializationSequence Init(S, To, Kind, &FromPtr, 1);
+ return Init;
+ }
+}
+
+ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait OTT,
+ SourceLocation KWLoc,
+ ParsedType Ty1,
+ ParsedType Ty2,
+ SourceLocation RParen) {
+
+ TypeSourceInfo *TSInfo1;
+ TypeSourceInfo *TSInfo2;
+ QualType T1 = GetTypeFromParser(Ty1, &TSInfo1);
+ QualType T2 = GetTypeFromParser(Ty2, &TSInfo2);
+
+ if (!TSInfo1)
+ TSInfo1 = Context.getTrivialTypeSourceInfo(T1);
+
+ if (!TSInfo2)
+ TSInfo2 = Context.getTrivialTypeSourceInfo(T2);
+
+ return BuildBinaryTypeTrait(OTT, KWLoc, TSInfo1, TSInfo2, RParen);
+}
+
+ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait OTT,
+ SourceLocation KWLoc,
+ TypeSourceInfo *TSInfo1,
+ TypeSourceInfo *TSInfo2,
+ SourceLocation RParen) {
+ QualType T1 = TSInfo1->getType();
+ QualType T2 = TSInfo2->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 (CheckTypeTraitArgument(*this, T1, KWLoc) ||
+ CheckTypeTraitArgument(*this, T2, KWLoc))
+ return ExprError();
+
+ bool Value = false;
+
+ if (!T1->isDependentType() && !T2->isDependentType())
+ Value = EvaluateBinaryTypeTrait(*this, OTT, T1, T2);
+
+ return Owned(new (Context) BinaryTypeTraitExpr(KWLoc, OTT, TSInfo1, TSInfo2,
+ Value, RParen, Context.BoolTy));
+}
+
QualType Sema::CheckPointerToMemberOperands(
Expr *&lex, Expr *&rex, SourceLocation Loc, bool isIndirect) {
const char *OpSpelling = isIndirect ? "->*" : ".*";
Index: tools/clang/lib/AST/ExprCXX.cpp
===================================================================
--- tools/clang/lib/AST/ExprCXX.cpp (revision 114230)
+++ tools/clang/lib/AST/ExprCXX.cpp (working copy)
@@ -295,6 +295,13 @@
Stmt::child_iterator UnaryTypeTraitExpr::child_end() {
return child_iterator();
}
+// UnaryTypeTraitExpr
+Stmt::child_iterator BinaryTypeTraitExpr::child_begin() {
+ return child_iterator();
+}
+Stmt::child_iterator BinaryTypeTraitExpr::child_end() {
+ return child_iterator();
+}
// DependentScopeDeclRefExpr
DependentScopeDeclRefExpr *
Property changes on: tools\clang\lib\AST\ExprCXX.cpp
___________________________________________________________________
Added: svn:eol-style
+ native
Index: tools/clang/lib/AST/ExprConstant.cpp
===================================================================
--- tools/clang/lib/AST/ExprConstant.cpp (revision 114230)
+++ tools/clang/lib/AST/ExprConstant.cpp (working copy)
@@ -951,6 +951,10 @@
return Success(E->getValue(), E);
}
+ bool VisitBinaryTypeTraitExpr(const BinaryTypeTraitExpr *E) {
+ return Success(E->getValue(), E);
+ }
+
bool VisitChooseExpr(const ChooseExpr *E) {
return Visit(E->getChosenSubExpr(Info.Ctx));
}
@@ -2447,6 +2451,7 @@
case Expr::CXXScalarValueInitExprClass:
case Expr::TypesCompatibleExprClass:
case Expr::UnaryTypeTraitExprClass:
+ case Expr::BinaryTypeTraitExprClass:
case Expr::CXXNoexceptExprClass:
return NoDiag();
case Expr::CallExprClass:
Index: tools/clang/lib/AST/StmtPrinter.cpp
===================================================================
--- tools/clang/lib/AST/StmtPrinter.cpp (revision 114230)
+++ tools/clang/lib/AST/StmtPrinter.cpp (working copy)
@@ -1230,11 +1230,25 @@
}
}
+static const char *getTypeTraitName(BinaryTypeTrait BTT) {
+ switch (BTT) {
+ default: assert(false && "Unknown type trait");
+ case BTT_IsBaseOf: return "__is_base_of";
+ case BTT_IsConvertibleTo: return "__is_convertible_to";
+ }
+}
+
void StmtPrinter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
OS << getTypeTraitName(E->getTrait()) << "("
<< E->getQueriedType().getAsString(Policy) << ")";
}
+void StmtPrinter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+ OS << getTypeTraitName(E->getTrait()) << "("
+ << E->getQueriedType(0).getAsString(Policy) << ","
+ << E->getQueriedType(1).getAsString(Policy) << ")";
+}
+
void StmtPrinter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
OS << "noexcept(";
PrintExpr(E->getOperand());
@@ -1333,6 +1347,10 @@
void StmtPrinter::VisitBlockDeclRefExpr(BlockDeclRefExpr *Node) {
OS << Node->getDecl();
}
+
+void StmtPrinter::VisitDummyExpr(DummyExpr *Node) {
+ assert(!"DummyExpr is a strictly internal feature.");
+}
//===----------------------------------------------------------------------===//
// Stmt method implementations
//===----------------------------------------------------------------------===//
Index: tools/clang/lib/AST/StmtProfile.cpp
===================================================================
--- tools/clang/lib/AST/StmtProfile.cpp (revision 114230)
+++ tools/clang/lib/AST/StmtProfile.cpp (working copy)
@@ -780,6 +780,13 @@
VisitType(S->getQueriedType());
}
+void StmtProfiler::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *S) {
+ VisitExpr(S);
+ ID.AddInteger(S->getTrait());
+ VisitType(S->getQueriedType(0));
+ VisitType(S->getQueriedType(1));
+}
+
void
StmtProfiler::VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *S) {
VisitExpr(S);
@@ -943,6 +950,10 @@
Name.Profile(ID);
}
+void StmtProfiler::VisitDummyExpr(DummyExpr *) {
+ assert(!"DummyExpr is a strictly internal feature.");
+}
+
void StmtProfiler::VisitTemplateArguments(const TemplateArgumentLoc *Args,
unsigned NumArgs) {
ID.AddInteger(NumArgs);
Index: tools/clang/lib/AST/Expr.cpp
===================================================================
--- tools/clang/lib/AST/Expr.cpp (revision 114230)
+++ tools/clang/lib/AST/Expr.cpp (working copy)
@@ -2574,3 +2574,6 @@
Stmt::child_iterator BlockDeclRefExpr::child_begin() { return child_iterator();}
Stmt::child_iterator BlockDeclRefExpr::child_end() { return child_iterator(); }
+
+Stmt::child_iterator DummyExpr::child_begin() { return child_iterator();}
+Stmt::child_iterator DummyExpr::child_end() { return child_iterator(); }
Index: tools/clang/lib/AST/ExprClassification.cpp
===================================================================
--- tools/clang/lib/AST/ExprClassification.cpp (revision 114230)
+++ tools/clang/lib/AST/ExprClassification.cpp (working copy)
@@ -119,6 +119,7 @@
case Expr::CXXNoexceptExprClass:
case Expr::CXXScalarValueInitExprClass:
case Expr::UnaryTypeTraitExprClass:
+ case Expr::BinaryTypeTraitExprClass:
case Expr::ObjCSelectorExprClass:
case Expr::ObjCProtocolExprClass:
case Expr::ObjCStringLiteralClass:
@@ -255,6 +256,9 @@
case Expr::CXXTemporaryObjectExprClass:
return Cl::CL_ClassTemporary;
+ case Expr::DummyExprClass:
+ return cast<DummyExpr>(E)->getKind();
+
case Expr::VAArgExprClass:
return ClassifyUnnamed(Ctx, E->getType());
Index: tools/clang/lib/CodeGen/CGExprScalar.cpp
===================================================================
--- tools/clang/lib/CodeGen/CGExprScalar.cpp (revision 114230)
+++ tools/clang/lib/CodeGen/CGExprScalar.cpp (working copy)
@@ -291,6 +291,9 @@
Value *VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) {
return llvm::ConstantInt::get(Builder.getInt1Ty(), E->getValue());
}
+ Value *VisitBinaryTypeTraitExpr(const BinaryTypeTraitExpr *E) {
+ return llvm::ConstantInt::get(Builder.getInt1Ty(), E->getValue());
+ }
Value *VisitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E) {
// C++ [expr.pseudo]p1:
Index: tools/clang/lib/CodeGen/Mangle.cpp
===================================================================
--- tools/clang/lib/CodeGen/Mangle.cpp (revision 114230)
+++ tools/clang/lib/CodeGen/Mangle.cpp (working copy)
@@ -1617,6 +1617,7 @@
case Expr::StmtExprClass:
case Expr::TypesCompatibleExprClass:
case Expr::UnaryTypeTraitExprClass:
+ case Expr::BinaryTypeTraitExprClass:
case Expr::VAArgExprClass:
case Expr::CXXUuidofExprClass:
case Expr::CXXNoexceptExprClass: {
Index: tools/clang/lib/Checker/GRExprEngine.cpp
===================================================================
--- tools/clang/lib/Checker/GRExprEngine.cpp (revision 114230)
+++ tools/clang/lib/Checker/GRExprEngine.cpp (working copy)
@@ -779,6 +779,7 @@
case Stmt::CXXScalarValueInitExprClass:
case Stmt::DependentScopeDeclRefExprClass:
case Stmt::UnaryTypeTraitExprClass:
+ case Stmt::BinaryTypeTraitExprClass:
case Stmt::UnresolvedLookupExprClass:
case Stmt::UnresolvedMemberExprClass:
case Stmt::CXXNoexceptExprClass:
Index: tools/clang/lib/Parse/ParseExpr.cpp
===================================================================
--- tools/clang/lib/Parse/ParseExpr.cpp (revision 114230)
+++ tools/clang/lib/Parse/ParseExpr.cpp (working copy)
@@ -488,7 +488,7 @@
/// [C++] 'typeid' '(' type-id ')' [C++ 5.2p1]
/// [C++] 'this' [C++ 9.3.2]
/// [G++] unary-type-trait '(' type-id ')'
-/// [G++] binary-type-trait '(' type-id ',' type-id ')' [TODO]
+/// [G++] binary-type-trait '(' type-id ',' type-id ')'
/// [clang] '^' block-literal
///
/// constant: [C99 6.4.4]
@@ -536,7 +536,8 @@
/// '__is_union'
///
/// [GNU] binary-type-trait:
-/// '__is_base_of' [TODO]
+/// '__is_base_of'
+/// '__is_convertible_to'
///
ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand,
@@ -988,6 +989,10 @@
case tok::kw___has_virtual_destructor:
return ParseUnaryTypeTrait();
+ case tok::kw___is_base_of:
+ case tok::kw___is_convertible_to:
+ return ParseBinaryTypeTrait();
+
case tok::at: {
SourceLocation AtLoc = ConsumeToken();
return ParseObjCAtExpression(AtLoc);
Index: tools/clang/lib/Parse/ParseExprCXX.cpp
===================================================================
--- tools/clang/lib/Parse/ParseExprCXX.cpp (revision 114230)
+++ tools/clang/lib/Parse/ParseExprCXX.cpp (working copy)
@@ -1807,6 +1807,14 @@
}
}
+static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) {
+ switch(kind) {
+ default: assert(false && "Not a known binary type trait.");
+ case tok::kw___is_base_of: return BTT_IsBaseOf;
+ case tok::kw___is_convertible_to: return BTT_IsConvertibleTo;
+ }
+}
+
/// ParseUnaryTypeTrait - Parse the built-in unary type-trait
/// pseudo-functions that allow implementation of the TR1/C++0x type traits
/// templates.
@@ -1835,6 +1843,38 @@
return Actions.ActOnUnaryTypeTrait(UTT, Loc, Ty.get(), RParen);
}
+/// ParseBinaryTypeTrait - Parse the build-in binary type-trait
+/// pseudo-functions that allow implementation of the TR1/C++0x type traits
+/// templates.
+///
+/// primary-expression:
+/// [GNU] binary-type-trait '(' type-id ',' type-id ')'
+ExprResult Parser::ParseBinaryTypeTrait() {
+ BinaryTypeTrait BTT = BinaryTypeTraitFromTokKind(Tok.getKind());
+ SourceLocation Loc = ConsumeToken();
+
+ SourceLocation LParen = Tok.getLocation();
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
+ return ExprError();
+
+ TypeResult Ty1 = ParseTypeName();
+ if (Ty1.isInvalid())
+ return ExprError();
+
+ SourceLocation Comma = Tok.getLocation();
+ if (ExpectAndConsume(tok::comma, diag::err_expected_comma))
+ return ExprError();
+
+ TypeResult Ty2 = ParseTypeName();
+ if (Ty2.isInvalid())
+ return ExprError();
+
+ SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
+
+ return Actions.ActOnBinaryTypeTrait(
+ BTT, Loc, Ty1.get(), Ty2.get(), RParen);
+}
+
/// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a
/// parenthesized ambiguous type-id. This uses tentative parsing to disambiguate
/// based on the context past the parens.
Index: tools/clang/lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- tools/clang/lib/Serialization/ASTReaderStmt.cpp (revision 114230)
+++ tools/clang/lib/Serialization/ASTReaderStmt.cpp (working copy)
@@ -156,6 +156,7 @@
void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
+ void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
};
}
@@ -1254,6 +1255,17 @@
E->QueriedType = Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx);
}
+void ASTStmtReader::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+ VisitExpr(E);
+ E->BTT = (BinaryTypeTrait)Record[Idx++];
+ E->Value = (bool)Record[Idx++];
+ SourceRange Range = Reader.ReadSourceRange(Record, Idx);
+ E->Loc = Range.getBegin();
+ E->RParen = Range.getEnd();
+ E->QueriedTypes[0] = Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx);
+ E->QueriedTypes[1] = Reader.GetTypeSourceInfo(DeclsCursor, Record, Idx);
+}
+
void ASTStmtReader::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
VisitExpr(E);
E->Value = (bool)Record[Idx++];
@@ -1773,6 +1785,10 @@
case EXPR_CXX_UNARY_TYPE_TRAIT:
S = new (Context) UnaryTypeTraitExpr(Empty);
break;
+
+ case EXPR_CXX_BINARY_TYPE_TRAIT:
+ S = new (Context) BinaryTypeTraitExpr(Empty);
+ break;
case EXPR_CXX_NOEXCEPT:
S = new (Context) CXXNoexceptExpr(Empty);
Index: tools/clang/lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- tools/clang/lib/Serialization/ASTWriterStmt.cpp (revision 114230)
+++ tools/clang/lib/Serialization/ASTWriterStmt.cpp (working copy)
@@ -152,6 +152,7 @@
void VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E);
void VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E);
+ void VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E);
void VisitCXXNoexceptExpr(CXXNoexceptExpr *E);
};
}
@@ -1286,6 +1287,16 @@
Code = serialization::EXPR_CXX_UNARY_TYPE_TRAIT;
}
+void ASTStmtWriter::VisitBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->getTrait());
+ Record.push_back(E->getValue());
+ Writer.AddSourceRange(E->getSourceRange(), Record);
+ Writer.AddTypeSourceInfo(E->getQueriedTypeSourceInfo(0), Record);
+ Writer.AddTypeSourceInfo(E->getQueriedTypeSourceInfo(1), Record);
+ Code = serialization::EXPR_CXX_BINARY_TYPE_TRAIT;
+}
+
void ASTStmtWriter::VisitCXXNoexceptExpr(CXXNoexceptExpr *E) {
VisitExpr(E);
Record.push_back(E->getValue());
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits