|
1 #!/usr/bin/perl -w |
|
2 |
|
3 # Copyright (C) 2008 Apple Inc. All rights reserved. |
|
4 # |
|
5 # Redistribution and use in source and binary forms, with or without |
|
6 # modification, are permitted provided that the following conditions |
|
7 # are met: |
|
8 # |
|
9 # 1. Redistributions of source code must retain the above copyright |
|
10 # notice, this list of conditions and the following disclaimer. |
|
11 # 2. Redistributions in binary form must reproduce the above copyright |
|
12 # notice, this list of conditions and the following disclaimer in the |
|
13 # documentation and/or other materials provided with the distribution. |
|
14 # 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
|
15 # its contributors may be used to endorse or promote products derived |
|
16 # from this software without specific prior written permission. |
|
17 # |
|
18 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
|
19 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
20 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|
21 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
|
22 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|
23 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
24 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
25 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
|
27 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
28 |
|
29 # |
|
30 # This script attempts to find instances of a problem where the signatures |
|
31 # of virtual methods fail to match because one is defined 'const', and another |
|
32 # is not. For example: |
|
33 # virtual void Base::doStuff() const; |
|
34 # virtual void Derived::doStuff(); |
|
35 # |
|
36 # The lack of 'const' on the derived class gives it a different signature, and |
|
37 # it will therefore not be called when doStuff() is called on a derived object |
|
38 # via a base class pointer. |
|
39 # |
|
40 # Limitations of this script: |
|
41 # * It only works on things in the WebCore namespace |
|
42 # * Not all templatized methods may be found correctly |
|
43 # * It doesn't know anything about inheritance, or if methods are actually virtual |
|
44 # * It has lots of false positives (should add a whitelist for known-good signatures, |
|
45 # and specific methods) |
|
46 # * It's rather slow |
|
47 # |
|
48 # Added by Simon Fraser <simon.fraser@apple.com> |
|
49 # |
|
50 # Run the script like this: |
|
51 # WebKitTools/Scripts/detect-mismatched-virtual-const WebKitBuild/Debug/WebCore.framework/WebCore |
|
52 # |
|
53 # Output consists of a series of warnings like this: |
|
54 # |
|
55 # Both const and non-const versions of bgColor(): |
|
56 # HTMLDocument::bgColor() |
|
57 # HTMLBodyElement::bgColor() const |
|
58 # HTMLTableElement::bgColor() const |
|
59 # HTMLTableRowElement::bgColor() const |
|
60 # HTMLTableCellElement::bgColor() const |
|
61 # |
|
62 |
|
63 use strict; |
|
64 no warnings qw /syntax/; |
|
65 |
|
66 |
|
67 my $file = $ARGV[0]; |
|
68 |
|
69 print "Looking for unmatched const methods in $file\n"; |
|
70 |
|
71 if (!open NM, "(nm '$file' | c++filt | sed 's/^/STDOUT:/') 2>&1 |") { |
|
72 die "Could not open $file\n"; |
|
73 } |
|
74 |
|
75 my $nestedParens; |
|
76 $nestedParens = qr / |
|
77 [(] |
|
78 [^()]* |
|
79 (?: |
|
80 (??{ $nestedParens }) |
|
81 [^()]* |
|
82 )* |
|
83 [)]/x; |
|
84 |
|
85 my $nestedAngleBrackets; |
|
86 $nestedAngleBrackets = qr / |
|
87 [<] |
|
88 [^<>]* |
|
89 (?: |
|
90 (??{ $nestedAngleBrackets }) |
|
91 [^<>]* |
|
92 )* |
|
93 [>]/x; |
|
94 |
|
95 my $bal; |
|
96 $bal = qr /([^:]+ |
|
97 (??{ $nestedAngleBrackets })? |
|
98 (??{ $nestedParens })) |
|
99 ([^()]*)$/x; |
|
100 |
|
101 my %signature_map = (); |
|
102 |
|
103 while (<NM>) { |
|
104 my $line = $_; |
|
105 chomp($line); |
|
106 if ($line =~ m/ [tT] WebCore::(.+)$/) { |
|
107 my $method = $1; |
|
108 |
|
109 if ($method =~ /$bal/) { |
|
110 my $signature = $1; |
|
111 my $const = $2 eq " const"; |
|
112 |
|
113 my $class = substr($method, 0, length($method) - length($signature) - ($const ? 6 : 0)); |
|
114 |
|
115 # print "line: $line\nclass: $class\nmethod: $method\nsignature: $signature\nconst: $const\n\n"; |
|
116 |
|
117 my %method_info = ( |
|
118 'class' => $class, |
|
119 'const' => $const, |
|
120 'method' => $method, |
|
121 ); |
|
122 |
|
123 push @{$signature_map{$signature}}, \%method_info; |
|
124 } else { |
|
125 print "unmatched line $method\n\n" |
|
126 } |
|
127 } |
|
128 } |
|
129 close NM; |
|
130 |
|
131 my $sig; |
|
132 for $sig (keys %signature_map) { |
|
133 #print "\n$sig\n"; |
|
134 |
|
135 my @entries = @{$signature_map{$sig}}; |
|
136 # print "$#entries\n"; |
|
137 |
|
138 my $num_const = 0; |
|
139 my $num_not_const = 0; |
|
140 my $i; |
|
141 for $i (0 .. $#entries) { |
|
142 my $entry = @entries[$i]; |
|
143 |
|
144 my $class = $entry->{'class'}; |
|
145 my $const = $entry->{'const'}; |
|
146 |
|
147 if ($const) { |
|
148 $num_const++; |
|
149 } else { |
|
150 $num_not_const++; |
|
151 } |
|
152 } |
|
153 |
|
154 if ($#entries > 1 && $num_const > 0 && $num_not_const > 0) { |
|
155 print "Both const and non-const versions of $sig:\n"; |
|
156 |
|
157 for $i (0 .. $#entries) { |
|
158 my $entry = @entries[$i]; |
|
159 my $method = $entry->{'method'}; |
|
160 print "\t$method\n"; |
|
161 } |
|
162 |
|
163 } |
|
164 } |
|
165 |
|
166 |
|
167 |