futogergely updated this revision to Diff 390270.
futogergely retitled this revision from "[clang-tidy] CERT MSC24-C Obsolescent
Functions check" to "[clang-tidy] Add cert-msc24-c checker.".
futogergely edited the summary of this revision.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D91000/new/
https://reviews.llvm.org/D91000
Files:
clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
clang-tools-extra/clang-tidy/cert/CMakeLists.txt
clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.cpp
clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.h
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/docs/clang-tidy/checks/cert-msc24-c.rst
clang-tools-extra/docs/clang-tidy/checks/list.rst
clang-tools-extra/test/clang-tidy/checkers/cert-msc24-c.c
Index: clang-tools-extra/test/clang-tidy/checkers/cert-msc24-c.c
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cert-msc24-c.c
@@ -0,0 +1,96 @@
+// RUN: %check_clang_tidy -check-suffix=WITH-ANNEX-K %s cert-msc24-c %t -- -- -D__STDC_LIB_EXT1__=1 -D__STDC_WANT_LIB_EXT1__=1
+// RUN: %check_clang_tidy -check-suffix=WITHOUT-ANNEX-K %s cert-msc24-c %t -- -- -U__STDC_LIB_EXT1__ -U__STDC_WANT_LIB_EXT1__
+// RUN: %check_clang_tidy -check-suffix=WITHOUT-ANNEX-K %s cert-msc24-c %t -- -- -D__STDC_LIB_EXT1__=1 -U__STDC_WANT_LIB_EXT1__
+// RUN: %check_clang_tidy -check-suffix=WITHOUT-ANNEX-K %s cert-msc24-c %t -- -- -U__STDC_LIB_EXT1__ -D__STDC_WANT_LIB_EXT1__=1
+
+typedef void *FILE;
+char *gets(char *s);
+void rewind(FILE *stream);
+void setbuf(FILE *stream, char *buf);
+
+void f1(char *s, FILE *f) {
+ gets(s);
+ // CHECK-MESSAGES-WITH-ANNEX-K: :[[@LINE-1]]:3: warning: function 'gets' is deprecated as of C99, removed from C11.
+ // CHECK-MESSAGES-WITHOUT-ANNEX-K: :[[@LINE-2]]:3: warning: function 'gets' is deprecated as of C99, removed from C11.
+
+ rewind(f);
+ // CHECK-MESSAGES-WITH-ANNEX-K: :[[@LINE-1]]:3: warning: function 'rewind' has no error detection; 'fseek' should be used instead.
+ // CHECK-MESSAGES-WITHOUT-ANNEX-K: :[[@LINE-2]]:3: warning: function 'rewind' has no error detection; 'fseek' should be used instead.
+
+ setbuf(f, s);
+ // CHECK-MESSAGES-WITH-ANNEX-K: :[[@LINE-1]]:3: warning: function 'setbuf' has no error detection; 'setvbuf' should be used instead.
+ // CHECK-MESSAGES-WITHOUT-ANNEX-K: :[[@LINE-2]]:3: warning: function 'setbuf' has no error detection; 'setvbuf' should be used instead.
+}
+
+struct tm;
+char *asctime(const struct tm *timeptr);
+
+void f2(const struct tm *timeptr) {
+ asctime(timeptr);
+ // CHECK-MESSAGES-WITH-ANNEX-K: :[[@LINE-1]]:3: warning: function 'asctime' is non-reentrant; 'asctime_s' should be used instead.
+ // no-warning WITHOUT-ANNEX-K
+
+ char *(*f_ptr1)(const struct tm *) = asctime;
+ // CHECK-MESSAGES-WITH-ANNEX-K: :[[@LINE-1]]:40: warning: function 'asctime' is non-reentrant; 'asctime_s' should be used instead.
+ // no-warning WITHOUT-ANNEX-K
+
+ char *(*f_ptr2)(const struct tm *) = &asctime;
+ // CHECK-MESSAGES-WITH-ANNEX-K: :[[@LINE-1]]:41: warning: function 'asctime' is non-reentrant; 'asctime_s' should be used instead.
+ // no-warning WITHOUT-ANNEX-K
+}
+
+FILE *fopen(const char *filename, const char *mode);
+FILE *freopen(const char *filename, const char *mode, FILE *stream);
+int fscanf(FILE *stream, const char *format, ...);
+
+void f3(char *s, FILE *f) {
+ fopen(s, s);
+ // CHECK-MESSAGES-WITH-ANNEX-K: :[[@LINE-1]]:3: warning: function 'fopen' has no exclusive access to file; 'fopen_s' should be used instead.
+ // no-warning WITHOUT-ANNEX-K
+
+ freopen(s, s, f);
+ // CHECK-MESSAGES-WITH-ANNEX-K: :[[@LINE-1]]:3: warning: function 'freopen' has no exclusive access to file; 'freopen_s' should be used instead.
+ // no-warning WITHOUT-ANNEX-K
+
+ int i;
+ fscanf(f, "%d", &i);
+ // CHECK-MESSAGES-WITH-ANNEX-K: :[[@LINE-1]]:3: warning: function 'fscanf' is obsolescent; 'fscanf_s' should be used instead.
+ // no-warning WITHOUT-ANNEX-K
+}
+
+typedef int time_t;
+char *ctime(const time_t *timer);
+
+void f4(const time_t *timer) {
+ ctime(timer);
+ // CHECK-MESSAGES-WITH-ANNEX-K: :[[@LINE-1]]:3: warning: function 'ctime' is non-reentrant; 'ctime_s' should be used instead.
+ // no-warning WITHOUT-ANNEX-K
+}
+
+typedef int errno_t;
+typedef size_t rsize_t;
+errno_t asctime_s(char *s, rsize_t maxsize, const struct tm *timeptr);
+errno_t strcat_s(char *s1, rsize_t s1max, const char *s2);
+int fseek(FILE *stream, long int offset, int whence);
+int setvbuf(FILE *stream, char *buf, int mode, size_t size);
+
+void fUsingSafeFunctions(const struct tm *timeptr, FILE *f) {
+ const size_t BUFFSIZE = 32;
+ char buf[BUFFSIZE] = {0};
+
+ // no-warning, safe function from annex K is used
+ if (asctime_s(buf, BUFFSIZE, timeptr) != 0)
+ return;
+
+ // no-warning, safe function from annex K is used
+ if (strcat_s(buf, BUFFSIZE, "something") != 0)
+ return;
+
+ // no-warning, fseeks supports error checking
+ if (fseek(f, 0, 0) != 0)
+ return;
+
+ // no-warning, setvbuf supports error checking
+ if (setvbuf(f, buf, 0, BUFFSIZE) != 0)
+ return;
+}
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -123,6 +123,7 @@
`cert-flp30-c <cert-flp30-c.html>`_,
`cert-flp37-c <cert-flp37-c.html>`_,
`cert-mem57-cpp <cert-mem57-cpp.html>`_,
+ `cert-msc24-c <cert-msc24-c.html>`_,
`cert-msc50-cpp <cert-msc50-cpp.html>`_,
`cert-msc51-cpp <cert-msc51-cpp.html>`_,
`cert-oop57-cpp <cert-oop57-cpp.html>`_,
Index: clang-tools-extra/docs/clang-tidy/checks/cert-msc24-c.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/cert-msc24-c.rst
@@ -0,0 +1,91 @@
+.. title:: clang-tidy - cert-msc24-c
+
+cert-msc24-c
+============
+
+Checks for deprecated and obsolescent functions listed in
+CERT C Coding Standard Recommendation MSC24-C (`MSC24-C. Do not use deprecated or obsolescent functions
+<https://wiki.sei.cmu.edu/confluence/display/c/MSC24-C.+Do+not+use+deprecated+or+obsolescent+functions>`_.).
+For the listed functions, an alternative, more secure replacement is suggested, if available.
+The checker heavily relies on the functions from annex K (Bounds-checking interfaces) of C11.
+
+For the following functions, replacement is suggested from annex K: `asctime`,
+`ctime`, `fopen`, `freopen`, `bsearch`, `fprintf`, `fscanf`, `fwprintf`, `fwscanf`,
+`getenv`, `gmtime`, `localtime`, `mbsrtowcs`, `mbstowcs`, `memcpy`, `memmove`, `printf`,
+`qsort`, `snprintf`, `sprintf`, `sscanf`, `strcat`, `strcpy`, `strerror`,
+`strncat`, `strncpy`, `strtok`, `swprintf`, `swscanf`, `vfprintf`, `vfscanf`, `vfwprintf`,
+`vfwscanf`, `vprintf`, `vscanf`, `vsnprintf`, `vsprintf`, `vsscanf`, `vswprintf`,
+`vswscanf`, `vwprintf`, `vwscanf`, `wcrtomb`, `wcscat`, `wcscpy`, `wcsncat`, `wcsncpy`,
+`wcsrtombs`, `wcstok`, `wcstombs`, `wctomb`, `wmemcpy`, `wmemmove`, `wprintf`, `wscanf`.
+If annex K is not available, the checker ignores these functions.
+
+The availability of annex K is checked based on the following macros.
+ - `__STDC_LIB_EXT1__`: feature macro, which indicates the presence of
+ annex K (Bounds-checking interfaces) in the library implementation
+ - `__STDC_WANT_LIB_EXT1__`: user defined macro, which indicates if the user wants the functions from
+ annex K to be defined.
+
+Both macros have to be defined to suggest replacement functions from annex K. `__STDC_LIB_EXT1__` is
+defined by the library implementation, and `__STDC_WANT_LIB_EXT1__` must be define to "1" by the user
+before including any system headers.
+
+Deprecated function `gets` is checked, and a warning is issued if used.
+
+The following functions are also checked, and an alternative replacement function is suggested:
+ - `rewind`, suggested replacement: `fseek`
+ - `setbuf`, suggested replacement: `setvbuf`
+
+The following functions are covered in the check `cert-err34-c <cert-err34-c.html>`_,
+so this checker **ignores** them: `atof`, `atoi`, `atol`, `atoll`.
+
+Examples:
+
+.. code-block:: c++
+
+ //__STDC_LIB_EXT1__ is defined by the library implementation
+ #define __STDC_WANT_LIB_EXT1__ 1
+
+ #include <string.h> // defines the functions from annex K
+ #include <stdio.h>
+
+ enum { BUFSIZE = 32 };
+
+ void fWarning(const char *msg) {
+ static const char prefix[] = "Error: ";
+ static const char suffix[] = "\n";
+ char buf[BUFSIZE] = {0};
+
+ strcpy(buf, prefix); // warning: function 'strcpy' is obsolescent; 'strcpy_s' should be used instead.
+ strcat(buf, msg); // warning: function 'strcat' is obsolescent; 'strcat_s' should be used instead.
+ strcat(buf, suffix); // warning: function 'strcat' is obsolescent; 'strcat_s' should be used instead.
+ if (fputs(buf, stderr) < 0) {
+ // error handling
+ return;
+ }
+ }
+
+ void fUsingSafeFunctions(const char *msg) {
+ static const char prefix[] = "Error: ";
+ static const char suffix[] = "\n";
+ char buf[BUFSIZE] = {0};
+
+ if (strcpy_s(buf, prefix) != 0) {
+ // error handling
+ return;
+ }
+
+ if (strcat_s(buf, msg) != 0) {
+ // error handling
+ return;
+ }
+
+ if (strcat_s(buf, suffix) != 0) {
+ // error handling
+ return;
+ }
+
+ if (fputs(buf, stderr) < 0) {
+ // error handling
+ return;
+ }
+ }
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -89,6 +89,14 @@
Finds potentially incorrect calls to ``memcmp()`` based on properties of the
arguments.
+- New :doc:`cert-msc24-c
+ <clang-tidy/checks/cert-msc24-c>` check.
+
+ Checks for deprecated and obsolescent functions listed in
+ CERT C Coding Standard Recommendation MSC24-C. For the listed functions,
+ an alternative, more secure replacement is suggested, if available. The checker heavily
+ relies on the functions from annex K (Bounds-checking interfaces) of C11.
+
- New :doc:`cppcoreguidelines-virtual-class-destructor
<clang-tidy/checks/cppcoreguidelines-virtual-class-destructor>` check.
Index: clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.h
@@ -0,0 +1,50 @@
+//===--- ObsolescentFunctionsCheck.h - clang-tidy ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_OBSOLESCENTFUNCTIONSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_OBSOLESCENTFUNCTIONSCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+/// Checks for deprecated and obsolescent function listed in
+/// CERT C Coding Standard Recommendation MSC24 - C. For the listed functions,
+/// an alternative, safe replacement is suggested if available.
+/// The checker heavily relies on the availability of annexK(Bounds - checking
+/// interfaces) from C11. For the user-facing documentation see:
+///
+/// http://clang.llvm.org/extra/clang-tidy/checks/cert-msc24-c.html
+class ObsolescentFunctionsCheck : public ClangTidyCheck {
+public:
+ ObsolescentFunctionsCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
+
+private:
+ bool useSafeFunctionsFromAnnexK() const;
+ Optional<std::string>
+ getReplacementFunctionNameFor(StringRef FunctionName,
+ bool FunctionHasAnnexKReplacement) const;
+
+ Preprocessor *PP = nullptr;
+
+ // Used for caching the result of useSafeFunctionsFromAnnexK.
+ mutable llvm::Optional<bool> IsAnnexKAvailable;
+};
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_OBSOLESCENTFUNCTIONSCHECK_H
Index: clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/cert/ObsolescentFunctionsCheck.cpp
@@ -0,0 +1,156 @@
+//===--- ObsolescentFunctionsCheck.cpp - clang-tidy -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "ObsolescentFunctionsCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include <cassert>
+
+using namespace clang::ast_matchers;
+using namespace llvm;
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+static constexpr llvm::StringLiteral DeprecatedFunctionNamesId =
+ "DeprecatedFunctionNamesId";
+static constexpr llvm::StringLiteral FunctionNamesId = "FunctionNamesId";
+static constexpr llvm::StringLiteral FunctionNamesWithAnnexKReplacementId =
+ "FunctionNamesWithAnnexKReplacementExpr";
+
+static constexpr llvm::StringLiteral DeclRefId = "DeclRefId";
+
+static StringRef getRationale(StringRef FunctionName) {
+ return StringSwitch<StringRef>(FunctionName)
+ .Cases("asctime", "ctime", "is non-reentrant")
+ .Cases("fopen", "freopen", "has no exclusive access to file")
+ .Cases("rewind", "setbuf", "has no error detection")
+ .Default("is obsolescent");
+}
+
+void ObsolescentFunctionsCheck::registerMatchers(MatchFinder *Finder) {
+
+ // Matching the `gets` deprecated function without replacement.
+ auto DeprecatedFunctionNamesMatcher = hasAnyName("::gets");
+
+ // Matching functions with replacements without annex K.
+ auto FunctionNamesMatcher = hasAnyName("::rewind", "::setbuf");
+
+ // Matching functions with safe replacements in annex K.
+ auto FunctionNamesWithAnnexKReplacementMatcher = hasAnyName(
+ "::asctime", "::ctime", "::fopen", "::freopen", "::bsearch", "::fprintf",
+ "::fscanf", "::fwprintf", "::fwscanf", "::getenv", "::gmtime",
+ "::localtime", "::mbsrtowcs", "::mbstowcs", "::memcpy", "::memmove",
+ "::printf", "::qsort", "::snprintf", "::sprintf", "::sscanf", "::strcat",
+ "::strcpy", "::strerror", "::strncat", "::strncpy", "::strtok",
+ "::swprintf", "::swscanf", "::vfprintf", "::vfscanf", "::vfwprintf",
+ "::vfwscanf", "::vprintf", "::vscanf", "::vsnprintf", "::vsprintf",
+ "::vsscanf", "::vswprintf", "::vswscanf", "::vwprintf", "::vwscanf",
+ "::wcrtomb", "::wcscat", "::wcscpy", "::wcsncat", "::wcsncpy",
+ "::wcsrtombs", "::wcstok", "::wcstombs", "::wctomb", "::wmemcpy",
+ "::wmemmove", "::wprintf", "::wscanf");
+
+ Finder->addMatcher(
+ declRefExpr(
+ to(anyOf(functionDecl(DeprecatedFunctionNamesMatcher)
+ .bind(DeprecatedFunctionNamesId),
+ functionDecl(FunctionNamesMatcher).bind(FunctionNamesId),
+ functionDecl(FunctionNamesWithAnnexKReplacementMatcher)
+ .bind(FunctionNamesWithAnnexKReplacementId))))
+ .bind(DeclRefId),
+ this);
+}
+
+void ObsolescentFunctionsCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *DeclRef = Result.Nodes.getNodeAs<DeclRefExpr>(DeclRefId);
+ assert(DeclRef && "No matching declaration reference found.");
+ SourceRange Range = SourceRange(DeclRef->getBeginLoc(), DeclRef->getEndLoc());
+
+ // FIXME: I'm not sure if this can ever happen, but to be on the safe side,
+ // validity is checked.
+ if (Range.isInvalid())
+ return;
+
+ if (const auto *Deprecated =
+ Result.Nodes.getNodeAs<FunctionDecl>(DeprecatedFunctionNamesId)) {
+ diag(Range.getBegin(),
+ "function '%0' is deprecated as of C99, removed from C11.")
+ << Deprecated->getName() << Range;
+ return;
+ }
+
+ const auto *Normal = Result.Nodes.getNodeAs<FunctionDecl>(FunctionNamesId);
+ const auto *AnnexK = Normal ? nullptr
+ : Result.Nodes.getNodeAs<FunctionDecl>(
+ FunctionNamesWithAnnexKReplacementId);
+ assert((Normal && !AnnexK) || (!Normal && AnnexK));
+
+ StringRef FunctionName = (Normal ? Normal : AnnexK)->getName();
+ Optional<std::string> ReplacementFunctionName =
+ getReplacementFunctionNameFor(FunctionName, AnnexK);
+
+ if (!ReplacementFunctionName.hasValue())
+ return;
+
+ diag(Range.getBegin(), "function '%0' %1; '%2' should be used instead.")
+ << FunctionName << getRationale(FunctionName)
+ << ReplacementFunctionName.getValue() << Range;
+}
+
+void ObsolescentFunctionsCheck::registerPPCallbacks(
+ const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
+ ObsolescentFunctionsCheck::PP = PP;
+}
+
+bool ObsolescentFunctionsCheck::useSafeFunctionsFromAnnexK() const {
+ if (IsAnnexKAvailable.hasValue())
+ return IsAnnexKAvailable.getValue();
+
+ assert(PP && "No Preprocessor registered.");
+
+ if (!PP->isMacroDefined("__STDC_LIB_EXT1__") ||
+ !PP->isMacroDefined("__STDC_WANT_LIB_EXT1__")) {
+ // Caching the result.
+ return (IsAnnexKAvailable = false).getValue();
+ }
+
+ const auto *MI =
+ PP->getMacroInfo(PP->getIdentifierInfo("__STDC_WANT_LIB_EXT1__"));
+ if (!MI || MI->tokens_empty()) {
+ // Caching the result.
+ return (IsAnnexKAvailable = false).getValue();
+ }
+
+ const Token &T = MI->tokens().back();
+ if (!T.isLiteral() || !T.getLiteralData()) {
+ // Caching the result.
+ return (IsAnnexKAvailable = false).getValue();
+ }
+
+ // Caching the result.
+ IsAnnexKAvailable = StringRef(T.getLiteralData(), T.getLength()) == "1";
+ return IsAnnexKAvailable.getValue();
+}
+
+Optional<std::string> ObsolescentFunctionsCheck::getReplacementFunctionNameFor(
+ StringRef FunctionName, bool FunctionHasAnnexKReplacement) const {
+ if (FunctionHasAnnexKReplacement && useSafeFunctionsFromAnnexK())
+ return (Twine{FunctionName} + "_s").str();
+
+ return StringSwitch<Optional<std::string>>(FunctionName)
+ .Case("rewind", Optional<std::string>{"fseek"})
+ .Case("setbuf", Optional<std::string>{"setvbuf"})
+ .Default(None);
+}
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/cert/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/cert/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/cert/CMakeLists.txt
@@ -12,6 +12,7 @@
LimitedRandomnessCheck.cpp
MutatingCopyCheck.cpp
NonTrivialTypesLibcMemoryCallsCheck.cpp
+ ObsolescentFunctionsCheck.cpp
PostfixOperatorCheck.cpp
ProperlySeededRandomGeneratorCheck.cpp
SetLongJmpCheck.cpp
Index: clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
+++ clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
@@ -32,6 +32,7 @@
#include "LimitedRandomnessCheck.h"
#include "MutatingCopyCheck.h"
#include "NonTrivialTypesLibcMemoryCallsCheck.h"
+#include "ObsolescentFunctionsCheck.h"
#include "PostfixOperatorCheck.h"
#include "ProperlySeededRandomGeneratorCheck.h"
#include "SetLongJmpCheck.h"
@@ -301,6 +302,7 @@
// FIO
CheckFactories.registerCheck<misc::NonCopyableObjectsCheck>("cert-fio38-c");
// MSC
+ CheckFactories.registerCheck<ObsolescentFunctionsCheck>("cert-msc24-c");
CheckFactories.registerCheck<LimitedRandomnessCheck>("cert-msc30-c");
CheckFactories.registerCheck<ProperlySeededRandomGeneratorCheck>(
"cert-msc32-c");
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits