forked from OSchip/llvm-project
parent
9a627e60cd
commit
576fd424df
|
@ -174,7 +174,7 @@ public:
|
|||
QualType UnsignedLongLongTy, UnsignedInt128Ty;
|
||||
QualType FloatTy, DoubleTy, LongDoubleTy;
|
||||
QualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
|
||||
QualType VoidPtrTy;
|
||||
QualType VoidPtrTy, NullPtrTy;
|
||||
QualType OverloadTy;
|
||||
QualType DependentTy;
|
||||
|
||||
|
|
|
@ -222,6 +222,24 @@ public:
|
|||
virtual child_iterator child_end();
|
||||
};
|
||||
|
||||
/// CXXNullPtrLiteralExpr - [C++0x 2.14.7] C++ Pointer Literal
|
||||
class CXXNullPtrLiteralExpr : public Expr {
|
||||
SourceLocation Loc;
|
||||
public:
|
||||
CXXNullPtrLiteralExpr(QualType Ty, SourceLocation l) :
|
||||
Expr(CXXNullPtrLiteralExprClass, Ty), Loc(l) {}
|
||||
|
||||
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == CXXNullPtrLiteralExprClass;
|
||||
}
|
||||
static bool classof(const CXXNullPtrLiteralExpr *) { return true; }
|
||||
|
||||
virtual child_iterator child_begin();
|
||||
virtual child_iterator child_end();
|
||||
};
|
||||
|
||||
/// CXXTypeidExpr - A C++ @c typeid expression (C++ [expr.typeid]), which gets
|
||||
/// the type_info that corresponds to the supplied type, or the (possibly
|
||||
/// dynamic) type of the supplied expression.
|
||||
|
|
|
@ -107,6 +107,7 @@ STMT(CXXConstCastExpr , CXXNamedCastExpr)
|
|||
STMT(CXXFunctionalCastExpr , ExplicitCastExpr)
|
||||
STMT(CXXTypeidExpr , Expr)
|
||||
STMT(CXXBoolLiteralExpr , Expr)
|
||||
STMT(CXXNullPtrLiteralExpr , Expr)
|
||||
STMT(CXXThisExpr , Expr)
|
||||
STMT(CXXThrowExpr , Expr)
|
||||
STMT(CXXDefaultArgExpr , Expr)
|
||||
|
|
|
@ -394,6 +394,7 @@ public:
|
|||
bool isObjCQualifiedInterfaceType() const; // NSString<foo>
|
||||
bool isObjCQualifiedIdType() const; // id<foo>
|
||||
bool isTemplateTypeParmType() const; // C++ template type parameter
|
||||
bool isNullPtrType() const; // C++0x nullptr_t
|
||||
|
||||
/// isDependentType - Whether this type is a dependent type, meaning
|
||||
/// that its definition somehow depends on a template parameter
|
||||
|
@ -404,7 +405,7 @@ public:
|
|||
/// hasPointerRepresentation - Whether this type is represented
|
||||
/// natively as a pointer; this includes pointers, references, block
|
||||
/// pointers, and Objective-C interface, qualified id, and qualified
|
||||
/// interface types.
|
||||
/// interface types, as well as nullptr_t.
|
||||
bool hasPointerRepresentation() const;
|
||||
|
||||
/// hasObjCPointerRepresentation - Whether this type can represent
|
||||
|
@ -559,6 +560,8 @@ public:
|
|||
|
||||
Float, Double, LongDouble,
|
||||
|
||||
NullPtr, // This is the type of C++0x 'nullptr'.
|
||||
|
||||
Overload, // This represents the type of an overloaded function declaration.
|
||||
Dependent // This represents the type of a type-dependent expression.
|
||||
};
|
||||
|
@ -1926,7 +1929,7 @@ inline bool Type::isOverloadableType() const {
|
|||
inline bool Type::hasPointerRepresentation() const {
|
||||
return (isPointerType() || isReferenceType() || isBlockPointerType() ||
|
||||
isObjCInterfaceType() || isObjCQualifiedIdType() ||
|
||||
isObjCQualifiedInterfaceType());
|
||||
isObjCQualifiedInterfaceType() || isNullPtrType());
|
||||
}
|
||||
|
||||
inline bool Type::hasObjCPointerRepresentation() const {
|
||||
|
|
|
@ -319,7 +319,9 @@ namespace clang {
|
|||
/// \brief The '__uint128_t' type.
|
||||
PREDEF_TYPE_UINT128_ID = 21,
|
||||
/// \brief The '__int128_t' type.
|
||||
PREDEF_TYPE_INT128_ID = 22
|
||||
PREDEF_TYPE_INT128_ID = 22,
|
||||
/// \brief The type of 'nullptr'.
|
||||
PREDEF_TYPE_NULLPTR_ID = 23
|
||||
};
|
||||
|
||||
/// \brief The number of predefined type IDs that are reserved for
|
||||
|
|
|
@ -963,7 +963,12 @@ public:
|
|||
|
||||
/// ActOnCXXBoolLiteral - Parse {true,false} literals.
|
||||
virtual OwningExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc,
|
||||
tok::TokenKind Kind) {
|
||||
tok::TokenKind Kind) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
/// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
|
||||
virtual OwningExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc) {
|
||||
return ExprEmpty();
|
||||
}
|
||||
|
||||
|
|
|
@ -276,6 +276,9 @@ void ASTContext::InitBuiltinTypes() {
|
|||
|
||||
// void * type
|
||||
VoidPtrTy = getPointerType(VoidTy);
|
||||
|
||||
// nullptr type (C++0x 2.14.7)
|
||||
InitBuiltinType(NullPtrTy, BuiltinType::NullPtr);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -431,6 +434,9 @@ ASTContext::getTypeInfo(const Type *T) {
|
|||
Width = Target.getLongDoubleWidth();
|
||||
Align = Target.getLongDoubleAlign();
|
||||
break;
|
||||
case BuiltinType::NullPtr:
|
||||
Width = Target.getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t)
|
||||
Align = Target.getPointerAlign(0); // == sizeof(void*)
|
||||
}
|
||||
break;
|
||||
case Type::FixedWidthInt:
|
||||
|
|
|
@ -1377,6 +1377,10 @@ bool Expr::isNullPointerConstant(ASTContext &Ctx) const
|
|||
return true;
|
||||
}
|
||||
|
||||
// C++0x nullptr_t is always a null pointer constant.
|
||||
if (getType()->isNullPtrType())
|
||||
return true;
|
||||
|
||||
// This expression must be an integer type.
|
||||
if (!getType()->isIntegerType())
|
||||
return false;
|
||||
|
|
|
@ -44,6 +44,14 @@ Stmt::child_iterator CXXBoolLiteralExpr::child_end() {
|
|||
return child_iterator();
|
||||
}
|
||||
|
||||
// CXXNullPtrLiteralExpr
|
||||
Stmt::child_iterator CXXNullPtrLiteralExpr::child_begin() {
|
||||
return child_iterator();
|
||||
}
|
||||
Stmt::child_iterator CXXNullPtrLiteralExpr::child_end() {
|
||||
return child_iterator();
|
||||
}
|
||||
|
||||
// CXXThisExpr
|
||||
Stmt::child_iterator CXXThisExpr::child_begin() { return child_iterator(); }
|
||||
Stmt::child_iterator CXXThisExpr::child_end() { return child_iterator(); }
|
||||
|
|
|
@ -299,7 +299,9 @@ public:
|
|||
{ return APValue((Expr*)0, 0); }
|
||||
APValue VisitConditionalOperator(ConditionalOperator *E);
|
||||
APValue VisitChooseExpr(ChooseExpr *E)
|
||||
{ return Visit(E->getChosenSubExpr(Info.Ctx)); }
|
||||
{ return Visit(E->getChosenSubExpr(Info.Ctx)); }
|
||||
APValue VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E)
|
||||
{ return APValue((Expr*)0, 0); }
|
||||
// FIXME: Missing: @protocol, @selector
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
|
|
@ -996,6 +996,10 @@ void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
|
|||
OS << (Node->getValue() ? "true" : "false");
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *Node) {
|
||||
OS << "nullptr";
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitCXXThisExpr(CXXThisExpr *Node) {
|
||||
OS << "this";
|
||||
}
|
||||
|
|
|
@ -889,6 +889,12 @@ bool Type::isPromotableIntegerType() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Type::isNullPtrType() const {
|
||||
if (const BuiltinType *BT = getAsBuiltinType())
|
||||
return BT->getKind() == BuiltinType::NullPtr;
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *BuiltinType::getName() const {
|
||||
switch (getKind()) {
|
||||
default: assert(0 && "Unknown builtin type!");
|
||||
|
@ -912,6 +918,7 @@ const char *BuiltinType::getName() const {
|
|||
case Double: return "double";
|
||||
case LongDouble: return "long double";
|
||||
case WChar: return "wchar_t";
|
||||
case NullPtr: return "nullptr_t";
|
||||
case Overload: return "<overloaded function type>";
|
||||
case Dependent: return "<dependent type>";
|
||||
}
|
||||
|
|
|
@ -499,6 +499,8 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
|
|||
// UNSUPPORTED: ::= Di # char32_t
|
||||
// UNSUPPORTED: ::= Ds # char16_t
|
||||
// ::= u <source-name> # vendor extended type
|
||||
// From our point of view, std::nullptr_t is a builtin, but as far as mangling
|
||||
// is concerned, it's a type called std::nullptr_t.
|
||||
switch (T->getKind()) {
|
||||
case BuiltinType::Void: Out << 'v'; break;
|
||||
case BuiltinType::Bool: Out << 'b'; break;
|
||||
|
@ -519,6 +521,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
|
|||
case BuiltinType::Float: Out << 'f'; break;
|
||||
case BuiltinType::Double: Out << 'd'; break;
|
||||
case BuiltinType::LongDouble: Out << 'e'; break;
|
||||
case BuiltinType::NullPtr: Out << "St9nullptr_t"; break;
|
||||
|
||||
case BuiltinType::Overload:
|
||||
case BuiltinType::Dependent:
|
||||
|
|
|
@ -1676,6 +1676,7 @@ QualType PCHReader::GetType(pch::TypeID ID) {
|
|||
case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy; break;
|
||||
case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context->OverloadTy; break;
|
||||
case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context->DependentTy; break;
|
||||
case pch::PREDEF_TYPE_NULLPTR_ID: T = Context->NullPtrTy; break;
|
||||
}
|
||||
|
||||
assert(!T.isNull() && "Unknown predefined type");
|
||||
|
|
|
@ -1837,6 +1837,7 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
|
|||
case BuiltinType::Float: ID = pch::PREDEF_TYPE_FLOAT_ID; break;
|
||||
case BuiltinType::Double: ID = pch::PREDEF_TYPE_DOUBLE_ID; break;
|
||||
case BuiltinType::LongDouble: ID = pch::PREDEF_TYPE_LONGDOUBLE_ID; break;
|
||||
case BuiltinType::NullPtr: ID = pch::PREDEF_TYPE_NULLPTR_ID; break;
|
||||
case BuiltinType::Overload: ID = pch::PREDEF_TYPE_OVERLOAD_ID; break;
|
||||
case BuiltinType::Dependent: ID = pch::PREDEF_TYPE_DEPENDENT_ID; break;
|
||||
}
|
||||
|
|
|
@ -430,6 +430,7 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) {
|
|||
/// constant
|
||||
/// string-literal
|
||||
/// [C++] boolean-literal [C++ 2.13.5]
|
||||
/// [C++0x] 'nullptr' [C++0x 2.14.7]
|
||||
/// '(' expression ')'
|
||||
/// '__func__' [C99 6.4.2.2]
|
||||
/// [GNU] '__FUNCTION__'
|
||||
|
@ -569,6 +570,9 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
|||
case tok::kw_false:
|
||||
return ParseCXXBoolLiteral();
|
||||
|
||||
case tok::kw_nullptr:
|
||||
return Actions.ActOnCXXNullPtrLiteral(ConsumeToken());
|
||||
|
||||
case tok::identifier: { // primary-expression: identifier
|
||||
// unqualified-id: identifier
|
||||
// constant: enumeration-constant
|
||||
|
|
|
@ -1534,6 +1534,9 @@ public:
|
|||
virtual OwningExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc,
|
||||
tok::TokenKind Kind);
|
||||
|
||||
/// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
|
||||
virtual OwningExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc);
|
||||
|
||||
//// ActOnCXXThrow - Parse throw expressions.
|
||||
virtual OwningExprResult ActOnCXXThrow(SourceLocation OpLoc,
|
||||
ExprArg expr);
|
||||
|
|
|
@ -3811,6 +3811,20 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,
|
|||
ImpCastExprToType(rex, lType); // promote the pointer to pointer
|
||||
return ResultTy;
|
||||
}
|
||||
// C++ allows comparison of pointers with null pointer constants.
|
||||
if (getLangOptions().CPlusPlus) {
|
||||
if (lType->isPointerType() && RHSIsNull) {
|
||||
ImpCastExprToType(rex, lType);
|
||||
return ResultTy;
|
||||
}
|
||||
if (rType->isPointerType() && LHSIsNull) {
|
||||
ImpCastExprToType(lex, rType);
|
||||
return ResultTy;
|
||||
}
|
||||
// And comparison of nullptr_t with itself.
|
||||
if (lType->isNullPtrType() && rType->isNullPtrType())
|
||||
return ResultTy;
|
||||
}
|
||||
// Handle block pointer types.
|
||||
if (!isRelational && lType->isBlockPointerType() && rType->isBlockPointerType()) {
|
||||
QualType lpointee = lType->getAsBlockPointerType()->getPointeeType();
|
||||
|
|
|
@ -85,6 +85,12 @@ Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
|
|||
Context.BoolTy, OpLoc));
|
||||
}
|
||||
|
||||
/// ActOnCXXNullPtrLiteral - Parse 'nullptr'.
|
||||
Action::OwningExprResult
|
||||
Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) {
|
||||
return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc));
|
||||
}
|
||||
|
||||
/// ActOnCXXThrow - Parse throw expressions.
|
||||
Action::OwningExprResult
|
||||
Sema::ActOnCXXThrow(SourceLocation OpLoc, ExprArg E) {
|
||||
|
|
|
@ -279,12 +279,26 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
|
|||
return;
|
||||
}
|
||||
|
||||
// See below for the enumeral issue.
|
||||
if (SrcType->isNullPtrType() && DestType->isIntegralType() &&
|
||||
!DestType->isEnumeralType()) {
|
||||
// C++0x 5.2.10p4: A pointer can be explicitly converted to any integral
|
||||
// type large enough to hold it. A value of std::nullptr_t can be
|
||||
// converted to an integral type; the conversion has the same meaning
|
||||
// and validity as a conversion of (void*)0 to the integral type.
|
||||
if (Self.Context.getTypeSize(SrcType) >
|
||||
Self.Context.getTypeSize(DestType)) {
|
||||
Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_small_int)
|
||||
<< OrigDestType << DestRange;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool destIsPtr = DestType->isPointerType();
|
||||
bool srcIsPtr = SrcType->isPointerType();
|
||||
if (!destIsPtr && !srcIsPtr) {
|
||||
// Except for std::nullptr_t->integer, which is not supported yet, and
|
||||
// lvalue->reference, which is handled above, at least one of the two
|
||||
// arguments must be a pointer.
|
||||
// Except for std::nullptr_t->integer and lvalue->reference, which are
|
||||
// handled above, at least one of the two arguments must be a pointer.
|
||||
Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic)
|
||||
<< "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange;
|
||||
return;
|
||||
|
|
|
@ -621,7 +621,8 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
|
|||
FromType->isEnumeralType() ||
|
||||
FromType->isPointerType() ||
|
||||
FromType->isBlockPointerType() ||
|
||||
FromType->isMemberPointerType())) {
|
||||
FromType->isMemberPointerType() ||
|
||||
FromType->isNullPtrType())) {
|
||||
SCS.Second = ICK_Boolean_Conversion;
|
||||
FromType = Context.BoolTy;
|
||||
}
|
||||
|
@ -898,6 +899,13 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType,
|
|||
return true;
|
||||
}
|
||||
|
||||
// If the left-hand-side is nullptr_t, the right side can be a null
|
||||
// pointer constant.
|
||||
if (ToType->isNullPtrType() && From->isNullPointerConstant(Context)) {
|
||||
ConvertedType = ToType;
|
||||
return true;
|
||||
}
|
||||
|
||||
const PointerType* ToTypePtr = ToType->getAsPointerType();
|
||||
if (!ToTypePtr)
|
||||
return false;
|
||||
|
|
|
@ -1198,6 +1198,10 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
|
|||
if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
|
||||
Arg = Cast->getSubExpr();
|
||||
|
||||
// C++0x allows nullptr, and there's no further checking to be done for that.
|
||||
if (Arg->getType()->isNullPtrType())
|
||||
return false;
|
||||
|
||||
// C++ [temp.arg.nontype]p1:
|
||||
//
|
||||
// A template-argument for a non-type, non-template
|
||||
|
@ -1296,6 +1300,10 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) {
|
|||
if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))
|
||||
Arg = Cast->getSubExpr();
|
||||
|
||||
// C++0x allows nullptr, and there's no further checking to be done for that.
|
||||
if (Arg->getType()->isNullPtrType())
|
||||
return false;
|
||||
|
||||
// C++ [temp.arg.nontype]p1:
|
||||
//
|
||||
// A template-argument for a non-type, non-template
|
||||
|
@ -1485,6 +1493,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
|||
// applied. If the template-argument represents a set of
|
||||
// overloaded functions (or a pointer to such), the matching
|
||||
// function is selected from the set (13.4).
|
||||
// In C++0x, any std::nullptr_t value can be converted.
|
||||
(ParamType->isPointerType() &&
|
||||
ParamType->getAsPointerType()->getPointeeType()->isFunctionType()) ||
|
||||
// -- For a non-type template-parameter of type reference to
|
||||
|
@ -1498,12 +1507,17 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
|||
// template-argument represents a set of overloaded member
|
||||
// functions, the matching member function is selected from
|
||||
// the set (13.4).
|
||||
// Again, C++0x allows a std::nullptr_t value.
|
||||
(ParamType->isMemberPointerType() &&
|
||||
ParamType->getAsMemberPointerType()->getPointeeType()
|
||||
->isFunctionType())) {
|
||||
if (Context.hasSameUnqualifiedType(ArgType,
|
||||
ParamType.getNonReferenceType())) {
|
||||
// We don't have to do anything: the types already match.
|
||||
} else if (ArgType->isNullPtrType() && (ParamType->isPointerType() ||
|
||||
ParamType->isMemberPointerType())) {
|
||||
ArgType = ParamType;
|
||||
ImpCastExprToType(Arg, ParamType);
|
||||
} else if (ArgType->isFunctionType() && ParamType->isPointerType()) {
|
||||
ArgType = Context.getPointerType(ArgType);
|
||||
ImpCastExprToType(Arg, ArgType);
|
||||
|
@ -1554,14 +1568,18 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
|||
// -- for a non-type template-parameter of type pointer to
|
||||
// object, qualification conversions (4.4) and the
|
||||
// array-to-pointer conversion (4.2) are applied.
|
||||
// C++0x also allows a value of std::nullptr_t.
|
||||
assert(ParamType->getAsPointerType()->getPointeeType()->isObjectType() &&
|
||||
"Only object pointers allowed here");
|
||||
|
||||
if (ArgType->isArrayType()) {
|
||||
if (ArgType->isNullPtrType()) {
|
||||
ArgType = ParamType;
|
||||
ImpCastExprToType(Arg, ParamType);
|
||||
} else if (ArgType->isArrayType()) {
|
||||
ArgType = Context.getArrayDecayedType(ArgType);
|
||||
ImpCastExprToType(Arg, ArgType);
|
||||
}
|
||||
|
||||
|
||||
if (IsQualificationConversion(ArgType, ParamType)) {
|
||||
ArgType = ParamType;
|
||||
ImpCastExprToType(Arg, ParamType);
|
||||
|
@ -1630,10 +1648,13 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
|
|||
|
||||
// -- For a non-type template-parameter of type pointer to data
|
||||
// member, qualification conversions (4.4) are applied.
|
||||
// C++0x allows std::nullptr_t values.
|
||||
assert(ParamType->isMemberPointerType() && "Only pointers to members remain");
|
||||
|
||||
if (Context.hasSameUnqualifiedType(ParamType, ArgType)) {
|
||||
// Types match exactly: nothing more to do here.
|
||||
} else if (ArgType->isNullPtrType()) {
|
||||
ImpCastExprToType(Arg, ParamType);
|
||||
} else if (IsQualificationConversion(ArgType, ParamType)) {
|
||||
ImpCastExprToType(Arg, ParamType);
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s
|
||||
#include <stdint.h>
|
||||
|
||||
// Don't have decltype yet.
|
||||
typedef __typeof__(nullptr) nullptr_t;
|
||||
|
||||
struct A {};
|
||||
|
||||
int o1(char*);
|
||||
void o1(uintptr_t);
|
||||
void o2(char*); // expected-note {{candidate}}
|
||||
void o2(int A::*); // expected-note {{candidate}}
|
||||
|
||||
nullptr_t f(nullptr_t null)
|
||||
{
|
||||
// Implicit conversions.
|
||||
null = nullptr;
|
||||
void *p = nullptr;
|
||||
p = null;
|
||||
int *pi = nullptr;
|
||||
pi = null;
|
||||
null = 0;
|
||||
int A::*pm = nullptr;
|
||||
pm = null;
|
||||
void (*pf)() = nullptr;
|
||||
pf = null;
|
||||
void (A::*pmf)() = nullptr;
|
||||
pmf = null;
|
||||
bool b = nullptr;
|
||||
|
||||
// Can't convert nullptr to integral implicitly.
|
||||
uintptr_t i = nullptr; // expected-error {{incompatible type initializing}}
|
||||
|
||||
// Operators
|
||||
(void)(null == nullptr);
|
||||
(void)(null <= nullptr);
|
||||
(void)(null == (void*)0);
|
||||
(void)((void*)0 == nullptr);
|
||||
(void)(null <= (void*)0);
|
||||
(void)((void*)0 <= nullptr);
|
||||
(void)(1 > nullptr); // expected-error {{invalid operands to binary expression}}
|
||||
(void)(1 != nullptr); // expected-error {{invalid operands to binary expression}}
|
||||
(void)(1 + nullptr); // expected-error {{invalid operands to binary expression}}
|
||||
(void)(0 ? nullptr : 0); // expected-error {{incompatible operand types}}
|
||||
(void)(0 ? nullptr : (void*)0);
|
||||
|
||||
// Overloading
|
||||
int t = o1(nullptr);
|
||||
t = o1(null);
|
||||
o2(nullptr); // expected-error {{ambiguous}}
|
||||
|
||||
// nullptr is an rvalue, null is an lvalue
|
||||
(void)&nullptr; // expected-error {{address expression must be an lvalue}}
|
||||
nullptr_t *pn = &null;
|
||||
|
||||
// You can reinterpret_cast nullptr to an integer.
|
||||
(void)reinterpret_cast<uintptr_t>(nullptr);
|
||||
|
||||
// You can throw nullptr.
|
||||
throw nullptr;
|
||||
}
|
||||
|
||||
// Template arguments can be nullptr.
|
||||
template <int *PI, void (*PF)(), int A::*PM, void (A::*PMF)()>
|
||||
struct T {};
|
||||
|
||||
typedef T<nullptr, nullptr, nullptr, nullptr> NT;
|
|
@ -1952,38 +1952,46 @@ welcome!</p>
|
|||
<tr><td>E [extendid]</td><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
<tr>
|
||||
<td colspan="6" align="center" bgcolor="#ffffcc">C++0x Features</td>
|
||||
<tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Explicit conversion operators (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf">N2437</a>)</td>
|
||||
<td class="complete" align="center">✓</td>
|
||||
<td class="medium" align="center"></td>
|
||||
<td class="advanced" align="center"></td>
|
||||
<td class="broken"></td>
|
||||
<td>No name mangling; ASTs don't contain calls to conversion operators</td>
|
||||
</tr>
|
||||
<tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Static assertions (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.pdf">N1720</a>)</td>
|
||||
<td class="complete" align="center">✓</td>
|
||||
<td class="complete" align="center">✓</td>
|
||||
<td class="complete" align="center">✓</td>
|
||||
<td class="na">N/A</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Deleted functions (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">N2346</a>)</td>
|
||||
<td class="complete" align="center">✓</td>
|
||||
<td class="complete" align="center">✓</td>
|
||||
<td class="complete" align="center">✓</td>
|
||||
<td class="na">N/A</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rvalue references (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html">N2118</a> + <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2831.html">N2831</a>)</td>
|
||||
<td class="complete" align="center">✓</td>
|
||||
<td class="complete" align="center">✓</td>
|
||||
<td class="complete" align="center">✓</td>
|
||||
<td class="broken"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>nullptr (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf">N2431</a>)</td>
|
||||
<td class="complete" align="center">✓</td>
|
||||
<td class="complete" align="center">✓</td>
|
||||
<td class="complete" align="center">✓</td>
|
||||
<td class="broken"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
|
Loading…
Reference in New Issue