void ElseAfterReturnCheck::registerMatchers(MatchFinder *Finder) {
  // FIXME: Support continue, break and throw.
  Finder->addMatcher(
      ifStmt(
          hasThen(stmt(anyOf(returnStmt(), compoundStmt(has(returnStmt()))))),
          hasElse(stmt().bind("else"))).bind("if"),
      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);
}
Пример #3
0
TEST_F(OneSubOptimizerTests,
EqOpAndXorOpSecOpOfXorIsTenNotOptimized) {
	// return (a == b) ^ 10;
	//
	// Not optimized.
	//
	ShPtr<Variable> varA(Variable::create("a", IntType::create(16, true)));
	ShPtr<Variable> varB(Variable::create("b", IntType::create(16, true)));
	ShPtr<ConstInt> constInt(ConstInt::create(10, 64));
	ShPtr<EqOpExpr> eqOpExpr(
		EqOpExpr::create(
			varA,
			varB
	));
	ShPtr<BitXorOpExpr> returnExpr(
		BitXorOpExpr::create(
			eqOpExpr,
			constInt
	));
	ShPtr<ReturnStmt> returnStmt(ReturnStmt::create(returnExpr));

	optimizer->tryOptimize(returnStmt->getRetVal());

	ShPtr<BitXorOpExpr> outBitXorOpExpr(cast<BitXorOpExpr>(returnStmt->getRetVal()));
	ASSERT_TRUE(outBitXorOpExpr) <<
		"expected `BitXorOpExpr`, "
		"got `" << returnStmt->getRetVal() << "`";
	ShPtr<EqOpExpr> outEqOpExpr(cast<EqOpExpr>(outBitXorOpExpr->getFirstOperand()));
	ASSERT_TRUE(outEqOpExpr) <<
		"expected `EqOpExpr`, "
		"got `" << outBitXorOpExpr->getFirstOperand() << "`";
	ShPtr<Variable> outOp1(cast<Variable>(outEqOpExpr->getFirstOperand()));
	ASSERT_TRUE(outOp1) <<
		"expected `Variable`, "
		"got `" << outEqOpExpr->getFirstOperand() << "`";
	EXPECT_EQ(varA, outOp1) <<
		"expected `" << varA << "`, "
		"got `" << outOp1 << "`";
	ShPtr<Variable> outOp2(cast<Variable>(outEqOpExpr->getSecondOperand()));
	ASSERT_TRUE(outOp2) <<
		"expected `Variable`, "
		"got `" << outEqOpExpr->getSecondOperand() << "`";
	EXPECT_EQ(varB, outOp2) <<
		"expected `" << varB << "`, "
		"got `" << outOp2 << "`";
	ShPtr<ConstInt> outConstInt(cast<ConstInt>(outBitXorOpExpr->getSecondOperand()));
	ASSERT_TRUE(outConstInt) <<
		"expected `ConstInt`, "
		"got `" << outBitXorOpExpr->getSecondOperand() << "`";
	EXPECT_EQ(constInt, outConstInt) <<
		"expected `" << constInt << "`, "
		"got `" << outConstInt << "`";
}
void ElseAfterReturnCheck::registerMatchers(MatchFinder *Finder) {
  const auto ControlFlowInterruptorMatcher =
      stmt(anyOf(returnStmt().bind("return"), continueStmt().bind("continue"),
                 breakStmt().bind("break"), cxxThrowExpr().bind("throw")));
  Finder->addMatcher(
      stmt(forEach(
          ifStmt(hasThen(stmt(
                     anyOf(ControlFlowInterruptorMatcher,
                           compoundStmt(has(ControlFlowInterruptorMatcher))))),
                 hasElse(stmt().bind("else")))
              .bind("if"))),
      this);
}
Пример #5
0
TEST_F(OneSubOptimizerTests,
EqOpWithCastsAndXorOpSecOpOfXorIsOneOptimized) {
	// return IntToPtr(IntToPtr((a == b))) ^ 1;
	//
	// Optimized to retun a != b.
	//
	ShPtr<Variable> varA(Variable::create("a", IntType::create(16, true)));
	ShPtr<Variable> varB(Variable::create("b", IntType::create(16, true)));
	ShPtr<EqOpExpr> eqOpExpr(
		EqOpExpr::create(
			varA,
			varB
	));
	ShPtr<IntToPtrCastExpr> intToPtrCastExprInner(
		IntToPtrCastExpr::create(
			eqOpExpr,
			IntType::create(16)
	));
	ShPtr<IntToPtrCastExpr> intToPtrCastExprOuter(
		IntToPtrCastExpr::create(
			intToPtrCastExprInner,
			IntType::create(16)
	));
	ShPtr<BitXorOpExpr> returnExpr(
		BitXorOpExpr::create(
			intToPtrCastExprOuter,
			ConstInt::create(1, 64)
	));
	ShPtr<ReturnStmt> returnStmt(ReturnStmt::create(returnExpr));

	optimizer->tryOptimize(returnStmt->getRetVal());

	ShPtr<NeqOpExpr> outNeqOpExpr(cast<NeqOpExpr>(returnStmt->getRetVal()));
	ASSERT_TRUE(outNeqOpExpr) <<
		"expected `NegOpExpr`, "
		"got `" << returnStmt->getRetVal() << "`";
	ShPtr<Variable> outOp1(cast<Variable>(outNeqOpExpr->getFirstOperand()));
	ASSERT_TRUE(outOp1) <<
		"expected `Variable`, "
		"got `" << outNeqOpExpr->getFirstOperand() << "`";
	EXPECT_EQ(varA, outOp1) <<
		"expected `" << varA << "`, "
		"got `" << outOp1 << "`";
	ShPtr<Variable> outOp2(cast<Variable>(outNeqOpExpr->getSecondOperand()));
	ASSERT_TRUE(outOp2) <<
		"expected `Variable`, "
		"got `" << outNeqOpExpr->getSecondOperand() << "`";
	EXPECT_EQ(varB, outOp2) <<
		"expected `" << varB << "`, "
		"got `" << outOp2 << "`";
}
Пример #6
0
TEST_F(OneSubOptimizerTests,
FirstOpIsOneConstFloatMulOptimized) {
	// return 1.0 * a;
	//
	// Optimized to return a.
	//
	ShPtr<Variable> varA(Variable::create("a", IntType::create(16)));
	ShPtr<MulOpExpr> returnExpr(
		MulOpExpr::create(
			ConstFloat::create(llvm::APFloat(1.0)),
			varA
	));
	ShPtr<ReturnStmt> returnStmt(ReturnStmt::create(returnExpr));

	optimizer->tryOptimize(returnStmt->getRetVal());

	EXPECT_EQ(varA, returnStmt->getRetVal()) <<
		"expected `" << varA << "`, "
		"got `" << returnStmt << "`";
}
Пример #7
0
TEST_F(OneSubOptimizerTests,
SecOpIsOneConstIntMulOptimized) {
	// return a * 1;
	//
	// Optimized to return a.
	//
	ShPtr<Variable> varA(Variable::create("a", IntType::create(16)));
	ShPtr<MulOpExpr> returnExpr(
		MulOpExpr::create(
			varA,
			ConstInt::create(1, 64)
	));
	ShPtr<ReturnStmt> returnStmt(ReturnStmt::create(returnExpr));

	optimizer->tryOptimize(returnStmt->getRetVal());

	EXPECT_EQ(varA, returnStmt->getRetVal()) <<
		"expected `" << varA << "`, "
		"got `" << returnStmt << "`";
}
void NonConstParameterCheck::registerMatchers(MatchFinder *Finder) {
  // Add parameters to Parameters.
  Finder->addMatcher(parmVarDecl(unless(isInstantiated())).bind("Parm"), this);

  // C++ constructor.
  Finder->addMatcher(cxxConstructorDecl().bind("Ctor"), this);

  // Track unused parameters, there is Wunused-parameter about unused
  // parameters.
  Finder->addMatcher(declRefExpr().bind("Ref"), this);

  // Analyse parameter usage in function.
  Finder->addMatcher(stmt(anyOf(unaryOperator(anyOf(hasOperatorName("++"),
                                                    hasOperatorName("--"))),
                                binaryOperator(), callExpr(), returnStmt(),
                                cxxConstructExpr()))
                         .bind("Mark"),
                     this);
  Finder->addMatcher(varDecl(hasInitializer(anything())).bind("Mark"), this);
}
void ReturnBracedInitListCheck::registerMatchers(MatchFinder *Finder) {
  // Only register the matchers for C++.
  if (!getLangOpts().CPlusPlus11)
    return;

  // Skip list initialization and constructors with an initializer list.
  auto ConstructExpr =
      cxxConstructExpr(
          unless(anyOf(hasDeclaration(cxxConstructorDecl(isExplicit())),
                       isListInitialization(), hasDescendant(initListExpr()),
                       isInTemplateInstantiation())))
          .bind("ctor");

  auto CtorAsArgument = materializeTemporaryExpr(anyOf(
      has(ConstructExpr), has(cxxFunctionalCastExpr(has(ConstructExpr)))));

  Finder->addMatcher(
      functionDecl(isDefinition(), // Declarations don't have return statements.
                   returns(unless(anyOf(builtinType(), autoType()))),
                   hasDescendant(returnStmt(hasReturnValue(
                       has(cxxConstructExpr(has(CtorAsArgument)))))))
          .bind("fn"),
      this);
}
void MisplacedWideningCastCheck::registerMatchers(MatchFinder *Finder) {
  const auto Calc =
      expr(anyOf(binaryOperator(
                     anyOf(hasOperatorName("+"), hasOperatorName("-"),
                           hasOperatorName("*"), hasOperatorName("<<"))),
                 unaryOperator(hasOperatorName("~"))),
           hasType(isInteger()))
          .bind("Calc");

  const auto ExplicitCast = explicitCastExpr(hasDestinationType(isInteger()),
                                             has(ignoringParenImpCasts(Calc)));
  const auto ImplicitCast =
      implicitCastExpr(hasImplicitDestinationType(isInteger()),
                       has(ignoringParenImpCasts(Calc)));
  const auto Cast = expr(anyOf(ExplicitCast, ImplicitCast)).bind("Cast");

  Finder->addMatcher(varDecl(hasInitializer(Cast)), this);
  Finder->addMatcher(returnStmt(hasReturnValue(Cast)), this);
  Finder->addMatcher(callExpr(hasAnyArgument(Cast)), this);
  Finder->addMatcher(binaryOperator(hasOperatorName("="), hasRHS(Cast)), this);
  Finder->addMatcher(
      binaryOperator(matchers::isComparisonOperator(), hasEitherOperand(Cast)),
      this);
}
#include "ASTUtility.h"

