head	1.1;
branch	1.1.1;
access;
symbols
	netbsd-11-0-RC4:1.1.1.6
	netbsd-11-0-RC3:1.1.1.6
	netbsd-11-0-RC2:1.1.1.6
	netbsd-11-0-RC1:1.1.1.6
	perseant-exfatfs-base-20250801:1.1.1.6
	netbsd-11:1.1.1.6.0.10
	netbsd-11-base:1.1.1.6
	netbsd-10-1-RELEASE:1.1.1.6
	perseant-exfatfs-base-20240630:1.1.1.6
	perseant-exfatfs:1.1.1.6.0.8
	perseant-exfatfs-base:1.1.1.6
	netbsd-8-3-RELEASE:1.1.1.4
	netbsd-9-4-RELEASE:1.1.1.5
	netbsd-10-0-RELEASE:1.1.1.6
	netbsd-10-0-RC6:1.1.1.6
	netbsd-10-0-RC5:1.1.1.6
	netbsd-10-0-RC4:1.1.1.6
	netbsd-10-0-RC3:1.1.1.6
	netbsd-10-0-RC2:1.1.1.6
	netbsd-10-0-RC1:1.1.1.6
	netbsd-10:1.1.1.6.0.6
	netbsd-10-base:1.1.1.6
	netbsd-9-3-RELEASE:1.1.1.5
	cjep_sun2x:1.1.1.6.0.4
	cjep_sun2x-base:1.1.1.6
	cjep_staticlib_x-base1:1.1.1.6
	netbsd-9-2-RELEASE:1.1.1.5
	cjep_staticlib_x:1.1.1.6.0.2
	cjep_staticlib_x-base:1.1.1.6
	netbsd-9-1-RELEASE:1.1.1.5
	phil-wifi-20200421:1.1.1.6
	phil-wifi-20200411:1.1.1.6
	phil-wifi-20200406:1.1.1.6
	netbsd-8-2-RELEASE:1.1.1.4
	netbsd-9-0-RELEASE:1.1.1.5
	netbsd-9-0-RC2:1.1.1.5
	netbsd-9-0-RC1:1.1.1.5
	netbsd-9:1.1.1.5.0.2
	netbsd-9-base:1.1.1.5
	phil-wifi-20190609:1.1.1.5
	netbsd-8-1-RELEASE:1.1.1.4
	netbsd-8-1-RC1:1.1.1.4
	pgoyette-compat-merge-20190127:1.1.1.4.14.1
	pgoyette-compat-20190127:1.1.1.5
	pgoyette-compat-20190118:1.1.1.5
	pgoyette-compat-1226:1.1.1.5
	pgoyette-compat-1126:1.1.1.5
	pgoyette-compat-1020:1.1.1.5
	pgoyette-compat-0930:1.1.1.5
	pgoyette-compat-0906:1.1.1.5
	netbsd-7-2-RELEASE:1.1.1.3
	pgoyette-compat-0728:1.1.1.5
	clang-337282:1.1.1.5
	netbsd-8-0-RELEASE:1.1.1.4
	phil-wifi:1.1.1.4.0.16
	phil-wifi-base:1.1.1.4
	pgoyette-compat-0625:1.1.1.4
	netbsd-8-0-RC2:1.1.1.4
	pgoyette-compat-0521:1.1.1.4
	pgoyette-compat-0502:1.1.1.4
	pgoyette-compat-0422:1.1.1.4
	netbsd-8-0-RC1:1.1.1.4
	pgoyette-compat-0415:1.1.1.4
	pgoyette-compat-0407:1.1.1.4
	pgoyette-compat-0330:1.1.1.4
	pgoyette-compat-0322:1.1.1.4
	pgoyette-compat-0315:1.1.1.4
	netbsd-7-1-2-RELEASE:1.1.1.3
	pgoyette-compat:1.1.1.4.0.14
	pgoyette-compat-base:1.1.1.4
	netbsd-7-1-1-RELEASE:1.1.1.3
	clang-319952:1.1.1.4
	matt-nb8-mediatek:1.1.1.4.0.12
	matt-nb8-mediatek-base:1.1.1.4
	clang-309604:1.1.1.4
	perseant-stdc-iso10646:1.1.1.4.0.10
	perseant-stdc-iso10646-base:1.1.1.4
	netbsd-8:1.1.1.4.0.8
	netbsd-8-base:1.1.1.4
	prg-localcount2-base3:1.1.1.4
	prg-localcount2-base2:1.1.1.4
	prg-localcount2-base1:1.1.1.4
	prg-localcount2:1.1.1.4.0.6
	prg-localcount2-base:1.1.1.4
	pgoyette-localcount-20170426:1.1.1.4
	bouyer-socketcan-base1:1.1.1.4
	pgoyette-localcount-20170320:1.1.1.4
	netbsd-7-1:1.1.1.3.0.10
	netbsd-7-1-RELEASE:1.1.1.3
	netbsd-7-1-RC2:1.1.1.3
	clang-294123:1.1.1.4
	netbsd-7-nhusb-base-20170116:1.1.1.3
	bouyer-socketcan:1.1.1.4.0.4
	bouyer-socketcan-base:1.1.1.4
	clang-291444:1.1.1.4
	pgoyette-localcount-20170107:1.1.1.4
	netbsd-7-1-RC1:1.1.1.3
	pgoyette-localcount-20161104:1.1.1.4
	netbsd-7-0-2-RELEASE:1.1.1.3
	localcount-20160914:1.1.1.4
	netbsd-7-nhusb:1.1.1.3.0.8
	netbsd-7-nhusb-base:1.1.1.3
	clang-280599:1.1.1.4
	pgoyette-localcount-20160806:1.1.1.4
	pgoyette-localcount-20160726:1.1.1.4
	pgoyette-localcount:1.1.1.4.0.2
	pgoyette-localcount-base:1.1.1.4
	netbsd-7-0-1-RELEASE:1.1.1.3
	clang-261930:1.1.1.4
	netbsd-7-0:1.1.1.3.0.6
	netbsd-7-0-RELEASE:1.1.1.3
	netbsd-7-0-RC3:1.1.1.3
	netbsd-7-0-RC2:1.1.1.3
	netbsd-7-0-RC1:1.1.1.3
	clang-237755:1.1.1.3
	clang-232565:1.1.1.3
	clang-227398:1.1.1.3
	tls-maxphys-base:1.1.1.3
	tls-maxphys:1.1.1.3.0.4
	netbsd-7:1.1.1.3.0.2
	netbsd-7-base:1.1.1.3
	clang-215315:1.1.1.3
	clang-209886:1.1.1.2
	yamt-pagecache:1.1.1.1.0.4
	yamt-pagecache-base9:1.1.1.1
	tls-earlyentropy:1.1.1.1.0.2
	tls-earlyentropy-base:1.1.1.2
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.1.1.1
	riastradh-drm2-base3:1.1.1.1
	clang-202566:1.1.1.1
	clang-201163:1.1.1.1
	clang-199312:1.1.1.1
	clang-198450:1.1.1.1
	clang-196603:1.1.1.1
	clang-195771:1.1.1.1
	LLVM:1.1.1;
