<commit_before>//===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the C++ expression evaluation engine.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/ParentMap.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"

using namespace clang;
using namespace ento;

void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
                                          ExplodedNode *Pred,
                                          ExplodedNodeSet &Dst) {
  StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
  const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
  ProgramStateRef state = Pred->getState();
  const LocationContext *LCtx = Pred->getLocationContext();

  state = createTemporaryRegionIfNeeded(state, LCtx, tempExpr, ME);
  Bldr.generateNode(ME, Pred, state);
}

// FIXME: This is the sort of code that should eventually live in a Core
// checker rather than as a special case in ExprEngine.
void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
                                    const CallEvent &Call) {
  SVal ThisVal;
  bool AlwaysReturnsLValue;
  if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
    assert(Ctor->getDecl()->isTrivial());
    assert(Ctor->getDecl()->isCopyOrMoveConstructor());
    ThisVal = Ctor->getCXXThisVal();
    AlwaysReturnsLValue = false;
  } else {
    assert(cast<CXXMethodDecl>(Call.getDecl())->isTrivial());
    assert(cast<CXXMethodDecl>(Call.getDecl())->getOverloadedOperator() ==
           OO_Equal);
    ThisVal = cast<CXXInstanceCall>(Call).getCXXThisVal();
    AlwaysReturnsLValue = true;
  }

  const LocationContext *LCtx = Pred->getLocationContext();

  ExplodedNodeSet Dst;
  Bldr.takeNodes(Pred);

  SVal V = Call.getArgSVal(0);

  // If the value being copied is not unknown, load from its location to get
  // an aggregate rvalue.
  if (Optional<Loc> L = V.getAs<Loc>())
    V = Pred->getState()->getSVal(*L);
  else
    assert(V.isUnknownOrUndef());

  const Expr *CallExpr = Call.getOriginExpr();
  evalBind(Dst, CallExpr, Pred, ThisVal, V, true);

  PostStmt PS(CallExpr, LCtx);
  for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end();
       I != E; ++I) {
    ProgramStateRef State = (*I)->getState();
    if (AlwaysReturnsLValue)
      State = State->BindExpr(CallExpr, LCtx, ThisVal);
    else
      State = bindReturnValue(Call, LCtx, State);
    Bldr.generateNode(PS, State, *I);
  }
}


SVal ExprEngine::makeZeroElementRegion(ProgramStateRef State, SVal LValue,
                                       QualType &Ty, bool &IsArray) {
  SValBuilder &SVB = State->getStateManager().getSValBuilder();
  ASTContext &Ctx = SVB.getContext();

  while (const ArrayType *AT = Ctx.getAsArrayType(Ty)) {
    Ty = AT->getElementType();
    LValue = State->getLValue(Ty, SVB.makeZeroArrayIndex(), LValue);
    IsArray = true;
  }

  return LValue;
}


