cvs: php-gcov-web /clang-checker README TODO patch.txt /clang-checker/tests Zpp.c num_args.c uninit.c uninit2.c

[email protected] ("Nuno Lopes")
Newsgroups php.webmaster
Message-ID <cvsnlopess1227715892@cvsserver>
nlopess		Wed Nov 26 16:11:32 2008 UTC

  Added files:                 
    /php-gcov-web/clang-checker	README TODO patch.txt 
    /php-gcov-web/clang-checker/tests	Zpp.c num_args.c uninit.c 
                                     	uninit2.c 
  Log:
  add new clang checker by Arnaud Le Blanc
nlopess-20081126161132.txt (text/plain, 20.3 KB)
http://cvs.php.net/viewvc.cgi/php-gcov-web/clang-checker/patch.txt?view=markup&rev=1.1
Index: php-gcov-web/clang-checker/patch.txt
+++ php-gcov-web/clang-checker/patch.txt
Index: include/clang/Basic/DiagnosticKinds.def
===================================================================
--- include/clang/Basic/DiagnosticKinds.def	(revision 60102)
+++ include/clang/Basic/DiagnosticKinds.def	(working copy)
@@ -1541,4 +1541,17 @@
 DIAG(err_object_size_invalid_argument, ERROR,
      "argument to __builtin_object_size must be a constant integer")
 
+
+// PHP
+DIAG(warn_zpp_duplicated_specifier, WARNING,
+    "duplicated specifier '%0'")
+
+DIAG(warn_zpp_non_preceded_specifier, WARNING,
+    "'%0' specifier must be preceded")
+
+DIAG(warn_zpp_invalid_specifier, WARNING,
+    "specifier '%0' cannot be applied to '%1'")
+
+
+
 #undef DIAG
Index: lib/Analysis/GRSimpleVals.h
===================================================================
--- lib/Analysis/GRSimpleVals.h	(revision 60102)
+++ lib/Analysis/GRSimpleVals.h	(working copy)
@@ -75,6 +75,8 @@
   static void GeneratePathDiagnostic(PathDiagnostic& PD, ASTContext& Ctx,
                                      ExplodedNode<GRState>* N);
   
+  const GRState* InvalidateArg(GRStateManager& StateMgr, const GRState* St, Expr* CE);
+
 protected:
   
   // Equality operators for Locs.
Index: lib/Analysis/GRSimpleVals.cpp
===================================================================
--- lib/Analysis/GRSimpleVals.cpp	(revision 60102)
+++ lib/Analysis/GRSimpleVals.cpp	(working copy)
@@ -385,6 +385,19 @@
 // Transfer function for function calls.
 //===----------------------------------------------------------------------===//
 
