parameters: (filename, clean_lines, linenum, file_extension,
                    include_state, nesting_state, error)
docstring: Checks rules from the 'C++ language rules' section of cppguide.html.
  
    Some of these rules are hard to test (function overloading, using
    uint32 inappropriately), but we do the best we can.
  
    Args:
      filename: The name of the current file.
      clean_lines: A CleansedLines instance containing the file.
      linenum: The number of the line to check.
      file_extension: The extension (without the dot) of the filename.
      include_state: An _IncludeState instance in which the headers are inserted.
      nesting_state: A _NestingState instance which maintains information about
                     the current stack of nested blocks being parsed.
      error: The function to call with any errors found.
docstring_summary: Checks rules from the 'C++ language rules' section of cppguide.html.
docstring_tokens: Checks rules from the C ++ language rules section of cppguide . html .
function: def CheckLanguage(filename, clean_lines, linenum, file_extension,
                    include_state, nesting_state, error):
    """Checks rules from the 'C++ language rules' section of cppguide.html.
  
    Some of these rules are hard to test (function overloading, using
    uint32 inappropriately), but we do the best we can.
  
    Args:
      filename: The name of the current file.
      clean_lines: A CleansedLines instance containing the file.
      linenum: The number of the line to check.
      file_extension: The extension (without the dot) of the filename.
      include_state: An _IncludeState instance in which the headers are inserted.
      nesting_state: A _NestingState instance which maintains information about
                     the current stack of nested blocks being parsed.
      error: The function to call with any errors found.
    """
    # If the line is empty or consists of entirely a comment, no need to
    # check it.
    line = clean_lines.elided[linenum]
    if not line:
      return
  
    match = _RE_PATTERN_INCLUDE.search(line)
    if match:
      CheckIncludeLine(filename, clean_lines, linenum, include_state, error)
      return
  
    # Reset include state across preprocessor directives.  This is meant
    # to silence warnings for conditional includes.
    if Match(r'^\s*#\s*(?:ifdef|elif|else|endif)\b', line):
      include_state.ResetSection()
  
    # Make Windows paths like Unix.
    fullname = os.path.abspath(filename).replace('\\', '/')
  
    # TODO(unknown): figure out if they're using default arguments in fn proto.
  
    # Check to see if they're using an conversion function cast.
    # I just try to capture the most common basic types, though there are more.
    # 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:
      matched_new = match.group(1)
      matched_type = match.group(2)
      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)
  
    CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
                    'static_cast',
                    r'\((int|float|double|bool|char|u?int(16|32|64))\)', error)
  
    # This doesn't catch all cases. Consider (const char * const)"hello".
    #
    # (char *) "foo" should always be a const_cast (reinterpret_cast won't
    # compile).
    if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
                       'const_cast', r'\((char\s?\*+\s?)\)\s*"', error):
      pass
    else:
      # Check pointer casts for other than string constants
      CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum],
                      'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error)
  
    # 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'))
  
    # Create an extended_line, which is the concatenation of the current and
    # next lines, for more effective checking of code that may span more than one
    # line.
    if linenum + 1 < clean_lines.NumLines():
      extended_line = line + clean_lines.elided[linenum + 1]
    else:
      extended_line = line
  
    # 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 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.
    match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
    if match and match.group(2) != '0':
      # If 2nd arg is zero, snprintf is used to calculate size.
      error(filename, linenum, 'runtime/printf', 3,
            'If you can, use sizeof(%s) instead of %s as the 2nd arg '
            'to snprintf.' % (match.group(1), match.group(2)))
  
    # Check if some verboten C functions are being used.
    if Search(r'\bsprintf\b', line):
      error(filename, linenum, 'runtime/printf', 5,
            'Never use sprintf.  Use snprintf instead.')
    match = Search(r'\b(strcpy|strcat)\b', line)
    if match:
      error(filename, linenum, 'runtime/printf', 4,
            '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
    # } if (a == b) {
    if Search(r'\}\s*if\s*\(', line):
      error(filename, linenum, 'readability/braces', 4,
            'Did you mean "else if"? If not, start a new line for "if".')
  
    # Check for potential format string bugs like printf(foo).
    # We constrain the pattern not to pick things like DocidForPrintf(foo).
    # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str())
    # TODO(sugawarayu): Catch the following case. Need to change the calling
    # convention of the whole function to process multiple line to handle it.
    #   printf(
    #       boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line);
    printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(')
    if printf_args:
      match = Match(r'([\w.\->()]+)$', printf_args)
      if match and match.group(1) != '__VA_ARGS__':
        function_name = re.search(r'\b((?:string)?printf)\s*\(',
                                  line, re.I).group(1)
        error(filename, linenum, 'runtime/printf', 4,
              'Potential format string bug. Do %s("%%s", %s) instead.'
              % (function_name, match.group(1)))
  
    # Check for potential memset bugs like memset(buf, sizeof(buf), 0).
    match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
    if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)):
      error(filename, linenum, 'runtime/memset', 4,
            'Did you mean "memset(%s, 0, %s)"?'
            % (match.group(1), match.group(2)))
  
    if Search(r'\busing namespace\b', line):
      error(filename, linenum, 'build/namespaces', 5,
            'Do not use namespace using-directives.  '
            'Use using-declarations instead.')
  
    # Detect variable-length arrays.
    match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
    if (match and match.group(2) != 'return' and match.group(2) != 'delete' and
        match.group(3).find(']') == -1):
      # Split the size using space and arithmetic operators as delimiters.
      # If any of the resulting tokens are not compile time constants then
      # report the error.
      tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3))
      is_const = True
      skip_next = False
      for tok in tokens:
        if skip_next:
          skip_next = False
          continue
  
        if Search(r'sizeof\(.+\)', tok): continue
        if Search(r'arraysize\(\w+\)', tok): continue
  
        tok = tok.lstrip('(')
        tok = tok.rstrip(')')
        if not tok: continue
        if Match(r'\d+', tok): continue
        if Match(r'0[xX][0-9a-fA-F]+', tok): continue
        if Match(r'k[A-Z0-9]\w*', tok): continue
        if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue
        if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue
        # A catch all for tricky sizeof cases, including 'sizeof expression',
        # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)'
        # requires skipping the next token because we split on ' ' and '*'.
        if tok.startswith('sizeof'):
          skip_next = True
          continue
        is_const = False
        break
      if not is_const:
        error(filename, linenum, 'runtime/arrays', 1,
              'Do not use variable-length arrays.  Use an appropriately named '
              "('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.')
function_tokens: def CheckLanguage ( filename , clean_lines , linenum , file_extension , include_state , nesting_state , error ) : # If the line is empty or consists of entirely a comment, no need to # check it. line = clean_lines . elided [ linenum ] if not line : return match = _RE_PATTERN_INCLUDE . search ( line ) if match : CheckIncludeLine ( filename , clean_lines , linenum , include_state , error ) return # Reset include state across preprocessor directives.  This is meant # to silence warnings for conditional includes. if Match ( r'^\s*#\s*(?:ifdef|elif|else|endif)\b' , line ) : include_state . ResetSection ( ) # Make Windows paths like Unix. fullname = os . path . abspath ( filename ) . replace ( '\\' , '/' ) # TODO(unknown): figure out if they're using default arguments in fn proto. # Check to see if they're using an conversion function cast. # I just try to capture the most common basic types, though there are more. # 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 : matched_new = match . group ( 1 ) matched_type = match . group ( 2 ) 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 ) CheckCStyleCast ( filename , linenum , line , clean_lines . raw_lines [ linenum ] , 'static_cast' , r'\((int|float|double|bool|char|u?int(16|32|64))\)' , error ) # This doesn't catch all cases. Consider (const char * const)"hello". # # (char *) "foo" should always be a const_cast (reinterpret_cast won't # compile). if CheckCStyleCast ( filename , linenum , line , clean_lines . raw_lines [ linenum ] , 'const_cast' , r'\((char\s?\*+\s?)\)\s*"' , error ) : pass else : # Check pointer casts for other than string constants CheckCStyleCast ( filename , linenum , line , clean_lines . raw_lines [ linenum ] , 'reinterpret_cast' , r'\((\w+\s?\*+\s?)\)' , error ) # 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' ) ) # Create an extended_line, which is the concatenation of the current and # next lines, for more effective checking of code that may span more than one # line. if linenum + 1 < clean_lines . NumLines ( ) : extended_line = line + clean_lines . elided [ linenum + 1 ] else : extended_line = line # 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 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. match = Search ( r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,' , line ) if match and match . group ( 2 ) != '0' : # If 2nd arg is zero, snprintf is used to calculate size. error ( filename , linenum , 'runtime/printf' , 3 , 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' 'to snprintf.' % ( match . group ( 1 ) , match . group ( 2 ) ) ) # Check if some verboten C functions are being used. if Search ( r'\bsprintf\b' , line ) : error ( filename , linenum , 'runtime/printf' , 5 , 'Never use sprintf.  Use snprintf instead.' ) match = Search ( r'\b(strcpy|strcat)\b' , line ) if match : error ( filename , linenum , 'runtime/printf' , 4 , '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 # } if (a == b) { if Search ( r'\}\s*if\s*\(' , line ) : error ( filename , linenum , 'readability/braces' , 4 , 'Did you mean "else if"? If not, start a new line for "if".' ) # Check for potential format string bugs like printf(foo). # We constrain the pattern not to pick things like DocidForPrintf(foo). # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str()) # TODO(sugawarayu): Catch the following case. Need to change the calling # convention of the whole function to process multiple line to handle it. #   printf( #       boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line); printf_args = _GetTextInside ( line , r'(?i)\b(string)?printf\s*\(' ) if printf_args : match = Match ( r'([\w.\->()]+)$' , printf_args ) if match and match . group ( 1 ) != '__VA_ARGS__' : function_name = re . search ( r'\b((?:string)?printf)\s*\(' , line , re . I ) . group ( 1 ) error ( filename , linenum , 'runtime/printf' , 4 , 'Potential format string bug. Do %s("%%s", %s) instead.' % ( function_name , match . group ( 1 ) ) ) # Check for potential memset bugs like memset(buf, sizeof(buf), 0). match = Search ( r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)' , line ) if match and not Match ( r"^''|-?[0-9]+|0x[0-9A-Fa-f]$" , match . group ( 2 ) ) : error ( filename , linenum , 'runtime/memset' , 4 , 'Did you mean "memset(%s, 0, %s)"?' % ( match . group ( 1 ) , match . group ( 2 ) ) ) if Search ( r'\busing namespace\b' , line ) : error ( filename , linenum , 'build/namespaces' , 5 , 'Do not use namespace using-directives.  ' 'Use using-declarations instead.' ) # Detect variable-length arrays. match = Match ( r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];' , line ) if ( match and match . group ( 2 ) != 'return' and match . group ( 2 ) != 'delete' and match . group ( 3 ) . find ( ']' ) == - 1 ) : # Split the size using space and arithmetic operators as delimiters. # If any of the resulting tokens are not compile time constants then # report the error. tokens = re . split ( r'\s|\+|\-|\*|\/|<<|>>]' , match . group ( 3 ) ) is_const = True skip_next = False for tok in tokens : if skip_next : skip_next = False continue if Search ( r'sizeof\(.+\)' , tok ) : continue if Search ( r'arraysize\(\w+\)' , tok ) : continue tok = tok . lstrip ( '(' ) tok = tok . rstrip ( ')' ) if not tok : continue if Match ( r'\d+' , tok ) : continue if Match ( r'0[xX][0-9a-fA-F]+' , tok ) : continue if Match ( r'k[A-Z0-9]\w*' , tok ) : continue if Match ( r'(.+::)?k[A-Z0-9]\w*' , tok ) : continue if Match ( r'(.+::)?[A-Z][A-Z0-9_]*' , tok ) : continue # A catch all for tricky sizeof cases, including 'sizeof expression', # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)' # requires skipping the next token because we split on ' ' and '*'. if tok . startswith ( 'sizeof' ) : skip_next = True continue is_const = False break if not is_const : error ( filename , linenum , 'runtime/arrays' , 1 , 'Do not use variable-length arrays.  Use an appropriately named ' "('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.' )