parameters: (filename, clean_lines, line_number, file_extension, include_state,
                     file_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.
        line_number: 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.
        file_state: A _FileState instance which maintains information about
                    the state of things in the file.
        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 check_language(filename, clean_lines, line_number, file_extension, include_state,
                     file_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.
        line_number: 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.
        file_state: A _FileState instance which maintains information about
                    the state of things in the file.
        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[line_number]
      if not line:
          return
  
      matched = _RE_PATTERN_INCLUDE.search(line)
      if matched:
          check_include_line(filename, file_extension, clean_lines, line_number, include_state, error)
          return
  
      # FIXME: 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.
      matched = search(
          r'\b(int|float|double|bool|char|int32|uint32|int64|uint64)\([^)]', line)
      if matched:
          # 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.
          if not match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line):
              error(line_number, 'readability/casting', 4,
                    'Using deprecated casting style.  '
                    'Use static_cast<%s>(...) instead' %
                    matched.group(1))
  
      check_c_style_cast(line_number, line, clean_lines.raw_lines[line_number],
                         '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".
      check_c_style_cast(line_number, line, clean_lines.raw_lines[line_number],
                         '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.
      if search(
          r'(&\([^)]+\)[\w(])|(&(static|dynamic|reinterpret)_cast\b)', line):
          error(line_number, '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'))
  
      # 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.
      matched = 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(...".
      if matched and not match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)',
                               matched.group(3)):
          error(line_number, 'runtime/string', 4,
                'For a static/global string constant, use a C style string instead: '
                '"%schar %s[]".' %
                (matched.group(1), matched.group(2)))
  
      # Check that we're not using RTTI outside of testing code.
      if search(r'\bdynamic_cast<', line):
          error(line_number, 'runtime/rtti', 5,
                'Do not use dynamic_cast<>.  If you need to cast within a class '
                "hierarchy, use static_cast<> to upcast.  Google doesn't support "
                'RTTI.')
  
      if file_extension == 'h':
          # FIXME: check that 1-arg constructors are explicit.
          #        How to tell it's a constructor?
          #        (handled in check_for_non_standard_constructs for now)
          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(line_number, 'runtime/int', 4,
                    'Use "unsigned short" for ports, not "short"')
  
      # When snprintf is used, the second argument shouldn't be a literal.
      matched = search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line)
      if matched:
          error(line_number, 'runtime/printf', 3,
                'If you can, use sizeof(%s) instead of %s as the 2nd arg '
                'to snprintf.' % (matched.group(1), matched.group(2)))
  
      # Check if some verboten C functions are being used.
      if search(r'\bsprintf\b', line):
          error(line_number, 'runtime/printf', 5,
                'Never use sprintf.  Use snprintf instead.')
      matched = search(r'\b(strcpy|strcat)\b', line)
      if matched:
          error(line_number, 'runtime/printf', 4,
                'Almost always, snprintf is better than %s' % matched.group(1))
  
      if search(r'\bsscanf\b', line):
          error(line_number, 'runtime/printf', 1,
                'sscanf can be ok, but is slow and can overflow buffers.')
  
      # Check for suspicious usage of "if" like
      # } if (a == b) {
      if search(r'\}\s*if\s*\(', line):
          error(line_number, '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())
      matched = re.search(r'\b((?:string)?printf)\s*\(([\w.\->()]+)\)', line, re.I)
      if matched:
          error(line_number, 'runtime/printf', 4,
                'Potential format string bug. Do %s("%%s", %s) instead.'
                % (matched.group(1), matched.group(2)))
  
      # Check for potential memset bugs like memset(buf, sizeof(buf), 0).
      matched = search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line)
      if matched and not match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", matched.group(2)):
          error(line_number, 'runtime/memset', 4,
                'Did you mean "memset(%s, 0, %s)"?'
                % (matched.group(1), matched.group(2)))
  
      # Detect variable-length arrays.
      matched = match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line)
      if (matched and matched.group(2) != 'return' and matched.group(2) != 'delete' and
          matched.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|\+|\-|\*|\/|<<|>>]', matched.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 becasue we split on ' ' and '*'.
              if tok.startswith('sizeof'):
                  skip_next = True
                  continue
              is_const = False
              break
          if not is_const:
              error(line_number, '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 == 'h'
          and search(r'\bnamespace\s*{', line)
          and line[-1] != '\\'):
          error(line_number, '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.')
  
      # Check for plain bitfields declared without either "singed" or "unsigned".
      # Most compilers treat such bitfields as signed, but there are still compilers like
      # RVCT 4.0 that use unsigned by default.
      matched = re.match(r'\s*((const|mutable)\s+)?(char|(short(\s+int)?)|int|long(\s+(long|int))?)\s+[a-zA-Z_][a-zA-Z0-9_]*\s*:\s*\d+\s*;', line)
      if matched:
          error(line_number, 'runtime/bitfields', 5,
                'Please declare integral type bitfields with either signed or unsigned.')
  
      # Beware of using enums as types for bitfields, there can sometimes be a mismatch
      # between the signedness of the enum and the enum bitfield type.
      # Visual Studio's 8.0 compiler is an example where it represents bit fields of
      # enum types with a signed type, but enums as unsigned.
      matched = re.match(r'\s*((const|mutable)\s+)?([a-zA-Z_][a-zA-Z0-9_]*)\s+[a-zA-Z_][a-zA-Z0-9_]*\s*:\s*\d+\s*;', line)
      if matched:
          # Make sure the type is an enum and not an integral type
          if not match(r'bool|char|(short(\s+int)?)|int|long(\s+(long|int))|(signed|unsigned)(\s+int)?', matched.group(3)):
              error(line_number, 'runtime/enum_bitfields', 5,
                    'Please declare enum bitfields as unsigned integral types.')
  
      check_identifier_name_in_declaration(filename, line_number, line, file_state, error)
  
      # Check for unsigned int (should be just 'unsigned')
      if search(r'\bunsigned int\b', line):
          error(line_number, 'runtime/unsigned', 1,
                'Omit int when using unsigned')
  
      # Check that we're not using static_cast<Text*>.
      if search(r'\bstatic_cast<Text\*>', line):
          error(line_number, 'readability/check', 4,
                'Consider using toText helper function in WebCore/dom/Text.h '
                'instead of static_cast<Text*>')
