ahatanak created this revision.
ahatanak added a reviewer: doug.gregor.
ahatanak added a subscriber: cfe-commits.
This patch fixes Sema to propagate the nullability of the initializer
expression of a variable declared with auto or __auto_type to the deduced type.
The patch consists of two parts:
- Define function QualType::setNullability, which is used to return a QualType
with the specified nullability, and use it in computeConditionalNullability.
- Propagate nullability when type of auto is being deduced.
rdar://problem/27062504
https://reviews.llvm.org/D22794
Files:
include/clang/AST/Type.h
lib/AST/Type.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaExpr.cpp
test/Sema/nullability.c
test/SemaCXX/nullability.cpp
Index: test/SemaCXX/nullability.cpp
===================================================================
--- test/SemaCXX/nullability.cpp
+++ test/SemaCXX/nullability.cpp
@@ -98,6 +98,11 @@
TakeNonnull(ReturnNullable()); //expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull}}
}
+void * _Nonnull DeduceAuto() {
+ auto *p = ReturnNullable();
+ return p; // expected-warning{{implicit conversion from nullable pointer 'void * _Nullable' to non-nullable pointer type 'void * _Nonnull'}}
+}
+
void ConditionalExpr(bool c) {
struct Base {};
struct Derived : Base {};
Index: test/Sema/nullability.c
===================================================================
--- test/Sema/nullability.c
+++ test/Sema/nullability.c
@@ -129,6 +129,13 @@
accepts_nonnull_1(ptr); // expected-warning{{implicit conversion from nullable pointer 'int * _Nullable' to non-nullable pointer type 'int * _Nonnull'}}
}
+int * _Nullable return_nullable();
+
+int * _Nonnull deduce_auto() {
+ __auto_type *p = return_nullable();
+ return p; // expected-warning{{implicit conversion from nullable pointer 'int * _Nullable' to non-nullable pointer type 'int * _Nonnull'}}
+}
+
// Check nullability of conditional expressions.
void conditional_expr(int c) {
int * _Nonnull p;
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -7052,13 +7052,8 @@
if (GetNullability(ResTy) == MergedKind)
return ResTy;
- // Strip all nullability from ResTy.
- while (ResTy->getNullability(Ctx))
- ResTy = ResTy.getSingleStepDesugaredType(Ctx);
-
- // Create a new AttributedType with the new nullability kind.
- auto NewAttr = AttributedType::getNullabilityAttrKind(MergedKind);
- return Ctx.getAttributedType(NewAttr, ResTy, ResTy);
+ // Create a new type with the merged nullability kind.
+ return ResTy.setNullability(MergedKind, Ctx);
}
/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -9733,6 +9733,11 @@
return;
}
+ // Propagate init expression's nullability to the deduced type.
+ if (!Init->getType().isNull() && DeducedType->isAnyPointerType())
+ DeducedType = DeducedType.setNullability(
+ Init->getType()->getNullability(Context), Context);
+
VDecl->setType(DeducedType);
assert(VDecl->isLinkageValid());
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp
+++ lib/AST/Type.cpp
@@ -1279,6 +1279,23 @@
return getUnqualifiedType();
}
+QualType QualType::setNullability(Optional<NullabilityKind> Kind,
+ ASTContext &Ctx) const {
+ assert(getTypePtr()->isAnyPointerType() && "type has to be a pointer type");
+ QualType ResTy = *this;
+
+ // Strip all nullability specifiers.
+ while (ResTy->getNullability(Ctx))
+ ResTy = ResTy.getSingleStepDesugaredType(Ctx);
+
+ if (!Kind)
+ return ResTy;
+
+ // Create a new AttributedType with the new nullability kind.
+ auto NewAttr = AttributedType::getNullabilityAttrKind(*Kind);
+ return Ctx.getAttributedType(NewAttr, ResTy, ResTy);
+}
+
Optional<ArrayRef<QualType>> Type::getObjCSubstitutions(
const DeclContext *dc) const {
// Look through method scopes.
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h
+++ include/clang/AST/Type.h
@@ -1093,6 +1093,10 @@
/// Remove all qualifiers including _Atomic.
QualType getAtomicUnqualifiedType() const;
+ /// Create a type having the specified nullability.
+ QualType setNullability(Optional<NullabilityKind> Kind,
+ ASTContext &Ctx) const;
+
private:
// These methods are implemented in a separate translation unit;
// "static"-ize them to avoid creating temporary QualTypes in the
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits