;
41#define DEBUG_LOGGING 0 46 for(
const auto*FD : RD->
fields()) {
47 if(FD->isUnnamedBitField())
49 if(FD->isZeroSize(FD->getASTContext()))
53 if(
const auto*FieldRD = FD->getType()->getAsRecordDecl();
79llvm::DenseMap<const VarDecl *, unsigned> map;
82DeclToIndex() =
default;
88 unsignedsize()
const{
returnmap.size(); }
91std::optional<unsigned> getValueIndex(
const VarDecl*d)
const;
96voidDeclToIndex::computeMap(
const DeclContext&dc) {
100 for( ; I !=
E; ++I) {
107std::optional<unsigned> DeclToIndex::getValueIndex(
const VarDecl*d)
const{
108llvm::DenseMap<const VarDecl *, unsigned>::const_iterator I = map.find(d);
135usingValueVector = llvm::PackedVector<Value, 2, llvm::SmallBitVector>;
137classCFGBlockValues {
141DeclToIndex declToIndex;
144CFGBlockValues(
const CFG&cfg);
146 unsignedgetNumEntries()
const{
returndeclToIndex.size(); }
148 voidcomputeSetOfDeclarations(
const DeclContext&dc);
150ValueVector &getValueVector(
const CFGBlock*block) {
154 voidsetAllScratchValues(
Value V);
155 voidmergeIntoScratch(ValueVector
const&source,
boolisFirst);
156 boolupdateValueVectorWithScratch(
const CFGBlock*block);
158 boolhasNoDeclarations()
const{
159 returndeclToIndex.size() == 0;
164ValueVector::reference operator[](
const VarDecl*vd);
168std::optional<unsigned> idx = declToIndex.getValueIndex(vd);
169 returngetValueVector(block)[*idx];
175CFGBlockValues::CFGBlockValues(
const CFG&
c) : cfg(
c), vals(0) {}
177voidCFGBlockValues::computeSetOfDeclarations(
const DeclContext&dc) {
178declToIndex.computeMap(dc);
179 unsigneddecls = declToIndex.size();
180scratch.resize(decls);
185 for(
auto&val : vals)
190static voidprintVector(
const CFGBlock*block, ValueVector &bv,
192llvm::errs() << block->
getBlockID() <<
" :";
193 for(
const auto&i : bv)
194llvm::errs() <<
' '<< i;
195llvm::errs() <<
" : "<< num <<
'\n';
199voidCFGBlockValues::setAllScratchValues(
Value V) {
200 for(
unsignedI = 0,
E= scratch.size(); I !=
E; ++I)
204voidCFGBlockValues::mergeIntoScratch(ValueVector
const&source,
212boolCFGBlockValues::updateValueVectorWithScratch(
const CFGBlock*block) {
213ValueVector &dst = getValueVector(block);
214 boolchanged = (dst != scratch);
218printVector(block, scratch, 0);
223voidCFGBlockValues::resetScratch() {
227ValueVector::reference CFGBlockValues::operator[](
const VarDecl*vd) {
228 returnscratch[*declToIndex.getValueIndex(vd)];
244 const DeclRefExpr*getDeclRefExpr()
const{
returndr; }
245 const VarDecl*getDecl()
const{
returnvd; }
253 if(
const auto*CE = dyn_cast<CastExpr>(Ex)) {
254 if(CE->getCastKind() == CK_LValueBitCast) {
255Ex = CE->getSubExpr();
267 if(
const auto*DRE =
269 if(
const auto*VD = dyn_cast<VarDecl>(DRE->getDecl()))
271 returnFindVarResult(VD, DRE);
272 returnFindVarResult(
nullptr,
nullptr);
280classClassifyRefs :
public StmtVisitor<ClassifyRefs> {
292llvm::DenseMap<const DeclRefExpr *, Class> Classification;
295return ::isTrackedVar(VD, DC);
298 voidclassify(
const Expr*
E, Class
C);
313llvm::DenseMap<const DeclRefExpr*, Class>::const_iterator I
314= Classification.find(DRE);
315 if(I != Classification.end())
318 const auto*VD = dyn_cast<VarDecl>(DRE->
getDecl());
334 if(DRE && DRE->
getDecl() == VD)
340voidClassifyRefs::classify(
const Expr*
E, Class
C) {
343 if(
const auto*CO = dyn_cast<ConditionalOperator>(
E)) {
344classify(CO->getTrueExpr(),
C);
345classify(CO->getFalseExpr(),
C);
349 if(
const auto*BCO = dyn_cast<BinaryConditionalOperator>(
E)) {
350classify(BCO->getFalseExpr(),
C);
354 if(
const auto*OVE = dyn_cast<OpaqueValueExpr>(
E)) {
355classify(OVE->getSourceExpr(),
C);
359 if(
const auto*ME = dyn_cast<MemberExpr>(
E)) {
360 if(
const auto*VD = dyn_cast<VarDecl>(ME->getMemberDecl())) {
361 if(!VD->isStaticDataMember())
362classify(ME->getBase(),
C);
367 if(
const auto*BO = dyn_cast<BinaryOperator>(
E)) {
368 switch(BO->getOpcode()) {
371classify(BO->getLHS(),
C);
374classify(BO->getRHS(),
C);
381FindVarResult Var =
findVar(
E, DC);
382 if(
const DeclRefExpr*DRE = Var.getDeclRefExpr())
383Classification[DRE] = std::max(Classification[DRE],
C);
386voidClassifyRefs::VisitDeclStmt(
DeclStmt*DS) {
387 for(
auto*DI : DS->
decls()) {
388 auto*VD = dyn_cast<VarDecl>(DI);
391Classification[DRE] = SelfInit;
402classify(BO->
getLHS(), Use);
404classify(BO->
getLHS(), Ignore);
416classify(cast<Expr>(S), Use);
426 returnFTD->getTemplatedDecl()->hasTrivialBody();
427 returnFD->hasTrivialBody();
432voidClassifyRefs::VisitCallExpr(
CallExpr*CE) {
437classify(CE->
getArg(0), Use);
448 if((*I)->isGLValue()) {
449 if((*I)->getType().isConstQualified())
450classify((*I), isTrivialBody ? Ignore : ConstRefUse);
453 const auto*UO = dyn_cast<UnaryOperator>(Ex);
454 if(UO && UO->
getOpcode() == UO_AddrOf)
456classify(Ex, Ignore);
461voidClassifyRefs::VisitCastExpr(
CastExpr*CE) {
464 else if(
const auto*CSE = dyn_cast<CStyleCastExpr>(CE)) {
465 if(CSE->getType()->isVoidType()) {
469classify(CSE->getSubExpr(), Ignore);
480classTransferFunctions :
public StmtVisitor<TransferFunctions> {
481CFGBlockValues &vals;
485 constClassifyRefs &classification;
490TransferFunctions(CFGBlockValues &vals,
const CFG&cfg,
492 constClassifyRefs &classification,
494: vals(vals), cfg(cfg), block(block), ac(ac),
495classification(classification), objCNoRet(ac.getASTContext()),
498 voidreportUse(
const Expr*ex,
const VarDecl*vd);
499 voidreportConstRefUse(
const Expr*ex,
const VarDecl*vd);
512return ::isTrackedVar(vd, cast<DeclContext>(ac.
getDecl()));
516return ::findVar(ex, cast<DeclContext>(ac.
getDecl()));
574Queue.push_back(block);
579 while(!Queue.empty()) {
580 const CFGBlock*B = Queue.pop_back_val();
584Use.setUninitAfterCall();
592 ValueAtPredExit = vals.getValue(Pred, B, vd);
603Use.setUninitAfterDecl();
607 unsigned&SV = SuccsVisited[Pred->
getBlockID()];
621Queue.push_back(Pred);
627 for(
const auto*
Block: cfg) {
630 if(SuccsVisited[BlockID] && SuccsVisited[BlockID] <
Block->
succ_size() &&
644 if(isa<SwitchStmt>(Term)) {
652Use.addUninitBranch(Branch);
657Use.addUninitBranch(Branch);
670voidTransferFunctions::reportUse(
const Expr*ex,
const VarDecl*vd) {
676voidTransferFunctions::reportConstRefUse(
const Expr*ex,
const VarDecl*vd) {
684 if(
const auto*DS = dyn_cast<DeclStmt>(FS->getElement())) {
691voidTransferFunctions::VisitOMPExecutableDirective(
694assert(S &&
"Expected non-null used-in-clause child.");
701voidTransferFunctions::VisitBlockExpr(
BlockExpr*be) {
703 for(
const auto&I : bd->
captures()) {
704 const VarDecl*vd = I.getVariable();
715voidTransferFunctions::VisitCallExpr(
CallExpr*ce) {
717 if(
Callee->hasAttr<ReturnsTwiceAttr>()) {
725 else if(
Callee->hasAttr<AnalyzerNoReturnAttr>()) {
733vals.setAllScratchValues(
Unknown);
738voidTransferFunctions::VisitDeclRefExpr(
DeclRefExpr*dr) {
739 switch(classification.get(dr)) {
740 caseClassifyRefs::Ignore:
742 caseClassifyRefs::Use:
743reportUse(dr, cast<VarDecl>(dr->
getDecl()));
745 caseClassifyRefs::Init:
748 caseClassifyRefs::SelfInit:
751 caseClassifyRefs::ConstRefUse:
752reportConstRefUse(dr, cast<VarDecl>(dr->
getDecl()));
760 if(
const VarDecl*VD = Var.getDecl())
765voidTransferFunctions::VisitDeclStmt(
DeclStmt*DS) {
766 for(
auto*DI : DS->
decls()) {
767 auto*VD = dyn_cast<VarDecl>(DI);
781}
else if(VD->getInit()) {
801voidTransferFunctions::VisitGCCAsmStmt(
GCCAsmStmt*as) {
812 while(
const auto*UO = dyn_cast<UnaryOperator>(Ex))
828vals.setAllScratchValues(
Unknown);
838 constClassifyRefs &classification,
839llvm::BitVector &wasAnalyzed,
844 boolisFirst =
true;
851vals.mergeIntoScratch(vals.getValueVector(pred), isFirst);
856TransferFunctions tf(vals, cfg, block, ac, classification, handler);
857 for(
const auto&I : *block) {
858 if(std::optional<CFGStmt> cs = I.getAs<
CFGStmt>())
859tf.Visit(
const_cast<Stmt*
>(cs->getStmt()));
862 if(
auto*as = dyn_cast_or_null<GCCAsmStmt>(terminator.
getStmt()))
865 returnvals.updateValueVectorWithScratch(block);
876llvm::BitVector hadUse;
879 boolhadAnyUse =
false;
882 unsignedcurrentBlock = 0;
884PruneBlocksHandler(
unsignednumBlocks) : hadUse(numBlocks,
false) {}
886~PruneBlocksHandler()
override=
default;
890hadUse[currentBlock] =
true;
896hadUse[currentBlock] =
true;
904hadUse[currentBlock] =
true;
917CFGBlockValues vals(cfg);
918vals.computeSetOfDeclarations(dc);
919 if(vals.hasNoDeclarations())
925ClassifyRefs classification(ac);
930ValueVector &vec = vals.getValueVector(&entry);
931 const unsignedn = vals.getNumEntries();
932 for(
unsignedj = 0; j < n; ++j) {
948 boolchanged =
runOnBlock(block, cfg, ac, vals,
949classification, wasAnalyzed, PBH);
951 if(changed || !previouslyVisited[block->
getBlockID()])
953previouslyVisited[block->
getBlockID()] =
true;
960 for(
const auto*block : cfg)
962 runOnBlock(block, cfg, ac, vals, classification, wasAnalyzed, handler);
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the Objective-C statement AST node classes.
C Language Family Type Representation.
static bool isAlwaysUninit(const Value v)
static bool isTrackedVar(const VarDecl *vd, const DeclContext *dc)
static const Expr * stripCasts(ASTContext &C, const Expr *Ex)
static bool isUninitialized(const Value v)
static bool isPointerToConst(const QualType &QT)
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 bool hasTrivialBody(CallExpr *CE)
static bool recordIsNotEmpty(const RecordDecl *RD)
static const DeclRefExpr * getSelfInitExpr(VarDecl *VD)
static bool runOnBlock(const CFGBlock *block, const CFG &cfg, AnalysisDeclContext &ac, CFGBlockValues &vals, const ClassifyRefs &classification, llvm::BitVector &wasAnalyzed, UninitVariablesHandler &handler)
__device__ __2f16 float c
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, method or block under analysis.
const Decl * getDecl() const
ASTContext & getASTContext() const
A builtin binary operation expression such as "x + y" or "x <= y".
static bool isCompoundAssignmentOp(Opcode Opc)
Represents a block literal declaration, which is like an unnamed FunctionDecl.
ArrayRef< Capture > captures() const
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
const BlockDecl * getBlockDecl() const
Represents a single basic block in a source-level CFG.
CFGTerminator getTerminator() const
succ_iterator succ_begin()
Stmt * getTerminatorStmt()
AdjacentBlocks::const_iterator const_pred_iterator
pred_iterator pred_begin()
unsigned getBlockID() const
AdjacentBlocks::const_iterator const_succ_iterator
unsigned succ_size() const
Represents CFGBlock terminator statement.
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
void VisitBlockStmts(Callback &O) const
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
bool isCallToStdMove() const
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CastKind getCastKind() const
const CFGBlock * dequeue()
specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
ASTContext & getParentASTContext() const
decl_iterator decls_end() const
decl_iterator decls_begin() const
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
const Decl * getSingleDecl() const
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
DeclContext * getDeclContext()
This represents one expression.
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Represents a function declaration or definition.
Declaration of a template function.
This represents a GCC inline-assembly statement extension.
This is a basic class for representing single OpenMP executable directive.
ArrayRef< OMPClause * > clauses() const
const Stmt * getStructuredBlock() const
Returns the AST node representing OpenMP structured-block of this OpenMP executable directive,...
bool isStandaloneDirective() const
Returns whether or not this is a Standalone directive.
static llvm::iterator_range< used_clauses_child_iterator > used_clauses_children(ArrayRef< OMPClause * > Clauses)
Represents Objective-C's collection statement.
An expression that sends a message to the given Objective-C object or class.
bool isImplicitNoReturn(const ObjCMessageExpr *ME)
Return true if the given message expression is known to never return.
A (possibly-)qualified type.
bool isConstQualified() const
Determine whether this type is const-qualified.
Represents a struct/union/class.
field_range fields() const
RetTy Visit(PTR(Stmt) S, ParamTys... P)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
bool isScalarType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isVectorType() const
bool isRVVSizelessBuiltinType() const
Returns true for RVV scalable vector types.
bool isAnyPointerType() const
bool isRecordType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Expr * getSubExpr() const
static bool isIncrementDecrementOp(Opcode Op)
A use of a variable, which might be uninitialized.
@ Always
The use is always uninitialized.
virtual void handleUseOfUninitVariable(const VarDecl *vd, const UninitUse &use)
Called when the uninitialized variable is used at the given expression.
virtual void handleSelfInit(const VarDecl *vd)
Called when the uninitialized variable analysis detects the idiom 'int x = x'.
virtual ~UninitVariablesHandler()
virtual void handleConstRefUseOfUninitVariable(const VarDecl *vd, const UninitUse &use)
Called when the uninitialized variable is used as const refernce argument.
Represents a variable declaration or definition.
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isExceptionVariable() const
Determine whether this variable is the exception variable in a C++ catch statememt or an Objective-C ...
const Expr * getInit() const
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
BlockID
The various types of blocks that can occur within a API notes file.
The JSON file list parser is used to communicate input to InstallAPI.
void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, AnalysisDeclContext &ac, UninitVariablesHandler &handler, UninitVariablesAnalysisStats &stats)
U cast(CodeGen::Address addr)
@ Class
The "class" keyword introduces the elaborated-type-specifier.
A worklist implementation for forward dataflow analysis.
void enqueueSuccessors(const CFGBlock *Block)
Iterator for iterating over Stmt * arrays that contain only T *.
unsigned NumVariablesAnalyzed
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4