Implement C++0x nullptr.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71405 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 3054028..20d1edb 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1534,6 +1534,9 @@
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);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 063e0ec..d2e84c1 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -3811,6 +3811,20 @@
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();
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 92df67a..5f2b705 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -85,6 +85,12 @@
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) {
diff --git a/lib/Sema/SemaNamedCast.cpp b/lib/Sema/SemaNamedCast.cpp
index f5bef4a..e0b94a4 100644
--- a/lib/Sema/SemaNamedCast.cpp
+++ b/lib/Sema/SemaNamedCast.cpp
@@ -279,12 +279,26 @@
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;
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index e6b8056..50330e3 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -621,7 +621,8 @@
FromType->isEnumeralType() ||
FromType->isPointerType() ||
FromType->isBlockPointerType() ||
- FromType->isMemberPointerType())) {
+ FromType->isMemberPointerType() ||
+ FromType->isNullPtrType())) {
SCS.Second = ICK_Boolean_Conversion;
FromType = Context.BoolTy;
}
@@ -898,6 +899,13 @@
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;
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index e62b9a2..c8fdc22 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1198,6 +1198,10 @@
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 @@
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 @@
// 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 @@
// 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 @@
// -- 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 @@
// -- 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 {