GithubHelp home page GithubHelp logo

josswhittle / flintplusplus Goto Github PK

View Code? Open in Web Editor NEW

This project forked from facebookarchive/flint

264.0 264.0 21.0 10.66 MB

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

License: Boost Software License 1.0

C++ 98.67% Makefile 0.69% Roff 0.65%

flintplusplus's People

Contributors

abbyssoul avatar andralex avatar andrewjcg avatar josswhittle avatar kanielc avatar nlohmann avatar pauldreik avatar tandztc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flintplusplus's Issues

Correction

Ignored.cpp line 55 fprintf(stderr, "%s(%d):
second format string is int but value is unsigned int (found with cppcheck :-) ).

GCC-like error report format

It might be nice to have GCC-style error reporting. The current multi-line format is kind of verbose and hard to glance at.

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 */

GNU Style --level option incorrect behavior

$ ./flint++ tests -l1 produces:

[Error  ] Blacklist.cpp:21: 'strtok' is not thread safe. Consider 'strtok_r'.
[Error  ] Constructor.cpp:24: Single - argument constructor 'Foo(int i)' may inadvertently be used as a type conversion constructor.
[Error  ] Constructor.cpp:29: Move constructors should not take a const argument: Foo(const Foo&& other)
[Error  ] Constructor.cpp:30: Copy constructors should take a const argument: Foo(Foo &other)
[Error  ] Constructor.cpp:21: Single - argument constructor 'FooU(char i)' may inadvertently be used as a type conversion constructor.
[Error  ] Define.hpp:12: Include guard doesn't cover the entire file.
[Error  ] Ifdef.cpp:15: Unmatched #if/#endif.
[Error  ] Includes.cpp:15: The associated header file of .cpp files should be included before any other includes.
[Error  ] Includes.cpp:4: An -inl file (Wrong-inl.h) was included even though this is not its associated header.
[Error  ] Memset.cpp:11: Did you mean memset(ptr, 0, 4) ?
[Error  ] Memset.cpp:13: Did you mean memset(ptr, 1, sizeof(int)) ?
[Error  ] Pointers.cpp:39: Mutex holder variable declared without a name, causing the lock to be released immediately.
[Error  ] Pointers.cpp:40: Mutex holder variable declared without a name, causing the lock to be released immediately.
[Error  ] Pointers.cpp:27: unique_ptr<T[]> should be used with an array type.
[Error  ] Pointers.cpp:28: unique_ptr<T> should be unique_ptr<T[]> when used with an array.
[Error  ] Pointers.cpp:31: unique_ptr<T[]> should be used with an array type.
[Error  ] Pointers.cpp:32: unique_ptr<T> should be unique_ptr<T[]> when used with an array.
[Error  ] Throw.cpp:15: Symbol 'i' of type ' Foo i' caught by value. Use catch by (preferably const) reference throughout.
[Error  ] Throw.cpp:21: Symbol 'Bar' of type ' Bar' caught by value. Use catch by (preferably const) reference throughout.
[Error  ] Throw.cpp:8: Heap-allocated exception: throw new MyException(); This is usually a mistake in c++.
[Error  ] Throw.cpp:10: Heap-allocated exception: throw new (MyException)(); This is usually a mistake in c++.
[Error  ] Throw.cpp:12: Heap-allocated exception: throw new MyException(); This is usually a mistake in c++.

but $ ./flint++ tests --level 1 produces:

