How To Silence C++ Warnings

A cookbook to make common pesky warnings go away so that the important ones can be seen.

Most common CASA Warnings by G++ identifier (G++ puts these at the end of the warning message):

Common warning messages (linked to solutions):

Deprecated conversion from string constant to 'char*'

This appears to be cause by statements similar to

char * s = "A String";

and be fixed by changing it to something like

const char * s = "A String";

Comparison between signed and unsigned integer expressions

Many of the casacore and STL containers return unsigned integers for their size-related methods. In the example below the compiler will find an int on the left of the "<" and an unsigned int on the right hand side causing it to issue a warning.

Vector v = anotherVector;
for (Int i = 0; i < v.nelements(); i++){
   doSomething();
}

The solution is to make the types match across the "<" operator.

for (uInt i = 0; i < v.nelements(); i++){

// OR

for (Int i = 0; i < static_cast<Int> (v.nelements()); i++){

Changing the type of the loop variable could possibly affect the contents of the loop body so the second solution might be safer. You could use a c-style type cast as well but that use is discouraged by the C++ community (c-style casts are not checked and can be used to do some fairly unsafe things).

Unused variable

Double f (Int a) { Int aSq = a * a; return pow (a, 2);}

The solution is to remove the unused variable. Sometimes the unused variable is receiving the result of method call; in that case in can be dangerous to remove the method call since it might have important side-effects.

If the variable is useful for debugging purposes you can try another trick: ((void) theVariable);. This basically does nothing but it makes the warning part of the compiler happy, while the optimizer will recognize it for a noop and remove it.

Unused parameter

Int f (Int a, Int b, Int c) { return a + c;}
inf g (Int a, Int b = 42, Int c) { return a + c;}

The solution is to comment out the variable name in the function/method header. You could also delete the name entirely, however, leaving it there might provide some useful context if the method is later modified (e.g., to make use of the variable).

Int f (Int a, Int /*b*/, Int c) { return a + c;}
inf g (Int a, Int /*b*/ = 42, Int c) { return a + c;}

Comparison of unsigned expression >= 0 is always true

The comparison can be replaced with true. If it's the only condition of an if and there's an else further investigation is warranted.

base class 'class casa::PlotFont' should be explicitly initialized in the copy constructor

class A {}
class B : public A {}

B::B (const B & other) {// whatever}

The compiler is uncertain how you want to initialize the "A" part of "B":

B::B (const B & other) : A() {//whatever}

// OR

B::B (const B & other) : A(other) {//whatever}

and is asking you to explicitly chose between them. If left to its own devices the compiler will call A().

'SomeMemberVariable' will be initialized after 'anotherMemberVariable'

This warning occurs when a constructor has an explicit initializer list where the order of initialization is differs from the order of declaration; for example:

class C {
public:
    C() : b(0), a(0) {}
private:
   Int a;
   Int b;
}

The solution is to either reorder the initializers or the declarations. Think through the ordering before you recompile or you will likely get another ordering warning.

Reference to local variable 'aVariable' returned

Vector & emptyVector () { Vector aVariable; return aVariable;}

This one is actually an accident waiting to happen. When emptyVector is exited, the stack storage for aVariable is reclaimed, though it's not immediately overwritten. So a use case like Vector myVector = emptyVector(); can actually work correctly despite its illegality. However, a sequence like:

Vector<Int> & refToVector = emptyVector();
doSomething();
Vector<Int> anotherVector = refToVector();

could very likely produce unpredictable and undesirable results.

This seems to occur when "stubbing" out a class. The warning will go away if the local declaration is made static:

Vector<Int> & emptyVector () 
{ 
    static Vector<Int> aVariable;
    return aVariable;
}

Control reaches end of non-void function

Occurs when a method/function with a return type other than void can exit without executing a return something statement. This could actually be an error or it could be that a series of conditional statements have covered the entire value space making it impossible to reach the end of the code.

The solution for correct code is to either rewrite the conditional code so that it cannot reach the end of the routine (e.g., change the last else-if+ to an =else) or to protect the end of the routine with a throw AipsError (...) since if the code does ever reach the end of the routine then something unintended is happening and it would be good to know about it.

Enumeration value X not handled in switch

The compiler is pointing out that the switch statement is not handling all elements defined in the enumeration used as the parameter to switch (x).

There are two solutions. First, look to see if some of the values in the enumeration set are missing. If so, add cases for them in the switch. If the missing cases are not expected to be handled and are there are not too many of them, just add in cases for them followed by break;. When there are numerous cases that are intentionally not handled, you can add a default: case to handle them; this is not the preferred approach if it is at all possible that additional cases might be added in the future since the person adding them may not find the switch statements to add in handling for the new enumeration value. The last solution is to add in a default: case but have it throw and AipsError; this way if an enumeration value was forgotten either now or in the future, a runtime error will occur which is easier to debug than having the case mishandled.

Suggest explicit braces to avoid ambiguous 'else' or Suggest parantheses ...

The compiler is flagging the existing construct as one that easily confuses the reader and writer about the actual intent of the statement. By using parantheses or braces the meaning will be made unambiguous.

-- JimJacobs - 2013-10-31
Topic revision: r7 - 2015-11-17, JimJacobs
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding NRAO Public Wiki? Send feedback