[clang-tidy] Add new checker for comparison with runtime string functions.

Summary:
This checker is validating suspicious usage of string compare functions.

Example:
```
  if (strcmp(...))       // Implicitly compare to zero
  if (!strcmp(...))      // Won't warn
  if (strcmp(...) != 0)  // Won't warn
```

This patch was checked over large amount of code.
There is three checks:
  [*] Implicit comparator to zero (coding-style, many warnings found),
  [*] Suspicious implicit cast to non-integral (bugs!?, almost none found),
  [*] Comparison to suspicious constant (bugs!?, found two cases),

Example:
[[https://github.com/kylepjohnson/sigma/blob/master/sigma/native-installers/debian/dependencies/files/opt/sigma/E/HEURISTICS/che_to_precgen.c |
https://github.com/kylepjohnson/sigma/blob/master/sigma/native-installers/debian/dependencies/files/opt/sigma/E/HEURISTICS/che_to_precgen.c]]

```
      else if(strcmp(id, "select") == 0)
      {
         array->array[i].key1 = 25;
      }
      else if(strcmp(id, "sk") == 28)      // BUG!?
      {
         array->array[i].key1 = 20;
      }
```

Reviewers: alexfh

Subscribers: Eugene.Zelenko, cfe-commits

Differential Revision: http://reviews.llvm.org/D18703

llvm-svn: 267009
This commit is contained in:
Etienne Bergeron 2016-04-21 17:19:36 +00:00
parent 1a299eab32
commit bae829ede5
8 changed files with 671 additions and 0 deletions

View File

@ -29,6 +29,7 @@ add_clang_library(clangTidyMiscModule
StringLiteralWithEmbeddedNulCheck.cpp
SuspiciousMissingCommaCheck.cpp
SuspiciousSemicolonCheck.cpp
SuspiciousStringCompareCheck.cpp
SwappedArgumentsCheck.cpp
ThrowByValueCatchByReferenceCheck.cpp
UndelegatedConstructor.cpp

View File

@ -37,6 +37,7 @@
#include "StringLiteralWithEmbeddedNulCheck.h"
#include "SuspiciousMissingCommaCheck.h"
#include "SuspiciousSemicolonCheck.h"
#include "SuspiciousStringCompareCheck.h"
#include "SwappedArgumentsCheck.h"
#include "ThrowByValueCatchByReferenceCheck.h"
#include "UndelegatedConstructor.h"
@ -106,6 +107,8 @@ public:
"misc-suspicious-missing-comma");
CheckFactories.registerCheck<SuspiciousSemicolonCheck>(
"misc-suspicious-semicolon");
CheckFactories.registerCheck<SuspiciousStringCompareCheck>(
"misc-suspicious-string-compare");
CheckFactories.registerCheck<SwappedArgumentsCheck>(
"misc-swapped-arguments");
CheckFactories.registerCheck<ThrowByValueCatchByReferenceCheck>(

View File

@ -0,0 +1,221 @@
//===--- SuspiciousStringCompareCheck.cpp - clang-tidy---------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "SuspiciousStringCompareCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
namespace misc {
AST_MATCHER(BinaryOperator, isComparisonOperator) {
return Node.isComparisonOp();
}
constexpr char KnownStringCompareFunctions[] = "__builtin_memcmp;"
"__builtin_strcasecmp;"
"__builtin_strcmp;"
"__builtin_strncasecmp;"
"__builtin_strncmp;"
"_mbscmp;"
"_mbscmp_l;"
"_mbsicmp;"
"_mbsicmp_l;"
"_mbsnbcmp;"
"_mbsnbcmp_l;"
"_mbsnbicmp;"
"_mbsnbicmp_l;"
"_mbsncmp;"
"_mbsncmp_l;"
"_mbsnicmp;"
"_mbsnicmp_l;"
"_memicmp;"
"_memicmp_l;"
"_stricmp;"
"_stricmp_l;"
"_strnicmp;"
"_strnicmp_l;"
"_wcsicmp;"
"_wcsicmp_l;"
"_wcsnicmp;"
"_wcsnicmp_l;"
"lstrcmp;"
"lstrcmpi;"
"memcmp;"
"memicmp;"
"strcasecmp;"
"strcmp;"
"strcmpi;"
"stricmp;"
"strncasecmp;"
"strncmp;"
"strnicmp;"
"wcscasecmp;"
"wcscmp;"
"wcsicmp;"
"wcsncmp;"
"wcsnicmp;"
"wmemcmp;";
static const char StringCompareLikeFunctionsDelimiter[] = ";";
static void ParseFunctionNames(StringRef Option,
std::vector<std::string> *Result) {
SmallVector<StringRef, 4> Functions;
Option.split(Functions, StringCompareLikeFunctionsDelimiter);
for (StringRef &Function : Functions) {
Function = Function.trim();
if (!Function.empty())
Result->push_back(Function);
}
}
SuspiciousStringCompareCheck::SuspiciousStringCompareCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
WarnOnImplicitComparison(Options.get("WarnOnImplicitComparison", 1)),
WarnOnLogicalNotComparison(Options.get("WarnOnLogicalNotComparison", 1)),
StringCompareLikeFunctions(
Options.get("StringCompareLikeFunctions", "")) {}
void SuspiciousStringCompareCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "WarnOnImplicitComparison", WarnOnImplicitComparison);
Options.store(Opts, "WarnOnLogicalNotComparison", WarnOnLogicalNotComparison);
Options.store(Opts, "StringCompareLikeFunctions", StringCompareLikeFunctions);
}
void SuspiciousStringCompareCheck::registerMatchers(MatchFinder *Finder) {
// Match relational operators.
const auto ComparisonUnaryOperator = unaryOperator(hasOperatorName("!"));
const auto ComparisonBinaryOperator = binaryOperator(isComparisonOperator());
const auto ComparisonOperator =
expr(anyOf(ComparisonUnaryOperator, ComparisonBinaryOperator));
// Add the list of known string compare-like functions and add user-defined
// functions.
std::vector<std::string> FunctionNames;
ParseFunctionNames(KnownStringCompareFunctions, &FunctionNames);
ParseFunctionNames(StringCompareLikeFunctions, &FunctionNames);
const auto FunctionCompareDecl =
functionDecl(hasAnyName(std::vector<StringRef>(FunctionNames.begin(),
FunctionNames.end())))
.bind("decl");
// Match a call to a string compare functions.
const auto StringCompareCallExpr =
callExpr(hasDeclaration(FunctionCompareDecl)).bind("call");
if (WarnOnImplicitComparison) {
// Detect suspicious calls to string compare (missing comparator) [only C]:
// 'if (strcmp())' -> 'if (strcmp() != 0)'
Finder->addMatcher(
stmt(anyOf(ifStmt(hasCondition(StringCompareCallExpr)),
whileStmt(hasCondition(StringCompareCallExpr)),
doStmt(hasCondition(StringCompareCallExpr)),
forStmt(hasCondition(StringCompareCallExpr))))
.bind("missing-comparison"),
this);
Finder->addMatcher(expr(StringCompareCallExpr,
unless(hasParent(ComparisonOperator)),
unless(hasParent(implicitCastExpr())))
.bind("missing-comparison"),
this);
// Detect suspicious calls to string compare with implicit comparison:
// 'if (strcmp())' -> 'if (strcmp() != 0)'
// 'if (!strcmp())' is considered valid (see WarnOnLogicalNotComparison)
Finder->addMatcher(
implicitCastExpr(hasType(isInteger()),
hasSourceExpression(StringCompareCallExpr),
unless(hasParent(ComparisonOperator)))
.bind("missing-comparison"),
this);
// Detect suspicious cast to an inconsistant type.
Finder->addMatcher(
implicitCastExpr(unless(hasType(isInteger())),
hasSourceExpression(StringCompareCallExpr))
.bind("invalid-conversion"),
this);
}
if (WarnOnLogicalNotComparison) {
// Detect suspicious calls to string compared with '!' operator:
// 'if (!strcmp())' -> 'if (strcmp() == 0)'
Finder->addMatcher(unaryOperator(hasOperatorName("!"),
hasUnaryOperand(ignoringParenImpCasts(
StringCompareCallExpr)))
.bind("logical-not-comparison"),
this);
}
// Detect suspicious calls to string compare functions: 'strcmp() == -1'.
const auto InvalidLiteral = ignoringParenImpCasts(
anyOf(integerLiteral(unless(equals(0))),
unaryOperator(hasOperatorName("-"),
has(integerLiteral(unless(equals(0))))),
characterLiteral(), cxxBoolLiteral()));
Finder->addMatcher(binaryOperator(isComparisonOperator(),
hasEitherOperand(StringCompareCallExpr),
hasEitherOperand(InvalidLiteral))
.bind("invalid-comparison"),
this);
}
void SuspiciousStringCompareCheck::check(
const MatchFinder::MatchResult &Result) {
const auto *Decl = Result.Nodes.getNodeAs<FunctionDecl>("decl");
const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call");
assert(Decl != nullptr && Call != nullptr);
if (Result.Nodes.getNodeAs<Stmt>("missing-comparison")) {
SourceLocation EndLoc = Lexer::getLocForEndOfToken(
Call->getRParenLoc(), 0, Result.Context->getSourceManager(),
Result.Context->getLangOpts());
diag(Call->getLocStart(),
"function %0 is called without explicitly comparing result")
<< Decl << FixItHint::CreateInsertion(EndLoc, " != 0");
}
if (const auto *E = Result.Nodes.getNodeAs<Expr>("logical-not-comparison")) {
SourceLocation EndLoc = Lexer::getLocForEndOfToken(
Call->getRParenLoc(), 0, Result.Context->getSourceManager(),
Result.Context->getLangOpts());
SourceLocation NotLoc = E->getLocStart();
diag(Call->getLocStart(),
"function %0 is compared using logical not operator")
<< Decl << FixItHint::CreateRemoval(
CharSourceRange::getTokenRange(NotLoc, NotLoc))
<< FixItHint::CreateInsertion(EndLoc, " == 0");
}
if (Result.Nodes.getNodeAs<Stmt>("invalid-comparison")) {
diag(Call->getLocStart(),
"function %0 is compared to a suspicious constant")
<< Decl;
}
if (Result.Nodes.getNodeAs<Stmt>("invalid-conversion")) {
diag(Call->getLocStart(), "function %0 has suspicious implicit cast")
<< Decl;
}
}
} // namespace misc
} // namespace tidy
} // namespace clang

