commit af53694fceb2db04ac9ba6b61a74fbb7af6a7d9b
Author: Timo Sirainen <timo.sirainen@dovecot.fi>
Date:   Fri Oct 28 19:16:19 2016 +0300

    Added -Wdefault-nonnull and null/returns_null attributes.

diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 709af0a..c221da6 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -1108,6 +1108,11 @@ def NonNull : InheritableAttr {
   let Documentation = [NonNullDocs];
 }
 
+def Null : InheritableAttr {
+  let Spellings = [GCC<"null">];
+  let Documentation = [NonNullDocs];
+}
+
 def ReturnsNonNull : InheritableAttr {
   let Spellings = [GCC<"returns_nonnull">];
   let Subjects = SubjectList<[ObjCMethod, Function], WarnDiag,
@@ -1115,6 +1120,13 @@ def ReturnsNonNull : InheritableAttr {
   let Documentation = [ReturnsNonNullDocs];
 }
 
+def ReturnsNull : InheritableAttr {
+  let Spellings = [GCC<"returns_null">];
+  let Subjects = SubjectList<[ObjCMethod, Function], WarnDiag,
+                             "ExpectedFunctionOrMethod">;
+  let Documentation = [ReturnsNonNullDocs];
+}
+
 // pass_object_size(N) indicates that the parameter should have
 // __builtin_object_size with Type=N evaluated on the parameter at the callsite.
 def PassObjectSize : InheritableParamAttr {
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 900bb04..10fea19 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -284,6 +284,7 @@ def NullCharacter : DiagGroup<"null-character">;
 def NullDereference : DiagGroup<"null-dereference">;
 def InitializerOverrides : DiagGroup<"initializer-overrides">;
 def NonNull : DiagGroup<"nonnull">;
+def DefaultNonNull : DiagGroup<"default-nonnull">;
 def NonPODVarargs : DiagGroup<"non-pod-varargs">;
 def ClassVarargs : DiagGroup<"class-varargs", [NonPODVarargs]>;
 def : DiagGroup<"nonportable-cfstrings">;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 80f481b..cb5993e 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7487,6 +7487,10 @@ def warn_null_ret : Warning<
   "null returned from %select{function|method}0 that requires a non-null return value">,
   InGroup<NonNull>;
 
+def warn_default_nonnull_arg : Warning<
+  "">,
+  InGroup<DefaultNonNull>, DefaultIgnore;
+
 // CHECK: returning address/reference of stack memory
 def warn_ret_stack_addr_ref : Warning<
   "%select{address of|reference to}0 stack memory associated with local "
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index a94ed53..d699d30 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -7730,6 +7730,8 @@ static void checkIsValidOpenCLKernelParameter(
   } while (!VisitStack.empty());
 }
 
+void AddDefaultNonNullAttributes(Sema &S, Decl *D);
+
 NamedDecl*
 Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
                               TypeSourceInfo *TInfo, LookupResult &Previous,
@@ -8558,6 +8560,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
   checkAttributesAfterMerging(*this, *NewFD);
 
   AddKnownFunctionAttributes(NewFD);
+  AddDefaultNonNullAttributes(*this, NewFD);
 
   if (NewFD->hasAttr<OverloadableAttr>() &&
       !NewFD->getType()->getAs<FunctionProtoType>()) {
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 936c297..af134b1 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1294,6 +1294,17 @@ static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D,
                          Attr.getAttributeSpellingListIndex()));
 }
 
+static void handleNullAttr(Sema &S, ParmVarDecl *D, const AttributeList &Attr) {
+  // Is the argument a pointer type?
+  if (!attrNonNullArgCheck(S, D->getType(), Attr, SourceRange(),
+                           D->getSourceRange()))
+    return;
+
+  D->addAttr(::new (S.Context)
+             NullAttr(Attr.getRange(), S.Context,
+                      Attr.getAttributeSpellingListIndex()));
+}
+
 static void handleReturnsNonNullAttr(Sema &S, Decl *D,
                                      const AttributeList &Attr) {
   QualType ResultType = getFunctionOrMethodResultType(D);
@@ -1307,6 +1318,80 @@ static void handleReturnsNonNullAttr(Sema &S, Decl *D,
                                Attr.getAttributeSpellingListIndex()));
 }
 