[Error  ] Blacklist.cpp:21: 'strtok' is not thread safe. Consider 'strtok_r'.
[Advice ] Blacklist.cpp:23: Prefer `nullptr' to `NULL' in new C++ code.
[Warning] Blacklist.cpp:8: 'volatile' is not thread-safe.
[Error  ] Constructor.cpp:24: Single - argument constructor 'Foo(int i)' may inadvertently be used as a type conversion constructor.
[Error  ] Constructor.cpp:29: Move constructors should not take a const argument: Foo(const Foo&& other)
[Error  ] Constructor.cpp:30: Copy constructors should take a const argument: Foo(Foo &other)
[Error  ] Constructor.cpp:21: Single - argument constructor 'FooU(char i)' may inadvertently be used as a type conversion constructor.
[Warning] Constructor.cpp:9: Protected inheritance is sometimes not a good idea.
[Warning] Constructor.cpp:12: Throw specifications on functions are deprecated.
[Warning] Constructor.cpp:18: Throw specifications on functions are deprecated.
[Warning] Constructor.cpp:5: Throw specifications on functions are deprecated.
[Error  ] Define.hpp:12: Include guard doesn't cover the entire file.
[Warning] Define.hpp:5: Symbol __BAD_DEFINE invalid.
[Warning] Destructors.cpp:1: Classes with virtual functions should not have a public non-virtual destructor.
[Warning] Destructors.cpp:10: Classes with virtual functions should not have a public non-virtual destructor.
[Warning] Exceptions.cpp:6: std::exception should be inherited publically (C++ std: 11.2)
[Warning] Exceptions.cpp:7: std::exception should be inherited publically (C++ std: 11.2)
[Warning] Exceptions.cpp:8: std::exception should be inherited publically (C++ std: 11.2)
[Warning] Exceptions.cpp:12: std::exception should be inherited publically (C++ std: 11.2)
[Warning] Exceptions.cpp:13: std::exception should be inherited publically (C++ std: 11.2)
[Error  ] Ifdef.cpp:15: Unmatched #if/#endif.
[Error  ] ImplicitConversion.cpp:15: operator bool() is dangerous.
[Error  ] Includes.cpp:15: The associated header file of .cpp files should be included before any other includes.
[Error  ] Includes.cpp:4: An -inl file (Wrong-inl.h) was included even though this is not its associated header.
[Warning] Includes.cpp:6: Including deprecated header 'common/base/Base.h'
[Error  ] Memset.cpp:11: Did you mean memset(ptr, 0, 4) ?
[Error  ] Memset.cpp:13: Did you mean memset(ptr, 1, sizeof(int)) ?
[Warning] Namespace.hpp:6: Avoid the use of using namespace directives at global/namespace scope in headers
[Warning] Namespace.hpp:9: Don't use static at global or namespace scopes in headers.
[Warning] Namespace.hpp:10: Don't use static at global or namespace scopes in headers.
[Warning] Namespace.hpp:19: Don't use static at global or namespace scopes in headers.
[Warning] Namespace.hpp:20: Don't use static at global or namespace scopes in headers.
[Warning] Namespace.hpp:23: Don't use static at global or namespace scopes in headers.
[Warning] Namespace.hpp:25: Don't use static at global or namespace scopes in headers.
[Warning] Namespace.hpp:27: Conflicting namespaces: boost and std
[Warning] Namespace.hpp:29: Conflicting namespaces: ::std and std
[Warning] Namespace.hpp:32: Conflicting namespaces: ::boost and std
[Error  ] Pointers.cpp:39: Mutex holder variable declared without a name, causing the lock to be released immediately.
[Error  ] Pointers.cpp:40: Mutex holder variable declared without a name, causing the lock to be released immediately.
[Error  ] Pointers.cpp:27: unique_ptr<T[]> should be used with an array type.
[Error  ] Pointers.cpp:28: unique_ptr<T> should be unique_ptr<T[]> when used with an array.
[Error  ] Pointers.cpp:31: unique_ptr<T[]> should be used with an array type.
[Error  ] Pointers.cpp:32: unique_ptr<T> should be unique_ptr<T[]> when used with an array.
[Warning] Pointers.cpp:34: Consider using 'allocate_shared' which performs better with fewer allocations.
[Warning] Pointers.cpp:35: Consider using 'make_shared' which performs better with fewer allocations.
[Warning] Pointers.cpp:36: Consider using 'make_shared' which performs better with fewer allocations.
[Warning] Pointers.cpp:37: Consider using 'allocate_shared' which performs better with fewer allocations.
[Warning] Throw.cpp:14: Symbol 'int' invalid in catch clause. You may only catch user-defined types.
[Error  ] Throw.cpp:15: Symbol 'i' of type ' Foo i' caught by value. Use catch by (preferably const) reference throughout.
[Error  ] Throw.cpp:21: Symbol 'Bar' of type ' Bar' caught by value. Use catch by (preferably const) reference throughout.
[Error  ] Throw.cpp:8: Heap-allocated exception: throw new MyException(); This is usually a mistake in c++.
[Error  ] Throw.cpp:10: Heap-allocated exception: throw new (MyException)(); This is usually a mistake in c++.
[Error  ] Throw.cpp:12: Heap-allocated exception: throw new MyException(); This is usually a mistake in c++.

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.

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

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

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) {}
};

error in Tokenizer.cpp:99

Running flint++ from master (c04020e) on my own code results in

flint++: Tokenizer.cpp:99: std::string flint::{anonymous}::munchSingleLineComment(std::string&, size_t&): Assertion `i < pc.size()' failed.

Program received signal SIGABRT, Aborted.
0x00007ffff75390d5 in __GI_raise (sig=) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
64 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 0x00007ffff75390d5 in __GI_raise (sig=) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1 0x00007ffff753c83b in __GI_abort () at abort.c:91
#2 0x00007ffff7531d9e in __assert_fail_base (fmt=, assertion=0x422b70 "i < pc.size()", file=0x4224ea "Tokenizer.cpp", line=, function=) at assert.c:94
#3 0x00007ffff7531e42 in __GI___assert_fail (assertion=0x422b70 "i < pc.size()", file=0x4224ea "Tokenizer.cpp", line=99,

function=0x423460 "std::string flint::{anonymous}::munchSingleLineComment(std::string&, size_t&)") at assert.c:103

#4 0x000000000041f7be in flint::tokenize(std::string const&, std::string const&, std::vector<flint::Token, std::allocatorflint::Token >&) ()
#5 0x0000000000413b2c in checkEntry(flint::ErrorReport&, std::string const&, unsigned int) ()
#6 0x00000000004140f6 in checkEntry(flint::ErrorReport&, std::string const&, unsigned int) ()
#7 0x00000000004140f6 in checkEntry(flint::ErrorReport&, std::string const&, unsigned int) ()
#8 0x0000000000402f7e in main ()

Todo: A discussion of possible ehancements

Tokenizer.cpp

Todo:

  • Exchange string copy pc for a non-destructive string::iterator
  • Profile for possible performance bottlenecks during tokenizing

Discuss:

  • Is it possible to check for blacklisted identifiers during Tokenization?

Checks.cpp

Todo:

  • NULL vs nullptr check can be combined with Banned Identifiers check
  • All checks which use iterateClasses could be combined to use a single call to that function

Flint thinks the filename in an #include is code...

I use paths that include c++, example:

#include <foo/c++14/bar.hpp>

When I check the file with flint++, I get:

Use prefix notation '++c'.

Postfix iterators inject a copy operation, almost doubling the workload.

For some reason, I have doubt that this will improve my code :)

False positive related to prefix notation

The prefix notation provides no benefit for primitive types. At the very least this false positive is noise. Worse, the advise is wrong in cases where changing it results in changing program behavior.

foo.cc:

int main()
{
    int x = 0;
    x++;
}
$ ./flint++ foo.cc
===============================================================================
File foo.cc:
Errors:   0
Warnings: 0
Advice:   1
===============================================================================

Line 4: Advice

Use prefix notation '++x'.

Postfix incrementers inject a copy operation, almost doubling the workload.

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:

kevinushey@Kevin-MBP:~/git/FlintPlusPlus/flint$ clang -v
clang version 3.5.0 (trunk 203549)
Target: x86_64-apple-darwin13.1.0
Thread model: posix

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.