How to exclude single checks from clang-tidy file? - c++

Let's talk about this simple example:
#include <iostream>
int main(int argc, char *argv[])
{
std::cout << "started " << argv[0] << " with " << argc << " params." << std::endl;
return 0;
}
We have a minimal .clang-tidy file which looks like this:
Checks:
'-*,
cppcoreguidelines-*,
-cppcoreguidelines-pro-bounds-pointer-arithmetic'
WarningsAsErrors:
'*'
Even though I get the following warning:
src/main.cpp:5:30: error: do not use pointer arithmetic [cppcoreguidelines-pro-bounds-pointer-arithmetic,-warnings-as-errors]
std::cout << "started " << argv[0] << " with " << argc << " params." << std::endl;
^
I don't want to mess around with NOLINT in my code and I don't want to add some additional flags to the CMakeLists.txt file just because of clang-tidy.
Is there a clean way, to mask some single checks in the .clang-tidy file?
I'm using gcc/g++ and clang-tidy in version 6.0.0 on Linux. I'm aware of How to disable a clang-tidy check? - but it doesn't answer my question and the duplicate link is simply wrong.

In my case, I think the problem had to do with glob expansion order. Originally, the Checks line in my .clang-tidy looked like this:
Checks: 'clang-diagnostic-*,clang-analyzer-*,*'
I wanted to disable the altera-unroll-loops diagnostic. The fix was to add it after that sneaky glob-all at the end:
Checks: 'clang-diagnostic-*,clang-analyzer-*,*,-altera-unroll-loops'
Initially, I had it placed before the *, which, I think, caused it to be overridden. I also had no problem with it being split across multiple lines, like you have above.

Related

Printing addresses with 0x notation

Currently when I print an address of a variable,
cout << &a, its displayed as a simple hexadecimal number, let's say: 008FFBB8.
How can I print an address with the 0x notation? e.g. 0x6FFDF4.
I tried doing:
cout << hex << &a;
but it doesn't seem to work.
There are many different solutions, the first two that came into my mind are the following:
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
int main()
{
std::cout << std::hex
<< "showbase: " << std::showbase<< 42 << '\n'
<< "noshowbase: " << std::noshowbase << 42 << '\n';
//2nd solution
std::string a{"008FFBB8"};
std::cout << "Given: " << a << '\n';
a.erase(0,2);
a = "0x"+a;
std::cout << "Edited: "<< a <<'\n';
//3rd string to int so you can use standard arithmetics
int b = std::stoul(a, nullptr, 16);
std::cout << "Represented as int: " << b << '\n';
std::cin.get();
}
Edit:
This is how it is printed after compilation with GNU GCC(g++) compiler.
The reason visual studio isn't printing it as shown on the screenshot is because visual studio tend not to use GNU GCC but its Microsoft compiler MSVC.(There are other things MSVC isn't doing as you may expect btw.) But good news: you can make it! or here:)
It is just how hex is presented in your configuration with "MSVC"
I hope that answers your question, else leave a comment :)
A simple approach
cout << "0x" << &a;
That said, given that other systems do inlude 0x in &a, in order to make it portable, you should make cout << "0x" conditional based on predefined macro that detects the systems where 0x isn't included.
A portable solution is to insert into a string stream first, then check whether the prefix was added, and concatenate if it wasn't. this also prevents possibility of 0x and the address being separated by concurrent output.
I just wanted to know why Visual Studio is not displaying this notation by default,
Because the authors of their standard library chose to do so.
so I don't have to manually do it.
I'm not sure if there is a way to change their implementation. Before asking how, I recommend considering why you think that you have to do it.
Taking inspiration ;) from MSDN and trying it on VS 2019:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
ios state(nullptr);
int a;
state.copyfmt(cout); // save current formatting
cout << "In hex: 0x" // now load up a bunch of formatting modifiers
<< hex
<< uppercase
<< setw(8)
<< setfill('0')
<< &a // the actual value we wanted to print out
<< endl;
cout.copyfmt(state); // restore previous formatting
}
Output:
In hex: 0x00AFFB44
And as for why, well...you could raise an issue on MSVC and claim parity with all other compilers and platforms if you have the data. But given that they themselves manually slipped in the 0x I'm guessing they are already comfortable with the behavior.

Clang AST find only syntax errors