StatementMatcher FuncStmtMatcher = compoundStmt(
				hasParent(functionDecl(returns(pointerType())).bind("functiondecl")),
                hasDescendant(returnStmt(
                        hasDescendant(declRefExpr().bind("decl"))))
                ).bind("funcstmt");

class ReturnChecker : public MatchFinder::MatchCallback {
public:
	virtual void run(const MatchFinder::MatchResult &Result)
    {
		clang::ASTContext *Context = Result.Context;
		const clang::CompoundStmt *cs = Result.Nodes.getNodeAs<clang::CompoundStmt>("funcstmt");
		const clang::FunctionDecl *fd = Result.Nodes.getNodeAs<clang::FunctionDecl>("functiondecl");
        const clang::DeclRefExpr *decl = Result.Nodes.getNodeAs<clang::DeclRefExpr>("decl");

		if(!cs || !fd || !decl || ASTUtility::IsStmtInSTDFile(cs, Context)) return;

        if (!clang::VarDecl::classof(decl -> getDecl())) return; 
        
        const clang::VarDecl *var = static_cast<const clang::VarDecl*>(decl -> getDecl());


        if (var -> hasLocalStorage()) 
            ASTUtility::Print(decl, Context, "Rule65");
	}
};

//@TestNeed
static llvm::cl::OptionCategory MyToolCategory("options");