Author Topic: howto use clang-tidy in code::blocks  (Read 5583 times)

Offline blauzahn

  • Multiple posting newcomer
  • *
  • Posts: 115
howto use clang-tidy in code::blocks
« on: October 03, 2017, 02:01:25 pm »
I use that very helpful tool in code::blocks regularly and just want to share that knowledge.
Trick is, to use it as if it were a compiler and rely on the build-mechanism within code::blocks
for that.

These notes have been tried with svn 11182 under ubuntu 16.04. Apart from the apt install part,
the rest should work for other Linux distros as well.


What is it?

Quote
clang-tidy is a clang-based C++ “linter” tool [...] for diagnosing and fixing typical programming errors,
like style violations, interface misuse, or bugs that can be deduced via static analysis.

see: http://clang.llvm.org/extra/clang-tidy/index.html


Installing clang and clang-tidy:

Here on ubuntu commandline, taken from
http://askubuntu.com/questions/787383/how-to-install-llvm-3-9#799998

Code
$ wget http://apt.llvm.org/llvm-snapshot.gpg.key
$ sudo apt-key add llvm-snapshot.gpg.key
$ sudo apt-add-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial main"
$ sudo apt-get update
$ sudo apt-get install clang-5.0 clang-tidy-5.0


Check, whether clang-tidy has been installed correctly:
Code
$ clang-tidy --version

Should print a few lines with version info on stdout.

You can try bleeding edge clang-6.0 clang-tidy-6.0 as well.
http://clang.llvm.org/extra/ReleaseNotes.html


Add compiler in code::blocks:
  • open Settings|compiler|Selected compiler: LLVM Clang Compiler
  • Copy|Please enter the new compiler's name: clang-tidy
  • open Toolchain executables|c++ compiler: clang-tidy-5.0
  • open Settings|compiler|clang-tidy|Other settings|Advanced options...|command line macro:
        $compiler $file -config='' -header-filter='^[^/].*' -- $includes $options

        Please change this only for clang-tidy, not for the other compiler.


Add target to your code::blocks project:
  • open your project workspace
  • open Project|Properties...|Build targets
  • select a Build target (e.g. Debug)| Duplicate
  • Enter the duplicated build target's name: (e.g. Debug clang-tidy)
  • select the newly duplicated Build target (e.g. Debug clang-tidy)
  • open Build options...| selected compiler: clang-tidy
  • select menu File | Save project


Create a file named .clang-tidy:

Please put it into the directory where your code::blocks workspace file resides.
Here is a sample file to begin with (Here I uncommented (activated) the NullDereference check):

Code
---

## disable all, then enable one check only:
Checks: '-*,clang-analyzer-core.NullDereference'

# Checks: '-*,modernize-use-nullptr'
# Checks: '-*,cppcoreguidelines-special-member-functions'

## disable all,then enable 2 checks:
# Checks: '-*,modernize-use-nullptr,readability-identifier-naming'

## enable all, then disable unwanted group and a single check:
# Checks: '*,-clang-analyzer-alpha*,-llvm-header-guard'

HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false

CheckOptions:
  - key:             modernize-use-nullptr.NullMacros
    value:           'NULL'
  - key:             readability-identifier-naming.PrivateMemberCase
    value:           aNy_CasE
  - key:             readability-identifier-naming.MemberPrefix
    value:           'm_'
...

Please feel free to adopt it to select the checks you want.


Execute clang-tidy from within code::blocks:
  • open your project
  • select menu Build | Rebuild (Ctrl-F11)
       Note: "compiling" takes longer than a regular compile
  • open View | Logs (F2) | Build messages
      Note: ignore the messages about missing object files like: error: no such file or directory: 'obj/foo.o
  • select one of the blue compiler-warnings and by that jump to the file and line
      (see attached screenshot)
  • fix it


Recommendation:

When applied to an existing larger codebase, start with a single check.
Otherwise you might get an overwhelming number of warnings.
That way helps you to focus and attack one problem at a time.
Once you cleaned your code enough, you might settle on your favourite set of checks
against future regressions.


Bjarne Stroustrup @ CppCon 2017:
Quote
People will not have to find the rule. The rule will find you.
https://www.youtube.com/watch?v=fX2W3nNjJIo

enjoy

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5391
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: howto use clang-tidy in code::blocks
« Reply #1 on: October 04, 2017, 05:52:23 am »
This is a nice tool, but it looks like configure the tool is complex. :)

