void UseNodiscardCheck::registerMatchers(MatchFinder *Finder) { // If we use ``[[nodiscard]]`` attribute, we require at least C++17. Use a // macro or ``__attribute__`` with pre c++17 compilers by using // ReplacementString option. if ((NoDiscardMacro == "[[nodiscard]]" && !getLangOpts().CPlusPlus17) || !getLangOpts().CPlusPlus) return; auto FunctionObj = cxxRecordDecl(hasAnyName("::std::function", "::boost::function")); // Find all non-void const methods which have not already been marked to // warn on unused result. Finder->addMatcher( cxxMethodDecl( allOf(isConst(), isDefinitionOrInline(), unless(anyOf( returns(voidType()), isNoReturn(), isOverloadedOperator(), isVariadic(), hasTemplateReturnType(), hasClassMutableFields(), isConversionOperator(), hasAttr(clang::attr::WarnUnusedResult), hasType(isInstantiationDependentType()), hasAnyParameter(anyOf( parmVarDecl(anyOf(hasType(FunctionObj), hasType(references(FunctionObj)))), hasType(isNonConstReferenceOrPointer()), hasParameterPack())))))) .bind("no_discard"), this); }
void ConstReturnTypeCheck::registerMatchers(MatchFinder *Finder) { // Find all function definitions for which the return types are `const` // qualified. Finder->addMatcher( functionDecl(returns(isConstQualified()), isDefinition()).bind("func"), this); }
void AssignOperatorSignatureCheck::registerMatchers( ast_matchers::MatchFinder *Finder) { // Only register the matchers for C++; the functionality currently does not // provide any benefit to other languages, despite being benign. if (getLangOpts().CPlusPlus) { const auto HasGoodReturnType = methodDecl(returns(lValueReferenceType( pointee(unless(isConstQualified()), hasDeclaration(equalsBoundNode("class")))))); const auto IsSelf = qualType(anyOf( hasDeclaration(equalsBoundNode("class")), referenceType(pointee(hasDeclaration(equalsBoundNode("class")))))); const auto IsSelfAssign = methodDecl(unless(anyOf(isDeleted(), isPrivate(), isImplicit())), hasName("operator="), ofClass(recordDecl().bind("class")), hasParameter(0, parmVarDecl(hasType(IsSelf)))) .bind("method"); Finder->addMatcher( methodDecl(IsSelfAssign, unless(HasGoodReturnType)).bind("ReturnType"), this); const auto BadSelf = referenceType( anyOf(lValueReferenceType(pointee(unless(isConstQualified()))), rValueReferenceType(pointee(isConstQualified())))); Finder->addMatcher( methodDecl(IsSelfAssign, hasParameter(0, parmVarDecl(hasType(BadSelf)))) .bind("ArgumentType"), this); Finder->addMatcher(methodDecl(IsSelfAssign, isConst()).bind("Const"), this); } }
void CloexecSocketCheck::registerMatchers(MatchFinder *Finder) { registerMatchersImpl(Finder, functionDecl(isExternC(), returns(isInteger()), hasName("socket"), hasParameter(0, hasType(isInteger())), hasParameter(1, hasType(isInteger())), hasParameter(2, hasType(isInteger())))); }
_tsTraceMethodExt &_tsTraceMethodExt::returnCOM(HRESULT hr) { tscrypto::tsCryptoString sHr = COMMessage(hr); setErrorTo(FAILED(hr) != FALSE); m_outMessage = sHr; returns(hr); return *this; }
void CloexecAcceptCheck::registerMatchers(MatchFinder *Finder) { auto SockAddrPointerType = hasType(pointsTo(recordDecl(isStruct(), hasName("sockaddr")))); auto SockLenPointerType = hasType(pointsTo(namedDecl(hasName("socklen_t")))); registerMatchersImpl(Finder, functionDecl(returns(isInteger()), hasName("accept"), hasParameter(0, hasType(isInteger())), hasParameter(1, SockAddrPointerType), hasParameter(2, SockLenPointerType))); }
void ContainerSizeEmptyCheck::registerMatchers(MatchFinder *Finder) { // Only register the matchers for C++; the functionality currently does not // provide any benefit to other languages, despite being benign. if (!getLangOpts().CPlusPlus) return; const auto ValidContainer = cxxRecordDecl(isSameOrDerivedFrom( namedDecl( has(cxxMethodDecl( isConst(), parameterCountIs(0), isPublic(), hasName("size"), returns(qualType(isInteger(), unless(booleanType())))) .bind("size")), has(cxxMethodDecl(isConst(), parameterCountIs(0), isPublic(), hasName("empty"), returns(booleanType())) .bind("empty"))) .bind("container"))); const auto WrongUse = anyOf( hasParent(binaryOperator( matchers::isComparisonOperator(), hasEitherOperand(ignoringImpCasts(anyOf( integerLiteral(equals(1)), integerLiteral(equals(0)))))) .bind("SizeBinaryOp")), hasParent(implicitCastExpr( hasImplicitDestinationType(booleanType()), anyOf( hasParent(unaryOperator(hasOperatorName("!")).bind("NegOnSize")), anything()))), hasParent(explicitCastExpr(hasDestinationType(booleanType())))); Finder->addMatcher( cxxMemberCallExpr(on(expr(anyOf(hasType(ValidContainer), hasType(pointsTo(ValidContainer)), hasType(references(ValidContainer)))) .bind("STLObject")), callee(cxxMethodDecl(hasName("size"))), WrongUse) .bind("SizeCallExpr"), this); }
void UnconventionalAssignOperatorCheck::registerMatchers( ast_matchers::MatchFinder *Finder) { // Only register the matchers for C++; the functionality currently does not // provide any benefit to other languages, despite being benign. if (!getLangOpts().CPlusPlus) return; const auto HasGoodReturnType = cxxMethodDecl(returns(lValueReferenceType( pointee(unless(isConstQualified()), anyOf(autoType(), hasDeclaration(equalsBoundNode("class"))))))); const auto IsSelf = qualType( anyOf(hasDeclaration(equalsBoundNode("class")), referenceType(pointee(hasDeclaration(equalsBoundNode("class")))))); const auto IsAssign = cxxMethodDecl(unless(anyOf(isDeleted(), isPrivate(), isImplicit())), hasName("operator="), ofClass(recordDecl().bind("class"))) .bind("method"); const auto IsSelfAssign = cxxMethodDecl(IsAssign, hasParameter(0, parmVarDecl(hasType(IsSelf)))) .bind("method"); Finder->addMatcher( cxxMethodDecl(IsAssign, unless(HasGoodReturnType)).bind("ReturnType"), this); const auto BadSelf = referenceType( anyOf(lValueReferenceType(pointee(unless(isConstQualified()))), rValueReferenceType(pointee(isConstQualified())))); Finder->addMatcher( cxxMethodDecl(IsSelfAssign, hasParameter(0, parmVarDecl(hasType(BadSelf)))) .bind("ArgumentType"), this); Finder->addMatcher( cxxMethodDecl(IsSelfAssign, anyOf(isConst(), isVirtual())).bind("cv"), this); const auto IsBadReturnStatement = returnStmt(unless(has(ignoringParenImpCasts( anyOf(unaryOperator(hasOperatorName("*"), hasUnaryOperand(cxxThisExpr())), cxxOperatorCallExpr(argumentCountIs(1), callee(unresolvedLookupExpr()), hasArgument(0, cxxThisExpr()))))))); const auto IsGoodAssign = cxxMethodDecl(IsAssign, HasGoodReturnType); Finder->addMatcher(returnStmt(IsBadReturnStatement, forFunction(IsGoodAssign)) .bind("returnStmt"), this); }
void TrailingReturnCheck::registerMatchers(MatchFinder *Finder) { // Requires C++11 or later. if (!getLangOpts().CPlusPlus11) return; // Functions that have trailing returns are disallowed, except for those // using decltype specifiers and lambda with otherwise unutterable // return types. Finder->addMatcher( functionDecl(allOf(hasTrailingReturn(), unless(anyOf(returns(decltypeType()), hasParent(cxxRecordDecl(isLambda())))))) .bind("decl"), this); }
void UseToStringCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; Finder->addMatcher( callExpr( hasDeclaration(functionDecl( returns(hasDeclaration(classTemplateSpecializationDecl( hasName("std::basic_string"), hasTemplateArgument(0, templateArgument().bind("char_type"))))), hasName("boost::lexical_cast"), hasParameter(0, hasType(qualType(has(substTemplateTypeParmType( isStrictlyInteger()))))))), argumentCountIs(1), unless(isInTemplateInstantiation())) .bind("to_string"), this); }
_tsTraceMethodExt &_tsTraceMethodExt::returnCOMMsg(HRESULT hr, tscrypto::tsCryptoString fmt, ...) { tscrypto::tsCryptoString sHr; va_list args; switch (hr) { case S_OK: sHr = "OK"; break; case S_FALSE: sHr = "FALSE"; break; case E_NOTIMPL: sHr = "Not Implemented"; break; case E_UNEXPECTED: sHr = "Unexpected operation"; break; case E_OUTOFMEMORY: sHr = "Out Of Memory"; break; case E_INVALIDARG: sHr = "Invalid Argument"; break; case E_NOINTERFACE: sHr = "No Interface"; break; case E_POINTER: sHr = "Invalid Pointer"; break; case E_HANDLE: sHr = "Invalid Handle"; break; case E_ABORT: sHr = "Aborted"; break; case E_FAIL: sHr = "General Failure"; break; case E_ACCESSDENIED: sHr = "Access Denied"; break; case E_PENDING: sHr = ""; break; default: sHr.Format("0x%08X", hr); break; } setErrorTo(FAILED(hr) != FALSE); va_start(args, fmt); m_outMessage.clear(); m_outMessage.resize(MAX_TRACE_MSG_LEN); #ifdef HAVE__VSNPRINTF_S _vsnprintf_s(m_outMessage.rawData(), m_outMessage.size(), m_outMessage.size(), fmt.c_str(), args); #elif defined(HAVE_VSNPRINTF) vsnprintf(m_outMessage.rawData(), m_outMessage.size(), fmt.c_str(), args); #elif defined(HAVE_VSPRINTF_S) vsprintf_s(m_outMessage.rawData(), m_outMessage.size(), fmt.c_str(), args); #elif defined(HAVE_VSPRINTF) vsprintf(m_outMessage.rawData(), fmt.c_str(), args); #else #error Implement me #endif m_outMessage.resize((uint32_t)TsStrLen(m_outMessage.c_str())); m_outMessage.Replace("~~", sHr.c_str()); returns(hr); return *this; }