View File

@ -0,0 +1,40 @@
//===--- SuspiciousStringCompareCheck.h - clang-tidy-------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_SUSPICIOUS_STRING_COMPARE_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_SUSPICIOUS_STRING_COMPARE_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace misc {
/// Find suspicious calls to string compare functions.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/misc-suspicious-string-compare.html
class SuspiciousStringCompareCheck : public ClangTidyCheck {
public:
SuspiciousStringCompareCheck(StringRef Name, ClangTidyContext *Context);
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
private:
const bool WarnOnImplicitComparison;
const bool WarnOnLogicalNotComparison;
const std::string StringCompareLikeFunctions;
};
} // namespace misc
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_SUSPICIOUS_STRING_COMPARE_H

View File

@ -73,6 +73,7 @@ Clang-Tidy Checks
misc-string-literal-with-embedded-nul
misc-suspicious-missing-comma
misc-suspicious-semicolon
misc-suspicious-string-compare
misc-swapped-arguments
misc-throw-by-value-catch-by-reference
misc-undelegated-constructor

View File

@ -0,0 +1,40 @@
.. title:: clang-tidy - misc-suspicious-string-compare
misc-suspicious-string-compare
==============================
Find suspicious usage of runtime string comparison functions.
This check is valid in C and C++.
Checks for calls with implicit comparator and proposed to explicitly add it.
.. code:: c++
if (strcmp(...)) // Implicitly compare to zero
if (!strcmp(...)) // Won't warn
if (strcmp(...) != 0) // Won't warn
Checks that compare function results (i,e, ``strcmp``) are compared to valid
constant. The resulting value is
.. code::
< 0 when lower than,
> 0 when greater than,
== 0 when equals.
A common mistake is to compare the result to '1' or '-1'.
.. code:: c++
if (strcmp(...) == -1) // Incorrect usage of the returned value.
Additionally, the check warns if the results value is implicitly cast to a
*suspicious* non-integer type. It's happening when the returned value is used in
a wrong context.
.. code:: c++
if (strcmp(...) < 0.) // Incorrect usage of the returned value.