+static void handleReturnsNullAttr(Sema &S, Decl *D,
+                                  const AttributeList &Attr) {
+  QualType ResultType = getFunctionOrMethodResultType(D);
+  SourceRange SR = getFunctionOrMethodResultSourceRange(D);
+  if (!attrNonNullArgCheck(S, ResultType, Attr, SourceRange(), SR,
+                           /* isReturnValue */ true))
+    return;
+
+  D->addAttr(::new (S.Context)
+            ReturnsNullAttr(Attr.getRange(), S.Context,
+                            Attr.getAttributeSpellingListIndex()));
+}
+
+static void addDefaultReturnsNonNullAttributes(Sema &S, Decl *D) {
+  if (!cast<NamedDecl>(D)->isExternallyVisible())
+    return; /* too much trouble to require the attribute for static functions */
+  if (D->hasAttr<ReturnsNonNullAttr>() || D->hasAttr<ReturnsNullAttr>())
+    return;
+  if (!S.isValidPointerAttrType(getFunctionOrMethodResultType(D)))
+    return;
+
+  D->addAttr(::new (S.Context)
+            ReturnsNonNullAttr(D->getLocation(), S.Context, 0));
+}
+
+static void addDefaultNonNullParameterAttributes(Sema &S, Decl *D) {
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    // if there are any nonnull attributes, skip adding them
+    if (D->hasAttr<NonNullAttr>() || D->hasAttr<NullAttr>())
+      return;
+    for (unsigned i = 0; i < FD->getNumParams(); i++) {
+      ParmVarDecl *PD = FD->getParamDecl(i);
+      if (PD->hasAttr<NonNullAttr>())
+        return;
+    }
+    // add nonnull attribute to all parameters that don't have null attribute
+    SmallVector<unsigned, 8> NonNullArgs;
+    for (unsigned i = 0; i < FD->getNumParams(); i++) {
+      ParmVarDecl *PD = FD->getParamDecl(i);
+      if (!PD->hasAttr<NullAttr>()) {
+        if (S.isValidPointerAttrType(PD->getType())) {
+          /*PD->addAttr(::new (S.Context)
+            NonNullAttr(PD->getLocation(), S.Context, nullptr, 0, 0));*/
+          NonNullArgs.push_back(i);
+        }
+      }
+    }
+
+    if (!NonNullArgs.empty()) {
+      unsigned *Start = NonNullArgs.data();
+      unsigned Size = NonNullArgs.size();
+      llvm::array_pod_sort(Start, Start + Size);
+      D->addAttr(::new (S.Context)
+        NonNullAttr(D->getLocation(), S.Context, Start, Size, 0));
+    } else {
+      // if this was a prototype, ignore null/nonnull attributes in function definition
+      D->addAttr(::new (S.Context)
+        NullAttr(D->getLocation(), S.Context, 0));
+    }
+  }
+}
+
+void AddDefaultNonNullAttributes(Sema &S, Decl *D) {
+  if (!isFunctionOrMethod(D))
+    return;
+  DiagnosticsEngine &Diags = S.Context.getDiagnostics();
+  if (Diags.getDiagnosticLevel(diag::warn_default_nonnull_arg, D->getLocStart())
+      == DiagnosticsEngine::Ignored)
+    return;
+
+  addDefaultReturnsNonNullAttributes(S, D);
+  addDefaultNonNullParameterAttributes(S, D);
+}
+
 static void handleAssumeAlignedAttr(Sema &S, Decl *D,
                                     const AttributeList &Attr) {
   Expr *E = Attr.getArgAsExpr(0),
@@ -5657,9 +5742,16 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
     else
       handleNonNullAttr(S, D, Attr);
     break;
+  case AttributeList::AT_Null:
+    if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D))
+      handleNullAttr(S, PVD, Attr);
+    break;
   case AttributeList::AT_ReturnsNonNull:
     handleReturnsNonNullAttr(S, D, Attr);
     break;
+  case AttributeList::AT_ReturnsNull:
+    handleReturnsNullAttr(S, D, Attr);
+    break;
   case AttributeList::AT_AssumeAligned:
     handleAssumeAlignedAttr(S, D, Attr);
     break;
