如何通过clang工具访问解析的C ++ 11属性

时间:2013-11-24 20:58:35

标签: c++11 attributes clang

This answer表示clang post 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?

1 个答案:

答案 0 :(得分:2)

如果Clang已经知道属性,那么这些属性只保留在AST中,而Clang是大多数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只打印&#34; annotate&#34;因为这是原始属性,为了获得有意义的值,我们将词法分析器中的实际标记作为字符串。

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