Index: include/clang/AST/ASTTypeTraits.h =================================================================== --- include/clang/AST/ASTTypeTraits.h +++ include/clang/AST/ASTTypeTraits.h @@ -64,9 +64,12 @@ bool isSame(ASTNodeKind Other) const; /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other. + bool isBaseOf(ASTNodeKind Other) const; + + /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other. /// \param Distance If non-null, used to return the distance between \c this /// and \c Other in the class hierarchy. - bool isBaseOf(ASTNodeKind Other, unsigned *Distance = nullptr) const; + bool isBaseOf(ASTNodeKind Other, unsigned &Distance) const; /// \brief String representation of the kind. StringRef asStringRef() const; @@ -100,15 +103,11 @@ NKI_NumberOfKinds }; + struct NodeParentMap; + /// \brief Use getFromNodeKind() to construct the kind. ASTNodeKind(NodeKindId KindId) : KindId(KindId) {} - /// \brief Returns \c true if \c Base is a base kind of (or same as) \c - /// Derived. - /// \param Distance If non-null, used to return the distance between \c Base - /// and \c Derived in the class hierarchy. - static bool isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance); - /// \brief Helper meta-function to convert a kind T to its enum value. /// /// This struct is specialized below for all known kinds. Index: lib/AST/ASTTypeTraits.cpp =================================================================== --- lib/AST/ASTTypeTraits.cpp +++ lib/AST/ASTTypeTraits.cpp @@ -39,27 +39,38 @@ #include "clang/AST/TypeNodes.def" }; -bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const { - return isBaseOf(KindId, Other.KindId, Distance); +struct ASTNodeKind::NodeParentMap { + NodeParentMap() { + for (unsigned Node = NKI_None; Node < NKI_NumberOfKinds; ++Node) { + for (unsigned Parent = NKI_None; Parent < NKI_NumberOfKinds; ++Parent) + ParentDistances[Node][Parent] = NotParent; + unsigned Distance = 0; + for (unsigned Parent = Node; Parent != NKI_None; + Parent = ASTNodeKind::AllKindInfo[Parent].ParentId) { + ParentDistances[Node][Parent] = Distance; + ++Distance; + } + } + } + + static const unsigned char NotParent = 255; + unsigned char ParentDistances[NKI_NumberOfKinds][NKI_NumberOfKinds]; +}; + +bool ASTNodeKind::isBaseOf(ASTNodeKind Other) const { + static const NodeParentMap *Map = new NodeParentMap; + return Map->ParentDistances[Other.KindId][KindId] != NodeParentMap::NotParent; +} +bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned &Distance) const { + static const NodeParentMap *Map = new NodeParentMap; + Distance = Map->ParentDistances[Other.KindId][KindId]; + return Distance != NodeParentMap::NotParent; } bool ASTNodeKind::isSame(ASTNodeKind Other) const { return KindId != NKI_None && KindId == Other.KindId; } -bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived, - unsigned *Distance) { - if (Base == NKI_None || Derived == NKI_None) return false; - unsigned Dist = 0; - while (Derived != Base && Derived != NKI_None) { - Derived = AllKindInfo[Derived].ParentId; - ++Dist; - } - if (Distance) - *Distance = Dist; - return Derived == Base; -} - StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; } ASTNodeKind ASTNodeKind::getFromNode(const Decl &D) { Index: lib/ASTMatchers/Dynamic/VariantValue.cpp =================================================================== --- lib/ASTMatchers/Dynamic/VariantValue.cpp +++ lib/ASTMatchers/Dynamic/VariantValue.cpp @@ -41,7 +41,7 @@ return true; } unsigned Distance; - if (!MatcherKind.isBaseOf(To.MatcherKind, &Distance)) + if (!MatcherKind.isBaseOf(To.MatcherKind, Distance)) return false; if (Specificity) Index: unittests/AST/ASTTypeTraitsTest.cpp =================================================================== --- unittests/AST/ASTTypeTraitsTest.cpp +++ unittests/AST/ASTTypeTraitsTest.cpp @@ -36,14 +36,14 @@ TEST(ASTNodeKind, BaseDistances) { unsigned Distance = 1; - EXPECT_TRUE(DNT().isBaseOf(DNT(), &Distance)); + EXPECT_TRUE(DNT().isBaseOf(DNT(), Distance)); EXPECT_EQ(0u, Distance); - EXPECT_TRUE(DNT().isBaseOf(DNT(), &Distance)); + EXPECT_TRUE(DNT().isBaseOf(DNT(), Distance)); EXPECT_EQ(1u, Distance); Distance = 3; - EXPECT_TRUE(DNT().isBaseOf(DNT(), &Distance)); + EXPECT_TRUE(DNT().isBaseOf(DNT(), Distance)); EXPECT_EQ(2u, Distance); }