mirror of
				https://github.com/MaskRay/ccls.git
				synced 2025-10-31 20:53:01 +00:00 
			
		
		
		
	Support llvm 4
This commit is contained in:
		
							parent
							
								
									c079ab45b3
								
							
						
					
					
						commit
						ebd467d31b
					
				
							
								
								
									
										107
									
								
								indexer.cpp
									
									
									
									
									
								
							
							
						
						
									
										107
									
								
								indexer.cpp
									
									
									
									
									
								
							| @ -84,7 +84,7 @@ IndexedTypeDef::IndexedTypeDef(TypeId id, const std::string& usr) : id(id), def( | |||||||
|   //std::cerr << "Creating type with usr " << usr << std::endl;
 |   //std::cerr << "Creating type with usr " << usr << std::endl;
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void IndexedTypeDef::AddUsage(Location loc, bool insert_if_not_present) { | void AddUsage(std::vector<Location>& uses, Location loc, bool insert_if_not_present = true) { | ||||||
|   for (int i = uses.size() - 1; i >= 0; --i) { |   for (int i = uses.size() - 1; i >= 0; --i) { | ||||||
|     if (uses[i].IsEqualTo(loc)) { |     if (uses[i].IsEqualTo(loc)) { | ||||||
|       if (loc.interesting) |       if (loc.interesting) | ||||||
| @ -395,7 +395,7 @@ void VisitDeclForTypeUsageVisitorHandler(clang::Cursor cursor, VisitDeclForTypeU | |||||||
|   if (param->is_interesting) { |   if (param->is_interesting) { | ||||||
|     IndexedTypeDef* ref_type_def = db->Resolve(ref_type_id); |     IndexedTypeDef* ref_type_def = db->Resolve(ref_type_id); | ||||||
|     Location loc = db->id_cache.Resolve(cursor, true /*interesting*/); |     Location loc = db->id_cache.Resolve(cursor, true /*interesting*/); | ||||||
|     ref_type_def->AddUsage(loc); |     AddUsage(ref_type_def->uses, loc); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -455,7 +455,7 @@ optional<TypeId> ResolveToDeclarationType(IndexedFile* db, clang::Cursor cursor) | |||||||
| // returns the first seen TypeRef or TemplateRef value, which can be useful if trying
 | // returns the first seen TypeRef or TemplateRef value, which can be useful if trying
 | ||||||
| // to figure out ie, what a using statement refers to. If trying to generally resolve
 | // to figure out ie, what a using statement refers to. If trying to generally resolve
 | ||||||
| // a cursor to a type, use ResolveToDeclarationType, which works in more scenarios.
 | // a cursor to a type, use ResolveToDeclarationType, which works in more scenarios.
 | ||||||
| optional<TypeId> AddDeclUsages(IndexedFile* db, clang::Cursor decl_cursor, | optional<TypeId> AddDeclTypeUsages(IndexedFile* db, clang::Cursor decl_cursor, | ||||||
|   bool is_interesting, const CXIdxContainerInfo* semantic_container, |   bool is_interesting, const CXIdxContainerInfo* semantic_container, | ||||||
|   const CXIdxContainerInfo* lexical_container) { |   const CXIdxContainerInfo* lexical_container) { | ||||||
| 
 | 
 | ||||||
| @ -584,6 +584,70 @@ optional<TypeId> AddDeclUsages(IndexedFile* db, clang::Cursor decl_cursor, | |||||||
|   return param.initial_type; |   return param.initial_type; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // Various versions of LLVM (ie, 4.0) will not visit inline variable references for template arguments.
 | ||||||
|  | clang::VisiterResult AddDeclInitializerUsagesVisitor(clang::Cursor cursor, clang::Cursor parent, IndexedFile* db) { | ||||||
|  |   /*
 | ||||||
|  |     We need to index the |DeclRefExpr| below (ie, |var| inside of Foo<int>::var). | ||||||
|  | 
 | ||||||
|  |       template<typename T> | ||||||
|  |       struct Foo { | ||||||
|  |         static constexpr int var = 3; | ||||||
|  |       }; | ||||||
|  | 
 | ||||||
|  |       int a = Foo<int>::var; | ||||||
|  | 
 | ||||||
|  |       => | ||||||
|  | 
 | ||||||
|  |       VarDecl a | ||||||
|  |         UnexposedExpr var | ||||||
|  |           DeclRefExpr var | ||||||
|  |             TemplateRef Foo | ||||||
|  | 
 | ||||||
|  |   */ | ||||||
|  | 
 | ||||||
|  |   switch (cursor.get_kind()) { | ||||||
|  |   case CXCursor_DeclRefExpr: | ||||||
|  |     CXCursorKind referenced_kind = cursor.get_referenced().get_kind(); | ||||||
|  |     if (cursor.get_referenced().get_kind() != CXCursor_VarDecl) | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |     // TODO: when we resolve the template type to the definition, we get a different USR.
 | ||||||
|  | 
 | ||||||
|  |     //clang::Cursor ref = cursor.get_referenced().template_specialization_to_template_definition().get_type().strip_qualifiers().get_usr();
 | ||||||
|  |     //std::string ref_usr = cursor.get_referenced().template_specialization_to_template_definition().get_type().strip_qualifiers().get_usr();
 | ||||||
|  |     std::string ref_usr = cursor.get_referenced().template_specialization_to_template_definition().get_usr(); | ||||||
|  |     //std::string ref_usr = ref.get_usr();
 | ||||||
|  |     if (ref_usr == "") | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |     VarId ref_id = db->ToVarId(ref_usr); | ||||||
|  |     IndexedVarDef* ref_def = db->Resolve(ref_id); | ||||||
|  |     Location loc = db->id_cache.Resolve(cursor, false /*interesting*/); | ||||||
|  |     std::cerr << "Adding usage to id=" << ref_id.id << " usr=" << ref_usr << " at " << loc.ToString() << std::endl; | ||||||
|  |     AddUsage(ref_def->uses, loc); | ||||||
|  |     break; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return clang::VisiterResult::Recurse; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void AddDeclInitializerUsages(IndexedFile* db, clang::Cursor decl_cursor) { | ||||||
|  |   decl_cursor.VisitChildren(&AddDeclInitializerUsagesVisitor, db); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { | void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { | ||||||
|   // TODO: we can minimize processing for cursors which return false for clang_Location_isFromMainFile (ie, only add usages)
 |   // TODO: we can minimize processing for cursors which return false for clang_Location_isFromMainFile (ie, only add usages)
 | ||||||
| 
 | 
 | ||||||
| @ -595,6 +659,8 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { | |||||||
|   IndexedFile* db = param->db; |   IndexedFile* db = param->db; | ||||||
|   NamespaceHelper* ns = param->ns; |   NamespaceHelper* ns = param->ns; | ||||||
| 
 | 
 | ||||||
|  |   // std::cerr << "DECL kind=" << decl->entityInfo->kind << " at " << db->id_cache.Resolve(decl->cursor, false).ToPrettyString(&db->id_cache) << std::endl;
 | ||||||
|  | 
 | ||||||
|   switch (decl->entityInfo->kind) { |   switch (decl->entityInfo->kind) { | ||||||
|   case CXIdxEntity_CXXNamespace: |   case CXIdxEntity_CXXNamespace: | ||||||
|   { |   { | ||||||
| @ -632,16 +698,19 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { | |||||||
|       var_def->def.definition = decl_loc; |       var_def->def.definition = decl_loc; | ||||||
|     else |     else | ||||||
|       var_def->def.declaration = decl_loc; |       var_def->def.declaration = decl_loc; | ||||||
|     var_def->uses.push_back(decl_loc); |     AddUsage(var_def->uses, decl_loc); | ||||||
| 
 | 
 | ||||||
|     //std::cerr << std::endl << "Visiting declaration" << std::endl;
 |     //std::cerr << std::endl << "Visiting declaration" << std::endl;
 | ||||||
|     //Dump(decl_cursor);
 |     //Dump(decl_cursor);
 | ||||||
| 
 | 
 | ||||||
|  |     AddDeclInitializerUsages(db, decl_cursor); | ||||||
|  |     var_def = db->Resolve(var_id); | ||||||
|  | 
 | ||||||
|     // Declaring variable type information. Note that we do not insert an
 |     // Declaring variable type information. Note that we do not insert an
 | ||||||
|     // interesting reference for parameter declarations - that is handled when
 |     // interesting reference for parameter declarations - that is handled when
 | ||||||
|     // the function declaration is encountered since we won't receive ParmDecl
 |     // the function declaration is encountered since we won't receive ParmDecl
 | ||||||
|     // declarations for unnamed parameters.
 |     // declarations for unnamed parameters.
 | ||||||
|     AddDeclUsages(db, decl_cursor, decl_cursor.get_kind() != CXCursor_ParmDecl /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer); |     AddDeclTypeUsages(db, decl_cursor, decl_cursor.get_kind() != CXCursor_ParmDecl /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer); | ||||||
|     optional<TypeId> var_type = ResolveToDeclarationType(db, decl_cursor); |     optional<TypeId> var_type = ResolveToDeclarationType(db, decl_cursor); | ||||||
|     if (var_type.has_value()) |     if (var_type.has_value()) | ||||||
|       var_def->def.variable_type = var_type.value(); |       var_def->def.variable_type = var_type.value(); | ||||||
| @ -672,10 +741,10 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { | |||||||
| 
 | 
 | ||||||
|     Location decl_loc = db->id_cache.Resolve(decl->loc, false /*interesting*/); |     Location decl_loc = db->id_cache.Resolve(decl->loc, false /*interesting*/); | ||||||
| 
 | 
 | ||||||
|     func_def->uses.push_back(decl_loc); |     AddUsage(func_def->uses, decl_loc); | ||||||
|     // We don't actually need to know the return type, but we need to mark it
 |     // We don't actually need to know the return type, but we need to mark it
 | ||||||
|     // as an interesting usage.
 |     // as an interesting usage.
 | ||||||
|     AddDeclUsages(db, decl_cursor, true /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer); |     AddDeclTypeUsages(db, decl_cursor, true /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer); | ||||||
| 
 | 
 | ||||||
|     // TODO: support multiple definitions per function; right now we are hacking the 'declarations' field by
 |     // TODO: support multiple definitions per function; right now we are hacking the 'declarations' field by
 | ||||||
|     // adding a definition when we really don't have one.
 |     // adding a definition when we really don't have one.
 | ||||||
| @ -712,7 +781,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { | |||||||
|         // TODO: Should it be interesting?
 |         // TODO: Should it be interesting?
 | ||||||
|         if (is_ctor_or_dtor) { |         if (is_ctor_or_dtor) { | ||||||
|           Location type_usage_loc = decl_loc; |           Location type_usage_loc = decl_loc; | ||||||
|           declaring_type_def->AddUsage(type_usage_loc); |           AddUsage(declaring_type_def->uses, type_usage_loc); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Register function in declaring type if it hasn't been registered yet.
 |         // Register function in declaring type if it hasn't been registered yet.
 | ||||||
| @ -742,7 +811,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { | |||||||
|             // We don't need to know the arg type, but we do want to mark it as
 |             // We don't need to know the arg type, but we do want to mark it as
 | ||||||
|             // an interesting usage. Note that we use semanticContainer twice
 |             // an interesting usage. Note that we use semanticContainer twice
 | ||||||
|             // because a parameter is not really part of the lexical container.
 |             // because a parameter is not really part of the lexical container.
 | ||||||
|             AddDeclUsages(db, arg, true /*is_interesting*/, decl->semanticContainer, decl->semanticContainer); |             AddDeclTypeUsages(db, arg, true /*is_interesting*/, decl->semanticContainer, decl->semanticContainer); | ||||||
| 
 | 
 | ||||||
|             //TypeResolution arg_type = ResolveToType(db, arg.get_type());
 |             //TypeResolution arg_type = ResolveToType(db, arg.get_type());
 | ||||||
|             //if (arg_type.resolved_type)
 |             //if (arg_type.resolved_type)
 | ||||||
| @ -792,7 +861,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { | |||||||
|   { |   { | ||||||
|     // Note we want to fetch the first TypeRef. Running ResolveCursorType(decl->cursor) would return
 |     // Note we want to fetch the first TypeRef. Running ResolveCursorType(decl->cursor) would return
 | ||||||
|     // the type of the typedef/using, not the type of the referenced type.
 |     // the type of the typedef/using, not the type of the referenced type.
 | ||||||
|     optional<TypeId> alias_of = AddDeclUsages(db, decl->cursor, true /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer); |     optional<TypeId> alias_of = AddDeclTypeUsages(db, decl->cursor, true /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer); | ||||||
| 
 | 
 | ||||||
|     TypeId type_id = db->ToTypeId(decl->entityInfo->USR); |     TypeId type_id = db->ToTypeId(decl->entityInfo->USR); | ||||||
|     IndexedTypeDef* type_def = db->Resolve(type_id); |     IndexedTypeDef* type_def = db->Resolve(type_id); | ||||||
| @ -807,7 +876,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { | |||||||
| 
 | 
 | ||||||
|     Location decl_loc = db->id_cache.Resolve(decl->loc, true /*interesting*/); |     Location decl_loc = db->id_cache.Resolve(decl->loc, true /*interesting*/); | ||||||
|     type_def->def.definition = decl_loc.WithInteresting(false); |     type_def->def.definition = decl_loc.WithInteresting(false); | ||||||
|     type_def->AddUsage(decl_loc); |     AddUsage(type_def->uses, decl_loc); | ||||||
|     break; |     break; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -841,7 +910,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { | |||||||
|     assert(decl->isDefinition); |     assert(decl->isDefinition); | ||||||
|     Location decl_loc = db->id_cache.Resolve(decl->loc, true /*interesting*/); |     Location decl_loc = db->id_cache.Resolve(decl->loc, true /*interesting*/); | ||||||
|     type_def->def.definition = decl_loc.WithInteresting(false); |     type_def->def.definition = decl_loc.WithInteresting(false); | ||||||
|     type_def->AddUsage(decl_loc); |     AddUsage(type_def->uses, decl_loc); | ||||||
| 
 | 
 | ||||||
|     //type_def->alias_of
 |     //type_def->alias_of
 | ||||||
|     //type_def->funcs
 |     //type_def->funcs
 | ||||||
| @ -855,7 +924,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { | |||||||
|       for (unsigned int i = 0; i < class_info->numBases; ++i) { |       for (unsigned int i = 0; i < class_info->numBases; ++i) { | ||||||
|         const CXIdxBaseClassInfo* base_class = class_info->bases[i]; |         const CXIdxBaseClassInfo* base_class = class_info->bases[i]; | ||||||
| 
 | 
 | ||||||
|         AddDeclUsages(db, base_class->cursor, true /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer); |         AddDeclTypeUsages(db, base_class->cursor, true /*is_interesting*/, decl->semanticContainer, decl->lexicalContainer); | ||||||
|         optional<TypeId> parent_type_id = ResolveToDeclarationType(db, base_class->cursor); |         optional<TypeId> parent_type_id = ResolveToDeclarationType(db, base_class->cursor); | ||||||
|         IndexedTypeDef* type_def = db->Resolve(type_id); // type_def ptr could be invalidated by ResolveDeclToType.
 |         IndexedTypeDef* type_def = db->Resolve(type_id); // type_def ptr could be invalidated by ResolveDeclToType.
 | ||||||
|         if (parent_type_id) { |         if (parent_type_id) { | ||||||
| @ -901,6 +970,8 @@ void indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* re | |||||||
|   IndexedFile* db = param->db; |   IndexedFile* db = param->db; | ||||||
|   clang::Cursor cursor(ref->cursor); |   clang::Cursor cursor(ref->cursor); | ||||||
| 
 | 
 | ||||||
|  |   //std::cerr << "REF kind=" << ref->referencedEntity->kind << " at " << db->id_cache.Resolve(cursor, false).ToPrettyString(&db->id_cache) << std::endl;
 | ||||||
|  | 
 | ||||||
|   switch (ref->referencedEntity->kind) { |   switch (ref->referencedEntity->kind) { | ||||||
|   case CXIdxEntity_CXXNamespace: |   case CXIdxEntity_CXXNamespace: | ||||||
|   { |   { | ||||||
| @ -919,7 +990,7 @@ void indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* re | |||||||
|     VarId var_id = db->ToVarId(referenced.get_usr()); |     VarId var_id = db->ToVarId(referenced.get_usr()); | ||||||
|     IndexedVarDef* var_def = db->Resolve(var_id); |     IndexedVarDef* var_def = db->Resolve(var_id); | ||||||
|     Location loc = db->id_cache.Resolve(ref->loc, false /*interesting*/); |     Location loc = db->id_cache.Resolve(ref->loc, false /*interesting*/); | ||||||
|     var_def->uses.push_back(loc); |     AddUsage(var_def->uses, loc); | ||||||
|     break; |     break; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -954,11 +1025,11 @@ void indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* re | |||||||
| 
 | 
 | ||||||
|       caller_def->def.callees.push_back(FuncRef(called_id, loc)); |       caller_def->def.callees.push_back(FuncRef(called_id, loc)); | ||||||
|       called_def->callers.push_back(FuncRef(caller_id, loc)); |       called_def->callers.push_back(FuncRef(caller_id, loc)); | ||||||
|       called_def->uses.push_back(loc); |       AddUsage(called_def->uses, loc); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|       IndexedFuncDef* called_def = db->Resolve(called_id); |       IndexedFuncDef* called_def = db->Resolve(called_id); | ||||||
|       called_def->uses.push_back(loc); |       AddUsage(called_def->uses, loc); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // For constructor/destructor, also add a usage against the type. Clang
 |     // For constructor/destructor, also add a usage against the type. Clang
 | ||||||
| @ -978,7 +1049,7 @@ void indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* re | |||||||
|         if (called_def->def.declaring_type) { |         if (called_def->def.declaring_type) { | ||||||
|           //assert(called_def->def.declaring_type.has_value());
 |           //assert(called_def->def.declaring_type.has_value());
 | ||||||
|           IndexedTypeDef* type_def = db->Resolve(called_def->def.declaring_type.value()); |           IndexedTypeDef* type_def = db->Resolve(called_def->def.declaring_type.value()); | ||||||
|           type_def->AddUsage(our_loc); |           AddUsage(type_def->uses, our_loc); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @ -1021,7 +1092,7 @@ void indexEntityReference(CXClientData client_data, const CXIdxEntityRefInfo* re | |||||||
|     //    Foo f;
 |     //    Foo f;
 | ||||||
|     //  }
 |     //  }
 | ||||||
|     //
 |     //
 | ||||||
|     referenced_def->AddUsage(db->id_cache.Resolve(ref->loc, false /*interesting*/)); |     AddUsage(referenced_def->uses, db->id_cache.Resolve(ref->loc, false /*interesting*/)); | ||||||
|     break; |     break; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -332,7 +332,6 @@ struct IndexedTypeDef { | |||||||
|   IndexedTypeDef() : def("") {} // For serialization
 |   IndexedTypeDef() : def("") {} // For serialization
 | ||||||
| 
 | 
 | ||||||
|   IndexedTypeDef(TypeId id, const std::string& usr); |   IndexedTypeDef(TypeId id, const std::string& usr); | ||||||
|   void AddUsage(Location loc, bool insert_if_not_present = true); |  | ||||||
| 
 | 
 | ||||||
|   bool operator<(const IndexedTypeDef& other) const { |   bool operator<(const IndexedTypeDef& other) const { | ||||||
|     return def.usr < other.def.usr; |     return def.usr < other.def.usr; | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								test.cc
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								test.cc
									
									
									
									
									
								
							| @ -97,10 +97,10 @@ void RunTests() { | |||||||
| 
 | 
 | ||||||
|   for (std::string path : GetFilesInFolder("tests", true /*recursive*/, true /*add_folder_to_path*/)) { |   for (std::string path : GetFilesInFolder("tests", true /*recursive*/, true /*add_folder_to_path*/)) { | ||||||
|     //if (path != "tests/templates/specialized_func_definition.cc") continue;
 |     //if (path != "tests/templates/specialized_func_definition.cc") continue;
 | ||||||
|     //if (path != "tests/outline/outline2.cc") continue;
 |     //if (path != "tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc") continue;
 | ||||||
|     //if (path == "tests/inheritance/class_inherit_templated_parent.cc") continue;
 |     //if (path == "tests/inheritance/class_inherit_templated_parent.cc") continue;
 | ||||||
|     //if (path != "tests/namespaces/namespace_reference.cc") continue;
 |     //if (path != "tests/namespaces/namespace_reference.cc") continue;
 | ||||||
|     //if (path != "tests/stl.cc") continue;
 |     //if (path != "tests/templates/implicit_variable_instantiation.cc") continue;
 | ||||||
| 
 | 
 | ||||||
|     //if (path != "tests/templates/template_class_type_usage_folded_into_one.cc") continue;
 |     //if (path != "tests/templates/template_class_type_usage_folded_into_one.cc") continue;
 | ||||||
|     //path = "C:/Users/jacob/Desktop/superindex/indexer/" + path;
 |     //path = "C:/Users/jacob/Desktop/superindex/indexer/" + path;
 | ||||||
|  | |||||||
| @ -7,8 +7,7 @@ T var = 3; | |||||||
| int a = var<A>; | int a = var<A>; | ||||||
| int b = var<B>; | int b = var<B>; | ||||||
| 
 | 
 | ||||||
| // TODO: No usages of types on var.
 | // NOTE: libclang before 4.0 doesn't expose template usage on |var|.
 | ||||||
| //       libclang doesn't expose the info. File a bug.
 |  | ||||||
| 
 | 
 | ||||||
| #if false | #if false | ||||||
| EnumDecl A | EnumDecl A | ||||||
| @ -48,11 +47,11 @@ OUTPUT: | |||||||
|     }], |     }], | ||||||
|   "vars": [{ |   "vars": [{ | ||||||
|       "id": 0, |       "id": 0, | ||||||
|       "usr": "c:@var", |       "usr": "c:@VT>1#T@var", | ||||||
|       "short_name": "var", |       "short_name": "var", | ||||||
|       "qualified_name": "var", |       "qualified_name": "var", | ||||||
|       "definition": "1:5:3", |       "definition": "1:5:3", | ||||||
|       "uses": ["1:5:3"] |       "uses": ["1:5:3", "1:7:9", "1:8:9"] | ||||||
|     }, { |     }, { | ||||||
|       "id": 1, |       "id": 1, | ||||||
|       "usr": "c:@a", |       "usr": "c:@a", | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user