locks; strict;
comment	@// @;


1.1
date	2013.11.28.14.14.53;	author joerg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	ow8OybrawrB1f3fx;

1.1.1.1
date	2013.11.28.14.14.53;	author joerg;	state Exp;
branches
	1.1.1.1.2.1
	1.1.1.1.4.1;
next	1.1.1.2;
commitid	ow8OybrawrB1f3fx;

1.1.1.2
date	2014.05.30.18.14.44;	author joerg;	state Exp;
branches;
next	1.1.1.3;
commitid	8q0kdlBlCn09GACx;

1.1.1.3
date	2014.08.10.17.08.35;	author joerg;	state Exp;
branches
	1.1.1.3.4.1;
next	1.1.1.4;
commitid	N85tXAN6Ex9VZPLx;

1.1.1.4
date	2016.02.27.22.12.05;	author joerg;	state Exp;
branches
	1.1.1.4.14.1
	1.1.1.4.16.1;
next	1.1.1.5;
commitid	tIimz3oDlh1NpBWy;

1.1.1.5
date	2018.07.17.18.31.05;	author joerg;	state Exp;
branches;
next	1.1.1.6;
commitid	wDzL46ALjrCZgwKA;

1.1.1.6
date	2019.11.13.22.19.29;	author joerg;	state dead;
branches;
next	;
commitid	QD8YATxuNG34YJKB;

1.1.1.1.2.1
date	2014.08.10.07.08.10;	author tls;	state Exp;
branches;
next	;
commitid	t01A1TLTYxkpGMLx;

1.1.1.1.4.1
date	2013.11.28.14.14.53;	author yamt;	state dead;
branches;
next	1.1.1.1.4.2;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.1.4.2
date	2014.05.22.16.18.31;	author yamt;	state Exp;
branches;
next	;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.3.4.1
date	2014.08.10.17.08.35;	author tls;	state dead;
branches;
next	1.1.1.3.4.2;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.3.4.2
date	2014.08.19.23.47.32;	author tls;	state Exp;
branches;
next	;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.4.14.1
date	2018.07.28.04.33.24;	author pgoyette;	state Exp;
branches;
next	;
commitid	1UP1xAIUxv1ZgRLA;

1.1.1.4.16.1
date	2019.06.10.21.45.29;	author christos;	state Exp;
branches;
next	1.1.1.4.16.2;
commitid	jtc8rnCzWiEEHGqB;

1.1.1.4.16.2
date	2020.04.13.07.46.39;	author martin;	state dead;
branches;
next	;
commitid	X01YhRUPVUDaec4C;


