r240158 - Check for consistent use of nullability type specifiers in a header.

Aaron Ballman aaron at aaronballman.com
Sat Jun 20 12:48:42 PDT 2015


On Fri, Jun 19, 2015 at 2:27 PM, Douglas Gregor <dgregor at apple.com> wrote:
> Author: dgregor
> Date: Fri Jun 19 13:27:45 2015
> New Revision: 240158
>
> URL: http://llvm.org/viewvc/llvm-project?rev=240158&view=rev
> Log:
> Check for consistent use of nullability type specifiers in a header.
>
> Adds a new warning (under -Wnullability-completeness) that complains
> about pointer, block pointer, or member pointer declarations that have
> not been annotated with nullability information (directly or inferred)
> within a header that contains some nullability annotations. This is
> intended to be used to help maintain the completeness of nullability
> information within a header that has already been audited.
>
> Note that, for performance reasons, this warning will underrepresent
> the number of non-annotated pointers in the case where more than one
> pointer is seen before the first nullability type specifier, because
> we're only tracking one piece of information per header. Part of
> rdar://problem/18868820.
>
> Added:
>     cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-1.h   (with props)
>     cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-2.h   (with props)
>     cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-3.h   (with props)
>     cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-4.h   (with props)
>     cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-5.h   (with props)
>     cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-6.h   (with props)
>     cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-7.h   (with props)
>     cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-8.h   (with props)
>     cfe/trunk/test/SemaObjCXX/nullability-consistency.mm
> Modified:
>     cfe/trunk/include/clang/Basic/DiagnosticGroups.td
>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>     cfe/trunk/include/clang/Sema/AttributeList.h
>     cfe/trunk/include/clang/Sema/Sema.h
>     cfe/trunk/lib/Parse/ParseObjc.cpp
>     cfe/trunk/lib/Sema/SemaType.cpp
>     cfe/trunk/test/SemaObjCXX/Inputs/nullability-pragmas-1.h
>     cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=240158&r1=240157&r2=240158&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Fri Jun 19 13:27:45 2015
> @@ -251,6 +251,7 @@ def NewlineEOF : DiagGroup<"newline-eof"
>  def Nullability : DiagGroup<"nullability">;
>  def NullabilityDeclSpec : DiagGroup<"nullability-declspec">;
>  def NullableToNonNullConversion : DiagGroup<"nullable-to-nonnull-conversion">;
> +def NullabilityCompleteness : DiagGroup<"nullability-completeness">;
>  def NullArithmetic : DiagGroup<"null-arithmetic">;
>  def NullCharacter : DiagGroup<"null-character">;
>  def NullDereference : DiagGroup<"null-dereference">;
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=240158&r1=240157&r2=240158&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jun 19 13:27:45 2015
> @@ -7718,6 +7718,11 @@ def warn_null_resettable_setter : Warnin
>    "synthesized setter %0 for null_resettable property %1 does not handle nil">,
>    InGroup<Nullability>;
>
> +def warn_nullability_missing : Warning<
> +  "%select{pointer|block pointer|member pointer}0 is missing a nullability "
> +  "type specifier (__nonnull, __nullable, or __null_unspecified)">,
> +  InGroup<NullabilityCompleteness>;
> +
>  }
>
>  } // end of sema component.
>
> Modified: cfe/trunk/include/clang/Sema/AttributeList.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=240158&r1=240157&r2=240158&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/AttributeList.h (original)
> +++ cfe/trunk/include/clang/Sema/AttributeList.h Fri Jun 19 13:27:45 2015
> @@ -81,6 +81,8 @@ public:
>      AS_Declspec,
>      /// __ptr16, alignas(...), etc.
>      AS_Keyword,
> +    /// Context-sensitive version of a keyword attribute.
> +    AS_ContextSensitiveKeyword,

I don't like this approach. These are meant to mirror spellings
generated by tablegen that the user can write, so this breaks the
attribute syntax model. Put slightly differently, as far as the table
definition for an attribute is concerned, *all* keywords are currently
context sensitive in that we don't (and likely will never) table
generate parsing for attribute keywords. So this provides no useful
distinction for the table definition of keyword attributes.