+const GRState* GRSimpleVals::InvalidateArg(GRStateManager& StateMgr, const GRState* St, Expr* CE) {
+
+    SVal V = StateMgr.GetSVal(St, CE);
+
+    if (isa<loc::MemRegionVal>(V))
+      St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal());
+    else if (isa<nonloc::LocAsInteger>(V))
+      St = StateMgr.BindLoc(St, cast<nonloc::LocAsInteger>(V).getLoc(),
+                            UnknownVal());
+
+    return St;
+}
+
 void GRSimpleVals::EvalCall(ExplodedNodeSet<GRState>& Dst,
                             GRExprEngine& Eng,
                             GRStmtNodeBuilder<GRState>& Builder,
@@ -393,20 +406,91 @@
   
   GRStateManager& StateMgr = Eng.getStateManager();
   const GRState* St = Builder.GetState(Pred);
-  
-  // Invalidate all arguments passed in by reference (Locs).
+  CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
+  do {
+    DeclRefExpr *DRExpr = NULL;
+    FunctionDecl *FDecl = NULL;
+    IdentifierInfo *FInfo = NULL;
+    const char * name;
+    unsigned length;
+    unsigned format_idx = 0;
 
-  for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
-        I != E; ++I) {
+    if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(CE->getCallee()))
+     DRExpr = dyn_cast<DeclRefExpr>(IcExpr->getSubExpr());
+    else 
+     DRExpr = dyn_cast<DeclRefExpr>(CE->getCallee());
+    if (!DRExpr) break;
 
-    SVal V = StateMgr.GetSVal(St, *I);
-    
-    if (isa<loc::MemRegionVal>(V))
-      St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal());
-    else if (isa<nonloc::LocAsInteger>(V))
-      St = StateMgr.BindLoc(St, cast<nonloc::LocAsInteger>(V).getLoc(),
-                            UnknownVal());
-    
+    if (!(FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl())))
+      break;
+
+    if (!(FInfo = FDecl->getIdentifier()))
+      break;
+
+    name = FInfo->getName();
+    length = FInfo->getLength();
+
+    if (length == sizeof("zend_parse_parameters")-1 && memcmp("zend_parse_parameters", name, length) == 0) {
+            format_idx = 1;
+    } else if (length == sizeof("zend_parse_parameters_ex")-1 && memcmp("zend_parse_parameters_ex", name, length) == 0) {
+            format_idx = 2;
+    } else {
+      break;
+    }
+
+    Expr *OrigFormatExpr = CE->getArg(format_idx)->IgnoreParenCasts();
+    StringLiteral *FExpr = dyn_cast<StringLiteral>(OrigFormatExpr);
+    if (!FExpr)  // FIXME: support simple things like a ? "x" : "y"
+      break;
+
+    const char * const Str = FExpr->getStrData();
+    const unsigned StrLen = FExpr->getByteLength();
+    unsigned StrIdx = 0;
+
+    for (++I; I != E && format_idx-- > 0; ++I);
+
+    for (; StrIdx < StrLen; ++StrIdx)
+    {
+      switch(Str[StrIdx]) {
+        case 'f':
+        case 's':
+        case 'O':
+        case '+':
+        case '*':
+          St = InvalidateArg(StateMgr, St, *I);
+          ++I;
+          /* no break */
+        case 'a':
+        case 'b':
+        case 'C':
+        case 'd':
+        case 'h':
+        case 'l':
+        case 'o':
+        case 'r':
+        case 'z':
+        case 'Z':
+          St = InvalidateArg(StateMgr, St, *I);
+          ++I;
+          break;
+        case '/':
+        case '!':
+          break;
+        case '|': // start of optional vars
+          StrIdx = StrLen;
+          continue;
+        default:
+          assert(0);
+          return;
+      }
+    }
+    for (; I != E; ++I) {}
+  } while (0);
+
+  // Invalidate all remaining arguments passed in by reference (Locs).
+
+  for (; I != E; ++I) {
+    St = InvalidateArg(StateMgr, St, *I);
   }
   
   // Make up a symbol for the return value of this function.  
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp	(revision 60102)
+++ lib/Sema/SemaChecking.cpp	(working copy)
@@ -20,6 +20,7 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/Diagnostic.h"
 #include "SemaUtil.h"
+#include <map>
 using namespace clang;
 
 /// CheckFunctionCall - Check a direct function call for various correctness
@@ -108,6 +109,13 @@
     }
     
     CheckPrintfArguments(TheCall.get(), HasVAListArg, format_idx);       
+  } else if (i == id_zend_parse_parameters || i == id_zend_parse_parameters_ex) {
+    unsigned format_idx = 0;
+    switch(i) {
+    case id_zend_parse_parameters:     format_idx = 1; break;
+    case id_zend_parse_parameters_ex:  format_idx = 2; break;
+    }
+    CheckZendParseParametersArguments(TheCall.get(), format_idx);
   }
   
   return TheCall.take();
@@ -991,3 +999,169 @@
     Diag(loc, diag::warn_floatingpoint_eq)
       << lex->getSourceRange() << rex->getSourceRange();
 }
