为何此Clang ASTMatcher会引发错误的多态转换?
问题分析与解决方案:Clang ASTMatcher 静态断言错误
先拆解你遇到的这个静态断言错误,核心原因是你用的decl()匹配器范围太宽泛,和hasType()不兼容。
从错误信息里的TypeList<clang::Expr, clang::TypedefNameDecl, clang::ValueDecl>能看出来,hasType()这个匹配器只能作用在特定类型的节点上——包括表达式(Expr)、typedef声明(TypedefNameDecl)、值声明(ValueDecl,比如变量、函数这类带类型的声明),但你用decl()来匹配所有的Decl类型,其中很多Decl子类是不支持hasType检查的(比如NamespaceDecl、RecordDecl这些),所以编译器触发静态断言来阻止这种不合法的组合。
修复方案
把通用的decl()替换成更具体的、支持hasType()的Decl子类匹配器。从你的业务逻辑(匹配带有内置类型的非typedef声明)来看,valueDecl()是最合适的,它涵盖了变量、函数、枚举常量等需要类型的声明:
修改后的registerMatchers函数:
void Rule_1_2_1::registerMatchers(MatchFinder *Finder) { // 用valueDecl()替代decl(),缩小匹配范围到支持hasType的Decl子类 DeclarationMatcher Matcher = valueDecl(hasType(builtinType().bind("non-typedef"))).bind("non-typedef-decl"); Finder->addMatcher(Matcher, this); }
另外,你还可以优化run函数的类型获取,直接用ValueDecl而不是通用的Decl,类型更精准:
void Rule_1_2_1::run(const MatchFinder::MatchResult &Result) { if (const BuiltinType *type = Result.Nodes.getNodeAs<BuiltinType>("non-typedef")) { if (!type->isFloatingPoint() && !type->isInteger()) return; // 直接获取ValueDecl,避免不必要的类型转换 if (const ValueDecl *decl = Result.Nodes.getNodeAs<ValueDecl>("non-typedef-decl")) { DiagnosticsEngine &DE = Result.Context->getDiagnostics(); Context->report(this->CheckerName, this->ReportMsg, DE, decl->getLocStart(), DiagnosticIDs::Note); } } }
如果之后你需要匹配其他支持hasType()的Decl类型(比如TypedefNameDecl),可以用anyOf组合多个匹配器,比如:
DeclarationMatcher Matcher = anyOf( valueDecl(hasType(builtinType().bind("non-typedef"))), typedefNameDecl(hasType(builtinType().bind("non-typedef"))) ).bind("non-typedef-decl");
内容的提问来源于stack exchange,提问作者linux40
相关产品推荐
相关产品推荐

