clang-tidy: How to suppress warnings? - suppress-warnings

I recently started experimenting with the clang-tidy tool of llvm. Now I am trying to suppress false warnings from third party library code. For this I want to use the command line options
-header-filter=<string> or -line-filter=<string>
but so far without success. So for people with limited time I will put the question here at the beginning and explain later what I already tried.
Question
What option do I need to give to the clang-tidy tool to suppress a warning from a certain line and file?
if this is not possible
What option works to suppress warnings from external header files?
What I did so far
My original call to clang-tidy looks like this
clang-tidy-3.8 -checks=-*,clang-analyzer-*,-clang-analyzer-alpha* -p Generated/LinuxMakeClangNoPCH Sources/CodeAssistant/ModuleListsFileManipulator_fixtures.cpp
and the first line of the yielded warning that I want to suppress looks like this
.../gmock/gmock-spec-builders.h:1272:5: warning: Use of memory after it is freed [clang-analyzer-cplusplus.NewDelete]
return function_mocker_->AddNewExpectation(
The gmock people told me that this is a false positive so I want to suppress it. First I tried to use the -line-filter=<string> option. The documentation says:
-line-filter=<string> - List of files with line ranges to filter the
warnings. Can be used together with
-header-filter. The format of the list is a JSON
array of objects:
[
{"name":"file1.cpp","lines":[[1,3],[5,7]]},
{"name":"file2.h"}
]
I assumed that warnings in the given lines are filtered out. But the doc doesent say if they are filterd out or in.
After some fiddeling arround I created a .json file with the content
[
{"name":"gmock-spec-builders.h","lines":[[1272,1272]]}
]
and modified the command line to
clang-tidy-3.8 -checks=-*,clang-analyzer-*,-clang-analyzer-alpha* -p Generated/LinuxMakeClangNoPCH -line-filter="$(< Sources/CodeAssistant/CodeAssistant_ClangTidySuppressions.json)" Sources/CodeAssistant/ModuleListsFileManipulator_fixtures.cpp
which writes the content of the file into the argument. This suppresses the warning, but not only this warning, but all warnings from the ModuleListsFileManipulator_fixtures.cpp file. I tried more stuff but I could not make it work.
So I tried the -header-filter=<string> option. Here the documentation states that one has to give a regular expression that matches all the header files from which diagnostics shall be displayed. Ok, I thought, lets use a regualar expression that matches everything that is in the same folder as the analyzed .cpp file. I can live with that although it may remove warnings that result from me using external headers wrong.
Here I was not sure if the regular expression must match the full (absolute) filename or only a part of the filename. I tried
-header-filter=.*\/CodeAssistant\/.*.h
which matches all absolute header filenames in the CodeAssistant folder but it did not suppress the warnings from the gmock-spec-builders.h file.
So preferably I would like to suppress each warning individually so I can determine for each if it is a real problem or not, but if this is not possible I could also live with suppressing warnings from entire external headers.
Thank you for your time.

I solved the problem by adding // NOLINT to line 1790 of gmock-spec-builders.h
Here is the diff:
--- gmock-spec-builders.orig.h 2016-09-17 09:46:48.527313088 +0200
+++ gmock-spec-builders.h 2016-09-17 09:46:58.958353697 +0200
## -1787,7 +1787,7 ##
#define ON_CALL(obj, call) GMOCK_ON_CALL_IMPL_(obj, call)
#define GMOCK_EXPECT_CALL_IMPL_(obj, call) \
- ((obj).gmock_##call).InternalExpectedAt(__FILE__, __LINE__, #obj, #call)
+ ((obj).gmock_##call).InternalExpectedAt(__FILE__, __LINE__, #obj, #call) // NOLINT
#define EXPECT_CALL(obj, call) GMOCK_EXPECT_CALL_IMPL_(obj, call)
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
It would be nice to either upstream this patch (I see other NOLINT in the code) or post a bug report with the clang-tidy folks.

I have found another non-invasive (without adding // NOLINT to a third-party library) way to suppress warnings. For example, the current version of Google Test fails some cppcoreguidelines-* checks. The following code allows you to validate the current diff excluding lines that contain gtest's macros:
git diff -U3 | sed '
s/^+\( *TEST(\)/ \1/;
s/^+\( *EXPECT_[A-Z]*(\)/ \1/;
s/^+\( *ASSERT_[A-Z]*(\)/ \1/;
' | recountdiff | interdiff -U0 /dev/null /dev/stdin | clang-tidy-diff.py -p1 -path build
It assumes that file build/compile_commands.json is generated before and clang-tidy-diff.py is available from your environment. recountdiff and interdiff from patchutils are the standard tools for manipulating patches.
The script works as follows:
git diff -U3 generates a patch with 3 context lines.
sed ... removes prefix + from the undesired lines, i.e. transform them to the context.
recountdiff correct offsets (in first ranges) in the chunk headers.
interdiff -U0 /dev/null /dev/stdin just removes all context lines from a patch. As a result, it splits the initial hunks.
clang-tidy-diff.py reads only second ranges from chunk headers and passes them to clang-tidy via -line-filter option.
UPD: It's important to provide interdiff with a sufficient number of context lines, otherwise it may produce some artifacts in the result. See the citation from man interdiff:
For best results, the diffs must have at least three lines of context.
Particularly, I have found that git diff -U0 | ... | interdiff generates some spurious literals $!otj after splitting chunks.

Use -isystem instead of -I to set your system and 3rd party include paths. -I should only be used to include code that is part of the project being built.
This is the only thing required to make clang-tidy ignore all errors in external code. All the other answers (at the point of writing) are just poor workarounds for something that is perfectly solved with -isystem.
If you use a build system like CMake or Meson it will automatically set -I and -isystem correctly for you.
-isystem is also the mechanism that is used for telling compilers, at least GCC and Clang, what's not your code. If you start to use -isystem you can also enable more compiler warnings without getting "false positives" from external code.

I couldn't achive what I wanted with the commmand line options, so I will use the // NOLINT comments in the cpp files which was proposed by the accepted answer.
I will also try to push the fix to googletest.
I found out that lines in the -line-filter options are filtered in.
But giving concrete lines is no real solution for my problem anyways.
I rather need a suppression mechanism like it is implemented in Valgrind.

Related

VSCode - How to delete a specific command history in command palette (as opposed to clearing everything)?

I would like to delete several commands from VSCode command palette's "recently used" section, but not clear the entire history. How?
So in Chrome's Omnibar, you can use Shift+del to delete a suggestion. But I cannot find an analogous shortcut in VSCode's command palette.
I also looked for a "meta-command" for this, but I only found Clear Command History in the command palette. I want something like Edit/Manage Command History instead.
Edit: a history file that I can directly edit (analogous to ~/.bash_history for Bash) would also do.
Okay, so this question was upvoted today, which brought it back to my attention. I decided to bite the bullet this time and dug into the nuts and bolts of VSCode's files and found where this history is stored.
TLDR
Modifying the history is doable (obviously, because it has to be stored somewhere), but it's not very practical at all. Unfortunately it will continue to be very difficult, until VSCode implements official support (which may be never). I recommend using the following method ONLY IF you absolutely need a history entry deleted.
The method
Note:
I'm using Code OSS (the debranded build of VSCode) on Linux. The method should be applicable to other OSes, but the specific commands and paths will be different.
This method works on VSCode 1.74.2, the latest version as of 2023-01-04. It may or may not work with future versions.
0. Exit VSCode completely
Obviously.
Check with your resource/task/process manager to make sure VSCode is completely killed. If you're not sure, just reboot.
1. Locate lastSyncglobalState.json
This file contains the command palette history data. On Linux it's located at $XDG_CONFIG_HOME/Code - OSS/User/sync/globalState/lastSyncglobalState.json. On Windows it's probably under a similar path in %APPDATA%. Not sure about MacOS. Copy this file to somewhere convenient.
If you are curious how I discovered this file, I did a search of a command I recently ran using rg in $XDG_CONFIG_HOME/Code - OSS/. Note that you have to search the "programmatic name" of the command, not its display name (e.g. rust-analyzer.reload, not rust-analyzer: Restart server).
2. Extract the relevant data
If you open up lastSyncglobalState.json with a text editor directly, you'll find a Russian doll of escaped JSON. Technically you can do the modification straight from here, but I'm not eating this 💩.
Fortunately jq makes this somewhat easier:
# This is Bash but I think it works on Windows CMD too? Not sure.
jq '.syncData.content | fromjson.storage."commandPalette.mru.cache".value | fromjson.entries' lastSyncglobalState.json > history.json
The extracted history.json should look something like this:
[
{
"key": "rust-analyzer.debug",
"value": 297
},
{
"key": "rust-analyzer.syntaxTree",
"value": 298
},
// more entries...
]
3. Modify
Copy history.json to history-new.json, and simply remove the entries you want to delete from history-new.json. Do not modify history.json; we will need it in a bit.
Check that it's still valid JSON after your edits; in particular make sure that you have not left a trailing comma in the array.
4. Write back
The responsible way to do this is to perform the inverse of step 2, starting from the bottom up, update a field, json-encode, then update the field one level up, json-encode again, etc, until we get to the top level. But that's an enormous pain in the arse to do with jq.
Much easier I think, simply double (triple?) json-encode history-new.json, and perform a textual replacement. This is where the original history.json comes in handy:
# In lastSyncglobalState.json, replace the output of...
jq 'tojson | tojson' history.json
# with the output of...
jq 'tojson | tojson' history-new.json
Note that since the output of jq is quoted, it's necessary to remove the outmost layer of quotes (") on both the search string and the replace string. With rg we can automate this:
jq 'tojson | tojson' history.json | rg '^"(.+)"$' -r '$1'
jq 'tojson | tojson' history-new.json | rg '^"(.+)"$' -r '$1'
Of course there's nothing wrong with doing it manually, or with using sed instead if you want to. Again, just be careful you're not creating invalid JSON.
5. Copy back into VSCode directory
Honestly, you probably want to make a backup of the entire $XDG_CONFIG_HOME/Code - OSS/ directory (or whatever it is on your machine) before doing this. It's probably big I know, but I'm not sure what crazy thing VSCode will do if it finds lastSyncglobalState.json unparseable. Better be safe than sorry.
After you've done that, just copy your modified lastSyncglobalState.json back into $XDG_CONFIG_HOME/Code - OSS/User/sync/globalState/lastSyncglobalState.json and voila.
VSCode terminal uses external shell. For linux the default shell it's bash, for windows it's powershell.
If your terminal shell is powershell, go to C:\Users\john\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline on your file explorer
Visit this link for more details, if the above does not help.

LaTeX command for last modified

Is there a LaTeX command that prints the "last modified" date of the actual document? Since LaTeX projects consist of more than one file this command ideally prints the date of the actual file, not that of the project.
pdfTeX provides the primitive \pdffilemoddate to query this information for files. (LuaTeX uses its own Lua functions for the same thing.) Since pdfTeX is used by default in all LaTeX distributions in the last few years (at least), there's no harm in using the new functionality unless you're dealing with very old production systems. Here's an example:
\documentclass{article}
\begin{document}
\def\parsedate #1:20#2#3#4#5#6#7#8\empty{20#2#3/#4#5/#6#7}
\def\moddate#1{\expandafter\parsedate\pdffilemoddate{#1}\empty}
this is the moddate: \moddate{\jobname.tex}
\end{document}
(Assuming the file has been modified since year 2000.)
The package filemod seems to do exactly what you need. To get the last modified date of the file you just include the package in the usual way:
\usepackage{filemod}
and the modification time of the current document is printed by:
\filemodprintdate{\jobname}
you can also print the modification time, and there are many options to format the output.
Unfortunately, TeX does not provide commands for such information; the only way to get such information is
by running a non-TeX script to create a TeX file before running LaTeX and including this file in your main LaTeX document somehow, or
by running the external script from TeX (which only works if the so-called write18 or shellescape feature is enabled; you'd have to consult the manual of your TeX implementation for this, and not have a stubborn sysadmin).
It is possible that extended TeXs do support file info commands (luaTeX perhaps?), but it's not part of TeX proper.
If you are using an automated build system, you could ask it to generate a file (perhaps named today.sty) which depends on all the source files.
In make that might look like:
today.sty: $LATEX_SRCS
echo "\date{" > $#
date +D >> $#
echo "}" >> $#
and \usepackage{today.sty}.
The will use the date of the first build after a file changes, and won't update until either you delete today.sty or alter another source file.
thank dmckee
LATEX_SRCS = test.tex
define moddate
date +%Y%m%d%H%M%S
endef
today.sty: $(LATEX_SRCS)
#echo "\def\moddate{"$(shell $(moddate))"}"> $#
There is the getfiledate LaTeX package (it was part of my LaTeX distribution by default). It seems to be designed to automatically output a paragraph like:
The date of last modification of file misc-test1.tex was 2009-10-11  21:45:50.
with a bit of ability to tweak the output. You can definitely get just the date. However, I couldn't figure out how to get rid of newlines around the date and how to change the date format. To be honest I think the authors implemented it exactly for the single purpose they needed it, and it is rather cumbersome for general use.

showing differences within a line in diff output

This StackOverflow answer has an image of KDiff3 highlighting intra-line differences. Does someone know of a tool which can show the same (ex, via color) on the command line?
Another way to think of this is wanting to diff each difference in a patch file.
I don't know if this is sufficiently command line for your purpose, but vimdiff can do this (even does colour). See for example the image in this related question.
I tried all the tools I found: wdiff, dwdiff, kdiff3, vimdiff to show the difference between two long and slightly different lines. My favourite is diff-highlight (part of git contrib)
it supports diff format - great advantage over tools requiring two files like (dwdiff), e.g. if you need to visualize the output of unit tests
it highlights with black+white or with color if you connect it to colordiff
highlights characterwise - helpful for comparing long lines without spaces (better than wdiff)
Installation
On Ubuntu, you probably already have it as part of git contrib (installed within the git deb package).
Copy or link it into your ~/bin folder from /usr/share/doc/git/contrib/diff-highlight/diff-highlight
Usage example
cat tmp.diff | diff-highlight | colordiff
Result:
Another intuitive way to see all word-sized differences (though not side-by-side) is to use wdiff together with colordiff (you might need to install both). An example of this would be:
wdiff -n {file-A} {file-A} | colordiff
You can optionally pipe this into less -R to scroll through the output (-R is used to show the colors in less).
I had a similar problem and wanted to avoid using vimdiff. I found dwdiff (which is available in Debian) to have several advantages over wdiff.
The most useful feature of dwdiff is that you can customise the delimiters with -d [CHARS], so it's useful for comparing all kinds of output. It also has color built in with the -c flag.
You might be able to use colordiff for this.
In their man page:
Any options passed to colordiff are
passed through to diff except for the
colordiff-specific option 'difftype',
e.g.
colordiff --difftype=debdiff file1
file2
Valid values for 'difftype' are: diff,
diffc, diffu, diffy, wdiff, debdiff;
these correspond to plain diffs,
context diffs, unified diffs,
side-by-side diffs, wdiff output and
debdiff output respectively. Use these
overrides when colordiff is not able
to determine the diff-type
automatically.
I haven't tested it, but the side-by-side output (as produced by diff -y file1 file2) might give you the equivalent of in-line differences.
ccdiff is a convenient dedicated tool for the task. Here is what an example may look like with it:
By default, it highlights the differences in color, but it can be used on a console without color support too.
The package is included in the main repository of Debian:
ccdiff is a colored diff that also colors inside changed lines.
All command-line tools that show the difference between two files fall short in showing minor changes visuably useful. ccdiff tries to give the look and feel of diff --color or colordiff, but extending the display of colored output from colored deleted and added lines to colors for deleted and addedd characters within the changed lines.

How do you use the diff command against two source trees

I tried running 'diff' against two source directories get a patch file with a 'diff' between the two directories.
diff -rupN flyingsaucer-R8pre2_b/ flyingsaucer-R8pre2/ > a.patch
The command above does not seem to work, it generates a diff of everything and I get a 13 MB file, when in reality, it should be a couple of changes.
Should work with any recent version of gnu diff (tested here with gnu diff 2.8.1.)
You might want to add -b (and perhaps -B) to ignore difference in white space which perhaps generate large patch files unnecessarily.
I don't see any reason why it wouldn't work. Try adding "wb" to the argument list to ignore whitespace changes. Are you sure you got the trailing slashes the same on both sides?

Using the output of diff to create the patch

I have something like this
src/sim/simulate.cc
41d40
< #include "mem/mem-interface.h"
90,91d88
< dram_print_stats_common(curTick/500);
<
src/mem/physical.hh
52d51
< public:
55,56d53
< public:
<
58a56,57
> public:
>
61,62c60,61
< virtual bool recvTiming(PacketPtr pkt); //baoyg
<
---
I believe this was created using the diff command in a source tree. What I want is to create the patch using that output, and to apply the same changes to my source tree.
I believe that diff -u oldfile newfile > a.patch is used to create patch files, although some other switched may be thrown in as well (-N?).
Edit: OK, 4 years later and finally going to explain what the switches mean:
-u creates a Unified diff. Unified diffs are the kind of diffs that the patch program expects to get as input. You can also specify a number after the u (min 3, default 3) to increase the number of lines output. This is in case 3 lines isn't unique enough to pinpoint just one spot in the program.
-N treats absent files as being empty, which means it will produce a lot of additional content if one of the files is empty (or see next point).
Also, newfile and oldfile can both be directories instead of single files. You'll likely want the -r argument for this to recurse any subdirectories.
If you want to get the same patch output as SVN or git diff, given two different files or folders:
diff -Naur file1.cpp file2.cpp
What you have there is a non-unified diff. patch can read it, but will be unable to make context matches and is more likely to make mistakes.
That is a (partial) patch file, though it would have been better if they provided you with a unified diff output.
The main issue with that patch is that it doesn't mention which files are being modified, and since there is no context provided, the files must be exact, patch will be unable to allow for minor changes in the file.
Copy the diff in the original post to a patch file named test.patch then run
patch <original file> test.patch
#Sparr and #Arafangion point out that this works best if you have the exact original file used to create the original diff.