+
+/// Get a QualType by its name (e.g. "char***", "double")
+QualType Sema::GetType(const char * name) {
+  std::string FullName(name);
+  std::string Name = FullName.substr(0, FullName.find_first_of(" *"));
+  IdentifierTable &IT = PP.getIdentifierTable();
+  IdentifierInfo * II = &IT.get(Name);
+  QualType QT = BuiltinTypes[Name];
+  if (QT.isNull()) {
+    Decl * D = LookupDecl(II, Decl::IDNS_Ordinary, 0, false);
+    if (!D) {
+      return QT;
+    }
+    QT = Context.getTypeDeclType(cast<TypeDecl>(D));
+    if (QT.isNull()) {
+      return QT;
+    }
+  }
+  size_t pos = -1;
+  while ((pos = FullName.find('*', pos+1)) != std::string::npos) {
+    QT = Context.getPointerType(QT);
+  }
+  return QT;
+}
+
+void
+Sema::CheckZendParseParametersArguments(CallExpr *TheCall, unsigned format_idx) {
+  Expr *Fn = TheCall->getCallee();
+
+  // CHECK: function is called with no format string.
+  if (format_idx >= TheCall->getNumArgs()) {
+    Diag(TheCall->getRParenLoc(), diag::warn_printf_missing_format_string)
+      << Fn->getSourceRange();
+    return;
+  }
+
+  Expr *OrigFormatExpr = TheCall->getArg(format_idx)->IgnoreParenCasts();
+
+  // CHECK: format string is not a string literal.
+  StringLiteral *FExpr = dyn_cast<StringLiteral>(OrigFormatExpr);
+
+  if (FExpr == NULL) {
+    Diag(TheCall->getArg(format_idx)->getLocStart(), diag::warn_printf_not_string_constant)
+      << OrigFormatExpr->getSourceRange();
+    return;
+  }
+
+  // Str - The format string.  NOTE: this is NOT null-terminated!
+  const char * const Str = FExpr->getStrData();
+  const unsigned StrLen = FExpr->getByteLength();
+  unsigned StrIdx;
+
+  unsigned ArgIdx = format_idx+1;
+
+  unsigned Optional = 0;
+  unsigned VarArgs = 0;
+
+  std::string Specifiers("!/|&%");
+
+  std::map<char,std::string> SpecifierPreds;
+  SpecifierPreds['/'] = std::string("rz");
+  SpecifierPreds['!'] = std::string("aCfhoOrstzZ");
+
+  std::map<char, std::vector<QualType> > Formats;
+
+  Formats['a'].push_back(GetType("zval**"));
+  Formats['o'] = Formats['a'];
+  Formats['r'] = Formats['a'];
+  Formats['z'] = Formats['a'];
+  Formats['b'].push_back(GetType("zend_bool*"));
+  Formats['C'].push_back(GetType("zend_class_entry**"));
+  Formats['d'].push_back(GetType("double*"));
+  Formats['f'].push_back(GetType("zend_fcall_info*"));
+  Formats['f'].push_back(GetType("zend_fcall_info_cache*"));
+  Formats['h'].push_back(GetType("HashTable**"));
+  Formats['l'].push_back(GetType("long*"));
+  Formats['O'].push_back(GetType("zval**"));
+  Formats['O'].push_back(GetType("zend_class_entry*"));
+  Formats['s'].push_back(GetType("char**"));
+  Formats['s'].push_back(GetType("int*"));
+  Formats['Z'].push_back(GetType("zval***"));
+  // TODO check PHP version
+  Formats['+'].push_back(GetType("zval****"));
+  Formats['+'].push_back(GetType("int*"));
+  Formats['*'] = Formats['+'];
+
+  for(StrIdx = 0; StrIdx < StrLen; ++StrIdx) {
+    switch(Str[StrIdx]) {
+      case '\0':
+        Diag(PP.AdvanceToTokenCharacter(FExpr->getLocStart(), StrIdx+1), diag::warn_printf_format_string_contains_null_char)
+          << OrigFormatExpr->getSourceRange();
+        return;
+      // CHECK: specifiers
+      case '|':
+        if (Optional++) {
+          Diag(PP.AdvanceToTokenCharacter(FExpr->getLocStart(), StrIdx+1), diag::warn_zpp_duplicated_specifier)
+            << std::string(&Str[StrIdx], 1)
+            << FExpr->getSourceRange();
+        }
+        break;
+      case '/':
+      case '!':
+      {
+        unsigned tmpStrIdx = StrIdx;
+        while (tmpStrIdx-- > 0 && Specifiers.find(Str[tmpStrIdx]) != std::string::npos) {
+          if (Str[tmpStrIdx] == Str[StrIdx]) {
+            Diag(PP.AdvanceToTokenCharacter(FExpr->getLocStart(), StrIdx+1), diag::warn_zpp_duplicated_specifier)
+              << std::string(&Str[StrIdx], 1)
+              << FExpr->getSourceRange();
+          }
+        }
+        if (tmpStrIdx == (size_t)-1) {
+          Diag(PP.AdvanceToTokenCharacter(FExpr->getLocStart(), StrIdx+1), diag::warn_zpp_non_preceded_specifier)
+            << std::string(&Str[StrIdx], 1)
+            << FExpr->getSourceRange();
+          break;
+        }
+        if (SpecifierPreds[Str[StrIdx]].find(Str[tmpStrIdx]) == std::string::npos) {
+          Diag(PP.AdvanceToTokenCharacter(FExpr->getLocStart(), StrIdx+1), diag::warn_zpp_invalid_specifier)
+            << std::string(&Str[StrIdx], 1)
+            << std::string(&Str[tmpStrIdx], 1)
+            << FExpr->getSourceRange();
+        }
+        break;
+      }
+      case '+':
+      case '*':
+        if (VarArgs++) {
+          Diag(PP.AdvanceToTokenCharacter(FExpr->getLocStart(), StrIdx+1), diag::warn_zpp_duplicated_specifier)
+            << std::string(&Str[StrIdx], 1)
+            << FExpr->getSourceRange();
+        }
+        /* no break */
+      // CHECK: Argument type
+      default: {
+        std::map<char, std::vector<QualType> >::const_iterator FI = Formats.find(Str[StrIdx]);
+        if (FI == Formats.end()) {
+          Diag(PP.AdvanceToTokenCharacter(FExpr->getLocStart(), StrIdx+1), diag::warn_printf_invalid_conversion)
+            << std::string(&Str[StrIdx], 1)
+            << FExpr->getSourceRange();
+          return;
+        }
+        std::vector<QualType> Format = FI->second;
+        for(std::vector<QualType>::const_iterator it = Format.begin();
+            it < Format.end(); ++it)
+        {
+          if (ArgIdx >= TheCall->getNumArgs()) {
+            Diag(PP.AdvanceToTokenCharacter(FExpr->getLocStart(), StrIdx+1), diag::warn_printf_insufficient_data_args)
+              << FExpr->getSourceRange();
+            return;
+          }
+          QualType QT = *it;
+          assert(!QT.isNull());
+
+          Expr * Arg = TheCall->getArg(ArgIdx++);
+          AssignConvertType ConvTy = CheckAssignmentConstraints(Arg->getType(), QT);
+          DiagnoseAssignmentResult(ConvTy, Arg->getExprLoc(), QT, Arg->getType(), Arg, "passing");
+        }
+      }
+    }
+  }
+  if (ArgIdx < TheCall->getNumArgs()) {
+    Diag(TheCall->getArg(ArgIdx)->getExprLoc(), diag::warn_printf_too_many_data_args)
+      << TheCall->getArg(ArgIdx)->getSourceRange();
+  }
+}
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp	(revision 60102)
+++ lib/Sema/Sema.cpp	(working copy)
@@ -138,7 +138,15 @@
   KnownFunctionIDs[id_vsnprintf]     = &IT.get("vsnprintf");
   KnownFunctionIDs[id_vsnprintf_chk] = &IT.get("__builtin___vsnprintf_chk");
   KnownFunctionIDs[id_vprintf]       = &IT.get("vprintf");
