<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Yeah, I’m pretty sure this was fixed on Friday with <a href="https://reviews.llvm.org/rC328406" class="">https://reviews.llvm.org/rC328406</a><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Mar 26, 2018, at 10:54 AM, Alexander Kornienko <<a href="mailto:alexfh@google.com" class="">alexfh@google.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">This checker crashes on almost each file in our codebase. No test case yet, but here's a stack trace:<div class=""><div class="">clang::Type::getTypeClass</div><div class="">clang::ReferenceType::classof</div><div class="">llvm::isa_impl::doit</div><div class="">llvm::isa_impl_cl::doit</div><div class="">llvm::isa_impl_wrap::doit</div><div class="">llvm::isa_impl_wrap::doit</div><div class="">llvm::isa</div><div class="">clang::Type::getAs</div><div class="">clang::ASTContext::getLValueReferenceType</div><div class="">::TrustNonnullChecker::checkPostCall</div><div class="">clang::ento::check::PostCall::_checkCall</div><div class="">clang::ento::CheckerFn::operator()</div><div class="">::CheckCallContext::runChecker</div><div class="">expandGraphWithCheckers</div><div class="">clang::ento::CheckerManager::runCheckersForCallEvent</div><div class="">clang::ento::CheckerManager::runCheckersForPostCall</div><div class="">clang::ento::ExprEngine::VisitCXXDestructor</div><div class="">clang::ento::ExprEngine::ProcessTemporaryDtor</div><div class="">clang::ento::ExprEngine::ProcessImplicitDtor</div><div class="">clang::ento::ExprEngine::processCFGElement</div><div class="">clang::ento::CoreEngine::dispatchWorkItem</div><div class="">clang::ento::CoreEngine::ExecuteWorkList</div><div class="">::AnalysisConsumer::ActionExprEngine</div><div class="">::AnalysisConsumer::HandleCode</div><div class="">::AnalysisConsumer::HandleTranslationUnit</div><div class="">clang::MultiplexConsumer::HandleTranslationUnit</div><div class="">clang::ParseAST</div><div class="">clang::FrontendAction::Execute</div><div class="">clang::CompilerInstance::ExecuteAction</div><div class="">clang::tooling::FrontendActionFactory::runInvocation</div><div class="">clang::tooling::ToolInvocation::runInvocation</div><div class="">clang::tooling::ToolInvocation::run</div></div><div class=""><br class=""></div><div class="">Could you fix or revert the patch?</div></div><br class=""><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Fri, Mar 23, 2018 at 1:18 AM George Karpenkov via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" class="">cfe-commits@lists.llvm.org</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: george.karpenkov<br class="">
Date: Thu Mar 22 17:16:03 2018<br class="">
New Revision: 328282<br class="">
<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=328282&view=rev" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project?rev=328282&view=rev</a><br class="">
Log:<br class="">
[analyzer] Trust _Nonnull annotations for system framework<br class="">
<br class="">
Changes the analyzer to believe that methods annotated with _Nonnull<br class="">
from system frameworks indeed return non null objects.<br class="">
Local methods with such annotation are still distrusted.<br class="">
<a href="rdar://24291919" class="">rdar://24291919</a><br class="">
<br class="">
Differential Revision: <a href="https://reviews.llvm.org/D44341" rel="noreferrer" target="_blank" class="">https://reviews.llvm.org/D44341</a><br class="">
<br class="">
Added:<br class="">
    cfe/trunk/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp<br class="">
    cfe/trunk/test/Analysis/trustnonnullchecker_test.m<br class="">
Modified:<br class="">
    cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td<br class="">
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h<br class="">
    cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt<br class="">
    cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp<br class="">
    cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp<br class="">
    cfe/trunk/test/Analysis/Inputs/system-header-simulator-for-nullability.h<br class="">
<br class="">
Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=328282&r1=328281&r2=328282&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=328282&r1=328281&r2=328282&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original)<br class="">
+++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Thu Mar 22 17:16:03 2018<br class="">
@@ -218,6 +218,14 @@ def NullableReturnedFromNonnullChecker :<br class="">
<br class="">
 } // end "nullability"<br class="">
<br class="">
+let ParentPackage = APIModeling in {<br class="">
+<br class="">
+def TrustNonnullChecker : Checker<"TrustNonnull">,<br class="">
+  HelpText<"Trust that returns from framework methods annotated with _Nonnull are not null">,<br class="">
+  DescFile<"TrustNonnullChecker.cpp">;<br class="">
+<br class="">
+}<br class="">
+<br class="">
 //===----------------------------------------------------------------------===//<br class="">
 // Evaluate "builtin" functions.<br class="">
 //===----------------------------------------------------------------------===//<br class="">
