static bool pointedUnqualifiedTypesAreEqual(QualType T1, QualType T2) {
  while ((T1->isPointerType() && T2->isPointerType()) ||
         (T1->isReferenceType() && T2->isReferenceType())) {
    T1 = T1->getPointeeType();
    T2 = T2->getPointeeType();
  }
  return T1.getUnqualifiedType() == T2.getUnqualifiedType();
}
bool pointedTypesAreEqual(QualType SourceType, QualType DestType) {
  SourceType = SourceType.getNonReferenceType();
  DestType = DestType.getNonReferenceType();
  while (SourceType->isPointerType() && DestType->isPointerType()) {
    SourceType = SourceType->getPointeeType();
    DestType = DestType->getPointeeType();
  }
  return SourceType.getUnqualifiedType() == DestType.getUnqualifiedType();
}
bool needsConstCast(QualType SourceType, QualType DestType) {
  SourceType = SourceType.getNonReferenceType();
  DestType = DestType.getNonReferenceType();
  while (SourceType->isPointerType() && DestType->isPointerType()) {
    SourceType = SourceType->getPointeeType();
    DestType = DestType->getPointeeType();
    if (SourceType.isConstQualified() && !DestType.isConstQualified())
      return true;
  }
  return false;
}
static bool needsConstCast(QualType SourceType, QualType DestType) {
  while ((SourceType->isPointerType() && DestType->isPointerType()) ||
         (SourceType->isReferenceType() && DestType->isReferenceType())) {
    SourceType = SourceType->getPointeeType();
    DestType = DestType->getPointeeType();
    if (SourceType.isConstQualified() && !DestType.isConstQualified()) {
      return (SourceType->isPointerType() == DestType->isPointerType()) &&
             (SourceType->isReferenceType() == DestType->isReferenceType());
    }
  }
  return false;
}
Esempio n. 5
0
bool ExprTypeAnalyser::checkExplicitCast(const ExplicitCastExpr* expr, QualType DestType, QualType SrcType) {
    // C99 6.5.4p2: the cast type needs to be void or scalar and the expression

    if (!DestType.isScalarType()) {
        // Dont allow any cast to non-scalar
        StringBuilder buf1(MAX_LEN_TYPENAME);
        StringBuilder buf2(MAX_LEN_TYPENAME);
        DestType.DiagName(buf1);
        SrcType.DiagName(buf2);
        Diags.Report(expr->getLocation(), diag::err_typecheck_cond_expect_scalar)
                << buf1 << buf2 << expr->getSourceRange();
        return false;
    }

    // If either type is a pointer, the other type has to be either an
    // integer or a pointer
    // TODO decide if Enums are arithmatic types or not (they are in C99, not is C++0x)
    if (DestType.isPointerType()) {
        if (SrcType.isPointerType()) {
            // allow all pointer casts
            return true;
        } else {
            // only allow cast to pointer from uint32/64 (pointer size)
            const BuiltinType* BT = dyncast<BuiltinType>(SrcType.getCanonicalType());
            // TODO use TargetInfo to check if 32-bit
            if (BT && BT->getKind() == BuiltinType::UInt64) return true;

            QualType expected = Type::UInt64();
            StringBuilder buf1(MAX_LEN_TYPENAME);
            expected.DiagName(buf1);
            Diags.Report(expr->getLocation(), diag::err_cast_nonword_to_pointer) << buf1;
        }
    } else {
        if (SrcType.isPointerType()) {
            // only allow cast to uint32/64 (pointer size)
            const BuiltinType* BT = dyncast<BuiltinType>(DestType.getCanonicalType());
            // TODO use TargetInfo to check if 32-bit
            if (BT && BT->getKind() == BuiltinType::UInt64) return true;

            QualType expected = Type::UInt64();
            StringBuilder buf1(MAX_LEN_TYPENAME);
            expected.DiagName(buf1);
            Diags.Report(expr->getLocation(), diag::err_cast_pointer_to_nonword) << buf1;
        } else {
            // check non-pointer to non-pointer type
            // TODO make this top level function? (switch on src-type)
            return checkNonPointerCast(expr, DestType, SrcType);
        }
    }
    return false;
}
void FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
                                       CheckerContext &C) const {
  // Using a fixed address is not portable because that address will probably
  // not be valid in all environments or platforms.

  if (B->getOpcode() != BO_Assign)
    return;

  QualType T = B->getType();
  if (!T->isPointerType())
    return;

  SVal RV = C.getSVal(B->getRHS());

  if (!RV.isConstant() || RV.isZeroConstant())
    return;

  if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
    if (!BT)
      BT.reset(
          new BuiltinBug(this, "Use fixed address",
                         "Using a fixed address is not portable because that "
                         "address will probably not be valid in all "
                         "environments or platforms."));
    auto R = llvm::make_unique<BugReport>(*BT, BT->getDescription(), N);
    R->addRange(B->getRHS()->getSourceRange());
    C.emitReport(std::move(R));
  }
}
Esempio n. 7
0
void FixedAddressChecker::checkPreStmt(const BinaryOperator *B,
                                       CheckerContext &C) const {
  // Using a fixed address is not portable because that address will probably
  // not be valid in all environments or platforms.

  if (B->getOpcode() != BO_Assign)
    return;

  QualType T = B->getType();
  if (!T->isPointerType())
    return;

  ProgramStateRef state = C.getState();
  SVal RV = state->getSVal(B->getRHS(), C.getLocationContext());

  if (!RV.isConstant() || RV.isZeroConstant())
    return;

  if (ExplodedNode *N = C.addTransition()) {
    if (!BT)
      BT.reset(
          new BuiltinBug(this, "Use fixed address",
                         "Using a fixed address is not portable because that "
                         "address will probably not be valid in all "
                         "environments or platforms."));
    BugReport *R = new BugReport(*BT, BT->getDescription(), N);
    R->addRange(B->getRHS()->getSourceRange());
    C.emitReport(R);
  }
}
  ValuePrinterInfo::ValuePrinterInfo(Expr* E, ASTContext* Ctx)
    : m_Expr(E), m_Context(Ctx), m_Flags(0) {
    assert(E && "Expression cannot be null!");
    assert(Ctx && "ASTContext cannot be null!");
    // 1. Get the flags
    const QualType QT = m_Expr->getType();

    if (E->isRValue() || QT.isLocalConstQualified() || QT.isConstant(*Ctx)){
      m_Flags |= VPI_Const;
    }

    if (QT->isPointerType()) {
      // treat arrary-to-pointer decay as array:
      QualType PQT = QT->getPointeeType();
      const Type* PTT = PQT.getTypePtr();
      if (!PTT || !PTT->isArrayType()) {
        m_Flags |= VPI_Ptr;
        if (const RecordType* RT = dyn_cast<RecordType>(QT.getTypePtr()))
          if (RecordDecl* RD = RT->getDecl()) {
            CXXRecordDecl* CRD = dyn_cast<CXXRecordDecl>(RD);
            if (CRD && CRD->isPolymorphic())
              m_Flags |= VPI_Polymorphic;
          }
      }
    }
  }
