Flint++ is cross-platform, zero-dependency port of flint, a lint program for C++ developed and used at Facebook.

Overview

Flint++

A Cross Platform Port of Facebook's C++ Linter

Flint++ is cross-platform, zero-dependency port of flint, a lint program for C++ developed and used at Facebook.

This project was motivated by a desire for a modern and extendable C++ Linter that just worked. Facebook had already done a fantastic job with their flint project; but through an unnecessarily high number of dependencies, poor documentation, and OS dependent coding the project is almost unusable. Flint++ aims to solve these problems by only using the C++11 std::library along with a minimal number of polyfill functions developed to bridge the gaps in the needed functionality.

The original flint is published on Github; and for discussions, there is a Google group.

Upcoming Features

  • More lint tests!
  • Visual Studio Integration!
  • JSON Config files to allow project dependent Lint settings
    • Set custom blacklisted identifiers/token sequences/includes
    • Enable/Disable certain tests
    • Track the config file with Git to give everyone on your team the same Lint checks

Current Lint Checks

  • Errors
    • Blacklisted Identifiers
    • Initialization from Self
    • #if ... #endif Balance
    • memset Usage
    • Include Associated Header First
    • Include Guards
    • Inl-Header Inclusions
    • Check for unamed mutex holders
    • explicit single argument constructors
    • try-catch by reference
    • Check for throw new ...
    • Check unique_ptr arrays
  • Warnings
    • Blacklisted Sequences
    • #define name rules
    • Deprecated #includes
    • Check for static scope
    • Warn about smart_ptr usage
    • implicit casts
    • protected inheritance
    • Check exception inheritance
    • Check for virtual destructors
    • function level throws
  • Advice
    • nullptr over NULL

Usage

$ flint++ --help
Usage: flint++ [options:] [files:]

-r, --recursive		  : Search subfolders for files.
-c, --cmode			  : Only perform C based lint checks.
-j, --json			  : Output report in JSON format.
-v, --verbose		  : Print full file paths.
-l, --level [def = 3] : Set the lint level.
		            1 : Errors only
		            2 : Errors & Warnings
		            3 : All feedback

-h, --help		      : Print usage.

Does it pass Linting itself?

Yes!

$ flint++ ./

Lint Summary: 13 files
Errors: 0 Warnings: 0 Advice: 0

Compiling Flint++ from source

From the flint subdirectory, use make with the included makefile to build on a Posix based system using G++ > v4.7. To run the simple output test case run make tests after compilation. This will run Flint++ on the test directory and compare its output to the text stored in tests/expected.txt.

Why Lint?

Linting is a form of static-code analysis by which common errors and bad practices are flagged for review. This can help to both optimize poorly written code and to set a unified code style for all the code in a project. For large organizations this can be tremendously powerful as it helps to keep the whole codebase consistent.

Dependencies

Windows, Unix, Linux, OSX

None! You're good to go! Happy linting :)

Edit: It's not really a dependency, but it's worth noting that this project makes extensive use of the C++11 Feature Set. You probably won't be able to compile it on a Pre-C++11 version of your compiler.

Tested On

So far I've managed to compile and test Flint++ on Windows 7/8/8.1, Ubuntu 14.04, and Raspbian Wheezy; compiling under MSVC++ '13 and G++ 4.7 respectively. Edit: We also have word people have successfully compiled under OSX with Clang 3.5


Lead Contributers: @L2Program (Joss Whittle) & @kanielc (Denton Cockburn)


##Pull Requests Welcome!

