balazske updated this revision to Diff 435082.
balazske added a comment.

small test change, removed a compile warning


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D125400/new/

https://reviews.llvm.org/D125400

Files:
  clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
  clang/test/Analysis/errno-stdlibraryfunctions-notes.c
  clang/test/Analysis/errno-stdlibraryfunctions.c

Index: clang/test/Analysis/errno-stdlibraryfunctions.c
===================================================================
--- /dev/null
+++ clang/test/Analysis/errno-stdlibraryfunctions.c
@@ -0,0 +1,55 @@
+// RUN: %clang_analyze_cc1 -verify %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=debug.ExprInspection \
+// RUN:   -analyzer-checker=apiModeling.StdCLibraryFunctions \
+// RUN:   -analyzer-checker=apiModeling.Errno \
+// RUN:   -analyzer-checker=alpha.unix.Errno \
+// RUN:   -analyzer-config apiModeling.StdCLibraryFunctions:ModelPOSIX=true
+
+#include "Inputs/errno_var.h"
+
+typedef typeof(sizeof(int)) size_t;
+typedef __typeof(sizeof(int)) off_t;
+typedef size_t ssize_t;
+ssize_t send(int sockfd, const void *buf, size_t len, int flags);
+off_t lseek(int fildes, off_t offset, int whence);
+
+void clang_analyzer_warnIfReached();
+void clang_analyzer_eval(int);
+
+int unsafe_errno_read(int sock, void *data, int data_size) {
+  if (send(sock, data, data_size, 0) != data_size) {
+    if (errno == 1) {
+      // expected-warning@-1{{An undefined value may be read from 'errno'}}
+      return 0;
+    }
+  }
+  return 1;
+}
+
+int errno_lseek(int fildes, off_t offset) {
+  off_t result = lseek(fildes, offset, 0);
+  if (result == (off_t)-1) {
+    // Failure path.
+    // check if the function is modeled
+    clang_analyzer_eval(errno != 0); // expected-warning{{TRUE}}
+    return 2;
+  }
+  if (result != offset) {
+    // Not success path (?)
+    // not sure if this is a valid case, allow to check 'errno'
+    if (errno == 1) { // no warning
+      return 1;
+    }
+  }
+  if (result == offset) {
+    // The checker does not differentiate for this case.
+    // In general case no relation exists between the arg 2 and the returned
+    // value, only for SEEK_SET.
+    if (errno == 1) { // no warning
+      return 1;
+    }
+    clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+  }
+  return 0;
+}
Index: clang/test/Analysis/errno-stdlibraryfunctions-notes.c
===================================================================
--- /dev/null
+++ clang/test/Analysis/errno-stdlibraryfunctions-notes.c
@@ -0,0 +1,49 @@
+// RUN: %clang_analyze_cc1 -verify -analyzer-output text %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=debug.ExprInspection \
+// RUN:   -analyzer-checker=apiModeling.StdCLibraryFunctions \
+// RUN:   -analyzer-checker=apiModeling.Errno \
+// RUN:   -analyzer-checker=alpha.unix.Errno \
+// RUN:   -analyzer-config apiModeling.StdCLibraryFunctions:ModelPOSIX=true
+
+#include "Inputs/errno_var.h"
+
+int access(const char *path, int amode);
+
+void clang_analyzer_warnIfReached();
+
+void test1() {
+  access("path", 0); // no note here
+  access("path", 0);
+  // expected-note@-1{{Assuming that function 'access' is successful, in this case the value 'errno' may be undefined after the call and should not be used}}
+  if (errno != 0) {
+    // expected-warning@-1{{An undefined value may be read from 'errno'}}
+    // expected-note@-2{{An undefined value may be read from 'errno'}}
+  }
+}
+
+void test2() {
+  if (access("path", 0) == -1) {
+    // expected-note@-1{{Taking true branch}}
+    // Failure path.
+    if (errno != 0) {
+      // expected-note@-1{{'errno' is not equal to 0}}
+      // expected-note@-2{{Taking true branch}}
+      clang_analyzer_warnIfReached(); // expected-note {{REACHABLE}} expected-warning {{REACHABLE}}
+    } else {
+      clang_analyzer_warnIfReached(); // no-warning: We are on the failure path.
+    }
+  }
+}
+
+void test3() {
+  if (access("path", 0) != -1) {
+    // Success path.
+    // expected-note@-2{{Assuming that function 'access' is successful, in this case the value 'errno' may be undefined after the call and should not be used}}
+    // expected-note@-3{{Taking true branch}}
+    if (errno != 0) {
+      // expected-warning@-1{{An undefined value may be read from 'errno'}}
+      // expected-note@-2{{An undefined value may be read from 'errno'}}
+    }
+  }
+}
Index: clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -40,6 +40,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "ErrnoModeling.h"
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
@@ -56,6 +57,17 @@
 using namespace clang;
 using namespace clang::ento;
 