Esempio n. 9
0
PathDiagnosticPiece *
ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
                                  const DeclRefExpr *DR,
                                  const bool tookTrue,
                                  BugReporterContext &BRC,
                                  const LocationContext *LC) {

    const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
    if (!VD)
        return 0;

    llvm::SmallString<256> Buf;
    llvm::raw_svector_ostream Out(Buf);

    Out << "Assuming '";
    VD->getDeclName().printName(Out);
    Out << "' is ";

    QualType VDTy = VD->getType();

    if (VDTy->isPointerType())
        Out << (tookTrue ? "non-null" : "null");
    else if (VDTy->isObjCObjectPointerType())
        Out << (tookTrue ? "non-nil" : "nil");
    else if (VDTy->isScalarType())
        Out << (tookTrue ? "not equal to 0" : "0");
    else
        return 0;

    PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LC);
    return new PathDiagnosticEventPiece(Loc, Out.str());
}
Esempio n. 10
0
// CWE-467: Use of sizeof() on a Pointer Type
void WalkAST::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
  if (!E->isSizeOf())
    return;

  // If an explicit type is used in the code, usually the coder knows what he is
  // doing.
  if (E->isArgumentType())
    return;

  QualType T = E->getTypeOfArgument();
  if (T->isPointerType()) {

    // Many false positives have the form 'sizeof *p'. This is reasonable 
    // because people know what they are doing when they intentionally 
    // dereference the pointer.
    Expr *ArgEx = E->getArgumentExpr();
    if (!isa<DeclRefExpr>(ArgEx->IgnoreParens()))
      return;

    SourceRange R = ArgEx->getSourceRange();
    BR.EmitBasicReport("Potential unintended use of sizeof() on pointer type",
                       "Logic",
                       "The code calls sizeof() on a pointer type. "
                       "This can produce an unexpected result.",
                       E->getLocStart(), &R, 1);
  }
}
Esempio n. 11
0
/// CastRetrievedVal - Used by subclasses of StoreManager to implement
///  implicit casts that arise from loads from regions that are reinterpreted
///  as another region.
SVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R,
                                    QualType castTy) {
  if (castTy.isNull() || V.isUnknownOrUndef())
    return V;

  // The dispatchCast() call below would convert the int into a float.
  // What we want, however, is a bit-by-bit reinterpretation of the int
  // as a float, which usually yields nothing garbage. For now skip casts
  // from ints to floats.
  // TODO: What other combinations of types are affected?
  if (castTy->isFloatingType()) {
    SymbolRef Sym = V.getAsSymbol();
    if (Sym && !Sym->getType()->isFloatingType())
      return UnknownVal();
  }

  // When retrieving symbolic pointer and expecting a non-void pointer,
  // wrap them into element regions of the expected type if necessary.
  // SValBuilder::dispatchCast() doesn't do that, but it is necessary to
  // make sure that the retrieved value makes sense, because there's no other
  // cast in the AST that would tell us to cast it to the correct pointer type.
  // We might need to do that for non-void pointers as well.
  // FIXME: We really need a single good function to perform casts for us
  // correctly every time we need it.
  if (castTy->isPointerType() && !castTy->isVoidPointerType())
    if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(V.getAsRegion()))
      if (SR->getSymbol()->getType().getCanonicalType() !=
          castTy.getCanonicalType())
        return loc::MemRegionVal(castRegion(SR, castTy));

  return svalBuilder.dispatchCast(V, castTy);
}
void FixedAddressChecker::PreVisitBinaryOperator(CheckerContext &C,
                                                 const BinaryOperator *B) {
  // Using a fixed address is not portable because that address will probably
  // not be valid in all environments or platforms.

  if (B->getOpcode() != BinaryOperator::Assign)
    return;

  QualType T = B->getType();
  if (!T->isPointerType())
    return;

  const GRState *state = C.getState();

  SVal RV = state->getSVal(B->getRHS());

  if (!RV.isConstant() || RV.isZeroConstant())
    return;

  if (ExplodedNode *N = C.GenerateNode()) {
    if (!BT)
      BT = new BuiltinBug("Use fixed address", 
                          "Using a fixed address is not portable because that "
                          "address will probably not be valid in all "
                          "environments or platforms.");
    RangedBugReport *R = new RangedBugReport(*BT, BT->getDescription(), N);
    R->addRange(B->getRHS()->getSourceRange());
    C.EmitReport(R);
  }
}
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
/// If there is already an implicit cast, merge into the existing one.
/// If isLvalue, the result of the cast is an lvalue.
void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
                             CastExpr::CastKind Kind, bool isLvalue) {
  QualType ExprTy = Context.getCanonicalType(Expr->getType());
  QualType TypeTy = Context.getCanonicalType(Ty);

  if (ExprTy == TypeTy)
    return;

  if (Expr->getType()->isPointerType() && Ty->isPointerType()) {
    QualType ExprBaseType = cast<PointerType>(ExprTy)->getPointeeType();
    QualType BaseType = cast<PointerType>(TypeTy)->getPointeeType();
    if (ExprBaseType.getAddressSpace() != BaseType.getAddressSpace()) {
      Diag(Expr->getExprLoc(), diag::err_implicit_pointer_address_space_cast)
        << Expr->getSourceRange();
    }
  }

  CheckImplicitConversion(Expr, Ty);

  if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) {
    if (ImpCast->getCastKind() == Kind) {
      ImpCast->setType(Ty);
      ImpCast->setLvalueCast(isLvalue);
      return;
    }
  }

  Expr = new (Context) ImplicitCastExpr(Ty, Kind, Expr, isLvalue);
}
Esempio n. 14
0
// CWE-467: Use of sizeof() on a Pointer Type
void WalkAST::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) {
    if (E->getKind() != UETT_SizeOf)
        return;

    // If an explicit type is used in the code, usually the coder knows what he is
    // doing.
    if (E->isArgumentType())
        return;

    QualType T = E->getTypeOfArgument();
    if (T->isPointerType()) {

        // Many false positives have the form 'sizeof *p'. This is reasonable
        // because people know what they are doing when they intentionally
        // dereference the pointer.
        Expr *ArgEx = E->getArgumentExpr();
        if (!isa<DeclRefExpr>(ArgEx->IgnoreParens()))
            return;

        PathDiagnosticLocation ELoc =
            PathDiagnosticLocation::createBegin(E, BR.getSourceManager(), AC);
        BR.EmitBasicReport(AC->getDecl(), Checker,
                           "Potential unintended use of sizeof() on pointer type",
                           categories::LogicError,
                           "The code calls sizeof() on a pointer type. "
                           "This can produce an unexpected result.",
                           ELoc, ArgEx->getSourceRange());
    }
}
void NonConstParameterCheck::check(const MatchFinder::MatchResult &Result) {
  if (const auto *Parm = Result.Nodes.getNodeAs<ParmVarDecl>("Parm")) {
    if (const DeclContext *D = Parm->getParentFunctionOrMethod()) {
      if (const auto *M = dyn_cast<CXXMethodDecl>(D)) {
        if (M->isVirtual() || M->size_overridden_methods() != 0)
          return;
      }
    }
    addParm(Parm);
  } else if (const auto *Ctor =
                 Result.Nodes.getNodeAs<CXXConstructorDecl>("Ctor")) {
    for (const auto *Parm : Ctor->parameters())
      addParm(Parm);
    for (const auto *Init : Ctor->inits())
      markCanNotBeConst(Init->getInit(), true);
  } else if (const auto *Ref = Result.Nodes.getNodeAs<DeclRefExpr>("Ref")) {
    setReferenced(Ref);
  } else if (const auto *S = Result.Nodes.getNodeAs<Stmt>("Mark")) {
    if (const auto *B = dyn_cast<BinaryOperator>(S)) {
      if (B->isAssignmentOp())
        markCanNotBeConst(B, false);
    } else if (const auto *CE = dyn_cast<CallExpr>(S)) {
      // Typically, if a parameter is const then it is fine to make the data
      // const. But sometimes the data is written even though the parameter
      // is const. Mark all data passed by address to the function.
      for (const auto *Arg : CE->arguments()) {
        markCanNotBeConst(Arg->IgnoreParenCasts(), true);
      }

      // Data passed by nonconst reference should not be made const.
      if (const FunctionDecl *FD = CE->getDirectCallee()) {
        unsigned ArgNr = 0U;
        for (const auto *Par : FD->parameters()) {
          if (ArgNr >= CE->getNumArgs())
            break;
          const Expr *Arg = CE->getArg(ArgNr++);
          // Is this a non constant reference parameter?
          const Type *ParType = Par->getType().getTypePtr();
          if (!ParType->isReferenceType() || Par->getType().isConstQualified())
            continue;
          markCanNotBeConst(Arg->IgnoreParenCasts(), false);
        }
      }
    } else if (const auto *CE = dyn_cast<CXXConstructExpr>(S)) {
      for (const auto *Arg : CE->arguments()) {
        markCanNotBeConst(Arg->IgnoreParenCasts(), true);
      }
    } else if (const auto *R = dyn_cast<ReturnStmt>(S)) {
      markCanNotBeConst(R->getRetValue(), true);
    } else if (const auto *U = dyn_cast<UnaryOperator>(S)) {
      markCanNotBeConst(U, true);
    }
  } else if (const auto *VD = Result.Nodes.getNodeAs<VarDecl>("Mark")) {
    const QualType T = VD->getType();
    if ((T->isPointerType() && !T->getPointeeType().isConstQualified()) ||
        T->isArrayType())
      markCanNotBeConst(VD->getInit(), true);
  }
}
Esempio n. 16
0
bool ExprTypeAnalyser::checkPointer(QualType left, QualType right, const Expr* expr) const {
    if (right->isPointerType()) {
        // TODO
        return true;
    }
    if (right->isArrayType()) {
        // TODO
        return true;
    }
    error(expr->getLocation(), left, right);
    return false;
}
Esempio n. 17
0
bool ConditionBRVisitor::patternMatch(const Expr *Ex, raw_ostream &Out,
                                      BugReporterContext &BRC,
                                      BugReport &report,
                                      const ExplodedNode *N,
                                      Optional<bool> &prunable) {
  const Expr *OriginalExpr = Ex;
  Ex = Ex->IgnoreParenCasts();

  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) {
    const bool quotes = isa<VarDecl>(DR->getDecl());
    if (quotes) {
      Out << '\'';
      const LocationContext *LCtx = N->getLocationContext();
      const ProgramState *state = N->getState().getPtr();
      if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
                                                LCtx).getAsRegion()) {
        if (report.isInteresting(R))
          prunable = false;
        else {
          const ProgramState *state = N->getState().getPtr();
          SVal V = state->getSVal(R);
          if (report.isInteresting(V))
            prunable = false;
        }
      }
    }
    Out << DR->getDecl()->getDeclName().getAsString();
    if (quotes)
      Out << '\'';
    return quotes;
  }
  
  if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) {
    QualType OriginalTy = OriginalExpr->getType();
    if (OriginalTy->isPointerType()) {
      if (IL->getValue() == 0) {
        Out << "null";
        return false;
      }
    }
    else if (OriginalTy->isObjCObjectPointerType()) {
      if (IL->getValue() == 0) {
        Out << "nil";
        return false;
      }
    }
    
    Out << IL->getValue();
    return false;
  }
  
  return false;
}
Esempio n. 18
0
/// CastsAwayConstness - Check if the pointer conversion from SrcType to
/// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by
/// the cast checkers.  Both arguments must denote pointer (possibly to member)
/// types.
bool
CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType)
{
  // Casting away constness is defined in C++ 5.2.11p8 with reference to
  // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since
  // the rules are non-trivial. So first we construct Tcv *...cv* as described
  // in C++ 5.2.11p8.
  assert((SrcType->isPointerType() || SrcType->isMemberPointerType()) &&
         "Source type is not pointer or pointer to member.");
  assert((DestType->isPointerType() || DestType->isMemberPointerType()) &&
         "Destination type is not pointer or pointer to member.");

  QualType UnwrappedSrcType = SrcType, UnwrappedDestType = DestType;
  llvm::SmallVector<unsigned, 8> cv1, cv2;

  // Find the qualifications.
  while (Self.UnwrapSimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
    cv1.push_back(UnwrappedSrcType.getCVRQualifiers());
    cv2.push_back(UnwrappedDestType.getCVRQualifiers());
  }
  assert(cv1.size() > 0 && "Must have at least one pointer level.");

  // Construct void pointers with those qualifiers (in reverse order of
  // unwrapping, of course).
  QualType SrcConstruct = Self.Context.VoidTy;
  QualType DestConstruct = Self.Context.VoidTy;
  for (llvm::SmallVector<unsigned, 8>::reverse_iterator i1 = cv1.rbegin(),
                                                        i2 = cv2.rbegin();
       i1 != cv1.rend(); ++i1, ++i2)
  {
    SrcConstruct = Self.Context.getPointerType(
      SrcConstruct.getQualifiedType(*i1));
    DestConstruct = Self.Context.getPointerType(
      DestConstruct.getQualifiedType(*i2));
  }

  // Test if they're compatible.
  return SrcConstruct != DestConstruct &&
    !Self.IsQualificationConversion(SrcConstruct, DestConstruct);
}
Esempio n. 19
0
// Check if type is a "Field() *" pointer type, or alternatively a pointer to
// any type in "alt" if provided.
bool CheckAllocationsInFunctionVisitor::IsFieldPointer(
    const QualType& qtype, const char* alt)
{
    if (qtype->isPointerType())
    {
        auto name = qtype->getPointeeType()
            .getDesugaredType(_mainVisitor->getContext()).getAsString();
        return StartsWith(name, "class Memory::WriteBarrierPtr<")
            || StartsWith(name, "typename WriteBarrierFieldTypeTraits<")
            || (alt && strstr(alt, name.c_str()));
    }

    return false;
}
void NonConstParameterCheck::addParm(const ParmVarDecl *Parm) {
  // Only add nonconst integer/float pointer parameters.
  const QualType T = Parm->getType();
  if (!T->isPointerType() || T->getPointeeType().isConstQualified() ||
      !(T->getPointeeType()->isIntegerType() ||
        T->getPointeeType()->isFloatingType()))
    return;

  if (Parameters.find(Parm) != Parameters.end())
    return;

  ParmInfo PI;
  PI.IsReferenced = false;
  PI.CanBeConst = true;
  Parameters[Parm] = PI;
}
Esempio n. 21
0
PathDiagnosticPiece *
ConditionBRVisitor::VisitTrueTest(const Expr *Cond,
                                  const DeclRefExpr *DR,
                                  const bool tookTrue,
                                  BugReporterContext &BRC,
                                  BugReport &report,
                                  const ExplodedNode *N) {

  const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl());
  if (!VD)
    return 0;
  
  SmallString<256> Buf;
  llvm::raw_svector_ostream Out(Buf);
    
  Out << "Assuming '";
  VD->getDeclName().printName(Out);
  Out << "' is ";
    
  QualType VDTy = VD->getType();
  
  if (VDTy->isPointerType())
    Out << (tookTrue ? "non-null" : "null");
  else if (VDTy->isObjCObjectPointerType())
    Out << (tookTrue ? "non-nil" : "nil");
  else if (VDTy->isScalarType())
    Out << (tookTrue ? "not equal to 0" : "0");
  else
    return 0;
  
  const LocationContext *LCtx = N->getLocationContext();
  PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
  PathDiagnosticEventPiece *event =
    new PathDiagnosticEventPiece(Loc, Out.str());
  
  const ProgramState *state = N->getState().getPtr();
  if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
    if (report.isInteresting(R))
      event->setPrunable(false);
    else {
      SVal V = state->getSVal(R);
      if (report.isInteresting(V))
        event->setPrunable(false);
    }
  }
  return event;
}
Esempio n. 22
0
  static bool hasViableCandidateToCall(clang::LookupResult& R,
                                       const cling::Value& V) {
    if (R.empty())
      return false;
    using namespace clang;
    ASTContext& C = V.getASTContext();
    Sema& SemaR = R.getSema();
    OverloadCandidateSet overloads(SourceLocation(),
                                    OverloadCandidateSet::CSK_Normal);
    QualType Ty = V.getType().getNonReferenceType();
    if (!Ty->isPointerType())
      Ty = C.getPointerType(Ty);

    NamespaceDecl* ClingNSD = utils::Lookup::Namespace(&SemaR, "cling");
    RecordDecl* ClingValueDecl
      = dyn_cast<RecordDecl>(utils::Lookup::Named(&SemaR, "Value",
                                                  ClingNSD));
    assert(ClingValueDecl && "Declaration must be found!");
    QualType ClingValueTy = C.getTypeDeclType(ClingValueDecl);

    // The OverloadCandidateSet requires a QualType to be passed in through an
    // Expr* as part of Args. We know that we won't be using any node generated.
    // We need only an answer whether there is an overload taking these argument
    // types. We cannot afford to create useless Expr* on the AST for this
    // utility function which may be called thousands of times. Instead, we
    // create them on the stack and pretend they are on the heap. We get our
    // answer and forget about doing anything wrong.
    llvm::SmallVector<Expr, 4> exprsOnStack;
    SourceLocation noLoc;
    exprsOnStack.push_back(CXXNullPtrLiteralExpr(Ty, noLoc));
    exprsOnStack.push_back(CXXNullPtrLiteralExpr(Ty, noLoc));
    exprsOnStack.push_back(CXXNullPtrLiteralExpr(ClingValueTy, noLoc));
    llvm::SmallVector<Expr*, 4> exprsFakedOnHeap;
    exprsFakedOnHeap.push_back(&exprsOnStack[0]);
    exprsFakedOnHeap.push_back(&exprsOnStack[1]);
    exprsFakedOnHeap.push_back(&exprsOnStack[2]);
    llvm::ArrayRef<Expr*> Args = llvm::makeArrayRef(exprsFakedOnHeap.data(),
                                                    exprsFakedOnHeap.size());
    // Could trigger deserialization of decls.
    cling::Interpreter::PushTransactionRAII RAII(V.getInterpreter());
    SemaR.AddFunctionCandidates(R.asUnresolvedSet(), Args, overloads);

    OverloadCandidateSet::iterator Best;
    OverloadingResult OR = overloads.BestViableFunction(SemaR,
                                                        SourceLocation(), Best);
    return OR == OR_Success;
  }
