Skip to content
UnintializedValues.cpp 3.61 KiB
Newer Older
//==- UninitializedValues.cpp - Find Unintialized Values --------*- C++ --*-==//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Ted Kremenek and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Uninitialized Values analysis for source-level CFGs.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/UninitializedValues.h"
#include "clang/Analysis/CFGVarDeclVisitor.h"
#include "clang/Analysis/CFGStmtVisitor.h"
#include "DataflowSolver.h"

using namespace clang;

//===--------------------------------------------------------------------===//
// Dataflow initialization logic.
//===--------------------------------------------------------------------===//      

namespace {

class RegisterDeclsAndExprs : public CFGVarDeclVisitor<RegisterDeclsAndExprs> {
  UninitializedValues::AnalysisDataTy& AD;
  RegisterDeclsAndExprs(const CFG& cfg, UninitializedValues::AnalysisDataTy& ad)
                        : CFGVarDeclVisitor<RegisterDeclsAndExprs>(cfg), AD(ad)
  {}
  
  void VisitVarDecl(VarDecl* D) {
    if (AD.VMap.find(D) == AD.VMap.end())
      AD.VMap[D] = AD.Counter++;
  }
  
  void BlockStmt_VisitExpr(Expr* E) {
    if (AD.EMap.find(E) == AD.EMap.end())
      AD.EMap[E] = AD.Counter++;
  }        
};
  
} // end anonymous namespace

void UninitializedValues::InitializeValues(const CFG& cfg) {
  RegisterDeclsAndExprs R(cfg,this->getAnalysisData());
  R.VisitAllDecls();    
  getBlockDataMap()[ &cfg.getEntry() ].resize( getAnalysisData().Counter );
}

//===--------------------------------------------------------------------===//
// Transfer functions.
//===--------------------------------------------------------------------===//      

namespace {
class TransferFuncs : public CFGStmtVisitor<TransferFuncs,bool> {
  UninitializedValues::ValTy V;
  UninitializedValues::AnalysisDataTy& AD;
  TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {
    V.resize(AD.Counter);
  }
  
  UninitializedValues::ValTy& getVal() { return V; }
  
//  bool VisitDeclRefExpr(DeclRefExpr* DR);
//  bool VisitBinaryOperator(BinaryOperator* B);
//  bool VisitUnaryOperator(UnaryOperator* U);    
};
} // end anonymous namespace

//===--------------------------------------------------------------------===//
// Merge operator.
//===--------------------------------------------------------------------===//      

namespace {
struct Merge {
  void operator()(UninitializedValues::ValTy& Dst,
                  UninitializedValues::ValTy& Src) {
    assert (Dst.size() == Src.size() && "Bitvector sizes do not match.");
    Src |= Dst;
  }
};
} // end anonymous namespace

//===--------------------------------------------------------------------===//
// Observer to flag warnings for uses of uninitialized variables.
//===--------------------------------------------------------------------===//      




//===--------------------------------------------------------------------===//
// External interface (driver logic).
//===--------------------------------------------------------------------===//      

void UninitializedValues::CheckUninitializedValues(const CFG& cfg) {

  typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver;

  UninitializedValues U;
  
  { // Compute the unitialized values information.
    Solver S(U);
    S.runOnCFG(cfg);
  }

//  WarnObserver O;
  Solver S(U);
    
  for (CFG::const_iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
    S.runOnBlock(&*I);
}