From: Argyrios Kyrtzidis Date: Sun, 12 Oct 2008 16:14:48 +0000 (+0000) Subject: Implement more efficient Decl <-> DeclContext conversions. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=42220c5432c141d47cc8ce786e472b49dc907378;p=clang Implement more efficient Decl <-> DeclContext conversions. When the static type on the Decl side is a subclass of DeclContext the compiler will use a "inlinable" static_cast, instead of always using an out-of-line function call. Note, though, that the isa<> check still uses an out-of-line function call. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57415 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 575daa5d90..a6593778ab 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -38,6 +38,12 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == TranslationUnit; } static bool classof(const TranslationUnitDecl *D) { return true; } + static DeclContext *castToDeclContext(const TranslationUnitDecl *D) { + return static_cast(const_cast(D)); + } + static TranslationUnitDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast(const_cast(DC)); + } protected: /// EmitImpl - Serialize this TranslationUnitDecl. Called by Decl::Emit. @@ -183,6 +189,12 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == Namespace; } static bool classof(const NamespaceDecl *D) { return true; } + static DeclContext *castToDeclContext(const NamespaceDecl *D) { + return static_cast(const_cast(D)); + } + static NamespaceDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast(const_cast(DC)); + } protected: /// EmitImpl - Serialize this NamespaceDecl. Called by Decl::Emit. @@ -547,6 +559,12 @@ public: return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast; } static bool classof(const FunctionDecl *D) { return true; } + static DeclContext *castToDeclContext(const FunctionDecl *D) { + return static_cast(const_cast(D)); + } + static FunctionDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast(const_cast(DC)); + } protected: /// EmitImpl - Serialize this FunctionDecl. Called by Decl::Emit. @@ -817,6 +835,12 @@ public: static bool classof(const Decl *D) { return D->getKind() == Enum; } static bool classof(const EnumDecl *D) { return true; } + static DeclContext *castToDeclContext(const EnumDecl *D) { + return static_cast(const_cast(D)); + } + static EnumDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast(const_cast(DC)); + } protected: /// EmitImpl - Serialize this EnumDecl. Called by Decl::Emit. @@ -1012,7 +1036,7 @@ public: Args.clear(); Args.insert(Args.begin(), args, args+numargs); } - DeclContext *getParentContext() { return ParentContext; } + DeclContext *getParentContext() const { return ParentContext; } /// arg_iterator - Iterate over the ParmVarDecl's for this block. typedef llvm::SmallVector::const_iterator param_iterator; @@ -1023,6 +1047,12 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == Block; } static bool classof(const BlockDecl *D) { return true; } + static DeclContext *castToDeclContext(const BlockDecl *D) { + return static_cast(const_cast(D)); + } + static BlockDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast(const_cast(DC)); + } protected: /// EmitImpl - Serialize this BlockDecl. Called by Decl::Emit. diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index b165991c17..d8b5b378f3 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -19,6 +19,7 @@ #include "clang/Basic/SourceLocation.h" namespace clang { +class DeclContext; class TranslationUnitDecl; class NamespaceDecl; class ScopedDecl; @@ -213,6 +214,8 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *) { return true; } + static DeclContext *castToDeclContext(const Decl *); + static Decl *castFromDeclContext(const DeclContext *); /// Emit - Serialize this Decl to Bitcode. void Emit(llvm::Serializer& S) const; @@ -313,12 +316,6 @@ public: ScopedDecl *getDeclChain() const { return DeclChain; } void setDeclChain(ScopedDecl *D) { DeclChain = D; } - /// ToDecl and FromDecl make Decl <-> DeclContext castings. - /// They are intended to be used by the simplify_type and cast_convert_val - /// templates. - static Decl *ToDecl (const DeclContext *D); - static DeclContext *FromDecl (const Decl *D); - static bool classof(const Decl *D) { switch (D->getKind()) { case Decl::TranslationUnit: @@ -362,49 +359,60 @@ template<> struct DeclContext::KindTrait { } // end clang. namespace llvm { -/// Implement simplify_type for DeclContext, so that we can dyn_cast from -/// DeclContext to a specific Decl class. - template<> struct simplify_type { - typedef ::clang::Decl* SimpleType; - static SimpleType getSimplifiedValue(const ::clang::DeclContext *Val) { - return ::clang::DeclContext::ToDecl(Val); - } -}; -template<> struct simplify_type< ::clang::DeclContext*> - : public simplify_type {}; -template<> struct simplify_type { - typedef ::clang::Decl SimpleType; - static SimpleType &getSimplifiedValue(const ::clang::DeclContext &Val) { - return *::clang::DeclContext::ToDecl(&Val); +/// Implement a isa_impl_wrap specialization to check whether a DeclContext is +/// a specific Decl. +template +struct isa_impl_wrap { + static bool doit(const ::clang::DeclContext &Val) { + return ToTy::classof(::clang::Decl::castFromDeclContext(&Val)); } }; -template<> struct simplify_type< ::clang::DeclContext> - : public simplify_type {}; +template +struct isa_impl_wrap + : public isa_impl_wrap {}; -/// Implement cast_convert_val for DeclContext, so that we can dyn_cast from -/// a Decl class to DeclContext. +/// Implement cast_convert_val for Decl -> DeclContext conversions. template -struct cast_convert_val< ::clang::DeclContext,const FromTy,const FromTy> { +struct cast_convert_val< ::clang::DeclContext, FromTy, FromTy> { static ::clang::DeclContext &doit(const FromTy &Val) { - return *::clang::DeclContext::FromDecl(&Val); + return *FromTy::castToDeclContext(&Val); } }; -template -struct cast_convert_val< ::clang::DeclContext,FromTy,FromTy> - : public cast_convert_val< ::clang::DeclContext,const FromTy,const FromTy> - {}; template -struct cast_convert_val< ::clang::DeclContext,const FromTy*,const FromTy*> { +struct cast_convert_val< ::clang::DeclContext, FromTy*, FromTy*> { static ::clang::DeclContext *doit(const FromTy *Val) { - return ::clang::DeclContext::FromDecl(Val); + return FromTy::castToDeclContext(Val); } }; -template -struct cast_convert_val< ::clang::DeclContext,FromTy*,FromTy*> - : public cast_convert_val< ::clang::DeclContext,const FromTy*,const FromTy*> - {}; + +/// Implement cast_convert_val for DeclContext -> Decl conversions. +template +struct cast_convert_val { + static ToTy &doit(const ::clang::DeclContext &Val) { + return *reinterpret_cast(ToTy::castFromDeclContext(&Val)); + } +}; +template +struct cast_convert_val + : public cast_convert_val {}; + +template +struct cast_convert_val { + static ToTy *doit(const ::clang::DeclContext *Val) { + return reinterpret_cast(ToTy::castFromDeclContext(Val)); + } +}; +template +struct cast_convert_val + : public cast_convert_val {}; } // end namespace llvm diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index dc72267554..e8beb62d7e 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -69,6 +69,12 @@ public: return D->getKind() >= CXXRecordFirst && D->getKind() <= CXXRecordLast; } static bool classof(const CXXRecordDecl *D) { return true; } + static DeclContext *castToDeclContext(const CXXRecordDecl *D) { + return static_cast(const_cast(D)); + } + static CXXRecordDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast(const_cast(DC)); + } protected: /// EmitImpl - Serialize this CXXRecordDecl. Called by Decl::Emit. diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 34e60e62f3..e8c383d73e 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -242,6 +242,12 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == ObjCMethod; } static bool classof(const ObjCMethodDecl *D) { return true; } + static DeclContext *castToDeclContext(const ObjCMethodDecl *D) { + return static_cast(const_cast(D)); + } + static ObjCMethodDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast(const_cast(DC)); + } }; /// ObjCInterfaceDecl - Represents an ObjC class declaration. For example: @@ -467,6 +473,12 @@ public: static bool classof(const Decl *D) { return D->getKind() == ObjCInterface; } static bool classof(const ObjCInterfaceDecl *D) { return true; } + static DeclContext *castToDeclContext(const ObjCInterfaceDecl *D) { + return static_cast(const_cast(D)); + } + static ObjCInterfaceDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast(const_cast(DC)); + } }; /// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 198bc4a19e..1ea545ba5d 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -332,23 +332,23 @@ void Decl::Destroy(ASTContext& C) { C.getAllocator().Deallocate((void *)this); } +Decl *Decl::castFromDeclContext (const DeclContext *D) { + return DeclContext::CastTo(D); +} + +DeclContext *Decl::castToDeclContext(const Decl *D) { + return DeclContext::CastTo(D); +} + //===----------------------------------------------------------------------===// // DeclContext Implementation //===----------------------------------------------------------------------===// DeclContext *DeclContext::getParent() const { - if (ScopedDecl *SD = dyn_cast(this)) + if (const ScopedDecl *SD = dyn_cast(this)) return SD->getDeclContext(); - else if (BlockDecl *BD = dyn_cast(this)) + else if (const BlockDecl *BD = dyn_cast(this)) return BD->getParentContext(); else return NULL; } - -Decl *DeclContext::ToDecl (const DeclContext *D) { - return CastTo(D); -} - -DeclContext *DeclContext::FromDecl (const Decl *D) { - return CastTo(D); -}