0

Is there a compiler flag that logs warning / error in case of any implicit conversions - like int32_t to uint32_t.

#include <cstdint>
#include <iostream>


using ::std::int32_t;
using ::std::uint32_t;


int main(int argc, char *argv[])
{

   int32_t x = 9;

    uint32_t i = x;

    std::cout << " " << x << " " << i << std::flush << std::endl;

    return 0;
}

c++ -std=c++11 -Wall -Wconversion -Wpedantic cast.cpp

I get no issues / warning / error during compilation - is there a way it can achieved.

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
Programmer
  • 8,303
  • 23
  • 78
  • 162
  • That's probably not a very good example as the compiler can see that `9` doesn't cause conversion errors. – Ken Y-N Mar 05 '18 at 06:35
  • [You should not tag in title](https://meta.stackexchange.com/questions/19190/should-questions-include-tags-in-their-titles). – user202729 Mar 05 '18 at 06:40
  • Thanks - I understand your point but is there a way that C++ compiler throws a warning / error in such implicit conversions? – Programmer Mar 05 '18 at 06:56
  • Possible duplicate of [Warnings or errors for C++ implicit conversion of primitives](https://stackoverflow.com/questions/4477139/warnings-or-errors-for-c-implicit-conversion-of-primitives) – Amith Mar 05 '18 at 07:00

2 Answers2

2
uint32_t i = x;

Signed int type to unsigned int type conversion is well defined in C++.

(C++11, §4.7 ¶2)

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). — end note ]

Gyapti Jain
  • 4,056
  • 20
  • 40
  • Thanks - can you please explain a bit more on C++ rule stated above and any technique to let compiler state warning / error during compilation? – Programmer Mar 05 '18 at 06:57
  • Rule means converting a positive signed int to unsigned int of same width is not a problem. Converting negative signed int to unsigned int of same width is same as adding pow(2, width in bits). – Gyapti Jain Mar 05 '18 at 07:09
  • I think -Wall -Wconversion -Wsign-conversion fixes the issue - thanks for the lead – Programmer Mar 05 '18 at 08:28
1

I don't know of a compiler that provides such a flag (though it's always possible I've missed one).

Lacking it, you could build a little template that will make such implicit conversions impossible in at least a few obvious situations:

#include <cstdint>
#include <iostream>

using ::std::int32_t;
using ::std::uint32_t;

template <class T>
class holder {
    T value;
public:
    holder(T value) : value(value) {}
    operator T&() { return value; }
    operator T() const { return value; }
    holder &operator=(holder const &other) { value = other.value; return *this; }
};

int main(int argc, char *argv[]) {
    holder<int32_t> x = 9;

    holder<uint32_t> i = x;

    ++i;

    std::cout << " " << x << " " << i << "\n";
}

Attempting to compile with g++ gives:

trash9.cpp:20:23: error: conversion from 'holder<int>' to non-scalar type 'holder<unsigned int>' requested
  holder<uint32_t> i = x;
                       ^

If, however, we change the second to holder<int32_t> i = x; it all works fine and acts as expected.

This suffices for the demo code you've given, but won't work in all situations. In particular, an implicit conversion in the course of evaluating an expression will still be allowed:

void use(holder<uint32_t> v) {
    std::cout << v;
}

int main(int argc, char *argv[]) {
    holder<int32_t> x = 9;

    holder<int32_t> i = x;

    use(i | 1u);
}

If you want to prevent conversions in cases like that as well, you can do it, but it's going to be a lot more work--you'll need to remove the operator T and operator T& from the code above, and then implement all the operators you do want to support. That would/will probably be tedious to the point that it's at least mildly painful, but you might find it acceptable anyway.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Thanks for the information - would the template version also solve for a function returning int32_t to an uint32_t variable? uint32_t x = fn(..) returning int32_t – Programmer Mar 05 '18 at 07:08
  • If you used `holder x = fn(...);` and `fn` was defined to return an `int32_t`, then yes, the code would be rejected (i.e., wouldn't compile). – Jerry Coffin Mar 05 '18 at 07:20
  • I think -Wall -Wconversion -Wsign-conversion fixes the issue – Programmer Mar 05 '18 at 08:27