Esempio n. 23
0
// CXXDeleteExpr
QualType CXXDeleteExpr::getDestroyedType() const {
  const Expr *Arg = getArgument();
  while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
    if (ICE->getCastKind() != CK_UserDefinedConversion &&
        ICE->getType()->isVoidPointerType())
      Arg = ICE->getSubExpr();
    else
      break;
  }
  // The type-to-delete may not be a pointer if it's a dependent type.
  const QualType ArgType = Arg->getType();

  if (ArgType->isDependentType() && !ArgType->isPointerType())
    return QualType();

  return ArgType->getAs<PointerType>()->getPointeeType();
}
Esempio n. 24
0
  // We need to artificially create:
  // cling_PrintValue(void* (ASTContext)C, void* (Expr)E, const void* (&i)
  Expr* ValuePrinterSynthesizer::SynthesizeVP(Expr* E) {
    QualType QT = E->getType();
    // For now we skip void and function pointer types.
    if (!QT.isNull() && (QT->isVoidType() || QT->isFunctionType()))
      return 0;

    // Find cling_PrintValue
    SourceLocation NoSLoc = SourceLocation();
    DeclarationName PVName = &m_Context->Idents.get("cling_PrintValue");
    LookupResult R(*m_Sema, PVName, NoSLoc, Sema::LookupOrdinaryName,
                   Sema::ForRedeclaration);

    Scope* S = m_Sema->getScopeForContext(m_Sema->CurContext);
    m_Sema->LookupName(R, S);
    assert(!R.empty() && "Cannot find cling_PrintValue(...)");

    CXXScopeSpec CSS;
    Expr* UnresolvedLookup
      = m_Sema->BuildDeclarationNameExpr(CSS, R, /*ADL*/ false).take();


    Expr* VoidEArg = utils::Synthesize::CStyleCastPtrExpr(m_Sema, 
                                                          m_Context->VoidPtrTy,
                                                          (uint64_t)E);
    Expr* VoidCArg = utils::Synthesize::CStyleCastPtrExpr(m_Sema, 
                                                          m_Context->VoidPtrTy,
                                                          (uint64_t)m_Context);

    if (!QT->isPointerType()) {
      while(ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(E))
        E = ICE->getSubExpr();
      E = m_Sema->BuildUnaryOp(S, NoSLoc, UO_AddrOf, E).take();
    }

    llvm::SmallVector<Expr*, 4> CallArgs;
    CallArgs.push_back(VoidEArg);
    CallArgs.push_back(VoidCArg);
    CallArgs.push_back(E);

    Expr* Result = m_Sema->ActOnCallExpr(S, UnresolvedLookup, NoSLoc,
                                         CallArgs, NoSLoc).take();
    assert(Result && "Cannot create value printer!");

    return Result;
  }
