This commit is contained in:
Jacob Dufault 2017-02-18 18:03:13 -08:00
parent e54d70e464
commit 41f2a75de0
26 changed files with 376 additions and 87 deletions

View File

@ -15,6 +15,13 @@ bool Type::operator==(const Type& rhs) const {
return clang_equalTypes(cx_type, rhs.cx_type);
}
bool Type::is_fundamental() const {
// NOTE: This will return false for pointed types. Should we call
// strip_qualifiers for the user?
return cx_type.kind >= CXType_FirstBuiltin &&
cx_type.kind <= CXType_LastBuiltin;
}
std::string Type::get_usr() const {
return clang::Cursor(clang_getTypeDeclaration(cx_type)).get_usr();
}
@ -22,6 +29,7 @@ std::string Type::get_usr() const {
Type Type::strip_qualifiers() const {
//CXRefQualifierKind qualifiers = clang_Type_getCXXRefQualifier(cx_type)
switch (cx_type.kind) {
case CXType_LValueReference:
case CXType_Pointer:
return clang_getPointeeType(cx_type);
}
@ -165,9 +173,9 @@ std::string Cursor::get_type_description() const {
return canonical_spelling + " &";
else
return canonical_spelling;
}
}
#endif
}
}
if (spelling.empty())
return get_spelling();
@ -256,7 +264,7 @@ std::string Cursor::evaluate() const {
#endif
}
}
std::string Cursor::get_comments() const {
Cursor referenced = get_referenced();
@ -270,4 +278,4 @@ std::string Cursor::ToString() const {
return clang::ToString(get_kind()) + " " + get_spelling();
}
} // namespace clang
} // namespace clang

View File

@ -19,6 +19,9 @@ public:
bool operator==(const Type& rhs) const;
// Returns true if this is a fundamental type like int.
bool is_fundamental() const;
std::string get_usr() const;
std::string get_spelling() const;

View File

