Пример #1
0
 void ICEVisitor::VisitImplicitCastExpr(ImplicitCastExpr *CE) {
   const NamedDecl *ACD = dyn_cast<NamedDecl>(AC->getDecl());
   VisitChildren(CE);
   const Expr *SE = CE->getSubExprAsWritten();
   std::string sename = SE->getType().getAsString();
   const clang::Expr *E = CE->getSubExpr();
   if (!(sename == "EventNumber_t"))
     return;
   QualType OTy = BR.getContext().getCanonicalType(E->getType());
   QualType TTy = BR.getContext().getCanonicalType(CE->getType());
   QualType ToTy = TTy.getUnqualifiedType();
   QualType OrigTy = OTy.getUnqualifiedType();
   if (!(ToTy->isIntegerType() || ToTy->isFloatingType()))
     return;
   if (ToTy->isBooleanType())
     return;
   CharUnits size_otype = BR.getContext().getTypeSizeInChars(OrigTy);
   CharUnits size_ttype = BR.getContext().getTypeSizeInChars(ToTy);
   std::string oname = OrigTy.getAsString();
   std::string tname = ToTy.getAsString();
   if (ToTy->isFloatingType()) {
     llvm::SmallString<100> buf;
     llvm::raw_svector_ostream os(buf);
     os << "Cast-to type, " << tname << ". Cast-from type, " << oname << " . " << support::getQualifiedName(*(ACD));
     clang::ento::PathDiagnosticLocation CELoc =
         clang::ento::PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
     BR.EmitBasicReport(ACD,
                        CheckName(),
                        "implicit cast of int type to float type",
                        "CMS code rules",
                        os.str(),
                        CELoc,
                        CE->getSourceRange());
   }
   if ((size_otype > size_ttype)) {
     llvm::SmallString<100> buf;
     llvm::raw_svector_ostream os(buf);
     os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Cast may result in truncation. "
        << support::getQualifiedName(*(ACD));
     clang::ento::PathDiagnosticLocation CELoc =
         clang::ento::PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
     BR.EmitBasicReport(ACD,
                        CheckName(),
                        "implicit cast of int type to smaller int type could truncate",
                        "CMS code rules",
                        os.str(),
                        CELoc,
                        CE->getSourceRange());
   }
   if (ToTy->hasSignedIntegerRepresentation() && OrigTy->hasUnsignedIntegerRepresentation() ||
       ToTy->hasUnsignedIntegerRepresentation() && OrigTy->hasSignedIntegerRepresentation()) {
     llvm::SmallString<100> buf;
     llvm::raw_svector_ostream os(buf);
     os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Changes int sign type. "
        << support::getQualifiedName(*(ACD));
     clang::ento::PathDiagnosticLocation CELoc =
         clang::ento::PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
     BR.EmitBasicReport(ACD,
                        CheckName(),
                        "implicit cast changes int sign type",
                        "CMS code rules",
                        os.str(),
                        CELoc,
                        CE->getSourceRange());
   }
   return;
 }
