#include "clang/Analysis/CFG.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/OperationKinds.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/ConstructionContext.h"
#include "clang/Analysis/Support/BumpVector.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/ExceptionSpecificationType.h"
#include "clang/Basic/JsonSupport.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DOTGraphTraits.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
usingnamespaceclang;
static SourceLocation GetEndLoc(Decl *D) { … }
static bool IsIntegerLiteralConstantExpr(const Expr *E) { … }
static const Expr *tryTransformToIntOrEnumConstant(const Expr *E) { … }
static std::tuple<const Expr *, BinaryOperatorKind, const Expr *>
tryNormalizeBinaryOperator(const BinaryOperator *B) { … }
static bool areExprTypesCompatible(const Expr *E1, const Expr *E2) { … }
namespace {
class CFGBuilder;
class AddStmtChoice { … };
class LocalScope { … };
}
int LocalScope::const_iterator::distance(LocalScope::const_iterator L) { … }
LocalScope::const_iterator
LocalScope::const_iterator::shared_parent(LocalScope::const_iterator L) { … }
namespace {
struct BlockScopePosPair { … };
class TryResult { … };
}
static TryResult bothKnownTrue(TryResult R1, TryResult R2) { … }
namespace {
class reverse_children { … };
}
reverse_children::reverse_children(Stmt *S) { … }
namespace {
class CFGBuilder { … };
}
Expr *
clang::extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE) { … }
inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
const Stmt *stmt) const { … }
bool CFGBuilder::alwaysAdd(const Stmt *stmt) { … }
static const VariableArrayType *FindVA(const Type *t) { … }
void CFGBuilder::consumeConstructionContext(
const ConstructionContextLayer *Layer, Expr *E) { … }
void CFGBuilder::findConstructionContexts(
const ConstructionContextLayer *Layer, Stmt *Child) { … }
void CFGBuilder::cleanupConstructionContext(Expr *E) { … }
std::unique_ptr<CFG> CFGBuilder::buildCFG(const Decl *D, Stmt *Statement) { … }
CFGBlock *CFGBuilder::createBlock(bool add_successor) { … }
CFGBlock *CFGBuilder::createNoReturnBlock() { … }
CFGBlock *CFGBuilder::addInitializer(CXXCtorInitializer *I) { … }
static QualType getReferenceInitTemporaryType(const Expr *Init,
bool *FoundMTE = nullptr) { … }
void CFGBuilder::addLoopExit(const Stmt *LoopStmt){ … }
void CFGBuilder::addAutomaticObjHandling(LocalScope::const_iterator B,
LocalScope::const_iterator E,
Stmt *S) { … }
void CFGBuilder::addAutomaticObjDestruction(LocalScope::const_iterator B,
LocalScope::const_iterator E,
Stmt *S) { … }
void CFGBuilder::addScopeExitHandling(LocalScope::const_iterator B,
LocalScope::const_iterator E, Stmt *S) { … }
void CFGBuilder::addScopeChangesHandling(LocalScope::const_iterator SrcPos,
LocalScope::const_iterator DstPos,
Stmt *S) { … }
CFGBlock *CFGBuilder::createScopeChangesHandlingBlock(
LocalScope::const_iterator SrcPos, CFGBlock *SrcBlk,
LocalScope::const_iterator DstPos, CFGBlock *DstBlk) { … }
void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) { … }
LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) { … }
void CFGBuilder::addLocalScopeForStmt(Stmt *S) { … }
LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS,
LocalScope* Scope) { … }
bool CFGBuilder::needsAutomaticDestruction(const VarDecl *VD) const { … }
bool CFGBuilder::hasTrivialDestructor(const VarDecl *VD) const { … }
LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD,
LocalScope* Scope) { … }
void CFGBuilder::addLocalScopeAndDtors(Stmt *S) { … }
CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
bool ExternallyDestructed) { … }
CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitChildren(Stmt *S) { … }
CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
AddStmtChoice asc) { … }
static bool isFallthroughStatement(const AttributedStmt *A) { … }
CFGBlock *CFGBuilder::VisitAttributedStmt(AttributedStmt *A,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U, AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitLogicalOperator(BinaryOperator *B) { … }
std::pair<CFGBlock*, CFGBlock*>
CFGBuilder::VisitLogicalOperator(BinaryOperator *B,
Stmt *Term,
CFGBlock *TrueBlock,
CFGBlock *FalseBlock) { … }
CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitNoRecurse(Expr *E, AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) { … }
static bool CanThrow(Expr *E, ASTContext &Ctx) { … }
CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C,
bool ExternallyDestructed) { … }
CFGBlock *CFGBuilder::VisitConditionalOperator(AbstractConditionalOperator *C,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) { … }
CFGBlock *CFGBuilder::VisitDeclSubExpr(DeclStmt *DS) { … }
CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) { … }
CFGBlock *CFGBuilder::VisitReturnStmt(Stmt *S) { … }
CFGBlock *CFGBuilder::VisitCoroutineSuspendExpr(CoroutineSuspendExpr *E,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitSEHExceptStmt(SEHExceptStmt *ES) { … }
CFGBlock *CFGBuilder::VisitSEHFinallyStmt(SEHFinallyStmt *FS) { … }
CFGBlock *CFGBuilder::VisitSEHLeaveStmt(SEHLeaveStmt *LS) { … }
CFGBlock *CFGBuilder::VisitSEHTryStmt(SEHTryStmt *Terminator) { … }
CFGBlock *CFGBuilder::VisitLabelStmt(LabelStmt *L) { … }
CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitLambdaExpr(LambdaExpr *E, AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitGotoStmt(GotoStmt *G) { … }
CFGBlock *CFGBuilder::VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) { … }
CFGBlock *
CFGBuilder::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { … }
CFGBlock *CFGBuilder::VisitObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) { … }
CFGBlock *CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { … }
CFGBlock *CFGBuilder::VisitPseudoObjectExpr(PseudoObjectExpr *E) { … }
CFGBlock *CFGBuilder::VisitWhileStmt(WhileStmt *W) { … }
CFGBlock *CFGBuilder::VisitArrayInitLoopExpr(ArrayInitLoopExpr *A,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt *CS) { … }
CFGBlock *CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { … }
CFGBlock *CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt *Terminator) { … }
CFGBlock *CFGBuilder::VisitObjCMessageExpr(ObjCMessageExpr *ME,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr *T) { … }
CFGBlock *CFGBuilder::VisitCXXTypeidExpr(CXXTypeidExpr *S, AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitDoStmt(DoStmt *D) { … }
CFGBlock *CFGBuilder::VisitContinueStmt(ContinueStmt *C) { … }
CFGBlock *CFGBuilder::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitSwitchStmt(SwitchStmt *Terminator) { … }
static bool shouldAddCase(bool &switchExclusivelyCovered,
const Expr::EvalResult *switchCond,
const CaseStmt *CS,
ASTContext &Ctx) { … }
CFGBlock *CFGBuilder::VisitCaseStmt(CaseStmt *CS) { … }
CFGBlock *CFGBuilder::VisitDefaultStmt(DefaultStmt *Terminator) { … }
CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) { … }
CFGBlock *CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt *CS) { … }
CFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) { … }
CFGBlock *CFGBuilder::VisitExprWithCleanups(ExprWithCleanups *E,
AddStmtChoice asc, bool ExternallyDestructed) { … }
CFGBlock *CFGBuilder::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitCXXNewExpr(CXXNewExpr *NE,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitCXXDeleteExpr(CXXDeleteExpr *DE,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitConstantExpr(ConstantExpr *E, AddStmtChoice asc) { … }
CFGBlock *CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt *I) { … }
CFGBlock *CFGBuilder::VisitForTemporaryDtors(Stmt *E, bool ExternallyDestructed,
TempDtorContext &Context) { … }
CFGBlock *CFGBuilder::VisitChildrenForTemporaryDtors(Stmt *E,
bool ExternallyDestructed,
TempDtorContext &Context) { … }
CFGBlock *CFGBuilder::VisitBinaryOperatorForTemporaryDtors(
BinaryOperator *E, bool ExternallyDestructed, TempDtorContext &Context) { … }
CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
CXXBindTemporaryExpr *E, bool ExternallyDestructed, TempDtorContext &Context) { … }
void CFGBuilder::InsertTempDtorDecisionBlock(const TempDtorContext &Context,
CFGBlock *FalseSucc) { … }
CFGBlock *CFGBuilder::VisitConditionalOperatorForTemporaryDtors(
AbstractConditionalOperator *E, bool ExternallyDestructed,
TempDtorContext &Context) { … }
CFGBlock *CFGBuilder::VisitOMPExecutableDirective(OMPExecutableDirective *D,
AddStmtChoice asc) { … }
CFGBlock *CFG::createBlock() { … }
std::unique_ptr<CFG> CFG::buildCFG(const Decl *D, Stmt *Statement,
ASTContext *C, const BuildOptions &BO) { … }
bool CFG::isLinear() const { … }
const CXXDestructorDecl *
CFGImplicitDtor::getDestructorDecl(ASTContext &astContext) const { … }
CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, bool IsReachable)
: … { … }
CFGBlock::AdjacentBlock::AdjacentBlock(CFGBlock *B, CFGBlock *AlternateBlock)
: … { … }
void CFGBlock::addSuccessor(AdjacentBlock Succ,
BumpVectorContext &C) { … }
bool CFGBlock::FilterEdge(const CFGBlock::FilterOptions &F,
const CFGBlock *From, const CFGBlock *To) { … }
namespace {
class StmtPrinterHelper : public PrinterHelper { … };
class CFGBlockTerminatorPrint
: public StmtVisitor<CFGBlockTerminatorPrint,void> { … };
}
static void print_initializer(raw_ostream &OS, StmtPrinterHelper &Helper,
const CXXCtorInitializer *I) { … }
static void print_construction_context(raw_ostream &OS,
StmtPrinterHelper &Helper,
const ConstructionContext *CC) { … }
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
const CFGElement &E);
void CFGElement::dumpToStream(llvm::raw_ostream &OS) const { … }
static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
const CFGElement &E) { … }
static void print_block(raw_ostream &OS, const CFG* cfg,
const CFGBlock &B,
StmtPrinterHelper &Helper, bool print_edges,
bool ShowColors) { … }
void CFG::dump(const LangOptions &LO, bool ShowColors) const { … }
void CFG::print(raw_ostream &OS, const LangOptions &LO, bool ShowColors) const { … }
size_t CFGBlock::getIndexInCFG() const { … }
void CFGBlock::dump(const CFG* cfg, const LangOptions &LO,
bool ShowColors) const { … }
LLVM_DUMP_METHOD void CFGBlock::dump() const { … }
void CFGBlock::print(raw_ostream &OS, const CFG* cfg,
const LangOptions &LO, bool ShowColors) const { … }
void CFGBlock::printTerminator(raw_ostream &OS,
const LangOptions &LO) const { … }
void CFGBlock::printTerminatorJson(raw_ostream &Out, const LangOptions &LO,
bool AddQuotes) const { … }
static bool isImmediateSinkBlock(const CFGBlock *Blk) { … }
bool CFGBlock::isInevitablySinking() const { … }
const Expr *CFGBlock::getLastCondition() const { … }
Stmt *CFGBlock::getTerminatorCondition(bool StripParens) { … }
static StmtPrinterHelper *GraphHelper;
void CFG::viewCFG(const LangOptions &LO) const { … }
namespace llvm {
template<>
struct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits { … };
}