1208600Srdivacky//===--- TypeVisitor.h - Visitor for Type subclasses ------------*- C++ -*-===//
2194613Sed//
3194613Sed//                     The LLVM Compiler Infrastructure
4194613Sed//
5194613Sed// This file is distributed under the University of Illinois Open Source
6194613Sed// License. See LICENSE.TXT for details.
7194613Sed//
8194613Sed//===----------------------------------------------------------------------===//
9194613Sed//
10194613Sed//  This file defines the TypeVisitor interface.
11194613Sed//
12194613Sed//===----------------------------------------------------------------------===//
13194613Sed
14194613Sed#ifndef LLVM_CLANG_AST_TYPEVISITOR_H
15194613Sed#define LLVM_CLANG_AST_TYPEVISITOR_H
16194613Sed
17194613Sed#include "clang/AST/Type.h"
18194613Sed
19194613Sednamespace clang {
20198092Srdivacky
21194613Sed#define DISPATCH(CLASS) \
22218893Sdim  return static_cast<ImplClass*>(this)-> \
23218893Sdim           Visit##CLASS(static_cast<const CLASS*>(T))
24198092Srdivacky
25263508Sdim/// \brief An operation on a type.
26263508Sdim///
27263508Sdim/// \tparam ImplClass Class implementing the operation. Must be inherited from
28263508Sdim///         TypeVisitor.
29263508Sdim/// \tparam RetTy %Type of result produced by the operation.
30263508Sdim///
31263508Sdim/// The class implements polymorphic operation on an object of type derived
32263508Sdim/// from Type. The operation is performed by calling method Visit. It then
33263508Sdim/// dispatches the call to function \c VisitFooType, if actual argument type
34263508Sdim/// is \c FooType.
35263508Sdim///
36263508Sdim/// The class implements static polymorphism using Curiously Recurring
37263508Sdim/// Template Pattern. It is designed to be a base class for some concrete
38263508Sdim/// class:
39263508Sdim///
40263508Sdim/// \code
41263508Sdim///     class SomeVisitor : public TypeVisitor<SomeVisitor,sometype> { ... };
42263508Sdim///     ...
43263508Sdim///     Type *atype = ...
44263508Sdim///     ...
45263508Sdim///     SomeVisitor avisitor;
46263508Sdim///     sometype result = avisitor.Visit(atype);
47263508Sdim/// \endcode
48263508Sdim///
49263508Sdim/// Actual treatment is made by methods of the derived class, TypeVisitor only
50263508Sdim/// dispatches call to the appropriate method. If the implementation class
51263508Sdim/// \c ImplClass provides specific action for some type, say
52263508Sdim/// \c ConstantArrayType, it should define method
53263508Sdim/// <tt>VisitConstantArrayType(const ConstantArrayType*)</tt>. Otherwise
54263508Sdim/// \c TypeVisitor dispatches call to the method that handles parent type. In
55263508Sdim/// this example handlers are tried in the sequence:
56263508Sdim///
57263508Sdim/// \li <tt>ImplClass::VisitConstantArrayType(const ConstantArrayType*)</tt>
58263508Sdim/// \li <tt>ImplClass::VisitArrayType(const ArrayType*)</tt>
59263508Sdim/// \li <tt>ImplClass::VisitType(const Type*)</tt>
60263508Sdim/// \li <tt>TypeVisitor::VisitType(const Type*)</tt>
61263508Sdim///
62263508Sdim/// The first function of this sequence that is defined will handle object of
63263508Sdim/// type \c ConstantArrayType.
64194613Sedtemplate<typename ImplClass, typename RetTy=void>
65194613Sedclass TypeVisitor {
66194613Sedpublic:
67263508Sdim
68263508Sdim  /// \brief Performs the operation associated with this visitor object.
69218893Sdim  RetTy Visit(const Type *T) {
70208600Srdivacky    // Top switch stmt: dispatch to VisitFooType for each FooType.
71194613Sed    switch (T->getTypeClass()) {
72198092Srdivacky#define ABSTRACT_TYPE(CLASS, PARENT)
73194613Sed#define TYPE(CLASS, PARENT) case Type::CLASS: DISPATCH(CLASS##Type);
74194613Sed#include "clang/AST/TypeNodes.def"
75194613Sed    }
76234353Sdim    llvm_unreachable("Unknown type class!");
77194613Sed  }
78198092Srdivacky
79194613Sed  // If the implementation chooses not to implement a certain visit method, fall
80194613Sed  // back on superclass.
81218893Sdim#define TYPE(CLASS, PARENT) RetTy Visit##CLASS##Type(const CLASS##Type *T) { \
82198092Srdivacky  DISPATCH(PARENT);                                                          \
83198092Srdivacky}
84194613Sed#include "clang/AST/TypeNodes.def"
85194613Sed
86263508Sdim  /// \brief Method called if \c ImpClass doesn't provide specific handler
87263508Sdim  /// for some type class.
88218893Sdim  RetTy VisitType(const Type*) { return RetTy(); }
89194613Sed};
90194613Sed
91194613Sed#undef DISPATCH
92194613Sed
93194613Sed}  // end namespace clang
94194613Sed
95194613Sed#endif
96