desc
@@


1.1
log
@Initial revision
@
text
@//== Environment.cpp - Map from Stmt* to Locations/Values -------*- C++ -*--==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defined the Environment and EnvironmentManager classes.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace ento;

static const Expr *ignoreTransparentExprs(const Expr *E) {
  E = E->IgnoreParens();

  switch (E->getStmtClass()) {
  case Stmt::OpaqueValueExprClass:
    E = cast<OpaqueValueExpr>(E)->getSourceExpr();
    break;
  case Stmt::ExprWithCleanupsClass:
    E = cast<ExprWithCleanups>(E)->getSubExpr();
    break;
  case Stmt::CXXBindTemporaryExprClass:
    E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
    break;
  case Stmt::SubstNonTypeTemplateParmExprClass:
    E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement();
    break;
  default:
    // This is the base case: we can't look through more than we already have.
    return E;
  }

  return ignoreTransparentExprs(E);
}

static const Stmt *ignoreTransparentExprs(const Stmt *S) {
  if (const Expr *E = dyn_cast<Expr>(S))
    return ignoreTransparentExprs(E);
  return S;
}

EnvironmentEntry::EnvironmentEntry(const Stmt *S, const LocationContext *L)
  : std::pair<const Stmt *,
              const StackFrameContext *>(ignoreTransparentExprs(S),
                                         L ? L->getCurrentStackFrame() : 0) {}

SVal Environment::lookupExpr(const EnvironmentEntry &E) const {
  const SVal* X = ExprBindings.lookup(E);
  if (X) {
    SVal V = *X;
    return V;
  }
  return UnknownVal();
}

SVal Environment::getSVal(const EnvironmentEntry &Entry,
                          SValBuilder& svalBuilder) const {
  const Stmt *S = Entry.getStmt();
  const LocationContext *LCtx = Entry.getLocationContext();

  switch (S->getStmtClass()) {
  case Stmt::CXXBindTemporaryExprClass:
  case Stmt::ExprWithCleanupsClass:
  case Stmt::GenericSelectionExprClass:
  case Stmt::OpaqueValueExprClass:
  case Stmt::ParenExprClass:
  case Stmt::SubstNonTypeTemplateParmExprClass:
    llvm_unreachable("Should have been handled by ignoreTransparentExprs");

  case Stmt::AddrLabelExprClass:
  case Stmt::CharacterLiteralClass:
  case Stmt::CXXBoolLiteralExprClass:
  case Stmt::CXXScalarValueInitExprClass:
  case Stmt::ImplicitValueInitExprClass:
  case Stmt::IntegerLiteralClass:
  case Stmt::ObjCBoolLiteralExprClass:
  case Stmt::CXXNullPtrLiteralExprClass:
  case Stmt::ObjCStringLiteralClass:
  case Stmt::StringLiteralClass:
    // Known constants; defer to SValBuilder.
    return svalBuilder.getConstantVal(cast<Expr>(S)).getValue();

  case Stmt::ReturnStmtClass: {
    const ReturnStmt *RS = cast<ReturnStmt>(S);
    if (const Expr *RE = RS->getRetValue())
      return getSVal(EnvironmentEntry(RE, LCtx), svalBuilder);
    return UndefinedVal();        
  }
    
  // Handle all other Stmt* using a lookup.
  default:
    return lookupExpr(EnvironmentEntry(S, LCtx));
  }
}

Environment EnvironmentManager::bindExpr(Environment Env,
                                         const EnvironmentEntry &E,
                                         SVal V,
                                         bool Invalidate) {
  if (V.isUnknown()) {
    if (Invalidate)
      return Environment(F.remove(Env.ExprBindings, E));
    else
      return Env;
  }
  return Environment(F.add(Env.ExprBindings, E, V));
}

namespace {
class MarkLiveCallback : public SymbolVisitor {
  SymbolReaper &SymReaper;
public:
  MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {}
  bool VisitSymbol(SymbolRef sym) {
    SymReaper.markLive(sym);
    return true;
  }
  bool VisitMemRegion(const MemRegion *R) {
    SymReaper.markLive(R);
    return true;
  }
};
} // end anonymous namespace

