<div dir="ltr"><span style="color:rgb(0,0,0);font-size:12.8px">Hi,</span><div style="color:rgb(0,0,0);font-size:12.8px"><br></div><div style="color:rgb(0,0,0);font-size:12.8px">I am using libclang API to implement semantic syntax highlighting. However, there are a few rough edges which should be polished in order to get satisfying results. Resolving dependent names ('CXType_DEPENDENT' AST nodes)<span style="font-family:roboto,sans-serif;font-size:14px;white-space:nowrap"> </span>is one of them that I've came across. libclang in this case does not provide the same depth of information about the node(s) as it does for a non-dependent-name node(s).  </div><div style="color:rgb(0,0,0);font-size:12.8px"><br></div><div style="color:rgb(0,0,0);font-size:12.8px">In particular, following example depicts what I am trying to explain (please mind the comments in the code):<br></div><div style="color:rgb(0,0,0);font-size:12.8px"><br></div><div style="color:rgb(0,0,0);font-size:12.8px">// demo.cpp</div><div style="color:rgb(0,0,0);font-size:12.8px"><div>#include <vector></div><div><br></div><div>template <typename T></div><div>bool foo() {</div><div><span class="gmail-m_-8467628047013451978gmail-Apple-tab-span" style="white-space:pre-wrap">  </span>std::vector<T> vec;</div><div>        vec._M_impl;          // 'vec' is identified as part of 'CXXDependentScopeMemberExpr' but access to member field '_M_impl' is not and it's completely missing from the AST</div><div><span class="gmail-m_-8467628047013451978gmail-Apple-tab-span" style="white-space:pre-wrap">       </span>return vec.empty(); // 'vec' is identified as part of 'CXXDependentScopeMemberExpr' but call expression 'empty' is not and it's completely missing from the AST</div><div>}</div><div><br></div><div>bool bar() {</div><div><span class="gmail-m_-8467628047013451978gmail-Apple-tab-span" style="white-space:pre-wrap">       </span>std::vector<int> vec;</div><div><span class="gmail-m_-8467628047013451978gmail-Apple-tab-span" style="white-space:pre-wrap">   vec._M_impl;          // both 'vec' & access to member field '_M_impl' are identified as expected</span></div><div>        return vec.empty(); // both 'vec' & 'empty' are identified as expected</div><div>}</div></div><div style="color:rgb(0,0,0);font-size:12.8px"><br></div><div style="color:rgb(0,0,0);font-size:12.8px">// output from clang -Xclang -ast-dump demo.cpp</div><div style="color:rgb(0,0,0);font-size:12.8px">|-FunctionTemplateDecl 0x564cf4e63c48 <demo.cpp:3:1, line:8:1> line:4:6 foo<br></div><div style="color:rgb(0,0,0);font-size:12.8px"><div>| |-TemplateTypeParmDecl 0x564cf4e63af8 <line:3:11, col:20> col:20 referenced typename T</div><div>| `-FunctionDecl 0x564cf4e63ba0 <line:4:1, line:8:1> line:4:6 foo '_Bool (void)'</div><div>|   `-CompoundStmt 0x564cf4e64190 <col:12, line:8:1></div><div>|     |-DeclStmt 0x564cf4e64038 <line:5:2, col:20></div><div>|     | `-VarDecl 0x564cf4e63fd8 <col:2, col:17> col:17 referenced vec 'std::vector<T>':'vector<T>'</div><div>|     |-CXXDependentScopeMemberExpr 0x564cf4e64078 <line:6:2, col:6> '<dependent type>' lvalue</div><div>|     | `-DeclRefExpr 0x564cf4e64050 <col:2> 'std::vector<T>':'vector<T>' lvalue Var 0x564cf4e63fd8 'vec' 'std::vector<T>':'vector<T>'</div><div>|     `-ReturnStmt 0x564cf4e64178 <line:7:2, col:19></div><div>|       `-CallExpr 0x564cf4e64150 <col:9, col:19> '<dependent type>'</div><div>|         `-CXXDependentScopeMemberExpr 0x564cf4e640f8 <col:9, col:13> '<dependent type>' lvalue</div><div>|           `-DeclRefExpr 0x564cf4e640d0 <col:9> 'std::vector<T>':'vector<T>' lvalue Var 0x564cf4e63fd8 'vec' 'std::vector<T>':'vector<T>'</div><div>`-FunctionDecl 0x564cf4e641e0 <line:10:1, line:14:1> line:10:6 bar '_Bool (void)'</div><div>  `-CompoundStmt 0x564cf4e76dd8 <col:12, line:14:1></div><div>    |-DeclStmt 0x564cf4e76898 <line:11:2, col:22></div><div>    | `-VarDecl 0x564cf4e646c8 <col:2, col:19> col:19 used vec 'std::vector<int>':'class std::vector<int, class std::allocator<int> >' callinit</div><div>    |   `-CXXConstructExpr 0x564cf4e76868 <col:19> 'std::vector<int>':'class std::vector<int, class std::allocator<int> >' 'void (void)'</div><div>    |-MemberExpr 0x564cf4e768f8 <line:12:2, col:6> 'struct std::_Vector_base<int, class std::allocator<int> >::_Vector_impl' lvalue ._M_impl 0x564cf4e6bb78</div><div>    | `-ImplicitCastExpr 0x564cf4e768d8 <col:2> 'struct std::_Vector_base<int, class std::allocator<int> >' lvalue <UncheckedDerivedToBase (_Vector_base)></div><div>    |   `-DeclRefExpr 0x564cf4e768b0 <col:2> 'std::vector<int>':'class std::vector<int, class std::allocator<int> >' lvalue Var 0x564cf4e646c8 'vec' 'std::vector<int>':'class std::vector<int, class std::allocator<int> >'</div><div>    `-ReturnStmt 0x564cf4e76dc0 <line:13:2, col:19></div><div>      `-CXXMemberCallExpr 0x564cf4e76d50 <col:9, col:19> '_Bool'</div><div>        `-MemberExpr 0x564cf4e76d18 <col:9, col:13> '<bound member function type>' .empty 0x564cf4e6fc20</div><div>          `-ImplicitCastExpr 0x564cf4e76da8 <col:9> 'const class std::vector<int, class std::allocator<int> >' lvalue <NoOp></div><div>            `-DeclRefExpr 0x564cf4e76cf0 <col:9> 'std::vector<int>':'class std::vector<int, class std::allocator<int> >' lvalue Var 0x564cf4e646c8 'vec' 'std::vector<int>':'class std::vector<int, class std::allocator<int> >'</div></div><div style="color:rgb(0,0,0);font-size:12.8px"><br></div><div style="color:rgb(0,0,0);font-size:12.8px">Is this really a technical issue from language POV or an implementation detail that is still missing? 14.6.2 [temp.dep] defines dependent-names as constructs whose semantics may differ from one instantiation to another. However, I am not quite sure if I understand this correctly because semantics of something being a data member or a function member cannot be really changed across different instantiations?</div><div style="color:rgb(0,0,0);font-size:12.8px"><br></div><div style="color:rgb(0,0,0);font-size:12.8px">I managed somehow to workaround this issue by tokenizing such (dependent) nodes and then trying to deduce their kinds by checking up their parent from the AST. I.e. 'MEMBER_REF_EXPR' dependent-name nodes ('CXType_DEPENDENT') which have 'CALL_EXPR' as their direct AST parent can be resolved as 'CXCursor_CXXMethod'. Otherwise, they would have been resolved as 'CXCursor_FieldDecl'. This satisfies the use-case which I am currently trying to cover and it seems to be working but I thought it would be better to have this functionality provided by the library, and probably a more generic solution which would fit other use-cases as well (i.e. non-'MEMBER_REF_EXPR' nodes). If this is possible I would be happy to contribute.</div><div style="color:rgb(0,0,0);font-size:12.8px"><br></div><div style="color:rgb(0,0,0);font-size:12.8px">Cheers,</div><div style="color:rgb(0,0,0);font-size:12.8px">Adi</div></div>