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))
  
      # 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 IsHeaderExtension(file_extension):
          # 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):
          if Search(r'\bliterals\b', line):
              error(filename, linenum, 'build/namespaces_literals', 5,
                    'Do not use namespace using-directives.  '
                    'Use using-declarations instead.')
          else:
              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 (IsHeaderExtension(file_extension)
          and Search(r'\bnamespace\s*{', line)
              and line[-1] != '\\'):
          error(filename, linenum, 'build/namespaces', 4,
                'Do not use unnamed namespaces in header files.  See '
                'https://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 ) ) # 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 IsHeaderExtension ( file_extension ) : # 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 ) : if Search ( r'\bliterals\b' , line ) : error ( filename , linenum , 'build/namespaces_literals' , 5 , 'Do not use namespace using-directives.  ' 'Use using-declarations instead.' ) else : 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 ( IsHeaderExtension ( file_extension ) and Search ( r'\bnamespace\s*{' , line ) and line [ - 1 ] != '\\' ) : error ( filename , linenum , 'build/namespaces' , 4 , 'Do not use unnamed namespaces in header files.  See ' 'https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces' ' for more information.' )