+static const char *describeErrnoCheckState(errno_modeling::ErrnoCheckState CS) {
+  switch (CS) {
+  case errno_modeling::Errno_Irrelevant:
+    return "is not significant";
+  case errno_modeling::Errno_MustBeChecked:
+    return "should be checked to verify if the call was successful";
+  case errno_modeling::Errno_MustNotBeChecked:
+    return "may be undefined after the call and should not be used";
+  };
+}
+
 namespace {
 class StdLibraryFunctionsChecker
     : public Checker<check::PreCall, check::PostCall, eval::Call> {
@@ -377,6 +389,113 @@
   /// The complete list of constraints that defines a single branch.
   using ConstraintSet = std::vector<ValueConstraintPtr>;
 
+  /// Define how a function affects the system variable 'errno'.
+  /// This works together with the ErrnoModeling and ErrnoChecker classes.
+  class ErrnoConstraintBase {
+  public:
+    /// Apply specific state changes related to the errno variable.
+    virtual ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
+                                  const Summary &Summary,
+                                  CheckerContext &C) const = 0;
+    /// Get a description about what is applied to 'errno' and how is it allowed
+    /// to be used. If ErrnoChecker generates a bug then this message is
+    /// displayed as a note at the function call.
+    /// It may return empty string if no note tag is to be added.
+    virtual std::string describe(StringRef FunctionName) const { return ""; }
+
+    virtual ~ErrnoConstraintBase() {}
+
+  protected:
+    /// Many of the descendant classes use this value.
+    errno_modeling::ErrnoCheckState const CheckState;
+
+    ErrnoConstraintBase(errno_modeling::ErrnoCheckState CS) : CheckState(CS) {}
+
+    /// This is used for conjure symbol for errno to differentiate from the
+    /// original call expression (same expression is used for the errno symbol).
+    static int Tag;
+  };
+
+  /// Set value of 'errno' to be related to 0 in a specified way, with a
+  /// specified "errno check state". For example with \c BO_GT 'errno' is
+  /// constrained to be greater than 0. Use this for failure cases of functions.
+  class ZeroRelatedErrnoConstraint : public ErrnoConstraintBase {
+    BinaryOperatorKind Op;
+
+  public:
+    ZeroRelatedErrnoConstraint(clang::BinaryOperatorKind OpK,
+                               errno_modeling::ErrnoCheckState CS)
+        : ErrnoConstraintBase(CS), Op(OpK) {
+      assert(BinaryOperator::isComparisonOp(OpK));
+    }
+
+    ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
+                          const Summary &Summary,
+                          CheckerContext &C) const override {
+      SValBuilder &SVB = C.getSValBuilder();
+      NonLoc ErrnoSVal =
+          SVB.conjureSymbolVal(&Tag, Call.getOriginExpr(),
+                               C.getLocationContext(), C.getASTContext().IntTy,
+                               C.blockCount())
+              .castAs<NonLoc>();
+      NonLoc ZeroVal =
+          SVB.makeZeroVal(C.getASTContext().IntTy).castAs<NonLoc>();
+      DefinedOrUnknownSVal Cond =
+          SVB.evalBinOpNN(State, Op, ErrnoSVal, ZeroVal, SVB.getConditionType())
+              .castAs<DefinedOrUnknownSVal>();
+      State = State->assume(Cond, true);
+      if (!State)
+        return State;
+      return errno_modeling::setErrnoValue(State, C.getLocationContext(),
+                                           ErrnoSVal, CheckState);
+    }
+
+    std::string describe(StringRef FunctionName) const override {
+      return (Twine("Assuming that function '") + FunctionName.str() +
+              "' fails, in this case the value 'errno' becomes " +
+              BinaryOperator::getOpcodeStr(Op).str() + " 0 and " +
+              describeErrnoCheckState(CheckState))
+          .str();
+    }
+  };
+
+  /// Applies the constraints to 'errno' for a common case when a standard
+  /// function is successful. The value of 'errno' after the call is not
+  /// specified by the standard (it may change or not). The \c ErrnoChecker can
+  /// generate a bug if 'errno' is read afterwards.
+  class SuccessErrnoConstraint : public ErrnoConstraintBase {
+  public:
+    SuccessErrnoConstraint()
+        : ErrnoConstraintBase(errno_modeling::Errno_MustNotBeChecked) {}
+
+    ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
+                          const Summary &Summary,
+                          CheckerContext &C) const override {
+      return errno_modeling::setErrnoState(State, CheckState);
+    }
+
+    std::string describe(StringRef FunctionName) const override {
+      return (Twine("Assuming that function '") + FunctionName.str() +
+              "' is successful, in this case the value 'errno' " +
+              describeErrnoCheckState(CheckState))
+          .str();
+    }
+  };
+
+  /// Set errno constraints if use of 'errno' is completely irrelevant to the
+  /// modeled function or modeling is not possible.
+  class NoErrnoConstraint : public ErrnoConstraintBase {
+  public:
+    NoErrnoConstraint()
+        : ErrnoConstraintBase(errno_modeling::Errno_Irrelevant) {}
+
+    ProgramStateRef apply(ProgramStateRef State, const CallEvent &Call,
+                          const Summary &Summary,
+                          CheckerContext &C) const override {
+      return errno_modeling::setErrnoState(State, CheckState);
+    }
+  };
+
   /// A single branch of a function summary.
   ///
   /// A branch is defined by a series of constraints - "assumptions" -
@@ -400,16 +519,23 @@
   ///     and the note may say "Assuming the character is non-alphabetical".
   class SummaryCase {
     ConstraintSet Constraints;
+    const ErrnoConstraintBase &ErrnoConstraint;
     StringRef Note;
 
   public:
-    SummaryCase(ConstraintSet &&Constraints, StringRef Note)
-        : Constraints(std::move(Constraints)), Note(Note) {}
+    SummaryCase(ConstraintSet &&Constraints, const ErrnoConstraintBase &ErrnoC,
+                StringRef Note)
+        : Constraints(std::move(Constraints)), ErrnoConstraint(ErrnoC),
+          Note(Note) {}
 
-    SummaryCase(const ConstraintSet &Constraints, StringRef Note)
-        : Constraints(Constraints), Note(Note) {}
+    SummaryCase(const ConstraintSet &Constraints,
+                const ErrnoConstraintBase &ErrnoC, StringRef Note)
+        : Constraints(Constraints), ErrnoConstraint(ErrnoC), Note(Note) {}
 
     const ConstraintSet &getConstraints() const { return Constraints; }
+    const ErrnoConstraintBase &getErrnoConstraint() const {
+      return ErrnoConstraint;
+    }
     StringRef getNote() const { return Note; }
   };
 
@@ -508,12 +634,14 @@
   public:
     Summary(InvalidationKind InvalidationKd) : InvalidationKd(InvalidationKd) {}
 
-    Summary &Case(ConstraintSet &&CS, StringRef Note = "") {
-      Cases.push_back(SummaryCase(std::move(CS), Note));
+    Summary &Case(ConstraintSet &&CS, const ErrnoConstraintBase &ErrnoC,
+                  StringRef Note = "") {
+      Cases.push_back(SummaryCase(std::move(CS), ErrnoC, Note));
       return *this;
     }
-    Summary &Case(const ConstraintSet &CS, StringRef Note = "") {
-      Cases.push_back(SummaryCase(CS, Note));
+    Summary &Case(const ConstraintSet &CS, const ErrnoConstraintBase &ErrnoC,
+                  StringRef Note = "") {
+      Cases.push_back(SummaryCase(CS, ErrnoC, Note));
       return *this;
     }
     Summary &ArgConstraint(ValueConstraintPtr VC) {
@@ -621,8 +749,20 @@
 
     C.emitReport(std::move(R));
   }
+
+  /// These are the errno constraints that can be passed to summary cases.
+  /// One of these should fit for a single summary case.
+  /// Usually if a failure return value exists for function, that function
+  /// needs different cases for success and failure with different errno
+  /// constraints (and different return value constraints).
+  const NoErrnoConstraint ErrnoIrrelevant;
+  const SuccessErrnoConstraint ErrnoMustNotBeChecked;
+  const ZeroRelatedErrnoConstraint ErrnoNEZeroIrrelevant{
+      clang::BinaryOperatorKind::BO_NE, errno_modeling::Errno_Irrelevant};
 };
 
+int StdLibraryFunctionsChecker::ErrnoConstraintBase::Tag = 0;
+
 const StdLibraryFunctionsChecker::ArgNo StdLibraryFunctionsChecker::Ret =
     std::numeric_limits<ArgNo>::max();
 
@@ -869,17 +1009,30 @@
         break;
     }
 