// removeDeadBindings:
//  - Remove subexpression bindings.
//  - Remove dead block expression bindings.
//  - Keep live block expression bindings:
//   - Mark their reachable symbols live in SymbolReaper,
//     see ScanReachableSymbols.
//   - Mark the region in DRoots if the binding is a loc::MemRegionVal.
Environment
EnvironmentManager::removeDeadBindings(Environment Env,
                                       SymbolReaper &SymReaper,
                                       ProgramStateRef ST) {

  // We construct a new Environment object entirely, as this is cheaper than
  // individually removing all the subexpression bindings (which will greatly
  // outnumber block-level expression bindings).
  Environment NewEnv = getInitialEnvironment();

  MarkLiveCallback CB(SymReaper);
  ScanReachableSymbols RSScaner(ST, CB);

  llvm::ImmutableMapRef<EnvironmentEntry,SVal>
    EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(),
             F.getTreeFactory());

  // Iterate over the block-expr bindings.
  for (Environment::iterator I = Env.begin(), E = Env.end();
       I != E; ++I) {

    const EnvironmentEntry &BlkExpr = I.getKey();
    const SVal &X = I.getData();

    if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) {
      // Copy the binding to the new map.
      EBMapRef = EBMapRef.add(BlkExpr, X);

      // If the block expr's value is a memory region, then mark that region.
      if (Optional<loc::MemRegionVal> R = X.getAs<loc::MemRegionVal>())
        SymReaper.markLive(R->getRegion());

      // Mark all symbols in the block expr's value live.
      RSScaner.scan(X);
      continue;
    } else {
      SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
      for (; SI != SE; ++SI)
        SymReaper.maybeDead(*SI);
    }
  }

  NewEnv.ExprBindings = EBMapRef.asImmutableMap();
  return NewEnv;
}

void Environment::print(raw_ostream &Out, const char *NL,
                        const char *Sep) const {
  bool isFirst = true;

  for (Environment::iterator I = begin(), E = end(); I != E; ++I) {
    const EnvironmentEntry &En = I.getKey();
    
    if (isFirst) {
      Out << NL << NL
          << "Expressions:"
          << NL;      
      isFirst = false;
    } else {
      Out << NL;
    }
    
    const Stmt *S = En.getStmt();
    
    Out << " (" << (const void*) En.getLocationContext() << ','
      << (const void*) S << ") ";
    LangOptions LO; // FIXME.
    S->printPretty(Out, 0, PrintingPolicy(LO));
    Out << " : " << I.getData();
  }
}
@


1.1.1.1
log
@Import Clang 3.4rc1 r195771.
@
text
@@


1.1.1.1.2.1
log
@Rebase.
@
text
@d57 1
a57 2
                                         L ? L->getCurrentStackFrame()
                                           : nullptr) {}
