|
@@ -418,6 +418,231 @@ _CPP_HEADERS = frozenset([
|
|
|
'cwctype',
|
|
|
])
|
|
|
|
|
|
+# List of functions from <type_traits>. See [meta.type.synop]
|
|
|
+_TYPE_TRAITS = [
|
|
|
+ # 23.15.3, helper class
|
|
|
+ 'integral_constant',
|
|
|
+ # 23.15.4.1, primary type categories
|
|
|
+ 'is_void',
|
|
|
+ 'is_null_pointer',
|
|
|
+ 'is_integral',
|
|
|
+ 'is_floating_point',
|
|
|
+ 'is_array',
|
|
|
+ 'is_pointer',
|
|
|
+ 'is_lvalue_reference',
|
|
|
+ 'is_rvalue_reference',
|
|
|
+ 'is_member_object_pointer',
|
|
|
+ 'is_member_function_pointer',
|
|
|
+ 'is_enum',
|
|
|
+ 'is_union',
|
|
|
+ 'is_class',
|
|
|
+ 'is_function',
|
|
|
+ # 23.15.4.2, composite type categories
|
|
|
+ 'is_reference',
|
|
|
+ 'is_arithmetic',
|
|
|
+ 'is_fundamental',
|
|
|
+ 'is_object',
|
|
|
+ 'is_scalar',
|
|
|
+ 'is_compound',
|
|
|
+ 'is_member_pointer',
|
|
|
+ # 23.15.4.3, type properties
|
|
|
+ 'is_const',
|
|
|
+ 'is_volatile',
|
|
|
+ 'is_trivial',
|
|
|
+ 'is_trivially_copyable',
|
|
|
+ 'is_standard_layout',
|
|
|
+ 'is_pod',
|
|
|
+ 'is_empty',
|
|
|
+ 'is_polymorphic',
|
|
|
+ 'is_abstract',
|
|
|
+ 'is_final',
|
|
|
+ 'is_aggregate',
|
|
|
+ 'is_signed',
|
|
|
+ 'is_unsigned',
|
|
|
+ 'is_constructible',
|
|
|
+ 'is_default_constructible',
|
|
|
+ 'is_copy_constructible',
|
|
|
+ 'is_move_constructible',
|
|
|
+ 'is_assignable',
|
|
|
+ 'is_copy_assignable',
|
|
|
+ 'is_move_assignable',
|
|
|
+ 'is_swappable_with',
|
|
|
+ 'is_swappable',
|
|
|
+ 'is_destructible',
|
|
|
+ 'is_trivially_constructible',
|
|
|
+ 'is_trivially_default_constructible',
|
|
|
+ 'is_trivially_copy_constructible',
|
|
|
+ 'is_trivially_move_constructible',
|
|
|
+ 'is_trivially_assignable',
|
|
|
+ 'is_trivially_copy_assignable',
|
|
|
+ 'is_trivially_move_assignable',
|
|
|
+ 'is_trivially_destructible',
|
|
|
+ 'is_nothrow_constructible',
|
|
|
+ 'is_nothrow_default_constructible',
|
|
|
+ 'is_nothrow_copy_constructible',
|
|
|
+ 'is_nothrow_move_constructible',
|
|
|
+ 'is_nothrow_assignable',
|
|
|
+ 'is_nothrow_copy_assignable',
|
|
|
+ 'is_nothrow_move_assignable',
|
|
|
+ 'is_nothrow_swappable_with',
|
|
|
+ 'is_nothrow_swappable',
|
|
|
+ 'is_nothrow_destructible',
|
|
|
+ 'has_virtual_destructor',
|
|
|
+ 'has_unique_object_representations',
|
|
|
+ # 23.15.5, type property queries
|
|
|
+ 'alignment_of',
|
|
|
+ 'rank',
|
|
|
+ 'extent',
|
|
|
+ # 23.15.6, type relations
|
|
|
+ 'is_same',
|
|
|
+ 'is_base_of',
|
|
|
+ 'is_convertible',
|
|
|
+ 'is_invocable',
|
|
|
+ 'is_invocable_r',
|
|
|
+ 'is_nothrow_invocable',
|
|
|
+ 'is_nothrow_invocable_r',
|
|
|
+ # 23.15.7.1, const-volatile modifications
|
|
|
+ 'remove_const',
|
|
|
+ 'remove_volatile',
|
|
|
+ 'remove_cv',
|
|
|
+ 'add_const',
|
|
|
+ 'add_volatile',
|
|
|
+ 'add_cv',
|
|
|
+ 'remove_const_t',
|
|
|
+ 'remove_volatile_t',
|
|
|
+ 'remove_cv_t',
|
|
|
+ 'add_const_t',
|
|
|
+ 'add_volatile_t',
|
|
|
+ 'add_cv_t',
|
|
|
+ # 23.15.7.2, reference modifications
|
|
|
+ 'remove_reference',
|
|
|
+ 'add_lvalue_reference',
|
|
|
+ 'add_rvalue_reference',
|
|
|
+ 'remove_reference_t',
|
|
|
+ 'add_lvalue_reference_t',
|
|
|
+ 'add_rvalue_reference_t',
|
|
|
+ # 23.15.7.3, sign modifications
|
|
|
+ 'make_signed',
|
|
|
+ 'make_unsigned',
|
|
|
+ 'make_signed_t',
|
|
|
+ 'make_unsigned_t',
|
|
|
+ # 23.15.7.4, array modifications
|
|
|
+ 'remove_extent',
|
|
|
+ 'remove_all_extents',
|
|
|
+ 'remove_extent_t',
|
|
|
+ 'remove_all_extents_t',
|
|
|
+ # 23.15.7.5, pointer modifications
|
|
|
+ 'remove_pointer',
|
|
|
+ 'add_pointer',
|
|
|
+ 'remove_pointer_t',
|
|
|
+ 'add_pointer_t',
|
|
|
+ # 23.15.7.6, other transformations
|
|
|
+ 'aligned_storage',
|
|
|
+ 'aligned_union',
|
|
|
+ 'decay',
|
|
|
+ 'enable_if',
|
|
|
+ 'conditional',
|
|
|
+ 'common_type',
|
|
|
+ 'underlying_type',
|
|
|
+ 'invoke_result',
|
|
|
+ 'aligned_storage_t',
|
|
|
+ 'aligned_union_t',
|
|
|
+ 'decay_t',
|
|
|
+ 'enable_if_t',
|
|
|
+ 'conditional_t',
|
|
|
+ 'common_type_t',
|
|
|
+ 'underlying_type_t',
|
|
|
+ 'invoke_result_t',
|
|
|
+ 'void_t',
|
|
|
+ # 23.15.8, logical operator traits
|
|
|
+ 'conjunction',
|
|
|
+ 'disjunction',
|
|
|
+ 'negation',
|
|
|
+ # 23.15.4.1, primary type categories
|
|
|
+ 'is_void_v',
|
|
|
+ 'is_null_pointer_v',
|
|
|
+ 'is_integral_v',
|
|
|
+ 'is_floating_point_v',
|
|
|
+ 'is_array_v',
|
|
|
+ 'is_pointer_v',
|
|
|
+ 'is_lvalue_reference_v',
|
|
|
+ 'is_rvalue_reference_v',
|
|
|
+ 'is_member_object_pointer_v',
|
|
|
+ 'is_member_function_pointer_v',
|
|
|
+ 'is_enum_v',
|
|
|
+ 'is_union_v',
|
|
|
+ 'is_class_v',
|
|
|
+ 'is_function_v',
|
|
|
+ # 23.15.4.2, composite type categories
|
|
|
+ 'is_reference_v',
|
|
|
+ 'is_arithmetic_v',
|
|
|
+ 'is_fundamental_v',
|
|
|
+ 'is_object_v',
|
|
|
+ 'is_scalar_v',
|
|
|
+ 'is_compound_v',
|
|
|
+ 'is_member_pointer_v',
|
|
|
+ # 23.15.4.3, type properties
|
|
|
+ 'is_const_v',
|
|
|
+ 'is_volatile_v',
|
|
|
+ 'is_trivial_v',
|
|
|
+ 'is_trivially_copyable_v',
|
|
|
+ 'is_standard_layout_v',
|
|
|
+ 'is_pod_v',
|
|
|
+ 'is_empty_v',
|
|
|
+ 'is_polymorphic_v',
|
|
|
+ 'is_abstract_v',
|
|
|
+ 'is_final_v',
|
|
|
+ 'is_aggregate_v',
|
|
|
+ 'is_signed_v',
|
|
|
+ 'is_unsigned_v',
|
|
|
+ 'is_constructible_v',
|
|
|
+ 'is_default_constructible_v',
|
|
|
+ 'is_copy_constructible_v',
|
|
|
+ 'is_move_constructible_v',
|
|
|
+ 'is_assignable_v',
|
|
|
+ 'is_copy_assignable_v',
|
|
|
+ 'is_move_assignable_v',
|
|
|
+ 'is_swappable_with_v',
|
|
|
+ 'is_swappable_v',
|
|
|
+ 'is_destructible_v',
|
|
|
+ 'is_trivially_constructible_v',
|
|
|
+ 'is_trivially_default_constructible_v',
|
|
|
+ 'is_trivially_copy_constructible_v',
|
|
|
+ 'is_trivially_move_constructible_v',
|
|
|
+ 'is_trivially_assignable_v',
|
|
|
+ 'is_trivially_copy_assignable_v',
|
|
|
+ 'is_trivially_move_assignable_v',
|
|
|
+ 'is_trivially_destructible_v',
|
|
|
+ 'is_nothrow_constructible_v',
|
|
|
+ 'is_nothrow_default_constructible_v',
|
|
|
+ 'is_nothrow_copy_constructible_v',
|
|
|
+ 'is_nothrow_move_constructible_v',
|
|
|
+ 'is_nothrow_assignable_v',
|
|
|
+ 'is_nothrow_copy_assignable_v',
|
|
|
+ 'is_nothrow_move_assignable_v',
|
|
|
+ 'is_nothrow_swappable_with_v',
|
|
|
+ 'is_nothrow_swappable_v',
|
|
|
+ 'is_nothrow_destructible_v',
|
|
|
+ 'has_virtual_destructor_v',
|
|
|
+ 'has_unique_object_representations_v',
|
|
|
+ # 23.15.5, type property queries
|
|
|
+ 'alignment_of_v',
|
|
|
+ 'rank_v',
|
|
|
+ 'extent_v',
|
|
|
+ 'is_same_v',
|
|
|
+ 'is_base_of_v',
|
|
|
+ 'is_convertible_v',
|
|
|
+ 'is_invocable_v',
|
|
|
+ 'is_invocable_r_v',
|
|
|
+ 'is_nothrow_invocable_v',
|
|
|
+ 'is_nothrow_invocable_r_v',
|
|
|
+ # 23.15.8, logical operator traits
|
|
|
+ 'conjunction_v',
|
|
|
+ 'disjunction_v',
|
|
|
+ 'negation_v',
|
|
|
+]
|
|
|
+_TYPE_TRAITS_RE = re.compile(r'\b::(?:' + ('|'.join(_TYPE_TRAITS)) + ')<')
|
|
|
+
|
|
|
# Type names
|
|
|
_TYPES = re.compile(
|
|
|
r'^(?:'
|
|
@@ -3832,10 +4057,10 @@ def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
|
|
|
line = clean_lines.elided[linenum]
|
|
|
|
|
|
# Block bodies should not be followed by a semicolon. Due to C++11
|
|
|
- # brace initialization, there are more places where semicolons are
|
|
|
- # required than not, so we use an allowlist approach to check these
|
|
|
- # rather than a blocklist. These are the places where "};" should
|
|
|
- # be replaced by just "}":
|
|
|
+ # brace initialization and C++20 concepts, there are more places
|
|
|
+ # where semicolons are required than not. Places that are
|
|
|
+ # recognized as true positives are listed below.
|
|
|
+ #
|
|
|
# 1. Some flavor of block following closing parenthesis:
|
|
|
# for (;;) {};
|
|
|
# while (...) {};
|
|
@@ -3903,6 +4128,10 @@ def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
|
|
|
# - Lambdas
|
|
|
# - alignas specifier with anonymous structs
|
|
|
# - decltype
|
|
|
+ # - Type casts with parentheses, e.g.: var = (Type){value};
|
|
|
+ # - Return type casts with parentheses, e.g.: return (Type){value};
|
|
|
+ # - Function pointers with initializer list, e.g.: int (*f)(){};
|
|
|
+ # - Requires expression, e.g. C = requires(){};
|
|
|
closing_brace_pos = match.group(1).rfind(')')
|
|
|
opening_parenthesis = ReverseCloseExpression(
|
|
|
clean_lines, linenum, closing_brace_pos)
|
|
@@ -3910,15 +4139,17 @@ def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
|
|
|
line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
|
|
|
macro = Search(r'\b([A-Z_][A-Z0-9_]*)\s*$', line_prefix)
|
|
|
func = Match(r'^(.*\])\s*$', line_prefix)
|
|
|
- if ((macro and
|
|
|
- macro.group(1) not in (
|
|
|
- 'TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST',
|
|
|
- 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED',
|
|
|
- 'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or
|
|
|
- (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or
|
|
|
- Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or
|
|
|
- Search(r'\bdecltype$', line_prefix) or
|
|
|
- Search(r'\s+=\s*$', line_prefix)):
|
|
|
+ if ((macro and macro.group(1) not in
|
|
|
+ ('TEST', 'TEST_F', 'MATCHER', 'MATCHER_P', 'TYPED_TEST',
|
|
|
+ 'EXCLUSIVE_LOCKS_REQUIRED', 'SHARED_LOCKS_REQUIRED',
|
|
|
+ 'LOCKS_EXCLUDED', 'INTERFACE_DEF'))
|
|
|
+ or (func and not Search(r'\boperator\s*\[\s*\]', func.group(1)))
|
|
|
+ or Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix)
|
|
|
+ or Search(r'\b(decltype|requires)$', line_prefix)
|
|
|
+ or Search(r'(?:\s+=|\breturn)\s*$', line_prefix)
|
|
|
+ or (Match(r'^\s*$', line_prefix) and Search(
|
|
|
+ r'(?:\s+=|\breturn)\s*$', clean_lines.elided[linenum - 1]))
|
|
|
+ or Search(r'\(\*\w+\)$', line_prefix)):
|
|
|
match = None
|
|
|
if (match and
|
|
|
opening_parenthesis[1] > 1 and
|
|
@@ -5285,14 +5516,15 @@ def ExpectingFunctionArgs(clean_lines, linenum):
|
|
|
of function types.
|
|
|
"""
|
|
|
line = clean_lines.elided[linenum]
|
|
|
- return (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or
|
|
|
- (linenum >= 2 and
|
|
|
- (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]) or
|
|
|
- Search(r'\bstd::m?function\s*\<\s*$',
|
|
|
- clean_lines.elided[linenum - 1]))))
|
|
|
+ return (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line)
|
|
|
+ or _TYPE_TRAITS_RE.search(line)
|
|
|
+ or (linenum >= 2 and
|
|
|
+ (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])
|
|
|
+ or Search(r'\b(::function|base::FunctionRef)\s*\<\s*$',
|
|
|
+ clean_lines.elided[linenum - 1]))))
|
|
|
|
|
|
|
|
|
_HEADERS_CONTAINING_TEMPLATES = (
|