| Source file | clang-analyzer | cppcheck | cpychecker | gcc | Notes | 
|---|---|---|---|---|---|
| coverage-3.5.1b1/coverage/tracer.c | 0 | 0 | 4 | 0 | Incomplete coverage: 4 analysis failure(s) | 
| python3-python-coverage-3.5.1-0.1.b1.fc17/coverage/tracer.c | 0 | 0 | 5 | 0 | Incomplete coverage: 4 analysis failure(s) | 
| Location | Tool | Test ID | Function | Issue | 
|---|---|---|---|---|
| coverage/tracer.c:458:1 | cpychecker | refcount-too-high | Tracer_trace | ob_refcnt of '*self' is 1 too high | 
| coverage/tracer.c:458:1 | cpychecker | refcount-too-high | Tracer_trace | ob_refcnt of '*tracename' is 1 too high | 
| coverage/tracer.c:532:5 | cpychecker | returns-NULL-without-setting-exception | Tracer_call | returning (PyObject*)NULL without setting an exception | 
| coverage/tracer.c:609:35 | cpychecker | flags-within-PyMethodDef | flags do not match callback signature for 'Tracer_get_stats' within PyMethodDef table | 
| Tool | Location | Function | Message | Data | 
|---|---|---|---|---|
| cpychecker | coverage/tracer.c:165:1 | Tracer_dealloc | Message(text='this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed') | CustomFields([('maxtrans', 256)]) | 
| cpychecker | coverage/tracer.c:256:1 | Tracer_trace | Message(text='this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed') | CustomFields([('maxtrans', 256)]) | 
| cpychecker | coverage/tracer.c:482:1 | Tracer_call | Message(text='this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed') | CustomFields([('maxtrans', 256)]) | 
| cpychecker | coverage/tracer.c:715:23 | inittracer | None | CustomFields([('traceback', 'Traceback (most recent call last):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/__init__.py", line 131, in _check_refcounts\n    self.options)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4355, in check_refcounts\n    rep = impl_check_refcounts(ctxt, fun, options)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4213, in impl_check_refcounts\n    limits=limits)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3053, in iter_traces\n    transitions = curstate.get_transitions()\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2105, in get_transitions\n    return self._get_transitions_for_stmt(stmt)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2121, in _get_transitions_for_stmt\n    return self._get_transitions_for_GimpleCall(stmt)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2292, in _get_transitions_for_GimpleCall\n    return meth(stmt, *args)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 2544, in impl_PyModule_AddObject\n    s_success.cpython.steal_reference(v_value, stmt.loc)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 741, in steal_reference\n    _steal_ref)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 551, in change_refcount\n    check_isinstance(oldvalue, RefcountValue)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/gccutils.py", line 642, in check_isinstance\n    raise TypeError(\'%s / %r is not an instance of %s\' % (obj, obj, types))\nTypeError: (long int)val [-0x7fffffffffffffff <= val <= 0x7fffffffffffffff] from coverage/tracer.c:714 / WithinRange(gcctype=\'long int\', loc=gcc.Location(file=\'coverage/tracer.c\', line=714), minvalue=-0x7fffffffffffffff, maxvalue=0x7fffffffffffffff) is not an instance of  | 
    
  1 /* C-based Tracer for Coverage. */
  2 
  3 #include "Python.h"
  4 #include "compile.h"        /* in 2.3, this wasn't part of Python.h */
  5 #include "eval.h"           /* or this. */
  6 #include "structmember.h"
  7 #include "frameobject.h"
  8 
  9 /* Compile-time debugging helpers */
 10 #undef WHAT_LOG         /* Define to log the WHAT params in the trace function. */
 11 #undef TRACE_LOG        /* Define to log our bookkeeping. */
 12 #undef COLLECT_STATS    /* Collect counters: stats are printed when tracer is stopped. */
 13 
 14 #if COLLECT_STATS
 15 #define STATS(x)        x
 16 #else
 17 #define STATS(x)
 18 #endif
 19 
 20 /* Py 2.x and 3.x compatibility */
 21 
 22 #ifndef Py_TYPE
 23 #define Py_TYPE(o)    (((PyObject*)(o))->ob_type)
 24 #endif
 25 
 26 #if PY_MAJOR_VERSION >= 3
 27 
 28 #define MyText_Type         PyUnicode_Type
 29 #define MyText_Check(o)     PyUnicode_Check(o)
 30 #define MyText_AS_STRING(o) PyBytes_AS_STRING(PyUnicode_AsASCIIString(o))
 31 #define MyInt_FromLong(l)   PyLong_FromLong(l)
 32 
 33 #define MyType_HEAD_INIT    PyVarObject_HEAD_INIT(NULL, 0)
 34 
 35 #else
 36 
 37 #define MyText_Type         PyString_Type
 38 #define MyText_Check(o)     PyString_Check(o)
 39 #define MyText_AS_STRING(o) PyString_AS_STRING(o)
 40 #define MyInt_FromLong(l)   PyInt_FromLong(l)
 41 
 42 #define MyType_HEAD_INIT    PyObject_HEAD_INIT(NULL)  0,
 43 
 44 #endif /* Py3k */
 45 
 46 /* The values returned to indicate ok or error. */
 47 #define RET_OK      0
 48 #define RET_ERROR   -1
 49 
 50 /* An entry on the data stack.  For each call frame, we need to record the
 51     dictionary to capture data, and the last line number executed in that
 52     frame.
 53 */
 54 typedef struct {
 55     PyObject * file_data;  /* PyMem_Malloc'ed, a borrowed ref. */
 56     int last_line;
 57 } DataStackEntry;
 58 
 59 /* The Tracer type. */
 60 
 61 typedef struct {
 62     PyObject_HEAD
 63 
 64     /* Python objects manipulated directly by the Collector class. */
 65     PyObject * should_trace;
 66     PyObject * warn;
 67     PyObject * data;
 68     PyObject * should_trace_cache;
 69     PyObject * arcs;
 70 
 71     /* Has the tracer been started? */
 72     int started;
 73     /* Are we tracing arcs, or just lines? */
 74     int tracing_arcs;
 75 
 76     /*
 77         The data stack is a stack of dictionaries.  Each dictionary collects
 78         data for a single source file.  The data stack parallels the call stack:
 79         each call pushes the new frame's file data onto the data stack, and each
 80         return pops file data off.
 81 
 82         The file data is a dictionary whose form depends on the tracing options.
 83         If tracing arcs, the keys are line number pairs.  If not tracing arcs,
 84         the keys are line numbers.  In both cases, the value is irrelevant
 85         (None).
 86     */
 87     /* The index of the last-used entry in data_stack. */
 88     int depth;
 89     /* The file data at each level, or NULL if not recording. */
 90     DataStackEntry * data_stack;
 91     int data_stack_alloc;       /* number of entries allocated at data_stack. */
 92 
 93     /* The current file_data dictionary.  Borrowed. */
 94     PyObject * cur_file_data;
 95 
 96     /* The line number of the last line recorded, for tracing arcs.
 97         -1 means there was no previous line, as when entering a code object.
 98     */
 99     int last_line;
100 
101     /* The parent frame for the last exception event, to fix missing returns. */
102     PyFrameObject * last_exc_back;
103     int last_exc_firstlineno;
104 
105 #if COLLECT_STATS
106     struct {
107         unsigned int calls;
108         unsigned int lines;
109         unsigned int returns;
110         unsigned int exceptions;
111         unsigned int others;
112         unsigned int new_files;
113         unsigned int missed_returns;
114         unsigned int stack_reallocs;
115         unsigned int errors;
116     } stats;
117 #endif /* COLLECT_STATS */
118 } Tracer;
119 
120 #define STACK_DELTA    100
121 
122 static int
123 Tracer_init(Tracer *self, PyObject *args_unused, PyObject *kwds_unused)
124 {
125 #if COLLECT_STATS
126     self->stats.calls = 0;
127     self->stats.lines = 0;
128     self->stats.returns = 0;
129     self->stats.exceptions = 0;
130     self->stats.others = 0;
131     self->stats.new_files = 0;
132     self->stats.missed_returns = 0;
133     self->stats.stack_reallocs = 0;
134     self->stats.errors = 0;
135 #endif /* COLLECT_STATS */
136 
137     self->should_trace = NULL;
138     self->warn = NULL;
139     self->data = NULL;
140     self->should_trace_cache = NULL;
141     self->arcs = NULL;
142 
143     self->started = 0;
144     self->tracing_arcs = 0;
145 
146     self->depth = -1;
147     self->data_stack = PyMem_Malloc(STACK_DELTA*sizeof(DataStackEntry));
148     if (self->data_stack == NULL) {
149         STATS( self->stats.errors++; )
150         PyErr_NoMemory();
151         return RET_ERROR;
152     }
153     self->data_stack_alloc = STACK_DELTA;
154 
155     self->cur_file_data = NULL;
156     self->last_line = -1;
157 
158     self->last_exc_back = NULL;
159 
160     return RET_OK;
161 }
162 
163 static void
164 Tracer_dealloc(Tracer *self)
165 {
      Message   this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed   maxtrans:   256166     if (self->started) {
167         PyEval_SetTrace(NULL, NULL);
168     }
169 
170     Py_XDECREF(self->should_trace);
171     Py_XDECREF(self->warn);
172     Py_XDECREF(self->data);
173     Py_XDECREF(self->should_trace_cache);
174 
175     PyMem_Free(self->data_stack);
176 
177     Py_TYPE(self)->tp_free((PyObject*)self);
178 }
179 
180 #if TRACE_LOG
181 static const char *
182 indent(int n)
183 {
184     static const char * spaces =
185         "                                                                    "
186         "                                                                    "
187         "                                                                    "
188         "                                                                    "
189         ;
190     return spaces + strlen(spaces) - n*2;
191 }
192 
193 static int logging = 0;
194 /* Set these constants to be a file substring and line number to start logging. */
195 static const char * start_file = "tests/views";
196 static int start_line = 27;
197 
198 static void
199 showlog(int depth, int lineno, PyObject * filename, const char * msg)
200 {
201     if (logging) {
202         printf("%s%3d ", indent(depth), depth);
203         if (lineno) {
204             printf("%4d", lineno);
205         }
206         else {
207             printf("    ");
208         }
209         if (filename) {
210             printf(" %s", MyText_AS_STRING(filename));
211         }
212         if (msg) {
213             printf(" %s", msg);
214         }
215         printf("\n");
216     }
217 }
218 
219 #define SHOWLOG(a,b,c,d)    showlog(a,b,c,d)
220 #else
221 #define SHOWLOG(a,b,c,d)
222 #endif /* TRACE_LOG */
223 
224 #if WHAT_LOG
225 static const char * what_sym[] = {"CALL", "EXC ", "LINE", "RET "};
226 #endif
227 
228 /* Record a pair of integers in self->cur_file_data. */
229 static int
230 Tracer_record_pair(Tracer *self, int l1, int l2)
231 {
232     int ret = RET_OK;
233 
234     PyObject * t = PyTuple_New(2);
235     if (t != NULL) {
236         PyTuple_SET_ITEM(t, 0, MyInt_FromLong(l1));
237         PyTuple_SET_ITEM(t, 1, MyInt_FromLong(l2));
238         if (PyDict_SetItem(self->cur_file_data, t, Py_None) < 0) {
239             STATS( self->stats.errors++; )
240             ret = RET_ERROR;
241         }
242         Py_DECREF(t);
243     }
244     else {
245         STATS( self->stats.errors++; )
246         ret = RET_ERROR;
247     }
248     return ret;
249 }
250 
251 /*
252  * The Trace Function
253  */
254 static int
255 Tracer_trace(Tracer *self, PyFrameObject *frame, int what, PyObject *arg_unused)
256 {
      Message   this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed   maxtrans:   256257     int ret = RET_OK;
258     PyObject * filename = NULL;
259     PyObject * tracename = NULL;
260 
261     #if WHAT_LOG
262     if (what <= sizeof(what_sym)/sizeof(const char *)) {
263         printf("trace: %s @ %s %d\n", what_sym[what], MyText_AS_STRING(frame->f_code->co_filename), frame->f_lineno);
264     }
265     #endif
266 
267     #if TRACE_LOG
268     if (strstr(MyText_AS_STRING(frame->f_code->co_filename), start_file) && frame->f_lineno == start_line) {
269         logging = 1;
270     }
271     #endif
272 
273     /* See below for details on missing-return detection. */
274     if (self->last_exc_back) {
275         if (frame == self->last_exc_back) {
276             /* Looks like someone forgot to send a return event. We'll clear
277                the exception state and do the RETURN code here.  Notice that the
278                frame we have in hand here is not the correct frame for the RETURN,
279                that frame is gone.  Our handling for RETURN doesn't need the
280                actual frame, but we do log it, so that will look a little off if
281                you're looking at the detailed log.
282 
283                If someday we need to examine the frame when doing RETURN, then
284                we'll need to keep more of the missed frame's state.
285             */
286             STATS( self->stats.missed_returns++; )
287             if (self->depth >= 0) {
288                 if (self->tracing_arcs && self->cur_file_data) {
289                     if (Tracer_record_pair(self, self->last_line, -self->last_exc_firstlineno) < 0) {
290                         return RET_ERROR;
291                     }
292                 }
293                 SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "missedreturn");
294                 self->cur_file_data = self->data_stack[self->depth].file_data;
295                 self->last_line = self->data_stack[self->depth].last_line;
296                 self->depth--;
297             }
298         }
299         self->last_exc_back = NULL;
300     }
301 
302 
303     switch (what) {
304     case PyTrace_CALL:      /* 0 */
305         STATS( self->stats.calls++; )
306         /* Grow the stack. */
307         self->depth++;
308         if (self->depth >= self->data_stack_alloc) {
309             STATS( self->stats.stack_reallocs++; )
310             /* We've outgrown our data_stack array: make it bigger. */
311             int bigger = self->data_stack_alloc + STACK_DELTA;
312             DataStackEntry * bigger_data_stack = PyMem_Realloc(self->data_stack, bigger * sizeof(DataStackEntry));
313             if (bigger_data_stack == NULL) {
314                 STATS( self->stats.errors++; )
315                 PyErr_NoMemory();
316                 self->depth--;
317                 return RET_ERROR;
318             }
319             self->data_stack = bigger_data_stack;
320             self->data_stack_alloc = bigger;
321         }
322 
323         /* Push the current state on the stack. */
324         self->data_stack[self->depth].file_data = self->cur_file_data;
325         self->data_stack[self->depth].last_line = self->last_line;
326 
327         /* Check if we should trace this line. */
328         filename = frame->f_code->co_filename;
329         tracename = PyDict_GetItem(self->should_trace_cache, filename);
330         if (tracename == NULL) {
331             STATS( self->stats.new_files++; )
332             /* We've never considered this file before. */
333             /* Ask should_trace about it. */
334             PyObject * args = Py_BuildValue("(OO)", filename, frame);
335             tracename = PyObject_Call(self->should_trace, args, NULL);
336             Py_DECREF(args);
337             if (tracename == NULL) {
338                 /* An error occurred inside should_trace. */
339                 STATS( self->stats.errors++; )
340                 return RET_ERROR;
341             }
342             if (PyDict_SetItem(self->should_trace_cache, filename, tracename) < 0) {
343                 STATS( self->stats.errors++; )
344                 return RET_ERROR;
345             }
346         }
347         else {
348             Py_INCREF(tracename);
349         }
350 
351         /* If tracename is a string, then we're supposed to trace. */
352         if (MyText_Check(tracename)) {
353             PyObject * file_data = PyDict_GetItem(self->data, tracename);
354             if (file_data == NULL) {
355                 file_data = PyDict_New();
356                 if (file_data == NULL) {
357                     STATS( self->stats.errors++; )
358                     return RET_ERROR;
359                 }
360                 ret = PyDict_SetItem(self->data, tracename, file_data);
361                 Py_DECREF(file_data);
362                 if (ret < 0) {
363                     STATS( self->stats.errors++; )
364                     return RET_ERROR;
365                 }
366             }
367             self->cur_file_data = file_data;
368             /* Make the frame right in case settrace(gettrace()) happens. */
369             Py_INCREF(self);
370             frame->f_trace = (PyObject*)self;
371             SHOWLOG(self->depth, frame->f_lineno, filename, "traced");
372         }
373         else {
374             self->cur_file_data = NULL;
375             SHOWLOG(self->depth, frame->f_lineno, filename, "skipped");
376         }
377 
378         Py_DECREF(tracename);
379 
380         self->last_line = -1;
381         break;
382 
383     case PyTrace_RETURN:    /* 3 */
384         STATS( self->stats.returns++; )
385         /* A near-copy of this code is above in the missing-return handler. */
386         if (self->depth >= 0) {
387             if (self->tracing_arcs && self->cur_file_data) {
388                 int first = frame->f_code->co_firstlineno;
389                 if (Tracer_record_pair(self, self->last_line, -first) < 0) {
390                     return RET_ERROR;
391                 }
392             }
393 
394             SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "return");
395             self->cur_file_data = self->data_stack[self->depth].file_data;
396             self->last_line = self->data_stack[self->depth].last_line;
397             self->depth--;
398         }
399         break;
400 
401     case PyTrace_LINE:      /* 2 */
402         STATS( self->stats.lines++; )
403         if (self->depth >= 0) {
404             SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "line");
405             if (self->cur_file_data) {
406                 /* We're tracing in this frame: record something. */
407                 if (self->tracing_arcs) {
408                     /* Tracing arcs: key is (last_line,this_line). */
409                     if (Tracer_record_pair(self, self->last_line, frame->f_lineno) < 0) {
410                         return RET_ERROR;
411                     }
412                 }
413                 else {
414                     /* Tracing lines: key is simply this_line. */
415                     PyObject * this_line = MyInt_FromLong(frame->f_lineno);
416                     if (this_line == NULL) {
417                         STATS( self->stats.errors++; )
418                         return RET_ERROR;
419                     }
420                     ret = PyDict_SetItem(self->cur_file_data, this_line, Py_None);
421                     Py_DECREF(this_line);
422                     if (ret < 0) {
423                         STATS( self->stats.errors++; )
424                         return RET_ERROR;
425                     }
426                 }
427             }
428             self->last_line = frame->f_lineno;
429         }
430         break;
431 
432     case PyTrace_EXCEPTION:
433         /* Some code (Python 2.3, and pyexpat anywhere) fires an exception event
434            without a return event.  To detect that, we'll keep a copy of the
435            parent frame for an exception event.  If the next event is in that
436            frame, then we must have returned without a return event.  We can
437            synthesize the missing event then.
438 
439            Python itself fixed this problem in 2.4.  Pyexpat still has the bug.
440            I've reported the problem with pyexpat as http://bugs.python.org/issue6359 .
441            If it gets fixed, this code should still work properly.  Maybe some day
442            the bug will be fixed everywhere coverage.py is supported, and we can
443            remove this missing-return detection.
444 
445            More about this fix: http://nedbatchelder.com/blog/200907/a_nasty_little_bug.html
446         */
447         STATS( self->stats.exceptions++; )
448         self->last_exc_back = frame->f_back;
449         self->last_exc_firstlineno = frame->f_code->co_firstlineno;
450         break;
451 
452     default:
453         STATS( self->stats.others++; )
454         break;
455     }
456 
457     return RET_OK;
458 }
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
459 
460 /*
461  * Python has two ways to set the trace function: sys.settrace(fn), which
462  * takes a Python callable, and PyEval_SetTrace(func, obj), which takes
463  * a C function and a Python object.  The way these work together is that
464  * sys.settrace(pyfn) calls PyEval_SetTrace(builtin_func, pyfn), using the
465  * Python callable as the object in PyEval_SetTrace.  So sys.gettrace()
466  * simply returns the Python object used as the second argument to
467  * PyEval_SetTrace.  So sys.gettrace() will return our self parameter, which
468  * means it must be callable to be used in sys.settrace().
469  *
470  * So we make our self callable, equivalent to invoking our trace function.
471  *
472  * To help with the process of replaying stored frames, this function has an
473  * optional keyword argument:
474  *
475  *      def Tracer_call(frame, event, arg, lineno=0)
476  *
477  * If provided, the lineno argument is used as the line number, and the
478  * frame's f_lineno member is ignored.
479  */
480 static PyObject *
481 Tracer_call(Tracer *self, PyObject *args, PyObject *kwds)
482 {
      Message   this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed   maxtrans:   256483     PyFrameObject *frame;
484     PyObject *what_str;
485     PyObject *arg;
486     int lineno = 0;
487     int what;
488     int orig_lineno;
489     PyObject *ret = NULL;
490 
491     static char *what_names[] = {
492         "call", "exception", "line", "return",
493         "c_call", "c_exception", "c_return",
494         NULL
495         };
496 
497     #if WHAT_LOG
498     printf("pytrace\n");
499     #endif
500 
501     static char *kwlist[] = {"frame", "event", "arg", "lineno", NULL};
502 
503     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!O|i:Tracer_call", kwlist,
504             &PyFrame_Type, &frame, &MyText_Type, &what_str, &arg, &lineno)) {
505         goto done;
506     }
507 
508     /* In Python, the what argument is a string, we need to find an int
509        for the C function. */
510     for (what = 0; what_names[what]; what++) {
511         if (!strcmp(MyText_AS_STRING(what_str), what_names[what])) {
512             break;
513         }
514     }
515 
516     /* Save off the frame's lineno, and use the forced one, if provided. */
517     orig_lineno = frame->f_lineno;
518     if (lineno > 0) {
519         frame->f_lineno = lineno;
520     }
521 
522     /* Invoke the C function, and return ourselves. */
523     if (Tracer_trace(self, frame, what, arg) == RET_OK) {
524         Py_INCREF(self);
525         ret = (PyObject *)self;
526     }
527 
528     /* Clean up. */
529     frame->f_lineno = orig_lineno;
530 
531 done:
532     return ret;
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
533 }
534 
535 static PyObject *
536 Tracer_start(Tracer *self, PyObject *args_unused)
537 {
538     PyEval_SetTrace((Py_tracefunc)Tracer_trace, (PyObject*)self);
539     self->started = 1;
540     self->tracing_arcs = self->arcs && PyObject_IsTrue(self->arcs);
541     self->last_line = -1;
542 
543     /* start() returns a trace function usable with sys.settrace() */
544     Py_INCREF(self);
545     return (PyObject *)self;
546 }
547 
548 static PyObject *
549 Tracer_stop(Tracer *self, PyObject *args_unused)
550 {
551     if (self->started) {
552         PyEval_SetTrace(NULL, NULL);
553         self->started = 0;
554     }
555 
556     return Py_BuildValue("");
557 }
558 
559 static PyObject *
560 Tracer_get_stats(Tracer *self)
561 {
562 #if COLLECT_STATS
563     return Py_BuildValue(
564         "{sI,sI,sI,sI,sI,sI,sI,sI,si,sI}",
565         "calls", self->stats.calls,
566         "lines", self->stats.lines,
567         "returns", self->stats.returns,
568         "exceptions", self->stats.exceptions,
569         "others", self->stats.others,
570         "new_files", self->stats.new_files,
571         "missed_returns", self->stats.missed_returns,
572         "stack_reallocs", self->stats.stack_reallocs,
573         "stack_alloc", self->data_stack_alloc,
574         "errors", self->stats.errors
575         );
576 #else
577     return Py_BuildValue("");
578 #endif /* COLLECT_STATS */
579 }
580 
581 static PyMemberDef
582 Tracer_members[] = {
583     { "should_trace",       T_OBJECT, offsetof(Tracer, should_trace), 0,
584             PyDoc_STR("Function indicating whether to trace a file.") },
585 
586     { "warn",               T_OBJECT, offsetof(Tracer, warn), 0,
587             PyDoc_STR("Function for issuing warnings.") },
588 
589     { "data",               T_OBJECT, offsetof(Tracer, data), 0,
590             PyDoc_STR("The raw dictionary of trace data.") },
591 
592     { "should_trace_cache", T_OBJECT, offsetof(Tracer, should_trace_cache), 0,
593             PyDoc_STR("Dictionary caching should_trace results.") },
594 
595     { "arcs",               T_OBJECT, offsetof(Tracer, arcs), 0,
596             PyDoc_STR("Should we trace arcs, or just lines?") },
597 
598     { NULL }
599 };
600 
601 static PyMethodDef
602 Tracer_methods[] = {
603     { "start",      (PyCFunction) Tracer_start,         METH_VARARGS,
604             PyDoc_STR("Start the tracer") },
605 
606     { "stop",       (PyCFunction) Tracer_stop,          METH_VARARGS,
607             PyDoc_STR("Stop the tracer") },
608 
609     { "get_stats",  (PyCFunction) Tracer_get_stats,     METH_VARARGS,
      (emitted by cpychecker)610             PyDoc_STR("Get statistics about the tracing") },
611 
612     { NULL }
613 };
614 
615 static PyTypeObject
616 TracerType = {
617     MyType_HEAD_INIT
618     "coverage.Tracer",         /*tp_name*/
619     sizeof(Tracer),            /*tp_basicsize*/
620     0,                         /*tp_itemsize*/
621     (destructor)Tracer_dealloc, /*tp_dealloc*/
622     0,                         /*tp_print*/
623     0,                         /*tp_getattr*/
624     0,                         /*tp_setattr*/
625     0,                         /*tp_compare*/
626     0,                         /*tp_repr*/
627     0,                         /*tp_as_number*/
628     0,                         /*tp_as_sequence*/
629     0,                         /*tp_as_mapping*/
630     0,                         /*tp_hash */
631     (ternaryfunc)Tracer_call,  /*tp_call*/
632     0,                         /*tp_str*/
633     0,                         /*tp_getattro*/
634     0,                         /*tp_setattro*/
635     0,                         /*tp_as_buffer*/
636     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
637     "Tracer objects",          /* tp_doc */
638     0,                         /* tp_traverse */
639     0,                         /* tp_clear */
640     0,                         /* tp_richcompare */
641     0,                         /* tp_weaklistoffset */
642     0,                         /* tp_iter */
643     0,                         /* tp_iternext */
644     Tracer_methods,            /* tp_methods */
645     Tracer_members,            /* tp_members */
646     0,                         /* tp_getset */
647     0,                         /* tp_base */
648     0,                         /* tp_dict */
649     0,                         /* tp_descr_get */
650     0,                         /* tp_descr_set */
651     0,                         /* tp_dictoffset */
652     (initproc)Tracer_init,     /* tp_init */
653     0,                         /* tp_alloc */
654     0,                         /* tp_new */
655 };
656 
657 /* Module definition */
658 
659 #define MODULE_DOC PyDoc_STR("Fast coverage tracer.")
660 
661 #if PY_MAJOR_VERSION >= 3
662 
663 static PyModuleDef
664 moduledef = {
665     PyModuleDef_HEAD_INIT,
666     "coverage.tracer",
667     MODULE_DOC,
668     -1,
669     NULL,       /* methods */
670     NULL,
671     NULL,       /* traverse */
672     NULL,       /* clear */
673     NULL
674 };
675 
676 
677 PyObject *
678 PyInit_tracer(void)
679 {
680     PyObject * mod = PyModule_Create(&moduledef);
681     if (mod == NULL) {
682         return NULL;
683     }
684 
685     TracerType.tp_new = PyType_GenericNew;
686     if (PyType_Ready(&TracerType) < 0) {
687         Py_DECREF(mod);
688         return NULL;
689     }
690 
691     Py_INCREF(&TracerType);
692     PyModule_AddObject(mod, "Tracer", (PyObject *)&TracerType);
693 
694     return mod;
695 }
696 
697 #else
698 
699 void
700 inittracer(void)
701 {
702     PyObject * mod;
703 
704     mod = Py_InitModule3("coverage.tracer", NULL, MODULE_DOC);
705     if (mod == NULL) {
706         return;
707     }
708 
709     TracerType.tp_new = PyType_GenericNew;
710     if (PyType_Ready(&TracerType) < 0) {
711         return;
712     }
713 
714     Py_INCREF(&TracerType);
715     PyModule_AddObject(mod, "Tracer", (PyObject *)&TracerType);
      traceback:   Traceback (most recent call last):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/__init__.py", line 131, in _check_refcounts
    self.options)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4355, in check_refcounts
    rep = impl_check_refcounts(ctxt, fun, options)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4213, in impl_check_refcounts
    limits=limits)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3053, in iter_traces
    transitions = curstate.get_transitions()
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2105, in get_transitions
    return self._get_transitions_for_stmt(stmt)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2121, in _get_transitions_for_stmt
    return self._get_transitions_for_GimpleCall(stmt)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2292, in _get_transitions_for_GimpleCall
    return meth(stmt, *args)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 2544, in impl_PyModule_AddObject
    s_success.cpython.steal_reference(v_value, stmt.loc)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 741, in steal_reference
    _steal_ref)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 551, in change_refcount
    check_isinstance(oldvalue, RefcountValue)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/gccutils.py", line 642, in check_isinstance
    raise TypeError('%s / %r is not an instance of %s' % (obj, obj, types))