const MemRegion *
ExprEngine::getRegionForConstructedObject(const CXXConstructExpr *CE,
                                          ExplodedNode *Pred,
                                          const ConstructionContext *CC,
                                          EvalCallOptions &CallOpts) {
  const LocationContext *LCtx = Pred->getLocationContext();
  ProgramStateRef State = Pred->getState();
  MemRegionManager &MRMgr = getSValBuilder().getRegionManager();

  // See if we're constructing an existing region by looking at the
  // current construction context.
  if (CC) {
    if (const Stmt *TriggerStmt = CC->getTriggerStmt()) {
      if (const CXXNewExpr *CNE = dyn_cast<CXXNewExpr>(TriggerStmt)) {
        if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
          // TODO: Detect when the allocator returns a null pointer.
          // Constructor shall not be called in this case.
          if (const SubRegion *MR = dyn_cast_or_null<SubRegion>(
                  getCXXNewAllocatorValue(State, CNE, LCtx).getAsRegion())) {
            if (CNE->isArray()) {
              // TODO: In fact, we need to call the constructor for every
              // allocated element, not just the first one!
              CallOpts.IsArrayCtorOrDtor = true;
              return getStoreManager().GetElementZeroRegion(
                  MR, CNE->getType()->getPointeeType());
            }
            return MR;
          }
        }
      } else if (auto *DS = dyn_cast<DeclStmt>(TriggerStmt)) {
        const auto *Var = cast<VarDecl>(DS->getSingleDecl());
        SVal LValue = State->getLValue(Var, LCtx);
        QualType Ty = Var->getType();
        LValue = makeZeroElementRegion(State, LValue, Ty,
                                       CallOpts.IsArrayCtorOrDtor);
        return LValue.getAsRegion();
      } else if (auto *RS = dyn_cast<ReturnStmt>(TriggerStmt)) {
        // TODO: We should construct into a CXXBindTemporaryExpr or a
        // MaterializeTemporaryExpr around the call-expression on the previous
        // stack frame. Currently we re-bind the temporary to the correct region
        // later, but that's not semantically correct. This of course does not
        // apply when we're in the top frame. But if we are in an inlined
        // function, we should be able to take the call-site CFG element,
        // and it should contain (but right now it wouldn't) some sort of
        // construction context that'd give us the right temporary expression.
        CallOpts.IsTemporaryCtorOrDtor = true;
        return MRMgr.getCXXTempObjectRegion(CE, LCtx);
      } else if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(TriggerStmt)) {
        CallOpts.IsTemporaryCtorOrDtor = true;
        return MRMgr.getCXXTempObjectRegion(CE, LCtx);
      }
      // TODO: Consider other directly initialized elements.
    } else if (const CXXCtorInitializer *Init = CC->getTriggerInit()) {
      assert(Init->isAnyMemberInitializer());
      const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
      Loc ThisPtr =
      getSValBuilder().getCXXThis(CurCtor, LCtx->getCurrentStackFrame());
      SVal ThisVal = State->getSVal(ThisPtr);

      const ValueDecl *Field;
      SVal FieldVal;
      if (Init->isIndirectMemberInitializer()) {
        Field = Init->getIndirectMember();
        FieldVal = State->getLValue(Init->getIndirectMember(), ThisVal);
      } else {
        Field = Init->getMember();
        FieldVal = State->getLValue(Init->getMember(), ThisVal);
      }<commit_msg>Silence some -Wunused-variable warnings; NFC.<commit_after>//===- ExprEngineCXX.cpp - ExprEngine support for C++ -----------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines the C++ expression evaluation engine.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/ParentMap.h"
#include "clang/Basic/PrettyStackTrace.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"

using namespace clang;
using namespace ento;

void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
                                          ExplodedNode *Pred,
                                          ExplodedNodeSet &Dst) {
  StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
  const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens();
  ProgramStateRef state = Pred->getState();
  const LocationContext *LCtx = Pred->getLocationContext();

  state = createTemporaryRegionIfNeeded(state, LCtx, tempExpr, ME);
  Bldr.generateNode(ME, Pred, state);
}

// FIXME: This is the sort of code that should eventually live in a Core
// checker rather than as a special case in ExprEngine.
void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
                                    const CallEvent &Call) {
  SVal ThisVal;
  bool AlwaysReturnsLValue;
  if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
    assert(Ctor->getDecl()->isTrivial());
    assert(Ctor->getDecl()->isCopyOrMoveConstructor());
    ThisVal = Ctor->getCXXThisVal();
    AlwaysReturnsLValue = false;
  } else {
    assert(cast<CXXMethodDecl>(Call.getDecl())->isTrivial());
    assert(cast<CXXMethodDecl>(Call.getDecl())->getOverloadedOperator() ==
           OO_Equal);
    ThisVal = cast<CXXInstanceCall>(Call).getCXXThisVal();
    AlwaysReturnsLValue = true;
  }

  const LocationContext *LCtx = Pred->getLocationContext();

  ExplodedNodeSet Dst;
  Bldr.takeNodes(Pred);

  SVal V = Call.getArgSVal(0);

  // If the value being copied is not unknown, load from its location to get
  // an aggregate rvalue.
  if (Optional<Loc> L = V.getAs<Loc>())
    V = Pred->getState()->getSVal(*L);
  else
    assert(V.isUnknownOrUndef());

  const Expr *CallExpr = Call.getOriginExpr();
  evalBind(Dst, CallExpr, Pred, ThisVal, V, true);

  PostStmt PS(CallExpr, LCtx);
  for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end();
       I != E; ++I) {
    ProgramStateRef State = (*I)->getState();
    if (AlwaysReturnsLValue)
      State = State->BindExpr(CallExpr, LCtx, ThisVal);
    else
      State = bindReturnValue(Call, LCtx, State);
    Bldr.generateNode(PS, State, *I);
  }
}