d126 1
a126 1
  bool VisitSymbol(SymbolRef sym) override {
d130 1
a130 1
  bool VisitMemRegion(const MemRegion *R) override {
d211 1
a211 1
    S->printPretty(Out, nullptr, PrintingPolicy(LO));
@


1.1.1.2
log
@Import Clang 3.5svn r209886.
@
text
@d57 1
a57 2
                                         L ? L->getCurrentStackFrame()
                                           : nullptr) {}
d126 1
a126 1
  bool VisitSymbol(SymbolRef sym) override {
d130 1
a130 1
  bool VisitMemRegion(const MemRegion *R) override {
d211 1
a211 1
    S->printPretty(Out, nullptr, PrintingPolicy(LO));
@


1.1.1.3
log
@Import clang 3.6svn r215315.
@
text
@d208 1
a208 2
    assert(S != nullptr && "Expected non-null Stmt");

@


1.1.1.4
log
@Import Clang 3.8.0rc3 r261930.
@
text
@a92 1
  case Stmt::TypeTraitExprClass:
d100 1
a100 1
    return UndefinedVal();
d102 1
a102 1

d123 1
a123 1
class MarkLiveCallback final : public SymbolVisitor {
d173 4
d197 1
a197 1

d201 1
a201 1
          << NL;
d206 1
a206 1

@


1.1.1.4.16.1
log
@Sync with HEAD
@
text
@d1 1
a1 1
//===- Environment.cpp - Map from Stmt* to Locations/Values ---------------===//
a13 2
#include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h"
#include "clang/AST/Expr.h"
d15 3
a17 5
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
a18 8
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
a19 1
#include <cassert>
d49 1
a49 1
  if (const auto *E = dyn_cast<Expr>(S))
d55 4
a58 4
    : std::pair<const Stmt *,
                const StackFrameContext *>(ignoreTransparentExprs(S),
                                           L ? L->getStackFrame()
                                             : nullptr) {}
d98 1
a98 1
    const auto *RS = cast<ReturnStmt>(S);
a123 1

a125 1

a127 1

a131 1

d137 1
a137 2

} // namespace
d150 1
d159 1
a159 1
  llvm::ImmutableMapRef<EnvironmentEntry, SVal>
d166 1
d189 13
a201 15
                        const char *Sep, const LocationContext *WithLC) const {
  if (ExprBindings.isEmpty())
    return;

  if (!WithLC) {
    // Find the freshest location context.
    llvm::SmallPtrSet<const LocationContext *, 16> FoundContexts;
    for (auto I : *this) {
      const LocationContext *LC = I.first.getLocationContext();
      if (FoundContexts.count(LC) == 0) {
        // This context is fresher than all other contexts so far.
        WithLC = LC;
        for (const LocationContext *LCI = LC; LCI; LCI = LCI->getParent())
          FoundContexts.insert(LCI);
      }
a202 1
  }
d204 2
a205 1
  assert(WithLC);
d207 6
a212 17
  LangOptions LO; // FIXME.
  PrintingPolicy PP(LO);

  Out << NL << NL << "Expressions by stack frame:" << NL;
  WithLC->dumpStack(Out, "", NL, Sep, [&](const LocationContext *LC) {
    for (auto I : ExprBindings) {
      if (I.first.getLocationContext() != LC)
        continue;

      const Stmt *S = I.first.getStmt();
      assert(S != nullptr && "Expected non-null Stmt");

      Out << "(" << (const void *)LC << ',' << (const void *)S << ") ";
      S->printPretty(Out, nullptr, PP);
      Out << " : " << I.second << NL;
    }
  });
@


1.1.1.4.16.2
log
@Mostly merge changes from HEAD upto 20200411
@
text
@@


1.1.1.4.14.1
log
@Sync with HEAD
@
text
@d1 1
a1 1
//===- Environment.cpp - Map from Stmt* to Locations/Values ---------------===//
a13 2
#include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h"
#include "clang/AST/Expr.h"
d15 3
a17 5
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
a18 8
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
a19 1
#include <cassert>
d49 1
a49 1
  if (const auto *E = dyn_cast<Expr>(S))
d55 4
a58 4
    : std::pair<const Stmt *,
                const StackFrameContext *>(ignoreTransparentExprs(S),
                                           L ? L->getStackFrame()
                                             : nullptr) {}
d98 1
a98 1
    const auto *RS = cast<ReturnStmt>(S);
a123 1

a125 1

a127 1

a131 1

d137 1
a137 2

} // namespace
d150 1
d159 1
a159 1
  llvm::ImmutableMapRef<EnvironmentEntry, SVal>
d166 1
d189 13
a201 15
                        const char *Sep, const LocationContext *WithLC) const {
  if (ExprBindings.isEmpty())
    return;

  if (!WithLC) {
    // Find the freshest location context.
    llvm::SmallPtrSet<const LocationContext *, 16> FoundContexts;
    for (auto I : *this) {
      const LocationContext *LC = I.first.getLocationContext();
      if (FoundContexts.count(LC) == 0) {
        // This context is fresher than all other contexts so far.
        WithLC = LC;
        for (const LocationContext *LCI = LC; LCI; LCI = LCI->getParent())
          FoundContexts.insert(LCI);
      }
a202 1
  }
d204 2
a205 1
  assert(WithLC);
d207 6
a212 17
  LangOptions LO; // FIXME.
  PrintingPolicy PP(LO);

  Out << NL << NL << "Expressions by stack frame:" << NL;
  WithLC->dumpStack(Out, "", NL, Sep, [&](const LocationContext *LC) {
    for (auto I : ExprBindings) {
      if (I.first.getLocationContext() != LC)
        continue;

      const Stmt *S = I.first.getStmt();
      assert(S != nullptr && "Expected non-null Stmt");

      Out << "(" << (const void *)LC << ',' << (const void *)S << ") ";
      S->printPretty(Out, nullptr, PP);
      Out << " : " << I.second << NL;
    }
  });
@


1.1.1.5
log
@Import clang r337282 from trunk
@
text
@d1 1
a1 1
//===- Environment.cpp - Map from Stmt* to Locations/Values ---------------===//
a13 2
#include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h"
#include "clang/AST/Expr.h"
d15 3
a17 5
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
a18 8
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
a19 1
#include <cassert>
d49 1
a49 1
  if (const auto *E = dyn_cast<Expr>(S))
d55 4
a58 4
    : std::pair<const Stmt *,
                const StackFrameContext *>(ignoreTransparentExprs(S),
                                           L ? L->getStackFrame()
                                             : nullptr) {}
d98 1
a98 1
    const auto *RS = cast<ReturnStmt>(S);
a123 1

a125 1

a127 1

a131 1

d137 1
a137 2

} // namespace
d150 1
d159 1
a159 1
  llvm::ImmutableMapRef<EnvironmentEntry, SVal>
d166 1
d189 13
a201 15
                        const char *Sep, const LocationContext *WithLC) const {
  if (ExprBindings.isEmpty())
    return;

  if (!WithLC) {
    // Find the freshest location context.
    llvm::SmallPtrSet<const LocationContext *, 16> FoundContexts;
    for (auto I : *this) {
      const LocationContext *LC = I.first.getLocationContext();
      if (FoundContexts.count(LC) == 0) {
        // This context is fresher than all other contexts so far.
        WithLC = LC;
        for (const LocationContext *LCI = LC; LCI; LCI = LCI->getParent())
          FoundContexts.insert(LCI);
      }
a202 1
  }
d204 2
a205 1
  assert(WithLC);
d207 6
a212 17
  LangOptions LO; // FIXME.
  PrintingPolicy PP(LO);

  Out << NL << NL << "Expressions by stack frame:" << NL;
  WithLC->dumpStack(Out, "", NL, Sep, [&](const LocationContext *LC) {
    for (auto I : ExprBindings) {
      if (I.first.getLocationContext() != LC)
        continue;

      const Stmt *S = I.first.getStmt();
      assert(S != nullptr && "Expected non-null Stmt");

      Out << "(" << (const void *)LC << ',' << (const void *)S << ") ";
      S->printPretty(Out, nullptr, PP);
      Out << " : " << I.second << NL;
    }
  });
@


1.1.1.6
log
@Mark old LLVM instance as dead.
@
text
@@


1.1.1.3.4.1
log
@file Environment.cpp was added on branch tls-maxphys on 2014-08-19 23:47:32 +0000
@
text
@d1 216
@


1.1.1.3.4.2
log
@Rebase to HEAD as of a few days ago.
@
text
@a0 216
//== Environment.cpp - Map from Stmt* to Locations/Values -------*- C++ -*--==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defined the Environment and EnvironmentManager classes.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace ento;

static const Expr *ignoreTransparentExprs(const Expr *E) {
  E = E->IgnoreParens();

  switch (E->getStmtClass()) {
  case Stmt::OpaqueValueExprClass:
    E = cast<OpaqueValueExpr>(E)->getSourceExpr();
    break;
  case Stmt::ExprWithCleanupsClass:
    E = cast<ExprWithCleanups>(E)->getSubExpr();
    break;
  case Stmt::CXXBindTemporaryExprClass:
    E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
    break;
  case Stmt::SubstNonTypeTemplateParmExprClass:
    E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement();
    break;
  default:
    // This is the base case: we can't look through more than we already have.
    return E;
  }

  return ignoreTransparentExprs(E);
}

static const Stmt *ignoreTransparentExprs(const Stmt *S) {
  if (const Expr *E = dyn_cast<Expr>(S))
    return ignoreTransparentExprs(E);
  return S;
}

EnvironmentEntry::EnvironmentEntry(const Stmt *S, const LocationContext *L)
  : std::pair<const Stmt *,
              const StackFrameContext *>(ignoreTransparentExprs(S),
                                         L ? L->getCurrentStackFrame()
                                           : nullptr) {}

SVal Environment::lookupExpr(const EnvironmentEntry &E) const {
  const SVal* X = ExprBindings.lookup(E);
  if (X) {
    SVal V = *X;
    return V;
  }
  return UnknownVal();
}

SVal Environment::getSVal(const EnvironmentEntry &Entry,
                          SValBuilder& svalBuilder) const {
  const Stmt *S = Entry.getStmt();
  const LocationContext *LCtx = Entry.getLocationContext();

  switch (S->getStmtClass()) {
  case Stmt::CXXBindTemporaryExprClass:
  case Stmt::ExprWithCleanupsClass:
  case Stmt::GenericSelectionExprClass:
  case Stmt::OpaqueValueExprClass:
  case Stmt::ParenExprClass:
  case Stmt::SubstNonTypeTemplateParmExprClass:
    llvm_unreachable("Should have been handled by ignoreTransparentExprs");

  case Stmt::AddrLabelExprClass:
  case Stmt::CharacterLiteralClass:
  case Stmt::CXXBoolLiteralExprClass:
  case Stmt::CXXScalarValueInitExprClass:
  case Stmt::ImplicitValueInitExprClass:
  case Stmt::IntegerLiteralClass:
  case Stmt::ObjCBoolLiteralExprClass:
  case Stmt::CXXNullPtrLiteralExprClass:
  case Stmt::ObjCStringLiteralClass:
  case Stmt::StringLiteralClass:
    // Known constants; defer to SValBuilder.
    return svalBuilder.getConstantVal(cast<Expr>(S)).getValue();

  case Stmt::ReturnStmtClass: {
    const ReturnStmt *RS = cast<ReturnStmt>(S);
    if (const Expr *RE = RS->getRetValue())
      return getSVal(EnvironmentEntry(RE, LCtx), svalBuilder);
    return UndefinedVal();        
  }
    
  // Handle all other Stmt* using a lookup.
  default:
    return lookupExpr(EnvironmentEntry(S, LCtx));
  }
}

Environment EnvironmentManager::bindExpr(Environment Env,
                                         const EnvironmentEntry &E,
                                         SVal V,
                                         bool Invalidate) {
  if (V.isUnknown()) {
    if (Invalidate)
      return Environment(F.remove(Env.ExprBindings, E));
    else
      return Env;
  }
  return Environment(F.add(Env.ExprBindings, E, V));
}

namespace {
class MarkLiveCallback : public SymbolVisitor {
  SymbolReaper &SymReaper;
public:
  MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {}
  bool VisitSymbol(SymbolRef sym) override {
    SymReaper.markLive(sym);
    return true;
  }
  bool VisitMemRegion(const MemRegion *R) override {
    SymReaper.markLive(R);
    return true;
  }
};
} // end anonymous namespace

// removeDeadBindings:
//  - Remove subexpression bindings.
//  - Remove dead block expression bindings.
//  - Keep live block expression bindings:
//   - Mark their reachable symbols live in SymbolReaper,
//     see ScanReachableSymbols.
//   - Mark the region in DRoots if the binding is a loc::MemRegionVal.
Environment
EnvironmentManager::removeDeadBindings(Environment Env,
                                       SymbolReaper &SymReaper,
                                       ProgramStateRef ST) {

  // We construct a new Environment object entirely, as this is cheaper than
  // individually removing all the subexpression bindings (which will greatly
  // outnumber block-level expression bindings).
  Environment NewEnv = getInitialEnvironment();

  MarkLiveCallback CB(SymReaper);
  ScanReachableSymbols RSScaner(ST, CB);

  llvm::ImmutableMapRef<EnvironmentEntry,SVal>
    EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(),
             F.getTreeFactory());

  // Iterate over the block-expr bindings.
  for (Environment::iterator I = Env.begin(), E = Env.end();
       I != E; ++I) {

    const EnvironmentEntry &BlkExpr = I.getKey();
    const SVal &X = I.getData();

    if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) {
      // Copy the binding to the new map.
      EBMapRef = EBMapRef.add(BlkExpr, X);

      // If the block expr's value is a memory region, then mark that region.
      if (Optional<loc::MemRegionVal> R = X.getAs<loc::MemRegionVal>())
        SymReaper.markLive(R->getRegion());

      // Mark all symbols in the block expr's value live.
      RSScaner.scan(X);
      continue;
    } else {
      SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
      for (; SI != SE; ++SI)
        SymReaper.maybeDead(*SI);
    }
  }

  NewEnv.ExprBindings = EBMapRef.asImmutableMap();
  return NewEnv;
}

void Environment::print(raw_ostream &Out, const char *NL,
                        const char *Sep) const {
  bool isFirst = true;

  for (Environment::iterator I = begin(), E = end(); I != E; ++I) {
    const EnvironmentEntry &En = I.getKey();
    
    if (isFirst) {
      Out << NL << NL
          << "Expressions:"
          << NL;      
      isFirst = false;
    } else {
      Out << NL;
    }
    
    const Stmt *S = En.getStmt();
    assert(S != nullptr && "Expected non-null Stmt");

    Out << " (" << (const void*) En.getLocationContext() << ','
      << (const void*) S << ") ";
    LangOptions LO; // FIXME.
    S->printPretty(Out, nullptr, PrintingPolicy(LO));
    Out << " : " << I.getData();
  }
}
@


1.1.1.1.4.1
log
@file Environment.cpp was added on branch yamt-pagecache on 2014-05-22 16:18:31 +0000
@
text
@d1 214
@


1.1.1.1.4.2
log
@sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs.  ("Protocol error: too many arguments")
@
text
@a0 214
//== Environment.cpp - Map from Stmt* to Locations/Values -------*- C++ -*--==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defined the Environment and EnvironmentManager classes.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace ento;

static const Expr *ignoreTransparentExprs(const Expr *E) {
  E = E->IgnoreParens();

  switch (E->getStmtClass()) {
  case Stmt::OpaqueValueExprClass:
    E = cast<OpaqueValueExpr>(E)->getSourceExpr();
    break;
  case Stmt::ExprWithCleanupsClass:
    E = cast<ExprWithCleanups>(E)->getSubExpr();
    break;
  case Stmt::CXXBindTemporaryExprClass:
    E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
    break;
  case Stmt::SubstNonTypeTemplateParmExprClass:
    E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement();
    break;
  default:
    // This is the base case: we can't look through more than we already have.
    return E;
  }

  return ignoreTransparentExprs(E);
}

static const Stmt *ignoreTransparentExprs(const Stmt *S) {
  if (const Expr *E = dyn_cast<Expr>(S))
    return ignoreTransparentExprs(E);
  return S;
}

EnvironmentEntry::EnvironmentEntry(const Stmt *S, const LocationContext *L)
  : std::pair<const Stmt *,
              const StackFrameContext *>(ignoreTransparentExprs(S),
                                         L ? L->getCurrentStackFrame() : 0) {}

SVal Environment::lookupExpr(const EnvironmentEntry &E) const {
  const SVal* X = ExprBindings.lookup(E);
  if (X) {
    SVal V = *X;
    return V;
  }
  return UnknownVal();
}

SVal Environment::getSVal(const EnvironmentEntry &Entry,
                          SValBuilder& svalBuilder) const {
  const Stmt *S = Entry.getStmt();
  const LocationContext *LCtx = Entry.getLocationContext();

  switch (S->getStmtClass()) {
  case Stmt::CXXBindTemporaryExprClass:
  case Stmt::ExprWithCleanupsClass:
  case Stmt::GenericSelectionExprClass:
  case Stmt::OpaqueValueExprClass:
  case Stmt::ParenExprClass:
  case Stmt::SubstNonTypeTemplateParmExprClass:
    llvm_unreachable("Should have been handled by ignoreTransparentExprs");

  case Stmt::AddrLabelExprClass:
  case Stmt::CharacterLiteralClass:
  case Stmt::CXXBoolLiteralExprClass:
  case Stmt::CXXScalarValueInitExprClass:
  case Stmt::ImplicitValueInitExprClass:
  case Stmt::IntegerLiteralClass:
  case Stmt::ObjCBoolLiteralExprClass:
  case Stmt::CXXNullPtrLiteralExprClass:
  case Stmt::ObjCStringLiteralClass:
  case Stmt::StringLiteralClass:
    // Known constants; defer to SValBuilder.
    return svalBuilder.getConstantVal(cast<Expr>(S)).getValue();

  case Stmt::ReturnStmtClass: {
    const ReturnStmt *RS = cast<ReturnStmt>(S);
    if (const Expr *RE = RS->getRetValue())
      return getSVal(EnvironmentEntry(RE, LCtx), svalBuilder);
    return UndefinedVal();        
  }
    
  // Handle all other Stmt* using a lookup.
  default:
    return lookupExpr(EnvironmentEntry(S, LCtx));
  }
}

Environment EnvironmentManager::bindExpr(Environment Env,
                                         const EnvironmentEntry &E,
                                         SVal V,
                                         bool Invalidate) {
  if (V.isUnknown()) {
    if (Invalidate)
      return Environment(F.remove(Env.ExprBindings, E));
    else
      return Env;
  }
  return Environment(F.add(Env.ExprBindings, E, V));
}

namespace {
class MarkLiveCallback : public SymbolVisitor {
  SymbolReaper &SymReaper;
public:
  MarkLiveCallback(SymbolReaper &symreaper) : SymReaper(symreaper) {}
  bool VisitSymbol(SymbolRef sym) {
    SymReaper.markLive(sym);
    return true;
  }
  bool VisitMemRegion(const MemRegion *R) {
    SymReaper.markLive(R);
    return true;
  }
};
} // end anonymous namespace

// removeDeadBindings:
//  - Remove subexpression bindings.
//  - Remove dead block expression bindings.
//  - Keep live block expression bindings:
//   - Mark their reachable symbols live in SymbolReaper,
//     see ScanReachableSymbols.
//   - Mark the region in DRoots if the binding is a loc::MemRegionVal.
Environment
EnvironmentManager::removeDeadBindings(Environment Env,
                                       SymbolReaper &SymReaper,
                                       ProgramStateRef ST) {

  // We construct a new Environment object entirely, as this is cheaper than
  // individually removing all the subexpression bindings (which will greatly
  // outnumber block-level expression bindings).
  Environment NewEnv = getInitialEnvironment();

  MarkLiveCallback CB(SymReaper);
  ScanReachableSymbols RSScaner(ST, CB);

  llvm::ImmutableMapRef<EnvironmentEntry,SVal>
    EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(),
             F.getTreeFactory());

  // Iterate over the block-expr bindings.
  for (Environment::iterator I = Env.begin(), E = Env.end();
       I != E; ++I) {

    const EnvironmentEntry &BlkExpr = I.getKey();
    const SVal &X = I.getData();

    if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) {
      // Copy the binding to the new map.
      EBMapRef = EBMapRef.add(BlkExpr, X);

      // If the block expr's value is a memory region, then mark that region.
      if (Optional<loc::MemRegionVal> R = X.getAs<loc::MemRegionVal>())
        SymReaper.markLive(R->getRegion());

      // Mark all symbols in the block expr's value live.
      RSScaner.scan(X);
      continue;
    } else {
      SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
      for (; SI != SE; ++SI)
        SymReaper.maybeDead(*SI);
    }
  }

  NewEnv.ExprBindings = EBMapRef.asImmutableMap();
  return NewEnv;
}

void Environment::print(raw_ostream &Out, const char *NL,
                        const char *Sep) const {
  bool isFirst = true;

  for (Environment::iterator I = begin(), E = end(); I != E; ++I) {
    const EnvironmentEntry &En = I.getKey();
    
    if (isFirst) {
      Out << NL << NL
          << "Expressions:"
          << NL;      
      isFirst = false;
    } else {
      Out << NL;
    }
    
    const Stmt *S = En.getStmt();
    
    Out << " (" << (const void*) En.getLocationContext() << ','
      << (const void*) S << ") ";
    LangOptions LO; // FIXME.
    S->printPretty(Out, 0, PrintingPolicy(LO));
    Out << " : " << I.getData();
  }
}
@