<br class="">
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h?rev=328282&r1=328281&r2=328282&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h?rev=328282&r1=328281&r2=328282&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h (original)<br class="">
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h Thu Mar 22 17:16:03 2018<br class="">
@@ -21,6 +21,8 @@ namespace clang {<br class="">
<br class="">
 class Expr;<br class="">
 class VarDecl;<br class="">
+class QualType;<br class="">
+class AttributedType;<br class="">
<br class="">
 namespace ento {<br class="">
<br class="">
@@ -42,6 +44,25 @@ template <class T> bool containsStmt(con<br class="">
 std::pair<const clang::VarDecl *, const clang::Expr *><br class="">
 parseAssignment(const Stmt *S);<br class="">
<br class="">
+// Do not reorder! The getMostNullable method relies on the order.<br class="">
+// Optimization: Most pointers expected to be unspecified. When a symbol has an<br class="">
+// unspecified or nonnull type non of the rules would indicate any problem for<br class="">
+// that symbol. For this reason only nullable and contradicted nullability are<br class="">
+// stored for a symbol. When a symbol is already contradicted, it can not be<br class="">
+// casted back to nullable.<br class="">
+enum class Nullability : char {<br class="">
+  Contradicted, // Tracked nullability is contradicted by an explicit cast. Do<br class="">
+                // not report any nullability related issue for this symbol.<br class="">
+                // This nullability is propagated aggressively to avoid false<br class="">
+                // positive results. See the comment on getMostNullable method.<br class="">
+  Nullable,<br class="">
+  Unspecified,<br class="">
+  Nonnull<br class="">
+};<br class="">
+<br class="">
+/// Get nullability annotation for a given type.<br class="">
+Nullability getNullabilityAnnotation(QualType Type);<br class="">
+<br class="">
 } // end GR namespace<br class="">
<br class="">
 } // end clang namespace<br class="">
<br class="">
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=328282&r1=328281&r2=328282&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=328282&r1=328281&r2=328282&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt (original)<br class="">
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Thu Mar 22 17:16:03 2018<br class="">
@@ -84,6 +84,7 @@ add_clang_library(clangStaticAnalyzerChe<br class="">
   TaintTesterChecker.cpp<br class="">
   TestAfterDivZeroChecker.cpp<br class="">
   TraversalChecker.cpp<br class="">
+  TrustNonnullChecker.cpp<br class="">
   UndefBranchChecker.cpp<br class="">
   UndefCapturedBlockVarChecker.cpp<br class="">
   UndefResultChecker.cpp<br class="">
<br class="">
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp?rev=328282&r1=328281&r2=328282&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp?rev=328282&r1=328281&r2=328282&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp (original)<br class="">
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp Thu Mar 22 17:16:03 2018<br class="">
@@ -30,6 +30,7 @@<br class="">
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"<br class="">
 #include "clang/StaticAnalyzer/Core/Checker.h"<br class="">
 #include "clang/StaticAnalyzer/Core/CheckerManager.h"<br class="">
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"<br class="">
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"<br class="">
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"<br class="">
<br class="">
@@ -40,21 +41,6 @@ using namespace clang;<br class="">
 using namespace ento;<br class="">
<br class="">
 namespace {<br class="">
-// Do not reorder! The getMostNullable method relies on the order.<br class="">
-// Optimization: Most pointers expected to be unspecified. When a symbol has an<br class="">
-// unspecified or nonnull type non of the rules would indicate any problem for<br class="">
-// that symbol. For this reason only nullable and contradicted nullability are<br class="">
-// stored for a symbol. When a symbol is already contradicted, it can not be<br class="">
-// casted back to nullable.<br class="">
-enum class Nullability : char {<br class="">
-  Contradicted, // Tracked nullability is contradicted by an explicit cast. Do<br class="">
-                // not report any nullability related issue for this symbol.<br class="">
-                // This nullability is propagated aggressively to avoid false<br class="">
-                // positive results. See the comment on getMostNullable method.<br class="">
-  Nullable,<br class="">
-  Unspecified,<br class="">
-  Nonnull<br class="">
-};<br class="">
<br class="">
 /// Returns the most nullable nullability. This is used for message expressions<br class="">
 /// like [receiver method], where the nullability of this expression is either<br class="">
@@ -345,17 +331,6 @@ NullabilityChecker::NullabilityBugVisito<br class="">
                                                     nullptr);<br class="">
 }<br class="">
<br class="">
-static Nullability getNullabilityAnnotation(QualType Type) {<br class="">
-  const auto *AttrType = Type->getAs<AttributedType>();<br class="">
-  if (!AttrType)<br class="">
-    return Nullability::Unspecified;<br class="">
-  if (AttrType->getAttrKind() == AttributedType::attr_nullable)<br class="">
-    return Nullability::Nullable;<br class="">
-  else if (AttrType->getAttrKind() == AttributedType::attr_nonnull)<br class="">
-    return Nullability::Nonnull;<br class="">
-  return Nullability::Unspecified;<br class="">
-}<br class="">
-<br class="">
 /// Returns true when the value stored at the given location is null<br class="">
 /// and the passed in type is nonnnull.<br class="">
 static bool checkValueAtLValForInvariantViolation(ProgramStateRef State,<br class="">
@@ -872,7 +847,7 @@ void NullabilityChecker::checkPostObjCMe<br class="">
     // are either item retrieval related or not interesting nullability wise.<br class="">
     // Using this fact, to keep the code easier to read just ignore the return<br class="">
     // value of every instance method of dictionaries.<br class="">
-    if (M.isInstanceMessage() && Name.find("Dictionary") != StringRef::npos) {<br class="">
+    if (M.isInstanceMessage() && Name.contains("Dictionary")) {<br class="">
       State =<br class="">
           State->set<NullabilityMap>(ReturnRegion, Nullability::Contradicted);<br class="">
       C.addTransition(State);<br class="">
@@ -880,7 +855,7 @@ void NullabilityChecker::checkPostObjCMe<br class="">
     }<br class="">
     // For similar reasons ignore some methods of Cocoa arrays.<br class="">
     StringRef FirstSelectorSlot = M.getSelector().getNameForSlot(0);<br class="">
-    if (Name.find("Array") != StringRef::npos &&<br class="">
+    if (Name.contains("Array") &&<br class="">
         (FirstSelectorSlot == "firstObject" ||<br class="">
          FirstSelectorSlot == "lastObject")) {<br class="">
       State =<br class="">
@@ -893,7 +868,7 @@ void NullabilityChecker::checkPostObjCMe<br class="">
     // encodings are used. Using lossless encodings is so frequent that ignoring<br class="">
     // this class of methods reduced the emitted diagnostics by about 30% on<br class="">
     // some projects (and all of that was false positives).<br class="">
-    if (Name.find("String") != StringRef::npos) {<br class="">
+    if (Name.contains("String")) {<br class="">
       for (auto Param : M.parameters()) {<br class="">
         if (Param->getName() == "encoding") {<br class="">
           State = State->set<NullabilityMap>(ReturnRegion,<br class="">
<br class="">
Added: cfe/trunk/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp?rev=328282&view=auto" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp?rev=328282&view=auto</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp (added)<br class="">
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp Thu Mar 22 17:16:03 2018<br class="">
@@ -0,0 +1,52 @@<br class="">
+//== TrustNonnullChecker.cpp - Checker for trusting annotations -*- C++ -*--==//<br class="">
+//<br class="">
+//                     The LLVM Compiler Infrastructure<br class="">
+//<br class="">
+// This file is distributed under the University of Illinois Open Source<br class="">
+// License. See LICENSE.TXT for details.<br class="">
+//<br class="">
+//===----------------------------------------------------------------------===//<br class="">
+//<br class="">
+// This checker adds an assumption that methods annotated with _Nonnull<br class="">
+// which come from system headers actually return a non-null pointer.<br class="">
+//<br class="">
+//===----------------------------------------------------------------------===//<br class="">
+<br class="">
+#include "ClangSACheckers.h"<br class="">
+#include "clang/StaticAnalyzer/Core/Checker.h"<br class="">
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"<br class="">
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"<br class="">
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"<br class="">
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"<br class="">
+<br class="">
+using namespace clang;<br class="">
+using namespace ento;<br class="">
+<br class="">
+namespace {<br class="">
+<br class="">
+class TrustNonnullChecker : public Checker<check::PostCall> {<br class="">
+public:<br class="">
+  void checkPostCall(const CallEvent &Call, CheckerContext &C) const {<br class="">
+    // Only trust annotations for system headers for non-protocols.<br class="">
+    if (!Call.isInSystemHeader())<br class="">
+      return;<br class="">
+<br class="">
+    QualType RetType = Call.getResultType();<br class="">
+    if (!RetType->isAnyPointerType())<br class="">
+      return;<br class="">
+<br class="">
+    ProgramStateRef State = C.getState();<br class="">
+    if (getNullabilityAnnotation(RetType) == Nullability::Nonnull)<br class="">
+      if (auto L = Call.getReturnValue().getAs<Loc>())<br class="">
+        State = State->assume(*L, /*Assumption=*/true);<br class="">
+<br class="">
+    C.addTransition(State);<br class="">
+  }<br class="">
+};<br class="">
+<br class="">
+} // end empty namespace<br class="">
+<br class="">
+<br class="">
+void ento::registerTrustNonnullChecker(CheckerManager &Mgr) {<br class="">
+  Mgr.registerChecker<TrustNonnullChecker>();<br class="">
+}<br class="">
<br class="">
Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp?rev=328282&r1=328281&r2=328282&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp?rev=328282&r1=328281&r2=328282&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp (original)<br class="">
+++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerHelpers.cpp Thu Mar 22 17:16:03 2018<br class="">
@@ -15,8 +15,12 @@<br class="">
 #include "clang/AST/Decl.h"<br class="">
 #include "clang/AST/Expr.h"<br class="">
<br class="">
+namespace clang {<br class="">
+<br class="">
+namespace ento {<br class="">
+<br class="">
 // Recursively find any substatements containing macros<br class="">
-bool clang::ento::containsMacro(const Stmt *S) {<br class="">
+bool containsMacro(const Stmt *S) {<br class="">
   if (S->getLocStart().isMacroID())<br class="">
     return true;<br class="">
<br class="">
@@ -31,7 +35,7 @@ bool clang::ento::containsMacro(const St<br class="">
 }<br class="">
<br class="">
 // Recursively find any substatements containing enum constants<br class="">
-bool clang::ento::containsEnum(const Stmt *S) {<br class="">
+bool containsEnum(const Stmt *S) {<br class="">
   const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);<br class="">
<br class="">
   if (DR && isa<EnumConstantDecl>(DR->getDecl()))<br class="">
@@ -45,7 +49,7 @@ bool clang::ento::containsEnum(const Stm<br class="">
 }<br class="">
<br class="">
 // Recursively find any substatements containing static vars<br class="">
-bool clang::ento::containsStaticLocal(const Stmt *S) {<br class="">
+bool containsStaticLocal(const Stmt *S) {<br class="">
   const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);<br class="">
<br class="">
   if (DR)<br class="">
@@ -61,7 +65,7 @@ bool clang::ento::containsStaticLocal(co<br class="">
 }<br class="">
<br class="">
 // Recursively find any substatements containing __builtin_offsetof<br class="">
-bool clang::ento::containsBuiltinOffsetOf(const Stmt *S) {<br class="">
+bool containsBuiltinOffsetOf(const Stmt *S) {<br class="">
   if (isa<OffsetOfExpr>(S))<br class="">
     return true;<br class="">
<br class="">
@@ -74,7 +78,7 @@ bool clang::ento::containsBuiltinOffsetO<br class="">
<br class="">
 // Extract lhs and rhs from assignment statement<br class="">
 std::pair<const clang::VarDecl *, const clang::Expr *><br class="">
-clang::ento::parseAssignment(const Stmt *S) {<br class="">
+parseAssignment(const Stmt *S) {<br class="">
   const VarDecl *VD = nullptr;<br class="">
   const Expr *RHS = nullptr;<br class="">
<br class="">
@@ -94,3 +98,18 @@ clang::ento::parseAssignment(const Stmt<br class="">
<br class="">
   return std::make_pair(VD, RHS);<br class="">
 }<br class="">
+<br class="">
+Nullability getNullabilityAnnotation(QualType Type) {<br class="">
+  const auto *AttrType = Type->getAs<AttributedType>();<br class="">
+  if (!AttrType)<br class="">
+    return Nullability::Unspecified;<br class="">
+  if (AttrType->getAttrKind() == AttributedType::attr_nullable)<br class="">
+    return Nullability::Nullable;<br class="">
+  else if (AttrType->getAttrKind() == AttributedType::attr_nonnull)<br class="">
+    return Nullability::Nonnull;<br class="">
+  return Nullability::Unspecified;<br class="">
+}<br class="">
+<br class="">
+<br class="">
+} // end namespace ento<br class="">
+} // end namespace clang<br class="">
<br class="">
Modified: cfe/trunk/test/Analysis/Inputs/system-header-simulator-for-nullability.h<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/system-header-simulator-for-nullability.h?rev=328282&r1=328281&r2=328282&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/system-header-simulator-for-nullability.h?rev=328282&r1=328281&r2=328282&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/test/Analysis/Inputs/system-header-simulator-for-nullability.h (original)<br class="">
+++ cfe/trunk/test/Analysis/Inputs/system-header-simulator-for-nullability.h Thu Mar 22 17:16:03 2018<br class="">
@@ -32,6 +32,8 @@ NSObject<NSObject><br class="">
 @interface NSString : NSObject<NSCopying><br class="">
 - (BOOL)isEqualToString : (NSString *)aString;<br class="">
 - (NSString *)stringByAppendingString:(NSString *)aString;<br class="">
++ (_Nonnull NSString *) generateString;<br class="">
++ (_Nullable NSString *) generatePossiblyNullString;<br class="">
 @end<br class="">
<br class="">
 void NSSystemFunctionTakingNonnull(NSString *s);<br class="">
@@ -40,4 +42,11 @@ void NSSystemFunctionTakingNonnull(NSStr<br class="">
 - (void) takesNonnull:(NSString *)s;<br class="">
 @end<br class="">
<br class="">
+NSString* _Nullable getPossiblyNullString();<br class="">
+NSString* _Nonnull  getString();<br class="">
+<br class="">
+@protocol MyProtocol<br class="">
+- (_Nonnull NSString *) getString;<br class="">
+@end<br class="">
+<br class="">
 NS_ASSUME_NONNULL_END<br class="">
<br class="">
Added: cfe/trunk/test/Analysis/trustnonnullchecker_test.m<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/trustnonnullchecker_test.m?rev=328282&view=auto" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/trustnonnullchecker_test.m?rev=328282&view=auto</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/test/Analysis/trustnonnullchecker_test.m (added)<br class="">
+++ cfe/trunk/test/Analysis/trustnonnullchecker_test.m Thu Mar 22 17:16:03 2018<br class="">
@@ -0,0 +1,43 @@<br class="">
+// RUN: %clang_analyze_cc1 -fblocks -analyze -analyzer-checker=core,nullability,apiModeling  -verify %s<br class="">
+<br class="">
+#include "Inputs/system-header-simulator-for-nullability.h"<br class="">
+<br class="">
+NSString* getUnknownString();<br class="">
+<br class="">
+NSString* _Nonnull trust_nonnull_framework_annotation() {<br class="">
+  NSString* out = [NSString generateString];<br class="">
+  if (out) {}<br class="">
+  return out; // no-warning<br class="">
+}<br class="">
+<br class="">
+NSString* _Nonnull distrust_without_annotation() {<br class="">
+  NSString* out = [NSString generatePossiblyNullString];<br class="">
+  if (out) {}<br class="">
+  return out; // expected-warning{{}}<br class="">
+}<br class="">
+<br class="">
+NSString* _Nonnull nonnull_please_trust_me();<br class="">
+<br class="">
+NSString* _Nonnull distrust_local_nonnull_annotation() {<br class="">
+  NSString* out = nonnull_please_trust_me();<br class="">
+  if (out) {}<br class="">
+  return out; // expected-warning{{}}<br class="">
+}<br class="">
+<br class="">
+NSString* _Nonnull trust_c_function() {<br class="">
+  NSString* out = getString();<br class="">
+  if (out) {};<br class="">
+  return out; // no-warning<br class="">
+}<br class="">
+<br class="">
+NSString* _Nonnull distrust_unannoted_function() {<br class="">
+  NSString* out = getPossiblyNullString();<br class="">
+  if (out) {};<br class="">
+  return out; // expected-warning{{}}<br class="">
+}<br class="">
+<br class="">
+NSString * _Nonnull distrustProtocol(id<MyProtocol> o) {<br class="">
+  NSString* out = [o getString];<br class="">
+  if (out) {};<br class="">
+  return out; // expected-warning{{}}<br class="">
+}<br class="">
<br class="">
<br class="">
_______________________________________________<br class="">
cfe-commits mailing list<br class="">
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" class="">cfe-commits@lists.llvm.org</a><br class="">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br class="">
</blockquote></div>
</div></blockquote></div><br class=""></body></html>