c++gccwarningsfinal

Cleanly suppress gcc's `final` suggestion warnings (`-Wsuggest-final-types` and `-Wsuggest-final-methods`)


I like compiling my code using -Wsuggest-final-types and -Wsuggest-final-methods in order to be warned about opportunities where the final keyword could be used to allow the compiler to optimize more aggressively.

Sometimes, though, the suggestions are incorrect - for example, I have a class Base with a virtual ~Base() destructor that is used polymorphically in another project, and gcc suggests me that Base could be marked as final.

Is there a way to "cleanly" tell the compiler that Base is used polymorphically and should not be marked as final?

The only way I can think of is using #pragma directives, but I find it makes the code cluttered and hard to read.

Ideally, I'm looking for a non-final keyword or attribute that can be prepended/appended to the class/method declaration.


Solution

  • I came up with a macro-based solution that I really don't like, but it solves the problem.

    #define MARK_NONFINAL_CLASS(base)                              \
        namespace SOME_UNIQUE_NAME                                 \
        {                                                          \
            struct [[unused]] temp_marker final : base             \
            {                                                      \
            };                                                     \
        }
    
    #define MARK_NONFINAL_METHOD(base, return_type, method)                  \
        namespace SOME_UNIQUE_NAME                                           \
        {                                                                    \
            struct [[unused]] temp_marker final : base                       \
            {                                                                \
                inline return_type [[unused]] method override {}             \
            };                                                               \
        }
    

    Usage:

    class Base
    {
        virtual ~Base()
        {
        }
    
        virtual int a(float f)
        {
        }
        virtual void b(double)
        {
        }
    };
    
    MARK_NONFINAL_CLASS(Base)
    MARK_NONFINAL_METHOD(Base, int, a(float))
    MARK_NONFINAL_METHOD(Base, void, b(double))