Skip to content

SamuelMarks/type-correct

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

type-correct

CC0 x86-Darwin x86-Ubuntu-llvm-from-sources x86-Darwin-llvm-from-sources x86-Ubuntu

LLVM LibClang / LibTooling solution to 'fix' types, rewriting inconsistent use of types to make them consistent.

Automatic conversions

#include <string.h>

int main(void) {

    /* FROM */
    const int n = strlen("FOO");

    /* TO */
    const size_t n = strlen("FOO");

    /* FROM */
    for(int i=0; i<strlen("BAR"); i++) {}

    /* TO */
    for(size_t i=0; i<strlen("BAR"); i++) {}

    /* FROM */
    int f(long b) { return b; }
    static const int c = f(5);

    /* TO */
    long f(long b) { return b; }
    static const long c = f(5);
}

Justification

Often when building third-party libraries I get a bunch of warnings "comparison between signed and unsigned types is UB".

Not every such occurrence has a trivial solution. But—in my experience—most do. Usually switching just one var from int to size_t also requires tracing all use of that var and changing all those types to size_t also.

From:

unsigned long f() {return 0;}
const size_t v = f();

int main() {
    std::vector<float> vec;
    for(int i=0; i<vec.size(); i++) {}
}

To:

unsigned long f() {return 0;}
const unsigned long v = f();

int main() {
    std::vector<float> vec;
    for(size_t i=0; i<vec.size(); i++) {}
}

PS: I'm aware that size_type isn't necessarily size_t—and that decltype(vec)::size_type would be more correct—but using it here anyway. Just to reiterate: C++ is an afterthought, my main target is C.

Integer promotion

#include <limits.h>

short sh=SHRT_MAX;
int i=INT_MAX;
long l=LONG_MAX;
long long ll=LLONG_MAX; /* C99 */

Technically, these are all defined and expected [on clang as an ImplicitCastExpr]:

ll = l;
l = i;
i = sh;

(but the other direction, 'narrowing', is implementation defined)

However, IMHO, people doing int sl = strlen(s); actually want size_t. This opinionated view is the assumption made for type_correct.

But… attempts are made to be reasonably conservative. See type_correct/tests/test_type_correct.cpp for false positive and true positive checks.

Build instructions

Install compiler suite, CMake, and LLVM (from brew, apt, or source), then run:

mkdir build && cd build
cmake .. \
      -DCMAKE_BUILD_TYPE='Debug' \
      -DCT_Clang_INSTALL_DIR='/usr/local/opt/llvm'

(replace /usr/local/opt/llvm with your LLVM install dir)

Thanks

Boilerplate from https://github.com/banach-space/clang-tutor


License

The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law.

You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. See Other Information below.

Other Information

  • In no way are the patent or trademark rights of any person affected by CC0, nor are the rights that other persons may have in the work or in how the work is used, such as publicity or privacy rights.
  • Unless expressly stated otherwise, the person who associated a work with this deed makes no warranties about the work, and disclaims liability for all uses of the work, to the fullest extent permitted by applicable law.
  • When using or citing the work, you should not imply endorsement by the author or the affirmer.