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