'\" t .\" Man page generated from reStructuredText .\" by the Docutils 0.23 manpage writer. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "EXTRACLANGTOOLS" "1" "Jun 21, 2026" "22" "Extra Clang Tools" .SH "نام (NAME)" extraclangtools \- مستندات ابزارهای تکمیلی کلنگ (Extra Clang Tools) .sp به پروژه clang\-tools\-extra که شامل ابزارهای اضافی ساخته‌شده با استفاده از APIهای ابزارسازی Clang است خوش آمدید. .SH یادداشت‌های انتشار EXTRA CLANG TOOLS 22.1.8 .INDENT 0.0 .IP \(bu 2 مقدمه .IP \(bu 2 چه چیزهایی در Extra Clang Tools 22.1.8 جدید است؟ .INDENT 2.0 .IP \(bu 2 ویژگی‌های عمده جدید .IP \(bu 2 تغییرات بالقوه ناسازگار .IP \(bu 2 بهبودهای clangd .INDENT 2.0 .IP \(bu 2 فلگ‌های کامپایل .IP \(bu 2 عیب‌یابی‌ها (Diagnostics) .IP \(bu 2 Hover .IP \(bu 2 ارجاعات متقابل (Cross\-references) .IP \(bu 2 نکات درون‌خطی (Inlay hints) .IP \(bu 2 سلسله‌مراتب فراخوانی (Call hierarchy) .IP \(bu 2 نمادهای سند (Document symbols) .IP \(bu 2 جمع‌کردن کد (Code folding) .IP \(bu 2 تکمیل خودکار کد (Code completion) .IP \(bu 2 اقدامات کد (Code actions) .IP \(bu 2 پشتیبانی از C++20 Modules .IP \(bu 2 متفرقه .UNINDENT .IP \(bu 2 بهبودهای clang\-doc .IP \(bu 2 بهبودهای clang\-query .IP \(bu 2 بهبودهای clang\-tidy .INDENT 2.0 .IP \(bu 2 بررسی‌های جدید .IP \(bu 2 نام‌های مستعار جدید برای بررسی‌ها .IP \(bu 2 تغییرات در بررسی‌های موجود .IP \(bu 2 بررسی‌های حذف‌شده .IP \(bu 2 متفرقه .UNINDENT .IP \(bu 2 بهبودهای include\-fixer .IP \(bu 2 بهبودهای clang\-include\-fixer .IP \(bu 2 بهبودهای modularize .IP \(bu 2 بهبودهای pp\-trace .IP \(bu 2 پلاگین Visual Studio برای Clang\-tidy .UNINDENT .UNINDENT .sp نوشته‌شده توسط تیم LLVM \% .SS مقدمه .sp این سند شامل یادداشت‌های انتشار برای Extra Clang Tools، بخشی از انتشار 22.1.8 نرم‌افزار Clang است\&. در اینجا وضعیت ابزارهای اضافی Clang را با جزئیات شرح می‌دهیم، از جمله بهبودهای عمده نسبت به نسخه قبلی و کارهای صورت‌گرفته روی ویژگی‌های جدید. تمام انتشارهای LLVM ممکن است از وبگاه انتشارهای LLVM بارگیری شوند \%\&. .sp برای اطلاعات بیشتر درباره Clang یا LLVM، شامل اطلاعات درباره آخرین نسخه، لطفاً به وبگاه Clang \% یا وبگاه LLVM \% مراجعه کنید\&. .sp توجه داشته باشید که اگر این فایل را از یک checkout در Git یا صفحه اصلی وبگاه Clang می‌خوانید، این سند برای نسخه \fIبعدی\fP صدق می‌کند، نه نسخه فعلی. برای مشاهده یادداشت‌های انتشار مربوط به یک نسخه خاص، لطفاً صفحه انتشارها را مشاهده کنید \%\&. .SS چه چیزهایی در Extra Clang Tools 22.1.8 جدید است؟ .sp برخی از ویژگی‌های اصلی جدید و بهبودهای صورت‌گرفته در Extra Clang Tools در اینجا فهرست شده‌اند. بهبودهای عمومی در کل Extra Clang Tools یا در زیرساخت‌های بنیادین آن ابتدا توضیح داده شده و به دنبال آن بخش‌های اختصاصی هر ابزار آمده است. .SS ویژگی‌های عمده جدید .SS تغییرات بالقوه ناسازگار .INDENT 0.0 .IP \(bu 2 ماژول \fBhicpp\fP در \fBclang\-tidy\fP منسوخ شد. تمام بررسی‌ها در عوض به ماژول‌های دیگر منتقل شده‌اند. ماژول \fBhicpp\fP برای نسخه 23.x حذف خواهد شد. .IP \(bu 2 ماژول \fBzircon\fP در \fBclang\-tidy\fP منسوخ شد. تمام بررسی‌ها در عوض به ماژول \fBfuchsia\fP منتقل شده‌اند. ماژول \fBzircon\fP در نسخه بیست و چهارم حذف خواهد شد. .IP \(bu 2 گزینه‌های سراسری \fIIgnoreMacros\fP و \fIStrictMode\fP از \fBclang\-tidy\fP حذف شدند، که از زمان \fBclang\-tidy\-20\fP به عنوان منسوخ‌شده مستند شده بودند\&. کاربران باید در عوض از گزینه‌های اختصاصی بررسی با همین نام استفاده کنند. .IP \(bu 2 بررسی‌های \fIclang\-analyzer\-*\fP از بررسی‌های پیش‌فرض در \fBclang\-tidy\fP حذف شدند\&. از این پس، کاربران باید صریحاً با استفاده از \fIclang\-analyzer\-*\fP مشخص کنند که می‌خواهند بررسی‌های CSA در \fBclang\-tidy\fP اجرا شوند. .IP \(bu 2 نام چند گزینه از بررسی‌های \fBclang\-tidy\fP تغییر یافت، زیرا دارای غلط املایی بودند: .INDENT 2.0 .IP \(bu 2 \fINamePrefixSuffixSilenceDissimilarityTreshold\fP به \fINamePrefixSuffixSilenceDissimilarityThreshold\fP در bugprone\-easily\-swappable\-parameters \%<> .IP \(bu 2 \fICharTypdefsToIgnore\fP به \fICharTypedefsToIgnore\fP در bugprone\-signed\-char\-misuse \%<> .UNINDENT .IP \(bu 2 قالب پیام سفارشی bugprone\-unsafe\-functions \%<> با اختصاص یک معنای خاص به نویسه \fB>\fP در ابتدای مقدار گزینه \fBCustomFunctions\fP اصلاح شد\&. اگر مقدار گزینه با \fB>\fP شروع شود، بخش پیشنهاد جایگزینی پیام (که به صورت پیش‌فرض گنجانده می‌شد) حذف می‌شود. (این کار مکان‌های هشدار را تغییر نمی‌دهد.) .IP \(bu 2 ابزار \fBclang\-tidy\fP اکنون به طور پیش‌فرض هشدارهای تمام هدرهای غیرسیستمی را نمایش می‌دهد. پیش از این، کاربران باید صریحاً با استفاده از \fI\-header\-filter=\(aq.*\(aq\fP برای دریافت هشدارهای هدر اعلام موافقت می‌کردند\&. برای غیرفعال کردن هشدارها از هدرهای غیرسیستمی، \fI\-header\-filter\fP را روی یک رشته خالی تنظیم کنید. .IP \(bu 2 هدر \fBclang\-tidy/ClangTidyModuleRegistry.h\fP منسوخ شده و در LLVM 24 حذف خواهد شد. تمام نمادهایی که قبلاً تعریف می‌کرد به \fBclang\-tidy/ClangTidyModule.h\fP منتقل شده‌اند\&. .UNINDENT .SS بهبودهای clangd .SS فلگ‌های کامپایل .INDENT 0.0 .IP \(bu 2 افزودن پشتیبانی مناسب از فلگ \fB\-std=c++latest\fP، که اغلب توسط کاربران ویندوز برای نوشتن کدهای C++23 استفاده می‌شود. .UNINDENT .SS عیب‌یابی‌ها .INDENT 0.0 .IP \(bu 2 رفع باگی که باعث کار نکردن رفع سریع (quick\-fix) برای عیب‌یابی \fBreadability\-identifier\-naming\fP در برخی ویرایشگرها می‌شد. .UNINDENT .SS قابلیت Hover .INDENT 0.0 .IP \(bu 2 افزودن پشتیبانی از تجزیه و نمایش مستندات doxygen و markdown .IP \(bu 2 افزودن گزینهٔ پیکربندی \fBMacroContentsLimit\fP تا کاربران بتوانند در صورت تمایل، تعاریف ماکروها را حتی اگر بسیار طولانی باشند در hover مشاهده کنند .IP \(bu 2 رفع باگی که مانع از نمایش مستندات برای اعضای قالب‌های کلاسی تعریف‌شده در یک هدر می‌شد .IP \(bu 2 رفع باگی که مانع از نمایش مستندات برای قالب‌های توابع خلاصه شده (abbreviated function templates) می‌شد .UNINDENT .SS مراجع متقابل (Cross\-references) .INDENT 0.0 .IP \(bu 2 بهبود پشتیبانی از \(dqgo to definition\(dq برای \fBauto\fP وابسته .IP \(bu 2 بهبود پشتیبانی از \(dqgo to definition\(dq برای قابلیت \(dqdeducing this\(dq در C++23 .IP \(bu 2 رفع باگی که در آن ویژگی‌ها (attributes) روی یک متد باعث اختلال در قابلیت‌های مختلف، از جمله \(dqgo to definition\(dq روی نام یک متد می‌شد .IP \(bu 2 اکنون قابلیت \(dqFind references\(dq روی یک سازنده، محل‌های فراخوانی توابع فورواردکننده مانند \fBmake_unique\fP را نیز پیدا می‌کند .IP \(bu 2 قابلیت \(dqDocument links\(dq اکنون از دایرکتیوهای \fB#include\fP با آرگومان ماکرو پشتیبانی می‌کند .UNINDENT .SS نکات درون‌خطی (Inlay hints) .INDENT 0.0 .IP \(bu 2 نمایش نکات مشخص‌کننده (designator hints) برای مقداردهی اولیهٔ تجمعی ساختارها با نحو مقداردهی پرانتز\-لیست (\fBCXXParenListInitExpr\fP). .IP \(bu 2 نمایش نکات نوع (type hints) برای حالت‌های سادهٔ \fBauto\fP وابسته .UNINDENT .SS سلسله‌مراتب فراخوانی (Call hierarchy) .INDENT 0.0 .IP \(bu 2 پشتیبانی از فراخوانی سلسله‌مراتب فراخوانی روی ثابت‌های enum .IP \(bu 2 هنگام اجرا روی یک تابع مجازی، فراخواننده‌های توابع پایه نیز نمایش داده می‌شوند .UNINDENT .SS نمادهای سند (Document symbols) .INDENT 0.0 .IP \(bu 2 شامل کردن توابع دوست درون‌خطی (inline friend) در نمادهای سند .UNINDENT .SS تا کردن کد (Code folding) .INDENT 0.0 .IP \(bu 2 پشتیبانی از تا کردن شاخه‌های پیش‌پردازنده .IP \(bu 2 پشتیبانی از تا کردن بلوک‌های \fB#pragma region\fP .UNINDENT .SS تکمیل خودکار کد (Code completion) .INDENT 0.0 .IP \(bu 2 افزودن گزینهٔ پیکربندی جدید \fBMacroFilter\fP به بخش \fBCompletion\fP به منظور امکان تطبیق تقریبی (fuzzy\-matching) با گزینهٔ \fBFuzzyMatch\fP هنگام پیشنهاد دادن ماکروها. حالت پیش‌فرض \fBExactPrefix\fP است که رفتار پیشین را در پیشنهاد ماکروهایی که دقیقاً با پیشوند مطابقت دارند حفظ می‌کند. .IP \(bu 2 بهبود پشتیبانی از \(dqdeducing this\(dq در C++23 .IP \(bu 2 درج هدرها اکنون به جای مسیرهای نوشته‌شده، \fBAngledHeaders\fP و \fBQuotedHeaders\fP را در برابر مسیرهای حل‌شده بررسی می‌کند که با رفتار موجود در عیب‌یابی‌های include\-cleaner سازگار است. .UNINDENT .SS عملیات‌های کد (Code actions) .INDENT 0.0 .IP \(bu 2 عملیات کد جدید \fBOverride pure virtual methods\fP. در صورت اجرا روی تعریف یک کلاس، این عملیات به‌طور خودکار اعلان‌های \fBoverride\fP در C++ را برای تمام متدهای مجازی محض ارث‌بری‌شده از کلاس‌های پایه که هنوز پیاده‌سازی نشده‌اند تولید می‌کند. بدنه‌های تولید‌شده برای متدها از کاربر درخواست پیاده‌سازی واقعی را می‌کنند. موارد بازنویسی‌شده به‌صورت هوشمندانه تحت مشخص‌کننده‌های دسترسی اصلی خود (مانند \fBpublic\fP، \fBprotected\fP) گروه‌بندی می‌شوند و در صورت نیاز بلوک‌های مشخص‌کنندهٔ دسترسی جدید ایجاد می‌گردد. .IP \(bu 2 بهبود منطق عملیات کد \(dqmove function body out\-of\-line\(dq برای انتخاب محل قرار دادن تعریف. اکنون تلاش می‌کند تا آن را در کنار تعریف متدی با یک اعلان مجاور قرار دهد. .UNINDENT .SS پشتیبانی از ماژول‌های C++20 .INDENT 0.0 .IP \(bu 2 رفع کرش هنگام استفاده از \fB\-\-experimental\-modules\-support\fP بدون پایگاه‌داده کامپایل (compilation database) .IP \(bu 2 افزودن گزینهٔ \fB\-\-debug\-modules\-builder\fP برای کمک به اشکال‌زدایی پشتیبانی ماژول‌ها در clangd .IP \(bu 2 بهبود عیب‌یابی‌های مربوط به ماژول‌ها .IP \(bu 2 اکنون clangd سعی می‌کند در صورت مناسب بودن، از ماژول ساخت پروژه مجدداً استفاده کند .UNINDENT .SS متفرقه .INDENT 0.0 .IP \(bu 2 افزودن فایل تطبیق الگوی \fB\&.gitignore\fP به دایرکتوری نمایه‌سازی clangd. .UNINDENT .SS بهبودهای clang\-doc .INDENT 0.0 .IP \(bu 2 استفاده از مولد HTML مبتنی بر Mustache به عنوان گزینهٔ پیش‌فرض HTML. .IP \(bu 2 مستندسازی conceptها، typedefها، aliasها، اعضای عمومی کلاس، رکوردهای تو در تو، فضاهای نام تو در تو، توابع سراسری، متغیرهای سراسری، متدها و اعضای محافظت‌شده و توابع دوست در HTML. .IP \(bu 2 مستندسازی کامنت‌های \fBthrows\fP در HTML. .IP \(bu 2 افزودن محل تعریف کلاس‌ها در HTML. .IP \(bu 2 نمایش اعلان قالب کلاس در HTML. .IP \(bu 2 افزودن یک صفحهٔ نمایه سطح بالا در HTML. این صفحه فضاهای نام سطح بالا را فهرست می‌کند و به عنوان نشانی وب ریشه مستندات عمل می‌کند. .IP \(bu 2 افزودن دکمهٔ \fBHome\fP به نوار ناوبری که جایگزین دکمه‌های غیرمفید می‌شود. این دکمه جدید به صفحهٔ نمایه سطح بالا پیوند دارد. .IP \(bu 2 افزودن نوار ناوبری مسیر راهنما (breadcrumb) به navbar. این به پیمایش در زمینهٔ موجودیت مستندشده کمک می‌کند. .IP \(bu 2 اگر نام فایل بیش از حد طولانی باشد، نام کوتاه شده و شناسه USR موجودیت مستندشده به انتهای آن اضافه می‌شود تا یکتا بودن آن تضمین گردد. .IP \(bu 2 بازگرداندن ساختار دایرکتوری تخت (flat) به ساختار دایرکتوری تو در تو. .UNINDENT .SS بهبودهای clang\-query .INDENT 0.0 .IP \(bu 2 پرس‌وجوهای Matcher که توسط clang\-query تفسیر می‌شوند اکنون از کامای انتهایی (,) در آرگومان‌های matcher پشتیبانی می‌کنند. توجه داشته باشید که C++ هنوز این مورد را در آرگومان‌های تابع مجاز نمی‌داند. بنابراین هنگام انتقال یک پرس‌وجو به C++، تمام نمونه‌های کامای پایانی را حذف کنید (در غیر این صورت کامپایلر C++ خطای \(dqexpected expression\(dq صادر می‌کند). .UNINDENT .SS بهبودها در clang\-tidy .INDENT 0.0 .IP \(bu 2 ابزار \fBcheck_clang_tidy.py\fP اکنون هنگام اجرا روی فایل‌های C، آرگومان \fB\-std\fP را شناسایی می‌کند. اگر \fB\-std\fP مشخص نشده باشد، مقدار پیش‌فرض آن \fBc99\-or\-later\fP خواهد بود. .IP \(bu 2 \fBclang\-tidy\fP اکنون به طور پیش‌فرض هشدارهای تمام هدرهای غیرسیستمی را نمایش می‌دهد. پیش از این، کاربران مجبور بودند با استفاده از \fI\-header\-filter=\(aq.*\(aq\fP به‌طور صریح هشدارهای مربوط به هدرها را فعال کنند. برای غیرفعال کردن هشدارهای هدرهای غیرسیستمی، \fI\-header\-filter\fP را روی یک رشته خالی تنظیم کنید. .IP \(bu 2 \fBclang\-tidy\fP دیگر به‌طور پیش‌فرض تلاشی برای تجزیه و تحلیل کدهای هدرهای سیستمی نمی‌کند، که این امر کارایی را به شدت بهبود می‌بخشد. در صورت فعال بودن گزینه \fISystemHeaders\fP، این رفتار غیرفعال می‌شود. .IP \(bu 2 \fBclang\-tidy\fP اکنون از بررسی‌های سفارشی مبتنی بر پرسمان (query based) به کمک گزینه پیکربندی \fICustomChecks\fP پشتیبانی می‌کند. مستندات Query Based Custom Check \%<> .IP \(bu 2 اسکریپت‌های \fBrun\-clang\-tidy.py\fP و \fBclang\-tidy\-diff.py\fP اکنون به‌طور پیش‌فرض با استفاده از تمام رشته‌های پردازشی (threads) سخت‌افزاری موجود، بررسی‌ها را به صورت موازی اجرا می‌کنند. هر دو اسکریپت تعداد رشته‌های مورد استفاده را در خروجی خود نمایش می‌دهند. .IP \(bu 2 ابزار \fBrun\-clang\-tidy.py\fP با افزودن گزینه جدید \fIenable\-check\-profile\fP بهبود یافته است تا پروفایل‌های زمانی را به ازای هر بررسی فعال کرده و گزارشی را بر اساس تمامی فایل‌های تجزیه و تحلیل‌شده چاپ کند. .IP \(bu 2 مستندات پرچم خط فرمان \fI\-line\-filter\fP در \fBclang\-tidy\fP و \fBrun\-clang\-tidy.py\fP بهبود یافته است. .IP \(bu 2 گزینه \fI\-quiet\fP در \fBclang\-tidy\fP با جلوگیری از نمایش پیام‌های شمارش عیب‌یابی‌ها بهبود یافته است. .IP \(bu 2 \fBclang\-tidy\fP بهبود یافته تا در صورت استفاده از یک فیلد خالی \fIdirectory\fP در پایگاه داده کامپایل، دچار فروپاشی (crash) نشود؛ در عوض، دایرکتوری کاری فعلی استفاده خواهد شد و یک پیام خطا چاپ می‌شود. .IP \(bu 2 گزینه‌های سراسری \fIIgnoreMacros\fP و \fIStrictMode\fP در \fBclang\-tidy\fP که از زمان \fBclang\-tidy\-20\fP به عنوان منسوخ‌شده مستند شده بودند، حذف شدند. کاربران باید به جای آن‌ها از گزینه‌های هم‌نام مخصوص هر بررسی استفاده کنند. .IP \(bu 2 اسکریپت‌های \fBrun\-clang\-tidy.py\fP و \fBclang\-tidy\-diff.py\fP با افزودن گزینه \fI\-hide\-progress\fP برای جلوگیری از نمایش پیام‌های پیشرفت و اطلاعاتی، بهبود یافته‌اند. .IP \(bu 2 بررسی‌های \fIclang\-analyzer\-*\fP از بررسی‌های پیش‌فرض در \fBclang\-tidy\fP حذف شدند. از این پس، کاربران باید صراحتاً مشخص کنند که تمایل به اجرای بررسی‌های CSA در \fBclang\-tidy\fP را دارند. .IP \(bu 2 \fBclang\-tidy\fP با اضافه شدن گزینه \fI\-\-removed\-arg\fP جهت حذف آرگومان‌های ارسال‌شده به کامپایلر در هنگام فراخوانی Clang\-Tidy بهبود یافته است. این گزینه همچنین به \fBrun\-clang\-tidy.py\fP و \fBclang\-tidy\-diff.py\fP اضافه شده و می‌تواند از طریق گزینه \fIRemovedArgs\fP در فایل پیکربندی تنظیم شود. .IP \(bu 2 ماژول \fBzircon\fP در \fBclang\-tidy\fP منسوخ شده است. تمامی بررسی‌ها به ماژول \fBfuchsia\fP منتقل شده‌اند. ماژول \fBzircon\fP در انتشار بیست و چهارم حذف خواهد شد. .IP \(bu 2 تجزیه پیکربندی \fBclang\-tidy\fP با امکان استفاده از نحو فهرست مشابه در \fIWarningsAsErrors\fP همانند \fIChecks\fP، بهبود یافته است. .UNINDENT .SS بررسی‌های جدید .INDENT 0.0 .IP \(bu 2 بررسی جدید abseil\-unchecked\-statusor\-access \%<>. .sp موارد استفاده از \fBabsl::StatusOr\fP را بدون بررسی وجود مقدار، پیدا می‌کند. .IP \(bu 2 بررسی جدید bugprone\-derived\-method\-shadowing\-base\-method \%<>. .sp متدهای کلاس مشتق را که متد کلاس پایه (غیرمجازی) را می‌پوشانند (shadow)، پیدا می‌کند. .IP \(bu 2 بررسی جدید bugprone\-invalid\-enum\-default\-initialization \%<>. .sp مقداردهی اولیه پیش‌فرض (به 0) متغیرهای دارای نوع \fBenum\fP را در شرایطی که شمارنده هیچ مقداری برابر با 0 ندارد، شناسایی می‌کند. .IP \(bu 2 بررسی جدید cppcoreguidelines\-pro\-bounds\-avoid\-unchecked\-container\-access \%<>. .sp فراخوانی‌های \fBoperator[]\fP در کانتینرهای STL را پیدا کرده و جایگزینی آن‌ها با موارد امن را پیشنهاد می‌دهد. .IP \(bu 2 بررسی جدید google\-runtime\-float \%<>. .sp موارد استفاده از \fBlong double\fP را پیدا کرده و به دلیل عدم پایداری در قابلیت حمل (portability)، پیشنهاد به عدم استفاده از آن می‌کند. .IP \(bu 2 بررسی جدید llvm\-mlir\-op\-builder \%<>. .sp موارد استفاده از فرم قدیمی/رو به منسوخ شدن \fBOpBuilder::create\fP در MLIR را بررسی کرده و استفاده از \fBT::create\fP را پیشنهاد می‌دهد. .IP \(bu 2 بررسی جدید llvm\-use\-ranges \%<>. .sp فراخوانی الگوریتم‌های تکرارگر کتابخانه STL را که می‌توانند با الگوریتم‌های مبتنی بر دامنه (range) متعلق به LLVM از \fBllvm/ADT/STLExtras.h\fP جایگزین شوند، پیدا می‌کند. .IP \(bu 2 بررسی جدید misc\-override\-with\-different\-visibility \%<>. .sp بازنویسی توابع مجازی با قابلیت دید (visibility) متفاوت نسبت به تابع در کلاس پایه را پیدا می‌کند. .IP \(bu 2 بررسی جدید readability\-inconsistent\-ifelse\-braces \%<>. .sp دستورات \fBif\fP/\fBelse\fP را که در آن‌ها یک شاخه از آکلاد استفاده می‌کند و شاخه دیگر استفاده نمی‌کند، شناسایی می‌کند. .IP \(bu 2 بررسی جدید readability\-redundant\-parentheses \%<>. .sp پرانتزهای اضافی را شناسایی می‌کند. .IP \(bu 2 بررسی جدید readability\-redundant\-typename \%<>. .sp موارد استفاده زائد از کلمه کلیدی \fBtypename\fP را پیدا می‌کند. .UNINDENT .SS نام‌های مستعار جدید بررسی‌ها .INDENT 0.0 .IP \(bu 2 تغییر نام cert\-dcl50\-cpp \%<> به modernize\-avoid\-variadic\-functions \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام cert\-dcl58\-cpp \%<> به bugprone\-std\-namespace\-modification \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام cert\-env33\-c \%<> به bugprone\-command\-processor \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام cert\-err34\-c \%<> به bugprone\-unchecked\-string\-to\-number\-conversion \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام cert\-err52\-cpp \%<> به modernize\-avoid\-setjmp\-longjmp \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام cert\-err58\-cpp \%<> به bugprone\-throwing\-static\-initialization \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام cert\-err60\-cpp \%<> به bugprone\-exception\-copy\-constructor\-throws \%<>. .IP \(bu 2 تغییر نام cert\-flp30\-c \%<> به bugprone\-float\-loop\-counter \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام cert\-mem57\-cpp \%<> به bugprone\-default\-operator\-new\-on\-overaligned\-type \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام cert\-msc30\-c \%<> به misc\-predictable\-rand \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام cert\-msc32\-c \%<> به bugprone\-random\-generator\-seed \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام cert\-msc50\-cpp \%<> به misc\-predictable\-rand \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام cert\-msc51\-cpp \%<> به bugprone\-random\-generator\-seed \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام cert\-oop57\-cpp \%<> به bugprone\-raw\-memory\-call\-on\-non\-trivial\-type \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام cert\-oop58\-cpp \%<> به bugprone\-copy\-constructor\-mutates\-argument \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام fuchsia\-multiple\-inheritance \%<> به misc\-multiple\-inheritance \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام google\-build\-namespaces \%<> به misc\-anonymous\-namespace\-in\-header \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .IP \(bu 2 تغییر نام google\-readability\-casting \%<> به modernize\-avoid\-c\-style\-cast \%<> ضمن حفظ بررسی اولیه به عنوان نام مستعار برای مورد جدید. .UNINDENT .SS تغییرات در بررسی‌های موجود .INDENT 0.0 .IP \(bu 2 بهبود بررسی bugprone\-chained\-comparison \%<> با افزودن گزینه جدید \fIIgnoreMacros\fP جهت فرونشاندن هشدارها در گسترش‌های ماکرو. .IP \(bu 2 بهبود بررسی bugprone\-dynamic\-static\-initializers \%<>: .INDENT 2.0 .IP \(bu 2 جلوگیری از هشدارهای نادرست (false positives) برای متغیرهای \fBconstexpr\fP که مقداردهنده‌های اولیه آن‌ها وابسته به مقدار (value\-dependent) است. .IP \(bu 2 افزودن پشتیبانی از متغیرهای \fBconstinit\fP در C++20. .UNINDENT .IP \(bu 2 بهبود بررسی bugprone\-easily\-swappable\-parameters \%<> با تصحیح یک غلط املایی در گزینه \fBNamePrefixSuffixSilenceDissimilarityTreshold\fP\&. .IP \(bu 2 بهبود بررسی bugprone\-exception\-escape \%<>: .INDENT 2.0 .IP \(bu 2 استثناها از گیراندازی‌های لامبدا (lambda captures) اکنون عیب‌یابی می‌شوند؛ استثناها در بدنه لامبداهایی که در واقع فراخوانی نمی‌شوند، گزارش نخواهند شد. .IP \(bu 2 رفع مشکلی که در آن بررسی، پرتاب استثناها در آرگومان‌های ارسالی به توابع یا سازنده‌ها را عیب‌یابی نمی‌کرد. .IP \(bu 2 افزودن پیکربندی دقیق از طریق گزینه‌های \fICheckDestructors\fP، \fICheckMoveMemberFunctions\fP، \fICheckMain\fP، \fICheckedSwapFunctions\fP، و \fICheckNothrowFunctions\fP\&. .UNINDENT .IP \(bu 2 بهبود بررسی bugprone\-infinite\-loop \%<> با افزودن تشخیص برای متغیرهای معرفی‌شده توسط مقیدسازی‌های ساختاریافته (structured bindings). .IP \(bu 2 بهبود bugprone\-invalid\-enum\-default\-initialization \%<> با گزینه جدید \fIIgnoredEnums\fP برای نادیده گرفتن enumهای مشخص‌شده در طول تحلیل. .IP \(bu 2 بهبود بررسی bugprone\-macro\-parentheses \%<> با رفع هشدارهای نادرست هنگام استفاده از پارامترهای قالب C++. .IP \(bu 2 بهبود بررسی bugprone\-narrowing\-conversions \%<> با رفع هشدار نادرست ناشی از تحلیل یک عبارت شرطی در C. .IP \(bu 2 بهبود بررسی bugprone\-not\-null\-terminated\-result \%<> با رفع اصلاحات خودکار (fix\-it) اشتباه برای \fBstrncmp\fP و \fBwcsncmp\fP در Windows و یک کرش ناشی از برخی عبارات وابسته به مقدار. .IP \(bu 2 بهبود بررسی bugprone\-reserved\-identifier \%<> با نادیده گرفتن اعلان‌ها و ماکروها در سرآیندهای سیستمی. .IP \(bu 2 بهبود بررسی bugprone\-signed\-char\-misuse \%<> با رفع هشدارهای نادرست روی enumهای C23 با نوع پایه‌ای ثابت signed char. .IP \(bu 2 بهبود بررسی bugprone\-sizeof\-expression \%<> با رفع یک کرش روی \fBsizeof\fP یک آرایه با نوع وابسته (dependent type). .IP \(bu 2 بهبود بررسی bugprone\-suspicious\-include \%<> با افزودن گزینه \fIIgnoredRegex\fP. .IP \(bu 2 بهبود bugprone\-tagged\-union\-member\-count \%<> با رفع یک هشدار نادرست هنگامی که enumها یا unionهای موجود در فایل‌های سرآیند سیستمی یا فضای نام \fBstd\fP به ترتیب به عنوان برچسب یا بخش داده یک tagged union تعریف‌شده توسط کاربر در نظر گرفته می‌شدند. .IP \(bu 2 بهبود بررسی bugprone\-throw\-keyword\-missing \%<>: .INDENT 2.0 .IP \(bu 2 اکنون فقط انواع متعارف (canonical types) کلاس‌های پایه را همان‌طور که نوشته شده‌اند در نظر می‌گیرد. .IP \(bu 2 افزودن یک یادداشت برای کلاس پایه‌ای که باعث برانگیختن هشدار شده است. .IP \(bu 2 رفع مشکلی که در آن بررسی در سازنده‌ها یا (در زمینه‌های خاص) لامبداها فعال نمی‌شد. .UNINDENT .IP \(bu 2 بهبود بررسی bugprone\-unchecked\-optional\-access \%<>: .INDENT 2.0 .IP \(bu 2 افزودن پشتیبانی از \fBNullableValue::makeValue\fP و \fBNullableValue::makeValueInplace\fP برای جلوگیری از هشدارهای نادرست برای \fBBloombergLP::bdlb::NullableValue\fP\&. .IP \(bu 2 رفع هشدارهای نادرست برای \fBbsl::optional\fP حاوی نوع allocator\-aware. .IP \(bu 2 افزودن گزینه \fIIgnoreValueCalls\fP برای فرونشاندن عیب‌یابی‌ها برای \fBoptional::value()\fP\&. .IP \(bu 2 افزودن گزینه \fIIgnoreSmartPointerDereference\fP برای نادیده گرفتن optionalهایی که از طریق ارجاع‌زدایی شبیه به اشاره‌گر هوشمند به دست آمده‌اند، در عین حفظ عیب‌یابی ارجاع‌زدایی‌های مستعد UB از طریق \fBoperator*\fP و \fBoperator\->\fP\&. .UNINDENT .IP \(bu 2 بهبود بررسی bugprone\-unhandled\-self\-assignment \%<> با افزودن یک تطبیق‌دهنده دیگر که تشخیص الگوی قاعده copy\-and\-swap را تعمیم می‌دهد. .IP \(bu 2 بهبود بررسی bugprone\-unsafe\-functions \%<> با پنهان کردن پسوند پیش‌فرض هنگامی که دلیل با نویسه \fI>\fP در گزینه \fICustomFunctions\fP آغاز می‌شود. .IP \(bu 2 بهبود بررسی bugprone\-use\-after\-move \%<>: .INDENT 2.0 .IP \(bu 2 افزودن گزینه \fIInvalidationFunctions\fP جهت پشتیبانی از توابع بی‌اعتبارسازی سفارشی. .IP \(bu 2 افزودن گزینه \fIReinitializationFunctions\fP جهت پشتیبانی از توابع مقداردهی اولیه مجدد سفارشی. .UNINDENT .IP \(bu 2 بهبود بررسی cppcoreguidelines\-avoid\-non\-const\-global\-variables \%<> با افزودن گزینه جدید \fIAllowThreadLocal\fP که هشدارها را برای متغیرهای سراسری غیر\-const با طول عمر ذخیره‌سازی thread\-local فرو می‌نشاند. .IP \(bu 2 بهبود بررسی cppcoreguidelines\-init\-variables \%<> با رفع محل درج برای اشاره‌گرهای تابع با چندین پارامتر. .IP \(bu 2 بهبود بررسی cppcoreguidelines\-macro\-usage \%<> با مستثنی کردن بدنه ماکروهایی که با کلیدواژه \fB__attribute__((..))\fP شروع می‌شوند. چنین بدنه ماکرویی بعید است یک عبارت معتبر باشد و بنابراین پیشنهاد دادن یک بازنویسی غیرممکن به یک تابع قالب به کاربران باید اجتناب شود. .IP \(bu 2 بهبود بررسی cppcoreguidelines\-prefer\-member\-initializer \%<> برای جلوگیری از هشدارهای نادرست روی اعضای به ارث رسیده در قالب‌های کلاس. .IP \(bu 2 بهبود بررسی cppcoreguidelines\-pro\-bounds\-pointer\-arithmetic \%<> با افزودن گزینه \fIAllowIncrementDecrementOperators\fP برای مجاز کردن محاسبات اشاره‌گر از طریق عملگرهای کاهش یا افزایش پیشوندی/پسوندی. .IP \(bu 2 بهبود بررسی cppcoreguidelines\-pro\-type\-member\-init \%<> برای نادیده گرفتن صحیح \fBstd::array\fP و سایر نگه‌دارنده‌های شبه‌آرایه هنگامی که گزینه \fIIgnoreArrays\fP روی \fItrue\fP تنظیم شده است. .IP \(bu 2 بهبود fuchsia\-multiple\-inheritance \%<> با رفع مشکلی که در آن بررسی فقط اولین کلاس با یک نام داده‌شده در برنامه را تحلیل می‌کرد، و کلاس‌های بعدی با همان نام (اعلان‌شده در یک حوزه متفاوت) را نادیده می‌گرفت. .IP \(bu 2 بهبود بررسی google\-readability\-casting \%<> با افزودن یادداشت‌های fix\-it برای تبدیل‌های روبه‌پایین (downcasts) و تبدیل به اشاره‌گر void. .IP \(bu 2 بهبود بررسی google\-readability\-todo \%<> برای پذیرش قالب جدید TODO از Google Style Guide. .IP \(bu 2 بهبود بررسی llvm\-prefer\-isa\-or\-dyn\-cast\-in\-conditionals \%<>: .INDENT 2.0 .IP \(bu 2 بخش Fix\-it فراخوانده‌شده‌ها با nested\-name\-specifier را به‌درستی مدیریت می‌کند. .IP \(bu 2 دستورهای \fBif\fP دارای init\-statement (\fBif (auto X = ...; ...)\fP) به‌درستی مدیریت می‌شوند. .IP \(bu 2 حلقه‌های \fBfor\fP پشتیبانی می‌شوند. .UNINDENT .IP \(bu 2 بهبود بررسی misc\-const\-correctness \%<>: .INDENT 2.0 .IP \(bu 2 رفع هشدارهای نادرست هنگام انتقال اشاره‌گرها به ارجاع‌های غیر\-const. .IP \(bu 2 رفع هشدارهای نادرست اشاره‌گر تابع، هنگام بازگرداندن اشاره‌گر غیر\-const، روی عملگر اشاره‌گر\-به\-عضو. .IP \(bu 2 رفع هشدارهای نادرست هنگامی که آدرس یک متغیر برای ارسال به یک تابع گرفته می‌شود. .UNINDENT .IP \(bu 2 بهبود بررسی misc\-coroutine\-hostile\-raii \%<> با افزودن گزینه \fIAllowedCallees\fP، که امکان معاف کردن توابع فراخوانده‌شده با قابلیت انتظار ایمن (safely awaitable) را از بررسی فراهم می‌کند. .IP \(bu 2 بهبود کارایی بررسی misc\-header\-include\-cycle \%<>. .IP \(bu 2 بهبود بررسی misc\-use\-internal\-linkage \%<>: .INDENT 2.0 .IP \(bu 2 افزودن پیشنهاد پیوند داخلی (internal linkage) برای انواع تعریف‌شده توسط کاربر (structها، classها، unionها و enumها). .IP \(bu 2 افزودن گزینه‌های دقیق \fIAnalyzeFunctions\fP، \fIAnalyzeVariables\fP، \fIAnalyzeTypes\fP برای کنترل اینکه آیا بررسی باید توابع، متغیرها، و/یا انواع تعریف‌شده توسط کاربر را عیب‌یابی کند یا خیر. .IP \(bu 2 فعال‌سازی این بررسی برای C. .UNINDENT .IP \(bu 2 بهبود modernize\-avoid\-c\-arrays \%<> جهت عدم عیب‌یابی انواع آرایه‌ای که بخشی از یک نمونه‌سازی ضمنی یک قالب هستند. .IP \(bu 2 بهبود بررسی modernize\-use\-constraints \%<> با رفع یک کرش در استفاده از \fBenable_if\fP غیر استاندارد با امضایی متفاوت از \fBstd::enable_if\fP (مانند \fBboost::enable_if\fP). .IP \(bu 2 بهبود بررسی modernize\-use\-default\-member\-init \%<> برای افزایش استحکام تشخیص مقداردهنده اولیه عضو. .IP \(bu 2 بهبود بررسی modernize\-use\-designated\-initializers \%<> برای پیشنهاد استفاده از مقداردهنده‌های اولیه تعیین‌شده (designated initializers) برای انواع تجمعی نام‌مستعاردار (aliased aggregate). .IP \(bu 2 بهبود modernize\-use\-integer\-sign\-comparison \%<> با ارائه fix\-itهای صحیح هنگامی که سمت راست یک مقایسه شامل یک تبدیل غیراستایل C است. .IP \(bu 2 بهبود بررسی modernize\-use\-nullptr \%<> با رفع یک کرش در Windows هنگامی که بررسی با یک باینری ۳۲ بیتی \fBclang\-tidy\fP فعال شده بود. .IP \(bu 2 بهبود modernize\-use\-override \%<> با رفع مشکلی که در آن بررسی گاهی اوقات درج \fBoverride\fP را در مکانی نامعتبر پیشنهاد می‌داد. .IP \(bu 2 بهبود بررسی modernize\-use\-ranges \%<> برای پیشنهاد استفاده از روش مصطلح‌تر \fBstd::views::reverse\fP در جایی که قبلاً \fBstd::ranges::reverse_view\fP را پیشنهاد می‌کرد. .IP \(bu 2 بهبود بررسی modernize\-use\-scoped\-lock \%<> با رفع یک کرش روی کدهای بدریخت (که هنگام استفاده از \fBclang\-tidy\fP از طریق \fBclangd\fP رایج است). .IP \(bu 2 بررسی modernize\-use\-std\-format \%<> بهبود یافته تا در مواردی که رشتهٔ قالب‌بندی با فراخوانی سازندهٔ ضمنی به نوع دیگری تبدیل می‌شود، به درستی تطابق پیدا کند. .IP \(bu 2 بررسی modernize\-use\-std\-print \%<> بهبود یافته تا هنگام تبدیل رشتهٔ قالب‌بندی به نوع دیگری از طریق فراخوانی سازندهٔ ضمنی به درستی تطابق یابد، و همچنین یک کرش هنگام پردازش رشته‌های قالب‌بندی حاوی نویسه‌های غیر ASCII رفع شده است. .IP \(bu 2 بررسی modernize\-use\-using \%<> بهبود یافته تا راه‌حل‌های اصلاحی (fix\-its) را برای typedefهای اشاره‌گرها یا ارجاع‌ها به انواع آرایه‌ای به‌درستی ارائه دهد. .IP \(bu 2 بررسی performance\-move\-const\-arg \%<> با جلوگیری از موارد مثبت کاذب در انواع با قابلیت کپی ساده (trivially copyable) که دارای سازندهٔ کپی غیرعمومی هستند، بهبود یافته است. .IP \(bu 2 بررسی performance\-unnecessary\-copy\-initialization \%<> با چاپ نوع متغیر خطایابی‌شده بهبود یافته است. .IP \(bu 2 بررسی performance\-unnecessary\-value\-param \%<> با چاپ نوع متغیر خطایابی‌شده و تولید صحیح اعلان‌های اصلاحی (fix\-it hints) برای آرگومان‌های بسته پارامتر (parameter\-pack) بهبود یافته است. .IP \(bu 2 بررسی portability\-template\-virtual\-member\-function \%<> بهبود یافته تا از موارد مثبت کاذب در توابع عضو مجازی محض (pure virtual) جلوگیری کند. .IP \(bu 2 بررسی readability\-container\-contains \%<> بهبود یافته تا از مقایسهٔ رشته با \fBnpos\fP پشتیبانی کند. تغییرات داخلی ممکن است باعث بروز مثبت کاذب‌های نادر جدیدی در کانتینرهای غیر استاندارد شود. .IP \(bu 2 بررسی readability\-container\-data\-pointer \%<> با اضافه کردن صحیح پرانتزها هنگامی که عبارت کانتینر عمل دی‌ریفرنس (dereference) است، بهبود یافته است. .IP \(bu 2 بررسی readability\-container\-size\-empty \%<> بهبود یافته تا هنگامی که متد size از \fBthis\fP ضمنی فراخوانی می‌شود، نکات اصلاحی را به‌درستی تولید کند؛ سازنده‌های پیش‌فرض با آرگومان‌های ارائه‌شده توسط کاربر را نادیده بگیرد؛ و قابلیت شناسایی را در متدهای کانتینر به‌جز \fBempty\fP اضافه کند. .IP \(bu 2 بررسی readability\-duplicate\-include \%<> با اضافه شدن گزینهٔ \fBIgnoredFilesList\fP (فهرستی از عبارت‌های منظم یا نام‌فایل‌ها که با نقطه‌ویرگول از هم جدا شده‌اند) برای مجاز کردن includeهای تکراریِ عمدی بهبود یافته است. .IP \(bu 2 بررسی readability\-identifier\-naming \%<> بهبود یافته است: .INDENT 2.0 .IP \(bu 2 اکنون اعلان‌ها و ماکروها را در هدرهای سیستمی نادیده می‌گیرد. .IP \(bu 2 مستندات برای تفکیک گزینه‌های عمومی از گزینه‌های خاص بهبود یافته است. .IP \(bu 2 گزینه‌هایی برای کنترل دقیق متغیرهای \fBconstexpr\fP اضافه شده‌اند. .IP \(bu 2 گزینه‌های پیش‌فرضی اضافه شده‌اند که با حذف نیاز به مشخص کردن جداگانهٔ هر نوع شناسه، پیکربندی‌ها را ساده می‌کنند. .UNINDENT .IP \(bu 2 بررسی readability\-implicit\-bool\-conversion \%<> بهبود یافته است: .INDENT 2.0 .IP \(bu 2 اکنون وقتی عبارات درونی چندین بار به‌طور ضمنی تبدیل می‌شوند، پرانتزها را به‌درستی اضافه می‌کند. .IP \(bu 2 این بررسی برای C99 و استانداردهای بعد از آن فعال شده است. .IP \(bu 2 اکنون تبدیل‌های ضمنی از \fBbool\fP به نوع صحیح را هنگام استفاده به‌عنوان عملوندهای عملگرهای منطقی (\fB&&\fP، \fB||\fP) در C مجاز می‌داند. .UNINDENT .IP \(bu 2 بررسی readability\-inconsistent\-declaration\-parameter\-name \%<> با عدم تحمیل یکسانی نام پارامتر بین یک بسته پارامتر متغیر (variadic parameter pack) در الگوی اصلی و پارامترهای مشخص در تخصیص‌های (specializations) آن بهبود یافته است. .IP \(bu 2 بررسی readability\-math\-missing\-parentheses \%<> با خطایابی و تشخیص صحیح اولویت عملگرها درون عبارات داخل پرانتز بهبود یافته است. .IP \(bu 2 بررسی readability\-qualified\-auto \%<> با افزودن گزینهٔ \fIIgnoreAliasing\fP بهبود یافته است، که امکان عدم بررسی انواع پایه‌ای نام‌های مستعار نوع (type aliases) را فراهم می‌کند. .IP \(bu 2 بررسی readability\-redundant\-casting \%<> با رفع موارد منفی کاذب در هنگام تبدیل صریح (explicit cast) از اشاره‌گر تابع بهبود یافته است. .IP \(bu 2 بررسی readability\-redundant\-control\-flow \%<> با رفع مشکلی که در آن بررسی گاهی پیشنهاد حذف نه تنها یک \fBreturn\fP یا \fBcontinue\fP اضافه، بلکه خطوط غیرمرتبطِ ماقبل آن را نیز می‌داد، بهبود یافته است. .IP \(bu 2 بررسی readability\-uppercase\-literal\-suffix \%<> برای شناسایی پسوندهای لیترال اضافه‌شده در C++23 و C23 بهبود یافته است. .IP \(bu 2 بررسی readability\-use\-concise\-preprocessor\-directives \%<> برای تولید اصلاحات مناسب برای حالت‌های بدون فاصله پس از دایرکتیو بهبود یافته است. .IP \(bu 2 بررسی readability\-use\-std\-min\-max \%<> با اطمینان از حفظ کامنت‌های بین شرط \fBif\fP و بلوک \fBthen\fP هنگام اعمال اصلاحات بهبود یافته است. .UNINDENT .SS بررسی‌های حذف‌شده .SS متفرقه .SS بهبودهای include\-fixer .sp بهبودها عبارتند از... .SS بهبودهای clang\-include\-fixer .sp بهبودها عبارتند از... .SS بهبودهای modularize .sp بهبودها عبارتند از... .SS بهبودهای pp\-trace .SS پلاگین Clang\-tidy برای Visual Studio .SH CLANG-TIDY .SS فهرست .INDENT 0.0 .IP \(bu 2 Clang\-Tidy .INDENT 2.0 .IP \(bu 2 استفاده از Clang\-Tidy .IP \(bu 2 اتوماسیون Clang\-Tidy .INDENT 2.0 .IP \(bu 2 اجرای موازی Clang\-Tidy .IP \(bu 2 اجرای Clang\-Tidy روی Diff .UNINDENT .IP \(bu 2 فرونشاندن عیب‌یابی‌های ناخواسته .UNINDENT .UNINDENT .sp همچنین ببینید: .SS بررسی‌های Clang\-Tidy .SS abseil\-cleanup\-ctad .sp پیشنهاد می‌دهد در C++17 و بالاتر، الگوی مقداردهی اولیه‌ی نمونه‌های \fBabsl::Cleanup\fP از تابع کارخانه‌ای (factory function) به استنتاج آرگومان الگوی کلاس (CTAD) تغییر یابد. .INDENT 0.0 .INDENT 3.5 .sp .EX auto c1 = absl::MakeCleanup([] {}); const auto c2 = absl::MakeCleanup(std::function([] {})); .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به .INDENT 0.0 .INDENT 3.5 .sp .EX absl::Cleanup c1 = [] {}; const absl::Cleanup c2 = std::function([] {}); .EE .UNINDENT .UNINDENT .SS abseil\-duration\-addition .sp مواردی را بررسی می‌کند که در آن‌ها جمع مقادیر باید در دامنهٔ \fBabsl::Time\fP انجام شود. هنگام جمع دو مقدار، در صورتی که مشخص باشد یکی از آن‌ها از نوع \fBabsl::Time\fP است، می‌توان نتیجه گرفت که مقدار دیگر باید به‌صورت یک \fBabsl::Duration\fP با مقیاس مشابه تفسیر شود، و این استنباط را صریح کرد. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX // Original \- Addition in the integer domain int x; absl::Time t; int result = absl::ToUnixSeconds(t) + x; // Suggestion \- Addition in the absl::Time domain int result = absl::ToUnixSeconds(t + absl::Seconds(x)); .EE .UNINDENT .UNINDENT .SS abseil\-duration\-comparison .sp مقایسه‌هایی را بررسی می‌کند که باید به‌جای دامنه‌های ممیز شناور (floating point) یا عدد صحیح (integer)، در دامنهٔ \fBabsl::Duration\fP انجام گیرند. .sp توجه: در مواردی که یک \fBDuration\fP ابتدا به عدد صحیح تبدیل شده و سپس با یک مقدار ممیز شناور مقایسه می‌شود، عمل قطع کردن اعشار (truncation) در حین تبدیل \fBDuration\fP ممکن است نتیجهٔ متفاوتی ایجاد کند. در عمل این حالت بسیار نادر است، و با این حال نشان‌دهندهٔ یک باگ است که باید برطرف شود. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX // Original \- Comparison in the floating point domain double x; absl::Duration d; if (x < absl::ToDoubleSeconds(d)) ... // Suggested \- Compare in the absl::Duration domain instead if (absl::Seconds(x) < d) ... // Original \- Comparison in the integer domain int x; absl::Duration d; if (x < absl::ToInt64Microseconds(d)) ... // Suggested \- Compare in the absl::Duration domain instead if (absl::Microseconds(x) < d) ... .EE .UNINDENT .UNINDENT .SS abseil\-duration\-conversion\-cast .sp تبدیل‌های نوع (cast) توابع تبدیل \fBabsl::Duration\fP را بررسی کرده و به‌جای آن‌ها تابع تبدیل مناسب را پیشنهاد می‌دهد. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX // Original \- Cast from a double to an integer absl::Duration d; int i = static_cast(absl::ToDoubleSeconds(d)); // Suggested \- Use the integer conversion function directly. int i = absl::ToInt64Seconds(d); // Original \- Cast from a double to an integer absl::Duration d; double x = static_cast(absl::ToInt64Seconds(d)); // Suggested \- Use the integer conversion function directly. double x = absl::ToDoubleSeconds(d); .EE .UNINDENT .UNINDENT .sp نکته: در مثال دوم، اصلاح پیشنهادی ممکن است نتیجهٔ متفاوتی در پی داشته باشد، زیرا تبدیل به عدد صحیح می‌تواند باعث قطع اعشار شود. در عمل، این حالت بسیار نادر است، و شما باید به‌جای آن از \fBabsl::Trunc\fP برای انجام صریح این عملیات استفاده کنید. .SS abseil\-duration\-division .sp عملیات ریاضی در \fBabsl::Duration\fP مانند اعداد صحیح عمل می‌کند. این بدان معناست که تقسیم دو شیء \fBabsl::Duration\fP یک \fBint64\fP برمی‌گرداند که هر بخش کسری آن به سمت ۰ قطع (truncate) می‌شود. برای اطلاعات بیشتر در مورد محاسبات ریاضی با \fBabsl::Duration\fP این پیوند را ببینید: \% .sp برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX absl::Duration d = absl::Seconds(3.5); int64 sec1 = d / absl::Seconds(1); // Truncates toward 0. int64 sec2 = absl::ToInt64Seconds(d); // Equivalent to division. assert(sec1 == 3 && sec2 == 3); double dsec = d / absl::Seconds(1); // WRONG: Still truncates toward 0. assert(dsec == 3.0); .EE .UNINDENT .UNINDENT .sp اگر نیاز به تقسیم ممیز شناور دارید، باید یا از تابع \fBabsl::FDivDuration()\fP استفاده کنید، یا یکی از توابع تبدیل واحد مانند \fBabsl::ToDoubleSeconds()\fP را به کار ببرید. برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX absl::Duration d = absl::Seconds(3.5); double dsec1 = absl::FDivDuration(d, absl::Seconds(1)); // GOOD: No truncation. double dsec2 = absl::ToDoubleSeconds(d); // GOOD: No truncation. assert(dsec1 == 3.5 && dsec2 == 3.5); .EE .UNINDENT .UNINDENT .sp این بررسی به دنبال مواردی از تقسیم \fBabsl::Duration\fP می‌گردد که در بستر ممیز شناور انجام می‌شوند، و استفاده از تابعی که مقدار ممیز شناور برمی‌گرداند را پیشنهاد می‌دهد. .SS abseil\-duration\-factory\-float .sp مواردی را بررسی می‌کند که در آن‌ها نسخه‌های بارگذاری‌مجددشدهٔ (overloaded) ممیز شناور توابع مختلف سازندهٔ \fBabsl::Duration\fP فراخوانی شده‌اند، در حالی که می‌شد به‌جای آن‌ها از نسخه‌های صحیح با کارایی بالاتر استفاده کرد. .sp این بررسی اصلاحاتی را برای مقادیر لیترال که شامل اجزای کسری اعشاری هستند یا عبارات غیرلیترال پیشنهاد نمی‌دهد. اما حذف تبدیل‌های نوع (cast) اضافی را پیشنهاد خواهد داد. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX // Original \- Providing a floating\-point literal. absl::Duration d = absl::Seconds(10.0); // Suggested \- Use an integer instead. absl::Duration d = absl::Seconds(10); // Original \- Explicitly casting to a floating\-point type. absl::Duration d = absl::Seconds(static_cast(10)); // Suggested \- Remove the explicit cast absl::Duration d = absl::Seconds(10); .EE .UNINDENT .UNINDENT .SS abseil\-duration\-factory\-scale .sp مواردی را بررسی می‌کند که در آن‌ها آرگومان‌های توابع کارخانه‌ای \fBabsl::Duration\fP در داخل مقیاس‌بندی شده‌اند و می‌توان آن‌ها را با تابع کارخانه‌ای متفاوتی جایگزین کرد. این بررسی همچنین به دنبال آرگومان‌هایی با مقدار صفر می‌گردد و استفاده از \fBabsl::ZeroDuration()\fP را به جای آن‌ها پیشنهاد می‌کند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX // Original \- Internal multiplication. int x; absl::Duration d = absl::Seconds(60 * x); // Suggested \- Use absl::Minutes instead. absl::Duration d = absl::Minutes(x); // Original \- Internal division. int y; absl::Duration d = absl::Milliseconds(y / 1000.); // Suggested \- Use absl:::Seconds instead. absl::Duration d = absl::Seconds(y); // Original \- Zero\-value argument. absl::Duration d = absl::Hours(0); // Suggested = Use absl::ZeroDuration instead absl::Duration d = absl::ZeroDuration(); .EE .UNINDENT .UNINDENT .SS abseil\-duration\-subtraction .sp مواردی را بررسی می‌کند که در آن‌ها عمل تفریق باید در دامنهٔ \fBabsl::Duration\fP انجام شود. هنگام تفریق دو مقدار، و زمانی که مشخص است مقدار اول حاصل یک تبدیل از \fBabsl::Duration\fP است، می‌توان نتیجه گرفت که مقدار دوم نیز باید به عنوان یک \fBabsl::Duration\fP تفسیر شود و این استنتاج را صریح کرد. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX // Original \- Subtraction in the double domain double x; absl::Duration d; double result = absl::ToDoubleSeconds(d) \- x; // Suggestion \- Subtraction in the absl::Duration domain instead double result = absl::ToDoubleSeconds(d \- absl::Seconds(x)); // Original \- Subtraction of two Durations in the double domain absl::Duration d1, d2; double result = absl::ToDoubleSeconds(d1) \- absl::ToDoubleSeconds(d2); // Suggestion \- Subtraction in the absl::Duration domain instead double result = absl::ToDoubleSeconds(d1 \- d2); .EE .UNINDENT .UNINDENT .sp نکته: همانند سایر بررسی‌های \fBclang\-tidy\fP، این احتمال وجود دارد که چند اصلاح با یکدیگر تداخل داشته باشند (مانند حالت عبارت‌های تو در تو)، بنابراین ممکن است تمام موارد در یک بار اجرا تبدیل نشوند. به‌طور خاص، این حالت ممکن است برای عبارت‌های تفریق تو در تو رخ دهد. اجرای چندبارهٔ \fBclang\-tidy\fP این تداخل‌ها را پیدا و برطرف خواهد کرد. .SS abseil\-duration\-unnecessary\-conversion .sp مواردی را پیدا و اصلاح می‌کند که در آن‌ها مقادیر \fBabsl::Duration\fP به انواع عددی و دوباره به حالت اولیه تبدیل می‌شوند. .sp مثال‌های ممیز شناور: .INDENT 0.0 .INDENT 3.5 .sp .EX // Original \- Conversion to double and back again absl::Duration d1; absl::Duration d2 = absl::Seconds(absl::ToDoubleSeconds(d1)); // Suggestion \- Remove unnecessary conversions absl::Duration d2 = d1; // Original \- Division to convert to double and back again absl::Duration d2 = absl::Seconds(absl::FDivDuration(d1, absl::Seconds(1))); // Suggestion \- Remove division and conversion absl::Duration d2 = d1; .EE .UNINDENT .UNINDENT .sp مثال‌های عدد صحیح: .INDENT 0.0 .INDENT 3.5 .sp .EX // Original \- Conversion to integer and back again absl::Duration d1; absl::Duration d2 = absl::Hours(absl::ToInt64Hours(d1)); // Suggestion \- Remove unnecessary conversions absl::Duration d2 = d1; // Original \- Integer division followed by conversion absl::Duration d2 = absl::Seconds(d1 / absl::Seconds(1)); // Suggestion \- Remove division and conversion absl::Duration d2 = d1; .EE .UNINDENT .UNINDENT .sp خارج کردن عملیات اسکالر از بسته‌بندی: .INDENT 0.0 .INDENT 3.5 .sp .EX // Original \- Multiplication by a scalar absl::Duration d1; absl::Duration d2 = absl::Seconds(absl::ToInt64Seconds(d1) * 2); // Suggestion \- Remove unnecessary conversion absl::Duration d2 = d1 * 2; .EE .UNINDENT .UNINDENT .sp نکته: تبدیل به یک عدد صحیح و سپس بازگرداندن آن به \fBabsl::Duration\fP، چنانچه مقدار با مقیاس تبدیل هم‌تراز نباشد ممکن است یک عملیات کوتاه کردن (حذف بخش کسری) باشد. در موارد نادری که این نتیجه مد نظر است، فراخوان‌ها باید از \fBabsl::Trunc\fP برای کوتاه کردن صریح استفاده کنند. .SS abseil\-faster\-strsplit\-delimiter .sp نمونه‌هایی از \fBabsl::StrSplit()\fP یا \fBabsl::MaxSplits()\fP را که در آن‌ها جداکننده یک لیترال رشته‌ای تک‌نویسه‌ای است پیدا کرده و با یک نویسه (کاراکتر) جایگزین می‌کند. این بررسی پیشنهادی برای تبدیل لیترال رشته‌ای به نویسه ارائه می‌دهد. همچنین کدهایی را که از \fBabsl::ByAnyChar()\fP فقط برای یک نویسهٔ واحد استفاده می‌کنند شناسایی کرده و آن‌ها را نیز به یک نویسهٔ منفرد تبدیل می‌کند. .sp این تغییرات نتیجهٔ یکسانی خواهند داشت، اما استفاده از نویسه‌ها به جای لیترال‌های رشته‌ای تک‌نویسه‌ای بهینه‌تر و خواناتر است. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX // Original \- the argument is a string literal. for (auto piece : absl::StrSplit(str, \(dqB\(dq)) { // Suggested \- the argument is a character, which causes the more efficient // overload of absl::StrSplit() to be used. for (auto piece : absl::StrSplit(str, \(aqB\(aq)) { // Original \- the argument is a string literal inside absl::ByAnyChar call. for (auto piece : absl::StrSplit(str, absl::ByAnyChar(\(dqB\(dq))) { // Suggested \- the argument is a character, which causes the more efficient // overload of absl::StrSplit() to be used and we do not need absl::ByAnyChar // anymore. for (auto piece : absl::StrSplit(str, \(aqB\(aq)) { // Original \- the argument is a string literal inside absl::MaxSplits call. for (auto piece : absl::StrSplit(str, absl::MaxSplits(\(dqB\(dq, 1))) { // Suggested \- the argument is a character, which causes the more efficient // overload of absl::StrSplit() to be used. for (auto piece : absl::StrSplit(str, absl::MaxSplits(\(aqB\(aq, 1))) { .EE .UNINDENT .UNINDENT .SS abseil\-no\-internal\-dependencies .sp اگر کدی که از Abseil استفاده می‌کند به جزئیات داخلی وابسته باشد، هشدار می‌دهد. اگر چیزی در یک فضای نام (namespace) قرار داشته باشد که شامل کلمه \(dqinternal\(dq است، کد مجاز نیست به آن وابسته باشد زیرا از جزئیات پیاده‌سازی محسوب می‌شود. نمی‌توان آن را دوست (friend) کرد، include کرد، به آن اشاره کرد یا به هر شکلی به آن ارجاع داد. انجام این کار راهنماهای سازگاری Abseil را نقض می‌کند و ممکن است منجر به شکست و خرابی کد شود. برای اطلاعات بیشتر به \% مراجعه کنید. .sp موارد زیر منجر به صدور هشدار خواهند شد: .INDENT 0.0 .INDENT 3.5 .sp .EX absl::strings_internal::foo(); // warning triggered on this line class foo { friend struct absl::container_internal::faa; // warning triggered on this line }; absl::memory_internal::MakeUniqueResult(); // warning triggered on this line .EE .UNINDENT .UNINDENT .SS abseil\-no\-namespace .sp اطمینان حاصل می‌کند که کد اقدام به باز کردن \fBnamespace absl\fP نکند، چرا که این کار راهنماهای سازگاری Abseil را نقض می‌کند. کد نباید \fBnamespace absl\fP را باز کند، زیرا این عمل با راهنماهای سازگاری Abseil در تعارض است و ممکن است به خرابی منجر شود. .sp هر کدی که از موارد زیر استفاده کند: .INDENT 0.0 .INDENT 3.5 .sp .EX namespace absl { ... } .EE .UNINDENT .UNINDENT .sp با یک هشدار مواجه خواهد شد. .sp برای اطلاعات بیشتر، راهنماهای کامل سازگاری Abseil را در \% ببینید. .SS abseil\-redundant\-strcat\-calls .sp حذف فراخوانی‌های غیرضروری به \fBabsl::StrCat\fP را هنگامی که نتیجه به یک فراخوانی دیگر به \fBabsl::StrCat\fP یا \fBabsl::StrAppend\fP فرستاده می‌شود، پیشنهاد می‌دهد. .sp فراخوانی‌های اضافه باعث ساخته‌شدن رشته‌های موقتِ غیرضروری می‌شوند. حذف آن‌ها کد را کوچک‌تر و سریع‌تر می‌کند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX std::string s = absl::StrCat(\(dqA\(dq, absl::StrCat(\(dqB\(dq, absl::StrCat(\(dqC\(dq, \(dqD\(dq))); //before std::string s = absl::StrCat(\(dqA\(dq, \(dqB\(dq, \(dqC\(dq, \(dqD\(dq); //after absl::StrAppend(&s, absl::StrCat(\(dqE\(dq, \(dqF\(dq, \(dqG\(dq)); //before absl::StrAppend(&s, \(dqE\(dq, \(dqF\(dq, \(dqG\(dq); //after .EE .UNINDENT .UNINDENT .SS abseil\-str\-cat\-append .sp استفاده از \fBabsl::StrCat()\fP را برای الحاق (append) به یک \fBstd::string\fP نشانه‌گذاری می‌کند. پیشنهاد می‌کند که به جای آن باید از \fBabsl::StrAppend()\fP استفاده شود. .sp فراخوانی‌های اضافی باعث ایجاد رشته‌های موقت غیرضروری می‌شوند. حذف آن‌ها کد را کوچک‌تر و سریع‌تر می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX a = absl::StrCat(a, b); // Use absl::StrAppend(&a, b) instead. .EE .UNINDENT .UNINDENT .sp مواردی را که در آن‌ها \fBabsl::StrCat()\fP به عنوان یک آرگومان قالب برای یک functor استفاده شده است، عیب‌یابی نمی‌کند. .SS abseil\-string\-find\-startswith .sp بررسی می‌کند که آیا نتیجهٔ \fBstd::string::find()\fP یا \fBstd::string::rfind()\fP (و متدهای متناظر در \fBstd::string_view\fP) با 0 مقایسه شده است یا خیر، و پیشنهاد می‌کند که با \fBabsl::StartsWith()\fP جایگزین شود. این موضوع هم از نظر خوانایی و هم از نظر عملکرد حائز اهمیت است. .sp تابع \fBstarts_with\fP به عنوان یک تابع توکار در C++20 به این نوع‌ها اضافه شد. در صورت در دسترس بودن، ترجیحاً فعال‌سازی modernize\-use\-starts\-ends\-with \%<> را به جای این بررسی مد نظر قرار دهید. .INDENT 0.0 .INDENT 3.5 .sp .EX string s = \(dq...\(dq; if (s.find(\(dqHello World\(dq) == 0) { /* do something */ } if (s.rfind(\(dqHello World\(dq, 0) == 0) { /* do something */ } .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به .INDENT 0.0 .INDENT 3.5 .sp .EX string s = \(dq...\(dq; if (absl::StartsWith(s, \(dqHello World\(dq)) { /* do something */ } if (absl::StartsWith(s, \(dqHello World\(dq)) { /* do something */ } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B StringLikeClasses فهرستی جدا شده با نقطه‌ویرگول از نام کلاس‌های شبه‌رشته (string-like). به صورت پیش‌فرض، هر دو \fBstd::basic_string\fP و \fBstd::basic_string_view\fP در نظر گرفته می‌شوند. فهرست متدهایی که در نظر گرفته می‌شوند ثابت است. .UNINDENT .INDENT 0.0 .TP .B IncludeStyle یک رشته که مشخص می‌کند کدام سبک include استفاده می‌شود: \fIllvm\fP یا \fIgoogle\fP\&. پیش‌فرض برابر \fIllvm\fP است. .UNINDENT .INDENT 0.0 .TP .B AbseilStringsMatchHeader مکان هدر \fBstrings/match.h\fP متعلق به Abseil. پیش‌فرض روی \fBabsl/strings/match.h\fP تنظیم شده است. .UNINDENT .SS abseil\-string\-find\-str\-contains .sp مقایسه‌های \fBs.find(...) == string::npos\fP را (برای انواع مختلف شبه‌رشته) پیدا کرده و پیشنهاد می‌دهد با \fBabsl::StrContains()\fP جایگزین شوند. .sp این کار خوانایی را بهبود می‌بخشد و احتمال ترکیب تصادفی \fBfind()\fP و \fBnpos\fP از انواع مختلف شبه‌رشته را کاهش می‌دهد. .sp به صورت پیش‌فرض، «انواع شبه‌رشته» شامل \fB::std::basic_string\fP، \fB::std::basic_string_view\fP، و \fB::absl::string_view\fP می‌شود. برای تغییر این مورد، گزینهٔ StringLikeClasses را ببینید. .INDENT 0.0 .INDENT 3.5 .sp .EX std::string s = \(dq...\(dq; if (s.find(\(dqHello World\(dq) == std::string::npos) { /* do something */ } absl::string_view a = \(dq...\(dq; if (absl::string_view::npos != a.find(\(dqHello World\(dq)) { /* do something */ } .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به .INDENT 0.0 .INDENT 3.5 .sp .EX std::string s = \(dq...\(dq; if (!absl::StrContains(s, \(dqHello World\(dq)) { /* do something */ } absl::string_view a = \(dq...\(dq; if (absl::StrContains(a, \(dqHello World\(dq)) { /* do something */ } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B StringLikeClasses فهرستی جداشده با نقطه\-ویرگول از نام‌های کلاس‌های شبه‌رشته (string\-like). به‌طور پیش‌فرض شامل \fB::std::basic_string\fP، \fB::std::basic_string_view\fP، و \fB::absl::string_view\fP است. .UNINDENT .INDENT 0.0 .TP .B IncludeStyle رشته‌ای که سبک include مورد استفاده را مشخص می‌کند، \fIllvm\fP یا \fIgoogle\fP\&. پیش‌فرض \fIllvm\fP است. .UNINDENT .INDENT 0.0 .TP .B AbseilStringsMatchHeader مکان پرونده سرآیند \fBstrings/match.h\fP متعلق به Abseil. مقدار پیش‌فرض \fBabsl/strings/match.h\fP است. .UNINDENT .SS abseil\-time\-comparison .sp مقایسه‌ها در دامنه \fBabsl::Time\fP را به مقایسه در دامنه اعداد صحیح (integer) ترجیح می‌دهد. .sp توجه: در مواردی که یک \fBabsl::Time\fP به عدد صحیح تبدیل می‌شود، ممکن است هم‌ترازی (alignment) رخ دهد. اگر مقایسه به این هم‌ترازی وابسته باشد، انجام مقایسه در دامنه \fBabsl::Time\fP ممکن است نتیجه متفاوتی به همراه داشته باشد. در عمل این وضعیت بسیار نادر است و با این حال نشان‌دهنده یک باگ است که باید رفع شود. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX // Original \- Comparison in the integer domain int x; absl::Time t; if (x < absl::ToUnixSeconds(t)) ... // Suggested \- Compare in the absl::Time domain instead if (absl::FromUnixSeconds(x) < t) ... .EE .UNINDENT .UNINDENT .SS abseil\-time\-subtraction .sp عبارت‌های تفریق \fBabsl::Time\fP را پیدا کرده و اصلاح می‌کند تا عمل تفریق به جای دامنه عددی، در دامنه زمان (Time) انجام شود. .sp دو حالت از تفریق زمانی وجود دارد که در آن‌ها اطلاعات نوع (type) اضافی استنتاج می‌شود: .INDENT 0.0 .IP \(bu 2 زمانی که نتیجه یک \fBabsl::Duration\fP باشد و آرگومان اول یک \fBabsl::Time\fP باشد. .IP \(bu 2 زمانی که آرگومان دوم یک \fBabsl::Time\fP باشد. .UNINDENT .sp در حالت اول، ما باید از نتیجه عملیات آگاه باشیم، چرا که بدون آن عملوند دوم می‌تواند یک \fBabsl::Time\fP یا یک \fBabsl::Duration\fP باشد. در حالت دوم، عملوند اول \fIباید\fP یک \fBabsl::Time\fP باشد، زیرا تفریق یک \fBabsl::Time\fP از یک \fBabsl::Duration\fP تعریف نشده است. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX int x; absl::Time t; // Original \- absl::Duration result and first operand is an absl::Time. absl::Duration d = absl::Seconds(absl::ToUnixSeconds(t) \- x); // Suggestion \- Perform subtraction in the Time domain instead. absl::Duration d = t \- absl::FromUnixSeconds(x); // Original \- Second operand is an absl::Time. int i = x \- absl::ToUnixSeconds(t); // Suggestion \- Perform subtraction in the Time domain instead. int i = absl::ToInt64Seconds(absl::FromUnixSeconds(x) \- t); .EE .UNINDENT .UNINDENT .SS abseil\-unchecked\-statusor\-access .sp این بررسی، دسترسی‌های ناامن به مقادیر موجود در اشیاء \fBabsl::StatusOr\fP را شناسایی می‌کند. در ادامه به این نوع با عنوان \fBStatusOr\fP اشاره خواهیم کرد. .sp دسترسی به مقدار یک \fBStatusOr\fP زمانی رخ می‌دهد که یکی از توابع عضو \fBvalue\fP، \fBoperator*\fP یا \fBoperator\->\fP آن فراخوانی شود. برای همسویی با باورهای نادرست رایج، این بررسی این توابع عضو را معادل هم در نظر می‌گیرد، اگرچه تفاوت‌های ظریفی در رابطه با استثناها (exceptions) در مقابل رفتار تعریف‌نشده (undefined behavior) وجود دارد. .sp دسترسی به مقدار یک \fBStatusOr\fP تنها در صورتی ایمن در نظر گرفته می‌شود که کد در حوزه محلی (مانند بدنه تابع) تضمین کند وضعیت \fBStatusOr\fP در تمام مسیرهای اجرایی ممکنی که می‌توانند به دسترسی برسند، ok است. این امر باید یا از طریق یک بررسی صریح، با استفاده از تابع عضو \fBStatusOr::ok\fP، یا با ساخت \fBStatusOr\fP به روشی که نشان دهد وضعیت آن بدون ابهام ok است (مثلاً با ارسال یک مقدار به سازنده آن) صورت گیرد. .sp در زیر چند نمونه از الگوهای دسترسی ایمن و ناامن به \fBStatusOr\fP آورده شده است. .sp نکته: اگر این بررسی در یک قطعه کد آن‌طور که انتظار داشتید رفتار نمی‌کند، لطفاً آن را در \% گزارش دهید. .SS منفی‌های کاذب (False negatives) .sp این بررسی عموماً منفی کاذب ایجاد \fBنمی‌کند\fP. این بدان معناست که اگر یک دسترسی به عنوان ناامن علامت‌گذاری نشود، از نظر منطقی قابل اثبات است که ایمن است. اگر نتواند ایمن بودن یک دسترسی را اثبات کند، آن را ناامن فرض می‌کند. در برخی موارد، تحلیل ایستای کد به دلایل گوناگون (مانند پایاها/invariants مدل‌سازی نشده از توابع فراخوانی‌شده) نمی‌تواند ایمن بودن یک دسترسی را با وجود ایمن بودن آن اثبات کند. در این موارد، تحلیل گزارش‌های مثبت کاذب (false positive) تولید می‌کند. .sp با این حال، برخی روش‌های مکاشفه‌ای (heuristics) استفاده می‌شوند که در موارد بسیار نادر ممکن است نادرست باشند: .INDENT 0.0 .IP \(bu 2 یک متد دسترسی‌دهنده const (بدون آرگومان) که هنگام چندین بار فراخوانی، مقادیر متفاوتی را برمی‌گرداند \%<#\:functionstability>\&. .UNINDENT .sp اگر فکر می‌کنید این بررسی یک منفی کاذب تولید کرده است، لطفاً آن را در \% گزارش دهید. .SS محدودیت‌های شناخته‌شده .sp این یک فهرست ناکامل از ساختارهایی است که در حال حاضر در این بررسی مدل‌سازی نشده‌اند و منجر به مثبت‌های کاذب (false positives) می‌شوند: .INDENT 0.0 .IP \(bu 2 بررسی یک StatusOr و سپس گرفتن آن در یک لامبدا \%<#\:lambdas> .IP \(bu 2 ایندکس کردن در یک ظرف (container) با همان ایندکس یکسان \%<#\:containers> .IP \(bu 2 توابع کمکی مختص پروژه \%<#\:uncommonapi>، .IP \(bu 2 توابعی با مقدار بازگشتی پایدار \%<#\:functionstability> .IP \(bu 2 \fBهرگونه\fP استدلال بین‌تابعی (cross\-function) \%<#\:crossfunction>\&. این مورد طبق طراحی قبلی است و در آینده تغییر نخواهد کرد. .UNINDENT .SS بررسی ok بودن وضعیت و سپس دسترسی به مقدار .sp این بررسی تمام روش‌های سرراست برای بررسی وضعیت و دسترسی به مقدار موجود در یک شیء \fBStatusOr\fP را تشخیص می‌دهد. برای نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(absl::StatusOr sor) { if (sor.ok()) { use(*sor); } } .EE .UNINDENT .UNINDENT .SS بررسی ok بودن وضعیت، سپس دسترسی به مقدار از یک کپی .sp معیاری که این بررسی به کار می‌برد معنایی (semantic) است، نه نحوی (syntactic). این ابزار متوجه می‌شود که چه زمانی یک رونوشت (کپی) از شیء \fBStatusOr\fP مورد دسترسی، دارای وضعیت ok شناخته شده است. برای نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(absl::StatusOr sor1) { if (sor1.ok()) { absl::optional sor2 = sor1; use(*sor2); } } .EE .UNINDENT .UNINDENT .SS اطمینان از ok بودن وضعیت با استفاده از ماکروهای متداول .sp این بررسی از ماکروهای متداول مانند \fBABSL_CHECK\fP و \fBASSERT_THAT\fP آگاه است\&. از آن‌ها می‌توان برای اطمینان از ok بودن وضعیت شیء \fBStatusOr\fP استفاده کرد. برای نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(absl::StatusOr sor) { ABSL_DCHECK_OK(sor); use(*sor); } .EE .UNINDENT .UNINDENT .SS اطمینان از ok بودن وضعیت، سپس دسترسی به مقدار در یک شاخه مرتبط .sp این بررسی از شاخه‌های همبسته و مرتبط در کد آگاه است و می‌تواند تشخیص دهد چه زمانی تضمین شده که یک شیء \fBStatusOr\fP در تمام مسیرهای اجرایی منتهی به دسترسی، دارای وضعیت ok است. برای نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(absl::StatusOr sor) { bool safe = false; if (sor.ok() && SomeOtherCondition()) { safe = true; } // ... more code... if (safe) { use(*sor); } } .EE .UNINDENT .UNINDENT .SS دسترسی به مقدار بدون بررسی وضعیت .sp این بررسی دسترسی‌هایی به مقدار را که به صورت محلی توسط بررسی وضعیت محافظت نشده‌اند پرچم‌گذاری می‌کند: .INDENT 0.0 .INDENT 3.5 .sp .EX void f1(absl::StatusOr sor) { use(*sor); // unsafe: it is unclear whether the status of \(gasor\(ga is ok. } void f2(absl::StatusOr sor) { use(sor\->member); // unsafe: it is unclear whether the status of \(gasor\(ga is ok. } void f3(absl::StatusOr sor) { use(sor.value()); // unsafe: it is unclear whether the status of \(gasor\(ga is ok. } .EE .UNINDENT .UNINDENT .sp از \fBABSL_CHECK_OK\fP استفاده کنید تا نشان دهید که آگاهانه می‌خواهید در مقادیر غیرِ OK برنامه دچار crash (فروپاشی) شود. .sp نکته: با این‌که استفاده از \fB\&.value()\fP روی یک \fBStatusOr\fP غیرِ \fBok()\fP طوری تعریف شده که کرش کند، اما این کار اغلب غیرعمدی است. به همین دلیل بررسی‌کننده ما این موارد را نیز پرچم‌گذاری می‌کند. .SS دسترسی به مقدار در شاخه اشتباه .sp این بررسی از حالت شیء \fBStatusOr\fP در شاخه‌های مختلف کد آگاه است. برای نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(absl::StatusOr sor) { if (sor.ok()) { } else { use(*sor); // unsafe: it is clear that the status of \(gasor\(ga is *not* ok. } } .EE .UNINDENT .UNINDENT .SS فرض بر پایدار بودن نتیجه تابع .sp این بررسی آگاه است که نتایج تابع ممکن است پایدار نباشند. یعنی فراخوانی‌های متوالی از یک تابع ممکن است مقادیر متفاوتی را بازگردانند. برای نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(Foo foo) { if (foo.sor().ok()) { use(*foo.sor()); // unsafe: it is unclear whether the status of \(gafoo.sor()\(ga is ok. } } .EE .UNINDENT .UNINDENT .sp در چنین مواردی بهتر است نتیجه فراخوانی تابع را در یک متغیر محلی ذخیره کرده و از آن برای دسترسی به مقدار استفاده کنید. برای نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(Foo foo) { if (const auto& foo_sor = foo.sor(); foo_sor.ok()) { use(*foo_sor); } } .EE .UNINDENT .UNINDENT .sp این بررسی \fBفرض می‌کند\fP که توابع دسترسی‌دهنده (accessor) با واجد شرایط \fBconst\fP، در صورتی که هیچ تابع غیرِ const دیگری بین دو فراخوانی اجرا نشده باشد، مقدار پایداری بازمی‌گردانند: .INDENT 0.0 .INDENT 3.5 .sp .EX class Foo { const absl::StatusOr& get() const { [...]; } } void f(Foo foo) { if (foo.get().ok()) { use(*foo.get()); } } .EE .UNINDENT .UNINDENT .sp اگر فراخوانی به یک تابع بدون مشخصه \fBconst\fP وجود داشته باشد، این بررسی فرض می‌کند که مقدار بازگشتی دسترسی‌دهنده تغییر یافته است. .INDENT 0.0 .INDENT 3.5 .sp .EX class Foo { const absl::StatusOr& get() const { [...]; } void mutate(); } void f(Foo foo) { if (foo.get().ok()) { foo.mutate(); use(*foo.get()); // unsafe: mutate might have changed the state of the object } } .EE .UNINDENT .UNINDENT .SS تکیه بر ناورداهای APIهای غیرمعمول .sp این بررسی از ناورداهای APIهای غیرمعمول آگاه نیست. به عنوان مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(Foo foo) { if (foo.HasProperty(\(dqbar\(dq)) { use(*foo.GetProperty(\(dqbar\(dq)); // unsafe: it is unclear whether the status of \(gafoo.GetProperty(\(dqbar\(dq)\(ga is ok. } } .EE .UNINDENT .UNINDENT .sp در چنین مواردی بهتر است به‌طور صریح بررسی شود که وضعیت شیء \fBStatusOr\fP مناسب (ok) است. به عنوان مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(Foo foo) { if (const auto& property = foo.GetProperty(\(dqbar\(dq); property.ok()) { use(*property); } } .EE .UNINDENT .UNINDENT .SS بررسی مناسب بودن وضعیت و سپس ارسال \fBStatusOr\fP به تابعی دیگر .sp این بررسی بر استدلال محلی متکی است. عمل بررسی و دسترسی به مقدار، هر دو باید در یک تابع رخ دهند. یک دسترسی حتی در صورتی که فراخوانندهٔ تابعِ دسترسی‌گیرنده اطمینان دهد وضعیت \fBStatusOr\fP مناسب (ok) است، باز هم ناامن تلقی می‌شود. به عنوان مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void g(absl::StatusOr sor) { use(*sor); // unsafe: it is unclear whether the status of \(gasor\(ga is ok. } void f(absl::StatusOr sor) { if (sor.ok()) { g(sor); } } .EE .UNINDENT .UNINDENT .sp در چنین مواردی بهتر است هنگام فراخوانی تابع یا مقدار را مستقیماً ارسال کنید، یا این‌که مناسب بودن وضعیت \fBStatusOr\fP را درون دامنهٔ محلی تابع فراخوانی‌شده بررسی نمایید. به عنوان مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void g(int val) { use(val); } void f(absl::StatusOr sor) { if (sor.ok()) { g(*sor); } } .EE .UNINDENT .UNINDENT .SS نام‌های مستعار ایجاد شده از طریق اعلان‌های \fBusing\fP .sp این بررسی از نام‌های مستعار انواع \fBStatusOr\fP که از طریق اعلان‌های \fBusing\fP ایجاد می‌شوند آگاه است. به عنوان مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX using StatusOrInt = absl::StatusOr; void f(StatusOrInt sor) { use(*sor); // unsafe: it is unclear whether the status of \(gasor\(ga is ok. } .EE .UNINDENT .UNINDENT .SS کانتینرها .sp این بررسی در مورد کانتینرهای مقادیر \fBStatusOr\fP بیش از حد سخت‌گیر است. صرفاً بررسی مناسب بودن وضعیت یکی از عناصر کانتینر برای امن تلقی شدن دسترسی به آن کافی نیست. به عنوان مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(std::vector> sors) { if (sors[0].ok()) { use(*sors[0]); // unsafe: it is unclear whether the status of \(gasors[0]\(ga is ok. } } .EE .UNINDENT .UNINDENT .sp باید یک ارجاع به آن شیء خاص دریافت کرده و به جای آن استفاده کنید: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(std::vector> sors) { absl::StatusOr& sor0 = sors[0]; if (sor0.ok()) { use(*sor0); } } .EE .UNINDENT .UNINDENT .sp نسخه‌های بعدی می‌توانند درک الگوهای امن‌تر استفاده که شامل کانتینرها هستند را بهبود بخشند. .SS لانمبداها .sp این بررسی قادر به گزارش دسترسی‌های ناامن \fBStatusOr\fP در لانمبداها هست، اما آن‌قدر هوشمند نیست که اطلاعات را از زمینهٔ بیرونی به درون لانمبدا منتقل کند. این بدان معناست که الگوی زیر به عنوان یک دسترسی ناامن گزارش خواهد شد: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(absl::StatusOr sor) { if (sor.ok()) { [&sor]() { use(*sor); // unsafe: it is unclear whether the status of \(gasor\(ga is ok. } } } .EE .UNINDENT .UNINDENT .sp برای جلوگیری از این مشکل، باید یک ارجاع به شیء موجود درون آن دریافت کنید و به جای آن، آن ارجاع را ضبط (capture) نمایید: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(absl::StatusOr sor) { if (sor.ok()) { auto& s = *sor; [&s]() { use(s); } } } .EE .UNINDENT .UNINDENT .sp همچنین می‌توانید بررسی را درون لانمبدا، جایی که به مقدار دسترسی پیدا می‌شود، اضافه کنید: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(absl::StatusOr sor) { [&sor]() { if (sor.ok()) { use(*sor); } } } .EE .UNINDENT .UNINDENT .SS abseil\-upgrade\-duration\-conversions .sp فراخوانی‌های عملگرهای محاسباتی و توابع سازنده (factory) مربوط به \fBabsl::Duration\fP را که آرگومان آن‌ها برای ادامه‌ی کامپایل پس از تغییرات آتی API نیاز به تبدیل صریح (explicit cast) دارد، پیدا می‌کند. .sp عملگرهای \fB*=\fP، \fB/=\fP، \fB*\fP و \fB/\fP برای \fBabsl::Duration\fP در حال حاضر آرگومانی از نوع کلاس را که به یک نوع محاسباتی قابل تبدیل باشد می‌پذیرند. چنین فراخوانی در حال حاضر مقدار را به یک \fBint64_t\fP تبدیل می‌کند، حتی در مواردی مانند \fBstd::atomic\fP که منجر به تبدیل همراه با اتلاف داده (lossy conversion) می‌شود. .sp علاوه بر این، توابع سازنده \fBabsl::Duration\fP (مانند \fBabsl::Hours\fP، \fBabsl::Minutes\fP و غیره) در حال حاضر یک \fBint64_t\fP یا یک نوع ممیز شناور را می‌پذیرند. مشابه عملگرهای محاسباتی، فراخوانی‌ها با آرگومانی از نوع کلاس که قابل تبدیل به یک نوع محاسباتی باشد از مسیر \fBint64_t\fP عبور می‌کنند. .sp این عملگرها و توابع سازنده برای جلوگیری از رفتارهای ناخواسته تغییر خواهند کرد تا فقط انواع محاسباتی را بپذیرند. پس از انتشار این تغییرات، ارسال آرگومانی از نوع کلاس دیگر کامپایل نخواهد شد، حتی اگر آن نوع به صورت ضمنی به یک نوع محاسباتی قابل تبدیل باشد. .sp در اینجا نمونه‌هایی از اصلاحات ایجاد شده توسط این بررسی آورده شده است: .INDENT 0.0 .INDENT 3.5 .sp .EX std::atomic a; absl::Duration d = absl::Milliseconds(a); d *= a; .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX std::atomic a; absl::Duration d = absl::Milliseconds(static_cast(a)); d *= static_cast(a); .EE .UNINDENT .UNINDENT .sp توجه داشته باشید که این بررسی برای حفظ رفتار فعلی کد کاربر، همیشه یک تبدیل نوع به \fBint64_t\fP اضافه می‌کند. این احتمال وجود دارد که این کار رفتارهای ناخواسته‌ای را به دلیل انواعِ به طور ضمنی قابل تبدیل به نوع ممیز شناور، آشکار کند. .SS altera\-id\-dependent\-backward\-branch .sp متغیرها و فیلدهای وابسته به شناسه (ID-dependent) را که درون حلقه‌ها استفاده می‌شوند، پیدا می‌کند. این امر باعث ایجاد انشعاب در داخل حلقه‌ها شده و در نتیجه منجر به افت کارایی می‌شود. .INDENT 0.0 .INDENT 3.5 .sp .EX // The following code will produce a warning because this ID\-dependent // variable is used in a loop condition statement. int ThreadID = get_local_id(0); // The following loop will produce a warning because the loop condition // statement depends on an ID\-dependent variable. for (int i = 0; i < ThreadID; ++i) { std::cout << i << std::endl; } // The following loop will not produce a warning, because the ID\-dependent // variable is not used in the loop condition statement. for (int i = 0; i < 100; ++i) { std::cout << ThreadID << std::endl; } .EE .UNINDENT .UNINDENT .sp بر اساس Altera SDK for OpenCL: Best Practices Guide \%\&. .SS altera\-kernel\-name\-restriction .sp فایل‌های کرنل و دستورات include را که نام فایل آن‌ها \fIkernel.cl\fP، \fIVerilog.cl\fP یا \fIVHDL.cl\fP است پیدا می‌کند. این بررسی به بزرگی و کوچکی حروف حساس نیست. .sp چنین نام‌هایی برای فایل‌های کرنل باعث می‌شوند کامپایلر آفلاین فایل‌های طراحی واسطی تولید کند که همنام برخی از فایل‌های داخلی هستند، که این امر منجر به خطای کامپایل می‌شود. .sp بر اساس بخش \fIGuidelines for Naming the Kernel\fP در Intel FPGA SDK for OpenCL Pro Edition: Programming Guide \%\&. .SS altera\-single\-work\-item\-barrier .sp توابع کرنل OpenCL را که یک تابع سد محافظ (barrier) را فراخوانی می‌کنند اما هیچ تابع شناسه‌ای (\fBget_local_id\fP، \fBget_local_id\fP، \fBget_group_id\fP یا \fBget_local_linear_id\fP) را فراخوانی نمی‌کنند، پیدا می‌کند. .sp این کرنل‌ها ممکن است کرنل‌های تک work\-item قابل اجرایی باشند، اما در صورت استفاده از نسخه‌های جدیدتر Altera Offline Compiler (نسخه 17.01 یا بالاتر) مجبور به اجرا به صورت کرنل‌های NDRange خواهند شد. .sp در صورت استفاده از نسخه قدیمی‌تر Altera Offline Compiler، این توابع کرنل به عنوان کرنل‌های تک work\-item در نظر گرفته می‌شوند، که اگر معناشناسی NDRange مد نظر بوده باشد، می‌تواند ناکارآمد بوده یا منجر به خطا شود. .sp بر اساس Altera SDK for OpenCL: Best Practices Guide \%\&. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX // error: function calls barrier but does not call an ID function. void __kernel barrier_no_id(__global int * foo, int size) { for (int i = 0; i < 100; i++) { foo[i] += 5; } barrier(CLK_GLOBAL_MEM_FENCE); } // ok: function calls barrier and an ID function. void __kernel barrier_with_id(__global int * foo, int size) { for (int i = 0; i < 100; i++) { int tid = get_global_id(0); foo[tid] += 5; } barrier(CLK_GLOBAL_MEM_FENCE); } // ok with AOC Version 17.01: the reqd_work_group_size turns this into // an NDRange. __attribute__((reqd_work_group_size(2,2,2))) void __kernel barrier_with_id(__global int * foo, int size) { for (int i = 0; i < 100; i++) { foo[tid] += 5; } barrier(CLK_GLOBAL_MEM_FENCE); } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B AOCVersion نسخه Altera Offline Compiler را مشخص می‌کند. مقدار پیش‌فرض \fB1600\fP است (متناظر با نسخه 16.00). .UNINDENT .SS altera\-struct\-pack\-align .sp ساختارهایی (structs) را که به شکلی ناکارآمد بسته‌بندی (pack) یا تراز (align) شده‌اند پیدا کرده و در صورت نیاز، بسته‌بندی و/یا تراز کردن آن‌ها را توصیه می‌کند. .sp ساختارهایی که بسته‌بندی نشده‌اند فضای بیشتری نسبت به آنچه نیاز دارند اشغال می‌کنند، و دسترسی به ساختارهایی که به خوبی تراز نشده‌اند ناکارآمد است. .sp راهکارهای اصلاحی (Fix-its) برای رفع هر دوی این مشکلات از طریق درج و/یا اصلاح ویژگی‌های (attributes) مرتبط در ساختار ارائه شده است. .sp بر اساس Altera SDK for OpenCL: Best Practices Guide \%\&. .INDENT 0.0 .INDENT 3.5 .sp .EX // The following struct is originally aligned to 4 bytes, and thus takes up // 12 bytes of memory instead of 10. Packing the struct will make it use // only 10 bytes of memory, and aligning it to 16 bytes will make it // efficient to access. struct example { char a; // 1 byte double b; // 8 bytes char c; // 1 byte }; // The following struct is arranged in such a way that packing is not needed. // However, it is aligned to 4 bytes instead of 8, and thus needs to be // explicitly aligned. struct implicitly_packed_example { char a; // 1 byte char b; // 1 byte char c; // 1 byte char d; // 1 byte int e; // 4 bytes }; // The following struct is explicitly aligned and packed. struct good_example { char a; // 1 byte double b; // 8 bytes char c; // 1 byte } __attribute__((packed)) __attribute__((aligned(16)); // Explicitly aligning a struct to the wrong value will result in a warning. // The following example should be aligned to 16 bytes, not 32. struct badly_aligned_example { char a; // 1 byte double b; // 8 bytes char c; // 1 byte } __attribute__((packed)) __attribute__((aligned(32))); .EE .UNINDENT .UNINDENT .SS altera\-unroll\-loops .sp حلقه‌های داخلی را که باز (unroll) نشده‌اند، و همچنین حلقه‌هایی که به طور کامل باز شده‌اند اما کران‌های نامشخص یا تعداد تکرار بالایی دارند را پیدا می‌کند. .sp باز کردن حلقه‌های داخلی می‌تواند کارایی هسته‌های (kernels) OpenCL را بهبود بخشد. با این حال، اگر آن‌ها دارای کران‌های حلقهٔ نامشخص یا تعداد تکرار بالایی باشند، نمی‌توان آن‌ها را به طور کامل باز کرد و باید به صورت جزئی باز شوند. .sp نکات: .INDENT 0.0 .IP \(bu 2 این بررسی قادر به تعیین تعداد تکرارها در حلقه‌های \fBwhile\fP یا \fBdo..while\fP نیست؛ بنابراین اگر چنین حلقه‌ای به طور کامل باز شود، یادداشتی صادر می‌شود که به کاربر توصیه می‌کند به جای آن از باز کردن جزئی استفاده کند. .IP \(bu 2 در حلقه‌های \fBfor\fP، بررسی ما تنها با گام‌های محاسباتی ساده کار می‌کند (\fB+\fP، \fB\-\fP، \fB*\fP، \fB/\fP). برای تمام گام‌های دیگر، باز کردن جزئی توصیه می‌شود. .IP \(bu 2 بسته به شرط خروج، محاسبات مربوط به تعیین بزرگ بودن تعداد تکرارها ممکن است ۱ مقدار خطا داشته باشد. این نباید مشکلی ایجاد کند چرا که حد آستانه به طور کلی دلخواه است. .UNINDENT .sp بر اساس راهنمای Altera SDK for OpenCL: Best Practices Guide \%\&. .INDENT 0.0 .INDENT 3.5 .sp .EX for (int i = 0; i < 10; i++) { // ok: outer loops should not be unrolled int j = 0; do { // warning: this inner do..while loop should be unrolled j++; } while (j < 15); int k = 0; #pragma unroll while (k < 20) { // ok: this inner loop is already unrolled k++; } } int A[1000]; #pragma unroll // warning: this loop is large and should be partially unrolled for (int a : A) { printf(\(dq%d\(dq, a); } #pragma unroll 5 // ok: this loop is large, but is partially unrolled for (int a : A) { printf(\(dq%d\(dq, a); } #pragma unroll // warning: this loop is large and should be partially unrolled for (int i = 0; i < 1000; ++i) { printf(\(dq%d\(dq, i); } #pragma unroll 5 // ok: this loop is large, but is partially unrolled for (int i = 0; i < 1000; ++i) { printf(\(dq%d\(dq, i); } #pragma unroll // warning: << operator not supported, recommend partial unrolling for (int i = 0; i < 1000; i<<1) { printf(\(dq%d\(dq, i); } std::vector someVector (100, 0); int i = 0; #pragma unroll // note: loop may be large, recommend partial unrolling while (i < someVector.size()) { someVector[i]++; } #pragma unroll // note: loop may be large, recommend partial unrolling while (true) { printf(\(dqIn loop\(dq); } #pragma unroll 5 // ok: loop may be large, but is partially unrolled while (i < someVector.size()) { someVector[i]++; } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B MaxLoopIterations حداکثر تعداد تکرار حلقه‌ای را مشخص می‌کند که یک حلقه با باز شدن کامل می‌تواند داشته باشد. به‌طور پیش‌فرض روی \fI100\fP تنظیم شده است. .sp در عمل، این به مقدار صحیح کران بالا در عبارت شرطی دستور حلقه اشاره دارد. .UNINDENT .SS android\-cloexec\-accept .sp استفاده از \fBaccept()\fP توصیه نمی‌شود، بهتر است از \fBaccept4()\fP استفاده شود. بدون این پرچم، یک توصیف‌کننده فایل (file descriptor) حساس باز شده در حین یک فراخوانی fork+exec به یک دامنه با دسترسی کمتر در SELinux، همچنان باز خواهد ماند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX accept(sockfd, addr, addrlen); // becomes accept4(sockfd, addr, addrlen, SOCK_CLOEXEC); .EE .UNINDENT .UNINDENT .SS android\-cloexec\-accept4 .sp تابع \fBaccept4()\fP باید \fBSOCK_CLOEXEC\fP را در آرگومان type خود بگنجاند تا از نشت توصیف‌کننده فایل جلوگیری شود. بدون این پرچم، یک فایل حساس باز شده در طول فراخوانی fork+exec به یک دامنه با دسترسی کمتر در SELinux باز خواهد ماند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX accept4(sockfd, addr, addrlen, SOCK_NONBLOCK); // becomes accept4(sockfd, addr, addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC); .EE .UNINDENT .UNINDENT .SS android\-cloexec\-creat .sp استفاده از \fBcreat()\fP توصیه نمی‌شود، بهتر است از \fBopen()\fP استفاده شود. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX int fd = creat(path, mode); // becomes int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode); .EE .UNINDENT .UNINDENT .SS android\-cloexec\-dup .sp استفاده از \fBdup()\fP توصیه نمی‌شود؛ بهتر است از \fBfcntl()\fP استفاده شود که می‌تواند فلگ close\-on\-exec را تنظیم کند. در غیر این صورت، یک فایل حساسِ بازشده در طول یک فراخوانی fork+exec به یک دامنهٔ SELinux با سطح دسترسی پایین‌تر، همچنان باز باقی خواهد ماند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX int fd = dup(oldfd); // becomes int fd = fcntl(oldfd, F_DUPFD_CLOEXEC); .EE .UNINDENT .UNINDENT .SS android\-cloexec\-epoll\-create .sp استفاده از \fBepoll_create()\fP توصیه نمی‌شود؛ بهتر است از \fBepoll_create1()\fP استفاده شود که اجازهٔ close\-on\-exec را می‌دهد. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX epoll_create(size); // becomes epoll_create1(EPOLL_CLOEXEC); .EE .UNINDENT .UNINDENT .SS android\-cloexec\-epoll\-create1 .sp تابع \fBepoll_create1()\fP باید شامل \fBEPOLL_CLOEXEC\fP در آرگومان type خود باشد تا از نشت توصیف‌گر فایل (file descriptor) جلوگیری شود. بدون این فلگ، یک فایل حساس بازشده در طول فراخوانی fork+exec به یک دامنهٔ SELinux با دسترسی کمتر باز باقی خواهد ماند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX epoll_create1(0); // becomes epoll_create1(EPOLL_CLOEXEC); .EE .UNINDENT .UNINDENT .SS android\-cloexec\-fopen .sp تابع \fBfopen()\fP باید شامل \fBe\fP در رشتهٔ mode خود باشد؛ بنابراین \fBre\fP معتبر خواهد بود. این کار معادل تنظیم فلگ \fBFD_CLOEXEC\fP روی آن توصیف‌گر است. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX fopen(\(dqfn\(dq, \(dqr\(dq); // becomes fopen(\(dqfn\(dq, \(dqre\(dq); .EE .UNINDENT .UNINDENT .SS android\-cloexec\-inotify\-init .sp استفاده از \fBinotify_init()\fP توصیه نمی‌شود؛ بهتر است از \fBinotify_init1()\fP استفاده شود. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX inotify_init(); // becomes inotify_init1(IN_CLOEXEC); .EE .UNINDENT .UNINDENT .SS android\-cloexec\-inotify\-init1 .sp تابع \fBinotify_init1()\fP باید شامل \fBIN_CLOEXEC\fP در آرگومان type خود باشد تا از نشت توصیف‌گر فایل جلوگیری شود. بدون این فلگ، یک فایل حساس بازشده در طول یک فراخوانی fork+exec به یک دامنهٔ SELinux با سطح دسترسی پایین‌تر، باز باقی می‌ماند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX inotify_init1(IN_NONBLOCK); // becomes inotify_init1(IN_NONBLOCK | IN_CLOEXEC); .EE .UNINDENT .UNINDENT .SS android\-cloexec\-memfd\-create .sp تابع \fBmemfd_create()\fP باید شامل \fBMFD_CLOEXEC\fP در آرگومان type خود باشد تا از نشت توصیف‌گر فایل جلوگیری شود. بدون این فلگ، یک فایل حساس بازشده در طول یک فراخوانی fork+exec به یک دامنهٔ SELinux با سطح دسترسی پایین‌تر باز خواهد ماند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX memfd_create(name, MFD_ALLOW_SEALING); // becomes memfd_create(name, MFD_ALLOW_SEALING | MFD_CLOEXEC); .EE .UNINDENT .UNINDENT .SS android\-cloexec\-open .sp یک منبع متداول از باگ‌های امنیتی، کدی است که فایلی را بدون استفاده از فلگ \fBO_CLOEXEC\fP باز می‌کند. بدون آن فلگ، یک فایل حساسِ بازشده در طول یک فراخوانی fork+exec به یک دامنهٔ SELinux با سطح دسترسی پایین‌تر همچنان باز مانده و آن داده‌های حساس را افشا می‌کند. توابع هم‌خانوادهٔ باز کردن فایل شامل \fBopen()\fP، \fBopenat()\fP و \fBopen64()\fP باید شامل \fBO_CLOEXEC\fP در آرگومان flags خود باشند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX open(\(dqfilename\(dq, O_RDWR); open64(\(dqfilename\(dq, O_RDWR); openat(0, \(dqfilename\(dq, O_RDWR); // becomes open(\(dqfilename\(dq, O_RDWR | O_CLOEXEC); open64(\(dqfilename\(dq, O_RDWR | O_CLOEXEC); openat(0, \(dqfilename\(dq, O_RDWR | O_CLOEXEC); .EE .UNINDENT .UNINDENT .SS android\-cloexec\-pipe .sp این بررسی استفاده از \fBpipe()\fP را تشخیص می‌دهد. استفاده از \fBpipe()\fP توصیه نمی‌شود، جایگزین پیشنهادی \fBpipe2()\fP است. این بررسی همچنین فلگ \fBO_CLOEXEC\fP را اضافه می‌کند که توصیف‌کننده فایل (file descriptor) را برای بسته شدن در فرآیندهای فرزند علامت‌گذاری می‌کند. بدون این فلگ، یک توصیف‌کننده فایل حساس ممکن است به یک فرآیند فرزند نشت کند، به‌ویژه به یک دامنه SELinux با سطح دسترسی پایین‌تر. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX pipe(pipefd); .EE .UNINDENT .UNINDENT .sp جایگزین پیشنهادی: .INDENT 0.0 .INDENT 3.5 .sp .EX pipe2(pipefd, O_CLOEXEC); .EE .UNINDENT .UNINDENT .SS android\-cloexec\-pipe2 .sp این بررسی اطمینان حاصل می‌کند که \fBpipe2()\fP با فلگ \fBO_CLOEXEC\fP فراخوانی شود. این بررسی همچنین فلگ \fBO_CLOEXEC\fP را اضافه می‌کند که توصیف‌کننده فایل را برای بسته شدن در فرآیندهای فرزند علامت‌گذاری می‌نماید. بدون این فلگ، یک توصیف‌کننده فایل حساس ممکن است به یک فرآیند فرزند نشت کند، به‌ویژه به یک دامنه SELinux با سطح دسترسی پایین‌تر. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX pipe2(pipefd, O_NONBLOCK); .EE .UNINDENT .UNINDENT .sp جایگزین پیشنهادی: .INDENT 0.0 .INDENT 3.5 .sp .EX pipe2(pipefd, O_NONBLOCK | O_CLOEXEC); .EE .UNINDENT .UNINDENT .SS android\-cloexec\-socket .sp تابع \fBsocket()\fP باید شامل \fBSOCK_CLOEXEC\fP در آرگومان type خود باشد تا از نشت توصیف‌کننده فایل جلوگیری شود. بدون این فلگ، یک فایل حساس باز شده در حین fork+exec به یک دامنه SELinux با دسترسی کمتر، باز باقی می‌ماند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX socket(domain, type, SOCK_STREAM); // becomes socket(domain, type, SOCK_STREAM | SOCK_CLOEXEC); .EE .UNINDENT .UNINDENT .SS android\-comparison\-in\-temp\-failure\-retry .sp مقایسه‌هایی را که به نظر می‌رسد به اشتباه در آرگومان ماکروی \fBTEMP_FAILURE_RETRY\fP قرار گرفته‌اند عیب‌یابی می‌کند. چنین استفاده‌ای در اکثریت قریب به اتفاق موارد نادرست است و اغلب بدون هیچ هشداری هدف ماکروی \fBTEMP_FAILURE_RETRY\fP را بی‌اثر می‌کند. .sp جهت اطلاع، ماکروی \fBTEMP_FAILURE_RETRY\fP یک ماکروی کمکی \% است که توسط هر دو کتابخانه glibc و Bionic ارائه می‌شود. هدف آن اجرای مکرر یک فراخوانی سیستمی (syscall) است تا زمانی که با موفقیت انجام شود، یا به دلایلی غیر از وقفه‌خوردن (interrupted) شکست بخورد. .sp نمونه استفاده دارای باگ بدین صورت است: .INDENT 0.0 .INDENT 3.5 .sp .EX char cs[1]; while (TEMP_FAILURE_RETRY(read(STDIN_FILENO, cs, sizeof(cs)) != 0)) { // Do something with cs. } .EE .UNINDENT .UNINDENT .sp چرا که \fBTEMP_FAILURE_RETRY\fP بررسی خواهد کرد که آیا نتیجه \fIحاصل از مقایسه\fP برابر با \fB\-1\fP است یا خیر، و در این صورت مجدداً تلاش می‌کند. .sp اگر با این مورد مواجه شدید، رفع آن ساده است: مقایسه را از داخل آرگومان \fBTEMP_FAILURE_RETRY\fP بیرون بکشید، به این صورت: .INDENT 0.0 .INDENT 3.5 .sp .EX char cs[1]; while (TEMP_FAILURE_RETRY(read(STDIN_FILENO, cs, sizeof(cs))) != 0) { // Do something with cs. } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B RetryMacros فهرستی جداشده با کاما از نام‌های ماکروهای تلاش مجدد (retry) جهت بررسی. پیش‌فرض \fITEMP_FAILURE_RETRY\fP است. .UNINDENT .SS boost\-use\-ranges .sp فراخوانی‌های الگوریتم‌های مبتنی بر تکرارکننده (iterator) کتابخانه استاندارد را که می‌توانند با نسخه دامنه‌های Boost (Boost ranges) جایگزین شوند، شناسایی می‌کند. .SS مثال .INDENT 0.0 .INDENT 3.5 .sp .EX auto Iter1 = std::find(Items.begin(), Items.end(), 0); auto AreSame = std::equal(Items1.cbegin(), Items1.cend(), std::begin(Items2), std::end(Items2)); .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX auto Iter1 = boost::range::find(Items, 0); auto AreSame = boost::range::equal(Items1, Items2); .EE .UNINDENT .UNINDENT .SS الگوریتم‌های پشتیبانی‌شده .sp فراخوانی الگوریتم‌های زیر از کتابخانه std بررسی می‌شوند: .sp \fBstd::accumulate\fP, \fBstd::adjacent_difference\fP, \fBstd::adjacent_find\fP, \fBstd::all_of\fP, \fBstd::any_of\fP, \fBstd::binary_search\fP, \fBstd::copy_backward\fP, \fBstd::copy_if\fP, \fBstd::copy\fP, \fBstd::count_if\fP, \fBstd::count\fP, \fBstd::equal_range\fP, \fBstd::equal\fP, \fBstd::fill\fP, \fBstd::find_end\fP, \fBstd::find_first_of\fP, \fBstd::find_if_not\fP, \fBstd::find_if\fP, \fBstd::find\fP, \fBstd::for_each\fP, \fBstd::generate\fP, \fBstd::includes\fP, \fBstd::iota\fP, \fBstd::is_partitioned\fP, \fBstd::is_permutation\fP, \fBstd::is_sorted_until\fP, \fBstd::is_sorted\fP, \fBstd::lexicographical_compare\fP, \fBstd::lower_bound\fP, \fBstd::make_heap\fP, \fBstd::max_element\fP, \fBstd::merge\fP, \fBstd::min_element\fP, \fBstd::mismatch\fP, \fBstd::next_permutation\fP, \fBstd::none_of\fP, \fBstd::partial_sum\fP, \fBstd::partial_sort_copy\fP, \fBstd::partition_copy\fP, \fBstd::partition_point\fP, \fBstd::partition\fP, \fBstd::pop_heap\fP, \fBstd::prev_permutation\fP, \fBstd::push_heap\fP, \fBstd::random_shuffle\fP, \fBstd::reduce\fP, \fBstd::remove_copy_if\fP, \fBstd::remove_copy\fP, \fBstd::remove_if\fP, \fBstd::remove\fP, \fBstd::replace_copy_if\fP, \fBstd::replace_copy\fP, \fBstd::replace_if\fP, \fBstd::replace\fP, \fBstd::reverse_copy\fP, \fBstd::reverse\fP, \fBstd::search\fP, \fBstd::set_difference\fP, \fBstd::set_intersection\fP, \fBstd::set_symmetric_difference\fP, \fBstd::set_union\fP, \fBstd::sort_heap\fP, \fBstd::sort\fP, \fBstd::stable_partition\fP, \fBstd::stable_sort\fP, \fBstd::transform\fP, \fBstd::unique_copy\fP, \fBstd::unique\fP, \fBstd::upper_bound\fP\&. .sp این بررسی همچنین توابع زیر را از فضای نام (namespace) \fBboost::algorithm\fP بررسی خواهد کرد: .sp \fBall_of_equal\fP, \fBany_of_equal\fP, \fBany_of\fP, \fBapply_permutation\fP, \fBapply_reverse_permutation\fP, \fBclamp_range\fP, \fBcopy_if_until\fP, \fBcopy_if_while\fP, \fBcopy_if\fP, \fBcopy_until\fP, \fBcopy_while\fP, \fBfind_backward\fP, \fBfind_if_backward\fP, \fBfind_if_not_backward\fP, \fBfind_if_not\fP, \fBfind_not_backward\fP, \fBhex_lower\fP, \fBhex\fP, \fBiota\fP, \fBall_of\fP, \fBis_decreasing\fP, \fBis_increasing\fP, \fBis_palindrome\fP, \fBis_partitioned_until\fP, \fBis_partitioned\fP, \fBis_permutation\fP, \fBis_sorted_until\fP, \fBis_sorted\fP, \fBis_strictly_decreasing\fP, \fBis_strictly_increasing\fP, \fBnone_of_equal\fP, \fBnone_of\fP, \fBone_of_equal\fP, \fBone_of\fP, \fBpartition_copy\fP, \fBpartition_point\fP, \fBreduce\fP, \fBunhex\fP\&. .SS پیمایش معکوس (Reverse Iteration) .sp اگر فراخوانی‌ها با استفاده از تکرارکننده‌های معکوس (reverse iterators) روی کانتینرها انجام شده باشند، کد با استفاده از تطبیق‌دهنده \fBboost::adaptors::reverse\fP اصلاح خواهد شد. .INDENT 0.0 .INDENT 3.5 .sp .EX auto AreSame = std::equal(Items1.rbegin(), Items1.rend(), std::crbegin(Items2), std::crend(Items2)); .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX auto AreSame = boost::range::equal(boost::adaptors::reverse(Items1), boost::adaptors::reverse(Items2)); .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IncludeStyle رشته‌ای که مشخص می‌کند کدام سبک include استفاده شود، \fIllvm\fP یا \fIgoogle\fP\&. مقدار پیش‌فرض \fIllvm\fP است. .UNINDENT .INDENT 0.0 .TP .B IncludeBoostSystem اگر \fItrue\fP باشد (مقدار پیش‌فرض)، هدرهای boost مانند هدرهای سیستمی با براکت‌های زاویه‌دار گنجانده می‌شوند (\fI#include \fP)، در غیر این صورت از علامت نقل‌قول استفاده می‌شود (\fI#include \(dqboost.hpp\(dq\fP). .UNINDENT .INDENT 0.0 .TP .B UseReversePipe هنگامی که \fItrue\fP باشد (پیش‌فرض \fIfalse\fP است)، اصلاحاتی که شامل محدوده‌های معکوس هستند به جای ساختار تابعی، از ساختار تطبیق‌دهنده پایپ (pipe) استفاده خواهند کرد. .INDENT 7.0 .INDENT 3.5 .sp .EX std::find(Items.rbegin(), Items.rend(), 0); .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 7.0 .INDENT 3.5 .sp .EX boost::range::find(Items | boost::adaptors::reversed, 0); .EE .UNINDENT .UNINDENT .UNINDENT .SS boost\-use\-to\-string .sp این بررسی تبدیل از انواع عدد صحیح مانند \fBint\fP به \fBstd::string\fP یا \fBstd::wstring\fP با استفاده از \fBboost::lexical_cast\fP را پیدا کرده، و آن را با فراخوانی‌های \fBstd::to_string\fP و \fBstd::to_wstring\fP جایگزین می‌کند. .sp این بررسی با وجود سربارگذاری‌های \fBto_string\fP، تبدیل از اعداد ممیز شناور (floating points) را جایگزین نمی‌کند، چرا که رفتار برنامه را تغییر می‌دهد. .INDENT 0.0 .INDENT 3.5 .sp .EX auto str = boost::lexical_cast(42); auto wstr = boost::lexical_cast(2137LL); // Will be changed to auto str = std::to_string(42); auto wstr = std::to_wstring(2137LL); .EE .UNINDENT .UNINDENT .SS bugprone\-argument\-comment .sp بررسی می‌کند که کامنت‌های آرگومان‌ها با نام پارامترها مطابقت داشته باشند. .sp این بررسی کامنت‌های آرگومان را در قالب \fB/*parameter_name=*/\fP که درست پیش از آرگومان قرار می‌گیرند، درک می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX void f(bool foo); \&... f(/*bar=*/true); // warning: argument name \(aqbar\(aq in comment does not match parameter name \(aqfoo\(aq .EE .UNINDENT .UNINDENT .sp این بررسی تلاش می‌کند غلط‌های املایی را تشخیص داده و اصلاحات خودکار برای آن‌ها پیشنهاد دهد..SS گزینه‌ها .INDENT 0.0 .TP .B StrictMode هنگامی که \fIfalse\fP باشد، بررسی هنگام مقایسه نام‌ها، زیرخط‌های (underscore) ابتدا و انتها و بزرگی و کوچکی حروف را نادیده می‌گیرد \-\- در غیر این صورت آن‌ها لحاظ می‌شوند. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .INDENT 0.0 .TP .B IgnoreSingleArgument هنگامی که \fItrue\fP باشد، بررسی از تک‌آرگومان صرف‌نظر خواهد کرد. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .INDENT 0.0 .TP .B CommentBoolLiterals هنگامی که \fItrue\fP باشد، بررسی یادداشت‌های آرگومان را در قالب \fB/*ParameterName=*/\fP درست پیش از لیترال بولی اضافه می‌کند. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .sp قبل: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(bool TurnKey, bool PressButton); foo(true, false); .EE .UNINDENT .UNINDENT .sp بعد: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(bool TurnKey, bool PressButton); foo(/*TurnKey=*/true, /*PressButton=*/false); .EE .UNINDENT .UNINDENT .INDENT 0.0 .TP .B CommentIntegerLiterals هنگامی که \fItrue\fP باشد، بررسی یادداشت‌های آرگومان را در قالب \fB/*ParameterName=*/\fP درست پیش از لیترال عدد صحیح اضافه می‌کند. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .sp قبل: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(int MeaningOfLife); foo(42); .EE .UNINDENT .UNINDENT .sp بعد: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(int MeaningOfLife); foo(/*MeaningOfLife=*/42); .EE .UNINDENT .UNINDENT .INDENT 0.0 .TP .B CommentFloatLiterals هنگامی که \fItrue\fP باشد، بررسی یادداشت‌های آرگومان را در قالب \fB/*ParameterName=*/\fP درست پیش از لیترال اعشاری float/double اضافه می‌کند. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .sp قبل: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(float Pi); foo(3.14159); .EE .UNINDENT .UNINDENT .sp بعد: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(float Pi); foo(/*Pi=*/3.14159); .EE .UNINDENT .UNINDENT .INDENT 0.0 .TP .B CommentStringLiterals هنگامی که \fItrue\fP باشد، بررسی یادداشت‌های آرگومان را در قالب \fB/*ParameterName=*/\fP درست پیش از لیترال رشته‌ای اضافه می‌کند. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .sp قبل: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(const char *String); void foo(const wchar_t *WideString); foo(\(dqHello World\(dq); foo(L\(dqHello World\(dq); .EE .UNINDENT .UNINDENT .sp بعد: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(const char *String); void foo(const wchar_t *WideString); foo(/*String=*/\(dqHello World\(dq); foo(/*WideString=*/L\(dqHello World\(dq); .EE .UNINDENT .UNINDENT .INDENT 0.0 .TP .B CommentCharacterLiterals هنگامی که \fItrue\fP باشد، بررسی یادداشت‌های آرگومان را در قالب \fB/*ParameterName=*/\fP درست پیش از لیترال نویسه‌ای اضافه می‌کند. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .sp قبل: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(char *Character); foo(\(aqA\(aq); .EE .UNINDENT .UNINDENT .sp بعد: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(char *Character); foo(/*Character=*/\(aqA\(aq); .EE .UNINDENT .UNINDENT .INDENT 0.0 .TP .B CommentUserDefinedLiterals هنگامی که \fItrue\fP باشد، بررسی یادداشت‌های آرگومان را در قالب \fB/*ParameterName=*/\fP درست پیش از لیترال تعریف‌شده توسط کاربر اضافه می‌کند. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .sp قبل: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(double Distance); double operator\(dq\(dq _km(long double); foo(402.0_km); .EE .UNINDENT .UNINDENT .sp بعد: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(double Distance); double operator\(dq\(dq _km(long double); foo(/*Distance=*/402.0_km); .EE .UNINDENT .UNINDENT .INDENT 0.0 .TP .B CommentNullPtrs هنگامی که \fItrue\fP باشد، بررسی یادداشت‌های آرگومان را در قالب \fB/*ParameterName=*/\fP درست پیش از لیترال nullptr اضافه می‌کند. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .sp قبل: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(A* Value); foo(nullptr); .EE .UNINDENT .UNINDENT .sp بعد: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(A* Value); foo(/*Value=*/nullptr); .EE .UNINDENT .UNINDENT .SS bugprone\-assert\-side\-effect .sp موارد استفاده از \fBassert()\fP دارای اثر جانبی (side effect) را پیدا می‌کند. .sp شرط درون \fBassert()\fP تنها در ساخت‌های حالت اشکال‌زدایی (debug) ارزیابی می‌شود، بنابراین یک شرط دارای اثر جانبی می‌تواند باعث رفتارهای متفاوت در ساخت‌های debug و release شود. .SS گزینه‌ها .INDENT 0.0 .TP .B AssertMacros فهرستی از نام‌های ماکروهای assert جداشده با کاما جهت بررسی شدن. پیش‌فرض \fIassert,NSAssert,NSCAssert\fP است. .UNINDENT .INDENT 0.0 .TP .B CheckFunctionCalls اینکه آیا با توابع عضو و غیرعضو غیر-const طوری رفتار شود که گویی اثرات جانبی تولید می‌کنند یا خیر. به‌طور پیش‌فرض غیرفعال است زیرا می‌تواند تعداد هشدارهای مثبت کاذب را افزایش دهد. .UNINDENT .INDENT 0.0 .TP .B IgnoredFunctions فهرستی از نام‌های توابع یا متدها جداشده با سمی‌کالن (نقطه‌ویرگول) که باید فاقد اثر جانبی در نظر گرفته شوند. عبارات باقاعده (regex) پذیرفته می‌شوند، مانند \fB[Rr]ef(erence)?$\fP که با هر نوعی با پسوند \fBRef\fP، \fBref\fP، \fBReference\fP و \fBreference\fP مطابقت دارد. پیش‌فرض خالی است. اگر نامی در فهرست شامل توالی \fI::\fP باشد، با نام نوع واجد شرایط کامل (یعنی \fBnamespace::Type\fP) مطابقت داده می‌شود، در غیر این صورت تنها با نام نوع (یعنی \fBType\fP) تطبیق داده می‌شود. .UNINDENT .SS bugprone\-assignment\-in\-if\-condition .sp انتساب‌ها (assignments) را درون شرط‌های دستورات \fIif\fP پیدا می‌کند. چنین انتساب‌هایی مستعد باگ هستند زیرا ممکن است هدف از آن‌ها بررسی تساوی بوده باشد. .sp این بررسی تمام انتساب‌های درون شرط‌های \fIif\fP را پیدا می‌کند، از جمله مواردی که به‌دلیل وجود یک جفت پرانتز اضافه توسط \fI\-Wparentheses\fP علامت‌گذاری نشده‌اند، و همچنین انتساب‌هایی که یک \fBoperator=()\fP بارگذاری‌مجدد شده را فراخوانی می‌کنند. انتساب‌های شناسایی‌شده، قانون «Rule 8.2.c» از گروه BARR را نقض می‌کنند \%\&. .INDENT 0.0 .INDENT 3.5 .sp .EX int f = 3; if(f = 4) { // This is identified by both \(gaWparentheses\(ga and this check \- should it have been: \(gaif (f == 4)\(ga ? f = f + 1; } if((f == 5) || (f = 6)) { // the assignment here \(ga(f = 6)\(ga is identified by this check, but not by \(ga\-Wparentheses\(ga. Should it have been \(ga(f == 6)\(ga ? f = f + 2; } .EE .UNINDENT .UNINDENT .SS bugprone\-bad\-signal\-to\-kill\-thread .sp فراخوانی‌های تابع \fBpthread_kill\fP را در مواردی پیدا می‌کند که یک ترد با ارسال سیگنال \fBSIGTERM\fP خاتمه می‌یابد و این سیگنال کل فرآیند را از بین می‌برد، نه تنها همان ترد مجزا را. از هر سیگنالی به جز \fBSIGTERM\fP استفاده کنید. .INDENT 0.0 .INDENT 3.5 .sp .EX pthread_kill(thread, SIGTERM); .EE .UNINDENT .UNINDENT .sp این بررسی با قاعده استانداردهای کدنویسی CERT C تحت عنوان POS44\-C. Do not use signals to terminate threads مطابقت دارد \%\&. .sp بررسی \fIcert\-pos44\-c\fP به‌عنوان نام مستعاری از این بررسی به اینجا تغییر مسیر می‌دهد. .SS bugprone\-bitwise\-pointer\-cast .sp در مورد کدهایی که سعی دارند با استفاده از \fBstd::bit_cast\fP یا \fBmemcpy\fP بین اشاره‌گرها تبدیل نوع (cast) انجام دهند، هشدار می‌دهد. .sp انگیزه این است که \fBstd::bit_cast\fP به عنوان جایگزینی امن برای تبدیل نوع با استفاده از \fBreinterpret_cast\fP در مدرن C++ تبلیغ می‌شود. با این حال، نباید کورکورانه \fBreinterpret_cast\fP را با \fBstd::bit_cast\fP به صورت زیر جایگزین کرد: .INDENT 0.0 .INDENT 3.5 .sp .EX int x{}; \-float y = *reinterpret_cast(&x); +float y = *std::bit_cast(&x); .EE .UNINDENT .UNINDENT .sp این جایگزینی مستقیم دقیقاً رفتاری مشابه با \fBreinterpret_cast\fP دارد، و همچنان رفتار تعریف‌نشده (Undefined Behavior) رخ می‌دهد. \fBstd::bit_cast\fP بایت‌های اشاره‌گر ورودی را (و نه شیء اشاره‌شده را) درون یک اشاره‌گر خروجی از نوعی دیگر کپی می‌کند، که ممکن است قواعد strict aliasing را نقض کند. با این وجود، با نگاه کردن ساده به کد، به نظر «امن» می‌رسد، چرا که از \fBstd::bit_cast\fP استفاده می‌کند که به عنوان امن معرفی شده است. .sp راهکار برای تبدیل نوع امن، اعمال \fBstd::bit_cast\fP روی نوع‌های مقداری (value types) است، نه روی نوع‌های اشاره‌گر: .INDENT 0.0 .INDENT 3.5 .sp .EX int x{}; float y = std::bit_cast(x); .EE .UNINDENT .UNINDENT .sp به این ترتیب، بایت‌های شیء ورودی در شیء خروجی کپی می‌شوند که بسیار امن‌تر است. توجه داشته باشید که اگر مقداری از نوع \fBTo\fP متناظر با نمایش مقداری تولیدشده وجود نداشته باشد، رفتار تعریف‌نشده هنوز می‌تواند رخ دهد. کامپایلرها ممکن است بتوانند این کپی را بهینه‌سازی کرده و کدهای اسمبلی همسانی با نسخه اولیه \fBreinterpret_cast\fP تولید کنند. .sp کدهای قبل از C++20 ممکن است \fBstd::bit_cast\fP را با استفاده از \fBmemcpy\fP شبیه‌سازی کرده، یا صرفاً مستقیماً \fBmemcpy\fP را فراخوانی کنند که به همان اندازه مشکل‌ساز است. این مورد نیز توسط این بررسی شناسایی می‌شود: .INDENT 0.0 .INDENT 3.5 .sp .EX int* x{}; float* y{}; std::memcpy(&y, &x, sizeof(x)); .EE .UNINDENT .UNINDENT .sp همچنین، اگر واقعاً تبدیل نوع میان اشاره‌گرها مد نظر است، باید از \fBreinterpret_cast\fP استفاده شود تا هدف را به وضوح منتقل کرده و هشدارهای کامپایلرها و لینترها فعال شوند، که باید به درستی رفع گردند. .SS bugprone\-bool\-pointer\-implicit\-conversion .sp شرط‌های مبتنی بر تبدیل نوع ضمنی (implicit conversion) از یک اشاره‌گر \fBbool\fP به \fBbool\fP را بررسی می‌کند. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX bool *p; if (p) { // Never used in a pointer\-specific way. } .EE .UNINDENT .UNINDENT .SS bugprone\-branch\-clone .sp شاخه\(aqهای تکراری را در زنجیره\(aqهای \fBif/else if/else\fP، شاخه\(aqهای تکراری متوالی را در دستورهای \fBswitch\fP و شاخه\(aqهای یکسان true و false را در عملگرهای شرطی بررسی می\(aqکند. .INDENT 0.0 .INDENT 3.5 .sp .EX if (test_value(x)) { y++; do_something(x, y); } else { y++; do_something(x, y); } .EE .UNINDENT .UNINDENT .sp در این مثال ساده (که می\(aqتواند مثلاً بر اثر خطای کپی\-پیست رخ دهد)، شاخه\(aqهای \fBthen\fP و \fBelse\fP یکسان هستند و کد با کد کوتاه‌تر و تمیزتر زیر معادل است: .INDENT 0.0 .INDENT 3.5 .sp .EX test_value(x); // can be omitted unless it has side effects y++; do_something(x, y); .EE .UNINDENT .UNINDENT .sp اگر این رفتار مورد نظر باشد، دلیلی برای استفاده از یک عبارت شرطی وجود ندارد؛ در غیر این صورت، مشکل با اصلاح شاخه\(aqای که به نادرستی مدیریت شده است، برطرف می\(aqشود. .sp این بررسی، شاخه\(aqهای تکراری را در زنجیره\(aqهای طولانی‌تر \fBif/else if/else\fP نیز تشخیص می\(aqدهد؛ جاهایی که متوجه شدن مشکل در آن‌ها حتی دشوارتر است. .sp این بررسی همچنین دستورهای تکراری \fBif\fP درونی و بیرونی را که ممکن است نتیجه خطای کپی\-پیست باشند، تشخیص می\(aqدهد. این بررسی در حال حاضر نمی‌تواند دستورهای \fBif\fP درونی و بیرونی یکسان را در صورتی که کدی بین شروط \fBif\fP قرار گرفته باشد، شناسایی کند. نمونه‌ای از آن به شرح زیر است: .INDENT 0.0 .INDENT 3.5 .sp .EX void test_warn_inner_if_1(int x) { if (x == 1) { // warns, if with identical inner if if (x == 1) // inner if is here ; if (x == 1) { // does not warn, cannot detect int y = x; if (x == 1) ; } } .EE .UNINDENT .UNINDENT .sp در دستورهای \fBswitch\fP، این بررسی تنها زمانی شاخه\(aqهای تکراری را گزارش می\(aqکند که متوالی باشند؛ زیرا نسبتاً معمول است که برچسب‌های \fBcase:\fP دارای یک ترتیب طبیعی باشند و مرتب‌سازی مجدد آن‌ها خوانایی کد را کاهش دهد. برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX switch (ch) { case \(aqa\(aq: return 10; case \(aqA\(aq: return 10; case \(aqb\(aq: return 11; case \(aqB\(aq: return 11; default: return 10; } .EE .UNINDENT .UNINDENT .sp در اینجا، بررسی گزارش می\(aqدهد که شاخه\(aqهای \fB\(aqa\(aq\fP و \fB\(aqA\(aq\fP یکسان هستند (و شاخه\(aqهای \fB\(aqb\(aq\fP و \fB\(aqB\(aq\fP نیز یکسان هستند)، اما گزارش نمی\(aqکند که شاخه \fBdefault:\fP نیز با دو شاخه اول یکسان است. اگر این واقعاً رفتار درستی باشد، می\(aqتوان آن را به شکل زیر پیاده‌سازی کرد: .INDENT 0.0 .INDENT 3.5 .sp .EX switch (ch) { case \(aqa\(aq: case \(aqA\(aq: return 10; case \(aqb\(aq: case \(aqB\(aq: return 11; default: return 10; } .EE .UNINDENT .UNINDENT .sp در اینجا، بررسی برای \fBreturn 10;\fP تکراری هشدار نمی\(aqدهد، که اگر بخواهیم حفظ کنیم که \fB\(aqa\(aq\fP قبل از \fB\(aqb\(aq\fP باشد و \fBdefault:\fP آخرین شاخه باشد، مناسب است. .sp موارد switch که با صفت \fB[[fallthrough]]\fP مشخص شده‌اند، نادیده گرفته می‌شوند. .sp در نهایت، این بررسی همچنین عملگرهای شرطی را بررسی کرده و کدهایی شبیه به مورد زیر را گزارش می\(aqدهد: .INDENT 0.0 .INDENT 3.5 .sp .EX return test_value(x) ? x : x; .EE .UNINDENT .UNINDENT .sp برخلاف دستورهای if، این بررسی زنجیره‌هایی از عملگرهای شرطی را شناسایی نمی\(aqکند. .sp نکته: این بررسی مواردی را نیز گزارش می\(aqکند که شاخه‌ها تنها پس از پیش‌پردازش یکسان می\(aqشوند. .SS bugprone\-capturing\-this\-in\-member\-variable .sp گرفتن‌های لامبدا (lambda captures) که اشاره‌گر \fBthis\fP را ضبط کرده و به عنوان اعضای کلاس ذخیره می‌کنند بدون اینکه سازنده‌های کپی و انتقال (copy/move constructors) و عملگرهای انتساب را مدیریت کنند، پیدا می‌کند. .sp گرفتن this در یک لامبدا و ذخیره آن به عنوان عضو کلاس خطرناک است زیرا طول عمر لامبدا می‌تواند بیشتر از شیئی باشد که آن را ضبط می‌کند. به ویژه هنگامی که شیء کپی یا جابه‌جا (move) می‌شود، اشاره‌گر ضبط‌شده \fBthis\fP به‌طور ضمنی به شیء جدید منتقل خواهد شد. اغلب اوقات، افراد تصور می‌کنند که اشاره‌گر ضبط‌شده \fBthis\fP به شیء جدید اشاره دارد که این موضوع منجر به باگ خواهد شد. .INDENT 0.0 .INDENT 3.5 .sp .EX struct C { C() : Captured([this]() \-> C const * { return this; }) {} std::function Captured; }; void foo() { C v1{}; C v2 = v1; // v2.Captured capture v1\(aqs \(aqthis\(aq pointer assert(v2.Captured() == v1.Captured()); // v2.Captured capture v1\(aqs \(aqthis\(aq pointer assert(v2.Captured() == &v2); // assertion failed. } .EE .UNINDENT .UNINDENT .INDENT 0.0 .TP .B راه‌حل‌های ممکن: .INDENT 7.0 .IP \(bu 2 علامت‌گذاری سازنده‌های کپی و انتقال و عملگرهای انتساب به صورت حذف‌شده (deleted). .IP \(bu 2 استفاده از متد عضو کلاس به جای متغیر عضو کلاس با انواع شیء تابعی (function object). .IP \(bu 2 ارسال اشاره‌گر \fBthis\fP به عنوان پارامتر. .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B FunctionWrapperTypes فهرستی از نام‌های انواع داده که با نقطه‌ویرگول (semicolon) از هم جدا شده‌اند. برای مشخص کردن بسته‌بندی‌های تابعی (function wrapper) که می‌توانند عبارات لامبدا را نگه دارند استفاده می‌شود. مقدار پیش‌فرض عبارت است از \fI::std::function;::std::move_only_function;::boost::function\fP\&. .UNINDENT .INDENT 0.0 .TP .B BindFunctions فهرستی از نام‌های کامل واجد شرایط (fully qualified) توابعی که می‌توانند اشاره‌گر \fBthis\fP را ضبط (capture) کنند، که با نقطه‌ویرگول از هم جدا شده‌اند. مقدار پیش‌فرض عبارت است از \fI::std::bind;::boost::bind;::std::bind_front;::std::bind_back; ::boost::compat::bind_front;::boost::compat::bind_back\fP\&. .UNINDENT .SS bugprone\-casting\-through\-void .sp عملیات تبدیل نوع (cast) دو مرحله‌ای ناامن یا زائد که شامل \fBvoid*\fP می‌شوند را شناسایی می‌کند، که طبق استاندارد C++ در \% معادل \fBreinterpret_cast\fP است. .sp تبدیل‌های نوع دو مرحله‌ای از طریق \fBvoid*\fP به دلایل متعددی توصیه نمی‌شوند. .INDENT 0.0 .IP \(bu 2 آن‌ها کد را مبهم کرده و خوانایی و درک آن را مختل می‌کنند، که در نتیجه نگهداری کد را پیچیده می‌سازد. .IP \(bu 2 این تبدیل‌ها پشتیبانی‌های ارزشمند کامپایلر را دور می‌زنند و هشدارهای مربوط به هم‌ترازی اشاره‌گر (pointer alignment) را نادیده می‌گیرند. این امر ممکن است قاعده strict aliasing را نقض کرده و منجر به رفتار تعریف‌نشده (undefined behavior) شود. .IP \(bu 2 در سناریوهایی که شامل وراثت چندگانه (multiple inheritance) هستند، به دلیل از دست رفتن اطلاعات نوع، ممکن است ابهام و نتایج غیرمنتظره‌ای رخ دهد که مشکلات زمان اجرا ایجاد می‌کند. .UNINDENT .sp به طور خلاصه، اجتناب از تبدیل‌های نوع دو مرحله‌ای از طریق \fBvoid*\fP تضمین می‌کند که کد شفاف‌تر باقی بماند، هشدارهای ضروری کامپایلر حفظ شوند، و از ابهام و خطاهای احتمالی زمان اجرا، به‌ویژه در سناریوهای پیچیده وراثت، جلوگیری شود. اگر چنین تبدیلی مد نظر است، باید از طریق \fBreinterpret_cast\fP انجام شود تا هدف به صورت واضح‌تری بیان گردد. .sp توجه: انتظار می‌رود پس از اعمال اصلاح پیشنهادی و استفاده از \fBreinterpret_cast\fP، بررسی cppcoreguidelines\-pro\-type\-reinterpret\-cast \%<> هشداری صادر کند. این رفتار عمدی است: \fBreinterpret_cast\fP عملیاتی خطرناک است که می‌تواند به راحتی قوانین strict aliasing را هنگام درک ارجاع (dereferencing) اشاره‌گر تبدیل‌شده نقض کرده و موجب رفتار تعریف‌نشده (Undefined Behavior) شود. این هشدار برای این قرار داده شده است که به کاربران گوشزد کند با دقت بررسی کنند که آیا استفاده از \fBreinterpret_cast\fP ایمن است یا خیر، که در صورت ایمن بودن می‌توان این هشدار را نادیده گرفت (suppress کرد). .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX using IntegerPointer = int *; double *ptr; static_cast(static_cast(ptr)); // WRONG reinterpret_cast(reinterpret_cast(ptr)); // WRONG (IntegerPointer)(void *)ptr; // WRONG IntegerPointer(static_cast(ptr)); // WRONG reinterpret_cast(ptr); // OK, clearly expresses intent. // NOTE: dereferencing this pointer violates // the strict aliasing rules, invoking // Undefined Behavior. .EE .UNINDENT .UNINDENT .SS bugprone\-chained\-comparison .sp این بررسی عملگرهای مقایسه‌ای زنجیره‌ای را که می‌توانند منجر به رفتارهای ناخواسته یا خطاهای منطقی شوند، شناسایی می‌کند. .sp مقایسه‌های زنجیره‌ای عباراتی هستند که از چندین عملگر مقایسه برای مقایسه سه مقدار یا بیشتر استفاده می‌کنند. به عنوان مثال، عبارت \fBa < b < c\fP مقادیر \fBa\fP، \fBb\fP و \fBc\fP را مقایسه می‌کند. با این حال، این عبارت به صورت \fB(a < b) && (b < c)\fP که احتمالاً مورد نظر توسعه‌دهنده بوده ارزیابی نمی‌شود. در عوض، به شکل \fB(a < b) < c\fP ارزیابی می‌شود که ممکن است نتایج ناخواسته‌ای به همراه داشته باشد، به ویژه زمانی که انواع داده \fBa\fP، \fBb\fP و \fBc\fP متفاوت باشند. .sp برای جلوگیری از چنین خطاهایی، هنگام شناسایی عملگر مقایسه زنجیره‌ای، این بررسی هشداری صادر کرده و پیشنهاد می‌کند که از پرانتز برای مشخص کردن اولویت ارزیابی یا از یک عملگر منطقی برای جداسازی عبارات مقایسه‌ای استفاده شود. .sp مثال‌های زیر را در نظر بگیرید: .INDENT 0.0 .INDENT 3.5 .sp .EX int a = 2, b = 6, c = 4; if (a < b < c) { // This block will be executed } .EE .UNINDENT .UNINDENT .sp در این مثال، قصد توسعه‌دهنده بررسی این بود که آیا \fBa\fP از \fBb\fP کوچک‌تر است و \fBb\fP از \fBc\fP کوچک‌تر است یا خیر. با این حال، عبارت \fBa < b < c\fP معادل \fB(a < b) < c\fP است. از آن‌جا که \fBa < b\fP برابر \fBtrue\fP است، عبارت \fB(a < b) < c\fP به عنوان \fB1 < c\fP ارزیابی می‌شود که معادل \fBtrue < c\fP است و در این حالت نادرست است، زیرا \fBb < c\fP مقدار \fBfalse\fP دارد. .sp حتی با وجود این‌که مشکل بالا را می‌توان به عنوان مقایسه \fBint\fP با \fBbool\fP شناسایی کرد، مثال خطرناک‌تری نیز وجود دارد: .INDENT 0.0 .INDENT 3.5 .sp .EX bool a = false, b = false, c = true; if (a == b == c) { // This block will be executed } .EE .UNINDENT .UNINDENT .sp در این مثال، قصد توسعه‌دهنده این بوده است که بررسی کند آیا \fBa\fP، \fBb\fP و \fBc\fP همگی برابر هستند یا خیر. با این وجود، عبارت \fBa == b == c\fP به صورت \fB(a == b) == c\fP ارزیابی می‌شود. از آن‌جا که \fBa == b\fP درست (true) است، عبارت \fB(a == b) == c\fP به عنوان \fBtrue == c\fP ارزیابی می‌شود که معادل \fBtrue == true\fP است. این مقایسه نتیجه \fBtrue\fP می‌دهد، با وجود این‌که مقادیر \fBa\fP و \fBb\fP برابر \fBfalse\fP بوده و با \fBc\fP برابر نیستند. .sp برای جلوگیری از این مشکل، توسعه‌دهنده می‌تواند از یک عملگر منطقی برای جداسازی عبارات مقایسه استفاده کند، مانند زیر: .INDENT 0.0 .INDENT 3.5 .sp .EX if (a == b && b == c) { // This block will not be executed } .EE .UNINDENT .UNINDENT .sp همچنین، استفاده از پرانتز در عبارات مقایسه‌ای می‌تواند قصد توسعه‌دهنده را واضح‌تر بیان کرده و به جلوگیری از سوءتفاهم کمک کند. .INDENT 0.0 .INDENT 3.5 .sp .EX if ((a == b) == c) { // This block will be executed } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoreMacros اگر \fItrue\fP باشد، این بررسی در مورد مقایسه‌های زنجیره‌ای داخل ماکروها هشدار نخواهد داد. پیش‌فرض \fIfalse\fP است\&. .UNINDENT .SS bugprone\-command\-processor .sp فراخوانی‌های تابع‌های \fBsystem()\fP، \fBpopen()\fP و \fB_popen()\fP را که یک پردازشگر دستور (command processor) را اجرا می‌کنند، علامت‌گذاری می‌کند. این بررسی فراخوانی‌های \fBsystem()\fP با آرگومان اشاره‌گر null را علامت‌گذاری نمی‌کند، زیرا چنین فراخوانی صرفاً وجود یک پردازشگر دستور را بررسی می‌کند و در عمل تلاشی برای اجرای یک دستور انجام نمی‌دهد. .SS مراجع .sp این بررسی با قاعدهٔ استاندارد کدنویسی CERT C زیر مطابقت دارد: ENV33\-C. Do not call system() \%\&. .SS bugprone\-compare\-pointer\-to\-member\-virtual\-function .sp رفتارهای مشخص‌نشده (unspecified behavior) مربوط به مقایسهٔ برابری بین یک اشاره‌گر به تابع مجازی عضو و هر چیزی غیر از یک مقدار ثابت اشاره‌گر پوچ (null\-pointer\-constant) را شناسایی می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX struct A { void f1(); void f2(); virtual void f3(); virtual void f4(); void g1(int); }; void fn() { bool r1 = (&A::f1 == &A::f2); // ok bool r2 = (&A::f1 == &A::f3); // bugprone bool r3 = (&A::f1 != &A::f3); // bugprone bool r4 = (&A::f3 == nullptr); // ok bool r5 = (&A::f3 == &A::f4); // bugprone void (A::*v1)() = &A::f3; bool r6 = (v1 == &A::f1); // bugprone bool r6 = (v1 == nullptr); // ok void (A::*v2)() = &A::f2; bool r7 = (v2 == &A::f1); // false positive, but potential risk if assigning other value to v2. void (A::*v3)(int) = &A::g1; bool r8 = (v3 == &A::g1); // ok, no virtual function match void(A::*)(int) signature. } .EE .UNINDENT .UNINDENT .sp هشدارهایی را دربارهٔ مقایسه‌های برابری شامل اشاره‌گرها به توابع مجازی عضو یا متغیرهایی که احتمالاً اشاره‌گری به یک تابع مجازی عضو هستند با هر موجودیتی غیر از یک مقدار ثابت اشاره‌گر null ارائه می‌دهد. .sp در برخی از کامپایلرها، آدرس‌های توابع مجازی اشاره‌گرهای معمولی نیستند بلکه از آفست‌ها و اندیس‌هایی در داخل جدول توابع مجازی (vtable) تشکیل شده‌اند. در نتیجه، این اشاره‌گرها ممکن است بین کلاس‌های پایه و مشتق‌شده متفاوت باشند که باعث بروز رفتارهای غیرقابل‌پیش‌بینی هنگام مقایسهٔ مستقیم آن‌ها می‌شود. این مسئله به‌ویژه هنگام کار با اشاره‌گرها به توابع مجازی محض (pure virtual) دشوارتر می‌شود، زیرا آن‌ها ممکن است حتی یک آدرس معتبر نیز نداشته باشند که این امر مقایسه‌ها را پیچیده‌تر می‌کند. .sp به جای آن، توصیه می‌شود از عملگر \fBtypeid\fP یا سایر سازوکارهای مناسب برای مقایسهٔ اشیاء استفاده کنید تا از رفتار پایدار و قابل‌پیش‌بینی در کد خود اطمینان حاصل نمایید. با توجه به این هشدار و به‌کارگیری روش مقایسهٔ مطمئن‌تر، می‌توانید مشکلات بالقوهٔ مربوط به رفتارهای مشخص‌نشده را به‌ویژه هنگام کار با اشاره‌گر به توابع مجازی عضو یا توابع مجازی محض کاهش داده و در نتیجه پایداری و نگهداری‌پذیری کلی کد خود را بهبود بخشید. در سناریوهای مربوط به اشاره‌گر به توابع مجازی عضو، فقط استفاده از \fBnullptr\fP برای مقایسه توصیه می‌شود. .SS محدودیت‌ها .sp مقادیر ذخیره‌شده در یک متغیر را تحلیل نمی‌کند. برای متغیرها، تنها تمامی متدهای مجازی در همان \fBclass\fP یا \fBstruct\fP را بررسی می‌کند و زمانی که انتساب یک اشاره‌گر به تابع مجازی عضو به این متغیر امکان‌پذیر باشد، عیب‌یابی را انجام می‌دهد. .SS bugprone\-copy\-constructor\-init .sp سازنده‌های رونوشتی (copy constructors) را پیدا می‌کند که در آن‌ها سازنده، سازندهٔ رونوشت کلاس پایه را فراخوانی نمی‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX class Copyable { public: Copyable() = default; Copyable(const Copyable &) = default; int memberToBeCopied = 0; }; class X2 : public Copyable { X2(const X2 &other) {} // Copyable(other) is missing }; .EE .UNINDENT .UNINDENT .sp همچنین سازنده‌های رونوشتی را پیدا می‌کند که در آن‌ها سازندهٔ کلاس پایه بدون پارامتر فراخوانی شده است. .INDENT 0.0 .INDENT 3.5 .sp .EX class X3 : public Copyable { X3(const X3 &other) : Copyable() {} // other is missing }; .EE .UNINDENT .UNINDENT .sp عدم مقداردهی اولیهٔ صحیح زیر‌اشیاء (sub\-objects) کلاس پایه در حین ساخت رونوشت می‌تواند منجر به رفتار تعریف‌نشده (undefined behavior)، کرش کردن برنامه، خرابی داده‌ها یا سایر پیامدهای غیرمنتظره شود. این بررسی اطمینان حاصل می‌کند که سازندهٔ رونوشت یک کلاس مشتق‌شده، سازندهٔ رونوشت کلاس پایه را به‌درستی فراخوانی کند و بدین ترتیب از باگ‌ها جلوگیری کرده و کیفیت کد را بهبود می‌بخشد. .SS محدودیت‌ها .INDENT 0.0 .IP \(bu 2 برای کلاس‌های خالی هشداری تولید نمی‌کند، زیرا اعضایی در کلاس (شامل زیر‌اشیاء کلاس پایه) وجود ندارد که نگران آن‌ها بود. .IP \(bu 2 برای کلاس‌های پایه‌ای که سازندهٔ رونوشت آن‌ها private یا deleted است هشداری ایجاد نمی‌کند. .IP \(bu 2 برای کلاس‌های پایه‌ای که با استفاده از سازنده‌های غیراصلی (non\-default) دیگر مقداردهی اولیه شده‌اند هشداری تولید نمی‌کند، چرا که این موضوع ممکن است عمدی باشد. .UNINDENT .sp این بررسی همچنین در برخی موارد پیشنهادهایی برای اصلاح خودکار (fix\-its) ارائه می‌دهد. .SS bugprone\-copy\-constructor\-mutates\-argument .sp انتساب‌ها به شیء کپی‌شده و اعضای مستقیم یا غیرمستقیم آن را در سازنده‌های رونوشت و عملگرهای انتساب رونوشت پیدا می‌کند. .sp این بررسی با قاعدهٔ استاندارد کدنویسی CERT C زیر مطابقت دارد: OOP58\-CPP. Copy operations must not mutate the source object \%\&. .SS bugprone\-crtp\-constructor\-accessibility .sp استفاده‌های مستعد خطای الگوی تکرارشوندهٔ عجیب قالب (Curiously Recurring Template Pattern یا CRTP) را در صورتی که نمونه‌سازی از CRTP در خارج از خود آن و کلاس مشتق‌شده امکان‌پذیر باشد، تشخیص می‌دهد. .sp الگوی CRTP اصطلاحی است که در آن یک کلاس از یک کلاس قالب مشتق می‌شود، در حالی که خودش آرگومان آن قالب است. باید اطمینان حاصل شود که اگر کلاسی قرار است به عنوان یک کلاس پایه در این الگو به کار رود، تنها در صورتی بتوان از آن نمونه‌سازی کرد که کلاس مشتق‌شده آرگومان قالب آن باشد. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX template class CRTP { private: CRTP() = default; friend T; }; class Derived : CRTP {}; .EE .UNINDENT .UNINDENT .sp در زیر برخی از اشتباهات رایج که امکان نقض این الگو را فراهم می‌کنند، مشاهده می‌شود. .sp اگر سازندهٔ کلاسی که قرار است در CRTP استفاده شود به صورت public باشد، به کاربران اجازه می‌دهد آن کلاس را به طور مستقل نمونه‌سازی کنند. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX template class CRTP { public: CRTP() = default; }; class Good : CRTP {}; Good GoodInstance; CRTP BadInstance; .EE .UNINDENT .UNINDENT .sp اگر سازنده به صورت protected باشد، از احتمال نمونه‌سازی تصادفی جلوگیری می‌شود، اما ممکن است خطایی را پنهان کند که در آن کلاسی متفاوت به جای کلاس مشتق‌شده به عنوان پارامتر قالب استفاده شود. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX template class CRTP { protected: CRTP() = default; }; class Good : CRTP {}; Good GoodInstance; class Bad : CRTP {}; Bad BadInstance; .EE .UNINDENT .UNINDENT .sp برای اطمینان از عدم وقوع نمونه‌سازی تصادفی، بهترین روش این است که سازنده private تعریف شود و کلاس مشتق‌شده به عنوان friend اعلام گردد. توجه داشته باشید که به عنوان یک مصالحه، این کار به کلاس مشتق‌شده دسترسی به سایر اعضای خصوصی (private) کلاس CRTP را نیز اعطا می‌کند. با این حال، سازنده‌ها همچنان می‌توانند در صورت حذف شدن (deleted)، به صورت public یا protected باشند. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX template class CRTP { CRTP() = default; friend T; }; class Good : CRTP {}; Good GoodInstance; class Bad : CRTP {}; Bad CompileTimeError; CRTP AlsoCompileTimeError; .EE .UNINDENT .UNINDENT .SS محدودیت‌ها .INDENT 0.0 .IP \(bu 2 این بررسی در نسخه‌های پایین‌تر از C++11 پشتیبانی نمی‌شود .IP \(bu 2 این بررسی مواردی را که کلاس مشتق‌شده به عنوان یک آرگومان قالب متغیر (variadic template) ارسال می‌شود مدیریت نمی‌کند .IP \(bu 2 توابع در دسترس که می‌توانند CRTP را بسازند، مانند توابع کارخانه‌ای (factory functions)، بررسی نمی‌شوند .UNINDENT .sp این بررسی همچنین در برخی موارد اصلاحات خودکار (fix\-its) پیشنهاد می‌دهد. .SS bugprone\-dangling\-handle .sp ارجاع‌های معلق (dangling references) را در هندل‌های مقداری مانند \fBstd::string_view\fP شناسایی می‌کند. این ارجاع‌های معلق می‌توانند نتیجه ساختن هندل‌ها از مقادیر موقت باشند، جایی که مقدار موقت اندکی پس از ایجاد هندل از بین می‌رود. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX string_view View = string(); // View will dangle. string A; View = A + \(dqA\(dq; // still dangle. vector V; V.push_back(string()); // V[0] is dangling. V.resize(3, string()); // V[1] and V[2] will also dangle. string_view f() { // All these return values will dangle. return string(); string S; return S; char Array[10]{}; return Array; } span g() { array V; return {V}; int Array[10]{}; return {Array}; } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B HandleClasses یک فهرست جدا شده با نقطه\-ویرگول از نام کلاس‌هایی که باید به عنوان هندل در نظر گرفته شوند. به طور پیش‌فرض فقط \fBstd::basic_string_view\fP، \fBstd::experimental::basic_string_view\fP و \fBstd::span\fP در نظر گرفته می‌شوند. .UNINDENT .SS bugprone\-default\-operator\-new\-on\-overaligned\-type .sp استفاده از \fBoperator new\fP پیش‌فرض را در مواردی که نوع داده دارای تراز گسترش‌یافته (ترازی بزرگ‌تر از تراز بنیادی / fundamental alignment) است علامت‌گذاری می‌کند. .sp در صورتی که تراز درخواستی کمتر یا مساوی با تراز بنیادی باشد، عملکرد \fBoperator new\fP پیش‌فرض تضمین‌کننده ارائه تراز صحیح است. تنها مواردی شناسایی می‌شوند (بر اساس طراحی) که در آن‌ها \fBoperator new\fP توسط کاربر تعریف نشده و از نوع placement new نباشد (دلیل آن این است که در این موارد فرض بر این است که کاربر تخصیص حافظه صحیح را فراهم کرده است). .SS مراجع .sp این بررسی با قاعده MEM57\-CPP از استاندارد کدنویسی CERT C++ مطابقت دارد: Avoid using default operator new for over\-aligned types \%\&. .SS bugprone\-derived\-method\-shadowing\-base\-method .sp متدهای کلاس مشتق‌شده را که یک متد (غیر مجازی) از کلاس پایه را پنهان (shadow) می‌کنند، پیدا می‌کند. .sp برای اینکه متدها «پنهان‌کننده» (shadowing) در نظر گرفته شوند، باید امضای یکسانی داشته باشند (یعنی نام یکسان، تعداد پارامترهای یکسان، انواع پارامتر یکسان و غیره). فقط متدهای عمومی (public) و غیر قالبی (non\-templated) بررسی می‌شوند. .sp مثال زیر مستعد باگ است زیرا استفاده‌کنندگان از کلاس \fBDerived\fP انتظار دارند متد \fBreset\fP علاوه بر کارهای اضافه مورد نیاز برای بازنشانی کلاس \fBDerived\fP، کار \fBBase::reset()\fP را نیز انجام دهد. اصلاحات رایج عبارتند از: .INDENT 0.0 .IP \(bu 2 چندریختی (polymorphic) کردن متد \fBreset\fP .IP \(bu 2 تغییر نام \fBDerived::reset\fP در صورتی که قرار نیست با \fBBase::reset\fP تلاقی داشته باشد .IP \(bu 2 استفاده از \fBusing Base::reset\fP برای تغییر مشخص‌کننده دسترسی (access specifier) .UNINDENT .sp این موضوع همچنین نقض اصل جایگزینی لیسکوف (Liskov Substitution Principle) است. .INDENT 0.0 .INDENT 3.5 .sp .EX struct Base { void reset() {/* reset the base class */}; }; struct Derived : public Base { void reset() {/* reset the derived class, but not the base class */}; }; .EE .UNINDENT .UNINDENT .SS bugprone\-dynamic\-static\-initializers .sp نمونه‌هایی از متغیرهای ایستا (static) را که به صورت پویا در فایل‌های هدر مقداردهی اولیه می‌شوند، پیدا می‌کند. .sp این امر می‌تواند در برخی زمینه‌های چندنخی مشکلاتی ایجاد کند. به عنوان مثال، هنگام غیرفعال کردن دستورالعمل‌های همگام‌سازی تولید شده توسط کامپایلر برای متغیرهای ایستا که در زمان اجرا مقداردهی می‌شوند (مثلاً با \fB\-fno\-threadsafe\-statics\fP)، حتی اگر یک پروژه خاص اقدامات احتیاطی لازم را برای جلوگیری از شرایط مسابقه (race conditions) در طول مقداردهی اولیه با ارائه همگام‌سازی اختصاصی خود انجام دهد، فایل‌های هدر گنجانده‌شده از پروژه‌های دیگر ممکن است این کار را نکنند. بنابراین، چنین بررسی‌ای برای اطمینان از اینکه غیرفعال کردن همگام‌سازی تولید شده توسط کامپایلر برای مقداردهی متغیرهای ایستا مشکلی ایجاد نمی‌کند، مفید است. .sp کد زیر را در نظر بگیرید: .INDENT 0.0 .INDENT 3.5 .sp .EX int foo() { static int k = bar(); return k; } .EE .UNINDENT .UNINDENT .sp هنگامی که همگام‌سازی مقداردهی اولیه متغیرهای ایستا غیرفعال باشد، اگر دو نخ هر دو تابع \fIfoo\fP را برای اولین بار فراخوانی کنند، این احتمال وجود دارد که \fIk\fP دو بار مقداردهی اولیه شود و یک شرایط مسابقه ایجاد گردد. .SS bugprone\-easily\-swappable\-parameters .sp تعاریف توابعی را پیدا می‌کند که در آن‌ها پارامترهایی از انواع قابل تبدیل مستقیماً پشت سر هم قرار گرفته‌اند، که این امر فراخوانی‌ها را مستعد ارسال آرگومان‌ها با ترتیب جابه‌جا شده (یا نادرست) می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX void drawPoint(int X, int Y) { /* ... */ } FILE *open(const char *Dir, const char *Name, Flags Mode) { /* ... */ } .EE .UNINDENT .UNINDENT .sp یک فراخوانی احتمالی مانند \fBdrawPoint(\-2, 5)\fP یا \fBopenPath(\(dqa.txt\(dq, \(dqtmp\(dq, Read)\fP از نظر زبان کاملاً معتبر است، اما ممکن است مد نظر توسعه‌دهنده تابع نبوده باشد. .sp برای جلوگیری از ترتیب اشتباه آرگومان‌ها، باید از ساختارهای دقیق‌تر و نوع‌امن‌تر (type\-safe)، مانند opaque typedefها یا انواع قوی (strong types) استفاده شود. .INDENT 0.0 .INDENT 3.5 .sp .EX struct Coord2D { int X; int Y; }; void drawPoint(const Coord2D Pos) { /* ... */ } FILE *open(const Path &Dir, const Filename &Name, Flags Mode) { /* ... */ } .EE .UNINDENT .UNINDENT .sp به دلیل بازسازی کد (refactoring) بالقوه پیچیده و شکستن احتمالی API که برای تقویت ایمنی انواع در یک پروژه ضروری است، هیچ اصلاح خودکاری (fix\-its) ارائه نمی‌شود. .SS گزینه‌ها .SS گزینه‌های گسترش/تسهیل .sp گزینه‌های تسهیل (یا گسترش) می‌توانند برای وسیع‌تر کردن دامنهٔ تحلیل و تنظیم دقیق فعال‌سازی ترکیب‌های بیشتر میان انواع داده به کار روند. برخی از ترکیب‌ها ممکن است به شیوهٔ کدنویسی یا ترجیحات خاص یک پروژه وابسته باشند، با این حال باید توجه داشت که فعال کردن \fIتمام\fP این تسهیل‌ها بیشترین انطباق را با شیوهٔ جابه‌جایی در فراخوانی‌ها مدل‌سازی می‌کند. انتظار می‌رود این گزینه‌ها موجب شوند بررسی برای توابع بیشتری گزارش دهد و دامنه‌های قابل جابه‌جایی طولانی‌تری را پوشش دهد. .INDENT 0.0 .TP .B QualifiersMix آیا پارامترهای دارای یک نوع با مشخصه‌های \fIcvr\-qualified\fP و نوع \fBT\fP با مشخصه‌های \fIcvr\-qualified\fP متفاوت (مثلاً \fBT\fP و \fBconst T\fP، \fBconst T\fP و \fBvolatile T\fP و غیره) قابل جابه‌جایی با یکدیگر در نظر گرفته شوند یا خیر. اگر \fIfalse\fP باشد، بررسی، انواع دارای مشخصه‌های متفاوت را غیرقابل جابه‌جایی در نظر می‌گیرد. مقدار \fITrue\fP هشدارها را فعال می‌کند. پیش‌فرض \fIfalse\fP است\&. .sp مثال زیر تنها در صورتی یک گزارش عیب‌یابی تولید می‌کند که \fIQualifiersMix\fP فعال باشد: .INDENT 7.0 .INDENT 3.5 .sp .EX void *memcpy(const void *Destination, void *Source, std::size_t N) { /* ... */ } .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B ModelImplicitConversions آیا پارامترهایی از نوع \fBT\fP و \fBU\fP در صورتی که تبدیل ضمنی (implicit conversion) از \fBT\fP به \fBU\fP و از \fBU\fP به \fBT\fP وجود داشته باشد، قابل جابه‌جایی در نظر گرفته شوند یا خیر\&. اگر \fIfalse\fP باشد، بررسی انواع دارای قابلیت تبدیل ضمنی را برای جابه‌جایی در نظر نمی‌گیرد. مقدار \fITrue\fP هشدارها را برای تبدیل‌های ضمنی فعال می‌کند. پیش‌فرض \fItrue\fP است\&. .sp مثال‌های زیر تنها در صورتی یک گزارش عیب‌یابی تولید می‌کنند که \fIModelImplicitConversions\fP فعال باشد: .INDENT 7.0 .INDENT 3.5 .sp .EX void fun(int Int, double Double) { /* ... */ } void compare(const char *CharBuf, std::string String) { /* ... */ } .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 7.0 .INDENT 3.5 تغییر مشخصه‌های نوع یک عبارت (مثلاً از \fBint\fP به \fBconst int\fP) در استاندارد C++ به عنوان یک \fIimplicit conversion\fP تعریف شده است. با این حال، این بررسی تصمیم‌گیری دربارهٔ قابلیت جابه‌جایی انواع دارای مشخصه‌های متفاوت را بر اساس فعال بودن یا نبودن \fIQualifiersMix\fP تفکیک می‌کند. .sp برای نمونه، قطعه‌کد زیر تنها در صورتی یک پیام عیب‌یابی تولید می‌کند که \fBهر دوی\fP گزینه‌های \fIQualifiersMix\fP و \fIModelImplicitConversions\fP فعال باشند: .INDENT 0.0 .INDENT 3.5 .sp .EX void fun2(int Int, const double Double) { /* ... */ } .EE .UNINDENT .UNINDENT .UNINDENT .UNINDENT .UNINDENT .SS گزینه‌های فیلترسازی .sp گزینه‌های فیلترسازی می‌توانند برای کاهش حجم گزارش‌های عیب‌یابی ارائه‌شده توسط بررسی‌کننده به کار روند؛ خواه هدف نادیده گرفتن ساختارهای خاص باشد یا کاستن از هشدارهای ناخواسته (نویز). .INDENT 0.0 .TP .B MinimumLength حداقل طول مورد نیاز برای یک توالی از پارامترهای مجاور جهت قرار گرفتن در گزارش عیب‌یابی. پیش‌فرض \fI2\fP است\&. می‌تواند هر عدد صحیح مثبت بزرگ‌تر یا مساوی با \fI2\fP باشد\&. اگر \fI0\fP یا \fI1\fP مشخص شود، مقدار پیش‌فرض \fI2\fP به جای آن استفاده خواهد شد. .sp برای نمونه، اگر \fI3\fP تعیین شود، مثال‌های بالا مطابقت داده نخواهند شد. .UNINDENT .INDENT 0.0 .TP .B IgnoredParameterNames فهرستی از \fBنام‌های\fP پارامتر که هرگز نباید بخشی از یک توالی پارامترهای مجاور قابل جابه‌جایی در نظر گرفته شوند. این مقدار، فهرستی از نام‌هاست که با \fI;\fP جدا شده‌اند. برای نادیده گرفتن پارامترهای بدون نام، \fI\(dq\(dq\fP را به صورت لفظی به فهرست اضافه کنید (نه رشتهٔ خالی، بلکه دو علامت نقل‌قول، احتمالاً با نویسهٔ گریز!). \fBاین گزینه به حروف کوچک و بزرگ حساس است!\fP .sp به صورت پیش‌فرض، نام‌های پارامتر زیر و نگارش‌های آن‌ها با حروف آغازین بزرگ نادیده گرفته می‌شوند: \fI\(dq\(dq\fP (پارامترهای بدون نام)، \fIiterator\fP، \fIbegin\fP، \fIend\fP، \fIfirst\fP، \fIlast\fP، \fIlhs\fP، \fIrhs\fP\&. .UNINDENT .INDENT 0.0 .TP .B IgnoredParameterTypeSuffixes فهرستی از \fBپسوندهای نام نوع\fP پارامتر که هرگز نباید بخشی از یک توالی پارامترهای مجاور قابل جابه‌جایی در نظر گرفته شوند. پارامترهایی که نوع آن‌ها، همان‌طور که در کد منبع نوشته شده، با یکی از موارد این گزینه پایان یابد، نادیده گرفته خواهند شد. این مقدار، فهرستی از نام‌هاست که با \fI;\fP جدا شده‌اند. \fBاین گزینه به حروف کوچک و بزرگ حساس است!\fP .sp به صورت پیش‌فرض، موارد زیر و نگارش‌های آن‌ها با حروف آغازین کوچک نادیده گرفته می‌شوند: \fIbool\fP، \fIIt\fP، \fIIterator\fP، \fIInputIt\fP، \fIForwardIt\fP، \fIBidirIt\fP، \fIRandomIt\fP، \fIrandom_iterator\fP، \fIReverseIt\fP، \fIreverse_iterator\fP، \fIreverse_const_iterator\fP، \fIRandomIt\fP، \fIrandom_iterator\fP، \fIReverseIt\fP، \fIreverse_iterator\fP، \fIreverse_const_iterator\fP، \fIConst_Iterator\fP، \fIConstIterator\fP، \fIconst_reverse_iterator\fP، \fIConstReverseIterator\fP\&. علاوه بر این، \fI_Bool\fP (اما نه \fI_bool\fP) نیز بخشی از مقدار پیش‌فرض است. .UNINDENT .INDENT 0.0 .TP .B SuppressParametersUsedTogether هشدارهای عیب‌یابی مربوط به پارامترهایی را که در بدنهٔ تابع همراه با یکدیگر یا به شیوه‌ای مشابه به کار رفته‌اند، سرکوب می‌کند. پیش‌فرض \fItrue\fP است\&. مشخص کردن \fIfalse\fP این قواعد تجربی (heuristics) را غیرفعال می‌کند. .sp در حال حاضر، قواعد تجربی زیر پیاده‌سازی شده‌اند که هشدار مربوط به جفت پارامتر مربوطه را متوقف خواهند کرد: .INDENT 7.0 .IP \(bu 2 پارامترها در یک عبارت مشابه استفاده شده باشند؛ مثلاً \fBf(a, b)\fP یا \fBa < b\fP\&. .IP \(bu 2 پارامترها مجدداً به همان تابع و به پارامتر یکسانی از آن تابع، با همان بارگذاری بیش‌ازحد (overload) یکسان ارسال شده باشند. مثلاً \fBf(a, 1)\fP و \fBf(b, 2)\fP به تابعی مانند \fBf(T, int)\fP\&. .sp \fBنکته:\fP .INDENT 2.0 .INDENT 3.5 این بررسی، تحلیل وابسته به مسیر (path-sensitive) انجام نمی‌دهد و از این رو، «تابع یکسان» در این زمینه به معنای اعلان تابع یکسان است. اگر تابع عضو یکسانی از یک نوع روی دو نمونهٔ متمایز با این پارامترها فراخوانی شود، همچنان به عنوان «تابع یکسان» تلقی خواهد شد. .UNINDENT .UNINDENT .IP \(bu 2 فیلد عضو یکسانی مورد دسترسی قرار گیرد، یا متد عضو یکسانی از آن دو پارامتر فراخوانی شود؛ مثلاً \fBa.foo()\fP و \fBb.foo()\fP\&. .IP \(bu 2 دستورهای \fBreturn\fP جداگانه هر یک از پارامترها را در مسیرهای مختلف کد بازگردانند. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B NamePrefixSuffixSilenceDissimilarityThreshold تعداد نویسه‌هایی که دو نام پارامتر ممکن است در \fIابتدا\fP یا \fIانتها\fP با یکدیگر تفاوت داشته باشند در حالی که بقیهٔ نام یکسان باشد، به گونه‌ای که هشدار مربوط به آن دو پارامتر متوقف شود. پیش‌فرض \fI1\fP است\&. می‌تواند هر عدد صحیح مثبت باشد. اگر \fI0\fP باشد، قاعدهٔ تجربی فیلترسازی بر اساس نام پارامترها غیرفعال می‌شود. .sp این گزینه می‌تواند برای متوقف کردن هشدارهای مربوط به پارامترهایی استفاده شود که روش نام‌گذاری آن‌ها نشان می‌دهد ترتیب قرارگیری آن‌ها اهمیتی ندارد. .sp برای نمونه، پارامترهای \fBLHS\fP و \fBRHS\fP پسوندهای با ۱ نویسه غیرمشابه نسبت به یکدیگر هستند: \fBL\fP و \fBR\fP نویسه‌های متفاوت هستند، در حالی که \fBHS\fP پسوند مشترک است. به طور مشابه، پارامترهای \fBtext1, text2, text3\fP پیشوندهایی با ۱ نویسه تفاوت نسبت به یکدیگرند، که اعداد انتهایی بخش غیرمشابه را تشکیل می‌دهند. اگر این مقدار حداقل \fI1\fP باشد، چنین مواردی گزارش نخواهند شد. .UNINDENT .SS محدودیت‌ها .sp \fBاین بررسی برای بررسی امضای توابع (function signatures) طراحی شده است!\fP .sp این بررسی توابعی را که توسط کامپایلر در زمینه‌ای تولید می‌شوند که فقط از محل فراخوانی مشخص است، مورد بررسی قرار نمی‌دهد. این موارد شامل توابع چندآرگومانی (variadic)، توابع در کد C که فاقد فهرست آرگومان هستند، و نمونه‌سازی‌های قالب C++ می‌شوند. بیشتر این موارد، که در غیر این صورت از دید فراخواننده قابل جابجایی هستند، هیچ راهی برای \(dqاصلاح شدن\(dq در نقطه تعریف ندارند. در مورد قالب‌های C++، فقط تعاریف اصلی قالب و تخصیص‌های صریح (explicit specializations) مطابقت داده شده و تحلیل می‌شوند. .sp هیچ‌یک از موارد زیر هشداری (diagnostic) ایجاد نمی‌کنند: .INDENT 0.0 .INDENT 3.5 .sp .EX int printf(const char *Format, ...) { /* ... */ } int someOldCFunction() { /* ... */ } template int add(T X, U Y) { return X + Y }; void theseAreNotWarnedAbout() { printf(\(dq%d %d\en\(dq, 1, 2); // Two ints passed, they could be swapped. someOldCFunction(1, 2, 3); // Similarly, multiple ints passed. add(1, 2); // Instantiates \(aqadd\(aq, but that\(aqs not a user\-defined function. } .EE .UNINDENT .UNINDENT .sp با توجه به محدودیت بالا، پارامترهایی که نوع آن‌ها برای \fIاثبات\fP اختلاط با نوع پارامتر دیگر همچنان به نمونه‌سازی‌های قالب وابسته است، بررسی نمی‌شوند. .INDENT 0.0 .INDENT 3.5 .sp .EX template struct Vector { typedef T element_type; }; // Diagnosed: Explicit instantiation was done by the user, we can prove it // is the same type. void instantiated(int A, Vector::element_type B) { /* ... */ } // Diagnosed: The two parameter types are exactly the same. template void exact(typename Vector::element_type A, typename Vector::element_type B) { /* ... */ } // Skipped: The two parameters are both \(aqT\(aq but we cannot prove this // without actually instantiating. template void falseNegative(T A, typename Vector::element_type B) { /* ... */ } .EE .UNINDENT .UNINDENT .sp در زمینه \fIتبدیل‌های ضمنی\fP (هنگامی که \fIModelImplicitConversions\fP فعال است)، مدل‌سازی انجام‌شده توسط این بررسی در صورتی هشدار می‌دهد که پارامترها قابل جابجایی باشند و ترتیب جابجاشده با تبدیل‌های ضمنی مطابقت داشته باشد. این بررسی مدل‌سازی نمی‌کند که آیا نوع سوم نامرتبطی وجود دارد که بتوان \fIهر دو\fP پارامتر را در یک فراخوانی تابع از آن نوع ارائه داد یا خیر. این بدان معناست که در مثال زیر، حتی با اینکه \fBstrs()\fP به وضوح امکان فراخوانی با آرگومان‌های جابجاشده را دارد (تا زمانی که آرگومان‌ها رشته‌های تحت‌اللفظی باشند)، هشداری درباره آن داده نخواهد شد. .INDENT 0.0 .INDENT 3.5 .sp .EX struct String { String(const char *Buf); }; struct StringView { StringView(const char *Buf); operator const char *() const; }; // Skipped: Directly swapping expressions of the two type cannot mix. // (Note: StringView \-> const char * \-> String would be **two** // user\-defined conversions, which is disallowed by the language.) void strs(String Str, StringView SV) { /* ... */ } // Diagnosed: StringView implicitly converts to and from a buffer. void cStr(StringView SV, const char *Buf() { /* ... */ } .EE .UNINDENT .UNINDENT .SS bugprone\-empty\-catch .sp مشکلات مربوط به دستورات catch خالی را شناسایی کرده و راهکارهایی برای رفع آن‌ها پیشنهاد می‌دهد. .INDENT 0.0 .INDENT 3.5 .sp .EX try { // Some code that can throw an exception } catch(const std::exception&) { } .EE .UNINDENT .UNINDENT .sp وجود دستورات catch خالی در پایگاه کد می‌تواند مشکل جدی باشد که توسعه‌دهندگان باید از آن آگاه باشند. دستورات catch برای مدیریت استثناهایی استفاده می‌شوند که در طول اجرای برنامه پرتاب می‌شوند. هنگامی که استثنایی رخ می‌دهد، برنامه به نزدیک‌ترین دستور catch که با نوع استثنا مطابقت دارد پرش می‌کند. .sp دستورات catch خالی، که با عنوان \(dqبلعیدن\(dq (swallowing) استثناها نیز شناخته می‌شوند، استثنا را دریافت می‌کنند اما کاری با آن انجام نمی‌دهند. این امر به این معنی است که استثنا به‌درستی مدیریت نشده و برنامه طوری به اجرای خود ادامه می‌دهد که گویی هیچ اتفاقی نیفتاده است. این وضعیت می‌تواند به چندین مشکل منجر شود، از جمله: .INDENT 0.0 .IP \(bu 2 \fIباگ‌های پنهان\fP: اگر استثنایی دریافت و نادیده گرفته شود، می‌تواند منجر به باگ‌های پنهانی شود که عیب‌یابی و رفع آن‌ها دشوار است. ممکن است علت اصلی مشکل آشکار نباشد و برنامه به رفتارهای غیرمنتظره ادامه دهد. .IP \(bu 2 \fImسائل امنیتی\fP: نادیده گرفتن استثناها می‌تواند منجر به مسائل امنیتی شود، مانند سرریز بافر یا ارجاع به اشاره‌گر تهی (null pointer dereferences). نفوذگران می‌توانند از این آسیب‌پذیری‌ها برای دستیابی به داده‌های حساس یا اجرای کدهای مخرب سوءاستفاده کنند. .IP \(bu 2 \fIکیفیت پایین کد\fP: دستورات catch خالی می‌توانند نشان‌دهنده کیفیت پایین کد و عدم توجه به جزئیات باشند. این مسئله نگهداری و به‌روزرسانی پایگاه کد را دشوار می‌سازد و به چرخه‌های طولانی‌تر توسعه و افزایش هزینه‌ها می‌انجامد. .IP \(bu 2 \fIکد غیرقابل اعتماد\fP: کدی که استثناها را نادیده می‌گیرد اغلب غیرقابل اعتماد است و می‌تواند منجر به رفتار غیرقابل پیش‌بینی شود. این امر می‌تواند موجب نارضایتی کاربران شده و اعتماد به نرم‌افزار را تضعیف کند. .UNINDENT .sp برای جلوگیری از این مشکلات، توسعه‌دهندگان باید همیشه استثناها را به‌درستی مدیریت کنند. این کار یا از طریق رفع مشکل اساسیِ ایجادکننده استثنا انجام می‌گیرد یا با انتشار (propagating) استثنا در پشته فراخوانی به یک مدیریت‌کننده سطح بالاتر. اگر استثنایی اهمیت چندانی ندارد، همچنان باید ثبت (log) شده یا به نوعی گزارش داده شود تا بتوان بعداً آن را پیگیری و برطرف نمود. .sp اگر استثنا چیزی است که می‌توان آن را به صورت محلی مدیریت کرد، باید درون همان بلوک catch مدیریت شود. این اقدام می‌تواند شامل لاگ کردن استثنا یا انجام عملیات مناسب دیگر باشد تا اطمینان حاصل شود که استثنا نادیده گرفته نشده است. .sp در اینجا یک مثال آورده شده است: .INDENT 0.0 .INDENT 3.5 .sp .EX try { // Some code that can throw an exception } catch (const std::exception& ex) { // Properly handle the exception, e.g.: std::cerr << \(dqException caught: \(dq << ex.what() << std::endl; } .EE .UNINDENT .UNINDENT .sp اگر استثنا نمی‌تواند به صورت محلی مدیریت شود و باید در پشته فراخوانی به بالا منتشر شود، باید مجدداً پرتاب (re\-thrown) شود یا استثنای جدیدی پرتاب گردد. .sp در اینجا یک مثال آورده شده است: .INDENT 0.0 .INDENT 3.5 .sp .EX try { // Some code that can throw an exception } catch (const std::exception& ex) { // Re\-throw the exception throw; } .EE .UNINDENT .UNINDENT .sp در برخی موارد، دریافت استثنا در این سطح ممکن است ضروری نباشد و مناسب‌تر باشد که اجازه داده شود استثنا در پشته فراخوانی به بالا منتشر شود. این کار به سادگی با استفاده نکردن از بلوک \fBtry/catch\fP قابل انجام است. .sp در اینجا یک مثال آورده شده است: .INDENT 0.0 .INDENT 3.5 .sp .EX void function() { // Some code that can throw an exception } void callerFunction() { try { function(); } catch (const std::exception& ex) { // Handling exception on higher level std::cerr << \(dqException caught: \(dq << ex.what() << std::endl; } } .EE .UNINDENT .UNINDENT .sp راهکار بالقوه دیگر برای جلوگیری از دستورات catch خالی، تغییر کد برای پیشگیری از پرتاب استثنا از همان ابتدا است. این هدف را می‌توان با استفاده از یک API متفاوت، بررسی شرایط خطا از پیش، یا مدیریت خطاها به روشی دیگر که شامل استثناها نباشد محقق کرد. با حذف نیاز به بلوک‌های try\-catch، کد ساده‌تر شده و کمتر مستعد خطا خواهد بود. .sp در اینجا یک مثال آورده شده است: .INDENT 0.0 .INDENT 3.5 .sp .EX // Old code: try { mapContainer[\(dqKey\(dq].callFunction(); } catch(const std::out_of_range&) { } // New code if (auto it = mapContainer.find(\(dqKey\(dq); it != mapContainer.end()) { it\->second.callFunction(); } .EE .UNINDENT .UNINDENT .sp در نتیجه، دستورات catch خالی رویه‌ای نادرست هستند که می‌توانند به باگ‌های پنهان، مشکلات امنیتی، کیفیت پایین کد و کدهای غیرقابل اعتماد منجر شوند. توسعه‌دهندگان با مدیریت صحیح استثناها می‌توانند مطمئن شوند که کد آن‌ها پایدار، امن و قابل نگهداری است. .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoreCatchWithKeywords این گزینه می‌تواند برای نادیده گرفتن دستورهای catch خاص حاوی کلیدواژه‌های مشخص استفاده شود. اگر بدنه یک دستور \fBcatch\fP (بدون حساسیت به حروف کوچک و بزرگ) شامل هر یک از کلیدواژه‌های ذکر شده در این گزینه جداشده با نقطه‌ویرگول (semicolon) باشد، آنگاه catch نادیده گرفته شده و هیچ هشداری صادر نخواهد شد. مقدار پیش‌فرض: \fI@TODO;@FIXME\fP\&. .UNINDENT .INDENT 0.0 .TP .B AllowEmptyCatchForExceptions این گزینه می‌تواند برای نادیده گرفتن دستورهای catch خالی برای انواع استثنای مشخص استفاده شود. به‌طور پیش‌فرض، این بررسی در صورت شناسایی یک دستور catch خالی، بدون در نظر گرفتن نوع استثنای دریافت‌شده، یک هشدار صادر می‌کند. با این حال، در شرایط خاص، مانند زمانی که توسعه‌دهنده می‌خواهد عمداً برخی استثناها را نادیده بگیرد یا آن‌ها را به روش دیگری مدیریت کند، ممکن است مجاز دانستن دستورهای catch خالی برای انواع استثنای خاص مطلوب باشد. برای پیکربندی این گزینه، باید فهرستی از نام‌های انواع استثنا که با نقطه‌ویرگول جدا شده‌اند ارائه شود. اگر نوع یک استثنا در این فهرست در یک دستور catch خالی دریافت شود، هیچ هشداری صادر نخواهد شد. مقدار پیش‌فرض: رشته خالی. .UNINDENT .SS bugprone\-exception\-copy\-constructor\-throws .sp بررسی می‌کند که آیا سازنده رونوشت (copy constructor) یک شیء پرتاب‌شده می‌تواند استثنا پرتاب کند یا خیر. .sp اشیاء استثنا در C++ ملزم هستند که قابل ساخت با رونوشت (copy constructible) باشند. با این حال، سازنده رونوشت یک استثنا برای جلوگیری از مشکلات احتمالی هنگام بازپیچی پشته (stack unwinding) نباید استثنا پرتاب کند. اگر در حین بازپیچی پشته استثنایی پرتاب شود (مانند سازنده رونوشت یک شیء استثنا)، برنامه از طریق \fBstd::terminate\fP خاتمه می‌یابد. .INDENT 0.0 .INDENT 3.5 .sp .EX class SomeException { public: SomeException() = default; SomeException(const SomeException&) { /* may throw */ } }; void f() { throw SomeException(); // warning: thrown exception type\(aqs copy constructor can throw } .EE .UNINDENT .UNINDENT .SS مراجع .sp این بررسی مطابق با قاعده استاندارد کدنویسی CERT C++ به شماره ERR60\-CPP است: Exception objects must be nothrow copy constructible \%\&. .SS bugprone\-exception\-escape .sp توابعی را پیدا می‌کند که ممکن است به‌طور مستقیم یا غیرمستقیم استثنا پرتاب کنند، در حالی که نباید این کار را انجام دهند. توابعی که نباید استثنا پرتاب کنند به شرح زیر هستند: .INDENT 0.0 .IP \(bu 2 مخرب‌ها (Destructors) .IP \(bu 2 سازنده‌های انتقال (Move constructors) .IP \(bu 2 عملگرهای انتساب انتقال (Move assignment operators) .IP \(bu 2 توابع \fBmain()\fP .IP \(bu 2 توابع \fBswap()\fP .IP \(bu 2 توابع \fBiter_swap()\fP .IP \(bu 2 توابع \fBiter_move()\fP .IP \(bu 2 توابع علامت‌گذاری‌شده با \fBthrow()\fP یا \fBnoexcept\fP .IP \(bu 2 سایر توابع مشخص‌شده به عنوان گزینه .UNINDENT .sp پرتاب استثنا توسط یک مخرب ممکن است منجر به رفتار تعریف‌نشده (undefined behavior)، نشت منابع یا خاتمه غیرمنتظره برنامه شود. سازنده انتقال یا انتساب انتقال پرتاب‌کننده استثنا نیز ممکن است منجر به رفتار تعریف‌نشده یا نشت منابع شود. عملیات‌های \fBswap()\fP در اکثر موارد انتظار می‌رود که بدون پرتاب استثنا باشند و همیشه پیاده‌سازی آن‌ها به صورت بدون پرتاب استثنا امکان‌پذیر است. از عملیات‌های \fBswap()\fP بدون پرتاب استثنا برای ساخت عملیات‌های انتقال نیز استفاده می‌شود. یک تابع \fBmain()\fP پرتاب‌کننده استثنا نیز منجر به خاتمه غیرمنتظره می‌شود. .sp توابعی که صراحتاً با \fBnoexcept(false)\fP یا \fBthrow(exception)\fP تعریف شده‌اند، از تحلیل کنار گذاشته می‌شوند، زیرا اگرچه برای توابعی مانند \fBswap()\fP، \fBmain()\fP، سازنده‌های انتقال، عملگرهای انتساب انتقال و مخرب‌ها توصیه نمی‌شود، اما نشان‌دهنده قصد صریح توسعه‌دهنده است و باید مورد احترام قرار گیرد. .sp هشدار! این بررسی ممکن است روی فایل‌های منبع بزرگ پرهزینه باشد. .SS گزینه‌ها .INDENT 0.0 .TP .B CheckDestructors وقتی برابر با \fItrue\fP باشد، مخرب‌ها تحلیل می‌شوند تا استثنا پرتاب نکنند. مقدار پیش‌فرض \fItrue\fP است\&. .UNINDENT .INDENT 0.0 .TP .B CheckMoveMemberFunctions وقتی برابر با \fItrue\fP باشد، سازنده‌های انتقال و عملگرهای انتساب انتقال تحلیل می‌شوند تا استثنا پرتاب نکنند. مقدار پیش‌فرض \fItrue\fP است\&. .UNINDENT .INDENT 0.0 .TP .B CheckMain وقتی برابر با \fItrue\fP باشد، تابع \fBmain()\fP تحلیل می‌شود تا استثنا پرتاب نکند. مقدار پیش‌فرض \fItrue\fP است\&. .UNINDENT .INDENT 0.0 .TP .B CheckNothrowFunctions وقتی برابر با \fItrue\fP باشد، توابع علامت‌گذاری‌شده با مشخصات استثنای \fBnoexcept\fP یا \fBthrow()\fP تحلیل می‌شوند تا استثنا پرتاب نکنند. مقدار پیش‌فرض \fItrue\fP است\&. .UNINDENT .INDENT 0.0 .TP .B CheckedSwapFunctions فهرستی جداشده با کاما از نام‌های توابع swap که نباید استثنا پرتاب کنند. مقدار پیش‌فرض \fIswap,iter_swap,iter_move\fP است\&. .UNINDENT .INDENT 0.0 .TP .B FunctionsThatShouldNotThrow فهرستی جداشده با کاما شامل نام‌های توابعی که نباید استثنا پرتاب کنند. یک مقدار نمونه برای این پارامتر می‌تواند \fBWinMain\fP باشد که تابع \fBWinMain()\fP در Windows API را به فهرست توابعی که نباید استثنا پرتاب کنند اضافه می‌کند. مقدار پیش‌فرض یک رشته خالی است. .UNINDENT .INDENT 0.0 .TP .B IgnoredExceptions فهرستی جداشده با کاما شامل نام‌های انواعی که در بررسی به عنوان استثناهای پرتاب‌شده به حساب نمی‌آیند. مقدار پیش‌فرض یک رشته خالی است. .UNINDENT .SS bugprone\-float\-loop\-counter .sp حلقه‌های \fBfor\fP که عبارت استقرای (induction expression) آن‌ها از نوع ممیز شناور (floating\-point) است را نشانه‌گذاری می‌کند. .SS مراجع .sp این بررسی مطابق با قاعده استاندارد کدنویسی CERT C به شماره FLP30\-C است: Do not use floating\-point variables as loop counters \%\&. .SS bugprone\-fold\-init\-type .sp این بررسی عدم تطابق نوع را در عملیات‌های فولد \% مانند \fBstd::accumulate\fP که ممکن است منجر به از دست رفتن دقت شود، نشانه‌گذاری می‌کند. تابع \fBstd::accumulate\fP یک محدوده ورودی را با استفاده از نوع مقدار اولیه به یک مقدار با کمک \fBoperator+\fP به‌طور پیش‌فرض تبدیل (fold) می‌کند. این کار می‌تواند منجر به از دست رفتن دقت از راه‌های زیر شود: .INDENT 0.0 .IP \(bu 2 کوتاه‌سازی (Truncation): کد زیر از یک محدوده ممیز شناور و یک مقدار اولیه int استفاده می‌کند، بنابراین کوتاه‌سازی در هر بار اعمال \fBoperator+\fP رخ می‌دهد و نتیجه \fI0\fP خواهد بود که ممکن است با انتظار کاربر مطابقت نداشته باشد. .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX auto a = {0.5f, 0.5f, 0.5f, 0.5f}; return std::accumulate(std::begin(a), std::end(a), 0); .EE .UNINDENT .UNINDENT .INDENT 0.0 .IP \(bu 2 سرریز (Overflow): کد زیر نیز مقدار \fI0\fP را برمی‌گرداند\&. .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX auto a = {65536LL * 65536 * 65536}; return std::accumulate(std::begin(a), std::end(a), 0); .EE .UNINDENT .UNINDENT .SS bugprone\-forward\-declaration\-namespace .sp بررسی می‌کند که آیا یک اعلان پیشاپیش (forward declaration) استفاده‌نشده در یک فضای نام (namespace) اشتباه قرار دارد یا خیر. .sp این بررسی تمام اعلان‌های پیشاپیش استفاده‌نشده را بازرسی کرده و وجود هرگونه اعلان/تعریف هم‌نام دیگر را بررسی می‌کند؛ موضوعی که می‌تواند نشان‌دهنده آن باشد که اعلان پیشاپیش در یک فضای نام بالقوه اشتباه قرار گرفته است. .INDENT 0.0 .INDENT 3.5 .sp .EX namespace na { struct A; } namespace nb { struct A {}; } nb::A a; // warning : no definition found for \(aqA\(aq, but a definition with the same name // \(aqA\(aq found in another namespace \(aqnb::\(aq .EE .UNINDENT .UNINDENT .sp این بررسی تنها می‌تواند هشدار تولید کند، اما در حال حاضر نمی‌تواند اصلاح خودکاری پیشنهاد دهد. .SS bugprone\-forwarding\-reference\-overload .sp این بررسی به دنبال سازنده‌های ارجاع بازپخش کامل (perfect forwarding) می‌گردد که می‌توانند سازنده‌های رونوشت (copy) یا انتقال (move) را پنهان (hide) کنند. اگر یک ارجاع lvalue غیر const به سازنده ارسال شود، پارامتر ارجاع بازپخش تطابق بهتری نسبت به پارامتر ارجاع const سازنده رونوشت خواهد داشت؛ بنابراین سازنده perfect forwarding فراخوانی می‌شود که می‌تواند سردرگم‌کننده باشد. برای توضیحات دقیق درباره این موضوع، به این منبع مراجعه کنید: Scott Meyers, Effective Modern C++, بخش ۲۶. .sp مثال زیر را در نظر بگیرید: .INDENT 0.0 .INDENT 3.5 .sp .EX class Person { public: // C1: perfect forwarding ctor template explicit Person(T&& n) {} // C2: perfect forwarding ctor with parameter default value template explicit Person(T&& n, int x = 1) {} // C3: perfect forwarding ctor guarded with enable_if template, void>> explicit Person(T&& n) {} // C4: variadic perfect forwarding ctor guarded with enable_if template, A&&...>, int> = 0> explicit Person(A&&... a) {} // C5: perfect forwarding ctor guarded with requires expression template requires requires { is_special; } explicit Person(T&& n) {} // C6: perfect forwarding ctor guarded with concept requirement template explicit Person(T&& n) {} // (possibly compiler generated) copy ctor Person(const Person& rhs); }; .EE .UNINDENT .UNINDENT .sp این بررسی برای سازنده‌های C1 و C2 هشدار صادر می‌کند، زیرا این موارد می‌توانند سازنده‌های رونوشت و انتقال را پنهان کنند. در صورتی که هر دو سازنده رونوشت و انتقال غیرفعال باشند (حذف‌شده یا private)، هشدارها متوقف می‌شوند، زیرا در این حالت چیزی وجود ندارد که سازنده perfect forwarding بتواند آن را پنهان کند. همچنین هشدارها برای سازنده‌هایی مانند C3\-C6 که توسط \fBenable_if\fP یا یک concept محافظت شده‌اند متوقف می‌شوند، با این فرض که برنامه‌نویس از پنهان‌سازی احتمالی آگاه بوده است. .SS Background .sp برای تصمیم‌گیری در مورد اینکه آیا یک سازنده با enable_if محافظت شده است یا خیر، انواع پارامترهای سازنده، مقادیر پیش‌فرض پارامترهای نوع قالب و انواع پارامترهای غیرنوعی قالب با یک مقدار لفظی (literal) پیش‌فرض در نظر گرفته می‌شوند. اگر هر بخشی از این انواع \fBstd::enable_if\fP یا \fBstd::enable_if_t\fP باشد، فرض می‌کنیم که سازنده محافظت شده است. .SS bugprone\-implicit\-widening\-of\-multiplication\-result .sp این بررسی مواردی را عیب‌یابی می‌کند که در آن‌ها نتیجه یک ضرب به‌صورت ضمنی عریض‌تر (widen) می‌شود، و (همراه با fix\-it) پیشنهاد می‌دهد که یا با صریح کردن تبدیل عریض‌تر، هشدار کد بی‌اثر شود، یا عمل ضرب در یک نوع داده عریض‌تر انجام گیرد تا از عریض‌سازی پس از آن جلوگیری شود. .sp این بررسی عمدتاً هنگام کار با بافرهای بسیار بزرگ مفید است. به عنوان مثال، قطعه کد زیر را در نظر بگیرید: .INDENT 0.0 .INDENT 3.5 .sp .EX void zeroinit(char* base, unsigned width, unsigned height) { for(unsigned row = 0; row != height; ++row) { for(unsigned col = 0; col != width; ++col) { char* ptr = base + row * width + col; *ptr = 0; } } } .EE .UNINDENT .UNINDENT .sp این کد به‌طور کلی مشکلی ندارد، اما اگر حاصل \fBwidth * height\fP سرریز (overflow) کند، به جای پردازش کل بافر درخواستی، اشاره‌گر مجدداً به ابتدای \fBbase\fP برمی‌گردد (wrap back رخ می‌دهد). .sp در واقع، این موضوع تنها برای بافرهای بسیار بزرگ (۴ گیگابایت به بالا) اهمیت دارد، اما این حالت می‌تواند به‌راحتی مثلاً در پردازش تصویر رخ دهد؛ جایی که برای وقوع آن «تنها» به یک تصویر حدوداً ۲۶۹ مگاپیکسلی نیاز است. .SS گزینه‌ها .INDENT 0.0 .TP .B UseCXXStaticCastsInCppSources هنگام پیشنهاد اصلاحات (fix\-it) برای کدهای C++، آیا تبدیل‌های نوع به سبک C++ یعنی \fBstatic_cast<>()\fP پیشنهاد شوند یا تبدیل‌های نوع به سبک C. مقدار پیش‌فرض: \fItrue\fP\&. .UNINDENT .INDENT 0.0 .TP .B UseCXXHeadersInCppSources هنگام پیشنهاد الحاق هدر مناسب در کد C++، آیا هدر \fB\fP پیشنهاد شود یا \fB\fP\&. مقدار پیش‌فرض: \fItrue\fP\&. .UNINDENT .INDENT 0.0 .TP .B IgnoreConstantIntExpr اگر عملوندهای ضرب از نوع ثوابت زمان کامپایل باشند (مانند مقادیر مستقیم یا عبارات \fBconstexpr\fP) و در نوع عبارت مبدأ جا شوند، هیچ عیب‌یابی یا پیشنهاد اصلاحی ارائه نکن. این گزینه تنها عباراتی را در نظر می‌گیرد که عبارت مبدأ در آن‌ها یک نوع عدد صحیح علامت‌دار باشد. مقدار پیش‌فرض: \fIfalse\fP\&. .UNINDENT .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX long mul(int a, int b) { return a * b; // warning: performing an implicit widening conversion to type \(aqlong\(aq of a multiplication performed in type \(aqint\(aq } char* ptr_add(char *base, int a, int b) { return base + a * b; // warning: result of multiplication in type \(aqint\(aq is used as a pointer offset after an implicit widening conversion to type \(aqssize_t\(aq } char ptr_subscript(char *base, int a, int b) { return base[a * b]; // warning: result of multiplication in type \(aqint\(aq is used as a pointer offset after an implicit widening conversion to type \(aqssize_t\(aq } .EE .UNINDENT .UNINDENT .SS bugprone\-inaccurate\-erase .sp استفاده‌های نادرست از متد \fBerase()\fP را بررسی می‌کند. .sp الگوریتم‌هایی مانند \fBremove()\fP در عمل هیچ عنصری را از نگه‌دارنده (container) حذف نمی‌کنند، بلکه یک تکرارکننده (iterator) به اولین عنصر مازاد در انتهای نگه‌دارنده برمی‌گردانند. این عناصر مازاد باید با استفاده از متد \fBerase()\fP حذف شوند. این بررسی زمانی هشدار می‌دهد که به دلیل استفاده از یک سربارگذاری (overload) نامناسب، تمام عناصر حذف نشوند. .sp برای مثال، کد زیر فقط یک عنصر را حذف می‌کند: .INDENT 0.0 .INDENT 3.5 .sp .EX std::vector xs; \&... xs.erase(std::remove(xs.begin(), xs.end(), 10)); .EE .UNINDENT .UNINDENT .sp برای حذف این زیربازه، سربارگذاریِ دوآرگومانیِ \fBerase()\fP را فراخوانی کنید: .INDENT 0.0 .INDENT 3.5 .sp .EX std::vector xs; \&... xs.erase(std::remove(xs.begin(), xs.end(), 10), xs.end()); .EE .UNINDENT .UNINDENT .SS bugprone\-inc\-dec\-in\-conditions .sp مواردی را شناسایی می‌کند که یک متغیر درون یک شرط پیچیده هم افزایش/کاهش یافته و هم به آن ارجاع داده شده است، و پیشنهاد می‌دهد برای جلوگیری از ابهام در مقدار متغیر، این عملیات به بیرون منتقل شود. .sp هنگامی که یک متغیر تغییر داده شده و هم‌زمان در یک شرط پیچیده استفاده می‌شود، می‌تواند رفتارهای غیرمنتظره‌ای به همراه داشته باشد. اثر جانبی تغییر مقدار متغیر درون شرط می‌تواند تحلیل و درک کد را دشوار سازد. علاوه بر این، زمان‌بندی مد نظر توسعه‌دهنده برای اصلاح متغیر ممکن است نامشخص باشد و منجر به سوءتفاهم و خطا شود. این موضوع به‌ویژه زمانی که شرط شامل عملگرهای منطقی مانند \fB&&\fP و \fB||\fP باشد مشکل‌سازتر می‌شود، جایی که ترتیب ارزیابی شرایط را پیچیده‌تر می‌کند. .sp مثال زیر را در نظر بگیرید: .INDENT 0.0 .INDENT 3.5 .sp .EX int i = 0; // ... if (i++ < 5 && i > 0) { // do something } .EE .UNINDENT .UNINDENT .sp در این مثال، ممکن است نتیجه عبارت آن چیزی نباشد که توسعه‌دهنده قصد داشته است. قصد اولیه توسعه‌دهنده ممکن است افزایش \fBi\fP پس از ارزیابی کل شرط بوده باشد، اما در واقعیت، \fBi\fP پیش از اجرای \fBi > 0\fP افزایش خواهد یافت. این موضوع می‌تواند به رفتار غیرمنتظره و باگ‌ها در کد منجر شود. برای رفع این مشکل، توسعه‌دهنده باید عملیات افزایش را از شرط جدا کرده و به‌طور مستقل انجام دهد. به‌عنوان مثال، می‌تواند \fBi\fP را در یک دستور جداگانه قبل یا بعد از ارزیابی شرط افزایش دهد. این کار تضمین می‌کند که مقدار \fBi\fP در سراسر کد قابل پیش‌بینی و پایدار باشد. .INDENT 0.0 .INDENT 3.5 .sp .EX int i = 0; // ... i++; if (i <= 5 && i > 0) { // do something } .EE .UNINDENT .UNINDENT .sp یک مشکل رایج دیگر زمانی رخ می‌دهد که چندین عمل افزایش یا کاهش روی همان متغیر درون یک شرط پیچیده انجام شود. به عنوان مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX int i = 4; // ... if (i++ < 5 || \-\-i > 2) { // do something } .EE .UNINDENT .UNINDENT .sp به دلیل ترتیب ارزیابی در C++ یک مشکل بالقوه در این کد وجود دارد. عملگر \fB||\fP استفاده‌شده در عبارت شرط تضمین می‌کند که اگر عملوند اول برابر با \fBtrue\fP ارزیابی شود، عملوند دوم ارزیابی نخواهد شد. این بدان معناست که اگر \fBi\fP در ابتدا \fB4\fP باشد، عملوند اول یعنی \fBi < 5\fP مقدار \fBtrue\fP خواهد داشت و عملوند دوم یعنی \fBi > 2\fP ارزیابی نخواهد شد. در نتیجه، عملیات کاهش \fB\-\-i\fP اجرا نخواهد شد و \fBi\fP مقدار \fB5\fP را نگه می‌دارد، که ممکن است رفتار مورد نظر توسعه‌دهنده نباشد. .sp برای جلوگیری از این مشکل بالقوه، هر دو عملیات افزایش و کاهش روی \fBi\fP باید به خارج از عبارت شرط منتقل شوند. .SS bugprone\-incorrect\-enable\-if .sp استفاده‌های نادرست از \fBstd::enable_if\fP را که نوع تودرتوی \fBtype\fP را نام نمی‌برند، تشخیص می‌دهد. .sp در C++11 ویژگی \fBstd::enable_if\fP به عنوان روشی مناسب برای بهره‌گیری از SFINAE معرفی شد. یکی از روش‌های استفاده از \fBstd::enable_if\fP، تعریف یک پارامتر نوع قالب بی‌نام با نوع پیش‌فرض برابر با \fBtypename std::enable_if::type\fP است. اگر نویسنده نام بردن نوع تودرتوی \fBtype\fP را فراموش کند، کد همیشه قالب کاندید را مد نظر قرار می‌دهد، حتی اگر شرط برقرار نباشد. .sp در زیر نمونه‌هایی از کدهایی که به درستی از \fBstd::enable_if\fP استفاده می‌کنند و نمونه‌های نادرستی که توسط این بررسی پرچم‌گذاری می‌شوند، آمده است. .INDENT 0.0 .INDENT 3.5 .sp .EX template ::type> void valid_usage() { ... } template > void valid_usage_with_trait_helpers() { ... } // The below code is not a correct application of SFINAE. Even if // T::some_trait is not true, the function will still be considered in the // set of function candidates. It can either incorrectly select the function // when it should not be a candidates, and/or lead to hard compile errors // if the body of the template does not compile if the condition is not // satisfied. template > void invalid_usage() { ... } // The tool suggests the following replacement for \(aqinvalid_usage\(aq: template ::type> void fixed_invalid_usage() { ... } .EE .UNINDENT .UNINDENT .sp در C++14 ویژگی کمکی \fBstd::enable_if_t\fP معرفی شد که احتمال بروز این خطا را کاهش می‌دهد. C++20 قیود (constraints) را معرفی می‌کند که به‌طور کلی جایگزین استفاده از \fBstd::enable_if\fP می‌شوند. برای ابزار دیگری که \fBstd::enable_if\fP را با \fBstd::enable_if_t\fP جایگزین می‌کند به modernize\-type\-traits \%<> مراجعه کنید، و برای ابزاری که \fBstd::enable_if\fP را با قیود C++20 جایگزین می‌سازد به modernize\-use\-constraints \%<> رجوع کنید. در صورت امکان استفاده از این سازوکارهای جدیدتر را مد نظر قرار دهید. .SS bugprone\-incorrect\-enable\-shared\-from\-this .sp کلاس‌ها یا ساختارهایی را که به‌صورت عمومی (\fBpublic\fP) از \fBstd::enable_shared_from_this\fP ارث‌بری نمی‌کنند شناسایی می‌کند، چرا که در غیر این صورت هنگام فراخوانی \fBshared_from_this\fP رفتارهای ناخواسته‌ای رخ خواهد داد. .sp کد زیر را در نظر بگیرید: .INDENT 0.0 .INDENT 3.5 .sp .EX #include // private inheritance class BadExample : std::enable_shared_from_this { // \(ga\(gashared_from_this\(ga\(ga\(ga unintended behaviour // \(galibstdc++\(ga implementation returns uninitialized \(ga\(gaweak_ptr\(ga\(ga public: BadExample* foo() { return shared_from_this().get(); } void bar() { return; } }; void using_not_public() { auto bad_example = std::make_shared(); auto* b_ex = bad_example\->foo(); b_ex\->bar(); } .EE .UNINDENT .UNINDENT .sp با استفاده از پیاده‌سازی \fIlibstdc++\fP، فراخوانی \fBshared_from_this\fP استثنای \fBstd::bad_weak_ptr\fP را صادر می‌کند. هنگام فراخوانی \fBusing_not_public()\fP، این کد در صورت عدم مدیریت استثنا، کرش خواهد کرد. .SS bugprone\-incorrect\-roundings .sp استفاده از الگوهایی را بررسی می‌کند که به ایجاد گرد کردن‌های نادرست شناخته شده‌اند. برنامه‌نویسان اغلب از الگوی زیر استفاده می‌کنند: .INDENT 0.0 .INDENT 3.5 .sp .EX (int)(double_expression + 0.5) .EE .UNINDENT .UNINDENT .sp تا عبارت ممیز شناور مضاعف (double) را به یک عدد صحیح گرد کنند. مشکل این روش عبارت است از: .INDENT 0.0 .IP 1. 3 به‌طور غیرضروری کُند است. .IP 2. 3 نادرست است. عدد 0.499999975 (کوچک‌ترین عدد شناور قابل بازنمایی کمتر از 0.5) به 1.0 گرد می‌شود. رفتار برای اعداد منفی حتی بدتر است، به‌طوری که هر دو مقدار \-0.5f و \-1.4f به 0.0 گرد می‌شوند. .UNINDENT .SS bugprone\-infinite\-loop .sp حلقه‌های بی‌نهایت آشکار را پیدا می‌کند (حلقه‌هایی که در آن‌ها متغیر شرط حلقه اصلاً تغییر نمی‌کند). .sp مشخص است که یافتن کلی حلقه‌های بی‌نهایت از نظر تئوری غیرممکن است (مسئله توقف یا Halting Problem). با این حال، می‌توان برخی از حلقه‌های بی‌نهایت واضح را شناسایی کرد، برای نمونه زمانی که شرط حلقه تغییر نمی‌کند. این بررسی چنین حلقه‌هایی را شناسایی می‌کند. یک حلقه در صورتی بی‌نهایت در نظر گرفته می‌شود که فاقد هرگونه دستور خروج از حلقه (\fBbreak\fP، \fBcontinue\fP، \fBgoto\fP، \fBreturn\fP، \fBthrow\fP یا فراخوانی تابعی با ویژگی \fB[[noreturn]]\fP) باشد و تمامی شرایط زیر برای تک‌تک متغیرهای موجود در شرط برقرار باشد: .INDENT 0.0 .IP \(bu 2 یک متغیر محلی باشد. .IP \(bu 2 فاقد هرگونه نام مستعار ارجاعی (reference) یا اشاره‌گری (pointer) باشد. .IP \(bu 2 عضو یک ساختار (structure) یا کلاس نباشد. .UNINDENT .sp علاوه بر این، برای اینکه حلقه بی‌نهایت تلقی شود، شرط نباید حاوی فراخوانی تابع باشد چرا که توابع ممکن است در فراخوانی‌های مختلف مقادیر متفاوتی برگردانند. .sp به عنوان مثال، در حلقه زیر متغیر \fIi\fP در بدنه حلقه تغییری نمی‌کند و بی‌نهایت تلقی می‌شود: .INDENT 0.0 .INDENT 3.5 .sp .EX int i = 0, j = 0; while (i < 10) { ++j; } .EE .UNINDENT .UNINDENT .SS bugprone\-integer\-division .sp مواردی را پیدا می‌کند که در آن‌ها تقسیم عدد صحیح در یک زمینه ممیز شناور (floating point) به احتمال زیاد باعث از دست رفتن ناخواسته دقت محاسبات می‌شود. .sp در صورتی که تقسیم‌ها بخشی از عبارات زیر باشند، هیچ هشداری گزارش نمی‌شود: .INDENT 0.0 .IP \(bu 2 عملوندهای عملگرهایی که انتظار انواع عددی صحیح یا bool را دارند، .IP \(bu 2 عبارات فراخوانی با انواع عددی صحیح یا bool، و .IP \(bu 2 عبارات تبدیل نوع صریح (explicit cast) به انواع عددی صحیح یا bool، .UNINDENT .sp زیرا این موارد به عنوان نشانه‌هایی از عمدی بودن عمل برنامه‌نویس تفسیر می‌شوند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX float floatFunc(float); int intFunc(int); double d; int i = 42; // Warn, floating\-point values expected. d = 32 * 8 / (2 + i); d = 8 * floatFunc(1 + 7 / 2); d = i / (1 << 4); // OK, no integer division. d = 32 * 8.0 / (2 + i); d = 8 * floatFunc(1 + 7.0 / 2); d = (double)i / (1 << 4); // OK, there are signs of deliberateness. d = 1 << (i / 2); d = 9 + intFunc(6 * i / 32); d = (int)(i / 32) \- 8; .EE .UNINDENT .UNINDENT .SS bugprone\-invalid\-enum\-default\-initialization .sp مقداردهی اولیه پیش‌فرض (به مقدار 0) متغیرهایی از نوع \fBenum\fP را شناسایی می‌کند که در آن‌ها شمارشگر فاقد مقداری با ارزش 0 است. .sp در زبان ++C، اگر متغیری با فهرست مقداردهی (initializer list) یا روش‌های ضمنی دیگر مقداردهی شود و هیچ مقداری در زمان مقداردهی تعیین نگردد، مقداردهی اولیه پیش‌فرض انجام می‌شود. در چنین مواردی از مقدار 0 برای مقداردهی اولیه استفاده می‌شود. این موضوع حتی اگر شمارشگر مقداری با ارزش 0 نداشته باشد نیز برای شمارش‌ها اعمال می‌گردد. در نتیجه، یک متغیر از نوع \fBenum\fP ممکن است در ابتدا حاوی مقداری نامعتبر باشد (اگر برنامه انتظار داشته باشد که تنها شامل مقادیر شمارشگر فهرست‌شده باشد). .sp این بررسی تنها در صورتی هشدار صادر می‌کند که یک متغیر \fBenum\fP به‌صورت پیش‌فرض مقداردهی اولیه شده باشد (نه اینکه بدون مقداردهی رها شده باشد) و آن \fBenum\fP فاقد شمارشگری با مقدار 0 باشد. این نوع می‌تواند یک \fBenum\fP دامنه‌دار (scoped) یا بدون دامنه (non-scoped) باشد. اجتماع‌ها (unions) توسط این بررسی مدیریت نمی‌شوند (در صورتی که عضوی از نوع شمارشی داشته باشند). .sp توجه داشته باشید که \fBenum\fP مربوط به \fBstd::errc\fP همیشه نادیده گرفته می‌شود زیرا انتظار می‌رود به‌صورت پیش‌فرض مقداردهی اولیه شود، با وجود اینکه هیچ شمارشگری با مقدار 0 تعریف نمی‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX enum class Enum1: int { A = 1, B }; enum class Enum0: int { A = 0, B }; void f() { Enum1 X1{}; // warn: \(aqX1\(aq is initialized to 0 Enum1 X2 = Enum1(); // warn: \(aqX2\(aq is initialized to 0 Enum1 X3; // no warning: \(aqX3\(aq is not initialized Enum0 X4{}; // no warning: type has an enumerator with value of 0 } struct S1 { Enum1 A; S(): A() {} // warn: \(aqA\(aq is initialized to 0 }; struct S2 { int A; Enum1 B; }; S2 VarS2{}; // warn: member \(aqB\(aq is initialized to 0 .EE .UNINDENT .UNINDENT .sp این بررسی برای مقداردهی اولیه آرایه‌ها یا ساختارها با فهرست‌های مقداردهی در کد C نیز اعمال می‌شود. در این موارد، عناصری که در فهرست مشخص نشده‌اند (و از نوع enum هستند) بر روی 0 تنظیم می‌شوند. .INDENT 0.0 .INDENT 3.5 .sp .EX enum Enum1 { Enum1_A = 1, Enum1_B }; struct Struct1 { int a; enum Enum1 b; }; enum Enum1 Array1[2] = {Enum1_A}; // warn: omitted elements are initialized to 0 enum Enum1 Array2[2][2] = {{Enum1_A}, {Enum1_A}}; // warn: last element of both nested arrays is initialized to 0 enum Enum1 Array3[2][2] = {{Enum1_A, Enum1_A}}; // warn: elements of second array are initialized to 0 struct Struct1 S1 = {1}; // warn: element \(aqb\(aq is initialized to 0 .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoredEnums فهرستی از عبارت‌های منظم (regex) که با نقطه\-ویرگول از هم جدا شده‌اند و enumهایی را مشخص می‌کنند که این بررسی روی آن‌ها اعمال نخواهد شد. پیش‌فرض \fI::std::errc\fP است. .UNINDENT .SS bugprone\-lambda\-function\-name .sp تلاش‌ها برای دریافت نام یک تابع از درون یک عبارت لامبدا (lambda) را بررسی می‌کند. نام یک لامبدا همیشه چیزی شبیه به \fBoperator()\fP است که تقریباً هیچ‌گاه مقصود اصلی برنامه‌نویس نبوده است. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void FancyFunction() { [] { printf(\(dqCalled from %s\en\(dq, __func__); }(); [] { printf(\(dqNow called from %s\en\(dq, __FUNCTION__); }(); } .EE .UNINDENT .UNINDENT .sp خروجی: .INDENT 0.0 .INDENT 3.5 .sp .EX Called from operator() Now called from operator() .EE .UNINDENT .UNINDENT .sp خروجی احتمالاً مورد نظر: .INDENT 0.0 .INDENT 3.5 .sp .EX Called from FancyFunction Now called from FancyFunction .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoreMacros مقدار \fItrue\fP مشخص می‌کند که تلاش برای دریافت نام تابع از درون یک ماکرو نباید عیب‌یابی شود. مقدار پیش‌فرض \fIfalse\fP است. .UNINDENT .SS bugprone\-macro\-parentheses .sp ماکروهایی را می‌یابد که به دلیل نبود پرانتز ممکن است رفتارهای غیرمنتظره داشته باشند. .sp ماکروها توسط پیش‌پردازنده دقیقاً همان‌طور که هستند بسط می‌یابند. در نتیجه، ممکن است رفتارهای غیرمنتظره‌ای رخ دهد؛ عملگرها ممکن است با ترتیبی غیرمنتظره ارزیابی شوند و عملگرهای یگانی ممکن است به عملگرهای دوتایی تبدیل شوند، و غیره. .sp هنگامی که فهرست جایگزینی شامل یک عبارت باشد، توصیه می‌شود آن را در پرانتز قرار دهید. این کار تضمین می‌کند که نتیجه ماکرو قبل از استفاده کاملاً ارزیابی شود. .sp همچنین توصیه می‌شود آرگومان‌های ماکرو در فهرست جایگزینی در پرانتز قرار گیرند. این کار اطمینان می‌دهد که مقدار آرگومان به درستی محاسبه می‌شود. .sp این بررسی با قاعده PRE02\-C از استاندارد کدنویسی CERT C مطابقت دارد. فهرست‌های جایگزینی ماکرو باید پرانتزگذاری شوند: \% .SS bugprone\-macro\-repeated\-side\-effects .sp آرگومان‌های تکراری دارای اثرات جانبی (side effects) را در ماکروها بررسی می‌کند. .SS bugprone\-misleading\-setter\-of\-reference .sp توابع عضو شبیه به setter را می‌یابد که یک پارامتر اشاره‌گر دریافت کرده و یک عضو مرجع (reference) از همان کلاس را با مقدار اشاره‌شده تنظیم می‌کنند. .sp این بررسی توابع عضوی را تشخیص می‌دهد که یک پارامتر اشاره‌گر تکی می‌گیرند و شامل یک دستور عبارت منفرد هستند که پارامتر را dereference کرده و نتیجه را به یک عضو داده‌ای با نوع مرجع اختصاص می‌دهد. .sp این واقعیت که یک تابع setter اشاره‌گر می‌گیرد ممکن است این باور اشتباه را ایجاد کند که یک مرجع داخلی (در صورتی که اشاره‌گر می‌بود) تغییر می‌کند، به جای مقداری که به آن اشاره شده (یا ارجاع داده شده) است. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX class MyClass { int &InternalRef; // non\-const reference member public: MyClass(int &Value) : InternalRef(Value) {} // Warning: This setter could lead to unintended behaviour. void setRef(int *Value) { InternalRef = *Value; // This assigns to the referenced value, not changing what InternalRef references. } }; int main() { int Value1 = 42; int Value2 = 100; MyClass X(Value1); // This might look like it changes what InternalRef references to, // but it actually modifies Value1 to be 100. X.setRef(&Value2); } .EE .UNINDENT .UNINDENT .INDENT 0.0 .TP .B اصلاحات ممکن: .INDENT 7.0 .IP \(bu 2 تغییر نوع پارامتر تابع \(dqset\(dq به نوع غیر اشاره‌گر (برای مثال، یک const reference). .IP \(bu 2 تغییر نوع متغیر عضو به یک اشاره‌گر و اختصاص یک مقدار به اشاره‌گر در تابع \(dqset\(dq (بدون dereference). .UNINDENT .UNINDENT .SS bugprone\-misplaced\-operator\-in\-strlen\-in\-alloc .sp مواردی را می‌یابد که در آن‌ها مقدار \fB1\fP به جای نتیجه، به رشته موجود در آرگومان \fBstrlen()\fP، \fBstrnlen()\fP، \fBstrnlen_s()\fP، \fBwcslen()\fP، \fBwcsnlen()\fP و \fBwcsnlen_s()\fP اضافه شده است و این مقدار به عنوان آرگومان یک تابع تخصیص حافظه (\fBmalloc()\fP، \fBcalloc()\fP، \fBrealloc()\fP، \fBalloca()\fP) یا عملگر \fBnew[]\fP در \fIC++\fP استفاده شده است. این بررسی موارد خطا را حتی در صورتی که یکی از این توابع (به جز عملگر \fBnew[]\fP) توسط یک اشاره‌گر تابع ثابت فراخوانی شده باشد، شناسایی می‌کند. مواردی که در آن‌ها \fB1\fP هم به پارامتر و هم به نتیجه تابع شبه\-\fBstrlen()\fP اضافه شده است نادیده گرفته می‌شوند، و همچنین مواردی که کل عمل جمع درون پرانتزهای اضافی قرار گرفته باشد. .sp کد نمونه \fIC\fP: .INDENT 0.0 .INDENT 3.5 .sp .EX void bad_malloc(char *str) { char *c = (char*) malloc(strlen(str + 1)); } .EE .UNINDENT .UNINDENT .sp اصلاح پیشنهادی این است که مقدار \fB1\fP به مقدار بازگشتی \fBstrlen()\fP اضافه شود نه به آرگومان آن. در مثال بالا اصلاح به شکل زیر خواهد بود .INDENT 0.0 .INDENT 3.5 .sp .EX char *c = (char*) malloc(strlen(str) + 1); .EE .UNINDENT .UNINDENT .sp کد نمونه \fIC++\fP: .INDENT 0.0 .INDENT 3.5 .sp .EX void bad_new(char *str) { char *c = new char[strlen(str + 1)]; } .EE .UNINDENT .UNINDENT .sp مشابه کد \fIC\fP با تابع \fBmalloc()\fP، اصلاح پیشنهادی افزودن \fB1\fP به مقدار بازگشتی \fBstrlen()\fP است و نه به آرگومان آن. در مثال بالا اصلاح به صورت زیر خواهد بود .INDENT 0.0 .INDENT 3.5 .sp .EX char *c = new char[strlen(str) + 1]; .EE .UNINDENT .UNINDENT .sp مثال برای فرونشاندن (silence) این عیب‌یابی: .INDENT 0.0 .INDENT 3.5 .sp .EX void bad_malloc(char *str) { char *c = (char*) malloc(strlen((str + 1))); } .EE .UNINDENT .UNINDENT .SS bugprone\-misplaced\-pointer\-arithmetic\-in\-alloc .sp مواردی را می‌یابد که در آن‌ها یک عبارت عددی صحیح به‌جای آرگومان توابع تخصیص حافظه (\fBmalloc()\fP، \fBcalloc()\fP، \fBrealloc()\fP، \fBalloca()\fP)، به نتیجهٔ خروجی آن‌ها اضافه یا از آن کم شده است. این بررسی خطاهای مربوطه را حتی در صورتی که یکی از این توابع توسط یک اشاره‌گر تابع ثابت فراخوانی شود، تشخیص می‌دهد. .sp کد نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX void bad_malloc(int n) { char *p = (char*) malloc(n) + 10; } .EE .UNINDENT .UNINDENT .sp اصلاح پیشنهادی این است که عبارت عددی صحیح به آرگومان \fBmalloc\fP اضافه شود و نه به نتیجهٔ آن. در مثال بالا اصلاح به شکل زیر خواهد بود: .INDENT 0.0 .INDENT 3.5 .sp .EX char *p = (char*) malloc(n + 10); .EE .UNINDENT .UNINDENT .SS bugprone\-misplaced\-widening\-cast .sp این بررسی زمانی هشدار می‌دهد که تبدیل نوع (cast) حاصل یک محاسبه به یک نوع بزرگ‌تر انجام شده باشد. اگر هدف از این تبدیل نوع جلوگیری از افت دقت باشد، در این صورت تبدیل در محل نادرستی قرار گرفته و ممکن است افت دقت رخ دهد. در غیر این صورت، تبدیل نوع بی‌اثر و بی‌فایده است. .sp کد نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX long f(int x) { return (long)(x * 1000); } .EE .UNINDENT .UNINDENT .sp نتیجهٔ \fBx * 1000\fP ابتدا با دقت \fBint\fP محاسبه می‌شود. اگر نتیجه فراتر از دقت نوع \fBint\fP برود، افت دقت رخ می‌دهد. سپس نتیجه به نوع \fBlong\fP تبدیل می‌شود. .sp اگر هیچ افت دقتی وجود ندارد، می‌توان تبدیل نوع را حذف کرد یا به‌طور صریح به نوع \fBint\fP تبدیل نمود. .sp اگر می‌خواهید از افت دقت جلوگیری کنید، تبدیل نوع را در جای مناسب قرار دهید؛ برای نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX long f(int x) { return (long)x * 1000; } .EE .UNINDENT .UNINDENT .SS Implicit casts .sp فراموش کردن قرار دادن تبدیل نوع به همان اندازهٔ قرار دادن آن در جای نادرست خطرناک بوده و حداقل به همان میزان نیز شایع است. اگر \fBCheckImplicitCasts\fP فعال باشد، این بررسی چنین مواردی را نیز شناسایی می‌کند؛ برای نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX long f(int x) { return x * 1000; } .EE .UNINDENT .UNINDENT .SS Floating point .sp در حال حاضر این هشدارها فقط برای تبدیل اعداد صحیح ثبت می‌شوند. هیچ هشداری برای این کد ثبت نخواهد شد: .INDENT 0.0 .INDENT 3.5 .sp .EX double f(float x) { return (double)(x * 10.0f); } .EE .UNINDENT .UNINDENT .SS Options .INDENT 0.0 .TP .B CheckImplicitCasts اگر مقدار آن \fItrue\fP باشد، تشخیص تبدیل‌های ضمنی (implicit casts) فعال می‌شود. پیش‌فرض \fIfalse\fP است. .UNINDENT .SS bugprone\-move\-forwarding\-reference .sp اگر تابع \fBstd::move\fP روی یک مرجع ارجاعی (forwarding reference) فراخوانی شود، هشدار می‌دهد؛ برای نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX template void foo(T&& t) { bar(std::move(t)); } .EE .UNINDENT .UNINDENT .sp مراجع ارجاعی (forwarding references) \% معمولاً باید به‌جای \fBstd::move\fP به تابع \fBstd::forward\fP ارسال شوند، و این همان اصلاحی است که پیشنهاد خواهد شد. .sp (یک مرجع ارجاعی، ارجاع rvalue از نوعی است که یک آرگومان قالب تابع استنباط‌شده می‌باشد.) .sp در این مثال، اصلاح پیشنهادی به این صورت خواهد بود: .INDENT 0.0 .INDENT 3.5 .sp .EX bar(std::forward(t)); .EE .UNINDENT .UNINDENT .SS Background .sp کدهایی مانند مثال بالا گاهی با این انتظار نوشته می‌شوند که \fBT&&\fP صرف‌نظر از نوعی که برای \fBT\fP استنباط می‌شود همواره یک مرجع rvalue باقی خواهد ماند، و بنابراین امکان ارسال یک lvalue به \fBfoo()\fP وجود ندارد. با این حال، این موضوع درست نیست. این مثال را در نظر بگیرید: .INDENT 0.0 .INDENT 3.5 .sp .EX std::string s = \(dqHello, world\(dq; foo(s); .EE .UNINDENT .UNINDENT .sp این کد کامپایل می‌شود و پس از فراخوانی تابع \fBfoo()\fP، متغیر \fBs\fP در یک وضعیت نامشخص (indeterminate state) باقی می‌ماند زیرا داده‌های آن منتقل شده‌اند (moved from). این موضوع ممکن است برای فراخوانندهٔ \fBfoo()\fP غافلگیرکننده باشد زیرا هنگام فراخوانی \fBfoo()\fP از هیچ \fBstd::move\fP استفاده نشده است. .sp دلیل این رفتار در قاعدهٔ خاص استنباط آرگومان قالب روی قالب‌های تابعی مانند \fBfoo()\fP نهفته است \-\- یعنی روی قالب‌های تابعی که یک آرگومان با ارجاع rvalue از نوعی که آرگومان قالب تابع استنباط‌شده است، دریافت می‌کنند. (بخش [temp.deduct.call]/3 را در استاندارد C++11 ببینید.) .sp اگر \fBfoo()\fP روی یک lvalue فراخوانی شود (مانند مثال بالا)، آنگاه نوع \fBT\fP به عنوان یک مرجع lvalue استنباط می‌شود. در این مثال، \fBT\fP به صورت \fBstd::string &\fP استنباط می‌شود. در نتیجه نوع آرگومان \fBt\fP به \fBstd::string& &&\fP تبدیل می‌شود؛ طبق قوانین انحلال ارجاع (reference collapsing)، این ساختار به \fBstd::string&\fP فروپاشی می‌شود. .sp این بدان معناست که فراخوانی \fBfoo(s)\fP متغیر \fBs\fP را به عنوان یک مرجع lvalue ارسال می‌کند، و \fBfoo()\fP در نهایت عملیات move را روی \fBs\fP انجام داده و در نتیجه آن را در وضعیتی نامشخص قرار می‌دهد. .SS bugprone\-multi\-level\-implicit\-pointer\-conversion .sp تبدیل‌های ضمنی میان اشاره‌گرهایی با سطوح غیرمستقیم (indirection) متفاوت را تشخیص می‌دهد. .sp تبدیل بین انواع اشاره‌گر با سطوح ارجاع غیرمستقیم متفاوت می‌تواند خطرناک باشد و ممکن است به رفتار تعریف‌نشده (undefined behavior) منجر شود، به‌ویژه اگر اشاره‌گر تبدیل‌شده بعداً به نوعی با سطح ارجاع غیرمستقیم متفاوتی تبدیل نوع (cast) شود. برای مثال، تبدیل اشاره‌گر به اشاره‌گری از نوع \fBint\fP (\fBint**\fP) به یک \fBvoid*\fP می‌تواند منجر به از دست رفتن اطلاعات درباره سطح اصلی ارجاع غیرمستقیم شود، که این موضوع هنگام تلاش برای استفاده از اشاره‌گر تبدیل‌شده مشکل‌ساز خواهد بود. اگر اشاره‌گر تبدیل‌شده بعداً به نوعی با سطح متفاوتی از ارجاع غیرمستقیم cast شده و عمل dereference روی آن انجام شود، ممکن است باعث خطاهای دسترسی به حافظه (access violation)، خرابی حافظه (memory corruption) یا سایر رفتارهای تعریف‌نشده شود. .sp مثال زیر را در نظر بگیرید: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(void* ptr); int main() { int x = 42; int* ptr = &x; int** ptr_ptr = &ptr; foo(ptr_ptr); // warning will trigger here return 0; } .EE .UNINDENT .UNINDENT .sp در این مثال، \fBfoo()\fP با آرگومان \fBptr_ptr\fP فراخوانی شده است. با این حال، \fBptr_ptr\fP یک اشاره‌گر از نوع \fBint**\fP است، در حالی که \fBfoo()\fP یک اشاره‌گر \fBvoid*\fP را انتظار دارد. این امر موجب یک تبدیل ضمنی در سطح اشاره‌گر می‌شود که چنانچه \fBfoo()\fP با فرض اینکه اشاره‌گر از نوع \fBint*\fP است آن را dereference کند، می‌تواند مشکلاتی به بار آورد. .sp استفاده از تبدیل صریح (explicit cast) راه‌حلی توصیه‌شده برای جلوگیری از مشکلات ناشی از تبدیل ضمنی سطح اشاره‌گر است، چرا که به توسعه‌دهنده امکان می‌دهد قصد و استدلال خود را برای تبدیل نوع صراحتاً بیان کند. علاوه بر این، توصیه می‌شود که توسعه‌دهندگان پیش از استفاده از تبدیل نوع صریح، ایمنی تبدیل را به‌دقت بررسی و تایید کنند. این سطح احتیاط بیشتر می‌تواند به شناسایی زودهنگام مشکلات احتمالی در فرآیند توسعه کمک کند و پایداری و نگه‌داری‌پذیری کلی کد را بهبود بخشد. .SS گزینه‌ها .INDENT 0.0 .TP .B EnableInC اگر مقدار آن \fItrue\fP باشد، این بررسی را در کدهای C فعال می‌کند (در کدهای C++ همواره فعال است). پیش‌فرض \fItrue\fP است\&. .UNINDENT .SS bugprone\-multiple\-new\-in\-one\-expression .sp فراخوانی‌های متعدد عملگر \fBnew\fP را در یک عبارت واحد پیدا می‌کند، جایی که اگر تخصیص دوم با شکست مواجه شده و یک استثنا (exception) پرتاب کند، حافظه تخصیص‌یافته توسط \fBnew\fP اول ممکن است دچار نشت (leak) شود. .sp زبان C++ اغلب ترتیب دقیق ارزیابی عملوندهای یک عملگر یا آرگومان‌های یک تابع را مشخص نمی‌کند. بنابراین اگر اولین تخصیص با موفقیت انجام شود و دومی شکست بخورد، در یک مدیریت‌کننده استثنا (exception handler) نمی‌توان تشخیص داد که کدام تخصیص با شکست مواجه شده تا حافظه آن آزاد شود. حتی اگر ترتیب مشخص باشد، ممکن است نتیجه اولین \fBnew\fP در یک مکان موقت ذخیره شود که در زمان شکست تخصیص دوم قابل دسترسی نباشد. بهتر است در صورتی که برای بررسی خطاهای تخصیص از مدیریت استثنا استفاده می‌شود، از هرگونه عبارتی که شامل بیش از یک فراخوانی \fBoperator new\fP است اجتناب شود. .sp قوانین متفاوتی برای عملگرهای اتصال کوتاه (short\-circuit) مانند \fB||\fP و \fB&&\fP و عملگر \fB,\fP اعمال می‌شود، که در آن‌ها ارزیابی یک سمت باید پیش از شروع ارزیابی سمت دیگر کامل شود. عبارات یک راه‌اندازی لیستی (list\-initialization یا مقداردهی اولیه یا ساخت شیء با استفاده از نویسه‌های \fB{\fP و \fB}\fP) با ترتیب ثابت ارزیابی می‌شوند. به همین ترتیب، شرط عملگر سه‌تایی \fB?\fP پیش از ارزیابی شاخه‌ها ارزیابی می‌شود. .sp این بررسی در صورتی هشدار می‌دهد که دو فراخوانی \fBnew\fP در دو سمت مختلف یک عملگر در یک عبارت ظاهر شوند، یا اگر فراخوانی‌های \fBnew\fP در آرگومان‌های متفاوتی از یک فراخوانی تابع (که می‌تواند ساخت شیء با نحو \fB()\fP باشد) ظاهر شوند. این فراخوانی‌های \fBnew\fP می‌توانند در هر سطحی تودرتو باشند. برای صدور هشدار، فراخوانی‌های \fBnew\fP باید در یک بلوک کد باشند که در آن از مدیریت استثنا همراه با catch برای \fBstd::bad_alloc\fP یا \fBstd::exception\fP استفاده شده باشد. برای عملگرهای \fB||\fP، \fB&&\fP، \fB,\fP و \fB?\fP (شرط و یک شاخه) هشداری صادر نمی‌شود. همچنین در صورتی که هر دو تخصیص حافظه به یک متغیر انتساب نیافته یا مستقیماً به یک تابع ارسال نشده باشند، هشداری صادر نخواهد شد. دلیل این امر آن است که در این حالت ممکن است حافظه عمداً آزاد نشده باشد یا اشیاء تخصیص‌یافته ممکن است اشیائی خودتخریب‌گر (self\-destructing) باشند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX struct A { int Var; }; struct B { B(); B(A *); int Var; }; struct C { int *X1; int *X2; }; void f(A *, B *); int f1(A *); int f1(B *); bool f2(A *); void foo() { A *PtrA; B *PtrB; try { // Allocation of \(aqB\(aq/\(aqA\(aq may fail after memory for \(aqA\(aq/\(aqB\(aq was allocated. f(new A, new B); // warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; order of these allocations is undefined // List (aggregate) initialization is used. C C1{new int, new int}; // no warning // Allocation of \(aqB\(aq/\(aqA\(aq may fail after memory for \(aqA\(aq/\(aqB\(aq was allocated but not yet passed to function \(aqf1\(aq. int X = f1(new A) + f1(new B); // warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; order of these allocations is undefined // Allocation of \(aqB\(aq may fail after memory for \(aqA\(aq was allocated. // From C++17 on memory for \(aqB\(aq is allocated first but still may leak if allocation of \(aqA\(aq fails. PtrB = new B(new A); // warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception // \(aqnew A\(aq and \(aqnew B\(aq may be performed in any order. // \(aqnew B\(aq/\(aqnew A\(aq may fail after memory for \(aqA\(aq/\(aqB\(aq was allocated but not assigned to \(aqPtrA\(aq/\(aqPtrB\(aq. (PtrA = new A)\->Var = (PtrB = new B)\->Var; // warning: memory allocation may leak if an other allocation is sequenced after it and throws an exception; order of these allocations is undefined // Evaluation of \(aqf2(new A)\(aq must be finished before \(aqf1(new B)\(aq starts. // If \(aqnew B\(aq fails the allocated memory for \(aqA\(aq is supposedly handled correctly because function \(aqf2\(aq could take the ownership. bool Z = f2(new A) || f1(new B); // no warning X = (f2(new A) ? f1(new A) : f1(new B)); // no warning // No warning if the result of both allocations is not passed to a function // or stored in a variable. (new A)\->Var = (new B)\->Var; // no warning // No warning if at least one non\-throwing allocation is used. f(new(std::nothrow) A, new B); // no warning } catch(std::bad_alloc) { } // No warning if the allocation is outside a try block (or no catch handler exists for std::bad_alloc). // (The fact if exceptions can escape from \(aqfoo\(aq is not taken into account.) f(new A, new B); // no warning } .EE .UNINDENT .UNINDENT .SS bugprone\-multiple\-statement\-macro .sp ماکروهای چنددستوری که در عبارات شرطی بدون آکولاد استفاده می‌شوند را شناسایی می‌کند. تنها اولین دستور ماکرو درون شرط قرار می‌گیرد و سایر دستورها بدون قید و شرط اجرا خواهند شد. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX #define INCREMENT_TWO(x, y) (x)++; (y)++ if (do_increment) INCREMENT_TWO(a, b); // (b)++ will be executed unconditionally. .EE .UNINDENT .UNINDENT.SS bugprone\-narrowing\-conversions .sp بررسی \fIcppcoreguidelines\-narrowing\-conversions\fP به عنوان یک نام مستعار برای این بررسی، به اینجا تغییر مسیر می‌دهد. .sp تبدیل‌های باریک‌کننده (narrowing conversions) خاموش را بررسی می‌کند، به عنوان مثال: \fBint i = 0; i += 0.1;\fP\&. در حالی که مشکل در این مثال اولیه آشکار است، ممکن است در حالت زیر چندان واضح نباشد: \fBvoid MyClass::f(double d) { int_member_ += d; }\fP\&. .INDENT 0.0 .TP .B ما تبدیل‌های باریک‌کننده را در موارد زیر علامت‌گذاری می‌کنیم: .INDENT 7.0 .IP \(bu 2 یک عدد صحیح به یک عدد صحیح باریک‌تر (مانند \fBchar\fP به \fBunsigned char\fP) در صورتی که گزینه WarnOnIntegerNarrowingConversion فعال باشد، .IP \(bu 2 یک عدد صحیح به یک عدد ممیز شناور باریک‌تر (مانند \fBuint64_t\fP به \fBfloat\fP) در صورتی که گزینه WarnOnIntegerToFloatingPointNarrowingConversion فعال باشد، .IP \(bu 2 یک عدد ممیز شناور به یک عدد صحیح (مانند \fBdouble\fP به \fBint\fP)، .IP \(bu 2 یک عدد ممیز شناور به یک عدد ممیز شناور باریک‌تر (مانند \fBdouble\fP به \fBfloat\fP) در صورتی که گزینه WarnOnFloatingPointNarrowingConversion فعال باشد. .UNINDENT .TP .B این بررسی موارد زیر را علامت‌گذاری خواهد کرد: .INDENT 7.0 .IP \(bu 2 تمام تبدیل‌های باریک‌کننده‌ای که با یک تبدیل صریح (به سبک c یا \fBstatic_cast\fP) مشخص نشده‌اند. به عنوان مثال: \fBint i = 0; i += 0.1;\fP، \fBvoid f(int); f(0.1);\fP، .IP \(bu 2 تمام کاربردهای عملگرهای دودویی همراه با تبدیل‌های باریک‌کننده. به عنوان مثال: \fBint i; i+= 0.1;\fP\&. .UNINDENT .UNINDENT .sp عملیات ریاضی با انواع عدد صحیح کوچک‌تر از \fBint\fP موجب تبدیل ضمنی (implicit conversions) می‌شوند، همان‌طور که در بخش \(dqIntegral Promotion\(dq در وب‌سایت cppreference.com \% توضیح داده شده است. این بررسی موارد بیشتری از باریک‌سازی را نسبت به هشدار کامپایلر \fI\-Wconversion\fP شناسایی و عیب‌یابی می‌کند. مثال زیر این رفتار را نشان می‌دهد. .INDENT 0.0 .INDENT 3.5 .sp .EX // The following function definition demonstrates usage of arithmetic with // integer types smaller than `int` and how the narrowing conversion happens // implicitly. void computation(short argument1, short argument2) { // Arithmetic written by humans: short result = argument1 + argument2; // Arithmetic actually performed by C++: short result = static_cast(static_cast(argument1) + static_cast(argument2)); } void recommended_resolution(short argument1, short argument2) { short result = argument1 + argument2; // ^ warning: narrowing conversion from 'int' to signed type 'short' is implementation-defined // The cppcoreguidelines recommend to resolve this issue by using the GSL // in one of two ways. Either by a cast that throws if a loss of precision // would occur. short result = gsl::narrow(argument1 + argument2); // Or it can be resolved without checking the result risking invalid results. short result = gsl::narrow_cast(argument1 + argument2); // A classical `static_cast` will silence the warning as well if the GSL // is not available. short result = static_cast(argument1 + argument2); } .EE .UNINDENT .UNINDENT .SS گزینه‌ها (Options) .INDENT 0.0 .TP .B WarnOnIntegerNarrowingConversion در صورت فعال بودن (\fItrue\fP)، این بررسی روی تبدیل‌های باریک‌کننده عدد صحیح هشدار می‌دهد (مانند \fBint\fP به \fBsize_t\fP). به طور پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B WarnOnIntegerToFloatingPointNarrowingConversion در صورت فعال بودن (\fItrue\fP)، این بررسی روی تبدیل‌های باریک‌کننده عدد صحیح به ممیز شناور هشدار می‌دهد (مانند \fBsize_t\fP به \fBdouble\fP). به طور پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B WarnOnFloatingPointNarrowingConversion در صورت فعال بودن (\fItrue\fP)، این بررسی روی تبدیل‌های باریک‌کننده ممیز شناور هشدار می‌دهد (مانند \fBdouble\fP به \fBfloat\fP). به طور پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B WarnWithinTemplateInstantiation در صورت فعال بودن (\fItrue\fP)، این بررسی در نمونه‌سازی‌های قالب (template instantiations) روی تبدیل‌های باریک‌کننده هشدار می‌دهد. به طور پیش‌فرض \fIfalse\fP است. .UNINDENT .INDENT 0.0 .TP .B WarnOnEquivalentBitWidth در صورت فعال بودن (\fItrue\fP)، این بررسی روی تبدیل‌های باریک‌کننده‌ای که ناشی از تبدیل بین انواع با پهنای بیت یکسان هستند، هشدار می‌دهد. (مانند \fIint n = uint(0);\fP یا \fIlong long n = double(0);\fP). به طور پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B IgnoreConversionFromTypes تبدیل‌های باریک‌کننده از هر نوع موجود در این لیستِ جدا شده با نقطه\-ویرگول نادیده گرفته می‌شوند. این گزینه می‌تواند برای حذف انتساب‌های بسیار رایج اما کمتر مشکل‌ساز مانند \fIint n = std::vector().size();\fP یا \fIint n = std::difference(it1, it2);\fP مفید باشد. لیست پیش‌فرض خالی است، اما یک لیست پیشنهادی برای کدهای قدیمی \fIsize_t;ptrdiff_t;size_type;difference_type\fP است. .UNINDENT .INDENT 0.0 .TP .B PedanticMode در صورت فعال بودن (\fItrue\fP)، این بررسی هنگام انتساب یک مقدار ثابت ممیز شناور به یک متغیر عدد صحیح هشدار می‌دهد، حتی اگر مقدار ممیز شناور در نوع مقصد دقیقاً قابل نمایش باشد (مانند \fBint i = 1.0;\fP). به طور پیش‌فرض \fIfalse\fP است. .UNINDENT .SS پرسش‌های متداول (FAQ) .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 عبارت \(dqnarrowing conversion from \(aqint\(aq to \(aqfloat\(aq\(dq به چه معناست؟ .UNINDENT .UNINDENT .UNINDENT .sp یک عدد ممیز شناور با استاندارد IEEE754 می‌تواند تمامی مقادیر صحیح در محدوده [\-2^PrecisionBits, 2^PrecisionBits] را نمایش دهد، که در آن PrecisionBits تعداد بیت‌های مانتیس است. .sp برای نوع \fBfloat\fP این محدوده [\-2^23, 2^23] خواهد بود، در حالی که \fBint\fP می‌تواند مقادیر را در محدوده [\-2^31, 2^31\-1] نمایش دهد. .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 عبارت \(dqimplementation\-defined\(dq به چه معناست؟ .UNINDENT .UNINDENT .UNINDENT .sp ممکن است با پیام‌هایی مانند \(dqnarrowing conversion from \(aqunsigned int\(aq to signed type \(aqint\(aq is implementation\-defined\(dq مواجه شده باشید. استاندارد C/C++ قالب متمم دو (two\(aqs complement) را برای اعداد صحیح علامت‌دار اجباری نمی‌کند، بنابراین کامپایلر آزاد است معناشناسی و رفتار تبدیل یک عدد صحیح بدون علامت به عدد صحیح علامت‌دار را تعیین کند. پیاده‌سازی Clang از فرمت متمم دو استفاده می‌کند. .SS bugprone\-no\-escape .sp اشاره‌گرهایی با مشخصهٔ \fBnoescape\fP را پیدا می‌کند که توسط یک بلوک با اجرای ناهمگام (asynchronously\-executed) تسخیر (capture) شده‌اند. آرگومان‌های بلوک در \fBdispatch_async()\fP و \fBdispatch_after()\fP تضمین شده است که فرار (escape) می‌کنند، بنابراین اگر اشاره‌گری با صفت \fBnoescape\fP توسط یکی از این بلوک‌ها تسخیر شود، یک خطا محسوب می‌شود. .sp در ادامه نمونه‌ای از استفادهٔ نامعتبر از مشخصهٔ \fBnoescape\fP آورده شده است. .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(__attribute__((noescape)) int *p) { dispatch_async(queue, ^{ *p = 123; }); }); .EE .UNINDENT .UNINDENT .UNINDENT .UNINDENT .SS bugprone\-non\-zero\-enum\-to\-bool\-conversion .sp تبدیل‌های نوع (cast) ضمنی و صریح از نوع \fBenum\fP به \fBbool\fP را در جایی که نوع \fBenum\fP دارای شمارنده‌ای با مقدار صفر نباشد، شناسایی می‌کند. اگر \fBenum\fP تنها برای نگهداری مقادیر برابر با شمارنده‌های خود استفاده شود، در این صورت تبدیل به \fBbool\fP همیشه منجر به مقدار \fBtrue\fP خواهد شد. این موضوع می‌تواند منجر به کدهای غیرضروری شود که خوانایی و نگه‌داری‌پذیری را کاهش داده و باعث ایجاد باگ شوند. .sp اگر از \fBenum\fP برای ذخیرهٔ مقادیر دیگر استفاده شود (استفاده به عنوان ماسک بیتی یا مقداردهی اولیهٔ عمدی با صفر)، ممکن است موارد مثبت کاذب (false positive) ایجاد کند. برای مقابله با آن‌ها، می‌توان از \fB// NOLINT\fP یا تبدیل نوع ابتدا به نوع زیربنایی پیش از تبدیل به \fBbool\fP استفاده کرد. .sp توجه به این نکته مهم است که اگر تعریف نوع شمارشی در دسترس نباشد، این بررسی هیچ هشداری تولید نخواهد کرد. علاوه بر این، کلاس‌های شمارشی C++11 نیز توسط این بررسی پشتیبانی می‌شوند. .sp به طور کلی، این بررسی با شناسایی و علامت‌گذاری مواردی که در آن‌ها تبدیل نوع‌های ضمنی یا صریح از انواع شمارشی به بولی می‌تواند مشکلات احتمالی ایجاد کند، به بهبود کیفیت و خوانایی کد کمک می‌کند. .SS مثال .INDENT 0.0 .INDENT 3.5 .sp .EX enum EStatus { OK = 1, NOT_OK, UNKNOWN }; void process(EStatus status) { if (!status) { // this true\-branch won\(aqt be executed return; } // proceed with \(dqvalid data\(dq } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B EnumIgnoreList این گزینه برای نادیده گرفتن انواع enum خاص هنگام بررسی تبدیل‌های ضمنی/صریح به bool استفاده می‌شود. این گزینه فهرستی جدا شده با نقطه\-ویرگول از نام‌های نوع enum (به صورت fully qualified) یا عبارات منظم منطبق بر نام‌های نوع enum را می‌پذیرد. مقدار پیش‌فرض یک رشتهٔ خالی است، به این معنی که هیچ enumای نادیده گرفته نخواهد شد. .UNINDENT .SS bugprone\-nondeterministic\-pointer\-iteration\-order .sp استفاده‌های غیرقطعی (nondeterministic) از اشاره‌گرها در کانتینرهای بدون ترتیب (unordered containers) را پیدا می‌کند. .sp یک نمونهٔ بارز، پیمایش روی کانتینری از اشاره‌گرها است. .INDENT 0.0 .INDENT 3.5 .sp .EX { int a = 1, b = 2; std::unordered_set UnorderedPtrSet = {&a, &b}; for (auto i : UnorderedPtrSet) f(i); } .EE .UNINDENT .UNINDENT .sp نمونهٔ دیگر، مرتب‌سازی کانتینری از اشاره‌گرها است. .INDENT 0.0 .INDENT 3.5 .sp .EX { int a = 1, b = 2; std::vector VectorOfPtr = {&a, &b}; std::sort(VectorOfPtr.begin(), VectorOfPtr.end()); } .EE .UNINDENT .UNINDENT .sp پیمایش کانتینری از اشاره‌گرها ممکن است ترتیب اشاره‌گرهای مختلف را در اجراهای گوناگون یک برنامه به شکل متفاوتی ارائه دهد. در برخی موارد ممکن است این رفتاری قابل قبول باشد، و در موارد دیگر می‌تواند رفتاری غیرمنتظره به بار آورد. این بررسی به همین دلیل جنبهٔ مشورتی دارد. .sp این بررسی فقط حلقه‌های for مبتنی بر بازه (range-based for loops) را روی setها و mapهای unordered تشخیص می‌دهد. همچنین فراخوانی الگوریتم‌های شبیه به مرتب‌سازی را روی کانتینرهای حاوی اشاره‌گر شناسایی می‌کند. سایر استفاده‌های مشابه پیدا نخواهند شد و به عنوان منفی کاذب (false negative) در نظر گرفته می‌شوند. .SS محدودیت‌ها .INDENT 0.0 .IP \(bu 2 این بررسی در حال حاضر بررسی نمی‌کند که آیا ترتیب پیمایش غیرقطعی احتمالاً یک اشتباه است یا خیر، بلکه در عوض تمامی این پیمایش‌ها را به عنوان مستعد خطا (bugprone) علامت‌گذاری می‌کند. .IP \(bu 2 نوع std::reference_wrapper هنوز در نظر گرفته نشده است. .IP \(bu 2 تنها حلقه‌های for مد نظر قرار می‌گیرند؛ سایر تکرارکننده‌ها (iterators) می‌توانند در بهبودهای بعدی گنجانده شوند. .UNINDENT .SS bugprone\-not\-null\-terminated\-result .sp فراخوانی‌های تابعی را پیدا می‌کند که در آن‌ها امکان ایجاد نتیجه‌ای بدون پایان‌دهندهٔ تهی (not null-terminated) وجود دارد. معمولاً طول مناسب یک رشته \fBstrlen(src) + 1\fP یا طولی برابر با این عبارت است، زیرا پایان‌دهندهٔ تهی به فضای اضافی نیاز دارد. بدون پایان‌دهندهٔ تهی، خواندن رشته ممکن است منجر به رفتار تعریف‌نشده (undefined behavior) شود. .sp توابع زیر و توابع معادل مبتنی بر \fBwchar_t\fP آن‌ها بررسی می‌شوند: .sp \fBmemcpy\fP, \fBmemcpy_s\fP, \fBmemchr\fP, \fBmemmove\fP, \fBmemmove_s\fP, \fBstrerror_s\fP, \fBstrncmp\fP, \fBstrxfrm\fP .sp در ادامه یک مثال واقعی آورده شده است که در آن برنامه‌نویس فراموش کرده آرگومان سوم ارسالی را، یعنی \fBsize_t length\fP، افزایش دهد. به همین دلیل طول حافظهٔ تخصیص‌یافته برای نگهداری پایان‌دهندهٔ تهی کافی نیست. .INDENT 0.0 .INDENT 3.5 .sp .EX static char *stringCpy(const std::string &str) { char *result = reinterpret_cast(malloc(str.size())); memcpy(result, str.data(), str.size()); return result; } .EE .UNINDENT .UNINDENT .sp علاوه بر صدور هشدارها، قابلیت اصلاح خودکار (fix-it) تمام کدهای لازم را بازنویسی می‌کند. همچنین تلاش می‌کند ظرفیت آرایهٔ مقصد را تنظیم نماید: .INDENT 0.0 .INDENT 3.5 .sp .EX static char *stringCpy(const std::string &str) { char *result = reinterpret_cast(malloc(str.size() + 1)); strcpy(result, str.data()); return result; } .EE .UNINDENT .UNINDENT .sp نکته: هیچ تضمینی وجود ندارد که تمامی تخصیص‌های حافظهٔ حساس به مسیر (path-sensitive) بازنویسی شوند. .SS قواعد تبدیل \(aqmemcpy()\(aq .sp امکان بازنویسی فراخوانی‌های \fBmemcpy()\fP و \fBmemcpy_s()\fP به چهار تابع زیر وجود دارد: \fBstrcpy()\fP، \fBstrncpy()\fP، \fBstrcpy_s()\fP و \fBstrncpy_s()\fP، که دو مورد آخر نسخه‌های امن‌تر دو مورد اول هستند. این بررسی توابع مدیریت حافظه مبتنی بر \fBwchar_t\fP را نیز به همین ترتیب بازنویسی می‌کند. .SS بازنویسی بر اساس آرایه مقصد .INDENT 0.0 .IP \(bu 2 اگر کپی در آرایه مقصد نتواند دچار سرریز شود [1]، تابع جدید باید تابع کپی قدیمی‌تر (با پسوند \fBcpy\fP) باشد، زیرا کارآمدتر از نسخه امن است. .IP \(bu 2 اگر کپی در آرایه مقصد بتواند دچار سرریز شود [1] و \fBWantToUseSafeFunctions\fP روی \fItrue\fP تنظیم شده باشد و به دست آوردن ظرفیت آرایه مقصد امکان‌پذیر باشد، تابع جدید می‌تواند نسخه امن (با پسوند \fBcpy_s\fP) باشد. .IP \(bu 2 اگر تابع جدید بتواند نسخه امن باشد و فایل‌های ++C در حال تحلیل باشند و آرایه مقصد یک \fBchar\fP/\fBwchar_t\fP ساده بدون \fBun/signed\fP باشد، می‌توان طول آرایه مقصد را حذف کرد. .IP \(bu 2 اگر تابع جدید بتواند نسخه امن باشد و آرایه مقصد از نوع \fBun/signed\fP باشد، باید به \fBchar *\fP/\fBwchar_t *\fP ساده تبدیل (cast) شود. .UNINDENT .INDENT 0.0 .TP .B [1] سرریز در این حالت‌ها ممکن است: .INDENT 7.0 .IP \(bu 2 اگر ظرفیت آرایه مقصد ناشناخته باشد. .IP \(bu 2 اگر طول داده‌شده برابر با ظرفیت آرایه مقصد باشد. .UNINDENT .UNINDENT .SS بازنویسی بر اساس طول رشته مبدا .INDENT 0.0 .IP \(bu 2 اگر طول داده‌شده برابر با \fBstrlen(source)\fP یا طولی معادل با این عبارت باشد، تابع جدید باید تابع کپی قدیمی‌تر (با پسوند \fBcpy\fP) باشد، زیرا کارآمدتر از نسخه امن (با پسوند \fBcpy_s\fP) است. .IP \(bu 2 در غیر این صورت، فرض می‌کنیم برنامه‌نویس قصد داشته است که \(aqN\(aq کاراکتر را کپی کند، بنابراین تابع جدید از نوع شبه \fBncpy\fP خواهد بود که \(aqN\(aq کاراکتر را کپی می‌کند. .UNINDENT .SS تبدیل‌ها با \(aqstrlen()\(aq یا طول معادل این عبارت .sp این بررسی توابع مدیریت حافظه و رشته مبتنی بر \fBwchar_t\fP را به همین ترتیب تبدیل می‌کند (که در این میان فقط \fBstrerror_s\fP نام مستعار مبتنی بر \fBwchar_t\fP ندارد). .SS توابع مدیریت حافظه .sp \fBmemcpy\fP لطفاً بخش قواعد تبدیل \(aqmemcpy()\(aq را بررسی کنید. .sp \fBmemchr\fP معمولاً یک C-style cast وجود دارد که باید حذف شود، زیرا نوع بازگشتی تابع جدید \fBstrchr\fP صحیح است. طول داده‌شده حذف خواهد شد. .sp \fBmemmove\fP اگر توابع امن در دسترس باشند، تابع جدید \fBmemmove_s\fP خواهد بود که آرگومان دوم جدیدی شامل طول آرایه مقصد دارد؛ این آرگومان تنظیم شده و طول رشته مبدا یک واحد افزایش می‌یابد. اگر توابع امن در دسترس نباشند، طول داده‌شده یک واحد افزایش می‌یابد. .sp \fBmemmove_s\fP طول داده‌شده یک واحد افزایش می‌یابد. .SS توابع مدیریت رشته .sp \fBstrerror_s\fP طول داده‌شده یک واحد افزایش می‌یابد. .sp \fBstrncmp\fP اگر آرگومان سوم برابر با \fBlength + 1\fP آرگومان اول یا دوم باشد، باید بدون عملیات \fB+ 1\fP کوتاه شود. .sp \fBstrxfrm\fP طول داده‌شده یک واحد افزایش می‌یابد. .SS گزینه‌ها .INDENT 0.0 .TP .B WantToUseSafeFunctions مقدار \fItrue\fP مشخص می‌کند که محیط هدف پیاده‌سازی‌کننده توابع مدیریت حافظه و رشته با پسوند \(aq_s\(aq در نظر گرفته می‌شود که امن‌تر از نسخه‌های قدیمی‌تر هستند (مانند \(aqmemcpy_s()\(aq). مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .SS bugprone\-optional\-value\-conversion .sp تبدیل‌های بالقوه ناخواسته و زائدی را شناسایی می‌کند که در آن‌ها مقداری از یک نوع اختیاری‌مانند (optional-like) استخراج شده و سپس برای ایجاد نمونه جدیدی از همان نوع اختیاری‌مانند استفاده می‌شود. .sp این تبدیل‌ها ممکن است ناشی از سهل‌انگاری توسعه‌دهنده، بقایای بازنویسی و بازآفرینی کد (refactoring)، یا شرایط دیگری باشند که می‌توانند منجر به استثناهای ناخواسته شوند یا مواردی ایجاد کنند که اختیاری حاصل همواره مقداردهی اولیه شده باشد، که ممکن است رفتاری غیرمنتظره باشد. .sp برای تشریح این موضوع، قطعه کد مشکل‌دار زیر را در نظر بگیرید: .INDENT 0.0 .INDENT 3.5 .sp .EX #include void print(std::optional); int main() { std::optional opt; // ... // Unintentional conversion from std::optional to int and back to // std::optional: print(opt.value()); // ... } .EE .UNINDENT .UNINDENT .sp رویکرد بهتر این است که بدون استخراج مقدار، \fBopt\fP را مستقیماً به تابع \fBprint\fP پاس دهید: .INDENT 0.0 .INDENT 3.5 .sp .EX #include void print(std::optional); int main() { std::optional opt; // ... // Proposed code: Directly pass the std::optional to the print // function. print(opt); // ... } .EE .UNINDENT .UNINDENT .sp با پاس دادن مستقیم \fBopt\fP به تابع print، از تبدیل‌های غیرضروری جلوگیری شده و رفتارها یا استثناهای بالقوه ناخواسته به حداقل می‌رسند. .sp استخراج مقدار با استفاده از \fBoperator *\fP به‌صورت پیش‌فرض تطبیق داده می‌شود. پشتیبانی از انواع غیراستاندارد اختیاری مانند \fBboost::optional\fP یا \fBabsl::optional\fP ممکن است محدود باشد. .SS گزینه‌ها: .INDENT 0.0 .TP .B OptionalTypes فهرستی جداشده با نقطه‌ویرگول (semicolon) از نام‌های کامل (fully qualified) انواع اختیاری یا عبارات باقاعده‌ای که با انواع اختیاری تطابق دارند. مقدار پیش‌فرض \fI::std::optional;::absl::optional;::boost::optional\fP است. .UNINDENT .INDENT 0.0 .TP .B ValueMethods فهرستی جداشده با نقطه‌ویرگول (semicolon) از نام‌های کامل متدها یا عبارات باقاعده‌ای که با متدها تطابق دارند. مقدار پیش‌فرض \fI::value$;::get$\fP است. .UNINDENT .SS bugprone\-parent\-virtual\-call .sp فراخوانی متدهای مجازی کلاس‌های نیا-...-والد را به‌جای فراخوانی متدهای مجازی بازنویسی‌شدهٔ (overridden) والد شناسایی و تصحیح می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX struct A { int virtual foo() {...} }; struct B: public A { int foo() override {...} }; struct C: public B { int foo() override { A::foo(); } // ^^^^^^^^ // warning: qualified name A::foo refers to a member overridden in subclass; did you mean \(aqB\(aq? [bugprone\-parent\-virtual\-call] }; .EE .UNINDENT .UNINDENT .SS bugprone\-pointer\-arithmetic\-on\-polymorphic\-object .sp محاسبات اشاره‌گر (pointer arithmetic) انجام‌شده روی کلاس‌هایی که حاوی تابع مجازی هستند را پیدا می‌کند. .sp محاسبات اشاره‌گر روی اشیاء چندریختی (polymorphic) هنگامی که نوع ایستا (static type) اشاره‌گر با نوع پویا (dynamic type) آن متفاوت باشد، رفتار تعریف‌نشده (undefined behavior) است؛ زیرا این دو نوع ممکن است اندازه‌های متفاوتی داشته باشند و در نتیجه اشاره‌گر جدول متدهای مجازی (vtable) ممکن است به یک آدرس نامعتبر اشاره کند. .sp یافتن اشاره‌گرهایی که نوع ایستای آن‌ها شامل یک تابع عضو مجازی است، یک روش مکاشفه‌ای (heuristic) مناسب است، زیرا این احتمال وجود دارد که اشاره‌گر به یک شیء مشتق‌شدهٔ متفاوت اشاره کند. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX struct Base { virtual ~Base(); int i; }; struct Derived : public Base {}; void foo(Base* b) { b += 1; // warning: pointer arithmetic on class that declares a virtual function can // result in undefined behavior if the dynamic type differs from the // pointer type } int bar(const Derived d[]) { return d[1].i; // warning due to pointer arithmetic on polymorphic object } // Making Derived final suppresses the warning struct FinalDerived final : public Base {}; int baz(const FinalDerived d[]) { return d[1].i; // no warning as FinalDerived is final } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoreInheritedVirtualFunctions هنگامی که \fItrue\fP باشد، اشیایی که صرفاً یک تابع مجازی را به ارث می‌برند بررسی نمی‌شوند. کلاس‌هایی که تابع مجازی جدیدی اعلان نمی‌کنند به‌طور پیش‌فرض نادیده گرفته می‌شوند، زیرا بیشترین سهم را در هشدارهای کاذب (false positives) دارند. پیش‌فرض: \fIfalse\fP است. .INDENT 7.0 .INDENT 3.5 .sp .EX void bar(Base b[], Derived d[]) { b += 1; // warning, as Base declares a virtual destructor d += 1; // warning only if IgnoreVirtualDeclarationsOnly is set to false } .EE .UNINDENT .UNINDENT .UNINDENT .SS مراجع .sp این بررسی با قاعدهٔ SEI Cert به شمارهٔ CTR56\-CPP مطابقت دارد: Do not use pointer arithmetic on polymorphic objects \%\&. .SS bugprone\-posix\-return .sp بررسی می‌کند که آیا فراخوانی توابع \fBpthread_*\fP یا \fBposix_*\fP (به‌جز \fBposix_openpt\fP) انتظار مقادیر بازگشتی منفی را دارد یا خیر. این توابع در صورت موفقیت مقدار \fB0\fP و در صورت شکست یک \fBerrno\fP را برمی‌گردانند که تنها مقداری مثبت است. .sp نمونه‌ای از کاربرد باگ‌دار بدین شکل است: .INDENT 0.0 .INDENT 3.5 .sp .EX if (posix_fadvise(...) < 0) { .EE .UNINDENT .UNINDENT .sp این حالت هرگز رخ نخواهد داد زیرا مقدار بازگشتی همواره غیرمنفی است. یک اصلاح ساده می‌تواند به‌صورت زیر باشد: .INDENT 0.0 .INDENT 3.5 .sp .EX if (posix_fadvise(...) > 0) { .EE .UNINDENT .UNINDENT .SS bugprone\-random\-generator\-seed .sp تمامی موتورهای تولید اعداد شبه‌تصادفی، نمونه‌سازی‌های مبدل موتور (engine adaptor) و تابع \fBsrand()\fP را در صورتی که با آرگومان پیش‌فرض، عبارت ثابت (constant expression) یا هر نوع قابل‌پیکربندی توسط کاربر مقداردهی اولیه یا دانه‌گذاری (seed) شوند نشانه‌گذاری می‌کند. موتورهای اعداد شبه‌تصادفی که با مقداری قابل‌پیش‌بینی دانه‌گذاری شوند ممکن است منجر به آسیب‌پذیری‌هایی، برای مثال در پروتکل‌های امنیتی، گردند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo() { std::mt19937 engine1; // Diagnose, always generate the same sequence std::mt19937 engine2(1); // Diagnose engine1.seed(); // Diagnose engine2.seed(1); // Diagnose std::time_t t; engine1.seed(std::time(&t)); // Diagnose, system time might be controlled by user int x = atoi(argv[1]); std::mt19937 engine3(x); // Will not warn } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B DisallowedSeedTypes فهرستی جداشده با کاما از نام انواع داده‌ای که غیرمجاز هستند. مقدار پیش‌فرض \fItime_t,std::time_t\fP است\&. .UNINDENT .SS مراجع .sp این بررسی با قوانین استاندارد کدنویسی CERT C++ مطابقت دارد: MSC51\-CPP. Ensure your random number generator is properly seeded \% و MSC32\-C. Properly seed pseudorandom number generators \%\&. .SS bugprone\-raw\-memory\-call\-on\-non\-trivial\-type .sp استفاده از توابع کتابخانه استاندارد C شامل \fBmemset\fP، \fBmemcpy\fP و \fBmemcmp\fP و مشتقات مشابه آن‌ها را روی انواع غیر‌بدیهی (non\-trivial types) نشانه‌گذاری می‌کند. .sp این بررسی توابع زیر را تشخیص خواهد داد: \fBmemset\fP، \fBstd::memset\fP، \fBstd::memcpy\fP، \fBmemcpy\fP، \fBstd::memmove\fP، \fBmemmove\fP، \fBstd::strcpy\fP، \fBstrcpy\fP، \fBmemccpy\fP، \fBstpncpy\fP، \fBstrncpy\fP، \fBstd::memcmp\fP، \fBmemcmp\fP، \fBstd::strcmp\fP، \fBstrcmp\fP، \fBstrncmp\fP\&. .SS گزینه‌ها .INDENT 0.0 .TP .B MemSetNames مشخص کردن توابع اضافی برای نشانه‌گذاری که عملکردی مشابه \fBmemset\fP دارند. نام‌ها را در یک فهرست جداشده با نقطه‌ویرگول (semicolon) مشخص کنید. پیش‌فرض یک رشته خالی است. .UNINDENT .INDENT 0.0 .TP .B MemCpyNames مشخص کردن توابع اضافی برای نشانه‌گذاری که عملکردی مشابه \fBmemcpy\fP دارند. نام‌ها را در یک فهرست جداشده با نقطه‌ویرگول مشخص کنید. پیش‌فرض یک رشته خالی است. .UNINDENT .INDENT 0.0 .TP .B MemCmpNames مشخص کردن توابع اضافی برای نشانه‌گذاری که عملکردی مشابه \fBmemcmp\fP دارند. نام‌ها را در یک فهرست جداشده با نقطه‌ویرگول مشخص کنید. پیش‌فرض یک رشته خالی است. .UNINDENT .sp این بررسی با قاعده استانداردهای کدنویسی CERT C++ مطابقت دارد: OOP57\-CPP. Prefer special member functions and overloaded operators to C Standard Library functions \%\&. .SS bugprone\-redundant\-branch\-condition .sp متغیرهای شرطی را در دستورهای \fBif\fP تودرتو پیدا می‌کند که در دستور \fBif\fP بیرونی نیز بررسی شده‌اند و مقداری در آن‌ها تغییر نکرده است. .sp مثال ساده: .INDENT 0.0 .INDENT 3.5 .sp .EX bool onFire = isBurning(); if (onFire) { if (onFire) scream(); } .EE .UNINDENT .UNINDENT .sp در اینجا \fIonFire\fP هم در دستور \fBif\fP بیرونی و هم در دستور \fBif\fP درونی بدون امکان تغییر میان دو بررسی، چک شده است. این بررسی برای این کد هشدار داده و حذف بررسی دوم متغیر \fIonFire\fP را پیشنهاد می‌کند\&. .sp بررسی‌کننده همچنین بررسی‌های شرطی زائد را در صورتی که متغیر شرط عملوند یک عملگر منطقی «و» (\fB&&\fP) یا «یا»ی منطقی (\fB||\fP) باشد تشخیص می‌دهد: .INDENT 0.0 .INDENT 3.5 .sp .EX bool onFire = isBurning(); if (onFire) { if (onFire && peopleInTheBuilding > 0) scream(); } .EE .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX bool onFire = isBurning(); if (onFire) { if (onFire || isCollapsing()) scream(); } .EE .UNINDENT .UNINDENT .sp در حالت اول («و»ی منطقی) اصلاح پیشنهادی حذف متغیر شرط زائد و نگه‌داشتن طرف دیگر \fB&&\fP است. در حالت دوم («یا»ی منطقی) کل \fBif\fP مشابه مثال ساده بالا حذف می‌شود. .sp شرط دستور \fBif\fP بیرونی نیز می‌تواند یک عبارت «و»ی منطقی (\fB&&\fP) باشد: .INDENT 0.0 .INDENT 3.5 .sp .EX bool onFire = isBurning(); if (onFire && fireFighters < 10) { if (someOtherCondition()) { if (onFire) scream(); } } .EE .UNINDENT .UNINDENT .sp همچنین اگر هر دو دستور بیرونی و درونی به صورت عبارات منطقی باشند خطا تشخیص داده می‌شود (دستور بیرونی یک «و»ی منطقی (\fB&&\fP) و دستور درونی یک «و»ی منطقی (\fB&&\fP) یا «یا»ی منطقی (\fB||\fP)). دستور \fBif\fP درونی لزومی ندارد فرزند مستقیم دستور بیرونی باشد. .sp در صورتی که متغیر شرط احتمالاً بین دو بررسی تغییر کرده باشد، هیچ خطایی تشخیص داده نمی‌شود: .INDENT 0.0 .INDENT 3.5 .sp .EX bool onFire = isBurning(); if (onFire) { tryToExtinguish(onFire); if (onFire && peopleInTheBuilding > 0) scream(); } .EE .UNINDENT .UNINDENT .sp هرگونه تغییر احتمالی مد نظر قرار می‌گیرد، بنابراین اگر متغیر شرط یک متغیر محلی تابع نباشد، volatile باشد یا دارای یک نام مستعار (اشاره‌گر یا ارجاع) باشد، هیچ هشداری صادر نمی‌شود. .SS محدودیت‌ها .sp شاخه \fBelse\fP در حال حاضر برای متغیر شرط منفی‌شده بررسی نمی‌شود: .INDENT 0.0 .INDENT 3.5 .sp .EX bool onFire = isBurning(); if (onFire) { scream(); } else { if (!onFire) { continueWork(); } } .EE .UNINDENT .UNINDENT .sp بررسی‌کننده در حال حاضر تنها بررسی زائد متغیرهای شرطی منفرد را تشخیص می‌دهد. عبارت‌های پیچیده‌تر بررسی نمی‌شوند: .INDENT 0.0 .INDENT 3.5 .sp .EX if (peopleInTheBuilding == 1) { if (peopleInTheBuilding == 1) { doSomething(); } } .EE .UNINDENT .UNINDENT .SS bugprone\-reserved\-identifier .sp نام‌های \fIcert\-dcl37\-c\fP و \fIcert\-dcl51\-cpp\fP به عنوان نام مستعار به این بررسی هدایت می‌شوند. .sp استفاده از شناسه‌های رزروشده برای استفاده توسط پیاده‌سازی (implementation) را بررسی می‌کند. .sp استانداردهای C و C++ هر دو نام‌های زیر را برای چنین استفاده‌ای رزرو کرده‌اند: .INDENT 0.0 .IP \(bu 2 شناسه‌هایی که با یک خط زیر (underscore) و به دنبال آن یک حرف بزرگ انگلیسی آغاز می‌شوند؛ .IP \(bu 2 شناسه‌هایی در فضای‌نام عمومی (global namespace) که با یک خط زیر آغاز می‌شوند. .UNINDENT .sp استاندارد C علاوه‌بر این، نام‌هایی که با دو خط زیر متوالی آغاز می‌شوند را رزرو می‌کند، در حالی که استاندارد C++ این محدودیت را تشدید کرده و نام‌هایی که در هر کجای آن‌ها دو خط زیر متوالی وجود داشته باشد را رزرو می‌کند. .sp نقض قواعد نام‌گذاری بالا به رفتار تعریف‌نشده (undefined behavior) منجر می‌شود. .INDENT 0.0 .INDENT 3.5 .sp .EX namespace NS { void __f(); // name is not allowed in user code using _Int = int; // same with this #define cool__macro // also this } int _g(); // disallowed in global namespace only .EE .UNINDENT .UNINDENT .sp این بررسی همچنین می‌تواند معکوس شود، یعنی طوری پیکربندی شود که هر شناسه که یک شناسه رزروشده \fIنیست\fP را علامت‌گذاری کند. این حالت برای مثال توسط توسعه‌دهندگان کتابخانه استاندارد استفاده می‌شود تا اطمینان حاصل کنند به فضای‌نام کاربر تعدی نکنند. .sp این بررسی (هنوز) سایر نام‌های رزروشده، مانند نام‌های ماکرو که با کلمات کلیدی زبان یکسان هستند، و نام‌هایی که به‌طور خاص توسط استانداردهای زبان رزرو شده‌اند، مانند \(aqzombie names\(aq در C++ و جهت‌گیری‌های آینده کتابخانه C را بررسی نمی‌کند. .sp این بررسی مطابق با قانون DCL37\-C از استاندارد کدنویسی CERT C تحت عنوان Do not declare or define a reserved identifier \% و همچنین معادل C++ آن، یعنی DCL51\-CPP تحت عنوان Do not declare or define a reserved identifier \% است. .SS گزینه‌ها .INDENT 0.0 .TP .B Invert اگر مقدار آن \fItrue\fP باشد، بررسی را معکوس می‌کند، یعنی نام‌هایی را که رزرو نشده‌اند علامت‌گذاری می‌کند. پیش‌فرض \fIfalse\fP است. .UNINDENT .INDENT 0.0 .TP .B AllowedIdentifiers فهرستی از عبارات باقاعده (regular expressions) جداشده با نقطه‌ویرگول که بررسی از آن‌ها صرف‌نظر می‌کند. پیش‌فرض یک فهرست خالی است. .UNINDENT .SS bugprone\-return\-const\-ref\-from\-parameter .sp دستورهای return را که یک پارامتر ارجاع ثابت (constant reference) را به عنوان ارجاع ثابت بازمی‌گردانند، شناسایی می‌کند. این امر در صورتی که فراخواننده از xvalueها به عنوان آرگومان استفاده کند، ممکن است موجب خطاهای استفاده پس از آزادسازی (use\-after\-free) شود. .sp در C++، پارامترهای ارجاع ثابت می‌توانند xvalueها را بپذیرند که پس از فراخوانی تخریب خواهند شد. هنگامی که تابع چنین پارامتری را نیز به عنوان ارجاع ثابت بازمی‌گرداند، ارجاع بازگردانده‌شده ممکن است پس از نابود شدن شیئی که به آن اشاره دارد، مورد استفاده قرار گیرد. .SS مثال .INDENT 0.0 .INDENT 3.5 .sp .EX struct S { int v; S(int); ~S(); }; const S &fn(const S &a) { return a; } const S& s = fn(S{1}); s.v; // use after free .EE .UNINDENT .UNINDENT .sp این مشکل را می‌توان با اعلان یک سربارگذاری (overload) از تابع مشکل‌ساز برطرف کرد که در آن پارامتر \fBconst &\fP به صورت \fB&&\fP اعلان شده باشد. توسعه‌دهنده باید اطمینان حاصل کند که پیاده‌سازی آن تابع باعث ایجاد use\-after\-free نمی‌شود؛ همان خطایی که این بررسی نسبت به آن هشدار می‌دهد. همچنین نشانه‌گذاری چنین سربارگذاری \fB&&\fP به صورت \fBdeleted\fP نیز هشدار را برطرف می‌کند. در صورتی که بسته به جریان کنترل تابع، پارامترهای مختلف \fBconst &\fP بازگردانده شوند، یک سربارگذاری که در آن تمام پارامترهای مشکل‌ساز \fBconst &\fP به صورت \fB&&\fP اعلان شده باشند، مشکل را حل خواهد کرد. .sp این مشکل همچنین می‌تواند با افزودن ویژگی \fB[[clang::lifetimebound]]\fP حل شود. Clang به صورت پیش‌فرض هشدار \fB\-Wdangling\fP را فعال می‌کند که می‌تواند سوءاستفاده از تابع حاشیه‌نویسی‌شده را شناسایی کند. برای جزئیات به ویژگی lifetimebound در \% مراجعه کنید. .INDENT 0.0 .INDENT 3.5 .sp .EX const int &f(const int &a [[clang::lifetimebound]]) { return a; } // no warning const int &v = f(1); // warning: temporary bound to local reference \(aqv\(aq will be destroyed at the end of the full\-expression [\-Wdangling] .EE .UNINDENT .UNINDENT .SS bugprone\-shared\-ptr\-array\-mismatch .sp مقداردهی‌های اولیه اشاره‌گرهای هوشمند اشتراکی C++ (از نوع shared pointer) از نوع غیرآرایه‌ای را که با یک آرایه مقداردهی اولیه شده‌اند، پیدا می‌کند. .sp اگر یک اشاره‌گر اشتراکی \fBstd::shared_ptr\fP با عبارت جدید \fBnew T[]\fP مقداردهی شود، حافظه به طور صحیح آزادسازی نمی‌شود. در این حالت اشاره‌گر برای آزادسازی حافظه هدف از \fBdelete\fP معمولی استفاده می‌کند، در حالی که به فراخوانی \fBdelete[]\fP نیاز است. عبارت \fBstd::shared_ptr\fP عملگر delete صحیح را فراخوانی می‌کند. .sp این بررسی در صورتی که در یک اعلان متغیر تکی استفاده شده باشد (یک متغیر در یک دستور)، پیشنهاد جایگزینی \fBshared_ptr\fP با \fBshared_ptr\fP را ارائه می‌دهد. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX std::shared_ptr x(new Foo[10]); // \-> std::shared_ptr x(new Foo[10]); // ^ warning: shared pointer to non\-array is initialized with array [bugprone\-shared\-ptr\-array\-mismatch] std::shared_ptr x1(new Foo), x2(new Foo[10]); // no replacement // ^ warning: shared pointer to non\-array is initialized with array [bugprone\-shared\-ptr\-array\-mismatch] std::shared_ptr x3(new Foo[10], [](const Foo *ptr) { delete[] ptr; }); // no warning struct S { std::shared_ptr x(new Foo[10]); // no replacement in this case // ^ warning: shared pointer to non\-array is initialized with array [bugprone\-shared\-ptr\-array\-mismatch] }; .EE .UNINDENT .UNINDENT .sp این بررسی به طور جزئی قانون MEM51\-CPP از استاندارد کدنویسی CERT C++ تحت عنوان Properly deallocate dynamically allocated resources \% را پوشش می‌دهد. با این حال، فقط حالت \fBstd::shared_ptr\fP توسط این بررسی شناسایی می‌شود. .SS bugprone\-signal\-handler .sp ساختارهای خاصی را در توابع مدیر سیگنال (signal handler) که می‌توانند باعث رفتار تعریف‌نشده شوند، پیدا می‌کند. قوانین مربوط به آنچه مجاز است بین نسخه‌های مختلف زبان C++ تفاوت دارد. .sp قوانین بررسی‌شده مدیر سیگنال برای C: .INDENT 0.0 .IP \(bu 2 فراخوانی توابعی که از نظر ناهمگام ایمن نیستند (non\-asynchronous\-safe) مجاز نیست. .UNINDENT .sp قوانین بررسی‌شده مدیر سیگنال تا و شامل C++14: .INDENT 0.0 .IP \(bu 2 فراخوانی توابعی که از نظر ناهمگام ایمن نیستند مجاز نیست. .IP \(bu 2 ساختارهای کدی اختصاصی C++ در توابع مدیر سیگنال مجاز نیستند. به عبارت دیگر، فقط استفاده از زیرمجموعه مشترک C و C++ مجاز است. .IP \(bu 2 فراخوانی توابعی با پیوند غیر C (از جمله خود تابع مدیر سیگنال) مجاز نیست. .UNINDENT .sp این بررسی در C++17 و نسخه‌های بعدی غیرفعال است. .sp ایمن بودن از نظر ناهمگام (Asynchronous\-safety) از طریق مقایسه نام تابع با مجموعه‌ای از توابع شناخته‌شده تعیین می‌شود. علاوه بر این، تابع باید از فایل سرآیند سیستم (system header) گنجانده شده و در فضای‌نام سراسری باشد. آرگومان‌های (احتمالی) ارسال‌شده به تابع بررسی نمی‌شوند. هر تابعی که نتوان ایمن بودن ناهمگام آن را مشخص کرد، توسط این بررسی ناامن فرض می‌شود، از جمله توابع کاربر که فقط اعلان آن‌ها قابل مشاهده است. فراخوانی توابع تعریف‌شده توسط کاربر با تعاریف قابل مشاهده، به صورت بازگشتی بررسی می‌شوند. .sp این بررسی قانون SIG30\-C از استاندارد کدنویسی CERT C تحت عنوان Call only asynchronous\-safe functions within signal handlers \% و همچنین قانون MSC54\-CPP تحت عنوان A signal handler must be a plain old function \% را پیاده‌سازی می‌کند. این بررسی دارای نام‌های مستعار \fBcert\-sig30\-c\fP و \fBcert\-msc54\-cpp\fP است. .SS گزینه‌ها .INDENT 0.0 .TP .B AsyncSafeFunctionSet مجموعه توابعی که به عنوان ایمن در برابر ناهمگامی (asynchronous\-safe) در نظر گرفته می‌شوند (و بنابراین در گرداننده‌های سیگنال یا همان signal handlerها مجاز هستند) را مشخص می‌کند. این گزینه می‌تواند روی مقادیر زیر تنظیم شود: .INDENT 7.0 .IP \(bu 2 .INDENT 2.0 .TP .B \fIminimal\fP مجموعه حداقلی تعریف‌شده در قاعده CERT SIG30\-C را انتخاب می‌کند و شامل توابع \fBabort()\fP، \fB_Exit()\fP، \fBquick_exit()\fP و \fBsignal()\fP است. .UNINDENT .IP \(bu 2 .INDENT 2.0 .TP .B \fIPOSIX\fP مجموعه بزرگ‌تری از توابع فهرست‌شده در POSIX.1\-2017 را انتخاب می‌کند (برای اطلاعات بیشتر پیوند \% را ببینید). توابع زیر شامل آن هستند: \fB_Exit\fP، \fB_exit\fP، \fBabort\fP، \fBaccept\fP، \fBaccess\fP، \fBaio_error\fP، \fBaio_return\fP، \fBaio_suspend\fP، \fBalarm\fP، \fBbind\fP، \fBcfgetispeed\fP، \fBcfgetospeed\fP، \fBcfsetispeed\fP، \fBcfsetospeed\fP، \fBchdir\fP، \fBchmod\fP، \fBchown\fP، \fBclock_gettime\fP، \fBclose\fP، \fBconnect\fP، \fBcreat\fP، \fBdup\fP، \fBdup2\fP، \fBexecl\fP، \fBexecle\fP، \fBexecv\fP، \fBexecve\fP، \fBfaccessat\fP، \fBfchdir\fP، \fBfchmod\fP، \fBfchmodat\fP، \fBfchown\fP، \fBfchownat\fP، \fBfcntl\fP، \fBfdatasync\fP، \fBfexecve\fP، \fBffs\fP، \fBfork\fP، \fBfstat\fP، \fBfstatat\fP، \fBfsync\fP، \fBftruncate\fP، \fBfutimens\fP، \fBgetegid\fP، \fBgeteuid\fP، \fBgetgid\fP، \fBgetgroups\fP، \fBgetpeername\fP، \fBgetpgrp\fP، \fBgetpid\fP، \fBgetppid\fP، \fBgetsockname\fP، \fBgetsockopt\fP، \fBgetuid\fP، \fBhtonl\fP، \fBhtons\fP، \fBkill\fP، \fBlink\fP، \fBlinkat\fP، \fBlisten\fP، \fBlongjmp\fP، \fBlseek\fP، \fBlstat\fP، \fBmemccpy\fP، \fBmemchr\fP، \fBmemcmp\fP، \fBmemcpy\fP، \fBmemmove\fP، \fBmemset\fP، \fBmkdir\fP، \fBmkdirat\fP، \fBmkfifo\fP، \fBmkfifoat\fP، \fBmknod\fP، \fBmknodat\fP، \fBntohl\fP، \fBntohs\fP، \fBopen\fP، \fBopenat\fP، \fBpause\fP، \fBpipe\fP، \fBpoll\fP، \fBposix_trace_event\fP، \fBpselect\fP، \fBpthread_kill\fP، \fBpthread_self\fP، \fBpthread_sigmask\fP، \fBquick_exit\fP، \fBraise\fP، \fBread\fP، \fBreadlink\fP، \fBreadlinkat\fP، \fBrecv\fP، \fBrecvfrom\fP، \fBrecvmsg\fP، \fBrename\fP، \fBrenameat\fP، \fBrmdir\fP، \fBselect\fP، \fBsem_post\fP، \fBsend\fP، \fBsendmsg\fP، \fBsendto\fP، \fBsetgid\fP، \fBsetpgid\fP، \fBsetsid\fP، \fBsetsockopt\fP، \fBsetuid\fP، \fBshutdown\fP، \fBsigaction\fP، \fBsigaddset\fP، \fBsigdelset\fP، \fBsigemptyset\fP، \fBsigfillset\fP، \fBsigismember\fP، \fBsiglongjmp\fP، \fBsignal\fP، \fBsigpause\fP، \fBsigpending\fP، \fBsigprocmask\fP، \fBsigqueue\fP، \fBsigset\fP، \fBsigsuspend\fP، \fBsleep\fP، \fBsockatmark\fP، \fBsocket\fP، \fBsocketpair\fP، \fBstat\fP، \fBstpcpy\fP، \fBstpncpy\fP، \fBstrcat\fP، \fBstrchr\fP، \fBstrcmp\fP، \fBstrcpy\fP، \fBstrcspn\fP، \fBstrlen\fP، \fBstrncat\fP، \fBstrncmp\fP، \fBstrncpy\fP، \fBstrnlen\fP، \fBstrpbrk\fP، \fBstrrchr\fP، \fBstrspn\fP، \fBstrstr\fP، \fBstrtok_r\fP، \fBsymlink\fP، \fBsymlinkat\fP، \fBtcdrain\fP، \fBtcflow\fP، \fBtcflush\fP، \fBtcgetattr\fP، \fBtcgetpgrp\fP، \fBtcsendbreak\fP، \fBtcsetattr\fP، \fBtcsetpgrp\fP، \fBtime\fP، \fBtimer_getoverrun\fP، \fBtimer_gettime\fP، \fBtimer_settime\fP، \fBtimes\fP، \fBumask\fP، \fBuname\fP، \fBunlink\fP، \fBunlinkat\fP، \fButime\fP، \fButimensat\fP، \fButimes\fP، \fBwait\fP، \fBwaitpid\fP، \fBwcpcpy\fP، \fBwcpncpy\fP، \fBwcscat\fP، \fBwcschr\fP، \fBwcscmp\fP، \fBwcscpy\fP، \fBwcscspn\fP، \fBwcslen\fP، \fBwcsncat\fP، \fBwcsncmp\fP، \fBwcsncpy\fP، \fBwcsnlen\fP، \fBwcspbrk\fP، \fBwcsrchr\fP، \fBwcsspn\fP، \fBwcsstr\fP، \fBwcstok\fP، \fBwmemchr\fP، \fBwmemcmp\fP، \fBwmemcpy\fP، \fBwmemmove\fP، \fBwmemset\fP، \fBwrite\fP .sp تابع \fBquick_exit\fP در فهرست POSIX گنجانده نشده است اما در اینجا در مجموعه توابع ایمن قرار دارد. .UNINDENT .UNINDENT .sp مقدار پیش‌فرض \fIPOSIX\fP است. .UNINDENT .SS bugprone\-signed\-char\-misuse .sp بررسی \fIcert\-str34\-c\fP به عنوان یک نام مستعار (alias) برای این بررسی به اینجا هدایت می‌شود. برای نام مستعار CERT، گزینه \fIDiagnoseSignedUnsignedCharComparisons\fP روی \fIfalse\fP تنظیم شده است. .sp تبدیل‌های نوع \fBsigned char\fP \-> integer را که ممکن است نشان‌دهنده خطای برنامه‌نویسی باشند، پیدا می‌کند. مشکل اساسی با نوع داده \fBsigned char\fP این است که ممکن است نویسه‌های غیر ASCII را به عنوان مقادیر منفی ذخیره کند. این رفتار می‌تواند چه در هنگام تبدیل صریح (explicit) و چه در هنگام تبدیل ضمنی (implicit)، منجر به برداشت نادرست از کد نوشته‌شده شود. .sp هنگامی که کد حاوی یک تبدیل صریح \fBsigned char\fP \-> integer است، برنامه‌نویس احتمالاً انتظار دارد که مقدار تبدیل‌شده با کد نویسه (مقداری در بازه [0..255]) مطابقت داشته باشد، اما مقدار واقعی در بازه [\-128..127] خواهد بود. برای جلوگیری از این نوع سوءبرداشت، روش مطلوب تبدیل از \fBsigned char\fP به یک مقدار عدد صحیح این است که ابتدا به \fBunsigned char\fP تبدیل شود، که تمام نویسه‌ها را در بازه مثبت [0..255] مطابق با کدهای نویسه شناخته‌شده ذخیره می‌کند. .sp در صورت تبدیل ضمنی، برنامه‌نویس ممکن است اصلاً متوجه رخ دادن تبدیل و استفاده از مقدار char به عنوان یک عدد صحیح نباشد. مواردی وجود دارد که این ناآگاهی ممکن است منجر به کدی با نقص عملکردی شود. به عنوان مثال، بررسی برابری متغیرهای \fBsigned char\fP و \fBunsigned char\fP کاری است که باید در کد C++ از آن اجتناب کرد. در حین این مقایسه، هر دو متغیر به اعداد صحیحی تبدیل می‌شوند که دامنه‌های مقادیر متفاوتی دارند. برای \fBsigned char\fP، نویسه‌های غیر ASCII به عنوان مقداری در بازه [\-128..\-1] ذخیره می‌شوند، در حالی که همان نویسه‌ها برای یک \fBunsigned char\fP در بازه [128..255] ذخیره می‌شوند. .sp اینکه نوع داده ساده \fBchar\fP به صورت پیش‌فرض به عنوان \fBsigned char\fP در نظر گرفته شود و در نتیجه توسط این بررسی شناسایی شود یا خیر، به پلتفرم واقعی بستگی دارد. برای تغییر رفتار پیش‌فرض می‌توانید از گزینه‌های کامپایل \fB\-funsigned\-char\fP و \fB\-fsigned\-char\fP استفاده کنید. .sp در حال حاضر، این بررسی در موارد زیر هشدار می‌دهد: .INDENT 0.0 .IP \(bu 2 مقدار \fBsigned char\fP به یک متغیر عدد صحیح (integer) انتساب داده شود .IP \(bu 2 انواع \fBsigned char\fP و \fBunsigned char\fP با عملگر برابری/نابرابری مقایسه شوند .IP \(bu 2 نوع \fBsigned char\fP در اندیس آرایه به یک عدد صحیح تبدیل شود .UNINDENT .sp همچنین ببینید: STR34\-C. Cast characters to unsigned char before converting to larger integer sizes \% .sp یک مثال خوب از توضیحات CERT زمانی است که از متغیر \fBchar\fP برای خواندن از فایلی استفاده می‌شود که ممکن است حاوی نویسه‌های غیر ASCII باشد. مشکل زمانی بروز می‌کند که کد از مقدار صحیح \fB\-1\fP به عنوان EOF استفاده می‌کند، در حالی که کد نویسه 255 نیز در نمایش متمم دو (two\(aqs complement) از نوع داده char به صورت \fB\-1\fP ذخیره می‌شود. نمونه ساده‌ای از این مورد را در زیر مشاهده کنید. این کد نه تنها با رسیدن به انتهای فایل، بلکه هنگام دریافت نویسه‌ای با کد 255 نیز متوقف می‌شود. .INDENT 0.0 .INDENT 3.5 .sp .EX #define EOF (\-1) int read(void) { char CChar; int IChar = EOF; if (readChar(CChar)) { IChar = CChar; } return IChar; } .EE .UNINDENT .UNINDENT .sp یک روش مناسب برای اصلاح کد بالا، تبدیل متغیر \fBchar\fP به یک مقدار \fBunsigned char\fP در ابتدا است. .INDENT 0.0 .INDENT 3.5 .sp .EX #define EOF (\-1) int read(void) { char CChar; int IChar = EOF; if (readChar(CChar)) { IChar = static_cast(CChar); } return IChar; } .EE .UNINDENT .UNINDENT .sp مورد استفاده دیگر، بررسی برابری دو متغیر \fBchar\fP با علامت‌داری (signedness) متفاوت است. در محدوده مقادیر غیر ASCII، این مقایسه بین یک \fBsigned char\fP و یک \fBunsigned char\fP همواره مقدار \fBfalse\fP را برمی‌گرداند. .INDENT 0.0 .INDENT 3.5 .sp .EX bool compare(signed char SChar, unsigned char USChar) { if (SChar == USChar) return true; return false; } .EE .UNINDENT .UNINDENT .sp ساده‌ترین راه برای تصحیح این نوع مقایسه، تبدیل نوع (cast) یکی از آرگومان‌ها است تا هر دو آرگومان نوع یکسانی داشته باشند. .INDENT 0.0 .INDENT 3.5 .sp .EX bool compare(signed char SChar, unsigned char USChar) { if (static_cast(SChar) == USChar) return true; return false; } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B CharTypedefsToIgnore فهرستی از نام‌های typedef که با نقطه\-ویرگول (semicolon) از یکدیگر جدا شده‌اند. در این فهرست می‌توان typedefهایی برای \fBchar\fP یا \fBsigned char\fP مشخص کرد که توسط بررسی نادیده گرفته خواهند شد. این ویژگی زمانی مفید است که یک typedef یک نام مستعار صحیح مانند \fBsal_Int8\fP یا \fBint8_t\fP معرفی می‌کند. در چنین حالتی، اشتباه در برداشت انسانی مشکلی ایجاد نمی‌کند. مقدار پیش‌فرض یک رشتهٔ خالی است. .UNINDENT .INDENT 0.0 .TP .B DiagnoseSignedUnsignedCharComparisons هنگامی که \fItrue\fP باشد، بررسی روی مقایسه‌های بین \fBsigned char\fP و \fBunsigned char\fP هشدار می‌دهد؛ در غیر این صورت این مقایسه‌ها نادیده گرفته می‌شوند. به‌طور پیش‌فرض، این گزینه روی \fItrue\fP تنظیم شده است. .UNINDENT .SS bugprone\-sizeof\-container .sp این بررسی کاربردهای \fBsizeof\fP بر روی عبارت‌هایی از نوع کانتینرهای STL را پیدا می‌کند. به احتمال زیاد کاربر قصد داشته به جای آن از \fB\&.size()\fP استفاده کند. .sp تمامی انواع class/struct اعلان‌شده در فضای نام \fBstd::\fP که دارای متد const \fBsize()\fP هستند، به عنوان کانتینر در نظر گرفته می‌شوند، به استثنای \fBstd::bitset\fP و \fBstd::array\fP\&. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX std::string s; int a = 47 + sizeof(s); // warning: sizeof() doesn\(aqt return the size of the container. Did you mean .size()? int b = sizeof(std::string); // no warning, probably intended. std::string array_of_strings[10]; int c = sizeof(array_of_strings) / sizeof(array_of_strings[0]); // no warning, definitely intended. std::array std_array; int d = sizeof(std_array); // no warning, probably intended. .EE .UNINDENT .UNINDENT .SS bugprone\-sizeof\-expression .sp این بررسی کاربردهایی از عبارت‌های \fBsizeof\fP را پیدا می‌کند که به احتمال زیاد خطا هستند. .sp عملگر \fBsizeof\fP اندازه (بر حسب بایت) عملوند خود را برمی‌گرداند، که ممکن است یک عبارت یا نام پرانتزگذاری‌شدهٔ یک نوع داده باشد. استفادهٔ نادرست از این عملگر ممکن است منجر به خطاها و آسیب‌پذیری‌های احتمالی نرم‌افزاری شود. .SS استفادهٔ مشکوک از \(aqsizeof(K)\(aq .sp یک اشتباه رایج، پرس‌وجوی \fBsizeof\fP برای یک لیترال عدد صحیح است. این کار معادل استعلام اندازهٔ نوع دادهٔ آن (احتمالاً \fBint\fP) است. هدف برنامه‌نویس احتمالاً صرفاً به‌دست آوردن خود عدد صحیح بوده است، نه اندازهٔ آن. .INDENT 0.0 .INDENT 3.5 .sp .EX #define BUFLEN 42 char buf[BUFLEN]; memset(buf, 0, sizeof(BUFLEN)); // sizeof(42) ==> sizeof(int) .EE .UNINDENT .UNINDENT .SS استفادهٔ مشکوک از \(aqsizeof(expr)\(aq .sp در مواردی که یک enum یا عدد صحیح برای نمایش یک نوع استفاده می‌شود، یک اشتباه رایج اجرای \fBsizeof\fP روی عدد صحیح یا enum نمایانگر آن نوع است که باید توسط \fBsizeof\fP استفاده می‌شد. این امر منجر به دریافت اندازهٔ عدد صحیح می‌شود و نه نوعی که آن عدد صحیح نمایش می‌دهد: .INDENT 0.0 .INDENT 3.5 .sp .EX enum data_type { FLOAT_TYPE, DOUBLE_TYPE }; struct data { data_type type; void* buffer; data_type get_type() { return type; } }; void f(data d, int numElements) { // should be sizeof(float) or sizeof(double), depending on d.get_type() int numBytes = numElements * sizeof(d.get_type()); ... } .EE .UNINDENT .UNINDENT .SS استفادهٔ مشکوک از \(aqsizeof(this)\(aq .sp کلمهٔ کلیدی \fBthis\fP به اشاره‌گری به یک شیء از نوع مشخص ارزیابی می‌شود. عبارت \fBsizeof(this)\fP اندازهٔ یک اشاره‌گر را برمی‌گرداند. برنامه‌نویس به احتمال زیاد اندازهٔ خود شیء را می‌خواسته است و نه اندازهٔ اشاره‌گر را. .INDENT 0.0 .INDENT 3.5 .sp .EX class Point { [...] size_t size() { return sizeof(this); } // should probably be sizeof(*this) [...] }; .EE .UNINDENT .UNINDENT .SS استفادهٔ مشکوک از \(aqsizeof(char*)\(aq .sp تفاوت ظریفی میان اعلان یک رشتهٔ متنی با \fBchar* A = \(dq\(dq\fP و \fBchar A[] = \(dq\(dq\fP وجود دارد. حالت اول به جای نوع تجمعی \fBchar[]\fP، دارای نوع \fBchar*\fP است. استفاده از \fBsizeof\fP روی شیئی که با نوع \fBchar*\fP اعلان شده است، به جای تعداد نویسه‌ها (بایت‌های) موجود در لیترال رشته، اندازهٔ یک اشاره‌گر را برمی‌گرداند. .INDENT 0.0 .INDENT 3.5 .sp .EX const char* kMessage = \(dqHello World!\(dq; // const char kMessage[] = \(dq...\(dq; void getMessage(char* buf) { memcpy(buf, kMessage, sizeof(kMessage)); // sizeof(char*) } .EE .UNINDENT .UNINDENT .SS استفادهٔ مشکوک از \(aqsizeof(A*)\(aq .sp یک اشتباه رایج، محاسبهٔ اندازهٔ یک اشاره‌گر به جای اشاره‌شوندهٔ آن است. این حالت‌ها ممکن است به دلیل تبدیل صریح (explicit cast) یا تبدیل ضمنی (implicit conversion) رخ دهند. .INDENT 0.0 .INDENT 3.5 .sp .EX int A[10]; memset(A, 0, sizeof(A + 0)); struct Point point; memset(point, 0, sizeof(&point)); .EE .UNINDENT .UNINDENT .SS استفادهٔ مشکوک از \(aqsizeof(...)/sizeof(...)\(aq .sp تقسیم عبارت‌های \fBsizeof\fP معمولاً برای بازیابی تعداد عناصر یک نوع تجمعی استفاده می‌شود. این بررسی در موارد ناسازگار یا مشکوک هشدار می‌دهد. .sp در مثال زیر، موجودیت ۱۰ بایتی است و با نوع \fBint\fP که ۴ بایتی است ناسازگار می‌باشد. .INDENT 0.0 .INDENT 3.5 .sp .EX char buf[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // sizeof(buf) => 10 void getMessage(char* dst) { memcpy(dst, buf, sizeof(buf) / sizeof(int)); // sizeof(int) => 4 [incompatible sizes] } .EE .UNINDENT .UNINDENT .sp در مثال زیر، عبارت \fBsizeof(Values)\fP اندازهٔ \fBchar*\fP را برمی‌گرداند. اعلان آن ممکن است به‌راحتی گمراه‌کننده باشد، اما در اعلان پارامتر، اندازهٔ \(aq10\(aq نادیده گرفته شده و تابع یک \fBchar*\fP دریافت می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX char OrderedValues[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; return CompareArray(char Values[10]) { return memcmp(OrderedValues, Values, sizeof(Values)) == 0; // sizeof(Values) ==> sizeof(char*) [implicit cast to char*] } .EE .UNINDENT .UNINDENT .SS عبارت مشکوک \(aqsizeof\(aq در \(aqsizeof\(aq .sp ضرب عبارت‌های \fBsizeof\fP معمولاً بی‌معنی است و احتمالاً یک خطای منطقی محسوب می‌شود. در مثال زیر، برنامه‌نویس به جای \fB/\fP از \fB*\fP استفاده کرده است. .INDENT 0.0 .INDENT 3.5 .sp .EX const char kMessage[] = \(dqHello World!\(dq; void getMessage(char* buf) { memcpy(buf, kMessage, sizeof(kMessage) * sizeof(char)); // sizeof(kMessage) / sizeof(char) } .EE .UNINDENT .UNINDENT .sp این بررسی ممکن است روی کدهایی که از ماکروی arraysize استفاده می‌کنند فعال شود. کد زیر به درستی کار می‌کند، اما باید با استفاده صرف از عملگر \fBsizeof\fP ساده‌سازی شود. .INDENT 0.0 .INDENT 3.5 .sp .EX extern Object objects[100]; void InitializeObjects() { memset(objects, 0, arraysize(objects) * sizeof(Object)); // sizeof(objects) } .EE .UNINDENT .UNINDENT .SS استفاده مشکوک از \(aqsizeof(sizeof(...))\(aq .sp گرفتن \fBsizeof\fP از یک \fBsizeof\fP دیگر بی‌معنی است و معمولاً خطایی است که پشت ماکروها پنهان شده است. .INDENT 0.0 .INDENT 3.5 .sp .EX #define INT_SZ sizeof(int) int buf[] = { 42 }; void getInt(int* dst) { memcpy(dst, buf, sizeof(INT_SZ)); // sizeof(sizeof(int)) is suspicious. } .EE .UNINDENT .UNINDENT .SS استفاده‌های مشکوک از \(aqsizeof(...)\(aq در محاسبات اشاره‌گر .sp عملگرهای محاسباتی روی اشاره‌گرها به طور خودکار نتیجه را بر اساس اندازه نوع داده مورد اشاره مقیاس‌بندی می‌کنند. استفاده بیشتر از \fBsizeof\fP در محاسبات اشاره‌گر معمولاً به نتیجه‌ای ناخواسته منجر می‌شود. .SS مقیاس‌بندی نتیجه تفاضل اشاره‌گرها .sp تفریق دو اشاره‌گر منجر به یک عبارت عدد صحیح (از نوع \fBptrdiff_t\fP) می‌شود که فاصله بین دو شیء مورد اشاره را بر حسب \(dqتعداد اشیاء بین آن‌ها\(dq بیان می‌کند. یک اشتباه رایج این است که تصور شود نتیجه \(dqتعداد بایت‌های بین آن‌ها\(dq است و تفاضل با \fBsizeof\fP مقیاس‌بندی شود؛ مانند \fBP1 \- P2 == N * sizeof(T)\fP (به جای \fBP1 \- P2 == N\fP) یا \fB(P1 \- P2) / sizeof(T)\fP به جای \fBP1 \- P2\fP\&. .INDENT 0.0 .INDENT 3.5 .sp .EX void splitFour(const Obj* Objs, size_t N, Obj Delimiter) { const Obj *P = Objs; while (P < Objs + N) { if (*P == Delimiter) { break; } } if (P \- Objs != 4 * sizeof(Obj)) { // Expecting a distance multiplied by sizeof is suspicious. error(); } } .EE .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX void iterateIfEvenLength(int *Begin, int *End) { auto N = (Begin \- End) / sizeof(int); // Dividing by sizeof() is suspicious. if (N % 2) return; // ... } .EE .UNINDENT .UNINDENT .SS گام برداشتن اشاره‌گر با یک عدد صحیح مقیاس‌بندی‌شده .sp برعکس، هنگام انجام محاسبات اشاره‌گر برای جمع یا تفریق از یک اشاره‌گر، عملگر محاسباتی به طور ضمنی مقداری را که در واقع به اشاره‌گر اضافه می‌شود با اندازه شیء اشاره‌شده مقیاس‌بندی می‌کند؛ چرا که در \fBPtr + N\fP انتظار می‌رود \fBN\fP به معنای \(dqتعداد اشیاء برای گام برداشتن\(dq باشد، نه \(dqتعداد بایت‌ها برای گام برداشتن\(dq. .sp دیدن محاسبه یک اشاره‌گر که در آن \fBsizeof\fP وجود دارد مشکوک است و نتیجه آن معمولاً ناخواسته و اغلب خارج از محدوده (out of bounds) است. عبارت \fBPtr + sizeof(T)\fP اشاره‌گر را به اندازه \fBsizeof(T)\fP عنصر جابه‌جا می‌کند که عملاً فاکتور مقیاس‌بندی را به توان ۲ می‌رساند. .sp به طور مشابه، ضرب یا تقسیم یک مقدار عددی با \fBsizeof\fP یک عنصر یا کل بافر مشکوک است، زیرا رابطه ابعادی بین مقدار عددی و نتیجه واقعی \fBsizeof\fP همیشه قابل استنتاج نیست. در حالی که افزایش مقیاس یک عدد صحیح (ضرب) با \fBsizeof\fP احتمالاً \fBهمیشه\fP یک مشکل است، کاهش مقیاس (تقسیم) در صورتی که توسعه‌دهنده آگاه باشد که تقسیم بین تعداد مناسبی از _بایت‌ها_ و یک مقدار \fBsizeof\fP انجام می‌شود، ذاتاً خطرناک نیست. غیرفعال کردن \fBWarnOnOffsetDividedBySizeOf\fP هشدارها را فقط به حالت ضرب محدود می‌کند. .sp این بررسی همچنین موارد مشکوک استفاده از \fBalignof\fP و \fBoffsetof\fP در محاسبات اشاره‌گر را بررسی می‌کند، زیرا هر دو \(dqاندازه\(dq را بر حسب بایت برمی‌گردانند و نه عنصر، که بالقوه منجر به آفست‌های با مقیاس‌بندی مضاعف می‌شود. .INDENT 0.0 .INDENT 3.5 .sp .EX struct Message { /* ... */; char Flags[8]; }; void clearFlags(Message *Array, size_t N) { const Message *End = Array + N; while (Array < End) { memset(Array + offsetof(Message, Flags), // Suspicious pointer arithmetic using offsetof()! 0, sizeof(Message::Flags)); ++Array; } } .EE .UNINDENT .UNINDENT .sp برای این الگوی نادرست بررسی‌شده، \fIcert\-arr39\-c\fP به عنوان یک نام مستعار از این بررسی به اینجا هدایت می‌شود. .sp این بررسی با قاعده استانداردهای کدنویسی CERT C مطابقت دارد: ARR39\-C. Do not add or subtract a scaled integer to a pointer \%\&. .SS محدودیت‌ها .sp مواردی که نوعِ اشاره‌شونده (pointee) اندازه‌ای برابر با \fI1\fP بایت دارد (مانند، و مهم‌تر از همه، \fBchar\fP) مستثنی هستند. .SS گزینه‌ها .INDENT 0.0 .TP .B WarnOnSizeOfConstant زمانی که \fItrue\fP باشد، این بررسی روی عبارتی مانند \fBsizeof(CONSTANT)\fP هشدار می‌دهد. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B WarnOnSizeOfIntegerExpression زمانی که \fItrue\fP باشد، این بررسی روی عبارتی مانند \fBsizeof(expr)\fP که در آن نتیجه عبارت یک عدد صحیح است، هشدار می‌دهد. مقدار پیش‌فرض \fIfalse\fP است. .UNINDENT .INDENT 0.0 .TP .B WarnOnSizeOfThis زمانی که \fItrue\fP باشد، این بررسی روی عبارتی مانند \fBsizeof(this)\fP هشدار می‌دهد. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B WarnOnSizeOfCompareToConstant زمانی که \fItrue\fP باشد، این بررسی روی عبارتی مانند \fBsizeof(expr) <= k\fP برای یک ثابت مشکوک \fIk\fP، در حالی که \fIk\fP برابر با \fI0\fP یا بزرگتر از \fI0x8000\fP باشد، هشدار می‌دهد. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B WarnOnSizeOfPointerToAggregate زمانی که \fItrue\fP باشد، اگر آرگومان \fBsizeof\fP یک نوع اشاره‌گر به نوع تجمیعی (pointer\-to\-aggregate)، عبارتی که مقداری از نوع اشاره‌گر به نوع تجمیعی را برمی‌گرداند، یا عبارتی باشد که حاصل تبدیل آرایه به اشاره‌گر است (که می‌تواند ضمنی یا صریح باشد، مانند \fBarray + 2\fP یا \fB(int *)array\fP)، این بررسی هشدار می‌دهد. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B WarnOnSizeOfPointer زمانی که \fItrue\fP باشد، این بررسی تمام عباراتی را گزارش می‌کند که آرگومان \fBsizeof\fP در آن‌ها عبارتی است که یک اشاره‌گر تولید می‌کند (به‌جز چند عبارت اصطلاحی که احتمالاً عامدانه و درست هستند). این گزینه رخدادهای CWE 467 را شناسایی می‌کند. مقدار پیش‌فرض \fIfalse\fP است. .UNINDENT .INDENT 0.0 .TP .B WarnOnOffsetDividedBySizeOf زمانی که \fItrue\fP باشد، این بررسی روی محاسبات اشاره‌گر (pointer arithmetic) که در آن تعداد عناصر از طریق تقسیم با \fBsizeof(...)\fP به دست می‌آید، هشدار می‌دهد؛ مانند \fBPtr + Bytes / sizeof(*T)\fP\&. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B WarnOnSizeOfInLoopTermination زمانی که \fItrue\fP باشد، این بررسی در مورد استفاده نادرست از عبارت sizeof در شرط پایان حلقه هشدار می‌دهد. این هشدار زمانی فعال می‌شود که به نظر برسد عبارت \fBsizeof\fP به اشتباه برای تعیین تعداد عناصر آرایه/بافر استفاده شده است؛ مانند \fBlong arr[10]; for(int i = 0; i < sizeof(arr); i++) { ... }\fP\&. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .SS bugprone\-spuriously\-wake\-up\-functions .sp فراخوانی‌های توابع \fBcnd_wait\fP، \fBcnd_timedwait\fP، \fBwait\fP، \fBwait_for\fP یا \fBwait_until\fP را زمانی پیدا می‌کند که تابع از داخل حلقه‌ای که برقراری یک گزاره شرطی را بررسی می‌کند فراخوانی نشده باشد، یا تابع فاقد پارامتر شرطی باشد. .INDENT 0.0 .INDENT 3.5 .sp .EX if (condition_predicate) { condition.wait(lk); } .EE .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX if (condition_predicate) { if (thrd_success != cnd_wait(&condition, &lock)) { } } .EE .UNINDENT .UNINDENT .sp این بررسی مطابق با استاندارد کدنویسی CERT C++ قاعده CON54\-CPP. Wrap functions that can spuriously wake up in a loop \% و استاندارد کدنویسی CERT C قاعده CON36\-C. Wrap functions that can spuriously wake up in a loop \% است. .SS bugprone\-standalone\-empty .sp زمانی که \fBempty()\fP روی یک بازه (range) استفاده شده و نتیجه آن نادیده گرفته شود، هشدار می‌دهد. در صورت وجود تابع عضو \fBclear()\fP، استفاده از آن را پیشنهاد می‌کند. .sp متد \fBempty()\fP در بسیاری از بازه‌های رایج، یک مقدار بولی برمی‌گرداند که نشان می‌دهد آیا بازه خالی است یا خیر، اما اغلب به اشتباه به عنوان راهی برای پاک کردن محتویات یک بازه تعبیر می‌شود. برخی از بازه‌ها برای این منظور یک متد \fBclear()\fP ارائه می‌دهند. این بررسی زمانی هشدار می‌دهد که یک فراخوانی empty نتیجه‌ای را برگرداند که نادیده گرفته شده است، و پیشنهاد می‌کند که در صورت در دسترس بودن به عنوان یک تابع عضو در بازه، با فراخوانی \fBclear()\fP جایگزین شود. .sp به عنوان مثال، کد زیر می‌تواند برای مشخص کردن خالی بودن یا نبودن یک بازه استفاده شود، اما نتیجه آن نادیده گرفته شده است: .INDENT 0.0 .INDENT 3.5 .sp .EX std::vector v; \&... v.empty(); .EE .UNINDENT .UNINDENT .sp یک فراخوانی به \fBclear()\fP به درستی محتویات بازه را پاک می‌کند: .INDENT 0.0 .INDENT 3.5 .sp .EX std::vector v; \&... v.clear(); .EE .UNINDENT .UNINDENT .SS محدودیت‌ها .INDENT 0.0 .IP \(bu 2 اگر \fBempty()\fP در تعریف الگوی کلاس (class template definition) تعریف شده و با نتیجه نادیده‌گرفته‌شده استفاده شود (به عنوان مثال در پیاده‌سازی کتابخانه)، هشداری نمی‌دهد. این موارد خطا را می‌توان با خصوصیت \fB[[nodiscard]]\fP شناسایی کرد. .UNINDENT .SS bugprone\-std\-namespace\-modification .sp در مورد تغییرات در فضاهای نام \fBstd\fP یا \fBposix\fP که می‌تواند منجر به رفتار تعریف‌نشده (undefined behavior) شود، هشدار می‌دهد. .sp فضای نام \fBstd\fP (یا \fBposix\fP) مجاز است با تخصیص‌های الگو (کلاس یا تابع) که وابسته به یک نوع تعریف‌شده توسط کاربر هستند (نوعی که در هدرهای استاندارد سیستم تعریف نشده است) گسترش یابد. .sp این بررسی اعلانات زیر (ارائه‌شده توسط کاربر) را در فضای نام \fBstd\fP یا \fBposix\fP شناسایی می‌کند: .INDENT 0.0 .IP \(bu 2 هر چیزی که یک تخصیص الگو (template specialization) نباشد. .IP \(bu 2 تخصیص‌های صریح هر الگوی تابع یا الگوی کلاس کتابخانه استاندارد، در صورتی که هیچ نوع تعریف‌شده توسط کاربری به عنوان آرگومان الگو نداشته باشد. .IP \(bu 2 تخصیص‌های صریح هر تابع عضو از یک الگوی کلاس کتابخانه استاندارد. .IP \(bu 2 تخصیص‌های صریح هر الگوی تابع عضو از یک کلاس یا الگوی کلاس کتابخانه استاندارد. .IP \(bu 2 تخصیص صریح یا جزئی هر الگوی کلاس عضو از یک کلاس یا الگوی کلاس کتابخانه استاندارد. .UNINDENT .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX namespace std { int x; // warning: modification of \(aqstd\(aq namespace can result in undefined behavior [bugprone\-dont\-modify\-std\-namespace] } namespace posix::a { // warning: modification of \(aqposix\(aq namespace can result in undefined behavior } template <> struct ::std::hash { // warning: modification of \(aqstd\(aq namespace can result in undefined behavior unsigned long operator()(const long &K) const { return K; } }; struct MyData { long data; }; template <> struct ::std::hash { // no warning: specialization with user\-defined type unsigned long operator()(const MyData &K) const { return K.data; } }; namespace std { template <> void swap(bool &a, bool &b); // warning: modification of \(aqstd\(aq namespace can result in undefined behavior template <> bool less::operator()(MyData &&, MyData &&) const { // warning: modification of \(aqstd\(aq namespace can result in undefined behavior return true; } } .EE .UNINDENT .UNINDENT .SS مراجع .sp این بررسی مطابق با استاندارد کدنویسی CERT C++ تحت قانون DCL58\-CPP. Do not modify the standard namespaces است \%\&. .SS bugprone\-string\-constructor .sp سازنده‌های (constructors) رشته‌ای مشکوک و احتمالا نادرست را پیدا می‌کند. .sp یک اشتباه رایج، جابجا کردن پارامترهای سازنده رشته پرکننده (\(aqfill\(aq) است. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX std::string str(\(aqx\(aq, 50); // should be str(50, \(aqx\(aq) .EE .UNINDENT .UNINDENT .sp فراخوانی سازنده رشته لیترال با طولی بزرگتر از خود لیترال مشکوک بوده و نویسه‌های تصادفی اضافه‌ای را به رشته می‌افزاید. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX std::string(\(dqtest\(dq, 200); // Will include random characters after \(dqtest\(dq. std::string(\(dqtest\(dq, 2, 5); // Will include random characters after \(dqst\(dq. std::string_view(\(dqtest\(dq, 200); .EE .UNINDENT .UNINDENT .sp ایجاد یک رشته خالی از طریق سازنده‌های دارای پارامتر، مشکوک در نظر گرفته می‌شود. برنامه‌نویس باید در عوض از سازنده خالی استفاده کند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX std::string(\(dqtest\(dq, 0); // Creation of an empty string. std::string(\(dqtest\(dq, 1, 0); std::string_view(\(dqtest\(dq, 0); .EE .UNINDENT .UNINDENT .sp ارسال یک پارامتر موقعیت نویسه اولِ نامعتبر به سازنده موجب پرتاب استثنای \fBstd::out_of_range\fP در زمان اجرا خواهد شد. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX std::string(\(dqtest\(dq, \-1, 10); // Negative first character position. std::string(\(dqtest\(dq, 10, 10); // First character position is bigger than string literal character range\(dq. .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B WarnOnLargeLength هنگامی که روی \fItrue\fP تنظیم شود، این بررسی برای رشته‌هایی با طول بیشتر از \fBLargeLengthThreshold\fP هشدار می‌دهد. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B LargeLengthThreshold یک عدد صحیح که آستانه طول بزرگ را مشخص می‌کند. مقدار پیش‌فرض \fI0x800000\fP است. .UNINDENT .INDENT 0.0 .TP .B StringNames مقدار پیش‌فرض \fI::std::basic_string;::std::basic_string_view\fP است. .sp فهرستی از نام‌های کلاس‌ها که با نقطه\-ویرگول (semicolon) از هم جدا شده‌اند تا این بررسی روی آن‌ها اعمال شود. به طور پیش‌فرض \fI::std::basic_string\fP برای \fBstd::string\fP و \fBstd::wstring\fP اعمال می‌شود. برای نمونه آن را روی \fI::std::basic_string;llvm::StringRef;QString\fP تنظیم کنید تا این بررسی روی کلاس‌های سفارشی انجام شود. .UNINDENT .SS bugprone\-string\-integer\-assignment .sp این بررسی، انتساب یک عدد صحیح به \fBstd::basic_string\fP (\fBstd::string\fP، \fBstd::wstring\fP و غیره) را شناسایی می‌کند. منشا مشکل عملگر انتساب زیر در \fBstd::basic_string\fP است: .INDENT 0.0 .INDENT 3.5 .sp .EX basic_string& operator=( CharT ch ); .EE .UNINDENT .UNINDENT .sp انواع داده‌های عددی می‌توانند به صورت ضمنی به انواع کاراکتری تبدیل (cast) شوند. .INDENT 0.0 .INDENT 3.5 .sp .EX std::string s; int x = 5965; s = 6; s = x; .EE .UNINDENT .UNINDENT .sp از توابع تبدیل مناسب یا کاراکترهای لیترال استفاده کنید. .INDENT 0.0 .INDENT 3.5 .sp .EX std::string s; int x = 5965; s = \(aq6\(aq; s = std::to_string(x); .EE .UNINDENT .UNINDENT .sp جهت فرونشاندن مثبت‌های کاذب (false positives)، از تبدیل صریح (explicit cast) استفاده کنید. .INDENT 0.0 .INDENT 3.5 .sp .EX std::string s; s = static_cast(6); .EE .UNINDENT .UNINDENT .SS bugprone\-string\-literal\-with\-embedded\-nul .sp موارد وقوع رشته لیترال دارای نویسه NUL توکار را پیدا کرده و نحوه استفاده از آن‌ها را اعتبارسنجی می‌کند. .SS گریزدهی نامعتبر .sp نویسه‌های خاص را می‌توان در یک رشته لیترال با استفاده از کدگذاری شانزده‌شانزدهی (hexadecimal) آن‌ها مانند \fB\ex42\fP گریز داد (escape کرد). یک اشتباه رایج، گریزدهی آن‌ها به شکل \fB\e0x42\fP است که در آن \fB\e0\fP به معنای نویسه NUL خواهد بود. .INDENT 0.0 .INDENT 3.5 .sp .EX const char* Example[] = \(dqInvalid character: \e0x12 should be \ex12\(dq; const char* Bytes[] = \(dq\ex03\e0x02\e0x01\e0x00\e0xFF\e0xFF\e0xFF\(dq; .EE .UNINDENT .UNINDENT .SS Truncated literal .sp کلاس‌های شبه‌رشته (string\-like) می‌توانند رشته‌های حاوی NUL داخلی را دستکاری کنند، زیرا آن‌ها بایت‌ها و طول رشته را ردیابی و نگهداری می‌کنند. اما این موضوع در مورد رشته‌های \fBchar*\fP (خاتمه‌یافته با NUL) صدق نمی‌کند. .sp یک اشتباه رایج، ارسال یک لیترال رشته‌ای با NUL داخلی به سازنده‌ای از رشته است که انتظار یک رشته خاتمه‌یافته با NUL را دارد. بایت‌های پس از اولین نویسه NUL کوتاه (ترانکیت) می‌شوند. .INDENT 0.0 .INDENT 3.5 .sp .EX std::string str(\(dqabc\e0def\(dq); // \(dqdef\(dq is truncated str += \(dq\e0\(dq; // This statement is doing nothing if (str == \(dq\e0abc\(dq) return; // This expression is always true .EE .UNINDENT .UNINDENT .SS bugprone\-stringview\-nullptr .sp روش‌های مختلفی را که ممکن است در آن‌ها یک آرگومان null به سازنده \fBconst CharT*\fP از \fBstd::basic_string_view\fP ارسال شود، بررسی کرده و در بیشتر موارد آن‌ها را با سازنده پیش‌فرض جایگزین می‌کند. برای عملگرهای مقایسه‌ای، لیست مقداردهی اولیه محصور در آکولاد (braced initializer list) کامپایل نمی‌شود، بنابراین در صورت لزوم به جای آن از یک فراخوانی به \fB\&.empty()\fP یا لیترال رشته خالی استفاده می‌شود. .sp این بررسی مانع از اجرای کدی می‌شود که رفتار تعریف‌نشده (undefined behavior) قطعی دارد. سازنده تک‌آرگومانی \fBconst CharT*\fP قبل از دی‌ریفرنس کردن ورودی خود، حالت null بودن را بررسی نمی‌کند. استاندارد در نظر دارد یک سربارگذاری (overload) صریحاً حذف‌شده اضافه کند تا برخی از این موارد را مدیریت کند: wg21.link/p2166 .sp برای پوشش موارد اضافی \fBNULL\fP (که به \fB__null\fP گسترش می‌یابد) و \fB0\fP، ابتدا بررسی \fBmodernize\-use\-nullptr\fP را اجرا کنید تا فراخواننده‌ها به \fBnullptr\fP تبدیل شوند. .INDENT 0.0 .INDENT 3.5 .sp .EX std::string_view sv = nullptr; sv = nullptr; bool is_empty = sv == nullptr; bool isnt_empty = sv != nullptr; accepts_sv(nullptr); accepts_sv({{}}); // A accepts_sv({nullptr, 0}); // B .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به... .INDENT 0.0 .INDENT 3.5 .sp .EX std::string_view sv = {}; sv = {}; bool is_empty = sv.empty(); bool isnt_empty = !sv.empty(); accepts_sv(\(dq\(dq); accepts_sv(\(dq\(dq); // A accepts_sv({nullptr, 0}); // B .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 الگوی کد منبع با کامنت انتهایی \(dqA\(dq، سربارگذاری سازنده \fB(const CharT*)\fP را انتخاب کرده و سپس اشاره‌گر را مقداردهی اولیه بر پایه مقدار (value\-initializes) می‌کند که باعث دی‌ریفرنس اشاره‌گر تهی (null dereference) می‌شود. با این‌که شامل لیترال \fBnullptr\fP نیست، اما همچنان در محدوده این بررسی ClangTidy قرار می‌گیرد. .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 الگوی کد منبع با کامنت انتهایی \(dqB\(dq سازنده \fB(const CharT*, size_type)\fP را انتخاب می‌کند که کاملاً معتبر است، زیرا آرگومان طول برابر با \fB0\fP است. این مورد توسط این بررسی ClangTidy تغییر نمی‌کند. .UNINDENT .UNINDENT .SS bugprone\-suspicious\-enum\-usage .sp این بررسی‌کننده موارد مختلفی را که یک enum احتمالاً به اشتباه (به عنوان بیت‌ماسک) استفاده شده است، تشخیص می‌دهد. .INDENT 0.0 .IP 1. 3 هنگامی که \(dqADD\(dq یا \(dqbitwise OR\(dq بین دو enum که از انواع مختلفی هستند استفاده شده و بازه مقادیر این انواع مجزا (disjoint) نباشد. .UNINDENT .sp موارد زیر تنها با استفاده از \fBStrictMode\fP \%<#\:cmdoption-arg-StrictMode> مورد بررسی قرار می‌گیرند. ما enum را به عنوان یک بیت‌ماسک (مشکوک) در نظر می‌گیریم اگر سه شرط زیر به طور همزمان برقرار باشند: .INDENT 0.0 .IP \(bu 2 حداکثر نیمی از عناصر enum اعدادی غیر از توان‌های ۲ باشند (به دلیل شمارش‌های کوتاه) .IP \(bu 2 عدد دیگری به جز ثابت enum که نشان‌دهنده همه گزینه‌ها باشد (نتیجه عملیات \(dqbitwise OR\(dq تمام عناصر enum)، غیر از توان ۲ باشد .IP \(bu 2 متغیر/ثابت از نوع enum به عنوان آرگومان یک عملگر \fI+\fP یا عملگر \(dqbitwise OR\(dq استفاده شود .UNINDENT .sp بنابراین هر زمان که عنصری که توان ۲ نیست به عنوان یک عنصر بیت‌ماسک استفاده شود، استفاده نادرست را تشخیص داده و یک هشدار صادر می‌کنیم. .INDENT 0.0 .IP 2. 3 بررسی سمت راست عملگرهای \fB+=\fP و \fB|=\fP. .IP 3. 3 بررسی تنها سمتی از عملگرهای \fB|\fP و \fB+\fP که مقدار enum دارد، در صورتی که یکی از آن‌ها مقدار enum نباشد. .IP 4. 3 بررسی هر دو سمت عملگر \fB|\fP یا \fB+\fP در صورتی که مقادیر enum از یک نوع enum یکسان باشند. .UNINDENT .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX enum { A, B, C }; enum { D, E, F = 5 }; enum { G = 10, H = 11, I = 12 }; unsigned flag; flag = A | H; // OK, disjoint value intervals in the enum types \->probably good use. flag = B | F; // Warning, have common values so they are probably misused. // Case 2: enum Bitmask { A = 0, B = 1, C = 2, D = 4, E = 8, F = 16, G = 31 // OK, real bitmask. }; enum Almostbitmask { AA = 0, BB = 1, CC = 2, DD = 4, EE = 8, FF = 16, GG // Problem, forgot to initialize. }; unsigned flag = 0; flag |= E; // OK. flag |= EE; // Warning at the decl, and note that it was used here as a bitmask. .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B StrictMode مقدار پیش‌فرض: 0. در صورتی که مقدار غیر صفر باشد، علاوه بر بررسی استفاده از enumهای متفاوت، استفاده‌های مشکوک از بیت‌ماسک (bitmask) نیز به صورت مضاعف بررسی خواهد شد. .UNINDENT .SS bugprone\-suspicious\-include .sp این بررسی مواردی را شناسایی می‌کند که در آن‌ها یک include به فایلی ارجاع می‌دهد که به نظر یک فایل پیاده‌سازی (implementation file) می‌آید؛ امری که اغلب منجر به نقض‌های ODR می‌شود که ردگیری آن‌ها دشوار است. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX #include \(dqDinosaur.hpp\(dq // OK, .hpp files tend not to have definitions. #include \(dqPterodactyl.h\(dq // OK, .h files tend not to have definitions. #include \(dqVelociraptor.cpp\(dq // Warning, filename is suspicious. #include_next // Warning, filename is suspicious. .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoredRegex یک عبارت باقاعده (regular expression) برای نام فایل‌هایی که باید توسط بررسی نادیده گرفته شوند. مقدار پیش‌فرض یک رشته خالی است. .UNINDENT .SS bugprone\-suspicious\-memory\-comparison .sp فراخوانی‌های بالقوه نادرست به \fBmemcmp()\fP را بر اساس ویژگی‌های آرگومان‌ها پیدا می‌کند. موارد زیر پوشش داده شده‌اند: .sp \fBمورد ۱: نوع با چیدمان غیر استاندارد (Non\-standard\-layout type)\fP .sp مقایسه نمایش شیء (object representation) اشیایی که چیدمان غیراستاندارد دارند، ممکن است نمایش مقدار (value representation) را به‌درستی مقایسه نکند. .sp \fBمورد ۲: انواع بدون نمایش شیء یکتا\fP .sp اشیایی با مقدار یکسان ممکن است نمایش شیء یکسانی نداشته باشند. این حالت می‌تواند ناشی از فاصله‌گذاری (padding) یا انواع ممیز شناور (floating\-point) باشد. .sp همچنین ببینید: EXP42\-C. Do not compare padding data \% و FLP37\-C. Do not use object representations to compare floating\-point values \% .sp این بررسی همچنین با قوانین استاندارد کدنویسی CERT C++ زیر مرتبط بوده و تا حدی هم‌پوشانی دارد: OOP57\-CPP. Prefer special member functions and overloaded operators to C Standard Library functions \% و EXP62\-CPP. Do not access the bits of an object representation that are not part of the object\(aqs value representation \% .sp بررسی \fIcert\-exp42\-c\fP به عنوان یک نام مستعار برای این بررسی، به اینجا تغییر مسیر می‌دهد. .SS bugprone\-suspicious\-memset\-usage .sp این بررسی فراخوانی‌های \fBmemset()\fP را که دارای خطاهای بالقوه در آرگومان‌هایشان هستند پیدا می‌کند. با در نظر گرفتن تابع به صورت \fBvoid* memset(void* destination, int fill_value, size_t byte_count)\fP، موارد زیر پوشش داده می‌شوند: .sp \fBمورد ۱: مقدار پرکننده یک کاراکتر \(ga\(ga\(aq0\(aq\(ga\(ga است\fP .sp پر کردن یک ناحیه از حافظه با کاراکترهای کد اسکی ۴۸ مرسوم نیست، احتمالاً منظور اعداد صحیح صفر بوده است. این بررسی پیشنهاد جایگزینی \fB\(aq0\(aq\fP با \fB0\fP را ارائه می‌دهد. اجرای memset بر روی اشاره‌گرهای کاراکتری با \fB\(aq0\(aq\fP مجاز است. .sp \fBمورد ۲: مقدار پرکننده دچار برش (truncated) می‌شود\fP .sp تابع memset مقدار \fBfill_value\fP را قبل از استفاده به \fBunsigned char\fP تبدیل می‌کند. اگر \fBfill_value\fP خارج از محدوده unsigned character باشد، دچار برش شده و حافظه حاوی الگوی مورد نظر نخواهد بود. .sp \fBمورد ۳: تعداد بایت‌ها صفر است\fP .sp فراخوانی memset با مقدار لیترال صفر در آرگومان \fBbyte_count\fP آن احتمالاً ناخواسته بوده و با \fBfill_value\fP جابه‌جا شده است. این بررسی پیشنهاد تعویض این دو آرگومان را ارائه می‌دهد. .sp نام بررسی متناظر در cpplint.py عبارت است از: \fBruntime/memset\fP\&. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo() { int i[5] = {1, 2, 3, 4, 5}; int *ip = i; char c = \(aq1\(aq; char *cp = &c; int v = 0; // Case 1 memset(ip, \(aq0\(aq, 1); // suspicious memset(cp, \(aq0\(aq, 1); // OK // Case 2 memset(ip, 0xabcd, 1); // fill value gets truncated memset(ip, 0x00, 1); // OK // Case 3 memset(ip, sizeof(int), v); // zero length, potentially swapped memset(ip, 0, 1); // OK } .EE .UNINDENT .UNINDENT .SS bugprone\-suspicious\-missing\-comma .sp لیترال‌های رشته‌ای که در کنار یکدیگر قرار می‌گیرند، در فاز ۶ ترجمه (پس از پیش‌پردازنده) الحاق (concatenate) می‌شوند. از این ویژگی برای نمایش لیترال رشته‌ای طولانی در چند خط استفاده می‌شود. .sp برای نمونه، اعلان‌های زیر معادل هستند: .INDENT 0.0 .INDENT 3.5 .sp .EX const char* A[] = \(dqThis is a test\(dq; const char* B[] = \(dqThis\(dq \(dq is a \(dq \(dqtest\(dq; .EE .UNINDENT .UNINDENT .sp یک اشتباه رایج برنامه‌نویسان فراموش کردن کاما بین دو لیترال رشته‌ای در یک لیست مقداردهی اولیه آرایه (array initializer list) است. .INDENT 0.0 .INDENT 3.5 .sp .EX const char* Test[] = { \(dqline 1\(dq, \(dqline 2\(dq // Missing comma! \(dqline 3\(dq, \(dqline 4\(dq, \(dqline 5\(dq }; .EE .UNINDENT .UNINDENT .sp این آرایه شامل رشته \(dqline 2line3\(dq در آفست ۱ (یعنی Test[1]) خواهد بود. ابزار Clang در زمان کامپایل هیچ هشداری تولید نخواهد کرد. .sp این بررسی ممکن است در مواردی مانند زیر به نادرستی هشدار دهد: .INDENT 0.0 .INDENT 3.5 .sp .EX const char* SupportedFormat[] = { \(dqError %s\(dq, \(dqCode \(dq PRIu64, // May warn here. \(dqWarning %s\(dq, }; .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B SizeThreshold یک عدد صحیح بدون علامت که حداقل اندازه یک لیترال رشته‌ای را برای در نظر گرفته شدن توسط بررسی تعیین می‌کند. مقدار پیش‌فرض \fB5U\fP است. .UNINDENT .INDENT 0.0 .TP .B RatioThreshold رشته‌ای که بیشینه نسبت آستانه [0, 1.0] لیترال‌های رشته‌ای مشکوک را برای در نظر گرفته شدن مشخص می‌کند. مقدار پیش‌فرض \fB\(dq.2\(dq\fP است. .UNINDENT .INDENT 0.0 .TP .B MaxConcatenatedTokens یک عدد صحیح بدون علامت که بیشینه تعداد توکن‌های متصل‌شده به یکدیگر را تعیین می‌کند. مقدار پیش‌فرض \fB5U\fP است. .UNINDENT .SS bugprone\-suspicious\-realloc\-usage .sp این بررسی مواردی از استفاده از \fBrealloc\fP را می‌یابد که در آن‌ها مقدار بازگشتی به همان عبارتی انتساب داده می‌شود که به عنوان آرگومان اول ارسال شده است: \fBp = realloc(p, size);\fP مشکل این ساختار آن است که اگر \fBrealloc\fP شکست بخورد، یک اشاره‌گر تهی (null) برمی‌گرداند اما حافظه اصلی را آزاد نمی‌کند. اگر متغیر دیگری به آن اشاره نکند، بلوک حافظه اصلی دیگر برای استفاده یا آزاد‌سازی در دسترس برنامه نخواهد بود. در هر صورت، \fBp = realloc(p, size);\fP نشان‌دهنده سبک کدنویسی بد است و می‌تواند با \fBq = realloc(p, size);\fP جایگزین شود. .sp عبارت اشاره‌گر (استفاده‌شده در \fBrealloc\fP) می‌تواند یک متغیر یا یک عضو فیلد از یک ساختار داده باشد، اما نمی‌تواند شامل فراخوانی‌های تابع یا انواع حل‌نشده (unresolved types) باشد. .sp در موارد واضحی که اشاره‌گر استفاده‌شده در realloc قبل از فراخوانی \fBrealloc\fP به متغیر دیگری انتساب داده شده باشد، هیچ هشداری صادر نمی‌شود. این حالت تنها زمانی رخ می‌دهد که یک عبارت ساده به شکل \fBq = p\fP یا \fBvoid *q = p\fP در همان تابعی یافت شود که \fBp = realloc(p, ...)\fP در آن پیدا شده است. این انتساب باید قبل از فراخوانی realloc (اما در غیر این صورت در هر نقطه‌ای) در همان تابع باشد. این نادیده‌گیری تنها در صورتی کار می‌کند که \fBp\fP یک متغیر تکی باشد. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX struct A { void *p; }; A &getA(); void foo(void *p, A *a, int new_size) { p = realloc(p, new_size); // warning: \(aqp\(aq may be set to null if \(aqrealloc\(aq fails, which may result in a leak of the original buffer a\->p = realloc(a\->p, new_size); // warning: \(aqa\->p\(aq may be set to null if \(aqrealloc\(aq fails, which may result in a leak of the original buffer getA().p = realloc(getA().p, new_size); // no warning } void foo1(void *p, int new_size) { void *p1 = p; p = realloc(p, new_size); // no warning } .EE .UNINDENT .UNINDENT .SS bugprone\-suspicious\-semicolon .sp بیشتر موارد وجود نقطه‌ویرگول‌های سرگردان را که به طور غیرمنتظره‌ای معنای کد را تغییر می‌دهند، پیدا می‌کند. به‌طور دقیق‌تر، به دنبال دستورهای \fBif\fP، \fBwhile\fP، \fBfor\fP و \fBfor\-range\fP می‌گردد که بدنه آن‌ها یک نقطه‌ویرگول تکی است، و سپس زمینه کد (مانند تورفتگی) را تحلیل می‌کند تا مشخص کند آیا این مورد عمدی بوده است یا خیر. .INDENT 0.0 .INDENT 3.5 .sp .EX if (x < y); { x++; } .EE .UNINDENT .UNINDENT .sp در اینجا بدنه دستور \fBif\fP تنها از یک نقطه‌ویرگول در انتهای خط اول تشکیل شده است، و \fIx\fP صرف‌نظر از شرط افزایش خواهد یافت. .INDENT 0.0 .INDENT 3.5 .sp .EX while ((line = readLine(file)) != NULL); processLine(line); .EE .UNINDENT .UNINDENT .sp در نتیجه این کد، \fIprocessLine()\fP تنها یک بار فراخوانی خواهد شد، یعنی زمانی که حلقه \fBwhile\fP با بدنه خالی با وضعیت \fBline == NULL\fP خاتمه یابد. تورفتگی کد قصد برنامه‌نویس را نشان می‌دهد. .INDENT 0.0 .INDENT 3.5 .sp .EX if (x >= y); x \-= y; .EE .UNINDENT .UNINDENT .sp با اینکه تورفتگی هیچ تودرتویی را نشان نمی‌دهد، اما وجود یک دستور \fIif\fP با بدنه خالی اساساً دلیل موجهی ندارد (هرچند ممکن است برای یک حلقه معنی‌دار باشد). بنابراین این بررسی برای کد بالا هشدار صادر می‌کند. .sp برای حل مشکل، نقطه‌ویرگول سرگردان را حذف کنید یا در صورتی که بدنه خالی عمدی است، این مورد را با استفاده از تورفتگی کد نشان دهید یا نقطه‌ویرگول را در یک خط جدید قرار دهید. برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX while (readWhitespace()); Token t = readNextToken(); .EE .UNINDENT .UNINDENT .sp در اینجا خط دوم به‌گونه‌ای تورفتگی دارد که نشان می‌دهد قرار است بدنه حلقه \fIwhile\fP باشد \- که در واقع بدنه آن به دلیل وجود نقطه‌ویرگول در انتهای خط اول خالی است. .sp یا تورفتگی را از خط دوم حذف کنید: .INDENT 0.0 .INDENT 3.5 .sp .EX while (readWhitespace()); Token t = readNextToken(); .EE .UNINDENT .UNINDENT .sp \&... یا نقطه‌ویرگول را از انتهای خط اول به یک خط جدید منتقل کنید: .INDENT 0.0 .INDENT 3.5 .sp .EX while (readWhitespace()) ; Token t = readNextToken(); .EE .UNINDENT .UNINDENT .sp در این حالت، بررسی فرض خواهد کرد که شما می‌دانید در حال انجام چه کاری هستید و هشداری صادر نخواهد کرد. .SS bugprone\-suspicious\-string\-compare .sp استفاده‌های مشکوک از توابع مقایسه رشته در زمان اجرا را می‌یابد. این بررسی در C و C++ معتبر است. .sp فراخوانی‌ها با عملگر مقایسه ضمنی را بررسی کرده و پیشنهاد می‌دهد که آن را صراحتاً اضافه کنید. .INDENT 0.0 .INDENT 3.5 .sp .EX if (strcmp(...)) // مقایسه ضمنی با صفر if (!strcmp(...)) // هشداری داده نخواهد شد if (strcmp(...) != 0) // هشداری داده نخواهد شد .EE .UNINDENT .UNINDENT .sp بررسی می‌کند که نتایج تابع مقایسه (مانند \fBstrcmp\fP) با یک مقدار ثابت معتبر مقایسه شوند. مقدار حاصل عبارت است از: .INDENT 0.0 .INDENT 3.5 .sp .EX < 0 زمانی که کوچکتر باشد، > 0 زمانی که بزرگتر باشد، == 0 زمانی که برابر باشد. .EE .UNINDENT .UNINDENT .sp یک اشتباه رایج، مقایسه نتیجه با \fI1\fP یا \fI\-1\fP است. .INDENT 0.0 .INDENT 3.5 .sp .EX if (strcmp(...) == \-1) // استفاده نادرست از مقدار بازگردانده‌شده. .EE .UNINDENT .UNINDENT .sp علاوه بر این، در صورتی که مقدار نتیجه به‌طور ضمنی به یک نوع غیرصحیح \fIمشکوک\fP تبدیل (cast) شود، این بررسی هشدار می‌دهد. این حالت زمانی رخ می‌دهد که مقدار بازگردانده‌شده در یک بافت (context) نادرست استفاده شود. .INDENT 0.0 .INDENT 3.5 .sp .EX if (strcmp(...) < 0.) // استفاده نادرست از مقدار بازگردانده‌شده. .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B WarnOnImplicitComparison هنگامی که \fItrue\fP باشد، بررسی روی مقایسه ضمنی هشدار می‌دهد. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B WarnOnLogicalNotComparison هنگامی که \fItrue\fP باشد، بررسی روی مقایسه نقیض منطقی (logical not) هشدار می‌دهد. مقدار پیش‌فرض \fIfalse\fP است. .UNINDENT .INDENT 0.0 .TP .B StringCompareLikeFunctions رشته‌ای که نام توابع اضافی مقایسه رشته را به‌صورت جداشده با کاما مشخص می‌کند. مقدار پیش‌فرض یک رشته خالی است. این بررسی توابع مقایسه رشته زیر را شناسایی خواهد کرد: \fI__builtin_memcmp\fP، \fI__builtin_strcasecmp\fP، \fI__builtin_strcmp\fP، \fI__builtin_strncasecmp\fP، \fI__builtin_strncmp\fP، \fI_mbscmp\fP، \fI_mbscmp_l\fP، \fI_mbsicmp\fP، \fI_mbsicmp_l\fP، \fI_mbsnbcmp\fP، \fI_mbsnbcmp_l\fP، \fI_mbsnbicmp\fP، \fI_mbsnbicmp_l\fP، \fI_mbsncmp\fP، \fI_mbsncmp_l\fP، \fI_mbsnicmp\fP، \fI_mbsnicmp_l\fP، \fI_memicmp\fP، \fI_memicmp_l\fP، \fI_stricmp\fP، \fI_stricmp_l\fP، \fI_strnicmp\fP، \fI_strnicmp_l\fP، \fI_wcsicmp\fP، \fI_wcsicmp_l\fP، \fI_wcsnicmp\fP، \fI_wcsnicmp_l\fP، \fIlstrcmp\fP، \fIlstrcmpi\fP، \fImemcmp\fP، \fImemicmp\fP، \fIstrcasecmp\fP، \fIstrcmp\fP، \fIstrcmpi\fP، \fIstricmp\fP، \fIstrncasecmp\fP، \fIstrncmp\fP، \fIstrnicmp\fP، \fIwcscasecmp\fP، \fIwcscmp\fP، \fIwcsicmp\fP، \fIwcsncmp\fP، \fIwcsnicmp\fP، \fIwmemcmp\fP\&. .UNINDENT .SS bugprone\-suspicious\-stringview\-data\-usage .sp استفاده‌های مشکوک از \fBstd::string_view::data()\fP را که ممکن است به دلیل خاتمه‌نیافتن مناسب یا صحیح رشته با null منجر به خواندن داده خارج از محدوده شود، شناسایی می‌کند. .sp زمانی هشدار می‌دهد که نتیجه \fBdata()\fP به یک سازنده یا تابع ارسال شود بدون اینکه نتیجه متناظر توابع عضو \fBsize()\fP یا \fBlength()\fP نیز ارسال شده باشد. چنین استفاده‌ای می‌تواند منجر به رفتارهای ناخواسته شود، به‌ویژه هنگامی که فرض بر این باشد که داده اشاره‌شده توسط \fBdata()\fP به null ختم شده است. .sp عدم وجود متد \fBc_str()\fP در \fBstd::string_view\fP اغلب توسعه‌دهندگان را به استفاده از \fBdata()\fP به عنوان جایگزین سوق می‌دهد، به‌ویژه هنگام تعامل با APIهای زبان C که انتظار رشته‌های خاتمه‌یافته با null را دارند. با این حال، از آنجا که \fBdata()\fP خاتمه با null را تضمین نمی‌کند، در صورتی که API برای تفسیر صحیح رشته به خاتمه مناسب با null متکی باشد، این امر می‌تواند به رفتار ناخواسته منجر شود. .sp در برنامه‌نویسی امروزی، این سناریو می‌تواند هنگام تبدیل ضمنی یک \fBstd::string_view\fP به \fBstd::string\fP رخ دهد. از آنجا که سازنده طراحی‌شده در \fBstd::string\fP برای اشیاء شبیه string\-view از نوع \fBexplicit\fP است، تلاش برای ارسال یک \fBstd::string_view\fP به تابعی که انتظار \fBstd::string\fP را دارد منجر به خطای کامپایل خواهد شد. به عنوان یک راهکار موقت، ممکن است توسعه‌دهندگان وسوسه شوند تا از متد \fB\&.data()\fP برای رفع خطای کامپایل استفاده کنند که خطرات بالقوه‌ای به همراه دارد. .sp برای نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX void printString(const std::string& str) { std::cout << \(dqString: \(dq << str << std::endl; } void something(std::string_view sv) { printString(sv.data()); } .EE .UNINDENT .UNINDENT .sp در این مثال، ارسال مستقیم \fBsv\fP به تابع \fBprintString\fP به دلیل صریح (explicit) بودن سازنده \fBstd::string\fP منجر به خطای کامپایل می‌شود. در نتیجه، ممکن است توسعه‌دهندگان \fBsv.data()\fP را برای حل خطای کامپایل برگزینند، هرچند که خطرات بالقوه ذکرشده را به همراه دارد. .SS گزینه‌ها .INDENT 0.0 .TP .B StringViewTypes گزینه‌ای که به کاربران اجازه می‌دهد انواع سفارشی شبیه string view را برای تحلیل مشخص کنند. این گزینه فهرستی از نام‌های انواع یا عبارات باقاعده (regular expressions) منطبق بر این انواع را که با سمی‌کالن از هم جدا شده‌اند می‌پذیرد. مقدار پیش‌فرض: \fI::std::basic_string_view;::llvm::StringRef\fP\&. .UNINDENT .INDENT 0.0 .TP .B AllowedCallees متدها، توابع یا کلاس‌هایی را مشخص می‌کند که نتیجه \fB\&.data()\fP به آن‌ها ارسال می‌شود. این گزینه اجازه می‌دهد چنین فراخوانی‌هایی را از تحلیل مستثنی کنید. فهرستی از نام‌ها یا عبارات باقاعده منطبق بر این موجودیت‌ها را که با سمی‌کالن از هم جدا شده‌اند می‌پذیرد. مقدار پیش‌فرض: رشته خالی است. .UNINDENT .SS bugprone\-swapped\-arguments .sp آرگومان‌هایی که احتمالاً جابه‌جا شده‌اند را با بررسی تبدیل‌های ضمنی پیدا می‌کند. این بررسی انواع آرگومان‌های ارسالی به یک تابع را تحلیل کرده و آن‌ها را با انواع مورد انتظار پارامترهای متناظر مقایسه می‌کند. در صورت عدم تطابق یا وجود تبدیل ضمنی که نشان‌دهنده جابه‌جایی احتمالی باشد، هشدار داده می‌شود. .INDENT 0.0 .INDENT 3.5 .sp .EX void printNumbers(int a, float b); int main() { // آرگومان‌های جابه‌جاشده: float به عنوان int ارسال شده، int به عنوان float printNumbers(10.0f, 5); return 0; } .EE .UNINDENT .UNINDENT .sp طیف گسترده‌ای از تبدیل‌های ضمنی را پوشش می‌دهد، از جمله: \- تبدیل‌های تعریف‌شده توسط کاربر (user\-defined) \- تبدیل‌ها از انواع ممیز شناور به انواع بولی یا صحیح \- تبدیل‌ها از انواع صحیح به انواع بولی یا ممیز شناور \- تبدیل‌ها از بولی به انواع صحیح یا انواع ممیز شناور \- تبدیل‌ها از اشاره‌گرها (و اشاره‌گرهای عضو) به بولی .sp مهم است توجه داشته باشید که برای بیشتر جابه‌جایی‌های آرگومان، انواع باید دقیقاً یکسان باشند. با این حال، استثناهایی برای این قاعده وجود دارد. به‌ویژه، هنگامی که آرگومان جابه‌جاشده از نوع صحیح باشد، تطابق دقیق همیشه الزامی نیست. تبدیل‌های صریح ضمنی (implicit casts) از سایر انواع صحیح نیز پذیرفته می‌شوند. به طور مشابه، هنگام کار با آرگومان‌های ممیز شناور، تبدیل‌های ضمنی میان انواع مختلف ممیز شناور قابل قبول در نظر گرفته می‌شوند. .sp برای جلوگیری از سردرگمی، جابه‌جایی‌هایی که در آن‌ها هر دو آرگومان جابه‌جاشده از نوع صحیح، یا هر دو از نوع ممیز شناور باشند، هشدار را فعال نمی‌کنند. در چنین مواردی، فرض بر این است که توسعه‌دهنده عمداً از انواع صحیح یا ممیز شناور مختلف استفاده کرده است و هشداری صادر نمی‌شود. این رویکرد مانع هشدارهای نادرست (false positives) شده و انعطاف‌پذیری لازم را در مدیریت شرایطی که انواع گوناگون صحیح یا ممیز شناور به‌صورت هدفمند استفاده شده‌اند، فراهم می‌کند. .SS bugprone\-switch\-missing\-default\-case .sp اطمینان حاصل می‌کند که دستورهای switch فاقد حالت default نشانه‌گذاری شوند؛ این بررسی تنها بر پوشش حالت‌های غیر enum تمرکز دارد، جایی که کامپایلر ممکن است هشداری صادر نکند. .sp دستورهای switch بدون حالت default می‌توانند منجر به رفتارهای غیرمنتظره و مدیریت ناقص تمام حالت‌های ممکن شوند. هنگامی که یک دستور switch فاقد حالت default باشد، در صورت مواجهه با مقداری که با هیچ‌یک از حالت‌های مشخص‌شده مطابقت ندارد، دستور switch هیچ کاری انجام نخواهد داد و برنامه بدون مدیریت آن مقدار، به اجرای خود ادامه می‌دهد. .sp این بررسی به شناسایی دستورهای switch فاقد حالت default کمک می‌کند و به توسعه‌دهندگان اجازه می‌دهد تا از مدیریت صحیح تمام حالت‌های ممکن مطمئن شوند. افزودن حالت default امکان مدیریت مناسب مقادیر غیرمنتظره یا تطابق‌نیافته را فراهم ساخته و خطر خطاهای برنامه و رفتارهای پیش‌بینی‌نشده را کاهش می‌دهد. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX // Example 1: // warning: switching on non\-enum value without default case may not cover all cases switch (i) { case 0: break; } // Example 2: enum E { eE1 }; E e = eE1; switch (e) { // no\-warning case eE1: break; } // Example 3: int i = 0; switch (i) { // no\-warning case 0: break; default: break; } .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 انواع enum در صورتی که یک دستور switch تمام مقادیر enum را پوشش ندهد، پیشاپیش توسط هشدارهای کامپایلر (تحت پرچم \-Wswitch) پوشش داده می‌شوند. این بررسی بر روی انواع غیر enum تمرکز دارد، جایی که ممکن است هشدارهای کامپایلر وجود نداشته باشند. .UNINDENT .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 دستورالعمل CppCoreGuideline ES.79 \% رهنمودهایی دربارهٔ دستورهای switch، از جمله توصیه به ارائهٔ همیشگی یک حالت default ارائه می‌دهد. .UNINDENT .UNINDENT .SS bugprone\-tagged\-union\-member\-count .sp هشدارهایی برای tagged unionها صادر می‌کند، در شرایطی که تعداد برچسب‌ها (tags) با تعداد اعضای داده‌ای درون union متفاوت باشد. .sp یک struct یا یک class در صورتی یک tagged union در نظر گرفته می‌شود که دقیقاً دارای یک عضو داده‌ای union و دقیقاً یک عضو داده‌ای enum باشد و هر تعداد عضو داده‌ای دیگر داشته باشد که نه union هستند و نه enum. علاوه بر این، انواع اعضای union و enum نباید از فایل‌های سرایند سیستمی یا فضای نام \fBstd\fP آمده باشند. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX enum Tags { Tag1, Tag2, }; struct TaggedUnion { // warning: tagged union has more data members (3) than tags (2) enum Tags Kind; union { int I; float F; char *Str; } Data; }; .EE .UNINDENT .UNINDENT .sp مثال زیر استثنای مربوط به unionها و enumهای برگرفته از فایل‌های سرایند سیستمی و فضای نام \fBstd\fP را نشان می‌دهد. .INDENT 0.0 .INDENT 3.5 .sp .EX #include struct NotTaggedUnion { enum MyEnum { MyEnumConstant1, MyEnumConstant2 } En; pthread_mutex_t Mutex; }; .EE .UNINDENT .UNINDENT .sp نوع \fBpthread_mutex_t\fP ممکن است در پس یک \fBtypedef\fP به صورت یک union تعریف شده باشد، که در این حالت بررسی ممکن است این نوع را به اشتباه به عنوان یک tagged union تعریف‌شده توسط کاربر تشخیص دهد؛ چرا که دقیقاً دارای یک عضو داده‌ای enum و دقیقاً یک عضو داده‌ای union است. برای جلوگیری از موارد مثبت کاذب (false-positive) ناشی از این مسئله، unionها و enumهای موجود در سرایندهای سیستمی و فضای نام \fBstd\fP هنگام مشخص کردن بخش union و بخش enum یک tagged union بالقوهٔ تعریف‌شده توسط کاربر، نادیده گرفته می‌شوند. .SS نحوهٔ شمارش ثوابت enum .sp عامل پیچیدگی اصلی هنگام شمارش تعداد ثوابت enum این است که برخی از آن‌ها ممکن است مقادیر کمکی باشند که عمداً هیچ عضو داده‌ای متناظری در union ندارند و برای مقاصد دیگری استفاده می‌شوند. به عنوان مثال، آخرین ثابت enum گاهی اوقات به‌طور صریح به آخرین ثابت enum معتبر اعلان‌شده \(dqاشاره می‌کند\(dq یا تعداد ثوابت enum اعلان‌شده را دنبال می‌کند. .sp جهت نمایش: .INDENT 0.0 .INDENT 3.5 .sp .EX enum TagWithLast { Tag1 = 0, Tag2 = 1, Tag3 = 2, LastTag = 2 }; enum TagWithCounter { Tag1, // is 0 Tag2, // is 1 Tag3, // is 2 TagCount, // is 3 }; .EE .UNINDENT .UNINDENT .sp این بررسی تعداد مقادیر متمایز را در بین ثوابت enum می‌شمارد و نه خود ثوابت enum را. به این ترتیب، ثوابت enum که در اصل تنها نام‌های مستعاری (alias) برای سایر ثوابت enum هستند، در شمارش نهایی لحاظ نمی‌شوند. .sp مدیریت شمارش ثوابت enum (مواردی مانند \fBTagCount\fP در مثال کد قبلی) با کاهش یک واحد از تعداد مقادیر enum انجام می‌شود، در صورتی که نام آخرین ثابت enum با پیشوند یا پسوند مشخص‌شده در \fBCountingEnumPrefixes\fP یا \fBCountingEnumSuffixes\fP مطابقت داشته باشد و مقدار آن یکی کمتر از تعداد کل مقادیر متمایز در enum باشد. .sp هنگامی که شمارش نهایی بر اساس این روش اکتشافی (heuristic) تنظیم شود، یک یادداشت عیب‌یابی صادر می‌شود که نشان می‌دهد کدام ثابت enum با معیارها مطابقت داشته است. .sp این روش اکتشافی می‌تواند کاملاً غیرفعال شود (\fBEnableCountingEnumHeuristic\fP) یا به گونه‌ای پیکربندی شود که از شیوه‌نامهٔ نام‌گذاری شما پیروی کند (\fBCountingEnumPrefixes\fP، \fBCountingEnumSuffixes\fP). رشته‌های مشخص‌شده در \fBCountingEnumPrefixes\fP و \fBCountingEnumSuffixes\fP بدون حساسیت به حروف کوچک و بزرگ مطابقت داده می‌شوند. .sp مثال‌های شمارش: .INDENT 0.0 .INDENT 3.5 .sp .EX // Enum count is 3, because the value 2 is counted only once enum TagWithLast { Tag1 = 0, Tag2 = 1, Tag3 = 2, LastTag = 2 }; // Enum count is 3, because TagCount is heuristically excluded enum TagWithCounter { Tag1, // is 0 Tag2, // is 1 Tag3, // is 2 TagCount, // is 3 }; .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B EnableCountingEnumHeuristic .UNINDENT .sp این گزینه اکتشاف شمارش مقادیر enum (counting enum heuristic) را فعال یا غیرفعال می‌کند. این گزینه از پیشوندها و پسوندهای مشخص‌شده در گزینه‌های \fBCountingEnumPrefixes\fP و \fBCountingEnumSuffixes\fP برای یافتن مقادیر ثابت شمارشگر enum از طریق تطبیق پیشوند و پسوند استفاده می‌کند. .sp این گزینه به‌طور پیش‌فرض فعال است. .sp هنگامی که \fBEnableCountingEnumHeuristic\fP برابر با \fIfalse\fP باشد: .INDENT 0.0 .INDENT 3.5 .sp .EX enum TagWithCounter { Tag1, Tag2, Tag3, TagCount, }; struct TaggedUnion { TagWithCounter Kind; union { int A; long B; char *Str; float F; } Data; }; .EE .UNINDENT .UNINDENT .sp هنگامی که \fBEnableCountingEnumHeuristic\fP برابر با \fItrue\fP باشد: .INDENT 0.0 .INDENT 3.5 .sp .EX enum TagWithCounter { Tag1, Tag2, Tag3, TagCount, }; struct TaggedUnion { // warning: tagged union has more data members (4) than tags (3) TagWithCounter Kind; union { int A; long B; char *Str; float F; } Data; }; .EE .UNINDENT .UNINDENT .INDENT 0.0 .TP .B CountingEnumPrefixes .UNINDENT .sp به \fBCountingEnumSuffixes\fP در زیر مراجعه کنید. .INDENT 0.0 .TP .B CountingEnumSuffixes .UNINDENT .sp گزینه‌های CountingEnumPrefixes و CountingEnumSuffixes فهرست‌هایی از رشته‌های جداشده با نقطه-ویرگول (semicolon) هستند که برای جستجوی مقادیر ثابت احتمالی شمارشگر enum استفاده می‌شوند. این رشته‌ها بدون حساسیت به حروف بزرگ و کوچک (case insensitively) به ترتیب به عنوان پیشوند و پسوند روی نام‌های مقادیر ثابت enum تطبیق داده می‌شوند. اگر \fBEnableCountingEnumHeuristic\fP برابر با \fIfalse\fP باشد، این گزینه‌ها هیچ عملی انجام نمی‌دهند. .sp مقدار پیش‌فرض \fBCountingEnumSuffixes\fP برابر با \fIcount\fP و برای \fBCountingEnumPrefixes\fP رشته خالی است. .sp هنگامی که \fBEnableCountingEnumHeuristic\fP برابر با \fItrue\fP و \fBCountingEnumSuffixes\fP برابر با \fIcount;size\fP باشد: .INDENT 0.0 .INDENT 3.5 .sp .EX enum TagWithCounterCount { Tag1, Tag2, Tag3, TagCount, }; struct TaggedUnionCount { // warning: tagged union has more data members (4) than tags (3) TagWithCounterCount Kind; union { int A; long B; char *Str; float F; } Data; }; enum TagWithCounterSize { Tag11, Tag22, Tag33, TagSize, }; struct TaggedUnionSize { // warning: tagged union has more data members (4) than tags (3) TagWithCounterSize Kind; union { int A; long B; char *Str; float F; } Data; }; .EE .UNINDENT .UNINDENT .sp هنگامی که \fBEnableCountingEnumHeuristic\fP برابر با \fItrue\fP و \fBCountingEnumPrefixes\fP برابر با \fImaxsize;last_\fP باشد: .INDENT 0.0 .INDENT 3.5 .sp .EX enum TagWithCounterLast { Tag1, Tag2, Tag3, last_tag, }; struct TaggedUnionLast { // warning: tagged union has more data members (4) than tags (3) TagWithCounterLast tag; union { int I; short S; char *C; float F; } Data; }; enum TagWithCounterMaxSize { Tag1, Tag2, Tag3, MaxSizeTag, }; struct TaggedUnionMaxSize { // warning: tagged union has more data members (4) than tags (3) TagWithCounterMaxSize tag; union { int I; short S; char *C; float F; } Data; }; .EE .UNINDENT .UNINDENT .INDENT 0.0 .TP .B StrictMode .UNINDENT .sp در صورت فعال بودن، این بررسی زمانی که تعداد برچسب‌ها (tags) بیشتر از تعداد اعضای داده‌ای union باشد نیز هشدار می‌دهد. .sp این گزینه به‌طور پیش‌فرض غیرفعال است. .sp هنگامی که \fBStrictMode\fP \%<#\:cmdoption-arg-StrictMode> برابر با \fIfalse\fP باشد: .INDENT 0.0 .INDENT 3.5 .sp .EX struct TaggedUnion { enum { Tag1, Tag2, Tag3, } Tags; union { int I; float F; } Data; }; .EE .UNINDENT .UNINDENT .sp هنگامی که \fBStrictMode\fP \%<#\:cmdoption-arg-StrictMode> برابر با \fItrue\fP باشد: .INDENT 0.0 .INDENT 3.5 .sp .EX struct TaggedUnion { // warning: tagged union has fewer data members (2) than tags (3) enum { Tag1, Tag2, Tag3, } Tags; union { int I; float F; } Data; }; .EE .UNINDENT .UNINDENT.SS bugprone\-terminating\-continue .sp حلقه‌های \fBdo while\fP با شرطی که همیشه به نادرست (false) ارزیابی می‌شود و دارای دستور \fBcontinue\fP هستند را شناسایی می‌کند، زیرا این \fBcontinue\fP عملاً حلقه را خاتمه می‌دهد. .INDENT 0.0 .INDENT 3.5 .sp .EX void f() { do { // some code continue; // terminating continue // some other code } while(false); .EE .UNINDENT .UNINDENT .SS bugprone\-throw\-keyword\-missing .sp درباره احتمال جا افتادن کلمه کلیدی \fBthrow\fP هشدار می‌دهد. اگر یک شیء موقت ایجاد شود، اما نوع شیء از کلاسی مشتق شده باشد (یا هم‌نام باشد) که عبارات \(aqEXCEPTION\(aq، \(aqException\(aq یا \(aqexception\(aq در نام آن وجود داشته باشد، می‌توانیم فرض کنیم که قصد برنامه‌نویس پرتاب کردن (throw) آن شیء بوده است. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(int i) { if (i < 0) { // Exception is created but is not thrown. std::runtime_error(\(dqUnexpected argument\(dq); } } .EE .UNINDENT .UNINDENT .SS bugprone\-throwing\-static\-initialization .sp تمام اعلان‌های متغیرهای \fBstatic\fP یا \fBthread_local\fP را که مقداردهنده اولیه آن شیء ممکن است استثنایی پرتاب کند، پیدا می‌کند. .SS References .sp این بررسی با قاعده ERR58\-CPP از استاندارد کدنویسی CERT C++ مطابقت دارد. مدیریت تمام استثناهای پرتاب‌شده پیش از آغاز اجرای ()main \%\&. .SS bugprone\-too\-small\-loop\-variable .sp حلقه‌های \fBfor\fP را شناسایی می‌کند که متغیر حلقه آن‌ها از یک نوع «بسیار کوچک» (\(dqtoo small\(dq) است، به این معنی که این نوع نمی‌تواند تمام مقادیر موجود در محدوده پیمایش را نمایش دهد. .INDENT 0.0 .INDENT 3.5 .sp .EX int main() { long size = 294967296l; for (short i = 0; i < size; ++i) {} } .EE .UNINDENT .UNINDENT .sp این حلقه \fBfor\fP یک حلقه بی‌نهایت است زیرا نوع \fBshort\fP نمی‌تواند تمام مقادیر بازه \fB[0..size]\fP را نمایش دهد. .sp در یک کاربرد واقعی، size به معنی اندازه یک ظرف (container) است که به ورودی کاربر بستگی دارد. .INDENT 0.0 .INDENT 3.5 .sp .EX int doSomething(const std::vector& items) { for (short i = 0; i < items.size(); ++i) {} } .EE .UNINDENT .UNINDENT .sp این الگوریتم برای تعداد اندکی شیء کار می‌کند، اما برای ورودی‌های بزرگتر کاربر منجر به فریز شدن (قفل کردن) برنامه خواهد شد. .sp توصیه می‌شود هشدار کامپایلر \fI\-Wtautological\-constant\-out\-of\-range\-compare\fP را نیز فعال کنید، چرا که این بررسی برای جلوگیری از تداخل با این هشدار، مرزهای ثابت حلقه در زمان کامپایل را بازرسی نمی‌کند. .SS Options .INDENT 0.0 .TP .B MagnitudeBitsUpperLimit حد بالای بیت‌های مقدار (magnitude bits) متغیر حلقه. در صورت تعیین، بررسی مواردی را که در آن‌ها نوع متغیر حلقه دارای بیت‌های مقدار بیشتری نسبت به حد بالای مشخص‌شده باشد، فیلتر می‌کند. مقدار پیش‌فرض ۱۶ است. برای مثال، اگر کاربر این گزینه را روی 31 (بیت) تنظیم کند، یک \fBunsigned int\fP ۳۲ بیتی توسط بررسی نادیده گرفته می‌شود، اما یک \fBint\fP ۳۲ بیتی نادیده گرفته نمی‌شود (یک \fBsigned int\fP ۳۲ بیتی دارای ۳۱ بیت مقدار است). .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX int main() { long size = 294967296l; for (unsigned i = 0; i < size; ++i) {} // no warning with MagnitudeBitsUpperLimit = 31 on a system where unsigned is 32\-bit for (int i = 0; i < size; ++i) {} // warning with MagnitudeBitsUpperLimit = 31 on a system where int is 32\-bit } .EE .UNINDENT .UNINDENT .SS bugprone\-unchecked\-optional\-access .sp \fIنکته\fP: این بررسی برای تولید نتایج خود از تحلیل ایستا حساس به جریان داده (flow\-sensitive) استفاده می‌کند. بنابراین، ممکن است نسبت به یک بررسی معمولی clang\-tidy به منابع بیشتری (RAM، CPU) نیاز داشته باشد. .sp این بررسی دسترسی‌های ناامن به مقادیر موجود در اشیاء \fBstd::optional\fP، \fBabsl::optional\fP، \fBbase::Optional\fP، \fBfolly::Optional\fP، \fBbsl::optional\fP، یا \fBBloombergLP::bdlb::NullableValue\fP را شناسایی می‌کند. در ادامه ما به همه این نوع‌ها به صورت جمعی با عنوان \fBoptional\fP اشاره خواهیم کرد. .sp دسترسی به مقدار یک \fBoptional\fP زمانی رخ می‌دهد که یکی از توابع عضو \fBvalue\fP، \fBoperator*\fP یا \fBoperator\->\fP آن فراخوانی شود. برای همسویی با باورهای نادرست رایج، این بررسی این توابع عضو را معادل در نظر می‌گیرد، اگرچه تفاوت‌های ظریفی بین استثناها و رفتار تعریف‌نشده (undefined behavior) وجود دارد. برای اطلاعات بیشتر در این باره، بخش \fIیادداشت‌های بیشتر\fP را در زیر ببینید. .sp دسترسی به مقدار یک \fBoptional\fP امن تلقی می‌شود اگر و تنها اگر کد موجود در حوزه محلی (برای مثال، بدنه یک تابع) تضمین کند که \fBoptional\fP در تمام مسیرهای ممکنِ اجرا که می‌توانند به این دسترسی برسند، دارای مقدار است. این امر باید یا از طریق یک بررسی صریح با استفاده از تابع عضو \fBoptional::has_value\fP انجام شود، یا از طریق ساختن \fBoptional\fP به روشی که بدون ابهام نشان دهد حاوی مقدار است (مانند استفاده از \fBstd::make_optional\fP که همیشه یک \fBstd::optional\fP پرشده را برمی‌گرداند). .sp در زیر مثال‌هایی آورده‌ایم که با الگوهای دسترسی ناامن به optional شروع شده و با الگوهای دسترسی امن ادامه می‌یابند. .SS Unsafe access patterns .SS Access the value without checking if it exists .sp این بررسی، دسترسی‌هایی به مقدار را نشانه‌گذاری می‌کند که به صورت محلی با بررسی وجود محافظت نشده‌اند: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(std::optional opt) { use(*opt); // unsafe: it is unclear whether \(gaopt\(ga has a value. } .EE .UNINDENT .UNINDENT .SS دسترسی به مقدار در شاخه نادرست .sp این بررسی از وضعیت یک شیء optional در شاخه‌های مختلف کد آگاه است. برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(std::optional opt) { if (opt.has_value()) { } else { use(opt.value()); // unsafe: it is clear that \(gaopt\(ga does *not* have a value. } } .EE .UNINDENT .UNINDENT .SS فرض بر پایدار بودن نتیجه یک تابع .sp این بررسی آگاه است که نتایج توابع ممکن است پایدار نباشند. یعنی فراخوانی‌های متوالی یک تابع یکسان ممکن است مقادیر متفاوتی را بازگردانند. برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(Foo foo) { if (foo.take().has_value()) { use(*foo.take()); // unsafe: it is unclear whether \(gafoo.take()\(ga has a value. } } .EE .UNINDENT .UNINDENT .SS استثنا: متدهای دستیابی (accessor) .sp این بررسی متدهای \fIaccessor\fP یک کلاس را با استفاده از یک روش ابتکاری (heuristic) برای تشخیص اینکه کدام متدها دستیاب هستند، پایدار فرض می‌کند. به‌طور مشخص، متدهای \fBconst\fP بدون پارامتر و APIهای شبه‌اشاره‌گر هوشمند (سربارگذاری‌های غیر \fBconst\fP از \fB*\fP در صورتی که یک سربارگذاری \fBconst\fP موازی وجود داشته باشد) به عنوان متدهای دستیاب در نظر گرفته می‌شوند. توجه داشته باشید که ایمن بودن این کار تضمین‌شده نیست \-\- اما در عمل به‌طور گسترده (و ایمن) استفاده می‌شود. فرض بر این است که فراخوانی متدهای غیر \fBconst\fP وضعیت شیء را تغییر داده و بر پایداری فراخوانی‌های قبلی متدهای دستیاب اثر می‌گذارد. .SS اتکا به ناورداهای APIهای نامعمول .sp این بررسی از ناورداهای (invariants) مربوط به APIهای نامعمول آگاه نیست. برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(Foo foo) { if (foo.HasProperty(\(dqbar\(dq)) { use(*foo.GetProperty(\(dqbar\(dq)); // unsafe: it is unclear whether \(gafoo.GetProperty(\(dqbar\(dq)\(ga has a value. } } .EE .UNINDENT .UNINDENT .SS بررسی وجود مقدار، سپس ارسال optional به تابعی دیگر .sp این بررسی بر استدلال محلی تکیه دارد. بررسی و دسترسی به مقدار هر دو باید در یک تابع یکسان رخ دهند. دسترسی ناامن تلقی می‌شود، حتی اگر فراخوانندهٔ تابعی که دسترسی را انجام می‌دهد اطمینان حاصل کند که شیء optional حاوی مقدار است. برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void g(std::optional opt) { use(*opt); // unsafe: it is unclear whether \(gaopt\(ga has a value. } void f(std::optional opt) { if (opt.has_value()) { g(opt); } } .EE .UNINDENT .UNINDENT .SS الگوهای دسترسی ایمن .SS بررسی وجود مقدار، سپس دسترسی به آن .sp این بررسی تمام روش‌های سرراست برای بررسی وجود مقدار و دسترسی به مقدارِ درون یک شیء optional را شناسایی می‌کند. برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(std::optional opt) { if (opt.has_value()) { use(*opt); } } .EE .UNINDENT .UNINDENT .SS بررسی وجود مقدار، سپس دسترسی به مقدار از طریق یک کپی .sp معیاری که این بررسی به کار می‌برد معنایی (semantic) است، نه نحوی (syntactic). این بررسی تشخیص می‌دهد چه زمانی یک کپی از شیء optional در حال دسترسی، دارای مقدار است. برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(std::optional opt1) { if (opt1.has_value()) { std::optional opt2 = opt1; use(*opt2); } } .EE .UNINDENT .UNINDENT .SS اطمینان از وجود مقدار با استفاده از ماکروهای رایج .sp این بررسی از ماکروهای رایجی مانند \fBCHECK\fP و \fBDCHECK\fP آگاه است. از این ماکروها می‌توان برای اطمینان از اینکه یک شیء optional دارای مقدار است استفاده کرد. برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(std::optional opt) { DCHECK(opt.has_value()); use(*opt); } .EE .UNINDENT .UNINDENT .SS اطمینان از وجود مقدار، سپس دسترسی به مقدار در شاخه‌ای مرتبط .sp این بررسی از شاخه‌های مرتبط در کد آگاه است و می‌تواند تشخیص دهد چه زمانی در تمام مسیرهای اجرایی منتهی به دسترسی، وجود مقدار در یک شیء optional تضمین شده است. برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(std::optional opt) { bool safe = false; if (opt.has_value() && SomeOtherCondition()) { safe = true; } // ... more code... if (safe) { use(*opt); } } .EE .UNINDENT .UNINDENT .SS تثبیت نتایج توابع .sp فرض بر این نیست که نتایج تابع در طول فراخوانی‌های پیاپی پایدار باشند، مگر برای متدهای دسترسی‌دهنده (accessor) از نوع const. برای متدهای دسترسی‌دهنده پیچیده‌تر (غیر const، یا وابسته به چندین پارامتر) بهتر است نتیجه فراخوانی تابع در یک متغیر محلی ذخیره شده و از آن متغیر برای دسترسی به مقدار استفاده شود. به عنوان مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(Foo foo) { if (const auto& foo_opt = foo.take(); foo_opt.has_value()) { use(*foo_opt); } } .EE .UNINDENT .UNINDENT .SS عدم اتکا به ناورداهای APIهای غیرمعمول .sp هنگامی که APIهای نامتعارف تضمین می‌کنند که یک optional حاوی محتوا است، به آن اعتماد نکنید \-\- در عوض، صریحاً بررسی کنید که شیء optional دارای مقدار باشد. برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(Foo foo) { if (const auto& property = foo.GetProperty(\(dqbar\(dq)) { use(*property); } } .EE .UNINDENT .UNINDENT .sp به جای زوج \fIHasProperty\fP و \fIGetProperty\fP که در بالا دیدیم. .SS عدم اتکا به بررسی‌های انجام‌شده توسط فراخواننده .sp اگر می‌دانید که تمام فراخواننده‌های یک تابع بررسی کرده‌اند که یک آرگومان optional دارای مقدار است، یا تابع را به گونه‌ای تغییر دهید که مقدار را مستقیماً دریافت کند یا optional را دوباره در حوزه محلی تابع فراخوانی‌شده بررسی کنید. برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void g(int val) { use(val); } void f(std::optional opt) { if (opt.has_value()) { g(*opt); } } .EE .UNINDENT .UNINDENT .sp و .INDENT 0.0 .INDENT 3.5 .sp .EX struct S { std::optional opt; int x; }; void g(const S &s) { if (s.opt.has_value() && s.x > 10) { use(*s.opt); } void f(S s) { if (s.opt.has_value()) { g(s); } } .EE .UNINDENT .UNINDENT .SS نکات تکمیلی .SS نام‌های مستعار ایجاد شده از طریق اعلان‌های \fBusing\fP .sp این بررسی از نام‌های مستعار انواع optional که از طریق اعلان‌های \fBusing\fP ایجاد می‌شوند آگاه است. برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX using OptionalInt = std::optional; void f(OptionalInt opt) { use(opt.value()); // unsafe: it is unclear whether \(gaopt\(ga has a value. } .EE .UNINDENT .UNINDENT .SS توابع لامبدا .sp این بررسی در حال حاضر دسترسی‌های ناامن optional را در توابع لامبدا گزارش نمی‌کند. نسخه بعدی با پیروی از قوانین مشخص‌شده در بالا، دامنه را به لامبداها گسترش خواهد داد. بهتر است هنگام استفاده از optionalها در لامبداها از همین اصول پیروی کنید. .SS دسترسی از طریق \fBoperator*()\fP در مقایسه با \fBvalue()\fP .sp با توجه به اینکه \fBvalue()\fP رفتار کاملاً تعریف‌شده‌ای دارد (یا استثنا پرتاب می‌کند یا برنامه را خاتمه می‌دهد)، چرا رفتاری مشابه با \fBoperator*()\fP دارد که باعث رفتار تعریف‌نشده (UB) می‌شود؟ به عبارت دیگر، چرا دسترسی به یک optional با استفاده از \fBvalue()\fP ناامن تلقی می‌شود، در صورتی که قابل اثبات نباشد که حاوی مقدار است؟ به همین ترتیب، چرا \fBCHECK()\fP به همراه \fBoperator*()\fP بهتر از \fBvalue()\fP است، با توجه به اینکه از نظر معنایی معادل یکدیگرند (در پیکربندی‌هایی که استثناها را غیرفعال کرده‌اند)؟ .sp پاسخ این است که ما فرض می‌کنیم اکثر کاربران متوجه تفاوت بین \fBvalue()\fP و \fBoperator*()\fP نیستند\&. تغییر شیوه به \fBoperator*()\fP و نوعی بررسی صریح وجود مقدار یا خاتمه صریح برنامه دارای دو مزیت است: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 خوانایی. بررسی انجام‌شده و هرگونه عوارض جانبی احتمالی مانند خاموش شدن برنامه، در کد کاملاً واضح هستند. جداسازی دسترسی از بررسی‌ها می‌تواند در عمل بررسی‌ها را مشهودتر سازد. .IP \(bu 2 کارایی. یک بررسی واحد می‌تواند بسیاری یا حتی تمام دسترسی‌های موجود در یک محدوده را پوشش دهد. این کار بهترین‌های هر دو حوزه را در اختیار کاربر قرار می‌دهد \-\- امنیت یک بررسی پویا، اما بدون تحمیل هزینه‌های مازاد و تکراری. .UNINDENT .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoreSmartPointerDereference اگر روی \fItrue\fP تنظیم شود، این بررسی از optionalهایی که از طریق ارجاع‌زدایی سربارگذاری‌شده شبه‌اشاره‌گر هوشمند (\fBoperator*\fP، \fBoperator\->\fP) روی کلاس‌هایی غیر از خود نوع optional به دست می‌آیند چشم‌پوشی می‌کند. این امر به جلوگیری از مثبت کاذب در مواردی که تحلیل نمی‌تواند نتایج حاصل از چنین فراخوانی‌هایی را تطبیق دهد، کمک می‌کند. این گزینه دسترسی از طریق \fBoperator[]\fP را پوشش نمی‌دهد\&. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .INDENT 0.0 .TP .B IgnoreValueCalls اگر روی \fItrue\fP تنظیم شود، این بررسی فراخوانی‌های مربوط به \fBoptional::value()\fP را عیب‌یابی نمی‌کند\&. عیب‌یابی برای \fBoperator*()\fP و \fBoperator\->()\fP همچنان فعال می‌ماند. این گزینه برای پایگاه‌های کدی مناسب است که به طور هدفمند به \fBvalue()\fP برای دسترسی محافظت‌شده و تعریف‌شده متکی هستند، در حالی که همچنان ارجاع‌زدایی‌های مستعد UB عملگرها را نشانه‌گذاری می‌کنند. پیش‌فرض \fIfalse\fP است\&. .UNINDENT .SS bugprone\-unchecked\-string\-to\-number\-conversion .sp این بررسی فراخوانی توابع تبدیل رشته به عدد را که صحت تبدیل را بررسی نمی‌کنند، مانند \fBatoi()\fP یا \fBscanf()\fP، نشانه‌گذاری می‌کند. این بررسی فراخوانی‌های \fBstrtol()\fP یا سایر توابع تبدیل مرتبط را که بررسی خطای بهتری انجام می‌دهند، نشانه‌گذاری نمی‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX #include void func(const char *buff) { int si; if (buff) { si = atoi(buff); /* \(aqatoi\(aq used to convert a string to an integer, but function will not report conversion errors; consider using \(aqstrtol\(aq instead. */ } else { /* Handle error */ } } .EE .UNINDENT .UNINDENT .SS مراجع .sp این بررسی با قاعده استاندارد کدنویسی CERT C مطابقت دارد: ERR34\-C. Detect errors when converting a string to a number \%\&. .SS bugprone\-undefined\-memory\-manipulation .sp فراخوانی توابع دستکاری حافظه \fBmemset()\fP، \fBmemcpy()\fP و \fBmemmove()\fP را روی اشیاء غیر TriviallyCopyable که منجر به رفتار تعریف‌نشده (undefined behavior) می‌شوند، پیدا می‌کند. .sp استفاده از توابع دستکاری حافظه روی اشیاء غیر TriviallyCopyable می‌تواند منجر به مجموعه‌ای از مشکلات ظریف و چالش‌برانگیز در کدهای C++ شود. فوری‌ترین نگرانی، احتمال بروز رفتار تعریف‌نشده است که در آن ممکن است وضعیت شیء خراب یا نامعتبر شود. این مسئله می‌تواند به صورت کرش، خرابی داده‌ها، یا رفتارهای غیرمنتظره در زمان اجرا ظاهر شود و شناسایی و عیب‌یابی علت اصلی را دشوار سازد. علاوه بر این، استفاده نادرست از توابع دستکاری حافظه می‌تواند عملیات ضروری مختص شیء، مانند سازنده‌ها و نابودکننده‌ها را دور بزند و منجر به نشت منابع یا مقداردهی اولیه نادرست شود. .sp به عنوان مثال، هنگام استفاده از \fBmemcpy\fP برای کپی کردن \fBstd::string\fP، داده‌های اشاره‌گر کپی می‌شوند و این امر می‌تواند منجر به خطای آزادسازی مضاعف (double free) شود. .INDENT 0.0 .INDENT 3.5 .sp .EX #include #include int main() { std::string source = \(dqHello\(dq; std::string destination; std::memcpy(&destination, &source, sizeof(std::string)); // Undefined behavior may occur here, during std::string destructor call. return 0; } .EE .UNINDENT .UNINDENT .SS bugprone\-undelegated\-constructor .sp ایجاد اشیاء موقت در سازنده‌ها را که شبیه به فراخوانی تابعی از یک سازنده دیگر از همان کلاس به نظر می‌رسند، پیدا می‌کند. .sp کاربر به احتمال زیاد قصد استفاده از یک سازنده واسط (delegating constructor) یا مقداردهی اولیه کلاس پایه را داشته است. .SS bugprone\-unhandled\-exception\-at\-new .sp فراخوانی‌های \fBnew\fP فاقد مدیریت‌کننده استثنا برای \fBstd::bad_alloc\fP را پیدا می‌کند. .sp فراخوانی‌های \fBnew\fP ممکن است استثناهایی از نوع \fBstd::bad_alloc\fP پرتاب کنند که باید مدیریت شوند. به عنوان روش جایگزین، می‌توان از شکل بدون پرتاب استثنای (nonthrowing) عملگر \fBnew\fP استفاده کرد. این بررسی صحت مدیریت استثنا در تابعی را که \fBnew\fP را فراخوانی می‌کند، تأیید می‌نماید. .sp اگر از نسخه nonthrowing استفاده شود یا اجازه داده شود استثنا به خارج از تابع منتشر (propagate) شود، هیچ هشداری تولید نمی‌شود. .sp بررسی می‌شود که آیا مدیریت‌کننده استثنا یک استثنا از نوع \fBstd::bad_alloc\fP، یا \fBstd::exception\fP، و یا همه استثناها (catch\-all) را دریافت می‌کند یا خیر. این بررسی فرض می‌کند هر \fBoperator new\fP تعریف‌شده توسط کاربر یا \fBnoexcept\fP است یا ممکن است استثنایی از نوع \fBstd::bad_alloc\fP (یا مشتق‌شده از آن) پرتاب کند. سایر انواع کلاس‌های استثنا در نظر گرفته نمی‌شوند. .INDENT 0.0 .INDENT 3.5 .sp .EX int *f() noexcept { int *p = new int[1000]; // warning: missing exception handler for allocation failure at \(aqnew\(aq // ... return p; } .EE .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX int *f1() { // not \(aqnoexcept\(aq int *p = new int[1000]; // no warning: exception can be handled outside // of this function // ... return p; } int *f2() noexcept { try { int *p = new int[1000]; // no warning: exception is handled // ... return p; } catch (std::bad_alloc &) { // ... } // ... } int *f3() noexcept { int *p = new (std::nothrow) int[1000]; // no warning: \(dqnothrow\(dq is used // ... return p; } .EE .UNINDENT .UNINDENT .SS bugprone\-unhandled\-self\-assignment .sp شناسه \fIcert\-oop54\-cpp\fP به عنوان نام مستعار این بررسی به اینجا تغییر مسیر می‌دهد. برای نام مستعار CERT، گزینه \fIWarnOnlyIfThisHasSuspiciousField\fP بر روی \fIfalse\fP تنظیم شده است. .sp عملگرهای انتساب کپی تعریف‌شده توسط کاربر را که با بررسی صریح انتساب به خود یا با استفاده از روش copy\-and\-swap یا copy\-and\-move از کد در برابر انتساب به خود محافظت نمی‌کنند، پیدا می‌کند. .sp به‌طور پیش‌فرض، این بررسی برای جلوگیری از هشدارهای نادرست (false positives)، تنها کلاس‌هایی را جستجو می‌کند که دارای فیلد اشاره‌گر یا آرایه C هستند. در صورت وجود اشاره‌گر یا آرایه C، اگر عملگر انتساب کپی با دقت نوشته نشده باشد، احتمال دارد انتساب کپی به خود باعث خرابی شیء شود. .sp همچنین ببینید: OOP54\-CPP. Gracefully handle self\-copy assignment \% .sp یک عملگر انتساب کپی باید از خراب شدن وضعیت شیء توسط انتساب کپی به خود جلوگیری کند. یک سناریوی رایج زمانی است که کلاس دارای یک فیلد اشاره‌گر باشد و عملگر انتساب کپی ابتدا شیء اشاره‌شده را آزاد کرده و سپس سعی کند آن را انتساب دهد: .INDENT 0.0 .INDENT 3.5 .sp .EX class T { int* p; public: T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {} ~T() { delete p; } // ... T& operator=(const T &rhs) { delete p; p = new int(*rhs.p); return *this; } }; .EE .UNINDENT .UNINDENT .sp برای جلوگیری از این مشکل، دو الگوی رایج C++ وجود دارد. الگوی اول، بررسی انتساب به خود (self\-assignment check) است: .INDENT 0.0 .INDENT 3.5 .sp .EX class T { int* p; public: T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {} ~T() { delete p; } // ... T& operator=(const T &rhs) { if(this == &rhs) return *this; delete p; p = new int(*rhs.p); return *this; } }; .EE .UNINDENT .UNINDENT .sp روش دوم روش copy\-and\-swap است، هنگامی که یک کپی موقت (با استفاده از سازنده کپی) ایجاد می‌کنیم و سپس این شیء موقت را با \fBthis\fP تعویض (swap) می‌نماییم: .INDENT 0.0 .INDENT 3.5 .sp .EX class T { int* p; public: T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {} ~T() { delete p; } // ... void swap(T &rhs) { using std::swap; swap(p, rhs.p); } T& operator=(const T &rhs) { T(rhs).swap(*this); return *this; } }; .EE .UNINDENT .UNINDENT .sp الگوی سومی نیز وجود دارد که کمتر رایج است. می‌توان آن را روش copy\-and\-move نامید، زمانی که یک کپی موقت ایجاد می‌کنیم (با استفاده از سازنده کپی) و سپس این شیء موقت را به \fBthis\fP انتقال (move) می‌دهیم (به یک عملگر انتساب انتقال نیاز دارد): .INDENT 0.0 .INDENT 3.5 .sp .EX class T { int* p; public: T(const T &rhs) : p(rhs.p ? new int(*rhs.p) : nullptr) {} ~T() { delete p; } // ... T& operator=(const T &rhs) { T t = rhs; *this = std::move(t); return *this; } T& operator=(T &&rhs) { p = rhs.p; rhs.p = nullptr; return *this; } }; .EE .UNINDENT .UNINDENT .SS Options .INDENT 0.0 .TP .B WarnOnlyIfThisHasSuspiciousField هنگامی که \fItrue\fP باشد، این بررسی تنها در صورتی هشدار می‌دهد که کلاس نگه‌دارندهٔ عملگر انتساب کپی (copy assignment operator) دارای هرگونه فیلد مشکوک (اشاره‌گر، آرایهٔ C و اشاره‌گر هوشمند ++C) باشد. این گزینه به طور پیش‌فرض روی \fItrue\fP تنظیم شده است. .UNINDENT .SS bugprone\-unintended\-char\-ostream\-output .sp خروجی‌های ناخواسته کاراکتر از نوع‌های \fBunsigned char\fP و \fBsigned char\fP به یک \fBostream\fP را می‌یابد. .sp معمولاً هنگامی که \fBunsigned char (uint8_t)\fP یا \fBsigned char (int8_t)\fP استفاده می‌شود، بیشتر بیانگر یک عدد است تا یک کاراکتر. با این حال، هنگامی که مستقیماً به \fBoperator<<\fP در \fBstd::ostream\fP فرستاده می‌شود، نتیجه به جای مقدار عددی، خروجی کاراکتری خواهد بود. این مسئله اغلب با قصد برنامه‌نویس برای چاپ مقادیر عددی صحیح مغایرت دارد. .INDENT 0.0 .INDENT 3.5 .sp .EX uint8_t v = 65; std::cout << v; // output \(aqA\(aq instead of \(aq65\(aq .EE .UNINDENT .UNINDENT .sp این بررسی پیشنهاد تبدیل نوع (cast) مقدار به نوعی مناسب را برای مشخص کردن هدف ارائه می‌دهد؛ به صورت پیش‌فرض، برای \fBunsigned char\fP به \fBunsigned int\fP و برای \fBsigned char\fP به \fBint\fP تبدیل می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX std::cout << static_cast(v); // when v is unsigned char std::cout << static_cast(v); // when v is signed char .EE .UNINDENT .UNINDENT .sp برای جلوگیری از عبارات طولانی تبدیل نوع، افزودن پیشوند \fB+\fP به متغیر نیز می‌تواند هشدارها را سرکوب کند؛ زیرا عبارت یکانی مقدار را به یک \fBint\fP ارتقا می‌دهد (type promotion). .INDENT 0.0 .INDENT 3.5 .sp .EX std::cout << +v; .EE .UNINDENT .UNINDENT .sp یا می‌توان آن را به صورت صریح به char تبدیل نوع کرد تا مشخص شود خروجی حتماً باید یک کاراکتر باشد. .INDENT 0.0 .INDENT 3.5 .sp .EX std::cout << static_cast(v); .EE .UNINDENT .UNINDENT .SS Options .INDENT 0.0 .TP .B AllowedTypes فهرستی از نام‌های انواع که با نقطه-ویرگول (semicolon) از هم جدا شده‌اند و همانند نوع \fBchar\fP با آن‌ها رفتار خواهد شد: این بررسی متغیرهای اعلان‌شده با این انواع یا عبارات تبدیل صریح به این انواع را گزارش نخواهد کرد. توجه داشته باشید که این گزینه میان نام‌های مستعار نوع (type aliases) و نوع اصلی تمایز قائل می‌شود، بنابراین مشخص کردن مواردی مانند \fBunsigned char\fP در اینجا، گزارش‌های مربوط به \fBuint8_t\fP را حتی اگر به عنوان یک نام مستعار \fBtypedef\fP برای \fBunsigned char\fP تعریف شده باشد، سرکوب نخواهد کرد. پیش‌فرض \fIunsigned char;signed char\fP است. .UNINDENT .INDENT 0.0 .TP .B CastTypeName هنگامی که \fICastTypeName\fP مشخص شده باشد، رفع خودکار (fix\-it) از \fICastTypeName\fP به عنوان نوع مقصد تبدیل استفاده می‌کند. در غیر این صورت، fix\-it نوع را به طور خودکار استنتاج خواهد کرد. .UNINDENT .SS bugprone\-unique\-ptr\-array\-mismatch .sp مقداردهی‌های اولیهٔ اشاره‌گرهای یکتای ++C (از نوع std::unique_ptr) از انواع غیرآرایه‌ای را که با یک آرایه مقداردهی شده‌اند، پیدا می‌کند. .sp اگر یک اشاره‌گر \fBstd::unique_ptr\fP با یک عبارت new از نوع \fBnew T[]\fP مقداردهی اولیه شود، حافظه به درستی آزاد نمی‌شود. در این حالت برای آزادسازی حافظهٔ هدف از یک \fBdelete\fP معمولی استفاده می‌شود؛ در حالی که به فراخوانی \fBdelete[]\fP نیاز است. ساختار \fBstd::unique_ptr\fP از عملگر delete صحیح استفاده می‌کند. اگر از یک \fBunique_ptr\fP با deleter تعریف‌شده توسط کاربر استفاده شود، این بررسی هشداری صادر نمی‌کند. .sp اگر در اعلان یک متغیر منفرد استفاده شده باشد (یک متغیر در یک دستور)، این بررسی جایگزینی \fBunique_ptr\fP با \fBunique_ptr\fP را پیشنهاد می‌دهد. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX std::unique_ptr x(new Foo[10]); // \-> std::unique_ptr x(new Foo[10]); // ^ warning: unique pointer to non\-array is initialized with array std::unique_ptr x1(new Foo), x2(new Foo[10]); // no replacement // ^ warning: unique pointer to non\-array is initialized with array D d; std::unique_ptr x3(new Foo[10], d); // no warning (custom deleter used) struct S { std::unique_ptr x(new Foo[10]); // no replacement in this case // ^ warning: unique pointer to non\-array is initialized with array }; .EE .UNINDENT .UNINDENT .sp این بررسی تا حدی قاعدهٔ MEM51\-CPP مربوط به CERT C++ Coding Standard را پوشش می‌دهد: Properly deallocate dynamically allocated resources \% با این حال، تنها حالت \fBstd::unique_ptr\fP توسط این بررسی شناسایی می‌شود. .SS bugprone\-unsafe\-functions .sp توابعی را بررسی می‌کند که جایگزین‌های ایمن‌تر و امن‌تری برای آن‌ها در دسترس است، یا به دلیل ایرادات طراحی منسوخ (deprecated) در نظر گرفته می‌شوند. این بررسی به شدت به توابع موجود در \fBAnnex K.\fP به عنوان «Bounds\-checking interfaces» در استاندارد C11 متکی است. .INDENT 0.0 .TP .B این بررسی قواعد زیر را از CERT C Coding Standard پیاده‌سازی می‌کند: .INDENT 7.0 .IP \(bu 2 توصیهٔ MSC24\-C: عدم استفاده از توابع منسوخ یا رو به زوال \%\&. .IP \(bu 2 قاعدهٔ MSC33\-C: عدم ارسال داده‌های نامعتبر به تابع asctime() \%\&. .UNINDENT .UNINDENT .sp گزینه‌های \fIcert\-msc24\-c\fP و \fIcert\-msc33\-c\fP به عنوان نام‌های مستعار این بررسی به اینجا هدایت می‌شوند. .SS Unsafe functions .sp توابع زیر در صورت فعال بودن \fBReportDefaultFunctions\fP گزارش می‌شوند. .sp در صورت در دسترس بودن \fIAnnex K.\fP، یک جایگزین از \fIAnnex K.\fP برای توابع زیر پیشنهاد می‌شود: .sp \fBasctime\fP, \fBasctime_r\fP, \fBbsearch\fP, \fBctime\fP, \fBfopen\fP, \fBfprintf\fP, \fBfreopen\fP, \fBfscanf\fP, \fBfwprintf\fP, \fBfwscanf\fP, \fBgetenv\fP, \fBgets\fP, \fBgmtime\fP, \fBlocaltime\fP, \fBmbsrtowcs\fP, \fBmbstowcs\fP, \fBmemcpy\fP, \fBmemmove\fP, \fBmemset\fP, \fBprintf\fP, \fBqsort\fP, \fBscanf\fP, \fBsnprintf\fP, \fBsprintf\fP, \fBsscanf\fP, \fBstrcat\fP, \fBstrcpy\fP, \fBstrerror\fP, \fBstrlen\fP, \fBstrncat\fP, \fBstrncpy\fP, \fBstrtok\fP, \fBswprintf\fP, \fBswscanf\fP, \fBvfprintf\fP, \fBvfscanf\fP, \fBvfwprintf\fP, \fBvfwscanf\fP, \fBvprintf\fP, \fBvscanf\fP, \fBvsnprintf\fP, \fBvsprintf\fP, \fBvsscanf\fP, \fBvswprintf\fP, \fBvswscanf\fP, \fBvwprintf\fP, \fBvwscanf\fP, \fBwcrtomb\fP, \fBwcscat\fP, \fBwcscpy\fP, \fBwcslen\fP, \fBwcsncat\fP, \fBwcsncpy\fP, \fBwcsrtombs\fP, \fBwcstok\fP, \fBwcstombs\fP, \fBwctomb\fP, \fBwmemcpy\fP, \fBwmemmove\fP, \fBwprintf\fP, \fBwscanf\fP\&. .sp اگر \fIAnnex K.\fP در دسترس نباشد، جایگزین‌ها تنها برای توابع زیر از فهرست قبلی پیشنهاد می‌شوند: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 \fBasctime\fP, \fBasctime_r\fP، جایگزین پیشنهادی: \fBstrftime\fP .IP \(bu 2 \fBgets\fP، جایگزین پیشنهادی: \fBfgets\fP .UNINDENT .UNINDENT .UNINDENT .sp توابع زیر بدون در نظر گرفتن در دسترس بودن \fIAnnex K\fP، همواره بررسی می‌شوند: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 \fBrewind\fP، جایگزین پیشنهادی: \fBfseek\fP .IP \(bu 2 \fBsetbuf\fP، جایگزین پیشنهادی: \fBsetvbuf\fP .UNINDENT .UNINDENT .UNINDENT .sp اگر \fBReportMoreUnsafeFunctions\fP فعال باشد، توابع زیر نیز بررسی می‌شوند: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 \fBbcmp\fP، جایگزین پیشنهادی: \fBmemcmp\fP .IP \(bu 2 \fBbcopy\fP، جایگزین پیشنهادی: \fBmemcpy_s\fP در صورت در دسترس بودن \fIAnnex K\fP، یا \fBmemcpy\fP .IP \(bu 2 \fBbzero\fP، جایگزین پیشنهادی: \fBmemset_s\fP در صورت در دسترس بودن \fIAnnex K\fP، یا \fBmemset\fP .IP \(bu 2 \fBgetpw\fP، جایگزین پیشنهادی: \fBgetpwuid\fP .IP \(bu 2 \fBvfork\fP، جایگزین پیشنهادی: \fBposix_spawn\fP .UNINDENT .UNINDENT .UNINDENT .sp اگرچه در قواعد مرتبط CERT ذکر شده‌اند، توابع زیر توسط این بررسی \fBنادیده گرفته می‌شوند\fP: .sp \fBatof\fP, \fBatoi\fP, \fBatol\fP, \fBatoll\fP, \fBtmpfile\fP\&. .sp در دسترس بودن \fIAnnex K\fP بر اساس ماکروهای زیر تعیین می‌شود: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 \fB__STDC_LIB_EXT1__\fP: ماکروی ویژگی (feature macro)، که نشان‌دهندهٔ حضور \fIAnnex K. \(dqBounds\-checking interfaces\(dq\fP در پیاده‌سازی کتابخانه است .IP \(bu 2 \fB__STDC_WANT_LIB_EXT1__\fP: ماکروی تعریف‌شده توسط کاربر، که نشان می‌دهد کاربر درخواست تعریف توابع موجود در \fIAnnex K.\fP را دارد. .UNINDENT .UNINDENT .UNINDENT .sp هر دو ماکرو باید تعریف شده باشند تا توابع جایگزین از \fIAnnex K.\fP پیشنهاد شوند. \fB__STDC_LIB_EXT1__\fP توسط پیاده‌سازی کتابخانه تعریف می‌شود، و \fB__STDC_WANT_LIB_EXT1__\fP باید \fBپیش از\fP گنجاندن هرگونه فایل سرایند سیستمی توسط کاربر برابر با \fB1\fP تعریف شود. .SS توابع سفارشی .sp گزینهٔ \fBCustomFunctions\fP به کاربر امکان می‌دهد تا توابع سفارشی را برای بررسی شدن تعریف کند. قالب آن به صورت زیر و بدون خطوط جدید (newline) است: .INDENT 0.0 .INDENT 3.5 .sp .EX bugprone\-unsafe\-functions.CustomFunctions=\(dq functionRegex1[, replacement1[, reason1]]; functionRegex2[, replacement2[, reason2]]; ... \(dq .EE .UNINDENT .UNINDENT .sp توابع با استفاده از عبارت‌های منظم تعمیم‌یافتهٔ POSIX تطبیق داده می‌شوند. \fI(نکته: عبارت‌های منظم از تطبیق‌های منفی\fP \fB(?!)\fP \fIپشتیبانی نمی‌کنند.)\fP .sp شناسهٔ \fIreason\fP اختیاری است و برای ارائهٔ اطلاعات بیشتر در مورد دلیلِ پشتِ این جایگزینی استفاده می‌شود. دلیل پیش‌فرض عبارت است از \fIis marked as unsafe\fP\&. .sp اگر \fIreplacement\fP خالی باشد، متن پیش‌فرض \fIit should not be used\fP به جای پیشنهادی برای جایگزینی نمایش داده خواهد شد. .sp اگر \fIreason\fP با نویسهٔ \fI>\fP شروع شود، دلیل کاملاً سفارشی می‌شود. پسوند پیش‌فرض حتی در صورت وجود \fIreplacement\fP نیز غیرفعال شده و برای ایجاد امکان کنترل بهتر بر روی پیشنهادات، تنها پیام دلیل پس از تابع تطبیق‌یافته نمایش داده می‌شود. (نویسهٔ \fI>\fP ابتدایی و فاصله‌های خالی بلافاصله پس از آن از پیام حذف می‌شوند.) .sp به عنوان مثال، پیکربندی زیر تنها تابع \fBoriginal\fP در فضای‌نام پیش‌فرض را تطبیق می‌دهد. یک پیام عیب‌یابی مشابه را می‌توان با استفاده از یک دلیل کاملاً سفارشی نیز چاپ کرد. .INDENT 0.0 .INDENT 3.5 .sp .EX // bugprone\-unsafe\-functions.CustomFunctions: // ^original$, replacement, is deprecated; // Using the fully custom message syntax: // ^suspicious$,,> should be avoided if possible. original(); // warning: function \(aqoriginal\(aq is deprecated; \(aqreplacement\(aq should be used instead. suspicious(); // warning: function \(aqsuspicious\(aq should be avoided if possible. ::std::original(); // no\-warning original_function(); // no\-warning .EE .UNINDENT .UNINDENT .sp اگر عبارت منظم شامل نویسهٔ \fI:\fP باشد، با نام دارای صلاحیت (یعنی \fBstd::original\fP) تطبیق داده می‌شود؛ در غیر این صورت عبارت منظم با نام بدون صلاحیت (\fBoriginal\fP) تطبیق داده خواهد شد. اگر عبارت منظم با \fI::\fP (یا \fI^::\fP) آغاز شود، با نام دارای صلاحیت کامل (\fB::std::original\fP) تطبیق داده می‌شود. .sp یکی از موارد کاربرد پیام‌های کاملاً سفارشی، پیشنهاد دادن گزینه‌های کامپایلر و فلگ‌های هشدار است: .INDENT 0.0 .INDENT 3.5 .sp .EX // bugprone\-unsafe\-functions.CustomFunctions: // ^memcpy$,,>is recommended to have compiler hardening using \(aq_FORTIFY_SOURCE\(aq; // ^printf$,,>is recommended to have the \(aq\-Werror=format\-security\(aq compiler warning flag; memcpy(dest, src, 999\(aq999); // warning: function \(aqmemcpy\(aq is recommended to have compiler hardening using \(aq_FORTIFY_SOURCE\(aq printf(raw_str); // warning: function \(aqprintf\(aq is recommended to have the \(aq\-Werror=format\-security\(aq compiler warning flag .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 نام‌های دارای صلاحیت کامل می‌توانند در برخی کلاس‌های C++ شامل پارامترهای الگو (template) باشند، اما در توابع C++ این‌گونه نیست. نام‌های مستعار نوع (Type aliases) پیش از تطبیق حل می‌شوند. .sp به عنوان مثال، تابع عضو \fBopen\fP در کلاس \fBstd::ifstream\fP دارای نامِ با صلاحیت کاملِ \fB::std::basic_ifstream::open\fP است. .sp این مثال همچنین می‌تواند با عبارت منظم \fB::std::basic_ifstream<[^>]*>::open\fP تطبیق یابد که تمام پارامترهای احتمالی الگو را تطبیق می‌دهد، اما کلاس‌های الگوی تودرتو را تطبیق نمی‌دهد. .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B ReportMoreUnsafeFunctions در صورت تنظیم روی \fItrue\fP، توابع اضافی از APIهای پرکاربرد (مانند POSIX) به فهرست توابع گزارش‌شده افزوده می‌شوند. برای مشاهدهٔ فهرست کامل مواردی که این گزینه فعال می‌کند، مستندات اصلی این بررسی را مشاهده کنید. پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B ReportDefaultFunctions در صورت تنظیم روی \fItrue\fP، این بررسی مجموعهٔ پیش‌فرض توابع را گزارش می‌کند. اگر تنها می‌خواهید توابع سفارشی تطبیق‌یافته از طریق Custom functions را ببینید، تغییر دادن این تنظیم به false را مد نظر قرار دهید. پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B CustomFunctions فهرستی جداشده با نقطه ویرگول (;) از توابع سفارشی برای تطبیق داده شدن. هر تابعِ تطبیق‌یافته شامل یک عبارت منظم، نام اختیاری تابع جایگزین و یک دلیل اختیاری است که با کاما جدا می‌شوند. برای اطلاعات بیشتر، بخش توابع سفارشی را ببینید. .UNINDENT .SS مثال‌ها .INDENT 0.0 .INDENT 3.5 .sp .EX #ifndef __STDC_LIB_EXT1__ #error \(dqAnnex K is not supported by the current standard library implementation.\(dq #endif #define __STDC_WANT_LIB_EXT1__ 1 #include // Defines functions from Annex K. #include enum { BUFSIZE = 32 }; void Unsafe(const char *Msg) { static const char Prefix[] = \(dqError: \(dq; static const char Suffix[] = \(dq\en\(dq; char Buf[BUFSIZE] = {0}; strcpy(Buf, Prefix); // warning: function \(aqstrcpy\(aq is not bounds\-checking; \(aqstrcpy_s\(aq should be used instead. strcat(Buf, Msg); // warning: function \(aqstrcat\(aq is not bounds\-checking; \(aqstrcat_s\(aq should be used instead. strcat(Buf, Suffix); // warning: function \(aqstrcat\(aq is not bounds\-checking; \(aqstrcat_s\(aq should be used instead. if (fputs(buf, stderr) < 0) { // error handling return; } } void UsingSafeFunctions(const char *Msg) { static const char Prefix[] = \(dqError: \(dq; static const char Suffix[] = \(dq\en\(dq; char Buf[BUFSIZE] = {0}; if (strcpy_s(Buf, BUFSIZE, Prefix) != 0) { // error handling return; } if (strcat_s(Buf, BUFSIZE, Msg) != 0) { // error handling return; } if (strcat_s(Buf, BUFSIZE, Suffix) != 0) { // error handling return; } if (fputs(Buf, stderr) < 0) { // error handling return; } } .EE .UNINDENT .UNINDENT .SS bugprone\-unused\-local\-non\-trivial\-variable .sp هنگامی که یک متغیر غیربدیهی (non\-trivial) محلی درون یک تابع بدون استفاده بماند، هشدار می‌دهد. انواع متغیرهای زیر از این بررسی مستثنی هستند: .INDENT 0.0 .IP \(bu 2 انواع بدیهی (trivial) و با قابلیت کپی بدیهی (trivially copyable) .IP \(bu 2 ارجاع‌ها (references) و اشاره‌گرها (pointers) .IP \(bu 2 متغیرهای استثنا در عبارت‌های catch .IP \(bu 2 متغیرهای static یا thread local .IP \(bu 2 اتصال‌های ساخت‌یافته (structured bindings) .IP \(bu 2 متغیرهای دارای صفت \fB[[maybe_unused]]\fP .IP \(bu 2 متغیرهای مستقل از نام (name\-independent) .UNINDENT .sp این بررسی می‌تواند پیکربندی شود تا با تنظیم \fIIncludeTypes\fP بر روی \fI\&.*\fP برای تمام متغیرهای غیربدیهی هشدار دهد، و انواع خاصی را با استفاده از \fIExcludeTypes\fP مستثنی کند. .sp در این مثال، \fImy_lock\fP هشداری مبنی بر استفاده نشدن ایجاد می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX std::mutex my_lock; // my_lock local variable is never used .EE .UNINDENT .UNINDENT .sp در مثال بعدی، \fIfuture2\fP هشداری مبنی بر استفاده نشدن ایجاد می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX std::future future1; std::future future2; // ... MyObject foo = future1.get(); // future2 is not used. .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IncludeTypes فهرستی جداشده با نقطه\-ویرگول از عبارات منظم که با انواع متغیرهای مورد بررسی مطابقت دارند. به‌طور پیش‌فرض انواع زیر بررسی می‌شوند: .INDENT 7.0 .IP \(bu 2 \fI::std::.*mutex\fP .IP \(bu 2 \fI::std::future\fP .IP \(bu 2 \fI::std::basic_string\fP .IP \(bu 2 \fI::std::basic_regex\fP .IP \(bu 2 \fI::std::basic_istringstream\fP .IP \(bu 2 \fI::std::basic_stringstream\fP .IP \(bu 2 \fI::std::bitset\fP .IP \(bu 2 \fI::std::filesystem::path\fP .UNINDENT .UNINDENT .INDENT 0.0 .TP .B ExcludeTypes فهرستی جداشده با نقطه\-ویرگول از عبارات منظم برای تطبیق انواعی که از موارد تطبیق‌یافته در \fIIncludeTypes\fP مستثنی می‌شوند. به‌طور پیش‌فرض یک فهرست خالی است. .UNINDENT .SS bugprone\-unused\-raii .sp اشیاء موقتی را که شبیه به اشیاء RAII هستند پیدا می‌کند. .sp مثال کلاسیک برای این مورد، یک قفل با محدوده متغیر (scoped lock) است. .INDENT 0.0 .INDENT 3.5 .sp .EX { scoped_lock(&global_mutex); critical_section(); } .EE .UNINDENT .UNINDENT .sp مخرب (destructor) مربوط به scoped_lock پیش از ورود به \fBcritical_section\fP فراخوانی می‌شود و آن را بدون محافظت باقی می‌گذارد. .sp ما از تعدادی روش ابتکاری (heuristics) برای کاهش تعداد موارد مثبت کاذب در این بررسی استفاده می‌کنیم: .INDENT 0.0 .IP \(bu 2 نادیده گرفتن کدهایی که از ماکروها گسترش یافته‌اند. فریم‌ورک‌های تست استفاده زیادی از این مورد می‌کنند. .IP \(bu 2 نادیده گرفتن انواعی که مخرب‌های بدیهی (trivial destructors) دارند. احتمال بسیار کمی وجود دارد که آن‌ها اشیاء RAII باشند و تفاوتی در زمان حذف شدن آن‌ها وجود ندارد. .IP \(bu 2 نادیده گرفتن اشیاء در انتهای یک عبارت مرکب (compound statement) (رفتار برنامه را تغییر نمی‌دهد). .IP \(bu 2 نادیده گرفتن اشیاء بازگردانده شده از یک فراخوانی. .UNINDENT .SS bugprone\-unused\-return\-value .sp در مورد مقادیر بازگشتی استفاده‌نشده توابع هشدار می‌دهد. توابع مورد بررسی را می‌توان پیکربندی کرد. .sp سربارگذاری عملگرها (operator overloading) با معنای انتساب نادیده گرفته می‌شوند. .SS گزینه‌ها .INDENT 0.0 .TP .B CheckedFunctions فهرستی جداشده با نقطه\-ویرگول از توابع برای بررسی. این پارامتر از عبارت منظم (regexp) پشتیبانی می‌کند. در صورتی که نام و حوزه (scope) تابع با هر آرگومانی مطابقت داشته باشد، بررسی می‌شود. به‌طور پیش‌فرض توابع زیر بررسی می‌شوند: \fB^::std::async$, ^::std::launder$, ^::std::remove$, ^::std::remove_if$, ^::std::unique$, ^::std::unique_ptr::release$, ^::std::basic_string::empty$, ^::std::vector::empty$, ^::std::back_inserter$, ^::std::distance$, ^::std::find$, ^::std::find_if$, ^::std::inserter$, ^::std::lower_bound$, ^::std::make_pair$, ^::std::map::count$, ^::std::map::find$, ^::std::map::lower_bound$, ^::std::multimap::equal_range$, ^::std::multimap::upper_bound$, ^::std::set::count$, ^::std::set::find$, ^::std::setfill$, ^::std::setprecision$, ^::std::setw$, ^::std::upper_bound$, ^::std::vector::at$, ^::bsearch$, ^::ferror$, ^::feof$, ^::isalnum$, ^::isalpha$, ^::isblank$, ^::iscntrl$, ^::isdigit$, ^::isgraph$, ^::islower$, ^::isprint$, ^::ispunct$, ^::isspace$, ^::isupper$, ^::iswalnum$, ^::iswprint$, ^::iswspace$, ^::isxdigit$, ^::memchr$, ^::memcmp$, ^::strcmp$, ^::strcoll$, ^::strncmp$, ^::strpbrk$, ^::strrchr$, ^::strspn$, ^::strstr$, ^::wcscmp$, ^::access$, ^::bind$, ^::connect$, ^::difftime$, ^::dlsym$, ^::fnmatch$, ^::getaddrinfo$, ^::getopt$, ^::htonl$, ^::htons$, ^::iconv_open$, ^::inet_addr$, isascii$, isatty$, ^::mmap$, ^::newlocale$, ^::openat$, ^::pathconf$, ^::pthread_equal$, ^::pthread_getspecific$, ^::pthread_mutex_trylock$, ^::readdir$, ^::readlink$, ^::recvmsg$, ^::regexec$, ^::scandir$, ^::semget$, ^::setjmp$, ^::shm_open$, ^::shmget$, ^::sigismember$, ^::strcasecmp$, ^::strsignal$, ^::ttyname$\fP .INDENT 7.0 .IP \(bu 2 \fBstd::async()\fP\&. استفاده نکردن از مقدار بازگشتی، فراخوانی را همگام (synchronous) می‌کند. .IP \(bu 2 \fBstd::launder()\fP\&. استفاده نکردن از مقدار بازگشتی معمولاً به این معنی است که رابط تابع توسط برنامه‌نویس اشتباه درک شده است. تنها اشاره‌گر بازگردانده شده «شستشو داده شده» (laundered) است، نه آرگومان. .IP \(bu 2 \fBstd::remove()\fP، \fBstd::remove_if()\fP و \fBstd::unique()\fP\&. تکرارکننده (iterator) بازگردانده شده مرز بین عناصر باقی‌مانده و عناصر برای حذف را مشخص می‌کند. استفاده نکردن از مقدار بازگشتی به این معنی است که اطلاعات مربوط به اینکه کدام عناصر باید حذف شوند از دست رفته است. .IP \(bu 2 \fBstd::unique_ptr::release()\fP\&. عدم استفاده از مقدار بازگشتی می‌تواند منجر به نشت منابع (resource leaks) شود اگر همان اشاره‌گر در جای دیگری ذخیره نشده باشد. اغلب، نادیده گرفتن مقدار بازگشتی \fBrelease()\fP نشان می‌دهد که برنامه‌نویس تابع را با \fBreset()\fP اشتباه گرفته است. .IP \(bu 2 \fBstd::basic_string::empty()\fP و \fBstd::vector::empty()\fP\&. عدم استفاده از مقدار بازگشتی معمولاً بیانگر این است که برنامه‌نویس تابع را با \fBclear()\fP اشتباه گرفته است. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B CheckedReturnTypes فهرستی جداشده با نقطه\-ویرگول از انواع مقادیر بازگشتی تابع جهت بررسی. به‌طور پیش‌فرض انواع بازگشتی توابع زیر بررسی می‌شوند: \fI^::std::error_code$\fP, \fI^::std::error_condition$\fP, \fI^::std::errc$\fP, \fI^::std::expected$\fP, \fI^::boost::system::error_code$\fP .UNINDENT .INDENT 0.0 .TP .B AllowCastToVoid تعیین می‌کند که آیا تبدیل نوع (cast) مقادیر بازگشتی به \fBvoid\fP مجاز است یا خیر. پیش‌فرض: \fIfalse\fP\&. .UNINDENT .sp بررسی cert\-err33\-c \%<> نام مستعاری (alias) برای این بررسی است که مجموعه ثابت و بزرگی از توابع کتابخانه استاندارد را بررسی می‌کند. .SS bugprone\-use\-after\-move .sp هشدار می‌دهد اگر از یک شیء پس از انتقال (\fBmove\fP) داده شدن استفاده شود، برای نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX std::string str = \(dqHello, world!\en\(dq; std::vector messages; messages.emplace_back(std::move(str)); std::cout << str; .EE .UNINDENT .UNINDENT .sp خط آخر هشداری صادر می‌کند مبنی بر اینکه \fBstr\fP پس از انتقال یافتن، استفاده شده است. .sp این بررسی در صورتی که شیء پس از انتقال و پیش از استفاده دوباره مقداردهی اولیه (\fBreinitialize\fP) شود، هشداری صادر نمی‌کند. برای نمونه، برای این کد هیچ هشداری ایجاد نخواهد شد: .INDENT 0.0 .INDENT 3.5 .sp .EX messages.emplace_back(std::move(str)); str = \(dqGreetings, stranger!\en\(dq; std::cout << str; .EE .UNINDENT .UNINDENT .sp بخش‌های زیر دقیق‌تر توضیح می‌دهند که این بررسی دقیقاً چه مواردی را انتقال، استفاده و مقداردهی اولیه در نظر می‌گیرد. .sp این بررسی جریان کنترل (\fBcontrol flow\fP) را در نظر می‌گیرد. هشدار تنها در صورتی صادر می‌شود که استفاده از شیء از نقطه انتقال قابل دستیابی باشد. این بدین معناست که کد زیر هشداری تولید نمی‌کند: .INDENT 0.0 .INDENT 3.5 .sp .EX if (condition) { messages.emplace_back(std::move(str)); } else { std::cout << str; } .EE .UNINDENT .UNINDENT .sp از سوی دیگر، کد زیر یک هشدار تولید می‌کند: .INDENT 0.0 .INDENT 3.5 .sp .EX for (int i = 0; i < 10; ++i) { std::cout << str; messages.emplace_back(std::move(str)); } .EE .UNINDENT .UNINDENT .sp (استفاده پس از انتقال در تکرار دوم حلقه رخ می‌دهد.) .sp در برخی موارد، این بررسی ممکن است قادر به تشخیص ناسازگار بودن (\fBmutually exclusive\fP) دو شاخه نباشد. برای نمونه (با فرض اینکه \fBi\fP یک \fBint\fP است): .INDENT 0.0 .INDENT 3.5 .sp .EX if (i == 1) { messages.emplace_back(std::move(str)); } if (i == 2) { std::cout << str; } .EE .UNINDENT .UNINDENT .sp در این حالت، بررسی به اشتباه هشداری تولید خواهد کرد، هرچند که اجرای هم‌زمان هر دو دستورِ انتقال و استفاده ناممکن است. به بیان رسمی‌تر، تحلیل این ابزار به جریان حساس است اما به مسیر حساس نیست (\fBflow\-sensitive but not path\-sensitive\fP) \%\&. .SS بی‌صدا کردن هشدارهای نادرست .sp یک هشدار نادرست را می‌توان با مقداردهی اولیه دوباره شیء پس از انتقال بی‌صدا کرد: .INDENT 0.0 .INDENT 3.5 .sp .EX if (i == 1) { messages.emplace_back(std::move(str)); str = \(dq\(dq; } if (i == 2) { std::cout << str; } .EE .UNINDENT .UNINDENT .sp اگر می‌خواهید از بار اضافی ناشی از مقداردهی اولیه مجدد شیء جلوگیری کنید، می‌توانید یک تابع صوری (\fBdummy\fP) بسازید که باعث شود این بررسی فرض کند شیء دوباره مقداردهی اولیه شده است: .INDENT 0.0 .INDENT 3.5 .sp .EX template void IS_INITIALIZED(T&) {} .EE .UNINDENT .UNINDENT .sp می‌توانید از آن به صورت زیر استفاده کنید: .INDENT 0.0 .INDENT 3.5 .sp .EX if (i == 1) { messages.emplace_back(std::move(str)); } if (i == 2) { IS_INITIALIZED(str); std::cout << str; } .EE .UNINDENT .UNINDENT .sp در این حالت، بررسی هشداری صادر نخواهد کرد زیرا ارسال شیء به یک تابع به عنوان یک اشاره‌گر یا ارجاع غیر\-ثابت (\fBnon\-const\fP) به عنوان مقداردهی اولیه دوباره به حساب می‌آید (بخش مقداردهی اولیه دوباره را در زیر ببینید). .SS انتقال‌ها، استفاده‌ها و مقداردهی‌های اولیه مرتب‌نشده (Unsequenced) .sp در بسیاری از موارد، C++ هیچ تضمینی در مورد ترتیبی که در آن زیرعبارت‌های یک گزاره ارزیابی می‌شوند ارائه نمی‌دهد. این بدان معناست که در کدهایی مانند نمونه زیر، تضمینی وجود ندارد که استفاده قبل از انتقال رخ خواهد داد یا بعد از آن: .INDENT 0.0 .INDENT 3.5 .sp .EX void f(int i, std::vector v); std::vector v = { 1, 2, 3 }; f(v[1], std::move(v)); .EE .UNINDENT .UNINDENT .sp در چنین شرایطی، بررسی متذکر خواهد شد که استفاده و انتقال از نوع مرتب‌نشده (\fBunsequenced\fP) هستند. .sp این بررسی همچنین قواعد ترتیب‌بندی را هنگامی که مقداردهی اولیه دوباره در همان عبارت انتقال یا استفاده رخ می‌دهد، در نظر می‌گیرد. مقداردهی اولیه دوباره تنها در صورتی برای یک متغیر معتبر شناخته می‌شود که تضمین شده باشد پس از انتقال و پیش از استفاده ارزیابی می‌شود. .SS انتقال (Move) .sp این بررسی در حال حاضر تنها فراخوانی‌های \fBstd::move\fP روی متغیرهای محلی یا پارامترهای تابع را در نظر می‌گیرد. این بررسی انتقال متغیرهای عضو یا متغیرهای سراسری (global) را بررسی نمی‌کند. .sp هرگونه فراخوانی \fBstd::move\fP روی یک متغیر به عنوان عامل ایجاد انتقال آن متغیر در نظر گرفته می‌شود، حتی اگر نتیجهٔ \fBstd::move\fP به یک پارامتر ارجاع rvalue ارسال نشود. .sp این بدان معناست که بررسی حتی روی نوعی که دارای سازندهٔ انتقال (move constructor) یا عملگر انتساب انتقال (move assignment operator) نیست نیز یک use\-after\-move را گزارش می‌کند. این رفتار عمدی است. توسعه‌دهندگان ممکن است با این انتظار که در آینده سمنتیک انتقال (move semantics) به این نوع اضافه خواهد شد، از \fBstd::move\fP استفاده کنند. اگر چنین فراخوانی \fBstd::move\fP پتانسیل ایجاد یک use\-after\-move را داشته باشد، می‌خواهیم دربارهٔ آن هشدار دهیم حتی اگر آن نوع هنوز سمنتیک انتقال را پیاده‌سازی نکرده باشد. .sp علاوه بر این، اگر نتیجهٔ \fBstd::move\fP به یک پارامتر ارجاع rvalue پاس داده \fIشود\fP، این حالت همواره به عنوان انتقال در نظر گرفته می‌شود، حتی اگر تابعی که این پارامتر را دریافت می‌کند مقداری از آن منتقل نکند، یا این کار را فقط به‌صورت مشروط انجام دهد. به عنوان مثال، در شرایط زیر، بررسی فرض می‌کند که انتقال همواره رخ می‌دهد: .INDENT 0.0 .INDENT 3.5 .sp .EX std::vector messages; void f(std::string &&str) { // Only remember the message if it isn\(aqt empty. if (!str.empty()) { messages.emplace_back(std::move(str)); } } std::string str = \(dq\(dq; f(std::move(str)); .EE .UNINDENT .UNINDENT .sp بررسی فرض خواهد کرد که خط آخر باعث یک انتقال می‌شود، اگرچه در این مورد خاص، چنین اتفاقی نمی‌افتد. مجدداً، این رفتار عمدی است. .sp یک حالت خاص وجود دارد: فراخوانی \fBstd::move\fP درون فراخوانی \fBtry_emplace\fP به صورت محتاطانه انتقال‌نیافته فرض می‌شود. این کار به منظور جلوگیری از هشدارهای کاذب است، زیرا این بررسی روشی برای استنتاج مقدار \fBbool\fP بازگردانده‌شده توسط \fBtry_emplace\fP ندارد. .sp هنگام تحلیل ترتیبی که در آن انتقال‌ها، استفاده‌ها و مقداردهی‌های مجدد رخ می‌دهند (بخش Unsequenced moves, uses, and reinitializations را ببینید)، فرض می‌شود که انتقال در همان تابعی رخ می‌دهد که نتیجهٔ \fBstd::move\fP به آن پاس داده شده است. .sp این بررسی همچنین perfect\-forwarding با \fBstd::forward\fP را مدیریت می‌کند، بنابراین کد زیر نیز باعث ایجاد یک هشدار use\-after\-move خواهد شد. .INDENT 0.0 .INDENT 3.5 .sp .EX void consume(int); void f(int&& i) { consume(std::forward(i)); consume(std::forward(i)); // use\-after\-move } .EE .UNINDENT .UNINDENT .SS استفاده (Use) .sp هرگونه رخداد متغیر منتقل‌شده که مقداردهی مجدد نباشد (زیر را ببینید) به‌عنوان یک استفاده در نظر گرفته می‌شود. .sp یک استثنا برای این موضوع اشیاء از نوع \fBstd::unique_ptr\fP، \fBstd::shared_ptr\fP، \fBstd::weak_ptr\fP، \fBstd::optional\fP و \fBstd::any\fP هستند. یک استثنا برای این موضوع اشیاء از نوع \fBstd::unique_ptr\fP، \fBstd::shared_ptr\fP، \fBstd::weak_ptr\fP، \fBstd::optional\fP و \fBstd::any\fP هستند که می‌توانند از طریق \fBreset\fP دوباره مقداردهی اولیه شوند. به طور خاص برای اشاره‌گرهای هوشمند، اشیاء منتقل‌شده دارای وضعیت مشخص \fBnullptr\fP هستند و تنها \fBoperator*\fP، \fBoperator\->\fP و \fBoperator[]\fP دسترسی‌های نامعتبر در نظر گرفته می‌شوند چرا که به یک \fBnullptr\fP ارجاع‌زدایی خواهند کرد. .sp اگر چندین استفاده پس از یک انتقال رخ دهد، تنها اولین مورد پرچم‌گذاری می‌شود. .SS مقداردهی مجدد (Reinitialization) .sp این بررسی یک متغیر را در موارد زیر مقداردهی‌مجدد‌شده در نظر می‌گیرد: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 متغیر در سمت چپ یک انتساب قرار گیرد. .IP \(bu 2 متغیر به عنوان یک اشاره‌گر non\-const یا یک ارجاع lvalue غیر ثابت (non\-const) به یک تابع ارسال شود. (فرض بر این است که متغیر ممکن است یک پارامتر خروجی برای تابع باشد.) .IP \(bu 2 تابع \fBclear()\fP یا \fBassign()\fP روی متغیر فراخوانی شود و متغیر از یکی از انواع کانتینرهای استاندارد \fBbasic_string\fP، \fBvector\fP، \fBdeque\fP، \fBforward_list\fP، \fBlist\fP، \fBset\fP، \fBmap\fP، \fBmultiset\fP، \fBmultimap\fP، \fBunordered_set\fP، \fBunordered_map\fP، \fBunordered_multiset\fP یا \fBunordered_multimap\fP باشد. .IP \(bu 2 تابع \fBreset()\fP روی متغیر فراخوانی شود و متغیر از نوع \fBstd::unique_ptr\fP، \fBstd::shared_ptr\fP، \fBstd::weak_ptr\fP، \fBstd::optional\fP یا \fBstd::any\fP باشد. .IP \(bu 2 یک تابع عضو دارای صفت \fB[[clang::reinitializes]]\fP روی متغیر فراخوانی شود. .UNINDENT .UNINDENT .UNINDENT .sp اگر متغیر مورد نظر یک struct باشد و مقداری در یکی از متغیرهای عضو مجزای آن نوشته شود، این بررسی آن را مقداردهی مجدد در نظر نمی‌گیرد \-\- حتی اگر در نهایت، تمامی متغیرهای عضو آن struct مقداردهی شوند. به عنوان مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX struct S { std::string str; int i; }; S s = { \(dqHello, world!\en\(dq, 42 }; S s_other = std::move(s); s.str = \(dqLorem ipsum\(dq; s.i = 99; .EE .UNINDENT .UNINDENT .sp این بررسی \fBs\fP را پس از خط آخر دوباره مقداردهی‌شده در نظر نخواهد گرفت؛ در عوض، خطی که به \fBs.str\fP مقدار انتساب می‌دهد به عنوان یک use\-after\-move پرچم‌گذاری خواهد شد. این رفتار عمدی است چرا که این الگوی مقداردهی مجدد یک struct مستعد خطا است. برای مثال، اگر یک متغیر عضو اضافی به \fBS\fP افزوده شود، به سادگی ممکن است مقداردهی مجدد برای این عضو اضافی فراموش شود. در عوض، انتساب به کل struct در یک گام ایمن‌تر است و از اخطار use\-after\-move نیز جلوگیری خواهد کرد. .SS گزینه‌ها (Options) .INDENT 0.0 .TP .B InvalidationFunctions یک فهرست جداشده با نقطه\-ویرگول از عبارات باقاعده (regular expressions) منطبق بر نام توابعی که باعث باطل شدن اولین آرگومان خود می‌شوند (مانند بستن یک handle). برای توابع عضو، اولین آرگومان همان آرگومان شیء ضمنی (\fBthis\fP) در نظر گرفته می‌شود. مقدار پیش‌فرض یک رشتهٔ خالی است. .UNINDENT .INDENT 0.0 .TP .B ReinitializationFunctions یک فهرست جداشده با نقطه\-ویرگول از عبارات باقاعده منطبق بر نام توابعی که شیء را دوباره مقداردهی اولیه می‌کنند. برای توابع عضو، آرگومان شیء ضمنی (\fB*this\fP) باز\-مقداردهی‌شده در نظر گرفته می‌شود. برای توابع غیر عضو یا توابع عضو ایستا (static)، اولین آرگومان دوباره مقداردهی‌شده فرض می‌شود. مقدار پیش‌فرض یک رشتهٔ خالی است. .UNINDENT .SS bugprone\-virtual\-near\-miss .sp اگر تابعی دچار خطای نزدیک به هدف باشد (یعنی نام آن بسیار شبیه و امضای تابع با یک تابع مجازی از کلاس پایه یکسان باشد)، هشدار می‌دهد. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX struct Base { virtual void func(); }; struct Derived : Base { virtual void funk(); // warning: \(aqDerived::funk\(aq has a similar name and the same signature as virtual method \(aqBase::func\(aq; did you mean to override it? }; .EE .UNINDENT .UNINDENT .SS cert\-arr39\-c .sp بررسی \fIcert\-arr39\-c\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به bugprone\-sizeof\-expression \%<> مراجعه کنید. .SS cert\-con36\-c .sp بررسی \fIcert\-con36\-c\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به bugprone\-spuriously\-wake\-up\-functions \%<> مراجعه کنید. .SS cert\-con54\-cpp .sp بررسی \fIcert\-con54\-cpp\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به bugprone\-spuriously\-wake\-up\-functions \%<> مراجعه کنید. .SS cert\-ctr56\-cpp .sp بررسی \fIcert\-ctr56\-cpp\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به bugprone\-pointer\-arithmetic\-on\-polymorphic\-object \%<> مراجعه کنید. .SS cert\-dcl03\-c .sp بررسی \fIcert\-dcl03\-c\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به misc\-static\-assert \%<> مراجعه کنید. .SS cert\-dcl16\-c .sp بررسی \fIcert\-dcl16\-c\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به readability\-uppercase\-literal\-suffix \%<> مراجعه کنید. .SS cert\-dcl37\-c .sp بررسی \fIcert\-dcl37\-c\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به bugprone\-reserved\-identifier \%<> مراجعه کنید. .SS cert\-dcl50\-cpp .sp بررسی \fIcert\-dcl50\-cpp\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به modernize\-avoid\-variadic\-functions \%<> مراجعه کنید. .sp این بررسی متناظر با قاعدهٔ DCL50\-CPP از استاندارد کدنویسی CERT C++ است: Do not define a C\-style variadic function \%\&. .SS cert\-dcl51\-cpp .sp بررسی \fIcert\-dcl51\-cpp\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به bugprone\-reserved\-identifier \%<> مراجعه کنید. .SS cert\-dcl54\-cpp .sp بررسی \fIcert\-dcl54\-cpp\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به misc\-new\-delete\-overloads \%<> مراجعه کنید. .SS cert\-dcl58\-cpp .sp بررسی \fIcert\-dcl58\-cpp\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به bugprone\-std\-namespace\-modification \%<> مراجعه کنید. .sp این بررسی متناظر با قاعدهٔ DCL58\-CPP از استاندارد کدنویسی CERT C++ است: Do not modify the standard namespaces \%\&. .SS cert\-dcl59\-cpp .sp بررسی \fIcert\-dcl59\-cpp\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به misc\-anonymous\-namespace\-in\-header \%<> مراجعه کنید. .SS cert\-env33\-c .sp بررسی \fIcert\-env33\-c\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به bugprone\-command\-processor \%<> مراجعه کنید. .sp این بررسی متناظر با قاعدهٔ ENV33\-C از استاندارد کدنویسی CERT C است: Do not call system() \%\&. .SS cert\-err09\-cpp .sp بررسی \fIcert\-err09\-cpp\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به misc\-throw\-by\-value\-catch\-by\-reference \%<> مراجعه کنید. .sp این بررسی با توصیهٔ ERR09\-CPP در استاندارد کدنویسی CERT C++ مطابقت دارد: Throw anonymous temporaries. با این حال، تمام توصیه‌های CERT از دید عموم حذف شده‌اند و بنابراین مشاهدهٔ توجیه آن‌ها برای رفتار این بررسی نیازمند داشتن یک حساب کاربری در ویکی آن‌ها است. .SS cert\-err33\-c .sp در مورد مقادیر بازگشتی استفاده‌نشدهٔ توابع هشدار می‌دهد. بسیاری از توابع کتابخانهٔ استاندارد مقداری را برمی‌گردانند که موفقیت‌آمیز بودن فراخوانی را مشخص می‌کند. نادیده گرفتن مقدار بازگشتی در صورت بروز خطا می‌تواند رفتارهای پیش‌بینی‌نشده‌ای ایجاد کند. توابع زیر بررسی می‌شوند: .INDENT 0.0 .IP \(bu 2 aligned_alloc() .IP \(bu 2 asctime_s() .IP \(bu 2 at_quick_exit() .IP \(bu 2 atexit() .IP \(bu 2 bsearch() .IP \(bu 2 bsearch_s() .IP \(bu 2 btowc() .IP \(bu 2 c16rtomb() .IP \(bu 2 c32rtomb() .IP \(bu 2 calloc() .IP \(bu 2 clock() .IP \(bu 2 cnd_broadcast() .IP \(bu 2 cnd_init() .IP \(bu 2 cnd_signal() .IP \(bu 2 cnd_timedwait() .IP \(bu 2 cnd_wait() .IP \(bu 2 ctime_s() .IP \(bu 2 fclose() .IP \(bu 2 fflush() .IP \(bu 2 fgetc() .IP \(bu 2 fgetpos() .IP \(bu 2 fgets() .IP \(bu 2 fgetwc() .IP \(bu 2 fopen() .IP \(bu 2 fopen_s() .IP \(bu 2 fprintf() .IP \(bu 2 fprintf_s() .IP \(bu 2 fputc() .IP \(bu 2 fputs() .IP \(bu 2 fputwc() .IP \(bu 2 fputws() .IP \(bu 2 fread() .IP \(bu 2 freopen() .IP \(bu 2 freopen_s() .IP \(bu 2 fscanf() .IP \(bu 2 fscanf_s() .IP \(bu 2 fseek() .IP \(bu 2 fsetpos() .IP \(bu 2 ftell() .IP \(bu 2 fwprintf() .IP \(bu 2 fwprintf_s() .IP \(bu 2 fwrite() .IP \(bu 2 fwscanf() .IP \(bu 2 fwscanf_s() .IP \(bu 2 getc() .IP \(bu 2 getchar() .IP \(bu 2 getenv() .IP \(bu 2 getenv_s() .IP \(bu 2 gets_s() .IP \(bu 2 getwc() .IP \(bu 2 getwchar() .IP \(bu 2 gmtime() .IP \(bu 2 gmtime_s() .IP \(bu 2 localtime() .IP \(bu 2 localtime_s() .IP \(bu 2 malloc() .IP \(bu 2 mbrtoc16() .IP \(bu 2 mbrtoc32() .IP \(bu 2 mbsrtowcs() .IP \(bu 2 mbsrtowcs_s() .IP \(bu 2 mbstowcs() .IP \(bu 2 mbstowcs_s() .IP \(bu 2 memchr() .IP \(bu 2 mktime() .IP \(bu 2 mtx_init() .IP \(bu 2 mtx_lock() .IP \(bu 2 mtx_timedlock() .IP \(bu 2 mtx_trylock() .IP \(bu 2 mtx_unlock() .IP \(bu 2 printf_s() .IP \(bu 2 putc() .IP \(bu 2 putwc() .IP \(bu 2 raise() .IP \(bu 2 realloc() .IP \(bu 2 remove() .IP \(bu 2 rename() .IP \(bu 2 setlocale() .IP \(bu 2 setvbuf() .IP \(bu 2 scanf() .IP \(bu 2 scanf_s() .IP \(bu 2 signal() .IP \(bu 2 snprintf() .IP \(bu 2 snprintf_s() .IP \(bu 2 sprintf() .IP \(bu 2 sprintf_s() .IP \(bu 2 sscanf() .IP \(bu 2 sscanf_s() .IP \(bu 2 strchr() .IP \(bu 2 strerror_s() .IP \(bu 2 strftime() .IP \(bu 2 strpbrk() .IP \(bu 2 strrchr() .IP \(bu 2 strstr() .IP \(bu 2 strtod() .IP \(bu 2 strtof() .IP \(bu 2 strtoimax() .IP \(bu 2 strtok() .IP \(bu 2 strtok_s() .IP \(bu 2 strtol() .IP \(bu 2 strtold() .IP \(bu 2 strtoll() .IP \(bu 2 strtoumax() .IP \(bu 2 strtoul() .IP \(bu 2 strtoull() .IP \(bu 2 strxfrm() .IP \(bu 2 swprintf() .IP \(bu 2 swprintf_s() .IP \(bu 2 swscanf() .IP \(bu 2 swscanf_s() .IP \(bu 2 thrd_create() .IP \(bu 2 thrd_detach() .IP \(bu 2 thrd_join() .IP \(bu 2 thrd_sleep() .IP \(bu 2 time() .IP \(bu 2 timespec_get() .IP \(bu 2 tmpfile() .IP \(bu 2 tmpfile_s() .IP \(bu 2 tmpnam() .IP \(bu 2 tmpnam_s() .IP \(bu 2 tss_create() .IP \(bu 2 tss_get() .IP \(bu 2 tss_set() .IP \(bu 2 ungetc() .IP \(bu 2 ungetwc() .IP \(bu 2 vfprintf() .IP \(bu 2 vfprintf_s() .IP \(bu 2 vfscanf() .IP \(bu 2 vfscanf_s() .IP \(bu 2 vfwprintf() .IP \(bu 2 vfwprintf_s() .IP \(bu 2 vfwscanf() .IP \(bu 2 vfwscanf_s() .IP \(bu 2 vprintf_s() .IP \(bu 2 vscanf() .IP \(bu 2 vscanf_s() .IP \(bu 2 vsnprintf() .IP \(bu 2 vsnprintf_s() .IP \(bu 2 vsprintf() .IP \(bu 2 vsprintf_s() .IP \(bu 2 vsscanf() .IP \(bu 2 vsscanf_s() .IP \(bu 2 vswprintf() .IP \(bu 2 vswprintf_s() .IP \(bu 2 vswscanf() .IP \(bu 2 vswscanf_s() .IP \(bu 2 vwprintf_s() .IP \(bu 2 vwscanf() .IP \(bu 2 vwscanf_s() .IP \(bu 2 wcrtomb() .IP \(bu 2 wcschr() .IP \(bu 2 wcsftime() .IP \(bu 2 wcspbrk() .IP \(bu 2 wcsrchr() .IP \(bu 2 wcsrtombs() .IP \(bu 2 wcsrtombs_s() .IP \(bu 2 wcsstr() .IP \(bu 2 wcstod() .IP \(bu 2 wcstof() .IP \(bu 2 wcstoimax() .IP \(bu 2 wcstok() .IP \(bu 2 wcstok_s() .IP \(bu 2 wcstol() .IP \(bu 2 wcstold() .IP \(bu 2 wcstoll() .IP \(bu 2 wcstombs() .IP \(bu 2 wcstombs_s() .IP \(bu 2 wcstoumax() .IP \(bu 2 wcstoul() .IP \(bu 2 wcstoull() .IP \(bu 2 wcsxfrm() .IP \(bu 2 wctob() .IP \(bu 2 wctrans() .IP \(bu 2 wctype() .IP \(bu 2 wmemchr() .IP \(bu 2 wprintf_s() .IP \(bu 2 wscanf() .IP \(bu 2 wscanf_s() .UNINDENT .sp این بررسی یک نام مستعار از بررسی bugprone\-unused\-return\-value \%<> با مجموعه‌ای ثابت از توابع است. .sp نادیده‌گرفتن هشدارها با تبدیل نوع (cast) به \fBvoid\fP به طور پیش‌فرض فعال است و می‌تواند با تنظیم گزینه \fIAllowCastToVoid\fP روی \fIfalse\fP غیرفعال شود\&. .sp این بررسی متناظر با بخشی از قاعده ERR33\-C در استاندارد کدنویسی CERT C است: «شناسایی و مدیریت خطاهای کتابخانه استاندارد» \%\&. فهرست توابع بررسی‌شده از این قاعده برگرفته شده است، به استثنای موارد زیر: .INDENT 0.0 .IP \(bu 2 این بررسی نمی‌تواند تشخیص دهد که آیا یک تابع با آرگومان \fBNULL\fP فراخوانی شده است یا خیر. بنابراین توابع زیر بررسی نمی‌شوند: \fBmblen\fP، \fBmbrlen\fP، \fBmbrtowc\fP، \fBmbtowc\fP، \fBwctomb\fP، \fBwctomb_s\fP .UNINDENT .SS cert\-err34\-c .sp بررسی cert\-err34\-c یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-unchecked\-string\-to\-number\-conversion \%<> را ببینید. .SS cert\-err52\-cpp .sp بررسی \fIcert\-err52\-cpp\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر modernize\-avoid\-setjmp\-longjmp \%<> را ببینید. .sp این بررسی متناظر با قاعده ERR52\-CPP در استاندارد کدنویسی CERT C++ است: «از setjmp() یا longjmp() استفاده نکنید» \%\&. .SS cert\-err58\-cpp .sp بررسی \fIcert\-err58\-cpp\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-throwing\-static\-initialization \%<> را ببینید. .sp این بررسی متناظر با قاعده ERR58\-CPP در استاندارد کدنویسی CERT C++ است: «مدیریت تمام استثناهای پرتاب‌شده پیش از آغاز اجرای main()» \%\&. .SS cert\-err60\-cpp .sp بررسی \fIcert\-err60\-cpp\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-exception\-copy\-constructor\-throws \%<> را ببینید. .sp این بررسی متناظر با قاعده ERR60\-CPP در استاندارد کدنویسی CERT C++ است: «اشیاء استثنا باید دارای سازنده کپی بدون پرتاب استثنا (nothrow) باشند» \%\&. .SS cert\-err61\-cpp .sp بررسی \fIcert\-err61\-cpp\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر misc\-throw\-by\-value\-catch\-by\-reference \%<> را ببینید. .SS cert\-exp42\-c .sp بررسی \fIcert\-exp42\-c\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-suspicious\-memory\-comparison \%<> را ببینید. .SS cert\-fio38\-c .sp بررسی \fIcert\-fio38\-c\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر misc\-non\-copyable\-objects \%<> را ببینید. .sp این بررسی متناظر با قاعده FIO38\-C در استاندارد کدنویسی CERT C++ است: «یک شیء FILE را کپی نکنید» \%\&. .SS cert\-flp30\-c .sp بررسی \fIcert\-flp30\-c\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-float\-loop\-counter \%<> را ببینید. .sp این بررسی متناظر با قاعده FLP30\-C در استاندارد کدنویسی CERT C است: «از متغیرهای ممیز شناور به عنوان شمارنده حلقه استفاده نکنید» \%\&. .SS cert\-flp37\-c .sp بررسی \fIcert\-flp37\-c\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-suspicious\-memory\-comparison \%<> را ببینید. .SS cert\-int09\-c .sp بررسی \fIcert\-int09\-c\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر readability\-enum\-initial\-value \%<> را ببینید. .SS cert\-mem57\-cpp .sp بررسی \fIcert\-mem57\-cpp\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-default\-operator\-new\-on\-overaligned\-type \%<> را ببینید. .sp این بررسی متناظر با قاعده MEM57\-CPP در استاندارد کدنویسی CERT C++ است: «اجتناب از استفاده از operator new پیش‌فرض برای انواع بیش‌از‌حد تراز‌شده (over-aligned)» \%\&. .SS cert\-msc24\-c .sp بررسی \fIcert\-msc24\-c\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-unsafe\-functions \%<> را ببینید. .SS cert\-msc30\-c .sp بررسی \fIcert\-msc30\-c\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر misc\-predictable\-rand \%<> را ببینید. .sp این بررسی متناظر با قاعده MSC30\-C در استاندارد کدنویسی CERT C است: «برای تولید اعداد شبه‌تصادفی از تابع rand() استفاده نکنید» \%\&. .SS cert\-msc32\-c .sp بررسی \fIcert\-msc32\-c\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-random\-generator\-seed \%<> را ببینید. .sp این بررسی متناظر با قاعده MSC32\-C در استاندارد کدنویسی CERT C است: «مولدهای اعداد شبه‌تصادفی را به درستی مقداردهی اولیه (seed) کنید» \%\&. .SS cert\-msc33\-c .sp بررسی \fIcert\-msc33\-c\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-unsafe\-functions \%<> را ببینید. .SS cert\-msc50\-cpp .sp بررسی \fIcert\-msc50\-cpp\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر misc\-predictable\-rand \%<> را ببینید. .sp این بررسی متناظر با قاعده MSC50\-CPP در استاندارد کدنویسی CERT C است: «برای تولید اعداد شبه‌تصادفی از std::rand() استفاده نکنید» \%\&. .SS cert\-msc51\-cpp .sp بررسی \fIcert\-msc51\-cpp\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-random\-generator\-seed \%<> را ببینید. .sp این بررسی متناظر با قاعده MSC51\-CPP در استاندارد کدنویسی CERT C++ است: «اطمینان حاصل کنید که مولد اعداد تصادفی شما به درستی مقداردهی اولیه (seed) شده است» \%\&. .SS cert\-msc54\-cpp .sp بررسی \fIcert\-msc54\-cpp\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-signal\-handler \%<> را ببینید. .SS cert\-oop11\-cpp .sp بررسی \fIcert\-oop11\-cpp\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر performance\-move\-constructor\-init \%<> را ببینید. .sp این بررسی با توصیه‌نامهٔ OOP11\-CPP از استاندارد کدنویسی CERT C++ مطابقت دارد: «اعضا یا کلاس‌های پایه را از طریق یک سازندهٔ انتقال به‌صورت رونوشت مقداردهی اولیه نکنید» (Do not copy\-initialize members or base classes from a move constructor). با این حال، تمامی توصیه‌های CERT از دید عموم حذف شده‌اند و به همین دلیل، مشاهدهٔ دلایل و توجیهات آن‌ها برای رفتار این بررسی نیازمند داشتن حساب کاربری در ویکی آن‌ها است. .SS cert\-oop54\-cpp .sp بررسی \fIcert\-oop54\-cpp\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-unhandled\-self\-assignment \%<> را ببینید. .SS cert\-oop57\-cpp .sp بررسی \fIcert\-oop57\-cpp\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-raw\-memory\-call\-on\-non\-trivial\-type \%<> را ببینید. .sp این بررسی با قاعدهٔ OOP57\-CPP از استاندارد کدنویسی CERT C++ مطابقت دارد: «توابع عضو ویژه و عملگرهای بارگذاری‌شده را به توابع کتابخانهٔ استاندارد C ترجیح دهید» (Prefer special member functions and overloaded operators to C Standard Library functions) \%\&. .SS cert\-oop58\-cpp .sp بررسی \fIcert\-oop58\-cpp\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-copy\-constructor\-mutates\-argument \%<> را ببینید. .SS cert\-pos44\-c .sp بررسی \fIcert\-pos44\-c\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-bad\-signal\-to\-kill\-thread \%<> را ببینید. .SS cert\-pos47\-c .sp بررسی \fIcert\-pos47\-c\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر concurrency\-thread\-canceltype\-asynchronous \%<> را ببینید. .SS cert\-sig30\-c .sp بررسی \fIcert\-sig30\-c\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-signal\-handler \%<> را ببینید. .SS cert\-str34\-c .sp بررسی \fIcert\-str34\-c\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر bugprone\-signed\-char\-misuse \%<> را ببینید. .SS clang\-analyzer\-core.BitwiseShift .sp مواردی را پیدا می‌کند که در آن‌ها عملیات تغییر بیتی (bitwise shift) منجر به رفتار تعریف‌نشده (undefined behaviour) می‌شود. .sp بررسی \fIclang\-analyzer\-core.BitwiseShift\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-core.CallAndMessage .sp خطاهای منطقی مربوط به فراخوانی‌های توابع و عبارات پیام Objective\-C را بررسی می‌کند (مانند آرگومان‌های مقداردهی‌نشده، اشاره‌گرهای تابع تهی/null). .sp بررسی \fIclang\-analyzer\-core.CallAndMessage\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-core.DivideZero .sp تقسیم بر صفر را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-core.DivideZero\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-core.NonNullParamChecker .sp اشاره‌گرهای تهی (null) پاس‌داده‌شده به‌عنوان آرگومان به تابعی که آرگومان‌های آن ارجاع هستند یا با صفت \(aqnonnull\(aq علامت‌گذاری شده‌اند را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-core.NonNullParamChecker\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-core.NullDereference .sp ابطال ارجاع (dereference) اشاره‌گرهای تهی (null) را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-core.NullDereference\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-core.StackAddressEscape .sp بررسی می‌کند که آدرس‌های حافظهٔ پشته (stack) به بیرون از تابع نشت نکنند (escape). .sp بررسی \fIclang\-analyzer\-core.StackAddressEscape\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-core.UndefinedBinaryOperatorResult .sp نتایج تعریف‌نشدهٔ عملگرهای باینری را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-core.UndefinedBinaryOperatorResult\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-core.VLASize .sp تعریف‌های آرایه‌های با طول متغیر (VLA) با اندازهٔ تعریف‌نشده یا صفر را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-core.VLASize\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-core.uninitialized.ArraySubscript .sp استفاده از مقادیر مقداردهی‌نشده به‌عنوان اندیس آرایه را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-core.uninitialized.ArraySubscript\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-core.uninitialized.Assign .sp انتساب مقادیر مقداردهی‌نشده را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-core.uninitialized.Assign\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-core.uninitialized.Branch .sp استفاده از مقادیر مقداردهی‌نشده به‌عنوان شرایط انشعاب (branch conditions) را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-core.uninitialized.Branch\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-core.uninitialized.CapturedBlockVariable .sp بلاک‌هایی را که مقادیر مقداردهی‌نشده را تسخیر می‌کنند (capture)، بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-core.uninitialized.CapturedBlockVariable\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-core.uninitialized.NewArraySize .sp بررسی می‌کند که آیا اندازهٔ آرایه در یک عبارت []new تعریف‌نشده است یا خیر. .sp بررسی \fIclang\-analyzer\-core.uninitialized.NewArraySize\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-core.uninitialized.UndefReturn .sp بازگرداندن مقادیر مقداردهی‌نشده به فراخواننده (caller) را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-core.uninitialized.UndefReturn\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-cplusplus.ArrayDelete .sp تخریب آرایه‌هایی از اشیاء چندریختی (polymorphic) را که به عنوان کلاس پایه‌شان تخریب می‌شوند، گزارش می‌دهد. .sp بررسی \fIclang\-analyzer\-cplusplus.ArrayDelete\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-cplusplus.InnerPointer .sp اشاره‌گرهای داخلی دربرگیرنده‌های ++C را که پس از تخصیص مجدد یا آزادسازی حافظه (re/deallocation) استفاده شده‌اند بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-cplusplus.InnerPointer\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-cplusplus.Move .sp باگ‌های استفاده پس از انتقال (use\-after\-move) را در ++C پیدا می‌کند. .sp بررسی \fIclang\-analyzer\-cplusplus.Move\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-cplusplus.NewDelete .sp مشکلات آزادسازی مضاعف (double\-free) و استفاده پس از آزادسازی (use\-after\-free) را بررسی می‌کند. حافظه مدیریت‌شده توسط new/delete را ردگیری می‌کند. .sp بررسی \fIclang\-analyzer\-cplusplus.NewDelete\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-cplusplus.NewDeleteLeaks .sp نشت‌های حافظه (memory leaks) را بررسی می‌کند. حافظه مدیریت‌شده توسط new/delete را ردگیری می‌کند. .sp بررسی \fIclang\-analyzer\-cplusplus.NewDeleteLeaks\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-cplusplus.PlacementNew .sp بررسی می‌کند که آیا placement new پیش‌فرض به اشاره‌گرهایی با ظرفیت ذخیره‌سازی کافی مجهز شده است یا خیر. .sp بررسی \fIclang\-analyzer\-cplusplus.PlacementNew\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-cplusplus.SelfAssignment .sp عملگرهای انتساب کپی و انتقال در ++C را برای انتساب به خود (self assignment) بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-cplusplus.SelfAssignment\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-cplusplus.StringChecker .sp باگ‌های std::string در ++C را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-cplusplus.StringChecker\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-deadcode.DeadStores .sp مقادیر ذخیره‌شده در متغیرهایی را که پس از آن هرگز خوانده نمی‌شوند بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-deadcode.DeadStores\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-fuchsia.HandleChecker .sp بررسی‌کننده‌ای که نشت‌های مربوط به هندل‌های Fuchsia را شناسایی می‌کند. .sp بررسی \fIclang\-analyzer\-fuchsia.HandleChecker\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% برای اطلاعات بیشتر مراجعه کنید. .SS clang\-analyzer\-nullability.NullPassedToNonnull .sp هنگامی که یک اشاره‌گر null به اشاره‌گری با نوع _Nonnull ارسال می‌شود، هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-nullability.NullPassedToNonnull\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-nullability.NullReturnedFromNonnull .sp هنگامی که یک اشاره‌گر null از تابعی که نوع بازگشتی آن _Nonnull است برگردانده شود، هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-nullability.NullReturnedFromNonnull\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-nullability.NullableDereferenced .sp هنگامی که ارجاع یک اشاره‌گر nullable بازمی‌شود (dereference می‌شود)، هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-nullability.NullableDereferenced\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-nullability.NullablePassedToNonnull .sp هنگامی که یک اشاره‌گر nullable به اشاره‌گری با نوع _Nonnull ارسال می‌شود، هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-nullability.NullablePassedToNonnull\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-nullability.NullableReturnedFromNonnull .sp هنگامی که یک اشاره‌گر nullable از تابعی با نوع بازگشتی _Nonnull بازگردانده می‌شود، هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-nullability.NullableReturnedFromNonnull\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-optin.core.EnumCastOutOfRange .sp تبدیل‌های نوع عدد صحیح به شمارشی را برای مقادیر خارج از محدوده بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-optin.core.EnumCastOutOfRange\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-optin.cplusplus.UninitializedObject .sp فیلدهای مقداردهی‌نشده پس از ساخت شیء را گزارش می‌دهد. .sp بررسی \fIclang\-analyzer\-optin.cplusplus.UninitializedObject\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-optin.cplusplus.VirtualCall .sp فراخوانی توابع مجازی در طول ساخت/تخریب شیء را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-optin.cplusplus.VirtualCall\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-optin.mpi.MPI\-Checker .sp کدهای MPI را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-optin.mpi.MPI\-Checker\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker .sp بررسی می‌کند که آیا ماکروهای NSLocalizedString شامل یک کامنت برای بافتار (context) هستند یا خیر. .sp بررسی \fIclang\-analyzer\-optin.osx.cocoa.localizability.EmptyLocalizationContextChecker\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-optin.osx.cocoa.localizability.NonLocalizedStringChecker .sp در مورد استفاده از NSStringهای محلی‌سازی‌نشده که به متدهای رابط کاربری نیازمند NSStringهای محلی‌سازی‌شده ارسال می‌شوند، هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-optin.osx.cocoa.localizability.NonLocalizedStringChecker\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-optin.performance.GCDAntipattern .sp بررسی ضدالگوهای (anti\-patterns) کارایی هنگام استفاده از Grand Central Dispatch. .sp بررسی \fIclang\-analyzer\-optin.performance.GCDAntipattern\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-optin.performance.Padding .sp بررسی structهایی که دارای لایه‌گذاری (padding) بیش از حد هستند. .sp بررسی \fIclang\-analyzer\-optin.performance.Padding\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-optin.portability.UnixAPI .sp یافتن رفتارهای وابسته به پیاده‌سازی (implementation\-defined) در توابع UNIX/Posix. .sp بررسی \fIclang\-analyzer\-optin.portability.UnixAPI\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-optin.taint.TaintedAlloc .sp بررسی تخصیص‌های حافظه‌ای که ممکن است پارامتر اندازهٔ آن‌ها یک مقدار آلوده (کنترل‌شده توسط مهاجم) باشد. .sp بررسی \fIclang\-analyzer\-optin.taint.TaintedAlloc\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.API .sp بررسی استفادهٔ صحیح از رابط‌های برنامه‌نویسی مختلف Apple. .sp بررسی \fIclang\-analyzer\-osx.API\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.NumberObjectConversion .sp بررسی تبدیل‌های نادرست شیءهای نمایش‌دهندهٔ اعداد به عددها. .sp بررسی \fIclang\-analyzer\-osx.NumberObjectConversion\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.ObjCProperty .sp بررسی استفادهٔ مناسب از ویژگی‌های Objective\-C. .sp بررسی \fIclang\-analyzer\-osx.ObjCProperty\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.SecKeychainAPI .sp بررسی استفادهٔ صحیح از APIهای Secure Keychain. .sp بررسی \fIclang\-analyzer\-osx.SecKeychainAPI\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.cocoa.AtSync .sp بررسی اشاره‌گرهای nil که به عنوان mutex برای @synchronized استفاده شده‌اند. .sp بررسی \fIclang\-analyzer\-osx.cocoa.AtSync\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.cocoa.AutoreleaseWrite .sp هشدار در مورد عملیات نوشتن بالقوه منجر به فروپاشی (crash) روی اشیاء autoreleasing از poolهای آزادسازی خودکار مختلف در Objective\-C. .sp بررسی \fIclang\-analyzer\-osx.cocoa.AutoreleaseWrite\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.cocoa.ClassRelease .sp بررسی ارسال مستقیم \(aqretain\(aq، \(aqrelease\(aq، یا \(aqautorelease\(aq به یک Class. .sp بررسی \fIclang\-analyzer\-osx.cocoa.ClassRelease\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.cocoa.Dealloc .sp هشدار دربارهٔ کلاس‌های Objective\-C که فاقد پیاده‌سازی صحیح \-dealloc هستند. .sp بررسی \fIclang\-analyzer\-osx.cocoa.Dealloc\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.cocoa.IncompatibleMethodTypes .sp هشدار در مورد امضای متدهای Objective\-C با ناسازگاری‌های نوع (type incompatibilities). .sp بررسی \fIclang\-analyzer\-osx.cocoa.IncompatibleMethodTypes\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.cocoa.Loops .sp مدل‌سازی بهبودیافته از حلقه‌ها با استفاده از انواع مجموعه‌های Cocoa. .sp بررسی \fIclang\-analyzer\-osx.cocoa.Loops\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.cocoa.MissingSuperCall .sp هشدار دربارهٔ متدهای Objective\-C که فاقد فراخوانی لازم به super هستند. .sp بررسی \fIclang\-analyzer\-osx.cocoa.MissingSuperCall\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.cocoa.NSAutoreleasePool .sp هشدار در مورد استفاده‌های غیربهینه از NSAutoreleasePool در حالت GC زبان Objective\-C. .sp بررسی \fIclang\-analyzer\-osx.cocoa.NSAutoreleasePool\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.cocoa.NSError .sp بررسی نحوهٔ استفاده از پارامترهای **NSError. .sp بررسی \fIclang\-analyzer\-osx.cocoa.NSError\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.cocoa.NilArg .sp بررسی آرگومان‌های غیرمجاز nil در فراخوانی متدهای ObjC. .sp بررسی \fIclang\-analyzer\-osx.cocoa.NilArg\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.cocoa.NonNilReturnValue .sp مدل‌سازی APIهایی که تضمین می‌کنند مقداری غیر از nil برمی‌گردانند. .sp بررسی \fIclang\-analyzer\-osx.cocoa.NonNilReturnValue\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.cocoa.ObjCGenerics .sp بررسی خطاهای نوع هنگام استفاده از جنریک‌های Objective\-C. .sp بررسی \fIclang\-analyzer\-osx.cocoa.ObjCGenerics\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.cocoa.RetainCount .sp بررسی نشت‌ها و مدیریت نادرست شمارندهٔ ارجاع (reference count). .sp بررسی \fIclang\-analyzer\-osx.cocoa.RetainCount\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.cocoa.RunLoopAutoreleaseLeak .sp بررسی حافظهٔ نشت‌یافته در autorelease poolهایی که هرگز تخلیه نمی‌شوند. .sp بررسی \fIclang\-analyzer\-osx.cocoa.RunLoopAutoreleaseLeak\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر بخش Clang Static Analyzer Available Checkers \% را ببینید. .SS clang\-analyzer\-osx.cocoa.SelfInit .sp بررسی می‌کند که \(aqself\(aq درون یک متد مقداردهی اولیه (initializer) به‌درستی مقداردهی شده باشد. .sp بررسی \fIclang\-analyzer\-osx.cocoa.SelfInit\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-osx.cocoa.SuperDealloc .sp درباره استفاده نادرست از \(aq[super dealloc]\(aq در Objective\-C هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-osx.cocoa.SuperDealloc\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-osx.cocoa.UnusedIvars .sp درباره ivarهای خصوصی که هرگز استفاده نشده‌اند هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-osx.cocoa.UnusedIvars\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-osx.cocoa.VariadicMethodTypes .sp ارسال انواع غیر Objective\-C به متدهای مقداردهی اولیه مجموعه‌های متغیر (variadic) را که فقط انتظار انواع Objective\-C دارند، بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-osx.cocoa.VariadicMethodTypes\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-osx.coreFoundation.CFError .sp استفاده از پارامترهای *CFErrorRef را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-osx.coreFoundation.CFError\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-osx.coreFoundation.CFNumber .sp استفاده صحیح از APIهای CFNumber را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-osx.coreFoundation.CFNumber\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-osx.coreFoundation.CFRetainRelease .sp آرگومان‌های تهی (null) به CFRetain/CFRelease/CFMakeCollectable را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-osx.coreFoundation.CFRetainRelease\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-osx.coreFoundation.containers.OutOfBounds .sp خارج از محدوده بودن اندیس را هنگام استفاده از API مربوط به \(aqCFArray\(aq بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-osx.coreFoundation.containers.OutOfBounds\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-osx.coreFoundation.containers.PointerSizedValues .sp اگر \(aqCFArray\(aq، \(aqCFDictionary\(aq یا \(aqCFSet\(aq با مقادیری با اندازه‌ای غیر از اندازه اشاره‌گر ساخته شوند، هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-osx.coreFoundation.containers.PointerSizedValues\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-security.FloatLoopCounter .sp در مورد استفاده از یک مقدار ممیز شناور به عنوان شمارنده حلقه هشدار می‌دهد (CERT: FLP30\-C, FLP30\-CPP). .sp بررسی \fIclang\-analyzer\-security.FloatLoopCounter\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-security.PutenvStackArray .sp فراخوانی‌های تابع putenv را پیدا می‌کند که اشاره‌گری به یک آرایه تخصیص‌یافته روی پشته (خودکار/اتوماتیک) را به عنوان آرگومان ارسال می‌کنند. تابع putenv رشته ارسالی را کپی نمی‌کند، بلکه تنها یک اشاره‌گر به داده ذخیره می‌شود و این داده حتی توسط ریسه‌های دیگر نیز قابل خواندن است. محتوای یک آرایه تخصیص‌یافته روی پشته به احتمال زیاد پس از خروج از تابع رونویسی می‌شود. .sp بررسی \fIclang\-analyzer\-security.PutenvStackArray\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-security.SetgidSetuidOrder .sp این بررسی‌کننده توالی‌های فراخوانی‌های \fBsetuid(getuid())\fP و \fBsetgid(getgid())\fP را (به همین ترتیب) بررسی می‌کند. اگر چنین توالی‌ای یافت شود و هیچ فراخوانی تابع تغییردهنده مجوز دیگری (\fBseteuid\fP، \fBsetreuid\fP، \fBsetresuid\fP و نسخه‌های GID آن‌ها) در این بین نباشد، یک هشدار صادر می‌شود. این بررسی‌کننده فقط فراخوانی‌های دقیقاً \fBsetuid(getuid())\fP (و نسخه‌های GID) را می‌یابد، نه مثلاً مواردی که نتیجه \fBgetuid()\fP در یک متغیر ذخیره شده باشد. .sp بررسی \fIclang\-analyzer\-security.SetgidSetuidOrder\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-security.cert.env.InvalidPtr .sp استفاده از اشاره‌گرهای احتمالاً باطل‌شده را می‌یابد. .sp بررسی \fIclang\-analyzer\-security.cert.env.InvalidPtr\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-security.insecureAPI.DeprecatedOrUnsafeBufferHandling .sp در مورد استفاده از توابع ناامن یا منسوخ‌شده دستکاری بافر هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-security.insecureAPI.DeprecatedOrUnsafeBufferHandling\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-security.insecureAPI.UncheckedReturn .sp در مورد استفاده از توابعی که مقادیر بازگشتی آن‌ها همیشه باید بررسی شوند، هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-security.insecureAPI.UncheckedReturn\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-security.insecureAPI.bcmp .sp در مورد استفاده از تابع \(aqbcmp\(aq هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-security.insecureAPI.bcmp\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-security.insecureAPI.bcopy .sp در مورد استفاده از تابع \(aqbcopy\(aq هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-security.insecureAPI.bcopy\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید..SS clang\-analyzer\-security.insecureAPI.bzero .sp درباره استفاده از تابع \(aqbzero\(aq هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-security.insecureAPI.bzero\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-security.insecureAPI.decodeValueOfObjCType .sp درباره استفاده از متد \(aq\-decodeValueOfObjCType:at:\(aq هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-security.insecureAPI.decodeValueOfObjCType\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer security.insecureAPI.decodeValueOfObjCType \% مراجعه کنید. .SS clang\-analyzer\-security.insecureAPI.getpw .sp درباره استفاده از تابع \(aqgetpw\(aq هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-security.insecureAPI.getpw\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-security.insecureAPI.gets .sp درباره استفاده از تابع \(aqgets\(aq هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-security.insecureAPI.gets\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-security.insecureAPI.mkstemp .sp هنگامی که کمتر از ۶ نویسه X در رشته قالب‌بندی به \(aqmkstemp\(aq ارسال شود، هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-security.insecureAPI.mkstemp\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-security.insecureAPI.mktemp .sp درباره استفاده از تابع \(aqmktemp\(aq هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-security.insecureAPI.mktemp\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-security.insecureAPI.rand .sp درباره استفاده از توابع \(aqrand\(aq، \(aqrandom\(aq و توابع مرتبط هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-security.insecureAPI.rand\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-security.insecureAPI.strcpy .sp درباره استفاده از توابع \(aqstrcpy\(aq و \(aqstrcat\(aq هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-security.insecureAPI.strcpy\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-security.insecureAPI.vfork .sp درباره استفاده از تابع \(aqvfork\(aq هشدار می‌دهد. .sp بررسی \fIclang\-analyzer\-security.insecureAPI.vfork\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-unix.API .sp فراخوانی توابع مختلف UNIX/Posix را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-unix.API\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-unix.BlockInCriticalSection .sp فراخوانی توابع مسدودکننده (blocking) در داخل بخش بحرانی (critical section) را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-unix.BlockInCriticalSection\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-unix.Errno .sp استفاده نادرست از \(aqerrno\(aq را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-unix.Errno\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-unix.Malloc .sp نشتی حافظه (memory leaks)، آزادسازی دوباره (double free) و مشکلات استفاده پس از آزادسازی (use\-after\-free) را بررسی می‌کند. حافظه مدیریت‌شده توسط malloc()/free() را ردیابی می‌کند. .sp بررسی \fIclang\-analyzer\-unix.Malloc\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-unix.MallocSizeof .sp آرگومان‌های مشکوک malloc شامل sizeof را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-unix.MallocSizeof\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-unix.MismatchedDeallocator .sp عدم تطابق توابع تخصیص‌زدا (deallocators) را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-unix.MismatchedDeallocator\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-unix.StdCLibraryFunctions .sp آرگومان‌های نامعتبر توابع کتابخانه استاندارد C را بررسی کرده و روابط میان آرگومان‌ها و مقدار بازگشتی را اعمال می‌کند. .sp بررسی \fIclang\-analyzer\-unix.StdCLibraryFunctions\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-unix.Stream .sp توابع مدیریت جریان (stream) را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-unix.Stream\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-unix.Vfork .sp استفاده صحیح از vfork را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-unix.Vfork\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-unix.cstring.BadSizeArg .sp آرگومان اندازه پاس داده شده به توابع رشته‌ای C را برای الگوهای خطای رایج بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-unix.cstring.BadSizeArg\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-unix.cstring.NullArg .sp پاس داده شدن اشاره‌گرهای تهی (null) به عنوان آرگومان به توابع رشته‌ای C را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-unix.cstring.NullArg\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-webkit.NoUncountedMemberChecker .sp عدم وجود متغیرهای عضو شمارش‌نشده (uncounted) را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-webkit.NoUncountedMemberChecker\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-webkit.RefCntblBaseVirtualDtor .sp بررسی می‌کند که آیا هر کلاس پایه‌ای با قابلیت شمارش ارجاع (ref\-countable) دارای مخرب مجازی (virtual destructor) است یا خیر. .sp بررسی \fIclang\-analyzer\-webkit.RefCntblBaseVirtualDtor\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS clang\-analyzer\-webkit.UncountedLambdaCapturesChecker .sp گرفتن‌های (captures) شمارش‌نشده در عبارات لامبدا را بررسی می‌کند. .sp بررسی \fIclang\-analyzer\-webkit.UncountedLambdaCapturesChecker\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر به Clang Static Analyzer Available Checkers \% مراجعه کنید. .SS concurrency\-mt\-unsafe .sp برخی از توابع ناامن از نظر ریسه‌بندی (thread\-unsafe) را در برابر یک لیست سیاه از توابع شناخته‌شده به ناامنی بررسی می‌کند. معمولاً این توابع بدون همگام‌سازی به متغیرهای ایستا دسترسی پیدا می‌کنند (مانند gmtime(3)) یا از سیگنال‌ها به شکلی همراه با شرایط رقابتی (racy) استفاده می‌نمایند. مجموعه توابعی که باید بررسی شوند با گزینه \fIFunctionSet\fP مشخص می‌شود. .sp توجه داشته باشید که استفاده از برخی توابع thread\-unsafe ممکن است در برنامه‌نویسی همروند در صورتی که تنها از یک ریسه استفاده شود همچنان معتبر باشد (مانند setenv(3))؛ با این حال، برخی از توابع ممکن است حالتی را در متغیرهای سراسری ردیابی کنند که با فراخوانی‌های بعدی (غیرموازی، اما همروند) به یک تابع مرتبط تخریب می‌شود. به عنوان مثال، کد زیر از دسترسی‌های محافظت‌نشده به یک وضعیت سراسری رنج می‌برد: .INDENT 0.0 .INDENT 3.5 .sp .EX // getnetent(3) maintains global state with DB connection, etc. // If a concurrent green thread calls getnetent(3), the global state is corrupted. netent = getnetent(); yield(); netent = getnetent(); .EE .UNINDENT .UNINDENT .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX tm = gmtime(timep); // uses a global buffer sleep(1); // implementation may use SIGALRM .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B FunctionSet مشخص می‌کند که کدام توابع در libc باید امن از نظر ریسه در نظر گرفته شوند؛ مقادیر ممکن عبارتند از \fIposix\fP، \fIglibc\fP، یا \fIany\fP\&. .sp مقدار \fIposix\fP به معنای توابع thread\-unsafe تعریف‌شده توسط POSIX است. استاندارد POSIX.1\-2001 در «2.9.1 Thread\-Safety» تعریف می‌کند که تمام توابع مشخص‌شده در استاندارد، به جز یک فهرست از پیش تعریف‌شده از توابع thread\-unsafe، امن از نظر ریسه هستند. .sp کتابخانه Glibc برخی از آن‌ها را به عنوان thread\-safe تعریف می‌کند (مانند dirname(3))، اما موارد ناامن غیراستاندارد POSIX را نیز اضافه می‌کند (مانند getopt_long(3)). فهرست Glibc از مستندات وب GNU با جستجو برای برچسب MT\-Safe گردآوری شده است: \% .sp اگر می‌خواهید APIهای thread\-unsafe را حداقل برای یک libc شناسایی کنید یا مطمئن نیستید از کدام libc استفاده خواهد شد، از \fIany\fP (پیش‌فرض) استفاده کنید. .UNINDENT .SS concurrency\-thread\-canceltype\-asynchronous .sp فراخوانی‌های تابع \fBpthread_setcanceltype\fP را که در آن‌ها نوع لغو ریسه روی ناهمگام (asynchronous) تنظیم شده است، پیدا می‌کند. نوع لغو ناهمگام (\fBPTHREAD_CANCEL_ASYNCHRONOUS\fP) به طور کلی ناامن است؛ به جای آن از نوع \fBPTHREAD_CANCEL_DEFERRED\fP که حالت پیش‌فرض است استفاده کنید. حتی با لغو به تعویق افتاده (deferred)، یک نقطه لغو در یک مدیر سیگنال ناهمگام ممکن است همچنان اعمال شود و اثر آن به گونه‌ای خواهد بود که گویی یک لغو ناهمگام بوده است. .INDENT 0.0 .INDENT 3.5 .sp .EX pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); .EE .UNINDENT .UNINDENT .sp این بررسی با قاعده استاندارد کدنویسی CERT C مطابقت دارد: POS47\-C. Do not use threads that can be canceled asynchronously \%\&. .sp بررسی \fIcert\-pos47\-c\fP به عنوان نام مستعار این بررسی به اینجا هدایت می‌شود. .SS cppcoreguidelines\-avoid\-c\-arrays .sp بررسی \fIcppcoreguidelines\-avoid\-c\-arrays\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر به modernize\-avoid\-c\-arrays \%<> مراجعه کنید. .SS cppcoreguidelines\-avoid\-capturing\-lambda\-coroutines .sp لامبداهای کوروتین C++20 با لیست‌های ضبط غیرخالی را که ممکن است باعث خطاهای use\-after\-free شوند نشانه‌گذاری می‌کند و پیشنهاد می‌کند از گرفتن مقادیر خودداری شود یا اطمینان حاصل شود که شیء بستار (closure) لامبدا دارای طول عمر تضمین‌شده است. .sp این بررسی قاعده CP.51 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .sp استفاده از لامبداهای کوروتین با لیست‌های گرفتن (capture lists) غیرخالی می‌تواند پرخطر باشد، زیرا گرفتن متغیرها می‌تواند منجر به دسترسی به حافظه آزاد شده پس از اولین نقطه تعلیق (suspension point) شود. این مشکل حتی ممکن است با اشاره‌گرهای هوشمند شمارش ارجاع‌شده (refcounted) و انواع قابل کپی نیز رخ دهد. هنگامی که یک عبارت لامبدا یک کوروتین ایجاد می‌کند، منجر به ایجاد یک شیء closure با فضای ذخیره‌سازی می‌شود که اغلب روی پشته قرار دارد و در نهایت از محدوده (scope) خارج می‌شود. هنگامی که شیء closure از محدوده خارج می‌شود، مقادیر ضبط‌شده آن نیز از محدوده خارج می‌شوند. در حالی که لامبداهای معمولی قبل از وقوع این امر اجرای خود را به پایان می‌رسانند، لامبداهای کوروتین ممکن است پس از تخریب شیء closure از حالت تعلیق از سر گرفته شوند که این امر منجر به دسترسی به حافظه use\-after\-free برای تمام مقادیر ضبط‌شده می‌شود. .sp مثال زیر را در نظر بگیرید: .INDENT 0.0 .INDENT 3.5 .sp .EX int value = get_value(); std::shared_ptr sharedFoo = get_foo(); { const auto lambda = [value, sharedFoo]() \-> std::future { co_await something(); // \(dqsharedFoo\(dq and \(dqvalue\(dq have already been destroyed // the \(dqshared\(dq pointer didn\(aqt accomplish anything }; lambda(); } // the lambda closure object has now gone out of scope .EE .UNINDENT .UNINDENT .sp در این مثال، شیء لامبدا با دو مورد ضبط تعریف شده است: value و \fBsharedFoo\fP\&. هنگامی که \fBlambda()\fP فراخوانی می‌شود، شیء لامبدا روی پشته ایجاد می‌شود و مقادیر ضبط‌شده در شیء closure کپی می‌شوند. هنگامی که کوروتین معلق می‌شود، شیء لامبدا از محدوده خارج شده و شیء closure تخریب می‌شود. هنگامی که کوروتین از سر گرفته می‌شود، متغیرهای ضبط‌شده ممکن است تخریب شده باشند که منجر به باگ‌های use\-after\-free می‌شود. .sp در نتیجه، استفاده از لامبداهای کوروتین با لیست‌های ضبط غیرخالی می‌تواند هنگام ازسرگیری کوروتین پس از تخریب شیء closure منجر به خطاهای use\-after\-free شود. این بررسی با نشانه‌گذاری لامبداهای کوروتین C++20 با لیست‌های ضبط غیرخالی و پیشنهاد اجتناب از captures یا تضمین طول عمر معتبر شیء closure لامبدا، به جلوگیری از چنین خطاهایی کمک می‌کند. .sp پیروی از این دستورالعمل‌ها می‌تواند به تضمین استفاده ایمن و قابل اعتماد از لامبداهای کوروتین در کدهای C++ کمک کند. .SS cppcoreguidelines\-avoid\-const\-or\-ref\-data\-members .sp این بررسی زمانی هشدار می‌دهد که ساختارها یا کلاس‌هایی که قابلیت کپی یا انتقال دارند، دارای اعضای داده‌ای واجد شرایط const یا ارجاعی (lvalue یا rvalue) باشند. داشتن چنین اعضایی به ندرت مفید است و باعث می‌شود کلاس تنها قابلیت ساخت با کپی (copy\-constructible) داشته باشد اما قابلیت انتساب با کپی (copy\-assignable) را از دست بدهد. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX // Bad, const\-qualified member struct Const { const int x; } // Good: class Foo { public: int get() const { return x; } private: int x; }; // Bad, lvalue reference member struct Ref { int& x; }; // Good: struct Foo { int* x; std::unique_ptr x; std::shared_ptr x; gsl::not_null x; }; // Bad, rvalue reference member struct RefRef { int&& x; }; .EE .UNINDENT .UNINDENT .sp این بررسی بند C.12 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .sp مطالعه بیشتر: Data members: Never const \%\&. .SS cppcoreguidelines\-avoid\-do\-while .sp هنگام استفاده از حلقه‌های \fBdo\-while\fP هشدار می‌دهد. خوانایی آن‌ها نسبت به حلقه‌های سادهٔ \fBwhile\fP کمتر است، زیرا شرط پایان در انتها قرار دارد و شرط پیش از اولین تکرار حلقه بررسی نمی‌شود. این مسئله می‌تواند منجر به باگ‌های نامحسوس شود. .sp این بررسی بند ES.75 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX int x; do { std::cin >> x; // ... } while (x < 0); .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoreMacros هنگام تحلیل ماکروها، این بررسی را نادیده می‌گیرد. این مورد برای تعریف ایمن ماکروهای شبه‌تابع کاربرد دارد: .INDENT 7.0 .INDENT 3.5 .sp .EX #define FOO_BAR(x) \e do { \e foo(x); \e bar(x); \e } while(0) .EE .UNINDENT .UNINDENT .sp پیش‌فرض \fIfalse\fP است\&. .UNINDENT .SS cppcoreguidelines\-avoid\-goto .sp استفاده از \fBgoto\fP برای کنترل جریان خطا‌پذیر است و باید با ساختارهای تکرار حلقه جایگزین شود. تنها پرش‌های روبه‌جلو در حلقه‌های تو‌در‌تو مجاز هستند. .sp این بررسی بند ES.76 \% از C++ Core Guidelines و بند 6.3.1 \% از High Integrity C++ Coding Standard را پیاده‌سازی می‌کند. .sp برای اطلاعات بیشتر در مورد چرایی پرهیز از برنامه‌نویسی با \fBgoto\fP می‌توانید مقالهٔ مشهور A Case against the GO TO Statement را مطالعه کنید: \%\&. .sp این بررسی \fBgoto\fP را برای پرش‌های روبه‌عقب در تمامی حالت‌های زبان عیب‌یابی می‌کند. این موارد باید با ساختارهای تکرار حلقه در \fIC/C++\fP جایگزین شوند. .INDENT 0.0 .INDENT 3.5 .sp .EX // Bad, handwritten for loop. int i = 0; // Jump label for the loop loop_start: do_some_operation(); if (i < 100) { ++i; goto loop_start; } // Better for(int i = 0; i < 100; ++i) do_some_operation(); .EE .UNINDENT .UNINDENT .sp زبان C++ مدرن فقط برای پرش به بیرون از حلقه‌های تودرتو به \fBgoto\fP نیاز دارد. .INDENT 0.0 .INDENT 3.5 .sp .EX for(int i = 0; i < 100; ++i) { for(int j = 0; j < 100; ++j) { if (i * j > 500) goto early_exit; } } early_exit: some_operation(); .EE .UNINDENT .UNINDENT .sp سایر کاربردهای \fBgoto\fP در \fIC++\fP عیب‌یابی می‌شوند. .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoreMacros اگر روی \fItrue\fP تنظیم شود، در صورتی که یک عبارت \fBgoto\fP از یک ماکرو بسط یافته باشد، این بررسی هشداری صادر نخواهد کرد. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .SS cppcoreguidelines\-avoid\-magic\-numbers .sp بررسی \fIcppcoreguidelines\-avoid\-magic\-numbers\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر به readability\-magic\-numbers \%<> مراجعه کنید. .SS cppcoreguidelines\-avoid\-non\-const\-global\-variables .sp متغیرهای سراسری غیر\-const را همان‌طور که در بند I.2 \% از C++ Core Guidelines توصیف شده است پیدا می‌کند. از آنجا که قاعده R.6 \% از C++ Core Guidelines تکرار قاعده I.2 \% است، این بررسی آن قاعده را نیز پوشش می‌دهد. .INDENT 0.0 .INDENT 3.5 .sp .EX char a; // Warns! const char b = 0; namespace some_namespace { char c; // Warns! const char d = 0; } char * c_ptr1 = &some_namespace::c; // Warns! char *const c_const_ptr = &some_namespace::c; // Warns! char & c_reference = some_namespace::c; // Warns! class Foo // No Warnings inside Foo, only namespace scope is covered { public: char e = 0; const char f = 0; protected: char g = 0; private: char h = 0; }; .EE .UNINDENT .UNINDENT .sp متغیرهای \fBa\fP، \fBc\fP، \fBc_ptr1\fP، \fBc_const_ptr\fP و \fBc_reference\fP همگی هشدار ایجاد خواهند کرد، زیرا یا یک متغیر غیر\-const با دسترسی سراسری هستند، یا اشاره‌گر یا ارجاعی هستند که دسترسی سراسری به داده‌های غیر\-const را فراهم می‌کنند، و یا هر دو. .SS گزینه‌ها .INDENT 0.0 .TP .B AllowInternalLinkage هنگامی که روی \fItrue\fP تنظیم شود، متغیرهای استاتیک غیر\-const و متغیرهای موجود در فضاهای نام بی‌نام (anonymous namespaces) هشداری ایجاد نخواهند کرد. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .INDENT 0.0 .TP .B AllowThreadLocal هنگامی که روی \fItrue\fP تنظیم شود، متغیرهای سراسری غیر\-const با طول عمر ذخیره‌سازی محلی-نخ (thread\-local storage duration) هشداری تولید نمی‌کنند. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .SS cppcoreguidelines\-avoid\-reference\-coroutine\-parameters .sp زمانی که یک کوروتین (coroutine) پارامترهای ارجاعی می‌پذیرد هشدار می‌دهد. پس از نقطه تعلیق (suspend point) کوروتین، ارجاع‌ها ممکن است معلق (dangling) شده و دیگر معتبر نباشند. در عوض، پارامترها را به صورت مقداری (by value) ارسال کنید. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX std::future someCoroutine(int& val) { co_await ...; // When the coroutine is resumed, \(aqval\(aq might no longer be valid. if (val) ... } .EE .UNINDENT .UNINDENT .sp این بررسی قاعده CP.53 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .SS cppcoreguidelines\-c\-copy\-assignment\-signature .sp بررسی \fIcppcoreguidelines\-c\-copy\-assignment\-signature\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر به misc\-unconventional\-assign\-operator \%<> مراجعه کنید. .SS cppcoreguidelines\-explicit\-virtual\-functions .sp بررسی \fIcppcoreguidelines\-explicit\-virtual\-functions\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر به modernize\-use\-override \%<> مراجعه کنید. .SS cppcoreguidelines\-init\-variables .sp بررسی می‌کند که آیا متغیرهای محلی وجود دارند که بدون مقدار اولیه اعلان شده باشند. در صورتی که مسیر کدی وجود داشته باشد که متغیر را قبل از مقداردهی بخواند، این امر ممکن است منجر به رفتار غیرمنتظره شود. .sp این قاعده بخشی از نمایه ایمنی نوع (Type.5) \% و ES.20 \% از C++ Core Guidelines است. .sp تنها اعداد صحیح، بولی‌ها، اعشاری‌های float و double و اشاره‌گرها بررسی می‌شوند. گزینه اصلاح (fix) تمام مقادیر شناسایی‌شده را با مقدار صفر مقداردهی اولیه می‌کند. یک استثنا انواع float و double هستند که با NaN مقداردهی اولیه می‌شوند. .sp به عنوان مثال تابعی که به این صورت است: .INDENT 0.0 .INDENT 3.5 .sp .EX void function() { int x; char *txt; double d; // Rest of the function. } .EE .UNINDENT .UNINDENT .sp به این صورت بازنویسی می‌شود: .INDENT 0.0 .INDENT 3.5 .sp .EX #include void function() { int x = 0; char *txt = nullptr; double d = NAN; // Rest of the function. } .EE .UNINDENT .UNINDENT .sp برای حالت enum مقداردهی‌نشده هشدار می‌دهد، اما بدون FixIt: .INDENT 0.0 .INDENT 3.5 .sp .EX enum A {A1, A2, A3}; enum A_c : char { A_c1, A_c2, A_c3 }; enum class B { B1, B2, B3 }; enum class B_i : int { B_i1, B_i2, B_i3 }; void function() { A a; // Warning: variable \(aqa\(aq is not initialized A_c a_c; // Warning: variable \(aqa_c\(aq is not initialized B b; // Warning: variable \(aqb\(aq is not initialized B_i b_i; // Warning: variable \(aqb_i\(aq is not initialized } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IncludeStyle رشته‌ای که شیوه درج include را مشخص می‌کند، \fIllvm\fP یا \fIgoogle\fP\&. مقدار پیش‌فرض \fIllvm\fP است\&. .UNINDENT .INDENT 0.0 .TP .B MathHeader رشته‌ای که هدر لازم جهت دریافت تعریف \fINAN\fP را مشخص می‌کند\&. پیش‌فرض \fI\fP است\&. .UNINDENT .SS cppcoreguidelines\-interfaces\-global\-init .sp این بررسی مقداردهنده‌های متغیرهای سراسری (globals) را که به اشیای extern دسترسی دارند پرچم‌گذاری می‌کند، چرا که این موضوع می‌تواند به مشکل در ترتیب مقداردهی اولیه (order\-of\-initialization) منجر شود. .sp این بررسی بخش I.22 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .sp توجه داشته باشید که در حال حاضر این بررسی، فراخوانی‌های توابع غیر constexpr را پرچم‌گذاری نمی‌کند، بنابراین متغیرهای سراسری همچنان ممکن است از درون خود توابع قابل دسترسی باشند. .SS cppcoreguidelines\-macro\-to\-enum .sp بررسی \fIcppcoreguidelines\-macro\-to\-enum\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر modernize\-macro\-to\-enum \%<> را ببینید. .SS cppcoreguidelines\-macro\-usage .sp موارد استفاده از ماکروها را که به دلیل وجود ساختارهای زبانی بهتر برای انجام آن کار مشکل‌ساز تلقی می‌شوند، پیدا می‌کند. .sp بخش‌های مربوطه در C++ Core Guidelines عبارتند از ES.31 \% و ES.32 \%\&. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX #define C 0 #define F1(x, y) ((a) > (b) ? (a) : (b)) #define F2(...) (__VA_ARGS__) #define F3(x, y) x##y #define COMMA , #define NORETURN [[noreturn]] #define DEPRECATED attribute((deprecated)) #if LIB_EXPORTS #define DLLEXPORTS __declspec(dllexport) #else #define DLLEXPORTS __declspec(dllimport) #endif .EE .UNINDENT .UNINDENT .sp به هشدارهای زیر منجر می‌شود: .INDENT 0.0 .INDENT 3.5 .sp .EX 4 warnings generated. test.cpp:1:9: warning: macro \(aqC\(aq used to declare a constant; consider using a \(aqconstexpr\(aq constant [cppcoreguidelines\-macro\-usage] #define C 0 ^ test.cpp:2:9: warning: function\-like macro \(aqF1\(aq used; consider a \(aqconstexpr\(aq template function [cppcoreguidelines\-macro\-usage] #define F1(x, y) ((a) > (b) ? (a) : (b)) ^ test.cpp:3:9: warning: variadic macro \(aqF2\(aq used; consider using a \(aqconstexpr\(aq variadic template function [cppcoreguidelines\-macro\-usage] #define F2(...) (__VA_ARGS__) ^ .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B AllowedRegexp یک عبارت باقاعده (regular expression) برای فیلتر کردن ماکروهای مجاز. برای مثال \fIDEBUG*|LIBTORRENT*|TORRENT*|UNI*\fP را می‌توان برای فیلتر کردن \fIlibtorrent\fP اعمال کرد\&. مقدار پیش‌فرض \fI^DEBUG_*\fP است\&. .UNINDENT .INDENT 0.0 .TP .B CheckCapsOnly پرچم بولی برای هشدار دادن روی تمام ماکروها به جز آن‌هایی که نامشان صرفاً با حروف بزرگ (CAPS_ONLY) است. هدف این گزینه، تسهیل ورود این بررسی به کدهای قدیمی‌تر است. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .INDENT 0.0 .TP .B IgnoreCommandLineMacros پرچم بولی برای نادیده گرفتن ماکروهای تعریف‌شده در خط فرمان. مقدار پیش‌فرض \fItrue\fP است\&. .UNINDENT .SS cppcoreguidelines\-misleading\-capture\-default\-by\-value .sp زمانی که یک لامبدا پیش‌فرض دریافت با مقدار (by-value) را مشخص کرده و \fBthis\fP را ضبط می‌کند، هشدار می‌دهد\&. .sp دریافت‌های پیش‌فرض با مقدار در توابع عضو می‌تواند درباره اینکه آیا اعضای داده‌ای با مقدار یا با ارجاع دریافت شده‌اند گمراه‌کننده باشد. این امر به این دلیل رخ می‌دهد که مشخص کردن دریافت پیش‌فرض با مقدار \fB[=]\fP در عمل اشاره‌گر \fBthis\fP را با مقدار دریافت می‌کند، نه خود اعضای داده‌ای را. در نتیجه، اعضای داده‌ای همچنان به‌طور غیرمستقیم از طریق اشاره‌گر دریافت‌شدهٔ \fBthis\fP در دسترس قرار می‌گیرند، که اساساً به این معنی است که با ارجاع مورد دسترسی قرار گرفته‌اند. بنابراین، حتی هنگام استفاده از \fB[=]\fP، اعضای داده‌ای عملاً با ارجاع ضبط می‌شوند، که ممکن است با انتظارات کاربر همخوانی نداشته باشد. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX struct AClass { int member; void misleadingLogic() { int local = 0; member = 0; auto f = [=]() mutable { local += 1; member += 1; }; f(); // Here, local is 0 but member is 1 } void clearLogic() { int local = 0; member = 0; auto f = [this, local]() mutable { local += 1; member += 1; }; f(); // Here, local is 0 but member is 1 } }; .EE .UNINDENT .UNINDENT .sp این بررسی بخش F.54 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .SS cppcoreguidelines\-missing\-std\-forward .sp زمانی که یک پارامتر ارجاع هدایت‌کننده (forwarding reference) در بدنه تابع فوروارد نشده باشد، هشدار می‌دهد. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX template void wrapper(T&& t) { impl(std::forward(t), 1, 2); // Correct } template void wrapper2(T&& t) { impl(t, 1, 2); // Oops \- should use std::forward(t) } template void wrapper3(T&& t) { impl(std::move(t), 1, 2); // Also buggy \- should use std::forward(t) } template void wrapper_function(F&& f) { std::forward(f)(1, 2); // Correct } template void wrapper_function2(F&& f) { f(1, 2); // Incorrect \- may not invoke the desired qualified function operator } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B ForwardFunction تابعی که برای فوروارد کردن استفاده می‌شود را تعیین می‌کند. پیش‌فرض \fI::std::forward\fP است. .UNINDENT .sp این بررسی، بخش F.19 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .SS cppcoreguidelines\-narrowing\-conversions .sp این بررسی بخشی از ES.46 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .sp بررسی \fIcppcoreguidelines\-narrowing\-conversions\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به bugprone\-narrowing\-conversions \%<> مراجعه کنید. .SS cppcoreguidelines\-no\-malloc .sp این بررسی مدیریت حافظه به سبک زبان C با استفاده از \fBmalloc()\fP، \fBrealloc()\fP، \fBcalloc()\fP و \fBfree()\fP را مدیریت می‌کند. درباره استفاده از آن‌ها هشدار داده و سعی می‌کند استفاده از یک شیء RAII مناسب را پیشنهاد دهد. علاوه بر این، می‌تواند طوری پیکربندی شود که فهرستی تعیین‌شده توسط کاربر از توابع مورد استفاده برای مدیریت حافظه (مانند \fBposix_memalign()\fP) را بررسی کند. .sp این بررسی، بخش R.10 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .sp هیچ تلاشی برای ارائه راهنمایی‌های تصحیح خودکار (fix\-it hints) صورت نگرفته است، زیرا مدیریت دستی منابع را نمی‌توان به سادگی و به صورت خودکار به RAII تبدیل کرد. .INDENT 0.0 .INDENT 3.5 .sp .EX // Warns each of the following lines. // Containers like std::vector or std::string should be used. char* some_string = (char*) malloc(sizeof(char) * 20); char* some_string = (char*) realloc(sizeof(char) * 30); free(some_string); int* int_array = (int*) calloc(30, sizeof(int)); // Rather use a smartpointer or stack variable. struct some_struct* s = (struct some_struct*) malloc(sizeof(struct some_struct)); .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B Allocations فهرستی جداشده با نقطه ویرگول (semicolon) از نام‌های کاملاً واجد شرایط (fully qualified) توابع تخصیص حافظه. پیش‌فرض \fI::malloc;::calloc\fP است. .UNINDENT .INDENT 0.0 .TP .B Deallocations فهرستی جداشده با نقطه ویرگول از نام‌های کاملاً واجد شرایط توابع آزادسازی حافظه. پیش‌فرض \fI::free\fP است. .UNINDENT .INDENT 0.0 .TP .B Reallocations فهرستی جداشده با نقطه ویرگول از نام‌های کاملاً واجد شرایط توابع تخصیص مجدد حافظه. پیش‌فرض \fI::realloc\fP است. .UNINDENT .SS cppcoreguidelines\-no\-suspend\-with\-lock .sp کوروتین‌هایی (coroutines) را نشانه‌گذاری می‌کند که در نقطه تعلیق، یک lock guard در دامنه (scope) آن‌ها وجود دارد و به حالت تعلیق درمی‌آیند. .sp هنگامی که یک کوروتین معلق می‌شود، هر قفل یا mutex در اختیار آن تا زمان ازسرگیری مجدد کوروتین و نهایتاً تخریب lock guard، قفل باقی خواهد ماند. این امر می‌تواند منجر به دوره‌های طولانی نگه‌داشتن mutex شده و خطر قفل متقابل (deadlock) را به همراه داشته باشد. .sp در عوض، قفل‌ها باید پیش از تعلیق یک کوروتین آزاد شوند. .sp این بررسی تنها تعلیق کوروتین‌ها در شرایطی که lock_guard در دامنه وجود دارد را بررسی می‌کند؛ و قفل‌گذاری یا آزادسازی دستی mutexها را، به عنوان مثال از طریق فراخوانی \fBstd::mutex::lock()\fP، در نظر نمی‌گیرد. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX future bad_coro() { std::lock_guard lock{mtx}; ++some_counter; co_await something(); // Suspending while holding a mutex } future good_coro() { { std::lock_guard lock{mtx}; ++some_counter; } // Destroy the lock_guard to release the mutex before suspending the coroutine co_await something(); // Suspending while holding a mutex } .EE .UNINDENT .UNINDENT .sp این بررسی، بخش CP.52 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .SS cppcoreguidelines\-noexcept\-destructor .sp این بررسی، بخش C.37 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .sp بررسی \fIcppcoreguidelines\-noexcept\-destructor\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر به performance\-noexcept\-destructor \%<> مراجعه کنید. .SS cppcoreguidelines\-noexcept\-move\-operations .sp این بررسی، بخش C.66 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .sp بررسی \fIcppcoreguidelines\-noexcept\-move\-operations\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر به performance\-noexcept\-move\-constructor \%<> مراجعه کنید. .SS cppcoreguidelines\-noexcept\-swap .sp این بررسی، بخش‌های C.83 \% ، C.84 \% و C.85 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .sp بررسی \fIcppcoreguidelines\-noexcept\-swap check\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر به performance\-noexcept\-swap \%<> مراجعه کنید. .SS cppcoreguidelines\-non\-private\-member\-variables\-in\-classes .sp بررسی \fIcppcoreguidelines\-non\-private\-member\-variables\-in\-classes\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر به misc\-non\-private\-member\-variables\-in\-classes \%<> مراجعه کنید. .SS cppcoreguidelines\-owning\-memory .sp این بررسی، معناشناسی مبتنی بر نوع \fBgsl::owner\fP را پیاده‌سازی می‌کند که تحلیل ایستا را روی کدهایی که از اشاره‌گرهای خام برای مدیریت منابعی مانند حافظه پویا استفاده می‌کنند ولی مفاهیم RAII را به کار نمی‌گیرند، امکان‌پذیر می‌سازد. .sp این بررسی، بخش‌های I.11 \%، C.33 \%، R.3 \% و GSL.Views \% از C++ Core Guidelines را پیاده‌سازی می‌کند. تعریف یک \fBgsl::owner\fP بسیار سرراست است .INDENT 0.0 .INDENT 3.5 .sp .EX namespace gsl { template owner = T; } .EE .UNINDENT .UNINDENT .sp بنابراین، معرفی مالک حتی بدون استفاده از پیاده‌سازی Guideline Support Library \% نیز ساده است. .sp همه بررسی‌ها کاملاً مبتنی بر نوع هستند و (هنوز) به جریان حساس (flow sensitive) نمی‌باشند. .sp مثال‌های زیر مقداردهی‌های اولیه درست و نادرست مالک‌ها را نشان می‌دهند؛ با انتساب‌ها نیز به همین روش برخورد می‌شود. توجه داشته باشید که هر دو توابع منابع \fBnew\fP و توابع مشابه \fBmalloc()\fP، به عنوان تولیدکننده منبع در نظر گرفته می‌شوند. .INDENT 0.0 .INDENT 3.5 .sp .EX // Creating an owner with factory functions is checked. gsl::owner function_that_returns_owner() { return gsl::owner(new int(42)); } // Dynamic memory must be assigned to an owner int* Something = new int(42); // BAD, will be caught gsl::owner Owner = new int(42); // Good gsl::owner Owner = new int[42]; // Good as well // Returned owner must be assigned to an owner int* Something = function_that_returns_owner(); // Bad, factory function gsl::owner Owner = function_that_returns_owner(); // Good, result lands in owner // Something not a resource or owner should not be assigned to owners int Stack = 42; gsl::owner Owned = &Stack; // Bad, not a resource assigned .EE .UNINDENT .UNINDENT .sp در مورد حافظه پویا به عنوان منبع، تنها متغیرهای \fBgsl::owner\fP مجاز به حذف (delete) شدن هستند. .INDENT 0.0 .INDENT 3.5 .sp .EX // Example Bad, non\-owner as resource handle, will be caught. int* NonOwner = new int(42); // First warning here, since new must land in an owner delete NonOwner; // Second warning here, since only owners are allowed to be deleted // Example Good, Ownership correctly stated gsl::owner Owner = new int(42); // Good delete Owner; // Good as well, statically enforced, that only owners get deleted .EE .UNINDENT .UNINDENT .sp علاوه بر این، بررسی تضمین می‌کند توابعی که یک \fBgsl::owner\fP را به عنوان شناسه انتظار دارند، یا با یک \fBgsl::owner\fP یا با یک منبع تازه‌ساخته‌شده فراخوانی شوند. .INDENT 0.0 .INDENT 3.5 .sp .EX void expects_owner(gsl::owner o) { delete o; } // Bad Code int NonOwner = 42; expects_owner(&NonOwner); // Bad, will get caught // Good Code gsl::owner Owner = new int(42); expects_owner(Owner); // Good expects_owner(new int(42)); // Good as well, recognized created resource // Port legacy code for better resource\-safety gsl::owner File = fopen(\(dqmy_file.txt\(dq, \(dqrw+\(dq); FILE* BadFile = fopen(\(dqanother_file.txt\(dq, \(dqw\(dq); // Bad, warned // ... use the file fclose(File); // Ok, File is annotated as \(aqowner<>\(aq fclose(BadFile); // BadFile is not an \(aqowner<>\(aq, will be warned .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B LegacyResourceProducers فهرستی جداشده با نقطه\-ویرگول (semicolon) از نام‌های کامل توابع قدیمی (legacy) که منابع را ایجاد می‌کنند اما نمی‌توانند \fBgsl::owner<>\fP را معرفی کنند. پیش‌فرض: \fI::malloc;::aligned_alloc;::realloc;::calloc;::fopen;::freopen;::tmpfile\fP\&. .UNINDENT .INDENT 0.0 .TP .B LegacyResourceConsumers فهرستی جداشده با نقطه\-ویرگول از نام‌های کامل توابع قدیمی که مالکان منابع را به عنوان آرگومان‌های اشاره‌گر می‌پذیرند اما نمی‌توانند \fBgsl::owner<>\fP را معرفی کنند. پیش‌فرض: \fI::free;::realloc;::freopen;::fclose\fP\&. .UNINDENT .SS محدودیت‌ها .sp استفاده از \fBgsl::owner\fP در یک typedef یا alias به درستی مدیریت نمی‌شود. .INDENT 0.0 .INDENT 3.5 .sp .EX using heap_int = gsl::owner; heap_int allocated = new int(42); // False positive! .EE .UNINDENT .UNINDENT .sp مورد \fBgsl::owner\fP به عنوان یک نام مستعار نوع قالب‌بندی‌شده (templated type alias) اعلان شده است. در توابع و کلاس‌های قالب (template)، مانند مثال زیر، اطلاعات نام‌های مستعار نوع از بین می‌رود. بنابراین، استفاده از \fBgsl::owner\fP در یک پایگاه کد به شدت مبتنی بر قالب ممکن است به مثبت کاذب (false positive) منجر شود. .sp ساختارهای کدی شناخته‌شده‌ای که به درستی عیب‌یابی نمی‌شوند عبارتند از: .INDENT 0.0 .IP \(bu 2 \fBstd::exchange\fP .IP \(bu 2 \fBstd::vector>\fP .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX // This template function works as expected. Type information doesn\(aqt get lost. template void delete_owner(gsl::owner owned_object) { delete owned_object; // Everything alright } gsl::owner function_that_returns_owner() { return gsl::owner(new int(42)); } // Type deduction does not work for auto variables. // This is caught by the check and will be noted accordingly. auto OwnedObject = function_that_returns_owner(); // Type of OwnedObject will be int* // Problematic function template that looses the typeinformation on owner template void bad_template_function(T some_object) { // This line will trigger the warning, that a non\-owner is assigned to an owner gsl::owner new_owner = some_object; } // Calling the function with an owner still yields a false positive. bad_template_function(gsl::owner(new int(42))); // The same issue occurs with templated classes like the following. template class OwnedValue { public: const T getValue() const { return _val; } private: T _val; }; // Code, that yields a false positive. OwnedValue> Owner(new int(42)); // Type deduction yield T \-> int * // False positive, getValue returns int* and not gsl::owner gsl::owner OwnedInt = Owner.getValue(); .EE .UNINDENT .UNINDENT .sp محدودیت دیگر پیاده‌سازی فعلی، بررسیِ صرفاً مبتنی بر نوع است. فرض کنید کدی شبیه به زیر دارید: .INDENT 0.0 .INDENT 3.5 .sp .EX // Two owners with assigned resources gsl::owner Owner1 = new int(42); gsl::owner Owner2 = new int(42); Owner2 = Owner1; // Conceptual Leak of initial resource of Owner2! Owner1 = nullptr; .EE .UNINDENT .UNINDENT .sp معناشناسی یک \fBgsl::owner\fP عمدتاً شبیه به یک \fBstd::unique_ptr\fP است، بنابراین انتساب دو \fBgsl::owner\fP به عنوان یک انتقال (move) در نظر گرفته می‌شود، که مستلزم آن است منبع \fBOwner2\fP باید قبل از انتساب آزاد شده باشد. این نوع شرایط می‌تواند در بهبودهای آینده این بررسی با تحلیل حساس به جریان (flow-sensitive analysis) شناسایی شود. در حال حاضر، ابزار \fIClang Static Analyzer\fP این باگ را برای حافظه پویا شناسایی می‌کند، اما نه برای انواع عمومی منابع. .SS cppcoreguidelines\-prefer\-member\-initializer .sp مقداردهی‌های اولیه اعضا را در بدنه سازنده پیدا می‌کند که می‌توانند به جای آن به مقداردهنده‌های اولیه عضو (member initializers) سازنده تبدیل شوند. این کار نه تنها خوانایی کد را بهبود می‌بخشد، بلکه بر کارایی و عملکرد آن نیز تأثیر مثبتی دارد. انتساب‌های اعضای کلاس در داخل یک عبارت کنترلی یا پس از اولین عبارت کنترلی نادیده گرفته می‌شوند. .sp این بررسی قاعده C.49 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .sp لطفاً توجه داشته باشید که این بررسی قاعده C.48 \% از C++ Core Guidelines را اعمال نمی‌کند. برای این منظور، بررسی modernize\-use\-default\-member\-init \%<> را ببینید. .SS مثال ۱ .INDENT 0.0 .INDENT 3.5 .sp .EX class C { int n; int m; public: C() { n = 1; // Literal in default constructor if (dice()) return; m = 1; } }; .EE .UNINDENT .UNINDENT .sp در اینجا \fBn\fP بر خلاف \fBm\fP می‌تواند در فهرست مقداردهنده اولیه سازنده مقداردهی شود، زیرا مقداردهی اولیه \fBm\fP پس از یک عبارت کنترلی (\fBif\fP) قرار دارد: .INDENT 0.0 .INDENT 3.5 .sp .EX class C { int n; int m; public: C(): n(1) { if (dice()) return; m = 1; } }; .EE .UNINDENT .UNINDENT .SS مثال ۲ .INDENT 0.0 .INDENT 3.5 .sp .EX class C { int n; int m; public: C(int nn, int mm) { n = nn; // Neither default constructor nor literal if (dice()) return; m = mm; } }; .EE .UNINDENT .UNINDENT .sp در اینجا برخلاف \fBm\fP، می‌توان \fBn\fP را در فهرست مقداردهی اولیهٔ سازنده مقداردهی کرد، زیرا مقداردهی اولیهٔ \fBm\fP پس از یک دستور کنترلی (\fBif\fP) قرار دارد: .INDENT 0.0 .INDENT 3.5 .sp .EX C(int nn, int mm) : n(nn) { if (dice()) return; m = mm; } .EE .UNINDENT .UNINDENT .SS cppcoreguidelines\-pro\-bounds\-array\-to\-pointer\-decay .sp این بررسی تمام زوال‌های آرایه به اشاره‌گر (decay) را پرچم‌گذاری می‌کند. .sp اشاره‌گرها نباید به عنوان آرایه استفاده شوند. ساختار \fBspan\fP یک جایگزین امن و با بررسی محدوده (bounds\-checked) برای استفاده از اشاره‌گرها جهت دسترسی به آرایه‌ها است. .sp این قاعده بخشی از نمایهٔ ایمنی محدوده (Bounds 3) \% از C++ Core Guidelines است. .SS cppcoreguidelines\-pro\-bounds\-avoid\-unchecked\-container\-access .sp فراخوانی‌های \fBoperator[]\fP را در نگه‌دارنده‌های STL پیدا کرده و جایگزینی آن‌ها با گزینه‌های امن را پیشنهاد می‌کند. جایگزین‌های امن شامل توابع \fBat\fP از STL یا \fBat\fP از GSL، توابع \fBbegin()\fP یا \fBend()\fP، حلقه‌های \fBrange\-for\fP، \fBstd::span\fP، یا یک تابع مناسب از \fB\fP هستند. .sp برای مثال، هر دوی .INDENT 0.0 .INDENT 3.5 .sp .EX std::vector a; int b = a[4]; .EE .UNINDENT .UNINDENT .sp و .INDENT 0.0 .INDENT 3.5 .sp .EX std::unique_ptr a; int b = a[0]; .EE .UNINDENT .UNINDENT .sp یک هشدار ایجاد خواهند کرد. .sp نگه‌دارنده‌های STL که در آن‌ها \fBoperator[]\fP برای همهٔ ورودی‌ها خوش‌تعریف است، از این بررسی مستثنی هستند (مانند: \fBstd::map::operator[]\fP). .sp این بررسی بخشی از رهنمود SL.con.3 \% را اعمال می‌کند و بخشی از نمایهٔ ایمنی محدوده (Bounds 4) \% از C++ Core Guidelines است. .SS گزینه‌ها .INDENT 0.0 .TP .B ExcludeClasses فهرستی جداشده با نقطه\-ویرگول از عبارات باقاعده (regex) مطابق با نام کلاس‌ها که فهرست استثناهای پیش‌فرض را بازنویسی می‌کند. مقدار پیش‌فرض عبارت است از: \fI::std::map;::std::unordered_map;::std::flat_map\fP\&. .UNINDENT .INDENT 0.0 .TP .B FixMode مشخص می‌کند چه اصلاحاتی پیشنهاد شوند. یکی از مقادیر \fInone\fP، \fIat\fP (استفاده از \fBa.at(index)\fP در صورت وجود تابعی مناسب) یا \fIfunction\fP (استفاده از یک تابع \fBf(a, index)\fP). مقدار پیش‌فرض \fInone\fP است. .UNINDENT .INDENT 0.0 .TP .B FixFunction تابعی که باید در حالت \fIfunction\fP استفاده شود. برای C++23 و پس از آن، تابع ارائه‌شده باید از عملگر زیرنویس خالی پشتیبانی کند، یعنی حالتی که \fBa[]\fP تبدیل به \fBf(a)\fP می‌شود. از \fBFixFunctionEmptyArgs\fP می‌توان برای بازنویسی تابع پیشنهادی در آن حالت استفاده کرد. مقدار پیش‌فرض \fIgsl::at\fP است. .UNINDENT .INDENT 0.0 .TP .B FixFunctionEmptyArgs تابعی که باید در حالت \fIfunction\fP فقط برای عملگر زیرنویس خالی در C++23 و پس از آن استفاده شود. اگر نباید هیچ اصلاحی برای عملگرهای زیرنویس خالی انجام شود، یک رشتهٔ خالی ارسال کنید. در این حالت، تنها هشدارها چاپ خواهند شد. مقدار پیش‌فرض، مقدار \fBFixFunction\fP است. .UNINDENT .SS cppcoreguidelines\-pro\-bounds\-constant\-array\-index .sp این بررسی تمام عبارات زیرنویس آرایه روی آرایه‌های ایستا و \fBstd::array\fPها را که فاقد اندیس از نوع عبارت عدد صحیح ثابت هستند یا از محدوده خارج‌اند (برای \fBstd::array\fP) پرچم‌گذاری می‌کند. برای بررسی خروج از محدوده در آرایه‌های ایستا، به عیب‌یابی \fI\-Warray\-bounds\fP در Clang مراجعه کنید. .sp این قاعده بخشی از نمایهٔ ایمنی محدوده (Bounds 2) \% از C++ Core Guidelines است. .sp به صورت اختیاری، این بررسی می‌تواند اصلاحاتی را با استفاده از \fBgsl::at\fP برای اندیس‌گذاری تولید کند. .SS گزینه‌ها .INDENT 0.0 .TP .B GslHeader این بررسی می‌تواند پس از تنظیم این گزینه روی نام فایل include حاوی \fBgsl::at()\fP (مانند \fI\(dqgsl/gsl.h\(dq\fP)، اصلاحات را تولید کند. مقدار پیش‌فرض یک رشتهٔ خالی است. .UNINDENT .INDENT 0.0 .TP .B IncludeStyle رشته‌ای که سبک include مورد استفاده را مشخص می‌کند: \fIllvm\fP یا \fIgoogle\fP\&. مقدار پیش‌فرض \fIllvm\fP است. .UNINDENT .SS cppcoreguidelines\-pro\-bounds\-pointer\-arithmetic .sp این بررسی تمام موارد استفاده از محاسبات اشاره‌گر (pointer arithmetic) را پرچم‌گذاری می‌کند، زیرا می‌تواند منجر به اشاره‌گر نامعتبر شود. تفریق دو اشاره‌گر توسط این بررسی پرچم‌گذاری نمی‌شود. .sp اشاره‌گرها فقط باید به اشیاء منفرد ارجاع دهند، و محاسبات اشاره‌گر شکننده بوده و خطایابی آن دشوار است. \fBspan\fP یک نوع دادهٔ امن و دارای بررسی محدوده برای دسترسی به آرایه‌های داده است. .sp این قاعده بخشی از نمایهٔ ایمنی محدوده (Bounds 1) \% از C++ Core Guidelines است. .SS گزینه‌ها .INDENT 0.0 .TP .B AllowIncrementDecrementOperators در صورت فعال بودن، این بررسی استفاده از عملگرهای افزایش یا کاهش پیشوندی/پسوندی را روی اشاره‌گرها مجاز می‌داند. مقدار پیش‌فرض \fBfalse\fP است. .UNINDENT .SS cppcoreguidelines\-pro\-type\-const\-cast .sp محدودیت‌هایی را بر استفاده از \fBconst_cast\fP در کدهای C++ اعمال می‌کند. این بررسی به تنظیم گزینهٔ \fBStrictMode\fP \%<#\:cmdoption-arg-StrictMode> وابسته است تا مشخص کند که آیا باید همهٔ موارد استفاده از \fBconst_cast\fP را علامت‌گذاری کند یا فقط مواردی که توصیف‌کنندهٔ \fBconst\fP یا \fBvolatile\fP را حذف می‌کنند. .sp تغییر دادن متغیری که در C++ به‌صورت \fBconst\fP اعلان شده است عموماً رفتاری تعریف‌نشده (undefined behavior) محسوب می‌شود و این موضوع حتی هنگام استفاده از \fBconst_cast\fP نیز صادق است. در C++، توصیف‌کنندهٔ \fBconst\fP نشان می‌دهد که متغیر فقط‌خواندنی است و کامپایلر با جلوگیری از هرگونه تلاش برای تغییر مقدار آن متغیر، این قاعده را اعمال می‌کند. .sp حذف توصیف‌کنندهٔ \fBvolatile\fP در C++ می‌تواند پیامدهای جدی داشته باشد. این توصیف‌کننده نشان می‌دهد که مقدار یک متغیر می‌تواند به‌طور غیرقابل‌پیش‌بینی تغییر کند، و حذف آن ممکن است منجر به رفتار تعریف‌نشده، مشکلات بهینه‌سازی و چالش‌های اشکال‌زدایی شود. حفظ توصیف‌کنندهٔ \fBvolatile\fP در شرایطی که فرار بودن متغیر بخش حیاتی درستی و قابلیت اطمینان برنامه است، ضروری می‌باشد. .sp این قاعده بخشی از نمایهٔ Type safety (Type 3) \% و قاعدهٔ ES.50: Don’t cast away const \% از C++ Core Guidelines است. .SS گزینه‌ها .INDENT 0.0 .TP .B StrictMode هنگامی که این تنظیم روی \fItrue\fP باشد، به این معنی است که هیچ استفاده‌ای از \fBconst_cast\fP مجاز نیست. از سوی دیگر، وقتی روی \fIfalse\fP تنظیم شود، تبدیل نوع به انواع \fBconst\fP یا \fBvolatile\fP را مجاز می‌داند. مقدار پیش‌فرض \fIfalse\fP است. .UNINDENT .SS cppcoreguidelines\-pro\-type\-cstyle\-cast .sp این بررسی تمام استفاده‌ها از تبدیل‌های نوع به سبک C (C\-style casts) را که یک تبدیل به پایینِ (downcast) \fBstatic_cast\fP، یا \fBconst_cast\fP، یا \fBreinterpret_cast\fP انجام می‌دهند علامت‌گذاری می‌کند. .sp استفاده از این تبدیل‌ها می‌تواند ایمنی نوع (type safety) را نقض کرده و باعث شود برنامه به متغیری که در واقع از نوع X است، به‌گونه‌ای دسترسی پیدا کند که گویی از نوع نامرتبط Z است. توجه داشته باشید که یک تبدیل به سبک C به‌صورت \fB(T)expression\fP به معنای انجام اولین تبدیل ممکن از موارد زیر است: یک \fBconst_cast\fP، یک \fBstatic_cast\fP، یک \fBstatic_cast\fP که به دنبال آن یک \fBconst_cast\fP آمده باشد، یک \fBreinterpret_cast\fP، یا یک \fBreinterpret_cast\fP که به دنبال آن یک \fBconst_cast\fP آمده باشد. این قاعده \fB(T)expression\fP را تنها زمانی که برای انجام یک تبدیل ناامن استفاده شود منع می‌کند. .sp این قاعده بخشی از نمایهٔ Type safety (Type.4) \% از C++ Core Guidelines است. .SS cppcoreguidelines\-pro\-type\-member\-init .sp این بررسی تعاریف سازنده‌های ارائه‌شده توسط کاربر را که تمام فیلدهایی که با مقداردهی اولیهٔ پیش‌فرض در حالت تعریف‌نشده باقی می‌مانند (مانند انواع داخلی، اشاره‌گرها و انواع رکوردی فاقد سازندهٔ پیش‌فرض ارائه‌شده توسط کاربر که حداقل شامل یکی از این انواع هستند) مقداردهی نمی‌کنند، علامت‌گذاری می‌کند. اگر این فیلدها مقداردهی نشوند، سازنده بخشی از حافظه را در وضعیتی تعریف‌نشده باقی می‌گذارد. .sp برای C++11، این بررسی اصلاحاتی جهت افزودن مقداردهنده‌های درون‌کلاسی فیلدها پیشنهاد می‌دهد. برای نسخه‌های قدیمی‌تر، مقداردهنده‌های فیلد را در لیست مقداردهی اولیهٔ سازنده (initializer list) درج می‌کند. همچنین هر کلاس پایهٔ مستقیمی را که باید صفر شود در لیست مقداردهی اولیهٔ سازنده مقداردهی می‌کند. .sp این بررسی انتساب فیلدها درون بدنهٔ سازنده را در نظر می‌گیرد، اما برای فیلدهایی که درون متدهای فراخوانی‌شده در بدنهٔ سازنده مقداردهی می‌شوند، هشدارهای نادرست (false positive) تولید می‌کند. .sp این بررسی همچنین متغیرهای با طول عمر ذخیره‌سازی خودکار را که انواع رکوردی بدون سازندهٔ ارائه‌شده توسط کاربر دارند و مقداردهی اولیه نشده‌اند علامت‌گذاری می‌کند. اصلاح پیشنهادی، مقداردهی اولیه با صفر از طریق \fB{}\fP برای C++11 به بعد، یا \fB= {}\fP برای نسخه‌های قدیمی‌تر زبان است. .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoreArrays در صورت تنظیم روی \fItrue\fP، این بررسی دربارهٔ اعضای آرایه‌ای که در طول ساخت با صفر مقداردهی اولیه نشده‌اند هشداری نمی‌دهد. برای کدهایی که کارایی در آن‌ها حیاتی است، عدم مقداردهی اولیهٔ اعضای آرایه‌ای با اندازهٔ ثابت می‌تواند مهم باشد. مقدار پیش‌فرض \fIfalse\fP است. .UNINDENT .INDENT 0.0 .TP .B UseAssignment در صورت تنظیم روی \fItrue\fP، این بررسی اصلاحات را با مقداردهنده‌های لیتورال ( \fBint i = 0;\fP ) به جای آکولادها ( \fBint i{};\fP ) ارائه می‌دهد. مقدار پیش‌فرض \fIfalse\fP است. .UNINDENT .sp این قاعده بخشی از نمایهٔ Type safety (Type.6) \% از C++ Core Guidelines است. .SS cppcoreguidelines\-pro\-type\-reinterpret\-cast .sp این بررسی تمام موارد استفاده از \fBreinterpret_cast\fP را در کدهای C++ علامت‌گذاری می‌کند. .sp استفاده از این تبدیل‌ها می‌تواند ایمنی نوع را نقض کرده و باعث شود برنامه به متغیری که در واقع از نوع \fBX\fP است، به‌گونه‌ای دسترسی پیدا کند که گویی از نوع نامرتبط \fBZ\fP است. .sp این قاعده بخشی از نمایهٔ Type safety (Type.1.1) \% از C++ Core Guidelines است. .SS cppcoreguidelines\-pro\-type\-static\-cast\-downcast .sp این بررسی تمام موارد استفاده از \fBstatic_cast\fP را که در آن یک کلاس پایه به یک کلاس مشتق‌شده تبدیل می‌شود، علامت‌گذاری می‌کند. در این موارد، یک راهکار اصلاحی جهت تبدیل آن به \fBdynamic_cast\fP ارائه می‌شود. .sp استفاده از این تبدیل‌ها می‌تواند ایمنی نوع را نقض کرده و باعث شود برنامه به متغیری که در واقع از نوع \fBX\fP است، به‌گونه‌ای دسترسی پیدا کند که گویی از نوع نامرتبط \fBZ\fP است. .sp این قاعده بخشی از نمایهٔ Type safety (Type.2) \% از C++ Core Guidelines است. .SS گزینه‌ها .INDENT 0.0 .TP .B StrictMode هنگامی که روی \fIfalse\fP تنظیم شود، هیچ هشداری برای تبدیل‌های روی انواع غیرچندریختی (non\-polymorphic) صادر نمی‌شود. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .SS cppcoreguidelines\-pro\-type\-union\-access .sp این بررسی تمام دسترسی‌ها به اعضای unionها را علامت‌گذاری می‌کند. ارسال unionها به‌طور کلی و یکپارچه علامت‌گذاری نمی‌شود. .sp خواندن از یک عضو union فرض را بر این می‌گذارد که آن عضو آخرین عضوی بوده که در آن نوشته شده است، و نوشتن در یک عضو union فرض را بر این می‌گذارد که عضوی دیگر با یک مخرب غیربدیهی (nontrivial destructor)، مخربش فراخوانی شده است. این رفتار شکننده است زیرا عموماً نمی‌توان در زبان امنیت آن را تضمین کرد و بنابراین برای درست انجام شدن به انضباط برنامه‌نویس متکی است. .sp این قاعده بخشی از نمایهٔ Type safety (Type.7) \% از C++ Core Guidelines است. .SS cppcoreguidelines\-pro\-type\-vararg .sp این بررسی تمام فراخوانی‌های توابع با تعداد آرگومان متغیر به سبک C (vararg) و تمام استفاده‌ها از \fBva_arg\fP را علامت‌گذاری می‌کند. .sp جهت امکان‌پذیر ساختن استفاده از توابع vararg در SFINAE، اگر یک لیترال 0 به عنوان تنها آرگومان vararg ارسال شود یا تابع در یک بافت ارزیابی‌نشده (unevaluated context) استفاده شود، فراخوانی علامت‌گذاری نمی‌گردد. .sp ارسال به vararg فرض می‌کند که نوع صحیح خوانده خواهد شد. این رفتار شکننده است زیرا عموماً نمی‌توان در زبان ایمنی آن را تضمین کرد و بنابراین برای عملکرد صحیح به انضباط برنامه‌نویس متکی است. .sp این قاعده بخشی از نمایهٔ Type safety (Type.8) \% از C++ Core Guidelines است. .SS cppcoreguidelines\-rvalue\-reference\-param\-not\-moved .sp زمانی که یک پارامتر تابع از نوع ارجاع rvalue هرگز در بدنهٔ تابع منتقل (move) نشود، هشدار می‌دهد. .sp پارامترهای ارجاع rvalue نشان‌دهندهٔ پارامتری هستند که باید با \fBstd::move\fP از داخل بدنهٔ تابع منتقل شوند. هرگونه پارامتر از این دست که هرگز منتقل نشود، گمراه‌کننده بوده و می‌تواند نشان‌دهندهٔ خطای برنامه‌نویسی باشد. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void logic(std::string&& Input) { std::string Copy(Input); // Oops \- forgot to std::move } .EE .UNINDENT .UNINDENT .sp توجه داشته باشید پارامترهایی که استفاده نشده‌اند و به عنوان استفاده‌نشده علامت‌گذاری شده‌اند، مورد عیب‌یابی قرار نمی‌گیرند. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX void conditional_use([[maybe_unused]] std::string&& Input) { // No diagnostic here since Input is unused and marked as such } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B AllowPartialMove .INDENT 7.0 .INDENT 3.5 اگر بر روی \fItrue\fP تنظیم شود، بررسی فراخوانی‌های \fBstd::move\fP شامل هر زیرعبارتی که دربردارنده پارامتر باشد را می‌پذیرد. راهنمای CppCoreGuideline F.18 رسماً الزام می‌کند که خود پارامتر باید جابه‌جا (move) شود. پیش‌فرض \fIfalse\fP است. .UNINDENT .UNINDENT .INDENT 7.0 .INDENT 3.5 .sp .EX // \(aqp\(aq is flagged by this check if and only if AllowPartialMove is false void move_members_of(pair&& p) { pair other; other.first = std::move(p.first); other.second = std::move(p.second); } // \(aqp\(aq is never flagged by this check void move_whole_pair(pair&& p) { pair other = std::move(p); } .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B IgnoreUnnamedParams اگر بر روی \fItrue\fP تنظیم شود، این بررسی پارامترهای مرجع rvalue بی‌نام را نادیده می‌گیرد. پیش‌فرض \fIfalse\fP است. .UNINDENT .INDENT 0.0 .TP .B IgnoreNonDeducedTemplateTypes .INDENT 7.0 .INDENT 3.5 اگر بر روی \fItrue\fP تنظیم شود، این بررسی پارامترهای مرجع rvalue از نوع قالب استنتاج‌نشده (non-deduced) را نادیده می‌گیرد. پیش‌فرض \fIfalse\fP است. .UNINDENT .UNINDENT .INDENT 7.0 .INDENT 3.5 .sp .EX template struct SomeClass { // Below, \(aqT\(aq is not deduced and \(aqT&&\(aq is an rvalue reference type. // This will be flagged if and only if IgnoreNonDeducedTemplateTypes is // false. One suggested fix would be to specialize the class for \(aqT\(aq and // \(aqT&\(aq separately (e.g., see std::future), or allow only one of \(aqT\(aq or // \(aqT&\(aq instantiations of SomeClass (e.g., see std::optional). SomeClass(T&& t) { } }; // Never flagged, since \(aqT\(aq is a forwarding reference in a deduced context template void forwarding_ref(T&& t) { T other = std::forward(t); } .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B MoveFunction تابعی که برای انتقال (move) استفاده می‌شود را مشخص می‌کند. پیش‌فرض \fI::std::move\fP است. .UNINDENT .sp این بررسی قاعده F.18 را از C++ Core Guidelines پیاده‌سازی می‌کند: \% .SS cppcoreguidelines\-slicing .sp برش (slicing) متغیرهای عضو یا vtable را علامت‌گذاری می‌کند. برش زمانی رخ می‌دهد که یک شیء مشتق‌شده در یک شیء پایه کپی شود: اعضای شیء مشتق‌شده (هم متغیرهای عضو و هم توابع عضو مجازی) نادیده گرفته و دور ریخته می‌شوند. این موضوع به ویژه برای برش توابع عضو می‌تواند گمراه‌کننده باشد، به عنوان مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX struct B { int a; virtual int f(); }; struct D : B { int b; int f() override; }; void use(B b) { // Missing reference, intended? b.f(); // Calls B::f. } D d; use(d); // Slice. .EE .UNINDENT .UNINDENT .sp این بررسی قواعد ES.63 \% و C.145 \% را از C++ Core Guidelines پیاده‌سازی می‌کند. .SS cppcoreguidelines\-special\-member\-functions .sp این بررسی کلاس‌هایی را که در آن‌ها تعدادی از توابع عضو ویژه تعریف شده‌اند اما نه همه آن‌ها، پیدا می‌کند. .sp به طور پیش‌فرض، کامپایلر یک سازنده کپی، عملگر انتساب کپی، سازنده جابه‌جایی، عملگر انتساب جابه‌جایی و ویرانگر را تعریف می‌کند. این رفتار پیش‌فرض را می‌توان با تعاریف صریح کاربر لغو کرد. رابطه میان اینکه کدام توابع با تعریف توابع دیگر لغو می‌شوند پیچیده است و توصیه می‌شود که هر پنج مورد یا به صورت پیش‌فرض (\fBdefault\fP) قرار گیرند یا به صورت صریح تعریف شوند. .sp توجه داشته باشید که تعریف یک تابع با عبارت \fB= delete\fP به عنوان یک تعریف در نظر گرفته می‌شود. .sp این بررسی قاعده C.21 را از C++ Core Guidelines پیاده‌سازی می‌کند: \% .SS گزینه‌ها .INDENT 0.0 .TP .B AllowSoleDefaultDtor هنگامی که بر روی \fItrue\fP تنظیم شود (پیش‌فرض \fIfalse\fP است)، این بررسی تنها زمانی روی ویرانگرها فعال می‌شود که آن‌ها تعریف شده باشند و از نوع پیش‌فرض (\fBdefault\fP) نباشند. .INDENT 7.0 .INDENT 3.5 .sp .EX struct A { // This is fine. virtual ~A() = default; }; struct B { // This is not fine. ~B() {} }; struct C { // This is not checked, because the destructor might be defaulted in // another translation unit. ~C(); }; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B AllowMissingMoveFunctions هنگامی که بر روی \fItrue\fP تنظیم شود (پیش‌فرض \fIfalse\fP است)، این بررسی کلاس‌هایی را که هیچ عملیات جابه‌جایی در آن‌ها تعریف نشده علامت‌گذاری نمی‌کند. با این حال همچنان کلاس‌هایی را که فقط یکی از سازنده جابه‌جایی یا عملگر انتساب جابه‌جایی را تعریف کرده‌اند علامت‌گذاری می‌کند. با فعال بودن این گزینه، کلاس زیر علامت‌گذاری نخواهد شد: .INDENT 7.0 .INDENT 3.5 .sp .EX struct A { A(const A&); A& operator=(const A&); ~A(); }; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B AllowMissingMoveFunctionsWhenCopyIsDeleted هنگامی که بر روی \fItrue\fP تنظیم شود (پیش‌فرض \fIfalse\fP است)، این بررسی کلاس‌هایی را که عملیات کپی در آن‌ها حذف شده (\fBdelete\fP) ولی عملیات جابه‌جایی را تعریف نکرده‌اند علامت‌گذاری نمی‌کند. این پرچم مرتبط با راهنمای سبک کدنویسی سی‌پلاس‌پلاس گوگل بخش Copyable and Movable Types است \%\&. با فعال بودن این گزینه، کلاس زیر علامت‌گذاری نخواهد شد: .INDENT 7.0 .INDENT 3.5 .sp .EX struct A { A(const A&) = delete; A& operator=(const A&) = delete; ~A(); }; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B AllowImplicitlyDeletedCopyOrMove هنگامی که بر روی \fItrue\fP تنظیم شود (پیش‌فرض \fIfalse\fP است)، این بررسی کلاس‌هایی را که عملیات کپی یا جابه‌جایی در آن‌ها به طور ضمنی حذف شده‌اند علامت‌گذاری نمی‌کند. با فعال بودن این گزینه، کلاس زیر علامت‌گذاری نخواهد شد: .INDENT 7.0 .INDENT 3.5 .sp .EX struct A : boost::noncopyable { ~A() { std::cout << \(dqdtor\en\(dq; } }; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B IgnoreMacros اگر بر روی \fItrue\fP تنظیم شود، این بررسی هشداری برای کلاس‌های تعریف‌شده درون ماکروها صادر نمی‌کند. پیش‌فرض \fItrue\fP است. .UNINDENT .SS cppcoreguidelines\-use\-default\-member\-init .sp این بررسی، بند C.48 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .sp بررسی \fIcppcoreguidelines\-use\-default\-member\-init\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر modernize\-use\-default\-member\-init \%<> را ببینید. .SS cppcoreguidelines\-use\-enum\-class .sp اعلان‌های \fBenum\fP با محدوده سراسری (غیر کلاسی یا unscoped) را پیدا کرده و پیشنهاد می‌دهد به جای آن از \fBenum class\fP استفاده شود. .sp این بررسی، بند Enum.3 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX enum E {}; // use \(dqenum class E {};\(dq instead enum class E {}; // OK struct S { enum E {}; // use \(dqenum class E {};\(dq instead // OK with option IgnoreUnscopedEnumsInClasses }; namespace N { enum E {}; // use \(dqenum class E {};\(dq instead } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoreUnscopedEnumsInClasses در صورت فعال بودن (\fItrue\fP)، اعلان‌های \fBenum\fP فاقد محدوده را در کلاس‌ها نادیده می‌گیرد. پیش‌فرض \fIfalse\fP است. .UNINDENT .SS cppcoreguidelines\-virtual\-class\-destructor .sp کلاس‌های مجاز را که مخرب آن‌ها نه عمومی و مجازی (\(lqpublic and virtual\(rq) است و نه حفاظت‌شده و غیرمجازی (\(lqprotected and non\-virtual\(rq)، پیدا می‌کند. مخرب یک کلاس مجازی باید به یکی از این دو روش تعریف شود تا از رفتار تعریف‌نشده (undefined behavior) جلوگیری شود. .sp این بررسی، بند C.35 \% از C++ Core Guidelines را پیاده‌سازی می‌کند. .sp توجه داشته باشید که این بررسی، کلاسی را که متد مجازی دارد، بدون در نظر گرفتن اینکه به عنوان کلاس پایه استفاده شده است یا نه، عیب‌یابی می‌کند. .sp اصلاحات خودکار برای مخرب‌های اعلان‌شده توسط کاربر یا ضمنی که عمومی و غیرمجازی، یا حفاظت‌شده و مجازی هستند، در دسترس است. هیچ اصلاحی برای مخرب‌های خصوصی (private) ارائه نمی‌شود؛ چرا که تصمیم‌گیری درباره خصوصی و مجازی بودن آن‌ها، یا حفاظت‌شده و غیرمجازی بودنشان، به کاربرد مد نظر وابسته است و بنابراین به کاربر واگذار شده است. .SS مثال .sp برای مثال، کلاس‌ها/ساختارهای زیر توسط این بررسی پرچم‌گذاری می‌شوند، زیرا دستورالعمل \fBC.35\fP را نقض می‌کنند: .INDENT 0.0 .INDENT 3.5 .sp .EX struct Foo { // NOK, protected destructor should not be virtual virtual void f(); protected: virtual ~Foo(){} }; class Bar { // NOK, public destructor should be virtual virtual void f(); public: ~Bar(){} }; .EE .UNINDENT .UNINDENT .sp این کد می‌تواند به شکل زیر بازنویسی شود: .INDENT 0.0 .INDENT 3.5 .sp .EX struct Foo { // OK, destructor is not virtual anymore virtual void f(); protected: ~Foo(){} }; class Bar { // OK, destructor is now virtual virtual void f(); public: virtual ~Bar(){} }; .EE .UNINDENT .UNINDENT .SS darwin\-avoid\-spinlock .sp موارد استفاده از \fBOSSpinlock\fP را پیدا می‌کند؛ این ساختار به دلیل مشکلات بالقوه قفل فعال (livelock) منسوخ شده است. .sp این بررسی، فراخوانی‌های توابع زیر را شناسایی می‌کند: .INDENT 0.0 .IP \(bu 2 \fBOSSpinlockLock\fP .IP \(bu 2 \fBOSSpinlockTry\fP .IP \(bu 2 \fBOSSpinlockUnlock\fP .UNINDENT .sp اطلاعات مرتبط در مورد مشکل \fBOSSpinlock\fP: \% .SS darwin\-dispatch\-once\-nonstatic .sp اعلان‌های متغیرهای \fBdispatch_once_t\fP را که فاقد فضای ذخیره‌سازی ایستا (static) یا سراسری هستند، پیدا می‌کند. رفتار استفاده از گزاره‌های \fBdispatch_once_t\fP با حافظه خودکار (automatic) یا پویا، توسط libdispatch تعریف‌نشده است و باید از آن اجتناب شود. .sp یک الگوی رایج این است که توابع، داده‌های ایستای داخلی یا سراسری را یک‌بار در هنگام اجرای تابع مقداردهی اولیه کنند؛ اما دیده شده است که برنامه‌نویسان واژه static را برای گزاره \fBdispatch_once_t\fP فراموش می‌کنند، که این امر منجر به مقدار پرچم مقداردهی‌نشده در پشته (stack) می‌شود. .sp همچنین برنامه‌نویسان متغیرهای \fBdispatch_once_t\fP را به عنوان اعضای ساختارها یا کلاس‌ها تعریف کرده‌اند، با این هدف که مقداردهی اولیه پرهزینه عضو کلاس را به صورت تنبل (lazy) تنها یک‌بار انجام دهند؛ با این حال، این کار پیش‌نیازهای libdispatch را نقض می‌کند. .sp برای اطلاعات بیشتر، بخش بحث در مستندات dispatch_once شرکت اپل \% را ببینید. .SS fuchsia\-default\-arguments\-calls .sp در صورتی که یک تابع یا متد با آرگومان‌های پیش‌فرض فراخوانی شود، هشدار می‌دهد. .sp به عنوان مثال، با فرض وجود این اعلان: .INDENT 0.0 .INDENT 3.5 .sp .EX int foo(int value = 5) { return value; } .EE .UNINDENT .UNINDENT .sp یک عبارت فراخوانی تابع که از یک آرگومان پیش‌فرض استفاده می‌کند، عیب‌یابی خواهد شد. فراخوانی آن بدون مقادیر پیش‌فرض هشداری ایجاد نمی‌کند: .INDENT 0.0 .INDENT 3.5 .sp .EX foo(); // warning foo(0); // no warning .EE .UNINDENT .UNINDENT .sp ویژگی‌های غیرمجاز در Fuchsia را در \% مشاهده کنید. .SS fuchsia\-default\-arguments\-declarations .sp اگر یک تابع یا متد با پارامترهای پیش‌فرض اعلان شده باشد، هشدار می‌دهد. .sp برای نمونه، اعلان زیر: .INDENT 0.0 .INDENT 3.5 .sp .EX int foo(int value = 5) { return value; } .EE .UNINDENT .UNINDENT .sp باعث ایجاد یک هشدار خواهد شد. .sp ویژگی‌های غیرمجاز در Fuchsia را در این نشانی ببینید: \% .SS fuchsia\-header\-anon\-namespaces .sp بررسی \fIfuchsia\-header\-anon\-namespaces\fP یک نام مستعار (alias) است؛ لطفاً برای اطلاعات بیشتر به misc\-anonymous\-namespace\-in\-header \%<> مراجعه کنید. .SS fuchsia\-multiple\-inheritance .sp بررسی \fIfuchsia\-multiple\-inheritance\fP یک نام مستعار است؛ لطفاً برای جزئیات به misc\-multiple\-inheritance \%<> مراجعه کنید. .sp ویژگی‌های غیرمجاز در Fuchsia را در این نشانی ببینید: \% .SS fuchsia\-overloaded\-operator .sp اگر یک عملگر سرریزشده (overload شده) باشد، به‌جز عملگرهای انتساب (کپی و جابه‌جایی)، هشدار می‌دهد. .sp برای نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX int operator+(int); // Warning B &operator=(const B &Other); // No warning B &operator=(B &&Other) // No warning .EE .UNINDENT .UNINDENT .sp ویژگی‌های غیرمجاز در Fuchsia را در این نشانی ببینید: \% .SS fuchsia\-statically\-constructed\-objects .sp اگر اشیاء سراسری و غیرساده (non-trivial) با فضای ذخیره‌سازی ایستا (static storage) ساخته شوند، هشدار می‌دهد، مگر اینکه شیء به‌طور ایستا با یک سازندهٔ \fBconstexpr\fP مقداردهی اولیه شود یا هیچ سازندهٔ صریحی نداشته باشد. .sp برای نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX class A {}; class B { public: B(int Val) : Val(Val) {} private: int Val; }; class C { public: constexpr C(int Val) : Val(Val) {} C(int Val1, int Val2) : Val(Val1+Val2) {} private: int Val; }; static A a; // No warning, as there is no explicit constructor static C c(0); // No warning, as constructor is constexpr static B b(0); // Warning, as constructor is not constexpr static C c2(0, 1); // Warning, as constructor is not constexpr static int i; // No warning, as it is trivial extern int get_i(); static C c3(get_i());// Warning, as the constructor is dynamically initialized .EE .UNINDENT .UNINDENT .sp ویژگی‌های غیرمجاز در Fuchsia را در این نشانی ببینید: \% .SS fuchsia\-temporary\-objects .sp هنگام ساخت اشیاء موقت مشخصی در هستهٔ Zircon هشدار می‌دهد. اگر شیء باید نشانه‌گذاری شود، نام نوع به‌طور کامل واجد شرایط (fully qualified) باید به‌طور صریح به این بررسی ارسال شود. .sp برای نمونه، با فرض فهرست کلاس‌های \(dqFoo\(dq و \(dqNS::Bar\(dq، تمامی موارد زیر باعث ایجاد هشدار می‌شوند: .INDENT 0.0 .INDENT 3.5 .sp .EX Foo(); Foo F = Foo(); func(Foo()); namespace NS { Bar(); } .EE .UNINDENT .UNINDENT .sp با همان فهرست، موارد زیر هشداری ایجاد نخواهند کرد: .INDENT 0.0 .INDENT 3.5 .sp .EX Foo F; // Non\-temporary construction okay Foo F(param); // Non\-temporary construction okay Foo *F = new Foo(); // New construction okay Bar(); // Not NS::Bar, so okay NS::Bar B; // Non\-temporary construction okay .EE .UNINDENT .UNINDENT .sp توجه داشته باشید که اشیاء برای نشانه‌گذاری شدن باید صریحاً مشخص شوند، بنابراین اشیایی که از یک شیء مشخص‌شده ارث‌بری می‌کنند نشانه‌گذاری نخواهند شد. .sp این بررسی اشیاء موقت را بدون در نظر گرفتن ارث‌بری تطبیق می‌دهد و بنابراین یک نوع کلاس پایهٔ ممنوع‌شده، به شکل مشابه انواع کلاس‌های مشتق‌شده را ممنوع نمی‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX class Derived : Foo {} // Derived is not explicitly disallowed Derived(); // and so temporary construction is okay .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B Names فهرستی جداشده با نقطه ویرگول (semi-colon) از نام‌های کاملاً واجد شرایط کلاس‌های C++ که نباید به‌صورت اشیاء موقت ساخته شوند. پیش‌فرض یک رشتهٔ خالی است. .UNINDENT .SS fuchsia\-trailing\-return .sp استفاده از توابعی که دارای نوع بازگشتی پس‌رو (trailing return) هستند مجاز نیست، به جز مواردی که از مشخص‌کننده‌های \fBdecltype\fP و توابع لامبدا با نوع بازگشتی غیرقابل بیان استفاده می‌کنند. .sp برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX // بدون هشدار int add_one(const int arg) { return arg; } // هشدار auto get_add_one() \-> int (*)(const int) { return add_one; } .EE .UNINDENT .UNINDENT .sp برای توابع لامبدا و مشخص‌کننده‌های \fBdecltype\fP استثنا قائل شده است: .INDENT 0.0 .INDENT 3.5 .sp .EX // بدون هشدار auto lambda = [](double x, double y) \-> double {return x + y;}; // بدون هشدار template auto fn(const T1 &lhs, const T2 &rhs) \-> decltype(lhs + rhs) { return lhs + rhs; } .EE .UNINDENT .UNINDENT .sp ویژگی‌های غیرمجاز در Fuchsia را در این نشانی ببینید: \% .SS fuchsia\-virtual\-inheritance .sp در صورتی که کلاس‌ها با توارث مجازی (virtual inheritance) تعریف شده باشند، هشدار می‌دهد. .sp برای مثال، کلاس‌ها نباید با توارث مجازی تعریف شوند: .INDENT 0.0 .INDENT 3.5 .sp .EX class B : public virtual A {}; // هشدار .EE .UNINDENT .UNINDENT .sp ویژگی‌های غیرمجاز در Fuchsia را در این نشانی ببینید: \% .SS google\-build\-explicit\-make\-pair .sp بررسی می‌کند که آرگومان‌های الگوی \fBmake_pair\fP استنتاج (deduce) شوند. .sp کامپایلر G++ 4.6 در حالت C++11 در صورتی که آرگومان‌های الگوی \fBmake_pair\fP به طور صریح مشخص شده باشند دچار خطای شدید می‌شود، و به هر حال چنین استفاده‌ای مد نظر نبوده است. .sp نام بررسی متناظر در cpplint.py عبارت است از: \fIbuild/explicit_make_pair\fP\&. .SS google\-build\-namespaces .sp بررسی \fIgoogle\-build\-namespaces\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر misc\-anonymous\-namespace\-in\-header \%<> را ببینید. .sp فضاهای نام ناشناس (anonymous namespaces) را در هدرها پیدا می‌کند. .sp \% .sp نام بررسی متناظر در cpplint.py عبارت است از: \fIbuild/namespaces\fP\&. .SS google\-build\-using\-namespace .sp دستورهای \fBusing namespace\fP را پیدا می‌کند. .sp این بررسی قاعده زیر را از راهنمای سبک کدنویسی Google C++ اعمال می‌کند \%: .INDENT 0.0 .INDENT 3.5 شما مجاز نیستید از یک using\-directive برای در دسترس قرار دادن تمام نام‌های یک فضای نام استفاده کنید. .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX // ممنوع \-\- این کار فضای نام را آلوده می‌کند. using namespace foo; .EE .UNINDENT .UNINDENT .sp نام بررسی متناظر در cpplint.py عبارت است از: \fIbuild/namespaces\fP\&. .SS google\-default\-arguments .sp بررسی می‌کند که برای متدهای مجازی (virtual methods) آرگومان‌های پیش‌فرض مشخص نشده باشد. .sp ببینید: \% .SS google\-explicit\-constructor .sp بررسی می‌کند که سازنده‌های قابل فراخوانی با یک آرگومان واحد و عملگرهای تبدیل نوع، با \fBexplicit\fP علامت‌گذاری شوند تا از ریسک تبدیل‌های ضمنی ناخواسته جلوگیری شود. .sp این مثال را در نظر بگیرید: .INDENT 0.0 .INDENT 3.5 .sp .EX struct S { int x; operator bool() const { return true; } }; bool f() { S a{1}; S b{2}; return a == b; } .EE .UNINDENT .UNINDENT .sp این تابع مقدار \fBtrue\fP را برمی‌گرداند، زیرا اشیاء قبل از مقایسه به طور ضمنی به \fBbool\fP تبدیل می‌شوند که احتمالاً این هدف مورد نظر نبوده است. .sp این بررسی پیشنهاد درج \fBexplicit\fP را پیش از اعلان سازنده یا عملگر تبدیل نوع ارائه می‌دهد. با این حال، سازنده‌های کپی و انتقال، و همچنین سازنده‌هایی که یک آرگومان \fBinitializer_list\fP واحد می‌گیرند، نباید explicit باشند. .sp این کد: .INDENT 0.0 .INDENT 3.5 .sp .EX struct S { S(int a); explicit S(const S&); operator bool() const; ... .EE .UNINDENT .UNINDENT .sp تبدیل خواهد شد به: .INDENT 0.0 .INDENT 3.5 .sp .EX struct S { explicit S(int a); S(const S&); explicit operator bool() const; ... .EE .UNINDENT .UNINDENT .sp ببینید: \% .SS google\-global\-names\-in\-headers .sp آلودگی فضای نام سراسری (global namespace pollution) در فایل‌های هدر را مشخص می‌کند. در حال حاضر این بررسی فقط روی اعلان‌ها و دستورهای \fBusing\fP فعال می‌شود. .sp بخش راهنمای شیوه‌نامه مرتبط عبارت است از: \%\&. .SS google\-objc\-avoid\-nsobject\-new .sp فراخوانی‌های متد \fB+new\fP یا بازنویسی (override) آن را که بر اساس شیوه‌نامه Objective\-C گوگل ممنوع شده‌اند، پیدا می‌کند. .sp شیوه‌نامه Objective\-C گوگل فراخوانی \fB+new\fP یا بازنویسی آن در پیاده‌سازی کلاس‌ها را ممنوع کرده و استفاده از متدهای \fB+alloc\fP و \fB\-init\fP را برای نمونه‌سازی اشیاء ترجیح می‌دهد. .sp یک مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX NSDate *now = [NSDate new]; Foo *bar = [Foo new]; .EE .UNINDENT .UNINDENT .sp در عوض، کد باید از متدهای \fB+alloc\fP/\fB\-init\fP یا متدهای کارخانه کلاس (class factory methods) استفاده کند. .INDENT 0.0 .INDENT 3.5 .sp .EX NSDate *now = [NSDate date]; Foo *bar = [[Foo alloc] init]; .EE .UNINDENT .UNINDENT .sp این بررسی مطابق با قاعده Do Not Use +new در شیوه‌نامه Objective\-C گوگل است \%\&. .SS google\-objc\-avoid\-throwing\-exception .sp موارد پرتاب استثناها (throwing exceptions) در فایل‌های Objective\-C را می‌یابد. .sp به همان دلیلی که در راهنمای سبک C++ گوگل آمده است، ترجیح داده می‌شود از پرتاب استثناها در کد Objective\-C خودداری شود. .sp قاعده متناظر در شیوه‌نامه C++: \% .sp در عوض، بهتر است \fBNSError **\fP ارسال شده و برای مشخص کردن موفقیت یا شکست، \fBBOOL\fP بازگردانده شود. .sp یک مثال نقض: .INDENT 0.0 .INDENT 3.5 .sp .EX \- (void)readFile { if ([self isError]) { @throw [NSException exceptionWithName:...]; } } .EE .UNINDENT .UNINDENT .sp به جای آن، بازگرداندن خطا از طریق \fBNSError **\fP ارجحیت دارد: .INDENT 0.0 .INDENT 3.5 .sp .EX \- (BOOL)readFileWithError:(NSError **)error { if ([self isError]) { *error = [NSError errorWithDomain:...]; return NO; } return YES; } .EE .UNINDENT .UNINDENT .sp قاعده متناظر در شیوه‌نامه: \% .SS google\-objc\-function\-naming .sp اعلان‌های توابع در فایل‌های Objective\-C را که از الگوی توصیف‌شده در راهنمای سبک Objective\-C گوگل پیروی نمی‌کنند، می‌یابد. .sp قاعده مربوطه در شیوه‌نامه را می‌توانید در اینجا بیابید: \% .sp تمام نام‌های توابع باید به صورت Pascal case باشند. توابعی که رده ذخیره‌سازی (storage class) آن‌ها static نیست باید یک پیشوند مناسب داشته باشند. .sp نمونه کد زیر از این الگو پیروی نمی‌کند: .INDENT 0.0 .INDENT 3.5 .sp .EX static bool is_positive(int i) { return i > 0; } bool IsNegative(int i) { return i < 0; } .EE .UNINDENT .UNINDENT .sp نمونه بالا ممکن است به صورت کد زیر تصحیح شود: .INDENT 0.0 .INDENT 3.5 .sp .EX static bool IsPositive(int i) { return i > 0; } bool *ABCIsNegative(int i) { return i < 0; } .EE .UNINDENT .UNINDENT .SS google\-objc\-global\-variable\-declaration .sp اعلان‌های متغیرهای سراسری در فایل‌های Objective\-C را که از الگوی نام‌گذاری متغیرها در شیوه‌نامه Objective\-C گوگل پیروی نمی‌کنند، می‌یابد. .sp قاعده متناظر در شیوه‌نامه: \% .sp تمام متغیرهای سراسری باید از الگوی \fBg[A\-Z].*\fP (متغیرها) یا \fBk[A\-Z].*\fP (ثابت‌ها) پیروی کنند. اگر نام متغیر از نام اولیه قابل استنباط باشد، این بررسی نامی مطابق با این الگو را پیشنهاد خواهد داد. .sp برای کد: .INDENT 0.0 .INDENT 3.5 .sp .EX static NSString* myString = @\(dqhello\(dq; .EE .UNINDENT .UNINDENT .sp اصلاح به شکل زیر خواهد بود: .INDENT 0.0 .INDENT 3.5 .sp .EX static NSString* gMyString = @\(dqhello\(dq; .EE .UNINDENT .UNINDENT .sp مثال دیگری برای متغیر ثابت: .INDENT 0.0 .INDENT 3.5 .sp .EX static NSString* const myConstString = @\(dqhello\(dq; .EE .UNINDENT .UNINDENT .sp اصلاح به شکل زیر خواهد بود: .INDENT 0.0 .INDENT 3.5 .sp .EX static NSString* const kMyConstString = @\(dqhello\(dq; .EE .UNINDENT .UNINDENT .sp اما برای کدهایی با پیشوند کاراکترهای غیرالفبایی مانند: .INDENT 0.0 .INDENT 3.5 .sp .EX static NSString* __anotherString = @\(dqworld\(dq; .EE .UNINDENT .UNINDENT .sp این بررسی یک پیام هشدار صادر می‌کند اما قادر به پیشنهاد اصلاح خودکار نخواهد بود. کاربر باید خودش آن را تصحیح کند. .SS google\-readability\-avoid\-underscore\-in\-googletest\-name .sp وجود خط زیر (underscore) را در نام‌های مجموعه آزمون (test suite) و نام‌های آزمون گوگل‌تست (googletest) در ماکروهای آزمون زیر بررسی می‌کند: .INDENT 0.0 .IP \(bu 2 \fBTEST\fP .IP \(bu 2 \fBTEST_F\fP .IP \(bu 2 \fBTEST_P\fP .IP \(bu 2 \fBTYPED_TEST\fP .IP \(bu 2 \fBTYPED_TEST_P\fP .UNINDENT .sp ماکروی \fBFRIEND_TEST\fP شامل این بررسی نمی‌شود. .sp برای نمونه: .INDENT 0.0 .INDENT 3.5 .sp .EX TEST(TestSuiteName, Illegal_TestName) {} TEST(Illegal_TestSuiteName, TestName) {} .EE .UNINDENT .UNINDENT .sp باعث اجرای این بررسی می‌شود. استفاده از خط زیر \% نه در نام مجموعه آزمون و نه در نام‌های آزمون مجاز نیست. .sp پیشوند \fBDISABLED_\fP، که ممکن است برای غیرفعال‌سازی مجموعه‌های آزمون و آزمون‌های تکی \% به کار رود، پیش از بررسی وجود خط زیر، از نام مجموعه آزمون و نام آزمون حذف می‌شود. .sp این بررسی هیچ اصلاحاتی (fix) پیشنهاد نمی‌دهد. .SS google\-readability\-braces\-around\-statements .sp بررسی \fIgoogle\-readability\-braces\-around\-statements\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر readability\-braces\-around\-statements \%<> را ببینید. .SS google\-readability\-casting .sp بررسی \fIgoogle\-readability\-casting\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر modernize\-avoid\-c\-style\-cast \%<> را ببینید. .sp موارد استفاده از تبدیل نوع‌های سبک C (C\-style casts) را پیدا می‌کند. .sp \% .sp نام بررسی متناظر در cpplint.py عبارت است از: \fIreadability/casting\fP\&. .SS google\-readability\-function\-size .sp بررسی \fIgoogle\-readability\-function\-size\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر readability\-function\-size \%<> را ببینید. .SS google\-readability\-namespace\-comments .sp بررسی \fIgoogle\-readability\-namespace\-comments\fP یک نام مستعار است؛ لطفاً برای اطلاعات بیشتر llvm\-namespace\-comment \%<> را ببینید. .SS google\-readability\-todo .sp کامنت‌های TODO فاقد نام کاربری یا شماره باگ را پیدا می‌کند. .sp بخش مرتبط در راهنمای سبک کدنویسی: \%\&. .sp بررسی متناظر در cpplint.py عبارت است از: \fIreadability/todo\fP .SS گزینه‌ها .INDENT 0.0 .TP .B Style رشته‌ای که سبک TODO را برای راهنمایی‌های اصلاح خودکار (fix\-it hints) مشخص می‌کند. مقادیر پذیرفته‌شده عبارتند از \fIHyphen\fP و \fIParentheses\fP\&. مقدار پیش‌فرض \fIHyphen\fP است. .INDENT 7.0 .IP \(bu 2 گزینه \fIHyphen\fP اصلاح را به این صورت قالب‌بندی می‌کند: \fB// TODO: username \- details\fP\&. .IP \(bu 2 گزینه \fIParentheses\fP اصلاح را به این صورت قالب‌بندی می‌کند: \fB// TODO(username): details\fP\&. .UNINDENT .UNINDENT .SS google\-runtime\-float .sp موارد استفاده از \fBlong double\fP را پیدا کرده و به دلیل عدم قابلیت حمل (portability)، عدم استفاده از آن را پیشنهاد می‌کند. .sp قاعده متناظر در راهنمای سبک کدنویسی: \% .SS google\-runtime\-int .sp موارد استفاده از \fBshort\fP، \fBlong\fP و \fBlong long\fP را پیدا کرده و جایگزینی آن‌ها با \fBu?intXX(_t)?\fP را پیشنهاد می‌دهد. .sp قاعده متناظر در راهنمای سبک کدنویسی: \%\&. .sp بررسی متناظر در cpplint.py عبارت است از: \fIruntime/int\fP\&. .SS گزینه‌ها .INDENT 0.0 .TP .B UnsignedTypePrefix رشته‌ای که پیشوند انواع بدون علامت (unsigned) را مشخص می‌کند. مقدار پیش‌فرض \fIuint\fP است. .UNINDENT .INDENT 0.0 .TP .B SignedTypePrefix رشته‌ای که پیشوند انواع علامت‌دار (signed) را مشخص می‌کند. مقدار پیش‌فرض \fIint\fP است. .UNINDENT .INDENT 0.0 .TP .B TypeSuffix رشته‌ای که پسوند نوع را مشخص می‌کند. مقدار پیش‌فرض یک رشته خالی است. .UNINDENT .SS google\-runtime\-operator .sp سربارگذاری‌های عملگر یکانی \fBoperator &\fP را پیدا می‌کند. .sp \% .sp نام بررسی متناظر در cpplint.py عبارت است از: \fIruntime/operator\fP\&. .SS google\-upgrade\-googletest\-case .sp موارد استفاده از APIهای منسوخ‌شده نگارش 1.9 Google Test که نام آن‌ها شامل \fBcase\fP است را پیدا کرده و آن‌ها را با APIهای معادل حاوی \fBsuite\fP جایگزین می‌کند. .sp تمام نام‌های حاوی \fBcase\fP در حال جایگزینی هستند تا با معانی \(dqtest case\(dq و \(dqtest suite\(dq مورد استفاده توسط هیئت بین‌المللی ارزیابی صلاحیت تست نرم‌افزار (ISTQB) و استاندارد ISO 29119 مطابقت داشته باشند. .sp نام‌های جدید بخشی از Google Test نگارش 1.9 (در انتظار انتشار) هستند. توصیه می‌شود کاربران وابستگی پروژه خود را به نگارش 1.9 به‌روزرسانی کنند و سپس از این بررسی برای حذف نام‌های منسوخ‌شده بهره ببرند. .sp APIهای تحت تأثیر عبارتند از: .INDENT 0.0 .IP \(bu 2 توابع عضو \fBtesting::Test\fP، \fBtesting::TestInfo\fP، \fBtesting::TestEventListener\fP، \fBtesting::UnitTest\fP و هر نوعی که از این نوع‌ها ارث‌بری می‌کند .IP \(bu 2 ماکروهای \fBTYPED_TEST_CASE\fP، \fBTYPED_TEST_CASE_P\fP، \fBREGISTER_TYPED_TEST_CASE_P\fP و \fBINSTANTIATE_TYPED_TEST_CASE_P\fP .IP \(bu 2 نام مستعار نوع \fBtesting::TestCase\fP .UNINDENT .sp نمونه‌هایی از اصلاحات انجام‌شده توسط این بررسی: .INDENT 0.0 .INDENT 3.5 .sp .EX class FooTest : public testing::Test { public: static void SetUpTestCase(); static void TearDownTestCase(); }; TYPED_TEST_CASE(BarTest, BarTypes); .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX class FooTest : public testing::Test { public: static void SetUpTestSuite(); static void TearDownTestSuite(); }; TYPED_TEST_SUITE(BarTest, BarTypes); .EE .UNINDENT .UNINDENT .sp برای یکپارچگی بهتر کدهای کاربر، این بررسی هم توابع عضو مجازی و هم غیرمجازی با نام‌های منطبق را در انواع مشتق‌شده تغییر نام می‌دهد. این بررسی در مواردی که امکان اصلاح با اطمینان کامل وجود ندارد، مانند برخی کاربردهای الگوها (template) و ماکروها، تلاش می‌کند تنها یک هشدار نمایش دهد. .SS hicpp\-avoid\-c\-arrays .sp بررسی hicpp\-avoid\-c\-arrays یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به modernize\-avoid\-c\-arrays \%<> مراجعه کنید. این بررسی بخشی از قاعدهٔ 4.1.1 \% را اعمال می‌کند. .SS hicpp\-avoid\-goto .sp بررسی \fIhicpp\-avoid\-goto\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به cppcoreguidelines\-avoid\-goto \%<> مراجعه کنید. این بررسی قاعدهٔ 6.3.1 \% را اعمال می‌کند. .SS hicpp\-braces\-around\-statements .sp بررسی \fIhicpp\-braces\-around\-statements\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به readability\-braces\-around\-statements \%<> مراجعه کنید. این بررسی قاعدهٔ 6.1.1 \% را اعمال می‌کند. .SS hicpp\-deprecated\-headers .sp بررسی \fIhicpp\-deprecated\-headers\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به modernize\-deprecated\-headers \%<> مراجعه کنید. این بررسی قاعدهٔ 1.3.3 \% را اعمال می‌کند. .SS hicpp\-exception\-baseclass .sp اطمینان حاصل می‌کند که هر مقداری در یک عبارت \fBthrow\fP نمونه‌ای از \fBstd::exception\fP باشد. .sp این بررسی قاعدهٔ 15.1 \% از استانداردهای کدنویسی High Integrity C++ را اعمال می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX class custom_exception {}; void throwing() noexcept(false) { // Problematic throw expressions. throw int(42); throw custom_exception(); } class mathematical_error : public std::exception {}; void throwing2() noexcept(false) { // These kind of throws are ok. throw mathematical_error(); throw std::runtime_error(); throw std::exception(); } .EE .UNINDENT .UNINDENT .SS hicpp\-explicit\-conversions .sp این بررسی یک نام مستعار برای google\-explicit\-constructor \%<>\& است. .sp برای اعمال بخش‌هایی از قاعدهٔ 5.4.1 \% به کار می‌رود. این بررسی الزام می‌کند که سازنده‌ها و عملگرهای تبدیل با \fBexplicit\fP علامت‌گذاری شوند. سایر اشکال بررسی‌های تبدیل نوع (casting) در بخش‌های دیگر پیاده‌سازی شده‌اند. برای بررسی اشکال بیشتر تبدیل نوع می‌توان از بررسی‌های زیر استفاده کرد: .INDENT 0.0 .IP \(bu 2 cppcoreguidelines\-pro\-type\-static\-cast\-downcast \%<> .IP \(bu 2 cppcoreguidelines\-pro\-type\-reinterpret\-cast \%<> .IP \(bu 2 cppcoreguidelines\-pro\-type\-const\-cast \%<> .IP \(bu 2 cppcoreguidelines\-pro\-type\-cstyle\-cast \%<> .UNINDENT .SS hicpp\-function\-size .sp این بررسی یک نام مستعار برای readability\-function\-size \%<>\& است. برای اعمال چندین بخش مربوط به پیچیدگی توابع مفید است. .INDENT 0.0 .IP \(bu 2 قاعدهٔ 8.2.2 \% .IP \(bu 2 قاعدهٔ 8.3.1 \% .IP \(bu 2 قاعدهٔ 8.3.2 \% .UNINDENT .SS hicpp\-ignored\-remove\-result .sp مطابق با قاعدهٔ 17.5.1 \% اطمینان حاصل می‌کند که نتیجهٔ \fBstd::remove\fP، \fBstd::remove_if\fP و \fBstd::unique\fP نادیده گرفته نشود. .sp الگوریتم‌های تغییردهندهٔ \fBstd::remove\fP، \fBstd::remove_if\fP و هر دو نسخهٔ سربارگذاری‌شدهٔ \fBstd::unique\fP با جابه‌جا کردن (swap یا move) عناصر بازه‌ای که روی آن عمل می‌کنند، کار می‌کنند. پس از اتمام، آن‌ها یک تکرارکننده (iterator) به آخرین عنصر معتبر برمی‌گردانند. در بیشتر موارد، رفتار صحیح این است که از این نتیجه به عنوان عملوند اول در فراخوانی \fBstd::erase\fP استفاده شود. .sp این بررسی زیرمجموعه‌ای از bugprone\-unused\-return\-value \%<> است و بسته به گزینه‌های استفاده‌شده، فعال کردن هر دو بررسی می‌تواند زاید باشد. .SS گزینه‌ها .INDENT 0.0 .TP .B AllowCastToVoid کنترل می‌کند که آیا تبدیل مقادیر بازگشتی به \fBvoid\fP مجاز است یا خیر. پیش‌فرض: \fItrue\fP\&. .UNINDENT .SS hicpp\-invalid\-access\-moved .sp این بررسی یک نام مستعار برای bugprone\-use\-after\-move \%<>\& است. .sp بخش‌هایی از قاعدهٔ 8.4.1 \% را برای بررسی این که آیا به اشیاء انتقال‌یافته (moved-from) دسترسی وجود دارد یا خیر پیاده‌سازی می‌کند. .SS hicpp\-member\-init .sp این بررسی یک نام مستعار برای cppcoreguidelines\-pro\-type\-member\-init \%<>\& است. بررسی مربوط به قاعدهٔ 12.4.2 \% را جهت مقداردهی اولیهٔ اعضای کلاس به ترتیب صحیح پیاده‌سازی می‌کند. .SS hicpp\-move\-const\-arg .sp بررسی \fIhicpp\-move\-const\-arg\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر به performance\-move\-const\-arg \%<> مراجعه کنید. این بررسی قاعدهٔ 17.3.1 \% را اعمال می‌کند. .SS hicpp\-multiway\-paths\-covered .sp این بررسی موقعیت‌هایی را پیدا می‌کند که مسیرهای کد به‌طور کامل پوشش داده نشده‌اند. علاوه بر این، پیشنهاد می‌کند در صورتی که کد واضح‌تر می‌شود، به جای \fBswitch\fP از \fBif\fP استفاده شود. قاعدهٔ 6.1.2 \% و قاعدهٔ 6.1.4 \% از استانداردهای کدنویسی High Integrity C++ اعمال می‌شوند. .sp زنجیره‌های \fBif\-else if\fP که شاخهٔ پایانی \fBelse\fP را ندارند ممکن است منجر به اجرای غیرمنتظرهٔ برنامه شده و ناشی از یک خطای منطقی باشند. اگر فقدان شاخهٔ \fBelse\fP عمدی است، می‌توانید آن را همراه با یک کامنت شفاف‌ساز خالی بگذارید. این هشدار می‌تواند در برخی پایگاه‌های کد پر سر و صدا باشد، بنابراین به‌طور پیش‌فرض غیرفعال است. .INDENT 0.0 .INDENT 3.5 .sp .EX void f1() { int i = determineTheNumber(); if(i > 0) { // Some Calculation } else if (i < 0) { // Precondition violated or something else. } // ... } .EE .UNINDENT .UNINDENT .sp استدلال‌های مشابهی برای دستورات \fBswitch\fP که تمام مسیرهای کد ممکن را پوشش نمی‌دهند وجود دارد. .INDENT 0.0 .INDENT 3.5 .sp .EX // The missing default branch might be a logical error. It can be kept empty // if there is nothing to do, making it explicit. void f2(int i) { switch (i) { case 0: // something break; case 1: // something else break; } // All other numbers? } // Violates this rule as well, but already emits a compiler warning (\-Wswitch). enum Color { Red, Green, Blue, Yellow }; void f3(enum Color c) { switch (c) { case Red: // We can\(aqt drive for now. break; case Green: // We are allowed to drive. break; } // Other cases missing } .EE .UNINDENT .UNINDENT .sp قاعدهٔ 6.1.4 \% الزام می‌کند که هر دستور \fBswitch\fP دست‌کم دو برچسب \fBcase\fP به غیر از برچسب \fIdefault\fP داشته باشد. در غیر این صورت، آن \fBswitch\fP را می‌توانستیم به شکل بهتری با یک دستور \fBif\fP بیان کنیم. دستورات تباهیدهٔ (degenerated) \fBswitch\fP بدون هیچ برچسبی نیز شناسایی می‌شوند. .INDENT 0.0 .INDENT 3.5 .sp .EX // Degenerated switch that could be better written as \(gaif\(ga int i = 42; switch(i) { case 1: // do something here default: // do something else here } // Should rather be the following: if (i == 1) { // do something here } else { // do something here } .EE .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX // A completely degenerated switch will be diagnosed. int i = 42; switch(i) {} .EE .UNINDENT .UNINDENT.SS گزینه‌ها .INDENT 0.0 .TP .B WarnOnMissingElse یک فلگ بولی که هشداری را برای شاخه‌های \fBelse\fP ناموجود فعال می‌کند. پیش‌فرض \fIfalse\fP است\&. .UNINDENT .SS hicpp\-named\-parameter .sp این بررسی یک نام مستعار برای readability\-named\-parameter \%<> است\&. .sp قاعدهٔ 8.2.1 را پیاده‌سازی می‌کند \%\&. .SS hicpp\-new\-delete\-operators .sp این بررسی یک نام مستعار برای misc\-new\-delete\-overloads \%<> است\&. قاعدهٔ 12.3.1 را پیاده‌سازی می‌کند \% تا اطمینان حاصل شود عملگرهای \fInew\fP و \fIdelete\fP امضای صحیحی دارند. .SS hicpp\-no\-array\-decay .sp بررسی \fIhicpp\-no\-array\-decay\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر cppcoreguidelines\-pro\-bounds\-array\-to\-pointer\-decay \%<> را ببینید. این بررسی قاعدهٔ 4.1.1 را اعمال می‌کند \%\&. .SS hicpp\-no\-assembler .sp دستورات اسمبلی را بررسی می‌کند. از به‌کارگیری اسمبلی درون‌خطی باید اجتناب شود زیرا قابلیت حمل‌پذیری کد را محدود می‌سازد. .sp این بررسی قاعدهٔ 7.5.1 \% از High Integrity C++ Coding Standard را اعمال می‌کند. .SS hicpp\-no\-malloc .sp بررسی \fIhicpp\-no\-malloc\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر cppcoreguidelines\-no\-malloc \%<> را ببینید. این بررسی قاعدهٔ 5.3.2 را اعمال می‌کند \%\&. .SS hicpp\-noexcept\-move .sp این بررسی یک نام مستعار برای performance\-noexcept\-move\-constructor \%<> است\&. قاعدهٔ 12.5.4 را بررسی می‌کند \% تا انتساب انتقال و سازندهٔ انتقال را \fInoexcept\fP نشانه‌گذاری کند\&. .SS hicpp\-signed\-bitwise .sp موارد استفاده از عملیات بیتی روی انواع عددی صحیح علامت‌دار را پیدا می‌کند، که ممکن است منجر به رفتار تعریف‌نشده یا وابسته به پیاده‌سازی شود. .sp قاعدهٔ مربوطه در High Integrity C++ Standard، بخش 5.6.1 تعریف شده است \%\&. .SS گزینه‌ها .INDENT 0.0 .TP .B IgnorePositiveIntegerLiterals اگر این گزینه روی \fItrue\fP تنظیم شود، بررسی روی عملیات بیتی با لیترال‌های صحیح مثبت، مانند \fI~0\fP، \fI2 << 1\fP و غیره هشدار نخواهد داد. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .SS hicpp\-special\-member\-functions .sp این بررسی یک نام مستعار برای cppcoreguidelines\-special\-member\-functions \%<> است\&. بررسی می‌کند که توابع عضو ویژه امضای صحیحی داشته باشند، بر اساس قاعدهٔ 12.5.7 \%\&. .SS hicpp\-static\-assert .sp بررسی \fIhicpp\-static\-assert\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر misc\-static\-assert \%<> را ببینید. این بررسی قاعدهٔ 7.1.10 را اعمال می‌کند \%\&. .SS hicpp\-undelegated\-constructor .sp این بررسی یک نام مستعار برای bugprone\-undelegated\-constructor \%<> است\&. به صورت جزئی قاعدهٔ 12.4.5 را پیاده‌سازی می‌کند \% برای یافتن فراخوانی‌های نابجای سازنده درون یک سازنده دیگر. .INDENT 0.0 .INDENT 3.5 .sp .EX struct Ctor { Ctor(); Ctor(int); Ctor(int, int); Ctor(Ctor *i) { // All Ctor() calls result in a temporary object Ctor(); // did you intend to call a delegated constructor? Ctor(0); // did you intend to call a delegated constructor? Ctor(1, 2); // did you intend to call a delegated constructor? foo(); } }; .EE .UNINDENT .UNINDENT .SS hicpp\-uppercase\-literal\-suffix .sp بررسی hicpp\-uppercase\-literal\-suffix یک نام مستعار است، لطفاً برای اطلاعات بیشتر readability\-uppercase\-literal\-suffix \%<> را ببینید. .sp به صورت جزئی قاعدهٔ 4.2.1 را پیاده‌سازی می‌کند \% تا اطمینان حاصل شود که پسوند \fBU\fP به درستی نوشته شده است. .SS hicpp\-use\-auto .sp بررسی \fIhicpp\-use\-auto\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر modernize\-use\-auto \%<> را ببینید. این بررسی قاعدهٔ 7.1.8 را اعمال می‌کند \%\&. .SS hicpp\-use\-emplace .sp بررسی \fIhicpp\-use\-emplace\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر modernize\-use\-emplace \%<> را ببینید. این بررسی قاعدهٔ 17.4.2 را اعمال می‌کند \%\&. .SS hicpp\-use\-equals\-default .sp این بررسی یک نام مستعار برای modernize\-use\-equals\-default \%<> است\&. قاعدهٔ 12.5.1 را پیاده‌سازی می‌کند \% تا توابع عضو ویژه را صراحتاً پیش‌فرض (default) کند. .SS hicpp\-use\-equals\-delete .sp این بررسی یک نام مستعار برای modernize\-use\-equals\-delete \%<> است\&. قاعدهٔ 12.5.1 را پیاده‌سازی می‌کند \% تا توابع عضو ویژه را صراحتاً پیش‌فرض یا حذف (delete) کند. .SS hicpp\-use\-noexcept .sp بررسی \fIhicpp\-use\-noexcept\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر modernize\-use\-noexcept \%<> را ببینید. این بررسی قاعدهٔ 1.3.5 را اعمال می‌کند \%\&. .SS hicpp\-use\-nullptr .sp بررسی \fIhicpp\-use\-nullptr\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر modernize\-use\-nullptr \%<> را ببینید. این بررسی قاعدهٔ 2.5.3 را اعمال می‌کند \%\&. .SS hicpp\-use\-override .sp این بررسی یک نام مستعار برای modernize\-use\-override \%<> است\&. قاعدهٔ 10.2.1 را پیاده‌سازی می‌کند \% تا یک تابع مجازی را در هنگام بازنویسی (overriding) با \fIoverride\fP اعلان کند. .SS hicpp\-vararg .sp بررسی \fIhicpp\-vararg\fP یک نام مستعار است، لطفاً برای اطلاعات بیشتر cppcoreguidelines\-pro\-type\-vararg \%<> را ببینید. این بررسی قاعدهٔ 14.1.1 را اعمال می‌کند \%\&. .SS linuxkernel\-must\-check\-errs .sp کد هستهٔ لینوکس را بررسی می‌کند تا ببیند آیا از نتایج توابع در \fBlinux/err.h\fP استفاده می‌کند یا خیر\&. همچنین بررسی می‌کند که آیا کد از نتایج توابعی که مستقیماً مقداری را از یکی از این توابع خطا برمی‌گردانند، استفاده می‌کند یا خیر. .sp این موضوع در هستهٔ لینوکس مهم است زیرا مقادیر بازگشتی \fBERR_PTR\fP، \fBPTR_ERR\fP، \fBIS_ERR\fP، \fBIS_ERR_OR_NULL\fP، \fBERR_CAST\fP، و \fBPTR_ERR_OR_ZERO\fP باید بررسی شوند، چرا که اشاره‌گرهای مثبت و کدهای خطای منفی در یک بستر مشترک استفاده می‌شوند. این توابع با ویژگی \fB__attribute__((warn_unused_result))\fP نشانه‌گذاری شده‌اند، اما برخی از نسخه‌های هسته این هشدار را برای clang فعال ندارند. .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX /* Trivial unused call to an ERR function */ PTR_ERR_OR_ZERO(some_function_call()); /* A function that returns ERR_PTR. */ void *fn() { ERR_PTR(\-EINVAL); } /* An invalid use of fn. */ fn(); .EE .UNINDENT .UNINDENT .SS llvm\-else\-after\-return .sp بررسی \fIllvm\-else\-after\-return\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر به readability\-else\-after\-return \%<> مراجعه کنید. .SS llvm\-header\-guard .sp گارد‌های هدر (header guards) که با شیوه‌نامه LLVM مطابقت ندارند را پیدا کرده و اصلاح می‌کند. .SS llvm\-include\-order .sp ترتیب صحیح \fB#include\fPها را بررسی می‌کند. .sp ببینید: \% .SS llvm\-namespace\-comment .sp بررسی \fIgoogle\-readability\-namespace\-comments\fP به عنوان یک نام مستعار برای این بررسی، به اینجا تغییر مسیر می‌دهد. .sp بررسی می‌کند که فضای نام‌های (namespaces) طولانی دارای یک کامنت پایانی باشند. .sp \% .sp \% .INDENT 0.0 .INDENT 3.5 .sp .EX namespace n1 { void f(); } // becomes namespace n1 { void f(); } // namespace n1 .EE .UNINDENT .UNINDENT .SS Options .INDENT 0.0 .TP .B ShortNamespaceLines در صورتی که بدنه فضای نام بیشتر از تعداد خطوط \fIShortNamespaceLines\fP کد داشته باشد، لازم می‌دارد که بعد از براکت بسته تعریف فضای نام، یک کامنت پایانی قرار گیرد. مقدار آن یک عدد صحیح بدون علامت است که پیش‌فرض آن \fI1U\fP می‌باشد. .UNINDENT .INDENT 0.0 .TP .B SpacesBeforeComments یک عدد صحیح بدون علامت که تعداد فاصله‌های (spaces) قبل از کامنت پایانی تعریف فضای نام را مشخص می‌کند. پیش‌فرض \fI1U\fP است. .UNINDENT .INDENT 0.0 .TP .B AllowOmittingNamespaceComments هنگامی که \fItrue\fP باشد، در صورتی که هیچ کامنتی برای فضای نام وجود نداشته باشد، بررسی با موفقیت انجام می‌شود. این بررسی تنها زمانی با خطا مواجه خواهد شد که کامنت مشخص‌شده برای فضای نام با آنچه که مورد انتظار است متفاوت باشد. پیش‌فرض \fIfalse\fP است. .UNINDENT .SS llvm\-prefer\-isa\-or\-dyn\-cast\-in\-conditionals .sp عبارات شرطی را بررسی کرده و مواردی از \fBcast<>\fP را که به جای بازگرداندن اشاره‌گر تهی (null pointer) خطا (assert) ایجاد می‌کنند، و همچنین مواردی از \fBdyn_cast<>\fP را که مقدار بازگشتی آن‌ها دریافت نمی‌شود، پیدا و جایگزین می‌کند. علاوه بر این، مواردی را که با الگوی \fBvar && isa(var)\fP مطابقت دارند و در آن‌ها \fBvar\fP دو بار ارزیابی می‌شود، پیدا و جایگزین می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX // Finds these: if (auto x = cast(y)) {} // is replaced by: if (auto x = dyn_cast(y)) {} if (cast(y)) {} // is replaced by: if (isa(y)) {} if (dyn_cast(y)) {} // is replaced by: if (isa(y)) {} if (var && isa(var)) {} // is replaced by: if (isa_and_nonnull(var.foo())) {} // Other cases are ignored, e.g.: if (auto f = cast(y)\->foo()) {} if (cast(y)\->foo()) {} if (X.cast(y)) {} .EE .UNINDENT .UNINDENT .SS llvm\-prefer\-register\-over\-unsigned .sp موارد استفاده قدیمی از \fBunsigned\fP برای نگهداری vregها و physregها را پیدا کرده و آن‌ها را جهت استفاده از \fBRegister\fP بازنویسی می‌کند. .sp در حال حاضر این سازوکار با یافتن تمام متغیرهایی از نوع عدد صحیح بدون علامت که مقداردهنده اولیه آن‌ها با یک تبدیل ضمنی (implicit cast) از \fBRegister\fP به \fBunsigned\fP آغاز می‌شود، کار می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX void example(MachineOperand &MO) { unsigned Reg = MO.getReg(); ... } .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX void example(MachineOperand &MO) { Register Reg = MO.getReg(); ... } .EE .UNINDENT .UNINDENT .SS llvm\-prefer\-static\-over\-anonymous\-namespace .sp اعلان‌های توابع و متغیرها را در داخل فضای نام بی‌نام (anonymous namespace) پیدا کرده و جایگزینی آن‌ها با اعلان‌های \fBstatic\fP را پیشنهاد می‌کند. .sp شیوه‌نامه کدنویسی LLVM \% توصیه می‌کند که فضاهای نام بی‌نام تا حد امکان کوچک نگه داشته شوند و فقط برای اعلان کلاس‌ها استفاده گردند. برای توابع و متغیرها، استفاده از مشخص‌کننده \fBstatic\fP جهت محدود کردن میدان دید (visibility) اولویت دارد. .sp به عنوان مثال، کد ناسازگار: .INDENT 0.0 .INDENT 3.5 .sp .EX namespace { class StringSort { public: StringSort(...) bool operator<(const char *RHS) const; }; // warning: place method definition outside of an anonymous namespace bool StringSort::operator<(const char *RHS) const {} // warning: prefer using \(aqstatic\(aq for restricting visibility void runHelper() {} // warning: prefer using \(aqstatic\(aq for restricting visibility int myVariable = 42; } .EE .UNINDENT .UNINDENT .sp باید به این صورت تبدیل شود: .INDENT 0.0 .INDENT 3.5 .sp .EX // Small anonymous namespace for class declaration namespace { class StringSort { public: StringSort(...) bool operator<(const char *RHS) const; }; } // placed method definition outside of the anonymous namespace bool StringSort::operator<(const char *RHS) const {} // used \(aqstatic\(aq instead of an anonymous namespace static void runHelper() {} // used \(aqstatic\(aq instead of an anonymous namespace static int myVariable = 42; .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B AllowVariableDeclarations اگر \fItrue\fP باشد، اجازه می‌دهد اعلان متغیرها در فضای نام ناشناس (anonymous namespace) قرار بگیرد. مقدار پیش‌فرض \fItrue\fP است\&. .UNINDENT .INDENT 0.0 .TP .B AllowMemberFunctionsInClass اگر \fItrue\fP باشد، فقط به متدهایی که درون فضای نام ناشناس خارج از کلاس مربوطه تعریف شده‌اند اخطار داده می‌شود. مقدار پیش‌فرض \fItrue\fP است\&. .UNINDENT .SS llvm\-qualified\-auto .sp بررسی \fIllvm\-qualified\-auto\fP یک نام مستعار (alias) است، لطفاً برای اطلاعات بیشتر readability\-qualified\-auto \%<> را ببینید. .SS llvm\-twine\-local .sp به دنبال متغیرهای محلی \fBTwine\fP می‌گردد که مستعد استفاده پس از آزادسازی (use after free) هستند و معمولاً باید از آن‌ها اجتناب شود. .INDENT 0.0 .INDENT 3.5 .sp .EX static Twine Moo = Twine(\(dqbark\(dq) + \(dqbah\(dq; // becomes static std::string Moo = (Twine(\(dqbark\(dq) + \(dqbah\(dq).str(); .EE .UNINDENT .UNINDENT .sp کلاس \fBTwine\fP مالک حافظه محتویات خود نیست، بنابراین توصیه نمی‌شود از \fBTwine\fP ایجاد شده از رشته‌های موقت یا لیترال‌های رشته‌ای استفاده شود. .INDENT 0.0 .INDENT 3.5 .sp .EX static Twine getModuleIdentifier(StringRef moduleName) { return moduleName + \(dq_module\(dq; } void foo() { Twine result = getModuleIdentifier(std::string{\(dqabc\(dq} + \(dqdef\(dq); // temporary std::string is destroyed here, result is dangling } .EE .UNINDENT .UNINDENT .sp پس از اعمال این نکات اصلاحی (fix-it)، کد به جای \fBTwine\fP از \fBstd::string\fP برای متغیرهای محلی استفاده خواهد کرد. با این حال، \fBTwine\fP متدهای زیادی دارد که با \fBstd::string\fP ناسازگار هستند، بنابراین ممکن است کاربر پس از اعمال نکات اصلاحی نیاز داشته باشد کد را به صورت دستی تطبیق دهد. .SS llvm\-mlir\-op\-builder .sp استفاده از فرم قدیمی و در شرف منسوخ‌شدن \fBOpBuilder::create\fP در MLIR را بررسی کرده و پیشنهاد می‌کند به جای آن از \fBT::create\fP استفاده شود. .SS مثال .INDENT 0.0 .INDENT 3.5 .sp .EX builder.create(builder.getUnknownLoc(), \(dqbaz\(dq); .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX FooOp::create(builder, builder.getUnknownLoc(), \(dqbaz\(dq); .EE .UNINDENT .UNINDENT .SS llvm\-use\-ranges .sp فراخوانی‌های الگوریتم‌های تکرارکننده (iterator) در کتابخانه STL را پیدا می‌کند که می‌توانند با الگوریتم‌های مبتنی بر بازه (range-based) در LLVM از مسیر \fBllvm/ADT/STLExtras.h\fP جایگزین شوند\&. .SS مثال .INDENT 0.0 .INDENT 3.5 .sp .EX auto it = std::find(vec.begin(), vec.end(), value); bool all = std::all_of(vec.begin(), vec.end(), [](int x) { return x > 0; }); .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX auto it = llvm::find(vec, value); bool all = llvm::all_of(vec, [](int x) { return x > 0; }); .EE .UNINDENT .UNINDENT .SS الگوریتم‌های پشتیبانی‌شده .sp فراخوانی‌های مربوط به الگوریتم‌های STL زیر بررسی می‌شوند: .sp \fBstd::all_of\fP, \fBstd::any_of\fP, \fBstd::binary_search\fP, \fBstd::copy\fP, \fBstd::copy_if\fP, \fBstd::count\fP, \fBstd::count_if\fP, \fBstd::equal\fP, \fBstd::fill\fP, \fBstd::find\fP, \fBstd::find_if\fP, \fBstd::find_if_not\fP, \fBstd::for_each\fP, \fBstd::includes\fP, \fBstd::is_sorted\fP, \fBstd::lower_bound\fP, \fBstd::max_element\fP, \fBstd::min_element\fP, \fBstd::mismatch\fP, \fBstd::none_of\fP, \fBstd::partition\fP, \fBstd::partition_point\fP, \fBstd::remove_if\fP, \fBstd::replace\fP, \fBstd::stable_sort\fP, \fBstd::transform\fP, \fBstd::uninitialized_copy\fP, \fBstd::unique\fP, \fBstd::upper_bound\fP\&. .sp این بررسی هنگام اعمال اصلاحات، دستور پیش‌پردازنده ضروری \fB#include \(dqllvm/ADT/STLExtras.h\(dq\fP را اضافه می‌کند. .SS llvmlibc\-callee\-namespace .sp بررسی می‌کند که تمام فراخوانی‌ها به توابعی درون فضای نام صحیح ارجاع داده شوند. .INDENT 0.0 .INDENT 3.5 .sp .EX // Implementation inside the LIBC_NAMESPACE namespace. // Correct if: // \- LIBC_NAMESPACE is a macro // \- LIBC_NAMESPACE expansion starts with \(ga__llvm_libc\(ga namespace LIBC_NAMESPACE { // Allow calls with the fully qualified name. LIBC_NAMESPACE::strlen(\(dqhello\(dq); // Allow calls to compiler provided functions. (void)__builtin_abs(\-1); // Bare calls are allowed as long as they resolve to the correct namespace. strlen(\(dqworld\(dq); // Disallow calling into functions in the global namespace. ::strlen(\(dq!\(dq); } // namespace LIBC_NAMESPACE .EE .UNINDENT .UNINDENT .SS llvmlibc\-implementation\-in\-namespace .sp بررسی می‌کند که تمام اعلان‌ها در پیاده‌سازی llvm\-libc درون فضای نام صحیح قرار گرفته باشند. .INDENT 0.0 .INDENT 3.5 .sp .EX // Implementation inside the LIBC_NAMESPACE_DECL namespace. // Correct if: // \- LIBC_NAMESPACE_DECL is a macro // \- LIBC_NAMESPACE_DECL expansion starts with \(ga[[gnu::visibility(\(dqhidden\(dq)]] __llvm_libc\(ga namespace LIBC_NAMESPACE_DECL { void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} // Namespaces within LIBC_NAMESPACE_DECL namespace are allowed. namespace inner { int localVar = 0; } // Functions with C linkage are allowed. extern \(dqC\(dq void str_fuzz() {} } // Incorrect: implementation not in the LIBC_NAMESPACE_DECL namespace. void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} // Incorrect: outer most namespace is not the LIBC_NAMESPACE_DECL macro. namespace something_else { void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} } // Incorrect: outer most namespace expansion does not start with \(ga[[gnu::visibility(\(dqhidden\(dq)]] __llvm_libc\(ga. #define LIBC_NAMESPACE_DECL custom_namespace namespace LIBC_NAMESPACE_DECL { void LLVM_LIBC_ENTRYPOINT(strcpy)(char *dest, const char *src) {} } .EE .UNINDENT .UNINDENT .SS llvmlibc\-inline\-function\-decl .sp بررسی می‌کند که تمام توابع inline به‌صورت صریح یا ضمنی در فایل‌های هدر، با ماکروی \fBLIBC_INLINE\fP نشانه‌گذاری شده باشند، به‌جز توابع ضمنی کلاس‌ها یا توابع حذف‌شده (deleted). برای اطلاعات بیشتر دربارهٔ این ماکرو، راهنمای سبک libc را در \% مشاهده کنید. .SS llvmlibc\-restrict\-system\-libc\-headers .sp موارد include هدرهای libc سیستم که توسط کامپایلر ارائه نشده‌اند را درون پیاده‌سازی‌های llvm\-libc پیدا می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX #include // Not allowed because it is part of system libc. #include // Allowed because it is provided by the compiler. #include \(dqinternal/stdio.h\(dq // Allowed because it is NOT part of system libc. .EE .UNINDENT .UNINDENT .sp این بررسی ضروری است زیرا include تصادفی هدرهای libc سیستم می‌تواند منجر به باگ‌های نامحسوس و سخت‌یاب شود. به عنوان مثال، یک libc سیستم را در نظر بگیرید که ترتیب فیلدهای ساختار \fBdirent\fP آن با llvm\-libc کمی متفاوت است. در حالی که این کد با موفقیت کامپایل خواهد شد، اما به دلیل ناسازگاری در ABI می‌تواند باعث بروز مشکلاتی در زمان اجرا شود. .SS گزینه‌ها .INDENT 0.0 .TP .B Includes یک رشته شامل فهرستی از الگوهای انطباقی (glob) نام‌های فایل مجاز برای include که با کاما از هم جدا شده‌اند. مشابه فهرست الگوهای \-checks برای اجرای خود clang\-tidy، دو نویسهٔ عام (wildcard) عبارتند از \fI*\fP و \fI\-\fP، به‌ترتیب برای شامل کردن و مستثنی کردن الگوها. مقدار پیش‌فرض \fI\-*\fP است که تمامی includeها را غیرمجاز می‌کند. .sp می‌توان از این گزینه برای مجاز کردن includeهای امن شناخته‌شده، مانند هدرهای توسعهٔ لینوکس استفاده کرد. برای جزئیات بیشتر به portability\-restrict\-system\-includes \%<> مراجعه کنید. .UNINDENT .SS misc\-anonymous\-namespace\-in\-header .sp فضاهای نام بی‌نام (anonymous) را در هدرها پیدا می‌کند. .sp فضاهای نام بی‌نام در هدرها می‌توانند منجر به نقض قاعدهٔ یک‌بار تعریف (ODR یا One Definition Rule) شوند، زیرا هر واحد ترجمه که هدر را include کند، نسخهٔ یکتای خود را از نمادها دریافت خواهد کرد. این امر حجم فایل اجرایی باینری را افزایش داده و می‌تواند خطاهای پیوندزنی (link-time) گیج‌کننده‌ای ایجاد کند. .SS مراجع .sp این بررسی مطابق با قاعدهٔ استاندارد کدنویسی CERT C++ با شناسهٔ DCL59\-CPP. Do not define an unnamed namespace in a header file \% است. .sp نام بررسی متناظر در cpplint.py: \fIbuild/namespaces\fP\&. .SS misc\-confusable\-identifiers .sp دربارهٔ شناسه‌های شبهه‌انگیز هشدار می‌دهد؛ یعنی شناسه‌هایی که از نظر ظاهری بسیار شبیه به هم هستند، اما از نویسه‌های یونیکد متفاوتی استفاده می‌کنند. این ویژگی حملهٔ بالقوه‌ای را که در CVE\-2021\-42574 \% شرح داده شده است شناسایی می‌کند. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX int fo; // Initial character is U+0066 (LATIN SMALL LETTER F). int 𝐟o; // Initial character is U+1D41F (MATHEMATICAL BOLD SMALL F) not U+0066 (LATIN SMALL LETTER F). .EE .UNINDENT .UNINDENT .SS misc\-const\-correctness .sp این بررسی، متغیرهای محلی را که می‌توانستند به‌صورت \fBconst\fP اعلان شوند ولی نشده‌اند، شناسایی می‌کند. اعلان متغیرها به‌صورت \fBconst\fP در بسیاری از راهنماهای کدنویسی الزامی یا توصیه‌شده است، مانند: ES.25 \% از C++ Core Guidelines. .sp لطفاً توجه داشته باشید که تحلیل این بررسی تنها مبتنی بر نوع داده (type-based) است. متغیرهایی که تغییر نمی‌کنند اما برای ایجاد یک دستگیرهٔ (handle) غیر-const که ممکن است از حوزه (scope) خارج شود به کار می‌روند، به‌عنوان کاندیدای \fBconst\fP تشخیص داده نمی‌شوند. .INDENT 0.0 .INDENT 3.5 .sp .EX // Declare a variable, which is not \(ga\(gaconst\(ga\(ga ... int i = 42; // but use it as read\-only. This means that \(gai\(ga can be declared \(ga\(gaconst\(ga\(ga. int result = i * i; // Before transformation int const result = i * i; // After transformation .EE .UNINDENT .UNINDENT .sp این بررسی می‌تواند مقادیر، اشاره‌گرها، ارجاع‌ها و مقادیر مورد اشاره (pointees) را تحلیل کند: .INDENT 0.0 .INDENT 3.5 .sp .EX // Normal values like built\-ins or objects. int potential_const_int = 42; // Before transformation int const potential_const_int = 42; // After transformation int copy_of_value = potential_const_int; MyClass could_be_const; // Before transformation MyClass const could_be_const; // After transformation could_be_const.const_qualified_method(); // References can be declared const as well. int &reference_value = potential_const_int; // Before transformation int const& reference_value = potential_const_int; // After transformation int another_copy = reference_value; // The similar semantics of pointers are analyzed. int *pointer_variable = &potential_const_int; // Before transformation int const*const pointer_variable = &potential_const_int; // After transformation, both pointer itself and pointee are supported. int last_copy = *pointer_variable; .EE .UNINDENT .UNINDENT .sp تبدیل خودکار کد فقط روی متغیرهایی اعمال می‌شود که در اعلان‌های تکی اعلام شده باشند. ممکن است ابتدا بخواهید پایگاه کد خود را با readability\-isolate\-declaration \%<> آماده کنید. .sp توجه داشته باشید که بررسی cppcoreguidelines\-avoid\-non\-const\-global\-variables \%<> برای اعمال درستی \fBconst\fP بر روی تمامی متغیرهای سراسری (globals) وجود دارد. .SS محدودیت‌ها .sp این بررسی روی کدهای \fIC\fP اجرا نمی‌شود. .sp این بررسی متغیرهای قالب‌بندی‌شده (templated) یا متغیرهایی را که وابسته به نمونه‌سازی (instantiation dependent) هستند تحلیل نخواهد کرد. نمونه‌سازی‌های مختلف می‌توانند منجر به ویژگی‌های درستیِ \fBconst\fP متفاوتی شوند و به‌طور کلی یافتن تمام نمونه‌سازی‌های یک قالب امکان‌پذیر نیست. ممکن است از قالب در یک واحد ترجمه (translation unit) مستقل به شکل متفاوتی استفاده شده باشد. .SS گزینه‌ها .INDENT 0.0 .TP .B AnalyzeValues فعال یا غیرفعال کردن تحلیل متغیرهای مقداری معمولی، مانند \fBint i = 42;\fP\&. مقدار پیش‌فرض \fItrue\fP است. .INDENT 7.0 .INDENT 3.5 .sp .EX // Warning int i = 42; // No warning int const i = 42; // Warning int a[] = {42, 42, 42}; // No warning int const a[] = {42, 42, 42}; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B AnalyzeReferences فعال یا غیرفعال کردن تحلیل متغیرهای ارجاعی، مانند \fBint &ref = i;\fP\&. مقدار پیش‌فرض \fItrue\fP است. .INDENT 7.0 .INDENT 3.5 .sp .EX int i = 42; // Warning int& ref = i; // No warning int const& ref = i; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B AnalyzePointers فعال یا غیرفعال کردن تحلیل متغیرهای اشاره‌گر، مانند \fBint *ptr = &i;\fP\&. برای بررسی‌های خاص‌تر، به \fBWarnPointersAsValues\fP و \fBWarnPointersAsPointers\fP مراجعه کنید. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B WarnPointersAsValues این گزینه پیشنهاد \fBconst\fP شدن خود اشاره‌گر را فعال می‌کند. مقادیر اشاره‌گر دو حالت برای \fBconst\fP بودن دارند: خود اشاره‌گر و مقداری که به آن اشاره می‌شود. مقدار پیش‌فرض \fIfalse\fP است. .INDENT 7.0 .INDENT 3.5 .sp .EX int value = 42; // Warning const int * pointer_variable = &value; // No warning const int *const pointer_variable = &value; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B WarnPointersAsPointers این گزینه پیشنهاد \fBconst\fP شدن مقداری را که اشاره‌گر به آن اشاره می‌کند، فعال می‌سازد. مقدار پیش‌فرض \fItrue\fP است. .sp نیازمند این است که \fBAnalyzePointers\fP برابر با \fItrue\fP باشد. .INDENT 7.0 .INDENT 3.5 .sp .EX int value = 42; // No warning const int *const pointer_variable = &value; // Warning int *const pointer_variable = &value; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B TransformValues راهنمایی‌های اصلاح خودکار (fixit-hints) را برای انواع مقداری فراهم می‌کند تا در صورت تک‌اعلانی بودن، \fBconst\fP را به‌طور خودکار اضافه کند. مقدار پیش‌فرض \fItrue\fP است. .INDENT 7.0 .INDENT 3.5 .sp .EX // Before int value = 42; // After int const value = 42; // Before int a[] = {42, 42, 42}; // After int const a[] = {42, 42, 42}; // Result is modified later in its life\-time. No diagnostic and fixit hint will be emitted. int result = value * 3; result \-= 10; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B TransformReferences راهنمایی‌های اصلاح خودکار (fixit-hints) را برای انواع ارجاعی فراهم می‌کند تا در صورت تک‌اعلانی بودن، \fBconst\fP را به‌طور خودکار اضافه کند. مقدار پیش‌فرض \fItrue\fP است. .INDENT 7.0 .INDENT 3.5 .sp .EX // This variable could still be a constant. But because there is a non\-const reference to // it, it can not be transformed (yet). int value = 42; // The reference \(aqref_value\(aq is not modified and can be made \(aqconst int &ref_value = value;\(aq // Before int &ref_value = value; // After int const &ref_value = value; // Result is modified later in its life\-time. No diagnostic and fixit hint will be emitted. int result = ref_value * 3; result \-= 10; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B TransformPointersAsValues راهنمایی‌های اصلاح خودکار (fixit-hints) را برای اشاره‌گرها در صورتی که شیء مورد اشاره تغییر نکند، فراهم می‌سازد. این گزینه تغییر نکردن مقداری را که به آن اشاره شده بررسی نمی‌کند! مقدار پیش‌فرض \fIfalse\fP است. .sp نیازمند این است که \(aqWarnPointersAsValues\(aq برابر با \(aqtrue\(aq باشد. .INDENT 7.0 .INDENT 3.5 .sp .EX int value = 42; // Before const int * pointer_variable = &value; // After const int *const pointer_variable = &value; // Before const int * a[] = {&value, &value}; // After const int *const a[] = {&value, &value}; // Before int *ptr_value = &value; // After int *const ptr_value = &value; int result = 100 * (*ptr_value); // Does not modify the pointer itself. // This modification of the pointee is still allowed and not diagnosed. *ptr_value = 0; // The following pointer may not become a \(aqint *const\(aq. int *changing_pointee = &value; changing_pointee = &result; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B TransformPointersAsPointers راهنمایی‌های اصلاح خودکار (fix-it hints) را برای اشاره‌گرها در صورتی که مقدار مورد اشاره تغییر نکند، فراهم می‌سازد. مقدار پیش‌فرض \fIfalse\fP است. .sp نیازمند این است که \fBWarnPointersAsPointers\fP برابر با \fItrue\fP باشد. .INDENT 7.0 .INDENT 3.5 .sp .EX int value = 42; // Before int * pointer_variable = &value; // After const int * pointer_variable = &value; // Before int * a[] = {&value, &value}; // After const int * a[] = {&value, &value}; .EE .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .TP .B AllowedTypes فهرستی از نام‌های انواع که با نقطه-ویرگول (semicolon) از یکدیگر جدا شده‌اند و از بررسی درستی const مستثنی خواهند شد. عبارت‌های منظم (regex) پذیرفته می‌شوند؛ به عنوان مثال \fB[Rr]ef(erence)?$\fP با هر نوعی که دارای پسوند \fBRef\fP، \fBref\fP، \fBReference\fP و \fBreference\fP باشد مطابقت دارد. اگر نامی در فهرست شامل توالی \fI::\fP باشد، با نام کامل نوع (یعنی \fBnamespace::Type\fP) مطابقت داده می‌شود؛ در غیر این صورت تنها با نام نوع (یعنی \fBType\fP) سنجیده خواهد شد. مقدار پیش‌فرض یک رشته خالی است. .UNINDENT .SS misc\-coroutine\-hostile\-raii .sp تشخیص می‌دهد که چه زمانی اشیایی از انواع خصمانه خاص RAII در طول نقاط تعلیق (suspension points) در یک کوروتین (coroutine) باقی می‌مانند. این انواع خصمانه شامل انواع قفل‌پذیر با حوزه مشخص (scoped\-lockable) و انواعی هستند که به یک لیست سیاه (denylist) قابل پیکربندی تعلق دارند. .sp برخی از اشیاء نیازمند آن هستند که در همان رشته‌ای (thread) که ایجاد شده‌اند، نابود شوند. به طور سنتی این الزام اغلب به صورت «باید یک متغیر محلی باشد» بیان می‌شد، با این فرض که متغیرهای محلی همیشه به این شیوه عمل می‌کنند. با این حال، در کوروتین‌های C++20 این فرض نادرست است، زیرا یک دستور میانی \fBco_await\fP ممکن است باعث تعلیق کوروتین شده و بعداً روی رشته دیگری از سر گرفته (resumed) شود. .sp طول عمر شیئی که نیاز به نابودی در همان رشته دارد، نباید یک نقطه \fBco_await\fP یا \fBco_yield\fP را در بر بگیرد. اگر شیئی را ایجاد یا نابود می‌کنید، باید این کار را بدون اجازه دادن به تعلیق کوروتین در این بین انجام دهید. .sp انواع زیر خصمانه در نظر گرفته می‌شوند: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 انواع Scoped\-lockable: باقی ماندن یک شیء scoped\-lockable در طول یک نقطه تعلیق مشکل‌ساز است زیرا قفلی که توسط این شیء نگه داشته شده می‌تواند توسط رشته متفاوتی آزاد شود. این امر رفتار تعریف‌نشده (undefined behaviour) خواهد بود. این شامل تمام انواعی می‌شود که با ویژگی \fBscoped_lockable\fP حاشیه‌نویسی شده‌اند. .IP \(bu 2 انواعی که به یک لیست سیاه (denylist) قابل پیکربندی تعلق دارند. .UNINDENT .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX // Call some async API while holding a lock. task coro() { const std::lock_guard l(&mu_); // Oops! The async Bar function may finish on a different // thread from the one that created the lock_guard (and called // Mutex::Lock). After suspension, Mutex::Unlock will be called on the wrong thread. co_await Bar(); } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B RAIITypesList یک فهرست جداشده با نقطه\-ویرگول از انواع واجد شرایط (qualified types) که نباید اجازه داشته باشند در طول نقاط تعلیق باقی بمانند. مثال: \fImy::lockable;a::b;::my::other::lockable\fP مقدار پیش‌فرض این گزینه \fIstd::lock_guard;std::scoped_lock\fP است. .UNINDENT .INDENT 0.0 .TP .B AllowedAwaitablesList یک فهرست جداشده با نقطه\-ویرگول از انواع واجد شرایط انواع awaitable که می‌توانند با وجود اشیاء خصمانه RAII در حوزه (scope)، با امنیت مورد انتظار (await) قرار گیرند. .sp اعمال \fBco_await\fP روی یک عبارت از نوع \fBawaitable\fP در صورتی امن تلقی می‌شود که نوع \fBawaitable\fP بخشی از این فهرست باشد. اشیاء RAII که در طول چنین عبارت \fBco_await\fP باقی می‌مانند امن تلقی شده و در نتیجه نشانه‌گذاری (flag) نمی‌شوند. .sp مثال کاربرد: .INDENT 7.0 .INDENT 3.5 .sp .EX // Consider option AllowedAwaitablesList = \(dqsafe_awaitable\(dq struct safe_awaitable { bool await_ready() noexcept { return false; } void await_suspend(std::coroutine_handle<>) noexcept {} void await_resume() noexcept {} }; auto wait() { return safe_awaitable{}; } task coro() { // This persists across both the co_await\(aqs but is not flagged // because the awaitable is considered safe to await on. const std::lock_guard l(&mu_); co_await safe_awaitable{}; co_await wait(); } .EE .UNINDENT .UNINDENT .sp مثال: \fImy::safe::awaitable;other::awaitable\fP پیش‌فرض یک رشته خالی است. .UNINDENT .INDENT 0.0 .TP .B AllowedCallees یک فهرست جداشده با نقطه\-ویرگول از نام توابع فراخوانی‌شده (callee) که می‌توانند با وجود اشیاء خصمانه RAII در حوزه، با امنیت مورد انتظار قرار گیرند. مثال کاربرد: .INDENT 7.0 .INDENT 3.5 .sp .EX // Consider option AllowedCallees = \(dqnoop\(dq task noop() { co_return; } task coro() { // This persists across the co_await but is not flagged // because the awaitable is considered safe to await on. const std::lock_guard l(&mu_); co_await noop(); } .EE .UNINDENT .UNINDENT .sp مثال: \fImy::safe::await;other::await\fP پیش‌فرض یک رشته خالی است. .UNINDENT .SS misc\-definitions\-in\-headers .sp تعاریف توابع و متغیرهای غیر extern و غیر inline را در فایل‌های هدر پیدا می‌کند، که در صورت include شدن این هدرها در چندین واحد ترجمه (translation units)، می‌تواند منجر به نقض احتمالی ODR (قاعده یک تعریف) شود. .INDENT 0.0 .INDENT 3.5 .sp .EX // Foo.h int a = 1; // Warning: variable definition. extern int d; // OK: extern variable. namespace N { int e = 2; // Warning: variable definition. } // Warning: variable definition. const char* str = \(dqfoo\(dq; // OK: internal linkage variable definitions are ignored for now. // Although these might also cause ODR violations, we can be less certain and // should try to keep the false\-positive rate down. static int b = 1; const int c = 1; const char* const str2 = \(dqfoo\(dq; constexpr int k = 1; namespace { int x = 1; } // Warning: function definition. int g() { return 1; } // OK: inline function definition is allowed to be defined multiple times. inline int e() { return 1; } class A { public: int f1() { return 1; } // OK: implicitly inline member function definition is allowed. int f2(); static int d; }; // Warning: not an inline member function definition. int A::f2() { return 1; } // OK: class static data member declaration is allowed. int A::d = 1; // OK: function template is allowed. template T f3() { T a = 1; return a; } // Warning: full specialization of a function template is not allowed. template <> int f3() { int a = 1; return a; } template struct B { void f1(); }; // OK: member function definition of a class template is allowed. template void B::f1() {} class CE { constexpr static int i = 5; // OK: inline variable definition. }; inline int i = 5; // OK: inline variable definition. constexpr int f10() { return 0; } // OK: constexpr function implies inline. // OK: C++14 variable templates are inline. template constexpr T pi = T(3.1415926L); .EE .UNINDENT .UNINDENT .sp هنگامی که \fBclang\-tidy\fP با گزینه \fI\-\-fix\-notes\fP اجرا می‌شود، این بررسی اصلاحاتی ارائه می‌دهد که کلمه کلیدی \fBinline\fP را به طور خودکار به توابع کشف‌شده اضافه می‌کند. لطفاً توجه داشته باشید که افزودن کلمه کلیدی \fBinline\fP به متغیرها در حال حاضر توسط این بررسی پشتیبانی نمی‌شود. .SS misc\-header\-include\-cycle .sp این بررسی وابستگی‌های چرخه‌ای \fB#include\fP را بین فایل‌های هدر تعریف‌شده توسط کاربر تشخیص می‌دهد. .INDENT 0.0 .INDENT 3.5 .sp .EX // Header A.hpp #pragma once #include \(dqB.hpp\(dq // Header B.hpp #pragma once #include \(dqC.hpp\(dq // Header C.hpp #pragma once #include \(dqA.hpp\(dq // Include chain: A\->B\->C\->A .EE .UNINDENT .UNINDENT .sp فایل‌های هدر بخش مهمی از بسیاری از برنامه‌های ++C هستند، چرا که روشی برای سازماندهی اعلان‌ها و تعاریف به اشتراک گذاشته‌شده میان چندین فایل منبع فراهم می‌کنند. با این حال، فایل‌های هدر زمانی که در چرخه‌های وابستگی پیچیده گرفتار شوند نیز می‌توانند مشکلاتی ایجاد کنند. چنین چرخه‌هایی می‌توانند موجب بروز مشکلاتی در زمان‌های کامپایل، کامپایل‌های مجدد غیرضروری، و دشوارتر شدن درک ساختار کلی کد شوند. .sp برای رفع این مشکلات، بررسی خاصی توسعه یافته است تا وابستگی‌های چرخه‌ای میان فایل‌های هدر را که با نام «چرخه‌های include» نیز شناخته می‌شوند، شناسایی کند. یک چرخه include زمانی رخ می‌دهد که فایل هدر \fIA\fP فایل هدر \fIB\fP را include کند، و \fIB\fP (یا هر فایل هدر includeشده بعدی) دوباره فایل هدر \fIA\fP را include کند که منجر به یک چرخه وابستگی دوار می‌گردد. .sp این بررسی در سطح پیش‌پردازنده عمل می‌کند و به‌طور ویژه هدرهای تعریف‌شده توسط کاربر و وابستگی‌های آن‌ها را تحلیل می‌نماید. این ابزار صرفاً بر شناسایی چرخه‌های include تمرکز دارد و سایر وابستگی‌های نوع یا تابع را نادیده می‌گیرد. این تحلیل تخصصی به شناسایی و جلوگیری از مشکلات مرتبط با سازماندهی فایل‌های هدر کمک می‌کند. .sp با تشخیص زودهنگام چرخه‌های include در فرایند توسعه، توسعه‌دهندگان می‌توانند این مشکلات را پیش از آنکه رفع آن‌ها دشوارتر و زمان‌برتر شود شناسایی و برطرف کنند. این امر می‌تواند به زمان‌های کامپایل سریع‌تر، بهبود کیفیت کد، و در مجموع به پایگاه کدی با قابلیت نگهداری بیشتر منجر شود. علاوه بر این، با اطمینان از سازماندهی فایل‌های هدر به‌گونه‌ای که از وابستگی‌های چرخه‌ای اجتناب شود، توسعه‌دهندگان می‌توانند درک و اصلاح کد خود را در طول زمان آسان‌تر کنند. .sp شایان ذکر است که تنها هدرهای تعریف‌شده توسط کاربر و وابستگی‌های آن‌ها تحلیل می‌شوند، و includeهای سیستمی مانند هدرهای کتابخانه استاندارد و هدرهای کتابخانه‌های شخص ثالث مستثنی هستند. includeهای سیستمی معمولاً به‌خوبی طراحی شده و عاری از چرخه‌های include هستند، و نادیده گرفتن آن‌ها به تمرکز بر مشکلات بالقوه موجود در پایگاه کد خود پروژه کمک می‌کند. این محدودیت توانایی تشخیص چرخه‌های \fB#include\fP را در کد تحلیل‌شده کاهش نمی‌دهد. .sp توسعه‌دهندگان باید هرگونه هشدار یا بازخورد ارائه‌شده توسط این راهکار را با دقت بررسی کنند. اگرچه هدف تحلیل شناسایی و جلوگیری از چرخه‌های include است، اما ممکن است شرایطی وجود داشته باشد که استثناها یا تغییراتی در آن ضروری باشد. هنگام اعمال تغییرات، قضاوت صحیح و در نظر گرفتن زمینه خاص پایگاه کد اهمیت دارد. .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoredFilesList روشی را برای مستثنی کردن فایل‌ها/هدرهای خاص از هشدارهای ارائه‌شده توسط بررسی فراهم می‌کند. این کار را می‌توان با مشخص کردن فهرستی از عبارات منظم یا نام فایل‌ها که با نقطه\-ویرگول (semicolon) از هم جدا شده‌اند، انجام داد. این گزینه می‌تواند به‌عنوان جایگزینی برای \fB//NOLINT\fP هنگامی که استفاده از آن ممکن نیست به کار رود. مقدار پیش‌فرض این گزینه یک رشته خالی است که نشان می‌دهد به‌طور پیش‌فرض هیچ فایلی نادیده گرفته نمی‌شود. .UNINDENT .SS misc\-include\-cleaner .sp مواردی از includeهای استفاده‌نشده و مفقود را بررسی می‌کند. یافته‌ها را تنها برای فایل اصلی یک واحد ترجمه (translation unit) تولید می‌نماید. یافته‌ها مطابق با \% هستند. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX // foo.h class Foo{}; // bar.h #include \(dqbaz.h\(dq class Bar{}; // baz.h class Baz{}; // main.cc #include \(dqbar.h\(dq // OK: uses class Bar from bar.h #include \(dqfoo.h\(dq // warning: unused include \(dqfoo.h\(dq Bar bar; Baz baz; // warning: missing include \(dqbaz.h\(dq .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoreHeaders فهرستی از regexها جداشده با نقطه\-ویرگول برای غیرفعال کردن درج/حذف فایل‌های هدری که با این regex به عنوان پسوند مطابقت دارند. به عنوان مثال، \fIfoo/.*\fP درج/حذف را برای تمام هدرهای زیر دایرکتوری \fIfoo\fP غیرفعال می‌کند. پیش‌فرض یک رشته خالی است، هیچ هدری نادیده گرفته نخواهد شد. .UNINDENT .INDENT 0.0 .TP .B DeduplicateFindings یک مقدار بولی که مشخص می‌کند آیا بررسی باید یافته‌های تکراری را برای یک نماد یکسان حذف کند یا خیر. پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B UnusedIncludes یک مقدار بولی که مشخص می‌کند آیا بررسی باید includeهای استفاده‌نشده را گزارش کند (includeهایی که مستقیماً استفاده نمی‌شوند) یا خیر. پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B MissingIncludes یک مقدار بولی که مشخص می‌کند آیا بررسی باید includeهای مفقود را گزارش کند (فایل‌های هدری که نمادهایی از آن‌ها استفاده شده اما مستقیماً include نشده‌اند) یا خیر. پیش‌فرض \fItrue\fP است. .UNINDENT .SS misc\-misleading\-bidirectional .sp در مورد توالی‌های یونیکد دوجهته (bidirectional) پایان‌نیافته هشدار می‌دهد و حملات احتمالی را همان‌طور که در حمله Trojan Source به آدرس \% شرح داده شده، تشخیص می‌دهد. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX #include int main() { bool isAdmin = false; /*‮ } ⁦if (isAdmin)⁩ ⁦ begin admins only */ std::cout << \(dqYou are an admin.\en\(dq; /* end admins only ‮ { ⁦*/ return 0; } .EE .UNINDENT .UNINDENT .SS misc\-misleading\-identifier .sp شناسه‌هایی را پیدا می‌کند که شامل نویسه‌های یونیکد با جهت راست‌به‌چپ هستند، که می‌تواند گمراه‌کننده باشد زیرا ممکن است فهم یک خط عبارت کامل را تغییر دهند، همان‌طور که در Trojan Source به آدرس \% شرح داده شده است. .sp نمونه‌ای از چنین کدهای گمراه‌کننده‌ای در ادامه آمده است: .INDENT 0.0 .INDENT 3.5 .sp .EX #include short int א = (short int)0; short int ג = (short int)12345; int main() { int א = ג; // a local variable, set to zero? printf(\(dqג is %d\en\(dq, ג); printf(\(dqא is %d\en\(dq, א); } .EE .UNINDENT .UNINDENT .SS misc\-misplaced\-const .sp این بررسی زمانی را تشخیص می‌دهد که یک توصیف‌کننده \fBconst\fP به‌جای اشاره‌شونده (pointee)، روی یک \fBtypedef\fP/ \fBusing\fP از نوع اشاره‌گر اعمال شده باشد؛ زیرا چنین ساختارهایی اغلب برای توسعه‌دهندگان گمراه‌کننده هستند چرا که \fBconst\fP به‌جای اشاره‌شونده، به خود اشاره‌گر اعمال می‌شود. .sp به‌عنوان مثال، در کد زیر، نوع حاصل \fBint * const\fP است نه \fBconst int *\fP: .INDENT 0.0 .INDENT 3.5 .sp .EX typedef int *int_ptr; void f(const int_ptr ptr) { *ptr = 0; // potentially quite unexpectedly the int can be modified here ptr = 0; // does not compile } .EE .UNINDENT .UNINDENT .sp اگر نوع زیربنایی \fBtypedef\fP/\fBusing\fP اشاره‌گری به یک نوع \fBconst\fP یا اشاره‌گر تابع باشد، این بررسی هشداری نمی‌دهد. دلیل این امر آن است که توصیف‌کننده \fBconst\fP کمتر ممکن است اشتباه گرفته شود، چرا که روی نوع اشاره‌شونده زیربنایی زائد (یا غیرمجاز) خواهد بود. .SS misc\-multiple\-inheritance .sp اگر کلاسی از چندین کلاس که تماماً مجازی محض (pure virtual) نیستند ارث‌بری کند، هشدار می‌دهد. .sp به‌عنوان مثال، اعلان کلاسی که از چندین کلاس انضمامی (concrete) ارث‌بری کند غیرمجاز است: .INDENT 0.0 .INDENT 3.5 .sp .EX class Base_A { public: virtual int foo() { return 0; } }; class Base_B { public: virtual int bar() { return 0; } }; // Warning class Bad_Child1 : public Base_A, Base_B {}; .EE .UNINDENT .UNINDENT .sp کلاسی که از کلاس‌های مجازی محض ارث‌بری کند مجاز است: .INDENT 0.0 .INDENT 3.5 .sp .EX class Interface_A { public: virtual int foo() = 0; }; class Interface_B { public: virtual int bar() = 0; }; // No warning class Good_Child1 : public Interface_A, Interface_B { virtual int foo() override { return 0; } virtual int bar() override { return 0; } }; .EE .UNINDENT .UNINDENT .SS منابع .sp ویژگی‌های غیرمجاز در Fuchsia را در این نشانی مشاهده کنید: \% .SS misc\-new\-delete\-overloads .sp بررسی \fIcert\-dcl54\-cpp\fP به‌عنوان نام مستعار این بررسی به اینجا هدایت می‌شود. .sp این بررسی توابع عملگر بازنویسی‌شدهٔ (overloaded) \fBnew()\fP و عملگر \fBdelete()\fP را که تابع ذخیره‌سازی آزاد (free store) متناظر آن‌ها در همان حوزه تعریف نشده است، پرچم‌گذاری می‌کند. برای مثال، این بررسی پیاده‌سازی عملگر غیرپایگانی (non-placement) \fBnew()\fP در یک کلاس را زمانی که کلاس یک تابع عملگر غیرپایگانی \fBdelete()\fP را نیز به‌طور هم‌زمان تعریف نکرده باشد، پرچم‌گذاری می‌کند. .sp این بررسی عملگرهای تعریف‌شده به‌صورت ضمنی، عملگرهای حذف‌شده (deleted) یا خصوصی (private)، یا عملگرهای جایابی (placement) را پرچم‌گذاری نمی‌کند. .sp این بررسی با قانون DCL54\-CPP از استاندارد کدنویسی CERT C++ مطابقت دارد: Overload allocation and deallocation functions as a pair in the same scope \%\&. .SS misc\-no\-recursion .sp توابع با اتصالات قوی را می‌یابد (با تحلیل نمودار فراخوانی برای SCCها یا مؤلفه‌های به‌شدت متصل که حلقه هستند)، هر تابع موجود در چرخه را شناسایی و عیب‌یابی می‌کند، و یک نمونه از حلقه نمودار فراخوانی ممکن (بازگشت یا recursion) را نمایش می‌دهد. .sp منابع: .INDENT 0.0 .IP \(bu 2 استاندارد کدنویسی CERT C++، قاعده DCL56\-CPP: Avoid cycles during initialization of static objects \%\&. .IP \(bu 2 استاندارد کدنویسی سازمانی JPL برای زبان برنامه‌نویسی C (JPL DOCID D\-60411)، قاعده \fI2.4 Do not use direct or indirect recursion\fP\&. .IP \(bu 2 مشخصات OpenCL، نسخه 1.2، قاعده 6.9 Restrictions: i. Recursion is not supported. \%\&. .UNINDENT .SS محدودیت‌ها .INDENT 0.0 .IP \(bu 2 این بررسی فراخوانی‌های انجام‌شده از طریق اشاره‌گرهای تابع را مدیریت نمی‌کند .IP \(bu 2 این بررسی مخرب‌های C++ را مدیریت نمی‌کند .UNINDENT .SS misc\-non\-copyable\-objects .sp بررسی \fIcert\-fio38\-c\fP به‌عنوان نام مستعار این بررسی به اینجا هدایت می‌شود. .sp ارجاع‌زدایی‌ها (dereferences) و اعلان‌های غیر اشاره‌گری اشیائی را که نباید با مقدار (by value) منتقل شوند، مانند شیءهای FILE در C یا شیءهای \fBpthread_mutex_t\fP در POSIX، پرچم‌گذاری می‌کند. .SS منابع .sp این بررسی با قانون FIO38\-C از استاندارد کدنویسی CERT C++ مطابقت دارد: Do not copy a FILE object \%\&. .SS misc\-non\-private\-member\-variables\-in\-classes .sp بررسی \fIcppcoreguidelines\-non\-private\-member\-variables\-in\-classes\fP به‌عنوان نام مستعار این بررسی به اینجا هدایت می‌شود. .sp کلاس‌هایی را می‌یابد که علاوه‌بر توابع عضو غیرایستای اعلان‌شده توسط کاربر، شامل اعضای داده‌ای غیرایستا نیز هستند، و تمامی اعضای داده‌ای را که با مشخص‌کننده دسترسی غیر از \fBpublic\fP اعلان شده‌اند عیب‌یابی می‌کند. این اعضای داده‌ای باید به‌صورت \fBprivate\fP اعلان شوند و از طریق توابع عضو دسترسی داشته باشند، به‌جای اینکه در معرض کلاس‌های مشتق‌شده یا مصرف‌کنندگان کلاس قرار گیرند. .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoreClassesWithAllMemberVariablesBeingPublic در صورت تنظیم روی \fItrue\fP، امکان نادیده‌گرفتن کامل کلاس‌ها را فراهم می‌کند اگر \fBتمام\fP متغیرهای عضو در آن کلاس با مشخص‌کننده دسترسی \fBpublic\fP اعلان شده باشند. پیش‌فرض \fIfalse\fP است. .UNINDENT .INDENT 0.0 .TP .B IgnorePublicMemberVariables در صورت تنظیم روی \fItrue\fP، امکان نادیده‌گرفتن (عدم عیب‌یابی) \fBتمام\fP متغیرهای عضو اعلان‌شده با مشخص‌کننده دسترسی \fBpublic\fP را فراهم می‌کند. پیش‌فرض \fIfalse\fP است. .UNINDENT .SS misc\-override\-with\-different\-visibility .sp بازنویسی‌های (overrides) توابع مجازی را که دارای سطح دسترسی (visibility) متفاوتی نسبت به تابع موجود در کلاس پایه هستند شناسایی می‌کند. این مورد به عنوان مثال شامل حالتی می‌شود که در آن یک تابع مجازی به عنوان \fBprivate\fP اعلان شده اما در یک زیرکلاس بازنویسی شده و به صورت \fBpublic\fP اعلان شده باشد. تغییر شناسایی‌شده عبارت است از تغییر سطح دسترسی ناشی از کلیدواژه‌های \fBpublic\fP، \fBprotected\fP و \fBprivate\fP در توابع مجازی بازنویسی‌شده. این بررسی برای هر تابع مجازی عادی و به صورت اختیاری برای مخرب‌ها (destructors) یا عملگرها اعمال می‌شود. استفاده از کلیدواژه \fBusing\fP توسط این بررسی به عنوان تغییر سطح دسترسی در نظر گرفته نمی‌شود. .INDENT 0.0 .INDENT 3.5 .sp .EX class A { public: virtual void f_pub(); private: virtual void f_priv(); }; class B: public A { public: void f_priv(); // warning: changed visibility from private to public private: void f_pub(); // warning: changed visibility from public to private }; class C: private A { // no warning: f_pub becomes private in this case but this is from the // private inheritance }; class D: private A { public: void f_pub(); // warning: changed visibility from private to public // \(aqf_pub\(aq would have private access but is forced to be // public }; .EE .UNINDENT .UNINDENT .sp اگر سطح دسترسی به این شیوه تغییر کند، می‌تواند نشان‌دهنده طراحی نادرست یا خطای برنامه‌نویسی باشد. .sp اگر یک تابع مجازی در یک زیرکلاس خصوصی (\fBprivate\fP) باشد اما در کلاس پایه عمومی (\fBpublic\fP) باشد، همچنان می‌توان از طریق اشاره‌گری به زیرکلاس در صورتی که اشاره‌گر به نوع پایه تبدیل شود، به آن دسترسی داشت. احتمالاً می‌توان به جای آن از ارث‌بری خصوصی (private inheritance) استفاده کرد. .sp یک تابع مجازی محافظت‌شده (\fBprotected\fP) که در یک زیرکلاس به صورت عمومی (\fBpublic\fP) درمی‌آید ممکن است کاربردهای معتبری داشته باشد، اما تأثیر مشابه (نه دقیقاً یکسان) را می‌توان با کلیدواژه \fBusing\fP به دست آورد. .SS گزینه‌ها .INDENT 0.0 .TP .B DisallowedVisibilityChange کنترل می‌کند که چه نوع تغییری در سطح دسترسی توسط این بررسی شناسایی شود. مقادیر ممکن عبارتند از \fIany\fP، \fIwidening\fP، \fInarrowing\fP\&. برای نمونه، گزینه \fIwidening\fP تنها در صورتی هشدار تولید می‌کند که سطح دسترسی از محدودتر (\fBprivate\fP) به کمتر محدودکننده (\fBpublic\fP) تغییر یابد. مقدار پیش‌فرض \fIany\fP است\&. .UNINDENT .INDENT 0.0 .TP .B CheckDestructors اگر روی \fItrue\fP تنظیم شود، این بررسی روی مخرب‌ها نیز اعمال می‌شود. در غیر این صورت مخرب‌ها توسط این بررسی نادیده گرفته می‌شوند. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .INDENT 0.0 .TP .B CheckOperators اگر روی \fItrue\fP تنظیم شود، این بررسی روی عملگرهای سربارگذاری‌شده C++ (به عنوان توابع عضو مجازی) نیز اعمال می‌شود. این مورد شامل سایر توابع عضو ویژه (مانند تبدیلات) نیز می‌شود. این گزینه احتمالاً تنها در موارد نادری کاربرد دارد زیرا عملگرها و تبدیلات به ندرت توابع مجازی هستند. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .INDENT 0.0 .TP .B IgnoredFunctions این گزینه می‌تواند برای نادیده گرفتن بررسی در توابع مشخص استفاده شود. برای پیکربندی این گزینه، باید فهرستی از نام‌های توابع که با نقطه\-ویرگول (semicolon) از هم جدا شده‌اند ارائه شود. این فهرست می‌تواند شامل عبارات باقاعده (regular expressions) باشد، از این طریق می‌توان تمام توابع یک کلاس خاص (مانند \fIMyClass::.*\fP) یا یک تابع خاص از هر کلاسی (مانند \fImy_function\fP یا \fI::.*::my_function\fP) را انتخاب کرد. تطبیق نام توابع بر اساس کلاس پایه انجام می‌شود. مقدار پیش‌فرض یک رشته خالی است. .UNINDENT .SS misc\-predictable\-rand .sp درباره استفاده از \fBstd::rand()\fP هشدار می‌دهد. مولدهای اعداد شبه‌تصادفی از الگوریتم‌های ریاضی برای تولید توالی‌ای از اعداد با ویژگی‌های آماری خوب استفاده می‌کنند، اما اعداد تولیدشده واقعاً تصادفی نیستند. تابع \fBstd::rand()\fP یک دانه یا سید (عدد) می‌گیرد، یک عملیات ریاضی روی آن اجرا می‌کند و نتیجه را برمی‌گرداند. با دستکاری دانه (seed)، نتیجه می‌تواند قابل پیش‌بینی باشد. .SS مراجع .sp این بررسی با قواعد استانداردهای کدنویسی CERT C زیر مطابقت دارد: MSC30\-C. Do not use the rand() function for generating pseudorandom numbers \%\&. MSC50\-CPP. Do not use std::rand() for generating pseudorandom numbers \%\&. .SS misc\-redundant\-expression .sp عبارت‌های زائد را که معمولاً خطاهایی ناشی از کپی\-پیست هستند شناسایی می‌کند. .sp بسته به عملگر، عبارت‌ها ممکن است: .INDENT 0.0 .IP \(bu 2 زائد باشند، .IP \(bu 2 همواره \fBtrue\fP باشند، .IP \(bu 2 همواره \fBfalse\fP باشند، .IP \(bu 2 همواره یک مقدار ثابت (صفر یا یک) باشند. .UNINDENT .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX ((x+1) | (x+1)) // (x+1) is redundant (p\->x == p\->x) // always true (p\->x < p\->x) // always false (speed \- speed + 1 == 12) // speed \- speed is always zero int b = a | 4 | a // identical expr on both sides ((x=1) | (x=1)) // expression is identical (DEFINE_1 | DEFINE_1) // same macro on the both sides ((DEF_1 + DEF_2) | (DEF_1+DEF_2)) // expressions differ in spaces only .EE .UNINDENT .UNINDENT .sp اعداد ممیز شناور (Floats) مدیریت می‌شوند مگر در حالتی که NaNها به این صورت بررسی شوند: .INDENT 0.0 .INDENT 3.5 .sp .EX int TestFloat(float F) { if (F == F) // Identical float values used return 1; return 0; } int TestFloat(float F) { // Testing NaN. if (F != F && F == F) // does not warn return 1; return 0; } .EE .UNINDENT .UNINDENT .SS misc\-static\-assert .sp بررسی \fIcert\-dcl03\-c\fP به عنوان یک نام مستعار برای این بررسی به اینجا تغییر مسیر می‌دهد. .sp در صورتی که شرط در زمان کامپایل قابل ارزیابی باشد، \fBassert()\fP را با \fBstatic_assert()\fP جایگزین می‌کند. .sp شرط \fBstatic_assert()\fP در زمان کامپایل ارزیابی می‌شود که ایمن‌تر و کارآمدتر است. .SS misc\-throw\-by\-value\-catch\-by\-reference .sp بررسی‌های \fIcert\-err09\-cpp\fP و \fIcert\-err61\-cpp\fP به عنوان نام‌های مستعار این بررسی به اینجا تغییر مسیر می‌دهند. .sp نقض‌های قاعدهٔ \(dqThrow by value, catch by reference\(dq را می‌یابد که به عنوان مثال در کتاب \(dqC++ Coding Standards\(dq نوشتهٔ H. Sutter و A. Alexandrescu، و همچنین در قاعدهٔ ERR61\-CPP از استاندارد کدنویسی CERT C++ با عنوان Catch exceptions by lvalue reference \% مطرح شده است. .INDENT 0.0 .TP .B استثناها: .INDENT 7.0 .IP \(bu 2 پرتاب رشته‌های لیترال با وجود اشاره‌گر بودن پرچم‌گذاری نخواهد شد. آن‌ها در معرض تکه‌تکه‌شدن (slicing) نیستند و استفاده از رشته‌های لیترال امری مصطلح است. .IP \(bu 2 گرفتن اشاره‌گرهای نویسه‌ای (\fBchar\fP، \fBwchar_t\fP، انواع نویسه‌ای یونیکد) به منظور فراهم کردن امکان دریافت رشته‌های لیترال پرچم‌گذاری نخواهد شد. .IP \(bu 2 مقدارهای نام‌گذاری‌شده‌ای که منتقل شده‌اند (moved named values) به عنوان پرتاب نکردن یک متغیر موقت ناشناس پرچم‌گذاری نخواهند شد. در این حالت می‌توان مطمئن بود که کاربر می‌داند که شیء در خارج از بلوک‌های catch رسیدگی‌کننده به خطا قابل دسترسی نیست. .IP \(bu 2 پرتاب پارامترهای تابع به عنوان عدم پرتاب یک متغیر موقت ناشناس پرچم‌گذاری نخواهد شد. این امر اجازه می‌دهد تا از توابع کمکی برای پرتاب استفاده شود. .IP \(bu 2 پرتاب مجدد (re-throw) متغیرهای استثنای دریافت‌شده به عنوان عدم پرتاب یک متغیر موقت ناشناس پرچم‌گذاری نخواهد شد. هرچند این کار معمولاً تنها با نوشتن \fBthrow;\fP انجام‌پذیر است، اما در کدهای واقعی به اندازه کافی رخ می‌دهد. .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B CheckThrowTemporaries شناسایی نقض‌های توصیهٔ ERR09\-CPP در CERT با عنوان Throw anonymous temporaries را فعال می‌کند. پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B WarnOnLargeObject همچنین برای هر شیء بزرگ و بدیهی (trivial) که بر اساس مقدار گرفته شده باشد هشدار می‌دهد. گرفتن یک شیء بزرگ بر اساس مقدار خطرناک نیست، اما تأثیر منفی بر عملکرد می‌گذارد. حداکثر اندازهٔ شیئی که دریافت آن بدون هشدار مجاز است را می‌توان با استفاده از گزینهٔ \fIMaxSize\fP تنظیم کرد. پیش‌فرض \fIfalse\fP است. .UNINDENT .INDENT 0.0 .TP .B MaxSize حداکثر اندازهٔ شیئی که دریافت آن بدون هشدار مجاز است را مشخص می‌کند. تنها زمانی اعمال می‌شود که \fBWarnOnLargeObject\fP روی \fItrue\fP تنظیم شده باشد. اگر این گزینه توسط کاربر روی \fIstd::numeric_limits::max()\fP تنظیم شود، به مقدار پیش‌فرض بازمی‌گردد. پیش‌فرض اندازهٔ \fIsize_t\fP است. .UNINDENT .SS misc\-unconventional\-assign\-operator .sp اعلان‌های عملگرهای انتساب با انواع بازگشتی و/یا انواع آرگومان نادرست، و تعاریف با نوع بازگشتی درست اما عبارت‌های \fBreturn\fP اشتباه را پیدا می‌کند. .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 نوع بازگشتی باید \fBClass&\fP باشد. .IP \(bu 2 انتساب می‌تواند از نوع کلاس بر اساس مقدار، ارجاع lvalue ثابت (const)، ارجاع rvalue غیرثابت، یا از یک نوع کاملاً متفاوت (مانند \fBint\fP) باشد. .IP \(bu 2 عملگرهای private و حذف‌شده (deleted) نادیده گرفته می‌شوند. .IP \(bu 2 عملگر همیشه باید \fB*this\fP را برگرداند. .UNINDENT .UNINDENT .UNINDENT .SS misc\-uniqueptr\-reset\-release .sp عبارت \fBunique_ptr::reset(release())\fP را پیدا کرده و با \fBstd::move()\fP جایگزین می‌کند. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX std::unique_ptr x, y; x.reset(y.release()); \-> x = std::move(y); .EE .UNINDENT .UNINDENT .sp اگر \fBy\fP از قبل یک rvalue باشد، \fBstd::move()\fP اضافه نخواهد شد. \fBx\fP و \fBy\fP می‌توانند \fBstd::unique_ptr*\fP نیز باشند. .SS گزینه‌ها .INDENT 0.0 .TP .B IncludeStyle رشته‌ای که مشخص می‌کند کدام سبک include استفاده شود: \fIllvm\fP یا \fIgoogle\fP. پیش‌فرض \fIllvm\fP است. .UNINDENT .SS misc\-unused\-alias\-decls .sp اعلان‌های بلااستفادهٔ نام مستعارِ فضای نام (namespace alias) را پیدا می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX namespace my_namespace { class C {}; } namespace unused_alias = ::my_namespace; .EE .UNINDENT .UNINDENT .SS misc\-unused\-parameters .sp پارامترهای استفاده‌نشدهٔ توابع را می‌یابد. پارامترهای استفاده‌نشده ممکن است نشان‌دهندهٔ یک باگ در کد باشند (برای مثال زمانی که به اشتباه از یک پارامتر دیگر استفاده شده باشد). اصلاحات پیشنهادی یا نام پارامتر را کامنت می‌کنند یا در صورتی که تمام فراخوان‌های تابع در همان واحد ترجمه (translation unit) باشند و امکان به‌روزرسانی آن‌ها وجود داشته باشد، پارامتر را کاملاً حذف می‌کنند. .sp این بررسی مشابه عیب‌یابی کامپایلر با فلگ \fI\-Wunused\-parameter\fP است و می‌تواند برای آماده‌سازی یک پایگاه‌کد جهت فعال‌سازی آن عیب‌یابی مورد استفاده قرار گیرد. به طور پیش‌فرض این بررسی مداراگرتر است (به \fBStrictMode\fP \%<#cmdoption-arg-StrictMode> مراجعه کنید). .INDENT 0.0 .INDENT 3.5 .sp .EX void a(int i) { /*some code that doesn\(aqt use \(gai\(ga*/ } // becomes void a(int /*i*/) { /*some code that doesn\(aqt use \(gai\(ga*/ } .EE .UNINDENT .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX static void staticFunctionA(int i); static void staticFunctionA(int i) { /*some code that doesn\(aqt use \(gai\(ga*/ } // becomes static void staticFunctionA() static void staticFunctionA() { /*some code that doesn\(aqt use \(gai\(ga*/ } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B StrictMode هنگامی که روی \fIfalse\fP باشد (مقدار پیش‌فرض)، این بررسی پارامترهایی که به وضوح استفاده نشده‌اند را نادیده می‌گیرد؛ یعنی زمانی که بدنه تابع مربوطه خالی باشد (و در مورد سازنده‌ها \- هیچ مقداردهی اولیه‌ای در سازنده وجود نداشته باشد). زمانی که بدنه تابع خالی است، بعید است که یک پارامتر استفاده‌نشده از دید یک خواننده انسان دور بماند و اساساً جایی برای پنهان شدن یک باگ وجود ندارد. .UNINDENT .INDENT 0.0 .TP .B IgnoreVirtual تعیین می‌کند که آیا پارامترهای متدهای مجازی (virtual) باید بررسی شوند یا خیر. برای نادیده گرفتن آن‌ها، مقدار را روی \fItrue\fP تنظیم کنید. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .SS misc\-unused\-using\-decls .sp اعلان‌های \fBusing\fP بدون استفاده را می‌یابد. .sp اعلان‌های \fBusing\fP استفاده‌نشده در فایل‌های هدر تشخیص داده نخواهند شد، چرا که این اعلان‌ها بخشی از API عمومی هدر محسوب می‌شوند. پسوندهای مجاز فایل‌های هدر را می‌توان از طریق گزینه سراسری \fIHeaderFileExtensions\fP پیکربندی کرد\&. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX // main.cpp namespace n { class C; } using n::C; // Never actually used. .EE .UNINDENT .UNINDENT .SS misc\-use\-anonymous\-namespace .sp مواردی از توابع یا متغیرهای \fBstatic\fP اعلان‌شده در دامنه عمومی (global scope) را می‌یابد که می‌توان آن‌ها را به جای آن به یک فضای نام ناشناس (anonymous namespace) منتقل کرد. .sp فضاهای نام ناشناس طبق استاندارد C++ «جایگزین برتر» هستند. استفاده از \fBstatic\fP ابتدا برای منسوخ شدن (deprecation) پیشنهاد شد، اما بعداً برای حفظ سازگاری با C از حالت منسوخ خارج شد [1]. عبارت \fBstatic\fP یک مفهوم چندمعنایی است که در زمینه‌های مختلف معانی متفاوتی دارد، بنابراین می‌تواند باعث سردرگمی شود. .sp موارد زیر در استفاده از \fBstatic\fP بررسی و گزارش \fIنخواهند شد\fP: .INDENT 0.0 .IP \(bu 2 توابع یا متغیرها در فایل‌های هدر، زیرا فضاهای نام ناشناس در هدرها یک الگوی نامناسب (antipattern) در نظر گرفته می‌شوند. پسوندهای مجاز فایل‌های هدر را می‌توان از طریق گزینه سراسری \fIHeaderFileExtensions\fP پیکربندی کرد\&. .IP \(bu 2 متغیرهای \fBconst\fP یا \fBconstexpr\fP، زیرا آن‌ها از پیش در C++ دارای پیوند درونی (internal linkage) ضمنی هستند. .UNINDENT .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX // Bad static void foo(); static int x; // Good namespace { void foo(); int x; } // namespace .EE .UNINDENT .UNINDENT .sp [1] Undeprecating static \% .SS misc\-use\-internal\-linkage .sp متغیرها، توابع و کلاس‌هایی را شناسایی می‌کند که می‌توان آن‌ها را به عنوان static علامت‌گذاری کرد یا (در C++) به یک فضای نام ناشناس منتقل نمود تا پیوند درونی (internal linkage) اعمال شود. .sp هر موجودیتی که فقط درون یک فایل مورد استفاده قرار می‌گیرد باید پیوند درونی داشته باشد. انجام این کار اطلاعات بیشتری در اختیار کامپایلر قرار می‌دهد و به آن اجازه می‌دهد کدهای مرده (dead code) را بهتر حذف کرده و بهینه‌سازی‌های تهاجمی‌تری انجام دهد. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX int v1; // can be marked as static void fn1() {} // can be marked as static // already declared as extern extern int v2; void fn3(); // without function body in all declaration, maybe external linkage void fn3(); // === C++\-specific === struct S1 {}; // can be moved into anonymous namespace namespace { // already in anonymous namespace int v2; void fn2(); struct S2 {}; } // export declarations export void fn4() {} export namespace t { void fn5() {} } export int v2; export class C {}; .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B FixMode نوع اصلاحی که این بررسی باید ارائه دهد را تعیین می‌کند. مقدار پیش‌فرض \fIUseStatic\fP است\&. .INDENT 7.0 .IP \(bu 2 \fINone\fP اصلاح خودکار انجام ندهد. .IP \(bu 2 \fIUseStatic\fP افزودن \fBstatic\fP برای متغیرها و توابع دارای پیوند درونی. .UNINDENT .UNINDENT .INDENT 0.0 .TP .B AnalyzeFunctions آیا پیشنهاد اعمال پیوند درونی برای توابع ارائه شود یا خیر. مقدار پیش‌فرض \fItrue\fP است\&. .UNINDENT .INDENT 0.0 .TP .B AnalyzeVariables آیا پیشنهاد اعمال پیوند درونی برای متغیرها ارائه شود یا خیر. مقدار پیش‌فرض \fItrue\fP است\&. .UNINDENT .INDENT 0.0 .TP .B AnalyzeTypes (فقط در C++) آیا پیشنهاد اعمال پیوند درونی برای انواع تعریف‌شده توسط کاربر (structها، classها، unionها و enumها) ارائه شود یا خیر. مقدار پیش‌فرض \fItrue\fP است\&. .UNINDENT .SS modernize\-avoid\-bind .sp این بررسی کاربردهای \fBstd::bind\fP و \fBboost::bind\fP را می‌یابد و آن‌ها را با عبارات لامبدا (lambdas) جایگزین می‌کند. لامبداها از تسخیر مقداری (value-capture) استفاده خواهند کرد، مگر اینکه تسخیر ارجاعی (reference capture) صراحتاً با استفاده از \fBstd::ref\fP یا \fBboost::ref\fP درخواست شده باشد\&. .sp از انواع مختلف فراخوان‌پذیرها (callables) از جمله متدهای عضو (member functions)، شیءهای تابعی (function objects) و توابع آزاد (free functions) و تمامی حالت‌های مختلف آن‌ها پشتیبانی می‌کند. هر چیزی که بتوان به عنوان آرگومان اول به \fBbind\fP پاس داد باید قابل تشخیص باشد. در حال حاضر، تنها حالت شناخته‌شده‌ای که در آن اصلاح خودکار (fix-it) پشتیبانی نمی‌شود این است که یک placeholder یکسان چندین بار در فهرست پارامترها مشخص شده باشد. .sp فرض کنید کد زیر وجود دارد: .INDENT 0.0 .INDENT 3.5 .sp .EX int add(int x, int y) { return x + y; } .EE .UNINDENT .UNINDENT .sp سپس کد: .INDENT 0.0 .INDENT 3.5 .sp .EX void f() { int x = 2; auto clj = std::bind(add, x, _1); } .EE .UNINDENT .UNINDENT .sp با این کد جایگزین می‌شود: .INDENT 0.0 .INDENT 3.5 .sp .EX void f() { int x = 2; auto clj = [=](auto && arg1) { return add(x, arg1); }; } .EE .UNINDENT .UNINDENT .sp خواندن کدهای شامل \fBstd::bind\fP می‌تواند دشوار باشد و به دلیل اطلاعات مربوط به نوع داده (type information) که در لامبداهای معادل تولید نمی‌شود، می‌تواند منجر به ایجاد فایل‌های شیء (object files) و فایل‌های اجرایی باینری با حجم بزرگ‌تر گردد. .SS گزینه‌ها .INDENT 0.0 .TP .B PermissiveParameterList اگر این گزینه روی \fItrue\fP تنظیم شود، بررسی عبارت \fBauto&&...\fP را به انتهای هر فهرست پارامتر جای‌نگهدار (placeholder) اضافه می‌کند. بدون این گزینه، ممکن است یک تبدیل اصلاحی (fix\-it) در مواردی که نتیجهٔ \fBbind\fP در بستر یک فانکتور با نوع حذف‌شده (type erased) مانند \fBstd::function\fP استفاده می‌شود که آرگومان‌های ناهمسان را می‌پذیرد، تبدیل نادرستی انجام دهد. مقدار پیش‌فرض \fIfalse\fP است. .UNINDENT .sp برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX int add(int x, int y) { return x + y; } int foo() { std::function ignore_args = std::bind(add, 2, 2); return ignore_args(3, 3); } .EE .UNINDENT .UNINDENT .sp کد معتبری است و مقدار \fI4\fP را برمی‌گرداند. مقادیر واقعی ارسال‌شده به \fBignore_args\fP به سادگی نادیده گرفته می‌شوند. بدون \fBPermissiveParameterList\fP، این کد به صورت زیر تبدیل می‌شود: .INDENT 0.0 .INDENT 3.5 .sp .EX int add(int x, int y) { return x + y; } int foo() { std::function ignore_args = [] { return add(2, 2); } return ignore_args(3, 3); } .EE .UNINDENT .UNINDENT .sp که کامپایل \fIنخواهد شد\fP، زیرا لامبدا شامل یک \fBoperator()\fP که ۲ آرگومان بپذیرد نیست. در صورت فعال بودن فهرست پارامتر مجاز (permissive parameter list)، در عوض کد زیر تولید می‌شود: .INDENT 0.0 .INDENT 3.5 .sp .EX int add(int x, int y) { return x + y; } int foo() { std::function ignore_args = [](auto&&...) { return add(2, 2); } return ignore_args(3, 3); } .EE .UNINDENT .UNINDENT .sp که درست است. .sp اجرای این بررسی نیازمند استفاده از C++14 یا بالاتر است. .SS modernize\-avoid\-c\-arrays .sp بررسی \fIcppcoreguidelines\-avoid\-c\-arrays\fP به عنوان یک نام مستعار برای این بررسی به اینجا هدایت می‌شود. .sp بررسی \fIhicpp\-avoid\-c\-arrays\fP به عنوان یک نام مستعار برای این بررسی به اینجا هدایت می‌شود. .sp انواع آرایه‌های به سبک C را پیدا کرده و استفاده از \fBstd::array<>\fP / \fBstd::vector<>\fP را توصیه می‌کند. تمامی انواع آرایه‌های C شناسایی و عیب‌یابی می‌شوند. .sp برای پارامترهایی با نوع آرایهٔ ناکامل به سبک C، بهتر است از \fBstd::span\fP / \fBgsl::span\fP به عنوان جایگزین استفاده شود. .sp با این حال، اصلاحات خودکار (fix\-it) در فایل‌های سرآیند بالقوه خطرناک هستند و بنابراین در حال حاضر ارائه نمی‌شوند. .INDENT 0.0 .INDENT 3.5 .sp .EX int a[] = {1, 2}; // warning: do not declare C\-style arrays, use \(aqstd::array\(aq instead int b[1]; // warning: do not declare C\-style arrays, use \(aqstd::array\(aq instead void foo() { int c[b[0]]; // warning: do not declare C VLA arrays, use \(aqstd::vector\(aq instead } template class array { T d[Size]; // warning: do not declare C\-style arrays, use \(aqstd::array\(aq instead int e[1]; // warning: do not declare C\-style arrays, use \(aqstd::array\(aq instead }; array d; // warning: do not declare C\-style arrays, use \(aqstd::array\(aq instead using k = int[4]; // warning: do not declare C\-style arrays, use \(aqstd::array\(aq instead .EE .UNINDENT .UNINDENT .sp با این حال، کدهای \fBextern \(dqC\(dq\fP نادیده گرفته می‌شوند، زیرا اشتراک‌گذاری چنین سرآیندهایی بین کدهای C و کدهای C++ رایج است. .INDENT 0.0 .INDENT 3.5 .sp .EX // Some header extern \(dqC\(dq { int f[] = {1, 2}; // not diagnosed int j[1]; // not diagnosed inline void bar() { { int j[j[0]]; // not diagnosed } } } .EE .UNINDENT .UNINDENT .sp به طور مشابه، تابع \fBmain()\fP نادیده گرفته می‌شود. پارامتر دوم و سوم آن می‌تواند \fBchar* argv[]\fP یا \fBchar** argv\fP باشد، اما نمی‌تواند \fBstd::array<>\fP باشد. .SS گزینه‌ها .INDENT 0.0 .TP .B AllowStringArrays هنگامی که روی \fItrue\fP تنظیم شود (پیش‌فرض \fIfalse\fP است)، متغیرهایی از نوع آرایهٔ نویسه‌ای با طول استنتاج‌شده که مستقیماً از رشته‌های لفظی (string literals) مقداردهی اولیه شده‌اند، نادیده گرفته می‌شوند. این گزینه بر مواردی که طول قابل استنتاج نیست و مشابه اشاره‌گرها هستند، مانند اعضای کلاس و پارامترها، تأثیری ندارد. مثال: .INDENT 7.0 .INDENT 3.5 .sp .EX const char name[] = \(dqSome name\(dq; .EE .UNINDENT .UNINDENT .UNINDENT .SS modernize\-avoid\-c\-style\-cast .sp موارد استفاده از تبدیل نوع‌های به سبک C (C\-style casts) را پیدا می‌کند. .sp تبدیل نوع‌های به سبک C می‌توانند تبدیلات گوناگونی را انجام دهند (\fBconst_cast\fP، \fBstatic_cast\fP، \fBreinterpret_cast\fP، یا ترکیبی از آن‌ها). این امر آن‌ها را خطرناک می‌سازد زیرا هدف تبدیل مشخص نیست، و ممکن است به طور خاموش تبدیلات ناامنی بین انواع ناسازگار انجام دهند. .sp این بررسی مشابه \fI\-Wold\-style\-cast\fP است، اما در برخی موارد اصلاحات خودکار را پیشنهاد می‌دهد. مکان‌های گزارش‌شده نباید با موارد تولیدشده توسط \fI\-Wold\-style\-cast\fP تفاوتی داشته باشند. .SS مثال‌ها .INDENT 0.0 .INDENT 3.5 .sp .EX class A { public: std::string v; }; A a; double *num = (double*)(&a); // Compiles! Hides danger // num = static_cast(&a); // Won\(aqt compile (good!) num = reinterpret_cast(&a); // Compiles, danger is explicit .EE .UNINDENT .UNINDENT .SS مراجع .sp نام بررسی متناظر در cpplint.py: \fIreadability/casting\fP\&. .SS modernize\-avoid\-setjmp\-longjmp .sp تمام عبارت‌های فراخوانی شامل \fBsetjmp()\fP و \fBlongjmp()\fP را در کد C++ علامت‌گذاری می‌کند. .sp به جای آن‌ها باید از مدیریت استثنا با \fBthrow\fP و \fBcatch\fP استفاده شود. .SS مراجع .sp این بررسی با قاعدهٔ استاندارد کدنویسی CERT C++ مطابقت دارد: ERR52\-CPP. Do not use setjmp() or longjmp() \%\&. .SS modernize\-avoid\-variadic\-functions .sp تمام تعاریف توابع (نه اعلان‌ها) از توابع با آرگومان متغیر (variadic) به سبک C را پیدا می‌کند. .sp به جای توابع با آرگومان متغیر به سبک C، باید از بسته پارامترهای تابع (parameter pack) در C++ استفاده شود. .SS مراجع .sp این بررسی با قاعدهٔ استاندارد کدنویسی CERT C++ مطابقت دارد: DCL50\-CPP. Do not define a C\-style variadic function \%\&. .SS modernize\-concat\-nested\-namespaces .sp استفاده از فضاهای نام تودرتو مانند \fBnamespace a { namespace b { ... } }\fP را بررسی کرده و پیشنهاد تغییر آن به ساختار موجزتر معرفی‌شده در C++17 را می‌دهد: \fBnamespace a::b { ... }\fP\&. فضاهای نام درون‌خطی (inline) تغییر داده نمی‌شوند. .sp به عنوان مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX namespace n1 { namespace n2 { void t(); } } namespace n3 { namespace n4 { namespace n5 { void t(); } } namespace n6 { namespace n7 { void t(); } } } // in c++20 namespace n8 { inline namespace n9 { void t(); } } .EE .UNINDENT .UNINDENT .sp به شکل زیر تغییر خواهد یافت: .INDENT 0.0 .INDENT 3.5 .sp .EX namespace n1::n2 { void t(); } namespace n3 { namespace n4::n5 { void t(); } namespace n6::n7 { void t(); } } // in c++20 namespace n8::inline n9 { void t(); } .EE .UNINDENT .UNINDENT .SS modernize\-deprecated\-headers .sp برخی از فایل‌های هدر کتابخانهٔ C در C++ منسوخ شده‌اند و دیگر استفاده از آن‌ها در پایگاه‌های کد C++ توصیه نمی‌شود. برخی از آن‌ها هیچ تأثیری در C++ ندارند. برای جزئیات بیشتر به بخش [depr.c.headers] در استاندارد C++14 مراجعه کنید. .sp این بررسی، هدرهای کتابخانه استاندارد C را با معادل‌های C++ آن‌ها جایگزین کرده و موارد زائد را حذف می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX // C++ source file... #include #include // becomes #include // No \(aqstdbool.h\(aq here. .EE .UNINDENT .UNINDENT .sp نکتهٔ مهم: استاندارد تضمین نمی‌کند که هدرهای C++ دقیقاً تمام همان توابع را در فضای نام سراسری (global namespace) اعلان کنند. این بررسی در شکل فعلی خود می‌تواند کدهایی را که از نمادهای کتابخانه در فضای نام سراسری استفاده می‌کنند، با شکست مواجه کند. .INDENT 0.0 .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP // deprecated since C++11 .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP // deprecated since C++11 .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP // deprecated since C++11 .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .UNINDENT .sp اگر استاندارد مشخص‌شده قدیمی‌تر از C++11 باشد، این بررسی فقط هدرهای منسوخ‌شده پیش از C++11 را جایگزین می‌کند، در غیر این صورت \-\- تمام هدرهایی که در فهرست قبلی آمده‌اند جایگزین خواهند شد. .sp این هدرها هیچ اثری در C++ ندارند: .INDENT 0.0 .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .IP \(bu 2 \fI\fP .UNINDENT .sp این بررسی‌کننده از دستورات \fIinclude\fP درون بلوک‌های \fIextern \(dqC\(dq { ... }\fP چشم‌پوشی می‌کند، چرا که ممکن است یک کتابخانه بخواهد رابط برنامه‌نویسی (API) مشخصی را برای کتابخانه‌های C و C++ ارائه دهد. .INDENT 0.0 .INDENT 3.5 .sp .EX // C++ source file... extern \(dqC\(dq { #include // Left intact. #include // Left intact. } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B CheckHeaderFile ابزار \fIclang\-tidy\fP نمی‌تواند تشخیص دهد که آیا فایل هدر include شده توسط فایل منبع C++ کنونیِ تحت تحلیل، توسط هیچ فایل منبع C دیگری include نشده است یا خیر. بنابراین، برای جلوگیری از مثبت کاذب (false-positive) و راهنمایی‌های تصحیح (fixit-hints) نادرست، از صدور گزارش‌ها در فایل‌های هدر صرف‌نظر می‌کنیم. کاربر در صورتی که بداند فایل‌های هدر در پروژه فقط توسط فایل‌های منبع C++ استفاده می‌شوند، می‌تواند این گزینه را روی \fItrue\fP تنظیم کند. مقدار پیش‌فرض \fIfalse\fP است\&. .UNINDENT .SS modernize\-deprecated\-ios\-base\-aliases .sp استفاده از نوع‌های عضو منسوخ‌شده‌ی \fBstd::ios_base\fP را شناسایی کرده و مواردی را که معادلِ غیرمنسوخ دارند، جایگزین می‌کند. .TS box center; l|l. T{ نوع عضو منسوخ‌شده T} T{ جایگزین T} _ T{ \fBstd::ios_base::io_state\fP T} T{ \fBstd::ios_base::iostate\fP T} _ T{ \fBstd::ios_base::open_mode\fP T} T{ \fBstd::ios_base::openmode\fP T} _ T{ \fBstd::ios_base::seek_dir\fP T} T{ \fBstd::ios_base::seekdir\fP T} _ T{ \fBstd::ios_base::streamoff\fP T} T{ T} _ T{ \fBstd::ios_base::streampos\fP T} T{ T} .TE .SS modernize\-loop\-convert .sp این بررسی حلقه‌های \fBfor(...; ...; ...)\fP را به استفاده از حلقه‌های جدید بر مبنای بازه (range-based) در C++11 تبدیل می‌کند. .sp سه نوع حلقه قابل تبدیل هستند: .INDENT 0.0 .IP \(bu 2 حلقه‌ها روی آرایه‌های ایستا تخصیص‌یافته. .IP \(bu 2 حلقه‌ها روی کانتینرها، با استفاده از تکرارکننده‌ها (iterators). .IP \(bu 2 حلقه‌ها روی کانتینرهای شبه‌آرایه، با استفاده از \fBoperator[]\fP و \fBat()\fP\&. .UNINDENT .SS گزینه MinConfidence .SS risky .sp در حلقه‌هایی که عبارت کانتینر پیچیده‌تر از صرفاً یک ارجاع به یک عبارت اعلان‌شده (متغیر، تابع، enum و غیره) باشد، و بخشی از آن در جای دیگری از حلقه ظاهر شود، به دلیل افزایش خطر تغییر در معناشناسی کد (semantics)، سطح اطمینان نسبت به تبدیل کاهش می‌یابد. تبدیل‌ها برای این حلقه‌ها به عنوان \fIrisky\fP علامت‌گذاری می‌شوند، و بنابراین تنها در صورتی تبدیل خواهند شد که حداقل سطح اطمینانِ لازم روی \fIrisky\fP تنظیم شده باشد\&. .INDENT 0.0 .INDENT 3.5 .sp .EX int arr[10][20]; int l = 5; for (int j = 0; j < 20; ++j) int k = arr[l][j] + l; // using l outside arr[l] is considered risky for (int i = 0; i < obj.getVector().size(); ++i) obj.foo(10); // using \(aqobj\(aq is considered risky .EE .UNINDENT .UNINDENT .sp برای مثالی از تبدیل نادرست در حالتی که حداقل سطح اطمینان لازم روی \fIrisky\fP تنظیم شده باشد، بخش Range\-based loops evaluate end() only once را مشاهده کنید. .SS reasonable (پیش‌فرض) .sp اگر یک حلقه پس از هر تکرار \fB\&.end()\fP یا \fB\&.size()\fP را فراخوانی کند، تبدیل آن حلقه به عنوان \fIreasonable\fP علامت‌گذاری می‌شود، و در نتیجه اگر سطح اطمینان لازم روی \fIreasonable\fP (پیش‌فرض) یا پایین‌تر تنظیم شده باشد تبدیل خواهد شد. .INDENT 0.0 .INDENT 3.5 .sp .EX // using size() is considered reasonable for (int i = 0; i < container.size(); ++i) cout << container[i]; .EE .UNINDENT .UNINDENT .SS safe .sp هر حلقهٔ دیگری که با معیارهای بالا برای علامت‌گذاری به عنوان \fIrisky\fP یا \fIreasonable\fP مطابقت نداشته باشد، به عنوان \fIsafe\fP علامت‌گذاری می‌شود، و بنابراین اگر سطح اطمینان لازم روی \fIsafe\fP یا پایین‌تر تنظیم شده باشد تبدیل خواهد شد. .INDENT 0.0 .INDENT 3.5 .sp .EX int arr[] = {1,2,3}; for (int i = 0; i < 3; ++i) cout << arr[i]; .EE .UNINDENT .UNINDENT .SS مثال .sp حالت اصلی: .INDENT 0.0 .INDENT 3.5 .sp .EX const int N = 5; int arr[] = {1,2,3,4,5}; vector v; v.push_back(1); v.push_back(2); v.push_back(3); // safe conversion for (int i = 0; i < N; ++i) cout << arr[i]; // reasonable conversion for (vector::iterator it = v.begin(); it != v.end(); ++it) cout << *it; // reasonable conversion for (vector::iterator it = begin(v); it != end(v); ++it) cout << *it; // reasonable conversion for (vector::iterator it = std::begin(v); it != std::end(v); ++it) cout << *it; // reasonable conversion for (int i = 0; i < v.size(); ++i) cout << v[i]; // reasonable conversion for (int i = 0; i < size(v); ++i) cout << v[i]; .EE .UNINDENT .UNINDENT .sp پس از اعمال بررسی با حداقل سطح اطمینان تنظیم‌شده روی \fIreasonable\fP (پیش‌فرض): .INDENT 0.0 .INDENT 3.5 .sp .EX const int N = 5; int arr[] = {1,2,3,4,5}; vector v; v.push_back(1); v.push_back(2); v.push_back(3); // safe conversion for (auto & elem : arr) cout << elem; // reasonable conversion for (auto & elem : v) cout << elem; // reasonable conversion for (auto & elem : v) cout << elem; .EE .UNINDENT .UNINDENT .SS پشتیبانی از تکرارگر معکوس (Reverse Iterator) .sp این مبدل همچنین قادر به تبدیل حلقه‌های تکرارگری است که از \fBrbegin\fP و \fBrend\fP برای پیمایش رو به عقب روی یک نگه‌دارنده (container) استفاده می‌کنند. به‌طور پیش‌فرض، این عمل در حالت C++20 با استفاده از کتابخانه \fBranges\fP به‌صورت خودکار انجام خواهد شد، با این حال می‌توان این بررسی را طوری پیکربندی کرد که بدون C++20 نیز با مشخص کردن تابعی برای معکوس کردن بازه و در صورت تمایل فایل هدر محل تعریف آن تابع، کار کند. .SS گزینه‌ها .INDENT 0.0 .TP .B UseCxx20ReverseRanges هنگامی که روی true تنظیم شود، در صورت قرار داشتن در حالت C++20 یا بالاتر، حلقه‌ها را با استفاده از \fBstd::views::reverse\fP تبدیل می‌کند. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B MakeReverseRangeFunction تابعی را مشخص می‌کند که برای معکوس کردن یک جفت تکرارگر به کار می‌رود؛ این تابع باید کلاسی با متدهای \fBrbegin\fP و \fBrend\fP را بپذیرد و کلاسی با متدهای \fBbegin\fP و \fBend\fP برگرداند که به ترتیب متدهای \fBrbegin\fP و \fBrend\fP را فراخوانی کنند. نمونه‌های متداول \fBstd::views::reverse\fP و \fBllvm::reverse\fP هستند. مقدار پیش‌فرض یک رشته خالی است. .UNINDENT .INDENT 0.0 .TP .B MakeReverseRangeHeader فایل هدری را مشخص می‌کند که \fBMakeReverseRangeFunction\fP در آن اعلان شده است. برای مثال‌های قبلی، این گزینه به ترتیب روی \fBrange/v3/view/reverse.hpp\fP و \fBllvm/ADT/STLExtras.h\fP تنظیم خواهد شد. اگر این گزینه یک رشته خالی باشد و \fBMakeReverseRangeFunction\fP تنظیم شده باشد، بررسی با این فرض ادامه می‌یابد که تابع هم‌اکنون در واحد ترجمه موجود است. می‌توان این مقدار را درون براکت‌های زاویه‌دار قرار داد تا مشخص شود include به عنوان یک include سیستمی اضافه شود. مقدار پیش‌فرض یک رشته خالی است. .UNINDENT .INDENT 0.0 .TP .B IncludeStyle رشته‌ای که سبک include مورد استفاده را مشخص می‌کند: \fIllvm\fP یا \fIgoogle\fP\&. مقدار پیش‌فرض \fIllvm\fP است. .UNINDENT .SS محدودیت‌ها .sp موقعیت‌های خاصی وجود دارد که در آن‌ها ممکن است ابزار به‌صورت نادرست دست به تبدیل‌هایی بزند که موجب حذف اطلاعات و تغییر معناشناسی (semantics) کد شود. کاربران ابزار باید از رفتار و محدودیت‌های این بررسی که در موارد زیر شرح داده شده است آگاه باشند. .SS کامنت‌های درون سرآیند حلقه .sp کامنت‌های درون سرآیند حلقه اصلی نادیده گرفته شده و هنگام تبدیل حذف می‌شوند. .INDENT 0.0 .INDENT 3.5 .sp .EX for (int i = 0; i < N; /* This will be deleted */ ++i) { } .EE .UNINDENT .UNINDENT .SS حلقه‌های مبتنی بر بازه end() را تنها یک‌بار ارزیابی می‌کنند .sp حلقه for مبتنی بر بازه C++11 متد \fB\&.end()\fP را در طول مقداردهی اولیه حلقه تنها یک بار فراخوانی می‌کند. اگر در حلقه اصلی \fB\&.end()\fP پس از هر تکرار فراخوانی شود، معناشناسی حلقه تبدیل‌شده ممکن است متفاوت باشد. .INDENT 0.0 .INDENT 3.5 .sp .EX // The following is semantically equivalent to the C++11 range\-based for loop, // therefore the semantics of the header will not change. for (iterator it = container.begin(), e = container.end(); it != e; ++it) { } // Instead of calling .end() after each iteration, this loop will be // transformed to call .end() only once during the initialization of the loop, // which may affect semantics. for (iterator it = container.begin(); it != container.end(); ++it) { } .EE .UNINDENT .UNINDENT .sp همان‌طور که در بالا توضیح داده شد، فراخوانی توابع عضو نگه‌دارنده درون بدنه حلقه \fIrisky\fP (پرخطر) در نظر گرفته می‌شود. اگر تابع عضو فراخوانی‌شده موجب تغییر نگه‌دارنده شود، به دلیل این‌که \fB\&.end()\fP تنها یک‌بار فراخوانی می‌شود، معناشناسی حلقه تبدیل‌شده متفاوت خواهد بود. .INDENT 0.0 .INDENT 3.5 .sp .EX bool flag = false; for (vector::iterator it = vec.begin(); it != vec.end(); ++it) { // Add a copy of the first element to the end of the vector. if (!flag) { // This line makes this transformation \(aqrisky\(aq. vec.push_back(*it); flag = true; } cout << *it; } .EE .UNINDENT .UNINDENT .sp کد اصلی بالا محتویات نگه‌دارنده را شامل عنصری که به تازگی اضافه شده است چاپ می‌کند، در حالی که حلقه تبدیل‌شده که در زیر نشان داده شده، تنها محتویات اولیه را چاپ کرده و عنصر اضافه شده جدید را چاپ نخواهد کرد. .INDENT 0.0 .INDENT 3.5 .sp .EX bool flag = false; for (auto & elem : vec) { // Add a copy of the first element to the end of the vector. if (!flag) { // This line makes this transformation \(aqrisky\(aq vec.push_back(elem); flag = true; } cout << elem; } .EE .UNINDENT .UNINDENT .sp همچنین اگر \fB\&.end()\fP دارای اثرات جانبی (side effects) باشد، معناشناسی تحت تأثیر قرار خواهد گرفت. به عنوان مثال، در حالتی که فراخوانی‌های \fB\&.end()\fP لاگ می‌شوند، اگر \fB\&.end()\fP در ابتدا پس از هر تکرار فراخوانی می‌شد، معناشناسی در حلقه تبدیل‌شده تغییر خواهد کرد. .INDENT 0.0 .INDENT 3.5 .sp .EX iterator end() { num_of_end_calls++; return container.end(); } .EE .UNINDENT .UNINDENT .SS عملگر بازتعریف‌شده operator\->() با اثرات جانبی .sp به طور مشابه، اگر \fBoperator\->()\fP طوری بارگذاری اضافه (overload) شده باشد که اثرات جانبی، مانند لاگ‌گیری، داشته باشد، معناشناسی تغییر خواهد کرد. اگر از \fBoperator\->()\fP تکرارگر در حلقه اصلی استفاده شده باشد، به دلیل بازارجاعی ضمنی (implicit dereference) به عنوان بخشی از حلقه for مبتنی بر بازه، با \fB.\fP جایگزین خواهد شد. بنابراین هرگونه اثر جانبی \fBoperator\->()\fP بارگذاری اضافه شده دیگر اجرا نخواهد شد. .INDENT 0.0 .INDENT 3.5 .sp .EX for (iterator it = c.begin(); it != c.end(); ++it) { it\->func(); // Using operator\->() } // Will be transformed to: for (auto & elem : c) { elem.func(); // No longer using operator\->() } .EE .UNINDENT .UNINDENT .SS اشاره‌گرها و ارجاع‌ها به کانتینرها .sp اگرچه بخش عمده‌ای از تحلیل ریسک این بررسی به تعیین اینکه آیا تکرارگر (iterator) یا کانتینر درون حلقه تغییر یافته است یا خیر اختصاص دارد، اما دور زدن این تحلیل از طریق دسترسی و تغییر کانتینر به وسیله یک اشاره‌گر یا ارجاع ممکن است. .sp اگر کانتینر به جای استفاده از اشاره‌گر یا ارجاع به طور مستقیم استفاده می‌شد، تبدیل زیر تنها در سطح \fIrisky\fP اعمال می‌شد، چرا که فراخوانی یک تابع عضو از کانتینر به عنوان \fIrisky\fP در نظر گرفته می‌شود. این بررسی نمی‌تواند عبارت‌های مرتبط با کانتینر را که متفاوت از عبارت استفاده شده در سرآیند حلقه هستند شناسایی کند، بنابراین تبدیل زیر در نهایت در سطح \fIsafe\fP انجام می‌شود. .INDENT 0.0 .INDENT 3.5 .sp .EX vector vec; vector *ptr = &vec; vector &ref = vec; for (vector::iterator it = vec.begin(), e = vec.end(); it != e; ++it) { if (!flag) { // Accessing and modifying the container is considered risky, but the risk // level is not raised here. ptr\->push_back(*it); ref.push_back(*it); flag = true; } } .EE .UNINDENT .UNINDENT .SS OpenMP .sp از آنجا که حلقه‌های for بر پایه بازه (range-based) تنها از نسخه OpenMP 5 به بعد در دسترس هستند، این بررسی نباید بر روی کدهایی با نیاز به سازگاری با نسخه‌های پیشین OpenMP 5 استفاده شود. این بررسی \fBبه‌عمد\fP هیچ تلاشی برای مستثنی کردن عیب‌یابی‌های نادرست در حلقه‌های for مربوط به نسخه‌های قبل از OpenMP 5 انجام نمی‌دهد. .sp برای جلوگیری از اعمال شدن (و خراب کردن) این بررسی روی حلقه‌های for متعلق به OpenMP، در عین حال که همچنان بر روی حلقه‌های for غیر OpenMP اعمال شود، استفاده از \fBNOLINT\fP (به بخش Suppressing Undesired Diagnostics \%<#\:clang-tidy-nolint> مراجعه کنید) روی حلقه‌های for خاص پیشنهاد می‌شود. .SS modernize\-macro\-to\-enum .sp گروه‌هایی از ماکروهای مجاور را با یک enum ناشناس بدون دامنه (unscoped anonymous enum) جایگزین می‌کند. استفاده از یک enum ناشناس بدون دامنه تضمین می‌کند در هر جایی که قبلاً از توکن ماکرو استفاده شده بود، نام شمارنده (enumerator) بتواند با اطمینان استفاده شود. .sp این بررسی می‌تواند برای اعمال راهنمای هسته C++ با عنوان Enum.1: Prefer enumerations over macros \%، تحت محدودیت‌های ذکر شده در زیر به کار رود. .sp ماکروهای بالقوه برای جایگزینی باید محدودیت‌های زیر را برآورده کنند: .INDENT 0.0 .IP \(bu 2 ماکروها فقط باید به توکن‌های لیترال صحیح (integral literal) یا عباراتی از توکن‌های لیترال بسط یابند. این عبارت می‌تواند شامل هر یک از عملگرهای یگانی \fB\-\fP، \fB+\fP، \fB~\fP یا \fB!\fP، هر یک از عملگرهای دوتایی \fB,\fP، \fB\-\fP، \fB+\fP، \fB*\fP، \fB/\fP، \fB%\fP، \fB&\fP، \fB|\fP، \fB^\fP، \fB<\fP، \fB>\fP، \fB<=\fP، \fB>=\fP، \fB==\fP، \fB!=\fP، \fB||\fP، \fB&&\fP، \fB<<\fP، \fB>>\fP یا \fB<=>\fP، عملگر سه‌گانه \fB?:\fP و افزونه GNU آن \% باشد. عبارت‌های داخل پرانتز نیز شناخته می‌شوند. این امر بیشتر عبارت‌های معتبر را شناسایی می‌کند. به ویژه، عبارت‌های دارای عملگر \fBsizeof\fP شناخته نمی‌شوند. .IP \(bu 2 ماکروها باید در خطوط متوالی فایل مبدأ تعریف شوند، یا تنها خطوط توضیحات (comment) بین تعاریف ماکروها وجود داشته باشد. .IP \(bu 2 همه ماکروها باید در همان یک فایل مبدأ تعریف شده باشند. .IP \(bu 2 ماکروها نباید در داخل یک بلوک کامپایل شرطی تعریف شده باشند. (include guardهای شرطی از این محدودیت مستثنی هستند.) .IP \(bu 2 ماکروها نباید در مجاورت سایر دستورات پیش‌پردازنده تعریف شده باشند. .IP \(bu 2 ماکروها نباید در هیچ دستور شرطی پیش‌پردازنده استفاده شده باشند. .IP \(bu 2 ماکروها نباید به عنوان آرگومان برای ماکروهای دیگر استفاده شوند. .IP \(bu 2 ماکروها نباید لغو تعریف (undefined) شده باشند. .IP \(bu 2 ماکروها باید در بالاترین سطح (top-level) تعریف شده باشند، نه درون هیچ اعلان یا تعریفی. .UNINDENT .sp هر دسته‌ای از ماکروها که محدودیت‌های بالا را برآورده کند به عنوان مجموعه‌ای از مقادیر مناسب برای جایگزینی با یک enum ناشناس در نظر گرفته می‌شود. از آنجا، توسعه‌دهنده می‌تواند در صورت تمایل نامی به enum ناشناس بدهد و بازآفرینی کد (refactoring) را به یک enum دارای دامنه (scoped enum) ادامه دهد. توضیحات موجود در همان خط تعریف ماکرو یا بین تعاریف متوالی ماکرو در خروجی حفظ می‌شوند. هیچ قالب‌بندی خاصی در جایگزینی‌های ارائه شده اعمال نمی‌شود، اگرچه clang\-tidy می‌تواند به صورت اختیاری تمام اصلاحات را قالب‌بندی کند. .sp \fBهشدار:\fP .INDENT 0.0 .INDENT 3.5 عبارت‌های مقداردهی اولیه به عنوان مقداردهنده‌های معتبر برای یک enum فرض می‌شوند. زبان C ایجاب می‌کند که مقادیر enum در یک \fBint\fP جا شوند، اما ممکن است این مورد برای برخی عبارت‌های ثابت پذیرفته شده صادق نباشد. برای نمونه \fB1 << 40\fP هنگامی که اندازه \fBint\fP برابر ۳۲ بیت است در یک \fBint\fP جا نخواهد شد. .UNINDENT .UNINDENT .sp مثال‌ها: .INDENT 0.0 .INDENT 3.5 .sp .EX #define RED 0xFF0000 #define GREEN 0x00FF00 #define BLUE 0x0000FF #define TM_NONE (\-1) // No method selected. #define TM_ONE 1 // Use tailored method one. #define TM_TWO 2 // Use tailored method two. Method two // is preferable to method one. #define TM_THREE 3 // Use tailored method three. .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX enum { RED = 0xFF0000, GREEN = 0x00FF00, BLUE = 0x0000FF }; enum { TM_NONE = (\-1), // No method selected. TM_ONE = 1, // Use tailored method one. TM_TWO = 2, // Use tailored method two. Method two // is preferable to method one. TM_THREE = 3 // Use tailored method three. }; .EE .UNINDENT .UNINDENT.SS modernize\-make\-shared .sp این بررسی ساخت اشیاء \fBstd::shared_ptr\fP را از طریق فراخوانی صریح سازنده به همراه یک عبارت \fBnew\fP پیدا کرده و آن را با فراخوانی \fBstd::make_shared\fP جایگزین می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX auto my_ptr = std::shared_ptr(new MyPair(1, 2)); // becomes auto my_ptr = std::make_shared(1, 2); .EE .UNINDENT .UNINDENT .sp این بررسی همچنین فراخوانی‌های \fBstd::shared_ptr::reset()\fP به همراه یک عبارت \fBnew\fP را پیدا کرده و آن را با فراخوانی \fBstd::make_shared\fP جایگزین می‌نماید. .INDENT 0.0 .INDENT 3.5 .sp .EX my_ptr.reset(new MyPair(1, 2)); // becomes my_ptr = std::make_shared(1, 2); .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B MakeSmartPtrFunction رشته‌ای که نام تابع make\-shared\-ptr را مشخص می‌کند. مقدار پیش‌فرض \fIstd::make_shared\fP است. .UNINDENT .INDENT 0.0 .TP .B MakeSmartPtrFunctionHeader رشته‌ای که هدر مربوط به تابع make\-shared\-ptr را مشخص می‌کند. مقدار پیش‌فرض \fI\fP است. .UNINDENT .INDENT 0.0 .TP .B IncludeStyle رشته‌ای که شیوه درج include استفاده‌شده را مشخص می‌کند: \fIllvm\fP یا \fIgoogle\fP\&. مقدار پیش‌فرض \fIllvm\fP است. .UNINDENT .INDENT 0.0 .TP .B IgnoreMacros اگر روی \fItrue\fP تنظیم شود، این بررسی هشداری درون ماکروها صادر نخواهد کرد. پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B IgnoreDefaultInitialization اگر روی \fIfalse\fP تنظیم شود، بررسی ویرایش‌هایی را که مقداردهی اولیه پیش‌فرض (default initialization) را به مقداردهی اولیه مقداری (value initialization) تبدیل می‌کنند پیشنهاد نمی‌دهد، زیرا این کار می‌تواند باعث افت کارایی شود. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .SS modernize\-make\-unique .sp این بررسی ساخت اشیاء \fBstd::unique_ptr\fP را از طریق فراخوانی صریح سازنده به همراه یک عبارت \fBnew\fP پیدا کرده و آن را با فراخوانی \fBstd::make_unique\fP (معرفی‌شده در C++14) جایگزین می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX auto my_ptr = std::unique_ptr(new MyPair(1, 2)); // becomes auto my_ptr = std::make_unique(1, 2); .EE .UNINDENT .UNINDENT .sp این بررسی همچنین فراخوانی‌های \fBstd::unique_ptr::reset()\fP به همراه یک عبارت \fBnew\fP را پیدا کرده و آن را با فراخوانی \fBstd::make_unique\fP جایگزین می‌نماید. .INDENT 0.0 .INDENT 3.5 .sp .EX my_ptr.reset(new MyPair(1, 2)); // becomes my_ptr = std::make_unique(1, 2); .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B MakeSmartPtrFunction رشته‌ای که نام تابع make\-unique\-ptr را مشخص می‌کند. مقدار پیش‌فرض \fIstd::make_unique\fP است. .UNINDENT .INDENT 0.0 .TP .B MakeSmartPtrFunctionHeader رشته‌ای که هدر مربوط به تابع make\-unique\-ptr را مشخص می‌کند. مقدار پیش‌فرض \fI\fP است. .UNINDENT .INDENT 0.0 .TP .B IncludeStyle رشته‌ای که شیوه درج include استفاده‌شده را مشخص می‌کند: \fIllvm\fP یا \fIgoogle\fP\&. مقدار پیش‌فرض \fIllvm\fP است. .UNINDENT .INDENT 0.0 .TP .B IgnoreMacros اگر روی \fItrue\fP تنظیم شود، این بررسی هشداری درون ماکروها صادر نخواهد کرد. پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B IgnoreDefaultInitialization اگر روی \fIfalse\fP تنظیم شود، بررسی ویرایش‌هایی را که مقداردهی اولیه پیش‌فرض (default initialization) را به مقداردهی اولیه مقداری (value initialization) تبدیل می‌کنند پیشنهاد نمی‌دهد، زیرا این کار می‌تواند باعث افت کارایی شود. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .SS modernize\-min\-max\-use\-initializer\-list .sp فراخوانی‌های تو در توی \fBstd::min\fP و \fBstd::max\fP را در صورت امکان با یک لیست مقداردهی اولیه (initializer list) جایگزین می‌کند. .sp برای مثال، کد زیر را در نظر بگیرید: .INDENT 0.0 .INDENT 3.5 .sp .EX int a = std::max(std::max(i, j), k); .EE .UNINDENT .UNINDENT .sp این بررسی کد بالا را به شکل زیر تبدیل خواهد کرد: .INDENT 0.0 .INDENT 3.5 .sp .EX int a = std::max({i, j, k}); .EE .UNINDENT .UNINDENT .SS ملاحظات مربوط به کارایی .sp اگرچه این بررسی کد را ساده‌تر کرده و خوانایی آن را افزایش می‌دهد، اما ممکن است به دلیل نیاز به کپی کردن اشیاء در initializer list، برای انواع غیربدیهی (non\-trivial) منجر به افت کارایی شود. .sp برای جلوگیری از این مشکل، توصیه می‌شود برای انواع غیربدیهی از \fIstd::ref\fP یا \fIstd::cref\fP استفاده شود: .INDENT 0.0 .INDENT 3.5 .sp .EX std::string b = std::max({std::ref(i), std::ref(j), std::ref(k)}); .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IncludeStyle رشته‌ای که مشخص می‌کند کدام سبک درج فایلهای سرآیند (include\-style) استفاده شود، \fIllvm\fP یا \fIgoogle\fP\&. مقدار پیش‌فرض \fIllvm\fP است. .UNINDENT .INDENT 0.0 .TP .B IgnoreNonTrivialTypes یک متغیر بولی که تعیین می‌کند آیا انواع غیربدیهی نادیده گرفته شوند یا خیر. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B IgnoreTrivialTypesOfSizeAbove یک مقدار صحیح که اندازه‌ای (به بایت) را مشخص می‌کند که انواع بدیهی بزرگ‌تر از آن نادیده گرفته می‌شوند. مقدار پیش‌فرض \fI32\fP است. .UNINDENT .SS modernize\-pass\-by\-value .sp با افزوده شدن مفاهیم انتقال (move semantics) به زبان و به‌روزرسانی کتابخانه استاندارد با سازنده‌های انتقال برای انواع داده متعدد، اکنون دریافت مستقیم یک آرگومان از طریق مقدار (pass\-by\-value) به جای دریافت با مرجع ثابت (const\-reference) و سپس کپی کردن آن، رویکرد مفیدی به شمار می‌رود. این بررسی به کامپایلر اجازه می‌دهد تا بهترین شیوه را برای ساخت رونوشت (کپی) انتخاب کند. .sp این تبدیل معمولاً زمانی مفید است که کد فراخواننده یک \fIrvalue\fP را ارسال کرده و فرض بر این باشد که ساخت با انتقال (move construction) عملیاتی کم‌هزینه و ارزان است. این مثال کوتاه نحوه ساخته شدن مقدار را نشان می‌دهد: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo(std::string s); std::string get_str(); void f(const std::string &str) { foo(str); // lvalue \-> copy construction foo(get_str()); // prvalue \-> move construction } .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 در حال حاضر، تنها سازنده‌ها برای استفاده از pass\-by\-value بازنویسی و تبدیل می‌شوند. از مشارکت‌ها برای پشتیبانی از موقعیت‌های دیگر استقبال می‌شود! .UNINDENT .UNINDENT .SS استفاده از Pass\-by\-value در سازنده‌ها .sp استفاده از پارامترهای سازنده با مرجع ثابت (const\-references) که در فیلدهای کلاس کپی می‌شوند را جایگزین می‌کند. سپس پارامتر با استفاده از \fIstd::move()\fP انتقال می‌یابد. .sp از آنجا که \fBstd::move()\fP یک تابع کتابخانه‌ای است که در \fI\fP اعلان شده، ممکن است اضافه کردن این دستور include لازم باشد. این بررسی در صورت لزوم دایرکتیو include را اضافه خواهد کرد. .INDENT 0.0 .INDENT 3.5 .sp .EX #include class Foo { public: \- Foo(const std::string &Copied, const std::string &ReadOnly) \- : Copied(Copied), ReadOnly(ReadOnly) + Foo(std::string Copied, const std::string &ReadOnly) + : Copied(std::move(Copied)), ReadOnly(ReadOnly) {} private: std::string Copied; const std::string &ReadOnly; }; std::string get_cwd(); void f(const std::string &Path) { // The parameter corresponding to \(aqget_cwd()\(aq is move\-constructed. By // using pass\-by\-value in the Foo constructor we managed to avoid a // copy\-construction. Foo foo(get_cwd(), Path); } .EE .UNINDENT .UNINDENT .sp اگر پارامتر بیش از یک بار استفاده شده باشد، هیچ تبدیلی صورت نمی‌گیرد، زیرا اشیاء منتقل‌شده دارای وضعیت نامعینی هستند. این بدان معناست که کد زیر بدون تغییر باقی خواهد ماند: .INDENT 0.0 .INDENT 3.5 .sp .EX #include void pass(const std::string &S); struct Foo { Foo(const std::string &S) : Str(S) { pass(S); } std::string Str; }; .EE .UNINDENT .UNINDENT .SS محدودیت‌ها .sp وضعیتی که در آن کد تولیدشده ممکن است نادرست باشد زمانی است که شیء ارجاع‌شده قبل از تخصیص در فهرست اولیه‌سازی (init\-list)، از طریق یک مرجع \(dqمخفی\(dq دستخوش تغییر شود. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX std::string s(\(dqfoo\(dq); struct Base { Base() { s = \(dqbar\(dq; } }; struct Derived : Base { \- Derived(const std::string &S) : Field(S) + Derived(std::string S) : Field(std::move(S)) { } std::string Field; }; void f() { \- Derived d(s); // d.Field holds \(dqbar\(dq + Derived d(s); // d.Field holds \(dqfoo\(dq } .EE .UNINDENT .UNINDENT .SS نکته‌ای درباره تجزیه با تأخیر الگو (delayed template parsing) .sp هنگامی که قابلیت تجزیه با تأخیر الگو فعال باشد، سازنده‌هایی که بخشی از زمینه‌های قالب‌بندی‌شده هستند؛ یعنی سازنده‌های قالب‌بندی‌شده، سازنده‌ها در کلاس‌های الگو، سازنده‌های کلاس‌های درونیِ کلاس‌های الگو و غیره، تبدیل نمی‌شوند. قابلیت تجزیه با تأخیر الگو به‌طور پیش‌فرض در ویندوز به‌عنوان یکی از قابلیت‌های الحاقی مایکروسافت فعال است: Clang Compiler User\(aqs Manual \- Microsoft extensions \%\&. .sp تجزیه با تأخیر الگو می‌تواند با استفاده از فلگ \fI\-fdelayed\-template\-parsing\fP فعال و با \fI\-fno\-delayed\-template\-parsing\fP غیرفعال شود. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX template class C { std::string S; public: = // using \-fdelayed\-template\-parsing (default on Windows) = C(const std::string &S) : S(S) {} + // using \-fno\-delayed\-template\-parsing (default on non\-Windows systems) + C(std::string S) : S(std::move(S)) {} }; .EE .UNINDENT .UNINDENT .sp \fBهمچنین ببینید:\fP .INDENT 0.0 .INDENT 3.5 برای اطلاعات بیشتر درباره الگوی ارسال با مقدار (pass\-by\-value)، مطالعه کنید: Want Speed? Pass by Value \%\&. .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IncludeStyle رشته‌ای که مشخص می‌کند کدام سبک include استفاده شود، \fIllvm\fP یا \fIgoogle\fP\&. مقدار پیش‌فرض \fIllvm\fP است. .UNINDENT .INDENT 0.0 .TP .B ValuesOnly وقتی \fItrue\fP باشد، این بررسی فقط درباره پارامترهای کپی‌شده‌ای هشدار می‌دهد که از پیش به صورت مقداری ارسال شده‌اند. مقدار پیش‌فرض \fIfalse\fP است. .UNINDENT .SS modernize\-raw\-string\-literal .sp این بررسی به‌طور گزینشی لیترال‌های رشته‌ای حاوی نویسه‌های اسکیپ‌شده را با لیترال‌های رشته‌ای خام (raw string literals) جایگزین می‌کند. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX const char *const Quotes{\(dqembedded \e\(dqquotes\e\(dq\(dq}; const char *const Paragraph{\(dqLine one.\enLine two.\enLine three.\en\(dq}; const char *const SingleLine{\(dqSingle line.\en\(dq}; const char *const TrailingSpace{\(dqLook here \-> \en\(dq}; const char *const Tab{\(dqOne\etTwo\en\(dq}; const char *const Bell{\(dqHello!\ea And welcome!\(dq}; const char *const Path{\(dqC:\e\eProgram Files\e\eVendor\e\eApplication.exe\(dq}; const char *const RegEx{\(dq\e\ew\e\e([a\-z]\e\e)\(dq}; .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX const char *const Quotes{R\(dq(embedded \(dqquotes\(dq)\(dq}; const char *const Paragraph{\(dqLine one.\enLine two.\enLine three.\en\(dq}; const char *const SingleLine{\(dqSingle line.\en\(dq}; const char *const TrailingSpace{\(dqLook here \-> \en\(dq}; const char *const Tab{\(dqOne\etTwo\en\(dq}; const char *const Bell{\(dqHello!\ea And welcome!\(dq}; const char *const Path{R\(dq(C:\eProgram Files\eVendor\eApplication.exe)\(dq}; const char *const RegEx{R\(dq(\ew\e([a\-z]\e))\(dq}; .EE .UNINDENT .UNINDENT .sp وجود هر یک از نویسه‌های اسکیپ زیر می‌تواند موجب تبدیل رشته به لیترال رشته‌ای خام شود: \fB\e\e\fP، \fB\e\(aq\fP، \fB\e\(dq\fP، \fB\e?\fP، و اسکیپ‌های اکتال یا هگزادسیمال برای نویسه‌های اسکی (ASCII) قابل چاپ. .sp یک لیترال رشته‌ای که تنها حاوی خط‌های جدید اسکیپ‌شده باشد، روشی رایج برای نوشتن خطوط خروجی متنی است. اضافه کردن خط‌های جدید فیزیکی با لیترال‌های رشته‌ای خام در این حالت احتمالاً به خوانایی آسیب می‌زند. این لیترال‌های رشته‌ای دست‌نخورده باقی می‌مانند. .sp یک تب افقی، form feed، یا تب عمودیِ اسکیپ‌شده از تبدیل لیترال رشته‌ای جلوگیری می‌کند. وجود تب افقی، form feed یا تب عمودی در کد مبدأ از نظر بصری چندان واضح نیست. .SS گزینه‌ها .INDENT 0.0 .TP .B DelimiterStem جداکننده سفارشی برای اسکیپ نویسه‌ها در لیترال‌های رشته‌ای خام. در ساختار زیر استفاده می‌شود: \fBR\(dqstem_delimiter(contents)stem_delimiter\(dq\fP\&. مقدار پیش‌فرض \fIlit\fP است. .UNINDENT .INDENT 0.0 .TP .B ReplaceShorterLiterals کنترل جایگزینی لیترال‌های رشته‌ای غیرخام کوتاه‌تر با لیترال‌های رشته‌ای خام طولانی‌تر. تنظیم این گزینه روی \fItrue\fP این جایگزینی را فعال می‌کند. مقدار پیش‌فرض \fIfalse\fP است (لیترال‌های کوتاه‌تر جایگزین نمی‌شوند). .UNINDENT .SS modernize\-redundant\-void\-arg .sp پیدا کردن و حذف لیست آرگومان‌های زائد \fBvoid\fP. .INDENT 0.0 .TP .B مثال‌ها: .TS box center; l|l. T{ کد اولیه T} T{ کد پس از اعمال اصلاحات T} _ T{ \fBint f(void);\fP T} T{ \fBint f();\fP T} _ T{ \fBint (*f(void))(void);\fP T} T{ \fBint (*f())();\fP T} _ T{ \fBtypedef int (*f_t(void))(void);\fP T} T{ \fBtypedef int (*f_t())();\fP T} _ T{ \fBvoid (C::*p)(void);\fP T} T{ \fBvoid (C::*p)();\fP T} _ T{ \fBC::C(void) {}\fP T} T{ \fBC::C() {}\fP T} _ T{ \fBC::~C(void) {}\fP T} T{ \fBC::~C() {}\fP T} .TE .UNINDENT .SS modernize\-replace\-auto\-ptr .sp این بررسی موارد استفاده از کلاس منسوخ‌شدهٔ \fBstd::auto_ptr\fP را با \fBstd::unique_ptr\fP (معرفی‌شده در C++11) جایگزین می‌کند. انتقال مالکیت، که توسط سازنده کپی و عملگر انتساب انجام می‌شد، با استفاده از فراخوانی‌های صریح \fBstd::move()\fP تغییر می‌یابد تا با نحوه استفاده از \fBstd::unique_ptr\fP مطابقت داشته باشد. .sp مثال مهاجرت: .INDENT 0.0 .INDENT 3.5 .sp .EX \-void take_ownership_fn(std::auto_ptr int_ptr); +void take_ownership_fn(std::unique_ptr int_ptr); void f(int x) { \- std::auto_ptr a(new int(x)); \- std::auto_ptr b; + std::unique_ptr a(new int(x)); + std::unique_ptr b; \- b = a; \- take_ownership_fn(b); + b = std::move(a); + take_ownership_fn(std::move(b)); } .EE .UNINDENT .UNINDENT .sp از آنجا که \fBstd::move()\fP یک تابع کتابخانه‌ای اعلان‌شده در \fB\fP است، ممکن است افزودن این دستور include ضروری باشد. این بررسی در صورت لزوم، دستور include را اضافه خواهد کرد. .SS محدودیت‌ها .INDENT 0.0 .IP \(bu 2 اگر تغییر هدرها فعال نباشد یا اجازه تغییر یک هدر داده نشده باشد، این بررسی کد خرابی (خطای کامپایل) ایجاد می‌کند که در آن کد هدرها بدون تغییر باقی مانده در حالی که کد مصرف‌کنندهٔ آن‌ها تغییر خواهد کرد. .IP \(bu 2 کد کاربری که یک ارجاع به \fBstd::auto_ptr\fP برگرفته از کدی که قابل مهاجرت نیست (مانند هدری از یک کتابخانه شخص ثالث) اعلان می‌کند، پس از مهاجرت منجر به خطای کامپایل خواهد شد. زیرا نوع ارجاع به \fBstd::unique_ptr\fP تغییر می‌یابد اما نوع برگردانده‌شده توسط کتابخانه تغییر نخواهد کرد که این امر باعث اتصال یک ارجاع به \fBstd::unique_ptr\fP از یک \fBstd::auto_ptr\fP می‌شود. این الگو منطقی نیست و معمولاً \fBstd::auto_ptr\fP به صورت مقداری ذخیره می‌شود (در غیر این صورت هدف از استفاده از آن‌ها به جای ارجاع یا اشاره‌گر چیست؟). .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX // <3rd\-party header...> std::auto_ptr get_value(); const std::auto_ptr & get_ref(); // \-std::auto_ptr a(get_value()); +std::unique_ptr a(get_value()); // ok, unique_ptr constructed from auto_ptr \-const std::auto_ptr & p = get_ptr(); +const std::unique_ptr & p = get_ptr(); // won\(aqt compile .EE .UNINDENT .UNINDENT .INDENT 0.0 .IP \(bu 2 قالب‌های نمونه‌سازی‌نشده (Non-instantiated templates) تغییر داده نمی‌شوند. .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX template void f() { std::auto_ptr p; } // only \(aqf()\(aq (or similar) will trigger the replacement. .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IncludeStyle یک رشته که سبک include مورد استفاده را مشخص می‌کند: \fIllvm\fP یا \fIgoogle\fP. پیش‌فرض \fIllvm\fP است. .UNINDENT .SS modernize\-replace\-disallow\-copy\-and\-assign\-macro .sp بسط‌های ماکروی \fBDISALLOW_COPY_AND_ASSIGN(Type)\fP را پیدا کرده و آن‌ها را با یک سازنده کپی حذف‌شده (deleted) و یک عملگر انتساب حذف‌شده جایگزین می‌کند. .sp پیش از معرفی کلمه کلیدی \fBdelete\fP در C++11، این یک روال معمول بود که سازنده کپی و عملگر انتساب به عنوان اعضای خصوصی (private) اعلان شوند. این کار عملاً آن‌ها را برای API عمومی کلاس غیرقابل‌استفاده می‌کرد. .sp با ظهور کلمه کلیدی \fBdelete\fP در C++11 می‌توانیم دسترسی \fBprivate\fP سازنده کپی و عملگر انتساب را رها کرده و این متدها را به طور کامل حذف (delete) کنیم. .sp هنگام اجرای این بررسی بر روی کدی مانند این: .INDENT 0.0 .INDENT 3.5 .sp .EX class Foo { private: DISALLOW_COPY_AND_ASSIGN(Foo); }; .EE .UNINDENT .UNINDENT .sp به این صورت تبدیل خواهد شد: .INDENT 0.0 .INDENT 3.5 .sp .EX class Foo { private: Foo(const Foo &) = delete; const Foo &operator=(const Foo &) = delete; }; .EE .UNINDENT .UNINDENT .SS محدودیت‌ها .INDENT 0.0 .IP \(bu 2 توجه داشته باشید که مثال مهاجرت بالا بخش دسترسی \fBprivate\fP را دست‌نخورده باقی می‌گذارد. ممکن است بخواهید بررسی modernize\-use\-equals\-delete \%<> را اجرا کنید تا هشدارهایی برای توابع حذف‌شده در بخش‌های private دریافت کنید. .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B MacroName رشته‌ای که نام ماکرویی را که بسط آن جایگزین خواهد شد مشخص می‌کند. پیش‌فرض \fIDISALLOW_COPY_AND_ASSIGN\fP است. .UNINDENT .sp ببینید: \% .SS modernize\-replace\-random\-shuffle .sp این بررسی موارد وقوع \fBstd::random_shuffle\fP را یافته و آن را با \fBstd::shuffle\fP جایگزین می‌کند. در C++17 دیگر \fBstd::random_shuffle\fP در دسترس نخواهد بود و بنابراین باید آن را جایگزین کنیم. .sp در زیر دو مثال از اینکه چه نوع رخدادهایی پیدا می‌شوند و دو مثال از آنچه با آن جایگزین خواهد شد آورده شده است. .INDENT 0.0 .INDENT 3.5 .sp .EX std::vector v; // First example std::random_shuffle(vec.begin(), vec.end()); // Second example std::random_shuffle(vec.begin(), vec.end(), randomFunc); .EE .UNINDENT .UNINDENT .sp هر دوی این مثال‌ها با عبارت زیر جایگزین خواهند شد: .INDENT 0.0 .INDENT 3.5 .sp .EX std::shuffle(vec.begin(), vec.end(), std::mt19937(std::random_device()())); .EE .UNINDENT .UNINDENT .sp مثال دوم همچنین هشداری دریافت می‌کند مبنی بر اینکه \fBrandomFunc\fP دیگر مانند گذشته پشتیبانی نمی‌شود، بنابراین اگر کاربر همان قابلیت را می‌خواهد، باید پیاده‌سازی \fBrandomFunc\fP را تغییر دهد. .sp یک نکته که در اینجا باید به آن توجه داشت این است که مقداردهی اولیه \fBstd::random_device\fP بسیار سنگین است. بنابراین اگر از این کد در جایی که کارایی حیاتی است استفاده می‌کنید، احتمالاً ترجیح می‌دهید آن را در جای دیگری مقداردهی اولیه کنید. .sp نکته دیگر این است که کیفیت تولید بذر (seeding) اصلاح پیشنهادی بسیار ضعیف است: \fBstd::mt19937\fP دارای وضعیت داخلی با ۶۲۴ عدد صحیح ۳۲ بیتی است، اما تنها با یک عدد صحیح بذردهی می‌شود. بنابراین اگر به تصادفی بودن با کیفیت بالاتری نیاز دارید، باید بذردهی بهتری را در نظر بگیرید، برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX std::shuffle(v.begin(), v.end(), []() { std::mt19937::result_type seeds[std::mt19937::state_size]; std::random_device device; std::uniform_int_distribution dist; std::generate(std::begin(seeds), std::end(seeds), [&] { return dist(device); }); std::seed_seq seq(std::begin(seeds), std::end(seeds)); return std::mt19937(seq); }()); .EE .UNINDENT .UNINDENT .SS modernize\-return\-braced\-init\-list .sp فراخوانی‌های صریح سازنده را در دستور return با یک فهرست مقداردهی اولیه قلاب‌دار (braced initializer list) جایگزین می‌کند. به این ترتیب، نوع بازگشتی به صورت بیهوده در تعریف تابع و عبارت return تکرار نمی‌شود. .INDENT 0.0 .INDENT 3.5 .sp .EX Foo bar() { Baz baz; return Foo(baz); } // transforms to: Foo bar() { Baz baz; return {baz}; } .EE .UNINDENT .UNINDENT .SS modernize\-shrink\-to\-fit .sp ترفندهای کپی و تعویض (copy and swap) را در نگه‌دارنده‌های دارای قابلیت کاهش اندازه با فراخوانی متد \fBshrink_to_fit()\fP جایگزین می‌کند. .sp متد \fBshrink_to_fit()\fP خواناتر و کارآمدتر از ترفند کپی و تعویض برای کاهش ظرفیت یک نگه‌دارنده با قابلیت کوچک‌شدن است. توجه داشته باشید که متد \fBshrink_to_fit()\fP تنها در C++11 به بعد در دسترس است. .SS modernize\-type\-traits .sp صفات نوع (type traits) کتابخانه استاندارد را از قالب \fBtraits<...>::type\fP و \fBtraits<...>::value\fP به ترتیب به \fBtraits_t<...>\fP و \fBtraits_v<...>\fP تبدیل می‌کند. .sp برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX std::is_integral::value std::is_same::value typename std::add_const::type std::make_signed::type .EE .UNINDENT .UNINDENT .sp به این صورت تبدیل خواهد شد: .INDENT 0.0 .INDENT 3.5 .sp .EX std::is_integral_v std::is_same_v std::add_const_t std::make_signed_t .EE .UNINDENT .UNINDENT .SS Options .INDENT 0.0 .TP .B IgnoreMacros اگر \fItrue\fP باشد، صفات (traits) تعریف‌شده در ماکروها را عیب‌یابی نمی‌کند. .sp نکته: اصلاحات خودکار (Fixes) هرگز برای کدهای داخل ماکروها صادر نخواهند شد. .INDENT 7.0 .INDENT 3.5 .sp .EX #define IS_SIGNED(T) std::is_signed::value .EE .UNINDENT .UNINDENT .sp مقدار پیش‌فرض \fIfalse\fP است. .UNINDENT .SS Limitations .sp در حال حاضر استفاده از صفات نوع با مشخص‌کننده‌های نام تودرتو (مانند \fBstd::chrono::is_clock\fP و \fBstd::chrono::treat_as_floating_point\fP) را بررسی و عیب‌یابی نمی‌کند. .SS modernize\-unary\-static\-assert .sp این بررسی، هرگونه اعلان \fBstatic_assert\fP با یک لیترال رشته‌ای خالی را تشخیص داده و یک یادداشت اصلاحی (fix\-it note) برای جایگزینی آن اعلان با یک اعلان تک‌آرگومانی \fBstatic_assert\fP ارائه می‌دهد. .sp این بررسی تنها برای کدهای C++17 و بالاتر قابل اعمال است. .sp کد زیر: .INDENT 0.0 .INDENT 3.5 .sp .EX void f_textless(int a) { static_assert(sizeof(a) <= 10, \(dq\(dq); } .EE .UNINDENT .UNINDENT .sp جایگزین می‌شود با: .INDENT 0.0 .INDENT 3.5 .sp .EX void f_textless(int a) { static_assert(sizeof(a) <= 10); } .EE .UNINDENT .UNINDENT .SS modernize\-use\-auto .sp این بررسی وظیفه دارد برای اعلان متغیرها از مشخص‌کننده نوع \fBauto\fP استفاده کند تا \fIخوانایی و نگه‌داری‌پذیری کد را بهبود بخشد\fP\&. برای مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX std::vector::iterator I = my_container.begin(); // transforms to: auto I = my_container.begin(); .EE .UNINDENT .UNINDENT .sp مشخص‌کننده نوع \fBauto\fP تنها در شرایطی اعمال خواهد شد که نوع متغیر با نوع عبارت مقداردهی اولیه مطابقت داشته باشد. به عبارت دیگر، \fBauto\fP باید همان نوعی را استنتاج کند که در ابتدا در متن مبدأ نوشته شده بود. با این حال، نباید هر شرایطی تغییر داده شود: .INDENT 0.0 .INDENT 3.5 .sp .EX int val = 42; InfoStruct &I = SomeObject.getInfo(); // Should not become: auto val = 42; auto &I = SomeObject.getInfo(); .EE .UNINDENT .UNINDENT .sp در این مثال، استفاده از \fBauto\fP برای انواع توکار خوانایی را افزایش نمی‌دهد. در شرایط دیگر، باعث می‌شود کد کمتر خودتوضیح (self\-documenting) باشد که این امر خوانایی و نگه‌داری‌پذیری را تضعیف می‌کند. در نتیجه، \fBauto\fP فقط در شرایط خاصی که در زیر توضیح داده شده استفاده و اعمال می‌شود. .SS تکرارکننده‌ها (Iterators) .sp مشخص‌کننده‌های نوع تکرارکننده معمولاً طولانی بوده و به‌ویژه در ساختارهای حلقه، به‌وفور استفاده می‌شوند. از آنجا که توابع تولیدکننده تکرارکننده‌ها ساختاری مشترک دارند، می‌توان مشخص‌کننده نوع را بدون مبهم کردن مفهوم کد جایگزین کرد و هم‌زمان خوانایی و نگه‌داری‌پذیری آن را ارتقا داد. .INDENT 0.0 .INDENT 3.5 .sp .EX for (std::vector::iterator I = my_container.begin(), E = my_container.end(); I != E; ++I) { } // تبدیل می‌شود به for (auto I = my_container.begin(), E = my_container.end(); I != E; ++I) { } .EE .UNINDENT .UNINDENT .sp این بررسی تنها زمانی مشخص‌کننده‌های نوع تکرارکننده را جایگزین می‌کند که همه شرایط زیر برقرار باشند: .INDENT 0.0 .IP \(bu 2 تکرارکننده مربوط به یکی از کانتینرهای استاندارد در فضای نام \fBstd\fP باشد: .INDENT 2.0 .IP \(bu 2 \fBarray\fP .IP \(bu 2 \fBdeque\fP .IP \(bu 2 \fBforward_list\fP .IP \(bu 2 \fBlist\fP .IP \(bu 2 \fBvector\fP .IP \(bu 2 \fBmap\fP .IP \(bu 2 \fBmultimap\fP .IP \(bu 2 \fBset\fP .IP \(bu 2 \fBmultiset\fP .IP \(bu 2 \fBunordered_map\fP .IP \(bu 2 \fBunordered_multimap\fP .IP \(bu 2 \fBunordered_set\fP .IP \(bu 2 \fBunordered_multiset\fP .IP \(bu 2 \fBqueue\fP .IP \(bu 2 \fBpriority_queue\fP .IP \(bu 2 \fBstack\fP .UNINDENT .IP \(bu 2 تکرارکننده یکی از انواع تکرارکننده مجاز برای کانتینرهای استاندارد باشد: .INDENT 2.0 .IP \(bu 2 \fBiterator\fP .IP \(bu 2 \fBreverse_iterator\fP .IP \(bu 2 \fBconst_iterator\fP .IP \(bu 2 \fBconst_reverse_iterator\fP .UNINDENT .IP \(bu 2 علاوه بر استفاده مستقیم از انواع تکرارکننده، استفاده از typedefها یا روش‌های دیگر ارجاع به این انواع نیز مجاز است. با این حال، انواع وابسته به پیاده‌سازی که نوعی مانند \fBstd::vector::iterator\fP خود یک typedef برای آن‌هاست، تبدیل نخواهند شد. مثال‌های زیر را در نظر بگیرید: .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX // استفاده‌های مستقیم زیر از انواع تکرارکننده تبدیل خواهند شد. std::vector::iterator I = MyVec.begin(); { using namespace std; list::iterator I = MyList.begin(); } // مشخص‌کننده نوع برای J به auto تبدیل می‌شود زیرا یک typedef // به یک نوع تکرارکننده استاندارد است. typedef std::map::const_iterator map_iterator; map_iterator J = MyMap.begin(); // نوع تکرارکننده وابسته به پیاده‌سازی زیر که ممکن است // std::vector::iterator یک typedef برای آن باشد، تبدیل نخواهد شد. __gnu_cxx::__normal_iterator K = MyVec.begin(); .EE .UNINDENT .UNINDENT .INDENT 0.0 .IP \(bu 2 مقداردهنده اولیه متغیری که تعریف می‌شود، یک لیست مقداردهی درون آک getUser (braced initializer list) نباشد. در غیر این صورت، استفاده از \fBauto\fP باعث می‌شود نوع متغیر به عنوان \fBstd::initializer_list\fP استنتاج گردد. .UNINDENT .SS عبارت‌های New .sp اغلب هنگامی که یک اشاره‌گر تعریف شده و با \fBnew\fP مقداردهی اولیه می‌شود، نوع مورد اشاره دو بار نوشته می‌شود: یک بار در نوع اعلان و بار دیگر در عبارت \fBnew\fP. در این حالت، می‌توان نوع اعلان را با \fBauto\fP جایگزین کرد تا خوانایی و نگه‌داری‌پذیری بهبود یابد. .INDENT 0.0 .INDENT 3.5 .sp .EX TypeName *my_pointer = new TypeName(my_param); // تبدیل می‌شود به auto *my_pointer = new TypeName(my_param); .EE .UNINDENT .UNINDENT .sp این بررسی همچنین در صورت برقراری شرایط زیر، نوع اعلان را در اعلان‌های چندگانه جایگزین خواهد کرد: .INDENT 0.0 .IP \(bu 2 همه متغیرهای اعلان‌شده نوع یکسانی داشته باشند (یعنی همگی اشاره‌گرهایی به یک نوع مشابه باشند). .IP \(bu 2 همه متغیرهای اعلان‌شده با یک عبارت \fBnew\fP مقداردهی اولیه شوند. .IP \(bu 2 انواع تمامی عبارت‌های new با نوع مورد اشاره در اعلان یکسان باشد. .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX TypeName *my_first_pointer = new TypeName, *my_second_pointer = new TypeName; // تبدیل می‌شود به auto *my_first_pointer = new TypeName, *my_second_pointer = new TypeName; .EE .UNINDENT .UNINDENT .SS عبارت‌های تبدیل نوع (Cast expressions) .sp اغلب، زمانی که یک متغیر تعریف شده و با یک تبدیل نوع مقداردهی اولیه می‌شود، نوع متغیر دو بار نوشته می‌شود: یک بار در نوع اعلان و بار دیگر در عبارت تبدیل نوع. در این حالت، نوع اعلان می‌تواند با \fBauto\fP جایگزین شود که خوانایی و قابلیت نگهداری را بهبود می‌بخشد. .INDENT 0.0 .INDENT 3.5 .sp .EX TypeName *my_pointer = static_cast(my_param); // becomes auto *my_pointer = static_cast(my_param); .EE .UNINDENT .UNINDENT .sp این بررسی تبدیل‌های \fBstatic_cast\fP، \fBdynamic_cast\fP، \fBconst_cast\fP، \fBreinterpret_cast\fP، تبدیل‌های تابعی، تبدیل‌های سبک C و الگوهای تابعی که مانند تبدیل نوع رفتار می‌کنند (مانند \fBllvm::dyn_cast\fP، \fBboost::lexical_cast\fP و \fBgsl::narrow_cast\fP) را مدیریت می‌کند. فراخوانی‌های الگوهای تابعی در صورتی به عنوان تبدیل نوع در نظر گرفته می‌شوند که نخستین آرگومان الگو صریح و از نوع یک type باشد، و تابع آن نوع، یا اشاره‌گر یا ارجاعی به آن را برگرداند. .SS محدودیت‌ها .INDENT 0.0 .IP \(bu 2 اگر مقداردهی اولیه یک سازنده تبدیل صریح (explicit conversion constructor) باشد، این بررسی مشخص‌کننده نوع را جایگزین نخواهد کرد، حتی اگر انجام آن ایمن باشد. .IP \(bu 2 تکرارکننده‌های تعریف‌شده توسط کاربر (User\-defined iterators) در حال حاضر پشتیبانی نمی‌شوند. .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B MinTypeNameLength اگر این گزینه روی مقداری غیر از صفر تنظیم شود (پیش‌فرض \fI5\fP است)، بررسی از نام‌های انواعی که طولی کمتر از مقدار گزینه دارند صرف‌نظر می‌کند. این گزینه فقط بر روی عبارت‌ها تأثیر می‌گذارد، نه تکرارکننده‌ها. فاصله‌های بین نام‌های انواع چندکلمه‌ای (\fBlong int\fP) به عنوان یکی در نظر گرفته می‌شوند. اگر گزینه \fBRemoveStars\fP (به زیر مراجعه کنید) روی \fItrue\fP تنظیم شده باشد، نمادهای \fB*\fP در نوع نیز به عنوان بخشی از نام نوع شمرده می‌شوند. .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX // MinTypeNameLength = 0, RemoveStars=0 int a = static_cast(foo()); // \-\-\-> auto a = ... // length(bool *) = 4 bool *b = new bool; // \-\-\-> auto *b = ... unsigned c = static_cast(foo()); // \-\-\-> auto c = ... // MinTypeNameLength = 5, RemoveStars=0 int a = static_cast(foo()); // \-\-\-> int a = ... bool b = static_cast(foo()); // \-\-\-> bool b = ... bool *pb = static_cast(foo()); // \-\-\-> bool *pb = ... unsigned c = static_cast(foo()); // \-\-\-> auto c = ... // length(long int) = 8 long int d = static_cast(foo()); // \-\-\-> auto d = ... // MinTypeNameLength = 5, RemoveStars=1 int a = static_cast(foo()); // \-\-\-> int a = ... // length(int * * ) = 5 int **pa = static_cast(foo()); // \-\-\-> auto pa = ... bool b = static_cast(foo()); // \-\-\-> bool b = ... bool *pb = static_cast(foo()); // \-\-\-> auto pb = ... unsigned c = static_cast(foo()); // \-\-\-> auto c = ... long int d = static_cast(foo()); // \-\-\-> auto d = ... .EE .UNINDENT .UNINDENT .INDENT 0.0 .TP .B RemoveStars اگر این گزینه روی \fItrue\fP تنظیم شود (پیش‌فرض \fIfalse\fP است)، بررسی هنگام جایگزینی نام‌های نوع با \fBauto\fP، ستاره‌ها را از انواع اشاره‌گر غیر typedef حذف می‌کند. در غیر این صورت، بررسی ستاره‌ها را باقی می‌گذارد. برای مثال: .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX TypeName *my_first_pointer = new TypeName, *my_second_pointer = new TypeName; // RemoveStars = 0 auto *my_first_pointer = new TypeName, *my_second_pointer = new TypeName; // RemoveStars = 1 auto my_first_pointer = new TypeName, my_second_pointer = new TypeName; .EE .UNINDENT .UNINDENT .SS modernize\-use\-bool\-literals .sp لیترال‌های عددی صحیح که به \fBbool\fP تبدیل می‌شوند را پیدا می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .EX bool p = 1; bool f = static_cast(1); std::ios_base::sync_with_stdio(0); bool x = p ? 1 : 0; // transforms to bool p = true; bool f = true; std::ios_base::sync_with_stdio(false); bool x = p ? true : false; .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoreMacros اگر روی \fItrue\fP تنظیم شود، بررسی در داخل ماکروها هشداری صادر نخواهد کرد. پیش‌فرض \fItrue\fP است. .UNINDENT .SS modernize\-use\-constraints .sp جایگزینی \fBstd::enable_if\fP با بندهای requires در C++20. .sp دستور \fBstd::enable_if\fP یک سازوکار SFINAE برای انتخاب الگوهای تابع یا کلاس مطلوب بر اساس صفات نوع (type traits) یا سایر نیازمندی‌ها است. \fBenable_if\fP تعداد آرگومان‌های فراالگو (meta\-arity) را تغییر داده و اثرات جانبی نامطلوب دیگری \% در کد دارد. استاندارد C++20 مفاهیم (concepts) و قیود (constraints) را به عنوان راه‌حلی تمیزتر و ارائه‌شده توسط زبان برای دستیابی به همان نتیجه معرفی می‌کند. .sp این بررسی برخی از الگوهای رایج \fBstd::enable_if\fP را که می‌توان با بندهای requires در C++20 جایگزین کرد پیدا می‌کند. ابزار می‌تواند برخی از این الگوها را به‌صورت خودکار جایگزین کند، در غیر این صورت، پیامی تشخیصی بدون جایگزینی صادر می‌کند. این ابزار الگوهای \fBstd::enable_if\fP زیر را شناسایی می‌کند .INDENT 0.0 .IP 1. 3 عبارت \fBstd::enable_if\fP در نوع بازگشتی یک تابع .IP 2. 3 عبارت \fBstd::enable_if\fP به عنوان پارامتر الگوی پایانی برای الگوهای تابع .UNINDENT .sp سایر کاربردها، برای مثال در الگوهای کلاس برای پارامترهای تابع، در حال حاضر توسط این ابزار پشتیبانی نمی‌شوند. گونه‌های دیگر مانند \fBboost::enable_if\fP در حال حاضر توسط این ابزار پشتیبانی نمی‌شوند. .sp در زیر نمونه‌هایی از کدهای استفاده‌کننده از \fBstd::enable_if\fP آمده است. .INDENT 0.0 .INDENT 3.5 .sp .EX // enable_if in function return type template std::enable_if_t only_if_t_has_the_trait() { ... } // enable_if in the trailing template parameter template = 0> void another_version() { ... } template typename std::enable_if::type existing_constraint() requires (T::another_value) { return Obj{}; } template = 0> struct my_class {}; .EE .UNINDENT .UNINDENT .sp ابزار، کد بالا را با موارد زیر جایگزین خواهد کرد: .INDENT 0.0 .INDENT 3.5 .sp .EX // warning: use C++20 requires constraints instead of enable_if [modernize\-use\-constraints] template int only_if_t_has_the_trait() requires T::some_trait { ... } // warning: use C++20 requires constraints instead of enable_if [modernize\-use\-constraints] template void another_version() requires T::some_trait { ... } // The tool will emit a diagnostic for the following, but will // not attempt to replace the code. // warning: use C++20 requires constraints instead of enable_if [modernize\-use\-constraints] template typename std::enable_if::type existing_constraint() requires (T::another_value) { return Obj{}; } // The tool will not emit a diagnostic or attempt to replace the code. template = 0> struct my_class {}; .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 هدرهای سیستمی توسط این بررسی تحلیل نمی‌شوند. .UNINDENT .UNINDENT .SS modernize\-use\-default .sp نام این بررسی به modernize\-use\-equals\-default \%<>\& تغییر یافته است. .SS modernize\-use\-default\-member\-init .sp این بررسی، مقداردهنده‌های اولیه اعضا در سازنده‌ها را به مقداردهنده‌های پیش‌فرض جدید اعضا در C++11 تبدیل می‌کند. سایر مقداردهنده‌های اولیه اعضا که با مقداردهنده اولیه پیش‌فرض عضو مطابقت دارند، حذف می‌شوند. این کار می‌تواند کد تکراری را کاهش داده یا امکان استفاده از \(aq= default\(aq را فراهم کند. .INDENT 0.0 .INDENT 3.5 .sp .EX struct A { A() : i(5), j(10.0) {} A(int i) : i(i), j(10.0) {} int i; double j; }; // becomes struct A { A() {} A(int i) : i(i) {} int i{5}; double j{10.0}; }; .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 تنها مقداردهنده‌های اولیه اعضا را برای انواع داخلی (built\-in)، شمارشی‌ها (enums) و اشاره‌گرها تبدیل می‌کند. بررسی \fIreadability\-redundant\-member\-init\fP مقداردهنده‌های افزونه اولیه اعضا را برای کلاس‌ها حذف خواهد کرد. .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B UseAssignment اگر این گزینه روی \fItrue\fP تنظیم شود (پیش‌فرض \fIfalse\fP است)، بررسی اعضا را با انتساب مقداردهی اولیه می‌کند. برای مثال: .UNINDENT .INDENT 0.0 .INDENT 3.5 .sp .EX struct A { A() {} A(int i) : i(i) {} int i = 5; double j = 10.0; }; .EE .UNINDENT .UNINDENT .INDENT 0.0 .TP .B IgnoreMacros اگر این گزینه روی \fItrue\fP تنظیم شود (پیش‌فرض \fItrue\fP است)، بررسی هشداری درباره اعضای تعریف‌شده درون ماکروها صادر نخواهد کرد. .UNINDENT .SS modernize\-use\-designated\-initializers .sp لیست‌های مقداردهی اولیه برای انواع تجمیعی (aggregate types) را که می‌توان به جای آن به صورت مقداردهنده‌های اولیه مشخص‌شده (designated initializers) نوشت، پیدا می‌کند. .sp با لیست‌های مقداردهی اولیه ساده، هنگام اضافه کردن فیلدهای جدید در میان یک struct یا کلاس، بروز باگ‌ها بسیار آسان است. همین سردرگمی ممکن است هنگام تغییر ترتیب فیلدها نیز پیش بیاید. .sp استاندارد C++20 از نحو مقداردهنده اولیه مشخص‌شده برای انواع تجمیعی پشتیبانی می‌کند. با به‌کارگیری آن، همیشه می‌توانیم مطمئن شویم که تجمیع‌ها به درستی ساخته شده‌اند، زیرا به هر متغیری که مقداردهی می‌شود با نام آن ارجاع داده می‌شود. .sp مثال: .INDENT 0.0 .INDENT 3.5 .sp .EX struct S { int i, j; }; .EE .UNINDENT .UNINDENT .sp یک نوع تجمیعی است که باید به شکل زیر مقداردهی اولیه شود .INDENT 0.0 .INDENT 3.5 .sp .EX S s{.i = 1, .j = 2}; .EE .UNINDENT .UNINDENT .sp به جای .INDENT 0.0 .INDENT 3.5 .sp .EX S s{1, 2}; .EE .UNINDENT .UNINDENT .sp که می‌تواند در صورت جابه‌جا شدن \fBi\fP و \fBj\fP در اعلان \fBS\fP به راحتی مشکل‌ساز شود. .sp حتی هنگام کامپایل در نسخه‌ای از زبان قدیمی‌تر از C++20، بسته به کامپایلر شما، مقداردهنده‌های مشخص‌شده احتمالاً پشتیبانی می‌شوند. بنابراین، این بررسی به‌طور پیش‌فرض به C99/C++20 و بالاتر محدود شده است. برای دریافت پشتیبانی از نشان‌دهنده‌های ترکیبی در لیست مقداردهی اولیه در C گزینه \fI\-Wc99\-designator\fP و برای پشتیبانی از مقداردهنده‌های مشخص‌شده در حالت‌های زبانی قدیمی‌تر C++ گزینه \fI\-Wc++20\-designator\fP را بررسی کنید. .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoreMacros مقدار \fIfalse\fP مشخص می‌کند که اجزای لیست‌های مقداردهی اولیه که از ماکروها بسط یافته‌اند بررسی نشوند. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B IgnoreSingleElementAggregates مقدار \fIfalse\fP مشخص می‌کند که حتی مقداردهنده‌های اولیه برای انواع تجمیعی تنها با یک عنصر نیز باید بررسی شوند. مقدار پیش‌فرض \fItrue\fP است. مقداردهی‌های اولیه \fBstd::array\fP همیشه مستثنی هستند، زیرا این نوع یک انتزاع کتابخانه استاندارد است و قرار نیست با مقداردهنده‌های اولیه مشخص‌شده مقداردهی شود. .UNINDENT .INDENT 0.0 .TP .B RestrictToPODTypes مقدار \fItrue\fP مشخص می‌کند که فقط انواع Plain Old Data (POD) باید بررسی شوند. این امر باعث می‌شود که بررسی حتی در استانداردهای قدیمی‌تر C++ نیز قابل اعمال باشد. مقدار پیش‌فرض \fIfalse\fP است. .UNINDENT .INDENT 0.0 .TP .B StrictCStandardCompliance هنگامی که روی \fIfalse\fP تنظیم شود، بررسی خود را به C99 و بالاتر محدود نمی‌کند. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .INDENT 0.0 .TP .B StrictCppStandardCompliance هنگامی که روی \fIfalse\fP تنظیم شود، بررسی خود را به C++20 و بالاتر محدود نمی‌کند. مقدار پیش‌فرض \fItrue\fP است. .UNINDENT .SS modernize\-use\-emplace .sp این بررسی، درج مواردی در یک نگه‌دارنده به سبک STL را که از طریق فراخوانی متدهای \fBpush_back\fP، \fBpush\fP یا \fBpush_front\fP با یک متغیر موقت صریحاً ساخته‌شده از نوع عنصر نگه‌دارنده انجام شده است، نشانه‌گذاری می‌کند. در این حالت، متدهای معادل متناظر \fBemplace\fP منجر به کدی کوتاه‌تر و به‌طور بالقوه کارآمدتر می‌شوند. در حال حاضر این بررسی از \fBinsert\fP پشتیبانی نمی‌کند. همچنین از توابع \fBinsert\fP برای نگه‌دارنده‌های انجمنی نیز پشتیبانی نمی‌کند، زیرا جایگزینی \fBinsert\fP با \fBemplace\fP ممکن است باعث افت سرعت شود \%، اما ممکن است در آینده با افزودن گزینه‌ای این پشتیبانی اضافه شود. .sp گزینه‌های \fBContainersWithPushBack\fP، \fBContainersWithPush\fP و \fBContainersWithPushFront\fP به ترتیب برای مشخص کردن انواع نگه‌دارنده‌هایی که از عملیات \fBpush_back\fP، \fBpush\fP و \fBpush_front\fP پشتیبانی می‌کنند به کار می‌روند. مقادیر پیش‌فرض این گزینه‌ها به شرح زیر است: .INDENT 0.0 .IP \(bu 2 \fBContainersWithPushBack\fP: \fBstd::vector\fP، \fBstd::deque\fP و \fBstd::list\fP\&. .IP \(bu 2 \fBContainersWithPush\fP: \fBstd::stack\fP، \fBstd::queue\fP و \fBstd::priority_queue\fP\&. .IP \(bu 2 \fBContainersWithPushFront\fP: \fBstd::forward_list\fP، \fBstd::list\fP و \fBstd::deque\fP\&. .UNINDENT .sp این بررسی همچنین مواردی را که در آن‌ها یک متد شبیه به \fBemplace\fP به‌طور نادرست استفاده شده است گزارش می‌دهد، مانند استفاده از \fBemplace_back\fP در حالی که یک سازنده نیز هم‌زمان فراخوانی می‌شود. این کار باعث ایجاد یک شیء موقت می‌شود که در بهترین حالت نیازمند انتقال (move) و در بدترین حالت نیازمند کپی (copy) است. تقریباً همه توابع شبیه به \fBemplace\fP در STL تحت پوشش این مورد قرار دارند، به استثنای \fBtry_emplace\fP در \fBstd::map\fP و \fBstd::unordered_map\fP، زیرا رفتار آن کمی با بقیه متفاوت است. نگه‌دارنده‌های بیشتری را می‌توان با گزینه \fBEmplacyFunctions\fP اضافه کرد، مشروط بر اینکه نگه‌دارنده یک نوع \fBvalue_type\fP تعریف کند و توابع شبیه به \fBemplace\fP یک شیء از نوع \fBvalue_type\fP بسازند. .sp قبل: .INDENT 0.0 .INDENT 3.5 .sp .EX std::vector v; v.push_back(MyClass(21, 37)); v.emplace_back(MyClass(21, 37)); std::vector> w; w.push_back(std::pair(21, 37)); w.push_back(std::make_pair(21L, 37L)); w.emplace_back(std::make_pair(21L, 37L)); .EE .UNINDENT .UNINDENT .sp بعد: .INDENT 0.0 .INDENT 3.5 .sp .EX std::vector v; v.emplace_back(21, 37); v.emplace_back(21, 37); std::vector> w; w.emplace_back(21, 37); w.emplace_back(21L, 37L); w.emplace_back(21L, 37L); .EE .UNINDENT .UNINDENT .sp به‌طور پیش‌فرض، این بررسی قادر است فراخوانی‌های غیرضروری \fBstd::make_pair\fP و \fBstd::make_tuple\fP را از فراخوانی‌های \fBpush_back\fP روی نگه‌دارنده‌های \fBstd::pair\fP و \fBstd::tuple\fP حذف کند. انواع سفارشی شبه‌تاپل را می‌توان با گزینه \fBTupleTypes\fP تغییر داد؛ توابع ساخت سفارشی را نیز می‌توان با گزینه \fBTupleMakeFunctions\fP تعیین کرد. .sp حالت دیگر زمانی است که آرگومان‌هایی را ارسال می‌کنیم که به نوعی در داخل نگه‌دارنده تبدیل خواهند شد. .sp قبل: .INDENT 0.0 .INDENT 3.5 .sp .EX std::vector > v; v.push_back(\(dqabc\(dq); .EE .UNINDENT .UNINDENT .sp بعد: .INDENT 0.0 .INDENT 3.5 .sp .EX std::vector > v; v.emplace_back(\(dqabc\(dq); .EE .UNINDENT .UNINDENT .sp در برخی موارد تبدیل معتبر خواهد بود، اما کد از نظر کنترل استثناها امن (exception safe) نخواهد بود. در چنین حالتی فراخوانی‌های \fBpush_back\fP جایگزین نخواهند شد. .INDENT 0.0 .INDENT 3.5 .sp .EX std::vector> v; v.push_back(std::unique_ptr(new int(0))); auto *ptr = new int(1); v.push_back(std::unique_ptr(ptr)); .EE .UNINDENT .UNINDENT .sp علت این است که جایگزینی آن با \fBemplace_back\fP در صورتی که پیش از جاگذاری (emplacement) استثنایی رخ دهد (برای مثال، حافظه کافی برای افزودن عنصر جدید وجود نداشته باشد)، ممکن است باعث نشت حافظه (leak) این اشاره‌گر شود. .sp برای اطلاعات بیشتر، بخش ۴۲ از کتاب «Effective Modern C++» نوشته اسکات مایرز با عنوان «Consider emplacement instead of insertion» را مطالعه کنید. .sp اشاره‌گرهای هوشمند پیش‌فرضی که در نظر گرفته می‌شوند عبارتند از: \fBstd::unique_ptr\fP، \fBstd::shared_ptr\fP و \fBstd::auto_ptr\fP\&. برای تعیین سایر اشاره‌گرهای هوشمند یا کلاس‌های دیگر از گزینه \fBSmartPointers\fP استفاده کنید. .sp این بررسی همچنین در صورتی که هر یک از آرگومان‌های فراخوانی سازنده شامل موارد زیر باشد عمل نخواهد کرد: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 یک میدان بیتی (bit-field) باشد (میدان‌های بیتی نمی‌توانند به rvalue/universal reference متصل شوند) .IP \(bu 2 یک عبارت \fBnew\fP باشد (به منظور جلوگیری از نشت حافظه) .IP \(bu 2 اگر آرگومان از طریق تبدیل مشتق به پایه (derived-to-base cast) تبدیل شود. .UNINDENT .UNINDENT .UNINDENT .sp این بررسی برای اجرا به C++11 یا بالاتر نیاز دارد. .SS گزینه‌ها .INDENT 0.0 .TP .B ContainersWithPushBack فهرستی جداشده با نقطه ویرگول (semicolon) از نام کلاس‌های نگه‌دارنده‌های سفارشی که از \fBpush_back\fP پشتیبانی می‌کنند. .UNINDENT .INDENT 0.0 .TP .B ContainersWithPush فهرستی جداشده با نقطه ویرگول از نام کلاس‌های نگه‌دارنده‌های سفارشی که از \fBpush\fP پشتیبانی می‌کنند. .UNINDENT .INDENT 0.0 .TP .B ContainersWithPushFront فهرستی جداشده با نقطه ویرگول از نام کلاس‌های نگه‌دارنده‌های سفارشی که از \fBpush_front\fP پشتیبانی می‌کنند. .UNINDENT .INDENT 0.0 .TP .B IgnoreImplicitConstructors هنگامی که برابر با \fItrue\fP باشد، بررسی آرگومان‌های به‌طور ضمنی ساخته‌شده در \fBpush_back\fP را نادیده می‌گیرد؛ به عنوان مثال: .INDENT 7.0 .INDENT 3.5 .sp .EX std::vector v; v.push_back(\(dqa\(dq); // Ignored when IgnoreImplicitConstructors is \(gatrue\(ga. .EE .UNINDENT .UNINDENT .sp پیش‌فرض برابر با \fIfalse\fP است. .UNINDENT .INDENT 0.0 .TP .B SmartPointers فهرستی جداشده با نقطه ویرگول از نام کلاس‌های اشاره‌گرهای هوشمند سفارشی. .UNINDENT .INDENT 0.0 .TP .B TupleTypes فهرستی جداشده با نقطه ویرگول از نام کلاس‌های شبه \fBstd::tuple\fP\&. .UNINDENT .INDENT 0.0 .TP .B TupleMakeFunctions فهرستی جداشده با نقطه ویرگول از نام توابع شبه \fBstd::make_tuple\fP\&. این فراخوانی‌های توابع از فراخوانی‌های \fBpush_back\fP حذف شده و به \fBemplace_back\fP تبدیل می‌شوند. .UNINDENT .INDENT 0.0 .TP .B EmplacyFunctions فهرستی جداشده با نقطه ویرگول از نگه‌دارنده‌ها بدون پارامترهای قالبشان به همراه یک متد شبه \fBemplace\fP از نگه‌دارنده. به عنوان مثال: \fBvector::emplace_back\fP\&. این متدها از نظر استفاده نادرست بررسی خواهند شد و در صورت ایجاد غیرضروری یک شیء موقت، بررسی آن را گزارش می‌کند. تمام نگه‌دارنده‌های STL با چنین توابع عضوی به‌طور پیش‌فرض پشتیبانی می‌شوند. .UNINDENT .SS مثال .INDENT 0.0 .INDENT 3.5 .sp .EX std::vector> x; x.push_back(MakeMyTuple(1, false, \(aqx\(aq)); x.emplace_back(MakeMyTuple(1, false, \(aqx\(aq)); .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX std::vector> x; x.emplace_back(1, false, \(aqx\(aq); x.emplace_back(1, false, \(aqx\(aq); .EE .UNINDENT .UNINDENT .sp هنگامی که \fBTupleTypes\fP روی \fBMyTuple\fP، \fBTupleMakeFunctions\fP روی \fBMakeMyTuple\fP و \fBEmplacyFunctions\fP روی \fBvector::emplace_back\fP تنظیم شده باشد\&. .SS modernize\-use\-equals\-default .sp این بررسی بدنه‌های پیش‌فرض توابع عضوی خاص را با \fB= default;\fP جایگزین می‌کند\&. اعلانات صریح پیش‌فرض‌شده توابع (explicitly defaulted) فرصت‌های بهینه‌سازی بیشتری را فراهم می‌کنند، زیرا ممکن است کامپایلر این توابع را به عنوان توابع ناچیز (trivial) در نظر بگیرد\&. .INDENT 0.0 .INDENT 3.5 .sp .EX struct A { A() {} ~A(); }; A::~A() {} // becomes struct A { A() = default; ~A(); }; A::~A() = default; .EE .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 سازنده جابجایی (Move-constructor) و عملگر انتساب جابجایی (move-assignment operator) هنوز پشتیبانی نمی‌شوند. .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoreMacros اگر روی \fItrue\fP تنظیم شود، بررسی در داخل ماکروها هشداری صادر نمی‌کند و اعضای خاصی را که بدنه آن‌ها حاوی ماکروها یا دستورات پیش‌پردازنده است نادیده می‌گیرد\&. پیش‌فرض \fItrue\fP است\&. .UNINDENT .SS modernize\-use\-equals\-delete .sp توابع عضوی خاص و خصوصیِ پیاده‌سازی‌نشده را شناسایی کرده و استفاده از \fB= delete\fP را برای آن‌ها توصیه می‌کند\&. علاوه بر این، انتقال هرگونه تابع عضو حذف‌شده از بخش \fBprivate\fP به بخش \fBpublic\fP را پیشنهاد می‌دهد\&. .sp پیش از معرفی C++11، روش اصلی برای عملاً «پاک کردن» یک تابع خاص شامل اعلان آن به صورت \fBprivate\fP بدون ارائه تعریف بود\&. این رویکرد به خطای کامپایلر (هنگام تلاش برای فراخوانی یک تابع خصوصی) یا خطای پیونددهنده (به دلیل ارجاع تعریف‌نشده) منجر می‌شد\&. .sp با این حال، پس از پیدایش C++11، رویکرد مرسوم‌تری برای دستیابی به این هدف پدید آمد\&. این روش شامل نشانه‌گذاری توابع به صورت \fB= delete\fP و نگه‌داشتن آن‌ها در بخش \fBpublic\fP کلاس است\&. .sp برای جلوگیری از هشدارهای نادرست (false positives)، این بررسی تنها در یک واحد ترجمه (translation unit) فعال است که تمام توابع عضوی دیگر در آن پیاده‌سازی شده باشند\&. این بررسی با افزودن \fB= delete\fP اصلاحات جزئی تولید می‌کند، اما انتقال دستی توابع به بخش \fBpublic\fP بر عهده کاربر است\&. .INDENT 0.0 .INDENT 3.5 .sp .EX // Example: bad class A { private: A(const A&); A& operator=(const A&); }; // Example: good class A { public: A(const A&) = delete; A& operator=(const A&) = delete; }; .EE .UNINDENT .UNINDENT .INDENT 0.0 .TP .B IgnoreMacros اگر این گزینه روی \fItrue\fP تنظیم شود (پیش‌فرض \fItrue\fP است)، بررسی درباره توابعی که داخل ماکروها اعلان شده‌اند هشداری نمی‌دهد\&. .UNINDENT .SS modernize\-use\-integer\-sign\-comparison .sp مقایسه‌های بین اعداد صحیح علامت‌دار و بدون علامت را در صورت وجود، با معادل امن C++20 آن‌ها یعنی \fBstd::cmp_*\fP جایگزین می‌کند\&. .sp این بررسی تنها برای C++20 یا بالاتر جایگزینی ارائه می‌دهد، در غیر این صورت مشکل را برجسته کرده و انتظار دارد کاربر آن را به صورت دستی برطرف کند\&. .sp نمونه‌هایی از اصلاحات ایجادشده توسط بررسی: .INDENT 0.0 .INDENT 3.5 .sp .EX unsigned int func(int a, unsigned int b) { return a == b; } .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به .INDENT 0.0 .INDENT 3.5 .sp .EX #include unsigned int func(int a, unsigned int b) { return std::cmp_equal(a, b); } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IncludeStyle رشته‌ای که شیوه درج include را مشخص می‌کند، \fIllvm\fP یا \fIgoogle\fP\&. پیش‌فرض \fIllvm\fP است\&. .UNINDENT .INDENT 0.0 .TP .B EnableQtSupport جایگزین \fBq20::cmp_*\fP در C++17 را برای برنامه‌های مبتنی بر Qt در دسترس قرار می‌دهد\&. پیش‌فرض \fIfalse\fP است\&. .UNINDENT .SS modernize\-use\-nodiscard .sp صفت‌های \fB[[nodiscard]]\fP (معرفی‌شده در C++17) را به توابع عضو اضافه می‌کند تا در زمان کامپایل مشخص شود که مقادیر بازگشتی کدام توابع نباید نادیده گرفته شوند. .sp توابع عضو برای بررسی شدن توسط این بررسی، باید شرایط زیر را داشته باشند: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 فاقد صفت‌های \fB[[nodiscard]]\fP، \fB[[noreturn]]\fP، \fB__attribute__((warn_unused_result))\fP، \fB[[clang::warn_unused_result]]\fP یا \fB[[gcc::warn_unused_result]]\fP باشند، .IP \(bu 2 نوع بازگشتی آن‌ها غیر از void باشد، .IP \(bu 2 انواع بازگشتی غیرقالب (non\-template) داشته باشند، .IP \(bu 2 تابع عضو از نوع const باشد، .IP \(bu 2 توابع با تعداد آرگومان متغیر (non\-variadic) نباشند، .IP \(bu 2 فاقد پارامترهای ارجاعی غیرثابت (non\-const reference) باشند، .IP \(bu 2 فاقد پارامترهای اشاره‌گر باشند، .IP \(bu 2 فاقد پارامترهای قالبی (template parameters) باشند، .IP \(bu 2 فاقد پارامترهای تابعی قالبی باشند، .IP \(bu 2 عضوی از کلاسی با متغیرهای عضو از نوع mutable نباشند، .IP \(bu 2 فاقد لامبداها (Lambdas) باشند، .IP \(bu 2 فاقد توابع تبدیل (conversion functions) باشند. .UNINDENT .UNINDENT .UNINDENT .sp چنین توابعی هیچ راهی برای تغییر وضعیت یا انتقال مقادیر به غیر از نوع بازگشتی ندارند. مگر اینکه توابع عضو از طریق فراخوانی‌های خارجی (مانند ورودی/خروجی I/O) وضعیتی را تغییر دهند. .SS مثال .INDENT 0.0 .INDENT 3.5 .sp .EX bool empty() const; bool empty(int i) const; .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX [[nodiscard]] bool empty() const; [[nodiscard]] bool empty(int i) const; .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B ReplacementString یک ماکرو را برای استفاده به جای \fB[[nodiscard]]\fP مشخص می‌کند. این گزینه زمانی مفید است که از کدهای منبعی نگهداری می‌کنید که باید با کامپایلرهای قدیمی‌تر از C++17 کامپایل شوند. .UNINDENT .SS مثال .INDENT 0.0 .INDENT 3.5 .sp .EX bool empty() const; bool empty(int i) const; .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX NO_DISCARD bool empty() const; NO_DISCARD bool empty(int i) const; .EE .UNINDENT .UNINDENT .sp در صورتی که گزینهٔ \fBReplacementString\fP روی \fINO_DISCARD\fP تنظیم شده باشد. .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 اگر \fBReplacementString\fP یک صفت C++ نبوده و در عوض یک ماکرو باشد، آن ماکرو باید در دامنه (scope) تعریف شده باشد، در غیر این صورت fix\-it اعمال نخواهد شد. .UNINDENT .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 برای گزینه‌های ساختار نحوی جایگزین \fB__attribute__\fP به منظور علامت‌گذاری توابع به عنوان \fB[[nodiscard]]\fP در کدهای منبع غیر از C++17، به \% مراجعه کنید. .UNINDENT .UNINDENT .SS modernize\-use\-noexcept .sp این بررسی مشخصه‌های استثنای پویای (dynamic exception specifications) منسوخ‌شده را با مشخصه مناسب noexcept (معرفی‌شده در C++11) جایگزین می‌کند. به‌طور پیش‌فرض، این بررسی \fBthrow()\fP را با \fBnoexcept\fP، و \fBthrow([,...])\fP یا \fBthrow(...)\fP را با \fBnoexcept(false)\fP جایگزین می‌کند. .SS مثال .INDENT 0.0 .INDENT 3.5 .sp .EX void foo() throw(); void bar() throw(int) {} .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo() noexcept; void bar() noexcept(false) {} .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B ReplacementString کاربران می‌توانند از \fBReplacementString\fP \%<#cmdoption-arg-ReplacementString> برای مشخص کردن یک ماکرو جهت استفاده به جای \fBnoexcept\fP استفاده کنند. این ویژگی زمانی مفید است که از کدهای منبعی نگهداری می‌شود که از نشانه‌گذاری مشخصه استثنای سفارشی دیگری غیر از \fBnoexcept\fP استفاده می‌کنند. راهنماهای Fix\-it تنها برای مشخصه‌های بدون پرتاب استثنا (non\-throwing) تولید خواهند شد. .UNINDENT .SS مثال .INDENT 0.0 .INDENT 3.5 .sp .EX void bar() throw(int); void foo() throw(); .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX void bar() throw(int); // No fix\-it generated. void foo() NOEXCEPT; .EE .UNINDENT .UNINDENT .sp اگر گزینهٔ \fBReplacementString\fP \%<#\:cmdoption-arg-ReplacementString> روی \fINOEXCEPT\fP تنظیم شده باشد. .INDENT 0.0 .TP .B UseNoexceptFalse .UNINDENT .sp به‌طور پیش‌فرض فعال است، غیرفعال کردن آن باعث ایجاد راهنمایی‌های fix\-it می‌شود که مشخصه‌های پویای پرتاب استثنا، مانند \fBthrow()\fP را کاملاً و بدون ارائهٔ متن جایگزین حذف می‌کند، به‌جز برای مخرب‌ها (destructors) و عملگرهای delete که به‌طور پیش‌فرض \fBnoexcept(true)\fP هستند. .SS مثال .INDENT 0.0 .INDENT 3.5 .sp .EX void foo() throw(int) {} struct bar { void foobar() throw(int); void operator delete(void *ptr) throw(int); void operator delete[](void *ptr) throw(int); ~bar() throw(int); } .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX void foo() {} struct bar { void foobar(); void operator delete(void *ptr) noexcept(false); void operator delete[](void *ptr) noexcept(false); ~bar() noexcept(false); } .EE .UNINDENT .UNINDENT .sp اگر گزینهٔ \fBUseNoexceptFalse\fP روی \fIfalse\fP تنظیم شده باشد. .SS modernize\-use\-nullptr .sp این بررسی، استفاده از ثابت‌های اشاره‌گر تهی (مانند \fBNULL\fP، \fB0\fP) را برای استفاده از کلیدواژهٔ جدید C++11 و C23 یعنی \fBnullptr\fP تبدیل می‌کند. .SS مثال .INDENT 0.0 .INDENT 3.5 .sp .EX void assignment() { char *a = NULL; char *b = 0; char c = 0; } int *ret_ptr() { return 0; } .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX void assignment() { char *a = nullptr; char *b = nullptr; char c = 0; } int *ret_ptr() { return nullptr; } .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoredTypes فهرستی جداشده با نقطه ویرگول (semicolon) از عبارات منظم (regex) برای مطابقت با انواع اشاره‌گرهایی که تبدیل‌های ضمنی (implicit casts) برای آن‌ها نادیده گرفته خواهد شد. مقدار پیش‌فرض: \fIstd::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec\fP\&. .UNINDENT .INDENT 0.0 .TP .B NullMacros فهرستی جداشده با کاما از نام‌های ماکرو که همراه با \fBNULL\fP تبدیل خواهند شد. به‌طور پیش‌فرض این بررسی تنها ماکروی \fBNULL\fP را جایگزین می‌کند و از هرگونه ماکروی مشابه تعریف‌شده توسط کاربر صرف‌نظر خواهد کرد. .UNINDENT .SS مثال .INDENT 0.0 .INDENT 3.5 .sp .EX #define MY_NULL (void*)0 void assignment() { void *p = MY_NULL; } .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX #define MY_NULL NULL void assignment() { int *p = nullptr; } .EE .UNINDENT .UNINDENT .sp اگر گزینهٔ \fBNullMacros\fP روی \fBMY_NULL\fP تنظیم شده باشد. .SS modernize\-use\-override .sp کلیدواژهٔ \fBoverride\fP (معرفی‌شده در C++11) را به توابع مجازی بازنویسی‌شده اضافه می‌کند و \fBvirtual\fP را از این توابع حذف می‌نماید چرا که دیگر نیازی به آن نیست. .sp استفاده از \fBvirtual\fP در پیاده‌سازی‌های کلاس‌های غیر پایه به این منظور استفاده می‌شد که به کاربر نشان دهد یک تابع مجازی است. کامپایلرهای C++ از وجود آن برای مشخص کردن یک تابع بازنویسی‌شده استفاده نمی‌کردند. .sp در C++11 کلیدواژه‌های \fBoverride\fP و \fBfinal\fP معرفی شدند تا توابع بازنویسی‌شده به‌درستی علامت‌گذاری شوند. وجود آن‌ها به کامپایلرها اجازه می‌دهد بررسی کنند که آیا یک تابع بازنویسی‌شده به‌درستی پیاده‌سازی کلاس پایه را بازنویسی (override) می‌کند یا خیر. .sp این قابلیت می‌تواند مفید باشد چرا که کامپایلرها می‌توانند در زمان کامپایل خطایی ایجاد کنند هرگاه: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .IP \(bu 2 امضای تابع پیاده‌سازی‌شده در کلاس پایه تغییر کند. .IP \(bu 2 کاربر بازنویسی را با امضای صحیح ایجاد نکرده باشد. .UNINDENT .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IgnoreDestructors اگر روی \fItrue\fP تنظیم شود، این بررسی مخرب‌ها (destructors) را عیب‌یابی نخواهد کرد. پیش‌فرض \fIfalse\fP است. .UNINDENT .INDENT 0.0 .TP .B IgnoreTemplateInstantiations اگر روی \fItrue\fP تنظیم شود، به این بررسی دستور می‌دهد که بازنویسی‌های توابع مجازی (virtual function overrides) که بخشی از مصداق‌سازی‌های الگو (template instantiations) هستند را نادیده بگیرد. پیش‌فرض \fIfalse\fP است. .UNINDENT .INDENT 0.0 .TP .B AllowOverrideAndFinal اگر روی \fItrue\fP تنظیم شود، این بررسی \fBoverride\fP را به عنوان افزونگی همراه با \fBfinal\fP تشخیص نخواهد داد. این مورد زمانی مفید است که کد توسط کامپایلری با پرچم‌های بررسی هشدار/خطا کامپایل می‌شود که صریحاً نیاز به \fBoverride\fP روی اعضای بازنویسی‌شده دارند، مانند \fBgcc \-Wsuggest\-override\fP/\fBgcc \-Werror=suggest\-override\fP. پیش‌فرض \fIfalse\fP است. .UNINDENT .INDENT 0.0 .TP .B OverrideSpelling یک ماکرو را برای استفاده به جای \fBoverride\fP مشخص می‌کند. این گزینه هنگام نگهداری کدهای منبعی که نیاز به کامپایل با کامپایلرهای قبل از C++11 نیز دارند مفید است. .UNINDENT .INDENT 0.0 .TP .B FinalSpelling یک ماکرو را برای استفاده به جای \fBfinal\fP مشخص می‌کند. این گزینه هنگام نگهداری کدهای منبعی که نیاز به کامپایل با کامپایلرهای قبل از C++11 نیز دارند مفید است. .UNINDENT .sp \fBنکته:\fP .INDENT 0.0 .INDENT 3.5 برای اطلاعات بیشتر در مورد استفاده از \fBoverride\fP صفحهٔ \% را ببینید. .UNINDENT .UNINDENT .SS modernize\-use\-ranges .sp فراخوانی‌های الگوریتم‌های تکرارکننده (iterator) کتابخانهٔ استاندارد را که می‌توانند با نسخهٔ ranges جایگزین شوند، شناسایی می‌کند. .SS مثال .INDENT 0.0 .INDENT 3.5 .sp .EX auto Iter1 = std::find(Items.begin(), Items.end(), 0); auto AreSame = std::equal(Items1.cbegin(), Items1.cend(), std::begin(Items2), std::end(Items2)); .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX auto Iter1 = std::ranges::find(Items, 0); auto AreSame = std::ranges::equal(Items1, Items2); .EE .UNINDENT .UNINDENT .SS الگوریتم‌های پشتیبانی‌شده .sp فراخوانی‌های مربوط به الگوریتم‌های زیر از کتابخانهٔ std بررسی می‌شوند: .sp \fBstd::adjacent_find\fP، \fBstd::all_of\fP، \fBstd::any_of\fP، \fBstd::binary_search\fP، \fBstd::copy_backward\fP، \fBstd::copy_if\fP، \fBstd::copy\fP، \fBstd::destroy\fP، \fBstd::equal_range\fP، \fBstd::equal\fP، \fBstd::fill\fP، \fBstd::find_end\fP، \fBstd::find_if_not\fP، \fBstd::find_if\fP، \fBstd::find\fP، \fBstd::for_each\fP، \fBstd::generate\fP، \fBstd::includes\fP، \fBstd::inplace_merge\fP، \fBstd::iota\fP، \fBstd::is_heap_until\fP، \fBstd::is_heap\fP، \fBstd::is_partitioned\fP، \fBstd::is_permutation\fP، \fBstd::is_sorted_until\fP، \fBstd::is_sorted\fP، \fBstd::lexicographical_compare\fP، \fBstd::lower_bound\fP، \fBstd::make_heap\fP، \fBstd::max_element\fP، \fBstd::merge\fP، \fBstd::min_element\fP، \fBstd::minmax_element\fP، \fBstd::mismatch\fP، \fBstd::move_backward\fP، \fBstd::move\fP، \fBstd::next_permutation\fP، \fBstd::none_of\fP، \fBstd::partial_sort_copy\fP، \fBstd::partition_copy\fP، \fBstd::partition_point\fP، \fBstd::partition\fP، \fBstd::pop_heap\fP، \fBstd::prev_permutation\fP، \fBstd::push_heap\fP، \fBstd::remove_copy_if\fP، \fBstd::remove_copy\fP، \fBstd::remove\fP، \fBstd::remove_if\fP، \fBstd::replace_if\fP، \fBstd::replace\fP، \fBstd::reverse_copy\fP، \fBstd::reverse\fP، \fBstd::rotate\fP، \fBstd::rotate_copy\fP، \fBstd::sample\fP، \fBstd::search\fP، \fBstd::set_difference\fP، \fBstd::set_intersection\fP، \fBstd::set_symmetric_difference\fP، \fBstd::set_union\fP، \fBstd::shift_left\fP، \fBstd::shift_right\fP، \fBstd::sort_heap\fP، \fBstd::sort\fP، \fBstd::stable_partition\fP، \fBstd::stable_sort\fP، \fBstd::transform\fP، \fBstd::uninitialized_copy\fP، \fBstd::uninitialized_default_construct\fP، \fBstd::uninitialized_fill\fP، \fBstd::uninitialized_move\fP، \fBstd::uninitialized_value_construct\fP، \fBstd::unique_copy\fP، \fBstd::unique\fP، \fBstd::upper_bound\fP\&. .sp نکته: برخی از الگوریتم‌های range برای \fBvector\fP به C++23 نیاز دارند زیرا از تکرارکننده‌های پروکسی (proxy iterators) استفاده می‌کند. .SS پیمایش معکوس (Reverse Iteration) .sp اگر فراخوانی‌ها با استفاده از تکرارکننده‌های معکوس بر روی کانتینرها انجام شوند، کد با استفاده از آداپتور \fBstd::views::reverse\fP اصلاح خواهد شد. .INDENT 0.0 .INDENT 3.5 .sp .EX auto AreSame = std::equal(Items1.rbegin(), Items1.rend(), std::crbegin(Items2), std::crend(Items2)); .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX auto AreSame = std::ranges::equal(std::views::reverse(Items1), std::views::reverse(Items2)); .EE .UNINDENT .UNINDENT .SS گزینه‌ها .INDENT 0.0 .TP .B IncludeStyle رشته‌ای که مشخص می‌کند کدام سبک include استفاده شود، \fIllvm\fP یا \fIgoogle\fP\&. مقدار پیش‌فرض \fIllvm\fP است. .UNINDENT .INDENT 0.0 .TP .B UseReversePipe هنگامی که \fItrue\fP باشد (پیش‌فرض \fIfalse\fP است)، اصلاحاتی که شامل دامنه‌های معکوس هستند به جای نحو تابعی، از نحو آداپتور پایپ (pipe) استفاده خواهند کرد. .INDENT 7.0 .INDENT 3.5 .sp .EX std::find(Items.rbegin(), Items.rend(), 0); .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 7.0 .INDENT 3.5 .sp .EX std::ranges::find(Items | std::views::reverse, 0); .EE .UNINDENT .UNINDENT .UNINDENT .SS modernize\-use\-scoped\-lock .sp موارد استفاده از \fBstd::lock_guard\fP را پیدا کرده و جایگزینی آن‌ها با جایگزین C++17 یعنی \fBstd::scoped_lock\fP را پیشنهاد می‌دهد. .sp اصلاحات خودکار (Fix\-its) برای اعلان‌های تکی \fBstd::lock_guard\fP ارائه می‌شوند و برای اعلان‌های چندگانه \fBstd::lock_guard\fP که می‌توانند با یک اعلان تکی از \fBstd::scoped_lock\fP جایگزین شوند، هشدار صادر می‌شود. .SS مثال‌ها .sp اعلان تکی \fBstd::lock_guard\fP: .INDENT 0.0 .INDENT 3.5 .sp .EX std::mutex M; std::lock_guard L(M); .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX std::mutex M; std::scoped_lock L(M); .EE .UNINDENT .UNINDENT .sp اعلان تکی \fBstd::lock_guard\fP همراه با \fBstd::adopt_lock\fP: .INDENT 0.0 .INDENT 3.5 .sp .EX std::mutex M; std::lock(M); std::lock_guard L(M, std::adopt_lock); .EE .UNINDENT .UNINDENT .sp تبدیل می‌شود به: .INDENT 0.0 .INDENT 3.5 .sp .EX std::mutex M; std::lock(M); std::scoped_lock L(std::adopt_lock, M); .EE .UNINDENT .UNINDENT .sp اعلان‌های چندگانه \fBstd::lock_guard\fP تنها هشدار صادر می‌کنند: .INDENT 0.0 .INDENT 3.5 .sp .EX std::mutex M1, M2; std::lock(M1, M2); std::lock_guard Lock1(M1, std::adopt_lock); // warning: use single \(aqstd::scoped_lock\(aq instead of multiple \(aqstd::lock_guard\(aq std::lock_guard Lock2(M2, std::adopt_lock); // note: additional \(aqstd::lock_guard\(aq declared here .EE .UNINDENT .UNINDENT .SS محدودیت‌ها .sp این بررسی در صورتی که \fBstd::lock_guard\fP به‌طور ضمنی از طریق پارامتر \fBtemplate\fP استفاده شده باشد، هشداری صادر نخواهد کرد: .INDENT 0.0 .INDENT 3.5 .sp .EX template