ASTTypeTraits.cpp revision 280031
1259701Sdim//===--- ASTTypeTraits.cpp --------------------------------------*- C++ -*-===// 2259701Sdim// 3259701Sdim// The LLVM Compiler Infrastructure 4259701Sdim// 5259701Sdim// This file is distributed under the University of Illinois Open Source 6259701Sdim// License. See LICENSE.TXT for details. 7259701Sdim// 8259701Sdim//===----------------------------------------------------------------------===// 9259701Sdim// 10259701Sdim// Provides a dynamic type identifier and a dynamically typed node container 11259701Sdim// that can be used to store an AST base node at runtime in the same storage in 12259701Sdim// a type safe way. 13259701Sdim// 14259701Sdim//===----------------------------------------------------------------------===// 15259701Sdim 16259701Sdim#include "clang/AST/ASTTypeTraits.h" 17259701Sdim#include "clang/AST/ASTContext.h" 18259701Sdim#include "clang/AST/DeclCXX.h" 19259701Sdim 20259701Sdimnamespace clang { 21259701Sdimnamespace ast_type_traits { 22259701Sdim 23259701Sdimconst ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = { 24259701Sdim { NKI_None, "<None>" }, 25259701Sdim { NKI_None, "CXXCtorInitializer" }, 26259701Sdim { NKI_None, "TemplateArgument" }, 27259701Sdim { NKI_None, "NestedNameSpecifier" }, 28259701Sdim { NKI_None, "NestedNameSpecifierLoc" }, 29259701Sdim { NKI_None, "QualType" }, 30259701Sdim { NKI_None, "TypeLoc" }, 31259701Sdim { NKI_None, "Decl" }, 32259701Sdim#define DECL(DERIVED, BASE) { NKI_##BASE, #DERIVED "Decl" }, 33259701Sdim#include "clang/AST/DeclNodes.inc" 34259701Sdim { NKI_None, "Stmt" }, 35259701Sdim#define STMT(DERIVED, BASE) { NKI_##BASE, #DERIVED }, 36259701Sdim#include "clang/AST/StmtNodes.inc" 37259701Sdim { NKI_None, "Type" }, 38259701Sdim#define TYPE(DERIVED, BASE) { NKI_##BASE, #DERIVED "Type" }, 39259701Sdim#include "clang/AST/TypeNodes.def" 40259701Sdim}; 41259701Sdim 42276479Sdimbool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const { 43276479Sdim return isBaseOf(KindId, Other.KindId, Distance); 44259701Sdim} 45259701Sdim 46259701Sdimbool ASTNodeKind::isSame(ASTNodeKind Other) const { 47259701Sdim return KindId != NKI_None && KindId == Other.KindId; 48259701Sdim} 49259701Sdim 50276479Sdimbool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived, 51276479Sdim unsigned *Distance) { 52259701Sdim if (Base == NKI_None || Derived == NKI_None) return false; 53276479Sdim unsigned Dist = 0; 54276479Sdim while (Derived != Base && Derived != NKI_None) { 55259701Sdim Derived = AllKindInfo[Derived].ParentId; 56276479Sdim ++Dist; 57276479Sdim } 58276479Sdim if (Distance) 59276479Sdim *Distance = Dist; 60259701Sdim return Derived == Base; 61259701Sdim} 62259701Sdim 63259701SdimStringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; } 64259701Sdim 65280031SdimASTNodeKind ASTNodeKind::getMostDerivedType(ASTNodeKind Kind1, 66280031Sdim ASTNodeKind Kind2) { 67280031Sdim if (Kind1.isBaseOf(Kind2)) return Kind2; 68280031Sdim if (Kind2.isBaseOf(Kind1)) return Kind1; 69280031Sdim return ASTNodeKind(); 70280031Sdim} 71280031Sdim 72280031SdimASTNodeKind ASTNodeKind::getMostDerivedCommonAncestor(ASTNodeKind Kind1, 73280031Sdim ASTNodeKind Kind2) { 74280031Sdim NodeKindId Parent = Kind1.KindId; 75280031Sdim while (!isBaseOf(Parent, Kind2.KindId, nullptr) && Parent != NKI_None) { 76280031Sdim Parent = AllKindInfo[Parent].ParentId; 77280031Sdim } 78280031Sdim return ASTNodeKind(Parent); 79280031Sdim} 80280031Sdim 81280031SdimASTNodeKind ASTNodeKind::getFromNode(const Decl &D) { 82280031Sdim switch (D.getKind()) { 83280031Sdim#define DECL(DERIVED, BASE) \ 84280031Sdim case Decl::DERIVED: return ASTNodeKind(NKI_##DERIVED##Decl); 85280031Sdim#define ABSTRACT_DECL(D) 86280031Sdim#include "clang/AST/DeclNodes.inc" 87280031Sdim }; 88280031Sdim llvm_unreachable("invalid decl kind"); 89280031Sdim} 90280031Sdim 91280031SdimASTNodeKind ASTNodeKind::getFromNode(const Stmt &S) { 92280031Sdim switch (S.getStmtClass()) { 93280031Sdim case Stmt::NoStmtClass: return NKI_None; 94280031Sdim#define STMT(CLASS, PARENT) \ 95280031Sdim case Stmt::CLASS##Class: return ASTNodeKind(NKI_##CLASS); 96280031Sdim#define ABSTRACT_STMT(S) 97280031Sdim#include "clang/AST/StmtNodes.inc" 98280031Sdim } 99280031Sdim llvm_unreachable("invalid stmt kind"); 100280031Sdim} 101280031Sdim 102280031SdimASTNodeKind ASTNodeKind::getFromNode(const Type &T) { 103280031Sdim switch (T.getTypeClass()) { 104280031Sdim#define TYPE(Class, Base) \ 105280031Sdim case Type::Class: return ASTNodeKind(NKI_##Class##Type); 106280031Sdim#define ABSTRACT_TYPE(Class, Base) 107280031Sdim#include "clang/AST/TypeNodes.def" 108280031Sdim } 109280031Sdim llvm_unreachable("invalid type kind"); 110280031Sdim} 111280031Sdim 112259701Sdimvoid DynTypedNode::print(llvm::raw_ostream &OS, 113259701Sdim const PrintingPolicy &PP) const { 114259701Sdim if (const TemplateArgument *TA = get<TemplateArgument>()) 115259701Sdim TA->print(PP, OS); 116259701Sdim else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>()) 117259701Sdim NNS->print(OS, PP); 118259701Sdim else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) 119259701Sdim NNSL->getNestedNameSpecifier()->print(OS, PP); 120259701Sdim else if (const QualType *QT = get<QualType>()) 121259701Sdim QT->print(OS, PP); 122259701Sdim else if (const TypeLoc *TL = get<TypeLoc>()) 123259701Sdim TL->getType().print(OS, PP); 124259701Sdim else if (const Decl *D = get<Decl>()) 125259701Sdim D->print(OS, PP); 126259701Sdim else if (const Stmt *S = get<Stmt>()) 127276479Sdim S->printPretty(OS, nullptr, PP); 128259701Sdim else if (const Type *T = get<Type>()) 129259701Sdim QualType(T, 0).print(OS, PP); 130259701Sdim else 131259701Sdim OS << "Unable to print values of type " << NodeKind.asStringRef() << "\n"; 132259701Sdim} 133259701Sdim 134259701Sdimvoid DynTypedNode::dump(llvm::raw_ostream &OS, SourceManager &SM) const { 135259701Sdim if (const Decl *D = get<Decl>()) 136259701Sdim D->dump(OS); 137259701Sdim else if (const Stmt *S = get<Stmt>()) 138259701Sdim S->dump(OS, SM); 139259701Sdim else 140259701Sdim OS << "Unable to dump values of type " << NodeKind.asStringRef() << "\n"; 141259701Sdim} 142259701Sdim 143259701SdimSourceRange DynTypedNode::getSourceRange() const { 144259701Sdim if (const CXXCtorInitializer *CCI = get<CXXCtorInitializer>()) 145259701Sdim return CCI->getSourceRange(); 146259701Sdim if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>()) 147259701Sdim return NNSL->getSourceRange(); 148259701Sdim if (const TypeLoc *TL = get<TypeLoc>()) 149259701Sdim return TL->getSourceRange(); 150259701Sdim if (const Decl *D = get<Decl>()) 151259701Sdim return D->getSourceRange(); 152259701Sdim if (const Stmt *S = get<Stmt>()) 153259701Sdim return S->getSourceRange(); 154259701Sdim return SourceRange(); 155259701Sdim} 156259701Sdim 157259701Sdim} // end namespace ast_type_traits 158259701Sdim} // end namespace clang 159