View File

@ -0,0 +1,66 @@
// RUN: %check_clang_tidy %s misc-suspicious-string-compare %t -- \
// RUN: -config='{CheckOptions: \
// RUN: [{key: misc-suspicious-string-compare.WarnOnImplicitComparison, value: 1}, \
// RUN: {key: misc-suspicious-string-compare.WarnOnLogicalNotComparison, value: 1}]}' \
// RUN: -- -std=c99
static const char A[] = "abc";
int strcmp(const char *, const char *);
int test_warning_patterns() {
if (strcmp(A, "a"))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result [misc-suspicious-string-compare]
// CHECK-FIXES: if (strcmp(A, "a") != 0)
if (strcmp(A, "a") != 0 ||
strcmp(A, "b"))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result
// CHECK-FIXES: strcmp(A, "b") != 0)
if (strcmp(A, "a") == 1)
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
if (strcmp(A, "a") == -1)
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
if (strcmp(A, "a") < '0')
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
if (strcmp(A, "a") < 0.)
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' has suspicious implicit cast
if (!strcmp(A, "a"))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:8: warning: function 'strcmp' is compared using logical not operator
// CHECK-FIXES: if (strcmp(A, "a") == 0)
}
void test_structure_patterns() {
if (strcmp(A, "a")) {}
// CHECK-MESSAGES: [[@LINE-1]]:7: warning: function 'strcmp' is called without explicitly comparing result
// CHECK-FIXES: if (strcmp(A, "a") != 0) {}
while (strcmp(A, "a")) {}
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: function 'strcmp' is called without explicitly comparing result
// CHECK-FIXES: while (strcmp(A, "a") != 0) {}
for (;strcmp(A, "a");) {}
// CHECK-MESSAGES: [[@LINE-1]]:9: warning: function 'strcmp' is called without explicitly comparing result
// CHECK-FIXES: for (;strcmp(A, "a") != 0;) {}
}
int test_valid_patterns() {
// The following cases are valid.
if (strcmp(A, "a") < 0) return 0;
if (strcmp(A, "a") == 0) return 0;
if (strcmp(A, "a") <= 0) return 0;
if (strcmp(A, "a") == strcmp(A, "b")) return 0;
return 1;
}