/// \brief If the member expression is operator-> (overloaded or not) on
/// IndexVar, include it as a valid usage and prune the traversal.
///
/// For example, given
/// \code
///   struct Foo { int bar(); int x; };
///   vector<Foo> v;
/// \endcode
/// the following uses will be considered convertible:
/// \code
///   for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
///     int b = i->bar();
///     int k = i->x + 1;
///   }
/// \endcode
/// though
/// \code
///   for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
///     int k = i.insert(1);
///   }
///   for (vector<Foo>::iterator i = v.begin(), e = v.end(); i != e; ++i) {
///     int b = e->bar();
///   }
/// \endcode
/// will not.
bool ForLoopIndexUseVisitor::TraverseMemberExpr(MemberExpr *Member) {
  const Expr *Base = Member->getBase();
  const DeclRefExpr *Obj = getDeclRef(Base);
  const Expr *ResultExpr = Member;
  QualType ExprType;
  if (const CXXOperatorCallExpr *Call =
      dyn_cast<CXXOperatorCallExpr>(Base->IgnoreParenImpCasts())) {
    // If operator->() is a MemberExpr containing a CXXOperatorCallExpr, then
    // the MemberExpr does not have the expression we want. We therefore catch
    // that instance here.
    // For example, if vector<Foo>::iterator defines operator->(), then the
    // example `i->bar()` at the top of this function is a CXXMemberCallExpr
    // referring to `i->` as the member function called. We want just `i`, so
    // we take the argument to operator->() as the base object.
    if(Call->getOperator() == OO_Arrow) {
      assert(Call->getNumArgs() == 1 &&
             "Operator-> takes more than one argument");
      Obj = getDeclRef(Call->getArg(0));
      ResultExpr = Obj;
      ExprType = Call->getCallReturnType();
    }
  }

  if (Member->isArrow() && Obj && exprReferencesVariable(IndexVar, Obj)) {
    if (ExprType.isNull())
      ExprType = Obj->getType();

    assert(ExprType->isPointerType() && "Operator-> returned non-pointer type");
    // FIXME: This works around not having the location of the arrow operator.
    // Consider adding OperatorLoc to MemberExpr?
    SourceLocation ArrowLoc =
        Lexer::getLocForEndOfToken(Base->getExprLoc(), 0,
                                   Context->getSourceManager(),
                                   Context->getLangOpts());
    // If something complicated is happening (i.e. the next token isn't an
    // arrow), give up on making this work.
    if (!ArrowLoc.isInvalid()) {
      Usages.push_back(Usage(ResultExpr, /*IsArrow=*/true,
                             SourceRange(Base->getExprLoc(), ArrowLoc)));
      return true;
    }
  }
  return TraverseStmt(Member->getBase());
}
Esempio n. 26
0
PathDiagnosticPiece *
ConditionBRVisitor::VisitConditionVariable(StringRef LhsString,
                                           const Expr *CondVarExpr,
                                           const bool tookTrue,
                                           BugReporterContext &BRC,
                                           BugReport &report,
                                           const ExplodedNode *N) {
  // FIXME: If there's already a constraint tracker for this variable,
  // we shouldn't emit anything here (c.f. the double note in
  // test/Analysis/inlining/path-notes.c)
  SmallString<256> buf;
  llvm::raw_svector_ostream Out(buf);
  Out << "Assuming " << LhsString << " is ";
  
  QualType Ty = CondVarExpr->getType();

  if (Ty->isPointerType())
    Out << (tookTrue ? "not null" : "null");
  else if (Ty->isObjCObjectPointerType())
    Out << (tookTrue ? "not nil" : "nil");
  else if (Ty->isBooleanType())
    Out << (tookTrue ? "true" : "false");
  else if (Ty->isIntegerType())
    Out << (tookTrue ? "non-zero" : "zero");
  else
    return 0;

  const LocationContext *LCtx = N->getLocationContext();
  PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
  PathDiagnosticEventPiece *event =
    new PathDiagnosticEventPiece(Loc, Out.str());

  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) {
    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
      const ProgramState *state = N->getState().getPtr();
      if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) {
        if (report.isInteresting(R))
          event->setPrunable(false);
      }
    }
  }
  
  return event;
}
Esempio n. 27
0
  // We need to artificially create:
  // cling_PrintValue(void* (ASTContext)C, void* (Expr)E, const void* (&i)
  Expr* ValuePrinterSynthesizer::SynthesizeVP(Expr* E) {
    QualType QT = E->getType();
    // For now we skip void and function pointer types.
    if (!QT.isNull() && (QT->isVoidType() || QT->isFunctionType()))
      return 0;

    // Find cling_PrintValue
    if (!m_LookupResult)
      FindAndCacheRuntimeLookupResult(E->getLocStart());


    Expr* VoidEArg = utils::Synthesize::CStyleCastPtrExpr(m_Sema,
                                                          m_Context->VoidPtrTy,
                                                          (uint64_t)E);
    Expr* VoidCArg = utils::Synthesize::CStyleCastPtrExpr(m_Sema,
                                                          m_Context->VoidPtrTy,
                                                          (uint64_t)m_Context);

    SourceLocation NoSLoc = SourceLocation();
    Scope* S = m_Sema->getScopeForContext(m_Sema->CurContext);
    if (!QT->isPointerType()) {
      while(ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(E))
        E = ICE->getSubExpr();
      E = m_Sema->BuildUnaryOp(S, NoSLoc, UO_AddrOf, E).get();
    }

    llvm::SmallVector<Expr*, 4> CallArgs;
    CallArgs.push_back(VoidEArg);
    CallArgs.push_back(VoidCArg);
    CallArgs.push_back(E);

    CXXScopeSpec CSS;
    Expr* unresolvedLookup
      = m_Sema->BuildDeclarationNameExpr(CSS, *m_LookupResult,
                                         /*ADL*/ false).get();

    Expr* Result = m_Sema->ActOnCallExpr(S, unresolvedLookup, E->getLocStart(),
                                         CallArgs, E->getLocEnd()).get();
    assert(Result && "Cannot create value printer!");

    return Result;
  }