Issues
  • Implement checkExceptionInheritance

    Implement checkExceptionInheritance

    Directly navigated the tokens (didn't use the structures of classes/structs/unions, as I saw that after).

    Seemed simple enough navigating directly I guess. Also updated the test file (now that we've sorted it.

    opened by kanielc 12
  • Update makefile to run tests

    Update makefile to run tests

    • Also add expected output file for tests.

    The test will generate an actual.txt file and compare that with the expected output.

    I'm not sure where in the README.md you'd want to put an instruction for running the tests, so I left that.

    enhancement 
    opened by kanielc 9
  • Using string iterator instead of creating new strings

    Using string iterator instead of creating new strings

    So instead of chomping the string we're processing, instead use an iterator into the data (since it's always a substring of input).

    This avoids a bunch of string re-allocations. The best part is that the performance is now much better.

    Run time from the original test run (a few commits ago): Flint++ - 0m0.987s Present run time after the iterator and file changes: real 0m0.281s It's actually faster now than Facebook's C++ version :)

    By the way, this is the profile of the project tested on: Lint Summary: 642 files Errors: 91 Warnings: 397 Advice: 268

    @L2Program I had to comment out some assert calls because I no longer had access to .size() from the iterator. I'll leave it up to you to decide what we should do with them.

    bug 
    opened by kanielc 7
  • Assertion failed: i < pc.size(), file Tokenizer.cpp, line 99

    Assertion failed: i < pc.size(), file Tokenizer.cpp, line 99

    Running the supplied Win64 binary (https://github.com/L2Program/FlintPlusPlus/blob/master/bin/x64/flint%2B%2B.exe) on a specific directoy on my Win7 machine results in: e:\somwhere>flint++ -r . Assertion failed: i < pc.size(), file Tokenizer.cpp, line 99

    opened by amaigil2 4
  • Additional optimizations

    Additional optimizations

    After some serious Valgrind profiling love:

    This PR also includes the optimize strings PR. Kept that open because I put a couple additional comments there.

    • Use more moves to save string and Error objects copying
    • Avoid some unnecessary string copying (in lint functions)
    • Use unordered_map and unordered_set when not needing order Unordered_map is faster for lookup, O(1) vs O(logn). We profiled them previously with GCC 4.8.1 to make sure, it holds even for small collections.
    • StartsWith works directly with a C-String
    • Replace atSequence's find_if with std::equal. This gave a massive cut in computation. Also got to get rid of pre-call check, as equal already does it.
    enhancement 
    opened by kanielc 4
  • Update tests

    Update tests

    I think we're soon going to need a new way to make sure the tests still work. Comparing against expected.txt won't remain viable if the output isn't determinate. Right now it's still working though.

    An easy option is to sort the output by Filename and line. Another would be to provide some "unit test" like way to validate the results on the test files (I have no idea what that would look like).

    opened by kanielc 3
  • Optimize checks

    Optimize checks

    We were creating a lot of temporary token objects in loops.

    Replace vectors created on each function call with static std::array instances.

    MASSIVE improvement in speed: On Folly+Gtest+double_conversion, time is now down to 1.6 s (vs 3.7 for Flint C++, and 2.4 before this PR)

    On my own code base, time is now 0.156s, used to be 0.98s in the initial tests (and 0.27s before this PR)

    enhancement 
    opened by kanielc 3
  • error: cannot combine with previous 'int' declaration specifier

    error: cannot combine with previous 'int' declaration specifier

    With some small mods to the makefile...

    clang++ -O3 -Wall -pedantic -mtune=native -std=c++11 -o ../bin/flint++ Checks.cpp FileCategories.cpp Ignored.cpp Main.cpp Polyfill.cpp Tokenizer.cpp  
    In file included from Checks.cpp:1:
    In file included from ./Checks.hpp:5:
    In file included from ./ErrorReport.hpp:7:
    In file included from ./Options.hpp:3:
    In file included from /usr/local/llvm/bin/../lib/clang/3.5.0/include/iostream:40:
    In file included from /usr/local/llvm/bin/../lib/clang/3.5.0/include/istream:156:
    In file included from /usr/local/llvm/bin/../lib/clang/3.5.0/include/ostream:133:
    In file included from /usr/local/llvm/bin/../lib/clang/3.5.0/include/locale:197:
    In file included from /usr/include/nl_types.h:45:
    /usr/include/sys/types.h:92:23: error: cannot combine with previous 'int' declaration
          specifier
    typedef unsigned int            uint;           /* Sys V compatibility */
                                    ^
    ./Polyfill.hpp:13:23: note: expanded from macro 'uint'
    #define uint unsigned int
                          ^
    

    Shouldn't that be a typedef, not a #define?

    This is on OS X Mavericks with clang 3.5:

    [email protected]:~/git/FlintPlusPlus/flint$ clang -v
    clang version 3.5.0 (trunk 203549)
    Target: x86_64-apple-darwin13.1.0
    Thread model: posix
    
    bug 
    opened by kevinushey 3
  • Use std::find in atBuiltIn

    Use std::find in atBuiltIn

    • Made builtIns vector static
    • Use std::find instead of hand-rolled loop

    Sorry about the EOL whitespace removal. My vim settings were really aggressive.

    I can undo them if you wish.

    enhancement 
    opened by kanielc 2
  • A simple fix for issue

    A simple fix for issue "Incorrect detection of copy-constructor #53"

    This change fixes string / token comparison bug and makes the checker a bit more robust. It doesn't really change the naive way a copy constructor is identified.

    opened by abbyssoul 1
  • Incorrect detection of copy-constructor

    Incorrect detection of copy-constructor

    This code example produces incorrect diagnostics on the master version of flint+++

    cat flint_bug.cpp

    struct C {};
    struct B {};
    
    struct CC {
        CC(C& a, B& b) {}
    };
    

    flint++ -v -r flint_bug.cpp [Error ] flint_bug.cpp:7: Copy constructors should take a const argument: CC(C& a, B& b)

    Lint Summary: 1 files Errors: 1 Warnings: 0 Advice: 0

    Please note that "CC(C& a, B& b)" is not a copy constructor. If I change the name of the struct C -> E everything works fine. So my guess is the name of the first argument 'collaids' with the name of the class and thus the constructor is identified as a copy constructor. This happened on a large code base where class names are not single letters. So for example the following also trip the parser:

    struct SomeType {};
    struct B {};
    
    struct SomeTypeButDifferent {
        SomeTypeButDifferent(SomeType& a, B& b) {}
    };
    
    opened by abbyssoul 1
  • False non-virtual dtor warning when passing structs or using nested classes

    False non-virtual dtor warning when passing structs or using nested classes

    The following four test cases all cause Flint++ to generate the warning "Classes with virtual functions should not have a public non-virtual destructor" erroneously, I believe. In three of the cases a struct is being returned from or passed to a method. In the last one there is a class inside another class. Strangely the warnings go away if the line following the one causing the warning is deleted or commented out.

    To reproduce, run flint++ in the same directory as the following four header files

    $ ~/cpp/flint++_false_vdtors$ flint++ -l3
    [Warning] cev.h:12: Classes with virtual functions should not have a public non-virtual destructor.
    [Warning] no_ctor.h:12: Classes with virtual functions should not have a public non-virtual destructor.
    [Warning] no_ctor.h:15: Classes with virtual functions should not have a public non-virtual destructor.
    [Warning] pd.h:9: Classes with virtual functions should not have a public non-virtual destructor.
    [Warning] struct_return.h:12: Classes with virtual functions should not have a public non-virtual destructor.
    
    Lint Summary: 4 files
    Errors: 0 Warnings: 5 Advice: 0
    
    Estimated Lines of Code: 72
    

    Instead, I would expect no warnings.

    CentOS Linux release 7.6.1810 (Core) g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36)

    #ifndef CEV_H
    #define CEV_H
    
    #include <time.h>
    
    class A
    {
    public:
        A() {}
        virtual ~A() {}
    
        virtual struct timeval getLastUpdate() { timeval t; return t; } // [Warning] cev.h:12: Classes with virtual functions should not have a public non-virtual destructor.
        virtual void m() {} // Deleting or commenting out this line gets rid of the warning in the line above
    };
    
    #endif /* CEV_H */
    
    #ifndef FOO_H
    #define FOO_H
    
    #include <sys/time.h>
    
    struct Z { int i, j; };
    
    class Foo 
    {
    public:
        virtual ~Foo() {}
        virtual void bar(struct timeval timestamp) {} // [Warning] no_ctor.h:12: Classes with virtual functions should not have a public non-virtual destructor.
    
        virtual void bar(Z z) {}         // No warning
        virtual void bar(struct Z& z) {} // [Warning] no_ctor.h:15: Classes with virtual functions should not have a public non-virtual destructor.
        virtual void baz() {}            // Removing this line gets rid of the warning for the line above
    };
    
    #endif /* FOO_H */
    
    #ifndef STRUCT_RETURN_H
    #define STRUCT_RETURN_H
    
    #include <time.h>
    
    class C
    {
    public:
        C() {}
        virtual ~C() {}
    
        virtual struct timeval getLastUpdate() { return {0,0}; } // [Warning] struct_return.h:12: Classes with virtual functions should not have a public non-virtual destructor.
    
        virtual bool foo(); // Deleting or commenting this line gets rid of the warning in the line above
    };
    #endif /* STRUCT_RETURN_H */
    
    
    #ifndef PD_H
    #define PD_H
    
    class B
    {
    public:
        virtual ~B();
    
        class C // [Warning] pd.h:9: Classes with virtual functions should not have a public non-virtual destructor.
        {   
        public:
            C() {}
        };  
    
        virtual bool foo(); // Deleting or commenting this line gets rid of the warning in the line above
    };
    #endif /* PD_H */
    
    
    opened by warmsocks 0
  • Whitespace between # and

    Whitespace between # and "error" or "line" causes bogus errors to be reported

    If a #error or #line preprocessor directive contains whitespace between the # and the word "error" or "line", the tokenizer breaks and bogus errors are reported.

    Example 1: "# errror ..."

    #ifndef ERROR_HPP
    #define ERROR_HPP
    #if abcdefg
    #                    error Gadzooks.
    #endif
    #endif // ERROR_HPP
    

    Results in this:

    $ flint++ Error.hpp
    [Error  ] Error.hpp:5: Unmatched #if/#endif.
    [Error  ] Error.hpp:5: Include guard doesn't cover the entire file.
    
    Lint Summary: 1 files
    Errors: 2 Warnings: 0 Advice: 0
    
    Estimated Lines of Code: 5
    

    Example 2: "# line ..."

    #ifndef LINE_HPP
    #define LINE_HPP
    #if abcdefg
    #            line 12345678
    #endif
    #endif // LINE_HPP
    

    Results in this:

    $ flint++ Error.hpp
    [Error  ] Line.hpp:5: Unmatched #if/#endif.
    [Error  ] Line.hpp:5: Include guard doesn't cover the entire file.
    
    Lint Summary: 1 files
    Errors: 2 Warnings: 0 Advice: 0
    
    Estimated Lines of Code: 5
    
    opened by warmsocks 0
  • Should take stdafx.h into account for PCH on Windows

    Should take stdafx.h into account for PCH on Windows

    On Windows in Visual Studio, precompiled headers are generally called stdafx.h and the include for them must the the first line in the file.

    This generates an incorrect Flint++ error The associated header file of .cpp files should be included before any other includes.

    Easy fix would be for Flint++ to allow stdafx.h above the associated header.

    opened by alarobric 0
  • Different filetypes

    Different filetypes

    Hello, is it possible to run flint++ with different file extensions? Specifically .ino files created for the Arduino IDE. Renaming the files to .cpp temporarily works but is not an ideal solution.

    Adding the .ino extension in the FileCategories.cpp file looks like a step in the right direction, but flint++ expects a header file which prevents it from completing any tests.

    Thanks in advance

    opened by kostasdizas 0
