useless-if-before-free: recognize more variants
authorJim Meyering <meyering@redhat.com>
Wed, 28 Jan 2009 08:19:28 +0000 (09:19 +0100)
committerJim Meyering <meyering@redhat.com>
Wed, 28 Jan 2009 08:19:28 +0000 (09:19 +0100)
* build-aux/useless-if-before-free: Also recognize e.g.,
if (NULL != p) free (p);

ChangeLog
build-aux/useless-if-before-free

index 3b3a0f0..3a3244e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2009-01-28  Jim Meyering  <meyering@redhat.com>
+
+       useless-if-before-free: recognize more variants
+       * build-aux/useless-if-before-free: Also recognize e.g.,
+       if (NULL != p) free (p);
+
 2009-01-27  Mark McLoughlin  <markmc@redhat.com>
 
        test-getaddrinfo: skip (don't fail) this test when there's no network
index 0bae2c4..a2fc773 100755 (executable)
@@ -1,14 +1,16 @@
 #!/usr/bin/perl -T
 # Detect instances of "if (p) free (p);".
 # Likewise for "if (p != NULL) free (p);".  And with braces.
+# Also detect "if (NULL != p) free (p);".
+# And with 0 or "(void *)0" in place of NULL.
 
-my $VERSION = '2008-05-25 17:36'; # UTC
+my $VERSION = '2009-01-28 08:16'; # UTC
 # The definition above must lie within the first 8 lines in order
 # for the Emacs time-stamp write hook (at end) to update it.
 # If you change this file with Emacs, please let the write hook
 # do its job.  Otherwise, update this string manually.
 
-# Copyright (C) 2008 Free Software Foundation, Inc.
+# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
 
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -60,7 +62,7 @@ detect free-like functions named FOO and BAR.
 OPTIONS:
 
    --list       print only the name of each matching FILE (\0-terminated)
-   --name=N     add name N to the list of `free'-like functions to detect;
+   --name=N     add name N to the list of \`free\'-like functions to detect;
                   may be repeated
 
    --help       display this help and exit
@@ -84,6 +86,14 @@ EOF
   exit $exit_code;
 }
 
+sub is_NULL ($)
+{
+  my ($expr) = @_;
+  return ($expr eq 'NULL'
+          || $expr eq '0'
+          || $expr =~ /^\(\s*(char|void)\s*\*\s*\)\s*0$/);
+}
+
 {
   sub EXIT_MATCH {0}
   sub EXIT_NO_MATCH {1}
@@ -122,21 +132,31 @@ EOF
       while (defined (my $line = <FH>))
         {
           while ($line =~
-              /\b(if\s*\(\s*([^)]+?)(?:\s*!=\s*NULL)?\s*\)
+              /\b(if\s*\(\s*([^)]+?)(?:\s*!=\s*([^)]+?))?\s*\)
+              #  1          2                  3
                (?:   \s*$regexp\s*\((?:\s*\([^)]+\))?\s*([^)]+)\)|
                 \s*\{\s*$regexp\s*\((?:\s*\([^)]+\))?\s*([^)]+)\)\s*;\s*\}))/sxg)
             {
-              # Compare "if" expression and free'd expression,
-              # without regard to white space.
-              (my $e1 = $2) =~ tr/ \t//d;
-              my $e2 = defined $3 ? $3 : $4;
+              my $all = $1;
+              my ($lhs, $rhs) = ($2, $3);
+              my ($free_opnd, $braced_free_opnd) = ($4, $5);
+              my $non_NULL;
+              if (!defined $rhs) { $non_NULL = $lhs }
+              elsif (is_NULL $rhs) { $non_NULL = $lhs }
+              elsif (is_NULL $lhs) { $non_NULL = $rhs }
+              else { next }
+
+              # Compare the non-NULL part of the "if" expression and the
+              # free'd expression, without regard to white space.
+              $non_NULL =~ tr/ \t//d;
+              my $e2 = defined $free_opnd ? $free_opnd : $braced_free_opnd;
               $e2 =~ tr/ \t//d;
-              if ($e1 eq $e2)
+              if ($non_NULL eq $e2)
                 {
                   $found_match = 1;
                   $list
                     and (print "$file\0"), next FILE;
-                  print "$file: $1\n";
+                  print "$file: $all\n";
                 }
             }
         }