Replace __double_underscored type nullability qualifiers with _Uppercase_underscored

Addresses a conflict with glibc's __nonnull macro by renaming the type
nullability qualifiers as follows:

  __nonnull -> _Nonnull
  __nullable -> _Nullable
  __null_unspecified -> _Null_unspecified

This is the major part of rdar://problem/21530726, but does not yet
provide the Darwin-specific behavior for the old names.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@240596 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2015-06-24 22:02:08 +00:00
parent 1e6e9d1a37
commit 673b679df9
45 changed files with 366 additions and 352 deletions

View File

@ -962,17 +962,17 @@ def ReturnsNonNull : InheritableAttr {
// Nullability type attributes.
def TypeNonNull : TypeAttr {
let Spellings = [Keyword<"__nonnull">];
let Spellings = [Keyword<"_Nonnull">];
let Documentation = [TypeNonNullDocs];
}
def TypeNullable : TypeAttr {
let Spellings = [Keyword<"__nullable">];
let Spellings = [Keyword<"_Nullable">];
let Documentation = [TypeNullableDocs];
}
def TypeNullUnspecified : TypeAttr {
let Spellings = [Keyword<"__null_unspecified">];
let Spellings = [Keyword<"_Null_unspecified">];
let Documentation = [TypeNullUnspecifiedDocs];
}

View File

@ -1456,22 +1456,22 @@ cannot point to the private address space.
def NullabilityDocs : DocumentationCategory<"Nullability Attributes"> {
let Content = [{
Whether a particular pointer may be "null" is an important concern when working with pointers in the C family of languages. The various nullability attributes indicate whether a particular pointer can be null or not, which makes APIs more expressive and can help static analysis tools identify bugs involving null pointers. Clang supports several kinds of nullability attributes: the ``nonnull`` and ``returns_nonnull`` attributes indicate which function or method parameters and result types can never be null, while nullability type qualifiers indicate which pointer types can be null (``__nullable``) or cannot be null (``__nonnull``).
Whether a particular pointer may be "null" is an important concern when working with pointers in the C family of languages. The various nullability attributes indicate whether a particular pointer can be null or not, which makes APIs more expressive and can help static analysis tools identify bugs involving null pointers. Clang supports several kinds of nullability attributes: the ``nonnull`` and ``returns_nonnull`` attributes indicate which function or method parameters and result types can never be null, while nullability type qualifiers indicate which pointer types can be null (``_Nullable``) or cannot be null (``_Nonnull``).
The nullability (type) qualifiers express whether a value of a given pointer type can be null (the ``__nullable`` qualifier), doesn't have a defined meaning for null (the ``__nonnull`` qualifier), or for which the purpose of null is unclear (the ``__null_unspecified`` qualifier). Because nullability qualifiers are expressed within the type system, they are more general than the ``nonnull`` and ``returns_nonnull`` attributes, allowing one to express (for example) a nullable pointer to an array of nonnull pointers. Nullability qualifiers are written to the right of the pointer to which they apply. For example:
The nullability (type) qualifiers express whether a value of a given pointer type can be null (the ``_Nullable`` qualifier), doesn't have a defined meaning for null (the ``_Nonnull`` qualifier), or for which the purpose of null is unclear (the ``_Null_unspecified`` qualifier). Because nullability qualifiers are expressed within the type system, they are more general than the ``nonnull`` and ``returns_nonnull`` attributes, allowing one to express (for example) a nullable pointer to an array of nonnull pointers. Nullability qualifiers are written to the right of the pointer to which they apply. For example:
.. code-block:: c
// No meaningful result when 'ptr' is null (here, it happens to be undefined behavior).
int fetch(int * __nonnull ptr) { return *ptr; }
int fetch(int * _Nonnull ptr) { return *ptr; }
// 'ptr' may be null.
int fetch_or_zero(int * __nullable ptr) {
int fetch_or_zero(int * _Nullable ptr) {
return ptr ? *ptr : 0;
}
// A nullable pointer to non-null pointers to const characters.
const char *join_strings(const char * __nonnull * __nullable strings, unsigned n);
const char *join_strings(const char * _Nonnull * _Nullable strings, unsigned n);
In Objective-C, there is an alternate spelling for the nullability qualifiers that can be used in Objective-C methods and properties using context-sensitive, non-underscored keywords. For example:
@ -1487,27 +1487,27 @@ In Objective-C, there is an alternate spelling for the nullability qualifiers th
def TypeNonNullDocs : Documentation {
let Category = NullabilityDocs;
let Heading = "__nonnull";
let Heading = "_Nonnull";
let Content = [{
The ``__nonnull`` nullability qualifier indicates that null is not a meaningful value for a value of the ``__nonnull`` pointer type. For example, given a declaration such as:
The ``_Nonnull`` nullability qualifier indicates that null is not a meaningful value for a value of the ``_Nonnull`` pointer type. For example, given a declaration such as:
.. code-block:: c
int fetch(int * __nonnull ptr);
int fetch(int * _Nonnull ptr);
a caller of ``fetch`` should not provide a null value, and the compiler will produce a warning if it sees a literal null value passed to ``fetch``. Note that, unlike the declaration attribute ``nonnull``, the presence of ``__nonnull`` does not imply that passing null is undefined behavior: ``fetch`` is free to consider null undefined behavior or (perhaps for backward-compatibility reasons) defensively handle null.
a caller of ``fetch`` should not provide a null value, and the compiler will produce a warning if it sees a literal null value passed to ``fetch``. Note that, unlike the declaration attribute ``nonnull``, the presence of ``_Nonnull`` does not imply that passing null is undefined behavior: ``fetch`` is free to consider null undefined behavior or (perhaps for backward-compatibility reasons) defensively handle null.
}];
}
def TypeNullableDocs : Documentation {
let Category = NullabilityDocs;
let Heading = "__nullable";
let Heading = "_Nullable";
let Content = [{
The ``__nullable`` nullability qualifier indicates that a value of the ``__nullable`` pointer type can be null. For example, given:
The ``_Nullable`` nullability qualifier indicates that a value of the ``_Nullable`` pointer type can be null. For example, given:
.. code-block:: c
int fetch_or_zero(int * __nullable ptr);
int fetch_or_zero(int * _Nullable ptr);
a caller of ``fetch_or_zero`` can provide null.
}];
@ -1515,9 +1515,9 @@ a caller of ``fetch_or_zero`` can provide null.
def TypeNullUnspecifiedDocs : Documentation {
let Category = NullabilityDocs;
let Heading = "__null_unspecified";
let Heading = "_Null_unspecified";
let Content = [{
The ``__null_unspecified`` nullability qualifier indicates that neither the ``__nonnull`` nor ``__nullable`` qualifiers make sense for a particular pointer type. It is used primarily to indicate that the role of null with specific pointers in a nullability-annotated header is unclear, e.g., due to overly-complex implementations or historical factors with a long-lived API.
The ``_Null_unspecified`` nullability qualifier indicates that neither the ``_Nonnull`` nor ``_Nullable`` qualifiers make sense for a particular pointer type. It is used primarily to indicate that the role of null with specific pointers in a nullability-annotated header is unclear, e.g., due to overly-complex implementations or historical factors with a long-lived API.
}];
}
@ -1547,7 +1547,7 @@ Clang also allows the ``nonnull`` attribute to be placed directly on a function
extern void * my_memcpy (void *dest __attribute__((nonnull)),
const void *src __attribute__((nonnull)), size_t len);
Note that the ``nonnull`` attribute indicates that passing null to a non-null parameter is undefined behavior, which the optimizer may take advantage of to, e.g., remove null checks. The ``__nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable.
Note that the ``nonnull`` attribute indicates that passing null to a non-null parameter is undefined behavior, which the optimizer may take advantage of to, e.g., remove null checks. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable.
}];
}
@ -1561,6 +1561,6 @@ The ``returns_nonnull`` attribute indicates that a particular function (or Objec
extern void * malloc (size_t size) __attribute__((returns_nonnull));
The ``returns_nonnull`` attribute implies that returning a null pointer is undefined behavior, which the optimizer may take advantage of. The ``__nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable
The ``returns_nonnull`` attribute implies that returning a null pointer is undefined behavior, which the optimizer may take advantage of. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable
}];
}

View File

@ -18,6 +18,7 @@
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@ -1107,6 +1108,13 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
return DB;
}
/// A nullability kind paired with a bit indicating whether it used a
/// context-sensitive keyword.
typedef std::pair<NullabilityKind, bool> DiagNullabilityKind;
const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
DiagNullabilityKind nullability);
inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc,
unsigned DiagID) {
assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");

View File

@ -102,31 +102,21 @@ def err_enum_template : Error<"enumeration cannot be a template">;
let CategoryName = "Nullability Issue" in {
def warn_nullability_duplicate : Warning<
"duplicate nullability specifier "
"'%select{__|}1%select{nonnull|nullable|null_unspecified}0'">,
"duplicate nullability specifier %0">,
InGroup<Nullability>;
def warn_conflicting_nullability_attr_overriding_ret_types : Warning<
"conflicting nullability specifier on return types, "
"'%select{%select{__|}1nonnull|"
"%select{__|}1nullable|%select{__|}1null_unspecified}0' "
"conflicts with existing specifier '%select{%select{__|}3nonnull|"
"%select{__|}3nullable|%select{__|}3null_unspecified}2'">,
"conflicting nullability specifier on return types, %0 "
"conflicts with existing specifier %1">,
InGroup<Nullability>;
def warn_conflicting_nullability_attr_overriding_param_types : Warning<
"conflicting nullability specifier on parameter types, "
"'%select{%select{__|}1nonnull|"
"%select{__|}1nullable|%select{__|}1null_unspecified}0' "
"conflicts with existing specifier '%select{%select{__|}3nonnull|"
"%select{__|}3nullable|%select{__|}3null_unspecified}2'">,
"conflicting nullability specifier on parameter types, %0 "
"conflicts with existing specifier %1">,
InGroup<Nullability>;
def err_nullability_conflicting : Error<
"nullability specifier "
"'%select{__|}1%select{nonnull|nullable|null_unspecified}0' conflicts with "
"existing specifier '%select{__|}3%select{nonnull|nullable|"
"null_unspecified}2'">;
"nullability specifier %0 conflicts with existing specifier %1">;
}

View File

@ -7679,28 +7679,21 @@ def warn_profile_data_unprofiled : Warning<
let CategoryName = "Nullability Issue" in {
def warn_mismatched_nullability_attr : Warning<
"nullability specifier "
"'%select{__|}1%select{nonnull|nullable|null_unspecified}0' "
"conflicts with existing specifier "
"'%select{__|}3%select{nonnull|nullable|null_unspecified}2'">,
"nullability specifier %0 conflicts with existing specifier %1">,
InGroup<Nullability>;
def warn_nullability_declspec : Warning<
"nullability specifier "
"'%select{__nonnull|__nullable|__null_unspecified}0' cannot be applied "
"nullability specifier %0 cannot be applied "
"to non-pointer type %1; did you mean to apply the specifier to the "
"%select{pointer|block pointer|member pointer|function pointer|"
"member function pointer}2?">,
InGroup<NullabilityDeclSpec>,
DefaultError;
def note_nullability_here : Note<
"'%select{__nonnull|__nullable|__null_unspecified}0' specified here">;
def note_nullability_here : Note<"%0 specified here">;
def err_nullability_nonpointer : Error<
"nullability specifier "
"'%select{__|}1%select{nonnull|nullable|null_unspecified}0' cannot be applied "
"to non-pointer type %2">;
"nullability specifier %0 cannot be applied to non-pointer type %1">;
def warn_nullability_lost : Warning<
"implicit conversion from nullable pointer %0 to non-nullable pointer "
@ -7708,12 +7701,9 @@ def warn_nullability_lost : Warning<
InGroup<NullableToNonNullConversion>, DefaultIgnore;
def err_nullability_cs_multilevel : Error<
"nullability keyword "
"'%select{nonnull|nullable|null_unspecified}0' cannot be applied to "
"multi-level pointer type %1">;
"nullability keyword %0 cannot be applied to multi-level pointer type %1">;
def note_nullability_type_specifier : Note<
"use nullability type specifier "
"'%select{__nonnull|__nullable|__null_unspecified}0' to affect the innermost "
"use nullability type specifier %0 to affect the innermost "
"pointer type of %1">;
def warn_null_resettable_setter : Warning<
@ -7722,7 +7712,7 @@ def warn_null_resettable_setter : Warning<
def warn_nullability_missing : Warning<
"%select{pointer|block pointer|member pointer}0 is missing a nullability "
"type specifier (__nonnull, __nullable, or __null_unspecified)">,
"type specifier (_Nonnull, _Nullable, or _Null_unspecified)">,
InGroup<NullabilityCompleteness>;
}

View File

@ -257,7 +257,8 @@ namespace clang {
};
/// Retrieve the spelling of the given nullability kind.
llvm::StringRef getNullabilitySpelling(NullabilityKind kind);
llvm::StringRef getNullabilitySpelling(NullabilityKind kind,
bool isContextSensitive = false);
} // end namespace clang
#endif // LLVM_CLANG_BASIC_SPECIFIERS_H

