Skip to content

Commit e56fb21

Browse files
authored
Merge pull request #401 from thk123/bug/linter-inline-structs
More linter fixes
2 parents 5c0cfb0 + 548195f commit e56fb21

File tree

11 files changed

+227
-43
lines changed

11 files changed

+227
-43
lines changed

CODING_STANDARD

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ Whitespaces:
1717
Exceptions: Spaces around &&, || and <<
1818
- Space after comma (parameter lists, argument lists, ...)
1919
- Space after colon inside 'for'
20+
- For pointers and references, the */& should be attached to the variable name
21+
as oppposed to the tyep. E.g. for a pointer to an int the syntax would be:
22+
`int *x;`
2023
- No whitespaces at end of line
2124
- No whitespaces in blank lines
2225
- Put argument lists on next line (and ident 2 spaces) if too long

regression/cpp-linter/class-decl-space/main.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,36 @@ Author: Thomas Kiley, thomas@diffblue.com
88

99
class temp_classt : public base_classt
1010
{}
11+
12+
class another_class : public base_classt
13+
{}
14+
15+
class more_class:public base_classt
16+
{}
17+
18+
class nonderived
19+
{}
20+
21+
class nonderivedt
22+
{}
23+
24+
#define ID_property_class dstring(23, 0)
25+
26+
int foo(class define);
27+
28+
int foo(class definet);
29+
30+
template <class U>
31+
void bar(U t);
32+
33+
template<class U>
34+
void bar(U t);
35+
36+
template < class U >
37+
void bar(U t);
38+
39+
class testt
40+
{
41+
template<class U>
42+
void bar(U t);
43+
}

regression/cpp-linter/class-decl-space/test.desc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@ CORE
22
main.cpp
33

44
^main\.cpp:9: There shouldn.t be a space between class identifier and : \[readability/identifiers\] \[4\]$
5-
^Total errors found: 1$
5+
^main\.cpp:12: There shouldn.t be a space between class identifier and : \[readability/identifiers\] \[4\]$
6+
^main\.cpp:12: Class or struct identifier should end with t \[readability/identifiers\] \[4\]$
7+
^main\.cpp:15: Class or struct identifier should end with t \[readability/identifiers\] \[4\]$
8+
^main\.cpp:18: Class or struct identifier should end with t \[readability/identifiers\] \[4\]$
9+
^main\.cpp:26: Class or struct identifier should end with t \[readability/identifiers\] \[4\]$
10+
^main\.cpp:30: Remove spaces around < \[whitespace/operators\] \[4\]$
11+
^main\.cpp:36: Remove spaces around < \[whitespace/operators\] \[4\]$
12+
^Total errors found: 8$
613
^SIGNAL=0$
714
--

regression/cpp-linter/operator-spacing2/main.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@ static void fun()
2424

2525
int x = 1<<4;
2626

27+
// Ideally this should produce an error, see operator-spacing3
2728
status()<<"Adding CPROVER library ("<<eom;
2829

2930
// Ideally this should produce an error, see operator-spacing3
3031
int x = 1 << 4;
32+
33+
int y = a<<b;
3134
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
main.cpp
33

4-
^main\.cpp:27: Missing spaces around << \[whitespace/operators\] \[3\]
5-
^Total errors found: 1$
4+
^Total errors found: 0$
5+
^EXIT=0$
66
^SIGNAL=0$
77
--

regression/cpp-linter/operator-spacing3/main.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,6 @@ static void fun()
2727
status()<<"Adding CPROVER library ("<<eom;
2828

