Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a tool to add the "override" identifier to existing C++ code

Tags:

The task

I am trying to work out how best to add C++0x's override identifier to all existing methods that are already overrides in a large body of C++ code, without doing it manually.

(We have many, many hundreds of thousands of lines of code, and doing it manually would be a complete non-starter.)

Current idea

Our coding standards say that we should add the virtual keyword against all implicitly virtual methods in derived classes, even though strictly unnecessary (to aid comprehension).

So if I were to script the addition myself, I'd write a script that read all our headers, found all functions beginning with virtual, and insert override before the following semi-colon. Then compile it on a compiler that supports override, and fix all the errors in base classes.

But I'd really much rather not use this home-grown way, as:

  • it's obviously going to be tedious and error-prone.
  • not everyone has remembered, every time, to add the virtual keyword, so this method would miss out some existing overrides

Is there an existing tool?

So, is there already a tool that parses C++ code, detects existing methods that overrides, and appends override to their declarations?

(I am aware of static analysis tools such as PC-lint that warn about functions that look like they should be overrides. What I'm after is something that would actually munge our code, so that future errors in overrides will be detected at compiler-time, rather than later on in static analysis)

(In case anyone is tempted to point out that C++03 doesn't support 'override'... In practice, I'd be adding a macro, rather than the actual "override" identifier, to use our code on older compilers that don't support this feature. So after the identifier was added, I'd run a separate script to replace it with whatever macro we're going to use...)

Thanks in advance...

like image 291
Clare Macrae Avatar asked Sep 03 '11 14:09

Clare Macrae


People also ask

Which keyword is used for overriding?

In that case, we can use the override keyword. This keyword is introduced in C+ +11. When the compiler finds this kind of keyword, it can understand that this is an overridden version of the same class. Let us see the example to understand the concept.

Is the override keyword required?

You don't need the override identifier to do this in C++, it simply enforces that you are doing it properly.

What is override in C?

Suppose, the same function is defined in both the derived class and the based class. Now if we call this function using the object of the derived class, the function of the derived class is executed. This is known as function overriding in C++. The function in derived class overrides the function in base class.

What is override in C ++ 11?

C++11 adds two inheritance control keywords: override and final. override ensures that an overriding virtual function declared in a derived class has the same signature as that of the base class. final blocks further derivation of a class and further overriding of a virtual function.


2 Answers

There is a tool under development by the LLVM project called "cpp11-migrate" which currently has the following features:

  • convert loops to range-based for loops
  • convert null pointer constants (like NULL or 0) to C++11 nullptr
  • replace the type specifier in variable declarations with the auto type specifier
  • add the override specifier to applicable member functions

This tool is documented here and should be released as part of clang 3.3. However, you can download the source and build it yourself today.

Edit

Some more info:

  • Status of the C++11 Migrator - a blog post, dated 2013-04-15
  • cpp11-migrate User’s Manual

Edit 2: 2013-09-07

"cpp11-migrate" has been renamed to "clang-modernize". For windows users, it is now included in the new LLVM Snapshot Builds.

Edit 3: 2020-10-07

"clang-modernize" has bee renamed to "Clang-Tidy".

like image 71
Marshall Clow Avatar answered Oct 09 '22 10:10

Marshall Clow


Our DMS Software Reengineering Toolkit with its C++11-capable C++ Front End can do this.

DMS is a general purpose program transformation system for arbitrary programming languages; the C++ front end allows it to process C++. DMS parses, builds ASTs and symbol tables that are accurate (this is hard to do for C++), provides support for querying properties of the AST nodes and trees, allows procedural and source-to-source transformations on the tree. After all changes are made, the modified tree can be regenerated with comments retained.

Your problem requires that you find derived virtual methods and change them. A DMS source-to-source transformation rule to do that would look something like:

    source domain Cpp.  -- tells DMS the following rules are for C++

    rule insert_virtual_keyword (n:identifier, a: arguments, s: statements):
       method_declaration -> method_declaration " =
       " void \n(\a) { \s } "  ->  " virtual void \n(\a) { \s }"
       if is_implicitly_virtual(n).

Such rules match against the syntax trees, so they can't mismatch to a comment, string, or whatever. The funny quotes are not C++ string quotes; they are meta-quotes to allow the rule language to know that what is inside them has to be treated as target language ("Cpp") syntax. The backslashes are escapes from the target language text, allowing matches to arbitrary structures e.g., \a indicates a need for an "a", which is defined to be the syntactic category "arguments".

You'd need more rules to handle cases where the function returns a non-void result, etc. but you shouldn't need a lot of them.

The fun part is implementing the predicate (returning TRUE or FALSE) controlling application of the transformation: is_implicitly_virtual. This predicate takes (an abstract syntax tree for) the method name n. This predicate would consult the full C++ symbol table to determine what n really is. We already know it is a method from just its syntactic setting, but we want to know in what class context. The symbol table provides the linkage between the method and class, and the symbol table information for the class tells us what the class inherits from, and for those classes, which methods they contain and how they are declared, eventually leading to the discovery (or not) that the parent class method is virtual. The code to do this has to be implemented as procedural code going against the C++ symbol table API. However, all the hard work is done; the symbol table is correct and contains references to all the other data needed. (If you don't have this information, you can't possibly decide algorithmically, and any code changes will likely be erroneous).

DMS has been used to carry out massive changes on C++ code in the past using program transformations.(Check the Papers page at the web site for C++ rearchitecting topics).

(I'm not a C++ expert, merely the DMS architect, so if I have minor detail wrong, please forgive.)

like image 30
Ira Baxter Avatar answered Oct 09 '22 09:10

Ira Baxter