>From what I can tell, context sensitivity is only used for error
reporting purposes (whether we want to print __nonnull or nonnull in a
diagnostic). That's part of the spelling of the attribute itself,
which AttributeList already tracks. Can that be used instead? If not,
the previous approach was marginally less heinous (though still
problematic).

>      /// #pragma ...
>      AS_Pragma
>    };
> @@ -120,9 +122,6 @@ private:
>    /// True if this has a ParsedType
>    unsigned HasParsedType : 1;
>
> -  /// True when this keyword attribute is a context-sensitive keyword.
> -  unsigned IsContextSensitiveKeyword : 1;

I do like that this bit field is now back to 32 bits. ;-)

> -
>    unsigned AttrKind : 8;
>
>    /// \brief The location of the 'unavailable' keyword in an
> @@ -223,8 +222,7 @@ private:
>        ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs),
>        SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false),
>        IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false),
> -      HasParsedType(false), IsContextSensitiveKeyword(false),
> -      NextInPosition(nullptr), NextInPool(nullptr) {
> +      HasParsedType(false), NextInPosition(nullptr), NextInPool(nullptr) {
>      if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion));
>      AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
>    }
> @@ -242,8 +240,8 @@ private:
>        ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed),
>        Invalid(false), UsedAsTypeAttr(false), IsAvailability(true),
>        IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
> -      IsContextSensitiveKeyword(false), UnavailableLoc(unavailable),
> -      MessageExpr(messageExpr), NextInPosition(nullptr), NextInPool(nullptr) {
> +      UnavailableLoc(unavailable), MessageExpr(messageExpr),
> +      NextInPosition(nullptr), NextInPool(nullptr) {
>      ArgsUnion PVal(Parm);
>      memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
>      new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced);
> @@ -263,8 +261,7 @@ private:
>      ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(3), SyntaxUsed(syntaxUsed),
>      Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
>      IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
> -    IsContextSensitiveKeyword(false), NextInPosition(nullptr),
> -    NextInPool(nullptr) {
> +    NextInPosition(nullptr), NextInPool(nullptr) {
>      ArgsVector Args;
>      Args.push_back(Parm1);
>      Args.push_back(Parm2);
> @@ -282,8 +279,7 @@ private:
>        ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed),
>        Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
>        IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false),
> -      IsContextSensitiveKeyword(false), NextInPosition(nullptr),
> -      NextInPool(nullptr) {
> +      NextInPosition(nullptr), NextInPool(nullptr) {
>      ArgsUnion PVal(ArgKind);
>      memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion));
>      TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot();
> @@ -301,8 +297,7 @@ private:
>          ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
>          Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
>          IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true),
> -        IsContextSensitiveKeyword(false), NextInPosition(nullptr),
> -        NextInPool(nullptr) {
> +        NextInPosition(nullptr), NextInPool(nullptr) {
>      new (&getTypeBuffer()) ParsedType(typeArg);
>      AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
>    }
> @@ -316,8 +311,7 @@ private:
>        ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed),
>        Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
>        IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false),
> -      IsContextSensitiveKeyword(false), NextInPosition(nullptr),
> -      NextInPool(nullptr) {
> +      NextInPosition(nullptr), NextInPool(nullptr) {
>      new (&getPropertyDataBuffer()) PropertyData(getterId, setterId);
>      AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
>    }
> @@ -351,22 +345,19 @@ public:
>
>    bool isAlignasAttribute() const {
>      // FIXME: Use a better mechanism to determine this.
> -    return getKind() == AT_Aligned && SyntaxUsed == AS_Keyword;
> +    return getKind() == AT_Aligned && isKeywordAttribute();
>    }
>
>    bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; }
>    bool isCXX11Attribute() const {
>      return SyntaxUsed == AS_CXX11 || isAlignasAttribute();
>    }
> -  bool isKeywordAttribute() const { return SyntaxUsed == AS_Keyword; }
> -
> -  bool isContextSensitiveKeywordAttribute() const {
> -    return IsContextSensitiveKeyword;
> +  bool isKeywordAttribute() const {
> +    return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword;
>    }
>
> -  void setContextSensitiveKeywordAttribute() {
> -    assert(SyntaxUsed == AS_Keyword);
> -    IsContextSensitiveKeyword = true;
> +  bool isContextSensitiveKeywordAttribute() const {
> +    return SyntaxUsed == AS_ContextSensitiveKeyword;
>    }
>
>    bool isInvalid() const { return Invalid; }
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=240158&r1=240157&r2=240158&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Fri Jun 19 13:27:45 2015
> @@ -210,6 +210,50 @@ namespace threadSafety {
>  typedef std::pair<llvm::PointerUnion<const TemplateTypeParmType*, NamedDecl*>,
>                    SourceLocation> UnexpandedParameterPack;
>
> +/// Describes whether we've seen any nullability information for the given
> +/// file.
> +struct FileNullability {
> +  /// The first pointer declarator (of any pointer kind) in the file that does
> +  /// not have a corresponding nullability annotation.
> +  SourceLocation PointerLoc;
> +
> +  /// Which kind of pointer declarator we saw.
> +  uint8_t PointerKind;
> +
> +  /// Whether we saw any type nullability annotations in the given file.
> +  bool SawTypeNullability = false;
> +};
> +
> +/// A mapping from file IDs to a record of whether we've seen nullability
> +/// information in that file.
> +class FileNullabilityMap {
> +  /// A mapping from file IDs to the nullability information for each file ID.
> +  llvm::DenseMap<FileID, FileNullability> Map;
> +
> +  /// A single-element cache based on the file ID.
> +  struct {
> +    FileID File;
> +    FileNullability Nullability;
> +  } Cache;
> +
> +public:
> +  FileNullability &operator[](FileID file) {
> +    // Check the single-element cache.
> +    if (file == Cache.File)
> +      return Cache.Nullability;
> +
> +    // It's not in the single-element cache; flush the cache if we have one.
> +    if (!Cache.File.isInvalid()) {
> +      Map[Cache.File] = Cache.Nullability;
> +    }
> +
> +    // Pull this entry into the cache.
> +    Cache.File = file;
> +    Cache.Nullability = Map[file];
> +    return Cache.Nullability;
> +  }
> +};
> +
>  /// Sema - This implements semantic analysis and AST building for C.
>  class Sema {
>    Sema(const Sema &) = delete;
> @@ -341,6 +385,9 @@ public:
>    PragmaStack<StringLiteral *> ConstSegStack;
>    PragmaStack<StringLiteral *> CodeSegStack;
>
> +  /// A mapping that describes the nullability we've seen in each header file.
> +  FileNullabilityMap NullabilityMap;
> +
>    /// Last section used with #pragma init_seg.
>    StringLiteral *CurInitSeg;
>    SourceLocation CurInitSegLoc;
>
> Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=240158&r1=240157&r2=240158&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseObjc.cpp Fri Jun 19 13:27:45 2015
> @@ -317,14 +317,12 @@ static void addContextSensitiveTypeNulla
>                                                 bool &addedToDeclSpec) {
>    // Create the attribute.
>    auto getNullabilityAttr = [&]() -> AttributeList * {
> -    auto attr = D.getAttributePool().create(
> -                  P.getNullabilityKeyword(nullability),
> -                  SourceRange(nullabilityLoc),
> -                  nullptr, SourceLocation(),
> -                  nullptr, 0,
> -                  AttributeList::AS_Keyword);
> -    attr->setContextSensitiveKeywordAttribute();
> -    return attr;
> +    return D.getAttributePool().create(
> +             P.getNullabilityKeyword(nullability),
> +             SourceRange(nullabilityLoc),
> +             nullptr, SourceLocation(),
> +             nullptr, 0,
> +             AttributeList::AS_ContextSensitiveKeyword);
>    };
>
>    if (D.getNumTypeObjects() > 0) {
>
> Modified: cfe/trunk/lib/Sema/SemaType.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=240158&r1=240157&r2=240158&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaType.cpp Fri Jun 19 13:27:45 2015
> @@ -2759,6 +2759,71 @@ static PointerDeclaratorKind classifyPoi
>    }
>  }
>
> +static FileID getNullabilityCompletenessCheckFileID(Sema &S,
> +                                                    SourceLocation loc) {
> +  // If we're anywhere in a function, method, or closure context, don't perform
> +  // completeness checks.
> +  for (DeclContext *ctx = S.CurContext; ctx; ctx = ctx->getParent()) {
> +    if (ctx->isFunctionOrMethod())
> +      return FileID();
> +
> +    if (ctx->isFileContext())
> +      break;
> +  }
> +
> +  // We only care about the expansion location.
> +  loc = S.SourceMgr.getExpansionLoc(loc);
> +  FileID file = S.SourceMgr.getFileID(loc);
> +  if (file.isInvalid())
> +    return FileID();
> +
> +  // Retrieve file information.
> +  bool invalid = false;
> +  const SrcMgr::SLocEntry &sloc = S.SourceMgr.getSLocEntry(file, &invalid);
> +  if (invalid || !sloc.isFile())
> +    return FileID();
> +
> +  // We don't want to perform completeness checks on the main file or in
> +  // system headers.
> +  const SrcMgr::FileInfo &fileInfo = sloc.getFile();
> +  if (fileInfo.getIncludeLoc().isInvalid() ||
> +      fileInfo.getFileCharacteristic() != SrcMgr::C_User)
> +    return FileID();
> +
> +  return file;
> +}
> +
> +/// Check for consistent use of nullability.
> +static void checkNullabilityConsistency(TypeProcessingState &state,
> +                                        SimplePointerKind pointerKind,
> +                                        SourceLocation pointerLoc) {
> +  Sema &S = state.getSema();
> +
> +  // Determine which file we're performing consistency checking for.
> +  FileID file = getNullabilityCompletenessCheckFileID(S, pointerLoc);
> +  if (file.isInvalid())
> +    return;
> +
> +  // If we haven't seen any type nullability in this file, we won't warn now
> +  // about anything.
> +  FileNullability &fileNullability = S.NullabilityMap[file];
> +  if (!fileNullability.SawTypeNullability) {
> +    // If this is the first pointer declarator in the file, record it.
> +    if (fileNullability.PointerLoc.isInvalid() &&
> +        !S.Context.getDiagnostics().isIgnored(diag::warn_nullability_missing,
> +                                              pointerLoc)) {
> +      fileNullability.PointerLoc = pointerLoc;
> +      fileNullability.PointerKind = static_cast<unsigned>(pointerKind);
> +    }
> +
> +    return;
> +  }
> +
> +  // Complain about missing nullability.
> +  S.Diag(pointerLoc, diag::warn_nullability_missing)
> +    << static_cast<unsigned>(pointerKind);
> +}
> +
>  static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
>                                                  QualType declSpecType,
>                                                  TypeSourceInfo *TInfo) {
> @@ -2836,6 +2901,22 @@ static TypeSourceInfo *GetFullTypeForDec
>        !state.getDeclarator().isObjCWeakProperty() &&
>        !S.deduceWeakPropertyFromType(T)) {
>      inAssumeNonNullRegion = true;
> +    // Determine which file we saw the assume-nonnull region in.
> +    FileID file = getNullabilityCompletenessCheckFileID(
> +                    S, S.PP.getPragmaAssumeNonNullLoc());
> +    if (!file.isInvalid()) {
> +      FileNullability &fileNullability = S.NullabilityMap[file];
> +
> +      // If we haven't seen any type nullability before, now we have.
> +      if (!fileNullability.SawTypeNullability) {
> +        if (fileNullability.PointerLoc.isValid()) {
> +          S.Diag(fileNullability.PointerLoc, diag::warn_nullability_missing)
> +              << fileNullability.PointerKind;
> +        }
> +
> +        fileNullability.SawTypeNullability = true;
> +      }
> +    }
>    }
>
>    // Whether to complain about missing nullability specifiers or not.
> @@ -2857,7 +2938,7 @@ static TypeSourceInfo *GetFullTypeForDec
>      // inner pointers.
>      complainAboutMissingNullability = CAMN_InnerPointers;
>
> -    if (T->canHaveNullability()) {
> +    if (T->canHaveNullability() && !T->getNullability(S.Context)) {
>        ++NumPointersRemaining;
>      }
>
> @@ -2967,27 +3048,42 @@ static TypeSourceInfo *GetFullTypeForDec
>
>      // If we're supposed to infer nullability, do so now.
>      if (inferNullability) {
> +      auto syntax = inferNullabilityCS ? AttributeList::AS_ContextSensitiveKeyword
> +                                       : AttributeList::AS_Keyword;
>        AttributeList *nullabilityAttr = state.getDeclarator().getAttributePool()
>                                           .create(
>                                             S.getNullabilityKeyword(
>                                               *inferNullability),
>                                             SourceRange(pointerLoc),
>                                             nullptr, SourceLocation(),
> -                                           nullptr, 0,
> -                                           AttributeList::AS_Keyword);
> -      if (inferNullabilityCS)
> -        nullabilityAttr->setContextSensitiveKeywordAttribute();
> +                                           nullptr, 0, syntax);
>
>        spliceAttrIntoList(*nullabilityAttr, attrs);
>        return nullabilityAttr;
>      }
>
> +    // If we're supposed to complain about missing nullability, do so
> +    // now if it's truly missing.
> +    switch (complainAboutMissingNullability) {
> +    case CAMN_No:
> +      break;
> +
> +    case CAMN_InnerPointers:
> +      if (NumPointersRemaining == 0)
> +        break;
> +      // Fallthrough.
> +
> +    case CAMN_Yes:
> +      checkNullabilityConsistency(state, pointerKind, pointerLoc);
> +    }
> +
>      return nullptr;
>    };
>
>    // If the type itself could have nullability but does not, infer pointer
> -  // nullability.
> -  if (T->canHaveNullability() && S.ActiveTemplateInstantiations.empty()) {
> +  // nullability and perform consistency checking.
> +  if (T->canHaveNullability() && S.ActiveTemplateInstantiations.empty() &&
> +      !T->getNullability(S.Context)) {
>      SimplePointerKind pointerKind = SimplePointerKind::Pointer;
>      if (T->isBlockPointerType())
>        pointerKind = SimplePointerKind::BlockPointer;
> @@ -4919,10 +5015,27 @@ static bool handleMSPointerTypeQualifier
>    return false;
>  }
>
> -bool Sema::checkNullabilityTypeSpecifier(QualType &type,
> +bool Sema::checkNullabilityTypeSpecifier(QualType &type,
>                                           NullabilityKind nullability,
>                                           SourceLocation nullabilityLoc,
>                                           bool isContextSensitive) {
> +  // We saw a nullability type specifier. If this is the first one for
> +  // this file, note that.
> +  FileID file = getNullabilityCompletenessCheckFileID(*this, nullabilityLoc);
> +  if (!file.isInvalid()) {
> +    FileNullability &fileNullability = NullabilityMap[file];
> +    if (!fileNullability.SawTypeNullability) {
> +      // If we have already seen a pointer declarator without a nullability
> +      // annotation, complain about it.
> +      if (fileNullability.PointerLoc.isValid()) {
> +        Diag(fileNullability.PointerLoc, diag::warn_nullability_missing)
> +          << fileNullability.PointerKind;
> +      }
> +
> +      fileNullability.SawTypeNullability = true;
> +    }
> +  }
> +
>    // Check for existing nullability attributes on the type.
>    QualType desugared = type;
>    while (auto attributed = dyn_cast<AttributedType>(desugared.getTypePtr())) {
>
> Added: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-1.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-1.h?rev=240158&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-1.h (added)
> +++ cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-1.h Fri Jun 19 13:27:45 2015
> @@ -0,0 +1,17 @@
> +void f1(int *ptr); // expected-warning{{pointer is missing a nullability type specifier}}
> +
> +void f2(int * __nonnull);
> +
> +#include "nullability-consistency-2.h"
> +
> +void f3(int *ptr) { // expected-warning{{pointer is missing a nullability type specifier}}
> +  int *other = ptr; // shouldn't warn
> +}
> +
> +class X {
> +  void mf(int *ptr); // expected-warning{{pointer is missing a nullability type specifier}}
> +  int X:: *memptr; // expected-warning{{member pointer is missing a nullability type specifier}}
> +};
> +
> +
> +
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-1.h
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-1.h
> ------------------------------------------------------------------------------
>     svn:keywords = Id
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-1.h
> ------------------------------------------------------------------------------
>     svn:mime-type = text/plain

There are a lot of svn prop changes that I don't think were
intentional (here and below).

>
> Added: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-2.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-2.h?rev=240158&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-2.h (added)
> +++ cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-2.h Fri Jun 19 13:27:45 2015
> @@ -0,0 +1,16 @@
> +void g1(int * __nonnull);
> +
> +void g2(int (^block)(int, int)); // expected-warning{{block pointer is missing a nullability type specifier}}
> +
> +void g3(const
> +        id // expected-warning{{missing a nullability type specifier}}
> +        volatile
> +        * // expected-warning{{missing a nullability type specifier}}
> +        );
> +
> + at interface SomeClass
> + at property (retain,nonnull) id property1;
> + at property (retain,nullable) SomeClass *property2;
> +- (nullable SomeClass *)method1;
> +- (void)method2:(nonnull SomeClass *)param;
> + at end
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-2.h
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-2.h
> ------------------------------------------------------------------------------
>     svn:keywords = Id
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-2.h
> ------------------------------------------------------------------------------
>     svn:mime-type = text/plain
>
> Added: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-3.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-3.h?rev=240158&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-3.h (added)
> +++ cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-3.h Fri Jun 19 13:27:45 2015
> @@ -0,0 +1 @@
> +void double_declarator1(int *__nonnull *); // expected-warning{{pointer is missing a nullability type specifier (__nonnull, __nullable, or __null_unspecified)}}
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-3.h
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-3.h
> ------------------------------------------------------------------------------
>     svn:keywords = Id
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-3.h
> ------------------------------------------------------------------------------
>     svn:mime-type = text/plain
>
> Added: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-4.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-4.h?rev=240158&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-4.h (added)
> +++ cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-4.h Fri Jun 19 13:27:45 2015
> @@ -0,0 +1 @@
> +void double_declarator1(int * * __nonnull); // expected-warning{{pointer is missing a nullability type specifier (__nonnull, __nullable, or __null_unspecified)}}
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-4.h
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-4.h
> ------------------------------------------------------------------------------
>     svn:keywords = Id
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-4.h
> ------------------------------------------------------------------------------
>     svn:mime-type = text/plain
>
> Added: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-5.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-5.h?rev=240158&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-5.h (added)
> +++ cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-5.h Fri Jun 19 13:27:45 2015
> @@ -0,0 +1,14 @@
> +#define SUPPRESS_NULLABILITY_WARNING(Type)                              \
> +  _Pragma("clang diagnostic push")                                      \
> +  _Pragma("clang diagnostic ignored \"-Wnullability-completeness\"")    \
> +  Type                                                                  \
> +  _Pragma("clang diagnostic pop")
> +
> +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 suppress2(SUPPRESS_NULLABILITY_WARNING(int *) ptr); // no warning
> +
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-5.h
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-5.h
> ------------------------------------------------------------------------------
>     svn:keywords = Id
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-5.h
> ------------------------------------------------------------------------------
>     svn:mime-type = text/plain
>
> Added: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-6.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-6.h?rev=240158&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-6.h (added)
> +++ cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-6.h Fri Jun 19 13:27:45 2015
> @@ -0,0 +1,8 @@
> +int *ptr; // expected-warning {{missing a nullability type specifier}}
> +
> +#pragma clang assume_nonnull begin
> +
> +extern void **blah; // expected-warning 2{{missing a nullability type specifier}}
> +
> +#pragma clang assume_nonnull end
> +
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-6.h
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-6.h
> ------------------------------------------------------------------------------
>     svn:keywords = Id
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-6.h
> ------------------------------------------------------------------------------
>     svn:mime-type = text/plain
>
> Added: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-7.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-7.h?rev=240158&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-7.h (added)
> +++ cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-7.h Fri Jun 19 13:27:45 2015
> @@ -0,0 +1,40 @@
> +#ifndef SOMEKIT_H
> +#define SOMEKIT_H
> +
> +__attribute__((objc_root_class))
> +#ifndef NS_ASSUME_NONNULL_BEGIN
> +#if __has_feature(assume_nonnull)
> +#define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
> +#define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
> +#else
> +#define NS_ASSUME_NONNULL_BEGIN
> +#define NS_ASSUME_NONNULL_END
> +#endif
> +#endif
> +
> +NS_ASSUME_NONNULL_BEGIN
> +
> + at interface A
> +-(null_unspecified A*)transform:(null_unspecified A*)input __attribute__((unavailable("anything but this")));
> +-(A*)transform:(A*)input integer:(int)integer;
> +
> + at property (null_unspecified, nonatomic, readonly, retain) A* someA;
> + at property (null_unspecified, nonatomic, retain) A* someOtherA;
> +
> + at property (nonatomic) int intValue __attribute__((unavailable("wouldn't work anyway")));
> + at end
> +
> +NS_ASSUME_NONNULL_END
> +
> +
> +__attribute__((unavailable("just don't")))
> + at interface B : A
> + at end
> +
> + at interface C : A
> +- (instancetype)init; // expected-warning{{pointer is missing a nullability type specifier}}
> +- (instancetype)initWithA:( A*)a __attribute__((objc_designated_initializer)); // expected-warning 2{{pointer is missing a nullability type specifier}}
> + at end
> +
> +#endif
> +
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-7.h
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-7.h
> ------------------------------------------------------------------------------
>     svn:keywords = Id
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-7.h
> ------------------------------------------------------------------------------
>     svn:mime-type = text/plain
>
> Added: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-8.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-8.h?rev=240158&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-8.h (added)
> +++ cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-8.h Fri Jun 19 13:27:45 2015
> @@ -0,0 +1,11 @@
> +typedef int* __nonnull mynonnull;
> +
> +__attribute__((objc_root_class))
> + at interface typedefClass
> +- (void) func1:(mynonnull)i;
> + at end
> +
> +void func2(mynonnull i);
> +
> +void func3(int *); // expected-warning{{pointer is missing a nullability type specifier}}
> +
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-8.h
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-8.h
> ------------------------------------------------------------------------------
>     svn:keywords = Id
>
> Propchange: cfe/trunk/test/SemaObjCXX/Inputs/nullability-consistency-8.h
> ------------------------------------------------------------------------------
>     svn:mime-type = text/plain
>
> Modified: cfe/trunk/test/SemaObjCXX/Inputs/nullability-pragmas-1.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/Inputs/nullability-pragmas-1.h?rev=240158&r1=240157&r2=240158&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/Inputs/nullability-pragmas-1.h (original)
> +++ cfe/trunk/test/SemaObjCXX/Inputs/nullability-pragmas-1.h Fri Jun 19 13:27:45 2015
> @@ -8,7 +8,7 @@ __attribute__((objc_root_class))
>
>  struct X { };
>
> -void f1(int *x);
> +void f1(int *x); // expected-warning{{pointer is missing a nullability type specifier}}
>
>  typedef struct __attribute__((objc_bridge(NSError))) __CFError *CFErrorRef;
>  typedef NSError *NSErrorPtr;
> @@ -38,14 +38,16 @@ 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}}
> -void f18(A **);
> -void f19(CFErrorRefPtr error);
> +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}}
>
>  void g1(int (^)(int, int));
> -void g2(int (^ *bp)(int, int));
> -void g3(block_ptr *bp);
> +void g2(int (^ *bp)(int, int)); // expected-warning{{block pointer is missing a nullability type specifier}}
> +// expected-warning at -1{{pointer is missing a nullability type specifier}}
> +void g3(block_ptr *bp); // expected-warning{{block pointer is missing a nullability type specifier}}
> +// expected-warning at -1{{pointer is missing a nullability type specifier}}
>  void g4(int (*fp)(int, int));
> -void g5(int (**fp)(int, int));
> +void g5(int (**fp)(int, int)); // expected-warning 2{{pointer is missing a nullability type specifier}}
>
>  @interface A(Pragmas1)
>  + (instancetype)aWithA:(A *)a;
> @@ -54,9 +56,10 @@ void g5(int (**fp)(int, int));
>  - (void)method3:(NSError **)error; // expected-note{{passing argument to parameter 'error' here}}
>  - (void)method4:(NSErrorPtr *)error; // expected-note{{passing argument to parameter 'error' here}}
>  - (void)method5:(NSErrorPtrPtr)error;
> +// expected-warning at -1{{pointer is missing a nullability type specifier}}
>
>  @property A *aProp;
> - at property NSError **anError;
> + at property NSError **anError; // expected-warning 2{{pointer is missing a nullability type specifier}}
>  @end
>
>  int *global_int_ptr;
> @@ -64,7 +67,7 @@ int *global_int_ptr;
>  // typedefs not inferred __nonnull
>  typedef int *int_ptr_2;
>
> -typedef int *
> +typedef int * // expected-warning{{pointer is missing a nullability type specifier}}
>              *int_ptr_ptr;
>
>  static inline void f30(void) {
> @@ -86,13 +89,13 @@ static inline void f30(void) {
>
>  #pragma clang assume_nonnull end
>
> -void f20(A *a);
> -void f21(int_ptr x);
> -void f22(A_ptr y);
> +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 f25(int_ptr_2 x);
> +void f25(int_ptr_2 x); // expected-warning{{pointer is missing a nullability type specifier}}
>
>  @interface A(OutsidePragmas1)
> -+ (instancetype)aWithInt:(int)value;
> ++ (instancetype)aWithInt:(int)value; // expected-warning{{pointer is missing a nullability type specifier}}
>  @end
>
> Added: cfe/trunk/test/SemaObjCXX/nullability-consistency.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/nullability-consistency.mm?rev=240158&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/nullability-consistency.mm (added)
> +++ cfe/trunk/test/SemaObjCXX/nullability-consistency.mm Fri Jun 19 13:27:45 2015
> @@ -0,0 +1,14 @@
> +// RUN: %clang_cc1 -fsyntax-only -fblocks -I %S/Inputs %s -verify
> +
> +#include "nullability-consistency-1.h"
> +#include "nullability-consistency-3.h"
> +#include "nullability-consistency-4.h"
> +#include "nullability-consistency-5.h"
> +#include "nullability-consistency-5.h"
> +#include "nullability-consistency-6.h"
> +#include "nullability-consistency-7.h"
> +#include "nullability-consistency-8.h"
> +
> +void h1(int *ptr) { } // don't warn
> +
> +void h2(int * __nonnull) { }
>
> Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=240158&r1=240157&r2=240158&view=diff
> ==============================================================================
> --- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
> +++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Fri Jun 19 13:27:45 2015
> @@ -2721,7 +2721,8 @@ void EmitClangAttrParsedAttrKinds(Record
>    StringMatcher("Name", Declspec, OS).Emit();
>    OS << "  } else if (AttributeList::AS_CXX11 == Syntax) {\n";
>    StringMatcher("Name", CXX11, OS).Emit();
> -  OS << "  } else if (AttributeList::AS_Keyword == Syntax) {\n";
> +  OS << "  } else if (AttributeList::AS_Keyword == Syntax || ";
> +  OS << "AttributeList::AS_ContextSensitiveKeyword == Syntax) {\n";
>    StringMatcher("Name", Keywords, OS).Emit();
>    OS << "  } else if (AttributeList::AS_Pragma == Syntax) {\n";
>    StringMatcher("Name", Pragma, OS).Emit();
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

~Aaron



More information about the cfe-commits mailing list