28 #include "llvm/ADT/BitVector.h" 29 #include "llvm/ADT/DenseMap.h" 30 #include "llvm/ADT/None.h" 31 #include "llvm/ADT/Optional.h" 32 #include "llvm/ADT/PackedVector.h" 33 #include "llvm/ADT/SmallBitVector.h" 34 #include "llvm/ADT/SmallVector.h" 35 #include "llvm/Support/Casting.h" 39 using namespace clang;
41 #define DEBUG_LOGGING 0 60 llvm::DenseMap<const VarDecl *, unsigned> map;
63 DeclToIndex() =
default;
69 unsigned size()
const {
return map.size(); }
77 void DeclToIndex::computeMap(
const DeclContext &dc) {
81 for ( ; I != E; ++I) {
89 llvm::DenseMap<const VarDecl *, unsigned>::const_iterator I = map.find(d);
116 using ValueVector = llvm::PackedVector<Value, 2, llvm::SmallBitVector>;
118 class CFGBlockValues {
122 DeclToIndex declToIndex;
125 CFGBlockValues(
const CFG &cfg);
127 unsigned getNumEntries()
const {
return declToIndex.size(); }
129 void computeSetOfDeclarations(
const DeclContext &dc);
131 ValueVector &getValueVector(
const CFGBlock *block) {
135 void setAllScratchValues(
Value V);
136 void mergeIntoScratch(ValueVector
const &source,
bool isFirst);
137 bool updateValueVectorWithScratch(
const CFGBlock *block);
139 bool hasNoDeclarations()
const {
140 return declToIndex.size() == 0;
145 ValueVector::reference operator[](
const VarDecl *vd);
150 assert(idx.hasValue());
151 return getValueVector(block)[idx.getValue()];
157 CFGBlockValues::CFGBlockValues(
const CFG &c) : cfg(c), vals(0) {}
159 void CFGBlockValues::computeSetOfDeclarations(
const DeclContext &dc) {
160 declToIndex.computeMap(dc);
161 unsigned decls = declToIndex.size();
162 scratch.resize(decls);
163 unsigned n = cfg.getNumBlockIDs();
167 for (
auto &val : vals)
172 static void printVector(
const CFGBlock *block, ValueVector &bv,
175 for (
const auto &i : bv)
176 llvm::errs() <<
' ' << i;
177 llvm::errs() <<
" : " << num <<
'\n';
181 void CFGBlockValues::setAllScratchValues(
Value V) {
182 for (
unsigned I = 0, E = scratch.size(); I != E; ++I)
186 void CFGBlockValues::mergeIntoScratch(ValueVector
const &source,
194 bool CFGBlockValues::updateValueVectorWithScratch(
const CFGBlock *block) {
195 ValueVector &dst = getValueVector(block);
196 bool changed = (dst != scratch);
200 printVector(block, scratch, 0);
205 void CFGBlockValues::resetScratch() {
209 ValueVector::reference CFGBlockValues::operator[](
const VarDecl *vd) {
211 assert(idx.hasValue());
212 return scratch[idx.getValue()];
221 class DataflowWorklist {
224 llvm::BitVector enqueuedBlocks;
228 : PO_I(view.
begin()), PO_E(view.
end()),
233 enqueuedBlocks[(*PO_I)->getBlockID()] =
false;
238 void enqueueSuccessors(
const CFGBlock *block);
244 void DataflowWorklist::enqueueSuccessors(
const CFGBlock *block) {
246 E = block->
succ_end(); I != E; ++I) {
248 if (!Successor || enqueuedBlocks[Successor->
getBlockID()])
250 worklist.push_back(Successor);
251 enqueuedBlocks[Successor->
getBlockID()] =
true;
255 const CFGBlock *DataflowWorklist::dequeue() {
260 if (!worklist.empty())
261 B = worklist.pop_back_val();
265 else if (PO_I != PO_E) {
272 assert(enqueuedBlocks[B->
getBlockID()] ==
true);
283 class FindVarResult {
290 const DeclRefExpr *getDeclRefExpr()
const {
return dr; }
291 const VarDecl *getDecl()
const {
return vd; }
299 if (
const auto *CE = dyn_cast<CastExpr>(Ex)) {
300 if (CE->getCastKind() == CK_LValueBitCast) {
301 Ex = CE->getSubExpr();
313 if (
const auto *DRE =
315 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
317 return FindVarResult(VD, DRE);
318 return FindVarResult(
nullptr,
nullptr);
326 class ClassifyRefs :
public StmtVisitor<ClassifyRefs> {
337 llvm::DenseMap<const DeclRefExpr *, Class> Classification;
343 void classify(
const Expr *E, Class
C);
355 void operator()(
Stmt *S) { Visit(S); }
358 llvm::DenseMap<const DeclRefExpr*, Class>::const_iterator I
359 = Classification.find(DRE);
360 if (I != Classification.end())
363 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
379 if (DRE && DRE->getDecl() == VD)
385 void ClassifyRefs::classify(
const Expr *E, Class
C) {
388 if (
const auto *CO = dyn_cast<ConditionalOperator>(E)) {
389 classify(CO->getTrueExpr(),
C);
390 classify(CO->getFalseExpr(),
C);
394 if (
const auto *BCO = dyn_cast<BinaryConditionalOperator>(E)) {
395 classify(BCO->getFalseExpr(),
C);
399 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(E)) {
400 classify(OVE->getSourceExpr(),
C);
404 if (
const auto *ME = dyn_cast<MemberExpr>(E)) {
405 if (
const auto *VD = dyn_cast<VarDecl>(ME->getMemberDecl())) {
406 if (!VD->isStaticDataMember())
407 classify(ME->getBase(),
C);
412 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
413 switch (BO->getOpcode()) {
416 classify(BO->getLHS(),
C);
419 classify(BO->getRHS(),
C);
426 FindVarResult Var =
findVar(E, DC);
428 Classification[DRE] =
std::max(Classification[DRE], C);
431 void ClassifyRefs::VisitDeclStmt(
DeclStmt *DS) {
432 for (
auto *DI : DS->
decls()) {
433 auto *VD = dyn_cast<
VarDecl>(DI);
436 Classification[DRE] = SelfInit;
447 classify(BO->
getLHS(), Use);
449 classify(BO->
getLHS(), Ignore);
461 classify(cast<Expr>(S), Use);
468 void ClassifyRefs::VisitCallExpr(
CallExpr *CE) {
473 classify(CE->
getArg(0), Use);
482 if ((*I)->isGLValue()) {
483 if ((*I)->getType().isConstQualified())
484 classify((*I), Ignore);
488 if (UO && UO->getOpcode() == UO_AddrOf)
489 Ex = UO->getSubExpr();
490 classify(Ex, Ignore);
495 void ClassifyRefs::VisitCastExpr(
CastExpr *CE) {
498 else if (
const auto *CSE = dyn_cast<CStyleCastExpr>(CE)) {
499 if (CSE->getType()->isVoidType()) {
503 classify(CSE->getSubExpr(), Ignore);
514 class TransferFunctions :
public StmtVisitor<TransferFunctions> {
515 CFGBlockValues &vals;
519 const ClassifyRefs &classification;
524 TransferFunctions(CFGBlockValues &vals,
const CFG &cfg,
526 const ClassifyRefs &classification,
528 : vals(vals), cfg(cfg), block(block), ac(ac),
529 classification(classification), objCNoRet(ac.
getASTContext()),
606 Queue.push_back(block);
611 while (!Queue.empty()) {
612 const CFGBlock *B = Queue.pop_back_val();
624 Value AtPredExit = vals.getValue(Pred, B, vd);
639 unsigned &SV = SuccsVisited[Pred->
getBlockID()];
653 Queue.push_back(Pred);
659 for (
const auto *Block : cfg) {
660 unsigned BlockID = Block->getBlockID();
661 const Stmt *Term = Block->getTerminatorStmt();
662 if (SuccsVisited[BlockID] && SuccsVisited[BlockID] < Block->succ_size() &&
668 E = Block->succ_end(); I != E; ++I) {
676 if (isa<SwitchStmt>(Term)) {
678 if (!Label || !isa<SwitchCase>(Label))
688 Branch.
Output = I - Block->succ_begin();
702 void TransferFunctions::reportUse(
const Expr *ex,
const VarDecl *vd) {
705 handler.handleUseOfUninitVariable(vd, getUninitUse(ex, vd, v));
710 if (
const auto *DS = dyn_cast<DeclStmt>(FS->
getElement())) {
717 void TransferFunctions::VisitOMPExecutableDirective(
720 assert(S &&
"Expected non-null used-in-clause child.");
727 void TransferFunctions::VisitBlockExpr(
BlockExpr *be) {
729 for (
const auto &I : bd->
captures()) {
730 const VarDecl *vd = I.getVariable();
741 void TransferFunctions::VisitCallExpr(
CallExpr *ce) {
743 if (Callee->hasAttr<ReturnsTwiceAttr>()) {
751 else if (Callee->hasAttr<AnalyzerNoReturnAttr>()) {
759 vals.setAllScratchValues(
Unknown);
764 void TransferFunctions::VisitDeclRefExpr(
DeclRefExpr *dr) {
765 switch (classification.get(dr)) {
766 case ClassifyRefs::Ignore:
768 case ClassifyRefs::Use:
769 reportUse(dr, cast<VarDecl>(dr->
getDecl()));
771 case ClassifyRefs::Init:
774 case ClassifyRefs::SelfInit:
775 handler.handleSelfInit(cast<VarDecl>(dr->
getDecl()));
783 if (
const VarDecl *VD = Var.getDecl())
788 void TransferFunctions::VisitDeclStmt(
DeclStmt *DS) {
789 for (
auto *DI : DS->
decls()) {
790 auto *VD = dyn_cast<
VarDecl>(DI);
804 }
else if (VD->getInit()) {
827 if (objCNoRet.isImplicitNoReturn(ME)) {
828 vals.setAllScratchValues(
Unknown);
838 const ClassifyRefs &classification,
839 llvm::BitVector &wasAnalyzed,
846 E = block->
pred_end(); I != E; ++I) {
851 vals.mergeIntoScratch(vals.getValueVector(pred), isFirst);
856 TransferFunctions tf(vals, cfg, block, ac, classification, handler);
857 for (
const auto &I : *block) {
859 tf.Visit(const_cast<Stmt *>(cs->getStmt()));
861 return vals.updateValueVectorWithScratch(block);
872 llvm::BitVector hadUse;
875 bool hadAnyUse =
false;
878 unsigned currentBlock = 0;
880 PruneBlocksHandler(
unsigned numBlocks) : hadUse(numBlocks,
false) {}
882 ~PruneBlocksHandler()
override =
default;
884 void handleUseOfUninitVariable(
const VarDecl *vd,
886 hadUse[currentBlock] =
true;
893 void handleSelfInit(
const VarDecl *vd)
override {
894 hadUse[currentBlock] =
true;
907 CFGBlockValues vals(cfg);
908 vals.computeSetOfDeclarations(dc);
909 if (vals.hasNoDeclarations())
915 ClassifyRefs classification(ac);
920 ValueVector &vec = vals.getValueVector(&entry);
921 const unsigned n = vals.getNumEntries();
922 for (
unsigned j = 0; j < n; ++j) {
929 worklist.enqueueSuccessors(&cfg.
getEntry());
934 while (
const CFGBlock *block = worklist.dequeue()) {
938 bool changed =
runOnBlock(block, cfg, ac, vals,
939 classification, wasAnalyzed, PBH);
941 if (changed || !previouslyVisited[block->
getBlockID()])
942 worklist.enqueueSuccessors(block);
943 previouslyVisited[block->
getBlockID()] =
true;
950 for (
const auto *block : cfg)
952 runOnBlock(block, cfg, ac, vals, classification, wasAnalyzed, handler);
const BlockDecl * getBlockDecl() const
bool isCallToStdMove() const
static llvm::iterator_range< used_clauses_child_iterator > used_clauses_children(ArrayRef< OMPClause *> Clauses)
A (possibly-)qualified type.
ArrayRef< OMPClause * > clauses()
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
AdjacentBlocks::const_iterator const_pred_iterator
virtual ~UninitVariablesHandler()
succ_iterator succ_begin()
Stmt - This represents one statement.
bool isStandaloneDirective() const
Returns whether or not this is a Standalone directive.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
C Language Family Type Representation.
bool isRecordType() const
unsigned getBlockID() const
static bool isPointerToConst(const QualType &QT)
Decl - This represents one declaration (or definition), e.g.
static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc)
static const Expr * stripCasts(ASTContext &C, const Expr *Ex)
unsigned succ_size() const
Represents a variable declaration or definition.
ASTContext & getASTContext() const
Defines the Objective-C statement AST node classes.
void setUninitAfterCall()
Kind getKind() const
Get the kind of uninitialized use.
const Stmt * getStructuredBlock() const
Returns the AST node representing OpenMP structured-block of this OpenMP executable directive...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
AnalysisDeclContext contains the context data for the function or method under analysis.
static bool isIncrementDecrementOp(Opcode Op)
__DEVICE__ int max(int __a, int __b)
static bool isAlwaysUninit(const Value v)
AdjacentBlocks::const_iterator const_succ_iterator
static bool runOnBlock(const CFGBlock *block, const CFG &cfg, AnalysisDeclContext &ac, CFGBlockValues &vals, const ClassifyRefs &classification, llvm::BitVector &wasAnalyzed, UninitVariablesHandler &handler)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
T * getAnalysis()
Return the specified analysis object, lazily running the analysis if necessary.
A builtin binary operation expression such as "x + y" or "x <= y".
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
bool isScalarType() const
Represents a single basic block in a source-level CFG.
Represents a block literal declaration, which is like an unnamed FunctionDecl.
This represents one expression.
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
bool isExceptionVariable() const
Determine whether this variable is the exception variable in a C++ catch statememt or an Objective-C ...
DeclContext * getDeclContext()
static FindVarResult findVar(const Expr *E, const DeclContext *DC)
If E is an expression comprising a reference to a single variable, find that variable.
static SVal getValue(SVal val, SValBuilder &svalBuilder)
void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, AnalysisDeclContext &ac, UninitVariablesHandler &handler, UninitVariablesAnalysisStats &stats)
An expression that sends a message to the given Objective-C object or class.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
A use of a variable, which might be uninitialized.
bool isConstQualified() const
Determine whether this type is const-qualified.
decl_iterator decls_begin() const
Expr * getSubExpr() const
This is a basic class for representing single OpenMP executable directive.
CastKind getCastKind() const
ASTContext & getASTContext() const LLVM_READONLY
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
const Decl * getDecl() const
bool isAnyPointerType() const
std::vector< const CFGBlock * >::reverse_iterator iterator
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
bool isVectorType() const
static const DeclRefExpr * getSelfInitExpr(VarDecl *VD)
pred_iterator pred_begin()
Dataflow Directional Tag Classes.
void VisitBlockStmts(CALLBACK &O) const
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
ArrayRef< Capture > captures() const
const Expr * getInit() const
void setUninitAfterDecl()
const Decl * getSingleDecl() const
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext, providing only those that are of type SpecificDecl (or a class derived from it).
Iterator for iterating over Stmt * arrays that contain only T *.
The use is always uninitialized.
Represents Objective-C's collection statement.
static bool isCompoundAssignmentOp(Opcode Opc)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
ASTContext & getParentASTContext() const
A reference to a declared variable, function, enum, etc.
unsigned NumVariablesAnalyzed
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
void addUninitBranch(Branch B)
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parenthese and casts which do not change the value (including ptr->int casts of the sam...
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point...
decl_iterator decls_end() const
static bool isUninitialized(const Value v)