Remove the unused, unmaintained, incomplete 'Index' library.
llvm-svn: 154672
This commit is contained in:
parent
d84bb48582
commit
0481c8f206
|
@ -14,7 +14,6 @@
|
|||
#ifndef LLVM_CLANG_FRONTEND_ASTUNIT_H
|
||||
#define LLVM_CLANG_FRONTEND_ASTUNIT_H
|
||||
|
||||
#include "clang/Index/ASTLocation.h"
|
||||
#include "clang/Serialization/ASTBitCodes.h"
|
||||
#include "clang/Sema/Sema.h"
|
||||
#include "clang/Sema/CodeCompleteConsumer.h"
|
||||
|
@ -57,8 +56,6 @@ class SourceManager;
|
|||
class TargetInfo;
|
||||
class ASTFrontendAction;
|
||||
|
||||
using namespace idx;
|
||||
|
||||
/// \brief Utility class for loading a ASTContext from an AST file.
|
||||
///
|
||||
class ASTUnit : public ModuleLoader {
|
||||
|
@ -134,9 +131,6 @@ private:
|
|||
/// The name of the original source file used to generate this ASTUnit.
|
||||
std::string OriginalSourceFile;
|
||||
|
||||
// Critical optimization when using clang_getCursor().
|
||||
ASTLocation LastLoc;
|
||||
|
||||
/// \brief The set of diagnostics produced when creating the preamble.
|
||||
SmallVector<StoredDiagnostic, 4> PreambleDiagnostics;
|
||||
|
||||
|
@ -474,10 +468,6 @@ public:
|
|||
bool getOwnsRemappedFileBuffers() const { return OwnsRemappedFileBuffers; }
|
||||
void setOwnsRemappedFileBuffers(bool val) { OwnsRemappedFileBuffers = val; }
|
||||
|
||||
void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; }
|
||||
ASTLocation getLastASTLocation() const { return LastLoc; }
|
||||
|
||||
|
||||
StringRef getMainFileName() const;
|
||||
|
||||
typedef std::vector<Decl *>::iterator top_level_iterator;
|
||||
|
|
|
@ -1,173 +0,0 @@
|
|||
//===--- ASTLocation.h - A <Decl, Stmt> pair --------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// ASTLocation is Decl or a Stmt and its immediate Decl parent.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_ASTLOCATION_H
|
||||
#define LLVM_CLANG_INDEX_ASTLOCATION_H
|
||||
|
||||
#include "clang/AST/TypeLoc.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
namespace clang {
|
||||
class Decl;
|
||||
class Stmt;
|
||||
class NamedDecl;
|
||||
|
||||
namespace idx {
|
||||
class TranslationUnit;
|
||||
|
||||
/// \brief Represents a Decl or a Stmt and its immediate Decl parent. It's
|
||||
/// immutable.
|
||||
///
|
||||
/// ASTLocation is intended to be used as a "pointer" into the AST. It is either
|
||||
/// just a Decl, or a Stmt and its Decl parent. Since a single Stmt is devoid
|
||||
/// of context, its parent Decl provides all the additional missing information
|
||||
/// like the declaration context, ASTContext, etc.
|
||||
///
|
||||
class ASTLocation {
|
||||
public:
|
||||
enum NodeKind {
|
||||
N_Decl, N_NamedRef, N_Stmt, N_Type
|
||||
};
|
||||
|
||||
struct NamedRef {
|
||||
NamedDecl *ND;
|
||||
SourceLocation Loc;
|
||||
|
||||
NamedRef() : ND(0) { }
|
||||
NamedRef(NamedDecl *nd, SourceLocation loc) : ND(nd), Loc(loc) { }
|
||||
};
|
||||
|
||||
private:
|
||||
llvm::PointerIntPair<Decl *, 2, NodeKind> ParentDecl;
|
||||
|
||||
union {
|
||||
Decl *D;
|
||||
Stmt *Stm;
|
||||
struct {
|
||||
NamedDecl *ND;
|
||||
unsigned RawLoc;
|
||||
} NDRef;
|
||||
struct {
|
||||
void *TyPtr;
|
||||
void *Data;
|
||||
} Ty;
|
||||
};
|
||||
|
||||
public:
|
||||
ASTLocation() { }
|
||||
|
||||
explicit ASTLocation(const Decl *d)
|
||||
: ParentDecl(const_cast<Decl*>(d), N_Decl), D(const_cast<Decl*>(d)) { }
|
||||
|
||||
ASTLocation(const Decl *parentDecl, const Stmt *stm)
|
||||
: ParentDecl(const_cast<Decl*>(parentDecl), N_Stmt),
|
||||
Stm(const_cast<Stmt*>(stm)) {
|
||||
if (!stm) ParentDecl.setPointer(0);
|
||||
}
|
||||
|
||||
ASTLocation(const Decl *parentDecl, NamedDecl *ndRef, SourceLocation loc)
|
||||
: ParentDecl(const_cast<Decl*>(parentDecl), N_NamedRef) {
|
||||
if (ndRef) {
|
||||
NDRef.ND = ndRef;
|
||||
NDRef.RawLoc = loc.getRawEncoding();
|
||||
} else
|
||||
ParentDecl.setPointer(0);
|
||||
}
|
||||
|
||||
ASTLocation(const Decl *parentDecl, TypeLoc tyLoc)
|
||||
: ParentDecl(const_cast<Decl*>(parentDecl), N_Type) {
|
||||
if (tyLoc) {
|
||||
Ty.TyPtr = tyLoc.getType().getAsOpaquePtr();
|
||||
Ty.Data = tyLoc.getOpaqueData();
|
||||
} else
|
||||
ParentDecl.setPointer(0);
|
||||
}
|
||||
|
||||
bool isValid() const { return ParentDecl.getPointer() != 0; }
|
||||
bool isInvalid() const { return !isValid(); }
|
||||
|
||||
NodeKind getKind() const {
|
||||
assert(isValid());
|
||||
return (NodeKind)ParentDecl.getInt();
|
||||
}
|
||||
|
||||
Decl *getParentDecl() const { return ParentDecl.getPointer(); }
|
||||
|
||||
Decl *AsDecl() const {
|
||||
assert(getKind() == N_Decl);
|
||||
return D;
|
||||
}
|
||||
Stmt *AsStmt() const {
|
||||
assert(getKind() == N_Stmt);
|
||||
return Stm;
|
||||
}
|
||||
NamedRef AsNamedRef() const {
|
||||
assert(getKind() == N_NamedRef);
|
||||
return NamedRef(NDRef.ND, SourceLocation::getFromRawEncoding(NDRef.RawLoc));
|
||||
}
|
||||
TypeLoc AsTypeLoc() const {
|
||||
assert(getKind() == N_Type);
|
||||
return TypeLoc(QualType::getFromOpaquePtr(Ty.TyPtr), Ty.Data);
|
||||
}
|
||||
|
||||
Decl *dyn_AsDecl() const { return isValid() && getKind() == N_Decl ? D : 0; }
|
||||
Stmt *dyn_AsStmt() const {
|
||||
return isValid() && getKind() == N_Stmt ? Stm : 0;
|
||||
}
|
||||
NamedRef dyn_AsNamedRef() const {
|
||||
return getKind() == N_Type ? AsNamedRef() : NamedRef();
|
||||
}
|
||||
TypeLoc dyn_AsTypeLoc() const {
|
||||
return getKind() == N_Type ? AsTypeLoc() : TypeLoc();
|
||||
}
|
||||
|
||||
bool isDecl() const { return isValid() && getKind() == N_Decl; }
|
||||
bool isStmt() const { return isValid() && getKind() == N_Stmt; }
|
||||
bool isNamedRef() const { return isValid() && getKind() == N_NamedRef; }
|
||||
bool isType() const { return isValid() && getKind() == N_Type; }
|
||||
|
||||
/// \brief Returns the declaration that this ASTLocation references.
|
||||
///
|
||||
/// If this points to a Decl, that Decl is returned.
|
||||
/// If this points to an Expr that references a Decl, that Decl is returned,
|
||||
/// otherwise it returns NULL.
|
||||
Decl *getReferencedDecl();
|
||||
const Decl *getReferencedDecl() const {
|
||||
return const_cast<ASTLocation*>(this)->getReferencedDecl();
|
||||
}
|
||||
|
||||
SourceRange getSourceRange() const LLVM_READONLY;
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
};
|
||||
|
||||
/// \brief Like ASTLocation but also contains the TranslationUnit that the
|
||||
/// ASTLocation originated from.
|
||||
class TULocation : public ASTLocation {
|
||||
TranslationUnit *TU;
|
||||
|
||||
public:
|
||||
TULocation(TranslationUnit *tu, ASTLocation astLoc)
|
||||
: ASTLocation(astLoc), TU(tu) {
|
||||
assert(tu && "Passed null translation unit");
|
||||
}
|
||||
|
||||
TranslationUnit *getTU() const { return TU; }
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -1,56 +0,0 @@
|
|||
//===--- Analyzer.h - Analysis for indexing information ---------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the Analyzer interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_ANALYZER_H
|
||||
#define LLVM_CLANG_INDEX_ANALYZER_H
|
||||
|
||||
namespace clang {
|
||||
class Decl;
|
||||
class ObjCMessageExpr;
|
||||
|
||||
namespace idx {
|
||||
class Program;
|
||||
class IndexProvider;
|
||||
class TULocationHandler;
|
||||
|
||||
/// \brief Provides indexing information, like finding all references of an
|
||||
/// Entity across translation units.
|
||||
class Analyzer {
|
||||
Program &Prog;
|
||||
IndexProvider &Idxer;
|
||||
|
||||
Analyzer(const Analyzer&); // do not implement
|
||||
Analyzer &operator=(const Analyzer &); // do not implement
|
||||
|
||||
public:
|
||||
explicit Analyzer(Program &prog, IndexProvider &idxer)
|
||||
: Prog(prog), Idxer(idxer) { }
|
||||
|
||||
/// \brief Find all TULocations for declarations of the given Decl and pass
|
||||
/// them to Handler.
|
||||
void FindDeclarations(Decl *D, TULocationHandler &Handler);
|
||||
|
||||
/// \brief Find all TULocations for references of the given Decl and pass
|
||||
/// them to Handler.
|
||||
void FindReferences(Decl *D, TULocationHandler &Handler);
|
||||
|
||||
/// \brief Find methods that may respond to the given message and pass them
|
||||
/// to Handler.
|
||||
void FindObjCMethods(ObjCMessageExpr *MsgE, TULocationHandler &Handler);
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -1,50 +0,0 @@
|
|||
//===--- DeclReferenceMap.h - Map Decls to their references -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// DeclReferenceMap creates a mapping from Decls to the ASTLocations that
|
||||
// reference them.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_DECLREFERENCEMAP_H
|
||||
#define LLVM_CLANG_INDEX_DECLREFERENCEMAP_H
|
||||
|
||||
#include "clang/Index/ASTLocation.h"
|
||||
#include "clang/Index/STLExtras.h"
|
||||
#include <map>
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class NamedDecl;
|
||||
|
||||
namespace idx {
|
||||
|
||||
/// \brief Maps NamedDecls with the ASTLocations that reference them.
|
||||
///
|
||||
/// References are mapped and retrieved using the canonical decls.
|
||||
class DeclReferenceMap {
|
||||
public:
|
||||
explicit DeclReferenceMap(ASTContext &Ctx);
|
||||
|
||||
typedef std::multimap<NamedDecl*, ASTLocation> MapTy;
|
||||
typedef pair_value_iterator<MapTy::iterator> astlocation_iterator;
|
||||
|
||||
astlocation_iterator refs_begin(NamedDecl *D) const;
|
||||
astlocation_iterator refs_end(NamedDecl *D) const;
|
||||
bool refs_empty(NamedDecl *D) const;
|
||||
|
||||
private:
|
||||
mutable MapTy Map;
|
||||
};
|
||||
|
||||
} // end idx namespace
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
|
@ -1,149 +0,0 @@
|
|||
//===--- Entity.h - Cross-translation-unit "token" for decls ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Entity is a ASTContext-independent way to refer to declarations that are
|
||||
// visible across translation units.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_ENTITY_H
|
||||
#define LLVM_CLANG_INDEX_ENTITY_H
|
||||
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <string>
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class Decl;
|
||||
|
||||
namespace idx {
|
||||
class Program;
|
||||
class EntityImpl;
|
||||
|
||||
/// \brief A ASTContext-independent way to refer to declarations.
|
||||
///
|
||||
/// Entity is basically the link for declarations that are semantically the same
|
||||
/// in multiple ASTContexts. A client will convert a Decl into an Entity and
|
||||
/// later use that Entity to find the "same" Decl into another ASTContext.
|
||||
/// Declarations that are semantically the same and visible across translation
|
||||
/// units will be associated with the same Entity.
|
||||
///
|
||||
/// An Entity may also refer to declarations that cannot be visible across
|
||||
/// translation units, e.g. static functions with the same name in multiple
|
||||
/// translation units will be associated with different Entities.
|
||||
///
|
||||
/// Entities can be checked for equality but note that the same Program object
|
||||
/// should be used when getting Entities.
|
||||
///
|
||||
class Entity {
|
||||
/// \brief Stores the Decl directly if it is not visible outside of its own
|
||||
/// translation unit, otherwise it stores the associated EntityImpl.
|
||||
llvm::PointerUnion<Decl *, EntityImpl *> Val;
|
||||
|
||||
explicit Entity(Decl *D);
|
||||
explicit Entity(EntityImpl *impl) : Val(impl) { }
|
||||
friend class EntityGetter;
|
||||
|
||||
public:
|
||||
Entity() { }
|
||||
|
||||
/// \brief Find the Decl that can be referred to by this entity.
|
||||
Decl *getDecl(ASTContext &AST) const;
|
||||
|
||||
/// \brief If this Entity represents a declaration that is internal to its
|
||||
/// translation unit, getInternalDecl() returns it.
|
||||
Decl *getInternalDecl() const {
|
||||
assert(isInternalToTU() && "This Entity is not internal!");
|
||||
return Val.get<Decl *>();
|
||||
}
|
||||
|
||||
/// \brief Get a printable name for debugging purpose.
|
||||
std::string getPrintableName() const;
|
||||
|
||||
/// \brief Get an Entity associated with the given Decl.
|
||||
/// \returns invalid Entity if an Entity cannot refer to this Decl.
|
||||
static Entity get(Decl *D, Program &Prog);
|
||||
|
||||
/// \brief Get an Entity associated with a name in the global namespace.
|
||||
static Entity get(StringRef Name, Program &Prog);
|
||||
|
||||
/// \brief true if the Entity is not visible outside the trasnlation unit.
|
||||
bool isInternalToTU() const {
|
||||
assert(isValid() && "This Entity is not valid!");
|
||||
return Val.is<Decl *>();
|
||||
}
|
||||
|
||||
bool isValid() const { return !Val.isNull(); }
|
||||
bool isInvalid() const { return !isValid(); }
|
||||
|
||||
void *getAsOpaquePtr() const { return Val.getOpaqueValue(); }
|
||||
static Entity getFromOpaquePtr(void *Ptr) {
|
||||
Entity Ent;
|
||||
Ent.Val = llvm::PointerUnion<Decl *, EntityImpl *>::getFromOpaqueValue(Ptr);
|
||||
return Ent;
|
||||
}
|
||||
|
||||
friend bool operator==(const Entity &LHS, const Entity &RHS) {
|
||||
return LHS.getAsOpaquePtr() == RHS.getAsOpaquePtr();
|
||||
}
|
||||
|
||||
// For use in a std::map.
|
||||
friend bool operator < (const Entity &LHS, const Entity &RHS) {
|
||||
return LHS.getAsOpaquePtr() < RHS.getAsOpaquePtr();
|
||||
}
|
||||
|
||||
// For use in DenseMap/DenseSet.
|
||||
static Entity getEmptyMarker() {
|
||||
Entity Ent;
|
||||
Ent.Val =
|
||||
llvm::PointerUnion<Decl *, EntityImpl *>::getFromOpaqueValue((void*)-1);
|
||||
return Ent;
|
||||
}
|
||||
static Entity getTombstoneMarker() {
|
||||
Entity Ent;
|
||||
Ent.Val =
|
||||
llvm::PointerUnion<Decl *, EntityImpl *>::getFromOpaqueValue((void*)-2);
|
||||
return Ent;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
namespace llvm {
|
||||
/// Define DenseMapInfo so that Entities can be used as keys in DenseMap and
|
||||
/// DenseSets.
|
||||
template<>
|
||||
struct DenseMapInfo<clang::idx::Entity> {
|
||||
static inline clang::idx::Entity getEmptyKey() {
|
||||
return clang::idx::Entity::getEmptyMarker();
|
||||
}
|
||||
|
||||
static inline clang::idx::Entity getTombstoneKey() {
|
||||
return clang::idx::Entity::getTombstoneMarker();
|
||||
}
|
||||
|
||||
static unsigned getHashValue(clang::idx::Entity);
|
||||
|
||||
static inline bool
|
||||
isEqual(clang::idx::Entity LHS, clang::idx::Entity RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct isPodLike<clang::idx::Entity> { static const bool value = true; };
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
|
@ -1,149 +0,0 @@
|
|||
//== GlobalCallGraph.h - Call graph building --------------------*- C++ -*--==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defined the CallGraph and CallGraphNode classes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_CALLGRAPH
|
||||
#define LLVM_CLANG_INDEX_CALLGRAPH
|
||||
|
||||
#include "clang/Index/ASTLocation.h"
|
||||
#include "clang/Index/Entity.h"
|
||||
#include "clang/Index/Program.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
using namespace clang;
|
||||
|
||||
namespace clang {
|
||||
namespace idx {
|
||||
|
||||
class CallGraphNode {
|
||||
Entity F;
|
||||
typedef std::pair<ASTLocation, CallGraphNode*> CallRecord;
|
||||
std::vector<CallRecord> CalledFunctions;
|
||||
|
||||
public:
|
||||
CallGraphNode(Entity f) : F(f) {}
|
||||
|
||||
typedef std::vector<CallRecord>::iterator iterator;
|
||||
typedef std::vector<CallRecord>::const_iterator const_iterator;
|
||||
|
||||
iterator begin() { return CalledFunctions.begin(); }
|
||||
iterator end() { return CalledFunctions.end(); }
|
||||
const_iterator begin() const { return CalledFunctions.begin(); }
|
||||
const_iterator end() const { return CalledFunctions.end(); }
|
||||
|
||||
void addCallee(ASTLocation L, CallGraphNode *Node) {
|
||||
CalledFunctions.push_back(std::make_pair(L, Node));
|
||||
}
|
||||
|
||||
bool hasCallee() const { return begin() != end(); }
|
||||
|
||||
std::string getName() const { return F.getPrintableName(); }
|
||||
|
||||
Decl *getDecl(ASTContext &Ctx) const { return F.getDecl(Ctx); }
|
||||
};
|
||||
|
||||
class CallGraph {
|
||||
/// Program manages all Entities.
|
||||
Program &Prog;
|
||||
|
||||
typedef std::map<Entity, CallGraphNode *> FunctionMapTy;
|
||||
|
||||
/// FunctionMap owns all CallGraphNodes.
|
||||
FunctionMapTy FunctionMap;
|
||||
|
||||
/// CallerCtx maps a caller to its ASTContext.
|
||||
llvm::DenseMap<CallGraphNode *, ASTContext *> CallerCtx;
|
||||
|
||||
/// Root node is the 'main' function or 0.
|
||||
CallGraphNode *Root;
|
||||
|
||||
/// ExternalCallingNode has edges to all external functions.
|
||||
CallGraphNode *ExternalCallingNode;
|
||||
|
||||
public:
|
||||
CallGraph(Program &P);
|
||||
~CallGraph();
|
||||
|
||||
typedef FunctionMapTy::iterator iterator;
|
||||
typedef FunctionMapTy::const_iterator const_iterator;
|
||||
|
||||
iterator begin() { return FunctionMap.begin(); }
|
||||
iterator end() { return FunctionMap.end(); }
|
||||
const_iterator begin() const { return FunctionMap.begin(); }
|
||||
const_iterator end() const { return FunctionMap.end(); }
|
||||
|
||||
CallGraphNode *getRoot() { return Root; }
|
||||
|
||||
CallGraphNode *getExternalCallingNode() { return ExternalCallingNode; }
|
||||
|
||||
void addTU(ASTContext &AST);
|
||||
|
||||
Program &getProgram() { return Prog; }
|
||||
|
||||
CallGraphNode *getOrInsertFunction(idx::Entity F);
|
||||
|
||||
Decl *getDecl(CallGraphNode *Node);
|
||||
|
||||
void print(raw_ostream &os);
|
||||
void dump();
|
||||
|
||||
void ViewCallGraph() const;
|
||||
};
|
||||
|
||||
}} // end clang idx namespace
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template <> struct GraphTraits<clang::idx::CallGraph> {
|
||||
typedef clang::idx::CallGraph GraphType;
|
||||
typedef clang::idx::CallGraphNode NodeType;
|
||||
|
||||
typedef std::pair<clang::idx::ASTLocation, NodeType*> CGNPairTy;
|
||||
typedef std::pointer_to_unary_function<CGNPairTy, NodeType*> CGNDerefFun;
|
||||
|
||||
typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType;
|
||||
|
||||
static NodeType *getEntryNode(GraphType *CG) {
|
||||
return CG->getExternalCallingNode();
|
||||
}
|
||||
|
||||
static ChildIteratorType child_begin(NodeType *N) {
|
||||
return map_iterator(N->begin(), CGNDerefFun(CGNDeref));
|
||||
}
|
||||
static ChildIteratorType child_end(NodeType *N) {
|
||||
return map_iterator(N->end(), CGNDerefFun(CGNDeref));
|
||||
}
|
||||
|
||||
typedef std::pair<clang::idx::Entity, NodeType*> PairTy;
|
||||
typedef std::pointer_to_unary_function<PairTy, NodeType*> DerefFun;
|
||||
|
||||
typedef mapped_iterator<GraphType::const_iterator, DerefFun> nodes_iterator;
|
||||
|
||||
static nodes_iterator nodes_begin(const GraphType &CG) {
|
||||
return map_iterator(CG.begin(), DerefFun(CGDeref));
|
||||
}
|
||||
static nodes_iterator nodes_end(const GraphType &CG) {
|
||||
return map_iterator(CG.end(), DerefFun(CGDeref));
|
||||
}
|
||||
|
||||
static NodeType *CGNDeref(CGNPairTy P) { return P.second; }
|
||||
|
||||
static NodeType *CGDeref(PairTy P) { return P.second; }
|
||||
};
|
||||
|
||||
} // end llvm namespace
|
||||
|
||||
#endif
|
|
@ -1,100 +0,0 @@
|
|||
//===--- GlobalSelector.h - Cross-translation-unit "token" for selectors --===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// GlobalSelector is a ASTContext-independent way to refer to selectors.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_GLOBALSELECTOR_H
|
||||
#define LLVM_CLANG_INDEX_GLOBALSELECTOR_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include <string>
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class Selector;
|
||||
|
||||
namespace idx {
|
||||
class Program;
|
||||
|
||||
/// \brief A ASTContext-independent way to refer to selectors.
|
||||
class GlobalSelector {
|
||||
void *Val;
|
||||
|
||||
explicit GlobalSelector(void *val) : Val(val) { }
|
||||
|
||||
public:
|
||||
GlobalSelector() : Val(0) { }
|
||||
|
||||
/// \brief Get the ASTContext-specific selector.
|
||||
Selector getSelector(ASTContext &AST) const;
|
||||
|
||||
bool isValid() const { return Val != 0; }
|
||||
bool isInvalid() const { return !isValid(); }
|
||||
|
||||
/// \brief Get a printable name for debugging purpose.
|
||||
std::string getPrintableName() const;
|
||||
|
||||
/// \brief Get a GlobalSelector for the ASTContext-specific selector.
|
||||
static GlobalSelector get(Selector Sel, Program &Prog);
|
||||
|
||||
void *getAsOpaquePtr() const { return Val; }
|
||||
|
||||
static GlobalSelector getFromOpaquePtr(void *Ptr) {
|
||||
return GlobalSelector(Ptr);
|
||||
}
|
||||
|
||||
friend bool operator==(const GlobalSelector &LHS, const GlobalSelector &RHS) {
|
||||
return LHS.getAsOpaquePtr() == RHS.getAsOpaquePtr();
|
||||
}
|
||||
|
||||
// For use in a std::map.
|
||||
friend bool operator< (const GlobalSelector &LHS, const GlobalSelector &RHS) {
|
||||
return LHS.getAsOpaquePtr() < RHS.getAsOpaquePtr();
|
||||
}
|
||||
|
||||
// For use in DenseMap/DenseSet.
|
||||
static GlobalSelector getEmptyMarker() { return GlobalSelector((void*)-1); }
|
||||
static GlobalSelector getTombstoneMarker() {
|
||||
return GlobalSelector((void*)-2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
namespace llvm {
|
||||
/// Define DenseMapInfo so that GlobalSelectors can be used as keys in DenseMap
|
||||
/// and DenseSets.
|
||||
template<>
|
||||
struct DenseMapInfo<clang::idx::GlobalSelector> {
|
||||
static inline clang::idx::GlobalSelector getEmptyKey() {
|
||||
return clang::idx::GlobalSelector::getEmptyMarker();
|
||||
}
|
||||
|
||||
static inline clang::idx::GlobalSelector getTombstoneKey() {
|
||||
return clang::idx::GlobalSelector::getTombstoneMarker();
|
||||
}
|
||||
|
||||
static unsigned getHashValue(clang::idx::GlobalSelector);
|
||||
|
||||
static inline bool
|
||||
isEqual(clang::idx::GlobalSelector LHS, clang::idx::GlobalSelector RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct isPodLike<clang::idx::GlobalSelector> { static const bool value = true;};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
|
@ -1,82 +0,0 @@
|
|||
//===--- Handlers.h - Interfaces for receiving information ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Abstract interfaces for receiving information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_HANDLERS_H
|
||||
#define LLVM_CLANG_INDEX_HANDLERS_H
|
||||
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
namespace idx {
|
||||
class Entity;
|
||||
class TranslationUnit;
|
||||
class TULocation;
|
||||
|
||||
/// \brief Abstract interface for receiving Entities.
|
||||
class EntityHandler {
|
||||
public:
|
||||
typedef Entity receiving_type;
|
||||
|
||||
virtual ~EntityHandler();
|
||||
virtual void Handle(Entity Ent) = 0;
|
||||
};
|
||||
|
||||
/// \brief Abstract interface for receiving TranslationUnits.
|
||||
class TranslationUnitHandler {
|
||||
public:
|
||||
typedef TranslationUnit* receiving_type;
|
||||
|
||||
virtual ~TranslationUnitHandler();
|
||||
virtual void Handle(TranslationUnit *TU) = 0;
|
||||
};
|
||||
|
||||
/// \brief Abstract interface for receiving TULocations.
|
||||
class TULocationHandler {
|
||||
public:
|
||||
typedef TULocation receiving_type;
|
||||
|
||||
virtual ~TULocationHandler();
|
||||
virtual void Handle(TULocation TULoc) = 0;
|
||||
};
|
||||
|
||||
/// \brief Helper for the Handler classes. Stores the objects into a vector.
|
||||
/// example:
|
||||
/// @code
|
||||
/// Storing<TranslationUnitHandler> TURes;
|
||||
/// IndexProvider.GetTranslationUnitsFor(Entity, TURes);
|
||||
/// for (Storing<TranslationUnitHandler>::iterator
|
||||
/// I = TURes.begin(), E = TURes.end(); I != E; ++I) { ....
|
||||
/// @endcode
|
||||
template <typename handler_type>
|
||||
class Storing : public handler_type {
|
||||
typedef typename handler_type::receiving_type receiving_type;
|
||||
typedef SmallVector<receiving_type, 8> StoreTy;
|
||||
StoreTy Store;
|
||||
|
||||
public:
|
||||
virtual void Handle(receiving_type Obj) {
|
||||
Store.push_back(Obj);
|
||||
}
|
||||
|
||||
typedef typename StoreTy::const_iterator iterator;
|
||||
iterator begin() const { return Store.begin(); }
|
||||
iterator end() const { return Store.end(); }
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -1,38 +0,0 @@
|
|||
//===--- IndexProvider.h - Maps information to translation units -*- C++ -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Maps information to TranslationUnits.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_INDEXPROVIDER_H
|
||||
#define LLVM_CLANG_INDEX_INDEXPROVIDER_H
|
||||
|
||||
namespace clang {
|
||||
|
||||
namespace idx {
|
||||
class Entity;
|
||||
class TranslationUnitHandler;
|
||||
class GlobalSelector;
|
||||
|
||||
/// \brief Maps information to TranslationUnits.
|
||||
class IndexProvider {
|
||||
public:
|
||||
virtual ~IndexProvider();
|
||||
virtual void GetTranslationUnitsFor(Entity Ent,
|
||||
TranslationUnitHandler &Handler) = 0;
|
||||
virtual void GetTranslationUnitsFor(GlobalSelector Sel,
|
||||
TranslationUnitHandler &Handler) = 0;
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -1,71 +0,0 @@
|
|||
//===--- Indexer.h - IndexProvider implementation ---------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// IndexProvider implementation.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_INDEXER_H
|
||||
#define LLVM_CLANG_INDEX_INDEXER_H
|
||||
|
||||
#include "clang/Index/IndexProvider.h"
|
||||
#include "clang/Index/Entity.h"
|
||||
#include "clang/Index/GlobalSelector.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include <map>
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class FunctionDecl;
|
||||
|
||||
namespace idx {
|
||||
class Program;
|
||||
class TranslationUnit;
|
||||
|
||||
/// \brief Maps information to TranslationUnits.
|
||||
class Indexer : public IndexProvider {
|
||||
public:
|
||||
typedef llvm::SmallPtrSet<TranslationUnit *, 4> TUSetTy;
|
||||
typedef llvm::DenseMap<ASTContext *, TranslationUnit *> CtxTUMapTy;
|
||||
typedef std::map<Entity, TUSetTy> MapTy;
|
||||
typedef std::map<GlobalSelector, TUSetTy> SelMapTy;
|
||||
typedef std::map<Entity, std::pair<FunctionDecl*,TranslationUnit*> > DefMapTy;
|
||||
|
||||
explicit Indexer(Program &prog) :
|
||||
Prog(prog) { }
|
||||
|
||||
Program &getProgram() const { return Prog; }
|
||||
|
||||
/// \brief Find all Entities and map them to the given translation unit.
|
||||
void IndexAST(TranslationUnit *TU);
|
||||
|
||||
virtual void GetTranslationUnitsFor(Entity Ent,
|
||||
TranslationUnitHandler &Handler);
|
||||
virtual void GetTranslationUnitsFor(GlobalSelector Sel,
|
||||
TranslationUnitHandler &Handler);
|
||||
|
||||
std::pair<FunctionDecl*, TranslationUnit*> getDefinitionFor(Entity Ent);
|
||||
|
||||
private:
|
||||
Program &Prog;
|
||||
|
||||
MapTy Map;
|
||||
// Map a function Entity to the its definition.
|
||||
DefMapTy DefMap;
|
||||
|
||||
CtxTUMapTy CtxTUMap;
|
||||
SelMapTy SelMap;
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -1,45 +0,0 @@
|
|||
//===--- Program.h - Cross-translation unit information ---------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the idx::Program interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_PROGRAM_H
|
||||
#define LLVM_CLANG_INDEX_PROGRAM_H
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
|
||||
namespace idx {
|
||||
class EntityHandler;
|
||||
|
||||
/// \brief Top level object that owns and maintains information
|
||||
/// that is common across translation units.
|
||||
class Program {
|
||||
void *Impl;
|
||||
|
||||
Program(const Program&); // do not implement
|
||||
Program &operator=(const Program &); // do not implement
|
||||
friend class Entity;
|
||||
friend class GlobalSelector;
|
||||
|
||||
public:
|
||||
Program();
|
||||
~Program();
|
||||
|
||||
/// \brief Traverses the AST and passes all the entities to the Handler.
|
||||
void FindEntities(ASTContext &Ctx, EntityHandler &Handler);
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -1,63 +0,0 @@
|
|||
//===--- STLExtras.h - Helper STL related templates -------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Helper templates for using with the STL.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_STLEXTRAS_H
|
||||
#define LLVM_CLANG_INDEX_STLEXTRAS_H
|
||||
|
||||
namespace clang {
|
||||
|
||||
namespace idx {
|
||||
|
||||
/// \brief Wraps an iterator whose value_type is a pair, and provides
|
||||
/// pair's second object as the value.
|
||||
template <typename iter_type>
|
||||
class pair_value_iterator {
|
||||
iter_type I;
|
||||
|
||||
public:
|
||||
typedef typename iter_type::value_type::second_type value_type;
|
||||
typedef value_type& reference;
|
||||
typedef value_type* pointer;
|
||||
typedef typename iter_type::iterator_category iterator_category;
|
||||
typedef typename iter_type::difference_type difference_type;
|
||||
|
||||
pair_value_iterator() { }
|
||||
pair_value_iterator(iter_type i) : I(i) { }
|
||||
|
||||
reference operator*() const { return I->second; }
|
||||
pointer operator->() const { return &I->second; }
|
||||
|
||||
pair_value_iterator& operator++() {
|
||||
++I;
|
||||
return *this;
|
||||
}
|
||||
|
||||
pair_value_iterator operator++(int) {
|
||||
pair_value_iterator tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
friend bool operator==(pair_value_iterator L, pair_value_iterator R) {
|
||||
return L.I == R.I;
|
||||
}
|
||||
friend bool operator!=(pair_value_iterator L, pair_value_iterator R) {
|
||||
return L.I != R.I;
|
||||
}
|
||||
};
|
||||
|
||||
} // end idx namespace
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
|
@ -1,57 +0,0 @@
|
|||
//===--- SelectorMap.h - Maps selectors to methods and messages -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// SelectorMap creates a mapping from selectors to ObjC method declarations
|
||||
// and ObjC message expressions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_SELECTORMAP_H
|
||||
#define LLVM_CLANG_INDEX_SELECTORMAP_H
|
||||
|
||||
#include "clang/Index/ASTLocation.h"
|
||||
#include "clang/Index/STLExtras.h"
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include <map>
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class ObjCMethodDecl;
|
||||
|
||||
namespace idx {
|
||||
|
||||
/// \brief Maps NamedDecls with the ASTLocations that reference them.
|
||||
///
|
||||
/// References are mapped and retrieved using the canonical decls.
|
||||
class SelectorMap {
|
||||
public:
|
||||
explicit SelectorMap(ASTContext &Ctx);
|
||||
|
||||
typedef std::multimap<Selector, ObjCMethodDecl *> SelMethMapTy;
|
||||
typedef std::multimap<Selector, ASTLocation> SelRefMapTy;
|
||||
|
||||
typedef pair_value_iterator<SelMethMapTy::iterator> method_iterator;
|
||||
typedef pair_value_iterator<SelRefMapTy::iterator> astlocation_iterator;
|
||||
|
||||
method_iterator methods_begin(Selector Sel) const;
|
||||
method_iterator methods_end(Selector Sel) const;
|
||||
|
||||
astlocation_iterator refs_begin(Selector Sel) const;
|
||||
astlocation_iterator refs_end(Selector Sel) const;
|
||||
|
||||
private:
|
||||
mutable SelMethMapTy SelMethMap;
|
||||
mutable SelRefMapTy SelRefMap;
|
||||
};
|
||||
|
||||
} // end idx namespace
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
|
@ -1,41 +0,0 @@
|
|||
//===--- TranslationUnit.h - Interface for a translation unit ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Abstract interface for a translation unit.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_TRANSLATIONUNIT_H
|
||||
#define LLVM_CLANG_INDEX_TRANSLATIONUNIT_H
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class DiagnosticsEngine;
|
||||
class Preprocessor;
|
||||
|
||||
namespace idx {
|
||||
class DeclReferenceMap;
|
||||
class SelectorMap;
|
||||
|
||||
/// \brief Abstract interface for a translation unit.
|
||||
class TranslationUnit {
|
||||
public:
|
||||
virtual ~TranslationUnit();
|
||||
virtual ASTContext &getASTContext() = 0;
|
||||
virtual Preprocessor &getPreprocessor() = 0;
|
||||
virtual DiagnosticsEngine &getDiagnostic() = 0;
|
||||
virtual DeclReferenceMap &getDeclReferenceMap() = 0;
|
||||
virtual SelectorMap &getSelectorMap() = 0;
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -22,11 +22,6 @@
|
|||
|
||||
namespace clang {
|
||||
|
||||
namespace idx {
|
||||
class Indexer;
|
||||
class TranslationUnit;
|
||||
}
|
||||
|
||||
namespace ento {
|
||||
class CheckerManager;
|
||||
|
||||
|
@ -46,11 +41,6 @@ class AnalysisManager : public BugReporterData {
|
|||
|
||||
CheckerManager *CheckerMgr;
|
||||
|
||||
/// \brief Provide function definitions in other translation units. This is
|
||||
/// NULL if we don't have multiple translation units. AnalysisManager does
|
||||
/// not own the Indexer.
|
||||
idx::Indexer *Idxer;
|
||||
|
||||
enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
|
||||
|
||||
/// \brief The maximum number of exploded nodes the analyzer will generate.
|
||||
|
@ -99,7 +89,6 @@ public:
|
|||
StoreManagerCreator storemgr,
|
||||
ConstraintManagerCreator constraintmgr,
|
||||
CheckerManager *checkerMgr,
|
||||
idx::Indexer *idxer,
|
||||
unsigned maxnodes, unsigned maxvisit,
|
||||
bool vizdot, bool vizubi, AnalysisPurgeMode purge,
|
||||
bool eager, bool trim,
|
||||
|
@ -137,8 +126,6 @@ public:
|
|||
|
||||
CheckerManager *getCheckerManager() const { return CheckerMgr; }
|
||||
|
||||
idx::Indexer *getIndexer() const { return Idxer; }
|
||||
|
||||
virtual ASTContext &getASTContext() {
|
||||
return Ctx;
|
||||
}
|
||||
|
@ -186,10 +173,6 @@ public:
|
|||
|
||||
bool shouldInlineCall() const { return (IPAMode == Inlining); }
|
||||
|
||||
bool hasIndexer() const { return Idxer != 0; }
|
||||
|
||||
AnalysisDeclContext *getAnalysisDeclContextInAnotherTU(const Decl *D);
|
||||
|
||||
CFG *getCFG(Decl const *D) {
|
||||
return AnaCtxMgr.getContext(D)->getCFG();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
set(LLVM_USED_LIBS clangBasic clangAST clangIndex)
|
||||
set(LLVM_USED_LIBS clangBasic clangAST)
|
||||
|
||||
add_clang_library(clangAnalysis
|
||||
AnalysisDeclContext.cpp
|
||||
|
|
|
@ -14,5 +14,4 @@ add_subdirectory(Serialization)
|
|||
add_subdirectory(Frontend)
|
||||
add_subdirectory(FrontendTool)
|
||||
add_subdirectory(Tooling)
|
||||
add_subdirectory(Index)
|
||||
add_subdirectory(StaticAnalyzer)
|
||||
|
|
|
@ -1,114 +0,0 @@
|
|||
//===--- ASTLocation.cpp - A <Decl, Stmt> pair ------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// ASTLocation is Decl or a Stmt and its immediate Decl parent.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/ASTLocation.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/Stmt.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
using namespace clang;
|
||||
using namespace idx;
|
||||
|
||||
static Decl *getDeclFromExpr(Stmt *E) {
|
||||
if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E))
|
||||
return RefExpr->getDecl();
|
||||
if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
|
||||
return ME->getMemberDecl();
|
||||
if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(E))
|
||||
return RE->getDecl();
|
||||
|
||||
if (CallExpr *CE = dyn_cast<CallExpr>(E))
|
||||
return getDeclFromExpr(CE->getCallee());
|
||||
if (CastExpr *CE = dyn_cast<CastExpr>(E))
|
||||
return getDeclFromExpr(CE->getSubExpr());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Decl *ASTLocation::getReferencedDecl() {
|
||||
if (isInvalid())
|
||||
return 0;
|
||||
|
||||
switch (getKind()) {
|
||||
case N_Type:
|
||||
return 0;
|
||||
case N_Decl:
|
||||
return D;
|
||||
case N_NamedRef:
|
||||
return NDRef.ND;
|
||||
case N_Stmt:
|
||||
return getDeclFromExpr(Stm);
|
||||
}
|
||||
|
||||
llvm_unreachable("Invalid ASTLocation Kind!");
|
||||
}
|
||||
|
||||
SourceRange ASTLocation::getSourceRange() const {
|
||||
if (isInvalid())
|
||||
return SourceRange();
|
||||
|
||||
switch (getKind()) {
|
||||
case N_Decl:
|
||||
return D->getSourceRange();
|
||||
case N_Stmt:
|
||||
return Stm->getSourceRange();
|
||||
case N_NamedRef:
|
||||
return SourceRange(AsNamedRef().Loc, AsNamedRef().Loc);
|
||||
case N_Type:
|
||||
return AsTypeLoc().getLocalSourceRange();
|
||||
}
|
||||
|
||||
llvm_unreachable("Invalid ASTLocation Kind!");
|
||||
}
|
||||
|
||||
void ASTLocation::print(raw_ostream &OS) const {
|
||||
if (isInvalid()) {
|
||||
OS << "<< Invalid ASTLocation >>\n";
|
||||
return;
|
||||
}
|
||||
|
||||
ASTContext &Ctx = getParentDecl()->getASTContext();
|
||||
|
||||
switch (getKind()) {
|
||||
case N_Decl:
|
||||
OS << "[Decl: " << AsDecl()->getDeclKindName() << " ";
|
||||
if (const NamedDecl *ND = dyn_cast<NamedDecl>(AsDecl()))
|
||||
OS << *ND;
|
||||
break;
|
||||
|
||||
case N_Stmt:
|
||||
OS << "[Stmt: " << AsStmt()->getStmtClassName() << " ";
|
||||
AsStmt()->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOpts()));
|
||||
break;
|
||||
|
||||
case N_NamedRef:
|
||||
OS << "[NamedRef: " << AsNamedRef().ND->getDeclKindName() << " ";
|
||||
OS << *AsNamedRef().ND;
|
||||
break;
|
||||
|
||||
case N_Type: {
|
||||
QualType T = AsTypeLoc().getType();
|
||||
OS << "[Type: " << T->getTypeClassName() << " " << T.getAsString();
|
||||
}
|
||||
}
|
||||
|
||||
OS << "] <";
|
||||
|
||||
SourceRange Range = getSourceRange();
|
||||
SourceManager &SourceMgr = Ctx.getSourceManager();
|
||||
Range.getBegin().print(OS, SourceMgr);
|
||||
OS << ", ";
|
||||
Range.getEnd().print(OS, SourceMgr);
|
||||
OS << ">\n";
|
||||
}
|
|
@ -1,143 +0,0 @@
|
|||
//===--- ASTVisitor.h - Visitor for an ASTContext ---------------*- 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 ASTVisitor interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_ASTVISITOR_H
|
||||
#define LLVM_CLANG_INDEX_ASTVISITOR_H
|
||||
|
||||
#include "clang/AST/DeclVisitor.h"
|
||||
#include "clang/AST/StmtVisitor.h"
|
||||
#include "clang/AST/TypeLocVisitor.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
namespace idx {
|
||||
|
||||
/// \brief Traverses the full AST, both Decls and Stmts.
|
||||
template<typename ImplClass>
|
||||
class ASTVisitor : public DeclVisitor<ImplClass>,
|
||||
public StmtVisitor<ImplClass>,
|
||||
public TypeLocVisitor<ImplClass> {
|
||||
public:
|
||||
ASTVisitor() : CurrentDecl(0) { }
|
||||
|
||||
Decl *CurrentDecl;
|
||||
|
||||
typedef ASTVisitor<ImplClass> Base;
|
||||
typedef DeclVisitor<ImplClass> BaseDeclVisitor;
|
||||
typedef StmtVisitor<ImplClass> BaseStmtVisitor;
|
||||
typedef TypeLocVisitor<ImplClass> BaseTypeLocVisitor;
|
||||
|
||||
using BaseStmtVisitor::Visit;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// DeclVisitor
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
void Visit(Decl *D) {
|
||||
Decl *PrevDecl = CurrentDecl;
|
||||
CurrentDecl = D;
|
||||
BaseDeclVisitor::Visit(D);
|
||||
CurrentDecl = PrevDecl;
|
||||
}
|
||||
|
||||
void VisitDeclaratorDecl(DeclaratorDecl *D) {
|
||||
BaseDeclVisitor::VisitDeclaratorDecl(D);
|
||||
if (TypeSourceInfo *TInfo = D->getTypeSourceInfo())
|
||||
Visit(TInfo->getTypeLoc());
|
||||
}
|
||||
|
||||
void VisitFunctionDecl(FunctionDecl *D) {
|
||||
BaseDeclVisitor::VisitFunctionDecl(D);
|
||||
if (D->isThisDeclarationADefinition())
|
||||
Visit(D->getBody());
|
||||
}
|
||||
|
||||
void VisitObjCMethodDecl(ObjCMethodDecl *D) {
|
||||
BaseDeclVisitor::VisitObjCMethodDecl(D);
|
||||
if (D->getBody())
|
||||
Visit(D->getBody());
|
||||
}
|
||||
|
||||
void VisitBlockDecl(BlockDecl *D) {
|
||||
BaseDeclVisitor::VisitBlockDecl(D);
|
||||
Visit(D->getBody());
|
||||
}
|
||||
|
||||
void VisitVarDecl(VarDecl *D) {
|
||||
BaseDeclVisitor::VisitVarDecl(D);
|
||||
if (Expr *Init = D->getInit())
|
||||
Visit(Init);
|
||||
}
|
||||
|
||||
void VisitDecl(Decl *D) {
|
||||
if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D) || isa<BlockDecl>(D))
|
||||
return;
|
||||
|
||||
if (DeclContext *DC = dyn_cast<DeclContext>(D))
|
||||
static_cast<ImplClass*>(this)->VisitDeclContext(DC);
|
||||
}
|
||||
|
||||
void VisitDeclContext(DeclContext *DC) {
|
||||
for (DeclContext::decl_iterator
|
||||
I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
|
||||
Visit(*I);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// StmtVisitor
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
void VisitDeclStmt(DeclStmt *Node) {
|
||||
for (DeclStmt::decl_iterator
|
||||
I = Node->decl_begin(), E = Node->decl_end(); I != E; ++I)
|
||||
Visit(*I);
|
||||
}
|
||||
|
||||
void VisitBlockExpr(BlockExpr *Node) {
|
||||
// The BlockDecl is also visited by 'VisitDeclContext()'. No need to visit it twice.
|
||||
}
|
||||
|
||||
void VisitStmt(Stmt *Node) {
|
||||
for (Stmt::child_range I = Node->children(); I; ++I)
|
||||
if (*I)
|
||||
Visit(*I);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// TypeLocVisitor
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
void Visit(TypeLoc TL) {
|
||||
for (; TL; TL = TL.getNextTypeLoc())
|
||||
BaseTypeLocVisitor::Visit(TL);
|
||||
}
|
||||
|
||||
void VisitArrayLoc(ArrayTypeLoc TL) {
|
||||
BaseTypeLocVisitor::VisitArrayTypeLoc(TL);
|
||||
if (TL.getSizeExpr())
|
||||
Visit(TL.getSizeExpr());
|
||||
}
|
||||
|
||||
void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
|
||||
BaseTypeLocVisitor::VisitFunctionTypeLoc(TL);
|
||||
for (unsigned i = 0; i != TL.getNumArgs(); ++i)
|
||||
Visit(TL.getArg(i));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -1,470 +0,0 @@
|
|||
//===--- Analyzer.cpp - Analysis for indexing information -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the Analyzer interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/Analyzer.h"
|
||||
#include "clang/Index/Entity.h"
|
||||
#include "clang/Index/TranslationUnit.h"
|
||||
#include "clang/Index/Handlers.h"
|
||||
#include "clang/Index/ASTLocation.h"
|
||||
#include "clang/Index/GlobalSelector.h"
|
||||
#include "clang/Index/DeclReferenceMap.h"
|
||||
#include "clang/Index/SelectorMap.h"
|
||||
#include "clang/Index/IndexProvider.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
using namespace clang;
|
||||
using namespace idx;
|
||||
|
||||
namespace {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DeclEntityAnalyzer Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class DeclEntityAnalyzer : public TranslationUnitHandler {
|
||||
Entity Ent;
|
||||
TULocationHandler &TULocHandler;
|
||||
|
||||
public:
|
||||
DeclEntityAnalyzer(Entity ent, TULocationHandler &handler)
|
||||
: Ent(ent), TULocHandler(handler) { }
|
||||
|
||||
virtual void Handle(TranslationUnit *TU) {
|
||||
assert(TU && "Passed null translation unit");
|
||||
|
||||
Decl *D = Ent.getDecl(TU->getASTContext());
|
||||
assert(D && "Couldn't resolve Entity");
|
||||
|
||||
for (Decl::redecl_iterator I = D->redecls_begin(),
|
||||
E = D->redecls_end(); I != E; ++I)
|
||||
TULocHandler.Handle(TULocation(TU, ASTLocation(*I)));
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// RefEntityAnalyzer Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class RefEntityAnalyzer : public TranslationUnitHandler {
|
||||
Entity Ent;
|
||||
TULocationHandler &TULocHandler;
|
||||
|
||||
public:
|
||||
RefEntityAnalyzer(Entity ent, TULocationHandler &handler)
|
||||
: Ent(ent), TULocHandler(handler) { }
|
||||
|
||||
virtual void Handle(TranslationUnit *TU) {
|
||||
assert(TU && "Passed null translation unit");
|
||||
|
||||
Decl *D = Ent.getDecl(TU->getASTContext());
|
||||
assert(D && "Couldn't resolve Entity");
|
||||
NamedDecl *ND = dyn_cast<NamedDecl>(D);
|
||||
if (!ND)
|
||||
return;
|
||||
|
||||
DeclReferenceMap &RefMap = TU->getDeclReferenceMap();
|
||||
for (DeclReferenceMap::astlocation_iterator
|
||||
I = RefMap.refs_begin(ND), E = RefMap.refs_end(ND); I != E; ++I)
|
||||
TULocHandler.Handle(TULocation(TU, *I));
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// RefSelectorAnalyzer Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// \brief Accepts an ObjC method and finds all message expressions that this
|
||||
/// method may respond to.
|
||||
class RefSelectorAnalyzer : public TranslationUnitHandler {
|
||||
Program &Prog;
|
||||
TULocationHandler &TULocHandler;
|
||||
|
||||
// The original ObjCInterface associated with the method.
|
||||
Entity IFaceEnt;
|
||||
GlobalSelector GlobSel;
|
||||
bool IsInstanceMethod;
|
||||
|
||||
/// \brief Super classes of the ObjCInterface.
|
||||
typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
|
||||
EntitiesSetTy HierarchyEntities;
|
||||
|
||||
public:
|
||||
RefSelectorAnalyzer(ObjCMethodDecl *MD,
|
||||
Program &prog, TULocationHandler &handler)
|
||||
: Prog(prog), TULocHandler(handler) {
|
||||
assert(MD);
|
||||
|
||||
// FIXME: Protocol methods.
|
||||
assert(!isa<ObjCProtocolDecl>(MD->getDeclContext()) &&
|
||||
"Protocol methods not supported yet");
|
||||
|
||||
ObjCInterfaceDecl *IFD = MD->getClassInterface();
|
||||
assert(IFD);
|
||||
IFaceEnt = Entity::get(IFD, Prog);
|
||||
GlobSel = GlobalSelector::get(MD->getSelector(), Prog);
|
||||
IsInstanceMethod = MD->isInstanceMethod();
|
||||
|
||||
for (ObjCInterfaceDecl *Cls = IFD->getSuperClass();
|
||||
Cls; Cls = Cls->getSuperClass())
|
||||
HierarchyEntities.insert(Entity::get(Cls, Prog));
|
||||
}
|
||||
|
||||
virtual void Handle(TranslationUnit *TU) {
|
||||
assert(TU && "Passed null translation unit");
|
||||
|
||||
ASTContext &Ctx = TU->getASTContext();
|
||||
// Null means it doesn't exist in this translation unit.
|
||||
ObjCInterfaceDecl *IFace =
|
||||
cast_or_null<ObjCInterfaceDecl>(IFaceEnt.getDecl(Ctx));
|
||||
Selector Sel = GlobSel.getSelector(Ctx);
|
||||
|
||||
SelectorMap &SelMap = TU->getSelectorMap();
|
||||
for (SelectorMap::astlocation_iterator
|
||||
I = SelMap.refs_begin(Sel), E = SelMap.refs_end(Sel); I != E; ++I) {
|
||||
if (ValidReference(*I, IFace))
|
||||
TULocHandler.Handle(TULocation(TU, *I));
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Determines whether the given message expression is likely to end
|
||||
/// up at the given interface decl.
|
||||
///
|
||||
/// It returns true "eagerly", meaning it will return false only if it can
|
||||
/// "prove" statically that the interface cannot accept this message.
|
||||
bool ValidReference(ASTLocation ASTLoc, ObjCInterfaceDecl *IFace) {
|
||||
assert(ASTLoc.isStmt());
|
||||
|
||||
// FIXME: Finding @selector references should be through another Analyzer
|
||||
// method, like FindSelectors.
|
||||
if (isa<ObjCSelectorExpr>(ASTLoc.AsStmt()))
|
||||
return false;
|
||||
|
||||
ObjCInterfaceDecl *MsgD = 0;
|
||||
ObjCMessageExpr *Msg = cast<ObjCMessageExpr>(ASTLoc.AsStmt());
|
||||
|
||||
switch (Msg->getReceiverKind()) {
|
||||
case ObjCMessageExpr::Instance: {
|
||||
const ObjCObjectPointerType *OPT =
|
||||
Msg->getInstanceReceiver()->getType()->getAsObjCInterfacePointerType();
|
||||
|
||||
// Can be anything! Accept it as a possibility..
|
||||
if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())
|
||||
return true;
|
||||
|
||||
// Expecting class method.
|
||||
if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType())
|
||||
return !IsInstanceMethod;
|
||||
|
||||
MsgD = OPT->getInterfaceDecl();
|
||||
assert(MsgD);
|
||||
|
||||
// Should be an instance method.
|
||||
if (!IsInstanceMethod)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
case ObjCMessageExpr::Class: {
|
||||
// Expecting class method.
|
||||
if (IsInstanceMethod)
|
||||
return false;
|
||||
|
||||
MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
|
||||
break;
|
||||
}
|
||||
|
||||
case ObjCMessageExpr::SuperClass:
|
||||
// Expecting class method.
|
||||
if (IsInstanceMethod)
|
||||
return false;
|
||||
|
||||
MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
|
||||
break;
|
||||
|
||||
case ObjCMessageExpr::SuperInstance:
|
||||
// Expecting instance method.
|
||||
if (!IsInstanceMethod)
|
||||
return false;
|
||||
|
||||
MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
|
||||
->getInterfaceDecl();
|
||||
break;
|
||||
}
|
||||
|
||||
assert(MsgD);
|
||||
|
||||
// Same interface ? We have a winner!
|
||||
if (declaresSameEntity(MsgD, IFace))
|
||||
return true;
|
||||
|
||||
// If the message interface is a superclass of the original interface,
|
||||
// accept this message as a possibility.
|
||||
if (HierarchyEntities.count(Entity::get(MsgD, Prog)))
|
||||
return true;
|
||||
|
||||
// If the message interface is a subclass of the original interface, accept
|
||||
// the message unless there is a subclass in the hierarchy that will
|
||||
// "steal" the message (thus the message "will go" to the subclass and not
|
||||
/// the original interface).
|
||||
if (IFace) {
|
||||
Selector Sel = Msg->getSelector();
|
||||
for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
|
||||
if (declaresSameEntity(Cls, IFace))
|
||||
return true;
|
||||
if (Cls->getMethod(Sel, IsInstanceMethod))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// The interfaces are unrelated, don't accept the message.
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MessageAnalyzer Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// \brief Accepts an ObjC message expression and finds all methods that may
|
||||
/// respond to it.
|
||||
class MessageAnalyzer : public TranslationUnitHandler {
|
||||
Program &Prog;
|
||||
TULocationHandler &TULocHandler;
|
||||
|
||||
// The ObjCInterface associated with the message. Can be null/invalid.
|
||||
Entity MsgIFaceEnt;
|
||||
GlobalSelector GlobSel;
|
||||
bool CanBeInstanceMethod;
|
||||
bool CanBeClassMethod;
|
||||
|
||||
/// \brief Super classes of the ObjCInterface.
|
||||
typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
|
||||
EntitiesSetTy HierarchyEntities;
|
||||
|
||||
/// \brief The interface in the message interface hierarchy that "intercepts"
|
||||
/// the selector.
|
||||
Entity ReceiverIFaceEnt;
|
||||
|
||||
public:
|
||||
MessageAnalyzer(ObjCMessageExpr *Msg,
|
||||
Program &prog, TULocationHandler &handler)
|
||||
: Prog(prog), TULocHandler(handler),
|
||||
CanBeInstanceMethod(false),
|
||||
CanBeClassMethod(false) {
|
||||
|
||||
assert(Msg);
|
||||
|
||||
ObjCInterfaceDecl *MsgD = 0;
|
||||
|
||||
while (true) {
|
||||
switch (Msg->getReceiverKind()) {
|
||||
case ObjCMessageExpr::Instance: {
|
||||
const ObjCObjectPointerType *OPT =
|
||||
Msg->getInstanceReceiver()->getType()
|
||||
->getAsObjCInterfacePointerType();
|
||||
|
||||
if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()) {
|
||||
CanBeInstanceMethod = CanBeClassMethod = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
|
||||
CanBeClassMethod = true;
|
||||
break;
|
||||
}
|
||||
|
||||
MsgD = OPT->getInterfaceDecl();
|
||||
assert(MsgD);
|
||||
CanBeInstanceMethod = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case ObjCMessageExpr::Class:
|
||||
CanBeClassMethod = true;
|
||||
MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
|
||||
break;
|
||||
|
||||
case ObjCMessageExpr::SuperClass:
|
||||
CanBeClassMethod = true;
|
||||
MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
|
||||
break;
|
||||
|
||||
case ObjCMessageExpr::SuperInstance:
|
||||
CanBeInstanceMethod = true;
|
||||
MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
|
||||
->getInterfaceDecl();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(CanBeInstanceMethod || CanBeClassMethod);
|
||||
|
||||
Selector sel = Msg->getSelector();
|
||||
assert(!sel.isNull());
|
||||
|
||||
MsgIFaceEnt = Entity::get(MsgD, Prog);
|
||||
GlobSel = GlobalSelector::get(sel, Prog);
|
||||
|
||||
if (MsgD) {
|
||||
for (ObjCInterfaceDecl *Cls = MsgD->getSuperClass();
|
||||
Cls; Cls = Cls->getSuperClass())
|
||||
HierarchyEntities.insert(Entity::get(Cls, Prog));
|
||||
|
||||
// Find the interface in the hierarchy that "receives" the message.
|
||||
for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
|
||||
bool isReceiver = false;
|
||||
|
||||
ObjCInterfaceDecl::lookup_const_iterator Meth, MethEnd;
|
||||
for (llvm::tie(Meth, MethEnd) = Cls->lookup(sel);
|
||||
Meth != MethEnd; ++Meth) {
|
||||
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth))
|
||||
if ((MD->isInstanceMethod() && CanBeInstanceMethod) ||
|
||||
(MD->isClassMethod() && CanBeClassMethod)) {
|
||||
isReceiver = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isReceiver) {
|
||||
ReceiverIFaceEnt = Entity::get(Cls, Prog);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Handle(TranslationUnit *TU) {
|
||||
assert(TU && "Passed null translation unit");
|
||||
ASTContext &Ctx = TU->getASTContext();
|
||||
|
||||
// Null means it doesn't exist in this translation unit or there was no
|
||||
// interface that was determined to receive the original message.
|
||||
ObjCInterfaceDecl *ReceiverIFace =
|
||||
cast_or_null<ObjCInterfaceDecl>(ReceiverIFaceEnt.getDecl(Ctx));
|
||||
|
||||
// No subclass for the original receiver interface, so it remains the
|
||||
// receiver.
|
||||
if (ReceiverIFaceEnt.isValid() && ReceiverIFace == 0)
|
||||
return;
|
||||
|
||||
// Null means it doesn't exist in this translation unit or there was no
|
||||
// interface associated with the message in the first place.
|
||||
ObjCInterfaceDecl *MsgIFace =
|
||||
cast_or_null<ObjCInterfaceDecl>(MsgIFaceEnt.getDecl(Ctx));
|
||||
|
||||
Selector Sel = GlobSel.getSelector(Ctx);
|
||||
SelectorMap &SelMap = TU->getSelectorMap();
|
||||
for (SelectorMap::method_iterator
|
||||
I = SelMap.methods_begin(Sel), E = SelMap.methods_end(Sel);
|
||||
I != E; ++I) {
|
||||
ObjCMethodDecl *D = *I;
|
||||
if (ValidMethod(D, MsgIFace, ReceiverIFace)) {
|
||||
for (ObjCMethodDecl::redecl_iterator
|
||||
RI = D->redecls_begin(), RE = D->redecls_end(); RI != RE; ++RI)
|
||||
TULocHandler.Handle(TULocation(TU, ASTLocation(*RI)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Determines whether the given method is likely to accept the
|
||||
/// original message.
|
||||
///
|
||||
/// It returns true "eagerly", meaning it will return false only if it can
|
||||
/// "prove" statically that the method cannot accept the original message.
|
||||
bool ValidMethod(ObjCMethodDecl *D, ObjCInterfaceDecl *MsgIFace,
|
||||
ObjCInterfaceDecl *ReceiverIFace) {
|
||||
assert(D);
|
||||
|
||||
// FIXME: Protocol methods ?
|
||||
if (isa<ObjCProtocolDecl>(D->getDeclContext()))
|
||||
return false;
|
||||
|
||||
// No specific interface associated with the message. Can be anything.
|
||||
if (MsgIFaceEnt.isInvalid())
|
||||
return true;
|
||||
|
||||
if ((!CanBeInstanceMethod && D->isInstanceMethod()) ||
|
||||
(!CanBeClassMethod && D->isClassMethod()))
|
||||
return false;
|
||||
|
||||
ObjCInterfaceDecl *IFace = D->getClassInterface();
|
||||
assert(IFace);
|
||||
|
||||
// If the original message interface is the same or a superclass of the
|
||||
// given interface, accept the method as a possibility.
|
||||
if (MsgIFace && MsgIFace->isSuperClassOf(IFace))
|
||||
return true;
|
||||
|
||||
if (ReceiverIFace) {
|
||||
// The given interface, "overrides" the receiver.
|
||||
if (ReceiverIFace->isSuperClassOf(IFace))
|
||||
return true;
|
||||
} else {
|
||||
// No receiver was found for the original message.
|
||||
assert(ReceiverIFaceEnt.isInvalid());
|
||||
|
||||
// If the original message interface is a subclass of the given interface,
|
||||
// accept the message.
|
||||
if (HierarchyEntities.count(Entity::get(IFace, Prog)))
|
||||
return true;
|
||||
}
|
||||
|
||||
// The interfaces are unrelated, or the receiver interface wasn't
|
||||
// "overriden".
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Analyzer Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void Analyzer::FindDeclarations(Decl *D, TULocationHandler &Handler) {
|
||||
assert(D && "Passed null declaration");
|
||||
Entity Ent = Entity::get(D, Prog);
|
||||
if (Ent.isInvalid())
|
||||
return;
|
||||
|
||||
DeclEntityAnalyzer DEA(Ent, Handler);
|
||||
Idxer.GetTranslationUnitsFor(Ent, DEA);
|
||||
}
|
||||
|
||||
void Analyzer::FindReferences(Decl *D, TULocationHandler &Handler) {
|
||||
assert(D && "Passed null declaration");
|
||||
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
|
||||
RefSelectorAnalyzer RSA(MD, Prog, Handler);
|
||||
GlobalSelector Sel = GlobalSelector::get(MD->getSelector(), Prog);
|
||||
Idxer.GetTranslationUnitsFor(Sel, RSA);
|
||||
return;
|
||||
}
|
||||
|
||||
Entity Ent = Entity::get(D, Prog);
|
||||
if (Ent.isInvalid())
|
||||
return;
|
||||
|
||||
RefEntityAnalyzer REA(Ent, Handler);
|
||||
Idxer.GetTranslationUnitsFor(Ent, REA);
|
||||
}
|
||||
|
||||
/// \brief Find methods that may respond to the given message and pass them
|
||||
/// to Handler.
|
||||
void Analyzer::FindObjCMethods(ObjCMessageExpr *Msg,
|
||||
TULocationHandler &Handler) {
|
||||
assert(Msg);
|
||||
MessageAnalyzer MsgAnalyz(Msg, Prog, Handler);
|
||||
GlobalSelector GlobSel = GlobalSelector::get(Msg->getSelector(), Prog);
|
||||
Idxer.GetTranslationUnitsFor(GlobSel, MsgAnalyz);
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
set(LLVM_USED_LIBS clangBasic clangAST)
|
||||
|
||||
add_clang_library(clangIndex
|
||||
ASTLocation.cpp
|
||||
Analyzer.cpp
|
||||
GlobalCallGraph.cpp
|
||||
DeclReferenceMap.cpp
|
||||
Entity.cpp
|
||||
GlobalSelector.cpp
|
||||
Handlers.cpp
|
||||
IndexProvider.cpp
|
||||
Indexer.cpp
|
||||
Program.cpp
|
||||
SelectorMap.cpp
|
||||
)
|
||||
|
||||
add_dependencies(clangIndex ClangAttrClasses ClangAttrList
|
||||
ClangDeclNodes ClangStmtNodes)
|
|
@ -1,90 +0,0 @@
|
|||
//===--- DeclReferenceMap.cpp - Map Decls to their references -------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// DeclReferenceMap creates a mapping from Decls to the ASTLocations that
|
||||
// reference them.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/DeclReferenceMap.h"
|
||||
#include "clang/Index/ASTLocation.h"
|
||||
#include "ASTVisitor.h"
|
||||
using namespace clang;
|
||||
using namespace idx;
|
||||
|
||||
namespace {
|
||||
|
||||
class RefMapper : public ASTVisitor<RefMapper> {
|
||||
DeclReferenceMap::MapTy ⤅
|
||||
|
||||
public:
|
||||
RefMapper(DeclReferenceMap::MapTy &map) : Map(map) { }
|
||||
|
||||
void VisitDeclRefExpr(DeclRefExpr *Node);
|
||||
void VisitMemberExpr(MemberExpr *Node);
|
||||
void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
|
||||
|
||||
void VisitTypedefTypeLoc(TypedefTypeLoc TL);
|
||||
void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// RefMapper Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void RefMapper::VisitDeclRefExpr(DeclRefExpr *Node) {
|
||||
NamedDecl *PrimD = cast<NamedDecl>(Node->getDecl()->getCanonicalDecl());
|
||||
Map.insert(std::make_pair(PrimD, ASTLocation(CurrentDecl, Node)));
|
||||
}
|
||||
|
||||
void RefMapper::VisitMemberExpr(MemberExpr *Node) {
|
||||
NamedDecl *PrimD = cast<NamedDecl>(Node->getMemberDecl()->getCanonicalDecl());
|
||||
Map.insert(std::make_pair(PrimD, ASTLocation(CurrentDecl, Node)));
|
||||
}
|
||||
|
||||
void RefMapper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
|
||||
Map.insert(std::make_pair(Node->getDecl(), ASTLocation(CurrentDecl, Node)));
|
||||
}
|
||||
|
||||
void RefMapper::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
|
||||
NamedDecl *ND = TL.getTypedefNameDecl();
|
||||
Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc())));
|
||||
}
|
||||
|
||||
void RefMapper::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
|
||||
NamedDecl *ND = TL.getIFaceDecl();
|
||||
Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc())));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DeclReferenceMap Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
DeclReferenceMap::DeclReferenceMap(ASTContext &Ctx) {
|
||||
RefMapper(Map).Visit(Ctx.getTranslationUnitDecl());
|
||||
}
|
||||
|
||||
DeclReferenceMap::astlocation_iterator
|
||||
DeclReferenceMap::refs_begin(NamedDecl *D) const {
|
||||
NamedDecl *Prim = cast<NamedDecl>(D->getCanonicalDecl());
|
||||
return astlocation_iterator(Map.lower_bound(Prim));
|
||||
}
|
||||
|
||||
DeclReferenceMap::astlocation_iterator
|
||||
DeclReferenceMap::refs_end(NamedDecl *D) const {
|
||||
NamedDecl *Prim = cast<NamedDecl>(D->getCanonicalDecl());
|
||||
return astlocation_iterator(Map.upper_bound(Prim));
|
||||
}
|
||||
|
||||
bool DeclReferenceMap::refs_empty(NamedDecl *D) const {
|
||||
NamedDecl *Prim = cast<NamedDecl>(D->getCanonicalDecl());
|
||||
return refs_begin(Prim) == refs_end(Prim);
|
||||
}
|
|
@ -1,270 +0,0 @@
|
|||
//===--- Entity.cpp - Cross-translation-unit "token" for decls ------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Entity is a ASTContext-independent way to refer to declarations that are
|
||||
// visible across translation units.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "EntityImpl.h"
|
||||
#include "ProgramImpl.h"
|
||||
#include "clang/Index/Program.h"
|
||||
#include "clang/Index/GlobalSelector.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/DeclVisitor.h"
|
||||
using namespace clang;
|
||||
using namespace idx;
|
||||
|
||||
// FIXME: Entity is really really basic currently, mostly written to work
|
||||
// on variables and functions. Should support types and other decls eventually..
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// EntityGetter
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace clang {
|
||||
namespace idx {
|
||||
|
||||
/// \brief Gets the Entity associated with a Decl.
|
||||
class EntityGetter : public DeclVisitor<EntityGetter, Entity> {
|
||||
Program &Prog;
|
||||
ProgramImpl &ProgImpl;
|
||||
|
||||
public:
|
||||
EntityGetter(Program &prog, ProgramImpl &progImpl)
|
||||
: Prog(prog), ProgImpl(progImpl) { }
|
||||
|
||||
// Get an Entity.
|
||||
Entity getEntity(Entity Parent, DeclarationName Name,
|
||||
unsigned IdNS, bool isObjCInstanceMethod);
|
||||
|
||||
// Get an Entity associated with the name in the global namespace.
|
||||
Entity getGlobalEntity(StringRef Name);
|
||||
|
||||
Entity VisitNamedDecl(NamedDecl *D);
|
||||
Entity VisitVarDecl(VarDecl *D);
|
||||
Entity VisitFieldDecl(FieldDecl *D);
|
||||
Entity VisitFunctionDecl(FunctionDecl *D);
|
||||
Entity VisitTypeDecl(TypeDecl *D);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Entity EntityGetter::getEntity(Entity Parent, DeclarationName Name,
|
||||
unsigned IdNS, bool isObjCInstanceMethod) {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
EntityImpl::Profile(ID, Parent, Name, IdNS, isObjCInstanceMethod);
|
||||
|
||||
ProgramImpl::EntitySetTy &Entities = ProgImpl.getEntities();
|
||||
void *InsertPos = 0;
|
||||
if (EntityImpl *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return Entity(Ent);
|
||||
|
||||
void *Buf = ProgImpl.Allocate(sizeof(EntityImpl));
|
||||
EntityImpl *New =
|
||||
new (Buf) EntityImpl(Parent, Name, IdNS, isObjCInstanceMethod);
|
||||
Entities.InsertNode(New, InsertPos);
|
||||
|
||||
return Entity(New);
|
||||
}
|
||||
|
||||
Entity EntityGetter::getGlobalEntity(StringRef Name) {
|
||||
IdentifierInfo *II = &ProgImpl.getIdents().get(Name);
|
||||
DeclarationName GlobName(II);
|
||||
unsigned IdNS = Decl::IDNS_Ordinary;
|
||||
return getEntity(Entity(), GlobName, IdNS, false);
|
||||
}
|
||||
|
||||
Entity EntityGetter::VisitNamedDecl(NamedDecl *D) {
|
||||
Entity Parent;
|
||||
if (!D->getDeclContext()->isTranslationUnit()) {
|
||||
Parent = Visit(cast<Decl>(D->getDeclContext()));
|
||||
// FIXME: Anonymous structs ?
|
||||
if (Parent.isInvalid())
|
||||
return Entity();
|
||||
}
|
||||
if (Parent.isValid() && Parent.isInternalToTU())
|
||||
return Entity(D);
|
||||
|
||||
// FIXME: Only works for DeclarationNames that are identifiers and selectors.
|
||||
// Treats other DeclarationNames as internal Decls for now..
|
||||
|
||||
DeclarationName LocalName = D->getDeclName();
|
||||
if (!LocalName)
|
||||
return Entity(D);
|
||||
|
||||
DeclarationName GlobName;
|
||||
|
||||
if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) {
|
||||
IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName());
|
||||
GlobName = DeclarationName(GlobII);
|
||||
} else {
|
||||
Selector LocalSel = LocalName.getObjCSelector();
|
||||
|
||||
// Treats other DeclarationNames as internal Decls for now..
|
||||
if (LocalSel.isNull())
|
||||
return Entity(D);
|
||||
|
||||
Selector GlobSel =
|
||||
(uintptr_t)GlobalSelector::get(LocalSel, Prog).getAsOpaquePtr();
|
||||
GlobName = DeclarationName(GlobSel);
|
||||
}
|
||||
|
||||
assert(GlobName);
|
||||
|
||||
unsigned IdNS = D->getIdentifierNamespace();
|
||||
|
||||
ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D);
|
||||
bool isObjCInstanceMethod = MD && MD->isInstanceMethod();
|
||||
return getEntity(Parent, GlobName, IdNS, isObjCInstanceMethod);
|
||||
}
|
||||
|
||||
Entity EntityGetter::VisitVarDecl(VarDecl *D) {
|
||||
// Local variables have no linkage, make invalid Entities.
|
||||
if (D->hasLocalStorage())
|
||||
return Entity();
|
||||
|
||||
// If it's static it cannot be referred to by another translation unit.
|
||||
if (D->getStorageClass() == SC_Static)
|
||||
return Entity(D);
|
||||
|
||||
return VisitNamedDecl(D);
|
||||
}
|
||||
|
||||
Entity EntityGetter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
// If it's static it cannot be referred to by another translation unit.
|
||||
if (D->getStorageClass() == SC_Static)
|
||||
return Entity(D);
|
||||
|
||||
return VisitNamedDecl(D);
|
||||
}
|
||||
|
||||
Entity EntityGetter::VisitFieldDecl(FieldDecl *D) {
|
||||
// Make FieldDecl an invalid Entity since it has no linkage.
|
||||
return Entity();
|
||||
}
|
||||
|
||||
Entity EntityGetter::VisitTypeDecl(TypeDecl *D) {
|
||||
// Although in C++ class name has external linkage, usually the definition of
|
||||
// the class is available in the same translation unit when it's needed. So we
|
||||
// make all of them invalid Entity.
|
||||
return Entity();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// EntityImpl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
Decl *EntityImpl::getDecl(ASTContext &AST) {
|
||||
DeclContext *DC =
|
||||
Parent.isInvalid() ? AST.getTranslationUnitDecl()
|
||||
: cast<DeclContext>(Parent.getDecl(AST));
|
||||
if (!DC)
|
||||
return 0; // Couldn't get the parent context.
|
||||
|
||||
DeclarationName LocalName;
|
||||
|
||||
if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) {
|
||||
IdentifierInfo &II = AST.Idents.get(GlobII->getName());
|
||||
LocalName = DeclarationName(&II);
|
||||
} else {
|
||||
Selector GlobSel = Name.getObjCSelector();
|
||||
assert(!GlobSel.isNull() && "A not handled yet declaration name");
|
||||
GlobalSelector GSel =
|
||||
GlobalSelector::getFromOpaquePtr(GlobSel.getAsOpaquePtr());
|
||||
LocalName = GSel.getSelector(AST);
|
||||
}
|
||||
|
||||
assert(LocalName);
|
||||
|
||||
DeclContext::lookup_result Res = DC->lookup(LocalName);
|
||||
for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) {
|
||||
Decl *D = *I;
|
||||
if (D->getIdentifierNamespace() == IdNS) {
|
||||
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
|
||||
if (MD->isInstanceMethod() == IsObjCInstanceMethod)
|
||||
return MD;
|
||||
} else
|
||||
return D;
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // Failed to find a decl using this Entity.
|
||||
}
|
||||
|
||||
/// \brief Get an Entity associated with the given Decl.
|
||||
/// \returns Null if an Entity cannot refer to this Decl.
|
||||
Entity EntityImpl::get(Decl *D, Program &Prog, ProgramImpl &ProgImpl) {
|
||||
assert(D && "Passed null Decl");
|
||||
return EntityGetter(Prog, ProgImpl).Visit(D);
|
||||
}
|
||||
|
||||
/// \brief Get an Entity associated with a global name.
|
||||
Entity EntityImpl::get(StringRef Name, Program &Prog,
|
||||
ProgramImpl &ProgImpl) {
|
||||
return EntityGetter(Prog, ProgImpl).getGlobalEntity(Name);
|
||||
}
|
||||
|
||||
std::string EntityImpl::getPrintableName() {
|
||||
return Name.getAsString();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Entity Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
Entity::Entity(Decl *D) : Val(D->getCanonicalDecl()) { }
|
||||
|
||||
/// \brief Find the Decl that can be referred to by this entity.
|
||||
Decl *Entity::getDecl(ASTContext &AST) const {
|
||||
if (isInvalid())
|
||||
return 0;
|
||||
|
||||
if (Decl *D = Val.dyn_cast<Decl *>())
|
||||
// Check that the passed AST is actually the one that this Decl belongs to.
|
||||
return (&D->getASTContext() == &AST) ? D : 0;
|
||||
|
||||
return Val.get<EntityImpl *>()->getDecl(AST);
|
||||
}
|
||||
|
||||
std::string Entity::getPrintableName() const {
|
||||
if (isInvalid())
|
||||
return "<< Invalid >>";
|
||||
|
||||
if (Decl *D = Val.dyn_cast<Decl *>()) {
|
||||
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
|
||||
return ND->getNameAsString();
|
||||
else
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return Val.get<EntityImpl *>()->getPrintableName();
|
||||
}
|
||||
|
||||
/// \brief Get an Entity associated with the given Decl.
|
||||
/// \returns Null if an Entity cannot refer to this Decl.
|
||||
Entity Entity::get(Decl *D, Program &Prog) {
|
||||
if (D == 0)
|
||||
return Entity();
|
||||
ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
|
||||
return EntityImpl::get(D, Prog, ProgImpl);
|
||||
}
|
||||
|
||||
Entity Entity::get(StringRef Name, Program &Prog) {
|
||||
ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
|
||||
return EntityImpl::get(Name, Prog, ProgImpl);
|
||||
}
|
||||
|
||||
unsigned
|
||||
llvm::DenseMapInfo<Entity>::getHashValue(Entity E) {
|
||||
return DenseMapInfo<void*>::getHashValue(E.getAsOpaquePtr());
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
//===--- EntityImpl.h - Internal Entity implementation---------*- C++ -*-=====//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Internal implementation for the Entity class
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_ENTITYIMPL_H
|
||||
#define LLVM_CLANG_INDEX_ENTITYIMPL_H
|
||||
|
||||
#include "clang/Index/Entity.h"
|
||||
#include "clang/AST/DeclarationName.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
namespace idx {
|
||||
class ProgramImpl;
|
||||
|
||||
class EntityImpl : public llvm::FoldingSetNode {
|
||||
Entity Parent;
|
||||
DeclarationName Name;
|
||||
|
||||
/// \brief Identifier namespace.
|
||||
unsigned IdNS;
|
||||
|
||||
/// \brief If Name is a selector, this keeps track whether it's for an
|
||||
/// instance method.
|
||||
bool IsObjCInstanceMethod;
|
||||
|
||||
public:
|
||||
EntityImpl(Entity parent, DeclarationName name, unsigned idNS,
|
||||
bool isObjCInstanceMethod)
|
||||
: Parent(parent), Name(name), IdNS(idNS),
|
||||
IsObjCInstanceMethod(isObjCInstanceMethod) { }
|
||||
|
||||
/// \brief Find the Decl that can be referred to by this entity.
|
||||
Decl *getDecl(ASTContext &AST);
|
||||
|
||||
/// \brief Get an Entity associated with the given Decl.
|
||||
/// \returns Null if an Entity cannot refer to this Decl.
|
||||
static Entity get(Decl *D, Program &Prog, ProgramImpl &ProgImpl);
|
||||
static Entity get(StringRef Name, Program &Prog, ProgramImpl &ProgImpl);
|
||||
|
||||
std::string getPrintableName();
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||
Profile(ID, Parent, Name, IdNS, IsObjCInstanceMethod);
|
||||
}
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, Entity Parent,
|
||||
DeclarationName Name, unsigned IdNS,
|
||||
bool isObjCInstanceMethod) {
|
||||
ID.AddPointer(Parent.getAsOpaquePtr());
|
||||
ID.AddPointer(Name.getAsOpaquePtr());
|
||||
ID.AddInteger(IdNS);
|
||||
ID.AddBoolean(isObjCInstanceMethod);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -1,152 +0,0 @@
|
|||
//== GlobalCallGraph.cpp - Call graph building ------------------*- C++ -*--==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defined the CallGraph and CGBuilder classes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/GlobalCallGraph.h"
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/StmtVisitor.h"
|
||||
|
||||
#include "llvm/Support/GraphWriter.h"
|
||||
|
||||
using namespace clang::idx;
|
||||
using clang::FunctionDecl;
|
||||
using clang::DeclContext;
|
||||
using clang::ASTContext;
|
||||
|
||||
namespace {
|
||||
class CGBuilder : public StmtVisitor<CGBuilder> {
|
||||
|
||||
CallGraph &G;
|
||||
FunctionDecl *FD;
|
||||
|
||||
Entity CallerEnt;
|
||||
|
||||
CallGraphNode *CallerNode;
|
||||
|
||||
public:
|
||||
CGBuilder(CallGraph &g, FunctionDecl *fd, Entity E, CallGraphNode *N)
|
||||
: G(g), FD(fd), CallerEnt(E), CallerNode(N) {}
|
||||
|
||||
void VisitStmt(Stmt *S) { VisitChildren(S); }
|
||||
|
||||
void VisitCallExpr(CallExpr *CE);
|
||||
|
||||
void VisitChildren(Stmt *S) {
|
||||
for (Stmt::child_range I = S->children(); I; ++I)
|
||||
if (*I)
|
||||
static_cast<CGBuilder*>(this)->Visit(*I);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void CGBuilder::VisitCallExpr(CallExpr *CE) {
|
||||
if (FunctionDecl *CalleeDecl = CE->getDirectCallee()) {
|
||||
Entity Ent = Entity::get(CalleeDecl, G.getProgram());
|
||||
CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent);
|
||||
CallerNode->addCallee(ASTLocation(FD, CE), CalleeNode);
|
||||
}
|
||||
}
|
||||
|
||||
CallGraph::CallGraph(Program &P) : Prog(P), Root(0) {
|
||||
ExternalCallingNode = getOrInsertFunction(Entity());
|
||||
}
|
||||
|
||||
CallGraph::~CallGraph() {
|
||||
if (!FunctionMap.empty()) {
|
||||
for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
|
||||
I != E; ++I)
|
||||
delete I->second;
|
||||
FunctionMap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void CallGraph::addTU(ASTContext& Ctx) {
|
||||
DeclContext *DC = Ctx.getTranslationUnitDecl();
|
||||
for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
|
||||
I != E; ++I) {
|
||||
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) {
|
||||
if (FD->doesThisDeclarationHaveABody()) {
|
||||
// Set caller's ASTContext.
|
||||
Entity Ent = Entity::get(FD, Prog);
|
||||
CallGraphNode *Node = getOrInsertFunction(Ent);
|
||||
CallerCtx[Node] = &Ctx;
|
||||
|
||||
// If this function has external linkage, anything could call it.
|
||||
if (FD->isGlobal())
|
||||
ExternalCallingNode->addCallee(idx::ASTLocation(), Node);
|
||||
|
||||
// Set root node to 'main' function.
|
||||
if (FD->getNameAsString() == "main")
|
||||
Root = Node;
|
||||
|
||||
CGBuilder builder(*this, FD, Ent, Node);
|
||||
builder.Visit(FD->getBody());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CallGraphNode *CallGraph::getOrInsertFunction(Entity F) {
|
||||
CallGraphNode *&Node = FunctionMap[F];
|
||||
if (Node)
|
||||
return Node;
|
||||
|
||||
return Node = new CallGraphNode(F);
|
||||
}
|
||||
|
||||
Decl *CallGraph::getDecl(CallGraphNode *Node) {
|
||||
// Get the function's context.
|
||||
ASTContext *Ctx = CallerCtx[Node];
|
||||
|
||||
return Node->getDecl(*Ctx);
|
||||
}
|
||||
|
||||
void CallGraph::print(raw_ostream &os) {
|
||||
for (iterator I = begin(), E = end(); I != E; ++I) {
|
||||
if (I->second->hasCallee()) {
|
||||
os << "function: " << I->first.getPrintableName()
|
||||
<< " calls:\n";
|
||||
for (CallGraphNode::iterator CI = I->second->begin(),
|
||||
CE = I->second->end(); CI != CE; ++CI) {
|
||||
os << " " << CI->second->getName();
|
||||
}
|
||||
os << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CallGraph::dump() {
|
||||
print(llvm::errs());
|
||||
}
|
||||
|
||||
void CallGraph::ViewCallGraph() const {
|
||||
llvm::ViewGraph(*this, "CallGraph");
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template <>
|
||||
struct DOTGraphTraits<CallGraph> : public DefaultDOTGraphTraits {
|
||||
|
||||
DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
|
||||
|
||||
static std::string getNodeLabel(const CallGraphNode *Node,
|
||||
const CallGraph &CG) {
|
||||
return Node->getName();
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
//===-- GlobalSelector.cpp - Cross-translation-unit "token" for selectors -===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// GlobalSelector is a ASTContext-independent way to refer to selectors.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/GlobalSelector.h"
|
||||
#include "ProgramImpl.h"
|
||||
#include "clang/Index/Program.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
using namespace clang;
|
||||
using namespace idx;
|
||||
|
||||
/// \brief Get the ASTContext-specific selector.
|
||||
Selector GlobalSelector::getSelector(ASTContext &AST) const {
|
||||
if (isInvalid())
|
||||
return Selector();
|
||||
|
||||
Selector GlobSel = Selector(reinterpret_cast<uintptr_t>(Val));
|
||||
|
||||
SmallVector<IdentifierInfo *, 8> Ids;
|
||||
for (unsigned i = 0, e = GlobSel.isUnarySelector() ? 1 : GlobSel.getNumArgs();
|
||||
i != e; ++i) {
|
||||
IdentifierInfo *GlobII = GlobSel.getIdentifierInfoForSlot(i);
|
||||
IdentifierInfo *II = &AST.Idents.get(GlobII->getName());
|
||||
Ids.push_back(II);
|
||||
}
|
||||
|
||||
return AST.Selectors.getSelector(GlobSel.getNumArgs(), Ids.data());
|
||||
}
|
||||
|
||||
/// \brief Get a printable name for debugging purpose.
|
||||
std::string GlobalSelector::getPrintableName() const {
|
||||
if (isInvalid())
|
||||
return "<< Invalid >>";
|
||||
|
||||
Selector GlobSel = Selector(reinterpret_cast<uintptr_t>(Val));
|
||||
return GlobSel.getAsString();
|
||||
}
|
||||
|
||||
/// \brief Get a GlobalSelector for the ASTContext-specific selector.
|
||||
GlobalSelector GlobalSelector::get(Selector Sel, Program &Prog) {
|
||||
if (Sel.isNull())
|
||||
return GlobalSelector();
|
||||
|
||||
ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
|
||||
|
||||
SmallVector<IdentifierInfo *, 8> Ids;
|
||||
for (unsigned i = 0, e = Sel.isUnarySelector() ? 1 : Sel.getNumArgs();
|
||||
i != e; ++i) {
|
||||
IdentifierInfo *II = Sel.getIdentifierInfoForSlot(i);
|
||||
IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName());
|
||||
Ids.push_back(GlobII);
|
||||
}
|
||||
|
||||
Selector GlobSel = ProgImpl.getSelectors().getSelector(Sel.getNumArgs(),
|
||||
Ids.data());
|
||||
return GlobalSelector(GlobSel.getAsOpaquePtr());
|
||||
}
|
||||
|
||||
unsigned
|
||||
llvm::DenseMapInfo<GlobalSelector>::getHashValue(GlobalSelector Sel) {
|
||||
return DenseMapInfo<void*>::getHashValue(Sel.getAsOpaquePtr());
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
//===--- Handlers.cpp - Interfaces for receiving information ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Abstract interfaces for receiving information.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/Handlers.h"
|
||||
#include "clang/Index/Entity.h"
|
||||
using namespace clang;
|
||||
using namespace idx;
|
||||
|
||||
// Out-of-line to give the virtual tables a home.
|
||||
EntityHandler::~EntityHandler() { }
|
||||
TranslationUnitHandler::~TranslationUnitHandler() { }
|
||||
TULocationHandler::~TULocationHandler() { }
|
|
@ -1,20 +0,0 @@
|
|||
//===- IndexProvider.cpp - Maps information to translation units -*- C++ -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Maps information to TranslationUnits.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/IndexProvider.h"
|
||||
#include "clang/Index/Entity.h"
|
||||
using namespace clang;
|
||||
using namespace idx;
|
||||
|
||||
// Out-of-line to give the virtual table a home.
|
||||
IndexProvider::~IndexProvider() { }
|
|
@ -1,121 +0,0 @@
|
|||
//===--- Indexer.cpp - IndexProvider implementation -------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// IndexProvider implementation.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/Indexer.h"
|
||||
#include "clang/Index/Program.h"
|
||||
#include "clang/Index/Handlers.h"
|
||||
#include "clang/Index/TranslationUnit.h"
|
||||
#include "ASTVisitor.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
using namespace clang;
|
||||
using namespace idx;
|
||||
|
||||
namespace {
|
||||
|
||||
class EntityIndexer : public EntityHandler {
|
||||
TranslationUnit *TU;
|
||||
Indexer::MapTy ⤅
|
||||
Indexer::DefMapTy &DefMap;
|
||||
|
||||
public:
|
||||
EntityIndexer(TranslationUnit *tu, Indexer::MapTy &map,
|
||||
Indexer::DefMapTy &defmap)
|
||||
: TU(tu), Map(map), DefMap(defmap) { }
|
||||
|
||||
virtual void Handle(Entity Ent) {
|
||||
if (Ent.isInternalToTU())
|
||||
return;
|
||||
Map[Ent].insert(TU);
|
||||
|
||||
Decl *D = Ent.getDecl(TU->getASTContext());
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
|
||||
if (FD->doesThisDeclarationHaveABody())
|
||||
DefMap[Ent] = std::make_pair(FD, TU);
|
||||
}
|
||||
};
|
||||
|
||||
class SelectorIndexer : public ASTVisitor<SelectorIndexer> {
|
||||
Program &Prog;
|
||||
TranslationUnit *TU;
|
||||
Indexer::SelMapTy ⤅
|
||||
|
||||
public:
|
||||
SelectorIndexer(Program &prog, TranslationUnit *tu, Indexer::SelMapTy &map)
|
||||
: Prog(prog), TU(tu), Map(map) { }
|
||||
|
||||
void VisitObjCMethodDecl(ObjCMethodDecl *D) {
|
||||
Map[GlobalSelector::get(D->getSelector(), Prog)].insert(TU);
|
||||
Base::VisitObjCMethodDecl(D);
|
||||
}
|
||||
|
||||
void VisitObjCMessageExpr(ObjCMessageExpr *Node) {
|
||||
Map[GlobalSelector::get(Node->getSelector(), Prog)].insert(TU);
|
||||
Base::VisitObjCMessageExpr(Node);
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void Indexer::IndexAST(TranslationUnit *TU) {
|
||||
assert(TU && "Passed null TranslationUnit");
|
||||
ASTContext &Ctx = TU->getASTContext();
|
||||
CtxTUMap[&Ctx] = TU;
|
||||
EntityIndexer Idx(TU, Map, DefMap);
|
||||
Prog.FindEntities(Ctx, Idx);
|
||||
|
||||
SelectorIndexer SelIdx(Prog, TU, SelMap);
|
||||
SelIdx.Visit(Ctx.getTranslationUnitDecl());
|
||||
}
|
||||
|
||||
void Indexer::GetTranslationUnitsFor(Entity Ent,
|
||||
TranslationUnitHandler &Handler) {
|
||||
assert(Ent.isValid() && "Expected valid Entity");
|
||||
|
||||
if (Ent.isInternalToTU()) {
|
||||
Decl *D = Ent.getInternalDecl();
|
||||
CtxTUMapTy::iterator I = CtxTUMap.find(&D->getASTContext());
|
||||
if (I != CtxTUMap.end())
|
||||
Handler.Handle(I->second);
|
||||
return;
|
||||
}
|
||||
|
||||
MapTy::iterator I = Map.find(Ent);
|
||||
if (I == Map.end())
|
||||
return;
|
||||
|
||||
TUSetTy &Set = I->second;
|
||||
for (TUSetTy::iterator I = Set.begin(), E = Set.end(); I != E; ++I)
|
||||
Handler.Handle(*I);
|
||||
}
|
||||
|
||||
void Indexer::GetTranslationUnitsFor(GlobalSelector Sel,
|
||||
TranslationUnitHandler &Handler) {
|
||||
assert(Sel.isValid() && "Expected valid GlobalSelector");
|
||||
|
||||
SelMapTy::iterator I = SelMap.find(Sel);
|
||||
if (I == SelMap.end())
|
||||
return;
|
||||
|
||||
TUSetTy &Set = I->second;
|
||||
for (TUSetTy::iterator I = Set.begin(), E = Set.end(); I != E; ++I)
|
||||
Handler.Handle(*I);
|
||||
}
|
||||
|
||||
std::pair<FunctionDecl *, TranslationUnit *>
|
||||
Indexer::getDefinitionFor(Entity Ent) {
|
||||
DefMapTy::iterator I = DefMap.find(Ent);
|
||||
if (I == DefMap.end())
|
||||
return std::make_pair((FunctionDecl *)0, (TranslationUnit *)0);
|
||||
else
|
||||
return I->second;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
##===- clang/lib/Index/Makefile ----------------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# This implements the Indexer library for the C-Language front-end.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
CLANG_LEVEL := ../..
|
||||
LIBRARYNAME := clangIndex
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
//===--- Program.cpp - Entity originator and misc -------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Storage for Entities and utility functions
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/Program.h"
|
||||
#include "ProgramImpl.h"
|
||||
#include "clang/Index/Handlers.h"
|
||||
#include "clang/Index/TranslationUnit.h"
|
||||
#include "clang/AST/DeclBase.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace clang;
|
||||
using namespace idx;
|
||||
|
||||
// Out-of-line to give the virtual tables a home.
|
||||
TranslationUnit::~TranslationUnit() { }
|
||||
|
||||
Program::Program() : Impl(new ProgramImpl()) { }
|
||||
|
||||
Program::~Program() {
|
||||
delete static_cast<ProgramImpl *>(Impl);
|
||||
}
|
||||
|
||||
static void FindEntitiesInDC(DeclContext *DC, Program &Prog,
|
||||
EntityHandler &Handler) {
|
||||
for (DeclContext::decl_iterator
|
||||
I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
|
||||
if (I->getLocation().isInvalid())
|
||||
continue;
|
||||
Entity Ent = Entity::get(*I, Prog);
|
||||
if (Ent.isValid())
|
||||
Handler.Handle(Ent);
|
||||
if (DeclContext *SubDC = dyn_cast<DeclContext>(*I))
|
||||
FindEntitiesInDC(SubDC, Prog, Handler);
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Traverses the AST and passes all the entities to the Handler.
|
||||
void Program::FindEntities(ASTContext &Ctx, EntityHandler &Handler) {
|
||||
FindEntitiesInDC(Ctx.getTranslationUnitDecl(), *this, Handler);
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
//===--- ProgramImpl.h - Internal Program implementation---------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Internal implementation for the Program class
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_INDEX_PROGRAMIMPL_H
|
||||
#define LLVM_CLANG_INDEX_PROGRAMIMPL_H
|
||||
|
||||
#include "EntityImpl.h"
|
||||
#include "clang/Basic/IdentifierTable.h"
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
namespace idx {
|
||||
class EntityListener;
|
||||
|
||||
class ProgramImpl {
|
||||
public:
|
||||
typedef llvm::FoldingSet<EntityImpl> EntitySetTy;
|
||||
|
||||
private:
|
||||
EntitySetTy Entities;
|
||||
llvm::BumpPtrAllocator BumpAlloc;
|
||||
|
||||
IdentifierTable Identifiers;
|
||||
SelectorTable Selectors;
|
||||
|
||||
ProgramImpl(const ProgramImpl&); // do not implement
|
||||
ProgramImpl &operator=(const ProgramImpl &); // do not implement
|
||||
|
||||
public:
|
||||
ProgramImpl() : Identifiers(LangOptions()) { }
|
||||
|
||||
EntitySetTy &getEntities() { return Entities; }
|
||||
IdentifierTable &getIdents() { return Identifiers; }
|
||||
SelectorTable &getSelectors() { return Selectors; }
|
||||
|
||||
void *Allocate(unsigned Size, unsigned Align = 8) {
|
||||
return BumpAlloc.Allocate(Size, Align);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace idx
|
||||
|
||||
} // namespace clang
|
||||
|
||||
#endif
|
|
@ -1,84 +0,0 @@
|
|||
//===- SelectorMap.cpp - Maps selectors to methods and messages -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// SelectorMap creates a mapping from selectors to ObjC method declarations
|
||||
// and ObjC message expressions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Index/SelectorMap.h"
|
||||
#include "ASTVisitor.h"
|
||||
using namespace clang;
|
||||
using namespace idx;
|
||||
|
||||
namespace {
|
||||
|
||||
class SelMapper : public ASTVisitor<SelMapper> {
|
||||
SelectorMap::SelMethMapTy &SelMethMap;
|
||||
SelectorMap::SelRefMapTy &SelRefMap;
|
||||
|
||||
public:
|
||||
SelMapper(SelectorMap::SelMethMapTy &MethMap,
|
||||
SelectorMap::SelRefMapTy &RefMap)
|
||||
: SelMethMap(MethMap), SelRefMap(RefMap) { }
|
||||
|
||||
void VisitObjCMethodDecl(ObjCMethodDecl *D);
|
||||
void VisitObjCMessageExpr(ObjCMessageExpr *Node);
|
||||
void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SelMapper Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void SelMapper::VisitObjCMethodDecl(ObjCMethodDecl *D) {
|
||||
if (D->getCanonicalDecl() == D)
|
||||
SelMethMap.insert(std::make_pair(D->getSelector(), D));
|
||||
Base::VisitObjCMethodDecl(D);
|
||||
}
|
||||
|
||||
void SelMapper::VisitObjCMessageExpr(ObjCMessageExpr *Node) {
|
||||
ASTLocation ASTLoc(CurrentDecl, Node);
|
||||
SelRefMap.insert(std::make_pair(Node->getSelector(), ASTLoc));
|
||||
}
|
||||
|
||||
void SelMapper::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
|
||||
ASTLocation ASTLoc(CurrentDecl, Node);
|
||||
SelRefMap.insert(std::make_pair(Node->getSelector(), ASTLoc));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SelectorMap Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
SelectorMap::SelectorMap(ASTContext &Ctx) {
|
||||
SelMapper(SelMethMap, SelRefMap).Visit(Ctx.getTranslationUnitDecl());
|
||||
}
|
||||
|
||||
SelectorMap::method_iterator
|
||||
SelectorMap::methods_begin(Selector Sel) const {
|
||||
return method_iterator(SelMethMap.lower_bound(Sel));
|
||||
}
|
||||
|
||||
SelectorMap::method_iterator
|
||||
SelectorMap::methods_end(Selector Sel) const {
|
||||
return method_iterator(SelMethMap.upper_bound(Sel));
|
||||
}
|
||||
|
||||
SelectorMap::astlocation_iterator
|
||||
SelectorMap::refs_begin(Selector Sel) const {
|
||||
return astlocation_iterator(SelRefMap.lower_bound(Sel));
|
||||
}
|
||||
|
||||
SelectorMap::astlocation_iterator
|
||||
SelectorMap::refs_end(Selector Sel) const {
|
||||
return astlocation_iterator(SelRefMap.upper_bound(Sel));
|
||||
}
|
|
@ -10,7 +10,7 @@ CLANG_LEVEL := ..
|
|||
|
||||
PARALLEL_DIRS = Headers Basic Lex Parse AST Sema CodeGen Analysis \
|
||||
StaticAnalyzer Edit Rewrite ARCMigrate Serialization Frontend \
|
||||
FrontendTool Tooling Index Driver
|
||||
FrontendTool Tooling Driver
|
||||
|
||||
include $(CLANG_LEVEL)/Makefile
|
||||
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
|
||||
#include "clang/Index/Entity.h"
|
||||
#include "clang/Index/Indexer.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace ento;
|
||||
|
@ -22,7 +20,6 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
|
|||
StoreManagerCreator storemgr,
|
||||
ConstraintManagerCreator constraintmgr,
|
||||
CheckerManager *checkerMgr,
|
||||
idx::Indexer *idxer,
|
||||
unsigned maxnodes, unsigned maxvisit,
|
||||
bool vizdot, bool vizubi,
|
||||
AnalysisPurgeMode purge,
|
||||
|
@ -38,7 +35,7 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
|
|||
: AnaCtxMgr(useUnoptimizedCFG, addImplicitDtors, addInitializers),
|
||||
Ctx(ctx), Diags(diags), LangOpts(lang), PD(pd),
|
||||
CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
|
||||
CheckerMgr(checkerMgr), Idxer(idxer),
|
||||
CheckerMgr(checkerMgr),
|
||||
AScope(ScopeDecl), MaxNodes(maxnodes), MaxVisit(maxvisit),
|
||||
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
|
||||
EagerlyAssume(eager), TrimGraph(trim),
|
||||
|
@ -62,7 +59,6 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
|
|||
CreateStoreMgr(ParentAM.CreateStoreMgr),
|
||||
CreateConstraintMgr(ParentAM.CreateConstraintMgr),
|
||||
CheckerMgr(ParentAM.CheckerMgr),
|
||||
Idxer(ParentAM.Idxer),
|
||||
AScope(ScopeDecl),
|
||||
MaxNodes(ParentAM.MaxNodes),
|
||||
MaxVisit(ParentAM.MaxVisit),
|
||||
|
@ -80,21 +76,3 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
|
|||
{
|
||||
AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd();
|
||||
}
|
||||
|
||||
|
||||
AnalysisDeclContext *
|
||||
AnalysisManager::getAnalysisDeclContextInAnotherTU(const Decl *D) {
|
||||
idx::Entity Ent = idx::Entity::get(const_cast<Decl *>(D),
|
||||
Idxer->getProgram());
|
||||
FunctionDecl *FuncDef;
|
||||
idx::TranslationUnit *TU;
|
||||
llvm::tie(FuncDef, TU) = Idxer->getDefinitionFor(Ent);
|
||||
|
||||
if (FuncDef == 0)
|
||||
return 0;
|
||||
|
||||
// This AnalysisDeclContext wraps function definition in another translation unit.
|
||||
// But it is still owned by the AnalysisManager associated with the current
|
||||
// translation unit.
|
||||
return AnaCtxMgr.getContext(FuncDef, TU);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
|
||||
#include "clang/Index/TranslationUnit.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
|
|
|
@ -207,7 +207,6 @@ public:
|
|||
PP.getLangOpts(), PD,
|
||||
CreateStoreMgr, CreateConstraintMgr,
|
||||
checkerMgr.get(),
|
||||
/* Indexer */ 0,
|
||||
Opts.MaxNodes, Opts.MaxLoop,
|
||||
Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
|
||||
Opts.AnalysisPurgeOpt, Opts.EagerlyAssume,
|
||||
|
|
Loading…
Reference in New Issue