使用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
相关产品推荐
相关产品推荐