+    if (NewState)
+      NewState = Case.getErrnoConstraint().apply(NewState, Call, Summary, C);
+
     if (NewState && NewState != State) {
-      StringRef Note = Case.getNote();
-      const NoteTag *Tag = C.getNoteTag(
-          // Sorry couldn't help myself.
-          [Node, Note]() {
-            // Don't emit "Assuming..." note when we ended up
-            // knowing in advance which branch is taken.
-            return (Node->succ_size() > 1) ? Note.str() : "";
-          },
-          /*IsPrunable=*/true);
-      C.addTransition(NewState, Tag);
+      if (Case.getNote().empty()) {
+        std::string Note;
+        if (const auto *D = dyn_cast_or_null<FunctionDecl>(Call.getDecl()))
+          Note = Case.getErrnoConstraint().describe(D->getNameAsString());
+        if (Note.empty())
+          C.addTransition(NewState);
+        else
+          C.addTransition(NewState, errno_modeling::getErrnoNoteTag(C, Note));
+      } else {
+        StringRef Note = Case.getNote();
+        const NoteTag *Tag = C.getNoteTag(
+            // Sorry couldn't help myself.
+            [Node, Note]() -> std::string {
+              // Don't emit "Assuming..." note when we ended up
+              // knowing in advance which branch is taken.
+              return (Node->succ_size() > 1) ? Note.str() : "";
+            },
+            /*IsPrunable=*/true);
+        C.addTransition(NewState, Tag);
+      }
     }
   }
 }
@@ -899,7 +1052,9 @@
     SVal V = C.getSValBuilder().conjureSymbolVal(
         CE, LC, CE->getType().getCanonicalType(), C.blockCount());
     State = State->BindExpr(CE, LC, V);
+
     C.addTransition(State);
+
     return true;
   }
   case NoEvalCall:
@@ -1239,17 +1394,18 @@
           .Case({ArgumentCondition(0U, WithinRange,
                                    {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}}),
                  ReturnValueCondition(OutOfRange, SingleValue(0))},
-                "Assuming the character is alphanumeric")
+                ErrnoIrrelevant, "Assuming the character is alphanumeric")
           // The locale-specific range.
           // No post-condition. We are completely unaware of
           // locale-specific return values.
-          .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})})
+          .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})},
+                ErrnoIrrelevant)
           .Case(
               {ArgumentCondition(
                    0U, OutOfRange,
                    {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}),
                ReturnValueCondition(WithinRange, SingleValue(0))},
-              "Assuming the character is non-alphanumeric")
+              ErrnoIrrelevant, "Assuming the character is non-alphanumeric")
           .ArgConstraint(ArgumentCondition(
               0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})));
   addToFunctionSummaryMap(
@@ -1257,59 +1413,66 @@
       Summary(EvalCallAsPure)
           .Case({ArgumentCondition(0U, WithinRange, {{'A', 'Z'}, {'a', 'z'}}),
                  ReturnValueCondition(OutOfRange, SingleValue(0))},
-                "Assuming the character is alphabetical")
+                ErrnoIrrelevant, "Assuming the character is alphabetical")
           // The locale-specific range.
-          .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})})
+          .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})},
+                ErrnoIrrelevant)
           .Case({ArgumentCondition(
                      0U, OutOfRange,
                      {{'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}),
                  ReturnValueCondition(WithinRange, SingleValue(0))},
-                "Assuming the character is non-alphabetical"));
+                ErrnoIrrelevant, "Assuming the character is non-alphabetical"));
   addToFunctionSummaryMap(
       "isascii", Signature(ArgTypes{IntTy}, RetType{IntTy}),
       Summary(EvalCallAsPure)
           .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)),
                  ReturnValueCondition(OutOfRange, SingleValue(0))},
-                "Assuming the character is an ASCII character")
+                ErrnoIrrelevant, "Assuming the character is an ASCII character")
           .Case({ArgumentCondition(0U, OutOfRange, Range(0, 127)),
                  ReturnValueCondition(WithinRange, SingleValue(0))},
+                ErrnoIrrelevant,
                 "Assuming the character is not an ASCII character"));
   addToFunctionSummaryMap(
       "isblank", Signature(ArgTypes{IntTy}, RetType{IntTy}),
       Summary(EvalCallAsPure)
           .Case({ArgumentCondition(0U, WithinRange, {{'\t', '\t'}, {' ', ' '}}),
                  ReturnValueCondition(OutOfRange, SingleValue(0))},
-                "Assuming the character is a blank character")
+                ErrnoIrrelevant, "Assuming the character is a blank character")
           .Case({ArgumentCondition(0U, OutOfRange, {{'\t', '\t'}, {' ', ' '}}),
                  ReturnValueCondition(WithinRange, SingleValue(0))},
+                ErrnoIrrelevant,
                 "Assuming the character is not a blank character"));
   addToFunctionSummaryMap(
       "iscntrl", Signature(ArgTypes{IntTy}, RetType{IntTy}),
       Summary(EvalCallAsPure)
           .Case({ArgumentCondition(0U, WithinRange, {{0, 32}, {127, 127}}),
                  ReturnValueCondition(OutOfRange, SingleValue(0))},
+                ErrnoIrrelevant,
                 "Assuming the character is a control character")
           .Case({ArgumentCondition(0U, OutOfRange, {{0, 32}, {127, 127}}),
                  ReturnValueCondition(WithinRange, SingleValue(0))},
+                ErrnoIrrelevant,
                 "Assuming the character is not a control character"));
   addToFunctionSummaryMap(
       "isdigit", Signature(ArgTypes{IntTy}, RetType{IntTy}),
       Summary(EvalCallAsPure)
           .Case({ArgumentCondition(0U, WithinRange, Range('0', '9')),
                  ReturnValueCondition(OutOfRange, SingleValue(0))},
-                "Assuming the character is a digit")
+                ErrnoIrrelevant, "Assuming the character is a digit")
           .Case({ArgumentCondition(0U, OutOfRange, Range('0', '9')),
                  ReturnValueCondition(WithinRange, SingleValue(0))},
-                "Assuming the character is not a digit"));
+                ErrnoIrrelevant, "Assuming the character is not a digit"));
   addToFunctionSummaryMap(
       "isgraph", Signature(ArgTypes{IntTy}, RetType{IntTy}),
       Summary(EvalCallAsPure)
           .Case({ArgumentCondition(0U, WithinRange, Range(33, 126)),
                  ReturnValueCondition(OutOfRange, SingleValue(0))},
+                ErrnoIrrelevant,
                 "Assuming the character has graphical representation")
           .Case(
               {ArgumentCondition(0U, OutOfRange, Range(33, 126)),
                ReturnValueCondition(WithinRange, SingleValue(0))},
+              ErrnoIrrelevant,
               "Assuming the character does not have graphical representation"));
   addToFunctionSummaryMap(
       "islower", Signature(ArgTypes{IntTy}, RetType{IntTy}),
@@ -1317,26 +1480,29 @@
           // Is certainly lowercase.
           .Case({ArgumentCondition(0U, WithinRange, Range('a', 'z')),
                  ReturnValueCondition(OutOfRange, SingleValue(0))},
-                "Assuming the character is a lowercase letter")
+                ErrnoIrrelevant, "Assuming the character is a lowercase letter")
           // Is ascii but not lowercase.
           .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)),
                  ArgumentCondition(0U, OutOfRange, Range('a', 'z')),
                  ReturnValueCondition(WithinRange, SingleValue(0))},
+                ErrnoIrrelevant,
                 "Assuming the character is not a lowercase letter")
           // The locale-specific range.