About the screen shot, I think the line
Code
*p = 0;
is a bug.

In line 730, I don't see any issue:
Code
    if (lines.GetCount() == 0)
        return false;
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline blauzahn

  • Multiple posting newcomer
  • *
  • Posts: 115
Re: howto use clang-tidy in code::blocks
« Reply #2 on: October 04, 2017, 07:48:49 am »
I made it deliberately detailed, so that even cb users with less experience than you can follow it.
The urls are there as a reference only. You can skip them.

Although recent clang-tidy got more checks, you can use the version a linux distro provides out of the box, like
Code
$ sudo apt-get install clang-tidy

The core part is to add in cb a compiler and adjust the way it is called:
open Settings|compiler|clang-tidy|Other settings|Advanced options...|command line macro:
Code
$compiler $file -config='' -header-filter='^[^/].*' -- $includes $options

The file .clang-tidy helps getting started and shows, how to select a check.

Quote
I think the line [...] is a bug.
See, how it helps to improve code. This may include cb as well;-)


Quote
In line 730, I don't see any issue
It is a note, no warning. Intention of the screenshot is to show, how it looks like and
that the apperearance and usage is like regular compiler warnings.

Offline jalcazo

  • Multiple posting newcomer
  • *
  • Posts: 23
Re: howto use clang-tidy in code::blocks
« Reply #3 on: October 18, 2021, 07:12:44 am »
Hi, I'm having problems with clang-tidy, my advanced options look like this:

Code
$compiler $file -header-filter='^[^/].*' -- $includes $options

But it can't find SOME .h files, it gets MOST of them but SOME are missing:


Offline jalcazo

  • Multiple posting newcomer
  • *
  • Posts: 23
Re: howto use clang-tidy in code::blocks
« Reply #4 on: October 18, 2021, 07:14:24 am »
Book.cpp for instance looks like this currently:



Audio.cpp for instance does #include <Audio.h> with no problems.

What's going on?

Offline jalcazo

  • Multiple posting newcomer
  • *
  • Posts: 23
Re: howto use clang-tidy in code::blocks
« Reply #5 on: October 18, 2021, 07:15:22 am »

Offline BlueHazzard

  • Developer
  • Lives here!
  • *****
  • Posts: 3019
Re: howto use clang-tidy in code::blocks
« Reply #6 on: October 18, 2021, 05:13:26 pm »
Again, a full rebuild log from the build log tab would help a lot.

If it is too large for the forum, please attach a txt file

In what directory are the headers?

Offline jalcazo

  • Multiple posting newcomer
  • *
  • Posts: 23
Re: howto use clang-tidy in code::blocks
« Reply #7 on: October 18, 2021, 05:59:49 pm »
Thanks again BlueHazzard  for your answer, time and help ;D

I'll use the .txt attach good idea! I didn't thought that.

