def error_check_comparison_recursive_target(self, token, left_token, right_token): ''' COMPARISON OPERATORS - MUST BE THE SAME ON BOTH SIDES input: token cppcheck token object left_token, right_token returns: nothing, with possible side effect of adding errors ''' if self.debug_verbose and self.cps_units_checker: self.cps_units_checker.handle_debug_verbose(inspect.stack()[0][3]) if token.isComparisonOp: if left_token and left_token.units and right_token and right_token.units: # BOTH HAVE UNITS if left_token.units != right_token.units: # CREATE VARIABLE ERROR OBJECT new_error = UnitError(self.cps_units_checker) new_error.var_name = '' # NO VAR NAME SINCE ITS A COMPARISON OPERATORS new_error.ERROR_TYPE = UnitErrorTypes.COMPARISON_INCOMPATIBLE_UNITS # LINENR new_error.linenr = token.linenr new_error.token_left = left_token new_error.token_right = right_token new_error.token = token # new_error.is_unit_propagation_based_on_constants = inner_dict['is_unit_propagation_based_on_constants'] # new_error.is_unit_propagation_based_on_unknown_variable = inner_dict['is_unit_propagation_based_on_unknown_variable'] # if inner_dict['is_unit_propagation_based_on_constants'] or inner_dict['is_unit_propagation_based_on_unknown_variable']: # new_error.is_warning = True # GET LINE FROM ORIGINAL FILE IF IT EXISTS if self.source_file_exists: new_error.source_code_at_first_assignment = self.source_file_lines[ new_error.linenr_at_first_unit_assignment - 1].strip() new_error.source_code_when_multiple_units_happened = self.source_file_lines[ new_error.linenr_of_multiple_unit_assignment - 1].strip() # COLLECT ERROR self.all_errors.append(new_error)
def error_check_function_args_consistent(self, cppcheck_configuration_unit): ''' VERIFIES UNIT CONSISTENCY OF FUNCTIONS AT EVERY CALL POINT input: cppcheck configuration unit from dump returns: none side_effects: might add UnitError objects to self.all_errors list ''' # FOR EACH FUNCTION for f in cppcheck_configuration_unit.functions: # FOR EACH ARG IN A FUNCTION for arg_list_of_call_points in f.arg_units: # FOR EACH TIME THE FUNCTION WAS CALLED error_found = False new_error = UnitError(self.cps_units_checker) first_call_point_with_units = None for call_point in arg_list_of_call_points: # FIND SOME CALL POINT WITH UNITS if not first_call_point_with_units: if call_point['units']: if self.debug: print 'CALL POINT UNITS:' + str( call_point['units']) first_call_point_with_units = call_point continue # CHECK UNITS OF FIRST CALL POINT AGAINST ALL OTHERS #HAS UNITS and UNITS ARE DIFFERENT THAN SOME OTHER CALL POINT if call_point['units'] and ( call_point['units'] != first_call_point_with_units['units']): error_found = True # FOUND DIFFERENT UNITS AT TWO DIFFERENT CALL POINTS new_error.var_name = f.name new_error.ERROR_TYPE = UnitErrorTypes.FUNCTION_CALLED_WITH_DIFFERENT_UNIT_ARGUMENTS new_error.token = first_call_point_with_units['token'] new_error.f = first_call_point_with_units['token'] # FIRST ASSIGNMENT new_error.set_primary_line_number( first_call_point_with_units['linenr']) new_error.linenr_at_first_unit_assignment = first_call_point_with_units[ 'linenr'] new_error.units_at_first_assignment = first_call_point_with_units[ 'units'] # SECOND (DIFFERENT) ASSIGNMENT new_error.linenr_of_multiple_unit_assignment = call_point[ 'linenr'] new_error.units_when_multiple_happened = call_point[ 'units'] break # FOR LOOP if error_found: # GET LINE FROM ORIGINAL FILE IF IT EXISTS if self.source_file_exists: # todo: resolve relative link to different file and load source if new_error.linenr_at_first_unit_assignment <= len( self.source_file_lines): if new_error.linenr_of_multiple_unit_assignment <= len( self.source_file_lines): new_error.source_code_at_first_assignment = self.source_file_lines[ new_error.linenr_at_first_unit_assignment - 1].strip() new_error.source_code_when_multiple_units_happened = self.source_file_lines[ new_error. linenr_of_multiple_unit_assignment - 1].strip() # COLLECT ERROR self.all_errors.append(new_error)
def error_check_multiple_units(self, cppcheck_configuration_unit): ''' MULTIPLE_UNIT_TYPE ASSIGNMENT ERROR CHECKING IMPLEMENTATION input: cppcheck configuration unit from dump returns: none side_effects: might add UnitError objects to self.all_errors list ''' # SANITY DEFENSE if not cppcheck_configuration_unit: return vars_with_multi_units_dict = OrderedDict( ) # {scope_id: [list_of_vars_with_multi_units]} # SEARCH SCOPE OBJECTS FOR CHECK FOR ERRORS for s in cppcheck_configuration_unit.scopes: #if self.debug: #print '- '*42 if s.var_ordered_dict: # FOR EACH VARIABLE for var_name, dict_of_assignments in s.var_ordered_dict.iteritems( ): # have_found_multi_units_for_this_var = False # FOR EACH LIST OF UNITS ASSIGNED TO A VARIABLE for linenr, inner_dict in dict_of_assignments.iteritems(): units_list = inner_dict['units'] # TEST FOR MULTIPLE UNITS ASSIGNED if len(units_list) > 1: # CREATE VARIABLE ERROR/WARNING OBJECT new_error = UnitError(self.cps_units_checker) new_error.var_name = var_name new_error.ERROR_TYPE = UnitErrorTypes.VARIABLE_MULTIPLE_UNITS # LINENR OF FIRST ASSIGNMENT new_error.linenr_at_first_unit_assignment = s.var_ordered_dict[ var_name].keys()[ 0] # WORKS BECAUSE ORDERED DICT # UNITS AT FIRST ASSIGNMENT new_error.units_at_first_assignment = s.var_ordered_dict[ var_name].values()[0][ 'units'] # WORKS BECAUSE ORDERED DICT new_error.all_units_assigned_to_var_as_dict = s.var_ordered_dict[ var_name] new_error.token = s.var_ordered_dict[ var_name].values()[0][ 'token'] # WORKS BECAUSE ORDERED DICT new_error.is_unit_propagation_based_on_constants = inner_dict[ 'is_unit_propagation_based_on_constants'] new_error.is_unit_propagation_based_on_unknown_variable = inner_dict[ 'is_unit_propagation_based_on_unknown_variable'] if inner_dict[ 'is_unit_propagation_based_on_constants'] or inner_dict[ 'is_unit_propagation_based_on_unknown_variable']: new_error.is_warning = True for linenr, units_list in s.var_ordered_dict[ var_name].iteritems(): if 'units' in units_list: if len(units_list['units']) > 1: # LINENR AT ERROR ASSIGNMENT new_error.set_primary_line_number( linenr) # UNITS AT ERROR ASSIGNMENT new_error.units_when_multiple_happened = units_list break # REPORT THE FIRST # GET LINE FROM ORIGINAL FILE IF IT EXISTS if self.source_file_exists: if new_error.linenr_at_first_unit_assignment <= len( self.source_file_lines): if new_error.linenr_of_multiple_unit_assignment <= len( self.source_file_lines): new_error.source_code_at_first_assignment = self.source_file_lines[ new_error. linenr_at_first_unit_assignment - 1].strip() new_error.source_code_when_multiple_units_happened = self.source_file_lines[ new_error. linenr_of_multiple_unit_assignment - 1].strip() # WAS VARIABLE ASSIGNED MULTIPLE UNITS if new_error.linenr_at_first_unit_assignment != new_error.linenr_of_multiple_unit_assignment: new_error.was_assigned_mutiple_units = True # COLLECT ERROR / WARNING self.all_errors.append(new_error) # MULTIPLE UNITS DETECTED # have_found_multi_units_for_this_var = True break
def error_check_unit_smell(self, cppcheck_configuration_unit): ''' UNIT_SMELL ERROR CHECKING IMPLEMENTATION input: cppcheck configuration unit from dump returns: none side_effects: might add UnitError objects to self.all_errors list ''' # SANITY DEFENSE if not cppcheck_configuration_unit: return # SEARCH SCOPE OBJECTS FOR ERRORS for s in cppcheck_configuration_unit.scopes: if s.var_ordered_dict: # FOR EACH VARIABLE for var_name, dict_of_assignments in s.var_ordered_dict.iteritems( ): # FOR EACH LIST OF UNITS ASSIGNED TO A VARIABLE for linenr, inner_dict in dict_of_assignments.iteritems(): units_list = inner_dict['units'] # TEST FOR MULTIPLE UNITS ASSIGNED for u in units_list: # WRITES ALL UNITS OUT TO A FILE FOR EMPIRICALLY LOOKING FOR UNUSUAL UNITS # with open('2016_07_20_1026_list_of_all_units.txt', 'a') as f: # f.write(str(u) + "\n") if u not in self.symbol_helper.list_of_vetted_units: # CREATE VARIABLE ERROR/WARNING OBJECT new_error = UnitError(self.cps_units_checker) new_error.var_name = var_name new_error.ERROR_TYPE = UnitErrorTypes.UNIT_SMELL # LINENR OF FIRST ASSIGNMENT new_error.linenr_at_first_unit_assignment = s.var_ordered_dict[ var_name].keys()[ 0] # WORKS BECAUSE ORDERED DICT new_error.set_primary_line_number( s.var_ordered_dict[var_name].keys() [0]) # WORKS BECAUSE ORDERED DICT # UNITS AT FIRST ASSIGNMENT new_error.units_at_first_assignment = s.var_ordered_dict[ var_name].values()[0][ 'units'] # WORKS BECAUSE ORDERED DICT new_error.all_units_assigned_to_var_as_dict = s.var_ordered_dict[ var_name] new_error.token = s.var_ordered_dict[ var_name].values()[0][ 'token'] # WORKS BECAUSE ORDERED DICT new_error.is_unit_propagation_based_on_constants = inner_dict[ 'is_unit_propagation_based_on_constants'] new_error.is_unit_propagation_based_on_unknown_variable = inner_dict[ 'is_unit_propagation_based_on_unknown_variable'] if inner_dict[ 'is_unit_propagation_based_on_constants'] or inner_dict[ 'is_unit_propagation_based_on_unknown_variable']: new_error.is_warning = True # GET LINE FROM ORIGINAL FILE IF IT EXISTS if self.source_file_exists: if new_error.linenr_at_first_unit_assignment <= len( self.source_file_lines): if new_error.linenr_of_multiple_unit_assignment <= len( self.source_file_lines): new_error.source_code_at_first_assignment = self.source_file_lines[ new_error. linenr_at_first_unit_assignment - 1].strip() new_error.source_code_when_multiple_units_happened = self.source_file_lines[ new_error. linenr_of_multiple_unit_assignment - 1].strip() # COLLECT ERROR / WARNING self.all_errors.append(new_error) break
def error_check_logical_recursive_target(self, token, left_token, right_token): if self.debug_verbose: self.cps_units_checker.handle_debug_verbose(inspect.stack()[0][3]) if token.isOp and token.str in [ '&&', '||', '!' ]: # NOT << and >> since theses are used in PRINT OUTS if (left_token and left_token.units) or (right_token and right_token.units): # CREATE VARIABLE ERROR OBJECT new_error = UnitError(self.cps_units_checker) new_error.var_name = '' # NO VAR NAME SINCE ITS A COMPARISON OPERATORS new_error.ERROR_TYPE = UnitErrorTypes.LOGICAL_OPERATOR_USED_ON_UNITS # LINENR new_error.set_primary_line_number(token.linenr) new_error.token_left = left_token new_error.token_right = right_token new_error.token = token # GET LINE FROM ORIGINAL FILE IF IT EXISTS if self.source_file_exists: new_error.source_code_at_first_assignment = self.source_file_lines[ new_error.linenr_at_first_unit_assignment - 1].strip() new_error.source_code_when_multiple_units_happened = self.source_file_lines[ new_error.linenr_of_multiple_unit_assignment - 1].strip() # COLLECT ERROR self.all_errors.append(new_error)
def error_check_addition_of_incompatible_units_recursive_target( self, token, left_token, right_token): ''' ERROR CHECK ADDITIONAL OF INCOMPATIBLE UNITS - RESURSIVE TARGET input: token cppcheck token object left_token, right_token returns: nothing, with possible side effect of adding errors ''' if token.str in ['+', '-', '+=', '-=']: # if token.isArithmeticalOp and token.str in ['+', '-', '+=', '-=']: if self.debug: print 'found + or - or += or -=' # THIS IS ADDITION OR SUBTRACTION # assert(token.astOperand1 and token.astOperand2) if token.astOperand1 and token.astOperand2: # WEIRD IF THIS WERE FALSE if token.astOperand1.units and token.astOperand2.units: # BOTH CHILDREN HAVE UNITS if token.astOperand1.units != token.astOperand2.units: if not self.have_found_addition_error_on_this_line: # UNIT MISMATCH ON ADDITION : REPORT ERROR new_error = UnitError(self.cps_units_checker) new_error.var_name = '' # NO VAR NAME SINCE ITS A COMPARISON OPERATORS new_error.ERROR_TYPE = UnitErrorTypes.ADDITION_OF_INCOMPATIBLE_UNITS new_error.is_unit_propagation_based_on_constants = token.is_unit_propagation_based_on_constants new_error.is_unit_propagation_based_on_unknown_variable = token.is_unit_propagation_based_on_unknown_variable if token.is_unit_propagation_based_on_constants or token.is_unit_propagation_based_on_unknown_variable: new_error.is_warning = True # LINENR new_error.linenr = token.linenr new_error.token_left = left_token new_error.token_right = right_token new_error.token = token # GET LINE FROM ORIGINAL FILE IF IT EXISTS if self.source_file_exists: new_error.source_code_at_first_assignment = self.source_file_lines[ new_error.linenr_at_first_unit_assignment - 1].strip() new_error.source_code_when_multiple_units_happened = self.source_file_lines[ new_error. linenr_of_multiple_unit_assignment - 1].strip() # COLLECT ERROR self.all_errors.append(new_error) self.have_found_addition_error_on_this_line = True
def error_check_multiple_units(self): ''' MULTIPLE_UNIT_TYPE ASSIGNMENT ERROR CHECKING IMPLEMENTATION returns: none side_effects: might add UnitError objects to self.all_errors list ''' for root_token, token, name, units, isKnownRhs in con.multi_unit_variables: new_error = UnitError() new_error.ERROR_TYPE = UnitErrorTypes.VARIABLE_MULTIPLE_UNITS new_error.linenr = token.linenr new_error.token = root_token new_error.token_left = token new_error.var_name = name new_error.units_when_multiple_happened = units new_error.dont_check_for_warning = isKnownRhs new_error.is_unit_propagation_based_on_constants = \ root_token.is_unit_propagation_based_on_constants new_error.is_unit_propagation_based_on_unknown_variable = \ root_token.is_unit_propagation_based_on_unknown_variable if new_error.is_unit_propagation_based_on_constants or \ new_error.is_unit_propagation_based_on_unknown_variable: new_error.is_warning = True if (not new_error.dont_check_for_warning) and ( new_error.linenr in self.marked_as_low_confidence): new_error.is_warning = True self.all_errors.append(new_error)
def error_check_logical_recursive(self, token, left_token, right_token): if token.isOp and token.str in ['&&', '||', '!']: if (left_token and left_token.units) or (right_token and right_token.units): # UNIT ERROR ON LOGICAL OPERATION new_error = UnitError() new_error.ERROR_TYPE = UnitErrorTypes.LOGICAL_OPERATOR_USED_ON_UNITS # LINENR new_error.linenr = token.linenr new_error.token_left = left_token new_error.token_right = right_token new_error.token = token new_error.var_name = self.get_var_name(left_token) new_error.is_unit_propagation_based_on_constants = token.is_unit_propagation_based_on_constants new_error.is_unit_propagation_based_on_unknown_variable = \ token.is_unit_propagation_based_on_unknown_variable if token.is_unit_propagation_based_on_constants or \ token.is_unit_propagation_based_on_unknown_variable: new_error.is_warning = True # GET LINE FROM ORIGINAL FILE IF IT EXISTS if self.source_file_exists: pass # COLLECT ERROR self.all_errors.append(new_error)
def error_check_comparison_recursive(self, token, left_token, right_token): ''' COMPARISON OPERATORS - MUST BE THE SAME ON BOTH SIDES input: token (cppcheck token object), left_token, right_token returns: nothing, with possible side effect of adding errors ''' if token.isComparisonOp: if left_token and left_token.units and right_token and right_token.units: # BOTH HAVE UNITS if left_token.units != right_token.units: # UNIT MISMATCH ON COMPARISON new_error = UnitError() new_error.ERROR_TYPE = UnitErrorTypes.COMPARISON_INCOMPATIBLE_UNITS # LINENR new_error.linenr = token.linenr new_error.token_left = left_token new_error.token_right = right_token new_error.token = token new_error.var_name = self.get_var_name(left_token) new_error.is_unit_propagation_based_on_constants = \ left_token.is_unit_propagation_based_on_constants or \ right_token.is_unit_propagation_based_on_constants new_error.is_unit_propagation_based_on_unknown_variable = \ left_token.is_unit_propagation_based_on_unknown_variable or \ right_token.is_unit_propagation_based_on_unknown_variable if new_error.is_unit_propagation_based_on_constants or \ new_error.is_unit_propagation_based_on_unknown_variable: new_error.is_warning = True if (not new_error.is_warning): new_error.is_warning = self.check_if_error_with_low_confidence( token, left_token, right_token) # GET LINE FROM ORIGINAL FILE IF IT EXISTS if self.source_file_exists: pass # COLLECT ERROR self.all_errors.append(new_error)
def error_check_addition_of_incompatible_units_recursive( self, token, left_token, right_token): ''' ERROR CHECK ADDITION OF INCOMPATIBLE UNITS - RESURSIVE TARGET input: token (cppcheck token object), left_token, right_token returns: nothing, with possible side effect of adding errors ''' if token.str in ['+', '-', '+=', '-=']: # THIS IS ADDITION OR SUBTRACTION if token.astOperand1 and token.astOperand2: if token.astOperand1.units and token.astOperand2.units: # BOTH CHILDREN HAVE UNITS if token.astOperand1.units != token.astOperand2.units: if not self.have_found_addition_error_on_this_line: # UNIT MISMATCH ON ADDITION new_error = UnitError() new_error.ERROR_TYPE = UnitErrorTypes.ADDITION_OF_INCOMPATIBLE_UNITS new_error.is_unit_propagation_based_on_constants = token.is_unit_propagation_based_on_constants new_error.is_unit_propagation_based_on_unknown_variable = \ token.is_unit_propagation_based_on_unknown_variable if token.is_unit_propagation_based_on_constants or \ token.is_unit_propagation_based_on_unknown_variable: new_error.is_warning = True if (not new_error.is_warning): new_error.is_warning = self.check_if_error_with_low_confidence( token, left_token, right_token) if new_error.is_warning: self.marked_as_low_confidence.append( token.linenr) # LINENR new_error.linenr = token.linenr new_error.token_left = left_token new_error.token_right = right_token new_error.token = token new_error.var_name = self.get_var_name(left_token) # GET LINE FROM ORIGINAL FILE IF IT EXISTS if self.source_file_exists: pass # COLLECT ERROR self.all_errors.append(new_error) self.have_found_addition_error_on_this_line = True