I'm using Clang to create some internal static code analyzers. For one of the analyzers, we need to take a raw string and check if it has any syntax errors.
We shouldn't consider missing symbols, missing headers, invalid function calls etc. as invalid syntax - as the only meaning is to see if it's a valid C/C++ code or not.
I thought initially that I could do it with ASTUnit:
auto AST = tooling::buildASTFromCodeWithArgs(MyCode,
Args,
"input.cc",
"clang-tool",
std::make_shared<PCHContainerOperations>(),
tooling::getClangStripDependencyFileAdjuster(),
tooling::FileContentMappings(),
&DiagConsumer);
llvm::outs() << "hasUncompilableErrorOccurred " << AST->getDiagnostics().hasUncompilableErrorOccurred() << "\n";
llvm::outs() << "hasUnrecoverableErrorOccurred " << AST->getDiagnostics().hasUnrecoverableErrorOccurred() << "\n";
llvm::outs() << "hasErrorOccurred " << AST->getDiagnostics().hasErrorOccurred() << "\n";
Taking two inputs: Hello world and #include <undefined.h> - both yields 1 in the outputs above - even when #include <undefined.h> is a correct C statement, but the issue with it (unlike with hello world, which's not a valid C code) - is that undefined.h is missing. Similarly, taking: int* p = malloc(sizeof(int)); as code will yield error in all of these calls if stdlib.h wasn't included.
I try to avoid such errors, so that every case, except from hello world, will be considered as valid code.
I did tried to iterate over it by creating a Raw Lexer, but it won't give me sufficient information.
Lexer Lex(CharRange.getBegin(), PP->getLangOpts(), Text.data(),
Text.data(), Text.data() + Text.size());
Token RawTok;
do {
Lex.LexFromRawLexer(RawTok);
llvm::outs() << "\t- " << RawTok.getKind() << "\n";
} while (RawTok.isNot(tok::eof));
I'd love to get any suggestions!

How to prevent clang-format from adding newlines between stream operator calls <<

We are currently in the process of formatting our code base with clang-format. We found a situation where for some reason the stream operator to std::cout is moved to the next line if two consecutive strings literals are present. Putting a variable in between thw two string literals causes clang-format to not change the format. What needs to be changed in the .clang-format file to avoid this?
int main()
{
std::cout << "something" << "something" << std::endl;
}
becomes
int main()
{
std::cout << "something"
<< "something" << std::endl;
}
while
int main()
{
int a = 0;
std::cout << "something" << a << "something" << std::endl;
}
stays untouched.
Note while this last snippet is wider, it is not split across multiple lines, while the shorter snippet above is.
This is with LLVM 9.0.0 Windows installer and is reproducible with the default config file.
This behavior can't be altered via the .clang-format file, as it is part of the code.
This behavior was introduced in this commit:
https://github.com/llvm-mirror/clang/commit/df28f7b8dd6a032515109de4ff5b4067be95da8e
Link to bug report: https://bugs.llvm.org/show_bug.cgi?id=45018

filesystem::* strange results in windows filesystem paths with extended chars

Code doesn't do anything useful. It's just try & error code to figure out what's going on:
fs::path path("e:\\Σtest");
cout<<path << " exsits="<< fs::exists(path) << " is dir=" << fs::is_directory(path) << std::endl;
fs::path pathL(L"e:\\Σtest");
cout<<pathL << " exsits="<< fs::exists(pathL) << " is dir=" << fs::is_directory(pathL) << std::endl;
fs::path pathu(u"e:\\Σtest");
cout<<pathu << " exsits="<< fs::exists(pathu) << " is dir=" << fs::is_directory(pathu) << std::endl;
Output:
e:\Σtest exsits=0 is dir=0
e:\Σtest exsits=0 is dir=0
e:\Σtest exsits=0 is dir=0
I sure that folder Σtest exists. I guess there is encoding involve somehow. I can't figure out what sophisticated problem we have encounter here, someone can explain output?
EDIT:
Following #cpplearner advice to pass /utf-8 to compiler output changes (also code page for console was changed to utf-8 by chcp 65001):
e:\Σtest exsits=0 is dir=0
e:\?test exsits=1 is dir=1
e:\?test exsits=1 is dir=1
Question remain the same, what magic happen here?

Cryptonote C++ compile error with invalid operands

I am working with cryptonote repo for a project and am at the point where I need to compile the binaries.
When I run make, I get the following error:
/Documents/huntcoin/src/CryptoNoteCore/SwappedMap.h:185:14: error: invalid operands of types ‘<unresolved overloaded function type>’ and ‘const char [24]’ to binary ‘operator<<’
std::count << "SwappedMap cache hits: " << m_cacheHits << ", misses: " << m_cacheMisses << " (" << std::fixed << std::setprecision(2) << static_cast<double>(m_cacheMisses) / (m_cacheHits + m_cacheMisses) * 100 << "%)" << std::endl;
~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
I am not super familiar with C++ and am sure it might be a simple parenthesis error, but it could be something more.
For some context, the previous make error I got was that std::cout was not defined, which I assumed was just a typo for count. Maybe that was wrong as well.
Any help with C++ or cryptonote would be much appreciated!
You've got an extra n that is causing you trouble. The code should read:
std::cout << "SwappedMap c.....
std::cout is the default console output (console output) stream while std::count is not defined
The std::cout is defined in a header file iostream so all you need to do is put this line of code next to other #include statements at the top of your file:
#include <iostream>
Cheers