Owner
Joss Whittle
Research Software Engineer at the Rosalind Franklin Institute working on the Opt-ID software for the optimization of Synchrotron Insertion Devices.
Joss Whittle
ELF static analysis and injection framework that parse, manipulate and camouflage ELF files.

elfspirit elfspirit is a useful program that parse, manipulate and camouflage ELF files. It provides a variety of functions, including adding or delet

null 12 Jul 27, 2022
A tool for use with clang to analyze #includes in C and C++ source files

Include What You Use For more in-depth documentation, see docs. Instructions for Users "Include what you use" means this: for every symbol (type, func

null 2.9k Aug 1, 2022
A static analyzer for Java, C, C++, and Objective-C

Infer Infer is a static analysis tool for Java, C++, Objective-C, and C. Infer is written in OCaml. Installation Read our Getting Started page for det

Facebook 13.4k Aug 9, 2022
Analysis of Argon and Xenon Collision data to test Bardeen-Cooper-Schrieffer Approximation

Univeristy of North Carolina Wilmington Analysis of Argon and Xenon Collision data to test Bardeen-Cooper-Schrieffer Approximation. Argon Data Tree Fi

William Jarratt 1 Nov 15, 2021
CMetrics measures size and complexity for C files

C metrics package ================= INSTALL ------- see INSTALL file USAGE ----- cmetrics [-h] [-f] [-p] [-n] target_dir positional arguments:

Metrics Grimoire 63 May 27, 2022
An open-source C++ library developed and used at Facebook.

Folly: Facebook Open-source Library What is folly? Folly (acronymed loosely after Facebook Open Source Library) is a library of C++14 components desig

Facebook 22.8k Aug 5, 2022
Embed read-only filesystems into any C++11 program w. a single header, zero dependencies and zero modifications to your code

c-embed Embed read-only filesystems into any C++11 program w. a single header, zero dependencies and zero modifications to your code. Usage c-embed al

Nick McDonald 5 Jun 24, 2022
Source code for the data dependency part of Jan Kossmann's PhD thesis "Unsupervised Database Optimization: Efficient Index Selection & Data Dependency-driven Query Optimization"

Unsupervised Database Optimization: Data Dependency-Driven Query Optimization Source code for the experiments presented in Chapter 8 of Jan Kossmann's

Jan Koßmann 4 Apr 24, 2022
🌱Light and powerful C++ web framework for highly scalable and resource-efficient web application. It's zero-dependency and easy-portable.

Oat++ News Hey, meet the new oatpp version 1.2.5! See the changelog for details. Check out the new oatpp ORM - read more here. Oat++ is a modern Web F

Oat++ 5.6k Aug 11, 2022
🌱Light and powerful C++ web framework for highly scalable and resource-efficient web application. It's zero-dependency and easy-portable.

Oat++ News Hey, meet the new oatpp version 1.2.5! See the changelog for details. Check out the new oatpp ORM - read more here. Oat++ is a modern Web F

Oat++ 5.6k Aug 10, 2022
LuaZDF - Lua Zero Dependency Functions

LuaZDF - Lua Zero Dependency Functions LuaZDF is a collection of independet functions that have zero dependencies among themselves. A function in LuaZ

null 46 Jun 4, 2022
Lightweight single-file utilities for C99. Portable & zero dependency

plainlibs Lightweight single-file utilities for C99. Key Features Portable across Unix & Windows (including MSVC) Zero dependencies (besides C stdlib)

null 2 Jun 19, 2022
PikaScript is an ultra-lightweight Python engine with zero dependencies and zero-configuration, that can run with 4KB of RAM (such as STM32G030C8 and STM32F103C8), and is very easy to deploy and expand.

PikaScript 中文页| Star please~ 1. Abstract PikaScript is an ultra-lightweight Python engine with zero dependencies and zero-configuration, that can run

Lyon 814 Aug 9, 2022
oZKS (Ordered Zero-Knowledge Set) is a library that provides an implementation of an Ordered (and Append Only) Zero-Knowledge Set.

Ordered Zero-Knowledge Set - oZKS Introduction oZKS is a library that provides an implementation of an Ordered (and Append Only) Zero Knowledge Set. A

Microsoft 8 Aug 10, 2022
📦 CMake's missing package manager. A small CMake script for setup-free, cross-platform, reproducible dependency management.

Setup-free CMake dependency management CPM.cmake is a CMake script that adds dependency management capabilities to CMake. It's built as a thin wrapper

CPM.cmake 1.3k Aug 8, 2022
📦 CMake's missing package manager. A small CMake script for setup-free, cross-platform, reproducible dependency management.

Setup-free CMake dependency management CPM.cmake is a CMake script that adds dependency management capabilities to CMake. It's built as a thin wrapper

CPM.cmake 1.3k Aug 7, 2022
Port-Fin(port finder) is a tool which scans for open and closed port on a website/host.

Port-Fin(port finder) is a tool which scans for open and closed port on a website/host. This tool scans the state of the well known/common ports.

AnonabdulJ 4 Dec 14, 2021
Microsoft 2.4k Aug 7, 2022
A continuation of FSund's pteron-keyboard project. Feel free to contribute, or use these files to make your own! Kits and PCBs are also available through my facebook page.

pteron-pcb Intro This project is the evolution of the Pteron-Keyboard project, an incredible ergonomic keyboard that was handwired only. I aimed to in

null 15 Mar 20, 2022
mvfst is a client and server implementation of IETF QUIC protocol in C++ by Facebook.

mvfst (Pronounced move fast) is a client and server implementation of IETF QUIC protocol in C++ by Facebook.

Meta Incubator 1.2k Aug 2, 2022
Facebook AI Research's Automatic Speech Recognition Toolkit

wav2letter++ Important Note: wav2letter has been moved and consolidated into Flashlight in the ASR application. Future wav2letter development will occ

Facebook Research 6.1k Aug 4, 2022
A Brute-Force Tool For Facebook Accounts

fblookup fblookup is a facebook password cracking tool written in C which allows you to hack every facebook account using a wordlist without any block

null 8 Jan 27, 2022
Powerful, mature open-source cross-platform game engine for Python and C++, developed by Disney and CMU

Panda3D Panda3D is a game engine, a framework for 3D rendering and game development for Python and C++ programs. Panda3D is open-source and free for a

Panda3D 3.4k Aug 3, 2022
The pico can be used to program other devices. Raspberry pi made such an effort. However there is no board yet, that is open-source and can be used with OpenOCD as a general-purpose programmer

pico-probe-programmer The pico can be used to program other devices. Raspberry pi made such an effort. However there is no board yet, that is open-sou

martijn 21 Jul 20, 2022
openFrameworks is a community-developed cross platform toolkit for creative coding in C++.

openFrameworks openFrameworks is a C++ toolkit for creative coding. If you are new to OF, welcome! Build status The master branch contains the newest,

openFrameworks 9k Aug 5, 2022
Mars is a cross-platform network component developed by WeChat.

Mars is a cross-platform infrastructure component developed by WeChat Mobile Team

Tencent 16.3k Aug 7, 2022
A tiny cross-platform webview library for C/C++/Golang to build modern cross-platform GUIs.

webview for golang and c/c++ A tiny cross-platform webview library for C/C++/Golang to build modern cross-platform GUIs. The goal of the project is to

polevpn 14 Jul 5, 2022
This is the Arduino® compatible port of the AIfES machine learning framework, developed and maintained by Fraunhofer Institute for Microelectronic Circuits and Systems.

AIfES for Arduino® AIfES (Artificial Intelligence for Embedded Systems) is a platform-independent and standalone AI software framework optimized for e

null 143 Aug 6, 2022
C++11 Lightweight Redis client: async, thread-safe, no dependency, pipelining, multi-platform

C++11 Lightweight Redis client: async, thread-safe, no dependency, pipelining, multi-platform

Simon Ninon 974 Aug 1, 2022