llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.12k stars 12.01k forks source link

-Wconversion missing warning on truncation #34757

Open LebedevRI opened 6 years ago

LebedevRI commented 6 years ago
Bugzilla Link 35409
Version trunk
OS Linux

Extended Description

With Serus's help in IRC, the following issue was discovered:

#include <stdint.h>
#include <stdio.h>
#include <limits>

template<typename T>
T mul(T a, T b) {
  printf("%u * %u", a, b);
  T c = a * b;
  printf(" = %u\n", c);
  return c;
}

int main(int argc, char *[]) {
    mul(static_cast<unsigned char>(argc), std::numeric_limits<unsigned char>::max());
    return 0;
}
GCC output:
$ g++ -std=c++14 -O2 -Wall -Wextra -Wconversion -pedantic -pthread main.cpp && ./a.out a b
main.cpp: In instantiation of 'T mul(T, T) [with T = unsigned char]':
main.cpp:14:84:   required from here
main.cpp:8:11: warning: conversion to 'unsigned char' from 'int' may alter its value [-Wconversion]
   T c = a * b;
         ~~^~~
3 * 255 = 253
Clang output:
clang++ -std=c++14 -O2 -Wall -Weverything -Wno-c++98-compat -pedantic -pthread main.cpp && ./a.out a b
3 * 255 = 253

An alternative variant of the testcase, on which clang does warn:

#include <stdint.h>
#include <stdio.h>
#include <limits>

template<typename T>
T mul(T a, T b) {
  printf("%u * %u", a, b);
  auto c = a * b;
  T d = c;
  printf(" = %u\n", c);
  return d;
}

int main(int argc, char *[]) {
    mul(static_cast<unsigned char>(argc), std::numeric_limits<unsigned char>::max());
    return 0;
}
clang++ -std=c++14 -O2 -Wall -Weverything -Wno-c++98-compat -pedantic -pthread main.cpp && ./a.out a b
main.cpp:9:9: warning: implicit conversion loses integer precision: 'int' to 'unsigned char' [-Wconversion]
  T d = c;
    ~   ^
main.cpp:15:5: note: in instantiation of function template specialization 'mul<unsigned char>' requested here
    mul(static_cast<unsigned char>(argc), std::numeric_limits<unsigned char>::max());
    ^
1 warning generated.
3 * 255 = 765
mclow commented 2 years ago

mentioned in issue llvm/llvm-bugzilla-archive#37552

llvmbot commented 4 months ago

@llvm/issue-subscribers-clang-static-analyzer

Author: Roman Lebedev (LebedevRI)

| | | | --- | --- | | Bugzilla Link | [35409](https://llvm.org/bz35409) | | Version | trunk | | OS | Linux | ## Extended Description With Serus's help in IRC, the following issue was discovered: ```cpp #include <stdint.h> #include <stdio.h> #include <limits> template<typename T> T mul(T a, T b) { printf("%u * %u", a, b); T c = a * b; printf(" = %u\n", c); return c; } int main(int argc, char *[]) { mul(static_cast<unsigned char>(argc), std::numeric_limits<unsigned char>::max()); return 0; } ``` ``` GCC output: $ g++ -std=c++14 -O2 -Wall -Wextra -Wconversion -pedantic -pthread main.cpp && ./a.out a b main.cpp: In instantiation of 'T mul(T, T) [with T = unsigned char]': main.cpp:14:84: required from here main.cpp:8:11: warning: conversion to 'unsigned char' from 'int' may alter its value [-Wconversion] T c = a * b; ~~^~~ 3 * 255 = 253 ``` ``` Clang output: clang++ -std=c++14 -O2 -Wall -Weverything -Wno-c++98-compat -pedantic -pthread main.cpp && ./a.out a b 3 * 255 = 253 ``` An alternative variant of the testcase, on which clang does warn: ```cpp #include <stdint.h> #include <stdio.h> #include <limits> template<typename T> T mul(T a, T b) { printf("%u * %u", a, b); auto c = a * b; T d = c; printf(" = %u\n", c); return d; } int main(int argc, char *[]) { mul(static_cast<unsigned char>(argc), std::numeric_limits<unsigned char>::max()); return 0; } ``` ``` clang++ -std=c++14 -O2 -Wall -Weverything -Wno-c++98-compat -pedantic -pthread main.cpp && ./a.out a b main.cpp:9:9: warning: implicit conversion loses integer precision: 'int' to 'unsigned char' [-Wconversion] T d = c; ~ ^ main.cpp:15:5: note: in instantiation of function template specialization 'mul<unsigned char>' requested here mul(static_cast<unsigned char>(argc), std::numeric_limits<unsigned char>::max()); ^ 1 warning generated. 3 * 255 = 765 ```