@ -85,7 +85,7 @@ struct TypeDef {
std::vector<clang::SourceLocation> uses;
TypeDef(TypeId id, const std::string& usr) : id(id), usr(usr) {
std::cout << "Creating type type with usr " << usr << std::endl;
std::cout << "Creating type with usr " << usr << std::endl;
}
};
@ -536,6 +536,16 @@ void Dump(clang::Cursor cursor) {
// The usage on |Foo| will be reported at the |x| variable location. We should
// report it at the start of |Foo| instead.
void InsertTypeUsageAtLocation(ParsingDatabase* db, clang::Type type, const clang::SourceLocation& location) {
clang::Type raw_type = type.strip_qualifiers();
if (raw_type.is_fundamental())
return;
// Add a usage to the type of the variable.
TypeId type_id = db->ToTypeId(raw_type.get_usr());
db->Resolve(type_id)->uses.push_back(location);
}
void HandleVarDecl(ParsingDatabase* db, NamespaceStack* ns, clang::Cursor var, std::optional<TypeId> declaring_type) {
//Dump(var);
@ -557,9 +567,7 @@ void HandleVarDecl(ParsingDatabase* db, NamespaceStack* ns, clang::Cursor var, s
}
// Add a usage to the type of the variable.
clang::Type var_type = var.get_type().strip_qualifiers();
TypeId var_type_id = db->ToTypeId(var_type.get_usr());
db->Resolve(var_type_id)->uses.push_back(var.get_source_location());
InsertTypeUsageAtLocation(db, var.get_type(), var.get_source_location());
// We don't do any additional processing for non-definitions.
if (!var.is_definition()) {
@ -693,43 +701,33 @@ void HandleFunc(ParsingDatabase* db, NamespaceStack* ns, clang::Cursor func, std
func_def->declaring_type = declaring_type;
}
// We don't do any additional processing for non-definitions.
// Insert return type usage here instead of in the visitor. The only way to
// do it in the visitor is to search for CXCursor_TypeRef, which does not
// necessarily refer to the return type.
InsertTypeUsageAtLocation(db, func.get_type().get_return_type(), func.get_source_location());
// Don't process definition/body for declarations.
if (!func.is_definition()) {
func_def->declaration = func.get_source_location();
// We insert type references for arguments but don't use the normal visitor
// because that will add a definition for the variable. These are not
// "real" variables so we don't want to add definitions for them.
// We navigate using cursor arguments so we can get location data.
for (clang::Cursor arg : func.get_arguments()) {
switch (arg.get_kind()) {
case CXCursor_ParmDecl:
InsertTypeUsageAtLocation(db, arg.get_type(), arg.get_source_location());
break;
}
}
return;
}
func_def->definition = func.get_source_location();
//std::cout << "!! Types: ";
//for (clang::Cursor arg : func.get_arguments())
// std::cout << arg.ToString() << ", ";
//std::cout << std::endl;
//std::cout << func.get_usr() << ": Set qualified name to " << db->Resolve(id)->qualified_name;
//std::cout << " IsDefinition? " << func.is_definition() << std::endl;
//clang::Type func_type = func.get_type();
//clang::Type return_type = func_type.get_return_type();
//std::vector<clang::Type> argument_types = func_type.get_arguments();
//auto argument_types = func.get_arguments();
//clang::Type cursor_type = func.get_type();
//clang::Type return_type_1 = func.get_type().get_result();
//clang::Type return_type_2 = clang_getCursorResultType(func.cx_cursor);
//Dump(func);
FuncDefinitionParam funcDefinitionParam(db, &NamespaceStack::kEmpty, func_id);
func.VisitChildren(&VisitFuncDefinition, &funcDefinitionParam);
//CXType return_type = clang_getResultType(func.get_type());
//CXType_FunctionProto
//std::cout << "!! HandleFunc " << func.get_type_description() << std::endl;
//std::cout << " comment: " << func.get_comments() << std::endl;
//std::cout << " spelling: " << func.get_spelling() << std::endl;
//for (clang::Cursor argument : func.get_arguments())
// std::cout << " arg: " << clang::ToString(argument.get_kind()) << " " << argument.get_spelling() << std::endl;
}
@ -925,7 +923,7 @@ void DiffDocuments(rapidjson::Document& expected, rapidjson::Document& actual) {
int len = std::min(actual_output.size(), expected_output.size());
for (int i = 0; i < len; ++i) {
if (actual_output[i] != expected_output[i]) {
std::cout << "Line " << i << " differs" << std::endl;
std::cout << "Line " << i << " differs:" << std::endl;
std::cout << " expected: " << expected_output[i] << std::endl;
std::cout << " actual: " << actual_output[i] << std::endl;
}
@ -947,7 +945,7 @@ void DiffDocuments(rapidjson::Document& expected, rapidjson::Document& actual) {
int main(int argc, char** argv) {
for (std::string path : GetFilesInFolder("tests")) {
// TODO: Fix all existing tests.
//if (path != "tests/usage/type_usage_declare_extern.cc") continue;
//if (path != "tests/method_definition.cc") continue;
// Parse expected output from the test, parse it into JSON document.
std::string expected_output;

View File

@ -8,13 +8,11 @@ void user() {
}
/*
// NOTE: used only has one caller!!
OUTPUT:
{
"types": [{
"id": 0,
"uses": ["tests/usage/func_usage_addr_func.cc:1:19", "tests/usage/func_usage_addr_func.cc:6:8"]
"uses": ["tests/usage/func_usage_addr_func.cc:6:8"]
}],
"functions": [{
"id": 0,

View File

@ -9,6 +9,8 @@ class Foo {
// TODO(libclang): libclang doesn't expose the |helper| reference in the ast,
// so we can't add the |helper| usage.
// TODO: Remove "id" 1 output
/*
OUTPUT:
{
@ -20,8 +22,7 @@ OUTPUT:
"definition": "tests/usage/func_usage_class_inline_var_def.cc:5:7",
"vars": [0]
}, {
"id": 1,
"uses": ["tests/usage/func_usage_class_inline_var_def.cc:6:7"]
"id": 1
}],
"functions": [{
"id": 0,

View File

@ -1,3 +1,4 @@
// TODO: implement this test. It is meant to support unique_ptr<T>
/*
OUTPUT:
{

View File

@ -1,8 +1,55 @@
struct ForwardType;
struct ImplementedType {};
struct Foo {
ForwardType* a;
ImplementedType b;
};
/*
OUTPUT:
{
"types": [],
"types": [{
"id": 0,
"usr": "c:@S@ForwardType",
"short_name": "ForwardType",
"qualified_name": "ForwardType",
"declaration": "tests/usage/type_usage_declare_field.cc:1:8",
"uses": ["tests/usage/type_usage_declare_field.cc:5:16"]
}, {
"id": 1,
"usr": "c:@S@ImplementedType",
"short_name": "ImplementedType",
"qualified_name": "ImplementedType",
"definition": "tests/usage/type_usage_declare_field.cc:2:8",
"uses": ["tests/usage/type_usage_declare_field.cc:6:19"]
}, {
"id": 2,
"usr": "c:@S@Foo",
"short_name": "Foo",
"qualified_name": "Foo",
"definition": "tests/usage/type_usage_declare_field.cc:4:8",
"vars": [0, 1]
}],
"functions": [],
"variables": []
"variables": [{
"id": 0,
"usr": "c:@S@Foo@FI@a",
"short_name": "a",
"qualified_name": "Foo::a",
"declaration": "tests/usage/type_usage_declare_field.cc:5:16",
"initializations": ["tests/usage/type_usage_declare_field.cc:5:16"],
"variable_type": 0,
"declaring_type": 2
}, {
"id": 1,
"usr": "c:@S@Foo@FI@b",
"short_name": "b",
"qualified_name": "Foo::b",
"declaration": "tests/usage/type_usage_declare_field.cc:6:19",
"initializations": ["tests/usage/type_usage_declare_field.cc:6:19"],
"variable_type": 1,
"declaring_type": 2
}]
}
*/

View File

@ -1,8 +1,52 @@
struct ForwardType;
struct ImplementedType {};
void Foo() {
ForwardType* a;
ImplementedType b;
}
/*
OUTPUT:
{
"types": [],
"functions": [],
"variables": []
"types": [{
"id": 0,
"usr": "c:@S@ForwardType",
"short_name": "ForwardType",
"qualified_name": "ForwardType",
"declaration": "tests/usage/type_usage_declare_local.cc:1:8",
"uses": ["tests/usage/type_usage_declare_local.cc:5:16"]
}, {
"id": 1,
"usr": "c:@S@ImplementedType",
"short_name": "ImplementedType",
"qualified_name": "ImplementedType",
"definition": "tests/usage/type_usage_declare_local.cc:2:8",
"uses": ["tests/usage/type_usage_declare_local.cc:6:19"]
}],
"functions": [{
"id": 0,
"usr": "c:@F@Foo#",
"short_name": "Foo",
"qualified_name": "Foo",
"definition": "tests/usage/type_usage_declare_local.cc:4:6"
}],
"variables": [{
"id": 0,
"usr": "c:type_usage_declare_local.cc@67@F@Foo#@a",
"short_name": "a",
"qualified_name": "a",
"declaration": "tests/usage/type_usage_declare_local.cc:5:16",
"initializations": ["tests/usage/type_usage_declare_local.cc:5:16"],
"variable_type": 0
}, {
"id": 1,
"usr": "c:type_usage_declare_local.cc@86@F@Foo#@b",
"short_name": "b",
"qualified_name": "b",
"declaration": "tests/usage/type_usage_declare_local.cc:6:19",
"initializations": ["tests/usage/type_usage_declare_local.cc:6:19"],
"variable_type": 1
}]
}
*/

View File

@ -1,8 +1,49 @@
struct ForwardType;
struct ImplementedType {};
void foo(ForwardType* f, ImplementedType a) {}
/*
OUTPUT:
{
"types": [],
"functions": [],
"variables": []
"types": [{
"id": 0,
"usr": "c:@S@ForwardType",
"short_name": "ForwardType",
"qualified_name": "ForwardType",
"declaration": "tests/usage/type_usage_declare_param.cc:1:8",
"uses": ["tests/usage/type_usage_declare_param.cc:4:23"]
}, {
"id": 1,
"usr": "c:@S@ImplementedType",
"short_name": "ImplementedType",
"qualified_name": "ImplementedType",
"definition": "tests/usage/type_usage_declare_param.cc:2:8",
"uses": ["tests/usage/type_usage_declare_param.cc:4:42"]
}],
"functions": [{
"id": 0,
"usr": "c:@F@foo#*$@S@ForwardType#$@S@ImplementedType#",
"short_name": "foo",
"qualified_name": "foo",
"definition": "tests/usage/type_usage_declare_param.cc:4:6"
}],
"variables": [{
"id": 0,
"usr": "c:type_usage_declare_param.cc@60@F@foo#*$@S@ForwardType#$@S@ImplementedType#@f",
"short_name": "f",
"qualified_name": "f",
"declaration": "tests/usage/type_usage_declare_param.cc:4:23",
"initializations": ["tests/usage/type_usage_declare_param.cc:4:23"],
"variable_type": 0
}, {
"id": 1,
"usr": "c:type_usage_declare_param.cc@76@F@foo#*$@S@ForwardType#$@S@ImplementedType#@a",
"short_name": "a",
"qualified_name": "a",
"declaration": "tests/usage/type_usage_declare_param.cc:4:42",
"initializations": ["tests/usage/type_usage_declare_param.cc:4:42"],
"variable_type": 1
}]
}
*/

View File

@ -0,0 +1,28 @@
struct ForwardType;
void foo(ForwardType*) {}
/*
OUTPUT:
{
"types": [{
"id": 0,
"usr": "c:@S@ForwardType",
"short_name": "ForwardType",
"qualified_name": "ForwardType",
"declaration": "tests/usage/type_usage_declare_param_unnamed.cc:1:8",
"uses": ["tests/usage/type_usage_declare_param_unnamed.cc:2:22"]
}],
"functions": [{
"id": 0,
"usr": "c:@F@foo#*$@S@ForwardType#",
"short_name": "foo",
"qualified_name": "foo",
"definition": "tests/usage/type_usage_declare_param_unnamed.cc:2:6"
}],
"variables": [{
"id": 0,
"declaration": "tests/usage/type_usage_declare_param_unnamed.cc:2:22",
"initializations": ["tests/usage/type_usage_declare_param_unnamed.cc:2:22"],
"variable_type": 0
}]
}
*/

View File

@ -1,8 +0,0 @@
/*
OUTPUT:
{
"types": [],
"functions": [],
"variables": []
}
*/

View File

@ -0,0 +1,35 @@
struct Foo;
void foo(Foo* f);
void foo(Foo* f) {}
/*
OUTPUT:
{
"types": [{
"id": 0,
"usr": "c:@S@Foo",
"short_name": "Foo",
"qualified_name": "Foo",
"declaration": "tests/usage/type_usage_on_prototype_parameter.cc:1:8",
"uses": ["tests/usage/type_usage_on_prototype_parameter.cc:2:15", "tests/usage/type_usage_on_prototype_parameter.cc:4:15"]
}],
"functions": [{
"id": 0,
"usr": "c:@F@foo#*$@S@Foo#",
"short_name": "foo",
"qualified_name": "foo",
"declaration": "tests/usage/type_usage_on_prototype_parameter.cc:2:6",
"definition": "tests/usage/type_usage_on_prototype_parameter.cc:4:6"
}],
"variables": [{
"id": 0,
"usr": "c:type_usage_on_prototype_parameter.cc@43@F@foo#*$@S@Foo#@f",
"short_name": "f",
"qualified_name": "f",
"declaration": "tests/usage/type_usage_on_prototype_parameter.cc:4:15",
"initializations": ["tests/usage/type_usage_on_prototype_parameter.cc:4:15"],
"variable_type": 0
}]
}
*/

View File

@ -1,8 +1,31 @@
struct Type;
Type* foo();
Type* foo();
Type* foo() {}
/*
// TODO: We should try to get the right location for type uses so it points to
// the return type and not the function name.
OUTPUT:
{
"types": [],
"functions": [],
"types": [{
"id": 0,
"usr": "c:@S@Type",
"short_name": "Type",
"qualified_name": "Type",
"declaration": "tests/usage/type_usage_on_return_type.cc:1:8",
"uses": ["tests/usage/type_usage_on_return_type.cc:3:7", "tests/usage/type_usage_on_return_type.cc:4:7", "tests/usage/type_usage_on_return_type.cc:5:7"]
}],
"functions": [{
"id": 0,
"usr": "c:@F@foo#",
"short_name": "foo",
"qualified_name": "foo",
"declaration": "tests/usage/type_usage_on_return_type.cc:4:7",
"definition": "tests/usage/type_usage_on_return_type.cc:5:7"
}],
"variables": []
}
*/

View File

@ -1,6 +1,4 @@
/*
// TODO: Idea with this test is to verify we will capture std::unique_ptr<T>
OUTPUT:
{
"types": [],

View File

@ -0,0 +1,77 @@
struct Type {};
void foo(Type& a0, const Type& a1) {
Type a2;
Type* a3;
const Type* a4;
const Type const* a5;
}
/*
OUTPUT:
{
"types": [{
"id": 0,
"usr": "c:@S@Type",
"short_name": "Type",
"qualified_name": "Type",
"definition": "tests/usage/type_usage_qualifiers.cc:1:8",
"uses": ["tests/usage/type_usage_qualifiers.cc:3:16", "tests/usage/type_usage_qualifiers.cc:3:32", "tests/usage/type_usage_qualifiers.cc:4:8", "tests/usage/type_usage_qualifiers.cc:5:9", "tests/usage/type_usage_qualifiers.cc:6:15", "tests/usage/type_usage_qualifiers.cc:7:21"]
}],
"functions": [{
"id": 0,
"usr": "c:@F@foo#&$@S@Type#&1S1_#",
"short_name": "foo",
"qualified_name": "foo",
"definition": "tests/usage/type_usage_qualifiers.cc:3:6"
}],
"variables": [{
"id": 0,
"usr": "c:type_usage_qualifiers.cc@28@F@foo#&$@S@Type#&1S1_#@a0",
"short_name": "a0",
"qualified_name": "a0",
"declaration": "tests/usage/type_usage_qualifiers.cc:3:16",
"initializations": ["tests/usage/type_usage_qualifiers.cc:3:16"],
"variable_type": 0
}, {
"id": 1,
"usr": "c:type_usage_qualifiers.cc@38@F@foo#&$@S@Type#&1S1_#@a1",
"short_name": "a1",
"qualified_name": "a1",
"declaration": "tests/usage/type_usage_qualifiers.cc:3:32",
"initializations": ["tests/usage/type_usage_qualifiers.cc:3:32"],
"variable_type": 0
}, {
"id": 2,
"usr": "c:type_usage_qualifiers.cc@59@F@foo#&$@S@Type#&1S1_#@a2",
"short_name": "a2",
"qualified_name": "a2",
"declaration": "tests/usage/type_usage_qualifiers.cc:4:8",
"initializations": ["tests/usage/type_usage_qualifiers.cc:4:8"],
"variable_type": 0
}, {
"id": 3,
"usr": "c:type_usage_qualifiers.cc@71@F@foo#&$@S@Type#&1S1_#@a3",
"short_name": "a3",
"qualified_name": "a3",
"declaration": "tests/usage/type_usage_qualifiers.cc:5:9",
"initializations": ["tests/usage/type_usage_qualifiers.cc:5:9"],
"variable_type": 0
}, {
"id": 4,
"usr": "c:type_usage_qualifiers.cc@84@F@foo#&$@S@Type#&1S1_#@a4",
"short_name": "a4",
"qualified_name": "a4",
"declaration": "tests/usage/type_usage_qualifiers.cc:6:15",
"initializations": ["tests/usage/type_usage_qualifiers.cc:6:15"],
"variable_type": 0
}, {
"id": 5,
"usr": "c:type_usage_qualifiers.cc@103@F@foo#&$@S@Type#&1S1_#@a5",
"short_name": "a5",
"qualified_name": "a5",
"declaration": "tests/usage/type_usage_qualifiers.cc:7:21",
"initializations": ["tests/usage/type_usage_qualifiers.cc:7:21"],
"variable_type": 0
}]
}
*/

View File

@ -0,0 +1,9 @@
// TODO: Verify using and typedef are treated as separate types for usage info.
/*
OUTPUT:
{
"types": [],
"functions": [],
"variables": []
}
*/

View File

@ -12,8 +12,7 @@ OUTPUT:
"definition": "tests/vars/class_member.cc:1:7",
"vars": [0]
}, {
"id": 1,
"uses": ["tests/vars/class_member.cc:2:7"]
"id": 1
}],
"functions": [],
"variables": [{

View File

@ -13,8 +13,7 @@ OUTPUT:
"definition": "tests/vars/class_static_member.cc:1:7",
"vars": [0]
}, {
"id": 1,
"uses": ["tests/vars/class_static_member.cc:2:14", "tests/vars/class_static_member.cc:4:10"]
"id": 1
}],
"functions": [],
"variables": [{

View File

@ -11,9 +11,6 @@ OUTPUT:
"qualified_name": "Foo",
"definition": "tests/vars/class_static_member_decl_only.cc:1:7",
"vars": [0]
}, {
"id": 1,
"uses": ["tests/vars/class_static_member_decl_only.cc:2:14"]
}],
"functions": [],
"variables": [{

View File

@ -5,8 +5,7 @@ void foo() {
OUTPUT:
{
"types": [{
"id": 0,
"uses": ["tests/vars/function_local.cc:2:7"]
"id": 0
}],
"functions": [{
"id": 0,

View File

@ -3,8 +3,7 @@ void foo(int p0, int p1) {}
OUTPUT:
{
"types": [{
"id": 0,
"uses": ["tests/vars/function_param.cc:1:14", "tests/vars/function_param.cc:1:22"]
"id": 0
}],
"functions": [{
"id": 0,

View File

@ -8,8 +8,7 @@ void foo(int, int) {}
OUTPUT:
{
"types": [{
"id": 0,
"uses": ["tests/vars/function_param_unnamed.cc:1:13", "tests/vars/function_param_unnamed.cc:1:18"]
"id": 0
}],
"functions": [{
"id": 0,

View File

@ -8,8 +8,7 @@ void foo() {
OUTPUT:
{
"types": [{
"id": 0,
"uses": ["tests/vars/function_shadow_local.cc:2:7", "tests/vars/function_shadow_local.cc:4:9"]
"id": 0
}],
"functions": [{
"id": 0,

View File

@ -5,8 +5,7 @@ void foo(int p) {
OUTPUT:
{
"types": [{
"id": 0,
"uses": ["tests/vars/function_shadow_param.cc:1:14", "tests/vars/function_shadow_param.cc:2:7"]
"id": 0
}],
"functions": [{
"id": 0,

View File

@ -3,8 +3,7 @@ static int global = 0;
OUTPUT:
{
"types": [{
"id": 0,
"uses": ["tests/vars/global_variable.cc:1:12"]
"id": 0
}],
"functions": [],
"variables": [{

View File

@ -2,10 +2,7 @@ extern int global;
/*
OUTPUT:
{
"types": [{
"id": 0,
"uses": ["tests/vars/global_variable_decl_only.cc:1:12"]
}],
"types": [],
"functions": [],
"variables": [{
"id": 0,