-          .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})})
+          .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})},
+                ErrnoIrrelevant)
           // Is not an unsigned char.
           .Case({ArgumentCondition(0U, OutOfRange, Range(0, UCharRangeMax)),
-                 ReturnValueCondition(WithinRange, SingleValue(0))}));
+                 ReturnValueCondition(WithinRange, SingleValue(0))},
+                ErrnoIrrelevant));
   addToFunctionSummaryMap(
       "isprint", Signature(ArgTypes{IntTy}, RetType{IntTy}),
       Summary(EvalCallAsPure)
           .Case({ArgumentCondition(0U, WithinRange, Range(32, 126)),
                  ReturnValueCondition(OutOfRange, SingleValue(0))},
-                "Assuming the character is printable")
+                ErrnoIrrelevant, "Assuming the character is printable")
           .Case({ArgumentCondition(0U, OutOfRange, Range(32, 126)),
                  ReturnValueCondition(WithinRange, SingleValue(0))},
-                "Assuming the character is non-printable"));
+                ErrnoIrrelevant, "Assuming the character is non-printable"));
   addToFunctionSummaryMap(
       "ispunct", Signature(ArgTypes{IntTy}, RetType{IntTy}),
       Summary(EvalCallAsPure)
@@ -1344,11 +1510,12 @@
                      0U, WithinRange,
                      {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}),
                  ReturnValueCondition(OutOfRange, SingleValue(0))},
-                "Assuming the character is a punctuation mark")
+                ErrnoIrrelevant, "Assuming the character is a punctuation mark")
           .Case({ArgumentCondition(
                      0U, OutOfRange,
                      {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}),
                  ReturnValueCondition(WithinRange, SingleValue(0))},
+                ErrnoIrrelevant,
                 "Assuming the character is not a punctuation mark"));
   addToFunctionSummaryMap(
       "isspace", Signature(ArgTypes{IntTy}, RetType{IntTy}),
@@ -1356,12 +1523,15 @@
           // Space, '\f', '\n', '\r', '\t', '\v'.
           .Case({ArgumentCondition(0U, WithinRange, {{9, 13}, {' ', ' '}}),
                  ReturnValueCondition(OutOfRange, SingleValue(0))},
+                ErrnoIrrelevant,
                 "Assuming the character is a whitespace character")
           // The locale-specific range.
-          .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})})
+          .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})},
+                ErrnoIrrelevant)
           .Case({ArgumentCondition(0U, OutOfRange,
                                    {{9, 13}, {' ', ' '}, {128, UCharRangeMax}}),
                  ReturnValueCondition(WithinRange, SingleValue(0))},
+                ErrnoIrrelevant,
                 "Assuming the character is not a whitespace character"));
   addToFunctionSummaryMap(
       "isupper", Signature(ArgTypes{IntTy}, RetType{IntTy}),
@@ -1369,13 +1539,16 @@
           // Is certainly uppercase.
           .Case({ArgumentCondition(0U, WithinRange, Range('A', 'Z')),
                  ReturnValueCondition(OutOfRange, SingleValue(0))},
+                ErrnoIrrelevant,
                 "Assuming the character is an uppercase letter")
           // The locale-specific range.
-          .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})})
+          .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})},
+                ErrnoIrrelevant)
           // Other.
           .Case({ArgumentCondition(0U, OutOfRange,
                                    {{'A', 'Z'}, {128, UCharRangeMax}}),
                  ReturnValueCondition(WithinRange, SingleValue(0))},
+                ErrnoIrrelevant,
                 "Assuming the character is not an uppercase letter"));
   addToFunctionSummaryMap(
       "isxdigit", Signature(ArgTypes{IntTy}, RetType{IntTy}),
@@ -1383,10 +1556,12 @@
           .Case({ArgumentCondition(0U, WithinRange,
                                    {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}),
                  ReturnValueCondition(OutOfRange, SingleValue(0))},
+                ErrnoIrrelevant,
                 "Assuming the character is a hexadecimal digit")
           .Case({ArgumentCondition(0U, OutOfRange,
                                    {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}),
                  ReturnValueCondition(WithinRange, SingleValue(0))},
+                ErrnoIrrelevant,
                 "Assuming the character is not a hexadecimal digit"));
   addToFunctionSummaryMap(
       "toupper", Signature(ArgTypes{IntTy}, RetType{IntTy}),
@@ -1409,18 +1584,21 @@
       {"getc", "fgetc"}, Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
       Summary(NoEvalCall)
           .Case({ReturnValueCondition(WithinRange,
-                                      {{EOFv, EOFv}, {0, UCharRangeMax}})}));
+                                      {{EOFv, EOFv}, {0, UCharRangeMax}})},
+                ErrnoIrrelevant));
   addToFunctionSummaryMap(
       "getchar", Signature(ArgTypes{}, RetType{IntTy}),
       Summary(NoEvalCall)
           .Case({ReturnValueCondition(WithinRange,
-                                      {{EOFv, EOFv}, {0, UCharRangeMax}})}));
+                                      {{EOFv, EOFv}, {0, UCharRangeMax}})},
+                ErrnoIrrelevant));
 
   // read()-like functions that never return more than buffer size.
   auto FreadSummary =
       Summary(NoEvalCall)
           .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
-                 ReturnValueCondition(WithinRange, Range(0, SizeMax))})
+                 ReturnValueCondition(WithinRange, Range(0, SizeMax))},
+                ErrnoIrrelevant)
           .ArgConstraint(NotNull(ArgNo(0)))
           .ArgConstraint(NotNull(ArgNo(3)))
           .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(0), /*BufSize=*/ArgNo(1),
@@ -1447,7 +1625,8 @@
   auto ReadSummary =
       Summary(NoEvalCall)
           .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
-                 ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))});
+                 ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))},
+                ErrnoIrrelevant);
 
   // FIXME these are actually defined by POSIX and not by the C standard, we
   // should handle them together with the rest of the POSIX functions.
@@ -1464,7 +1643,8 @@
   auto GetLineSummary =
       Summary(NoEvalCall)
           .Case({ReturnValueCondition(WithinRange,
-                                      Range({-1, -1}, {1, Ssize_tMax}))});
+                                      Range({-1, -1}, {1, Ssize_tMax}))},
+                ErrnoIrrelevant);
 
   QualType CharPtrPtrRestrictTy = getRestrictTy(getPointerTy(CharPtrTy));
 
@@ -1492,10 +1672,11 @@
     Summary GetenvSummary =
         Summary(NoEvalCall)
             .ArgConstraint(NotNull(ArgNo(0)))
-            .Case({NotNull(Ret)}, "Assuming the environment variable exists");
+            .Case({NotNull(Ret)}, ErrnoIrrelevant,
+                  "Assuming the environment variable exists");
     // In untrusted environments the envvar might not exist.
     if (!ShouldAssumeControlledEnvironment)
-      GetenvSummary.Case({NotNull(Ret)->negate()},
+      GetenvSummary.Case({NotNull(Ret)->negate()}, ErrnoIrrelevant,
                          "Assuming the environment variable does not exist");
 
     // char *getenv(const char *name);
@@ -1520,14 +1701,22 @@
 
     const auto ReturnsZeroOrMinusOne =
         ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, 0))};