TypeError: (long int)val [-0x7fffffffffffffff <= val <= 0x7fffffffffffffff] from coverage/tracer.c:714 / WithinRange(gcctype='long int', loc=gcc.Location(file='coverage/tracer.c', line=714), minvalue=-0x7fffffffffffffff, maxvalue=0x7fffffffffffffff) is not an instance of <class 'libcpychecker.refcounts.RefcountValue'>
716 }
717 
718 #endif /* Py3k */
| Location | Tool | Test ID | Function | Issue | 
|---|---|---|---|---|
| coverage/tracer.c:458:1 | cpychecker | refcount-too-high | Tracer_trace | ob_refcnt of '*self' is 1 too high | 
| coverage/tracer.c:458:1 | cpychecker | refcount-too-high | Tracer_trace | ob_refcnt of '*tracename' is 1 too high | 
| coverage/tracer.c:532:5 | cpychecker | refcount-too-high | Tracer_call | ob_refcnt of new ref from (unknown) PyUnicodeUCS4_AsASCIIString is 1 too high | 
| coverage/tracer.c:532:5 | cpychecker | returns-NULL-without-setting-exception | Tracer_call | returning (PyObject*)NULL without setting an exception | 
| coverage/tracer.c:609:35 | cpychecker | flags-within-PyMethodDef | flags do not match callback signature for 'Tracer_get_stats' within PyMethodDef table | 
| Tool | Location | Function | Message | Data | 
|---|---|---|---|---|
| cpychecker | coverage/tracer.c:165:1 | Tracer_dealloc | Message(text='this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed') | CustomFields([('maxtrans', 256)]) | 
| cpychecker | coverage/tracer.c:256:1 | Tracer_trace | Message(text='this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed') | CustomFields([('maxtrans', 256)]) | 
| cpychecker | coverage/tracer.c:482:1 | Tracer_call | Message(text='this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed') | CustomFields([('maxtrans', 256)]) | 
| cpychecker | coverage/tracer.c:692:23 | PyInit_tracer | None | CustomFields([('traceback', 'Traceback (most recent call last):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/__init__.py", line 131, in _check_refcounts\n    self.options)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4355, in check_refcounts\n    rep = impl_check_refcounts(ctxt, fun, options)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4213, in impl_check_refcounts\n    limits=limits)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces\n    depth + 1):\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3053, in iter_traces\n    transitions = curstate.get_transitions()\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2105, in get_transitions\n    return self._get_transitions_for_stmt(stmt)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2121, in _get_transitions_for_stmt\n    return self._get_transitions_for_GimpleCall(stmt)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2292, in _get_transitions_for_GimpleCall\n    return meth(stmt, *args)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 2544, in impl_PyModule_AddObject\n    s_success.cpython.steal_reference(v_value, stmt.loc)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 741, in steal_reference\n    _steal_ref)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 551, in change_refcount\n    check_isinstance(oldvalue, RefcountValue)\n  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/gccutils.py", line 642, in check_isinstance\n    raise TypeError(\'%s / %r is not an instance of %s\' % (obj, obj, types))\nTypeError: (long int)val [-0x7fffffffffffffff <= val <= 0x7fffffffffffffff] from coverage/tracer.c:691 / WithinRange(gcctype=\'long int\', loc=gcc.Location(file=\'coverage/tracer.c\', line=691), minvalue=-0x7fffffffffffffff, maxvalue=0x7fffffffffffffff) is not an instance of  | 
    
  1 /* C-based Tracer for Coverage. */
  2 
  3 #include "Python.h"
  4 #include "compile.h"        /* in 2.3, this wasn't part of Python.h */
  5 #include "eval.h"           /* or this. */
  6 #include "structmember.h"
  7 #include "frameobject.h"
  8 
  9 /* Compile-time debugging helpers */
 10 #undef WHAT_LOG         /* Define to log the WHAT params in the trace function. */
 11 #undef TRACE_LOG        /* Define to log our bookkeeping. */
 12 #undef COLLECT_STATS    /* Collect counters: stats are printed when tracer is stopped. */
 13 
 14 #if COLLECT_STATS
 15 #define STATS(x)        x
 16 #else
 17 #define STATS(x)
 18 #endif
 19 
 20 /* Py 2.x and 3.x compatibility */
 21 
 22 #ifndef Py_TYPE
 23 #define Py_TYPE(o)    (((PyObject*)(o))->ob_type)
 24 #endif
 25 
 26 #if PY_MAJOR_VERSION >= 3
 27 
 28 #define MyText_Type         PyUnicode_Type
 29 #define MyText_Check(o)     PyUnicode_Check(o)
 30 #define MyText_AS_STRING(o) PyBytes_AS_STRING(PyUnicode_AsASCIIString(o))
 31 #define MyInt_FromLong(l)   PyLong_FromLong(l)
 32 
 33 #define MyType_HEAD_INIT    PyVarObject_HEAD_INIT(NULL, 0)
 34 
 35 #else
 36 
 37 #define MyText_Type         PyString_Type
 38 #define MyText_Check(o)     PyString_Check(o)
 39 #define MyText_AS_STRING(o) PyString_AS_STRING(o)
 40 #define MyInt_FromLong(l)   PyInt_FromLong(l)
 41 
 42 #define MyType_HEAD_INIT    PyObject_HEAD_INIT(NULL)  0,
 43 
 44 #endif /* Py3k */
 45 
 46 /* The values returned to indicate ok or error. */
 47 #define RET_OK      0
 48 #define RET_ERROR   -1
 49 
 50 /* An entry on the data stack.  For each call frame, we need to record the
 51     dictionary to capture data, and the last line number executed in that
 52     frame.
 53 */
 54 typedef struct {
 55     PyObject * file_data;  /* PyMem_Malloc'ed, a borrowed ref. */
 56     int last_line;
 57 } DataStackEntry;
 58 
 59 /* The Tracer type. */
 60 
 61 typedef struct {
 62     PyObject_HEAD
 63 
 64     /* Python objects manipulated directly by the Collector class. */
 65     PyObject * should_trace;
 66     PyObject * warn;
 67     PyObject * data;
 68     PyObject * should_trace_cache;
 69     PyObject * arcs;
 70 
 71     /* Has the tracer been started? */
 72     int started;
 73     /* Are we tracing arcs, or just lines? */
 74     int tracing_arcs;
 75 
 76     /*
 77         The data stack is a stack of dictionaries.  Each dictionary collects
 78         data for a single source file.  The data stack parallels the call stack:
 79         each call pushes the new frame's file data onto the data stack, and each
 80         return pops file data off.
 81 
 82         The file data is a dictionary whose form depends on the tracing options.
 83         If tracing arcs, the keys are line number pairs.  If not tracing arcs,
 84         the keys are line numbers.  In both cases, the value is irrelevant
 85         (None).
 86     */
 87     /* The index of the last-used entry in data_stack. */
 88     int depth;
 89     /* The file data at each level, or NULL if not recording. */
 90     DataStackEntry * data_stack;
 91     int data_stack_alloc;       /* number of entries allocated at data_stack. */
 92 
 93     /* The current file_data dictionary.  Borrowed. */
 94     PyObject * cur_file_data;
 95 
 96     /* The line number of the last line recorded, for tracing arcs.
 97         -1 means there was no previous line, as when entering a code object.
 98     */
 99     int last_line;
100 
101     /* The parent frame for the last exception event, to fix missing returns. */
102     PyFrameObject * last_exc_back;
103     int last_exc_firstlineno;
104 
105 #if COLLECT_STATS
106     struct {
107         unsigned int calls;
108         unsigned int lines;
109         unsigned int returns;
110         unsigned int exceptions;
111         unsigned int others;
112         unsigned int new_files;
113         unsigned int missed_returns;
114         unsigned int stack_reallocs;
115         unsigned int errors;
116     } stats;
117 #endif /* COLLECT_STATS */
118 } Tracer;
119 
120 #define STACK_DELTA    100
121 
122 static int
123 Tracer_init(Tracer *self, PyObject *args_unused, PyObject *kwds_unused)
124 {
125 #if COLLECT_STATS
126     self->stats.calls = 0;
127     self->stats.lines = 0;
128     self->stats.returns = 0;
129     self->stats.exceptions = 0;
130     self->stats.others = 0;
131     self->stats.new_files = 0;
132     self->stats.missed_returns = 0;
133     self->stats.stack_reallocs = 0;
134     self->stats.errors = 0;
135 #endif /* COLLECT_STATS */
136 
137     self->should_trace = NULL;
138     self->warn = NULL;
139     self->data = NULL;
140     self->should_trace_cache = NULL;
141     self->arcs = NULL;
142 
143     self->started = 0;
144     self->tracing_arcs = 0;
145 
146     self->depth = -1;
147     self->data_stack = PyMem_Malloc(STACK_DELTA*sizeof(DataStackEntry));
148     if (self->data_stack == NULL) {
149         STATS( self->stats.errors++; )
150         PyErr_NoMemory();
151         return RET_ERROR;
152     }
153     self->data_stack_alloc = STACK_DELTA;
154 
155     self->cur_file_data = NULL;
156     self->last_line = -1;
157 
158     self->last_exc_back = NULL;
159 
160     return RET_OK;
161 }
162 
163 static void
164 Tracer_dealloc(Tracer *self)
165 {
      Message   this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed   maxtrans:   256166     if (self->started) {
167         PyEval_SetTrace(NULL, NULL);
168     }
169 
170     Py_XDECREF(self->should_trace);
171     Py_XDECREF(self->warn);
172     Py_XDECREF(self->data);
173     Py_XDECREF(self->should_trace_cache);
174 
175     PyMem_Free(self->data_stack);
176 
177     Py_TYPE(self)->tp_free((PyObject*)self);
178 }
179 
180 #if TRACE_LOG
181 static const char *
182 indent(int n)
183 {
184     static const char * spaces =
185         "                                                                    "
186         "                                                                    "
187         "                                                                    "
188         "                                                                    "
189         ;
190     return spaces + strlen(spaces) - n*2;
191 }
192 
193 static int logging = 0;
194 /* Set these constants to be a file substring and line number to start logging. */
195 static const char * start_file = "tests/views";
196 static int start_line = 27;
197 
198 static void
199 showlog(int depth, int lineno, PyObject * filename, const char * msg)
200 {
201     if (logging) {
202         printf("%s%3d ", indent(depth), depth);
203         if (lineno) {
204             printf("%4d", lineno);
205         }
206         else {
207             printf("    ");
208         }
209         if (filename) {
210             printf(" %s", MyText_AS_STRING(filename));
211         }
212         if (msg) {
213             printf(" %s", msg);
214         }
215         printf("\n");
216     }
217 }
218 
219 #define SHOWLOG(a,b,c,d)    showlog(a,b,c,d)
220 #else
221 #define SHOWLOG(a,b,c,d)
222 #endif /* TRACE_LOG */
223 
224 #if WHAT_LOG
225 static const char * what_sym[] = {"CALL", "EXC ", "LINE", "RET "};
226 #endif
227 
228 /* Record a pair of integers in self->cur_file_data. */
229 static int
230 Tracer_record_pair(Tracer *self, int l1, int l2)
231 {
232     int ret = RET_OK;
233 
234     PyObject * t = PyTuple_New(2);
235     if (t != NULL) {
236         PyTuple_SET_ITEM(t, 0, MyInt_FromLong(l1));
237         PyTuple_SET_ITEM(t, 1, MyInt_FromLong(l2));
238         if (PyDict_SetItem(self->cur_file_data, t, Py_None) < 0) {
239             STATS( self->stats.errors++; )
240             ret = RET_ERROR;
241         }
242         Py_DECREF(t);
243     }
244     else {
245         STATS( self->stats.errors++; )
246         ret = RET_ERROR;
247     }
248     return ret;
249 }
250 
251 /*
252  * The Trace Function
253  */
254 static int
255 Tracer_trace(Tracer *self, PyFrameObject *frame, int what, PyObject *arg_unused)
256 {
      Message   this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed   maxtrans:   256257     int ret = RET_OK;
258     PyObject * filename = NULL;
259     PyObject * tracename = NULL;
260 
261     #if WHAT_LOG
262     if (what <= sizeof(what_sym)/sizeof(const char *)) {
263         printf("trace: %s @ %s %d\n", what_sym[what], MyText_AS_STRING(frame->f_code->co_filename), frame->f_lineno);
264     }
265     #endif
266 
267     #if TRACE_LOG
268     if (strstr(MyText_AS_STRING(frame->f_code->co_filename), start_file) && frame->f_lineno == start_line) {
269         logging = 1;
270     }
271     #endif
272 
273     /* See below for details on missing-return detection. */
274     if (self->last_exc_back) {
275         if (frame == self->last_exc_back) {
276             /* Looks like someone forgot to send a return event. We'll clear
277                the exception state and do the RETURN code here.  Notice that the
278                frame we have in hand here is not the correct frame for the RETURN,
279                that frame is gone.  Our handling for RETURN doesn't need the
280                actual frame, but we do log it, so that will look a little off if
281                you're looking at the detailed log.
282 
283                If someday we need to examine the frame when doing RETURN, then
284                we'll need to keep more of the missed frame's state.
285             */
286             STATS( self->stats.missed_returns++; )
287             if (self->depth >= 0) {
288                 if (self->tracing_arcs && self->cur_file_data) {
289                     if (Tracer_record_pair(self, self->last_line, -self->last_exc_firstlineno) < 0) {
290                         return RET_ERROR;
291                     }
292                 }
293                 SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "missedreturn");
294                 self->cur_file_data = self->data_stack[self->depth].file_data;
295                 self->last_line = self->data_stack[self->depth].last_line;
296                 self->depth--;
297             }
298         }
299         self->last_exc_back = NULL;
300     }
301 
302 
303     switch (what) {
304     case PyTrace_CALL:      /* 0 */
305         STATS( self->stats.calls++; )
306         /* Grow the stack. */
307         self->depth++;
308         if (self->depth >= self->data_stack_alloc) {
309             STATS( self->stats.stack_reallocs++; )
310             /* We've outgrown our data_stack array: make it bigger. */
311             int bigger = self->data_stack_alloc + STACK_DELTA;
312             DataStackEntry * bigger_data_stack = PyMem_Realloc(self->data_stack, bigger * sizeof(DataStackEntry));
313             if (bigger_data_stack == NULL) {
314                 STATS( self->stats.errors++; )
315                 PyErr_NoMemory();
316                 self->depth--;
317                 return RET_ERROR;
318             }
319             self->data_stack = bigger_data_stack;
320             self->data_stack_alloc = bigger;
321         }
322 
323         /* Push the current state on the stack. */
324         self->data_stack[self->depth].file_data = self->cur_file_data;
325         self->data_stack[self->depth].last_line = self->last_line;
326 
327         /* Check if we should trace this line. */
328         filename = frame->f_code->co_filename;
329         tracename = PyDict_GetItem(self->should_trace_cache, filename);
330         if (tracename == NULL) {
331             STATS( self->stats.new_files++; )
332             /* We've never considered this file before. */
333             /* Ask should_trace about it. */
334             PyObject * args = Py_BuildValue("(OO)", filename, frame);
335             tracename = PyObject_Call(self->should_trace, args, NULL);
336             Py_DECREF(args);
337             if (tracename == NULL) {
338                 /* An error occurred inside should_trace. */
339                 STATS( self->stats.errors++; )
340                 return RET_ERROR;
341             }
342             if (PyDict_SetItem(self->should_trace_cache, filename, tracename) < 0) {
343                 STATS( self->stats.errors++; )
344                 return RET_ERROR;
345             }
346         }
347         else {
348             Py_INCREF(tracename);
349         }
350 
351         /* If tracename is a string, then we're supposed to trace. */
352         if (MyText_Check(tracename)) {
353             PyObject * file_data = PyDict_GetItem(self->data, tracename);
354             if (file_data == NULL) {
355                 file_data = PyDict_New();
356                 if (file_data == NULL) {
357                     STATS( self->stats.errors++; )
358                     return RET_ERROR;
359                 }
360                 ret = PyDict_SetItem(self->data, tracename, file_data);
361                 Py_DECREF(file_data);
362                 if (ret < 0) {
363                     STATS( self->stats.errors++; )
364                     return RET_ERROR;
365                 }
366             }
367             self->cur_file_data = file_data;
368             /* Make the frame right in case settrace(gettrace()) happens. */
369             Py_INCREF(self);
370             frame->f_trace = (PyObject*)self;
371             SHOWLOG(self->depth, frame->f_lineno, filename, "traced");
372         }
373         else {
374             self->cur_file_data = NULL;
375             SHOWLOG(self->depth, frame->f_lineno, filename, "skipped");
376         }
377 
378         Py_DECREF(tracename);
379 
380         self->last_line = -1;
381         break;
382 
383     case PyTrace_RETURN:    /* 3 */
384         STATS( self->stats.returns++; )
385         /* A near-copy of this code is above in the missing-return handler. */
386         if (self->depth >= 0) {
387             if (self->tracing_arcs && self->cur_file_data) {
388                 int first = frame->f_code->co_firstlineno;
389                 if (Tracer_record_pair(self, self->last_line, -first) < 0) {
390                     return RET_ERROR;
391                 }
392             }
393 
394             SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "return");
395             self->cur_file_data = self->data_stack[self->depth].file_data;
396             self->last_line = self->data_stack[self->depth].last_line;
397             self->depth--;
398         }
399         break;
400 
401     case PyTrace_LINE:      /* 2 */
402         STATS( self->stats.lines++; )
403         if (self->depth >= 0) {
404             SHOWLOG(self->depth, frame->f_lineno, frame->f_code->co_filename, "line");
405             if (self->cur_file_data) {
406                 /* We're tracing in this frame: record something. */
407                 if (self->tracing_arcs) {
408                     /* Tracing arcs: key is (last_line,this_line). */
409                     if (Tracer_record_pair(self, self->last_line, frame->f_lineno) < 0) {
410                         return RET_ERROR;
411                     }
412                 }
413                 else {
414                     /* Tracing lines: key is simply this_line. */
415                     PyObject * this_line = MyInt_FromLong(frame->f_lineno);
416                     if (this_line == NULL) {
417                         STATS( self->stats.errors++; )
418                         return RET_ERROR;
419                     }
420                     ret = PyDict_SetItem(self->cur_file_data, this_line, Py_None);
421                     Py_DECREF(this_line);
422                     if (ret < 0) {
423                         STATS( self->stats.errors++; )
424                         return RET_ERROR;
425                     }
426                 }
427             }
428             self->last_line = frame->f_lineno;
429         }
430         break;
431 
432     case PyTrace_EXCEPTION:
433         /* Some code (Python 2.3, and pyexpat anywhere) fires an exception event
434            without a return event.  To detect that, we'll keep a copy of the
435            parent frame for an exception event.  If the next event is in that
436            frame, then we must have returned without a return event.  We can
437            synthesize the missing event then.
438 
439            Python itself fixed this problem in 2.4.  Pyexpat still has the bug.
440            I've reported the problem with pyexpat as http://bugs.python.org/issue6359 .
441            If it gets fixed, this code should still work properly.  Maybe some day
442            the bug will be fixed everywhere coverage.py is supported, and we can
443            remove this missing-return detection.
444 
445            More about this fix: http://nedbatchelder.com/blog/200907/a_nasty_little_bug.html
446         */
447         STATS( self->stats.exceptions++; )
448         self->last_exc_back = frame->f_back;
449         self->last_exc_firstlineno = frame->f_code->co_firstlineno;
450         break;
451 
452     default:
453         STATS( self->stats.others++; )
454         break;
455     }
456 
457     return RET_OK;
458 }
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
459 
460 /*
461  * Python has two ways to set the trace function: sys.settrace(fn), which
462  * takes a Python callable, and PyEval_SetTrace(func, obj), which takes
463  * a C function and a Python object.  The way these work together is that
464  * sys.settrace(pyfn) calls PyEval_SetTrace(builtin_func, pyfn), using the
465  * Python callable as the object in PyEval_SetTrace.  So sys.gettrace()
466  * simply returns the Python object used as the second argument to
467  * PyEval_SetTrace.  So sys.gettrace() will return our self parameter, which
468  * means it must be callable to be used in sys.settrace().
469  *
470  * So we make our self callable, equivalent to invoking our trace function.
471  *
472  * To help with the process of replaying stored frames, this function has an
473  * optional keyword argument:
474  *
475  *      def Tracer_call(frame, event, arg, lineno=0)
476  *
477  * If provided, the lineno argument is used as the line number, and the
478  * frame's f_lineno member is ignored.
479  */
480 static PyObject *
481 Tracer_call(Tracer *self, PyObject *args, PyObject *kwds)
482 {
      Message   this function is too complicated for the reference-count checker to fully analyze: not all paths were analyzed   maxtrans:   256483     PyFrameObject *frame;
484     PyObject *what_str;
485     PyObject *arg;
486     int lineno = 0;
487     int what;
488     int orig_lineno;
489     PyObject *ret = NULL;
490 
491     static char *what_names[] = {
492         "call", "exception", "line", "return",
493         "c_call", "c_exception", "c_return",
494         NULL
495         };
496 
497     #if WHAT_LOG
498     printf("pytrace\n");
499     #endif
500 
501     static char *kwlist[] = {"frame", "event", "arg", "lineno", NULL};
502 
503     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!O|i:Tracer_call", kwlist,
504             &PyFrame_Type, &frame, &MyText_Type, &what_str, &arg, &lineno)) {
505         goto done;
506     }
507 
508     /* In Python, the what argument is a string, we need to find an int
509        for the C function. */
510     for (what = 0; what_names[what]; what++) {
511         if (!strcmp(MyText_AS_STRING(what_str), what_names[what])) {
512             break;
513         }
514     }
515 
516     /* Save off the frame's lineno, and use the forced one, if provided. */
517     orig_lineno = frame->f_lineno;
518     if (lineno > 0) {
519         frame->f_lineno = lineno;
520     }
521 
522     /* Invoke the C function, and return ourselves. */
523     if (Tracer_trace(self, frame, what, arg) == RET_OK) {
524         Py_INCREF(self);
525         ret = (PyObject *)self;
526     }
527 
528     /* Clean up. */
529     frame->f_lineno = orig_lineno;
530 
531 done:
532     return ret;
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
      (emitted by cpychecker)TODO: a detailed trace is available in the data model (not yet rendered in this report)
