diff --git a/cpplint.py b/cpplint.py index 8c56fec..2b259e4 100755 --- a/cpplint.py +++ b/cpplint.py @@ -920,6 +920,10 @@ # Match string that indicates we're working on a Linux Kernel file. _SEARCH_KERNEL_FILE = re.compile(r"\b(?:LINT_KERNEL_FILE)") +# Operator sequences beginning with '<' (used to strip before counting angle brackets). +# Longer sequences must come first so '<<=' is not partially matched as '<<'. +_LANGLE_OPS_RE = re.compile(r"<<=|<=|<<") + # Commands for sed to fix the problem _SED_FIXUPS = { "Remove spaces around =": r"s/ = /=/", @@ -3972,15 +3976,27 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum, nesting_state, constructor_args = explicit_constructor_match.group(2).split(",") # collapse arguments so that commas in template parameter lists and function - # argument parameter lists don't split arguments in two + # argument parameter lists don't split arguments in two. + # Strip operator sequences that begin with '<' before counting angle + # brackets, to avoid confusing operators with unmatched template + # brackets. Longer sequences must come first so that '<<=' is not + # partially matched as '<<' leaving a stray '='. + # Note: '>>' and '>=' are intentionally left alone because extra '>' + # characters do not trigger the joining loop (condition is + # count('<') > count('>')), and stripping '>>' would break nested + # template types such as vector>. i = 0 while i < len(constructor_args): constructor_arg = constructor_args[i] - while constructor_arg.count("<") > constructor_arg.count(">") or constructor_arg.count( + cleaned_arg = _LANGLE_OPS_RE.sub("", constructor_arg) + while cleaned_arg.count("<") > cleaned_arg.count(">") or cleaned_arg.count( "(" - ) > constructor_arg.count(")"): + ) > cleaned_arg.count(")"): + if i + 1 >= len(constructor_args): + break constructor_arg += "," + constructor_args[i + 1] del constructor_args[i + 1] + cleaned_arg = _LANGLE_OPS_RE.sub("", constructor_arg) constructor_args[i] = constructor_arg i += 1 diff --git a/cpplint_unittest.py b/cpplint_unittest.py index c7737f4..774f3d6 100755 --- a/cpplint_unittest.py +++ b/cpplint_unittest.py @@ -1823,6 +1823,32 @@ class Foo { """ class Foo { explicit Foo(int f, int g); + };""", + "", + ) + # No crash or warning for constructors with '<'-containing operators + # in default parameter values (regression test for issue #223). + # left shift << + self.TestMultiLineLint( + """ + class A { + A(int b, int c, int a = 1 << 1) {} + };""", + "", + ) + # compound left-shift-assign <<= + self.TestMultiLineLint( + """ + class A { + A(int b, int c, int a = (x <<= 1)) {} + };""", + "", + ) + # less-or-equal <= + self.TestMultiLineLint( + """ + class A { + A(int b, int c, int a = b <= c ? 1 : 0) {} };""", "", )