+    const auto ReturnsZero =
+        ConstraintSet{ReturnValueCondition(WithinRange, SingleValue(0))};
+    const auto ReturnsMinusOne =
+        ConstraintSet{ReturnValueCondition(WithinRange, SingleValue(-1))};
+    const auto ReturnsNonnegative =
+        ConstraintSet{ReturnValueCondition(WithinRange, Range(0, IntMax))};
     const auto ReturnsFileDescriptor =
         ConstraintSet{ReturnValueCondition(WithinRange, Range(-1, IntMax))};
+    const auto &ReturnsValidFileDescriptor = ReturnsNonnegative;
 
     // int access(const char *pathname, int amode);
     addToFunctionSummaryMap(
         "access", Signature(ArgTypes{ConstCharPtrTy, IntTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0))));
 
     // int faccessat(int dirfd, const char *pathname, int mode, int flags);
@@ -1536,21 +1725,25 @@
         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, IntTy},
                   RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(1))));
 
     // int dup(int fildes);
-    addToFunctionSummaryMap("dup", Signature(ArgTypes{IntTy}, RetType{IntTy}),
-                            Summary(NoEvalCall)
-                                .Case(ReturnsFileDescriptor)
-                                .ArgConstraint(ArgumentCondition(
-                                    0, WithinRange, Range(0, IntMax))));
+    addToFunctionSummaryMap(
+        "dup", Signature(ArgTypes{IntTy}, RetType{IntTy}),
+        Summary(NoEvalCall)
+            .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
+            .ArgConstraint(
+                ArgumentCondition(0, WithinRange, Range(0, IntMax))));
 
     // int dup2(int fildes1, int filedes2);
     addToFunctionSummaryMap(
         "dup2", Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsFileDescriptor)
+            .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
             .ArgConstraint(
                 ArgumentCondition(1, WithinRange, Range(0, IntMax))));
@@ -1559,7 +1752,8 @@
     addToFunctionSummaryMap("fdatasync",
                             Signature(ArgTypes{IntTy}, RetType{IntTy}),
                             Summary(NoEvalCall)
-                                .Case(ReturnsZeroOrMinusOne)
+                                .Case(ReturnsZero, ErrnoMustNotBeChecked)
+                                .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
                                 .ArgConstraint(ArgumentCondition(
                                     0, WithinRange, Range(0, IntMax))));
 
@@ -1568,14 +1762,15 @@
         "fnmatch",
         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy, IntTy},
                   RetType{IntTy}),
-        Summary(EvalCallAsPure)
+        Summary(NoEvalCall)
             .ArgConstraint(NotNull(ArgNo(0)))
             .ArgConstraint(NotNull(ArgNo(1))));
 
     // int fsync(int fildes);
     addToFunctionSummaryMap("fsync", Signature(ArgTypes{IntTy}, RetType{IntTy}),
                             Summary(NoEvalCall)
-                                .Case(ReturnsZeroOrMinusOne)
+                                .Case(ReturnsZero, ErrnoMustNotBeChecked)
+                                .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
                                 .ArgConstraint(ArgumentCondition(
                                     0, WithinRange, Range(0, IntMax))));
 
@@ -1586,7 +1781,8 @@
         "truncate",
         Signature(ArgTypes{ConstCharPtrTy, Off_tTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0))));
 
     // int symlink(const char *oldpath, const char *newpath);
@@ -1594,7 +1790,8 @@
         "symlink",
         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0)))
             .ArgConstraint(NotNull(ArgNo(1))));
 
@@ -1604,7 +1801,8 @@
         Signature(ArgTypes{ConstCharPtrTy, IntTy, ConstCharPtrTy},
                   RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0)))
             .ArgConstraint(ArgumentCondition(1, WithinRange, Range(0, IntMax)))
             .ArgConstraint(NotNull(ArgNo(2))));
@@ -1613,7 +1811,8 @@
     addToFunctionSummaryMap(
         "lockf", Signature(ArgTypes{IntTy, IntTy, Off_tTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(
                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
 
@@ -1623,7 +1822,8 @@
     addToFunctionSummaryMap(
         "creat", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsFileDescriptor)
+            .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0))));
 
     // unsigned int sleep(unsigned int seconds);
@@ -1637,11 +1837,12 @@
     Optional<QualType> DirPtrTy = getPointerTy(DirTy);
 
     // int dirfd(DIR *dirp);
-    addToFunctionSummaryMap("dirfd",
-                            Signature(ArgTypes{DirPtrTy}, RetType{IntTy}),
-                            Summary(NoEvalCall)
-                                .Case(ReturnsFileDescriptor)
-                                .ArgConstraint(NotNull(ArgNo(0))));
+    addToFunctionSummaryMap(
+        "dirfd", Signature(ArgTypes{DirPtrTy}, RetType{IntTy}),
+        Summary(NoEvalCall)
+            .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
+            .ArgConstraint(NotNull(ArgNo(0))));
 
     // unsigned int alarm(unsigned int seconds);
     addToFunctionSummaryMap(
@@ -1654,7 +1855,8 @@
     addToFunctionSummaryMap("closedir",
                             Signature(ArgTypes{DirPtrTy}, RetType{IntTy}),
                             Summary(NoEvalCall)
-                                .Case(ReturnsZeroOrMinusOne)
+                                .Case(ReturnsZero, ErrnoMustNotBeChecked)
+                                .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
                                 .ArgConstraint(NotNull(ArgNo(0))));
 
     // char *strdup(const char *s);
@@ -1677,18 +1879,21 @@
         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
 
     // int mkstemp(char *template);
-    addToFunctionSummaryMap("mkstemp",
-                            Signature(ArgTypes{CharPtrTy}, RetType{IntTy}),
-                            Summary(NoEvalCall)
-                                .Case(ReturnsFileDescriptor)
-                                .ArgConstraint(NotNull(ArgNo(0))));
+    addToFunctionSummaryMap(
+        "mkstemp", Signature(ArgTypes{CharPtrTy}, RetType{IntTy}),
+        Summary(NoEvalCall)
+            .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
+            .ArgConstraint(NotNull(ArgNo(0))));
 
     // char *mkdtemp(char *template);
+    // FIXME: Improve for errno modeling.
     addToFunctionSummaryMap(
         "mkdtemp", Signature(ArgTypes{CharPtrTy}, RetType{CharPtrTy}),
         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
 
     // char *getcwd(char *buf, size_t size);
+    // FIXME: Improve for errno modeling.
     addToFunctionSummaryMap(
         "getcwd", Signature(ArgTypes{CharPtrTy, SizeTy}, RetType{CharPtrTy}),
         Summary(NoEvalCall)
@@ -1696,44 +1901,53 @@
                 ArgumentCondition(1, WithinRange, Range(0, SizeMax))));
 
     // int mkdir(const char *pathname, mode_t mode);
+    // FIXME: returns 0 on success, ReturnsValidFileDescriptor is incorrect
     addToFunctionSummaryMap(
         "mkdir", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0))));
 
     // int mkdirat(int dirfd, const char *pathname, mode_t mode);