2929
int x = 1 << 4;
30+
31+
result=((result<<1)^it->hash())-result;
3032
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*******************************************************************\
2+
3+
Module: Lint Examples
4+
5+
Author: Thomas Kiley, thomas@diffblue.com
6+
7+
\*******************************************************************/
8+
9+
/*******************************************************************\
10+
11+
Function: fun
12+
13+
Inputs:
14+
15+
Outputs:
16+
17+
Purpose:
18+
19+
\*******************************************************************/
20+
21+
static void fun()
22+
{
23+
bool *x=nullptr; // Valid
24+
bool* x=nullptr; // Invalid
25+
26+
int &x=nullptr; // Valid
27+
int& x=nullptr; // Invalid
28+
29+
int y=at*bt; // Valid
30+
31+
// Probably valid - could be a pointer to type yt or a
32+
// variable called yt multilied by z. Would have to know
33+
// it is a function call rather than a function declaration
34+
foo(
35+
x,
36+
yt*z);
37+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.cpp
3+
4+
^main\.cpp:24: Pointer type name must have \* attached to the type name \[whitespace/operators\] \[4\]$
5+
^main\.cpp:27: Reference type name must have & attached to the type name \[whitespace/operators\] \[4\]$
6+
^Total errors found: 2$
7+
^SIGNAL=0$
8+
--
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*******************************************************************\
2+
3+
Module: Lint Examples
4+
5+
Author: Thomas Kiley, thomas@diffblue.com
6+
7+
\*******************************************************************/
8+
9+
/*******************************************************************\
10+
11+
Function: fun
12+
13+
Inputs:
14+
15+
Outputs:
16+
17+
Purpose:
18+
19+
\*******************************************************************/
20+
21+
static void fun()
22+
{
23+
bar(struct mystructt& struct_var);
24+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.cpp
3+
4+
5+
^Total errors found: 0$
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--

scripts/cpplint.py

Lines changed: 99 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,34 +1547,28 @@ def IsTemplateArgumentList_DB(clean_lines, linenum, pos):
15471547

15481548
return True
15491549

1550-
def OpenExpression(clean_lines, linenum, pos):
1551-
"""If input points to ) or } or ] or >, finds the position that opens it.
1552-
1553-
If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the
1554-
linenum/pos that correspond to the closing of the expression.
1555-
1556-
Essentially a mirror of what CloseExpression does
1550+
def ForceOpenExpression(clean_lines, linenum, pos, bracket):
1551+
"""Find an opening bracket matching the specified closing bracket
15571552
1558-
TODO(tkiley): could probably be merged with CloseExpression
1553+
Search starting at the position for a matching closing bracket of the
1554+
same type as bracket.
15591555
15601556
Args:
15611557
clean_lines: A CleansedLines instance containing the file.
15621558
linenum: The number of the line to check.
15631559
pos: A position on the line.
1560+
bracket: The style of bracket to match
15641561
15651562
Returns:
15661563
A tuple (line, linenum, pos) pointer *to* the closing brace, or
15671564
(line, len(lines), -1) if we never find a close. Note we ignore
15681565
strings and comments when matching; and the line we return is the
15691566
'cleansed' line at linenum.
15701567
"""
1571-
15721568
line = clean_lines.elided[linenum]
1573-
if (line[pos] not in ')}]>'):
1574-
return (line, clean_lines.NumLines(), -1)
15751569

15761570
# Check first line
1577-
(end_pos, stack) = FindStartOfExpressionInLine(line, pos , [])
1571+
(end_pos, stack) = FindStartOfExpressionInLine(line, pos , [bracket])
15781572
if end_pos > -1:
15791573
return (line, linenum, end_pos)
15801574

@@ -1589,6 +1583,37 @@ def OpenExpression(clean_lines, linenum, pos):
15891583
# Did not find end of expression before end of file, give up
15901584
return (line, clean_lines.NumLines(), -1)
15911585

1586+
def OpenExpression(clean_lines, linenum, pos):
1587+
"""If input points to ) or } or ] or >, finds the position that opens it.
1588+
1589+
If lines[linenum][pos] points to a ')' or '}' or ']' or '>', finds the
1590+
linenum/pos that correspond to the closing of the expression.
1591+
1592+
Essentially a mirror of what CloseExpression does
1593+
1594+
Calls ForceOpenExpression with the bracket type pointed at
1595+
1596+
TODO(tkiley): could probably be merged with CloseExpression
1597+
1598+
Args:
1599+
clean_lines: A CleansedLines instance containing the file.
1600+
linenum: The number of the line to check.
1601+
pos: A position on the line.
1602+
1603+
Returns:
1604+
A tuple (line, linenum, pos) pointer *to* the closing brace, or
1605+
(line, len(lines), -1) if we never find a close. Note we ignore
1606+
strings and comments when matching; and the line we return is the
1607+
'cleansed' line at linenum.
1608+
"""
1609+
1610+
line = clean_lines.elided[linenum]
1611+
if (line[pos] not in ')}]>'):
1612+
return (line, clean_lines.NumLines(), -1)
1613+
else:
1614+
return ForceOpenExpression(clean_lines, linenum, pos-1, line[pos])
1615+
1616+
15921617
def FindEndOfExpressionInLine(line, startpos, stack):
15931618
"""Find the position just after the end of current parenthesized expression.
15941619
@@ -3525,15 +3550,12 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
35253550
# Otherwise not. Note we only check for non-spaces on *both* sides;
35263551
# sometimes people put non-spaces on one side when aligning ='s among
35273552
# many lines (not that this is behavior that I approve of...)
3528-
match1 = Search(r'[^\s]+[\s](=|>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=|>|<|\^|\+[^\+]|\/)', line)
3529-
match2 = Search(r'(=|>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=|>|<|!|\^|\+|\/)[\s]', line)
3530-
operator_pos, op_end = match1.span(1) if match1 else (-1, -1)
3531-
operator_pos2, op_end2 = match2.span(1) if match2 else (-1, -1)
3553+
left_hand_space_match = Search(r'[^\s]+[\s](=|>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=|>|<|\^|\+[^\+]|\/)', line)
3554+
right_hand_space_match = Search(r'(=|>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=|>|<|!|\^|\+|\/)[\s]', line)
3555+
operator_pos, op_end = left_hand_space_match.span(1) if left_hand_space_match else (-1, -1)
3556+
operator_pos2, op_end2 = right_hand_space_match.span(1) if right_hand_space_match else (-1, -1)
35323557

