Skip to content

Commit

Permalink
ClangCountingConditions: Add scope aware conditions
Browse files Browse the repository at this point in the history
This adds a few scope aware counting conditions which is probably an
important step to reduce the number of false positive results the clone
detection still yields.
  • Loading branch information
sils committed May 18, 2015
1 parent 8283799 commit 1e276f5
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 5 deletions.
34 changes: 29 additions & 5 deletions bears/codeclone_detection/ClangCountingConditions.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,15 @@ def is_condition(cursor, stack):
def in_condition(cursor, stack):
# In every case the first child of IF_STMT is the condition itself
# (non-NULL) so the second and third child are in the then/else branch
return _is_nth_child_of_kind(stack, [1, 2], CursorKind.IF_STMT) != 0
return _is_nth_child_of_kind(stack, [1, 2], CursorKind.IF_STMT) == 1


def in_second_level_condition(cursor, stack):
return _is_nth_child_of_kind(stack, [1, 2], CursorKind.IF_STMT) == 2


def in_third_level_condition(cursor, stack):
return _is_nth_child_of_kind(stack, [1, 2], CursorKind.IF_STMT) > 2


def is_assignee(cursor, stack):
Expand Down Expand Up @@ -239,11 +247,23 @@ def is_assigner(cursor, stack):
return is_inc_or_dec(cursor, stack)


def loop_content(cursor, stack):
def _loop_level(cursor, stack):
positions_in_for = _get_positions_in_for_loop(cursor, stack)
return (_is_nth_child_of_kind(stack, [1], CursorKind.WHILE_STMT) != 0 or
FOR_POSITION.INC in positions_in_for or
FOR_POSITION.BODY in positions_in_for)
return (positions_in_for.count(FOR_POSITION.INC) +
positions_in_for.count(FOR_POSITION.BODY) +
_is_nth_child_of_kind(stack, [1], CursorKind.WHILE_STMT))


def loop_content(cursor, stack):
return _loop_level(cursor, stack) == 1


def second_level_loop_content(cursor, stack):
return _loop_level(cursor, stack) == 2


def third_level_loop_content(cursor, stack):
return _loop_level(cursor, stack) > 2


def is_param(cursor, stack):
Expand All @@ -254,9 +274,13 @@ def is_param(cursor, stack):
"returned": returned,
"is_condition": is_condition,
"in_condition": in_condition,
"in_second_level_condition": in_second_level_condition,
"in_third_level_condition": in_third_level_condition,
"is_assignee": is_assignee,
"is_assigner": is_assigner,
"loop_content": loop_content,
"second_level_loop_content": second_level_loop_content,
"third_level_loop_content": third_level_loop_content,
"is_param": is_param,
"in_sum": in_sum,
"in_product": in_product,
Expand Down
42 changes: 42 additions & 0 deletions bears/tests/codeclone_detection/ClangCountingConditionsTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,27 @@ def test_in_condition(self):
"c": [1],
"d": [1]})

self.check_counting_condition(
"in_condition",
(111, "levels(int, int, int)"),
{"first": [3],
"second": [0],
"third": [0]})

self.check_counting_condition(
"in_second_level_condition",
(111, "levels(int, int, int)"),
{"first": [0],
"second": [1],
"third": [0]})

self.check_counting_condition(
"in_third_level_condition",
(111, "levels(int, int, int)"),
{"first": [0],
"second": [0],
"third": [2]})

def test_is_assignee(self):
self.check_counting_condition(
"is_assignee",
Expand All @@ -103,6 +124,27 @@ def test_loop_content(self):
{"a": [0],
"b": [6]})

self.check_counting_condition(
"loop_content",
(111, "levels(int, int, int)"),
{"first": [1],
"second": [0],
"third": [0]})

self.check_counting_condition(
"second_level_loop_content",
(111, "levels(int, int, int)"),
{"first": [0],
"second": [1],
"third": [0]})

self.check_counting_condition(
"third_level_loop_content",
(111, "levels(int, int, int)"),
{"first": [0],
"second": [0],
"third": [2]})

def test_is_param(self):
self.check_counting_condition(
"is_param",
Expand Down
34 changes: 34 additions & 0 deletions bears/tests/codeclone_detection/conditions_samples.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,37 @@ int arithmetics(int a, int b) {
a &= a;
a |= a;
}

int levels(int first, int second, int third) {
if (0)
first = 1;
else
if (2) {
second = 1;
if (3) {
third = 2;
} else
third = 3;
}

if (1) {
first = 1;
} else {
first = 2
}

while (1)
while (1) {
for(;;)
third = 3;

second = 2;
while (2) {
third = 5;
}
}

for (;;) {
first = 1;
}
}

0 comments on commit 1e276f5

Please sign in to comment.