+    // FIXME: returns 0 on success, ReturnsValidFileDescriptor is incorrect
     addToFunctionSummaryMap(
         "mkdirat",
         Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(1))));
 
     Optional<QualType> Dev_tTy = lookupTy("dev_t");
 
     // int mknod(const char *pathname, mode_t mode, dev_t dev);
+    // FIXME: returns 0 on success, ReturnsValidFileDescriptor is incorrect
     addToFunctionSummaryMap(
         "mknod",
         Signature(ArgTypes{ConstCharPtrTy, Mode_tTy, Dev_tTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0))));
 
     // int mknodat(int dirfd, const char *pathname, mode_t mode, dev_t dev);
+    // FIXME: returns 0 on success, ReturnsValidFileDescriptor is incorrect
     addToFunctionSummaryMap(
         "mknodat",
         Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy, Dev_tTy},
                   RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(1))));
 
     // int chmod(const char *path, mode_t mode);
     addToFunctionSummaryMap(
         "chmod", Signature(ArgTypes{ConstCharPtrTy, Mode_tTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0))));
 
     // int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags);
@@ -1742,7 +1956,8 @@
         Signature(ArgTypes{IntTy, ConstCharPtrTy, Mode_tTy, IntTy},
                   RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
             .ArgConstraint(NotNull(ArgNo(1))));
 
@@ -1750,7 +1965,8 @@
     addToFunctionSummaryMap(
         "fchmod", Signature(ArgTypes{IntTy, Mode_tTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(
                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
 
@@ -1764,7 +1980,8 @@
         Signature(ArgTypes{IntTy, ConstCharPtrTy, Uid_tTy, Gid_tTy, IntTy},
                   RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
             .ArgConstraint(NotNull(ArgNo(1))));
 
@@ -1773,7 +1990,8 @@
         "chown",
         Signature(ArgTypes{ConstCharPtrTy, Uid_tTy, Gid_tTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0))));
 
     // int lchown(const char *path, uid_t owner, gid_t group);
@@ -1781,14 +1999,16 @@
         "lchown",
         Signature(ArgTypes{ConstCharPtrTy, Uid_tTy, Gid_tTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0))));
 
     // int fchown(int fildes, uid_t owner, gid_t group);
     addToFunctionSummaryMap(
         "fchown", Signature(ArgTypes{IntTy, Uid_tTy, Gid_tTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(
                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
 
@@ -1796,14 +2016,16 @@
     addToFunctionSummaryMap("rmdir",
                             Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}),
                             Summary(NoEvalCall)
-                                .Case(ReturnsZeroOrMinusOne)
+                                .Case(ReturnsZero, ErrnoMustNotBeChecked)
+                                .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
                                 .ArgConstraint(NotNull(ArgNo(0))));
 
     // int chdir(const char *path);
     addToFunctionSummaryMap("chdir",
                             Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}),
                             Summary(NoEvalCall)
-                                .Case(ReturnsZeroOrMinusOne)
+                                .Case(ReturnsZero, ErrnoMustNotBeChecked)
+                                .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
                                 .ArgConstraint(NotNull(ArgNo(0))));
 
     // int link(const char *oldpath, const char *newpath);
@@ -1811,7 +2033,8 @@
         "link",
         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0)))
             .ArgConstraint(NotNull(ArgNo(1))));
 
@@ -1822,7 +2045,8 @@
         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, ConstCharPtrTy, IntTy},
                   RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
             .ArgConstraint(NotNull(ArgNo(1)))
             .ArgConstraint(ArgumentCondition(2, WithinRange, Range(0, IntMax)))
@@ -1832,7 +2056,8 @@
     addToFunctionSummaryMap("unlink",
                             Signature(ArgTypes{ConstCharPtrTy}, RetType{IntTy}),
                             Summary(NoEvalCall)
-                                .Case(ReturnsZeroOrMinusOne)
+                                .Case(ReturnsZero, ErrnoMustNotBeChecked)
+                                .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
                                 .ArgConstraint(NotNull(ArgNo(0))));
 
     // int unlinkat(int fd, const char *path, int flag);
@@ -1840,7 +2065,8 @@
         "unlinkat",
         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
             .ArgConstraint(NotNull(ArgNo(1))));
 
@@ -1852,7 +2078,8 @@
     addToFunctionSummaryMap(
         "fstat", Signature(ArgTypes{IntTy, StructStatPtrTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
             .ArgConstraint(NotNull(ArgNo(1))));
 
@@ -1862,7 +2089,8 @@
         Signature(ArgTypes{ConstCharPtrRestrictTy, StructStatPtrRestrictTy},
                   RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0)))
             .ArgConstraint(NotNull(ArgNo(1))));
 
@@ -1872,7 +2100,8 @@
         Signature(ArgTypes{ConstCharPtrRestrictTy, StructStatPtrRestrictTy},
                   RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0)))
             .ArgConstraint(NotNull(ArgNo(1))));
 
@@ -1884,17 +2113,20 @@
                            StructStatPtrRestrictTy, IntTy},
                   RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
             .ArgConstraint(NotNull(ArgNo(1)))
             .ArgConstraint(NotNull(ArgNo(2))));
 
     // DIR *opendir(const char *name);
