Vijay
Vijay

Reputation: 111

Automatically flag unused structure members in C

I need a tool to automatically flag unused structure members in a C codebase. My definition of "unused" is simple - if the structure member definition is removed from the code, and the code compiles successfully, then the structure member is declared unused. The question is - how can this be done in an automated way? (speed isn't too much of concern as the codebase is small).

The existing stack overflow articles on this topic seem to hint that there is no existing static analysis tool that can do this today. On the other hand, given the modularity of Clang, I feel that this should be doable with AST manipulation. Let's take a single file, for example. What I would like to do is the following (this can be later generalized to a set of source files in the codebase):

  1. Generate AST from C code.
  2. Recursively visit all structure field defintions and remove them one-by-one. We can keep a "seen" dictionary to ensure we don't remove already seen field definition nodes.
    • Filter out field definitions to only those that are present in the codebase to analyzed (to avoid definitions in standard libraries, for example).
  3. Compile the code.
  4. If the code compiles successfully, then the corresponding field declaration is unused and is flagged.
  5. Proceed to #1.

The keyword above is remove. How can I remove a field definition? There seems to be two ways using Clang.

  1. At a source level, we can remove the field declaration using Clang Rewriter (there is a "RemoveText(SourceRange)" option). But, I don't know if this will work all the time (ex: for structures are autogenerated using MACRO expansion).
  2. Delete the field declaration node from AST, and then "re-compile" the AST (whatever that means).

Among the above two options, #1 seems hacky - you'll need to create a copy of the source file, re-write it after a field definition is removed, and then re-compile the modified source. And, I am not sure how well it will work when there are complex MACROS involved for generating structure field definitions.

#2 seems clean, but from Googling, there seems to be no such thing as "deleting a AST node" (it is immutable). Please correct me if I am wrong. Even if I succeed in this, how I proceed from this point to re-evaluate the AST for missing references to structure fields? ("the compilation" step).

Any sugesstions appreciated (thanks in advance!). I've already have some initial success with #1 approach above, but I feel that this isn't the right direction.

Upvotes: 3

Views: 512

Answers (1)

icebp
icebp

Reputation: 1709

cppcheck can do this. For example:

// test.cpp
struct Struct
{
    int used;
    int unused;
};

int main()
{
    Struct s;
    s.used = 0;
    return s.used;
}
$ cppcheck test.cpp --enable=all
Checking test.cpp ...
test.cpp:5:9: style: struct member 'Struct::unused' is never used. [unusedStructMember]
    int unused;
        ^

While I used C++ code in the example it behaves the same for C.

Upvotes: 3

Related Questions