Esempio n. 28
0
/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
/// If there is already an implicit cast, merge into the existing one.
/// The result is of the given category.
void Sema::ImpCastExprToType(Expr *&Expr, QualType Ty,
                             CastExpr::CastKind Kind, 
                             ImplicitCastExpr::ResultCategory Category,
                             const CXXCastPath *BasePath) {
  QualType ExprTy = Context.getCanonicalType(Expr->getType());
  QualType TypeTy = Context.getCanonicalType(Ty);

  if (ExprTy == TypeTy)
    return;

  if (Expr->getType()->isPointerType() && Ty->isPointerType()) {
    QualType ExprBaseType = cast<PointerType>(ExprTy)->getPointeeType();
    QualType BaseType = cast<PointerType>(TypeTy)->getPointeeType();
    if (ExprBaseType.getAddressSpace() != BaseType.getAddressSpace()) {
      Diag(Expr->getExprLoc(), diag::err_implicit_pointer_address_space_cast)
        << Expr->getSourceRange();
    }
  }

  // If this is a derived-to-base cast to a through a virtual base, we
  // need a vtable.
  if (Kind == CastExpr::CK_DerivedToBase && 
      BasePathInvolvesVirtualBase(*BasePath)) {
    QualType T = Expr->getType();
    if (const PointerType *Pointer = T->getAs<PointerType>())
      T = Pointer->getPointeeType();
    if (const RecordType *RecordTy = T->getAs<RecordType>())
      MarkVTableUsed(Expr->getLocStart(), 
                     cast<CXXRecordDecl>(RecordTy->getDecl()));
  }

  if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(Expr)) {
    if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) {
      ImpCast->setType(Ty);
      ImpCast->setCategory(Category);
      return;
    }
  }

  Expr = ImplicitCastExpr::Create(Context, Ty, Kind, Expr, BasePath, Category);
}
Esempio n. 29
0
/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
/// @code ::delete ptr; @endcode
/// or
/// @code delete [] ptr; @endcode
Action::OwningExprResult
Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
                     bool ArrayForm, ExprArg Operand)
{
  // C++ 5.3.5p1: "The operand shall have a pointer type, or a class type
  //   having a single conversion function to a pointer type. The result has
  //   type void."
  // DR599 amends "pointer type" to "pointer to object type" in both cases.

  Expr *Ex = (Expr *)Operand.get();
  if (!Ex->isTypeDependent()) {
    QualType Type = Ex->getType();

    if (Type->isRecordType()) {
      // FIXME: Find that one conversion function and amend the type.
    }

    if (!Type->isPointerType())
      return ExprError(Diag(StartLoc, diag::err_delete_operand)
        << Type << Ex->getSourceRange());

    QualType Pointee = Type->getAsPointerType()->getPointeeType();
    if (Pointee->isFunctionType() || Pointee->isVoidType())
      return ExprError(Diag(StartLoc, diag::err_delete_operand)
        << Type << Ex->getSourceRange());
    else if (!Pointee->isDependentType() &&
             RequireCompleteType(StartLoc, Pointee, 
                                 diag::warn_delete_incomplete,
                                 Ex->getSourceRange()))
      return ExprError();

    // FIXME: Look up the correct operator delete overload and pass a pointer
    // along.
    // FIXME: Check access and ambiguity of operator delete and destructor.
  }

  Operand.release();
  return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm,
                                           0, Ex, StartLoc));
}
Esempio n. 30
0
void MicrosoftCXXNameMangler::mangleVariableEncoding(const VarDecl *VD) {
  // <type-encoding> ::= <storage-class> <variable-type>
  // <storage-class> ::= 0  # private static member
  //                 ::= 1  # protected static member
  //                 ::= 2  # public static member
  //                 ::= 3  # global
  //                 ::= 4  # static local
  
  // The first character in the encoding (after the name) is the storage class.
  if (VD->isStaticDataMember()) {
    // If it's a static member, it also encodes the access level.
    switch (VD->getAccess()) {
      default:
      case AS_private: Out << '0'; break;
      case AS_protected: Out << '1'; break;
      case AS_public: Out << '2'; break;
    }
  }
  else if (!VD->isStaticLocal())
    Out << '3';
  else
    Out << '4';
  // Now mangle the type.
  // <variable-type> ::= <type> <cvr-qualifiers>
  //                 ::= <type> A # pointers, references, arrays
  // Pointers and references are odd. The type of 'int * const foo;' gets
  // mangled as 'QAHA' instead of 'PAHB', for example.
  QualType Ty = VD->getType();
  if (Ty->isPointerType() || Ty->isReferenceType()) {
    mangleType(Ty);
    Out << 'A';
  } else if (Ty->isArrayType()) {
    // Global arrays are funny, too.
    mangleType(cast<ArrayType>(Ty.getTypePtr()), true);
    Out << 'A';
  } else {
    mangleType(Ty.getLocalUnqualifiedType());
    mangleQualifiers(Ty.getLocalQualifiers(), false);
  }
}