+    // FIXME: Improve for errno modeling.
     addToFunctionSummaryMap(
         "opendir", Signature(ArgTypes{ConstCharPtrTy}, RetType{DirPtrTy}),
         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
 
     // DIR *fdopendir(int fd);
+    // FIXME: Improve for errno modeling.
     addToFunctionSummaryMap("fdopendir",
                             Signature(ArgTypes{IntTy}, RetType{DirPtrTy}),
                             Summary(NoEvalCall)
@@ -1905,11 +2137,13 @@
     addToFunctionSummaryMap(
         "isatty", Signature(ArgTypes{IntTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case({ReturnValueCondition(WithinRange, Range(0, 1))})
+            .Case({ReturnValueCondition(WithinRange, Range(0, 1))},
+                  ErrnoIrrelevant)
             .ArgConstraint(
                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
 
     // FILE *popen(const char *command, const char *type);
+    // FIXME: Improve for errno modeling.
     addToFunctionSummaryMap(
         "popen",
         Signature(ArgTypes{ConstCharPtrTy, ConstCharPtrTy}, RetType{FilePtrTy}),
@@ -1918,6 +2152,7 @@
             .ArgConstraint(NotNull(ArgNo(1))));
 
     // int pclose(FILE *stream);
+    // FIXME: Improve for errno modeling.
     addToFunctionSummaryMap(
         "pclose", Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
@@ -1925,7 +2160,8 @@
     // int close(int fildes);
     addToFunctionSummaryMap("close", Signature(ArgTypes{IntTy}, RetType{IntTy}),
                             Summary(NoEvalCall)
-                                .Case(ReturnsZeroOrMinusOne)
+                                .Case(ReturnsZero, ErrnoMustNotBeChecked)
+                                .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
                                 .ArgConstraint(ArgumentCondition(
                                     0, WithinRange, Range(-1, IntMax))));
 
@@ -1942,6 +2178,7 @@
         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
 
     // FILE *fdopen(int fd, const char *mode);
+    // FIXME: Improve for errno modeling.
     addToFunctionSummaryMap(
         "fdopen",
         Signature(ArgTypes{IntTy, ConstCharPtrTy}, RetType{FilePtrTy}),
@@ -1965,18 +2202,19 @@
         Summary(NoEvalCall).ArgConstraint(NotNull(ArgNo(0))));
 
     // int fileno(FILE *stream);
-    addToFunctionSummaryMap("fileno",
-                            Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
-                            Summary(NoEvalCall)
-                                .Case(ReturnsFileDescriptor)
-                                .ArgConstraint(NotNull(ArgNo(0))));
+    addToFunctionSummaryMap(
+        "fileno", Signature(ArgTypes{FilePtrTy}, RetType{IntTy}),
+        Summary(NoEvalCall)
+            .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
+            .ArgConstraint(NotNull(ArgNo(0))));
 
     // int fseeko(FILE *stream, off_t offset, int whence);
     addToFunctionSummaryMap(
         "fseeko",
         Signature(ArgTypes{FilePtrTy, Off_tTy, IntTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZeroOrMinusOne, ErrnoIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0))));
 
     // off_t ftello(FILE *stream);
@@ -1986,6 +2224,7 @@
 
     // void *mmap(void *addr, size_t length, int prot, int flags, int fd,
     // off_t offset);
+    // FIXME: Improve for errno modeling.
     addToFunctionSummaryMap(
         "mmap",
         Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off_tTy},
@@ -1998,6 +2237,7 @@
     Optional<QualType> Off64_tTy = lookupTy("off64_t");
     // void *mmap64(void *addr, size_t length, int prot, int flags, int fd,
     // off64_t offset);
+    // FIXME: Improve for errno modeling.
     addToFunctionSummaryMap(
         "mmap64",
         Signature(ArgTypes{VoidPtrTy, SizeTy, IntTy, IntTy, IntTy, Off64_tTy},
@@ -2011,13 +2251,20 @@
     addToFunctionSummaryMap("pipe",
                             Signature(ArgTypes{IntPtrTy}, RetType{IntTy}),
                             Summary(NoEvalCall)
-                                .Case(ReturnsZeroOrMinusOne)
+                                .Case(ReturnsZero, ErrnoMustNotBeChecked)
+                                .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
                                 .ArgConstraint(NotNull(ArgNo(0))));
 
     // off_t lseek(int fildes, off_t offset, int whence);
+    // In the first case we can not tell for sure if it failed or not.
+    // A return value different from of the expected offset (that is unknown
+    // here) may indicate failure. For this reason we do not enforce the errno
+    // check (can cause false positive).
     addToFunctionSummaryMap(
         "lseek", Signature(ArgTypes{IntTy, Off_tTy, IntTy}, RetType{Off_tTy}),
         Summary(NoEvalCall)
+            .Case(ReturnsNonnegative, ErrnoIrrelevant)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(
                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
 
@@ -2029,7 +2276,9 @@
                   RetType{Ssize_tTy}),
         Summary(NoEvalCall)
             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
-                   ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
+                   ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
+                  ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0)))
             .ArgConstraint(NotNull(ArgNo(1)))
             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
@@ -2046,7 +2295,9 @@
             RetType{Ssize_tTy}),
         Summary(NoEvalCall)
             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(3)),
-                   ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
+                   ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
+                  ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
             .ArgConstraint(NotNull(ArgNo(1)))
             .ArgConstraint(NotNull(ArgNo(2)))
@@ -2062,12 +2313,14 @@
         Signature(ArgTypes{IntTy, ConstCharPtrTy, IntTy, ConstCharPtrTy},
                   RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(1)))
             .ArgConstraint(NotNull(ArgNo(3))));
 
     // char *realpath(const char *restrict file_name,
     //                char *restrict resolved_name);
+    // FIXME: Improve for errno modeling.
     addToFunctionSummaryMap(
         "realpath",
         Signature(ArgTypes{ConstCharPtrRestrictTy, CharPtrRestrictTy},
@@ -2081,7 +2334,8 @@
         "execv",
         Signature(ArgTypes{ConstCharPtrTy, CharPtrConstPtr}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case({ReturnValueCondition(WithinRange, SingleValue(-1))})
+            .Case({ReturnValueCondition(WithinRange, SingleValue(-1))},
+                  ErrnoIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0))));
 
     // int execvp(const char *file, char *const argv[]);
@@ -2089,7 +2343,8 @@
         "execvp",
         Signature(ArgTypes{ConstCharPtrTy, CharPtrConstPtr}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case({ReturnValueCondition(WithinRange, SingleValue(-1))})
+            .Case({ReturnValueCondition(WithinRange, SingleValue(-1))},
+                  ErrnoIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0))));
 
     // int getopt(int argc, char * const argv[], const char *optstring);
@@ -2098,7 +2353,8 @@
         Signature(ArgTypes{IntTy, CharPtrConstPtr, ConstCharPtrTy},
                   RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case({ReturnValueCondition(WithinRange, Range(-1, UCharRangeMax))})
+            .Case({ReturnValueCondition(WithinRange, Range(-1, UCharRangeMax))},
+                  ErrnoIrrelevant)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
             .ArgConstraint(NotNull(ArgNo(1)))
             .ArgConstraint(NotNull(ArgNo(2))));
@@ -2124,7 +2380,8 @@
     // constraints which require pointer types for the sockaddr param.
     auto Accept =
         Summary(NoEvalCall)
-            .Case(ReturnsFileDescriptor)
+            .Case(ReturnsValidFileDescriptor, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)));
     if (!addToFunctionSummaryMap(
             "accept",
@@ -2147,7 +2404,8 @@
             Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy},
                       RetType{IntTy}),
             Summary(NoEvalCall)
-                .Case(ReturnsZeroOrMinusOne)
+                .Case(ReturnsZero, ErrnoMustNotBeChecked)
+                .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
                 .ArgConstraint(
                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
                 .ArgConstraint(NotNull(ArgNo(1)))
@@ -2160,7 +2418,8 @@
           "bind",
           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}),
           Summary(NoEvalCall)
-              .Case(ReturnsZeroOrMinusOne)
+              .Case(ReturnsZero, ErrnoMustNotBeChecked)
+              .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
               .ArgConstraint(
                   ArgumentCondition(0, WithinRange, Range(0, IntMax)))
               .ArgConstraint(
@@ -2174,7 +2433,8 @@
                                Socklen_tPtrRestrictTy},
                       RetType{IntTy}),
             Summary(NoEvalCall)
-                .Case(ReturnsZeroOrMinusOne)
+                .Case(ReturnsZero, ErrnoMustNotBeChecked)
+                .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
                 .ArgConstraint(
                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
                 .ArgConstraint(NotNull(ArgNo(1)))
@@ -2184,7 +2444,8 @@
           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
                     RetType{IntTy}),
           Summary(NoEvalCall)
-              .Case(ReturnsZeroOrMinusOne)
+              .Case(ReturnsZero, ErrnoMustNotBeChecked)
+              .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
               .ArgConstraint(
                   ArgumentCondition(0, WithinRange, Range(0, IntMax))));
 