View File

@ -549,9 +549,9 @@ ALIAS("__volatile" , volatile , KEYALL)
ALIAS("__volatile__" , volatile , KEYALL)
// Type nullability.
KEYWORD(__nonnull , KEYALL)
KEYWORD(__nullable , KEYALL)
KEYWORD(__null_unspecified , KEYALL)
KEYWORD(_Nonnull , KEYALL)
KEYWORD(_Nullable , KEYALL)
KEYWORD(_Null_unspecified , KEYALL)
// Microsoft extensions which should be disabled in strict conformance mode
KEYWORD(__ptr64 , KEYMS)

View File

@ -303,7 +303,7 @@ public:
return true;
}
/// Retrieve the underscored keyword (__nonnull, __nullable) that corresponds
/// Retrieve the underscored keyword (_Nonnull, _Nullable) that corresponds
/// to the given nullability kind.
IdentifierInfo *getNullabilityKeyword(NullabilityKind nullability) {
return Actions.getNullabilityKeyword(nullability);

View File

@ -2978,7 +2978,7 @@ public:
bool SynthesizeProperties);
/// Diagnose any null-resettable synthesized setters.
void diagnoseNullResettableSynthesizedSetters(ObjCImplDecl *impDecl);
void diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl);
/// DefaultSynthesizeProperties - This routine default synthesizes all
/// properties which must be synthesized in the class's \@implementation.
@ -8854,9 +8854,9 @@ private:
mutable IdentifierInfo *Ident___float128;
/// Nullability type specifiers.
IdentifierInfo *Ident___nonnull = nullptr;
IdentifierInfo *Ident___nullable = nullptr;
IdentifierInfo *Ident___null_unspecified = nullptr;
IdentifierInfo *Ident__Nonnull = nullptr;
IdentifierInfo *Ident__Nullable = nullptr;
IdentifierInfo *Ident__Null_unspecified = nullptr;
IdentifierInfo *Ident_NSError = nullptr;

View File

@ -954,9 +954,8 @@ void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,
if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Oneway)
Out << "oneway ";
if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_CSNullability) {
if (auto nullability = AttributedType::stripOuterNullability(T)) {
Out << getNullabilitySpelling(*nullability).substr(2) << ' ';
}
if (auto nullability = AttributedType::stripOuterNullability(T))
Out << getNullabilitySpelling(*nullability, true) << ' ';
}
Out << Ctx.getUnqualifiedObjCPointerType(T).getAsString(Policy);
@ -1207,7 +1206,7 @@ void DeclPrinter::VisitObjCPropertyDecl(ObjCPropertyDecl *PDecl) {
Out << (first ? ' ' : ',') << "null_resettable";
} else {
Out << (first ? ' ' : ',')
<< getNullabilitySpelling(*nullability).substr(2);
<< getNullabilitySpelling(*nullability, true);
}
first = false;
}

View File

