//===--- 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 "clang/AST/Stmt.h"
#include "clang/Analysis/Support/BumpVector.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.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
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) {}
CFGElement() {}
public:
/// \brief Convert to the specified CFGElement type, asserting that this
/// CFGElement is of the desired type.
template<typename T>
T castAs() const {
assert(T::isKind(*this));
T t;
CFGElement& e = t;
e = *this;
return t;
}
/// \brief Convert to the specified CFGElement type, returning None if this
/// CFGElement is not of the desired type.
template<typename T>
Optional<T> getAs() const {
if (!T::isKind(*this))
return None;
T t;
CFGElement& e = t;
e = *this;
return t;
}
Kind getKind() const {
unsigned x = Data2.getInt();
x <<= 2;
x |= Data1.getInt();
return (Kind) x;
}
};
class CFGStmt : public CFGElement {
public:
CFGStmt(Stmt *S) : CFGElement(Statement, S) {}
const Stmt *getStmt() const {
return static_cast<const Stmt *>(Data1.getPointer());
}
private:
friend class CFGElement;
CFGStmt() {}
static bool isKind(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());
}
private:
friend class CFGElement;
CFGInitializer() {}
static bool isKind(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() {}
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;
private:
friend class CFGElement;
static bool isKind(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