From 84a6396ae6286eaaba899137f95bf98704be787f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20Umann?= Date: Thu, 21 Sep 2023 12:32:49 +0200 Subject: [PATCH] [gcc] Add support for the GCC Static Analyzer --- .github/workflows/install-deps.sh | 5 +- .github/workflows/pypi.yml | 4 +- analyzer/.coverage | Bin 0 -> 110592 bytes .../analyzers/analyzer_types.py | 4 +- .../analyzers/gcc/__init__.py | 7 + .../analyzers/gcc/analyzer.py | 274 +++++++++++++++++ .../analyzers/gcc/config_handler.py | 18 ++ .../analyzers/gcc/result_handler.py | 88 ++++++ .../codechecker_analyzer/cmd/analyzers.py | 2 + analyzer/codechecker_analyzer/cmd/checkers.py | 4 + analyzer/pytest.ini | 2 +- .../tests/functional/analyze/test_analyze.py | 2 +- .../test_analyze_and_parse.py | 4 +- .../analyze_and_parse/test_files/Makefile | 2 + .../test_files/gcc_simple.cpp | 6 + .../test_files/gcc_simple.output | 57 ++++ config/labels/analyzers/gcc.json | 285 ++++++++++++++++++ config/package_layout.json | 3 +- docs/README.md | 7 +- .../checker_and_analyzer_configuration.md | 4 + docs/analyzer/user_guide.md | 12 +- 21 files changed, 774 insertions(+), 16 deletions(-) create mode 100644 analyzer/.coverage create mode 100644 analyzer/codechecker_analyzer/analyzers/gcc/__init__.py create mode 100644 analyzer/codechecker_analyzer/analyzers/gcc/analyzer.py create mode 100644 analyzer/codechecker_analyzer/analyzers/gcc/config_handler.py create mode 100644 analyzer/codechecker_analyzer/analyzers/gcc/result_handler.py create mode 100644 analyzer/tests/functional/analyze_and_parse/test_files/gcc_simple.cpp create mode 100644 analyzer/tests/functional/analyze_and_parse/test_files/gcc_simple.output create mode 100644 config/labels/analyzers/gcc.json diff --git a/.github/workflows/install-deps.sh b/.github/workflows/install-deps.sh index c9d37e56c9..37bf443384 100755 --- a/.github/workflows/install-deps.sh +++ b/.github/workflows/install-deps.sh @@ -2,11 +2,13 @@ wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-14 main' -y +# Required for g++-13, as the latest LTS at the time of this change hasn't made it available. +sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test sudo apt-get update -q sudo apt-get install \ - g++-9 \ + g++-13 \ gcc-multilib \ libc6-dev-i386 \ libpq-dev \ @@ -20,3 +22,4 @@ sudo apt-get install \ sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-14 9999 sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-14 9999 sudo update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-14 9999 +sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 9999 diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 70b5129feb..26836213a0 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -73,12 +73,12 @@ jobs: - name: "Install run-time dependencies (Linux)" if: ${{ matrix.os == 'ubuntu-20.04' }} run: - sudo apt-get update && sudo apt-get install g++ clang clang-tidy cppcheck + sudo apt-get update && sudo apt-get install g++-13 clang clang-tidy cppcheck - name: "Install run-time dependencies (OSX)" if: ${{ matrix.os == 'macos-10.15' }} run: - brew install llvm cppcheck + brew install llvm cppcheck g++-13 - name: "Install run-time dependencies (Windows)" if: ${{ matrix.os == 'windows-2019' }} diff --git a/analyzer/.coverage b/analyzer/.coverage new file mode 100644 index 0000000000000000000000000000000000000000..80261d58ae0c6c65656b6059d4eb7759f5d718b6 GIT binary patch literal 110592 zcmeHw31Aat+W#|?$(>9>TWC3(Lgl6@cR8DuLoT^bInp#u+t4%#Nm^R2W&jmM7sLZu z5zuu#QCMA9yl6y4Ki3uAZx>WliuZ~_LFBN|{GWFwX;Y5ffSLXF`~EY~JnziB^ZwrF z_ulu6X_K4*hpE`(E4Kwq{lN$n1s0PD05tg59{-}35)DlB1|=0^zM4@3S#u`n4YNU~ zxE~CQ^m7e;bidb|wV&uJ)%R#0S1wk&@P%|q3`h(}3`h(}4Dbwa({#$zwr#1^D+9Jd zmm}b_*&RONS3hd{n7o-|Of&QHCyg-)&rIDlCcOIeG3A+jo~0(Q!)GdXx*R5_yU1y` z1)S~@Q=rrlwO!$N6p<1SpJACtEN1cF6O+|hgkJ?5CFq3L=PbARs!e5%>fXGC2wK2V z6%ZbvBMxVYo7gaQk9^+4AIMwyzNOx@<-b+Y;F_+Q&X z8+_2L%J^b*$nNnK5#Ja3Y;Jq0!{6IvYtqo}L4Q^S1Z{nua&y3Aayi|+nr^={;Pkjn zjw*+}BH$>xqJq5%Y0(SGi`53*Dj*6K2wz69V%TZ^_zGV}tVcdBM$frDQCgcnB+&RV z?`L;Kc_C81xT4%k0tdekfCHYZeR;KS1D=Soafi(n!m?T47Qq>%oP?^2h!PkBZqO=Hha^*gvC>iHU*f`wm(^Ag@bLFm418-}{L!s#rBbG* zr&G5r;Ufy6$6DwN_?rys7Llgu@l~P@d4KhILsCi0NJ3JP%VqKu^GSw$Z4v?pV{>ep zF-OU;`A9-Dc_J3kr~jj|jd&LQU@CNZ3R}iCKF0VRm_RTuh*~SIaN9{z@e>{Fo=S($ zR^rHtycM#A|LKT?QKzq3kvb;*YEh>t3RwF#88uv6g)+5$dup|sk4BNuiU?(kC=?CJ zD`cb5SLF_yzrq*INd8$S8U3O;myD*7$Qx9rk5ZAE*ZykiMC@7nMhq%W$tY7>x28BD zMUZ@n{K;D=L7p@xflCU4_`UD71xihq`<*;Sk9U(RQirv^n#YM3tbNI^V$F1#_wsE@ zp8ayn^vR#Bg_p^bW-m{4RQIX0xiB~J+MGU2vX}=8C4h-oEV7|xTcM{Sz{g*5%STUA z_B8ufaG?1<%01fZ!CS}VjX?gP(Hm2@Qk$P-KK^c|LXXGgu(^dI0WFUABb3u`;-N1u zjB=aZ@K+NzN-DeYUWt||BzK>QX)T(p&`@4(a~DO5DN_0hu40x?(j>tV@(%pa)D6?3 zA5-QfZbluAyd@b`)cq_kQbAlTw-pJgoPg~ua z-6C#W^0GOaOu>8>D><>zgK!r^2e}mxNS-EyV4=W5)K;X5qv@eXUs8q!!2i-EF(5G@ zF(5G@F(5G@F(5G@F(5G@F(5G@F(5JUe~$qfMN>-B{$~t>z~C_y7)GN(x+Df91|$X~ z1|$X~1|$X~1|$X~1|$X~1|$X~1|kgT7+FU{blyaEJDIF?e=={NUv|I#eX1kQ}M3`a9TnxaGN02t+GDRMcen$7 zoLp7pz)1r3GKbGx>2OzCiyW0^m$T69tqzoW-2JoqW}9)2pQDf0W-r4TOMddg;SZRt z)^eNEZMEWDh;F@2-TK(cukbF*>2{JkV$W~JnIVC03&|vZ#_(4#{MB&U@SWj^6vPq( z5(5$g5(5$g5(5$g5(5$g5(5$g5(5$g5(EDm7|_W&QqisnMkQ-ak)8>eR@R=1bVJZu zSx0rW2SSc2F@|GAv9^W=!x_U#;pTsXrjj2e1|$X~1|$X~1|$X~1|$X~1|$X~1|$X~ z1|$Zq#6TM^9UrGu<4>z8_+#uwvvWYMzn$#mm&z_SY}VhdKgGU*chV&>ATb~@ATb~@ zATb~@ATb~@ATb~@ATb~s1Fee~ZX%Vq8R6E*l<-oA%Zpnn7CTFDQuvMN{dNTmH%bH` zUxnN4@FBb%h!nGG{s2-JvxLAZytFpI ztOz(=$lgk6|38s}PjXgbKw>~*Kw>~*Kw>~*Kw>~*Kw>~*Kw>~*;6H-_86^WfS^rNN zE&%?QE{Oq&0f_;L0f_;L0f_;L0f_;L0f_;L0f_;Lf&YUH$YgpoS^rNPekR(r$Myfb z;s2njl1dT-5(5$g5(5$g5(5$g5(5$g5(5$g5(5$g|6ekY%=JLMlk&*;|8C6(fNlTN zh93>z7>*b|GJI%w*YJknRl^I0XAO@Vb{Mu8HW}6%)*4nCD)F4aQiIKKvtfo|l3|Qt zq+zfj+t9<%+0fpQV$d5DY?wXAo@BpgzhpmU|IWV8zRiZ%m)Pgnr`bo@huHhs4eUCW zW0$dh*2Oy5MeH1QDm$LdXNR!^*gkAmHl0mlTd^8eroW*7S$|yrt-enGvHq|6KkMJr zzo!3_ewY3U{log->hICtslP?PO21U^)jRct`uX~q`kVA)^||^SeP4Y~eHVQPeQQ0d z#}f{9=XIxa$8=xmKGPl49nig_dtLXk?s?r#-S2hVbenY>b+_w+x}`d|&Y@eNo1vSa z%hToP%(||+j=B_`R!3{kYwNY&YCqThUHhK)4eiU?KWLxOZr9$gy-T}RyIkwjI<*Db zIoiqEG1}qU{@R|}3~id$pjButYEEm8X}-{Wj08)U#DK(r#DK(r#DK(r#DK(rC=93= zT1~@l*ew`#!7jn@EIcb1o`Gis!%o;K7@mfw1;bPDlwf!go)ipEz!QSuad=!XJO+;m zhTp^Q1;eB8s9^XV{7x`D0*?rWhv8wtumg4ohV8IjFl>Wug5e=}NHA=Lt%Bh}cu+9> z7Je%jw!jv_@Blm@7&gOZ!Eis^FBtBF`vk+iaIavv2ksFJn_!b*xEt;k3>#siVAuc~ z1jBFOH-h0VxJxkH33m#H^{`$r+yQq8hTGwG!LSb235MI?Ho z*1#IUuo_ki1`asE5QLzDq104O4KG%$;>F69yjZb<7t5FPV%aiYR9Ew&s)`p&m-3>r zk{1;fya)t%;rH{x=i|kaCA{!@dExQ!!tLfoc{wj!E?$(C@nZ2}UO1h+C@tkhNeM5C zi+SO2@S>=Q7j`=@3JZB*v+<&!fEQLPFBUE0#lnTWSg?Q>^XK#8=9_sjZyqn^&gI3N zIlP!Xn-{ZY@nYsoUd))mi|NyOF>M+zrcUL>lqtNJJee0a-NcJYlXx+4A}=OP;Klgy zycjo*7dPI>i?L&QF=h-eMvvyjs8PJg&*w#69xp5wUgYNTV&q6(j2OX-;lp_`Y#1+w z4&}v=A-u@R;l<#=ycjfy7Xt_KV!!}i^zYA$e*JjSw=XZUvw2}Q^CByY7k&EhqIYjz z^yCaGUUccgi_V>Sk&(d*lZhAU>AdLFi5DF^ z@}ffrUbJt|i+1gJ(Y7rw($aX5n#zkdZFteTH7`<9c#)jUi=-r8v}(l*qmdT|120&X z7kWJ}bUI#WwY<=1c%fGFLZ#w`QppR2f){c*FBpawG8r#unqkyxHCg`;Mp3e2$x(>` zi2;cLi2;cLi2;cLi2;cLi2;cLi2;cLiGlwR2FUoo)c*eu2@J^_5(5$g5(5$g5(5$g z5(5$g5(5$g5(5$g5(6SJAdUZvM6Bej#DK(r#DK(r#DK(r#DK(r#DK(r#DK(r#K3BhX6gS+Z`GaF-KuM+-KCwV`BJl7qgQWN52uz<$?zEM zQhljfrs|~Jt6ZoED;}nf(jO~k$Q$I3$rs{MgWdE%*}bwMiB!_XaPzM1+{oC&51S5? zj2irAyVuK~B#DP4l5;Vwr8akwi$A&&o-Ss%o5TT&;*(=5pAruy=FCcXat6b7OMo_! zb2s@DH}Ao~9ef?ZD_$u29R3PdAT|_tS{W`k5qf*dy-t@c;PkkyMYe#g(B^lL;JY97 zfAKmv_@Dm7&Tuy-fR<=X_M4+7YoOZe;G@SA^BHb%qA>hUzqK4ON`%Du=q!fo6W7VL zQGZ?a1X(`GJKf|=T<>g#GyghQ3oD$iB71p})#10>yn?fH#xY#-bvqlAif7}wxxKE< zp)2Npr5=AkI6)VcUOI>2`X<2961&|>PN21y+MI55*L@SibxeS}4tFKGR=SYkMkK&B zK73rB5;Oi;y*8hpk58^dyWWD~vbc{~Zi=i|47Mh}^M;t@uoyGByhM^C0NCs#yF>Cl zn39Ji(*2k??JQ-uX^F}u@T6#R0CH?0V2$R~x6Wm_{s~Yb8b*F|vCBqs4Syl#r3rQT zvdW0BoZ;ptlq9>$<}L|1i>fc73-y6JL`1txHMqTm;iibBTQsbQR_jE>iHXl}8y2nO z6B`{!Sov*cJkQ%NB*?183^zvJQf6ph5oB6)?A;bw`W7>OHJkC)`sq}COP`?UCI+Gue;eAC0I0h>sX z*cW|*AWK98iAhN1HijFMP|l(nM2m!*7cktggd)Uvf8Nbl`%R$ZR*X~uM^ymnpFbVj zatUxc#UV#U-DVojHF!`OD8`LkTN2)$l-K_jZxkPbMahIYMwsAN)vs!y?nLDXN`py0T zwzd2Lr`?Z=yIh!PJ-!w(^(q!3R{iD}<=`>-c+f^#T+evMZ$n&? zXTh!&3|AeOi-Kl8hu7l^^ugf7{5;@jsg>}OgmvU)G|t9!Rm5uc%mjvO9T#}iq08Dq zky;FF#t1v`*EwasN+bEcYi|h#E+L)Ig{+YhkgvE4Z7aBUGBz`QrMF8R_A)G6F=@dj zt`)QTS|dneVyxfmusdxotIrXr@VTv(Hdh7T#qc<``g;624KFLz;h{y?p8BQ{E|a584KGA>0El%quR1`JEmbRq%x>~hT2;wodV#}9r_h0pH5Y_5p>l$Sf)v7L6S zJPc~!&odQE`goMK}N{Tt?{RJr!wp=bm&+UyQi zGMq=Wh!hFT2xd&lSQB?A^Yz5v2yCg%Pns>T8g(oeJ1`?X?^c(s(Bb0aEr;pECN{M( zoUT~HaCXtujAlZ9b5pk*Z2WiCt@u_H-yPBnz9Ig~>-EH;W_^Xa4UZmu7?TsMF~lw(#c=AlfMWZCNnz=6 zn=1lN7iK)xxNAgLaKm4QT`yQ&iybYyCGL@mD>;ZYa+f2(_ZXLqVL1KuYKOHnVVGxO z+(QUg@XlrV<)RxIuGRJWDJJ9=#GN9dQOqpl4_9fj7CE9`y`qH}WcWSyVfT$IF*ZYA z(vb336ncFgyTk9d2At&%PX%Ay+eYU9cY`1pwi$-8AF&=*gZt}`#l7-Z>rC2OtyObQ zbGIf_y;r?Ztx`R#8ln6|=~uFf#}uRGN99Z92IdhaNA_pgBKj14JDpCwN==2Y(Yd%U zdp8ESiRMyIxx?(JD7TgQoaWIUdj+W)V%rxhiV>2q7t~#8Epk+vUCu%?c6gO~-2Joq zW}E%afTNGsW-r4rLciJRb_%_4u^j=9^ue#3-BWzrR~L~&x-kAz-mQ}Z0!(9giHbp z5UiB&Gd>F1BE*=)krvHfNuG+CJqeby#0EQQu|V85g*KD z21F5|6eB1&5K``R+gyB!$%i+KU?QcCnDBP!MS>w!RF-(i@CoqOZ-EZm;F3=!A0`vALfZc{8cKpywfm$4dfX`+Z>M8{)aS)p4B^D^f zL1?Z8;rRigghO*h!7fJx5z0Qkx1VpxVSFuN5JZGpz5o)FzHKrD5~K8M4iXzJ5=3*D z6i^6}$kZpaTVr@4?f>pz13cqz5POha%BJE8dt-Embsn8gyHh(s^AF8BO?&n8>glR_ z)t#!I%D0pY6lWE8E3)K&kuR33n8%pWvQK48WhwL@=*iRx>Q1UVyonA*FWVGxSn>xP z-la}{GIrr)gb<+`;>Q75uNS+BG2#~9BqD~#?IP6$+az(QT1@6JRF#vS!-W$OA~$j6 zQM5+l_V6KLn;?z`UK<8?AwRv?HeMVE(k&X9w{06I4g?7X(r<*}V80O|M96GQ9WJlX zw}K$WV-X~QjoD~mM>=nsYM}*V5J!w$svKvO^NrYo(TPQfYJ!b2(gZ}V3Py>8K>D;P6SAqZ*q{ zeE*AmB%+9r{#=d{o1LJL=5fgg1QDUKQ|xm%mN~3`ESzvE0|MEHi=&Ou%WlQ>EF^^t zLy!cf@@V8L^4KGpV&PCk5TP6|aui~#Dbf}gB90cg=m%$Skv?B*4kCz<2!+5vfa1Xj zAV#)s!=V-&BdT;3@hP!v5aNi?>~HQU5BMtFq*sivHc%YaaI8xRclD*0T+|zJM2Ko` z>>VTVU|}zGUxaoDsWGDSi+YOVeH^IgXMWjwp!*3-DKVqg{5&L7!OJRJp>lxiQ zy7zR?=_cyB=+bmb?HAflw41a6%_o|>)jQQa)F#zM)hDVCRC`rVs0GLT3c(@t!auvR^6+@jMR|?2+F!z_J~;ME z-7`nCFEA7U{wJ3axNrS^RaIy-b%IcPuGk`{)N3YLz6giIFXG>J%UHm93E9Lh`H>~B zm6`IrAu5Qjn1Z3==f~Z>A8q`l`0mdCpkN%lSrAl$Ows+25`rdB0Q_PAcp#1H%05vc zLkEI)gDPnHKnY;MJB!7lG6B#~2PU9}^AuSKQRp!f{xLhy9)EfHU!^xleA5AdDMbzH zAlM0?H(3HuWqyGVSak4C$hI&{ehx4jhu{Z6H}3#`$e>dydPpu36Uc20XZ6Py4Dk(< z?SmDF_fg6Ak;HNvOTnwec@q=F9}5AdVUKKV{z#;VV@5U}3y0;(oA2DR<#s&JHFBvs zckaBpi?UU#8#6nFWZ$i?M>M06R*y4rOh3qXZCbMFhl07qsu2jEG-4S&oTG=MbE}!* zjp5pJ%sIrjQ|h%AH3t-qck!16Jy(#=8<}-M>~6$MH7+!l2x8uWRG{x}BEMI=Xc{c; z3rnu>`m0W(4fbI~rLn^r!{Liz>)!OQU#zXIJ+k2|!}x;aDFr+TKrZYy>|6u13ED-R z$p=di+Tabvq~R|Hwr~*-H(h9CXbxk}prNR50#Jn|9Y0@K%9CPg#Nw2MfBJfSUVKBYmOlujw^U)b4RX8icge zsl7kscc8{i@0~EEZ%&q_7K%+&r^FW?f51pimmtglw z?%3hVi<(a{1PKjL+;Cye{bSzrtlVl{`F@|tMH5&2DG48|UOi@wFr@3sg|wC)o6rFy zCMW}1g|QNJolLX7P6x1Lv!^j*+ELp~D1HwRAgRb=fDg!X@>7R+CSY(Bj9d```_Me~ z;$V}`d;H*C&;_vvWM@toOrl20;8Qgi+f8*h{h~hvIxWHn<)JP?<}{w}aLe`$OSeJJ0a<+q_mH;d%+5Q)E54dFt2TV=2diLYea-6g z0QEW^5g=vil1i1iz9wa0?S%fkulqNK&xWl=IG>dPs9tsmWIJEj4|>d+f>a&kJaJ@~ zCG&REllyjr^Ulla!(UGI+@M~p?#g;m!N{d*)en7`*^hp;4(eZ^PjH%dRNTD2Bog%N zi;)0%35UA{fBQn~ZEAS6lZB0Z7woVJb3O>aee(5ixEwxB?v{nOisOb4K6&QL)6Y<{ z;<9)E3>YR4kON7{?4tim#{pC9T!c}=6gzOt@CHX)m*F1s<@Fp*sxUaky= z<#77*#sj|`dYIkQhz^!?&ff8PG8BZVV>Q|}d3jXmWT1cS2EyD1skf{(}* zqJqIg#9%otXSltA^`t#>|SM&*at}`Rwjo zdx|al-qglN^6T4Jf>1ye)Kg1)5hQmn%;m%3DHmYR#fA}$BMvm2UwLl%k+T;sHm=HT zT#XoKbMdEs&6b`0*1Wn&2}_^5=W8n1s<(f{u8R$S*JjV$Y*_r4_8(yuF=fO7DpYx~ zLAG&N`PiYu!ynBL^Jfy_=OhQ%4uHOUR>mdwL@v7bT-8t3mc03+=IgJuvy46PVdozA zuh?7u;6s(UhD@cZJ3dM3-o~uT=!T}z-TJ}QmtXp`PWJ%S?@tw3%m4nHPxQL9x-^p_ zbO)8um00Q8xGVK_ZvmfmVJR0xqJJ!^+7!lgOC>9BKr6-@d(4$9<Cqa0hB=% zlmQ7EOmrbkZN%ydxPVXac}V81lcBd5uCNPwVa@0+m|DX}E{1Df2ft<3#~C>x84Gn| zE%lHb1l754IQQF&({uhbyUb)v*xKR-5Y~--`8km`g>P} zR~x|65$;v&S$@2sM*jKSl)Fy!n z3#o$itI!kq2;C;T?{30G#dbN>mszg?P$8;Xeri zDO#}>g%=XVzb2^=vttNysTm}|vNA{kcVKfy$${#}_m(_ay8W!YzOQUKg2bE)sI}>!%0sSIk(^nshs0gN*I+!p{4K+13zE$)3ZTN7|@@1Yc+D=8&f*t2Oj7=v5 z=+bx8Zd>xMZ5$YNdzV{T6R`IlmGAfxOtfW};1=2^83wy%-Qn`K*@Hr9m9YOPHIfqi zK`S~T3fn2IOGlLBIxee5{}hmSL3l4)M-16%ydEY~A#Lb@mP{RfX>$*%jjt$mdwh`6 zp8kk+b!~^n$?bmGwYuM$VdKBw)_YiJtGNm-VXVgNg~VAXP(Y5OE%Eq-wj_3*NJ?QI zDZv+b8NmXK$pjg7=w0GG4XA(x-!POh2S`plTnz=UZ%p3ZzW~Er z9rSSBVCC?c-Nt1zTffuLX=&)4erb)4mlkAgcFbejc}=%s^)p@gX{OG)_LmPZEw9P7-v4o813C05NQ0Rk$n8sJgxZKtxrmSjx24hO+iTRr{ z@f+wK%(N-cw;}XF-{6};YLn5JJsaB2q%7-TN~K0!&}u8funB7|DvZiB(7`R3N2{`7bS7;AqXl0^FSHB_{zeuGQbI(J zz7wR$h%F3Nati9#J>`tHt*Nd?Cuf5AGFg#~57}f|nS|1q^nqenD>PKKIulMU=xdah zWK0fb5)ypqD=JH_z7IZHHyR+s6j`}81c~tUbN1LAGb3WZ$!@Lr_$TX%ZWJCv9nt~>hZr6@t)aslI z=zadG!Dtw{(rD8DFNM#*FpB+8nm3pUsfqsm>mp((!>Kb(4 z>HeyFTenO1xNf^{jc&GXvTlG*r9GqlM*F$;L+#tzXS7~ziFTnjPdh~0QESjF)XdV1 z(+twc)UT@VRo||5tF7vMbzgP5+Mt%Heo;NGx?g2i%~y?6jZk$^DV0wsHz?i8B4rz; z9OoGPsQ6NGQ1Oalo8k^dv0{c|w4#SXBmYMJv3$S0RE|lO`Ib4vye_+4)|&o^3Q=3B z94ZT=7z^K`LgZ3%Js4We!jp6+*Bwpc;0f3_|B%{(sm_Gi05;5xLEa|$p~0BUbwg`i zu`}X(-J=+Sn5ZdGVHDt5+sPOCW!JPIdkdoCpI@mC0o0ZddvqQ&G* zk~)7`NJ>in5->%X_x?abh*ZUz-bO6N2pTLITo**khu`fu5xzC0%CrDh0jw-vR7b3l ztN~k0t5dkn=#jNu;gKDUH5k4g71R$=1bwT`=fdY|p#R*5-a;57+Rv^#+!YFhNQLv2 z$YtSwn|~tyVH)3Tz?h2+;bp=G36W^(59hEDMqUxc?JR) zZ^R$sD(`aS0S)h@TS%N-m%ieQWAFU3T6SkcO-HZFW`Yo=0b39eg4F(wE`Z;naX{oV zkmY~^c`gW*DzLGtkl~9Eet?&*{~JTO4CF2V51X)Aa^}x~?OEZfiO6Wi+H{Ks!A_7` z!kI|m7QhbE>F|SnyAwN&hWhYN;kBFhJV0&i{P4~f_B}PdRsHsF;lIZ`mfOEO)X~8n zNDLjUSwaKsk>}SjNV&{{Uot_YKX|Tqf2t7KELiTnk2MUKstDmHJb^0H>H%Cj3CLpD z9)w_c12*`u6T|vFPo_ZNqm3^sb)*DYlFYZ^3uZK)VozGoM)&((jOu3ra$%VS4;OTh zp#j11T4w<`+S#(kq)NdLrsA9*knb=WM^ngX4s10Xn1Pm}m#zSk`OlDE6Mi0ALuG?3 zEtIWL!Qu`fv}PQqB5f6{+GO({Bwvy+4gT()!?amWBL`S=_S0dSA`ang^m-s_F!I&> zabqo!2N>arQBalTBgj^~=Y3CpiS>2#G{mG4%7l01nv~3S!hr4y+hAX>F6TCHHPx=2 z0XjX`5udh$hal^~x>rufQn?Ozp9NdtppQn6*VLNuW0lH6wc^_2o6hhc+}wG{e+_-w z{n^XZRIVKf|4#5*IQ71lhRI+&@z&vehhNxNlG?bu8^QhJ1Y!17?TKNO}w#3N+umw)_d1Ft_mv=y@5B=%m z4<6syK)>Aov(9k#A8o?nv#BS(KJiF{@1+Id^{?#C@o z#s#(Ksz1}_o_OuxS^1gg+k9GyA1RDn8Y*GJT?lM#Gt6gR{^&5J;ZpHY3T%ey2M1mfs%~1^q2~_J9k|wLCkO6>Q(r^DiC?~b$&*s{ z3}om2shr+@cy1b(g0HjTUML(tx!>B>pYE+YBY)AnXXQ&W9hZ!+(%>FQ+WqYj%E%?* ztqC^4^qW68^hRsf>G}-ZU4!7?4W~|>Y1sd>HY3y^*M<(SG1RSjM7BB7N6>)`0F@`?3f#%S98PTsv?$bR?Si9#sA`1fc=(NcYA4%OcK#H_zP^*8s+ z6Z6mqn7u2Go-xQ~F&Otv!6*0qdUsg!2G<_b>fUe*EO7+)ycjfh7^pIyk>9#*0ml#@4T80B^2PmQ-_873x9_`W zZr%D*^+bY`U zzMgAXicd^S;bFZBCm%~%LN{GFlh zk&j+qj3N2W?k}bV8^R05EFpwwmcYrU&VGF~U17gCXZ~ZUMkXor`HP%Bf0{g(3)X-8 zMy3kt+|NF1!W(^iO zz5mkN8@6xHtr@xfz_-tv-#GD>`}w7>Os%pVmdlJD{G_u7+R~x2x3p^2DoX3dCuwfj zx7JE`Qk3HjTTXLk7pXcga={| z-=&wHHt@a(R*Y)fxauM(@V33K41M0N433h(47OX0cY_vV9&p2jBW5fqo3Eh4Npy75 z?MjKAQur8y)3O6-6Y4`qhT#3Qss!I9mB4e0l*MQ=7B|X=InYq$XnbWU+7I#}0#6LB zqM_^U6zoVB>irloMq41eDklg-vCrgZStipFnV`~&@Z)|(2T6KpzJhX~RCa=7@A;li zTZpE#LK?<~I;~LH@P@UmVhd1qD%gADtZ6Cvo6gZjE8cgu!qEws5kS@ALQBs@_+<8? z`{56NIDQaEnObLS_Eg>9MW^4x?r{GMpWl|>vDDN3j@hTb{~$GOA=>S?5Kex1=+p0r zs#QiyCMYOVo?-#MVHeQ7=A)cDAM%#J1szKo`b<95rfmJG^`}-YUp6skbk70(e=066 z-v843Kfki&_x^S_qvb(2!_gP-Jmyv??xb+)HYOwm^<%h5F^@Pnk5EzLL{?XB&56IyCA*yNkC~4Zz=X27gqN(51 zRW&EQ%4hHYUGC{rFqy55r@l^YJq6$No^pIM_Vyj;y?^soD+6it&~a$FavW)6 z$i2(&8FXSPb^fsR!fUS&>=u0d-qamOTn|wYWOJ;Bp}{`AsGL1)efkR0H)oAmO zC})nwA(bK+-U)Sv!Hw8o$6vZ&Xx+M?2}ZziY|M`Ejv|~Ej3Qm(*6)&k+U21__dQtR zC8<||^;6iGTe0$J!`_ug&f@|Ho~78tnnPChaWSa&-av> zzCAjkq3l%68#2oY>=LUx_soW$AKP5})Z1sDKlw}f`WNP47J%KfCnj9%l??TxSPflp z;I#&QUG4$OXr$_7A*Bi4yLh(YuIeCIuwbb>kh*H{X)IQ!A8VYBWMP-dkXj6o5K>V$ zag-X`t*uK&%AhCKM+^@c2DAUgTJ`7jck9RLPU^Pl^0Y^^Yqi5QXEaY}iqsd?_o@4+ z-o$x{{95=+}JG{>HB1oTWBIwfn`=Xng#O$xX$b+uN zHJj|8d;OA)(3|!tpY2BX`(Bf;V|Es4&OS;m*~;EtE*9l6Q|%VG5M;!!_k0sMEjBw` zP?liVTVzSr#prrmbDgg#V4D|K-t0txAqgZWhWJUP=yu0n@3wGI!Hp&8T5>$D#YR0` zLqqm;A~RN_TPPJ4qeF3(Px0-DL)Hk`TpqI1DQ0iQ#A7d~|1UJnsDSTr~O?7ehz43@^ADosMf!LiFQ*Rf~(-i*BYqe;y(XOPuFh zY|A%oE;`=r*E=3V_N+PRr1_ehytIbHm$a9h^>gEFbT+Q+KT2TihTJj!bId}A5|}2V zs}}IAg%Yx26N?$L*26JV9GGGoZY11%np)`$gh^l_5Y;A7>T}qNnlfip$Tc02;%Xhm zSKLIAD%?Js({C$uIbzX@rXku*@x-EQLyN4qi!30tO+}QrS{2uZ64~~M6g3)V8>C}X zUAtYI!(22xXc)l$g)P>f*WaV>t$Ro3z)_4_;U~&U51`(oA7Vzx{##Z;hgD|fo5}+0 z1K6VICqE!B)=t$N*R0p{RKKOR;{5*y<8JszEaIlU^QpwM*}T#$CV`paKG@{iNNomd z-v2E_bj4zp&QcaPqr`}CQQBHzPGY^*yyP0}ixiPB+l+=0 z3Fxwg;3MKblI+^TK4t}H-(ozrON2nbq~b7Bq_p3>+I(0M!%Y-HkrsRXrP|{?6ztjp zBz8&r(74aDx;BhR<`TQRZC7#gv8EapshQk>V!N(}t_7!WBJyrh*jOQiff zrVyvaf@mHMlZge*|*@5Sei%>4L+|$!2Qp@CudwLqg zVy@+mw{1j(iAgc6STHTO4%LfPKWVWaqnwQYcZJ8maG#+!uK1sWYy69J^}1@@{qF&7 z7tLQaP7S5rqVA=7O*LNmu5y&(9mPbPfxi}4@gHSwVS38mmDR|4(Vx(_(%q;RsX|JP zjwSpm;BfL-eEpd5)p5Lj(#DM40C+aeBfi!_#7jE{uXx77bexI|T#tBqH?Gt*NH8L& z!o&=jm*ae9;H>dDdOc^{5Ph9le)2f9bh# zlexC&W=1>|U6uD1L#fknlJ&3kUjB<5kc z*XhDzI6ZD_ku6}0oai+d=Z6C~@K<@2bckHR>3KM}{8~pqE)D*x9TYhYC#PR)s9l+s z=F=i4;SBdUN28ipz0AMO&P~VJ@xL~QxNL~agVX7Ov&R!$*ONm;^@=&QYZ*?~2d-Lt z#F!JSnojMi!o>i4E44PdoaeC!y-FZad@T;>4W%73dbVroT8aBT%} zCE~-!V3y%3jySidi}LlahBtYN`6JncEzo1i+%jAxA{v^|*%E{1;8chf*FfO4>lXcj z3E!m1dTzQj3sBI>(;6;>@nC^{fL8JEz+S?mZde91wH0f_;L0f~YC-3;KYki59gs*SI! z)`cgR#CFueZX8Y;lR$uIU$EEj_4u7tSSZ5pM1ycS-4#5OtE7$*Lt_*kKsX ze#BO=t@Y1g>;G%rT5SD?w9_@;Yi`5V{|oAIs>5hax+Df91|$X~1|$X~1|$Zqoq+_m z_nMXrl=wUqUbD5iw%;kiGh8o4D)#uwZGnJr)>yj8U`^npUEVRlEwU!ZBOKz9eEcDq z9YhYR<_dND1lM$&0UqaOz*I371?aM>dC86pKo%o)G=B0aYT>w$OqNnHe6ibEX zBfQ5axa+b>g_tAZCyR*@ITHRRv4SFUC!tz!*Qo3@b0@dL#I}cnF9(^sm+fG^u*oEZ4;xId5DXu*+6%6mdNfEUwML zu359_2V_129&RNTOiVc0@Z_vGHzA99?q7vd)Lv7c31`4_w_x=(CNPi3gpQrqOPbuW+A0s z1+mBxU5s!Q3r${%VZRCw9E)>VTS9yh13iz+MCe3qOX+v|amtn3R^sp>y9Ic%nJDYI zo9FNqaGk}1h|b}&;u&LcZhstKxf7j<*ffXF%9%t%5a#fa@&6P&TNUU34`u((`q>oy zPJO=aBb`r|qjka3u;XF;GZJZ(~Hm?&^87|TgssMrjIU)_&35zB8Hi1Q? z04IBCyPSonL|d_xu;Jiop_9a^2_iw@i4E8&;3pWgTf}g=B1|xFd;Fx~J5i(&N4KYl z_kM4YQXMvD${f`g*nIz5u1G`vJ;`eHKm2A4b{#3Yd* zN=%O9qwC7F5wpq1^90be=CC! J1St#X{vTY}>U;nI literal 0 HcmV?d00001 diff --git a/analyzer/codechecker_analyzer/analyzers/analyzer_types.py b/analyzer/codechecker_analyzer/analyzers/analyzer_types.py index b1400b2258..943a11ee27 100644 --- a/analyzer/codechecker_analyzer/analyzers/analyzer_types.py +++ b/analyzer/codechecker_analyzer/analyzers/analyzer_types.py @@ -24,12 +24,14 @@ from .clangtidy.analyzer import ClangTidy from .clangsa.analyzer import ClangSA from .cppcheck.analyzer import Cppcheck +from .gcc.analyzer import Gcc LOG = get_logger('analyzer') supported_analyzers = {ClangSA.ANALYZER_NAME: ClangSA, ClangTidy.ANALYZER_NAME: ClangTidy, - Cppcheck.ANALYZER_NAME: Cppcheck} + Cppcheck.ANALYZER_NAME: Cppcheck, + Gcc.ANALYZER_NAME: Gcc} def is_ctu_capable(): diff --git a/analyzer/codechecker_analyzer/analyzers/gcc/__init__.py b/analyzer/codechecker_analyzer/analyzers/gcc/__init__.py new file mode 100644 index 0000000000..4259749345 --- /dev/null +++ b/analyzer/codechecker_analyzer/analyzers/gcc/__init__.py @@ -0,0 +1,7 @@ +# ------------------------------------------------------------------------- +# +# Part of the CodeChecker project, under the Apache License v2.0 with +# LLVM Exceptions. See LICENSE for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# ------------------------------------------------------------------------- diff --git a/analyzer/codechecker_analyzer/analyzers/gcc/analyzer.py b/analyzer/codechecker_analyzer/analyzers/gcc/analyzer.py new file mode 100644 index 0000000000..27d181c4e9 --- /dev/null +++ b/analyzer/codechecker_analyzer/analyzers/gcc/analyzer.py @@ -0,0 +1,274 @@ +# ------------------------------------------------------------------------- +# +# Part of the CodeChecker project, under the Apache License v2.0 with +# LLVM Exceptions. See LICENSE for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# ------------------------------------------------------------------------- +""" +""" +from collections import defaultdict +# TODO distutils will be removed in python3.12 +from distutils.version import StrictVersion +import os +import pickle +import shlex +import subprocess + +from codechecker_common.logger import get_logger + +from codechecker_analyzer import analyzer_context + +from .. import analyzer_base +from ..flag import has_flag + +from .config_handler import GccConfigHandler +from .result_handler import GccResultHandler + +LOG = get_logger('analyzer.gcc') + + +class Gcc(analyzer_base.SourceAnalyzer): + """ + Constructs the Gcc analyzer commands. + """ + + ANALYZER_NAME = 'gcc' + + @classmethod + def analyzer_binary(cls): + return analyzer_context.get_context() \ + .analyzer_binaries[cls.ANALYZER_NAME] + + @classmethod + def get_version(cls, env=None): + """ Get analyzer version information. """ + return cls.__get_analyzer_version(cls.analyzer_binary(), env) + + def add_checker_config(self, checker_cfg): + LOG.error("Checker configuration for Gcc is not implemented yet") + + def get_analyzer_mentioned_files(self, output): + """ + Return a collection of files that were mentioned by the analyzer in + its standard outputs, which should be analyzer_stdout or + analyzer_stderr from a result handler. + """ + pass + + def construct_analyzer_cmd(self, result_handler): + """ + Construct analyzer command for gcc. + """ + # TODO: This is not a try-catch block, like the other analyzers. Why + # should it? Should the others be? When can list creating list to have + # unforeseen exceptions where a general catch is justified? + config = self.config_handler + + # We don't want GCC do start linking, but -fsyntax-only stops the + # compilation process too early for proper diagnostics generation. + analyzer_cmd = [Gcc.analyzer_binary(), '-fanalyzer', '-c', + '-o/dev/null'] + + # Add extra arguments. + analyzer_cmd.extend(config.analyzer_extra_arguments) + + analyzer_cmd.extend(self.buildaction.analyzer_options) + + analyzer_cmd.append('-fdiagnostics-format=sarif-file') + + compile_lang = self.buildaction.lang + if not has_flag('-x', analyzer_cmd): + analyzer_cmd.extend(['-x', compile_lang]) + + analyzer_cmd.append(self.source_file) + + LOG.debug_analyzer("Running analysis command " + f"'{shlex.join(analyzer_cmd)}'") + + return analyzer_cmd + + @classmethod + def get_analyzer_checkers(cls): + """ + Return the list of the supported checkers. + """ + command = [cls.analyzer_binary(), "--help=warning"] + checker_list = [] + + try: + output = subprocess.check_output(command) + + # Still contains the help message we need to remove. + for entry in output.decode().split('\n'): + warning_name, _, description = entry.strip().partition(' ') + if warning_name.startswith('-Wanalyzer'): + checker_list.append((warning_name, description)) + return checker_list + except (subprocess.CalledProcessError) as e: + LOG.error(e.stderr) + except (OSError) as e: + LOG.error(e.errno) + return [] + + @classmethod + def get_analyzer_config(cls): + """ + Config options for gcc. + """ + # TODO + return [] + + @classmethod + def get_checker_config(cls): + """ + TODO add config options for gcc checkers. + """ + # TODO + return [] + + def analyze(self, analyzer_cmd, res_handler, proc_callback=None): + env = None + + original_env_file = os.environ.get( + 'CODECHECKER_ORIGINAL_BUILD_ENV') + if original_env_file: + with open(original_env_file, 'rb') as env_file: + env = pickle.load(env_file, encoding='utf-8') + + return super().analyze(analyzer_cmd, res_handler, proc_callback, env) + + def post_analyze(self, result_handler: GccResultHandler): + """ + Post process the reuslts after the analysis. + Will copy the sarif files created by gcc into the root of the reports + folder. + Renames the source plist files to *.plist.bak because + The report parsing of the Parse command is done recursively. + + """ + pass + + @classmethod + def resolve_missing_binary(cls, configured_binary, env): + """ + In case of the configured binary for the analyzer is not found in the + PATH, this method is used to find a callable binary. + """ + + LOG.error("%s not found in path for GCC!", configured_binary) + + # if os.path.isabs(configured_binary): + # # Do not autoresolve if the path is an absolute path as there + # # is nothing we could auto-resolve that way. + # return False + + # cppcheck = get_binary_in_path(['g++-13'], + # r'^cppcheck(-\d+(\.\d+){0,2})?$', + # env) + + # if cppcheck: + # LOG.debug("Using '%s' for Cppcheck!", cppcheck) + # return cppcheck + + @classmethod + def __get_analyzer_version(cls, analyzer_binary, env): + """ + Return the analyzer version. + """ + # --version outputs a lot of garbage as well (like copyright info), + # this only contains the version info. + version = [analyzer_binary, '-dumpfullversion'] + try: + output = subprocess.check_output(version, + env=env, + encoding="utf-8", + errors="ignore") + return output + except (subprocess.CalledProcessError, OSError) as oerr: + LOG.warning("Failed to get analyzer version: %s", + ' '.join(version)) + LOG.warning(oerr) + + return None + + @classmethod + def version_compatible(cls, configured_binary, environ): + """ + Check the version compatibility of the given analyzer binary. + """ + analyzer_version = \ + cls.__get_analyzer_version(configured_binary, environ) + + # The analyzer version should be above 13.0.0 because the + # '-fdiagnostics-format=sarif-file' argument was introduced in this + # release. + if analyzer_version >= StrictVersion("13.0.0"): + return True + + # FIXME: Maybe this isn't to place to emit an error, especially when + # we cycle over multiple binarier to find the correct one. + LOG.error("GCC binary found is too old at " + f"v{analyzer_version.strip()}; minimum version is 13.0.0.") + return False + + def construct_result_handler(self, buildaction, report_output, + skiplist_handler): + """ + See base class for docs. + """ + res_handler = GccResultHandler(buildaction, report_output, + self.config_handler.report_hash) + + res_handler.skiplist_handler = skiplist_handler + + return res_handler + + @classmethod + def construct_config_handler(cls, args): + context = analyzer_context.get_context() + handler = GccConfigHandler() + + analyzer_config = defaultdict(list) + + if 'analyzer_config' in args and \ + isinstance(args.analyzer_config, list): + for cfg in args.analyzer_config: + if cfg.analyzer == cls.ANALYZER_NAME: + analyzer_config[cfg.option].append(cfg.value) + + handler.analyzer_config = analyzer_config + + # check_env = context.analyzer_env + + # # Overwrite PATH to contain only the parent of the cppcheck binary. + # if os.path.isabs(Gcc.analyzer_binary()): + # check_env['PATH'] = os.path.dirname(Gcc.analyzer_binary()) + + checkers = cls.get_analyzer_checkers() + + # Cppcheck can and will report with checks that have a different + # name than marked in the --errorlist xml. To be able to suppress + # these reports, the checkerlist needs to be extended by those found + # in the label file. + checker_labels = context.checker_labels + checkers_from_label = checker_labels.checkers("gcc") + parsed_set = set([data[0] for data in checkers]) + for checker in set(checkers_from_label): + if checker not in parsed_set: + checkers.append((checker, "")) + + try: + cmdline_checkers = args.ordered_checkers + except AttributeError: + LOG.debug_analyzer('No checkers were defined in ' + 'the command line for %s', + cls.ANALYZER_NAME) + cmdline_checkers = [] + + handler.initialize_checkers( + checkers, + cmdline_checkers, + 'enable_all' in args and args.enable_all) + + return handler diff --git a/analyzer/codechecker_analyzer/analyzers/gcc/config_handler.py b/analyzer/codechecker_analyzer/analyzers/gcc/config_handler.py new file mode 100644 index 0000000000..0e88e50ee6 --- /dev/null +++ b/analyzer/codechecker_analyzer/analyzers/gcc/config_handler.py @@ -0,0 +1,18 @@ +# ------------------------------------------------------------------------- +# +# Part of the CodeChecker project, under the Apache License v2.0 with +# LLVM Exceptions. See LICENSE for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# ------------------------------------------------------------------------- +""" +Config handler for Gcc analyzer. +""" +from .. import config_handler + + +class GccConfigHandler(config_handler.AnalyzerConfigHandler): + """ + Configuration handler for Gcc analyzer. + """ + pass diff --git a/analyzer/codechecker_analyzer/analyzers/gcc/result_handler.py b/analyzer/codechecker_analyzer/analyzers/gcc/result_handler.py new file mode 100644 index 0000000000..6a02648bf6 --- /dev/null +++ b/analyzer/codechecker_analyzer/analyzers/gcc/result_handler.py @@ -0,0 +1,88 @@ +# ------------------------------------------------------------------------- +# +# Part of the CodeChecker project, under the Apache License v2.0 with +# LLVM Exceptions. See LICENSE for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# ------------------------------------------------------------------------- +""" +Result handler for Gcc. +""" +from typing import Optional +from pathlib import Path +import shutil +import os + +from codechecker_report_converter.report.parser.base import AnalyzerInfo +from codechecker_report_converter.analyzers.gcc.analyzer_result import \ + AnalyzerResult +from codechecker_report_converter.report import report_file +from codechecker_report_converter.report.hash import get_report_hash, HashType + +from codechecker_common.logger import get_logger +from codechecker_common.skiplist_handler import SkipListHandlers + +from ..result_handler_base import ResultHandler + +LOG = get_logger('analyzer.gcc') + + +class GccResultHandler(ResultHandler): + """ + Create analyzer result file for Gcc output. + """ + + def __init__(self, *args, **kwargs): + self.analyzer_info = AnalyzerInfo(name=AnalyzerResult.TOOL_NAME) + self.gcc_analyzer_result = AnalyzerResult() + + super(GccResultHandler, self).__init__(*args, **kwargs) + + def postprocess_result(self, skip_handlers: Optional[SkipListHandlers]): + """ + Generate analyzer result output file which can be parsed and stored + into the database. + """ + LOG.debug_analyzer(self.analyzer_stdout) + gcc_output_file = self.analyzed_source_file + ".sarif" + + # Gcc doesn't create any files when there are no diagnostics. + # Unfortunately, we can't tell whethet the file missing was because of + # that or some other error, we need to bail out here. + if not os.path.exists(gcc_output_file): + return + + reports = report_file.get_reports( + gcc_output_file, self.checker_labels, + source_dir_path=self.source_dir_path) + + reports = [r for r in reports if not r.skip(skip_handlers)] + # for report in reports: + # # TODO check if prefix cascading still occurs. + # if not report.checker_name.startswith("gcc-"): + # report.checker_name = "gcc-" + report.checker_name + + hash_type = HashType.PATH_SENSITIVE + if self.report_hash_type == 'context-free-v2': + hash_type = HashType.CONTEXT_FREE + elif self.report_hash_type == 'diagnostic-message': + hash_type = HashType.DIAGNOSTIC_MESSAGE + + for report in reports: + report.report_hash = get_report_hash(report, hash_type) + + report_file.create( + self.analyzer_result_file, reports, self.checker_labels, + self.analyzer_info) + + # TODO Maybe move this to post_analyze? + gcc_out_folder = Path(self.workspace, "gcc") + gcc_out_folder.mkdir(exist_ok=True) + gcc_dest_file_name = \ + Path(gcc_out_folder, os.path.basename(self.analyzed_source_file) + + self.buildaction_hash + ".sarif.bak") + try: + shutil.move(gcc_output_file, gcc_dest_file_name) + except(OSError) as e: + LOG.error(f"Failed to move '{gcc_output_file}' to " + f"'{gcc_out_folder}': {e}") diff --git a/analyzer/codechecker_analyzer/cmd/analyzers.py b/analyzer/codechecker_analyzer/cmd/analyzers.py index d66a190340..d599695895 100644 --- a/analyzer/codechecker_analyzer/cmd/analyzers.py +++ b/analyzer/codechecker_analyzer/cmd/analyzers.py @@ -145,6 +145,8 @@ def main(args): elif args.dump_config == 'cppcheck': # TODO: Not supported by CppCheck yet! LOG.warning("'--dump-config cppcheck' is not supported.") + elif args.dump_config == 'gcc': + raise NotImplementedError('--dump-config') return diff --git a/analyzer/codechecker_analyzer/cmd/checkers.py b/analyzer/codechecker_analyzer/cmd/checkers.py index 273ac632e3..e55032dc8d 100644 --- a/analyzer/codechecker_analyzer/cmd/checkers.py +++ b/analyzer/codechecker_analyzer/cmd/checkers.py @@ -545,6 +545,10 @@ def __print_checker_config(args: argparse.Namespace): if analyzer != "cppcheck": analyzer_failures.append(analyzer) continue + # TODO + if analyzer != "gcc": + analyzer_failures.append(analyzer) + continue rows.extend((':'.join((analyzer, c[0])), c[1]) if 'details' in args else (':'.join((analyzer, c[0])),) for c in configs) diff --git a/analyzer/pytest.ini b/analyzer/pytest.ini index 7ee6b8962d..12ad627b24 100644 --- a/analyzer/pytest.ini +++ b/analyzer/pytest.ini @@ -10,4 +10,4 @@ addopts = # --maxfail=1 # do not capture stdout - --capture=sys + --capture=no diff --git a/analyzer/tests/functional/analyze/test_analyze.py b/analyzer/tests/functional/analyze/test_analyze.py index 3cc6b53ede..39027cc447 100644 --- a/analyzer/tests/functional/analyze/test_analyze.py +++ b/analyzer/tests/functional/analyze/test_analyze.py @@ -1134,7 +1134,7 @@ def test_disable_all_checkers(self): out, _ = process.communicate() # Checkers of all 3 analyzers are disabled. - self.assertEqual(out.count("No checkers enabled for"), 3) + self.assertEqual(out.count("No checkers enabled for"), 4) def test_analyzer_and_checker_config(self): """Test analyzer configuration through command line flags.""" diff --git a/analyzer/tests/functional/analyze_and_parse/test_analyze_and_parse.py b/analyzer/tests/functional/analyze_and_parse/test_analyze_and_parse.py index 3ad7890b2b..98fabd73ce 100644 --- a/analyzer/tests/functional/analyze_and_parse/test_analyze_and_parse.py +++ b/analyzer/tests/functional/analyze_and_parse/test_analyze_and_parse.py @@ -223,7 +223,8 @@ def check_one_file(self, path, mode): "[] - Enabled checkers:", "clang-tidy:", "clangsa:", - "cppcheck:"] + "cppcheck:", + "gcc:"] for line in output: # replace timestamps line = re.sub(r'\[\w+ \d{4}-\d{2}-\d{2} \d{2}:\d{2}\]', @@ -249,6 +250,7 @@ def check_one_file(self, path, mode): print(correct_output) print("Test output file: " + path) + self.maxDiff = None self.assertEqual(''.join(post_processed_output), correct_output) def test_json_output_for_macros(self): diff --git a/analyzer/tests/functional/analyze_and_parse/test_files/Makefile b/analyzer/tests/functional/analyze_and_parse/test_files/Makefile index 49d037b5cb..0e214e6557 100644 --- a/analyzer/tests/functional/analyze_and_parse/test_files/Makefile +++ b/analyzer/tests/functional/analyze_and_parse/test_files/Makefile @@ -49,3 +49,5 @@ cppcheck_include: $(CXX) -w cppcheck_include.cpp -I ./includes/ -o /dev/null cppcheck_undef_include: $(CXX) -w cppcheck_include.cpp -I./includes/ -U HAVE_NULL_DEREFERENCE -o /dev/null +gcc_simple: + $(CXX) -w gcc_simple.cpp -o /dev/null -c diff --git a/analyzer/tests/functional/analyze_and_parse/test_files/gcc_simple.cpp b/analyzer/tests/functional/analyze_and_parse/test_files/gcc_simple.cpp new file mode 100644 index 0000000000..cc1180eea1 --- /dev/null +++ b/analyzer/tests/functional/analyze_and_parse/test_files/gcc_simple.cpp @@ -0,0 +1,6 @@ +#include +void g(void *i) { + i = malloc(sizeof(int)); + free(i); + free(i); +} diff --git a/analyzer/tests/functional/analyze_and_parse/test_files/gcc_simple.output b/analyzer/tests/functional/analyze_and_parse/test_files/gcc_simple.output new file mode 100644 index 0000000000..d7573c3334 --- /dev/null +++ b/analyzer/tests/functional/analyze_and_parse/test_files/gcc_simple.output @@ -0,0 +1,57 @@ +NORMAL#CodeChecker log --output $LOGFILE$ --build "make gcc_simple" --quiet +NORMAL#CodeChecker analyze $LOGFILE$ --output $OUTPUT$ --analyzers gcc --enable=sensitive +NORMAL#CodeChecker parse $OUTPUT$ +CHECK#CodeChecker check --build "make gcc_simple" --output $OUTPUT$ --quiet --analyzers gcc --enable=sensitive +----------------------------------------------- +[] - Starting build... +[] - Using CodeChecker ld-logger. +[] - Build finished successfully. +[] - Starting static analysis ... +[] - [1/1] gcc analyzed gcc_simple.cpp successfully. +[] - ----==== Summary ====---- +[] - Successfully analyzed +[] - gcc: 1 +[] - Total analyzed compilation commands: 1 +[] - ----=================---- +[] - Analysis finished. +[] - To view results in the terminal use the "CodeChecker parse" command. +[] - To store results use the "CodeChecker store" command. +[] - See --help and the user guide for further options about parsing and storing the reports. +[] - ----=================---- +[LOW] gcc_simple.cpp:5:3: double-‘free’ of ‘i’ [-Wanalyzer-double-free] + free(i); + ^ + +Found 1 defect(s) in gcc_simple.cpp + + +----==== Severity Statistics ====---- +---------------------------- +Severity | Number of reports +---------------------------- +LOW | 1 +---------------------------- +----=================---- + +----==== Checker Statistics ====---- +----------------------------------------------------- +Checker name | Severity | Number of reports +----------------------------------------------------- +-Wanalyzer-double-free | LOW | 1 +----------------------------------------------------- +----=================---- + +----==== File Statistics ====---- +---------------------------------- +File name | Number of reports +---------------------------------- +gcc_simple.cpp | 1 +---------------------------------- +----=================---- + +----======== Summary ========---- +--------------------------------------------- +Number of processed analyzer result files | 2 +Number of analyzer reports | 1 +--------------------------------------------- +----=================---- diff --git a/config/labels/analyzers/gcc.json b/config/labels/analyzers/gcc.json new file mode 100644 index 0000000000..c71860920f --- /dev/null +++ b/config/labels/analyzers/gcc.json @@ -0,0 +1,285 @@ +{ + "analyzer": "gcc", + "labels": { + "-Wanalyzer-allocation-size": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-allocation-size", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-deref-before-check": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-deref-before-check", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-double-fclose": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-double-fclose", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-double-free": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-double-free", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-exposure-through-output-file": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-exposure-through-output-file", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-exposure-through-uninit-copy": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-exposure-through-uninit-copy", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-fd-access-mode-mismatch": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-fd-access-mode-mismatch", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-fd-double-close": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-fd-double-close", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-fd-leak": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-fd-leak", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-fd-phase-mismatch": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-fd-phase-mismatch", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-fd-type-mismatch": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-fd-type-mismatch", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-fd-use-after-close": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-fd-use-after-close", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-fd-use-without-check": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-fd-use-without-check", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-file-leak": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-file-leak", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-free-of-non-heap": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-free-of-non-heap", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-imprecise-fp-arithmetic": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-imprecise-fp-arithmetic", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-infinite-recursion": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-infinite-recursion", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-jump-through-null": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-jump-through-null", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-malloc-leak": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-malloc-leak", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-mismatching-deallocation": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-mismatching-deallocation", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-null-argument": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-null-argument", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-null-dereference": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-null-dereference", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-out-of-bounds": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-out-of-bounds", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-overlapping-buffers": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-overlapping-buffers", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-possible-null-argument": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-possible-null-argument", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-possible-null-dereference": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-possible-null-dereference", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-putenv-of-auto-var": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-putenv-of-auto-var", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-shift-count-negative": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-shift-count-negative", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-shift-count-overflow": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-shift-count-overflow", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-stale-setjmp-buffer": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-stale-setjmp-buffer", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-unsafe-call-within-signal-handler": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-unsafe-call-within-signal-handler", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-use-after-free": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-use-after-free", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-use-of-pointer-in-stale-stack-frame": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-use-of-pointer-in-stale-stack-frame", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-use-of-uninitialized-value": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-use-of-uninitialized-value", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-va-arg-type-mismatch": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-va-arg-type-mismatch", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-va-list-exhausted": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-va-list-exhausted", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-va-list-leak": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-va-list-leak", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-va-list-use-after-va-end": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-va-list-use-after-va-end", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-write-to-const": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-write-to-const", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ], + "-Wanalyzer-write-to-string-literal": [ + "doc_url:https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-write-to-string-literal", + "profile:extreme", + "profile:security", + "profile:sensitive", + "severity:LOW" + ] + } +} diff --git a/config/package_layout.json b/config/package_layout.json index abfef0572f..49579fe89b 100644 --- a/config/package_layout.json +++ b/config/package_layout.json @@ -3,7 +3,8 @@ "analyzers": { "clangsa": "clang", "clang-tidy": "clang-tidy", - "cppcheck": "cppcheck" + "cppcheck": "cppcheck", + "gcc": "g++" }, "clang-apply-replacements": "clang-apply-replacements" }, diff --git a/docs/README.md b/docs/README.md index 539092b6c0..2e6357e7e7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -32,7 +32,7 @@ macOS (OS X) development environment. # Main features ## Command line C/C++ Analysis - * Executes [_Clang-Tidy_](http://clang.llvm.org/extra/clang-tidy/), [_Clang Static Analyzer_](http://clang-analyzer.llvm.org/) with Cross-Translation Unit analysis, Statistical Analysis (when checkers are available), and [_Cppcheck_](https://cppcheck.sourceforge.io/). + * Executes [_Clang-Tidy_](http://clang.llvm.org/extra/clang-tidy/), [_Clang Static Analyzer_](http://clang-analyzer.llvm.org/) with Cross-Translation Unit analysis, Statistical Analysis (when checkers are available), [_Cppcheck_](https://cppcheck.sourceforge.io/), and the [_GCC Static Analyzer_](https://gcc.gnu.org/wiki/StaticAnalyzer). * Creates the JSON compilation database by wiretapping any build process (e.g., `CodeChecker log -b "make"`). * Automatically analyzes GCC cross-compiled projects: detecting GCC or Clang compiler configuration and forming the corresponding clang analyzer invocations. * Incremental analysis: Only the changed files and its dependencies need to be reanalyzed. @@ -238,8 +238,9 @@ The following commands are used to bootstrap CodeChecker on Ubuntu 20.04 LTS: # NOTE: clang or clang-tidy can be any sufficiently fresh version, and need not # come from package manager! # In case of Cppcheck, the minimal supported version is 1.80. -sudo apt-get install clang clang-tidy cppcheck build-essential curl gcc-multilib \ - git python3-dev python3-venv python3-setuptools +# In case of gcc, the minimal supported version is 13.0.0. +sudo apt-get install clang clang-tidy cppcheck g++ build-essential curl + gcc-multilib git python3-dev python3-venv python3-setuptools # Install nodejs dependency for web. In case of Debian/Ubuntu you can use the # following commands. For more information see the official docs: diff --git a/docs/analyzer/checker_and_analyzer_configuration.md b/docs/analyzer/checker_and_analyzer_configuration.md index 21c41a7d68..7adda1631d 100644 --- a/docs/analyzer/checker_and_analyzer_configuration.md +++ b/docs/analyzer/checker_and_analyzer_configuration.md @@ -267,3 +267,7 @@ CodeChecker check -l ./compile_commands.json \ --analyzer-config cppcheck:inconclusive=true \ # allow inconclusive reports -o ./reports ``` + +# Cppcheck + +TODO diff --git a/docs/analyzer/user_guide.md b/docs/analyzer/user_guide.md index 96c814995a..27ea582c9b 100644 --- a/docs/analyzer/user_guide.md +++ b/docs/analyzer/user_guide.md @@ -1168,11 +1168,13 @@ analyzer arguments: CodeChecker supports several analyzer tools. Currently, these analyzers are the [_Clang Static Analyzer_](http://clang-analyzer.llvm.org), -[_Clang-Tidy_](http://clang.llvm.org/extra/clang-tidy) and -[_Cppcheck_](http://cppcheck.sourceforge.net/). `--analyzers` can be -used to specify which analyzer tool should be used (by default, all supported -are used). The tools are completely independent, so either can be omitted if -not present as they are provided by different binaries. +[_Clang-Tidy_](http://clang.llvm.org/extra/clang-tidy), +[_Cppcheck_](http://cppcheck.sourceforge.net/) and +[_GCC Static Analyzer_](https://gcc.gnu.org/wiki/StaticAnalyzer). +`--analyzers` can be used to specify which analyzer tool should be used (by +default, all supported are used). The tools are completely independent, so +either can be omitted if not present as they are provided by different +binaries. See [Configure Clang Static Analyzer and checkers](checker_and_analyzer_configuration.md) documentation for a more detailed description how to use the `saargs`,