of using mygcc
The first example concerns a simple check involving only syntax matching. Consider the following simple C++ program ex2.C:
#include <iostream> int main() { int i, *p; i = 0; p = new int; if(!p) { std::cout << "failed to malloc p" << std::endl; /* should return here! */ } *p = i; /* should delete p here! */ return 0; }
To find all the assignment statements in this program, use g++ with the --tree-check option, and maybe the –tree-checks-verbose option as well to get more detail:
[nic@paco mygcc]$ mygcc/1.0.0/bin/g++ --tree-check="%X=%Y" --tree-checks-verbose ex/ex2.C ex/ex2.C: In function ‘int main()’: ex/ex2.C:6: warning: user-defined warning %X=%Y: . ex/ex2.C:6: instance = {X <- i, Y <- 0}, ex/ex2.C:6: reached: i = 0. ex/ex2.C:7: warning: user-defined warning %X=%Y: . ex/ex2.C:7: instance = {X <- p, Y <- (int *) D.27487}, ex/ex2.C:7: reached: p = (int *) D.27487. ex/ex2.C:12: warning: user-defined warning %X=%Y: . ex/ex2.C:12: instance = {X <- *p, Y <- i}, ex/ex2.C:12: reached: *p = i. ...
(At the end of the trace, you'll also find many assignments within system template classes.)
Let us examine the above output. Each warning consists of three consecutive lines, the first of which telling the user-defined warning that was triggered, which is the user-supplied syntactic pattern. All the three lines are preceded by the source file and the line number raising the problem. The second line gives the problem instance, that is, the binding of pattern variables that made the check fail. The third line contains the statement reached (that was not supposed to be reached in case of a correct program).
Note that in the last warning message, D.27487 is a temporary variable introduced by gcc in the Gimple form. To see the Gimple form, use option --tree-dump-gimple, which generates it in file ex2.C.004t.gimple.
The second example concerns a full check on the same file ex2.C, that contains two errors. ex2.chk is a simple check file containing 5 checks, also called condates, involving control flow and data flow in addition to pure syntax:
condate new_deref { from "%X = operator new(%_)" # any new to "%_ = %X->%_" or "%X->%_ = %_" or "*%X = %_" or "%_ = *%X" avoid "%X = %_" or +"%X != 0B" or -"%X == 0B" } warning("Unsafe dereference of X after new"); condate undeleted { from "%X = operator new(%_)" to "return" or "return %_" avoid "operator delete(%X)" or +"%X == 0B" or -"%X != 0B" } warning("Un-deleted memory for variable X"); condate missing_unlock { from "flockfile (%X)" to ("return" or "return %_") avoid "funlockfile (%X)" } warning("Unreleased lock on file X"); condate missing_tryunlock { from "%L = ftrylockfile (%X)" to ("return" or "return %_") avoid "funlockfile (%X)" or +"%L != 0" or -"%L == 0" } warning("Unreleased (successful) trylock on file X"); condate gets { # "degenerate" condate, of only one pattern # 'from' keyword must be omitted: "%X = gets(%Y)" or "gets(%Y)" } warning("Never use gets(), see man gets");
To find the errors in ex2.C, invoke mygcc using g++ with the --tree-checks option (notice that "checks" is plural now), and maybe the –tree-checks-verbose option as well to get more detail:
[nic@paco mygcc]$ mygcc/1.0.0/bin/g++ --tree-checks=ex/ex2.chk --tree-checks-verbose ex/ex2.C ex/ex2.C: In function ‘int main()’: ex/ex2.C:12: warning: user-defined warning new_deref: Unsafe dereference of X after new. ex/ex2.C:12: instance = {X <- p}, ex/ex2.C:12: reached: *p = i. ex/ex2.C:16: warning: user-defined warning undeleted: Un-deleted memory for variable X. ex/ex2.C:16: instance = {X <- p}, ex/ex2.C:16: reached: return D.27489.
The warning messages have the same three-line layout as for simple checks. The first line tells the user-defined warning that was triggered: if the condate is named, then its name is given; if the condate is anonymous, it is identified by its defining file and its number within the file (numbering starts by 1). If detailed information on the line number cannot be computed, the starting or ending line of the containing function is indicated. The second line gives the problem instance, that is, the binding of pattern variables that made the check fail. The third line contains the statement reached (that was not supposed to be reached in case of a correct program).
Last update: 18/4/2007. Contact: mygcc@free.fr