Here it is, do you see anything interesting here on why JUST SOME headers are not found while it founds the others (apparently there's no difference).

For instance, Book.cpp uses #include <Book.h> and it DOESN'T find it, but Mouse.cpp uses as well #include <Mouse.h> and it doesn't complain about it.

Offline BlueHazzard

  • Developer
  • Lives here!
  • *****
  • Posts: 3019
Re: howto use clang-tidy in code::blocks
« Reply #8 on: October 18, 2021, 07:54:23 pm »
hmm... i see no obvious problem...
i probably would try to use
Code
#include "Book.h"
instead, because <> is generally used for system includes

Offline jalcazo

  • Multiple posting newcomer
  • *
  • Posts: 23
Re: howto use clang-tidy in code::blocks
« Reply #9 on: October 18, 2021, 10:12:52 pm »
Sadly that yields the same result.

Interestingly, when using:

Code
#include 'Book.h'

(notice the single ' ) the results are different:

Code

-------------- Build: Compilar amb CLANG-tidy STATIC ANALYSIS in Morgana (compiler: Clang-TIDY Static Analysis)---------------

clang-tidy.exe W:\Morgana\main.cpp -header-filter='^[^/].*' -- -IW:\Morgana\include -Wall -fexceptions -m64 -pedantic -w
clang-tidy.exe W:\Morgana\src\animations\AttributesAnimation.cpp -header-filter='^[^/].*' -- -IW:\Morgana\include -Wall -fexceptions -m64 -pedantic -w
clang-tidy.exe W:\Morgana\src\Audio.cpp -header-filter='^[^/].*' -- -IW:\Morgana\include -Wall -fexceptions -m64 -pedantic -w
clang-tidy.exe W:\Morgana\src\Companion.cpp -header-filter='^[^/].*' -- -IW:\Morgana\include -Wall -fexceptions -m64 -pedantic -w
clang-tidy.exe W:\Morgana\src\Engine.cpp -header-filter='^[^/].*' -- -IW:\Morgana\include -Wall -fexceptions -m64 -pedantic -w
clang-tidy.exe W:\Morgana\src\Error.cpp -header-filter='^[^/].*' -- -IW:\Morgana\include -Wall -fexceptions -m64 -pedantic -w
clang-tidy.exe W:\Morgana\src\Inventory.cpp -header-filter='^[^/].*' -- -IW:\Morgana\include -Wall -fexceptions -m64 -pedantic -w
clang-tidy.exe W:\Morgana\src\items\Book.cpp -header-filter='^[^/].*' -- -IW:\Morgana\include -Wall -fexceptions -m64 -pedantic -w
5 errors generated.
Error while processing W:\Morgana\src\items\Book.cpp.
Found compiler error(s).
W:\Morgana\src\items\Book.cpp:1:10: error: expected "FILENAME" or <FILENAME> [clang-diagnostic-error]
#include 'Book.h'
         ^
W:\Morgana\src\items\Book.cpp:4:1: error: use of undeclared identifier 'Book' [clang-diagnostic-error]
Book::Book(const string& name, const string& name_to_show){
^
W:\Morgana\src\items\Book.cpp:4:18: error: unknown type name 'string' [clang-diagnostic-error]
Book::Book(const string& name, const string& name_to_show){
                 ^
W:\Morgana\src\items\Book.cpp:4:38: error: unknown type name 'string' [clang-diagnostic-error]
Book::Book(const string& name, const string& name_to_show){
                                     ^
W:\Morgana\src\items\Book.cpp:13:1: error: use of undeclared identifier 'Book' [clang-diagnostic-error]
Book::~Book(){} // don't delete or "undefined reference to vtable..."
^
Process terminated with status 1 (0 minute(s), 0 second(s))
 
1 error generated.
Error while processing W:\Morgana\src\Engine.cpp.
Found compiler error(s).
W:\Morgana\src\Engine.cpp:3:10: error: 'Screen.h' file not found [clang-diagnostic-error]
#include <Screen.h>
         ^
Process terminated with status 1 (0 minute(s), 0 second(s))
 
1 error generated.
Error while processing W:\Morgana\main.cpp.
Found compiler error(s).
W:\Morgana\main.cpp:2:10: error: 'Level1.h' file not found [clang-diagnostic-error]
#include <Level1.h>
         ^
1 error generated.
Error while processing W:\Morgana\src\animations\AttributesAnimation.cpp.
Found compiler error(s).
W:\Morgana\src\animations\AttributesAnimation.cpp:1:10: error: 'AttributesAnimation.h' file not found [clang-diagnostic-error]
#include <AttributesAnimation.h>
         ^
1 error generated.
Error while processing W:\Morgana\src\Inventory.cpp.
Found compiler error(s).
W:\Morgana\include\Inventory.h:6:10: error: 'Item.h' file not found [clang-diagnostic-error]
#include <Item.h>
         ^
Process terminated with status 1 (0 minute(s), 0 second(s))
 
Process terminated with status 1 (0 minute(s), 0 second(s))
 
1 error generated.
Error while processing W:\Morgana\src\Audio.cpp.
Found compiler error(s).
W:\Morgana\include\SDL2/SDL_stdinc.h:683:12: error: use of undeclared identifier 'memcpy' [clang-diagnostic-error]
    return SDL_memcpy(dst, src, dwords * 4);
           ^
W:\Morgana\include\SDL2/SDL_stdinc.h:653:20: note: expanded from macro 'SDL_memcpy'
#define SDL_memcpy memcpy
                   ^
Process terminated with status 1 (0 minute(s), 0 second(s))
 
Process terminated with status 1 (0 minute(s), 0 second(s))
 
Process terminated with status 0 (0 minute(s), 3 second(s))
10 error(s), 0 warning(s) (0 minute(s), 3 second(s))

This has something to do with the regular expression:

Code
-header-filter='^[^/].*'

I must dig into this and how it is formed. I don't understand it at all. Any resource explaining this particular type of regular expression?

Offline blauzahn

  • Multiple posting newcomer
  • *
  • Posts: 115
Re: howto use clang-tidy in code::blocks
« Reply #10 on: October 19, 2021, 03:35:46 am »
Hello,
my command line looks like this:

Code
$compiler $file -config='' -header-filter='^[^/].*' -- $includes $options

I am using Linux and this has worked so far for several years. The code compiles with MSVC as well but I do not use clang-tidy on windows.

Please do not use single quotes for header names. For separators of directory names I recommend / instead of \. This also works on Windows.

Offline jalcazo

  • Multiple posting newcomer
  • *
  • Posts: 23
Re: howto use clang-tidy in code::blocks
« Reply #11 on: October 19, 2021, 06:09:08 am »
Thank you blauzahn for your answer and original post!

Using exactly your line from your last message the error for me is: (I use Code::Blocks on Windows 10)

Code
File    Line     Message
YAML     1      error: not a mapping
                Error: invalid configuration specified.

The log attached:
« Last Edit: October 19, 2021, 06:11:15 am by jalcazo »

Offline jalcazo

  • Multiple posting newcomer
  • *
  • Posts: 23
Re: howto use clang-tidy in code::blocks
« Reply #12 on: October 19, 2021, 06:15:35 am »
Examining the log I don't understand why it just tries to compile a few specific .cpp files of all the total. Seems to ignore the rest. From a ignored file, for instance, Tarot_Wall.cpp, I tried both
Code
#include "Tarot_Wall.h"
and
Code
#include <Tarot_Wall.h>
with no luck. It ignores Tarot_Wall.cpp every time (among others) (check the log.txt from my last message, please).
« Last Edit: October 19, 2021, 06:17:06 am by jalcazo »

Offline blauzahn

  • Multiple posting newcomer
  • *
  • Posts: 115
Re: howto use clang-tidy in code::blocks
« Reply #13 on: October 19, 2021, 08:13:30 am »
Maybe your .clang-tidy file is not correct.  Please try to move it away and try temporarily without or with a minimal one. Then create a new one (see docs howto). Start small.

You can set within the compiler settings the max errors count to zero, so that cb continues calling the "compiler" with the next "translation unit" regardless of the number of "hard compiler errors" seen so far. Output that is parsed and considered to be a warning is not limited though.

You do not have the compiler warning "-Werror" enabled, haven't you?

As for the #include<> versus "": Please have look into the core-guidelines on isocpp.org or/and read a decent book about C++. E.g. "A tour of C++" by Bjarne Stroustrup.

What version of clang tidy do you use?

Offline jalcazo

  • Multiple posting newcomer
  • *
  • Posts: 23
Re: howto use clang-tidy in code::blocks
« Reply #14 on: October 20, 2021, 11:09:09 am »
Hi again blauzahn. Thanks for your answer, your help, your time and your patience.

The project structure is like this:



Is there where the file goes? It has no extension, right? I created a new empty file and added only to the build option "Clang Tidy".

The contents of the file are the ones you provided:

Code
---

## disable all, then enable one check only:
Checks: '-*,clang-analyzer-core.NullDereference'

# Checks: '-*,modernize-use-nullptr'
# Checks: '-*,cppcoreguidelines-special-member-functions'

## disable all,then enable 2 checks:
# Checks: '-*,modernize-use-nullptr,readability-identifier-naming'

## enable all, then disable unwanted group and a single check:
# Checks: '*,-clang-analyzer-alpha*,-llvm-header-guard'

HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false

CheckOptions:
  - key:             modernize-use-nullptr.NullMacros
    value:           'NULL'
  - key:             readability-identifier-naming.PrivateMemberCase
    value:           aNy_CasE
  - key:             readability-identifier-naming.MemberPrefix
    value:           'm_'
...

I tried it with or without "..." at the end (I don't understand if this is necessary).

Every time it tells the error YAML error: not a mapping, as seen in the attached log:

When you tell me "Then create a new one (see docs howto)." I don't understand what you are saying to me exactly. Please expand on this point, I don't know where is "docs howto".

About -Werror I looked it and it's not checked.

Clang-tidy version:

Code
H:\morgana>clang-tidy --version
LLVM (http://llvm.org/):
  LLVM version 11.0.0
  Optimized build.
  Default target: i686-pc-windows-msvc
  Host CPU: haswell

Finally, removing the file .clang-tidy alltogether produces the same YAML errors seen in the log.txt attached.