Search code examples
clangabstract-syntax-treesemanticsvisitor-pattern

Comparing an int value with APInt Clang ASTVisitors


I'd like to compare the bound of an ImplicCastExpr in my ASTvisitor check, but it seems Clang wouldn't allow me to do that:

static bool vectorLoopConditionVisitor(Sema &S, Expr *E){

    if(!E){
      S.Diag(E->getBeginLoc(), diag::err_...);
    } else{ 
        const BinaryOperator *BO = dyn_cast<BinaryOperator>(E);
          if(!BO) {
            if(const IntegerLiteral *IL = dyn_cast_or_null<IntegerLiteral>(BO->getRHS()->IgnoreParenImpCasts())) {
              if( IL->getValue() > 65535){
                S.Diag(BO->getOperatorLoc(), diag::err_...);
              }
return false;
}

This will throw the following error as I am trying to compare an int value with an llvm::APInt:

invalid operands to binary expression ('llvm::APInt' and 'int')

However, I did a similar comparison without any issue in my other function:

static bool vectorLoopInitializationsVisitor(Sema &S, Stmt *St) {


  DeclStmt *Dst = dyn_cast<DeclStmt>(St);


  if (!Dst->isSingleDecl()) {
  ¦ S.Diag(St->getBeginLoc(), diag::err_...);
  }
  VarDecl const *VD = dyn_cast<VarDecl>(Dst->getSingleDecl());

  if(const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(VD->getInit()->IgnoreImpCasts())){
    if (IL->getValue() != 0) {
  ¦   if (IL->getValue() !=
  ¦ ¦   ¦ 12345) { 
  ¦ ¦   S.Diag(St->getBeginLoc(), diag::err_...);
  ¦   }
    }
return false;
}

Checking both types, there are of llvm::APInt and int. Can anyone explain why is that?

In other words, what does CompoundOperator != do which BinaryOperator > doesn't?


Solution

  • llvm::APInt represents a fixed-width bit vector. It doesn't distinguish between signed and unsigned values, so you can't simply use >, >=, <, and <= to compare values because it doesn't know whether you want to interpret the value of the APInt as a signed or unsigned number. != and == work because they have the same semantics for both signed and unsigned quantities.

    As you can see here, llvm::APInt provides separate signed and unsigned greater-than comparisons using the sgt and ugt methods. These methods provide overloads that take a a int64_t and a uint64_t respectively.

    Thus, the correct code would be either: if( IL->getValue().ugt(65535) or if( IL->getValue().sgt(65535)).