+  KnownFunctionIDs[id_zend_parse_parameters]    = &IT.get("zend_parse_parameters");
+  KnownFunctionIDs[id_zend_parse_parameters_ex] = &IT.get("zend_parse_parameters_ex");
 
+  // BuiltinTypes lookup
+  BuiltinTypes["char"]   = Context.CharTy;
+  BuiltinTypes["int"]    = Context.IntTy;
+  BuiltinTypes["long"]   = Context.LongTy;
+  BuiltinTypes["double"] = Context.DoubleTy;
+
   StdNamespace = 0;
   TUScope = 0;
   if (getLangOptions().CPlusPlus)
Index: lib/Sema/Sema.h
===================================================================
--- lib/Sema/Sema.h	(revision 60102)
+++ lib/Sema/Sema.h	(working copy)
@@ -25,6 +25,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/OwningPtr.h"
 #include <vector>
+#include <map>
 
 namespace llvm {
   class APSInt;
@@ -185,6 +186,8 @@
     id_vsprintf,
     id_vsprintf_chk,
     id_vprintf,
+    id_zend_parse_parameters,
+    id_zend_parse_parameters_ex,
     id_num_known_functions
   };
   
@@ -223,6 +226,8 @@
   /// extremely uncommon (only 1% of selectors are "overloaded").
   llvm::DenseMap<Selector, ObjCMethodList> InstanceMethodPool;
   llvm::DenseMap<Selector, ObjCMethodList> FactoryMethodPool;
