From a117002d93b1f0e9488a68d5d3b540ca795bc9e5 Mon Sep 17 00:00:00 2001 From: Samuel Benzaquen Date: Mon, 6 Oct 2014 13:14:30 +0000 Subject: Fix bug in DynTypedMatcher::constructVariadic() that would cause false negatives. Summary: DynTypedMatcher::constructVariadic() where the restrict kind of the different matchers are not related causes the matcher to have a "None" restrict kind. This causes false negatives for anyOf and eachOf. Change the logic to get a common ancestor if there is one. Also added regression tests that fail without the fix. Reviewers: klimek Subscribers: klimek, cfe-commits Differential Revision: http://reviews.llvm.org/D5580 llvm-svn: 219118 --- clang/lib/AST/ASTTypeTraits.cpp | 16 +++++++++++++++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 28 ++++----------------------- 2 files changed, 20 insertions(+), 24 deletions(-) (limited to 'clang/lib') diff --git a/clang/lib/AST/ASTTypeTraits.cpp b/clang/lib/AST/ASTTypeTraits.cpp index 56915b96406..ec0671ceb1b 100644 --- a/clang/lib/AST/ASTTypeTraits.cpp +++ b/clang/lib/AST/ASTTypeTraits.cpp @@ -62,6 +62,22 @@ bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived, StringRef ASTNodeKind::asStringRef() const { return AllKindInfo[KindId].Name; } +ASTNodeKind ASTNodeKind::getMostDerivedType(ASTNodeKind Kind1, + ASTNodeKind Kind2) { + if (Kind1.isBaseOf(Kind2)) return Kind2; + if (Kind2.isBaseOf(Kind1)) return Kind1; + return ASTNodeKind(); +} + +ASTNodeKind ASTNodeKind::getMostDerivedCommonAncestor(ASTNodeKind Kind1, + ASTNodeKind Kind2) { + NodeKindId Parent = Kind1.KindId; + while (!isBaseOf(Parent, Kind2.KindId, nullptr) && Parent != NKI_None) { + Parent = AllKindInfo[Parent].ParentId; + } + return ASTNodeKind(Parent); +} + ASTNodeKind ASTNodeKind::getFromNode(const Decl &D) { switch (D.getKind()) { #define DECL(DERIVED, BASE) \ diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index 4cff381f3f4..ec60f0d9498 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -64,28 +64,6 @@ class IdDynMatcher : public DynMatcherInterface { const IntrusiveRefCntPtr InnerMatcher; }; -/// \brief Return the most derived type between \p Kind1 and \p Kind2. -/// -/// Return the null type if they are not related. -ast_type_traits::ASTNodeKind getMostDerivedType( - const ast_type_traits::ASTNodeKind Kind1, - const ast_type_traits::ASTNodeKind Kind2) { - if (Kind1.isBaseOf(Kind2)) return Kind2; - if (Kind2.isBaseOf(Kind1)) return Kind1; - return ast_type_traits::ASTNodeKind(); -} - -/// \brief Return the least derived type between \p Kind1 and \p Kind2. -/// -/// Return the null type if they are not related. -static ast_type_traits::ASTNodeKind getLeastDerivedType( - const ast_type_traits::ASTNodeKind Kind1, - const ast_type_traits::ASTNodeKind Kind2) { - if (Kind1.isBaseOf(Kind2)) return Kind1; - if (Kind2.isBaseOf(Kind1)) return Kind2; - return ast_type_traits::ASTNodeKind(); -} - } // namespace DynTypedMatcher DynTypedMatcher::constructVariadic( @@ -98,7 +76,8 @@ DynTypedMatcher DynTypedMatcher::constructVariadic( assert(Result.SupportedKind.isSame(M.SupportedKind) && "SupportedKind must match!"); Result.RestrictKind = - getLeastDerivedType(Result.RestrictKind, M.RestrictKind); + ast_type_traits::ASTNodeKind::getMostDerivedCommonAncestor( + Result.RestrictKind, M.RestrictKind); } Result.Implementation = new VariadicMatcher(Func, std::move(InnerMatchers)); return Result; @@ -108,7 +87,8 @@ DynTypedMatcher DynTypedMatcher::dynCastTo( const ast_type_traits::ASTNodeKind Kind) const { auto Copy = *this; Copy.SupportedKind = Kind; - Copy.RestrictKind = getMostDerivedType(Kind, RestrictKind); + Copy.RestrictKind = + ast_type_traits::ASTNodeKind::getMostDerivedType(Kind, RestrictKind); return Copy; } -- cgit v1.2.3