//===--- CFG.h - Classes for representing and building CFGs------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the CFG and CFGBuilder classes for representing and
// building Control-Flow Graphs (CFGs) from ASTs.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_CFG_H
#define LLVM_CLANG_CFG_H
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/DenseMap.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/Support/BumpVector.h"
#include "clang/Basic/SourceLocation.h"
#include <bitset>
#include <cassert>
#include <iterator>
namespace clang {
class CXXDestructorDecl;
class Decl;
class Stmt;
class Expr;
class FieldDecl;
class VarDecl;
class CXXCtorInitializer;
class CXXBaseSpecifier;
class CXXBindTemporaryExpr;
class CFG;
class PrinterHelper;
class LangOptions;
class ASTContext;
/// CFGElement - Represents a top-level expression in a basic block.
class CFGElement {
public:
enum Kind {
// main kind
Invalid,
Statement,
Initializer,
// dtor kind
AutomaticObjectDtor,
BaseDtor,
MemberDtor,
TemporaryDtor,
DTOR_BEGIN = AutomaticObjectDtor,
DTOR_END = TemporaryDtor
};
protected:
// The int bits are used to mark the kind.
llvm::PointerIntPair<void *, 2> Data1;
llvm::PointerIntPair<void *, 2> Data2;
CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = 0)
: Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3),
Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {}
public:
CFGElement() {}
Kind getKind() const {
unsigned x = Data2.getInt();
x <<= 2;
x |= Data1.getInt();
return (Kind) x;
}
bool isValid() const { return getKind() != Invalid; }
operator bool() const { return isValid(); }
template<class ElemTy> const ElemTy *getAs() const {
if (llvm::isa<ElemTy>(this))
return static_cast<const ElemTy*>(this);
return 0;
}
static bool classof(const CFGElement *E) { return true; }
};
class CFGStmt : public CFGElement {
public:
CFGStmt(Stmt *S) : CFGElement(Statement, S) {}
const Stmt *getStmt() const {
return static_cast<const Stmt *>(Data1.getPointer());
}
static bool classof(const CFGElement *E) {
return E->getKind() == Statement;
}
};
/// CFGInitializer - Represents C++ base or member initializer from
/// constructor's initialization list.
class CFGInitializer : public CFGElement {
public:
CFGInitializer(CXXCtorInitializer *initializer)
: CFGElement(Initializer, initializer) {}
CXXCtorInitializer* getInitializer() const {
return static_cast<CXXCtorInitializer*>(Data1.getPointer());
}
static bool classof(const CFGElement *E) {
return E->getKind() == Initializer;
}
};
/// CFGImplicitDtor - Represents C++ object destructor implicitly generated
/// by compiler on various occasions.
class CFGImplicitDtor : public CFGElement {
protected:
CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = 0)
: CFGElement(kind, data1, data2) {
assert(kind >= DTOR_BEGIN && kind <= DTOR_END);
}
public:
const CXXDestructorDecl *getDestructorDecl(ASTContext &astContext) const;
bool isNoReturn(ASTContext &astContext) const;
static bool classof(const CFGElement *E) {
Kind kind = E->getKind();
return kind >= DTOR_BEGIN && kind <= DTOR_END;
}
};
/// CFGAutomaticObjDtor - Represents C++ object destructor implicitly generated
/// for automatic object or temporary bound to const reference at the point
/// of leaving its local scope.
class CFGAutomaticObjDtor: public CFGImplicitDtor {
public:
CFGAutomaticObjDtor(const VarDecl *var, const Stmt *stmt)
: CFGImplicitDtor(AutomaticObjectDtor, var, stmt) {}
const VarDecl *getVarDecl() const {
return static_cast<VarDecl*>(Data1.getPointer());
}
// Get statement end of which triggered the destructor call.
const Stmt *getTriggerStmt() const {
return static_cast<Stmt*>(D