Start here

Home
About Klocwork
What's new
Fixed issues
Release notes
Installation

Reference

C/C++ checkers
Java checkers
C# checkers
MISRA C 2004 checkers
MISRA C++ 2008 checkers
MISRA C 2012 checkers
MISRA C 2012 checkers with Amendment 1
Commands
Metrics
Troubleshooting
Reference

Product components

C/C++ Integration build analysis
Java Integration build analysis
Desktop analysis
Refactoring
Klocwork Static Code Analysis
Klocwork Code Review
Structure101
Tuning
Custom checkers

Coding environments

Visual Studio
Eclipse for C/C++
Eclipse for Java
IntelliJ IDEA
Other

Administration

Project configuration
Build configuration
Administration
Analysis performance
Server performance
Security/permissions
Licensing
Klocwork Static Code Analysis Web API
Klocwork Code Review Web API

Community

View help online
Visit RogueWave.com
Klocwork Support
Rogue Wave Videos

Legal

Legal information

Example 3: Listing classes and members

In this example, we'll use the semantics tree to find all the members of the class to which the node of interest belongs. Once we've found them, for now, we're just going to log them and return a place-holder.

Creating new test case code

First, let's modify our testcase.cc code, so that it reads like this:

 class CFoo
 {
 public:
   CFoo() { init(); }
   CFoo(int x) { init(x); }
   void init(int x = 0, const char* y = 0);
  
 private:
   int m_x;
   const char* m_y;
 };
  
 void CFoo::init(int x, const char* y)
 {
   m_x = x;
   m_y = y;
 }


Adding a check for class

Next, we'll modify the checker pattern so that the checker gets invoked only for function definitions for the 'init' function. We'll switch back to a simple custom predicate function type, as we're just going to log the function name, and we'll call it listClassInfo():

<error id="EX.FIRST" enabled="true" severity="3"
  title="Function Definition" message="Called.">
  <pattern> 
    // FuncDef [ getName() = ‘init’] [
    listClassInfo() ]  
  </pattern>
</error>      

Now let's create our custom predicate so that it navigates up the semantics tree to our outer scope, validates that this outer scope is a class, and logs the name of the class in the build log:

 #include <stdio.h>
 #include <XPath_plugins.h>
 #include <ktcAPI.h>
   
 int listClassInfo(ktc_tree_t node)
 {      
   ktc_semanticInfo_t si = ktc_getSemanticInfo(node);
   if( ktc_sema_isFunction(si) )
   {
     ktc_semanticInfo_t ci = ktc_sema_getScope(si);
     if( ci && ktc_sema_isClass(ci) )
       fprintf(stderr, "Class name: %s\n", ktc_sema_getIdentifier(ci));
   }
  
   return 1;
 }
  
 HOOKS_SET_START
   XPath_register_int_hook("listClassInfo", listClassInfo);
 HOOKS_SET_END

When you execute this checker on the new test case, your build log should now contain a line reading:

Class name: CFoo

Adding a list of class members

We've made our way from a member function definition to its surrounding class scope, so now let's list all the class members and log them. The ktc API provides a simple means of iterating through all members of a class, or of any scope, which we can use by modifying the previous code:

 #include <stdio.h>
 #include <XPath_plugins.h>
 #include <ktcAPI.h>
  
 void logger(ktc_semanticInfo_t mi)
 {
   fprintf(stderr, "\tMember: %s\n", ktc_sema_getQualifiedName(mi));
 }
  
 int listClassInfo(ktc_tree_t node)
 {      
   ktc_semanticInfo_t si = ktc_getSemanticInfo(node);
   if( ktc_sema_isFunction(si) )
   {
     ktc_semanticInfo_t ci = ktc_sema_getScope(si);
     if( ci && ktc_sema_isClass(ci) )
     {
       fprintf(stderr, "Class name: %s\n", ktc_sema_getIdentifier(ci));
       ktc_sema_forAllClassDeclarations(ci, logger);
     }
   }
        
   return 1;
 }
  
 HOOKS_SET_START
   XPath_register_int_hook("listClassInfo", listClassInfo);
 HOOKS_SET_END

When you execute the checker, you should see the following entries in the build log:

Class name: CFoo
        Member: CFoo::#destructor
        Member: CFoo::m_x
        Member: CFoo::m_y
        Member: CFoo::#constructor
        Member: CFoo::#constructor
        Member: CFoo::init
        Member: CFoo::init

Filtering the logger function

The checker logs each declaration or definition of a class member, whether it's a method or a variable. To narrow it down to just the member variables, we can add a filter in the logger() function:

 void logger(ktc_semanticInfo_t mi)
 {
   if( ktc_sema_isVariable(mi) )
     fprintf(stderr, "\tMember: %s\n", ktc_sema_getQualifiedName(mi));
 }


Now the build log will contain:

Class name: CFoo
        Member: CFoo::m_x
        Member: CFoo::m_y