+
+  std::map<std::string, QualType> BuiltinTypes;
 public:
   Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer);
   
@@ -1360,6 +1365,9 @@
   bool SemaBuiltinObjectSize(CallExpr *TheCall); 
   void CheckPrintfArguments(CallExpr *TheCall,
                             bool HasVAListArg, unsigned format_idx);
+  QualType GetType(const char * type);
+  void CheckZendParseParametersArguments(CallExpr *TheCall, 
+                                         unsigned format_idx);
   void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
                             SourceLocation ReturnLoc);
   void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex);

http://cvs.php.net/viewvc.cgi/php-gcov-web/clang-checker/tests/Zpp.c?view=markup&rev=1.1
Index: php-gcov-web/clang-checker/tests/Zpp.c
+++ php-gcov-web/clang-checker/tests/Zpp.c
// RUN: clang -fsyntax-only -verify %s

int zend_parse_parameters(int num_args, char *type_spec, ...);
int zend_parse_parameters_ex(int flags, int num_args, char *type_spec, ...);

typedef struct _zval zval;
typedef unsigned char zend_bool;
typedef struct _zend_class_entry zend_class_entry;
typedef struct _zend_fcall_info zend_fcall_info;
typedef struct _zend_fcall_info_cache zend_fcall_info_cache;
typedef struct _HashTable HashTable;

#define FOO

void tests() {
  {
    zval *z;
    zend_bool b;
    zend_class_entry *zce;
    double d;
    zend_fcall_info *zfi;
    zend_fcall_info_cache *zfic;
    HashTable *ht;
    long l;
    char *c;
    int i;
    zval **zp;
    zval ***zpp;
    zend_parse_parameters(13, "abCdfh|loOr/sz!Z+",
        &z, &b, &zce, &d, zfi, zfic, &ht, &l,
        &z, &z, zce, &z, &c, &i, &z, &zp, &zpp, &i);
  }
  {
    zend_parse_parameters(0, "");
  }
  {
    int l;
    char *s;
    int s_len;
    char format[] = "sl";
    zend_parse_parameters(2, format, &s, &s_len, &l); // expected-warning {{format string is not a string literal (potentially insecure)}}
  }
  {
    int l;
    char *s;
    int s_len;
    zend_parse_parameters(2, "sl", &s, &s_len, &l); // expected-warning {{incompatible pointer types passing 'int *', expected 'long *'}}
  }
  {
    long l;
    char *s;
    long s_len;
    zend_parse_parameters(2, "sl", &s, &s_len, &l); // expected-warning {{incompatible pointer types passing 'long *', expected 'int *'}}
  }
  {
    zval *z;
    zend_parse_parameters(13, "Z", &z); // expected-warning {{incompatible pointer types passing 'zval **', expected 'zval ***'}}
  }
  {
    long l;
    zval **z;
    int i;
    zend_parse_parameters(2, "l*", &l, &z, &i); // expected-warning {{incompatible pointer types passing 'zval ***', expected 'zval ****'}}
  }
  {
    long l;
    zend_parse_parameters(1, "l", l); // expected-warning {{incompatible pointer to integer conversion passing 'long', expected 'long *'}}
  }
  {
#undef FOO
#define FOO l
    long l;
    zend_parse_parameters(1, "l", FOO); // expected-warning {{incompatible pointer to integer conversion passing 'long', expected 'long *'}}
  }
  {
    typedef long * foobar_t;
    foobar_t l;
    void * v;
    zend_parse_parameters(2, "ll", l, (foobar_t)v);
  }
  {
#undef FOO
#define FOO "l"
    long l;
    zend_parse_parameters(1, FOO, &l);
  }
  {
    long l;
    char *s;
    int s_len;
    zend_parse_parameters(2, "s\000l", &s, &s_len, &l); // expected-warning {{format string contains '\0' within the string body}}
  }
  {
#undef FOO
#define FOO "l\000l"
    long l;
    zend_parse_parameters(1, FOO, &l, &l); // expected-warning {{format string contains '\0' within the string body}}
  }
  {
    long l = 0;
    char *s = 0;
    int s_len = 0;
    zend_parse_parameters(2, "|l|s", &l, &s, &s_len); // expected-warning {{duplicated specifier '|'}}
  }
  {
    long l;
    zval ***z;
    int i;
    zend_parse_parameters(2, "l+*", &l, &z, &i, &z, &i); // expected-warning {{duplicated specifier '*'}}
  }
  {
    zval *z;
    zend_parse_parameters(2, "z//", &z); // expected-warning {{duplicated specifier '/'}}
  }
  {
    long l = 0;
    char *s = 0;
    int s_len = 0;
    zend_parse_parameters(2, "l|/s", &l, &s, &s_len); // expected-warning {{specifier '/' cannot be applied to 'l'}}
  }
  {
    long l = 0;
    char *s = 0;
    int s_len = 0;
    zend_parse_parameters(2, "l|!s", &l, &s, &s_len); // expected-warning {{specifier '!' cannot be applied to 'l'}}
  }
  {
    long l = 0;
    char *s = 0;
    int s_len = 0;
    zend_parse_parameters(2, "ls", &l, &s); // expected-warning {{more '%' conversions than data arguments}}
  }
  {
    long l = 0;
    zend_parse_parameters(2, "ll", &l); // expected-warning {{more '%' conversions than data arguments}}
  }
  {
    long l = 0;
    zend_parse_parameters(2, "A", &l); // expected-warning {{invalid conversion 'A'}}
  }
  {
    long l = 0;
    zend_parse_parameters(2, "l", &l, &l); // expected-warning {{more data arguments than '%' conversions}}
  }
}