SVal ExprEngine::makeZeroElementRegion(ProgramStateRef State, SVal LValue,
                                       QualType &Ty, bool &IsArray) {
  SValBuilder &SVB = State->getStateManager().getSValBuilder();
  ASTContext &Ctx = SVB.getContext();

  while (const ArrayType *AT = Ctx.getAsArrayType(Ty)) {
    Ty = AT->getElementType();
    LValue = State->getLValue(Ty, SVB.makeZeroArrayIndex(), LValue);
    IsArray = true;
  }

  return LValue;
}


const MemRegion *
ExprEngine::getRegionForConstructedObject(const CXXConstructExpr *CE,
                                          ExplodedNode *Pred,
                                          const ConstructionContext *CC,
                                          EvalCallOptions &CallOpts) {
  const LocationContext *LCtx = Pred->getLocationContext();
  ProgramStateRef State = Pred->getState();
  MemRegionManager &MRMgr = getSValBuilder().getRegionManager();

  // See if we're constructing an existing region by looking at the
  // current construction context.
  if (CC) {
    if (const Stmt *TriggerStmt = CC->getTriggerStmt()) {
      if (const CXXNewExpr *CNE = dyn_cast<CXXNewExpr>(TriggerStmt)) {
        if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
          // TODO: Detect when the allocator returns a null pointer.
          // Constructor shall not be called in this case.
          if (const SubRegion *MR = dyn_cast_or_null<SubRegion>(
                  getCXXNewAllocatorValue(State, CNE, LCtx).getAsRegion())) {
            if (CNE->isArray()) {
              // TODO: In fact, we need to call the constructor for every
              // allocated element, not just the first one!
              CallOpts.IsArrayCtorOrDtor = true;
              return getStoreManager().GetElementZeroRegion(
                  MR, CNE->getType()->getPointeeType());
            }
            return MR;
          }
        }
      } else if (auto *DS = dyn_cast<DeclStmt>(TriggerStmt)) {
        const auto *Var = cast<VarDecl>(DS->getSingleDecl());
        SVal LValue = State->getLValue(Var, LCtx);
        QualType Ty = Var->getType();
        LValue = makeZeroElementRegion(State, LValue, Ty,
                                       CallOpts.IsArrayCtorOrDtor);
        return LValue.getAsRegion();
      } else if (isa<ReturnStmt>(TriggerStmt)) {
        // TODO: We should construct into a CXXBindTemporaryExpr or a
        // MaterializeTemporaryExpr around the call-expression on the previous
        // stack frame. Currently we re-bind the temporary to the correct region
        // later, but that's not semantically correct. This of course does not
        // apply when we're in the top frame. But if we are in an inlined
        // function, we should be able to take the call-site CFG element,
        // and it should contain (but right now it wouldn't) some sort of
        // construction context that'd give us the right temporary expression.
        CallOpts.IsTemporaryCtorOrDtor = true;
        return MRMgr.getCXXTempObjectRegion(CE, LCtx);
      } else if (isa<CXXBindTemporaryExpr>(TriggerStmt)) {
        CallOpts.IsTemporaryCtorOrDtor = true;
        return MRMgr.getCXXTempObjectRegion(CE, LCtx);
      }
      // TODO: Consider other directly initialized elements.
    } else if (const CXXCtorInitializer *Init = CC->getTriggerInit()) {
      assert(Init->isAnyMemberInitializer());
      const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl());
      Loc ThisPtr =
      getSValBuilder().getCXXThis(CurCtor, LCtx->getCurrentStackFrame());
      SVal ThisVal = State->getSVal(ThisPtr);

      const ValueDecl *Field;
      SVal FieldVal;
      if (Init->isIndirectMemberInitializer()) {
        Field = Init->getIndirectMember();
        FieldVal = State->getLValue(Init->getIndirectMember(), ThisVal);
      } else {
        Field = Init->getMember();
        FieldVal = State->getLValue(Init->getMember(), ThisVal);
      }
{'fraction_non_alphanumeric': 0.13466017361846283, 'fraction_numerical': 0.00014115322182228809, 'mean_word_length': 2.5964467005076144, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 109, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 26, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3618396', 'n_tokens_mistral': 4079, 'n_tokens_neox': 4063, 'n_words': 1036}