Пример #2
0
// FIXME: should rewrite according to the cast kind.
SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
  castTy = Context.getCanonicalType(castTy);
  originalTy = Context.getCanonicalType(originalTy);
  if (val.isUnknownOrUndef() || castTy == originalTy)
    return val;

  // For const casts, just propagate the value.
  if (!castTy->isVariableArrayType() && !originalTy->isVariableArrayType())
    if (haveSimilarTypes(Context, Context.getPointerType(castTy),
                                  Context.getPointerType(originalTy)))
      return val;
  
  // Check for casts from pointers to integers.
  if (castTy->isIntegerType() && Loc::isLocType(originalTy))
    return evalCastFromLoc(cast<Loc>(val), castTy);

  // Check for casts from integers to pointers.
  if (Loc::isLocType(castTy) && originalTy->isIntegerType()) {
    if (nonloc::LocAsInteger *LV = dyn_cast<nonloc::LocAsInteger>(&val)) {
      if (const MemRegion *R = LV->getLoc().getAsRegion()) {
        StoreManager &storeMgr = StateMgr.getStoreManager();
        R = storeMgr.castRegion(R, castTy);
        return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
      }
      return LV->getLoc();
    }
    return dispatchCast(val, castTy);
  }

  // Just pass through function and block pointers.
  if (originalTy->isBlockPointerType() || originalTy->isFunctionPointerType()) {
    assert(Loc::isLocType(castTy));
    return val;
  }

  // Check for casts from array type to another type.
  if (originalTy->isArrayType()) {
    // We will always decay to a pointer.
    val = StateMgr.ArrayToPointer(cast<Loc>(val));

    // Are we casting from an array to a pointer?  If so just pass on
    // the decayed value.
    if (castTy->isPointerType())
      return val;

    // Are we casting from an array to an integer?  If so, cast the decayed
    // pointer value to an integer.
    assert(castTy->isIntegerType());

    // FIXME: Keep these here for now in case we decide soon that we
    // need the original decayed type.
    //    QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
    //    QualType pointerTy = C.getPointerType(elemTy);
    return evalCastFromLoc(cast<Loc>(val), castTy);
  }

  // Check for casts from a region to a specific type.
  if (const MemRegion *R = val.getAsRegion()) {
    // FIXME: We should handle the case where we strip off view layers to get
    //  to a desugared type.

    if (!Loc::isLocType(castTy)) {
      // FIXME: There can be gross cases where one casts the result of a function
      // (that returns a pointer) to some other value that happens to fit
      // within that pointer value.  We currently have no good way to
      // model such operations.  When this happens, the underlying operation
      // is that the caller is reasoning about bits.  Conceptually we are
      // layering a "view" of a location on top of those bits.  Perhaps
      // we need to be more lazy about mutual possible views, even on an
      // SVal?  This may be necessary for bit-level reasoning as well.
      return UnknownVal();
    }

    // We get a symbolic function pointer for a dereference of a function
    // pointer, but it is of function type. Example:

    //  struct FPRec {
    //    void (*my_func)(int * x);
    //  };
    //
    //  int bar(int x);
    //
    //  int f1_a(struct FPRec* foo) {
    //    int x;
    //    (*foo->my_func)(&x);
    //    return bar(x)+1; // no-warning
    //  }

    assert(Loc::isLocType(originalTy) || originalTy->isFunctionType() ||
           originalTy->isBlockPointerType() || castTy->isReferenceType());

    StoreManager &storeMgr = StateMgr.getStoreManager();

    // Delegate to store manager to get the result of casting a region to a
    // different type.  If the MemRegion* returned is NULL, this expression
    // Evaluates to UnknownVal.
    R = storeMgr.castRegion(R, castTy);
    return R ? SVal(loc::MemRegionVal(R)) : UnknownVal();
  }

  return dispatchCast(val, castTy);
}
Пример #3
0
/// Create a fake body for dispatch_once.
static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
  // Check if we have at least two parameters.
  if (D->param_size() != 2)
    return 0;

  // Check if the first parameter is a pointer to integer type.
  const ParmVarDecl *Predicate = D->getParamDecl(0);
  QualType PredicateQPtrTy = Predicate->getType();
  const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>();
  if (!PredicatePtrTy)
    return 0;
  QualType PredicateTy = PredicatePtrTy->getPointeeType();
  if (!PredicateTy->isIntegerType())
    return 0;
  
  // Check if the second parameter is the proper block type.
  const ParmVarDecl *Block = D->getParamDecl(1);
  QualType Ty = Block->getType();
  if (!isDispatchBlock(Ty))
    return 0;
  
  // Everything checks out.  Create a fakse body that checks the predicate,
  // sets it, and calls the block.  Basically, an AST dump of:
  //
  // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) {
  //  if (!*predicate) {
  //    *predicate = 1;
  //    block();
  //  }
  // }
  
  ASTMaker M(C);
  
  // (1) Create the call.
  DeclRefExpr *DR = M.makeDeclRefExpr(Block);
  ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
  CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue,
                                  SourceLocation());

  // (2) Create the assignment to the predicate.
  IntegerLiteral *IL =
    IntegerLiteral::Create(C, llvm::APInt(C.getTypeSize(C.IntTy), (uint64_t) 1),
                           C.IntTy, SourceLocation());
  BinaryOperator *B =
    M.makeAssignment(
       M.makeDereference(
          M.makeLvalueToRvalue(
            M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
            PredicateTy),
       M.makeIntegralCast(IL, PredicateTy),
       PredicateTy);
  
  // (3) Create the compound statement.
  Stmt *Stmts[2];
  Stmts[0] = B;
  Stmts[1] = CE;
  CompoundStmt *CS = M.makeCompound(ArrayRef<Stmt*>(Stmts, 2));
  
  // (4) Create the 'if' condition.
  ImplicitCastExpr *LValToRval =
    M.makeLvalueToRvalue(
      M.makeDereference(
        M.makeLvalueToRvalue(
          M.makeDeclRefExpr(Predicate),
          PredicateQPtrTy),
        PredicateTy),
    PredicateTy);
  
  UnaryOperator *UO = new (C) UnaryOperator(LValToRval, UO_LNot, C.IntTy,
                                           VK_RValue, OK_Ordinary,
                                           SourceLocation());
  
  // (5) Create the 'if' statement.
  IfStmt *If = new (C) IfStmt(C, SourceLocation(), 0, UO, CS);
  return If;
}
Пример #4
0
const GRState *SimpleConstraintManager::AssumeSymRel(const GRState *state,
                                                     const SymExpr *LHS,
                                                     BinaryOperator::Opcode op,
                                                     const llvm::APSInt& Int) {
  assert(BinaryOperator::isComparisonOp(op) &&
         "Non-comparison ops should be rewritten as comparisons to zero.");

   // We only handle simple comparisons of the form "$sym == constant"
   // or "($sym+constant1) == constant2".
   // The adjustment is "constant1" in the above expression. It's used to
   // "slide" the solution range around for modular arithmetic. For example,
   // x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which
   // in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to
   // the subclasses of SimpleConstraintManager to handle the adjustment.
   llvm::APSInt Adjustment;

  // First check if the LHS is a simple symbol reference.
  SymbolRef Sym = dyn_cast<SymbolData>(LHS);
  if (Sym) {
    Adjustment = 0;
  } else {
    // Next, see if it's a "($sym+constant1)" expression.
    const SymIntExpr *SE = dyn_cast<SymIntExpr>(LHS);

    // We don't handle "($sym1+$sym2)".
    // Give up and assume the constraint is feasible.
    if (!SE)
      return state;

    // We don't handle "(<expr>+constant1)".
    // Give up and assume the constraint is feasible.
    Sym = dyn_cast<SymbolData>(SE->getLHS());
    if (!Sym)
      return state;

    // Get the constant out of the expression "($sym+constant1)".
    switch (SE->getOpcode()) {
    case BO_Add:
      Adjustment = SE->getRHS();
      break;
    case BO_Sub:
      Adjustment = -SE->getRHS();
      break;
    default:
      // We don't handle non-additive operators.
      // Give up and assume the constraint is feasible.
      return state;
    }
  }

  // FIXME: This next section is a hack. It silently converts the integers to
  // be of the same type as the symbol, which is not always correct. Really the
  // comparisons should be performed using the Int's type, then mapped back to
  // the symbol's range of values.
  GRStateManager &StateMgr = state->getStateManager();
  ASTContext &Ctx = StateMgr.getContext();

  QualType T = Sym->getType(Ctx);
  assert(T->isIntegerType() || Loc::IsLocType(T));
  unsigned bitwidth = Ctx.getTypeSize(T);
  bool isSymUnsigned = T->isUnsignedIntegerType() || Loc::IsLocType(T);

  // Convert the adjustment.
  Adjustment.setIsUnsigned(isSymUnsigned);
  Adjustment.extOrTrunc(bitwidth);

  // Convert the right-hand side integer.
  llvm::APSInt ConvertedInt(Int, isSymUnsigned);
  ConvertedInt.extOrTrunc(bitwidth);

  switch (op) {
  default:
    // No logic yet for other operators.  Assume the constraint is feasible.
    return state;

  case BO_EQ:
    return AssumeSymEQ(state, Sym, ConvertedInt, Adjustment);

  case BO_NE:
    return AssumeSymNE(state, Sym, ConvertedInt, Adjustment);

  case BO_GT:
    return AssumeSymGT(state, Sym, ConvertedInt, Adjustment);

  case BO_GE:
    return AssumeSymGE(state, Sym, ConvertedInt, Adjustment);

  case BO_LT:
    return AssumeSymLT(state, Sym, ConvertedInt, Adjustment);

  case BO_LE:
    return AssumeSymLE(state, Sym, ConvertedInt, Adjustment);
  } // end switch
}
Пример #5
0
void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const {
  ProgramStateRef state = C.getState();

  if (CE->getNumArgs() < 2) {
    // The frontend should issue a warning for this case, so this is a sanity
    // check.
    return;
  } else if (CE->getNumArgs() == 3) {
    const Expr *Arg = CE->getArg(2);
    QualType QT = Arg->getType();
    if (!QT->isIntegerType()) {
      ReportOpenBug(C, state,
                    "Third argument to 'open' is not an integer",
                    Arg->getSourceRange());
      return;
    }
  } else if (CE->getNumArgs() > 3) {
    ReportOpenBug(C, state,
                  "Call to 'open' with more than three arguments",
                  CE->getArg(3)->getSourceRange());
    return;
  }

  // The definition of O_CREAT is platform specific.  We need a better way
  // of querying this information from the checking environment.
  if (!Val_O_CREAT.hasValue()) {
    if (C.getASTContext().getTargetInfo().getTriple().getVendor() 
                                                      == llvm::Triple::Apple)
      Val_O_CREAT = 0x0200;
    else {
      // FIXME: We need a more general way of getting the O_CREAT value.
      // We could possibly grovel through the preprocessor state, but
      // that would require passing the Preprocessor object to the ExprEngine.
      // See also: MallocChecker.cpp / M_ZERO.
      return;
    }
  }

  // Now check if oflags has O_CREAT set.
  const Expr *oflagsEx = CE->getArg(1);
  const SVal V = state->getSVal(oflagsEx, C.getLocationContext());
  if (!V.getAs<NonLoc>()) {
    // The case where 'V' can be a location can only be due to a bad header,
    // so in this case bail out.
    return;
  }
  NonLoc oflags = V.castAs<NonLoc>();
  NonLoc ocreateFlag = C.getSValBuilder()
      .makeIntVal(Val_O_CREAT.getValue(), oflagsEx->getType()).castAs<NonLoc>();
  SVal maskedFlagsUC = C.getSValBuilder().evalBinOpNN(state, BO_And,
                                                      oflags, ocreateFlag,
                                                      oflagsEx->getType());
  if (maskedFlagsUC.isUnknownOrUndef())
    return;
  DefinedSVal maskedFlags = maskedFlagsUC.castAs<DefinedSVal>();

  // Check if maskedFlags is non-zero.
  ProgramStateRef trueState, falseState;
  std::tie(trueState, falseState) = state->assume(maskedFlags);

  // Only emit an error if the value of 'maskedFlags' is properly
  // constrained;
  if (!(trueState && !falseState))
    return;

  if (CE->getNumArgs() < 3) {
    ReportOpenBug(C, trueState,
                  "Call to 'open' requires a third argument when "
                  "the 'O_CREAT' flag is set",
                  oflagsEx->getSourceRange());
  }
}
bool AuditCFNumberCreate::Audit(ExplodedNode* N,GRStateManager&){
  const CallExpr* CE =
    cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
  const Expr* Callee = CE->getCallee();
  SVal CallV = N->getState()->getSVal(Callee);
  const FunctionDecl* FD = CallV.getAsFunctionDecl();

  if (!FD || FD->getIdentifier() != II || CE->getNumArgs()!=3)
    return false;

  // Get the value of the "theType" argument.
  SVal TheTypeVal = N->getState()->getSVal(CE->getArg(1));

    // FIXME: We really should allow ranges of valid theType values, and
    //   bifurcate the state appropriately.
  nonloc::ConcreteInt* V = dyn_cast<nonloc::ConcreteInt>(&TheTypeVal);

  if (!V)
    return false;

  uint64_t NumberKind = V->getValue().getLimitedValue();
  Optional<uint64_t> TargetSize = GetCFNumberSize(Ctx, NumberKind);

  // FIXME: In some cases we can emit an error.
  if (!TargetSize.isKnown())
    return false;

  // Look at the value of the integer being passed by reference.  Essentially
  // we want to catch cases where the value passed in is not equal to the
  // size of the type being created.
  SVal TheValueExpr = N->getState()->getSVal(CE->getArg(2));

  // FIXME: Eventually we should handle arbitrary locations.  We can do this
  //  by having an enhanced memory model that does low-level typing.
  loc::MemRegionVal* LV = dyn_cast<loc::MemRegionVal>(&TheValueExpr);

  if (!LV)
    return false;

  const TypedRegion* R = dyn_cast<TypedRegion>(LV->StripCasts());

  if (!R)
    return false;

  QualType T = Ctx.getCanonicalType(R->getValueType(Ctx));

  // FIXME: If the pointee isn't an integer type, should we flag a warning?
  //  People can do weird stuff with pointers.

  if (!T->isIntegerType())
    return false;

  uint64_t SourceSize = Ctx.getTypeSize(T);

  // CHECK: is SourceSize == TargetSize

  if (SourceSize == TargetSize)
    return false;

  AddError(R, CE->getArg(2), N, SourceSize, TargetSize, NumberKind);

  // FIXME: We can actually create an abstract "CFNumber" object that has
  //  the bits initialized to the provided values.
  return SourceSize < TargetSize;
}
Пример #7
0
StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
                                 bool IsVolatile, unsigned NumOutputs,
                                 unsigned NumInputs, IdentifierInfo **Names,
                                 MultiExprArg constraints, MultiExprArg exprs,
                                 Expr *asmString, MultiExprArg clobbers,
                                 SourceLocation RParenLoc) {
  unsigned NumClobbers = clobbers.size();
  StringLiteral **Constraints =
    reinterpret_cast<StringLiteral**>(constraints.data());
  Expr **Exprs = exprs.data();
  StringLiteral *AsmString = cast<StringLiteral>(asmString);
  StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data());

  SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;

  // The parser verifies that there is a string literal here.
  if (!AsmString->isAscii())
    return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character)
      << AsmString->getSourceRange());

  for (unsigned i = 0; i != NumOutputs; i++) {
    StringLiteral *Literal = Constraints[i];
    if (!Literal->isAscii())
      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
        << Literal->getSourceRange());

    StringRef OutputName;
    if (Names[i])
      OutputName = Names[i]->getName();

    TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
    if (!Context.getTargetInfo().validateOutputConstraint(Info))
      return StmtError(Diag(Literal->getLocStart(),
                            diag::err_asm_invalid_output_constraint)
                       << Info.getConstraintStr());

    // Check that the output exprs are valid lvalues.
    Expr *OutputExpr = Exprs[i];
    if (CheckAsmLValue(OutputExpr, *this)) {
      return StmtError(Diag(OutputExpr->getLocStart(),
                  diag::err_asm_invalid_lvalue_in_output)
        << OutputExpr->getSourceRange());
    }

    OutputConstraintInfos.push_back(Info);
  }

  SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;

  for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
    StringLiteral *Literal = Constraints[i];
    if (!Literal->isAscii())
      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
        << Literal->getSourceRange());

    StringRef InputName;
    if (Names[i])
      InputName = Names[i]->getName();

    TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
    if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(),
                                                NumOutputs, Info)) {
      return StmtError(Diag(Literal->getLocStart(),
                            diag::err_asm_invalid_input_constraint)
                       << Info.getConstraintStr());
    }

    Expr *InputExpr = Exprs[i];

    // Only allow void types for memory constraints.
    if (Info.allowsMemory() && !Info.allowsRegister()) {
      if (CheckAsmLValue(InputExpr, *this))
        return StmtError(Diag(InputExpr->getLocStart(),
                              diag::err_asm_invalid_lvalue_in_input)
                         << Info.getConstraintStr()
                         << InputExpr->getSourceRange());
    }

    if (Info.allowsRegister()) {
      if (InputExpr->getType()->isVoidType()) {
        return StmtError(Diag(InputExpr->getLocStart(),
                              diag::err_asm_invalid_type_in_input)
          << InputExpr->getType() << Info.getConstraintStr()
          << InputExpr->getSourceRange());
      }
    }

    ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
    if (Result.isInvalid())
      return StmtError();

    Exprs[i] = Result.take();
    InputConstraintInfos.push_back(Info);

    const Type *Ty = Exprs[i]->getType().getTypePtr();
    if (Ty->isDependentType() || Ty->isIncompleteType())
      continue;

    unsigned Size = Context.getTypeSize(Ty);
    if (!Context.getTargetInfo().validateInputSize(Literal->getString(),
                                                   Size))
      return StmtError(Diag(InputExpr->getLocStart(),
                            diag::err_asm_invalid_input_size)
                       << Info.getConstraintStr());
  }

  // Check that the clobbers are valid.
  for (unsigned i = 0; i != NumClobbers; i++) {
    StringLiteral *Literal = Clobbers[i];
    if (!Literal->isAscii())
      return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character)
        << Literal->getSourceRange());

    StringRef Clobber = Literal->getString();

    if (!Context.getTargetInfo().isValidClobber(Clobber))
      return StmtError(Diag(Literal->getLocStart(),
                  diag::err_asm_unknown_register_name) << Clobber);
  }

  GCCAsmStmt *NS =
    new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
                             NumInputs, Names, Constraints, Exprs, AsmString,
                             NumClobbers, Clobbers, RParenLoc);
  // Validate the asm string, ensuring it makes sense given the operands we
  // have.
  SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces;
  unsigned DiagOffs;
  if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
    Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
           << AsmString->getSourceRange();
    return StmtError();
  }

  // Validate constraints and modifiers.
  for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
    GCCAsmStmt::AsmStringPiece &Piece = Pieces[i];
    if (!Piece.isOperand()) continue;

    // Look for the correct constraint index.
    unsigned Idx = 0;
    unsigned ConstraintIdx = 0;
    for (unsigned i = 0, e = NS->getNumOutputs(); i != e; ++i, ++ConstraintIdx) {
      TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
      if (Idx == Piece.getOperandNo())
        break;
      ++Idx;

      if (Info.isReadWrite()) {
        if (Idx == Piece.getOperandNo())
          break;
        ++Idx;
      }
    }

    for (unsigned i = 0, e = NS->getNumInputs(); i != e; ++i, ++ConstraintIdx) {
      TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
      if (Idx == Piece.getOperandNo())
        break;
      ++Idx;

      if (Info.isReadWrite()) {
        if (Idx == Piece.getOperandNo())
          break;
        ++Idx;
      }
    }

    // Now that we have the right indexes go ahead and check.
    StringLiteral *Literal = Constraints[ConstraintIdx];
    const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
    if (Ty->isDependentType() || Ty->isIncompleteType())
      continue;

    unsigned Size = Context.getTypeSize(Ty);
    if (!Context.getTargetInfo()
          .validateConstraintModifier(Literal->getString(), Piece.getModifier(),
                                      Size))
      Diag(Exprs[ConstraintIdx]->getLocStart(),
           diag::warn_asm_mismatched_size_modifier);
  }

  // Validate tied input operands for type mismatches.
  for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
    TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];

    // If this is a tied constraint, verify that the output and input have
    // either exactly the same type, or that they are int/ptr operands with the
    // same size (int/long, int*/long, are ok etc).
    if (!Info.hasTiedOperand()) continue;

    unsigned TiedTo = Info.getTiedOperand();
    unsigned InputOpNo = i+NumOutputs;
    Expr *OutputExpr = Exprs[TiedTo];
    Expr *InputExpr = Exprs[InputOpNo];

    if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent())
      continue;

    QualType InTy = InputExpr->getType();
    QualType OutTy = OutputExpr->getType();
    if (Context.hasSameType(InTy, OutTy))
      continue;  // All types can be tied to themselves.

    // Decide if the input and output are in the same domain (integer/ptr or
    // floating point.
    enum AsmDomain {
      AD_Int, AD_FP, AD_Other
    } InputDomain, OutputDomain;

    if (InTy->isIntegerType() || InTy->isPointerType())
      InputDomain = AD_Int;
    else if (InTy->isRealFloatingType())
      InputDomain = AD_FP;
    else
      InputDomain = AD_Other;

    if (OutTy->isIntegerType() || OutTy->isPointerType())
      OutputDomain = AD_Int;
    else if (OutTy->isRealFloatingType())
      OutputDomain = AD_FP;
    else
      OutputDomain = AD_Other;

    // They are ok if they are the same size and in the same domain.  This
    // allows tying things like:
    //   void* to int*
    //   void* to int            if they are the same size.
    //   double to long double   if they are the same size.
    //
    uint64_t OutSize = Context.getTypeSize(OutTy);
    uint64_t InSize = Context.getTypeSize(InTy);
    if (OutSize == InSize && InputDomain == OutputDomain &&
        InputDomain != AD_Other)
      continue;

    // If the smaller input/output operand is not mentioned in the asm string,
    // then we can promote the smaller one to a larger input and the asm string
    // won't notice.
    bool SmallerValueMentioned = false;

    // If this is a reference to the input and if the input was the smaller
    // one, then we have to reject this asm.
    if (isOperandMentioned(InputOpNo, Pieces)) {
      // This is a use in the asm string of the smaller operand.  Since we
      // codegen this by promoting to a wider value, the asm will get printed
      // "wrong".
      SmallerValueMentioned |= InSize < OutSize;
    }
    if (isOperandMentioned(TiedTo, Pieces)) {
      // If this is a reference to the output, and if the output is the larger
      // value, then it's ok because we'll promote the input to the larger type.
      SmallerValueMentioned |= OutSize < InSize;
    }

    // If the smaller value wasn't mentioned in the asm string, and if the
    // output was a register, just extend the shorter one to the size of the
    // larger one.
    if (!SmallerValueMentioned && InputDomain != AD_Other &&
        OutputConstraintInfos[TiedTo].allowsRegister())
      continue;

    // Either both of the operands were mentioned or the smaller one was
    // mentioned.  One more special case that we'll allow: if the tied input is
    // integer, unmentioned, and is a constant, then we'll allow truncating it
    // down to the size of the destination.
    if (InputDomain == AD_Int && OutputDomain == AD_Int &&
        !isOperandMentioned(InputOpNo, Pieces) &&
        InputExpr->isEvaluatable(Context)) {
      CastKind castKind =
        (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
      InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take();
      Exprs[InputOpNo] = InputExpr;
      NS->setInputExpr(i, InputExpr);
      continue;
    }

    Diag(InputExpr->getLocStart(),
         diag::err_asm_tying_incompatible_types)
      << InTy << OutTy << OutputExpr->getSourceRange()
      << InputExpr->getSourceRange();
    return StmtError();
  }

  return Owned(NS);
}
Пример #8
0
StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
                                 bool IsVolatile, unsigned NumOutputs,
                                 unsigned NumInputs, IdentifierInfo **Names,
                                 MultiExprArg constraints, MultiExprArg Exprs,
                                 Expr *asmString, MultiExprArg clobbers,
                                 SourceLocation RParenLoc) {
  unsigned NumClobbers = clobbers.size();
  StringLiteral **Constraints =
    reinterpret_cast<StringLiteral**>(constraints.data());
  StringLiteral *AsmString = cast<StringLiteral>(asmString);
  StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data());

  SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;

  // The parser verifies that there is a string literal here.
  assert(AsmString->isAscii());

  // If we're compiling CUDA file and function attributes indicate that it's not
  // for this compilation side, skip all the checks.
  if (!DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl())) {
    GCCAsmStmt *NS = new (Context) GCCAsmStmt(
        Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names,
        Constraints, Exprs.data(), AsmString, NumClobbers, Clobbers, RParenLoc);
    return NS;
  }

  // If we're compiling HCC file and function attributes indicate that it's not
  // for this compilation side, skip all the checks.
  if (!DeclAttrsMatchHCCMode(getLangOpts(), getCurFunctionDecl())) {
    GCCAsmStmt *NS = new (Context) GCCAsmStmt(
        Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names,
        Constraints, Exprs.data(), AsmString, NumClobbers, Clobbers, RParenLoc);
    return NS;
  }

  for (unsigned i = 0; i != NumOutputs; i++) {
    StringLiteral *Literal = Constraints[i];
    assert(Literal->isAscii());

    StringRef OutputName;
    if (Names[i])
      OutputName = Names[i]->getName();

    TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
    if (!Context.getTargetInfo().validateOutputConstraint(Info))
      return StmtError(Diag(Literal->getLocStart(),
                            diag::err_asm_invalid_output_constraint)
                       << Info.getConstraintStr());

    ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
    if (ER.isInvalid())
      return StmtError();
    Exprs[i] = ER.get();

    // Check that the output exprs are valid lvalues.
    Expr *OutputExpr = Exprs[i];

    // Referring to parameters is not allowed in naked functions.
    if (CheckNakedParmReference(OutputExpr, *this))
      return StmtError();

    // Check that the output expression is compatible with memory constraint.
    if (Info.allowsMemory() &&
        checkExprMemoryConstraintCompat(*this, OutputExpr, Info, false))
      return StmtError();

    OutputConstraintInfos.push_back(Info);

    // If this is dependent, just continue.
    if (OutputExpr->isTypeDependent())
      continue;

    Expr::isModifiableLvalueResult IsLV =
        OutputExpr->isModifiableLvalue(Context, /*Loc=*/nullptr);
    switch (IsLV) {
    case Expr::MLV_Valid:
      // Cool, this is an lvalue.
      break;
    case Expr::MLV_ArrayType:
      // This is OK too.
      break;
    case Expr::MLV_LValueCast: {
      const Expr *LVal = OutputExpr->IgnoreParenNoopCasts(Context);
      if (!getLangOpts().HeinousExtensions) {
        Diag(LVal->getLocStart(), diag::err_invalid_asm_cast_lvalue)
            << OutputExpr->getSourceRange();
      } else {
        Diag(LVal->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
            << OutputExpr->getSourceRange();
      }
      // Accept, even if we emitted an error diagnostic.
      break;
    }
    case Expr::MLV_IncompleteType:
    case Expr::MLV_IncompleteVoidType:
      if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(),
                              diag::err_dereference_incomplete_type))
        return StmtError();
    default:
      return StmtError(Diag(OutputExpr->getLocStart(),
                            diag::err_asm_invalid_lvalue_in_output)
                       << OutputExpr->getSourceRange());
    }

    unsigned Size = Context.getTypeSize(OutputExpr->getType());
    if (!Context.getTargetInfo().validateOutputSize(Literal->getString(),
                                                    Size))
      return StmtError(Diag(OutputExpr->getLocStart(),
                            diag::err_asm_invalid_output_size)
                       << Info.getConstraintStr());
  }

  SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;

  for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
    StringLiteral *Literal = Constraints[i];
    assert(Literal->isAscii());

    StringRef InputName;
    if (Names[i])
      InputName = Names[i]->getName();

    TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
    if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos,
                                                         Info)) {
      return StmtError(Diag(Literal->getLocStart(),
                            diag::err_asm_invalid_input_constraint)
                       << Info.getConstraintStr());
    }

    ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
    if (ER.isInvalid())
      return StmtError();
    Exprs[i] = ER.get();

    Expr *InputExpr = Exprs[i];

    // Referring to parameters is not allowed in naked functions.
    if (CheckNakedParmReference(InputExpr, *this))
      return StmtError();

    // Check that the input expression is compatible with memory constraint.
    if (Info.allowsMemory() &&
        checkExprMemoryConstraintCompat(*this, InputExpr, Info, true))
      return StmtError();

    // Only allow void types for memory constraints.
    if (Info.allowsMemory() && !Info.allowsRegister()) {
      if (CheckAsmLValue(InputExpr, *this))
        return StmtError(Diag(InputExpr->getLocStart(),
                              diag::err_asm_invalid_lvalue_in_input)
                         << Info.getConstraintStr()
                         << InputExpr->getSourceRange());
    } else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
      if (!InputExpr->isValueDependent()) {
        llvm::APSInt Result;
        if (!InputExpr->EvaluateAsInt(Result, Context))
           return StmtError(
               Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected)
                << Info.getConstraintStr() << InputExpr->getSourceRange());
         if (!Info.isValidAsmImmediate(Result))
           return StmtError(Diag(InputExpr->getLocStart(),
                                 diag::err_invalid_asm_value_for_constraint)
                            << Result.toString(10) << Info.getConstraintStr()
                            << InputExpr->getSourceRange());
      }

    } else {
      ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
      if (Result.isInvalid())
        return StmtError();

      Exprs[i] = Result.get();
    }

    if (Info.allowsRegister()) {
      if (InputExpr->getType()->isVoidType()) {
        return StmtError(Diag(InputExpr->getLocStart(),
                              diag::err_asm_invalid_type_in_input)
          << InputExpr->getType() << Info.getConstraintStr()
          << InputExpr->getSourceRange());
      }
    }

    InputConstraintInfos.push_back(Info);

    const Type *Ty = Exprs[i]->getType().getTypePtr();
    if (Ty->isDependentType())
      continue;

    if (!Ty->isVoidType() || !Info.allowsMemory())
      if (RequireCompleteType(InputExpr->getLocStart(), Exprs[i]->getType(),
                              diag::err_dereference_incomplete_type))
        return StmtError();

    unsigned Size = Context.getTypeSize(Ty);
    if (!Context.getTargetInfo().validateInputSize(Literal->getString(),
                                                   Size))
      return StmtError(Diag(InputExpr->getLocStart(),
                            diag::err_asm_invalid_input_size)
                       << Info.getConstraintStr());
  }

  // Check that the clobbers are valid.
  for (unsigned i = 0; i != NumClobbers; i++) {
    StringLiteral *Literal = Clobbers[i];
    assert(Literal->isAscii());

    StringRef Clobber = Literal->getString();

    if (!Context.getTargetInfo().isValidClobber(Clobber))
      return StmtError(Diag(Literal->getLocStart(),
                  diag::err_asm_unknown_register_name) << Clobber);
  }

  GCCAsmStmt *NS =
    new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
                             NumInputs, Names, Constraints, Exprs.data(),
                             AsmString, NumClobbers, Clobbers, RParenLoc);
  // Validate the asm string, ensuring it makes sense given the operands we
  // have.
  SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces;
  unsigned DiagOffs;
  if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
    Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
           << AsmString->getSourceRange();
    return StmtError();
  }

  // Validate constraints and modifiers.
  for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
    GCCAsmStmt::AsmStringPiece &Piece = Pieces[i];
    if (!Piece.isOperand()) continue;

    // Look for the correct constraint index.
    unsigned ConstraintIdx = Piece.getOperandNo();
    unsigned NumOperands = NS->getNumOutputs() + NS->getNumInputs();

    // Look for the (ConstraintIdx - NumOperands + 1)th constraint with
    // modifier '+'.
    if (ConstraintIdx >= NumOperands) {
      unsigned I = 0, E = NS->getNumOutputs();

      for (unsigned Cnt = ConstraintIdx - NumOperands; I != E; ++I)
        if (OutputConstraintInfos[I].isReadWrite() && Cnt-- == 0) {
          ConstraintIdx = I;
          break;
        }

      assert(I != E && "Invalid operand number should have been caught in "
                       " AnalyzeAsmString");
    }

    // Now that we have the right indexes go ahead and check.
    StringLiteral *Literal = Constraints[ConstraintIdx];
    const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
    if (Ty->isDependentType() || Ty->isIncompleteType())
      continue;

    unsigned Size = Context.getTypeSize(Ty);
    std::string SuggestedModifier;
    if (!Context.getTargetInfo().validateConstraintModifier(
            Literal->getString(), Piece.getModifier(), Size,
            SuggestedModifier)) {
      Diag(Exprs[ConstraintIdx]->getLocStart(),
           diag::warn_asm_mismatched_size_modifier);

      if (!SuggestedModifier.empty()) {
        auto B = Diag(Piece.getRange().getBegin(),
                      diag::note_asm_missing_constraint_modifier)
                 << SuggestedModifier;
        SuggestedModifier = "%" + SuggestedModifier + Piece.getString();
        B.AddFixItHint(FixItHint::CreateReplacement(Piece.getRange(),
                                                    SuggestedModifier));
      }
    }
  }

  // Validate tied input operands for type mismatches.
  unsigned NumAlternatives = ~0U;
  for (unsigned i = 0, e = OutputConstraintInfos.size(); i != e; ++i) {
    TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
    StringRef ConstraintStr = Info.getConstraintStr();
    unsigned AltCount = ConstraintStr.count(',') + 1;
    if (NumAlternatives == ~0U)
      NumAlternatives = AltCount;
    else if (NumAlternatives != AltCount)
      return StmtError(Diag(NS->getOutputExpr(i)->getLocStart(),
                            diag::err_asm_unexpected_constraint_alternatives)
                       << NumAlternatives << AltCount);
  }
  SmallVector<size_t, 4> InputMatchedToOutput(OutputConstraintInfos.size(),
                                              ~0U);
  for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
    TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
    StringRef ConstraintStr = Info.getConstraintStr();
    unsigned AltCount = ConstraintStr.count(',') + 1;
    if (NumAlternatives == ~0U)
      NumAlternatives = AltCount;
    else if (NumAlternatives != AltCount)
      return StmtError(Diag(NS->getInputExpr(i)->getLocStart(),
                            diag::err_asm_unexpected_constraint_alternatives)
                       << NumAlternatives << AltCount);

    // If this is a tied constraint, verify that the output and input have
    // either exactly the same type, or that they are int/ptr operands with the
    // same size (int/long, int*/long, are ok etc).
    if (!Info.hasTiedOperand()) continue;

    unsigned TiedTo = Info.getTiedOperand();
    unsigned InputOpNo = i+NumOutputs;
    Expr *OutputExpr = Exprs[TiedTo];
    Expr *InputExpr = Exprs[InputOpNo];

    // Make sure no more than one input constraint matches each output.
    assert(TiedTo < InputMatchedToOutput.size() && "TiedTo value out of range");
    if (InputMatchedToOutput[TiedTo] != ~0U) {
      Diag(NS->getInputExpr(i)->getLocStart(),
           diag::err_asm_input_duplicate_match)
          << TiedTo;
      Diag(NS->getInputExpr(InputMatchedToOutput[TiedTo])->getLocStart(),
           diag::note_asm_input_duplicate_first)
          << TiedTo;
      return StmtError();
    }
    InputMatchedToOutput[TiedTo] = i;

    if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent())
      continue;

    QualType InTy = InputExpr->getType();
    QualType OutTy = OutputExpr->getType();
    if (Context.hasSameType(InTy, OutTy))
      continue;  // All types can be tied to themselves.

    // Decide if the input and output are in the same domain (integer/ptr or
    // floating point.
    enum AsmDomain {
      AD_Int, AD_FP, AD_Other
    } InputDomain, OutputDomain;

    if (InTy->isIntegerType() || InTy->isPointerType())
      InputDomain = AD_Int;
    else if (InTy->isRealFloatingType())
      InputDomain = AD_FP;
    else
      InputDomain = AD_Other;

    if (OutTy->isIntegerType() || OutTy->isPointerType())
      OutputDomain = AD_Int;
    else if (OutTy->isRealFloatingType())
      OutputDomain = AD_FP;
    else
      OutputDomain = AD_Other;

    // They are ok if they are the same size and in the same domain.  This
    // allows tying things like:
    //   void* to int*
    //   void* to int            if they are the same size.
    //   double to long double   if they are the same size.
    //
    uint64_t OutSize = Context.getTypeSize(OutTy);
    uint64_t InSize = Context.getTypeSize(InTy);
    if (OutSize == InSize && InputDomain == OutputDomain &&
        InputDomain != AD_Other)
      continue;

    // If the smaller input/output operand is not mentioned in the asm string,
    // then we can promote the smaller one to a larger input and the asm string
    // won't notice.
    bool SmallerValueMentioned = false;

    // If this is a reference to the input and if the input was the smaller
    // one, then we have to reject this asm.
    if (isOperandMentioned(InputOpNo, Pieces)) {
      // This is a use in the asm string of the smaller operand.  Since we
      // codegen this by promoting to a wider value, the asm will get printed
      // "wrong".
      SmallerValueMentioned |= InSize < OutSize;
    }
    if (isOperandMentioned(TiedTo, Pieces)) {
      // If this is a reference to the output, and if the output is the larger
      // value, then it's ok because we'll promote the input to the larger type.
      SmallerValueMentioned |= OutSize < InSize;
    }

    // If the smaller value wasn't mentioned in the asm string, and if the
    // output was a register, just extend the shorter one to the size of the
    // larger one.
    if (!SmallerValueMentioned && InputDomain != AD_Other &&
        OutputConstraintInfos[TiedTo].allowsRegister())
      continue;

    // Either both of the operands were mentioned or the smaller one was
    // mentioned.  One more special case that we'll allow: if the tied input is
    // integer, unmentioned, and is a constant, then we'll allow truncating it
    // down to the size of the destination.
    if (InputDomain == AD_Int && OutputDomain == AD_Int &&
        !isOperandMentioned(InputOpNo, Pieces) &&
        InputExpr->isEvaluatable(Context)) {
      CastKind castKind =
        (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
      InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).get();
      Exprs[InputOpNo] = InputExpr;
      NS->setInputExpr(i, InputExpr);
      continue;
    }

    Diag(InputExpr->getLocStart(),
         diag::err_asm_tying_incompatible_types)
      << InTy << OutTy << OutputExpr->getSourceRange()
      << InputExpr->getSourceRange();
    return StmtError();
  }

  // Check for conflicts between clobber list and input or output lists
  SourceLocation ConstraintLoc =
      getClobberConflictLocation(Exprs, Constraints, Clobbers, NumClobbers,
                                 Context.getTargetInfo(), Context);
  if (ConstraintLoc.isValid())
    return Diag(ConstraintLoc, diag::error_inoutput_conflict_with_clobber);
  
  return NS;
}
Пример #9
0
// caller must free returned value
const EmuVal* eval_rexpr(const Expr* e){
	errs() << "\nDEBUG: about to eval rexpr:\n";
	e->dump();

	if(isa<IntegerLiteral>(e)){
		const IntegerLiteral *obj = (const IntegerLiteral*)e;
		APInt i = obj->getValue();
		if(i.slt(EMU_MIN_INT) || i.sgt(EMU_MAX_INT)){
			e->dump();
			cant_handle();
		}
		return new EmuNum<NUM_TYPE_INT>(i);
	} else if(isa<CharacterLiteral>(e)){
		const CharacterLiteral *obj = (const CharacterLiteral*)e;
		unsigned int i = obj->getValue();
		if(i > 127){
			e->dump();
			cant_handle();
		}
		return new EmuNum<NUM_TYPE_CHAR>(new APInt(8, i, true));
	} else if(isa<UnaryOperator>(e)){
		const UnaryOperator *obj = (const UnaryOperator*)e;
		const Expr* sub = obj->getSubExpr();
		const auto op = obj->getOpcode();
		switch(op){
		case UO_AddrOf:
		{
			lvalue arg = eval_lexpr(sub);
			return new EmuPtr(arg.ptr, e->getType());
		}
		case UO_LNot:
		case UO_Minus:
		{
			const EmuVal* arg = eval_rexpr(sub);
			if(!arg->obj_type->isIntegerType()){
				cant_cast();
			}
			if(op == UO_LNot){
				return ((const EmuNumGeneric*)arg)->lnot();
			} else if (op == UO_Minus){
				return ((const EmuNumGeneric*)arg)->neg();
			}
		}
		case UO_Deref:
		case UO_Extension:
		case UO_Imag:
		case UO_Real:
		case UO_Not:
		case UO_PostInc:
		case UO_PostDec:
		case UO_PreInc:
		case UO_PreDec:
		case UO_Plus:
		default:
			llvm::errs() << "Got opcode " << obj->getOpcode() << "\n";
			cant_handle();
		}
	} else if(isa<BinaryOperator>(e)){
		const BinaryOperator* ex = (const BinaryOperator*)e;
		BinaryOperatorKind op = ex->getOpcode();

		// right always an rexpr
		const EmuVal *right = eval_rexpr(ex->getRHS());

		switch(op){
		case BO_Assign:
		{
			lvalue left = eval_lexpr(ex->getLHS());
			const EmuVal* ans = right->cast_to(left.type);
			delete right;
			left.ptr.block->write(ans, left.ptr.offset);
			return ans;
		}
		case BO_LT:
		case BO_GT:
		case BO_LE:
		case BO_GE:
		case BO_EQ:
		case BO_NE:
		{
			const EmuVal *left = eval_rexpr(ex->getLHS());
			QualType tl = left->obj_type.getCanonicalType();
			QualType tr = right->obj_type.getCanonicalType();
			if(tl != IntType || tr != IntType){
				left->obj_type.dump();
				right->obj_type.dump();
				cant_handle();
			}
			const llvm::APInt* lval = &((const EmuNum<NUM_TYPE_INT>*)left)->val;
			llvm::APInt rval = ((const EmuNum<NUM_TYPE_INT>*)right)->val;
			int ans;
			if(lval->isNegative()){
				if(op == BO_LT)    ans = (lval->slt(rval))?1:0;
				else if(op==BO_GT) ans = (lval->sgt(rval))?1:0;
				else if(op==BO_LE) ans = (lval->sle(rval))?1:0;
				else if(op==BO_GE) ans = (lval->sge(rval))?1:0;
				else if(op==BO_EQ) ans = (lval->eq( rval))?1:0;
				else if(op==BO_NE) ans = (lval->ne( rval))?1:0;
			} else if(rval.isNegative()){
				if(op == BO_LT)    ans = 0;
				else if(op==BO_GT) ans = 1;
				else if(op==BO_LE) ans = 0;
				else if(op==BO_GE) ans = 1;
				else if(op==BO_EQ) ans = 0;
				else if(op==BO_NE) ans = 1;
			} else {
				if(op == BO_LT)    ans = (lval->ult(rval))?1:0;
				else if(op==BO_GT) ans = (lval->ugt(rval))?1:0;
				else if(op==BO_LE) ans = (lval->ule(rval))?1:0;
				else if(op==BO_GE) ans = (lval->uge(rval))?1:0;
				else if(op==BO_EQ) ans = (lval->eq( rval))?1:0;
				else if(op==BO_NE) ans = (lval->ne( rval))?1:0;
			}
			delete left;
			delete right;
			return new EmuNum<NUM_TYPE_INT>(APInt(32, apint_signed_repr(ans), true));
		}
		case BO_AddAssign:
		case BO_SubAssign:
		{
			lvalue left = eval_lexpr(ex->getLHS());
			QualType tl = left.type.getCanonicalType();
			QualType tr = right->obj_type.getCanonicalType();
			if(tl != IntType || tr != IntType){
				left.type.dump();
				right->obj_type.dump();
				cant_handle();
			}
			void* ptr = &((char*)left.ptr.block->data)[left.ptr.offset];
			size_t space = left.ptr.block->size;
			if(space < 4 || space-4 < left.ptr.offset){
				bad_memread();
			}
			const EmuNum<NUM_TYPE_INT> value(ptr);
			const EmuNum<NUM_TYPE_INT>* result;
			if(op == BO_AddAssign) result = value.add((const EmuNum<NUM_TYPE_INT>*)right);
			else                   result = value.sub((const EmuNum<NUM_TYPE_INT>*)right);
			left.ptr.block->write(result, left.ptr.offset);
			delete right;
			return result;
		}
		case BO_Add:
		case BO_Sub:
		case BO_Mul:
		case BO_Div:
		case BO_And:
		case BO_Or:
		{
			const EmuVal* left = eval_rexpr(ex->getLHS());
			if(!right->obj_type->isIntegerType()){
				right->obj_type.dump();
				cant_cast();
			}
			const EmuNumGeneric* trueright = (const EmuNumGeneric*)right;
			const EmuVal* retval;

			QualType tl = left->obj_type;
			// special case: add integer to pointer
			if(tl->isPointerType()){
				int n;
				if(op == BO_Add) n = trueright->val.getSExtValue();
				else if(op == BO_Sub) n = -trueright->val.getSExtValue();
				else err_exit("Undefined op on pointer");
				
				QualType sub = tl->getAs<PointerType>()->getPointeeType();
				int s = getSizeOf(sub);
				const EmuPtr* lp = (const EmuPtr*)left;
				retval = new EmuPtr(mem_ptr(lp->u.block,lp->offset+n*s), tl);
			} else if(tl->isIntegerType()){
				const EmuNumGeneric* trueleft = (const EmuNumGeneric*)left;
				if(op == BO_Add)      retval = trueleft->add(trueright);
				else if(op == BO_Sub) retval = trueleft->sub(trueright);
				else if(op == BO_Mul) retval = trueleft->mul(trueright);
				else if(op == BO_Div) retval = trueleft->div(trueright);
				else if(op == BO_Or) retval = trueleft->_or(trueright);
				else if(op == BO_And)retval = trueleft->_and(trueright);
				else cant_cast();
			} else {
				tl.dump();
				cant_cast();
			}

			delete left;
			delete right;

			return retval;
		}
		case BO_PtrMemD:
		case BO_PtrMemI:
		case BO_Rem:
		case BO_Shl:
		case BO_Shr:
		case BO_LAnd:
		case BO_Xor:
		case BO_LOr:
		case BO_MulAssign:
		case BO_DivAssign:
		case BO_RemAssign:
		case BO_ShlAssign:
		case BO_ShrAssign:
		case BO_AndAssign:
		case BO_XorAssign:
		case BO_OrAssign:
		case BO_Comma:
		default:
			e->dump();
			cant_handle();
		}
	} else if(isa<CastExpr>(e)){
		const CastExpr* expr = (const CastExpr*)e;
		const Expr* sub = expr->getSubExpr();
		switch(expr->getCastKind()){
		case CK_LValueToRValue:
			return from_lvalue(eval_lexpr(sub));
		case CK_NoOp:
			return eval_rexpr(sub);
		case CK_BitCast:
		{
			if(isa<ExplicitCastExpr>(e)){
				const ExplicitCastExpr* expr = (const ExplicitCastExpr*)e;
				return eval_rexpr(sub)->cast_to(expr->getTypeAsWritten());
			}
			// else ImplicitCastExpr
			return eval_rexpr(sub)->cast_to(e->getType());
		}
		case CK_IntegralCast:
		{
			return eval_rexpr(sub)->cast_to(expr->getType());
		}
		case CK_FunctionToPointerDecay:
		{
			lvalue l = eval_lexpr(sub);
			if(!l.type->isFunctionType()){
				e->dump();
				cant_cast();
			}
			return new EmuPtr(l.ptr, sources[curr_source]->getPointerType(l.type));
		}
		case CK_ArrayToPointerDecay:
		{
			lvalue l = eval_lexpr(sub);
			const EmuVal* ans = new EmuPtr(l.ptr, expr->getType());
			return ans;
		}
		case CK_BuiltinFnToFnPtr:
		{
			if(!isa<DeclRefExpr>(sub)){
				err_exit("Don't know how to convert builtin function");
			}
			std::string name = ((const DeclRefExpr*)sub)->getDecl()->getNameAsString();
			const EmuFunc* f = get_external_func(name, sub->getType());
			mem_block* ptr = new mem_block(MEM_TYPE_STATIC, f);
			delete f;
			return new EmuPtr(mem_ptr(ptr,0), expr->getType());
		}
		case CK_NullToPointer:
		{
			return new EmuPtr(mem_ptr(nullptr,0), expr->getType());
		}
		case CK_PointerToIntegral:
		{
			const EmuVal* ptr = eval_rexpr(sub);
			if(!ptr->obj_type->isPointerType()){
				err_exit("Expected pointer");
			}
			const EmuPtr* p = (const EmuPtr*)ptr;
			if(p->status != STATUS_DEFINED) cant_handle();
			uint64_t segment;
			uint64_t offset = p->offset;
			if(p->u.block == nullptr){
				segment = 0;
			} else {
				segment = p->u.block->id;
			}
			delete ptr;
			if((expr->getType()->getAs<BuiltinType>())->isSignedInteger()){
				return new EmuNum<NUM_TYPE_LONGLONG>(APInt(64, (segment << 32) + offset, true));
			} else {
				return new EmuNum<NUM_TYPE_ULONGLONG>(APInt(64, (segment << 32) + offset, false));				
			}
		}
		case CK_VectorSplat:
		case CK_IntegralToBoolean:
		case CK_IntegralToFloating:
		case CK_FloatingToIntegral:
		case CK_FloatingToBoolean:
		case CK_FloatingCast:
		case CK_CPointerToObjCPointerCast:
		case CK_BlockPointerToObjCPointerCast:
		case CK_AnyPointerToBlockPointerCast:
		case CK_ObjCObjectLValueCast:
		case CK_FloatingRealToComplex:
		case CK_FloatingComplexToReal:
		case CK_FloatingComplexToBoolean:
		case CK_FloatingComplexCast:
		case CK_FloatingComplexToIntegralComplex:
		case CK_IntegralRealToComplex:
		case CK_IntegralComplexToReal:
		case CK_IntegralComplexToBoolean:
		case CK_IntegralComplexCast:
		case CK_IntegralComplexToFloatingComplex:
		case CK_ARCProduceObject:
		case CK_ARCConsumeObject:
		case CK_ARCReclaimReturnedObject:
		case CK_ARCExtendBlockObject:
		case CK_AtomicToNonAtomic:
		case CK_NonAtomicToAtomic:
		case CK_CopyAndAutoreleaseBlockObject:
		case CK_ZeroToOCLEvent:
		case CK_AddressSpaceConversion:
		case CK_ReinterpretMemberPointer:
		case CK_UserDefinedConversion:
		case CK_ConstructorConversion:
		case CK_IntegralToPointer:
		case CK_PointerToBoolean:
		case CK_ToVoid:
		default:
			llvm::errs() << "\n\n";
			e->dump();
			cant_cast();
		}
	} else if(isa<CallExpr>(e)){
		const CallExpr* expr = (const CallExpr*)e;
		const Expr* const* args = expr->getArgs();
		const Expr* callee = expr->getCallee();

		llvm::errs() << "DOUG DEBUG: executing the following call:\n";
		callee->dump();

		const EmuVal* f = eval_rexpr(callee);
		if(f->status != STATUS_DEFINED || !f->obj_type->isFunctionPointerType()){
			f->obj_type.dump();
			err_exit("Calling an invalid function");
		}

		const EmuPtr* p = (const EmuPtr*)f;
		if(p->u.block->memtype == MEM_TYPE_EXTERN){
			err_exit("Tried to call an unimplemented function");
		}

		const EmuFunc* func = (const EmuFunc*)from_lvalue(lvalue(p->u.block, ((const PointerType*)p->obj_type.getTypePtr())->getPointeeType(), p->offset));
		uint32_t fid = func->func_id;
		
		const EmuVal* retval;

		add_stack_frame();
		if(fid < NUM_EXTERNAL_FUNCTIONS){
			if(is_lvalue_based_macro(fid)){
				// special handling for va_args stuff
				for(unsigned int i=0; i < expr->getNumArgs(); i++){
					const Expr* arg = args[i];
					while(isa<ImplicitCastExpr>(arg)){
						arg = ((const ImplicitCastExpr*)arg)->getSubExpr();
					}
					if(!isa<DeclRefExpr>(arg)){
						err_exit("Passed non-variable as lvalue to builtin macro");
					}
					std::string name = ((const DeclRefExpr*)arg)->getDecl()->getNameAsString();
					std::unordered_map<std::string,std::deque<std::pair<int,int> > >::const_iterator list = stack_var_map.find(name);
					if(list == stack_var_map.end()){
						err_exit("Can't find appropriate lvalue for macro");
					}
					const auto test = list->second;
					const auto item = test.back();
					const EmuVal* val = new EmuStackPos(item.first, item.second);
					mem_block* storage = new mem_block(MEM_TYPE_STACK, val);
					add_stack_var("", lvalue(storage,val->obj_type,0));
					delete val;
				}
			} else {
				// we are dealing with an external function
				for(unsigned int i=0; i < expr->getNumArgs(); i++){
					const EmuVal* val = eval_rexpr(args[i]);
					mem_block* storage = new mem_block(MEM_TYPE_STACK, val);
					add_stack_var("", lvalue(storage,val->obj_type,0));
					delete val;
				}
			}
			retval = call_external(fid);
		} else {
			const auto it = global_functions.find(fid);
			const FunctionDecl* defn = (const FunctionDecl*)it->second.second;

			for(unsigned int i=0; i < expr->getNumArgs(); i++){
				const EmuVal* val = eval_rexpr(args[i]);
				mem_block* storage = new mem_block(MEM_TYPE_STACK, val);
				std::string name;
				if(i >= defn->getNumParams()){
					name = ""; // relevant for later args of e.g. printf(char*, ...)
				} else {
					name = defn->getParamDecl(i)->getNameAsString();
				}
				llvm::errs() << "DOUG DEBUG: adding stack variable "<<name<<" for arg "<<i<<" of internal function call (numparams="<< defn->getNumParams() <<")\n";
				defn->dump();
				
				add_stack_var(name, lvalue(storage,val->obj_type,0));
				delete val;
			}

			int save = curr_source;
			curr_source = it->second.first;
			llvm::errs() << "DOUG DEBUG: actually executing:\n";
			defn->getBody()->dump();
			retval = exec_stmt(defn->getBody());
			llvm::errs() << "DOUG DEBUG: call returned with retval at "<<((const void*)retval)<<"\n";
			curr_source = save;
		}
		llvm::errs() << "DOUG DEBUG: popping frame leaving call\n";
		pop_stack_frame();
		return retval;
	} else if(isa<UnaryExprOrTypeTraitExpr>(e)){
		const UnaryExprOrTypeTraitExpr* expr = (const UnaryExprOrTypeTraitExpr*)e;
		switch(expr->getKind()){
		case UETT_SizeOf:
		{
			QualType qt = expr->getArgumentType();
			const EmuVal* fake = from_lvalue(lvalue(nullptr, qt, 0));
			uint64_t thesize = (uint64_t)fake->size();
			delete fake;
			return new EmuNum<NUM_TYPE_ULONG>(APInt(32, thesize, false));
		}
		case UETT_AlignOf:
		case UETT_VecStep:
		default:
			e->dump();
			cant_handle();
		}
	} else if(isa<InitListExpr>(e)){
		const InitListExpr* expr = (const InitListExpr*)e;
		unsigned int n = expr->getNumInits();
		QualType qt = expr->getType();
		if(qt->isArrayType()){
			const EmuPtr* array = (const EmuPtr*)from_lvalue(lvalue(nullptr, qt, 0));
			if(array->status != STATUS_DEFINED) cant_handle();
			size_t loc = 0;
			for(unsigned int i = 0; i < n; i++){
				const EmuVal* curr = eval_rexpr(expr->getInit(i));
				array->u.block->write(curr, loc);
				loc += curr->size();
				delete curr;
			}
			return array;
		} else if(qt->isStructureType()){
			unsigned int n = expr->getNumInits();
			const EmuVal** arr = new const EmuVal*[n];
			for(unsigned int i = 0; i < n; i++){
				arr[i] = eval_rexpr(expr->getInit(i));
			}
			return new EmuStruct(STATUS_DEFINED, qt, n, arr);
		}
		cant_handle();
	} else if(isa<ImplicitValueInitExpr>(e)){
		return zero_init(e->getType());
	} else if(isa<ParenExpr>(e)){
		return eval_rexpr(((const ParenExpr*)e)->getSubExpr());
	}
	e->dump();
	cant_handle();
}
void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE,
                                         CheckerContext &C) const {
  ProgramStateRef state = C.getState();
  const FunctionDecl *FD = C.getCalleeDecl(CE);
  if (!FD)
    return;
  
  ASTContext &Ctx = C.getASTContext();
  if (!II)
    II = &Ctx.Idents.get("CFNumberCreate");

  if (FD->getIdentifier() != II || CE->getNumArgs() != 3)
    return;

  // Get the value of the "theType" argument.
  const LocationContext *LCtx = C.getLocationContext();
  SVal TheTypeVal = state->getSVal(CE->getArg(1), LCtx);

  // FIXME: We really should allow ranges of valid theType values, and
  //   bifurcate the state appropriately.
  nonloc::ConcreteInt* V = dyn_cast<nonloc::ConcreteInt>(&TheTypeVal);
  if (!V)
    return;

  uint64_t NumberKind = V->getValue().getLimitedValue();
  Optional<uint64_t> TargetSize = GetCFNumberSize(Ctx, NumberKind);

  // FIXME: In some cases we can emit an error.
  if (!TargetSize.isKnown())
    return;

  // Look at the value of the integer being passed by reference.  Essentially
  // we want to catch cases where the value passed in is not equal to the
  // size of the type being created.
  SVal TheValueExpr = state->getSVal(CE->getArg(2), LCtx);

  // FIXME: Eventually we should handle arbitrary locations.  We can do this
  //  by having an enhanced memory model that does low-level typing.
  loc::MemRegionVal* LV = dyn_cast<loc::MemRegionVal>(&TheValueExpr);
  if (!LV)
    return;

  const TypedValueRegion* R = dyn_cast<TypedValueRegion>(LV->stripCasts());
  if (!R)
    return;

  QualType T = Ctx.getCanonicalType(R->getValueType());

  // FIXME: If the pointee isn't an integer type, should we flag a warning?
  //  People can do weird stuff with pointers.

  if (!T->isIntegerType())
    return;

  uint64_t SourceSize = Ctx.getTypeSize(T);

  // CHECK: is SourceSize == TargetSize
  if (SourceSize == TargetSize)
    return;

  // Generate an error.  Only generate a sink if 'SourceSize < TargetSize';
  // otherwise generate a regular node.
  //
  // FIXME: We can actually create an abstract "CFNumber" object that has
  //  the bits initialized to the provided values.
  //
  if (ExplodedNode *N = SourceSize < TargetSize ? C.generateSink() 
                                                : C.addTransition()) {
    SmallString<128> sbuf;
    llvm::raw_svector_ostream os(sbuf);
    
    os << (SourceSize == 8 ? "An " : "A ")
       << SourceSize << " bit integer is used to initialize a CFNumber "
                        "object that represents "
       << (TargetSize == 8 ? "an " : "a ")
       << TargetSize << " bit integer. ";
    
    if (SourceSize < TargetSize)
      os << (TargetSize - SourceSize)
      << " bits of the CFNumber value will be garbage." ;
    else
      os << (SourceSize - TargetSize)
      << " bits of the input integer will be lost.";

    if (!BT)
      BT.reset(new APIMisuse("Bad use of CFNumberCreate"));
    
    BugReport *report = new BugReport(*BT, os.str(), N);
    report->addRange(CE->getArg(2)->getSourceRange());
    C.EmitReport(report);
  }
}
SVal SimpleSValBuilder::evalBinOpNN(const ProgramState *state,
                                  BinaryOperator::Opcode op,
                                  NonLoc lhs, NonLoc rhs,
                                  QualType resultTy)  {
  // Handle trivial case where left-side and right-side are the same.
  if (lhs == rhs)
    switch (op) {
      default:
        break;
      case BO_EQ:
      case BO_LE:
      case BO_GE:
        return makeTruthVal(true, resultTy);
      case BO_LT:
      case BO_GT:
      case BO_NE:
        return makeTruthVal(false, resultTy);
      case BO_Xor:
      case BO_Sub:
        return makeIntVal(0, resultTy);
      case BO_Or:
      case BO_And:
        return evalCastFromNonLoc(lhs, resultTy);
    }

  while (1) {
    switch (lhs.getSubKind()) {
    default:
      return generateUnknownVal(state, op, lhs, rhs, resultTy);
    case nonloc::LocAsIntegerKind: {
      Loc lhsL = cast<nonloc::LocAsInteger>(lhs).getLoc();
      switch (rhs.getSubKind()) {
        case nonloc::LocAsIntegerKind:
          return evalBinOpLL(state, op, lhsL,
                             cast<nonloc::LocAsInteger>(rhs).getLoc(),
                             resultTy);
        case nonloc::ConcreteIntKind: {
          // Transform the integer into a location and compare.
          llvm::APSInt i = cast<nonloc::ConcreteInt>(rhs).getValue();
          i.setIsUnsigned(true);
          i = i.extOrTrunc(Context.getTypeSize(Context.VoidPtrTy));
          return evalBinOpLL(state, op, lhsL, makeLoc(i), resultTy);
        }
        default:
          switch (op) {
            case BO_EQ:
              return makeTruthVal(false, resultTy);
            case BO_NE:
              return makeTruthVal(true, resultTy);
            default:
              // This case also handles pointer arithmetic.
              return generateUnknownVal(state, op, lhs, rhs, resultTy);
          }
      }
    }
    case nonloc::SymExprValKind: {
      nonloc::SymExprVal *selhs = cast<nonloc::SymExprVal>(&lhs);

      // Only handle LHS of the form "$sym op constant", at least for now.
      const SymIntExpr *symIntExpr =
        dyn_cast<SymIntExpr>(selhs->getSymbolicExpression());

      if (!symIntExpr)
        return generateUnknownVal(state, op, lhs, rhs, resultTy);

      // Is this a logical not? (!x is represented as x == 0.)
      if (op == BO_EQ && rhs.isZeroConstant()) {
        // We know how to negate certain expressions. Simplify them here.

        BinaryOperator::Opcode opc = symIntExpr->getOpcode();
        switch (opc) {
        default:
          // We don't know how to negate this operation.
          // Just handle it as if it were a normal comparison to 0.
          break;
        case BO_LAnd:
        case BO_LOr:
          llvm_unreachable("Logical operators handled by branching logic.");
        case BO_Assign:
        case BO_MulAssign:
        case BO_DivAssign:
        case BO_RemAssign:
        case BO_AddAssign:
        case BO_SubAssign:
        case BO_ShlAssign:
        case BO_ShrAssign:
        case BO_AndAssign:
        case BO_XorAssign:
        case BO_OrAssign:
        case BO_Comma:
          llvm_unreachable("'=' and ',' operators handled by ExprEngine.");
        case BO_PtrMemD:
        case BO_PtrMemI:
          llvm_unreachable("Pointer arithmetic not handled here.");
        case BO_LT:
        case BO_GT:
        case BO_LE:
        case BO_GE:
        case BO_EQ:
        case BO_NE:
          // Negate the comparison and make a value.
          opc = NegateComparison(opc);
          assert(symIntExpr->getType(Context) == resultTy);
          return makeNonLoc(symIntExpr->getLHS(), opc,
                                   symIntExpr->getRHS(), resultTy);
        }
      }

      // For now, only handle expressions whose RHS is a constant.
      const nonloc::ConcreteInt *rhsInt = dyn_cast<nonloc::ConcreteInt>(&rhs);
      if (!rhsInt)
        return generateUnknownVal(state, op, lhs, rhs, resultTy);

      // If both the LHS and the current expression are additive,
      // fold their constants.
      if (BinaryOperator::isAdditiveOp(op)) {
        BinaryOperator::Opcode lop = symIntExpr->getOpcode();
        if (BinaryOperator::isAdditiveOp(lop)) {
          // resultTy may not be the best type to convert to, but it's
          // probably the best choice in expressions with mixed type
          // (such as x+1U+2LL). The rules for implicit conversions should
          // choose a reasonable type to preserve the expression, and will
          // at least match how the value is going to be used.
          const llvm::APSInt &first =
            BasicVals.Convert(resultTy, symIntExpr->getRHS());
          const llvm::APSInt &second =
            BasicVals.Convert(resultTy, rhsInt->getValue());
          const llvm::APSInt *newRHS;
          if (lop == op)
            newRHS = BasicVals.evalAPSInt(BO_Add, first, second);
          else
            newRHS = BasicVals.evalAPSInt(BO_Sub, first, second);
          return MakeSymIntVal(symIntExpr->getLHS(), lop, *newRHS, resultTy);
        }
      }

      // Otherwise, make a SymExprVal out of the expression.
      return MakeSymIntVal(symIntExpr, op, rhsInt->getValue(), resultTy);
    }
    case nonloc::ConcreteIntKind: {
      const nonloc::ConcreteInt& lhsInt = cast<nonloc::ConcreteInt>(lhs);

      // Is the RHS a symbol we can simplify?
      // FIXME: This was mostly copy/pasted from the LHS-is-a-symbol case.
      if (const nonloc::SymbolVal *srhs = dyn_cast<nonloc::SymbolVal>(&rhs)) {
        SymbolRef RSym = srhs->getSymbol();
        if (RSym->getType(Context)->isIntegerType()) {
          if (const llvm::APSInt *Constant = state->getSymVal(RSym)) {
            // The symbol evaluates to a constant.
            const llvm::APSInt *rhs_I;
            if (BinaryOperator::isRelationalOp(op))
              rhs_I = &BasicVals.Convert(lhsInt.getValue(), *Constant);
            else
              rhs_I = &BasicVals.Convert(resultTy, *Constant);

            rhs = nonloc::ConcreteInt(*rhs_I);
          }
        }
      }

      if (isa<nonloc::ConcreteInt>(rhs)) {
        return lhsInt.evalBinOp(*this, op, cast<nonloc::ConcreteInt>(rhs));
      } else {
        const llvm::APSInt& lhsValue = lhsInt.getValue();
        
        // Swap the left and right sides and flip the operator if doing so
        // allows us to better reason about the expression (this is a form
        // of expression canonicalization).
        // While we're at it, catch some special cases for non-commutative ops.
        NonLoc tmp = rhs;
        rhs = lhs;
        lhs = tmp;

        switch (op) {
          case BO_LT:
          case BO_GT:
          case BO_LE:
          case BO_GE:
            op = ReverseComparison(op);
            continue;
          case BO_EQ:
          case BO_NE:
          case BO_Add:
          case BO_Mul:
          case BO_And:
          case BO_Xor:
          case BO_Or:
            continue;
          case BO_Shr:
            if (lhsValue.isAllOnesValue() && lhsValue.isSigned())
              // At this point lhs and rhs have been swapped.
              return rhs;
            // FALL-THROUGH
          case BO_Shl:
            if (lhsValue == 0)
              // At this point lhs and rhs have been swapped.
              return rhs;
            return generateUnknownVal(state, op, lhs, rhs, resultTy);
          default:
            return generateUnknownVal(state, op, lhs, rhs, resultTy);
        }
      }
    }
    case nonloc::SymbolValKind: {
      nonloc::SymbolVal *slhs = cast<nonloc::SymbolVal>(&lhs);
      SymbolRef Sym = slhs->getSymbol();
      QualType lhsType = Sym->getType(Context);

      // The conversion type is usually the result type, but not in the case
      // of relational expressions.
      QualType conversionType = resultTy;
      if (BinaryOperator::isRelationalOp(op))
        conversionType = lhsType;

      // Does the symbol simplify to a constant?  If so, "fold" the constant
      // by setting 'lhs' to a ConcreteInt and try again.
      if (lhsType->isIntegerType())
        if (const llvm::APSInt *Constant = state->getSymVal(Sym)) {
          // The symbol evaluates to a constant. If necessary, promote the
          // folded constant (LHS) to the result type.
          const llvm::APSInt &lhs_I = BasicVals.Convert(conversionType,
                                                        *Constant);
          lhs = nonloc::ConcreteInt(lhs_I);
          
          // Also promote the RHS (if necessary).

          // For shifts, it is not necessary to promote the RHS.
          if (BinaryOperator::isShiftOp(op))
            continue;
          
          // Other operators: do an implicit conversion.  This shouldn't be
          // necessary once we support truncation/extension of symbolic values.
          if (nonloc::ConcreteInt *rhs_I = dyn_cast<nonloc::ConcreteInt>(&rhs)){
            rhs = nonloc::ConcreteInt(BasicVals.Convert(conversionType,
                                                        rhs_I->getValue()));
          }
          
          continue;
        }

      // Is the RHS a symbol we can simplify?
      if (const nonloc::SymbolVal *srhs = dyn_cast<nonloc::SymbolVal>(&rhs)) {
        SymbolRef RSym = srhs->getSymbol();
        if (RSym->getType(Context)->isIntegerType()) {
          if (const llvm::APSInt *Constant = state->getSymVal(RSym)) {
            // The symbol evaluates to a constant.
            const llvm::APSInt &rhs_I = BasicVals.Convert(conversionType,
                                                          *Constant);
            rhs = nonloc::ConcreteInt(rhs_I);
          }
        }
      }

      if (isa<nonloc::ConcreteInt>(rhs)) {
        return MakeSymIntVal(slhs->getSymbol(), op,
                             cast<nonloc::ConcreteInt>(rhs).getValue(),
                             resultTy);
      }

      return generateUnknownVal(state, op, lhs, rhs, resultTy);
    }
    }
  }
}
Пример #12
0
/// Create a fake body for dispatch_once.
static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
  // Check if we have at least two parameters.
  if (D->param_size() != 2)
    return nullptr;

  // Check if the first parameter is a pointer to integer type.
  const ParmVarDecl *Predicate = D->getParamDecl(0);
  QualType PredicateQPtrTy = Predicate->getType();
  const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>();
  if (!PredicatePtrTy)
    return nullptr;
  QualType PredicateTy = PredicatePtrTy->getPointeeType();
  if (!PredicateTy->isIntegerType())
    return nullptr;

  // Check if the second parameter is the proper block type.
  const ParmVarDecl *Block = D->getParamDecl(1);
  QualType Ty = Block->getType();
  if (!isDispatchBlock(Ty))
    return nullptr;

  // Everything checks out.  Create a fakse body that checks the predicate,
  // sets it, and calls the block.  Basically, an AST dump of:
  //
  // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) {
  //  if (*predicate != ~0l) {
  //    *predicate = ~0l;
  //    block();
  //  }
  // }

  ASTMaker M(C);

  // (1) Create the call.
  CallExpr *CE = CallExpr::Create(
      /*ASTContext=*/C,
      /*StmtClass=*/M.makeLvalueToRvalue(/*Expr=*/Block),
      /*args=*/None,
      /*QualType=*/C.VoidTy,
      /*ExprValueType=*/VK_RValue,
      /*SourceLocation=*/SourceLocation());

  // (2) Create the assignment to the predicate.
  Expr *DoneValue =
      new (C) UnaryOperator(M.makeIntegerLiteral(0, C.LongTy), UO_Not, C.LongTy,
                            VK_RValue, OK_Ordinary, SourceLocation(),
                            /*CanOverflow*/false);

  BinaryOperator *B =
    M.makeAssignment(
       M.makeDereference(
          M.makeLvalueToRvalue(
            M.makeDeclRefExpr(Predicate), PredicateQPtrTy),
            PredicateTy),
       M.makeIntegralCast(DoneValue, PredicateTy),
       PredicateTy);

  // (3) Create the compound statement.
  Stmt *Stmts[] = { B, CE };
  CompoundStmt *CS = M.makeCompound(Stmts);

  // (4) Create the 'if' condition.
  ImplicitCastExpr *LValToRval =
    M.makeLvalueToRvalue(
      M.makeDereference(
        M.makeLvalueToRvalue(
          M.makeDeclRefExpr(Predicate),
          PredicateQPtrTy),
        PredicateTy),
    PredicateTy);

  Expr *GuardCondition = M.makeComparison(LValToRval, DoneValue, BO_NE);
  // (5) Create the 'if' statement.
  auto *If = IfStmt::Create(C, SourceLocation(),
                            /* IsConstexpr=*/false,
                            /* init=*/nullptr,
                            /* var=*/nullptr,
                            /* cond=*/GuardCondition,
                            /* then=*/CS);
  return If;
}
Пример #13
0
void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
                                           const Decl *TargetDecl,
                                           AttributeListType &PAL, 
                                           unsigned &CallingConv) {
  unsigned FuncAttrs = 0;
  unsigned RetAttrs = 0;

  CallingConv = FI.getEffectiveCallingConvention();

  // FIXME: handle sseregparm someday...
  if (TargetDecl) {
    if (TargetDecl->hasAttr<NoThrowAttr>())
      FuncAttrs |= llvm::Attribute::NoUnwind;
    if (TargetDecl->hasAttr<NoReturnAttr>())
      FuncAttrs |= llvm::Attribute::NoReturn;
    if (TargetDecl->hasAttr<ConstAttr>())
      FuncAttrs |= llvm::Attribute::ReadNone;
    else if (TargetDecl->hasAttr<PureAttr>())
      FuncAttrs |= llvm::Attribute::ReadOnly;
    if (TargetDecl->hasAttr<MallocAttr>())
      RetAttrs |= llvm::Attribute::NoAlias;
  }

  if (CodeGenOpts.OptimizeSize)
    FuncAttrs |= llvm::Attribute::OptimizeForSize;
  if (CodeGenOpts.DisableRedZone)
    FuncAttrs |= llvm::Attribute::NoRedZone;
  if (CodeGenOpts.NoImplicitFloat)
    FuncAttrs |= llvm::Attribute::NoImplicitFloat;

  QualType RetTy = FI.getReturnType();
  unsigned Index = 1;
  const ABIArgInfo &RetAI = FI.getReturnInfo();
  switch (RetAI.getKind()) {
  case ABIArgInfo::Extend:
   if (RetTy->isSignedIntegerType()) {
     RetAttrs |= llvm::Attribute::SExt;
   } else if (RetTy->isUnsignedIntegerType()) {
     RetAttrs |= llvm::Attribute::ZExt;
   }
   // FALLTHROUGH
  case ABIArgInfo::Direct:
    break;

  case ABIArgInfo::Indirect:
    PAL.push_back(llvm::AttributeWithIndex::get(Index,
                                                llvm::Attribute::StructRet |
                                                llvm::Attribute::NoAlias));
    ++Index;
    // sret disables readnone and readonly
    FuncAttrs &= ~(llvm::Attribute::ReadOnly |
                   llvm::Attribute::ReadNone);
    break;

  case ABIArgInfo::Ignore:
  case ABIArgInfo::Coerce:
    break;

  case ABIArgInfo::Expand:
    assert(0 && "Invalid ABI kind for return argument");
  }

  if (RetAttrs)
    PAL.push_back(llvm::AttributeWithIndex::get(0, RetAttrs));

  // FIXME: we need to honour command line settings also...
  // FIXME: RegParm should be reduced in case of nested functions and/or global
  // register variable.
  signed RegParm = 0;
  if (TargetDecl)
    if (const RegparmAttr *RegParmAttr
          = TargetDecl->getAttr<RegparmAttr>())
      RegParm = RegParmAttr->getNumParams();

  unsigned PointerWidth = getContext().Target.getPointerWidth(0);
  for (CGFunctionInfo::const_arg_iterator it = FI.arg_begin(),
         ie = FI.arg_end(); it != ie; ++it) {
    QualType ParamType = it->type;
    const ABIArgInfo &AI = it->info;
    unsigned Attributes = 0;

    switch (AI.getKind()) {
    case ABIArgInfo::Coerce:
      break;

    case ABIArgInfo::Indirect:
      if (AI.getIndirectByVal())
        Attributes |= llvm::Attribute::ByVal;

      Attributes |=
        llvm::Attribute::constructAlignmentFromInt(AI.getIndirectAlign());
      // byval disables readnone and readonly.
      FuncAttrs &= ~(llvm::Attribute::ReadOnly |
                     llvm::Attribute::ReadNone);
      break;

    case ABIArgInfo::Extend:
     if (ParamType->isSignedIntegerType()) {
       Attributes |= llvm::Attribute::SExt;
     } else if (ParamType->isUnsignedIntegerType()) {
       Attributes |= llvm::Attribute::ZExt;
     }
     // FALLS THROUGH
    case ABIArgInfo::Direct:
      if (RegParm > 0 &&
          (ParamType->isIntegerType() || ParamType->isPointerType())) {
        RegParm -=
          (Context.getTypeSize(ParamType) + PointerWidth - 1) / PointerWidth;
        if (RegParm >= 0)
          Attributes |= llvm::Attribute::InReg;
      }
      // FIXME: handle sseregparm someday...
      break;

    case ABIArgInfo::Ignore:
      // Skip increment, no matching LLVM parameter.
      continue;

    case ABIArgInfo::Expand: {
      std::vector<const llvm::Type*> Tys;
      // FIXME: This is rather inefficient. Do we ever actually need to do
      // anything here? The result should be just reconstructed on the other
      // side, so extension should be a non-issue.
      getTypes().GetExpandedTypes(ParamType, Tys);
      Index += Tys.size();
      continue;
    }
    }

    if (Attributes)
      PAL.push_back(llvm::AttributeWithIndex::get(Index, Attributes));
    ++Index;
  }
  if (FuncAttrs)
    PAL.push_back(llvm::AttributeWithIndex::get(~0, FuncAttrs));
}
Пример #14
0
/// \brief Build an Objective-C instance message expression.
///
/// This routine takes care of both normal instance messages and
/// instance messages to the superclass instance.
///
/// \param Receiver The expression that computes the object that will
/// receive this message. This may be empty, in which case we are
/// sending to the superclass instance and \p SuperLoc must be a valid
/// source location.
///
/// \param ReceiverType The (static) type of the object receiving the
/// message. When a \p Receiver expression is provided, this is the
/// same type as that expression. For a superclass instance send, this
/// is a pointer to the type of the superclass.
///
/// \param SuperLoc The location of the "super" keyword in a
/// superclass instance message.
///
/// \param Sel The selector to which the message is being sent.
///
/// \param Method The method that this instance message is invoking, if
/// already known.
///
/// \param LBracLoc The location of the opening square bracket ']'.
///
/// \param RBrac The location of the closing square bracket ']'.
///
/// \param Args The message arguments.
Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE,
                                                  QualType ReceiverType,
                                                  SourceLocation SuperLoc,
                                                  Selector Sel,
                                                  ObjCMethodDecl *Method,
                                                  SourceLocation LBracLoc, 
                                                  SourceLocation RBracLoc,
                                                  MultiExprArg ArgsIn) {
  // If we have a receiver expression, perform appropriate promotions
  // and determine receiver type.
  Expr *Receiver = ReceiverE.takeAs<Expr>();
  if (Receiver) {
    if (Receiver->isTypeDependent()) {
      // If the receiver is type-dependent, we can't type-check anything
      // at this point. Build a dependent expression.
      unsigned NumArgs = ArgsIn.size();
      Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
      assert(SuperLoc.isInvalid() && "Message to super with dependent type");
      return Owned(ObjCMessageExpr::Create(Context, Context.DependentTy,
                                           LBracLoc, Receiver, Sel, 
                                           /*Method=*/0, Args, NumArgs, 
                                           RBracLoc));
    }

    // If necessary, apply function/array conversion to the receiver.
    // C99 6.7.5.3p[7,8].
    DefaultFunctionArrayLvalueConversion(Receiver);
    ReceiverType = Receiver->getType();
  }

  // The location of the receiver.
  SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();

  if (!Method) {
    // Handle messages to id.
    bool receiverIsId = ReceiverType->isObjCIdType();
    if (receiverIsId || ReceiverType->isBlockPointerType() ||
        (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) {
      Method = LookupInstanceMethodInGlobalPool(Sel, 
                                                SourceRange(LBracLoc, RBracLoc),
                                                receiverIsId);
      if (!Method)
        Method = LookupFactoryMethodInGlobalPool(Sel, 
                                                 SourceRange(LBracLoc, RBracLoc),
                                                 receiverIsId);
    } else if (ReceiverType->isObjCClassType() ||
               ReceiverType->isObjCQualifiedClassType()) {
      // Handle messages to Class.
      if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) {
        if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) {
          // First check the public methods in the class interface.
          Method = ClassDecl->lookupClassMethod(Sel);

          if (!Method)
            Method = LookupPrivateClassMethod(Sel, ClassDecl);

          // FIXME: if we still haven't found a method, we need to look in
          // protocols (if we have qualifiers).
        }
        if (Method && DiagnoseUseOfDecl(Method, Loc))
          return ExprError();
      }
      if (!Method) {
        // If not messaging 'self', look for any factory method named 'Sel'.
        if (!Receiver || !isSelfExpr(Receiver)) {
          Method = LookupFactoryMethodInGlobalPool(Sel, 
                                               SourceRange(LBracLoc, RBracLoc),
                                                   true);
          if (!Method) {
            // If no class (factory) method was found, check if an _instance_
            // method of the same name exists in the root class only.
            Method = LookupInstanceMethodInGlobalPool(Sel,
                                               SourceRange(LBracLoc, RBracLoc),
                                                      true);
            if (Method)
                if (const ObjCInterfaceDecl *ID =
                  dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
                if (ID->getSuperClass())
                  Diag(Loc, diag::warn_root_inst_method_not_found)
                    << Sel << SourceRange(LBracLoc, RBracLoc);
              }
          }
        }
      }
    } else {
      ObjCInterfaceDecl* ClassDecl = 0;

      // We allow sending a message to a qualified ID ("id<foo>"), which is ok as
      // long as one of the protocols implements the selector (if not, warn).
      if (const ObjCObjectPointerType *QIdTy 
                                   = ReceiverType->getAsObjCQualifiedIdType()) {
        // Search protocols for instance methods.
        for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(),
               E = QIdTy->qual_end(); I != E; ++I) {
          ObjCProtocolDecl *PDecl = *I;
          if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel)))
            break;
          // Since we aren't supporting "Class<foo>", look for a class method.
          if (PDecl && (Method = PDecl->lookupClassMethod(Sel)))
            break;
        }
      } else if (const ObjCObjectPointerType *OCIType
                   = ReceiverType->getAsObjCInterfacePointerType()) {
        // We allow sending a message to a pointer to an interface (an object).
        ClassDecl = OCIType->getInterfaceDecl();
        // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be
        // faster than the following method (which can do *many* linear searches).
        // The idea is to add class info to MethodPool.
        Method = ClassDecl->lookupInstanceMethod(Sel);

        if (!Method) {
          // Search protocol qualifiers.
          for (ObjCObjectPointerType::qual_iterator QI = OCIType->qual_begin(),
                 E = OCIType->qual_end(); QI != E; ++QI) {
            if ((Method = (*QI)->lookupInstanceMethod(Sel)))
              break;
          }
        }
        if (!Method) {
          // If we have implementations in scope, check "private" methods.
          Method = LookupPrivateInstanceMethod(Sel, ClassDecl);

          if (!Method && (!Receiver || !isSelfExpr(Receiver))) {
            // If we still haven't found a method, look in the global pool. This
            // behavior isn't very desirable, however we need it for GCC
            // compatibility. FIXME: should we deviate??
            if (OCIType->qual_empty()) {
              Method = LookupInstanceMethodInGlobalPool(Sel,
                                                 SourceRange(LBracLoc, RBracLoc)); 
              if (Method && !OCIType->getInterfaceDecl()->isForwardDecl())
                Diag(Loc, diag::warn_maynot_respond)
                  << OCIType->getInterfaceDecl()->getIdentifier() << Sel;
            }
          }
        }
        if (Method && DiagnoseUseOfDecl(Method, Loc))
          return ExprError();
      } else if (!Context.getObjCIdType().isNull() &&
                 (ReceiverType->isPointerType() || 
                  ReceiverType->isIntegerType())) {
        // Implicitly convert integers and pointers to 'id' but emit a warning.
        Diag(Loc, diag::warn_bad_receiver_type)
          << ReceiverType 
          << Receiver->getSourceRange();
        if (ReceiverType->isPointerType())
          ImpCastExprToType(Receiver, Context.getObjCIdType(), 
                            CastExpr::CK_BitCast);
        else
          ImpCastExprToType(Receiver, Context.getObjCIdType(),
                            CastExpr::CK_IntegralToPointer);
        ReceiverType = Receiver->getType();
      } 
      else if (getLangOptions().CPlusPlus &&
               !PerformContextuallyConvertToObjCId(Receiver)) {
        if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Receiver)) {
          Receiver = ICE->getSubExpr();
          ReceiverType = Receiver->getType();
        }
        return BuildInstanceMessage(Owned(Receiver),
                                    ReceiverType,
                                    SuperLoc,
                                    Sel,
                                    Method,
                                    LBracLoc, 
                                    RBracLoc,
                                    move(ArgsIn));
      } else {
        // Reject other random receiver types (e.g. structs).
        Diag(Loc, diag::err_bad_receiver_type)
          << ReceiverType << Receiver->getSourceRange();
        return ExprError();
      }
    }
  }

  // Check the message arguments.
  unsigned NumArgs = ArgsIn.size();
  Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release());
  QualType ReturnType;
  if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, false,
                                LBracLoc, RBracLoc, ReturnType))
    return ExprError();
  
  if (!ReturnType->isVoidType()) {
    if (RequireCompleteType(LBracLoc, ReturnType, 
                            diag::err_illegal_message_expr_incomplete_type))
      return ExprError();
  }

  // Construct the appropriate ObjCMessageExpr instance.
  Expr *Result;
  if (SuperLoc.isValid())
    Result = ObjCMessageExpr::Create(Context, ReturnType, LBracLoc,
                                     SuperLoc,  /*IsInstanceSuper=*/true,
                                     ReceiverType, Sel, Method, 
                                     Args, NumArgs, RBracLoc);
  else
    Result = ObjCMessageExpr::Create(Context, ReturnType, LBracLoc, Receiver, 
                                     Sel, Method, Args, NumArgs, RBracLoc);
  return MaybeBindToTemporary(Result);
}