mirror of
https://github.com/neovim/neovim.git
synced 2025-09-08 04:18:18 +00:00
remove C++ only stuff from CheckLanguage
Do we want VLAs?
This commit is contained in:

committed by
Thiago de Arruda

parent
4bfb03c630
commit
ccc3375d99
151
clint.py
151
clint.py
@@ -3768,112 +3768,11 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
|
|||||||
|
|
||||||
# TODO(unknown): figure out if they're using default arguments in fn proto.
|
# TODO(unknown): figure out if they're using default arguments in fn proto.
|
||||||
|
|
||||||
# Check to see if they're using an conversion function cast.
|
# Check if people are using the verboten C basic types.
|
||||||
# I just try to capture the most common basic types, though there are more.
|
match = Search(r'\b(short|long(?! +double)|long long)\b', line)
|
||||||
# Parameterless conversion functions, such as bool(), are allowed as they are
|
|
||||||
# probably a member operator declaration or default constructor.
|
|
||||||
match = Search(
|
|
||||||
r'(\bnew\s+)?\b' # Grab 'new' operator, if it's there
|
|
||||||
r'(int|float|double|bool|char|int32|uint32|int64|uint64)'
|
|
||||||
r'(\([^)].*)', line)
|
|
||||||
if match:
|
if match:
|
||||||
matched_new = match.group(1)
|
error(filename, linenum, 'runtime/int', 4,
|
||||||
matched_type = match.group(2)
|
'Use int16_t/int64_t/etc, rather than the C type %s' % match.group(1))
|
||||||
matched_funcptr = match.group(3)
|
|
||||||
|
|
||||||
# gMock methods are defined using some variant of MOCK_METHODx(name, type)
|
|
||||||
# where type may be float(), int(string), etc. Without context they are
|
|
||||||
# virtually indistinguishable from int(x) casts. Likewise, gMock's
|
|
||||||
# MockCallback takes a template parameter of the form return_type(arg_type),
|
|
||||||
# which looks much like the cast we're trying to detect.
|
|
||||||
#
|
|
||||||
# std::function<> wrapper has a similar problem.
|
|
||||||
#
|
|
||||||
# Return types for function pointers also look like casts if they
|
|
||||||
# don't have an extra space.
|
|
||||||
if (matched_new is None and # If new operator, then this isn't a cast
|
|
||||||
not (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or
|
|
||||||
Search(r'\bMockCallback<.*>', line) or
|
|
||||||
Search(r'\bstd::function<.*>', line)) and
|
|
||||||
not (matched_funcptr and
|
|
||||||
Match(r'\((?:[^() ]+::\s*\*\s*)?[^() ]+\)\s*\(',
|
|
||||||
matched_funcptr))):
|
|
||||||
# Try a bit harder to catch gmock lines: the only place where
|
|
||||||
# something looks like an old-style cast is where we declare the
|
|
||||||
# return type of the mocked method, and the only time when we
|
|
||||||
# are missing context is if MOCK_METHOD was split across
|
|
||||||
# multiple lines. The missing MOCK_METHOD is usually one or two
|
|
||||||
# lines back, so scan back one or two lines.
|
|
||||||
#
|
|
||||||
# It's not possible for gmock macros to appear in the first 2
|
|
||||||
# lines, since the class head + section name takes up 2 lines.
|
|
||||||
if (linenum < 2 or
|
|
||||||
not (Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\((?:\S+,)?\s*$',
|
|
||||||
clean_lines.elided[linenum - 1]) or
|
|
||||||
Match(r'^\s*MOCK_(?:CONST_)?METHOD\d+(?:_T)?\(\s*$',
|
|
||||||
clean_lines.elided[linenum - 2]))):
|
|
||||||
error(filename, linenum, 'readability/casting', 4,
|
|
||||||
'Using deprecated casting style. '
|
|
||||||
'Use static_cast<%s>(...) instead' %
|
|
||||||
matched_type)
|
|
||||||
|
|
||||||
# In addition, we look for people taking the address of a cast. This
|
|
||||||
# is dangerous -- casts can assign to temporaries, so the pointer doesn't
|
|
||||||
# point where you think.
|
|
||||||
match = Search(
|
|
||||||
r'(?:&\(([^)]+)\)[\w(])|'
|
|
||||||
r'(?:&(static|dynamic|down|reinterpret)_cast\b)', line)
|
|
||||||
if match and match.group(1) != '*':
|
|
||||||
error(filename, linenum, 'runtime/casting', 4,
|
|
||||||
('Are you taking an address of a cast? '
|
|
||||||
'This is dangerous: could be a temp var. '
|
|
||||||
'Take the address before doing the cast, rather than after'))
|
|
||||||
|
|
||||||
# Check for people declaring static/global STL strings at the top level.
|
|
||||||
# This is dangerous because the C++ language does not guarantee that
|
|
||||||
# globals with constructors are initialized before the first access.
|
|
||||||
match = Match(
|
|
||||||
r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)',
|
|
||||||
line)
|
|
||||||
# Make sure it's not a function.
|
|
||||||
# Function template specialization looks like: "string foo<Type>(...".
|
|
||||||
# Class template definitions look like: "string Foo<Type>::Method(...".
|
|
||||||
#
|
|
||||||
# Also ignore things that look like operators. These are matched separately
|
|
||||||
# because operator names cross non-word boundaries. If we change the pattern
|
|
||||||
# above, we would decrease the accuracy of matching identifiers.
|
|
||||||
if (match and
|
|
||||||
not Search(r'\boperator\W', line) and
|
|
||||||
not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', match.group(3))):
|
|
||||||
error(filename, linenum, 'runtime/string', 4,
|
|
||||||
'For a static/global string constant, use a C style string instead: '
|
|
||||||
'"%schar %s[]".' %
|
|
||||||
(match.group(1), match.group(2)))
|
|
||||||
|
|
||||||
if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line):
|
|
||||||
error(filename, linenum, 'runtime/init', 4,
|
|
||||||
'You seem to be initializing a member variable with itself.')
|
|
||||||
|
|
||||||
if file_extension == 'h':
|
|
||||||
# TODO(unknown): check that 1-arg constructors are explicit.
|
|
||||||
# How to tell it's a constructor?
|
|
||||||
# (handled in CheckForNonStandardConstructs for now)
|
|
||||||
# TODO(unknown): check that classes have DISALLOW_EVIL_CONSTRUCTORS
|
|
||||||
# (level 1 error)
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Check if people are using the verboten C basic types. The only exception
|
|
||||||
# we regularly allow is "unsigned short port" for port.
|
|
||||||
if not (file_extension == 'c' or file_extension == 'h'):
|
|
||||||
if Search(r'\bshort port\b', line):
|
|
||||||
if not Search(r'\bunsigned short port\b', line):
|
|
||||||
error(filename, linenum, 'runtime/int', 4,
|
|
||||||
'Use "unsigned short" for ports, not "short"')
|
|
||||||
else:
|
|
||||||
match = Search(r'\b(short|long(?! +double)|long long)\b', line)
|
|
||||||
if match:
|
|
||||||
error(filename, linenum, 'runtime/int', 4,
|
|
||||||
'Use int16/int64/etc, rather than the C type %s' % match.group(1))
|
|
||||||
|
|
||||||
# When snprintf is used, the second argument shouldn't be a literal.
|
# When snprintf is used, the second argument shouldn't be a literal.
|
||||||
match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
|
match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
|
||||||
@@ -3892,16 +3791,6 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
|
|||||||
error(filename, linenum, 'runtime/printf', 4,
|
error(filename, linenum, 'runtime/printf', 4,
|
||||||
'Almost always, snprintf is better than %s' % match.group(1))
|
'Almost always, snprintf is better than %s' % match.group(1))
|
||||||
|
|
||||||
# Check if some verboten operator overloading is going on
|
|
||||||
# TODO(unknown): catch out-of-line unary operator&:
|
|
||||||
# class X {};
|
|
||||||
# int operator&(const X& x) { return 42; } // unary operator&
|
|
||||||
# The trick is it's hard to tell apart from binary operator&:
|
|
||||||
# class Y { int operator&(const Y& x) { return 23; } }; // binary operator&
|
|
||||||
if Search(r'\boperator\s*&\s*\(\s*\)', line):
|
|
||||||
error(filename, linenum, 'runtime/operator', 4,
|
|
||||||
'Unary operator& is dangerous. Do not use it.')
|
|
||||||
|
|
||||||
# Check for suspicious usage of "if" like
|
# Check for suspicious usage of "if" like
|
||||||
# } if (a == b) {
|
# } if (a == b) {
|
||||||
if Search(r'\}\s*if\s*\(', line):
|
if Search(r'\}\s*if\s*\(', line):
|
||||||
@@ -3938,6 +3827,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
|
|||||||
'Use using-declarations instead.')
|
'Use using-declarations instead.')
|
||||||
|
|
||||||
# Detect variable-length arrays.
|
# Detect variable-length arrays.
|
||||||
|
# XXX: Do we want this in Neovim?
|
||||||
match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
|
match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
|
||||||
if (match and match.group(2) != 'return' and match.group(2) != 'delete' and
|
if (match and match.group(2) != 'return' and match.group(2) != 'delete' and
|
||||||
match.group(3).find(']') == -1):
|
match.group(3).find(']') == -1):
|
||||||
@@ -3976,37 +3866,6 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
|
|||||||
'Do not use variable-length arrays. Use an appropriately named '
|
'Do not use variable-length arrays. Use an appropriately named '
|
||||||
"('k' followed by CamelCase) compile-time constant for the size.")
|
"('k' followed by CamelCase) compile-time constant for the size.")
|
||||||
|
|
||||||
# If DISALLOW_EVIL_CONSTRUCTORS, DISALLOW_COPY_AND_ASSIGN, or
|
|
||||||
# DISALLOW_IMPLICIT_CONSTRUCTORS is present, then it should be the last thing
|
|
||||||
# in the class declaration.
|
|
||||||
match = Match(
|
|
||||||
(r'\s*'
|
|
||||||
r'(DISALLOW_(EVIL_CONSTRUCTORS|COPY_AND_ASSIGN|IMPLICIT_CONSTRUCTORS))'
|
|
||||||
r'\(.*\);$'),
|
|
||||||
line)
|
|
||||||
if match and linenum + 1 < clean_lines.NumLines():
|
|
||||||
next_line = clean_lines.elided[linenum + 1]
|
|
||||||
# We allow some, but not all, declarations of variables to be present
|
|
||||||
# in the statement that defines the class. The [\w\*,\s]* fragment of
|
|
||||||
# the regular expression below allows users to declare instances of
|
|
||||||
# the class or pointers to instances, but not less common types such
|
|
||||||
# as function pointers or arrays. It's a tradeoff between allowing
|
|
||||||
# reasonable code and avoiding trying to parse more C++ using regexps.
|
|
||||||
if not Search(r'^\s*}[\w\*,\s]*;', next_line):
|
|
||||||
error(filename, linenum, 'readability/constructors', 3,
|
|
||||||
match.group(1) + ' should be the last thing in the class')
|
|
||||||
|
|
||||||
# Check for use of unnamed namespaces in header files. Registration
|
|
||||||
# macros are typically OK, so we allow use of "namespace {" on lines
|
|
||||||
# that end with backslashes.
|
|
||||||
if (file_extension == 'h'
|
|
||||||
and Search(r'\bnamespace\s*{', line)
|
|
||||||
and line[-1] != '\\'):
|
|
||||||
error(filename, linenum, 'build/namespaces', 4,
|
|
||||||
'Do not use unnamed namespaces in header files. See '
|
|
||||||
'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
|
|
||||||
' for more information.')
|
|
||||||
|
|
||||||
|
|
||||||
def ProcessLine(filename, file_extension, clean_lines, line,
|
def ProcessLine(filename, file_extension, clean_lines, line,
|
||||||
include_state, function_state, nesting_state, error,
|
include_state, function_state, nesting_state, error,
|
||||||
|
Reference in New Issue
Block a user