[cfe-commits] r61746 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Parse/ lib/AST/ lib/Parse/ lib/Sema/ test/SemaCXX/
Sebastian Redl
sebastian.redl at getdesigned.at
Mon Jan 5 12:52:14 PST 2009
Author: cornedbee
Date: Mon Jan 5 14:52:13 2009
New Revision: 61746
URL: http://llvm.org/viewvc/llvm-project?rev=61746&view=rev
Log:
PODness and Type Traits
Make C++ classes track the POD property (C++ [class]p4)
Track the existence of a copy assignment operator.
Implicitly declare the copy assignment operator if none is provided.
Implement most of the parsing job for the G++ type traits extension.
Fully implement the low-hanging fruit of the type traits:
__is_pod: Whether a type is a POD.
__is_class: Whether a type is a (non-union) class.
__is_union: Whether a type is a union.
__is_enum: Whether a type is an enum.
__is_polymorphic: Whether a type is polymorphic (C++ [class.virtual]p1).
Added:
cfe/trunk/include/clang/Basic/TypeTraits.h
cfe/trunk/test/SemaCXX/type-traits.cpp
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/AST/ExprCXX.h
cfe/trunk/include/clang/AST/StmtNodes.def
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/Basic/TokenKinds.def
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/AST/ExprCXX.cpp
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/lib/AST/StmtPrinter.cpp
cfe/trunk/lib/AST/StmtSerialization.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Parse/ParseExprCXX.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Jan 5 14:52:13 2009
@@ -22,6 +22,7 @@
class CXXConstructorDecl;
class CXXDestructorDecl;
class CXXConversionDecl;
+class CXXMethodDecl;
/// TemplateTypeParmDecl - Declaration of a template type parameter,
/// e.g., "T" in
@@ -263,6 +264,10 @@
/// user-declared copy constructor.
bool UserDeclaredCopyConstructor : 1;
+ /// UserDeclaredCopyAssignment - True when this class has a
+ /// user-declared copy assignment operator.
+ bool UserDeclaredCopyAssignment : 1;
+
/// UserDeclaredDestructor - True when this class has a
/// user-declared destructor.
bool UserDeclaredDestructor : 1;
@@ -270,6 +275,9 @@
/// Aggregate - True when this class is an aggregate.
bool Aggregate : 1;
+ /// PlainOldData - True when this class is a POD-type.
+ bool PlainOldData : 1;
+
/// Polymorphic - True when this class is polymorphic, i.e. has at least one
/// virtual member or derives from a polymorphic class.
bool Polymorphic : 1;
@@ -321,6 +329,10 @@
/// copy constructor that accepts a const-qualified argument.
bool hasConstCopyConstructor(ASTContext &Context) const;
+ /// hasConstCopyAssignment - Determines whether this class has a
+ /// copy assignment operator that accepts a const-qualified argument.
+ bool hasConstCopyAssignment(ASTContext &Context) const;
+
/// addedConstructor - Notify the class that another constructor has
/// been added. This routine helps maintain information about the
/// class based on which constructors have been added.
@@ -338,6 +350,18 @@
return UserDeclaredCopyConstructor;
}
+ /// addedAssignmentOperator - Notify the class that another assignment
+ /// operator has been added. This routine helps maintain information about the
+ /// class based on which operators have been added.
+ void addedAssignmentOperator(ASTContext &Context, CXXMethodDecl *OpDecl);
+
+ /// hasUserDeclaredCopyAssignment - Whether this class has a
+ /// user-declared copy assignment operator. When false, a copy
+ /// assigment operator will be implicitly declared.
+ bool hasUserDeclaredCopyAssignment() const {
+ return UserDeclaredCopyAssignment;
+ }
+
/// hasUserDeclaredDestructor - Whether this class has a
/// user-declared destructor. When false, a destructor will be
/// implicitly declared.
@@ -373,6 +397,15 @@
/// [dcl.init.aggr]).
void setAggregate(bool Agg) { Aggregate = Agg; }
+ /// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class
+ /// that is an aggregate that has no non-static non-POD data members, no
+ /// reference data members, no user-defined copy assignment operator and no
+ /// user-defined destructor.
+ bool isPOD() const { return PlainOldData; }
+
+ /// setPOD - Set whether this class is a POD-type (C++ [class]p4).
+ void setPOD(bool POD) { PlainOldData = POD; }
+
/// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]),
/// which means that the class contains or inherits a virtual function.
bool isPolymorphic() const { return Polymorphic; }
Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Mon Jan 5 14:52:13 2009
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_EXPRCXX_H
#define LLVM_CLANG_AST_EXPRCXX_H
+#include "clang/Basic/TypeTraits.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
@@ -701,6 +702,51 @@
static CXXDependentNameExpr *CreateImpl(llvm::Deserializer& D, ASTContext& C);
};
+/// UnaryTypeTraitExpr - A GCC or MS unary type trait, as used in the
+/// implementation of TR1/C++0x type trait templates.
+/// Example:
+/// __is_pod(int) == true
+/// __is_enum(std::string) == false
+class UnaryTypeTraitExpr : public Expr {
+ /// UTT - The trait.
+ UnaryTypeTrait UTT;
+
+ /// Loc - The location of the type trait keyword.
+ SourceLocation Loc;
+
+ /// RParen - The location of the closing paren.
+ SourceLocation RParen;
+
+ /// QueriedType - The type we're testing.
+ QualType QueriedType;
+
+public:
+ UnaryTypeTraitExpr(SourceLocation loc, UnaryTypeTrait utt, QualType queried,
+ SourceLocation rparen, QualType ty)
+ : Expr(UnaryTypeTraitExprClass, ty, false, queried->isDependentType()),
+ UTT(utt), Loc(loc), RParen(rparen), QueriedType(queried) { }
+
+ virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen);}
+
+ UnaryTypeTrait getTrait() const { return UTT; }
+
+ QualType getQueriedType() const { return QueriedType; }
+
+ bool Evaluate() const;
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == UnaryTypeTraitExprClass;
+ }
+ static bool classof(const UnaryTypeTraitExpr *) { return true; }
+
+ // Iterators
+ virtual child_iterator child_begin();
+ virtual child_iterator child_end();
+
+ virtual void EmitImpl(llvm::Serializer& S) const;
+ static UnaryTypeTraitExpr *CreateImpl(llvm::Deserializer& D, ASTContext& C);
+};
+
} // end namespace clang
#endif
Modified: cfe/trunk/include/clang/AST/StmtNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtNodes.def?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/StmtNodes.def (original)
+++ cfe/trunk/include/clang/AST/StmtNodes.def Mon Jan 5 14:52:13 2009
@@ -113,6 +113,7 @@
STMT(CXXNewExpr , Expr)
STMT(CXXDeleteExpr , Expr)
STMT(CXXDependentNameExpr , Expr)
+STMT(UnaryTypeTraitExpr , Expr)
// Obj-C Expressions.
STMT(ObjCStringLiteral , Expr)
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Mon Jan 5 14:52:13 2009
@@ -295,7 +295,10 @@
bool isIncompleteOrObjectType() const {
return !isFunctionType();
}
-
+
+ /// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10).
+ bool isPODType() const;
+
/// isVariablyModifiedType (C99 6.7.5.2p2) - Return true for variable array
/// types that have a non-constant expression. This does not include "[]".
bool isVariablyModifiedType() const;
Modified: cfe/trunk/include/clang/Basic/TokenKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TokenKinds.def (original)
+++ cfe/trunk/include/clang/Basic/TokenKinds.def Mon Jan 5 14:52:13 2009
@@ -304,6 +304,25 @@
KEYWORD(__real , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
KEYWORD(__thread , EXTC90|EXTC99|EXTCPP|EXTCPP0x)
+// GNU and MS Type Traits
+KEYWORD(__has_nothrow_assign , NOTC90|NOTC99)
+KEYWORD(__has_nothrow_copy , NOTC90|NOTC99)
+KEYWORD(__has_nothrow_constructor , NOTC90|NOTC99)
+KEYWORD(__has_trivial_assign , NOTC90|NOTC99)
+KEYWORD(__has_trivial_copy , NOTC90|NOTC99)
+KEYWORD(__has_trivial_constructor , NOTC90|NOTC99)
+KEYWORD(__has_trivial_destructor , NOTC90|NOTC99)
+KEYWORD(__has_virtual_destructor , NOTC90|NOTC99)
+KEYWORD(__is_abstract , NOTC90|NOTC99)
+KEYWORD(__is_base_of , NOTC90|NOTC99)
+KEYWORD(__is_class , NOTC90|NOTC99)
+KEYWORD(__is_empty , NOTC90|NOTC99)
+KEYWORD(__is_enum , NOTC90|NOTC99)
+KEYWORD(__is_pod , NOTC90|NOTC99)
+KEYWORD(__is_polymorphic , NOTC90|NOTC99)
+KEYWORD(__is_union , NOTC90|NOTC99)
+// FIXME: Add MS's traits, too.
+
// Apple Extension.
KEYWORD(__private_extern__ , EXTC90|EXTC99|NOTCPP)
Added: cfe/trunk/include/clang/Basic/TypeTraits.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TypeTraits.h?rev=61746&view=auto
==============================================================================
--- cfe/trunk/include/clang/Basic/TypeTraits.h (added)
+++ cfe/trunk/include/clang/Basic/TypeTraits.h Mon Jan 5 14:52:13 2009
@@ -0,0 +1,40 @@
+//===--- TypeTraits.h - C++ Type Traits Support Enumerations ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines enumerations for the type traits support.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TYPETRAITS_H
+#define LLVM_CLANG_TYPETRAITS_H
+
+namespace clang {
+
+ /// UnaryTypeTrait - Names for the unary type traits.
+ enum UnaryTypeTrait {
+ UTT_HasNothrowAssign,
+ UTT_HasNothrowCopy,
+ UTT_HasNothrowConstructor,
+ UTT_HasTrivialAssign,
+ UTT_HasTrivialCopy,
+ UTT_HasTrivialConstructor,
+ UTT_HasTrivialDestructor,
+ UTT_HasVirtualDestructor,
+ UTT_IsAbstract,
+ UTT_IsClass,
+ UTT_IsEmpty,
+ UTT_IsEnum,
+ UTT_IsPOD,
+ UTT_IsPolymorphic,
+ UTT_IsUnion
+ };
+
+}
+
+#endif
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Mon Jan 5 14:52:13 2009
@@ -16,6 +16,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TypeTraits.h"
#include "clang/Parse/AccessSpecifier.h"
#include "clang/Parse/Ownership.h"
@@ -892,6 +893,14 @@
return 0;
}
+ virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
+ SourceLocation KWLoc,
+ SourceLocation LParen,
+ TypeTy *Ty,
+ SourceLocation RParen) {
+ return ExprEmpty();
+ }
+
//===---------------------------- C++ Classes ---------------------------===//
/// ActOnBaseSpecifier - Parsed a base specifier
virtual BaseResult ActOnBaseSpecifier(DeclTy *classdecl,
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Jan 5 14:52:13 2009
@@ -984,7 +984,10 @@
void AnnotateTemplateIdToken(DeclTy *Template, const CXXScopeSpec *SS = 0);
bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
OwningTemplateArgResult ParseTemplateArgument();
-
+
+ //===--------------------------------------------------------------------===//
+ // GNU G++: Type Traits [Type-Traits.html in the GCC manual]
+ OwningExprResult ParseUnaryTypeTrait();
};
} // end namespace clang
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Mon Jan 5 14:52:13 2009
@@ -56,9 +56,9 @@
SourceLocation L, IdentifierInfo *Id)
: RecordDecl(CXXRecord, TK, DC, L, Id),
UserDeclaredConstructor(false), UserDeclaredCopyConstructor(false),
- UserDeclaredDestructor(false), Aggregate(true), Polymorphic(false),
- Bases(0), NumBases(0),
- Conversions(DC, DeclarationName()) { }
+ UserDeclaredCopyAssignment(false), UserDeclaredDestructor(false),
+ Aggregate(true), PlainOldData(true), Polymorphic(false), Bases(0),
+ NumBases(0), Conversions(DC, DeclarationName()) { }
CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
@@ -91,7 +91,8 @@
}
bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
- QualType ClassType = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
+ QualType ClassType
+ = Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
DeclarationName ConstructorName
= Context.DeclarationNames.getCXXConstructorName(
Context.getCanonicalType(ClassType));
@@ -107,7 +108,49 @@
return false;
}
-void
+bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const {
+ QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
+ const_cast<CXXRecordDecl*>(this)));
+ DeclarationName OpName =Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+
+ DeclContext::lookup_const_iterator Op, OpEnd;
+ for (llvm::tie(Op, OpEnd) = this->lookup(Context, OpName);
+ Op != OpEnd; ++Op) {
+ // C++ [class.copy]p9:
+ // A user-declared copy assignment operator is a non-static non-template
+ // member function of class X with exactly one parameter of type X, X&,
+ // const X&, volatile X& or const volatile X&.
+ const CXXMethodDecl* Method = cast<CXXMethodDecl>(*Op);
+ if (Method->isStatic())
+ continue;
+ // TODO: Skip templates? Or is this implicitly done due to parameter types?
+ const FunctionTypeProto *FnType =
+ Method->getType()->getAsFunctionTypeProto();
+ assert(FnType && "Overloaded operator has no prototype.");
+ // Don't assert on this; an invalid decl might have been left in the AST.
+ if (FnType->getNumArgs() != 1 || FnType->isVariadic())
+ continue;
+ bool AcceptsConst = true;
+ QualType ArgType = FnType->getArgType(0);
+ if (const ReferenceType *Ref = ArgType->getAsReferenceType()) {
+ ArgType = Ref->getPointeeType();
+ // Is it a non-const reference?
+ if (!ArgType.isConstQualified())
+ AcceptsConst = false;
+ }
+ if (Context.getCanonicalType(ArgType).getUnqualifiedType() != ClassType)
+ continue;
+
+ // We have a single argument of type cv X or cv X&, i.e. we've found the
+ // copy assignment operator. Return whether it accepts const arguments.
+ return AcceptsConst;
+ }
+ assert(isInvalidDecl() &&
+ "No copy assignment operator declared in valid code.");
+ return false;
+}
+
+void
CXXRecordDecl::addedConstructor(ASTContext &Context,
CXXConstructorDecl *ConDecl) {
if (!ConDecl->isImplicitlyDeclared()) {
@@ -119,6 +162,10 @@
// user-declared constructors (12.1) [...].
Aggregate = false;
+ // C++ [class]p4:
+ // A POD-struct is an aggregate class [...]
+ PlainOldData = false;
+
// Note when we have a user-declared copy constructor, which will
// suppress the implicit declaration of a copy constructor.
if (ConDecl->isCopyConstructor(Context))
@@ -126,6 +173,35 @@
}
}
+void CXXRecordDecl::addedAssignmentOperator(ASTContext &Context,
+ CXXMethodDecl *OpDecl) {
+ // We're interested specifically in copy assignment operators.
+ // Unlike addedConstructor, this method is not called for implicit
+ // declarations.
+ const FunctionTypeProto *FnType = OpDecl->getType()->getAsFunctionTypeProto();
+ assert(FnType && "Overloaded operator has no proto function type.");
+ assert(FnType->getNumArgs() == 1 && !FnType->isVariadic());
+ QualType ArgType = FnType->getArgType(0);
+ if (const ReferenceType *Ref = ArgType->getAsReferenceType())
+ ArgType = Ref->getPointeeType();
+
+ ArgType = ArgType.getUnqualifiedType();
+ QualType ClassType = Context.getCanonicalType(Context.getTypeDeclType(
+ const_cast<CXXRecordDecl*>(this)));
+
+ if (ClassType != Context.getCanonicalType(ArgType))
+ return;
+
+ // This is a copy assignment operator.
+ // Suppress the implicit declaration of a copy constructor.
+ UserDeclaredCopyAssignment = true;
+
+ // C++ [class]p4:
+ // A POD-struct is an aggregate class that [...] has no user-defined copy
+ // assignment operator [...].
+ PlainOldData = false;
+}
+
void CXXRecordDecl::addConversionFunction(ASTContext &Context,
CXXConversionDecl *ConvDecl) {
Conversions.addOverload(ConvDecl);
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Mon Jan 5 14:52:13 2009
@@ -1092,6 +1092,10 @@
case CXXDefaultArgExprClass:
return cast<CXXDefaultArgExpr>(this)
->isIntegerConstantExpr(Result, Ctx, Loc, isEvaluated);
+
+ case UnaryTypeTraitExprClass:
+ Result = cast<UnaryTypeTraitExpr>(this)->Evaluate();
+ return true;
}
// Cases that are valid constant exprs fall through to here.
Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Mon Jan 5 14:52:13 2009
@@ -120,6 +120,35 @@
return child_iterator();
}
+// UnaryTypeTraitExpr
+Stmt::child_iterator UnaryTypeTraitExpr::child_begin() {
+ return child_iterator();
+}
+Stmt::child_iterator UnaryTypeTraitExpr::child_end() {
+ return child_iterator();
+}
+
+bool UnaryTypeTraitExpr::Evaluate() const {
+ switch(UTT) {
+ default: assert(false && "Unknown type trait or not implemented");
+ case UTT_IsPOD: return QueriedType->isPODType();
+ case UTT_IsClass: // Fallthrough
+ case UTT_IsUnion:
+ if (const RecordType *Record = QueriedType->getAsRecordType()) {
+ bool Union = Record->getDecl()->isUnion();
+ return UTT == UTT_IsUnion ? Union : !Union;
+ }
+ return false;
+ case UTT_IsEnum: return QueriedType->isEnumeralType();
+ case UTT_IsPolymorphic:
+ if (const RecordType *Record = QueriedType->getAsRecordType()) {
+ // Type traits are only parsed in C++, so we've got CXXRecords.
+ return cast<CXXRecordDecl>(Record->getDecl())->isPolymorphic();
+ }
+ return false;
+ }
+}
+
OverloadedOperatorKind CXXOperatorCallExpr::getOperator() const {
// All simple function calls (e.g. func()) are implicitly cast to pointer to
// function. As a result, we try and obtain the DeclRefExpr from the
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Mon Jan 5 14:52:13 2009
@@ -428,6 +428,12 @@
return true;
}
+ bool VisitUnaryTypeTraitExpr(const UnaryTypeTraitExpr *E) {
+ Result.zextOrTrunc(getIntTypeSizeInBits(E->getType()));
+ Result = E->Evaluate();
+ return true;
+ }
+
private:
bool HandleCast(CastExpr* E);
};
Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Mon Jan 5 14:52:13 2009
@@ -1020,6 +1020,32 @@
OS << E->getName()->getName();
}
+static const char *getTypeTraitName(UnaryTypeTrait UTT) {
+ switch (UTT) {
+ default: assert(false && "Unknown type trait");
+ case UTT_HasNothrowAssign: return "__has_nothrow_assign";
+ case UTT_HasNothrowCopy: return "__has_nothrow_copy";
+ case UTT_HasNothrowConstructor: return "__has_nothrow_constructor";
+ case UTT_HasTrivialAssign: return "__has_trivial_assign";
+ case UTT_HasTrivialCopy: return "__has_trivial_copy";
+ case UTT_HasTrivialConstructor: return "__has_trivial_constructor";
+ case UTT_HasTrivialDestructor: return "__has_trivial_destructor";
+ case UTT_HasVirtualDestructor: return "__has_virtual_destructor";
+ case UTT_IsAbstract: return "__is_abstract";
+ case UTT_IsClass: return "__is_class";
+ case UTT_IsEmpty: return "__is_empty";
+ case UTT_IsEnum: return "__is_enum";
+ case UTT_IsPOD: return "__is_pod";
+ case UTT_IsPolymorphic: return "__is_polymorphic";
+ case UTT_IsUnion: return "__is_union";
+ }
+}
+
+void StmtPrinter::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) {
+ OS << getTypeTraitName(E->getTrait()) << "("
+ << E->getQueriedType().getAsString() << ")";
+}
+
// Obj-C
void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
Modified: cfe/trunk/lib/AST/StmtSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtSerialization.cpp?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtSerialization.cpp (original)
+++ cfe/trunk/lib/AST/StmtSerialization.cpp Mon Jan 5 14:52:13 2009
@@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Basic/TypeTraits.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
@@ -1530,6 +1531,24 @@
return new CXXDependentNameExpr(N, Ty, L);
}
+void UnaryTypeTraitExpr::EmitImpl(llvm::Serializer& S) const {
+ S.EmitInt(UTT);
+ S.Emit(Loc);
+ S.Emit(RParen);
+ S.Emit(QueriedType);
+ S.Emit(getType());
+}
+
+UnaryTypeTraitExpr *
+UnaryTypeTraitExpr::CreateImpl(llvm::Deserializer& D, ASTContext& C) {
+ UnaryTypeTrait UTT = static_cast<UnaryTypeTrait>(D.ReadInt());
+ SourceLocation Loc = SourceLocation::ReadVal(D);
+ SourceLocation RParen = SourceLocation::ReadVal(D);
+ QualType QueriedType = QualType::ReadVal(D);
+ QualType Ty = QualType::ReadVal(D);
+ return new UnaryTypeTraitExpr(Loc, UTT, QueriedType, RParen, Ty);
+}
+
void CXXCatchStmt::EmitImpl(llvm::Serializer& S) const {
S.Emit(CatchLoc);
S.EmitOwnedPtr(ExceptionDecl);
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Mon Jan 5 14:52:13 2009
@@ -670,6 +670,42 @@
}
}
+/// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10)
+bool Type::isPODType() const {
+ // The compiler shouldn't query this for incomplete types, but the user might.
+ // We return false for that case.
+ if (isIncompleteType())
+ return false;
+
+ switch (CanonicalType->getTypeClass()) {
+ // Everything not explicitly mentioned is not POD.
+ default: return false;
+ case ASQual:
+ return cast<ASQualType>(CanonicalType)->getBaseType()->isPODType();
+ case VariableArray:
+ case ConstantArray:
+ // IncompleteArray is caught by isIncompleteType() above.
+ return cast<ArrayType>(CanonicalType)->getElementType()->isPODType();
+
+ case Builtin:
+ case Complex:
+ case Pointer:
+ case Vector:
+ case ExtVector:
+ // FIXME: pointer-to-member
+ return true;
+
+ case Tagged:
+ if (isEnumeralType())
+ return true;
+ if (CXXRecordDecl *RDecl = dyn_cast<CXXRecordDecl>(
+ cast<TagType>(CanonicalType)->getDecl()))
+ return RDecl->isPOD();
+ // C struct/union is POD.
+ return true;
+ }
+}
+
bool Type::isPromotableIntegerType() const {
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
return ASQT->getBaseType()->isPromotableIntegerType();
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Mon Jan 5 14:52:13 2009
@@ -381,6 +381,8 @@
/// [C++] 'typeid' '(' expression ')' [C++ 5.2p1]
/// [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]
/// [clang] '^' block-literal
///
/// constant: [C99 6.4.4]
@@ -410,6 +412,26 @@
/// '::'[opt] 'delete' cast-expression
/// '::'[opt] 'delete' '[' ']' cast-expression
///
+/// [GNU] unary-type-trait:
+/// '__has_nothrow_assign' [TODO]
+/// '__has_nothrow_copy' [TODO]
+/// '__has_nothrow_constructor' [TODO]
+/// '__has_trivial_assign' [TODO]
+/// '__has_trivial_copy' [TODO]
+/// '__has_trivial_constructor' [TODO]
+/// '__has_trivial_destructor' [TODO]
+/// '__has_virtual_destructor' [TODO]
+/// '__is_abstract' [TODO]
+/// '__is_class'
+/// '__is_empty' [TODO]
+/// '__is_enum'
+/// '__is_pod'
+/// '__is_polymorphic'
+/// '__is_union'
+///
+/// [GNU] binary-type-trait:
+/// '__is_base_of' [TODO]
+///
Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
OwningExprResult Res(Actions);
tok::TokenKind SavedKind = Tok.getKind();
@@ -650,6 +672,13 @@
case tok::kw_delete: // [C++] delete-expression
return ParseCXXDeleteExpression(false, Tok.getLocation());
+ case tok::kw___is_pod: // [GNU] unary-type-trait
+ case tok::kw___is_class:
+ case tok::kw___is_enum:
+ case tok::kw___is_union:
+ case tok::kw___is_polymorphic:
+ return ParseUnaryTypeTrait();
+
case tok::at: {
SourceLocation AtLoc = ConsumeToken();
return ParseObjCAtExpression(AtLoc);
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Mon Jan 5 14:52:13 2009
@@ -839,3 +839,51 @@
return Owned(Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete,
Operand.release()));
}
+
+static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind)
+{
+ switch(kind) {
+ default: assert(false && "Not a known unary type trait.");
+ case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign;
+ case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy;
+ case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
+ case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign;
+ case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy;
+ case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor;
+ case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor;
+ case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor;
+ case tok::kw___is_abstract: return UTT_IsAbstract;
+ case tok::kw___is_class: return UTT_IsClass;
+ case tok::kw___is_empty: return UTT_IsEmpty;
+ case tok::kw___is_enum: return UTT_IsEnum;
+ case tok::kw___is_pod: return UTT_IsPOD;
+ case tok::kw___is_polymorphic: return UTT_IsPolymorphic;
+ case tok::kw___is_union: return UTT_IsUnion;
+ }
+}
+
+/// ParseUnaryTypeTrait - Parse the built-in unary type-trait
+/// pseudo-functions that allow implementation of the TR1/C++0x type traits
+/// templates.
+///
+/// primary-expression:
+/// [GNU] unary-type-trait '(' type-id ')'
+///
+Parser::OwningExprResult Parser::ParseUnaryTypeTrait()
+{
+ UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
+ SourceLocation Loc = ConsumeToken();
+
+ SourceLocation LParen = Tok.getLocation();
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
+ return ExprError();
+
+ // FIXME: Error reporting absolutely sucks! If the this fails to parse a type
+ // there will be cryptic errors about mismatched parentheses and missing
+ // specifiers.
+ TypeTy *Ty = ParseTypeName();
+
+ SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
+
+ return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty, RParen);
+}
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Jan 5 14:52:13 2009
@@ -918,6 +918,14 @@
SourceLocation EqualLoc,
ExprTy *AssignExprVal);
+ /// ActOnUnaryTypeTrait - Parsed one of the unary type trait support
+ /// pseudo-functions.
+ virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
+ SourceLocation KWLoc,
+ SourceLocation LParen,
+ TypeTy *Ty,
+ SourceLocation RParen);
+
/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
/// global scope ('::').
virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S,
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Jan 5 14:52:13 2009
@@ -1153,7 +1153,7 @@
FunctionDecl::StorageClass SC = FunctionDecl::None;
switch (D.getDeclSpec().getStorageClassSpec()) {
default: assert(0 && "Unknown storage class!");
- case DeclSpec::SCS_auto:
+ case DeclSpec::SCS_auto:
case DeclSpec::SCS_register:
case DeclSpec::SCS_mutable:
Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_func);
@@ -1319,9 +1319,14 @@
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD))
InvalidDecl = InvalidDecl || CheckConstructor(Constructor);
- else if (isa<CXXDestructorDecl>(NewFD))
- cast<CXXRecordDecl>(NewFD->getParent())->setUserDeclaredDestructor(true);
- else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(NewFD))
+ else if (isa<CXXDestructorDecl>(NewFD)) {
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(NewFD->getParent());
+ Record->setUserDeclaredDestructor(true);
+ // C++ [class]p4: A POD-struct is an aggregate class that has [...] no
+ // user-defined destructor.
+ Record->setPOD(false);
+ } else if (CXXConversionDecl *Conversion =
+ dyn_cast<CXXConversionDecl>(NewFD))
ActOnConversionDeclarator(Conversion);
// Extra checking for C++ overloaded operators (C++ [over.oper]).
@@ -2836,7 +2841,7 @@
QualType T = GetTypeForDeclarator(D, S);
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
bool InvalidDecl = false;
-
+
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
if (T->isVariablyModifiedType()) {
@@ -2872,8 +2877,11 @@
DeclSpec::SCS_mutable,
/*PrevDecl=*/0);
- if (getLangOptions().CPlusPlus)
+ if (getLangOptions().CPlusPlus) {
CheckExtraCXXDefaultArguments(D);
+ if (!T->isPODType())
+ cast<CXXRecordDecl>(Record)->setPOD(false);
+ }
ProcessDeclAttributes(NewFD, D);
@@ -3088,7 +3096,7 @@
++NumNamedMembers;
}
}
-
+
// Okay, we successfully defined 'Record'.
if (Record) {
Record->completeDefinition(Context);
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Jan 5 14:52:13 2009
@@ -317,7 +317,7 @@
Sema::ActOnBaseSpecifier(DeclTy *classdecl, SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
TypeTy *basetype, SourceLocation BaseLoc) {
- RecordDecl *Decl = (RecordDecl*)classdecl;
+ CXXRecordDecl *Decl = (CXXRecordDecl*)classdecl;
QualType BaseType = Context.getTypeDeclType((TypeDecl*)basetype);
// Base specifiers must be record types.
@@ -347,7 +347,12 @@
BaseDecl = BaseDecl->getDefinition(Context);
assert(BaseDecl && "Base type is not incomplete, but has no definition");
if (cast<CXXRecordDecl>(BaseDecl)->isPolymorphic())
- cast<CXXRecordDecl>(Decl)->setPolymorphic(true);
+ Decl->setPolymorphic(true);
+
+ // C++ [dcl.init.aggr]p1:
+ // An aggregate is [...] a class with [...] no base classes [...].
+ Decl->setAggregate(false);
+ Decl->setPOD(false);
// Create the base specifier.
return new CXXBaseSpecifier(SpecifierRange, Virtual,
@@ -537,8 +542,12 @@
// C++ [dcl.init.aggr]p1:
// An aggregate is an array or a class (clause 9) with [...] no
// private or protected non-static data members (clause 11).
- if (isInstField && (AS == AS_private || AS == AS_protected))
- cast<CXXRecordDecl>(CurContext)->setAggregate(false);
+ // A POD must be an aggregate.
+ if (isInstField && (AS == AS_private || AS == AS_protected)) {
+ CXXRecordDecl *Record = cast<CXXRecordDecl>(CurContext);
+ Record->setAggregate(false);
+ Record->setPOD(false);
+ }
if (DS.isVirtualSpecified()) {
if (!isFunc || DS.getStorageClassSpec() == DeclSpec::SCS_static) {
@@ -547,6 +556,7 @@
} else {
CXXRecordDecl *CurClass = cast<CXXRecordDecl>(CurContext);
CurClass->setAggregate(false);
+ CurClass->setPOD(false);
CurClass->setPolymorphic(true);
}
}
@@ -827,17 +837,17 @@
}
}
- // Otherwise, the implicitly declared copy constructor will have
- // the form
+ // Otherwise, the implicitly declared copy constructor will have
+ // the form
//
// X::X(X&)
- QualType ArgType = Context.getTypeDeclType(ClassDecl);
+ QualType ArgType = ClassType;
if (HasConstCopyConstructor)
ArgType = ArgType.withConst();
ArgType = Context.getReferenceType(ArgType);
- // An implicitly-declared copy constructor is an inline public
- // member of its class.
+ // An implicitly-declared copy constructor is an inline public
+ // member of its class.
DeclarationName Name
= Context.DeclarationNames.getCXXConstructorName(ClassType);
CXXConstructorDecl *CopyConstructor
@@ -862,6 +872,83 @@
ClassDecl->addDecl(Context, CopyConstructor);
}
+ if (!ClassDecl->hasUserDeclaredCopyAssignment()) {
+ // Note: The following rules are largely analoguous to the copy
+ // constructor rules. Note that virtual bases are not taken into account
+ // for determining the argument type of the operator. Note also that
+ // operators taking an object instead of a reference are allowed.
+ //
+ // C++ [class.copy]p10:
+ // If the class definition does not explicitly declare a copy
+ // assignment operator, one is declared implicitly.
+ // The implicitly-defined copy assignment operator for a class X
+ // will have the form
+ //
+ // X& X::operator=(const X&)
+ //
+ // if
+ bool HasConstCopyAssignment = true;
+
+ // -- each direct base class B of X has a copy assignment operator
+ // whose parameter is of type const B&, const volatile B& or B,
+ // and
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
+ HasConstCopyAssignment && Base != ClassDecl->bases_end(); ++Base) {
+ const CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
+ HasConstCopyAssignment = BaseClassDecl->hasConstCopyAssignment(Context);
+ }
+
+ // -- for all the nonstatic data members of X that are of a class
+ // type M (or array thereof), each such class type has a copy
+ // assignment operator whose parameter is of type const M&,
+ // const volatile M& or M.
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin();
+ HasConstCopyAssignment && Field != ClassDecl->field_end(); ++Field) {
+ QualType FieldType = (*Field)->getType();
+ if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+ FieldType = Array->getElementType();
+ if (const RecordType *FieldClassType = FieldType->getAsRecordType()) {
+ const CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ HasConstCopyAssignment
+ = FieldClassDecl->hasConstCopyAssignment(Context);
+ }
+ }
+
+ // Otherwise, the implicitly declared copy assignment operator will
+ // have the form
+ //
+ // X& X::operator=(X&)
+ QualType ArgType = ClassType;
+ QualType RetType = Context.getReferenceType(ArgType);
+ if (HasConstCopyAssignment)
+ ArgType = ArgType.withConst();
+ ArgType = Context.getReferenceType(ArgType);
+
+ // An implicitly-declared copy assignment operator is an inline public
+ // member of its class.
+ DeclarationName Name =
+ Context.DeclarationNames.getCXXOperatorName(OO_Equal);
+ CXXMethodDecl *CopyAssignment =
+ CXXMethodDecl::Create(Context, ClassDecl, ClassDecl->getLocation(), Name,
+ Context.getFunctionType(RetType, &ArgType, 1,
+ false, 0),
+ /*isStatic=*/false, /*isInline=*/true, 0);
+ CopyAssignment->setAccess(AS_public);
+
+ // Add the parameter to the operator.
+ ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
+ ClassDecl->getLocation(),
+ /*IdentifierInfo=*/0,
+ ArgType, VarDecl::None, 0, 0);
+ CopyAssignment->setParams(&FromParam, 1);
+
+ // Don't call addedAssignmentOperator. There is no way to distinguish an
+ // implicit from an explicit assignment operator.
+ ClassDecl->addDecl(Context, CopyAssignment);
+ }
+
if (!ClassDecl->hasUserDeclaredDestructor()) {
// C++ [class.dtor]p2:
// If a class has no user-declared destructor, a destructor is
@@ -879,8 +966,6 @@
Destructor->setAccess(AS_public);
ClassDecl->addDecl(Context, Destructor);
}
-
- // FIXME: Implicit copy assignment operator
}
void Sema::ActOnFinishCXXClassDef(DeclTy *D) {
@@ -1963,7 +2048,7 @@
return Diag(FnDecl->getLocation(), diag::err_operator_overload_must_be)
<< FnDecl->getDeclName() << NumParams << ErrorKind;
}
-
+
// Overloaded operators other than operator() cannot be variadic.
if (Op != OO_Call &&
FnDecl->getType()->getAsFunctionTypeProto()->isVariadic()) {
@@ -2000,6 +2085,15 @@
<< LastParam->getType() << (Op == OO_MinusMinus);
}
+ // Notify the class if it got an assignment operator.
+ if (Op == OO_Equal) {
+ // Would have returned earlier otherwise.
+ assert(isa<CXXMethodDecl>(FnDecl) &&
+ "Overloaded = not member, but not filtered.");
+ CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
+ Method->getParent()->addedAssignmentOperator(Context, Method);
+ }
+
return false;
}
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=61746&r1=61745&r2=61746&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Jan 5 14:52:13 2009
@@ -842,3 +842,20 @@
return false;
}
+Sema::OwningExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait OTT,
+ SourceLocation KWLoc,
+ SourceLocation LParen,
+ TypeTy *Ty,
+ SourceLocation RParen) {
+ // FIXME: Some of the type traits have requirements. Interestingly, only the
+ // __is_base_of requirement is explicitly stated to be diagnosed. Indeed,
+ // G++ accepts __is_pod(Incomplete) without complaints, and claims that the
+ // type is indeed a POD.
+
+ // There is no point in eagerly computing the value. The traits are designed
+ // to be used from type trait templates, so Ty will be a template parameter
+ // 99% of the time.
+ return Owned(new UnaryTypeTraitExpr(KWLoc, OTT,
+ QualType::getFromOpaquePtr(Ty),
+ RParen, Context.BoolTy));
+}
Added: cfe/trunk/test/SemaCXX/type-traits.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=61746&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/type-traits.cpp (added)
+++ cfe/trunk/test/SemaCXX/type-traits.cpp Mon Jan 5 14:52:13 2009
@@ -0,0 +1,111 @@
+// RUN: clang -fsyntax-only -verify %s
+#define T(b) (b) ? 1 : -1
+#define F(b) (b) ? -1 : 1
+
+struct NonPOD { NonPOD(int); };
+
+// PODs
+enum Enum { EV };
+struct POD { Enum e; int i; float f; NonPOD* p; };
+typedef int Int;
+typedef Int IntAr[10];
+class Statics { static int priv; static NonPOD np; };
+
+// Not PODs
+struct Derives : POD {};
+struct HasCons { HasCons(int); };
+struct HasAssign { HasAssign operator =(const HasAssign&); };
+struct HasDest { ~HasDest(); };
+class HasPriv { int priv; };
+class HasProt { protected: int prot; };
+struct HasRef { int i; int& ref; HasRef() : i(0), ref(i) {} };
+struct HasNonPOD { NonPOD np; };
+struct HasVirt { virtual void Virt() {}; };
+typedef Derives NonPODAr[10];
+
+void is_pod()
+{
+ int t01[T(__is_pod(int))];
+ int t02[T(__is_pod(Enum))];
+ int t03[T(__is_pod(POD))];
+ int t04[T(__is_pod(Int))];
+ int t05[T(__is_pod(IntAr))];
+ int t06[T(__is_pod(Statics))];
+
+ int t21[F(__is_pod(Derives))];
+ int t22[F(__is_pod(HasCons))];
+ int t23[F(__is_pod(HasAssign))];
+ int t24[F(__is_pod(HasDest))];
+ int t25[F(__is_pod(HasPriv))];
+ int t26[F(__is_pod(HasProt))];
+ int t27[F(__is_pod(HasRef))];
+ int t28[F(__is_pod(HasNonPOD))];
+ int t29[F(__is_pod(HasVirt))];
+ int t30[F(__is_pod(NonPODAr))];
+}
+
+union Union { int i; float f; };
+typedef Derives ClassType;
+
+void is_class()
+{
+ int t01[T(__is_class(Derives))];
+ int t02[T(__is_class(HasPriv))];
+ int t03[T(__is_class(ClassType))];
+
+ int t11[F(__is_class(int))];
+ int t12[F(__is_class(Enum))];
+ int t13[F(__is_class(Int))];
+ int t14[F(__is_class(IntAr))];
+ int t15[F(__is_class(NonPODAr))];
+ int t16[F(__is_class(Union))];
+}
+
+typedef Union UnionAr[10];
+typedef Union UnionType;
+
+void is_union()
+{
+ int t01[T(__is_union(Union))];
+ int t02[T(__is_union(UnionType))];
+
+ int t11[F(__is_union(int))];
+ int t12[F(__is_union(Enum))];
+ int t13[F(__is_union(Int))];
+ int t14[F(__is_union(IntAr))];
+ int t15[F(__is_union(UnionAr))];
+}
+
+typedef Enum EnumType;
+
+void is_enum()
+{
+ int t01[T(__is_enum(Enum))];
+ int t02[T(__is_enum(EnumType))];
+
+ int t11[F(__is_enum(int))];
+ int t12[F(__is_enum(Union))];
+ int t13[F(__is_enum(Int))];
+ int t14[F(__is_enum(IntAr))];
+ int t15[F(__is_enum(UnionAr))];
+ int t16[F(__is_enum(Derives))];
+ int t17[F(__is_enum(ClassType))];
+}
+
+struct Polymorph { virtual void f(); };
+struct InheritPolymorph : Polymorph {};
+
+void is_polymorphic()
+{
+ int t01[T(__is_polymorphic(Polymorph))];
+ int t02[T(__is_polymorphic(InheritPolymorph))];
+
+ int t11[F(__is_polymorphic(int))];
+ int t12[F(__is_polymorphic(Union))];
+ int t13[F(__is_polymorphic(Int))];
+ int t14[F(__is_polymorphic(IntAr))];
+ int t15[F(__is_polymorphic(UnionAr))];
+ int t16[F(__is_polymorphic(Derives))];
+ int t17[F(__is_polymorphic(ClassType))];
+ int t18[F(__is_polymorphic(Enum))];
+}
More information about the cfe-commits
mailing list