http://cvs.php.net/viewvc.cgi/php-gcov-web/clang-checker/tests/num_args.c?view=markup&rev=1.1
Index: php-gcov-web/clang-checker/tests/num_args.c
+++ php-gcov-web/clang-checker/tests/num_args.c
// RUN: clang -checker-simple -verify %s
// XFAIL: ZEND_NUM_ARGS not checked yet

int zend_parse_parameters(int num_args, const char *type_spec, ...);
#define ZEND_NUM_ARGS() ht

void bar(char c);

void foo(int ht)
{
	char *str;
	int l;

	zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &str, &l);

	if (ZEND_NUM_ARGS() > 0) {
		bar(*str); // no-warning
	}

	bar(*str); // expected-warning {{Dereference of undefined value}}
}

http://cvs.php.net/viewvc.cgi/php-gcov-web/clang-checker/tests/uninit.c?view=markup&rev=1.1
Index: php-gcov-web/clang-checker/tests/uninit.c
+++ php-gcov-web/clang-checker/tests/uninit.c
// RUN: clang -checker-simple -verify %s

int zend_parse_parameters(int num_args, const char *type_spec, ...);
#define SUCCESS 0

void bar(int x);

void foo()
{
	long a, b;

	if (zend_parse_parameters(1, "l|l", &a, &b) != SUCCESS) {
		return;
	}

	bar(a); // no-warning
	bar(b); // expected-warning {{Pass-by-value argument in function is undefined}}
}

http://cvs.php.net/viewvc.cgi/php-gcov-web/clang-checker/tests/uninit2.c?view=markup&rev=1.1
Index: php-gcov-web/clang-checker/tests/uninit2.c
+++ php-gcov-web/clang-checker/tests/uninit2.c
// RUN: clang -checker-simple -verify %s
// XFAIL: return value not checked yet

int zend_parse_parameters(int num_args, const char *type_spec, ...);
#define SUCCESS 0

void bar(int x);

void foo2()
{
	long a, b;

	zend_parse_parameters(1, "l|l", &a, &b);

	bar(a); // expected-warning {{Pass-by-value argument in function is undefined}}
	bar(b); // expected-warning {{Pass-by-value argument in function is undefined}}
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.