Example #1
0
bool ParseRepetition(Repetition *Repetition, CallExpr *Call, Assertion *A,
                     vector<ValueDecl*>& References,
                     ASTContext& Ctx) {
  unsigned Args = Call->getNumArgs();
  if (Args < 3) {
    Report("Repetition must have at least three arguments (min, max, events)",
        Call->getLocStart(), Ctx)
      << Call->getSourceRange();
    return false;
  }

  auto Min = ParseIntegerLiteral(Call->getArg(0), Ctx);
  Repetition->set_min(Min.getLimitedValue());

  auto Max = ParseIntegerLiteral(Call->getArg(1), Ctx);
  if (Max != INT_MAX) Repetition->set_max(Max.getLimitedValue());

  for (unsigned i = 2; i < Args; ++i) {
    auto Ev = Call->getArg(i);
    if (!ParseEvent(Repetition->add_event(), Ev, A, References, Ctx)) {
      Report("Failed to parse repeated event", Ev->getLocStart(), Ctx)
        << Ev->getSourceRange();
      return false;
    }
  }

  return true;
}
Example #2
0
CharacterConstantExpr *CharacterConstantExpr::
CreateCopyWithCompatibleLength(ASTContext &C, QualType T) {
  auto CTy = T->asCharacterType();
  uint64_t Len = CTy->hasLength()? CTy->getLength() : 1;

  StringRef Str(Data);
  if(Str.size() == Len)
    return this;
  else if(Str.size() > Len)
    // FIXME: the existing memory can be reused.
    return Create(C, getSourceRange(), Str.slice(0, Len), T);
  else {
    auto NewData = new (C) char[Len + 1];
    std::strncpy(NewData, Str.data(), Str.size());
    std::memset(NewData + Str.size(), ' ', (Len - Str.size()));
    NewData[Len] = '\0';
    return new (C) CharacterConstantExpr(NewData, getSourceRange(), T);
  }
}
Example #3
0
bool ParseFunctionCall(FunctionEvent *Event, BinaryOperator *Bop,
                       vector<ValueDecl*>& References,
                       ASTContext& Ctx) {

  // TODO: better distinguishing between callee and/or caller
  Event->set_context(FunctionEvent::Callee);

  // Since we might care about the return value, we must instrument exiting
  // the function rather than entering it.
  Event->set_direction(FunctionEvent::Exit);

  Expr *LHS = Bop->getLHS();
  bool LHSisICE = LHS->isIntegerConstantExpr(Ctx);

  Expr *RHS = Bop->getRHS();

  if (!(LHSisICE ^ RHS->isIntegerConstantExpr(Ctx))) {
    Report("One of {LHS,RHS} must be ICE", Bop->getLocStart(), Ctx)
      << Bop->getSourceRange();
    return false;
  }

  Expr *RetVal = (LHSisICE ? LHS : RHS);
  Expr *FnCall = (LHSisICE ? RHS : LHS);
  if (!ParseArgument(Event->mutable_expectedreturnvalue(), RetVal, References,
                     Ctx))
    return false;

  auto FnCallExpr = dyn_cast<CallExpr>(FnCall);
  if (!FnCallExpr) {
    Report("Not a function call", FnCall->getLocStart(), Ctx)
      << FnCall->getSourceRange();
    return false;
  }

  auto Fn = FnCallExpr->getDirectCallee();
  if (!Fn) {
    Report("Not a direct function call", FnCallExpr->getLocStart(), Ctx)
      << FnCallExpr->getSourceRange();
    return false;
  }

  if (!ParseFunctionRef(Event->mutable_function(), Fn, Ctx)) return false;

  for (auto I = FnCallExpr->arg_begin(); I != FnCallExpr->arg_end(); ++I) {
    if (!ParseArgument(Event->add_argument(), I->IgnoreImplicit(), References,
                       Ctx))
      return false;
  }

  return true;
}
Example #4
0
/**
 * Checks if buffer type and specified mpi datatype matches.
 *
 * @param mpiCall call to check type correspondence for
 */
void MPICheckerAST::checkBufferTypeMatch(const MPICall &mpiCall) const {
    // one pair consists of {bufferIdx, mpiDatatypeIdx}
    IndexPairs indexPairs = bufferDataTypeIndices(mpiCall);

    // for every buffer mpi-data pair in function
    // check if their types match
    for (const auto &idxPair : indexPairs) {
        const VarDecl *bufferArg =
            mpiCall.arguments()[idxPair.first].vars().front();

        // collect buffer type information
        const mpi::TypeVisitor typeVisitor{bufferArg->getType()};

        // get mpi datatype as string
        auto mpiDatatype = mpiCall.arguments()[idxPair.second].stmt_;
        StringRef mpiDatatypeString{util::sourceRangeAsStringRef(
            mpiDatatype->getSourceRange(), analysisManager_)};

        selectTypeMatcher(typeVisitor, mpiCall, mpiDatatypeString, idxPair);
    }
}
Example #5
0
bool ParseEvent(Event *Ev, Expr *E, Assertion *A,
                vector<ValueDecl*>& References, ASTContext& Ctx) {

  E = E->IgnoreImplicit();

  if (auto Ref = dyn_cast<DeclRefExpr>(E)) {
    auto D = Ref->getDecl();
    assert(D);

    // The __tesla_ignore "event" helps TESLA assertions look like ISO C.
    if (D->getName() == "__tesla_ignore") {
      Ev->set_type(Event::IGNORE);
      return true;
    }

    // The only other static __tesla_event is the "now" event.
    if (D->getName() != "__tesla_now") {
      Report("TESLA static reference must be __tesla_ignore or __tesla_now",
             E->getLocStart(), Ctx)
        << E->getSourceRange();
      return false;
    }

    Ev->set_type(Event::NOW);
    *Ev->mutable_now()->mutable_location() = A->location();
    return true;
  } else if (auto Bop = dyn_cast<BinaryOperator>(E)) {
    // This is a call-and-return like "foo(x) == y".
    Ev->set_type(Event::FUNCTION);
    return ParseFunctionCall(Ev->mutable_function(), Bop, References, Ctx);
  }

  // Otherwise, it's a call to a TESLA "function" like __tesla_predicate().
  auto Call = dyn_cast<CallExpr>(E);
  if (!Call) {
    Report("Event should look like a function call", E->getLocStart(), Ctx)
      << E->getSourceRange();
    return false;
  }

  auto Callee = Call->getDirectCallee();
  if (!Callee) {
    Report("TESLA event referenced indirectly", Call->getLocStart(), Ctx)
      << Call->getSourceRange();
    return false;
  }

  if (Callee->getName() == "__tesla_repeat") {
    Ev->set_type(Event::REPETITION);
    return ParseRepetition(Ev->mutable_repetition(), Call, A, References, Ctx);
  }

  typedef bool (*FnEventParser)(FunctionEvent*, CallExpr*, vector<ValueDecl*>&,
                                ASTContext&);

  FnEventParser Parser = llvm::StringSwitch<FnEventParser>(Callee->getName())
    .Case("__tesla_entered", &ParseFunctionEntry)
    .Case("__tesla_leaving", &ParseFunctionExit)
    .Case("__tesla_call",    &ParseFunctionCall)
    .Default(NULL);

  if (!Parser) {
    Report("Unknown TESLA event", E->getLocStart(), Ctx)
      << E->getSourceRange();
    return false;
  }

  Ev->set_type(Event::FUNCTION);
  return Parser(Ev->mutable_function(), Call, References, Ctx);
}