@@ -2196,7 +2457,8 @@
                                Socklen_tPtrRestrictTy},
                       RetType{IntTy}),
             Summary(NoEvalCall)
-                .Case(ReturnsZeroOrMinusOne)
+                .Case(ReturnsZero, ErrnoMustNotBeChecked)
+                .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
                 .ArgConstraint(
                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
                 .ArgConstraint(NotNull(ArgNo(1)))
@@ -2206,7 +2468,8 @@
           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tPtrRestrictTy},
                     RetType{IntTy}),
           Summary(NoEvalCall)
-              .Case(ReturnsZeroOrMinusOne)
+              .Case(ReturnsZero, ErrnoMustNotBeChecked)
+              .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
               .ArgConstraint(
                   ArgumentCondition(0, WithinRange, Range(0, IntMax))));
 
@@ -2217,7 +2480,8 @@
             Signature(ArgTypes{IntTy, ConstStructSockaddrPtrTy, Socklen_tTy},
                       RetType{IntTy}),
             Summary(NoEvalCall)
-                .Case(ReturnsZeroOrMinusOne)
+                .Case(ReturnsZero, ErrnoMustNotBeChecked)
+                .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
                 .ArgConstraint(
                     ArgumentCondition(0, WithinRange, Range(0, IntMax)))
                 .ArgConstraint(NotNull(ArgNo(1)))))
@@ -2225,14 +2489,17 @@
           "connect",
           Signature(ArgTypes{IntTy, Irrelevant, Socklen_tTy}, RetType{IntTy}),
           Summary(NoEvalCall)
-              .Case(ReturnsZeroOrMinusOne)
+              .Case(ReturnsZero, ErrnoMustNotBeChecked)
+              .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
               .ArgConstraint(
                   ArgumentCondition(0, WithinRange, Range(0, IntMax))));
 
     auto Recvfrom =
         Summary(NoEvalCall)
             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
-                   ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
+                   ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
+                  ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
                                       /*BufSize=*/ArgNo(2)));
@@ -2257,7 +2524,9 @@
     auto Sendto =
         Summary(NoEvalCall)
             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
-                   ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
+                   ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
+                  ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
                                       /*BufSize=*/ArgNo(2)));
@@ -2281,7 +2550,8 @@
     addToFunctionSummaryMap("listen",
                             Signature(ArgTypes{IntTy, IntTy}, RetType{IntTy}),
                             Summary(NoEvalCall)
-                                .Case(ReturnsZeroOrMinusOne)
+                                .Case(ReturnsZero, ErrnoMustNotBeChecked)
+                                .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
                                 .ArgConstraint(ArgumentCondition(
                                     0, WithinRange, Range(0, IntMax))));
 
@@ -2292,7 +2562,9 @@
                   RetType{Ssize_tTy}),
         Summary(NoEvalCall)
             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
-                   ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
+                   ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
+                  ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
                                       /*BufSize=*/ArgNo(2))));
@@ -2308,7 +2580,9 @@
         Signature(ArgTypes{IntTy, StructMsghdrPtrTy, IntTy},
                   RetType{Ssize_tTy}),
         Summary(NoEvalCall)
-            .Case({ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
+            .Case({ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
+                  ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(
                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
 
@@ -2318,7 +2592,9 @@
         Signature(ArgTypes{IntTy, ConstStructMsghdrPtrTy, IntTy},
                   RetType{Ssize_tTy}),
         Summary(NoEvalCall)
-            .Case({ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
+            .Case({ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
+                  ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(
                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
 
@@ -2329,7 +2605,8 @@
         Signature(ArgTypes{IntTy, IntTy, IntTy, ConstVoidPtrTy, Socklen_tTy},
                   RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(3)))
             .ArgConstraint(
                 BufferSize(/*Buffer=*/ArgNo(3), /*BufSize=*/ArgNo(4)))
@@ -2345,7 +2622,8 @@
                            Socklen_tPtrRestrictTy},
                   RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(3)))
             .ArgConstraint(NotNull(ArgNo(4))));
 
@@ -2356,7 +2634,9 @@
                   RetType{Ssize_tTy}),
         Summary(NoEvalCall)
             .Case({ReturnValueCondition(LessThanOrEq, ArgNo(2)),
-                   ReturnValueCondition(WithinRange, Range(-1, Ssize_tMax))})
+                   ReturnValueCondition(WithinRange, Range(0, Ssize_tMax))},
+                  ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(ArgumentCondition(0, WithinRange, Range(0, IntMax)))
             .ArgConstraint(BufferSize(/*Buffer=*/ArgNo(1),
                                       /*BufSize=*/ArgNo(2))));
@@ -2366,7 +2646,8 @@
         "socketpair",
         Signature(ArgTypes{IntTy, IntTy, IntTy, IntPtrTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(3))));
 
     // int getnameinfo(const struct sockaddr *restrict sa, socklen_t salen,
@@ -2404,7 +2685,8 @@
         "utime",
         Signature(ArgTypes{ConstCharPtrTy, StructUtimbufPtrTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0))));
 
     Optional<QualType> StructTimespecTy = lookupTy("timespec");
@@ -2417,7 +2699,8 @@
         "futimens",
         Signature(ArgTypes{IntTy, ConstStructTimespecPtrTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(
                 ArgumentCondition(0, WithinRange, Range(0, IntMax))));
 
@@ -2428,7 +2711,8 @@
                                                ConstStructTimespecPtrTy, IntTy},
                                       RetType{IntTy}),
                             Summary(NoEvalCall)
-                                .Case(ReturnsZeroOrMinusOne)
+                                .Case(ReturnsZero, ErrnoMustNotBeChecked)
+                                .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
                                 .ArgConstraint(NotNull(ArgNo(1))));
 
     Optional<QualType> StructTimevalTy = lookupTy("timeval");
@@ -2441,7 +2725,8 @@
         Signature(ArgTypes{ConstCharPtrTy, ConstStructTimevalPtrTy},
                   RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0))));
 
     // int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
@@ -2450,7 +2735,8 @@
         Signature(ArgTypes{ConstStructTimespecPtrTy, StructTimespecPtrTy},
                   RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(0))));
 
     Optional<QualType> Time_tTy = lookupTy("time_t");
@@ -2526,7 +2812,8 @@
         "clock_gettime",
         Signature(ArgTypes{Clockid_tTy, StructTimespecPtrTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(1))));
 
     Optional<QualType> StructItimervalTy = lookupTy("itimerval");
@@ -2537,7 +2824,8 @@
         "getitimer",
         Signature(ArgTypes{IntTy, StructItimervalPtrTy}, RetType{IntTy}),
         Summary(NoEvalCall)
-            .Case(ReturnsZeroOrMinusOne)
+            .Case(ReturnsZero, ErrnoMustNotBeChecked)
+            .Case(ReturnsMinusOne, ErrnoNEZeroIrrelevant)
             .ArgConstraint(NotNull(ArgNo(1))));
 
     Optional<QualType> Pthread_cond_tTy = lookupTy("pthread_cond_t");
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to