//===--- ASTMatchersInternal.h - Structural query framework -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Implements the base layer of the matcher framework.
//
// Matchers are methods that return a Matcher<T> which provides a method
// Matches(...) which is a predicate on an AST node. The Matches method's
// parameters define the context of the match, which allows matchers to recurse
// or store the current node as bound to a specific string, so that it can be
// retrieved later.
//
// In general, matchers have two parts:
// 1. A function Matcher<T> MatcherName(<arguments>) which returns a Matcher<T>
// based on the arguments and optionally on template type deduction based
// on the arguments. Matcher<T>s form an implicit reverse hierarchy
// to clang's AST class hierarchy, meaning that you can use a Matcher<Base>
// everywhere a Matcher<Derived> is required.
// 2. An implementation of a class derived from MatcherInterface<T>.
//
// The matcher functions are defined in ASTMatchers.h. To make it possible
// to implement both the matcher function and the implementation of the matcher
// interface in one place, ASTMatcherMacros.h defines macros that allow
// implementing a matcher in a single place.
//
// This file contains the base classes needed to construct the actual matchers.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Decl.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/VariadicFunction.h"
#include "llvm/Support/type_traits.h"
#include <map>
#include <string>
#include <vector>
namespace clang {
namespace ast_matchers {
/// FIXME: Move into the llvm support library.
template <bool> struct CompileAssert {};
#define TOOLING_COMPILE_ASSERT(Expr, Msg) \
typedef CompileAssert<(bool(Expr))> Msg[bool(Expr) ? 1 : -1]
class BoundNodes;
namespace internal {
class BoundNodesTreeBuilder;
/// \brief Internal version of BoundNodes. Holds all the bound nodes.
class BoundNodesMap {
public:
/// \brief Adds \c Node to the map with key \c ID.
///
/// The node's base type should be in NodeBaseType or it will be unaccessible.
template <typename T>
void addNode(StringRef ID, const T* Node) {
NodeMap[ID] = ast_type_traits::DynTypedNode::create(*Node);
}
void addNode(StringRef ID, ast_type_traits::DynTypedNode Node) {
NodeMap[ID] = Node;
}
/// \brief Returns the AST node bound to \c ID.
///
/// Returns NULL if there was no node bound to \c ID or if there is a node but
/// it cannot be converted to the specified type.
template <typename T>
const T *getNodeAs(StringRef ID) const {
IDToNodeMap::const_iterator It = NodeMap.find(ID);
if (It == NodeMap.end()) {
return NULL;
}
return It->second.get<T>();
}
/// \brief Copies all ID/Node pairs to BoundNodesTreeBuilder \c Builder.
void copyTo(BoundNodesTreeBuilder *Builder) const;
/// \brief Copies all ID/Node pairs to BoundNodesMap \c Other.
void copyTo(BoundNodesMap *Other) const;
private:
/// \brief A map from IDs to the bound nodes.
typedef std::map<std::string, ast_type_traits::DynTypedNode> IDToNodeMap;
IDToNodeMap NodeMap;
};
/// \brief A tree of bound nodes in match results.
///
/// If a match can contain multiple matches on the same node with different
/// matching subexpressions, BoundNodesTree contains a branch for each of
/// those matching subexpressions.
///
/// BoundNodesTree's are created during the matching process; when a match
/// is found, we iterate over the tree and create a BoundNodes object containing
/// the union of all bound nodes on the path from the root to a each leaf.
class BoundNodesTree {
public:
/// \brief A visitor interface to visit all BoundNodes results for a
/// BoundNodesTree.
class Visitor {
public:
virtual ~Visitor() {}
/// \brief Called multiple times during a single call to VisitMatches(...).
///
/// 'BoundNodesView' contains the bound nodes for a single match.
virtual void visitMatch(const BoundNodes& BoundNodesView) = 0;
};
BoundNodesTree();
/// \brief Create a BoundNodesTree from pre-filled maps of bindings.