首页 > 解决方案 > 确保每个字符串文字都包含在宏中

问题描述

我想用宏包装我项目中的每个字符串文字。我想确保我的项目中的每个字符串文字都用宏包装,并有一些外部工具帮助我提供未包装在宏中的字符串文字的位置。

有什么方法可以使用 Clang 插件来确保每个字符串文字都包含在宏中?

我要处理的案例:

  1. #define MY_ASSERT(Y) {if(!(Y)) throw Exception(#Y); }
    

    #Y 应该被警告为未包装的字符串文字。

  2. "a" "b" "c"
    

    它将要求整个事物都在一个宏中,如下所示:

    MY_STR("a" "b" "c")
    

我怎么能用 Clang 插件做到这一点,或者一般有其他方法吗?

标签: c++clangclang-plugin

解决方案


您可以使用 DMS Software Reengineering Toolkit 及其 C++ 前端来做到这一点。

DMS 可以根据 C++ 的显式语法定义读取源代码(在 GCC 和 MS 方言中处理 C++17),构建 AST,应用提供的重写规则来修改树,然后将 AST 漂亮地打印回源文本,保留注释、文本对齐、数字基数等。

为此,您只需要一个 DMS 规则(有关详细信息,请参阅DMS 重写规则):

rule wrap_string_in_macro(s:string_literal):primary_expression->primary_expression
 = "\s" -> " my_macro_name(\s) ";

非终结符string_literal涵盖了各种各样的 C++ 字符串(8 位、ISO、宽、原始、字符串序列……),因此您不必担心它们,这条规则会选择它们。但是您的宏可能需要担心这些。因此,您可以编写一组更大的规则,以便您可以专门化宏调用:

rule wrap_ISO_string_in_macro(s:ISO_STRING_LITERAL):primary_expression->primary_expression
 = "\s" -> " my_macro_name_for_ISO_string(\s) ";

rule wrap_ISO_string_in_macro(s:WIDE_STRING_LITERAL):primary_expression->primary_expression
 = "\s" -> " my_macro_name_for_wide_string(\s) ";

...

这些规则将获取单个字符串,但这留下了处理字符串序列的问题:

rule wrap_ISO_string_list_in_macro(seq: string_literal_list,s:ISO_STRING_LITERAL):primary_expression->primary_expression
 = " \string_literal_list \s" -> " my_macro_name_for_ISO_string_list(\s) ";

...

推荐阅读