Get number of unique operators and operands for calculation of Halstead metrics

Hi all,

Can anyone help me with this. How can i find number of unique operators and operands in a function. Here’s what i am doing.
I first got an CFG of the function and then i am going through each block. I am stuck after that, i dont know how to parse each Stmt/Expr in a block to get operators and operands ?


You can gather this information by walking the abstract syntax tree. Look for StmtVisitor in the Clang code-base; it will help you walk the AST so you can count operators and operands.

  - Doug

Hi Manavender,

I don't know if your metrics actually require a CFG, or just can be done with a walk on the AST.

Assuming you are starting with a FunctionDecl*, it is possible to query the FunctionDecl for its body (getBody()). That value will be a Stmt*. After that, you can walk the AST using a variety of schemes. To "pattern match" a Stmt* against a particular AST kind (i.e., a subclass of Stmt), do:

  if (CallExpr *CE = dyn_cast<CallExpr>(S))

There are plenty of examples like this in the Clang codebase. Specific Stmt/Expr classes will have accessors to their subexpressions, but there is also a generic iterator interface in Stmt (child_begin(), child_end()) which allows you to recursively walk the AST. We also have various visitor classes that you can use, e.g. StmtVisitor, RecursiveASTVisitor, which also have example uses in the codebase.

Using the CFG is a bit tricker. The CFG consists of basic blocks, which you can iterate through. Each CFGBlock contains an ordered set of statements, and those statements can be traversed just like you would traverse an AST. The main catch is that CFGBlocks have a notion of "block-level expression", which are the Stmt* that appear in the ordered set (not all subexpressions appear in the set). Those block-level expressions may appear as subexpressions of later block-level expressions, but they are ordered in the CFGBlock to represent control-flow dependencies.


Thanks guys :slight_smile: