myint / cppclean Goto Github PK
View Code? Open in Web Editor NEWFinds problems in C++ source that slow development of large code bases
Home Page: https://pypi.python.org/pypi/cppclean
License: Apache License 2.0
Finds problems in C++ source that slow development of large code bases
Home Page: https://pypi.python.org/pypi/cppclean
License: Apache License 2.0
It gives warning when you declare a variable in header file but you this variable in another files only.
Hey all,
I am running Cppclean on 2 Ogre3d based projects and both segfault on a specific token:
Got invalid token in ? @ 1710 token:@: u'SION_10_6\n@interface'
This can be reproduced when running on a fresh download from the ogre website.
The file that causes this seems to be: OgrePrerequisites.h which gets called quite a lot.
Running just on that file seems to do no harm.
Thanks
Traceback (most recent call last):
File "/usr/local/bin/cppclean", line 135, in
sys.exit(main())
File "/usr/local/bin/cppclean", line 127, in main
quiet=args.quiet)
File "/usr/local/lib/python2.7/dist-packages/cpp/find_warnings.py", line 533, in run
hunter.find_warnings()
File "/usr/local/lib/python2.7/dist-packages/cpp/find_warnings.py", line 124, in find_warnings
self._find_header_warnings()
File "/usr/local/lib/python2.7/dist-packages/cpp/find_warnings.py", line 396, in _find_header_warnings
self._find_unused_warnings()
File "/usr/local/lib/python2.7/dist-packages/cpp/find_warnings.py", line 387, in _find_unused_warnings
included_files, forward_declarations = self._read_and_parse_includes()
File "/usr/local/lib/python2.7/dist-packages/cpp/find_warnings.py", line 171, in _read_and_parse_includes
module = self._get_module(node)
File "/usr/local/lib/python2.7/dist-packages/cpp/find_warnings.py", line 149, in _get_module
[_f for _f in builder.generate() if _f])
File "/usr/local/lib/python2.7/dist-packages/cpp/ast.py", line 698, in generate
token = self._get_next_token()
File "/usr/local/lib/python2.7/dist-packages/cpp/ast.py", line 916, in _get_next_token
return next(self.tokens)
File "/usr/local/lib/python2.7/dist-packages/cpp/tokenize.py", line 276, in get_tokens
raise TokenError('unexpected token')
cpp.tokenize.TokenError: unexpected token
Parsing the following piece of code throw an exeption because of the use of MY_THROW() :
#define MY_THROW() throw ()
void Foo() MY_THROW() {}
The callstack of the exception being :
PS cppclean> python3 .\cppclean .\Test --verbose
Processing .\Test\Headers\AbstractProperty.h
Got exception in .\Test\Headers\AbstractProperty.h @ Token('void', 29, 33) []
Traceback (most recent call last):
File ".\cppclean", line 130, in <module>
sys.exit(main())
File ".\cppclean", line 112, in main
entire_ast = list([_f for _f in builder.generate() if _f])
File ".\cppclean", line 112, in <listcomp>
entire_ast = list([_f for _f in builder.generate() if _f])
File "cppclean\cpp\ast.py", line 709, in generate
result = self._generate_one(token)
File "cppclean\cpp\ast.py", line 798, in _generate_one
return self._get_method(temp_tokens, 0, None, False)
File "cppclean\cpp\ast.py", line 1089, in _get_method
if parameters[0].name == '*':
IndexError: list index out of range
Cppclean doesn't recognize default template arguments as references to included file.
See below example:
A.h
class A
{
};
B.h
#include "A.h"
template<typename T = A>
void f()
{
}
Cppclean prints
./B.h:1: 'A.h' does not need to be #included
When include is removed, g++ gives an error:
B.h:3:23: error: ‘A’ does not name a type
template<typename T = A>
cppclean seems to be clever enough to determine that you can have a std::shared_ptr<X>
to a forward-declared type X
, which is good.
Unfortunately, if the name is hidden behind an alias declaration, cppclean then warns that X
must be #included. The following test code demonstrates the issue:
#include <memory>
// Forward declaration of class X is all that is required to have a std::shared_ptr
class X;
// Alias declaration - requires C++11
template<typename T>
using MySharedPtr = std::shared_ptr<T>;
struct A
{
MySharedPtr<X> x;
};
For this case, cppclean prints:
cppclean_test5.h:4: 'X' forward declared, but needs to be #included
On the other hand, if you change the line MySharedPtr<X> x;
to simply std::shared_ptr<X> x;
, the warning goes away. So I guess this is really more of a feature request to better handle alias declarations, as we use this technique to handle backwards compatibility with older compilers in our library.
Hi,
Not sure if you really want bug reports about specific files here, but in trying to run cppclean on this particular header I get a crash with the following stack trace:
Traceback (most recent call last):
File "/opt/miniconda/bin/cppclean", line 140, in <module>
sys.exit(main())
File "/opt/miniconda/bin/cppclean", line 133, in main
quiet=args.quiet):
File "/opt/miniconda/lib/python2.7/site-packages/cpp/find_warnings.py", line 518, in run
hunter.find_warnings()
File "/opt/miniconda/lib/python2.7/site-packages/cpp/find_warnings.py", line 119, in find_warnings
self._find_header_warnings()
File "/opt/miniconda/lib/python2.7/site-packages/cpp/find_warnings.py", line 390, in _find_header_warnings
self._find_unused_warnings(included_files, forward_declarations)
File "/opt/miniconda/lib/python2.7/site-packages/cpp/find_warnings.py", line 381, in _find_unused_warnings
self._determine_uses(included_files, forward_declarations)
File "/opt/miniconda/lib/python2.7/site-packages/cpp/find_warnings.py", line 348, in _determine_uses
_process_function_body(node, node.namespace)
File "/opt/miniconda/lib/python2.7/site-packages/cpp/find_warnings.py", line 318, in _process_function_body
_add_use(t.name, namespace)
File "/opt/miniconda/lib/python2.7/site-packages/cpp/find_warnings.py", line 274, in _add_use
name = file_use_node[1].filename
KeyError: 1
With the following code, I get the message 'namespace_parent.h' does not need to be #included
, which is incorrect.
parent.h
namespace parent
{
class Parent {};
}
child.h
#include "namespace_parent.h"
using namespace parent;
namespace child
{
class Child : Parent {};
}
The code compiles correctly but 'using namespace' in a header file is bad practice, so it might be better to give a warning that it is better to use full namespaces.
Consider the following:
class Blah;
class Foo: public Bar{
public:
Foo();
virtual bool doSomething(Blah* blah);
};
Cppclean thinks that I need to #include "blah.h" even though I'm only using it in pointer form:
"Foo.h:1: 'Blah' forward declared, but needs to be #included"
The code compiles fine with the forward declare.
cppclean version 0.9
Traceback (most recent call last):
File "/usr/local/bin/cppclean", line 145, in <module>
sys.exit(main())
File "/usr/local/bin/cppclean", line 138, in main
quiet=args.quiet):
File "/usr/local/lib/python2.7/site-packages/cpp/static_data.py", line 117, in run
_find_warnings(filename, lines, entire_ast, True) +
File "/usr/local/lib/python2.7/site-packages/cpp/static_data.py", line 67, in _find_warnings
find_static(node)
File "/usr/local/lib/python2.7/site-packages/cpp/static_data.py", line 49, in find_static
_find_warnings(filename, lines, body, False)
File "/usr/local/lib/python2.7/site-packages/cpp/static_data.py", line 64, in _find_warnings
print_warning(node)
File "/usr/local/lib/python2.7/site-packages/cpp/static_data.py", line 31, in print_warning
for name in node.name.split(','):
AttributeError: 'NoneType' object has no attribute 'split'
Consider the following
class Bar;
class Foo1 {
friend Bar;
};
Since it is not friend class Bar
, cppclean will give the warning .foo1.h:1: 'Bar' not used
even though the syntax is valid and the forward declaration has a purpose.
cppclean 0.6 tells me
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 12: ordinal not in range(128)
How can I find out the problem - e.g. which file is triggering the message?
You have a code:
void f2()
{
...
f();
}
void f()
{
...
}
You will have a warning for function f().
The following code will make it crash(although I know it's non-standard, many people use it).
union test
{
unsigned int data;
struct
{
unsigned int first;
unsigned int second;
};
};
Running cppclean on boost/tr1/array.hpp crashes
Processing boost/boost/tr1/array.hpp
Traceback (most recent call last):
File "/usr/bin/cppclean", line 145, in <module>
sys.exit(main())
File "/usr/bin/cppclean", line 120, in main
entire_ast = list([_f for _f in builder.generate() if _f])
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 668, in generate
result = self._generate_one(token)
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 692, in _generate_one
return method()
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 1417, in handle_template
templated_types)
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 1520, in _get_class
body = list(ast.generate())
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 668, in generate
result = self._generate_one(token)
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 757, in _generate_one
return self._get_method(temp_tokens, 0, None, False)
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 1125, in _get_method
templated_types, body, self.namespace_stack)
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 286, in __init__
self.parameters = converter.to_parameters(parameters)
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 595, in to_parameters
add_parameter()
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 550, in add_parameter
True)
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 502, in declaration_to_parts
parts, i + 1)
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 387, in _get_template_end
token = tokens[end]
IndexError: list index out of range
I am using boost 1.53 (http://www.boost.org/users/history/version_1_53_0.html)
The crash stack:
Traceback (most recent call last):
File "cppclean", line 166, in <module>
sys.exit(main())
File "cppclean", line 159, in main
quiet=args.quiet):
File "cppclean/cpp/static_data.py", line 118, in run
_find_warnings(filename, lines, entire_ast, True) +
File "cppclean/cpp/static_data.py", line 64, in _find_warnings
print_warning(node)
File "cppclean/cpp/static_data.py", line 31, in print_warning
for name in node.name.split(','):
AttributeError: 'NoneType' object has no attribute 'split'
In static_data.py you must include if node.name:
before line 31 to avoid the crash.
This is not a bug; it's an enhancement request. Would it be possible to check for inconsistency in the case of file names in #include statements, so that attempting to include myfile.h with #include "MyFile.h" would throw a warning?
This would be a big help for people developing on (say) Windows, where the case doesn't matter, who want to port their code to Linux.
If one includes a header where a macro is defined, cppclean
will not be able to detect that the header can actually be needed. This may be clearer with the following dummy example.
foo.h
#ifndef FOO_H
# define FOO_H
# include "bar.h"
class Foo
{
public:
Foo () : bar (BAR) {}
private:
int bar;
};
#endif //! FOO_H
bar.h
#ifndef BAR_H
# define BAR_H
# define BAR 1
#endif //! BAR_H
Running cppclean
gives:
$ cppclean --verbose .
Processing ./bar.h
Processing ./foo.h
./foo.h:4: 'bar.h' does not need to be #included
This may be something to add to the "planned" features, unless this requires some analysis that this tool is not meant to achieve. If that's the case, this may be worth noting somewhere in the documentation/help message.
Hello, cppclean gives me an error on a very simple example.
'f' not found in any directly #included header
What is wrong?
Best regards
Here is how to reproduce.
~>pip install --user --upgrade cppclean
~>source /mysoft/Python-3.4.3/setenv
~>PYTHONPATH=$PYTHONPATH:~/.local/lib/python2.6/site-packages
~>cat >| main.cpp << EOF
//#include <iostream>
void g(int j) {
if (j == 3) {
g(j+1);
}
}
int f(const int& i) {
g(i);
return i - 1;
}
int main() {
return f(1);
}
EOF
~>g++ ./main.cpp -o main && ./main ; echo $?
0
~>python3 ~/.local/bin/cppclean ./main.cpp ; echo $?
./main.cpp:3: 'g' not found in any directly #included header
./main.cpp:9: 'f' not found in any directly #included header
1
cppclean prints the following warning:
cppclean_test.h:7: 'A' not used
for the sample cppclean_test.h below:
// A function template
template<class T> void foo();
// This forward declaration really is used in the full specialization
// below, but cppclean thinks it is not. The code will not compile
// without it.
class A;
// A full specialization of foo declared before A.
template<>
void foo<A>();
// Actual class definition.
class A {};
It's not a crash so I don't think it counts as a bug, just a warning that I have to ignore a lot, as I use a framework that makes extensive use of this pattern.
@r-e-d, do you use the siteheaders configuration? If not, I think I will remove it. (I added support for defining the include paths from the command line.)
Similar to #72 a token exception is raised when parsing a C++11 std::function. See below for error message and code example. Version is 02db685.
Got exception in MyClass.h @ Token('std', 92, 95) []
Got exception in MyClass.h @ Token('class', 37, 42) []
MyClass.h: parsing error (Token('>', 126, 127), [Token('std', 92, 95), Token('::', 95, 97), Token('function', 97, 105), Token('<', 105, 106)], [Token('double', 111, 117), Token(',', 117, 118), Token('double', 119, 125)])
#pragma once
#include <functional>
class CMyClass
{
public:
CMyClass();
private:
std::function<void(double, double)> mFunctor;
};
From C++11 on, nested templates do not require a whitespace between closing '>' anymore.
Before C++11:
std::vector<std::vector<double> >
C++11:
std::vector<std::vector<double>>
The second version yields a token exception.
Hello,
cppclean crashes on a particular code. For some reasons, in the AST you end up with a node with "None" as name.
You can reproduce the bug easily:
>> wget https://raw.githubusercontent.com/victorprad/InfiniTAM/master/InfiniTAM/ITMLib/Engine/DeviceAgnostic/ITMVisualisationEngine.h
>> cppclean ITMVisualisationEngine.h
ITMVisualisationEngine.h:5: unable to find '../../Utils/ITMLibDefines.h'
Traceback (most recent call last):
File "/usr/bin/cppclean", line 145, in <module>
sys.exit(main())
File "/usr/bin/cppclean", line 138, in main
quiet=args.quiet):
File "/usr/lib/python2.7/site-packages/cpp/static_data.py", line 117, in run
_find_warnings(filename, lines, entire_ast, True) +
File "/usr/lib/python2.7/site-packages/cpp/static_data.py", line 64, in _find_warnings
print_warning(node)
File "/usr/lib/python2.7/site-packages/cpp/static_data.py", line 31, in print_warning
for name in node.name.split(','):
AttributeError: 'NoneType' object has no attribute 'split'
Cheers,
Bruno
I can see if I declare only function pointers cppclean throws warnings declared but not defined
We have several header files that contain a macro:
class DBExample : public DBCURSORHELPER(CSExample) {
Which results in the error:
Exception while processing '../build/foo/dbexample.h': Token(u'{', 323, 324)
If I replace the macro with the expanded code, the error does not occur.
A included file has the same namespace as current file. Included file contains in namespace using namespace
which is within the file:
file a.h:
namespace A
{
class T;
}
namespace B
{
using namespace A;
}
file b.h:
namespace B
{
void someFunction(A a);
}
a warning does not need to be #included
will be rised.
Running 793bd44 on my 64bit cygwin I get an error somewhere in the middle of a run (--verbose is active):
Processing ./PlatformSupport/numerictypeinfo.h
Traceback (most recent call last):
File "/usr/bin/cppclean", line 145, in <module>
sys.exit(main())
File "/usr/bin/cppclean", line 138, in main
quiet=args.quiet):
File "/usr/lib/python2.7/site-packages/cpp/find_warnings.py", line 524, in run
hunter.find_warnings()
File "/usr/lib/python2.7/site-packages/cpp/find_warnings.py", line 119, in find_warnings
self._find_header_warnings()
File "/usr/lib/python2.7/site-packages/cpp/find_warnings.py", line 396, in _find_header_warnings
self._find_unused_warnings(included_files, forward_declarations)
File "/usr/lib/python2.7/site-packages/cpp/find_warnings.py", line 387, in _find_unused_warnings
forward_declarations)
File "/usr/lib/python2.7/site-packages/cpp/find_warnings.py", line 354, in _determine_uses
_process_function_body(node, node.namespace)
File "/usr/lib/python2.7/site-packages/cpp/find_warnings.py", line 323, in _process_function_body
_add_use(t.name, namespace)
File "/usr/lib/python2.7/site-packages/cpp/find_warnings.py", line 276, in _add_use
name = file_use_node[1].filename
KeyError: 1
Hey everyone.
I have quite a big project and want to check my include hierarchy and patch it up, but the problem is that i can't seem to make it work.
We have a file structure which is quite complex, and the project is made with CMake, defining multiple include folders as actual include directories.
It seems that cppclean is not able to work in such conditions, adding every single folder with --include-path is not doable, and also seems not to be able to find files with matching names.
Is this something that is fixable within cppclean, or am I screwed and do I really need to write something like a CMake wrapper for it.
Thanks
Seems CppClean doesn't recognize declaration (class, typedef and enum) inside a class, and complains about forward declare Foo is enough.
Foo.h
class Foo
{
public:
class Dummy;
typedef int Type;
enum EnumType { Type1, Type2 };
};
Bar.h
#include "Foo.h"
class Bar : public Foo::Dummy
{
public:
Bar(Foo::Type type, Foo::EnumType eType);
};
One of the messages that I got is
calcfinesstrategy.h:6: 'dates.h' does not need to be #included
Which is wrong, since removing it will result in a compiler error. Below is a simplified example.
calcfinesstrategy.h:
ifndef CALCFINESSTRATEGY_H
define CALCFINESSTRATEGY_H
include "dates.h"
class CCCalcFinesStrategy
{
public:
CCCalcFinesStrategy();
private:
void Initialize();
};endif`
calcfinesstrategy.cpp:
include "calcfinesstrategy.h"
void CCCalcFinesStrategy::Initialize()
{
current_date_time( var1, var2, var3, 1 );
}
dates.h:
ifndef DATES_H
define DATES_H
int current_date_time( long long &f_ts, wchar_t *sa_date, long &d_dayno, int i_format );
endif
Traceback (most recent call last):
File "/usr/bin/cppclean", line 145, in <module>
sys.exit(main())
File "/usr/bin/cppclean", line 138, in main
quiet=args.quiet):
File "/usr/lib/python3.6/site-packages/cpp/static_data.py", line 117, in run
_find_warnings(filename, lines, entire_ast, True) +
File "/usr/lib/python3.6/site-packages/cpp/static_data.py", line 67, in _find_warnings
find_static(node)
File "/usr/lib/python3.6/site-packages/cpp/static_data.py", line 48, in find_static
ast.ASTBuilder(iter(tokens), filename).generate())
File "/usr/lib/python3.6/site-packages/cpp/ast.py", line 651, in generate
result = self._generate_one(token)
File "/usr/lib/python3.6/site-packages/cpp/ast.py", line 726, in _generate_one
return self._get_method(temp_tokens, 0, None, False)
File "/usr/lib/python3.6/site-packages/cpp/ast.py", line 1092, in _get_method
(token, return_type_and_name, parameters))
File "/usr/lib/python3.6/site-packages/cpp/ast.py", line 1569, in assert_parse
raise ParseError(message)
cpp.ast.ParseError: (Token(',', 2622, 2623), [], [Token('"color"', 2614, 2621)])
To reproduce:
git clone https://github.com/OSSIA/libossia -b master --depth=1
cppclean libossia/OSSIA/ossia/editor/dataspace/dataspace_visitors.cpp
Hi,
I have a python KeyError raised when running cppclean, it is in a big project then I'm not sure when exactly it happens.
End of traceback is:
File "/usr/local/lib/python2.7/site-packages/cpp/find_warnings.py", line 260, in _add_reference
name = file_use_node[1].filename
KeyError: 1
Note that, I had first installed cppclean through "pip install --upgrade cppclean", and had the same issue in "add_use(name, namespace)" that is, now that I installed from cppclean-master, fixed with (lines with + are lines that fixed the problem):
def _add_use(name, namespace):
[...]
+ if isinstance(file_use_node, dict):
+ return
# TODO(nnorwitz): do proper check for ref/pointer/symbol.
name = file_use_node[1].filename
if name in file_uses:
file_uses[name] |= USES_DECLARATION
[...]
I then added the same "if isinstance return" in _add_reference(name, namespace) before calling "name = file_use_node[1].filename" an it seems to do the job, but since I'm not sure if this is the right thing to do I prefer filing a new issue, anyway, if you need more information to track this issue do not hesitate to ask.
Thanks and best regards.
Running cppclean on this invalid/incomplete code
#define FOO
extern void foo(
triggers a crash:
Traceback (most recent call last):
File "/usr/bin/cppclean", line 145, in <module>
sys.exit(main())
File "/usr/bin/cppclean", line 120, in main
entire_ast = list([_f for _f in builder.generate() if _f])
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 668, in generate
result = self._generate_one(token)
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 757, in _generate_one
return self._get_method(temp_tokens, 0, None, False)
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 989, in _get_method
last_token = parameters.pop() # Remove trailing ')'.
IndexError: pop from empty list
I have the following include files:
A.hpp
class A {
public:
A();
int value() { return mValue; }
private:
int mValue;
};
B.hpp
#include "A.hpp"
class B {
public:
B();
int getAValue() { return mA->value(); }
private:
A *mA;
};
And here is what cppclean tells me:
$ cppclean B.hpp
B.hpp:1: 'A.hpp' does not need to be #included; use a forward declaration instead
However if I replace #include "A.cpp"
with class A;
, it doesn't compile anymore:
$ gcc B.hpp
B.hpp: In member function 'int B::getAValue()':
B.hpp:6:30: error: invalid use of incomplete type 'class A'
int getAValue() { return mA->value(); }
^
B.hpp:2:7: note: forward declaration of 'class A'
class A;
^
$ cppclean .
Traceback (most recent call last):
File "/usr/bin/cppclean", line 145, in <module>
sys.exit(main())
File "/usr/bin/cppclean", line 138, in main
quiet=args.quiet):
File "/usr/lib/python3.6/site-packages/cpp/find_warnings.py", line 597, in run
hunter.find_warnings()
File "/usr/lib/python3.6/site-packages/cpp/find_warnings.py", line 126, in find_warnings
self._find_source_warnings()
File "/usr/lib/python3.6/site-packages/cpp/find_warnings.py", line 542, in _find_source_warnings
included_files, forward_declarations = self._read_and_parse_includes()
File "/usr/lib/python3.6/site-packages/cpp/find_warnings.py", line 177, in _read_and_parse_includes
module = self._get_module(node)
File "/usr/lib/python3.6/site-packages/cpp/find_warnings.py", line 151, in _get_module
ast_list = [_f for _f in builder.generate() if _f]
File "/usr/lib/python3.6/site-packages/cpp/find_warnings.py", line 151, in <listcomp>
ast_list = [_f for _f in builder.generate() if _f]
File "/usr/lib/python3.6/site-packages/cpp/ast.py", line 651, in generate
result = self._generate_one(token)
File "/usr/lib/python3.6/site-packages/cpp/ast.py", line 675, in _generate_one
return method()
File "/usr/lib/python3.6/site-packages/cpp/ast.py", line 1180, in handle_struct
return self._handle_class_and_struct(Struct)
File "/usr/lib/python3.6/site-packages/cpp/ast.py", line 1174, in _handle_class_and_struct
return self._get_class(class_type, None)
File "/usr/lib/python3.6/site-packages/cpp/ast.py", line 1507, in _get_class
name_tokens = [class_token] + name_tokens
UnboundLocalError: local variable 'name_tokens' referenced before assignment
Arch Linux, installed from pip
constructors
like
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); are treated as functions and fails.
p11_CrystalBall.zip
Just ran cppclean on a c++11 code base (normally compiled with gcc 4.8 on linux as well as windows using VS 2013+.
I see this stack trace:
Traceback (most recent call last):
File "/usr/bin/cppclean", line 145, in <module>
sys.exit(main())
File "/usr/bin/cppclean", line 138, in main
quiet=args.quiet):
File "/usr/lib/python2.7/site-packages/cpp/find_warnings.py", line 565, in run
hunter.find_warnings()
File "/usr/lib/python2.7/site-packages/cpp/find_warnings.py", line 124, in find_warnings
self._find_header_warnings()
File "/usr/lib/python2.7/site-packages/cpp/find_warnings.py", line 437, in _find_header_warnings
self._find_unused_warnings(included_files, forward_declarations)
File "/usr/lib/python2.7/site-packages/cpp/find_warnings.py", line 413, in _find_unused_warnings
forward_declarations)
File "/usr/lib/python2.7/site-packages/cpp/find_warnings.py", line 401, in _determine_uses
_add_declaration(node.name, node.namespace)
File "/usr/lib/python2.7/site-packages/cpp/find_warnings.py", line 252, in _add_declaration
name = '::'.join(names) + '::' + name
TypeError: coercing to Unicode: need string or buffer, NoneType found
Unfortunately I can't include the code which caused this error. Also, it doesn't actually tell me which line in the C++ file caused this so it could be any of 150+ lines.
cppclean master reports:
cppclean_test2.h:4: 'Foo::Bar' not used
for the following code snippet. I think it may be getting tricked by the using namespace
declaration into thinking that the Bar
forward declaration is not required, when in fact it is.
// Forward declare Foo::Bar
namespace Foo
{
class Bar;
}
// So we can reference Bar without qualification below.
using namespace Foo;
class A
{
// The namespaced forward declaration is required for this line of code.
void f(Bar & bar);
};
cppclean fails on
class SharedCount {
friend inline bool operator==( SharedCount const & a, SharedCount const & b )
{
return a._pi == b._pi;
}
};
with
$ cppclean --verbose SharedCount.h
Processing SharedCount.h
Traceback (most recent call last):
File "/usr/bin/cppclean", line 145, in <module>
sys.exit(main())
File "/usr/bin/cppclean", line 120, in main
entire_ast = list([_f for _f in builder.generate() if _f])
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 668, in generate
result = self._generate_one(token)
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 692, in _generate_one
return method()
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 1261, in handle_class
return self._handle_class_and_struct(Class, 'class')
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 1258, in _handle_class_and_struct
return self._get_class(class_type, None)
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 1512, in _get_class
body = list(ast.generate())
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 668, in generate
result = self._generate_one(token)
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 692, in _generate_one
return method()
File "/usr/lib/python2.7/site-packages/cpp/ast.py", line 1320, in handle_friend
assert result
AssertionError
This line explicitly ignores headers ending in ".hxx", even though they are included in the list of header extensions. Is this done on purpose? Forgive me if I'm being dim, but I had a look, and I couldn't find anything that explained why ".hxx" files are skipped.
Hey, you know us already IIRC, just wanted to let you know that we added CPPClean support in coala (coala-analyzer.org). Usual things apply, this opens it up for several editor plugins, our automatic GitHub pull request review thingy, various analysis data dumps and so on. As always we're open for collaboration but I think we had this discussion so feel free to close this bug when read. :)
Have a nice day!
Maybe this was done by design, but --include-path isn't recursive. This means instead of doing
--include-path ../src/
I have to do
--include-path ../src/A --include-path ../src/B --include-path ../src/C --include-path ../src/D
This ends up in a rather large command line. Would be nice if I didn't have to.
For projects that use #include <someInclude.h>
rather than #include "someInclude.h"
for non-system includes, cppclean will print
filename:line: 'Func' not found in any directly #included header
The logic is found in ast.py
here. (If there is <
then it is a system include). It looks like whether a include is system or not is used in find_warnings.py
here. Removing this logic (making all includes non-system includes) removes the false positive described above but introduces a new false positive:
filename:line: unable to find 'cmath'
This may be obvious but can you help me understand why system includes aren't being checked in the same way?
Assuming system includes do need to be differentiated, a solution to the above problem is to have users distinguish system includes on the cppclean call (e.g., using -I
for system includes and -i
for non-system includes.). It would then be a simple check in ast.py for whether a given include is in one of those sets of paths. If it is in neither, system could be assumed.
I am happy to submit a pull request if desired.
A practical example can be found from cloning SCRIMMAGE here and running the following:
cppclean -I src/proto_conversions/ProtoConversions.cpp
But this isn't allowed by the C++03 standard. The following simple test code (two files) demonstrates the issue:
myenum.h:
enum MyEnum {FOO, BAR, BAZ};
cppclean_test4.h:
// Header file where enum MyEnum is defined.
#include "myenum.h"
class A
{
// f takes a reference to MyEnum, but as an enum it can't be forward declared.
void f(MyEnum & bar);
};
cppclean prints:
cppclean_test4.h:2: 'myenum.h' does not need to be #included; use a forward declaration instead
Cppclean used to work before transitioning to C++11.
Running on valid C++11 code causes parsing errors of the form:
Token(u'return', 3189, 3195)
There are no line numbers in error messages to see what is wrong.
Header code in https://github.com/rakhimov/scram can be used to get the errors.
EDIT: I dug into this a bit, added some details below, and changed the name to be more descriptive. Sorry for the non-descript issue name. I haven't actually dug into what's causing it to crash, so I don't have much more detail there. I have however narrowed it down to a small example file which actually causes two separate crashes. If you run cppclean
on the file as is it'll complain about popping from an empty namespaces
list, but if you comment out the int
member, it'll give you a parsing error. The example file is here:
class Foo {
private:
atomic<bool> m_shutdown { false };
int m_threads_started = 0; // Comment this line out for a different error
vector<const function<void()> *> & list_of(const function<void()> &) { return m_callbacks; }
}
The stack trace the file as-is is:
Traceback (most recent call last):
File "/Users/user/venv/bin/cppclean", line 145, in <module>
sys.exit(main())
File "/Users/user/venv/bin/cppclean", line 120, in main
entire_ast = list([_f for _f in builder.generate() if _f])
File "/Users/user/venv/lib/python2.7/site-packages/cpp/ast.py", line 651, in generate
result = self._generate_one(token)
File "/Users/user/venv/lib/python2.7/site-packages/cpp/ast.py", line 675, in _generate_one
return method()
File "/Users/user/venv/lib/python2.7/site-packages/cpp/ast.py", line 1158, in handle_class
return self._handle_class_and_struct(Class)
File "/Users/user/venv/lib/python2.7/site-packages/cpp/ast.py", line 1155, in _handle_class_and_struct
return self._get_class(class_type, None)
File "/Users/user/venv/lib/python2.7/site-packages/cpp/ast.py", line 1456, in _get_class
body = list(ast.generate())
File "/Users/user/venv/lib/python2.7/site-packages/cpp/ast.py", line 647, in generate
if self.namespaces.pop():
IndexError: pop from empty list
And the error message when the int
member is commented out:
/Users/user/test_header.hpp: parsing error: (Token(u'>', 128, 129), [Token(u'bool', 32, 36), Token(u'>', 36, 37), Token(u'm_shutdown', 38, 48), Token(u'{', 49, 50), Token(u'false', 51, 56), Token(u'}', 57, 58), Token(u';', 58, 59), Token(u'vector', 64, 70), Token(u'<', 70, 71), Token(u'const', 71, 76), Token(u'function', 77, 85), Token(u'<', 85, 86), Token(u'void', 86, 90), Token(u'(', 90, 91), Token(u')', 91, 92), Token(u'>', 92, 93), Token(u'*', 94, 95), Token(u'>', 95, 96), Token(u'&', 97, 98), Token(u'list_of', 99, 106), Token(u'(', 106, 107), Token(u'const', 107, 112), Token(u'function', 113, 121), Token(u'<', 121, 122)], [])
This is on cppclean 0.8 as installed by pip
.
Hi,
I've tried today to run Cppclean on my code base, mostly for the header related feature. It didn't work well though; I had to modify slightly the Python sources so that it can go until the end.
These modifications are far from being clean (I'm far to be a Python expert!) but should point out some cases that might fail while using your software; the point where they fail in my code were clean (it might be due to new C++11 feature, such as alias with using or '= default' for class special members).
Best regards,
Sébastien
This is correct behaviour to put static variable in cpp file like for example for singletons while putting it in header file could be dangerous.
When parsing this header file:
#include <boost/function.hpp>
#include <boost/shared_array.hpp>
typedef boost::function<void(const boost::shared_array<uint8_t>&, uint32_t, bool)> ReadFinishedFunc;
I get:
Got exception in roscpp/include/ros/connection.h @ Token(u'typedef', 65, 72) []
Traceback (most recent call last):
File "/home/kruset/.virtualenvs/cppclean/bin/cppclean", line 120, in <module>
sys.exit(main())
File "/home/kruset/.virtualenvs/cppclean/bin/cppclean", line 101, in main
entire_ast = list([_f for _f in builder.generate() if _f])
File "/home/kruset/.virtualenvs/cppclean/local/lib/python2.7/site-packages/cpp/ast.py", line 730, in generate
result = self._generate_one(token)
File "/home/kruset/.virtualenvs/cppclean/local/lib/python2.7/site-packages/cpp/ast.py", line 756, in _generate_one
return method()
File "/home/kruset/.virtualenvs/cppclean/local/lib/python2.7/site-packages/cpp/ast.py", line 1431, in handle_typedef
new_type = self.converter.to_type(tokens)[0]
File "/home/kruset/.virtualenvs/cppclean/local/lib/python2.7/site-packages/cpp/ast.py", line 496, in to_type
add_type(self.to_type(new_tokens))
File "/home/kruset/.virtualenvs/cppclean/local/lib/python2.7/site-packages/cpp/ast.py", line 502, in to_type
add_type([])
File "/home/kruset/.virtualenvs/cppclean/local/lib/python2.7/site-packages/cpp/ast.py", line 485, in add_type
result.append(Type(name_tokens[0].start, name_tokens[-1].end,
IndexError: list index out of range
Another C++11 feature yields a token exception: Trailing return types in function declarations. Used version is ba20ade.
Got exception in MyClass.h @ Token('auto', 41, 45) []
Got exception in MyClass.h @ Token('class', 14, 19) []
MyClass.h: parsing error (Token('->', 68, 70), [Token('auto', 41, 45)], [Token('double', 50, 56), Token('const', 57, 62), Token('&', 63, 64), Token('t', 65, 66)])
#pragma once
class CMyClass
{
public:
auto Foo(double const & t) -> int {
return 42;
}
};
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.