@ -1147,11 +1147,11 @@ void TypePrinter::printAttributedBefore(const AttributedType *T,
T->getAttrKind() == AttributedType::attr_nullable ||
T->getAttrKind() == AttributedType::attr_null_unspecified) {
if (T->getAttrKind() == AttributedType::attr_nonnull)
OS << " __nonnull";
OS << " _Nonnull";
else if (T->getAttrKind() == AttributedType::attr_nullable)
OS << " __nullable";
OS << " _Nullable";
else if (T->getAttrKind() == AttributedType::attr_null_unspecified)
OS << " __null_unspecified";
OS << " _Null_unspecified";
else
llvm_unreachable("unhandled nullability");
spaceBeforePlaceHolder(OS);
@ -1186,11 +1186,11 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
T->getAttrKind() == AttributedType::attr_nullable ||
T->getAttrKind() == AttributedType::attr_null_unspecified) {
if (T->getAttrKind() == AttributedType::attr_nonnull)
OS << " __nonnull";
OS << " _Nonnull";
else if (T->getAttrKind() == AttributedType::attr_nullable)
OS << " __nullable";
OS << " _Nullable";
else if (T->getAttrKind() == AttributedType::attr_null_unspecified)
OS << " __null_unspecified";
OS << " _Null_unspecified";
else
llvm_unreachable("unhandled nullability");

View File

@ -24,6 +24,27 @@
using namespace clang;
const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
DiagNullabilityKind nullability) {
StringRef string;
switch (nullability.first) {
case NullabilityKind::NonNull:
string = nullability.second ? "'nonnull'" : "'_Nonnull'";
break;
case NullabilityKind::Nullable:
string = nullability.second ? "'nullable'" : "'_Nullable'";
break;
case NullabilityKind::Unspecified:
string = nullability.second ? "'null_unspecified'" : "'_Null_unspecified'";
break;
}
DB.AddString(string);
return DB;
}
static void DummyArgToStringFn(DiagnosticsEngine::ArgumentKind AK, intptr_t QT,
StringRef Modifier, StringRef Argument,
ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,

View File

@ -647,16 +647,17 @@ const char *clang::getOperatorSpelling(OverloadedOperatorKind Operator) {
llvm_unreachable("Invalid OverloadedOperatorKind!");
}
StringRef clang::getNullabilitySpelling(NullabilityKind kind) {
StringRef clang::getNullabilitySpelling(NullabilityKind kind,
bool isContextSensitive) {
switch (kind) {
case NullabilityKind::NonNull:
return "__nonnull";
return isContextSensitive ? "nonnull" : "_Nonnull";
case NullabilityKind::Nullable:
return "__nullable";
return isContextSensitive ? "nullable" : "_Nullable";
case NullabilityKind::Unspecified:
return "__null_unspecified";
return isContextSensitive ? "null_unspecified" : "_Null_unspecified";
}
llvm_unreachable("Unknown nullability kind.");
}

View File

@ -691,9 +691,9 @@ void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) {
// Treat these like attributes, even though they're type specifiers.
while (true) {
switch (Tok.getKind()) {
case tok::kw___nonnull:
case tok::kw___nullable:
case tok::kw___null_unspecified: {
case tok::kw__Nonnull:
case tok::kw__Nullable:
case tok::kw__Null_unspecified: {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
if (!getLangOpts().ObjC1)
@ -3076,9 +3076,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
continue;
// Nullability type specifiers.
case tok::kw___nonnull:
case tok::kw___nullable:
case tok::kw___null_unspecified:
case tok::kw__Nonnull:
case tok::kw__Nullable:
case tok::kw__Null_unspecified:
ParseNullabilityTypeSpecifiers(DS.getAttributes());
continue;
@ -4326,9 +4326,9 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw___pascal:
case tok::kw___unaligned:
case tok::kw___nonnull:
case tok::kw___nullable:
case tok::kw___null_unspecified:
case tok::kw__Nonnull:
case tok::kw__Nullable:
case tok::kw__Null_unspecified:
case tok::kw___private:
case tok::kw___local:
@ -4503,9 +4503,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::kw___pascal:
case tok::kw___unaligned:
case tok::kw___nonnull:
case tok::kw___nullable:
case tok::kw___null_unspecified:
case tok::kw__Nonnull:
case tok::kw__Nullable:
case tok::kw__Null_unspecified:
case tok::kw___private:
case tok::kw___local:
@ -4738,9 +4738,9 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs,
goto DoneWithTypeQuals;
// Nullability type specifiers.
case tok::kw___nonnull:
case tok::kw___nullable:
case tok::kw___null_unspecified:
case tok::kw__Nonnull:
case tok::kw__Nullable:
case tok::kw__Null_unspecified:
ParseNullabilityTypeSpecifiers(DS.getAttributes());
continue;

View File

@ -557,14 +557,14 @@ static void diagnoseRedundantPropertyNullability(Parser &P,
SourceLocation nullabilityLoc){
if (DS.getNullability() == nullability) {
P.Diag(nullabilityLoc, diag::warn_nullability_duplicate)
<< static_cast<unsigned>(nullability) << true
<< DiagNullabilityKind(nullability, true)
<< SourceRange(DS.getNullabilityLoc());
return;
}
P.Diag(nullabilityLoc, diag::err_nullability_conflicting)
<< static_cast<unsigned>(nullability) << true
<< static_cast<unsigned>(DS.getNullability()) << true
<< DiagNullabilityKind(nullability, true)
<< DiagNullabilityKind(DS.getNullability(), true)
<< SourceRange(DS.getNullabilityLoc());
}

View File

@ -632,8 +632,8 @@ Parser::TPResult Parser::TryParsePtrOperatorSeq() {
// ptr-operator
ConsumeToken();
while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict,
tok::kw___nonnull, tok::kw___nullable,
tok::kw___null_unspecified))
tok::kw__Nonnull, tok::kw__Nullable,
tok::kw__Null_unspecified))
ConsumeToken();
} else {
return TPResult::True;
@ -1276,9 +1276,9 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
case tok::kw___ptr32:
case tok::kw___forceinline:
case tok::kw___unaligned:
case tok::kw___nonnull:
case tok::kw___nullable:
case tok::kw___null_unspecified:
case tok::kw__Nonnull:
case tok::kw__Nullable:
case tok::kw__Null_unspecified:
return TPResult::True;
// Borland

View File

@ -1343,9 +1343,9 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts,
}
// Nullability
Results.AddResult(Result("__nonnull", CCP_Type));
Results.AddResult(Result("__null_unspecified", CCP_Type));
Results.AddResult(Result("__nullable", CCP_Type));
Results.AddResult(Result("_Nonnull", CCP_Type));
Results.AddResult(Result("_Null_unspecified", CCP_Type));
Results.AddResult(Result("_Nullable", CCP_Type));
}
static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,

View File

@ -2472,13 +2472,15 @@ static void mergeParamDeclTypes(ParmVarDecl *NewParam,
if (auto Oldnullability = OldParam->getType()->getNullability(S.Context)) {
if (auto Newnullability = NewParam->getType()->getNullability(S.Context)) {
if (*Oldnullability != *Newnullability) {
unsigned unsNewnullability = static_cast<unsigned>(*Newnullability);
unsigned unsOldnullability = static_cast<unsigned>(*Oldnullability);
S.Diag(NewParam->getLocation(), diag::warn_mismatched_nullability_attr)
<< unsNewnullability
<< ((NewParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0)
<< unsOldnullability
<< ((OldParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0);
<< DiagNullabilityKind(
*Newnullability,
((NewParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
!= 0))
<< DiagNullabilityKind(
*Oldnullability,
((OldParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
!= 0));
S.Diag(OldParam->getLocation(), diag::note_previous_declaration);
}
} else {

View File

@ -1400,16 +1400,20 @@ static bool CheckMethodOverrideReturn(Sema &S,
!S.Context.hasSameNullabilityTypeQualifier(MethodImpl->getReturnType(),
MethodDecl->getReturnType(),
false)) {
unsigned unsNullabilityMethodImpl =
static_cast<unsigned>(*MethodImpl->getReturnType()->getNullability(S.Context));
unsigned unsNullabilityMethodDecl =
static_cast<unsigned>(*MethodDecl->getReturnType()->getNullability(S.Context));
auto nullabilityMethodImpl =
*MethodImpl->getReturnType()->getNullability(S.Context);
auto nullabilityMethodDecl =
*MethodDecl->getReturnType()->getNullability(S.Context);
S.Diag(MethodImpl->getLocation(),
diag::warn_conflicting_nullability_attr_overriding_ret_types)
<< unsNullabilityMethodImpl
<< ((MethodImpl->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0)
<< unsNullabilityMethodDecl
<< ((MethodDecl->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0);
<< DiagNullabilityKind(
nullabilityMethodImpl,
((MethodImpl->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
!= 0))
<< DiagNullabilityKind(
nullabilityMethodDecl,
((MethodDecl->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
!= 0));
S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration);
}
@ -1486,15 +1490,17 @@ static bool CheckMethodOverrideParam(Sema &S,
if (Warn && IsOverridingMode &&
!isa<ObjCImplementationDecl>(MethodImpl->getDeclContext()) &&
!S.Context.hasSameNullabilityTypeQualifier(ImplTy, IfaceTy, true)) {
unsigned unsImplTy = static_cast<unsigned>(*ImplTy->getNullability(S.Context));
unsigned unsIfaceTy = static_cast<unsigned>(*IfaceTy->getNullability(S.Context));
S.Diag(ImplVar->getLocation(),
diag::warn_conflicting_nullability_attr_overriding_param_types)
<< unsImplTy
<< ((ImplVar->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0)
<< unsIfaceTy
<< ((IfaceVar->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) != 0);
S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration);
<< DiagNullabilityKind(
*ImplTy->getNullability(S.Context),
((ImplVar->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
!= 0))
<< DiagNullabilityKind(
*IfaceTy->getNullability(S.Context),
((IfaceVar->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
!= 0));
S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration);
}
if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy))
return true;
@ -3184,8 +3190,8 @@ static QualType mergeTypeNullabilityForRedecl(Sema &S, SourceLocation loc,
// Complain about mismatched nullability.
S.Diag(loc, diag::err_nullability_conflicting)
<< static_cast<unsigned>(*nullability) << usesCSKeyword
<< static_cast<unsigned>(*prevNullability) << prevUsesCSKeyword;
<< DiagNullabilityKind(*nullability, usesCSKeyword)
<< DiagNullabilityKind(*prevNullability, prevUsesCSKeyword);
return type;
}

View File

@ -1758,7 +1758,7 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
}
}
void Sema::diagnoseNullResettableSynthesizedSetters(ObjCImplDecl *impDecl) {
void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl) {
for (const auto *propertyImpl : impDecl->property_impls()) {
const auto *property = propertyImpl->getPropertyDecl();
@ -2025,7 +2025,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
if (property->getPropertyAttributes() &
ObjCPropertyDecl::OBJC_PR_null_resettable) {
QualType modifiedTy = resultTy;
if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){
if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)) {
if (*nullability == NullabilityKind::Unspecified)
resultTy = Context.getAttributedType(AttributedType::attr_nonnull,
modifiedTy, modifiedTy);

View File

@ -2567,19 +2567,19 @@ namespace {
IdentifierInfo *Sema::getNullabilityKeyword(NullabilityKind nullability) {
switch (nullability) {
case NullabilityKind::NonNull:
if (!Ident___nonnull)
Ident___nonnull = PP.getIdentifierInfo("__nonnull");
return Ident___nonnull;
if (!Ident__Nonnull)
Ident__Nonnull = PP.getIdentifierInfo("_Nonnull");
return Ident__Nonnull;
case NullabilityKind::Nullable:
if (!Ident___nullable)
Ident___nullable = PP.getIdentifierInfo("__nullable");
return Ident___nullable;
if (!Ident__Nullable)
Ident__Nullable = PP.getIdentifierInfo("_Nullable");
return Ident__Nullable;
case NullabilityKind::Unspecified:
if (!Ident___null_unspecified)
Ident___null_unspecified = PP.getIdentifierInfo("__null_unspecified");
return Ident___null_unspecified;
if (!Ident__Null_unspecified)
Ident__Null_unspecified = PP.getIdentifierInfo("_Null_unspecified");
return Ident__Null_unspecified;
}
llvm_unreachable("Unknown nullability kind.");
}
@ -2900,7 +2900,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
// Determine whether we should infer __nonnull on pointer types.
// Determine whether we should infer _Nonnull on pointer types.
Optional<NullabilityKind> inferNullability;
bool inferNullabilityCS = false;
bool inferNullabilityInnerOnly = false;
@ -3003,7 +3003,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
break;
case PointerDeclaratorKind::SingleLevelPointer:
// Infer __nonnull if we are in an assumes-nonnull region.
// Infer _Nonnull if we are in an assumes-nonnull region.
if (inAssumeNonNullRegion) {
inferNullability = NullabilityKind::NonNull;
inferNullabilityCS = (context == Declarator::ObjCParameterContext ||
@ -3013,7 +3013,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case PointerDeclaratorKind::CFErrorRefPointer:
case PointerDeclaratorKind::NSErrorPointerPointer:
// Within a function or method signature, infer __nullable at both
// Within a function or method signature, infer _Nullable at both
// levels.
if (isFunctionOrMethod && inAssumeNonNullRegion)
inferNullability = NullabilityKind::Nullable;
@ -3023,7 +3023,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (isFunctionOrMethod) {
// On pointer-to-pointer parameters marked cf_returns_retained or
// cf_returns_not_retained, if the outer pointer is explicit then
// infer the inner pointer as __nullable.
// infer the inner pointer as _Nullable.
auto hasCFReturnsAttr = [](const AttributeList *NextAttr) -> bool {
while (NextAttr) {
if (NextAttr->getKind() == AttributeList::AT_CFReturnsRetained ||
@ -3070,7 +3070,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
// Local function that checks the nullability for a given pointer declarator.
// Returns true if __nonnull was inferred.
// Returns true if _Nonnull was inferred.
auto inferPointerNullability = [&](SimplePointerKind pointerKind,
SourceLocation pointerLoc,
AttributeList *&attrs) -> AttributeList * {
@ -5084,8 +5084,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
// Duplicated nullability.
if (nullability == *existingNullability) {
Diag(nullabilityLoc, diag::warn_nullability_duplicate)
<< static_cast<unsigned>(nullability)
<< isContextSensitive
<< DiagNullabilityKind(nullability, isContextSensitive)
<< FixItHint::CreateRemoval(nullabilityLoc);
break;
@ -5093,10 +5092,8 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
// Conflicting nullability.
Diag(nullabilityLoc, diag::err_nullability_conflicting)
<< static_cast<unsigned>(nullability)
<< isContextSensitive
<< static_cast<unsigned>(*existingNullability)
<< false;
<< DiagNullabilityKind(nullability, isContextSensitive)
<< DiagNullabilityKind(*existingNullability, false);
return true;
}
@ -5110,10 +5107,8 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
if (auto existingNullability = desugared->getNullability(Context)) {
if (nullability != *existingNullability) {
Diag(nullabilityLoc, diag::err_nullability_conflicting)
<< static_cast<unsigned>(nullability)
<< isContextSensitive
<< static_cast<unsigned>(*existingNullability)
<< false;
<< DiagNullabilityKind(nullability, isContextSensitive)
<< DiagNullabilityKind(*existingNullability, false);
// Try to find the typedef with the existing nullability specifier.
if (auto typedefType = desugared->getAs<TypedefType>()) {
@ -5123,7 +5118,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
= AttributedType::stripOuterNullability(underlyingType)) {
if (*typedefNullability == *existingNullability) {
Diag(typedefDecl->getLocation(), diag::note_nullability_here)
<< static_cast<unsigned>(*existingNullability);
<< DiagNullabilityKind(*existingNullability, false);
}
}
}
@ -5135,7 +5130,7 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
// If this definitely isn't a pointer type, reject the specifier.
if (!desugared->canHaveNullability()) {
Diag(nullabilityLoc, diag::err_nullability_nonpointer)
<< static_cast<unsigned>(nullability) << isContextSensitive << type;
<< DiagNullabilityKind(nullability, isContextSensitive) << type;
return true;
}
@ -5148,10 +5143,10 @@ bool Sema::checkNullabilityTypeSpecifier(QualType &type,
pointeeType->isObjCObjectPointerType() ||
pointeeType->isMemberPointerType()) {
Diag(nullabilityLoc, diag::err_nullability_cs_multilevel)
<< static_cast<unsigned>(nullability)
<< DiagNullabilityKind(nullability, true)
<< type;
Diag(nullabilityLoc, diag::note_nullability_type_specifier)
<< static_cast<unsigned>(nullability)
<< DiagNullabilityKind(nullability, false)
<< type
<< FixItHint::CreateReplacement(nullabilityLoc,
getNullabilitySpelling(nullability));
@ -5216,7 +5211,8 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
auto diag = state.getSema().Diag(attr.getLoc(),
diag::warn_nullability_declspec)
<< static_cast<unsigned>(mapNullabilityAttrKind(attr.getKind()))
<< DiagNullabilityKind(mapNullabilityAttrKind(attr.getKind()),
attr.isContextSensitiveKeywordAttribute())
<< type
<< static_cast<unsigned>(pointerKind);

View File

@ -5405,7 +5405,7 @@ QualType TreeTransform<Derived>::TransformAttributedType(
if (auto nullability = oldType->getImmediateNullability()) {
if (!modifiedType->canHaveNullability()) {
SemaRef.Diag(TL.getAttrNameLoc(), diag::err_nullability_nonpointer)
<< static_cast<unsigned>(*nullability) << false << modifiedType;
<< DiagNullabilityKind(*nullability, false) << modifiedType;
return QualType();
}
}

View File

@ -2165,7 +2165,7 @@ void testCFReturnsNotRetained() {
}
void testCFReturnsNotRetainedAnnotated() {
extern void getViaParam2(CFTypeRef * __nonnull CF_RETURNS_NOT_RETAINED outObj);
extern void getViaParam2(CFTypeRef * _Nonnull CF_RETURNS_NOT_RETAINED outObj);
CFTypeRef obj;
getViaParam2(&obj);
CFRelease(obj); // // expected-warning {{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}}

View File

@ -4,6 +4,6 @@
// RUN: not %clang_cc1 -fixit -fblocks -Werror=nullability-declspec -x c++ %t
// RUN: %clang_cc1 -fblocks -Werror=nullability-declspec -x c++ %t
__nullable int *ip1; // expected-error{{nullability specifier '__nullable' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the pointer?}}
__nullable int (*fp1)(int); // expected-error{{nullability specifier '__nullable' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the function pointer?}}
__nonnull int (^bp1)(int); // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the block pointer?}}
_Nullable int *ip1; // expected-error{{nullability specifier '_Nullable' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the pointer?}}
_Nullable int (*fp1)(int); // expected-error{{nullability specifier '_Nullable' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the function pointer?}}
_Nonnull int (^bp1)(int); // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the block pointer?}}

View File

@ -345,4 +345,4 @@ void test_Nullability(Nullability *n, A* a) {
// CHECK-DISTRIB-OBJECTS: ObjCInstanceMethodDecl:{ResultType void}{TypedText method:}{Placeholder (in bycopy A *)}{HorizontalSpace }{TypedText result:}{Placeholder (out byref A **)} (35)
// RUN: c-index-test -code-completion-at=%s:197:6 %s | FileCheck -check-prefix=CHECK-NULLABLE %s
// CHECK-NULLABLE: ObjCInstanceMethodDecl:{ResultType A * __nonnull}{TypedText method:}{Placeholder (nullable A *)}
// CHECK-NULLABLE: ObjCInstanceMethodDecl:{ResultType A * _Nonnull}{TypedText method:}{Placeholder (nullable A *)}

View File

@ -16,8 +16,8 @@ void f(int x) {
// CHECK-IF-ELSE-SIMPLE: NotImplemented:{TypedText else}{HorizontalSpace }{Text if}{HorizontalSpace }{LeftParen (}{Placeholder expression}{RightParen )} (40)
// RUN: c-index-test -code-completion-at=%s:6:1 %s | FileCheck -check-prefix=CHECK-STMT %s
// CHECK-STMT: NotImplemented:{TypedText __nonnull} (50)
// CHECK-STMT: NotImplemented:{TypedText __nullable} (50)
// CHECK-STMT: NotImplemented:{TypedText _Nonnull} (50)
// CHECK-STMT: NotImplemented:{TypedText _Nullable} (50)
// CHECK-STMT: NotImplemented:{TypedText char} (50)
// CHECK-STMT: NotImplemented:{TypedText const} (50)
// CHECK-STMT: NotImplemented:{TypedText double} (50)

View File

@ -1,10 +1,10 @@
// RUN: %clang_cc1 -fsyntax-only -std=c99 -Wno-nullability-declspec -pedantic %s -verify
__nonnull int *ptr; // expected-warning{{type nullability specifier '__nonnull' is a Clang extension}}
_Nonnull int *ptr; // expected-warning{{type nullability specifier '_Nonnull' is a Clang extension}}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnullability-extension"
__nonnull int *ptr2; // no-warning
_Nonnull int *ptr2; // no-warning
#pragma clang diagnostic pop
#if __has_feature(nullability)

View File

@ -7,29 +7,29 @@
#endif
int * __nullable foo(int * __nonnull x);
int * _Nullable foo(int * _Nonnull x);
int *__nonnull ret_nonnull();
int *_Nonnull ret_nonnull();
int *foo(int *x) {
return 0;
}
int * __nullable foo1(int * __nonnull x); // expected-note {{previous declaration is here}}
int * _Nullable foo1(int * _Nonnull x); // expected-note {{previous declaration is here}}
int *foo1(int * __nullable x) { // expected-warning {{nullability specifier '__nullable' conflicts with existing specifier '__nonnull'}}
int *foo1(int * _Nullable x) { // expected-warning {{nullability specifier '_Nullable' conflicts with existing specifier '_Nonnull'}}
return 0;
}
int * __nullable foo2(int * __nonnull x);
int * _Nullable foo2(int * _Nonnull x);
int *foo2(int * __nonnull x) {
int *foo2(int * _Nonnull x) {
return 0;
}
int * __nullable foo3(int * __nullable x); // expected-note {{previous declaration is here}}
int * _Nullable foo3(int * _Nullable x); // expected-note {{previous declaration is here}}
int *foo3(int * __nonnull x) { // expected-warning {{nullability specifier '__nonnull' conflicts with existing specifier '__nullable'}}
int *foo3(int * _Nonnull x) { // expected-warning {{nullability specifier '_Nonnull' conflicts with existing specifier '_Nullable'}}
return 0;
}

View File

@ -8,88 +8,88 @@
typedef int * int_ptr;
// Parse nullability type specifiers.
typedef int * __nonnull nonnull_int_ptr; // expected-note{{'__nonnull' specified here}}
typedef int * __nullable nullable_int_ptr;
typedef int * __null_unspecified null_unspecified_int_ptr;
typedef int * _Nonnull nonnull_int_ptr; // expected-note{{'_Nonnull' specified here}}
typedef int * _Nullable nullable_int_ptr;
typedef int * _Null_unspecified null_unspecified_int_ptr;
// Redundant nullability type specifiers.
typedef int * __nonnull __nonnull redundant_1; // expected-warning{{duplicate nullability specifier '__nonnull'}}
typedef int * _Nonnull _Nonnull redundant_1; // expected-warning{{duplicate nullability specifier '_Nonnull'}}
// Conflicting nullability type specifiers.
typedef int * __nonnull __nullable conflicting_1; // expected-error{{nullability specifier '__nonnull' conflicts with existing specifier '__nullable'}}
typedef int * __null_unspecified __nonnull conflicting_2; // expected-error{{nullability specifier '__null_unspecified' conflicts with existing specifier '__nonnull'}}
typedef int * _Nonnull _Nullable conflicting_1; // expected-error{{nullability specifier '_Nonnull' conflicts with existing specifier '_Nullable'}}
typedef int * _Null_unspecified _Nonnull conflicting_2; // expected-error{{nullability specifier '_Null_unspecified' conflicts with existing specifier '_Nonnull'}}
// Redundant nullability specifiers via a typedef are okay.
typedef nonnull_int_ptr __nonnull redundant_okay_1;
typedef nonnull_int_ptr _Nonnull redundant_okay_1;
// Conflicting nullability specifiers via a typedef are not.
typedef nonnull_int_ptr __nullable conflicting_2; // expected-error{{nullability specifier '__nullable' conflicts with existing specifier '__nonnull'}}
typedef nonnull_int_ptr _Nullable conflicting_2; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Nonnull'}}
typedef nonnull_int_ptr nonnull_int_ptr_typedef;
typedef nonnull_int_ptr_typedef __nullable conflicting_2; // expected-error{{nullability specifier '__nullable' conflicts with existing specifier '__nonnull'}}
typedef nonnull_int_ptr_typedef _Nullable conflicting_2; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Nonnull'}}
typedef nonnull_int_ptr_typedef nonnull_int_ptr_typedef_typedef;
typedef nonnull_int_ptr_typedef_typedef __null_unspecified conflicting_3; // expected-error{{nullability specifier '__null_unspecified' conflicts with existing specifier '__nonnull'}}
typedef nonnull_int_ptr_typedef_typedef _Null_unspecified conflicting_3; // expected-error{{nullability specifier '_Null_unspecified' conflicts with existing specifier '_Nonnull'}}
// Nullability applies to all pointer types.
typedef int (* __nonnull function_pointer_type_1)(int, int);
typedef int (^ __nonnull block_type_1)(int, int);
typedef int (* _Nonnull function_pointer_type_1)(int, int);
typedef int (^ _Nonnull block_type_1)(int, int);
// Nullability must be on a pointer type.
typedef int __nonnull int_type_1; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'int'}}
typedef int _Nonnull int_type_1; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int'}}
// Nullability can move out to a pointer/block pointer declarator
// (with a suppressed warning).
typedef __nonnull int * nonnull_int_ptr_2;
typedef int __nullable * nullable_int_ptr_2;
typedef __nonnull int (* function_pointer_type_2)(int, int);
typedef __nonnull int (^ block_type_2)(int, int);
typedef __nonnull int * * __nullable nonnull_int_ptr_ptr_1;
typedef __nonnull int *(^ block_type_3)(int, int);
typedef __nonnull int *(* function_pointer_type_3)(int, int);
typedef __nonnull int_ptr (^ block_type_4)(int, int);
typedef __nonnull int_ptr (* function_pointer_type_4)(int, int);
typedef _Nonnull int * nonnull_int_ptr_2;
typedef int _Nullable * nullable_int_ptr_2;
typedef _Nonnull int (* function_pointer_type_2)(int, int);
typedef _Nonnull int (^ block_type_2)(int, int);
typedef _Nonnull int * * _Nullable nonnull_int_ptr_ptr_1;
typedef _Nonnull int *(^ block_type_3)(int, int);
typedef _Nonnull int *(* function_pointer_type_3)(int, int);
typedef _Nonnull int_ptr (^ block_type_4)(int, int);
typedef _Nonnull int_ptr (* function_pointer_type_4)(int, int);
void acceptFunctionPtr(__nonnull int *(*)(void));
void acceptBlockPtr(__nonnull int *(^)(void));
void acceptFunctionPtr(_Nonnull int *(*)(void));
void acceptBlockPtr(_Nonnull int *(^)(void));
void testBlockFunctionPtrNullability() {
float *fp;
fp = (function_pointer_type_3)0; // expected-warning{{from 'function_pointer_type_3' (aka 'int * __nonnull (*)(int, int)')}}
fp = (block_type_3)0; // expected-error{{from incompatible type 'block_type_3' (aka 'int * __nonnull (^)(int, int)')}}
fp = (function_pointer_type_4)0; // expected-warning{{from 'function_pointer_type_4' (aka 'int_ptr __nonnull (*)(int, int)')}}
fp = (block_type_4)0; // expected-error{{from incompatible type 'block_type_4' (aka 'int_ptr __nonnull (^)(int, int)')}}
fp = (function_pointer_type_3)0; // expected-warning{{from 'function_pointer_type_3' (aka 'int * _Nonnull (*)(int, int)')}}
fp = (block_type_3)0; // expected-error{{from incompatible type 'block_type_3' (aka 'int * _Nonnull (^)(int, int)')}}
fp = (function_pointer_type_4)0; // expected-warning{{from 'function_pointer_type_4' (aka 'int_ptr _Nonnull (*)(int, int)')}}
fp = (block_type_4)0; // expected-error{{from incompatible type 'block_type_4' (aka 'int_ptr _Nonnull (^)(int, int)')}}
acceptFunctionPtr(0); // no-warning
acceptBlockPtr(0); // no-warning
}
// Moving nullability where it creates a conflict.
typedef __nonnull int * __nullable * conflict_int_ptr_ptr_2; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'int'}}
typedef _Nonnull int * _Nullable * conflict_int_ptr_ptr_2; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int'}}
// Nullability is not part of the canonical type.
typedef int * __nonnull ambiguous_int_ptr;
typedef int * _Nonnull ambiguous_int_ptr;
typedef int * ambiguous_int_ptr;
typedef int * __nullable ambiguous_int_ptr;
typedef int * _Nullable ambiguous_int_ptr;
// Printing of nullability.
float f;
int * __nonnull ip_1 = &f; // expected-warning{{incompatible pointer types initializing 'int * __nonnull' with an expression of type 'float *'}}
int * _Nonnull ip_1 = &f; // expected-warning{{incompatible pointer types initializing 'int * _Nonnull' with an expression of type 'float *'}}
// Check printing of nullability specifiers.
void printing_nullability(void) {
int * __nonnull iptr;
float *fptr = iptr; // expected-warning{{incompatible pointer types initializing 'float *' with an expression of type 'int * __nonnull'}}
int * _Nonnull iptr;
float *fptr = iptr; // expected-warning{{incompatible pointer types initializing 'float *' with an expression of type 'int * _Nonnull'}}
int * * __nonnull iptrptr;
float **fptrptr = iptrptr; // expected-warning{{incompatible pointer types initializing 'float **' with an expression of type 'int ** __nonnull'}}
int * * _Nonnull iptrptr;
float **fptrptr = iptrptr; // expected-warning{{incompatible pointer types initializing 'float **' with an expression of type 'int ** _Nonnull'}}
int * __nullable * __nonnull iptrptr2;
float * *fptrptr2 = iptrptr2; // expected-warning{{incompatible pointer types initializing 'float **' with an expression of type 'int * __nullable * __nonnull'}}
int * _Nullable * _Nonnull iptrptr2;
float * *fptrptr2 = iptrptr2; // expected-warning{{incompatible pointer types initializing 'float **' with an expression of type 'int * _Nullable * _Nonnull'}}
}
// Check passing null to a __nonnull argument.
void accepts_nonnull_1(__nonnull int *ptr);
void (*accepts_nonnull_2)(__nonnull int *ptr);
void (^accepts_nonnull_3)(__nonnull int *ptr);
// Check passing null to a _Nonnull argument.
void accepts_nonnull_1(_Nonnull int *ptr);
void (*accepts_nonnull_2)(_Nonnull int *ptr);
void (^accepts_nonnull_3)(_Nonnull int *ptr);
void test_accepts_nonnull_null_pointer_literal() {
accepts_nonnull_1(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
@ -97,17 +97,17 @@ void test_accepts_nonnull_null_pointer_literal() {
accepts_nonnull_3(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
}
// Check returning nil from a __nonnull-returning function.
__nonnull int *returns_int_ptr(int x) {
// Check returning nil from a _Nonnull-returning function.
_Nonnull int *returns_int_ptr(int x) {
if (x) {
return 0; // expected-warning{{null returned from function that requires a non-null return value}}
}
return (__nonnull int *)0;
return (_Nonnull int *)0;
}
// Check nullable-to-nonnull conversions.
void nullable_to_nonnull(__nullable int *ptr) {
void nullable_to_nonnull(_Nullable int *ptr) {
int *a = ptr; // okay
__nonnull int *b = ptr; // expected-warning{{implicit conversion from nullable pointer 'int * __nullable' to non-nullable pointer type 'int * __nonnull'}}
_Nonnull int *b = ptr; // expected-warning{{implicit conversion from nullable pointer 'int * _Nullable' to non-nullable pointer type 'int * _Nonnull'}}
}

View File

@ -2,8 +2,8 @@
struct X { };
__nullable int *ip1; // expected-error{{nullability specifier '__nullable' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the pointer?}}
__nullable int (*fp1)(int); // expected-error{{nullability specifier '__nullable' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the function pointer?}}
__nonnull int (^bp1)(int); // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the block pointer?}}
__nonnull int X::*pmd1; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the member pointer?}}
__nonnull int (X::*pmf1)(int); // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the member function pointer?}}
_Nullable int *ip1; // expected-error{{nullability specifier '_Nullable' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the pointer?}}
_Nullable int (*fp1)(int); // expected-error{{nullability specifier '_Nullable' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the function pointer?}}
_Nonnull int (^bp1)(int); // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the block pointer?}}
_Nonnull int X::*pmd1; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the member pointer?}}
_Nonnull int (X::*pmf1)(int); // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int'; did you mean to apply the specifier to the member function pointer?}}

View File

@ -6,24 +6,24 @@ class X {
};
// Nullability applies to all pointer types.
typedef int (X::* __nonnull member_function_type_1)(int);
typedef int X::* __nonnull member_data_type_1;
typedef nullptr_t __nonnull nonnull_nullptr_t; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'nullptr_t'}}
typedef int (X::* _Nonnull member_function_type_1)(int);
typedef int X::* _Nonnull member_data_type_1;
typedef nullptr_t _Nonnull nonnull_nullptr_t; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'nullptr_t'}}
// Nullability can move into member pointers (this is suppressing a warning).
typedef __nonnull int (X::* member_function_type_2)(int);
typedef int (X::* __nonnull member_function_type_3)(int);
typedef __nonnull int X::* member_data_type_2;
typedef _Nonnull int (X::* member_function_type_2)(int);
typedef int (X::* _Nonnull member_function_type_3)(int);
typedef _Nonnull int X::* member_data_type_2;
// Adding non-null via a template.
template<typename T>
struct AddNonNull {
typedef __nonnull T type; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'int'}}
// expected-error@-1{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'nullptr_t'}}
typedef _Nonnull T type; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'int'}}
// expected-error@-1{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'nullptr_t'}}
};
typedef AddNonNull<int *>::type nonnull_int_ptr_1;
typedef AddNonNull<int * __nullable>::type nonnull_int_ptr_2; // FIXME: check that it was overridden
typedef AddNonNull<int * _Nullable>::type nonnull_int_ptr_2; // FIXME: check that it was overridden
typedef AddNonNull<nullptr_t>::type nonnull_int_ptr_3; // expected-note{{in instantiation of template class}}
typedef AddNonNull<int>::type nonnull_non_pointer_1; // expected-note{{in instantiation of template class 'AddNonNull<int>' requested here}}
@ -31,22 +31,22 @@ typedef AddNonNull<int>::type nonnull_non_pointer_1; // expected-note{{in instan
// Non-null checking within a template.
template<typename T>
struct AddNonNull2 {
typedef __nonnull AddNonNull<T> invalid1; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}}
typedef __nonnull AddNonNull2 invalid2; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'AddNonNull2<T>'}}
typedef __nonnull AddNonNull2<T> invalid3; // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'AddNonNull2<T>'}}
typedef __nonnull typename AddNonNull<T>::type okay1;
typedef _Nonnull AddNonNull<T> invalid1; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}}
typedef _Nonnull AddNonNull2 invalid2; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull2<T>'}}
typedef _Nonnull AddNonNull2<T> invalid3; // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull2<T>'}}
typedef _Nonnull typename AddNonNull<T>::type okay1;
// Don't move past a dependent type even if we know that nullability
// cannot apply to that specific dependent type.
typedef __nonnull AddNonNull<T> (*invalid4); // expected-error{{nullability specifier '__nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}}
typedef _Nonnull AddNonNull<T> (*invalid4); // expected-error{{nullability specifier '_Nonnull' cannot be applied to non-pointer type 'AddNonNull<T>'}}
};
// Check passing null to a __nonnull argument.
void (*accepts_nonnull_1)(__nonnull int *ptr);
void (*& accepts_nonnull_2)(__nonnull int *ptr) = accepts_nonnull_1;
void (X::* accepts_nonnull_3)(__nonnull int *ptr);
void accepts_nonnull_4(__nonnull int *ptr);
void (&accepts_nonnull_5)(__nonnull int *ptr) = accepts_nonnull_4;
// Check passing null to a _Nonnull argument.
void (*accepts_nonnull_1)(_Nonnull int *ptr);
void (*& accepts_nonnull_2)(_Nonnull int *ptr) = accepts_nonnull_1;
void (X::* accepts_nonnull_3)(_Nonnull int *ptr);
void accepts_nonnull_4(_Nonnull int *ptr);
void (&accepts_nonnull_5)(_Nonnull int *ptr) = accepts_nonnull_4;
void test_accepts_nonnull_null_pointer_literal(X *x) {
accepts_nonnull_1(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
@ -56,7 +56,7 @@ void test_accepts_nonnull_null_pointer_literal(X *x) {
accepts_nonnull_5(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
}
template<void FP(__nonnull int*)>
template<void FP(_Nonnull int*)>
void test_accepts_nonnull_null_pointer_literal_template() {
FP(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
}

View File

@ -56,7 +56,7 @@ __attribute__((objc_arc_weak_reference_unavailable))
@interface I
{
}
@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont * __nullable', which does not support weak references}}
@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont * _Nullable', which does not support weak references}}
@end
@implementation I // expected-note {{when implemented by class I}}
@ -65,7 +65,7 @@ __attribute__((objc_arc_weak_reference_unavailable))
// rdar://13676793
@protocol MyProtocol
@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont * __nullable', which does not support weak references}}
@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont * _Nullable', which does not support weak references}}
@end
@interface I1 <MyProtocol>
@ -76,7 +76,7 @@ __attribute__((objc_arc_weak_reference_unavailable))
@end
@interface Super
@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont * __nullable', which does not support weak references}}
@property (weak) NSFont *font; // expected-error {{synthesizing __weak instance variable of type 'NSFont * _Nullable', which does not support weak references}}
@end

View File

@ -5,6 +5,6 @@ __attribute__((objc_root_class))
@end
// ARC qualifiers stacked with nullability.
void accepts_arc_qualified(NSFoo * __unsafe_unretained __nonnull obj) {
void accepts_arc_qualified(NSFoo * __unsafe_unretained _Nonnull obj) {
accepts_arc_qualified(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
}

View File

@ -2,29 +2,29 @@
__attribute__((objc_root_class))
@interface NSFoo
- (void)methodTakingIntPtr:(__nonnull int *)ptr;
- (__nonnull int *)methodReturningIntPtr;
- (void)methodTakingIntPtr:(_Nonnull int *)ptr;
- (_Nonnull int *)methodReturningIntPtr;
@end
// Nullability applies to all pointer types.
typedef NSFoo * __nonnull nonnull_NSFoo_ptr;
typedef id __nonnull nonnull_id;
typedef SEL __nonnull nonnull_SEL;
typedef NSFoo * _Nonnull nonnull_NSFoo_ptr;
typedef id _Nonnull nonnull_id;
typedef SEL _Nonnull nonnull_SEL;
// Nullability can move into Objective-C pointer types.
typedef __nonnull NSFoo * nonnull_NSFoo_ptr_2;
typedef _Nonnull NSFoo * nonnull_NSFoo_ptr_2;
// Conflicts from nullability moving into Objective-C pointer type.
typedef __nonnull NSFoo * __nullable conflict_NSFoo_ptr_2; // expected-error{{'__nonnull' cannot be applied to non-pointer type 'NSFoo'}}
typedef _Nonnull NSFoo * _Nullable conflict_NSFoo_ptr_2; // expected-error{{'_Nonnull' cannot be applied to non-pointer type 'NSFoo'}}
void testBlocksPrinting(NSFoo * __nullable (^bp)(int)) {
int *ip = bp; // expected-error{{'NSFoo * __nullable (^)(int)'}}
void testBlocksPrinting(NSFoo * _Nullable (^bp)(int)) {
int *ip = bp; // expected-error{{'NSFoo * _Nullable (^)(int)'}}
}
// Check returning nil from a __nonnull-returning method.
// Check returning nil from a _Nonnull-returning method.
@implementation NSFoo
- (void)methodTakingIntPtr:(__nonnull int *)ptr { }
- (__nonnull int *)methodReturningIntPtr {
- (void)methodTakingIntPtr:(_Nonnull int *)ptr { }
- (_Nonnull int *)methodReturningIntPtr {
return 0; // no warning
}
@end
@ -35,15 +35,15 @@ __attribute__((objc_root_class))
- (nonnull NSFoo *)methodWithFoo:(nonnull NSFoo *)foo;
- (nonnull NSFoo **)invalidMethod1; // expected-error{{nullability keyword 'nonnull' cannot be applied to multi-level pointer type 'NSFoo **'}}
// expected-note@-1{{use nullability type specifier '__nonnull' to affect the innermost pointer type of 'NSFoo **'}}
- (nonnull NSFoo * __nullable)conflictingMethod1; // expected-error{{nullability specifier '__nullable' conflicts with existing specifier '__nonnull'}}
- (nonnull NSFoo * __nonnull)redundantMethod1; // expected-warning{{duplicate nullability specifier '__nonnull'}}
// expected-note@-1{{use nullability type specifier '_Nonnull' to affect the innermost pointer type of 'NSFoo **'}}
- (nonnull NSFoo * _Nullable)conflictingMethod1; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Nonnull'}}
- (nonnull NSFoo * _Nonnull)redundantMethod1; // expected-warning{{duplicate nullability specifier '_Nonnull'}}
@property(nonnull,retain) NSFoo *property1;
@property(nullable,assign) NSFoo ** invalidProperty1; // expected-error{{nullability keyword 'nullable' cannot be applied to multi-level pointer type 'NSFoo **'}}
// expected-note@-1{{use nullability type specifier '__nullable' to affect the innermost pointer type of 'NSFoo **'}}
@property(null_unspecified,retain) NSFoo * __nullable conflictingProperty1; // expected-error{{nullability specifier '__nullable' conflicts with existing specifier '__null_unspecified'}}
@property(retain,nonnull) NSFoo * __nonnull redundantProperty1; // expected-warning{{duplicate nullability specifier '__nonnull'}}
// expected-note@-1{{use nullability type specifier '_Nullable' to affect the innermost pointer type of 'NSFoo **'}}
@property(null_unspecified,retain) NSFoo * _Nullable conflictingProperty1; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Null_unspecified'}}
@property(retain,nonnull) NSFoo * _Nonnull redundantProperty1; // expected-warning{{duplicate nullability specifier '_Nonnull'}}
@property(null_unspecified,retain,nullable) NSFoo *conflictingProperty3; // expected-error{{nullability specifier 'nullable' conflicts with existing specifier 'null_unspecified'}}
@property(nullable,retain,nullable) NSFoo *redundantProperty3; // expected-warning{{duplicate nullability specifier 'nullable'}}
@ -52,19 +52,19 @@ __attribute__((objc_root_class))
@interface NSBar ()
@property(nonnull,retain) NSFoo *property2;
@property(nullable,assign) NSFoo ** invalidProperty2; // expected-error{{nullability keyword 'nullable' cannot be applied to multi-level pointer type 'NSFoo **'}}
// expected-note@-1{{use nullability type specifier '__nullable' to affect the innermost pointer type of 'NSFoo **'}}
@property(null_unspecified,retain) NSFoo * __nullable conflictingProperty2; // expected-error{{nullability specifier '__nullable' conflicts with existing specifier '__null_unspecified'}}
@property(retain,nonnull) NSFoo * __nonnull redundantProperty2; // expected-warning{{duplicate nullability specifier '__nonnull'}}
// expected-note@-1{{use nullability type specifier '_Nullable' to affect the innermost pointer type of 'NSFoo **'}}
@property(null_unspecified,retain) NSFoo * _Nullable conflictingProperty2; // expected-error{{nullability specifier '_Nullable' conflicts with existing specifier '_Null_unspecified'}}
@property(retain,nonnull) NSFoo * _Nonnull redundantProperty2; // expected-warning{{duplicate nullability specifier '_Nonnull'}}
@end
void test_accepts_nonnull_null_pointer_literal(NSFoo *foo, __nonnull NSBar *bar) {
void test_accepts_nonnull_null_pointer_literal(NSFoo *foo, _Nonnull NSBar *bar) {
[foo methodTakingIntPtr: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}}
[bar methodWithFoo: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}}
bar.property1 = 0; // expected-warning{{null passed to a callee that requires a non-null argument}}
bar.property2 = 0; // expected-warning{{null passed to a callee that requires a non-null argument}}
[bar setProperty1: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}}
[bar setProperty2: 0]; // expected-warning{{null passed to a callee that requires a non-null argument}}
int *ptr = bar.property1; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'NSFoo * __nonnull'}}
int *ptr = bar.property1; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'NSFoo * _Nonnull'}}
}
// Check returning nil from a nonnull-returning method.
@ -82,7 +82,7 @@ void test_accepts_nonnull_null_pointer_literal(NSFoo *foo, __nonnull NSBar *bar)
}
- (NSFoo *)redundantMethod1 {
int *ip = 0;
return ip; // expected-warning{{result type 'NSFoo * __nonnull'}}
return ip; // expected-warning{{result type 'NSFoo * _Nonnull'}}
}
@end
@ -95,8 +95,8 @@ __attribute__((objc_root_class))
@implementation NSMerge
- (NSFoo *)methodA:(NSFoo*)foo {
int *ptr = foo; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'NSFoo * __nonnull'}}
return ptr; // expected-warning{{result type 'NSFoo * __nonnull'}}
int *ptr = foo; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'NSFoo * _Nonnull'}}
return ptr; // expected-warning{{result type 'NSFoo * _Nonnull'}}
}
- (nullable NSFoo *)methodB:(null_unspecified NSFoo*)foo { // expected-error{{nullability specifier 'nullable' conflicts with existing specifier 'nonnull'}} \
@ -106,7 +106,7 @@ __attribute__((objc_root_class))
- (nonnull NSFoo *)methodC:(nullable NSFoo*)foo {
int *ip = 0;
return ip; // expected-warning{{result type 'NSFoo * __nonnull'}}
return ip; // expected-warning{{result type 'NSFoo * _Nonnull'}}
}
@end
@ -119,27 +119,27 @@ __attribute__((objc_root_class))
@end
void test_receiver_merge(NSMergeReceiver *none,
__nonnull NSMergeReceiver *nonnull,
__nullable NSMergeReceiver *nullable,
__null_unspecified NSMergeReceiver *null_unspecified) {
_Nonnull NSMergeReceiver *nonnull,
_Nullable NSMergeReceiver *nullable,
_Null_unspecified NSMergeReceiver *null_unspecified) {
int *ptr;
ptr = [nullable returnsNullable]; // expected-warning{{'id __nullable'}}
ptr = [nullable returnsNullUnspecified]; // expected-warning{{'id __nullable'}}
ptr = [nullable returnsNonNull]; // expected-warning{{'id __nullable'}}
ptr = [nullable returnsNone]; // expected-warning{{'id __nullable'}}
ptr = [nullable returnsNullable]; // expected-warning{{'id _Nullable'}}
ptr = [nullable returnsNullUnspecified]; // expected-warning{{'id _Nullable'}}
ptr = [nullable returnsNonNull]; // expected-warning{{'id _Nullable'}}
ptr = [nullable returnsNone]; // expected-warning{{'id _Nullable'}}
ptr = [null_unspecified returnsNullable]; // expected-warning{{'id __nullable'}}
ptr = [null_unspecified returnsNullUnspecified]; // expected-warning{{'id __null_unspecified'}}
ptr = [null_unspecified returnsNonNull]; // expected-warning{{'id __null_unspecified'}}
ptr = [null_unspecified returnsNullable]; // expected-warning{{'id _Nullable'}}
ptr = [null_unspecified returnsNullUnspecified]; // expected-warning{{'id _Null_unspecified'}}
ptr = [null_unspecified returnsNonNull]; // expected-warning{{'id _Null_unspecified'}}
ptr = [null_unspecified returnsNone]; // expected-warning{{'id'}}
ptr = [nonnull returnsNullable]; // expected-warning{{'id __nullable'}}
ptr = [nonnull returnsNullUnspecified]; // expected-warning{{'id __null_unspecified'}}
ptr = [nonnull returnsNonNull]; // expected-warning{{'id __nonnull'}}
ptr = [nonnull returnsNullable]; // expected-warning{{'id _Nullable'}}
ptr = [nonnull returnsNullUnspecified]; // expected-warning{{'id _Null_unspecified'}}
ptr = [nonnull returnsNonNull]; // expected-warning{{'id _Nonnull'}}
ptr = [nonnull returnsNone]; // expected-warning{{'id'}}
ptr = [none returnsNullable]; // expected-warning{{'id __nullable'}}
ptr = [none returnsNullable]; // expected-warning{{'id _Nullable'}}
ptr = [none returnsNullUnspecified]; // expected-warning{{'id'}}
ptr = [none returnsNonNull]; // expected-warning{{'id'}}
ptr = [none returnsNone]; // expected-warning{{'id'}}
@ -157,19 +157,19 @@ __attribute__((objc_root_class))
- (nullable instancetype)returnMe;
+ (nullable instancetype)returnInstanceOfMe;
- (nonnull instancetype __nullable)initWithBlah2:(nonnull id)blah; // expected-error {{nullability specifier '__nullable' conflicts with existing specifier '__nonnull'}}
- (instancetype __nullable)returnMe2;
+ (__nonnull instancetype)returnInstanceOfMe2;
- (nonnull instancetype _Nullable)initWithBlah2:(nonnull id)blah; // expected-error {{nullability specifier '_Nullable' conflicts with existing specifier '_Nonnull'}}
- (instancetype _Nullable)returnMe2;
+ (_Nonnull instancetype)returnInstanceOfMe2;
@end
void test_instancetype(InitializableClass * __nonnull ic, id __nonnull object) {
int *ip = [ic returnMe]; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'InitializableClass * __nullable'}}
ip = [InitializableClass returnMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'id __nullable'}}
ip = [InitializableClass returnInstanceOfMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * __nullable'}}
ip = [object returnMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'id __nullable'}}
void test_instancetype(InitializableClass * _Nonnull ic, id _Nonnull object) {
int *ip = [ic returnMe]; // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'InitializableClass * _Nullable'}}
ip = [InitializableClass returnMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'id _Nullable'}}
ip = [InitializableClass returnInstanceOfMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * _Nullable'}}
ip = [object returnMe]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'id _Nullable'}}
ip = [ic returnMe2]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * __nullable'}}
ip = [InitializableClass returnInstanceOfMe2]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * __nonnull'}}
ip = [ic returnMe2]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * _Nullable'}}
ip = [InitializableClass returnInstanceOfMe2]; // expected-warning{{incompatible pointer types assigning to 'int *' from 'InitializableClass * _Nonnull'}}
}
// Check null_resettable getters/setters.
@ -184,14 +184,14 @@ __attribute__((objc_root_class))
@end
void test_null_resettable(NSResettable *r, int *ip) {
[r setResettable1:ip]; // expected-warning{{incompatible pointer types sending 'int *' to parameter of type 'NSResettable * __nullable'}}
r.resettable1 = ip; // expected-warning{{incompatible pointer types assigning to 'NSResettable * __nullable' from 'int *'}}
[r setResettable1:ip]; // expected-warning{{incompatible pointer types sending 'int *' to parameter of type 'NSResettable * _Nullable'}}
r.resettable1 = ip; // expected-warning{{incompatible pointer types assigning to 'NSResettable * _Nullable' from 'int *'}}
}
@implementation NSResettable // expected-warning{{synthesized setter 'setResettable4:' for null_resettable property 'resettable4' does not handle nil}}
- (NSResettable *)resettable1 {
int *ip = 0;
return ip; // expected-warning{{result type 'NSResettable * __nonnull'}}
return ip; // expected-warning{{result type 'NSResettable * _Nonnull'}}
}
- (void)setResettable1:(NSResettable *)param {
@ -218,15 +218,15 @@ void test_null_resettable(NSResettable *r, int *ip) {
void testMultiProp(MultiProp *foo) {
int *ip;
ip = foo.a; // expected-warning{{from 'id __nullable'}}
ip = foo.d; // expected-warning{{from 'MultiProp * __nullable'}}
ip = foo.e; // expected-error{{incompatible type 'MultiProp *(^ __nullable)(int)'}}
ip = foo.a; // expected-warning{{from 'id _Nullable'}}
ip = foo.d; // expected-warning{{from 'MultiProp * _Nullable'}}
ip = foo.e; // expected-error{{incompatible type 'MultiProp *(^ _Nullable)(int)'}}
}
void testBlockLiterals() {
(void)(^id(void) { return 0; });
(void)(^id __nullable (void) { return 0; });
(void)(^ __nullable id(void) { return 0; });
(void)(^id _Nullable (void) { return 0; });
(void)(^ _Nullable id(void) { return 0; });
int *x = (^ __nullable id(void) { return 0; })(); // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'id __nullable'}}
int *x = (^ _Nullable id(void) { return 0; })(); // expected-warning{{incompatible pointer types initializing 'int *' with an expression of type 'id _Nullable'}}
}

View File

@ -5,7 +5,7 @@
@interface NSObject @end
@class NSFoo;
void foo (NSFoo * __nonnull);
void foo (NSFoo * _Nonnull);
@interface NSBar : NSObject
@property(weak) NSFoo *property1;
@ -13,6 +13,6 @@ void foo (NSFoo * __nonnull);
@implementation NSBar
- (void) Meth {
foo (self.property1); // expected-warning {{implicit conversion from nullable pointer 'NSFoo * __nullable' to non-nullable pointer type 'NSFoo * __nonnull'}}
foo (self.property1); // expected-warning {{implicit conversion from nullable pointer 'NSFoo * _Nullable' to non-nullable pointer type 'NSFoo * _Nonnull'}}
}
@end

View File

@ -1,6 +1,6 @@
void f1(int *ptr); // expected-warning{{pointer is missing a nullability type specifier}}
void f2(int * __nonnull);
void f2(int * _Nonnull);
#include "nullability-consistency-2.h"

View File

@ -1,4 +1,4 @@
void g1(int * __nonnull);
void g1(int * _Nonnull);
void g2(int (^block)(int, int)); // expected-warning{{block pointer is missing a nullability type specifier}}

View File

@ -1 +1 @@
void double_declarator1(int *__nonnull *); // expected-warning{{pointer is missing a nullability type specifier (__nonnull, __nullable, or __null_unspecified)}}
void double_declarator1(int *_Nonnull *); // expected-warning{{pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}}

View File

@ -1 +1 @@
void double_declarator1(int * * __nonnull); // expected-warning{{pointer is missing a nullability type specifier (__nonnull, __nullable, or __null_unspecified)}}
void double_declarator1(int * * _Nonnull); // expected-warning{{pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)}}

View File

@ -8,7 +8,7 @@ void suppress1(SUPPRESS_NULLABILITY_WARNING(int *) ptr); // no warning
void shouldwarn5(int *ptr); //expected-warning{{missing a nullability type specifier}}
void trigger5(int * __nonnull);
void trigger5(int * _Nonnull);
void suppress2(SUPPRESS_NULLABILITY_WARNING(int *) ptr); // no warning

View File

@ -1,4 +1,4 @@
typedef int* __nonnull mynonnull;
typedef int* _Nonnull mynonnull;
__attribute__((objc_root_class))
@interface typedefClass
@ -13,15 +13,15 @@ void func3(int *); // expected-warning{{pointer is missing a nullability type sp
typedef void *CFTypeRef;
void cf1(CFTypeRef * p CF_RETURNS_NOT_RETAINED); // expected-warning {{pointer is missing a nullability type specifier}}
void cf2(CFTypeRef * __nullable p CF_RETURNS_NOT_RETAINED);
void cf3(CFTypeRef * __nonnull p CF_RETURNS_NOT_RETAINED);
void cf2(CFTypeRef * _Nullable p CF_RETURNS_NOT_RETAINED);
void cf3(CFTypeRef * _Nonnull p CF_RETURNS_NOT_RETAINED);
void cf4(CFTypeRef __nullable * __nullable p CF_RETURNS_NOT_RETAINED);
void cf5(CFTypeRef __nonnull * __nullable p CF_RETURNS_NOT_RETAINED);
void cf4(CFTypeRef _Nullable * _Nullable p CF_RETURNS_NOT_RETAINED);
void cf5(CFTypeRef _Nonnull * _Nullable p CF_RETURNS_NOT_RETAINED);
void cf6(CFTypeRef * __nullable CF_RETURNS_NOT_RETAINED p);
void cf7(CF_RETURNS_NOT_RETAINED CFTypeRef * __nonnull p);
void cf6(CFTypeRef * _Nullable CF_RETURNS_NOT_RETAINED p);
void cf7(CF_RETURNS_NOT_RETAINED CFTypeRef * _Nonnull p);
typedef CFTypeRef __nullable *CFTypeRefPtr;
typedef CFTypeRef _Nullable *CFTypeRefPtr;
void cfp1(CFTypeRefPtr p CF_RETURNS_NOT_RETAINED); // expected-warning {{pointer is missing a nullability type specifier}}
void cfp2(CFTypeRefPtr __nonnull p CF_RETURNS_NOT_RETAINED);
void cfp2(CFTypeRefPtr _Nonnull p CF_RETURNS_NOT_RETAINED);

View File

@ -5,4 +5,4 @@ void system1(int *ptr);
// expected-warning@-2{{pointer is missing a nullability type specifier}}
#endif
void system2(int * __nonnull);
void system2(int * _Nonnull);

View File

@ -25,19 +25,19 @@ void f3(A* obj);
void f4(int (^block)(int, int));
void f5(int_ptr x);
void f6(A_ptr obj);
void f7(int * __nullable x);
void f8(A * __nullable obj);
void f7(int * _Nullable x);
void f8(A * _Nullable obj);
void f9(int X::* mem_ptr);
void f10(int (X::*mem_func)(int, int));
void f11(int X::* __nullable mem_ptr);
void f12(int (X::* __nullable mem_func)(int, int));
void f11(int X::* _Nullable mem_ptr);
void f12(int (X::* _Nullable mem_func)(int, int));
int_ptr f13(void);
A *f14(void);
int * __null_unspecified f15(void);
A * __null_unspecified f16(void);
void f17(CFErrorRef *error); // expected-note{{no known conversion from 'A * __nonnull' to 'CFErrorRef __nullable * __nullable' (aka '__CFError **') for 1st argument}}
int * _Null_unspecified f15(void);
A * _Null_unspecified f16(void);
void f17(CFErrorRef *error); // expected-note{{no known conversion from 'A * _Nonnull' to 'CFErrorRef _Nullable * _Nullable' (aka '__CFError **') for 1st argument}}
void f18(A **); // expected-warning 2{{pointer is missing a nullability type specifier}}
void f19(CFErrorRefPtr error); // expected-warning{{pointer is missing a nullability type specifier}}
@ -64,14 +64,14 @@ void g5(int (**fp)(int, int)); // expected-warning 2{{pointer is missing a nulla
int *global_int_ptr;
// typedefs not inferred __nonnull
// typedefs not inferred _Nonnull
typedef int *int_ptr_2;
typedef int * // expected-warning{{pointer is missing a nullability type specifier}}
*int_ptr_ptr;
static inline void f30(void) {
float *fp = global_int_ptr; // expected-error{{cannot initialize a variable of type 'float *' with an lvalue of type 'int * __nonnull'}}
float *fp = global_int_ptr; // expected-error{{cannot initialize a variable of type 'float *' with an lvalue of type 'int * _Nonnull'}}
int_ptr_2 ip2;
float *fp2 = ip2; // expected-error{{cannot initialize a variable of type 'float *' with an lvalue of type 'int_ptr_2' (aka 'int *')}}
@ -83,7 +83,7 @@ static inline void f30(void) {
@interface AA : A {
@public
id ivar1;
__nonnull id ivar2;
_Nonnull id ivar2;
}
@end
@ -92,8 +92,8 @@ static inline void f30(void) {
void f20(A *a); // expected-warning{{pointer is missing a nullability type specifier}}
void f21(int_ptr x); // expected-warning{{pointer is missing a nullability type specifier}}
void f22(A_ptr y); // expected-warning{{pointer is missing a nullability type specifier}}
void f23(int_ptr __nullable x);
void f24(A_ptr __nullable y);
void f23(int_ptr _Nullable x);
void f24(A_ptr _Nullable y);
void f25(int_ptr_2 x); // expected-warning{{pointer is missing a nullability type specifier}}
@interface A(OutsidePragmas1)

View File

@ -13,4 +13,4 @@
void h1(int *ptr) { } // don't warn
void h2(int * __nonnull) { }
void h2(int * _Nonnull) { }

View File

@ -7,7 +7,7 @@
# error assume_nonnull feature is not set
#endif
void test_pragmas_1(A * __nonnull a, AA * __nonnull aa) {
void test_pragmas_1(A * _Nonnull a, AA * _Nonnull aa) {
f1(0); // okay: no nullability annotations
f2(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
f3(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
@ -23,19 +23,19 @@ void test_pragmas_1(A * __nonnull a, AA * __nonnull aa) {
[a method1:0]; // expected-warning{{null passed to a callee that requires a non-null argument}}
f17(a); // expected-error{{no matching function for call to 'f17'}}
[a method3: a]; // expected-error{{cannot initialize a parameter of type 'NSError * __nullable * __nullable' with an lvalue of type 'A * __nonnull'}}
[a method4: a]; // expected-error{{cannot initialize a parameter of type 'NSErrorPtr __nullable * __nullable' (aka 'NSError **') with an lvalue of type 'A * __nonnull'}}
[a method3: a]; // expected-error{{cannot initialize a parameter of type 'NSError * _Nullable * _Nullable' with an lvalue of type 'A * _Nonnull'}}
[a method4: a]; // expected-error{{cannot initialize a parameter of type 'NSErrorPtr _Nullable * _Nullable' (aka 'NSError **') with an lvalue of type 'A * _Nonnull'}}
float *ptr;
ptr = f13(); // expected-error{{assigning to 'float *' from incompatible type 'int_ptr __nonnull' (aka 'int *')}}
ptr = f14(); // expected-error{{assigning to 'float *' from incompatible type 'A * __nonnull'}}
ptr = [a method1:a]; // expected-error{{assigning to 'float *' from incompatible type 'A * __nonnull'}}
ptr = a.aProp; // expected-error{{assigning to 'float *' from incompatible type 'A * __nonnull'}}
ptr = global_int_ptr; // expected-error{{assigning to 'float *' from incompatible type 'int * __nonnull'}}
ptr = f15(); // expected-error{{assigning to 'float *' from incompatible type 'int * __null_unspecified'}}
ptr = f16(); // expected-error{{assigning to 'float *' from incompatible type 'A * __null_unspecified'}}
ptr = [a method2]; // expected-error{{assigning to 'float *' from incompatible type 'A * __null_unspecified'}}
ptr = f13(); // expected-error{{assigning to 'float *' from incompatible type 'int_ptr _Nonnull' (aka 'int *')}}
ptr = f14(); // expected-error{{assigning to 'float *' from incompatible type 'A * _Nonnull'}}
ptr = [a method1:a]; // expected-error{{assigning to 'float *' from incompatible type 'A * _Nonnull'}}
ptr = a.aProp; // expected-error{{assigning to 'float *' from incompatible type 'A * _Nonnull'}}
ptr = global_int_ptr; // expected-error{{assigning to 'float *' from incompatible type 'int * _Nonnull'}}
ptr = f15(); // expected-error{{assigning to 'float *' from incompatible type 'int * _Null_unspecified'}}
ptr = f16(); // expected-error{{assigning to 'float *' from incompatible type 'A * _Null_unspecified'}}
ptr = [a method2]; // expected-error{{assigning to 'float *' from incompatible type 'A * _Null_unspecified'}}
ptr = aa->ivar1; // expected-error{{from incompatible type 'id'}}
ptr = aa->ivar2; // expected-error{{from incompatible type 'id __nonnull'}}
ptr = aa->ivar2; // expected-error{{from incompatible type 'id _Nonnull'}}
}