3533-
if match2 and match2.group(1) == '>':
3534-
res = IsTemplateArgumentList_DB(clean_lines, linenum, operator_pos2)
3535-
3536-
if (match1 and
3558+
if (left_hand_space_match and
35373559
not Search(r'<<', line) and # We ignore the left shift operator since might be a stream and then formatting rules go out of the window
35383560
not Search(r'char \*', line) and # I don't know why this exception exists?
35393561
not Search(r'\#include', line) and # I suppose file names could contains operators??
@@ -3545,12 +3567,12 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
35453567
# and not Search(r'operator=', line)):
35463568
error(filename, linenum, 'whitespace/operators', 4,
35473569
# 'Missing spaces around =')
3548-
'Remove spaces around %s' % match1.group(1))
3549-
elif (match2 and
3570+
'Remove spaces around %s' % left_hand_space_match.group(1))
3571+
elif (right_hand_space_match and
35503572
not Search(r'<<', line) and
35513573
not IsTemplateArgumentList_DB(clean_lines, linenum, operator_pos2)):
35523574
error(filename, linenum, 'whitespace/operators', 4,
3553-
'Remove spaces around %s' % match2.group(0))
3575+
'Remove spaces around %s' % right_hand_space_match.group(0))
35543576

35553577
# these would cause too many false alarms if we checked for one-sided spaces only
35563578
match = Search(r'\s(-|\*)(\s|$)', line)
@@ -3562,10 +3584,16 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
35623584
if Search(r'(struct|class)\s[\w_]*\s+:', line):
35633585
error(filename, linenum, 'readability/identifiers', 4, 'There shouldn\'t be a space between class identifier and :')
35643586

3565-
#check type definitions end with t
3566-
if Search(r'(struct|class)\s[\w_]*[^t^;^:^\s](;$|\s|:|$)', line) and not Search(r'^template <', line) and not Search(r'^template<', line):
3567-
error(filename, linenum, 'readability/identifiers', 4,
3568-
'Class or struct identifier should end with t')
3587+
#check type definitions end with t
3588+
# Look for class declarations and check the final character is a t
3589+
# Exclude classes in side template argument lists (why?)
3590+
class_name_match = Search(r'\b(struct|class)\s(?P<class_name>[\w_]+)', line)
3591+
if class_name_match:
3592+
class_name = class_name_match.group('class_name')
3593+
if not class_name.endswith('t'):
3594+
if not Search(r'\btemplate <', line) and not Search(r'\btemplate<', line):
3595+
error(filename, linenum, 'readability/identifiers', 4,
3596+
'Class or struct identifier should end with t')
35693597

35703598
if Search(r'(struct|class)\s[\w_]*_t(;$|\s|:|$)', line):
35713599
error(filename, linenum, 'readability/identifiers', 4,
@@ -3630,17 +3658,6 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
36303658
# error(filename, linenum, 'whitespace/operators', 3,
36313659
# 'Missing spaces around >')
36323660

3633-
# We allow no-spaces around << when used like this: 10<<20, but
3634-
# not otherwise (particularly, not when used as streams)
3635-
#
3636-
# We also allow operators following an opening parenthesis, since
3637-
# those tend to be macros that deal with operators.
3638-
match = Search(r'(operator|[^\s(<])(?:L|UL|LL|ULL|l|ul|ll|ull)?<<([^\s,=<])', line)
3639-
if (match and not (match.group(1).isdigit() and match.group(2).isdigit()) and
3640-
not (match.group(1) == 'operator' and match.group(2) == ';')):
3641-
error(filename, linenum, 'whitespace/operators', 3,
3642-
'Missing spaces around <<')
3643-
36443661
# We allow no-spaces around >> for almost anything. This is because
36453662
# C++11 allows ">>" to close nested templates, which accounts for
36463663
# most cases when ">>" is not followed by a space.
@@ -3664,6 +3681,48 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
36643681
error(filename, linenum, 'whitespace/operators', 4,
36653682
'Extra space for operator %s' % match.group(1))
36663683

3684+
def CheckPointerReferenceSpacing(filename, clean_lines, linenum, error):
3685+
"""Checks the */& are attached to variable names rather than types
3686+
3687+
A pointer or reference type should have the */& attached to the variable
3688+
name rather than the type. I.e. a pointer to an int should be:
3689+
3690+
int *var_name;
3691+
3692+
Args:
3693+
filename: The name of the current file.
3694+
clean_lines: A CleansedLines instance containing the file.
3695+
linenum: The number of the line to check.
3696+
error: The function to call with any errors found.
3697+
"""
3698+
line = clean_lines.elided[linenum]
3699+
3700+
# Find types by looking for word_names that are at the start of the line
3701+
# If there are followed by a * or & (after an optional ' const')
3702+
# then they appear to be a reference/pointer type with it attached to
3703+
# the type rather than the variable
3704+
wrong_type_match = Search(r'^\s*([\w_])+( const)?(?P<type>[&\*])\s*\w', line)
3705+
3706+
if wrong_type_match:
3707+
# This still could be a false positive, we must
3708+
# check that we are not inside brackets as then could be just be
3709+
# operators (multiply and logical AND)
3710+
pos = wrong_type_match.start(1)
3711+
_, _, opening_pos = ForceOpenExpression(clean_lines, linenum, pos, ')')
3712+
3713+
# If we don't find a matching close brace then we aren't in brackets
3714+
# so can assume this is a type with the * or & attached to it
3715+
if opening_pos == -1:
3716+
op_type = wrong_type_match.group('type')
3717+
op_word = ""
3718+
if op_type == '*':
3719+
op_word = 'Pointer'
3720+
else:
3721+
op_word = 'Reference'
3722+
error(filename, linenum, 'whitespace/operators', 4,
3723+
op_word + ' type name must have ' + op_type + ' attached to the type name')
3724+
3725+
36673726

36683727
def CheckParenthesisSpacing(filename, clean_lines, linenum, error):
36693728
"""Checks for horizontal spacing around parentheses.
@@ -4679,6 +4738,7 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
46794738
CheckAccess(filename, clean_lines, linenum, nesting_state, error)
46804739
CheckSpacing(filename, clean_lines, linenum, nesting_state, error)
46814740
CheckOperatorSpacing(filename, clean_lines, linenum, error)
4741+
CheckPointerReferenceSpacing(filename, clean_lines, linenum, error)
46824742
CheckParenthesisSpacing(filename, clean_lines, linenum, error)
46834743
CheckCommaSpacing(filename, clean_lines, linenum, error)
46844744
CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error)
@@ -5088,8 +5148,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
50885148
break
50895149
if not is_const:
50905150
error(filename, linenum, 'runtime/arrays', 1,
5091-
'Do not use variable-length arrays. Use an appropriately named '
5092-
"('k' followed by CamelCase) compile-time constant for the size.")
5151+
'Do not use variable-length arrays.')
50935152

50945153
# Check for use of unnamed namespaces in header files. Registration
50955154
# macros are typically OK, so we allow use of "namespace {" on lines

0 commit comments

Comments
 (0)