forked from OSchip/llvm-project
Do not issue -Wnullability-completeness for dependent types that are not written as pointer types.
llvm-svn: 303451
This commit is contained in:
parent
d05a006a53
commit
0a12b90c98
|
@ -2011,10 +2011,11 @@ public:
|
||||||
Optional<NullabilityKind> getNullability(const ASTContext &context) const;
|
Optional<NullabilityKind> getNullability(const ASTContext &context) const;
|
||||||
|
|
||||||
/// Determine whether the given type can have a nullability
|
/// Determine whether the given type can have a nullability
|
||||||
/// specifier applied to it, i.e., if it is any kind of pointer type
|
/// specifier applied to it, i.e., if it is any kind of pointer type.
|
||||||
/// or a dependent type that could instantiate to any kind of
|
///
|
||||||
/// pointer type.
|
/// \param ResultIfUnknown The value to return if we don't yet know whether
|
||||||
bool canHaveNullability() const;
|
/// this type can have nullability because it is dependent.
|
||||||
|
bool canHaveNullability(bool ResultIfUnknown = true) const;
|
||||||
|
|
||||||
/// Retrieve the set of substitutions required when accessing a member
|
/// Retrieve the set of substitutions required when accessing a member
|
||||||
/// of the Objective-C receiver type that is declared in the given context.
|
/// of the Objective-C receiver type that is declared in the given context.
|
||||||
|
|
|
@ -3531,7 +3531,7 @@ Optional<NullabilityKind> Type::getNullability(const ASTContext &context) const
|
||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::canHaveNullability() const {
|
bool Type::canHaveNullability(bool ResultIfUnknown) const {
|
||||||
QualType type = getCanonicalTypeInternal();
|
QualType type = getCanonicalTypeInternal();
|
||||||
|
|
||||||
switch (type->getTypeClass()) {
|
switch (type->getTypeClass()) {
|
||||||
|
@ -3559,7 +3559,8 @@ bool Type::canHaveNullability() const {
|
||||||
case Type::SubstTemplateTypeParmPack:
|
case Type::SubstTemplateTypeParmPack:
|
||||||
case Type::DependentName:
|
case Type::DependentName:
|
||||||
case Type::DependentTemplateSpecialization:
|
case Type::DependentTemplateSpecialization:
|
||||||
return true;
|
case Type::Auto:
|
||||||
|
return ResultIfUnknown;
|
||||||
|
|
||||||
// Dependent template specializations can instantiate to pointer
|
// Dependent template specializations can instantiate to pointer
|
||||||
// types unless they're known to be specializations of a class
|
// types unless they're known to be specializations of a class
|
||||||
|
@ -3571,12 +3572,7 @@ bool Type::canHaveNullability() const {
|
||||||
if (isa<ClassTemplateDecl>(templateDecl))
|
if (isa<ClassTemplateDecl>(templateDecl))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return ResultIfUnknown;
|
||||||
|
|
||||||
// auto is considered dependent when it isn't deduced.
|
|
||||||
case Type::Auto:
|
|
||||||
case Type::DeducedTemplateSpecialization:
|
|
||||||
return !cast<DeducedType>(type.getTypePtr())->isDeduced();
|
|
||||||
|
|
||||||
case Type::Builtin:
|
case Type::Builtin:
|
||||||
switch (cast<BuiltinType>(type.getTypePtr())->getKind()) {
|
switch (cast<BuiltinType>(type.getTypePtr())->getKind()) {
|
||||||
|
@ -3595,7 +3591,7 @@ bool Type::canHaveNullability() const {
|
||||||
case BuiltinType::PseudoObject:
|
case BuiltinType::PseudoObject:
|
||||||
case BuiltinType::UnknownAny:
|
case BuiltinType::UnknownAny:
|
||||||
case BuiltinType::ARCUnbridgedCast:
|
case BuiltinType::ARCUnbridgedCast:
|
||||||
return true;
|
return ResultIfUnknown;
|
||||||
|
|
||||||
case BuiltinType::Void:
|
case BuiltinType::Void:
|
||||||
case BuiltinType::ObjCId:
|
case BuiltinType::ObjCId:
|
||||||
|
@ -3614,6 +3610,7 @@ bool Type::canHaveNullability() const {
|
||||||
case BuiltinType::OMPArraySection:
|
case BuiltinType::OMPArraySection:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
llvm_unreachable("unknown builtin type");
|
||||||
|
|
||||||
// Non-pointer types.
|
// Non-pointer types.
|
||||||
case Type::Complex:
|
case Type::Complex:
|
||||||
|
@ -3629,6 +3626,7 @@ bool Type::canHaveNullability() const {
|
||||||
case Type::FunctionProto:
|
case Type::FunctionProto:
|
||||||
case Type::FunctionNoProto:
|
case Type::FunctionNoProto:
|
||||||
case Type::Record:
|
case Type::Record:
|
||||||
|
case Type::DeducedTemplateSpecialization:
|
||||||
case Type::Enum:
|
case Type::Enum:
|
||||||
case Type::InjectedClassName:
|
case Type::InjectedClassName:
|
||||||
case Type::PackExpansion:
|
case Type::PackExpansion:
|
||||||
|
|
|
@ -3735,16 +3735,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||||
// inner pointers.
|
// inner pointers.
|
||||||
complainAboutMissingNullability = CAMN_InnerPointers;
|
complainAboutMissingNullability = CAMN_InnerPointers;
|
||||||
|
|
||||||
auto isDependentNonPointerType = [](QualType T) -> bool {
|
if (T->canHaveNullability(/*ResultIfUnknown*/false) &&
|
||||||
// Note: This is intended to be the same check as Type::canHaveNullability
|
!T->getNullability(S.Context)) {
|
||||||
// except with all of the ambiguous cases being treated as 'false' rather
|
|
||||||
// than 'true'.
|
|
||||||
return T->isDependentType() && !T->isAnyPointerType() &&
|
|
||||||
!T->isBlockPointerType() && !T->isMemberPointerType();
|
|
||||||
};
|
|
||||||
|
|
||||||
if (T->canHaveNullability() && !T->getNullability(S.Context) &&
|
|
||||||
!isDependentNonPointerType(T)) {
|
|
||||||
// Note that we allow but don't require nullability on dependent types.
|
// Note that we allow but don't require nullability on dependent types.
|
||||||
++NumPointersRemaining;
|
++NumPointersRemaining;
|
||||||
}
|
}
|
||||||
|
@ -3962,7 +3954,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
||||||
// If the type itself could have nullability but does not, infer pointer
|
// If the type itself could have nullability but does not, infer pointer
|
||||||
// nullability and perform consistency checking.
|
// nullability and perform consistency checking.
|
||||||
if (S.CodeSynthesisContexts.empty()) {
|
if (S.CodeSynthesisContexts.empty()) {
|
||||||
if (T->canHaveNullability() && !T->getNullability(S.Context)) {
|
if (T->canHaveNullability(/*ResultIfUnknown*/false) &&
|
||||||
|
!T->getNullability(S.Context)) {
|
||||||
if (isVaList(T)) {
|
if (isVaList(T)) {
|
||||||
// Record that we've seen a pointer, but do nothing else.
|
// Record that we've seen a pointer, but do nothing else.
|
||||||
if (NumPointersRemaining > 0)
|
if (NumPointersRemaining > 0)
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
template<typename T> struct Template final {
|
||||||
|
int *_Nonnull x;
|
||||||
|
T y;
|
||||||
|
};
|
|
@ -1,10 +1,12 @@
|
||||||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wno-nullability-declspec %s -verify -Wnullable-to-nonnull-conversion
|
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wno-nullability-declspec %s -verify -Wnullable-to-nonnull-conversion -I%S/Inputs
|
||||||
|
|
||||||
#if __has_feature(nullability)
|
#if __has_feature(nullability)
|
||||||
#else
|
#else
|
||||||
# error nullability feature should be defined
|
# error nullability feature should be defined
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "nullability-completeness.h"
|
||||||
|
|
||||||
typedef decltype(nullptr) nullptr_t;
|
typedef decltype(nullptr) nullptr_t;
|
||||||
|
|
||||||
class X {
|
class X {
|
||||||
|
@ -130,3 +132,7 @@ void arraysInLambdas() {
|
||||||
withTypedef(nullptr); // expected-warning {{null passed to a callee that requires a non-null argument}}
|
withTypedef(nullptr); // expected-warning {{null passed to a callee that requires a non-null argument}}
|
||||||
auto withTypedefBad = [](INTS _Nonnull[2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int [4]')}}
|
auto withTypedefBad = [](INTS _Nonnull[2]) {}; // expected-error {{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'INTS' (aka 'int [4]')}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testNullabilityCompletenessWithTemplate() {
|
||||||
|
Template<int*> tip;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue