How to obtain warning for forgotten cast in arithmetic?

前端 未结 3 1609
悲哀的现实
悲哀的现实 2021-01-13 13:01

Consider this situation:

uint64_t add(uint32_t a, uint32_t b)
{
   return a + b; // programmer neglected (uint64_t) a + b.
}

How do we get

3条回答
  •  Happy的楠姐
    2021-01-13 13:44

    Since the code I'm working with compiles as C or C++, and the types in question are all typedefs (which are easily retargeted to classes), it occurs to me that a C++ solution is possible. The following code sample hints at the idea:

    #include 
    
    template  class arith {
    public:
      underlying val;
    
      arith(underlying v) : val(v) { }
      explicit operator underlying () const { return val; }
      outer operator +(const inner &rhs) { return val + rhs.val; }
    };
    
    struct narrow;
    
    struct narrow_result : public arith {
      narrow_result(uint32_t v) : arith(v) { }
      narrow_result(const narrow &v);
    };
    
    struct narrow : public arith {
      narrow(uint32_t v) : arith(v) { }
      narrow(const narrow_result &v) : arith(v.val) { }
    };
    
    inline narrow_result::narrow_result(const narrow &v)
    : arith(v.val)
    {
    }
    
    struct wide {
      uint64_t val;
    
      wide(uint64_t v) : val(v) { }
      wide(const narrow &v) : val(v) { }
      operator uint64_t () const { return val; }
      wide operator +(const wide &rhs) { return val + rhs.val; }
    };
    
    int main()
    {
      narrow a = 42;
      narrow b = 9;
      wide c = wide(a) + b;
      wide d = a + b;          // line 43
      narrow e = a + b;
      wide f = a;              // line 45
      narrow g = a + b + b;    // line 46
      return 0;
    }
    

    Here, GNU C++ diagnoses only line 43:

    overflow.cc: In function ‘int main()’:
    overflow.cc:43:16: error: conversion from ‘narrow_result’ to non-scalar type ‘wide’ requested
    

    Note that a narrow to wide implicit conversion is still allowed, as seen in line 45, simply because wide has a conversion constructor targeting narrow directly. It just lacks one for narrow_result.

    Line 46 shows that we can compound the arithmetic operations. This is possible because narrow implicitly converts to narrow_result and vice versa. However, this implicit conversion doesn't kick in on line 45; the narrow_result of the addition doesn't convert to narrow so that this could then convert to wide.

    This can all be wrapped with #ifdef __cplusplus and the presence of a conditional debug macro, that same macro also enabling alternative definitions of the types as typedefs for narrow and wide. Of course, numerous other arithmetic operations must be supported in the arith template base.

提交回复
热议问题