【问题标题】:How to access parsed C++11 attributes via clang tooling如何通过 clang 工具访问解析的 C++11 属性
【发布时间】:2013-11-24 20:58:35
【问题描述】:

This answer 建议 clang 帖子 revision 165082 应该在 AST 中保留所有已解析的属性。

我最初认为这意味着所有属性都将被保留,但事实并非如此:

$ clang++ -v
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.0
Thread model: posix

$ cat att.cpp 
void f [[noreturn, foo]] () {}

$ clang++ att.cpp -Xclang -ast-dump -fsyntax-only -std=c++11
att.cpp:1:20: warning: unknown attribute 'foo' ignored [-Wattributes]
void f [[noreturn, foo]] () {}
                   ^
att.cpp:1:30: warning: function declared 'noreturn' should not return [-Winvalid-noreturn]
void f [[noreturn, foo]] () {}
                             ^
TranslationUnitDecl 0x102021cd0 <<invalid sloc>>
|-TypedefDecl 0x102022210 <<invalid sloc>> __int128_t '__int128'
|-TypedefDecl 0x102022270 <<invalid sloc>> __uint128_t 'unsigned __int128'
|-TypedefDecl 0x102022630 <<invalid sloc>> __builtin_va_list '__va_list_tag [1]'
`-FunctionDecl 0x1020226d0 <att.cpp:1:1, col:30> f 'void (void)'
  |-CompoundStmt 0x1020227b0 <col:29, col:30>
  `-CXX11NoReturnAttr 0x102022770 <col:10>
2 warnings generated.

在上面,请注意属性“foo”确实被忽略了,并且在 AST 中不存在,与属性“noreturn”相反。

属性“foo”会在某个时候保留在 AST 中,还是所有属性都必须是实际编译器的一部分(在 Attr.td 等中定义,如 Clang Internals Manual 中所述)保留在AST?

【问题讨论】:

  • 据我从 Michael Han 的补丁中可以看出,我希望它们会保留在 AST 中。请注意,没有出现在 AST 转储中并不意味着不存在于 AST 本身;可能只是转储不完整......

标签: c++11 attributes clang


【解决方案1】:

只有在 Clang 已知的情况下,属性才会保留在 AST 中,这是大多数 GCC 属性和 clang 定义自己的属性。但是,您可以(在某种程度上)使用来自this link 的提示添加您自己的属性。这使您能够定义任何新属性,然后按以下方式在 ast 中处理它: 例如,您从上面的链接中获取了代码行

__attribute__((annotate("async"))) uint c;

然后在您的 RecursiveASTVisitor 实例化中,您可以执行以下操作:

 bool MyRecursiveASTVisitor::VisitVarDecl(VarDecl* v)                                                                                                                                                    
  {                                                                                                                                                                                                       
          v->dump();                                                                                                                                                                                      
          if(v->hasAttrs()){                                                                                                                                                                              
                  clang::AttrVec vec = v->getAttrs();                                                                                                                                                     
                  printf("%s\n",vec[0]->getSpelling());                                                                                                                                                   
                  printf("%s\n", Lexer::getSourceText(                                                                                                                                                    
                                          CharSourceRange::getTokenRange(                                                                                                                                 
                                                  vec[0]->getRange()),                                                                                                                                    
                                          compiler.getSourceManager(),                                                                                                                                    
                                          langOpts).str().c_str());                                                                                                                                       
          }                                                                                                                                                                                               
          return true;                                                                                                                                                                                    
  }          

第一个 printf 只打印“annotate”,因为那是原始属性,为了获得感兴趣的值,我们从词法分析器中获取实际标记作为字符串。

由于我们没有创建新的属性,我们只获得了附加属性类型,但我们可以进一步挖掘并区分我们新创建的属性。不如新创建的属性优雅(尽管可能需要更改 clang 代码本身)但仍然有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    • 1970-01-01
    • 2019-12-01
    相关资源
    最近更新 更多