function_tokens: def check_language ( filename , clean_lines , line_number , file_extension , include_state , file_state , error ) : # If the line is empty or consists of entirely a comment, no need to # check it. line = clean_lines . elided [ line_number ] if not line : return matched = _RE_PATTERN_INCLUDE . search ( line ) if matched : check_include_line ( filename , file_extension , clean_lines , line_number , include_state , error ) return # FIXME: 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. matched = search ( r'\b(int|float|double|bool|char|int32|uint32|int64|uint64)\([^)]' , line ) if matched : # 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. if not match ( r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(' , line ) : error ( line_number , 'readability/casting' , 4 , 'Using deprecated casting style.  ' 'Use static_cast<%s>(...) instead' % matched . group ( 1 ) ) check_c_style_cast ( line_number , line , clean_lines . raw_lines [ line_number ] , '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". check_c_style_cast ( line_number , line , clean_lines . raw_lines [ line_number ] , '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. if search ( r'(&\([^)]+\)[\w(])|(&(static|dynamic|reinterpret)_cast\b)' , line ) : error ( line_number , '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' ) ) # 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. matched = 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(...". if matched and not match ( r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)' , matched . group ( 3 ) ) : error ( line_number , 'runtime/string' , 4 , 'For a static/global string constant, use a C style string instead: ' '"%schar %s[]".' % ( matched . group ( 1 ) , matched . group ( 2 ) ) ) # Check that we're not using RTTI outside of testing code. if search ( r'\bdynamic_cast<' , line ) : error ( line_number , 'runtime/rtti' , 5 , 'Do not use dynamic_cast<>.  If you need to cast within a class ' "hierarchy, use static_cast<> to upcast.  Google doesn't support " 'RTTI.' ) if file_extension == 'h' : # FIXME: check that 1-arg constructors are explicit. #        How to tell it's a constructor? #        (handled in check_for_non_standard_constructs for now) 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 ( line_number , 'runtime/int' , 4 , 'Use "unsigned short" for ports, not "short"' ) # When snprintf is used, the second argument shouldn't be a literal. matched = search ( r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,' , line ) if matched : error ( line_number , 'runtime/printf' , 3 , 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' 'to snprintf.' % ( matched . group ( 1 ) , matched . group ( 2 ) ) ) # Check if some verboten C functions are being used. if search ( r'\bsprintf\b' , line ) : error ( line_number , 'runtime/printf' , 5 , 'Never use sprintf.  Use snprintf instead.' ) matched = search ( r'\b(strcpy|strcat)\b' , line ) if matched : error ( line_number , 'runtime/printf' , 4 , 'Almost always, snprintf is better than %s' % matched . group ( 1 ) ) if search ( r'\bsscanf\b' , line ) : error ( line_number , 'runtime/printf' , 1 , 'sscanf can be ok, but is slow and can overflow buffers.' ) # Check for suspicious usage of "if" like # } if (a == b) { if search ( r'\}\s*if\s*\(' , line ) : error ( line_number , '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()) matched = re . search ( r'\b((?:string)?printf)\s*\(([\w.\->()]+)\)' , line , re . I ) if matched : error ( line_number , 'runtime/printf' , 4 , 'Potential format string bug. Do %s("%%s", %s) instead.' % ( matched . group ( 1 ) , matched . group ( 2 ) ) ) # Check for potential memset bugs like memset(buf, sizeof(buf), 0). matched = search ( r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)' , line ) if matched and not match ( r"^''|-?[0-9]+|0x[0-9A-Fa-f]$" , matched . group ( 2 ) ) : error ( line_number , 'runtime/memset' , 4 , 'Did you mean "memset(%s, 0, %s)"?' % ( matched . group ( 1 ) , matched . group ( 2 ) ) ) # Detect variable-length arrays. matched = match ( r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];' , line ) if ( matched and matched . group ( 2 ) != 'return' and matched . group ( 2 ) != 'delete' and matched . 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|\+|\-|\*|\/|<<|>>]' , matched . 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 becasue we split on ' ' and '*'. if tok . startswith ( 'sizeof' ) : skip_next = True continue is_const = False break if not is_const : error ( line_number , '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 == 'h' and search ( r'\bnamespace\s*{' , line ) and line [ - 1 ] != '\\' ) : error ( line_number , '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.' ) # Check for plain bitfields declared without either "singed" or "unsigned". # Most compilers treat such bitfields as signed, but there are still compilers like # RVCT 4.0 that use unsigned by default. matched = re . match ( r'\s*((const|mutable)\s+)?(char|(short(\s+int)?)|int|long(\s+(long|int))?)\s+[a-zA-Z_][a-zA-Z0-9_]*\s*:\s*\d+\s*;' , line ) if matched : error ( line_number , 'runtime/bitfields' , 5 , 'Please declare integral type bitfields with either signed or unsigned.' ) # Beware of using enums as types for bitfields, there can sometimes be a mismatch # between the signedness of the enum and the enum bitfield type. # Visual Studio's 8.0 compiler is an example where it represents bit fields of # enum types with a signed type, but enums as unsigned. matched = re . match ( r'\s*((const|mutable)\s+)?([a-zA-Z_][a-zA-Z0-9_]*)\s+[a-zA-Z_][a-zA-Z0-9_]*\s*:\s*\d+\s*;' , line ) if matched : # Make sure the type is an enum and not an integral type if not match ( r'bool|char|(short(\s+int)?)|int|long(\s+(long|int))|(signed|unsigned)(\s+int)?' , matched . group ( 3 ) ) : error ( line_number , 'runtime/enum_bitfields' , 5 , 'Please declare enum bitfields as unsigned integral types.' ) check_identifier_name_in_declaration ( filename , line_number , line , file_state , error ) # Check for unsigned int (should be just 'unsigned') if search ( r'\bunsigned int\b' , line ) : error ( line_number , 'runtime/unsigned' , 1 , 'Omit int when using unsigned' ) # Check that we're not using static_cast<Text*>. if search ( r'\bstatic_cast<Text\*>' , line ) : error ( line_number , 'readability/check' , 4 , 'Consider using toText helper function in WebCore/dom/Text.h ' 'instead of static_cast<Text*>' )