You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用CLANG的getUnqualifiedDesugaredType()获取底层类型不符的解决办法

问题:获取typedef的原始类型名而非内置类型别名

场景复现

头文件代码:

using UWORD = uint16_t;
UWORD var;

编写的Clang代码用于获取底层类型:

std::string qualTypeToUnderTypeStr(const clang::QualType& qualType, const clang::ASTContext& context)
{
    clang::Type const* underType = qualType.getTypePtr()->getUnqualifiedDesugaredType();
    std::string output;
    llvm::raw_string_ostream stream(output);
    clang::PrintingPolicy printingPolicy(context.getLangOpts());
    clang::QualType::print(underType, clang::Qualifiers(), stream, printingPolicy, llvm::Twine());

    return output;
}

实际返回unsigned short,但预期得到uint16_t。

解决办法

思路1:追踪typedef链,显式保留目标类型名

遍历类型的typedef解析链,遇到uint16_t这类标准固定宽度类型时直接返回其名称,否则继续解析到最终底层类型:

std::string qualTypeToUnderTypeStr(const clang::QualType& qualType, const clang::ASTContext& context)
{
    const clang::Type* currentType = qualType.getTypePtr()->getUnqualifiedDesugaredType();
    
    // 回溯typedef链,寻找目标标准类型
    while (const auto* typedefType = llvm::dyn_cast<clang::TypedefType>(currentType)) {
        const clang::TypedefNameDecl* decl = typedefType->getDecl();
        std::string typeName = decl->getNameAsString();
        
        // 匹配需要保留的标准固定宽度类型
        if (typeName == "uint16_t" || typeName == "int16_t" || 
            typeName == "uint32_t" || typeName == "int32_t" ||
            typeName == "uint64_t" || typeName == "int64_t") {
            return typeName;
        }
        
        currentType = decl->getUnderlyingType().getTypePtr()->getUnqualifiedDesugaredType();
    }
    
    // 非目标类型则按原逻辑打印底层类型
    std::string output;
    llvm::raw_string_ostream stream(output);
    clang::PrintingPolicy printingPolicy(context.getLangOpts());
    clang::QualType::print(currentType, clang::Qualifiers(), stream, printingPolicy, llvm::Twine());
    return output;
}

思路2:通过系统头文件判断,自动保留标准typedef名

利用Clang的AST信息判断typedef是否来自系统头文件(如<cstdint>),如果是则直接返回其名称,无需继续解析:

std::string qualTypeToUnderTypeStr(const clang::QualType& qualType, const clang::ASTContext& context)
{
    const clang::Type* currentType = qualType.getTypePtr()->getUnqualifiedDesugaredType();
    
    while (const auto* typedefType = llvm::dyn_cast<clang::TypedefType>(currentType)) {
        const clang::TypedefNameDecl* decl = typedefType->getDecl();
        // 检查typedef是否定义在系统头文件中
        if (decl->getLocation().isValid() && context.getSourceManager().isInSystemHeader(decl->getLocation())) {
            return decl->getNameAsString();
        }
        currentType = decl->getUnderlyingType().getTypePtr()->getUnqualifiedDesugaredType();
    }
    
    // 非系统头文件中的typedef则打印底层类型
    std::string output;
    llvm::raw_string_ostream stream(output);
    clang::PrintingPolicy printingPolicy(context.getLangOpts());
    clang::QualType::print(currentType, clang::Qualifiers(), stream, printingPolicy, llvm::Twine());
    return output;
}

说明

  • 思路1简单直接,适合只关注特定标准类型的场景。
  • 思路2扩展性更强,能自动识别所有系统头文件中的typedef(如size_t、intptr_t等)。

内容的提问来源于stack exchange,提问作者user24669219

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 06:54:57