void InaccurateEraseCheck::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 EndCall =
      callExpr(
          callee(functionDecl(hasAnyName("remove", "remove_if", "unique"))),
          hasArgument(
              1,
              anyOf(cxxConstructExpr(has(ignoringImplicit(
                        cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end"))))
                            .bind("end")))),
                    anything())))
          .bind("alg");

  const auto DeclInStd = type(hasUnqualifiedDesugaredType(
      tagType(hasDeclaration(decl(isInStdNamespace())))));
  Finder->addMatcher(
      cxxMemberCallExpr(
          on(anyOf(hasType(DeclInStd), hasType(pointsTo(DeclInStd)))),
          callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1),
          hasArgument(0, has(ignoringImplicit(
                             anyOf(EndCall, has(ignoringImplicit(EndCall)))))),
          unless(isInTemplateInstantiation()))
          .bind("erase"),
      this);
}
void InaccurateEraseCheck::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 CheckForEndCall = hasArgument(
      1, anyOf(cxxConstructExpr(has(ignoringParenImpCasts(
                   cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end"))))
                       .bind("InaccEndCall")))),
               anything()));

  Finder->addMatcher(
      cxxMemberCallExpr(
          on(hasType(namedDecl(matchesName("^::std::")))),
          callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1),
          hasArgument(0, has(ignoringParenImpCasts(
                             callExpr(callee(functionDecl(matchesName(
                                          "^::std::(remove(_if)?|unique)$"))),
                                      CheckForEndCall)
                                 .bind("InaccAlgCall")))),
          unless(isInTemplateInstantiation()))
          .bind("InaccErase"),
      this);
}
void ParentVirtualCallCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(
      cxxMemberCallExpr(
          callee(memberExpr(hasDescendant(implicitCastExpr(
                                hasImplicitDestinationType(pointsTo(
                                    type(anything()).bind("castToType"))),
                                hasSourceExpression(cxxThisExpr(hasType(
                                    type(anything()).bind("thisType")))))))
                     .bind("member")),
          callee(cxxMethodDecl(isVirtual()))),
      this);
}
void ContainerSizeEmptyCheck::registerMatchers(MatchFinder *Finder) {
  const auto WrongUse = anyOf(
      hasParent(
          binaryOperator(
              anyOf(has(integerLiteral(equals(0))),
                    allOf(anyOf(hasOperatorName("<"), hasOperatorName(">="),
                                hasOperatorName(">"), hasOperatorName("<=")),
                          hasEitherOperand(integerLiteral(equals(1))))))
              .bind("SizeBinaryOp")),
      hasParent(implicitCastExpr(
          hasImplicitDestinationType(isBoolType()),
          anyOf(
              hasParent(unaryOperator(hasOperatorName("!")).bind("NegOnSize")),
              anything()))),
      hasParent(explicitCastExpr(hasDestinationType(isBoolType()))));

  Finder->addMatcher(
      memberCallExpr(
          on(expr(anyOf(hasType(namedDecl(stlContainer())),
                        hasType(pointsTo(namedDecl(stlContainer()))),
                        hasType(references(namedDecl(stlContainer())))))
                 .bind("STLObject")),
          callee(methodDecl(hasName("size"))), WrongUse).bind("SizeCallExpr"),
      this);
}
void MultiwayPathsCoveredCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(
      switchStmt(
          hasCondition(allOf(
              // Match on switch statements that have either a bit-field or
              // an integer condition. The ordering in 'anyOf()' is
              // important because the last condition is the most general.
              anyOf(ignoringImpCasts(memberExpr(hasDeclaration(
                        fieldDecl(isBitField()).bind("bitfield")))),
                    ignoringImpCasts(declRefExpr().bind("non-enum-condition"))),
              // 'unless()' must be the last match here and must be bound,
              // otherwise the matcher does not work correctly, because it
              // will not explicitly ignore enum conditions.
              unless(ignoringImpCasts(
                  declRefExpr(hasType(enumType())).bind("enum-condition"))))))
          .bind("switch"),
      this);

  // This option is noisy, therefore matching is configurable.
  if (WarnOnMissingElse) {
    Finder->addMatcher(
        ifStmt(allOf(hasParent(ifStmt()), unless(hasElse(anything()))))
            .bind("else-if"),
        this);
  }
}
void ExceptionBaseclassCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;

  Finder->addMatcher(
      cxxThrowExpr(allOf(has(expr(unless(hasType(qualType(hasCanonicalType(
                             hasDeclaration(cxxRecordDecl(isSameOrDerivedFrom(
                                 hasName("std::exception")))))))))),
                         has(expr(unless(cxxUnresolvedConstructExpr()))),
                         eachOf(has(expr(hasType(namedDecl().bind("decl")))),
                                anything())))
          .bind("bad_throw"),
      this);
}
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 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 UseBoolLiteralsCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;

  Finder->addMatcher(
      implicitCastExpr(
          has(ignoringParenImpCasts(integerLiteral().bind("literal"))),
          hasImplicitDestinationType(qualType(booleanType())),
          unless(isInTemplateInstantiation()),
          anyOf(hasParent(explicitCastExpr().bind("cast")), anything())),
      this);

  Finder->addMatcher(
      conditionalOperator(
          hasParent(implicitCastExpr(
              hasImplicitDestinationType(qualType(booleanType())),
              unless(isInTemplateInstantiation()))),
          eachOf(hasTrueExpression(
                     ignoringParenImpCasts(integerLiteral().bind("literal"))),
                 hasFalseExpression(
                     ignoringParenImpCasts(integerLiteral().bind("literal"))))),
      this);
}
예제 #10
0
파일: death.hpp 프로젝트: jimporter/mettle
inline auto exited() {
  return detail::exited_impl<decltype(anything())>(anything(), false);
}
예제 #11
0
파일: death.hpp 프로젝트: jimporter/mettle
inline auto killed() {
  return detail::killed_impl<decltype(anything())>(anything(), false);
}
예제 #12
0
namespace caf {

/// A wildcard that matches any number of any values.
constexpr auto any_vals = anything();

/// A wildcard that matches any value of type `T`.
template <class T>
constexpr typename detail::boxed<T>::type val() {
  return typename detail::boxed<T>::type();
}

/// A wildcard that matches the argument types
/// of a given callback, must be the last argument to `on()`.

constexpr auto arg_match = detail::boxed<detail::arg_match_t>::type();

/// Generates function objects from a binary predicate and a value.
template <class T, typename BinaryPredicate>
std::function<optional<T>(const T&)> guarded(BinaryPredicate p, T value) {
  return [=](const T& other) -> optional<T> {
    if (p(other, value)) {
      return value;
    }
    return none;
  };
}

// special case covering arg_match as argument to guarded()
template <class T, typename Predicate>
unit_t guarded(Predicate, const detail::wrapped<T>&) {
  return unit;
}

inline unit_t to_guard(const anything&) {
  return unit;
}

template <class T>
unit_t to_guard(detail::wrapped<T> (*)()) {
  return unit;
}

template <class T>
unit_t to_guard(const detail::wrapped<T>&) {
  return unit;
}

template <class T>
std::function<optional<typename detail::strip_and_convert<T>::type>(
  const typename detail::strip_and_convert<T>::type&)>
to_guard(const T& value,
         typename std::enable_if<! detail::is_callable<T>::value>::type* = 0) {
  using type = typename detail::strip_and_convert<T>::type;
  return guarded<type>(std::equal_to<type>{}, value);
}

template <class F>
F to_guard(F fun,
           typename std::enable_if<detail::is_callable<F>::value>::type* = 0) {
  return fun;
}

template <atom_value V>
auto to_guard(const atom_constant<V>&) -> decltype(to_guard(V)) {
  return to_guard(V);
}

/// Returns a generator for `match_case` objects.
template <class... Ts>
auto on(const Ts&... xs)
-> detail::advanced_match_case_builder<
    detail::type_list<
      decltype(to_guard(xs))...
    >,
    detail::type_list<
      typename detail::pattern_type<typename std::decay<Ts>::type>::type...>
    > {
  return {detail::variadic_ctor{}, to_guard(xs)...};
}

/// Returns a generator for `match_case` objects.
template <class T, class... Ts>
decltype(on(val<T>(), val<Ts>()...)) on() {
  return on(val<T>(), val<Ts>()...);
}

/// Returns a generator for `match_case` objects.
template <atom_value A0, class... Ts>
decltype(on(A0, val<Ts>()...)) on() {
  return on(A0, val<Ts>()...);
}

/// Returns a generator for `match_case` objects.
template <atom_value A0, atom_value A1, class... Ts>
decltype(on(A0, A1, val<Ts>()...)) on() {
  return on(A0, A1, val<Ts>()...);
}

/// Returns a generator for `match_case` objects.
template <atom_value A0, atom_value A1, atom_value A2, class... Ts>
decltype(on(A0, A1, A2, val<Ts>()...)) on() {
  return on(A0, A1, A2, val<Ts>()...);
}

/// Returns a generator for `match_case` objects.
template <atom_value A0, atom_value A1, atom_value A2, atom_value A3,
          class... Ts>
decltype(on(A0, A1, A2, A3, val<Ts>()...)) on() {
  return on(A0, A1, A2, A3, val<Ts>()...);
}

/// Returns a generator for timeouts.
template <class Rep, class Period>
constexpr detail::timeout_definition_builder
after(const std::chrono::duration<Rep, Period>& d) {
  return {duration(d)};
}

/// Generates catch-all `match_case` objects.
constexpr auto others = detail::catch_all_match_case_builder();

/// Semantically equal to `on(arg_match)`, but uses a (faster)
/// special-purpose `match_case` implementation.
constexpr auto on_arg_match = detail::trivial_match_case_builder();

} // namespace caf
예제 #13
0
void CanRunScriptChecker::registerMatchers(MatchFinder *AstMatcher) {
  auto InvalidArg =
      // We want to find any expression,
      ignoreTrivials(expr(
          // which has a refcounted pointer type,
          hasType(pointerType(
              pointee(hasDeclaration(cxxRecordDecl(isRefCounted()))))),
          // and which is not this,
          unless(cxxThisExpr()),
          // and which is not a method call on a smart ptr,
          unless(cxxMemberCallExpr(on(hasType(isSmartPtrToRefCounted())))),
          // and which is not a parameter of the parent function,
          unless(declRefExpr(to(parmVarDecl()))),
          // and which is not a MOZ_KnownLive wrapped value.
          unless(callExpr(callee(functionDecl(hasName("MOZ_KnownLive"))))),
          expr().bind("invalidArg")));

  auto OptionalInvalidExplicitArg = anyOf(
      // We want to find any argument which is invalid.
      hasAnyArgument(InvalidArg),

      // This makes this matcher optional.
      anything());

  // Please not that the hasCanRunScriptAnnotation() matchers are not present
  // directly in the cxxMemberCallExpr, callExpr and constructExpr matchers
  // because we check that the corresponding functions can run script later in
  // the checker code.
  AstMatcher->addMatcher(
      expr(
          anyOf(
              // We want to match a method call expression,
              cxxMemberCallExpr(
                  // which optionally has an invalid arg,
                  OptionalInvalidExplicitArg,
                  // or which optionally has an invalid implicit this argument,
                  anyOf(
                      // which derefs into an invalid arg,
                      on(cxxOperatorCallExpr(
                          anyOf(hasAnyArgument(InvalidArg), anything()))),
                      // or is an invalid arg.
                      on(InvalidArg),

                      anything()),
                  expr().bind("callExpr")),
              // or a regular call expression,
              callExpr(
                  // which optionally has an invalid arg.
                  OptionalInvalidExplicitArg, expr().bind("callExpr")),
              // or a construct expression,
              cxxConstructExpr(
                  // which optionally has an invalid arg.
                  OptionalInvalidExplicitArg, expr().bind("constructExpr"))),

          anyOf(
              // We want to match the parent function.
              forFunction(functionDecl().bind("nonCanRunScriptParentFunction")),

              // ... optionally.
              anything())),
      this);
}
void DanglingOnTemporaryChecker::registerMatchers(MatchFinder *AstMatcher) {
  ////////////////////////////////////////
  // Quick annotation conflict checkers //
  ////////////////////////////////////////

  AstMatcher->addMatcher(
      // This is a matcher on a method declaration,
      cxxMethodDecl(
          // which is marked as no dangling on temporaries,
          noDanglingOnTemporaries(),

          // and which is && ref-qualified.
          isRValueRefQualified(),

          decl().bind("invalidMethodRefQualified")),
      this);

  AstMatcher->addMatcher(
      // This is a matcher on a method declaration,
      cxxMethodDecl(
          // which is marked as no dangling on temporaries,
          noDanglingOnTemporaries(),

          // which returns a primitive type,
          returns(builtinType()),

          // and which doesn't return a pointer.
          unless(returns(pointerType())),

          decl().bind("invalidMethodPointer")),
      this);

  //////////////////
  // Main checker //
  //////////////////

  auto hasParentCall =
      hasParent(expr(anyOf(
          cxxOperatorCallExpr(
              // If we're in a lamda, we may have an operator call expression
              // ancestor in the AST, but the temporary we're matching
              // against is not going to have the same lifetime as the
              // constructor call.
              unless(has(expr(ignoreTrivials(lambdaExpr())))),
              expr().bind("parentOperatorCallExpr")),
          callExpr(
              // If we're in a lamda, we may have a call expression
              // ancestor in the AST, but the temporary we're matching
              // against is not going to have the same lifetime as the
              // function call.
              unless(has(expr(ignoreTrivials(lambdaExpr())))),
              expr().bind("parentCallExpr")),
          objcMessageExpr(
              // If we're in a lamda, we may have an objc message expression
              // ancestor in the AST, but the temporary we're matching
              // against is not going to have the same lifetime as the
              // function call.
              unless(has(expr(ignoreTrivials(lambdaExpr())))),
              expr().bind("parentObjCMessageExpr")),
          cxxConstructExpr(
              // If we're in a lamda, we may have a construct expression
              // ancestor in the AST, but the temporary we're matching
              // against is not going to have the same lifetime as the
              // constructor call.
              unless(has(expr(ignoreTrivials(lambdaExpr())))),
              expr().bind("parentConstructExpr")))));

  AstMatcher->addMatcher(
      // This is a matcher on a method call,
      cxxMemberCallExpr(
          // which is in first party code,
          isFirstParty(),

          // and which is performed on a temporary,
          on(allOf(
              unless(hasType(pointerType())),
              isTemporary(),
              // but which is not `this`.
              unless(cxxThisExpr()))),

          // and which is marked as no dangling on temporaries.
          callee(cxxMethodDecl(noDanglingOnTemporaries())),

          expr().bind("memberCallExpr"),

          // We optionally match a parent call expression or a parent construct
          // expression because using a temporary inside a call is fine as long
          // as the pointer doesn't escape the function call.
          anyOf(
              // This is the case where the call is the direct parent, so we
              // know that the member call expression is the argument.
              allOf(hasParentCall, expr().bind("parentCallArg")),

              // This is the case where the call is not the direct parent, so we
              // get its child to know in which argument tree we are.
              hasAncestor(expr(
                  hasParentCall,
                  expr().bind("parentCallArg"))),
              // To make it optional.
              anything())),
      this);
}
예제 #15
0
auto thrown() {
  return thrown_raw<Exception>(anything());
}
예제 #16
0
#include <vcc.h>

unsigned anything()
  _(reads \universe());

void isqrt(unsigned x)
  _(requires x < 0xfffe0001)
{
  unsigned r = 0, s;

  _(assert r*r <= x) // invariant initially holds
  r = anything();
  _(assume r*r <= x)
  if ((r+1)*(r+1) <= x) {
    r++;
    _(assert r*r <= x)
    _(assume \false)
  }
  _(assert r*r <= x && x < (r+1)*(r+1))
}
/*`
Verification of isqrt succeeded.
`*/