533 }
534 
535 static PyObject *
536 Tracer_start(Tracer *self, PyObject *args_unused)
537 {
538     PyEval_SetTrace((Py_tracefunc)Tracer_trace, (PyObject*)self);
539     self->started = 1;
540     self->tracing_arcs = self->arcs && PyObject_IsTrue(self->arcs);
541     self->last_line = -1;
542 
543     /* start() returns a trace function usable with sys.settrace() */
544     Py_INCREF(self);
545     return (PyObject *)self;
546 }
547 
548 static PyObject *
549 Tracer_stop(Tracer *self, PyObject *args_unused)
550 {
551     if (self->started) {
552         PyEval_SetTrace(NULL, NULL);
553         self->started = 0;
554     }
555 
556     return Py_BuildValue("");
557 }
558 
559 static PyObject *
560 Tracer_get_stats(Tracer *self)
561 {
562 #if COLLECT_STATS
563     return Py_BuildValue(
564         "{sI,sI,sI,sI,sI,sI,sI,sI,si,sI}",
565         "calls", self->stats.calls,
566         "lines", self->stats.lines,
567         "returns", self->stats.returns,
568         "exceptions", self->stats.exceptions,
569         "others", self->stats.others,
570         "new_files", self->stats.new_files,
571         "missed_returns", self->stats.missed_returns,
572         "stack_reallocs", self->stats.stack_reallocs,
573         "stack_alloc", self->data_stack_alloc,
574         "errors", self->stats.errors
575         );
576 #else
577     return Py_BuildValue("");
578 #endif /* COLLECT_STATS */
579 }
580 
581 static PyMemberDef
582 Tracer_members[] = {
583     { "should_trace",       T_OBJECT, offsetof(Tracer, should_trace), 0,
584             PyDoc_STR("Function indicating whether to trace a file.") },
585 
586     { "warn",               T_OBJECT, offsetof(Tracer, warn), 0,
587             PyDoc_STR("Function for issuing warnings.") },
588 
589     { "data",               T_OBJECT, offsetof(Tracer, data), 0,
590             PyDoc_STR("The raw dictionary of trace data.") },
591 
592     { "should_trace_cache", T_OBJECT, offsetof(Tracer, should_trace_cache), 0,
593             PyDoc_STR("Dictionary caching should_trace results.") },
594 
595     { "arcs",               T_OBJECT, offsetof(Tracer, arcs), 0,
596             PyDoc_STR("Should we trace arcs, or just lines?") },
597 
598     { NULL }
599 };
600 
601 static PyMethodDef
602 Tracer_methods[] = {
603     { "start",      (PyCFunction) Tracer_start,         METH_VARARGS,
604             PyDoc_STR("Start the tracer") },
605 
606     { "stop",       (PyCFunction) Tracer_stop,          METH_VARARGS,
607             PyDoc_STR("Stop the tracer") },
608 
609     { "get_stats",  (PyCFunction) Tracer_get_stats,     METH_VARARGS,
      (emitted by cpychecker)610             PyDoc_STR("Get statistics about the tracing") },
611 
612     { NULL }
613 };
614 
615 static PyTypeObject
616 TracerType = {
617     MyType_HEAD_INIT
618     "coverage.Tracer",         /*tp_name*/
619     sizeof(Tracer),            /*tp_basicsize*/
620     0,                         /*tp_itemsize*/
621     (destructor)Tracer_dealloc, /*tp_dealloc*/
622     0,                         /*tp_print*/
623     0,                         /*tp_getattr*/
624     0,                         /*tp_setattr*/
625     0,                         /*tp_compare*/
626     0,                         /*tp_repr*/
627     0,                         /*tp_as_number*/
628     0,                         /*tp_as_sequence*/
629     0,                         /*tp_as_mapping*/
630     0,                         /*tp_hash */
631     (ternaryfunc)Tracer_call,  /*tp_call*/
632     0,                         /*tp_str*/
633     0,                         /*tp_getattro*/
634     0,                         /*tp_setattro*/
635     0,                         /*tp_as_buffer*/
636     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
637     "Tracer objects",          /* tp_doc */
638     0,                         /* tp_traverse */
639     0,                         /* tp_clear */
640     0,                         /* tp_richcompare */
641     0,                         /* tp_weaklistoffset */
642     0,                         /* tp_iter */
643     0,                         /* tp_iternext */
644     Tracer_methods,            /* tp_methods */
645     Tracer_members,            /* tp_members */
646     0,                         /* tp_getset */
647     0,                         /* tp_base */
648     0,                         /* tp_dict */
649     0,                         /* tp_descr_get */
650     0,                         /* tp_descr_set */
651     0,                         /* tp_dictoffset */
652     (initproc)Tracer_init,     /* tp_init */
653     0,                         /* tp_alloc */
654     0,                         /* tp_new */
655 };
656 
657 /* Module definition */
658 
659 #define MODULE_DOC PyDoc_STR("Fast coverage tracer.")
660 
661 #if PY_MAJOR_VERSION >= 3
662 
663 static PyModuleDef
664 moduledef = {
665     PyModuleDef_HEAD_INIT,
666     "coverage.tracer",
667     MODULE_DOC,
668     -1,
669     NULL,       /* methods */
670     NULL,
671     NULL,       /* traverse */
672     NULL,       /* clear */
673     NULL
674 };
675 
676 
677 PyObject *
678 PyInit_tracer(void)
679 {
680     PyObject * mod = PyModule_Create(&moduledef);
681     if (mod == NULL) {
682         return NULL;
683     }
684 
685     TracerType.tp_new = PyType_GenericNew;
686     if (PyType_Ready(&TracerType) < 0) {
687         Py_DECREF(mod);
688         return NULL;
689     }
690 
691     Py_INCREF(&TracerType);
692     PyModule_AddObject(mod, "Tracer", (PyObject *)&TracerType);
      traceback:   Traceback (most recent call last):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/__init__.py", line 131, in _check_refcounts
    self.options)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4355, in check_refcounts
    rep = impl_check_refcounts(ctxt, fun, options)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 4213, in impl_check_refcounts
    limits=limits)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3089, in iter_traces
    depth + 1):
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 3053, in iter_traces
    transitions = curstate.get_transitions()
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2105, in get_transitions
    return self._get_transitions_for_stmt(stmt)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2121, in _get_transitions_for_stmt
    return self._get_transitions_for_GimpleCall(stmt)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/absinterp.py", line 2292, in _get_transitions_for_GimpleCall
    return meth(stmt, *args)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 2544, in impl_PyModule_AddObject
    s_success.cpython.steal_reference(v_value, stmt.loc)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 741, in steal_reference
    _steal_ref)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/libcpychecker/refcounts.py", line 551, in change_refcount
    check_isinstance(oldvalue, RefcountValue)
  File "/usr/lib/gcc/x86_64-redhat-linux/4.7.2/plugin/python2/gccutils.py", line 642, in check_isinstance
    raise TypeError('%s / %r is not an instance of %s' % (obj, obj, types))
TypeError: (long int)val [-0x7fffffffffffffff <= val <= 0x7fffffffffffffff] from coverage/tracer.c:691 / WithinRange(gcctype='long int', loc=gcc.Location(file='coverage/tracer.c', line=691), minvalue=-0x7fffffffffffffff, maxvalue=0x7fffffffffffffff) is not an instance of <class 'libcpychecker.refcounts.RefcountValue'>
693 
694     return mod;
695 }
696 
697 #else
698 
699 void
700 inittracer(void)
701 {
702     PyObject * mod;
703 
704     mod = Py_InitModule3("coverage.tracer", NULL, MODULE_DOC);
705     if (mod == NULL) {
706         return;
707     }
708 
709     TracerType.tp_new = PyType_GenericNew;
710     if (PyType_Ready(&TracerType) < 0) {
711         return;
712     }
713 
714     Py_INCREF(&TracerType);
715     PyModule_AddObject(mod, "Tracer", (PyObject *)&TracerType);
716 }
717 
718 #endif /* Py3k */