View File

@ -0,0 +1,299 @@
// RUN: %check_clang_tidy %s misc-suspicious-string-compare %t -- \
// RUN: -config='{CheckOptions: \
// RUN: [{key: misc-suspicious-string-compare.WarnOnImplicitComparison, value: 1}, \
// RUN: {key: misc-suspicious-string-compare.WarnOnLogicalNotComparison, value: 1}]}' \
// RUN: --
typedef __SIZE_TYPE__ size;
struct locale_t {
void* dummy;
} locale;
static const char A[] = "abc";
static const unsigned char U[] = "abc";
static const unsigned char V[] = "xyz";
static const wchar_t W[] = L"abc";
int memcmp(const void *, const void *, size);
int wmemcmp(const wchar_t *, const wchar_t *, size);
int memicmp(const void *, const void *, size);
int _memicmp(const void *, const void *, size);
int _memicmp_l(const void *, const void *, size, locale_t);
int strcmp(const char *, const char *);
int strncmp(const char *, const char *, size);
int strcasecmp(const char *, const char *);
int strncasecmp(const char *, const char *, size);
int stricmp(const char *, const char *);
int strcmpi(const char *, const char *);
int strnicmp(const char *, const char *, size);
int _stricmp(const char *, const char * );
int _strnicmp(const char *, const char *, size);
int _stricmp_l(const char *, const char *, locale_t);
int _strnicmp_l(const char *, const char *, size, locale_t);
int wcscmp(const wchar_t *, const wchar_t *);
int wcsncmp(const wchar_t *, const wchar_t *, size);
int wcscasecmp(const wchar_t *, const wchar_t *);
int wcsicmp(const wchar_t *, const wchar_t *);
int wcsnicmp(const wchar_t *, const wchar_t *, size);
int _wcsicmp(const wchar_t *, const wchar_t *);
int _wcsnicmp(const wchar_t *, const wchar_t *, size);
int _wcsicmp_l(const wchar_t *, const wchar_t *, locale_t);
int _wcsnicmp_l(const wchar_t *, const wchar_t *, size, locale_t);
int _mbscmp(const unsigned char *, const unsigned char *);
int _mbsncmp(const unsigned char *, const unsigned char *, size);
int _mbsnbcmp(const unsigned char *, const unsigned char *, size);
int _mbsnbicmp(const unsigned char *, const unsigned char *, size);
int _mbsicmp(const unsigned char *, const unsigned char *);
int _mbsnicmp(const unsigned char *, const unsigned char *, size);
int _mbscmp_l(const unsigned char *, const unsigned char *, locale_t);
int _mbsncmp_l(const unsigned char *, const unsigned char *, size, locale_t);
int _mbsicmp_l(const unsigned char *, const unsigned char *, locale_t);
int _mbsnicmp_l(const unsigned char *, const unsigned char *, size, locale_t);
int _mbsnbcmp_l(const unsigned char *, const unsigned char *, size, locale_t);
int _mbsnbicmp_l(const unsigned char *, const unsigned char *, size, locale_t);
int test_warning_patterns() {
if (strcmp(A, "a"))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result [misc-suspicious-string-compare]
// CHECK-FIXES: if (strcmp(A, "a") != 0)
if (strcmp(A, "a") == 0 ||
strcmp(A, "b"))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result
// CHECK-FIXES: strcmp(A, "b") != 0)
if (strcmp(A, "a") == 1)
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
if (strcmp(A, "a") == -1)
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
if (strcmp(A, "a") == true)
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
if (strcmp(A, "a") < '0')
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant
if (strcmp(A, "a") < 0.)
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' has suspicious implicit cast
}
int test_valid_patterns() {
// The following cases are valid.
if (strcmp(A, "a") < 0)
return 0;
if (strcmp(A, "a") == 0)
return 0;
if (strcmp(A, "a") <= 0)
return 0;
if (wcscmp(W, L"a") < 0)
return 0;
if (wcscmp(W, L"a") == 0)
return 0;
if (wcscmp(W, L"a") <= 0)
return 0;
return 1;
}
int test_implicit_compare_with_functions() {
if (memcmp(A, "a", 1))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'memcmp' is called without explicitly comparing result
// CHECK-FIXES: memcmp(A, "a", 1) != 0)
if (wmemcmp(W, L"a", 1))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wmemcmp' is called without explicitly comparing result
// CHECK-FIXES: wmemcmp(W, L"a", 1) != 0)
if (memicmp(A, "a", 1))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'memicmp' is called without explicitly comparing result
// CHECK-FIXES: memicmp(A, "a", 1) != 0)
if (_memicmp(A, "a", 1))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_memicmp' is called without explicitly comparing result
// CHECK-FIXES: _memicmp(A, "a", 1) != 0)
if (_memicmp_l(A, "a", 1, locale))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_memicmp_l' is called without explicitly comparing result
// CHECK-FIXES: _memicmp_l(A, "a", 1, locale) != 0)
if (strcmp(A, "a"))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result
// CHECK-FIXES: strcmp(A, "a") != 0)
if (strncmp(A, "a", 1))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strncmp' is called without explicitly comparing result
// CHECK-FIXES: strncmp(A, "a", 1) != 0)
if (strcasecmp(A, "a"))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcasecmp' is called without explicitly comparing result
// CHECK-FIXES: strcasecmp(A, "a") != 0)
if (strncasecmp(A, "a", 1))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strncasecmp' is called without explicitly comparing result
// CHECK-FIXES: strncasecmp(A, "a", 1) != 0)
if (stricmp(A, "a"))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'stricmp' is called without explicitly comparing result
// CHECK-FIXES: stricmp(A, "a") != 0)
if (strcmpi(A, "a"))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmpi' is called without explicitly comparing result
// CHECK-FIXES: strcmpi(A, "a") != 0)
if (_stricmp(A, "a"))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_stricmp' is called without explicitly comparing result
// CHECK-FIXES: _stricmp(A, "a") != 0)
if (strnicmp(A, "a", 1))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strnicmp' is called without explicitly comparing result
// CHECK-FIXES: strnicmp(A, "a", 1) != 0)
if (_strnicmp(A, "a", 1))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_strnicmp' is called without explicitly comparing result
// CHECK-FIXES: _strnicmp(A, "a", 1) != 0)
if (_stricmp_l(A, "a", locale))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_stricmp_l' is called without explicitly comparing result
// CHECK-FIXES: _stricmp_l(A, "a", locale) != 0)
if (_strnicmp_l(A, "a", 1, locale))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_strnicmp_l' is called without explicitly comparing result
// CHECK-FIXES: _strnicmp_l(A, "a", 1, locale) != 0)
if (wcscmp(W, L"a"))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcscmp' is called without explicitly comparing result
// CHECK-FIXES: wcscmp(W, L"a") != 0)
if (wcsncmp(W, L"a", 1))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsncmp' is called without explicitly comparing result
// CHECK-FIXES: wcsncmp(W, L"a", 1) != 0)
if (wcscasecmp(W, L"a"))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcscasecmp' is called without explicitly comparing result
// CHECK-FIXES: wcscasecmp(W, L"a") != 0)
if (wcsicmp(W, L"a"))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsicmp' is called without explicitly comparing result
// CHECK-FIXES: wcsicmp(W, L"a") != 0)
if (_wcsicmp(W, L"a"))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsicmp' is called without explicitly comparing result
// CHECK-FIXES: _wcsicmp(W, L"a") != 0)
if (_wcsicmp_l(W, L"a", locale))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsicmp_l' is called without explicitly comparing result
// CHECK-FIXES: _wcsicmp_l(W, L"a", locale) != 0)
if (wcsnicmp(W, L"a", 1))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsnicmp' is called without explicitly comparing result
// CHECK-FIXES: wcsnicmp(W, L"a", 1) != 0)
if (_wcsnicmp(W, L"a", 1))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsnicmp' is called without explicitly comparing result
// CHECK-FIXES: _wcsnicmp(W, L"a", 1) != 0)
if (_wcsnicmp_l(W, L"a", 1, locale))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsnicmp_l' is called without explicitly comparing result
// CHECK-FIXES: _wcsnicmp_l(W, L"a", 1, locale) != 0)
if (_mbscmp(U, V))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbscmp' is called without explicitly comparing result
// CHECK-FIXES: _mbscmp(U, V) != 0)
if (_mbsncmp(U, V, 1))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsncmp' is called without explicitly comparing result
// CHECK-FIXES: _mbsncmp(U, V, 1) != 0)
if (_mbsnbcmp(U, V, 1))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbcmp' is called without explicitly comparing result
// CHECK-FIXES: _mbsnbcmp(U, V, 1) != 0)
if (_mbsnbicmp(U, V, 1))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbicmp' is called without explicitly comparing result
// CHECK-FIXES: _mbsnbicmp(U, V, 1) != 0)
if (_mbsicmp(U, V))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsicmp' is called without explicitly comparing result
// CHECK-FIXES: _mbsicmp(U, V) != 0)
if (_mbsnicmp(U, V, 1))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnicmp' is called without explicitly comparing result
// CHECK-FIXES: _mbsnicmp(U, V, 1) != 0)
if (_mbscmp_l(U, V, locale))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbscmp_l' is called without explicitly comparing result
// CHECK-FIXES: _mbscmp_l(U, V, locale) != 0)
if (_mbsncmp_l(U, V, 1, locale))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsncmp_l' is called without explicitly comparing result
// CHECK-FIXES: _mbsncmp_l(U, V, 1, locale) != 0)
if (_mbsicmp_l(U, V, locale))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsicmp_l' is called without explicitly comparing result
// CHECK-FIXES: _mbsicmp_l(U, V, locale) != 0)
if (_mbsnicmp_l(U, V, 1, locale))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnicmp_l' is called without explicitly comparing result
// CHECK-FIXES: _mbsnicmp_l(U, V, 1, locale) != 0)
if (_mbsnbcmp_l(U, V, 1, locale))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbcmp_l' is called without explicitly comparing result
// CHECK-FIXES: _mbsnbcmp_l(U, V, 1, locale) != 0)
if (_mbsnbicmp_l(U, V, 1, locale))
return 0;
// CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbicmp_l' is called without explicitly comparing result
// CHECK-FIXES: _mbsnbicmp_l(U, V, 1, locale) != 0)
return 1;
}