tldr;> ¿Cómo oculto las advertencias de los encabezados del sistema en clang-tidy?
Tengo el siguiente archivo fuente de ejemplo mínimo, que activa una advertencia de aviso en los encabezados del sistema:
#include <future>
int main() {
std::promise<int> p;
p.set_value(3);
}
Llamándolo con libstdc++ 7.0.1 usando clang-tidy 4.0.0 en Ubuntu 17.04:
$ clang-tidy main.cpp -extra-arg=-std=c++14
rendimientos
Running without flags.
1 warning generated.
/usr/lib/gcc/x86_64-linux-gnu/7.0.1/../../../../include/c++/7.0.1/mutex:693:5: warning: Address of stack memory associated with local variable '__callable' is still referred to by the global variable '__once_callable' upon returning to the caller. This will be a dangling reference [clang-analyzer-core.StackAddressEscape]
}
^
/home/user/main.cpp:5:3: note: Calling 'promise::set_value'
p.set_value(3);
^
/usr/lib/gcc/x86_64-linux-gnu/7.0.1/../../../../include/c++/7.0.1/future:1094:9: note: Calling '_State_baseV2::_M_set_result'
{ _M_future->_M_set_result(_State::__setter(this, std::move(__r))); }
^
/usr/lib/gcc/x86_64-linux-gnu/7.0.1/../../../../include/c++/7.0.1/future:401:2: note: Calling 'call_once'
call_once(_M_once, &_State_baseV2::_M_do_set, this,
^
/usr/lib/gcc/x86_64-linux-gnu/7.0.1/../../../../include/c++/7.0.1/mutex:691:11: note: Assuming '__e' is 0
if (__e)
^
/usr/lib/gcc/x86_64-linux-gnu/7.0.1/../../../../include/c++/7.0.1/mutex:691:7: note: Taking false branch
if (__e)
^
/usr/lib/gcc/x86_64-linux-gnu/7.0.1/../../../../include/c++/7.0.1/mutex:693:5: note: Address of stack memory associated with local variable '__callable' is still referred to by the global variable '__once_callable' upon returning to the caller. This will be a dangling reference
}
Quiero ocultar las advertencias en los encabezados del sistema. Intenté lo siguiente:
$ clang-tidy -extra-arg=-std=c++14 main.cpp -header-filter=$(realpath .) -system-headers=0
pero la advertencia todavía se muestra.
jason creighton
También me encontré con este problema y pasé un tiempo tratando de resolverlo, pero no pude ver una manera de desactivar este tipo de advertencia en clang-tidy.
de la lectura esta discusión sobre el rastreador de problemas de LLVM con respecto a un problema similarme da la impresión de que el problema es que desde la perspectiva de clang-tidy, la advertencia en realidad se encuentra en main.cpp
porque la llamada a set_value
es de ahi
Mi solución ha sido deshabilitar las comprobaciones de análisis estático en clang-tidy y usar el utilidad de escaneo y construcción para ejecutar el análisis estático de clang, que parece evitar estos problemas. Por ejemplo, usando su main.cpp
:
$ scan-build-3.9 clang++ -std=c++14 main.cpp
scan-build: Using '/usr/lib/llvm-3.9/bin/clang' for static analysis
In file included from main.cpp:1:
In file included from /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/future:39:
/usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/mutex:621:11: warning: Address of stack memory associated with local variable '__callable' is still referred to by the global variable '__once_callable' upon returning to the caller. This will be a dangling reference
if (__e)
^~~
1 warning generated.
scan-build: Removing directory '/tmp/scan-build-2017-12-02-112018-13035-1' because it contains no reports.
scan-build: No bugs found.
El analizador encuentra el mismo error en un encabezado del sistema, pero es lo suficientemente inteligente como para no incluirlo en el informe final. (“No se encontraron errores”)
Aún necesitará ejecutar clang-tidy por separado si está interesado en las advertencias de tipo de guía de estilo, como modernize-*
o readability-*
.
-
Como lo hizo
disabled the static analysis checks in clang-tidy
?–Livne Rosenblum
27 de diciembre de 2020 a las 10:39
-
scan-build
seguirá informando el error si intenta excluir un encabezado que no sea del sistema pasándolo como-isystem
.– Martín
19 de febrero de 2021 a las 17:28
pete baughman
Inicialmente llegué a la conclusión de que esto no era posible, pero tengo un truco que se acerca bastante.
Cuando compilo, uso CMAKE_EXPORT_COMPILE_COMMANDS=ON, que genera un archivo compile_commands.json que muestra qué comandos se pasaron al compilador para cada archivo cpp compilado. cuando corro clang-tidy
Le doy la opción -p para apuntar al directorio que contiene este archivo.
Una entrada típica en este archivo se parece a esto:
{
"directory": "/project/build/package1",
"command": "/usr/bin/clang++-9 -I/opt/thirdparty/include -isystem /usr/include . . . /project/src/package1/src/foo.cpp",
"file": "/project/src/package1/src/foo.cpp"
},
Si vuelvo a escribir este archivo para que -I/opt/thirdparty/include
se convierte -isystem /opt/thirdparty/include
los encabezados previamente problemáticos en /opt/third-party/include se ignoran porque clang-tidy los verá como encabezados del sistema.
yo suelo sed
para reescribir el archivo
# Trick clang-tidy into thinking anything in /opt/thirdparty/include is a system header
sed -i 's|-I/opt/thirdparty/include|-isystem /opt/thirdparty/include|g' build/compile_commands.json
# Run clang-tidy using the run-clang-tidy python wrapper
run-clang-tidy.py -p build -header-filter .* $(find src -iname "*.cpp")
-
Si está usando CMake, usando el
SYSTEM
palabra clave en sutarget_include_directories
llamar a sus directorios de inclusión de terceros personalizados debe hacer lo que quiera sin tener que editar los comandos de compilación. cmake.org/cmake/help/v3.16/command/… y cmake.org/cmake/help/v3.16/manual/…– Kymiko Loco
21 de febrero de 2020 a las 19:58
-
Desafortunadamente, estaba lidiando con una compilación que contenía muchos proyectos de CMake, algunos de terceros que no se podían cambiar fácilmente.
–Pete Baughman
21 de febrero de 2020 a las 21:02
-
Acabo de probar esto en un proyecto de prueba usando clang-tidy de LLVM 6.0.0; no funciona. Todavía veo que se generan las advertencias, aunque intenté usar
-isystem
y--system-header-prefix
.– Martín
18 de febrero de 2021 a las 0:19
-
Lo siento, es un fastidio, funcionó para mí, pero actualmente no estoy haciendo ningún trabajo para la empresa que necesitaba esto, así que no puedo volver atrás y jugar con él para tratar de averiguar qué podría estar mal cuando lo pruebes. Ni siquiera recuerdo la versión clang-tidy que estaban usando.
–Pete Baughman
3 de mayo de 2021 a las 3:37
cristian
Mi solución a este problema es ejecutar clang-tidy
desde un script y luego filtre todos los problemas según la ubicación del archivo porque los problemas del código de usuario se encuentran en, por ejemplo, C:\Repos\myLib
mientras que los problemas de los encabezados del sistema se encuentran en C:\Program Files (x86)
o similar.
El guion es un powershell
guión, tal vez puedas hacer algo similar con bash
:
# clang-filter-user-code.ps1
Param(
[parameter(Mandatory=$true)]
[string]$CLANG_TIDY,
[parameter(Mandatory=$true)]
[string[]]$SOURCE_FILES,
[parameter(Mandatory=$true)]
[string]$SOURCE_DIR,
[parameter(Mandatory=$true)]
[string]$TARGET_DIR
)
$TMP = $TARGET_DIR + "/tmp-clang-output.txt"
$PATTERN = "(?s)(" + $SOURCE_DIR.Replace("/", "\\") + "[^\^]*\^)"
# Reading the content as Raw text, where everything is stored within one line, is only possible with specifying a path to a file.
# Therefore we store the clang-tidy output in a temporary file, that is deleted afterwards.
&($CLANG_TIDY) $SOURCE_FILES > $TMP
Get-Content -Raw -Path $TMP | Select-String -Pattern $PATTERN -AllMatches | Select-Object -ExpandProperty Matches | % {$_.Groups[1].Value }
Remove-Item $TMP
Debe pasar la ruta a clang-tidy, sus archivos de origen, la ruta de su directorio de origen y la ruta de su directorio de destino al script.
Usando CMAKE
puede integrar esto en su compilación:
# clang-dev-tools.cmake
function(PREPARE_SOURCE_FILE_LIST SOURCE_FILES OUTPUT)
# Put each entry between single quotes
foreach(SOURCE_FILE ${SOURCE_FILES})
list(APPEND SOURCE_FILES_LIST '${SOURCE_FILE}')
endforeach()
# Join all entries using comma as delimiter - based on https://stackoverflow.com/questions/7172670/best-shortest-way-to-join-a-list-in-cmake
string(REGEX REPLACE "([^\\]|^);" "\\1," TMP_STR "${SOURCE_FILES_LIST}")
string(REGEX REPLACE "[\\](.)" "\\1" TMP_STR "${TMP_STR}") #fixes escaping
set(${OUTPUT} "${TMP_STR}" PARENT_SCOPE)
endfunction()
# Detect all source files
file(GLOB_RECURSE
SOURCE_FILES
${CMAKE_SOURCE_DIR}/Src/Libs/*/Src/*.cpp
${CMAKE_SOURCE_DIR}/Src/Libs/*/Src/*.h)
find_program(CLANG_TIDY NAMES clang-tidy clang-tidy-6.0)
if (CLANG_TIDY)
PREPARE_SOURCE_FILE_LIST("${SOURCE_FILES}" SOURCE_FILES_LIST)
set(SCRIPT_ARGUMENTS "-CLANG_TIDY" '${CLANG_TIDY}' "-SOURCE_FILES" ("${SOURCE_FILES_LIST}") "-SOURCE_DIR" '${CMAKE_SOURCE_DIR}' "-TARGET_DIR" '${CMAKE_BINARY_DIR}')
# Because clang-tidy also detects warnings/errors in non-user code, we need to filter its output via this script.
add_custom_command(
OUTPUT clang-output
COMMAND PowerShell (${CMAKE_CURRENT_SOURCE_DIR}/cmake/clang-filter-user-code.ps1 ${SCRIPT_ARGUMENTS})
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
add_custom_target(
FilterClang ALL
DEPENDS clang-output
)
endif ()
no estoy tan familiarizado con ambos CMAKE
y powershell
así que tengan paciencia conmigo si no encuentro la solución más elegante.
También hay un abra relaciones públicas a una solución aún mejor en LLVMpero dado que ya está abierto desde hace casi 4 años, no sabemos si llegará ni cuándo.
Aparte: Esa advertencia fue suprimida en GCC 7.3 (su PR 82481 error), pero las versiones recientes de clang-tidy no parecen dar esa advertencia de todos modos, incluso con
-system-headers
.–Jonathan Wakely
13 de enero de 2021 a las 10:53
Esto no funciona de forma genérica, pero puede usar la definición
__clang_analyzer__
para evitar el análisis. Si se trata de un código generado por una máquina como qt moc, a menudo algunas declaraciones simples pueden evitar procesar el archivo generado por la máquina con clang-tidy. También puede funcionar para algunos archivos de encabezado. No funcionará para este ejemplo con plantillas… pero para otras situaciones podría ser útil.– ruido sin arte
16 de noviembre de 2021 a las 20:47