223223 'readability/nul' ,
224224 'readability/strings' ,
225225 'readability/todo' ,
226+ 'readability/throw' ,
226227 'readability/utf8' ,
227228 'readability/function_comment'
228229 'runtime/arrays' ,
@@ -1929,7 +1930,7 @@ def GetHeaderGuardCPPVariable(filename):
19291930
19301931 fileinfo = FileInfo (filename )
19311932 file_path_from_root = fileinfo .RepositoryName ()
1932- file_path_from_root = 'CPROVER_2LS_ ' + file_path_from_root [4 :]
1933+ file_path_from_root = 'CPROVER_ ' + file_path_from_root [4 :]
19331934 if _root :
19341935 suffix = os .sep
19351936 # On Windows using directory separator will leave us with
@@ -3125,7 +3126,7 @@ def CheckForFunctionCommentHeaders(filename, raw_lines, error):
31253126 # Look for declaration function_name( but allowing for *, & being attached to the function name
31263127 # but not being considered part of it
31273128 regexp = r'\w(\w|::|\s|\*|\&)* (\*|\&)?(?P<fnc_name>(\w(\w|::)*))\(' #
3128- operator_regexp = r'\w(\w|::|\s|\*|\&)* (\*|\&)?(?P<fnc_name>(| operator\(.*\)|operator.*))\('
3129+ operator_regexp = r'\w(\w|::|\s|\*|\&)* (\*|\&)?(?P<fnc_name>(\w(\w|::)*::)?( operator\(.*\)|operator.*))\('
31293130 operator_match = Match (operator_regexp , line )
31303131 match_result = Match (regexp , line )
31313132 function_name = ""
@@ -3152,9 +3153,9 @@ def CheckForFunctionCommentHeaders(filename, raw_lines, error):
31523153 body_found = False
31533154 break
31543155
3155- # body found, i.e. not a declaration
3156- if body_found :
3157- CheckForFunctionCommentHeader (filename , raw_lines , linenum , function_name , error )
3156+ # body found, i.e. not a declaration
3157+ if body_found :
3158+ CheckForFunctionCommentHeader (filename , raw_lines , linenum , function_name , error )
31583159 linenum += 1
31593160
31603161def CheckForFunctionCommentHeader (filename , raw_lines , linenum , function_name , error ):
@@ -4686,9 +4687,79 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
46864687 if linenum > 0 :
46874688 while prev_initial_spaces < len (prev ) and prev [prev_initial_spaces ] == ' ' :
46884689 prev_initial_spaces += 1
4689- if Search (r'\([^\)]*,$' , elided_line ) or Search (r'\(\[^\)]*, $' , elided_line ):
4690- error (filename , linenum , 'whitespace/indent' , 4 ,
4691- 'If parameters or arguments require a line break, each parameter should be put on its own line.' )
4690+ # here a regex isn't sufficent we need a stack to match brackets
4691+ # because even an open bracket and a , at the end might just be function call
4692+ # as a parameter.
4693+ # Instead the rule we try to apply here is:
4694+ # - if we find an opening bracket, we find the matching closing bracket
4695+ # - if the bracket is on a different line we require all of the parameters to be on a separate line
4696+ # - if there is another opening bracket Skip to the closing bracket as will be checked in a subsequent line check
4697+ # - ignore the line if it is a for/if etc since rules are different
4698+
4699+ # Look for an opening bracket that doesn't have a semi-colon on the same line
4700+ bracket_search = Search (r'[\w_]+\s*(?P<bracket>\()[^;]*$' , elided_line )
4701+
4702+ # Exclude the check if any of these keywords are present
4703+ # They could trip us up as they have different formatting rules to functions
4704+ keyword_search = Search (r'\b(if|for|while|catch|switch)\b' , elided_line )
4705+
4706+ if bracket_search and not keyword_search :
4707+ open_bracket_pos = bracket_search .start ('bracket' )
4708+ close_line , close_linenum , close_pos = CloseExpression (clean_lines , linenum , open_bracket_pos )
4709+ if close_pos != - 1 :
4710+ # If the closing line is different from the opening line we need to
4711+ # verify that each of the parameters are on separate lines
4712+ if close_linenum != linenum :
4713+ # The first line needs to have no parameters on it
4714+ if (Search (r'\(+[^\(]+' , elided_line )):
4715+ error (filename , linenum , 'whitespace/indent' , 4 ,
4716+ 'If parameters or arguments require a line break, each parameter should be put on its own line.' )
4717+
4718+ # For each line afer we need to verify it consists of exactly one parameter
4719+ # Except if we find an opening bracket - in this case we ignore everything until the closing
4720+ # bracket (any errors within these brackets will be picked up when we check this line)
4721+ start_linenum = linenum + 1
4722+ while (start_linenum < close_linenum ):
4723+ arg_line = clean_lines .elided [start_linenum ]
4724+ nested_bracket_search = Search ('\(' , arg_line )
4725+ if nested_bracket_search :
4726+ nested_open_bracket_pos = nested_bracket_search .start ()
4727+ # Just because we are calling a nested function doesn't mean
4728+ # we allow multiple parameters on the line
4729+ if (Search (',' , arg_line [:nested_open_bracket_pos ])):
4730+ error (filename , start_linenum , 'whitespace/indent' , 4 ,
4731+ 'If parameters or arguments require a line break, each parameter should be put on its own line.' )
4732+
4733+ nested_close_line , nested_close_linenum , _ = CloseExpression (clean_lines , start_linenum , nested_open_bracket_pos )
4734+
4735+ # If anything other closing statements or commas appear there is another parameter after the nested call
4736+ if not Search (r'\)(,|\)|;)*' , nested_close_line ):
4737+ error (filename , start_linenum , 'whitespace/indent' , 4 ,
4738+ 'If parameters or arguments require a line break, each parameter should be put on its own line.' )
4739+ # Skip to the end of the bracket
4740+ start_linenum = nested_close_linenum
4741+ else :
4742+ if (not Match ('^\s*[^,]+,$' , arg_line )):
4743+ error (filename , start_linenum , 'whitespace/indent' , 4 ,
4744+ 'If parameters or arguments require a line break, each parameter should be put on its own line.' )
4745+
4746+ start_linenum += 1
4747+ # For the final line we also need to check one parameter on it
4748+ # e.g. we require bracket on same line as last parameter
4749+ # foo(
4750+ # x);
4751+ if not Search (r'^\s*[^,]+\)' , close_line ):
4752+ # If this is true, the we failed because we just had the close bracket
4753+ if Search (r'[^,]*\)' , close_line ):
4754+ error (filename , close_linenum , 'whitespace/indent' , 4 ,
4755+ 'If parameters or arguments require a line break, the closing bracket should be on the same line as the final parameter' )
4756+ else :
4757+ # In this case the problem is we had a bracket
4758+ # i.e. more than one parameter on the last line
4759+ error (filename , close_linenum , 'whitespace/indent' , 4 ,
4760+ 'If parameters or arguments require a line break, each parameter should be put on its own line.' )
4761+
4762+
46924763 if (Search (r'\([^\)]*$' , elided_prev ) and initial_spaces - 2 != prev_initial_spaces ) and not Search (r'for|while|if|;' , elided_prev ):
46934764 error (filename , linenum , 'whitespace/indent' , 4 ,
46944765 'Indent of wrapped parenthesized expression or parameter or argument list should be 2' )
@@ -5162,6 +5233,20 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
51625233 ' for more information.' )
51635234
51645235
5236+
5237+ # Check that throw statements don't include the optional bracket
5238+ # We use raw lines as we want to check the contents of the string too
5239+ # We require the error message starts with a lower case character
5240+ raw_line = clean_lines .raw_lines [linenum ]
5241+ if (Match (r'^\s*throw' , raw_line )):
5242+ if (Match (r'^\s*throw\s*\(' , raw_line )):
5243+ error (filename , linenum , 'readability/throw' , 4 ,
5244+ 'Do not include brackets when throwing an error' )
5245+ if (Match (r'\s*throw\s*\(?"[A-Z]' , raw_line )):
5246+ error (filename , linenum , 'readability/throw' , 4 ,
5247+ 'First character of throw error message should be lower case' )
5248+
5249+
51655250def CheckGlobalStatic (filename , clean_lines , linenum , error ):
51665251 """Check for unsafe global or static objects.
51675252
0 commit comments