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.
    match = Match(r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b', line)
    if match:
      include_state.ResetSection(match.group(1))
  
    # Make Windows paths like Unix.
    fullname = os.path.abspath(filename).replace('\\', '/')
  
    # Perform other checks now that we are sure that this is not an include line
    CheckCasts(filename, clean_lines, linenum, error)
    CheckGlobalStatic(filename, clean_lines, linenum, error)
    CheckPrintf(filename, clean_lines, linenum, error)
  
    if file_extension in ['h', 'hpp']:
      # 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 declare or disable copy/assign
      #                (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))
  
    # 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(unknown): 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.")
  
    # 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 in ['h', 'hpp']
        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. match = Match ( r'^\s*#\s*(if|ifdef|ifndef|elif|else|endif)\b' , line ) if match : include_state . ResetSection ( match . group ( 1 ) ) # Make Windows paths like Unix. fullname = os . path . abspath ( filename ) . replace ( '\\' , '/' ) # Perform other checks now that we are sure that this is not an include line CheckCasts ( filename , clean_lines , linenum , error ) CheckGlobalStatic ( filename , clean_lines , linenum , error ) CheckPrintf ( filename , clean_lines , linenum , error ) if file_extension in [ 'h' , 'hpp' ] : # 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 declare or disable copy/assign #                (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 ) ) # 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(unknown): 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.") # 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 in [ 'h' , 'hpp' ] 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.' )