parameters: (filename, clean_lines, linenum,
                                    nesting_state, error)
docstring: r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
  
    Complain about several constructs which gcc-2 accepts, but which are
    not standard C++.  Warning about these in lint is one way to ease the
    transition to new compilers.
    - put storage class first (e.g. "static const" instead of "const static").
    - "%lld" instead of %qd" in printf-type functions.
    - "%1$d" is non-standard in printf-type functions.
    - "\%" is an undefined character escape sequence.
    - text after #endif is not allowed.
    - invalid inner-style forward declaration.
    - >? and <? operators, and their >?= and <?= cousins.
  
    Additionally, check for constructor/destructor style violations and reference
    members, as it is very convenient to do so while checking for
    gcc-2 compliance.
  
    Args:
      filename: The name of the current file.
      clean_lines: A CleansedLines instance containing the file.
      linenum: The number of the line to check.
      nesting_state: A _NestingState instance which maintains information about
                     the current stack of nested blocks being parsed.
      error: A callable to which errors are reported, which takes 4 arguments:
             filename, line number, error level, and message
docstring_summary: r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
docstring_tokens: r Logs an error if we see certain non - ANSI constructs ignored by gcc - 2 .
function: def CheckForNonStandardConstructs(filename, clean_lines, linenum,
                                    nesting_state, error):
    r"""Logs an error if we see certain non-ANSI constructs ignored by gcc-2.
  
    Complain about several constructs which gcc-2 accepts, but which are
    not standard C++.  Warning about these in lint is one way to ease the
    transition to new compilers.
    - put storage class first (e.g. "static const" instead of "const static").
    - "%lld" instead of %qd" in printf-type functions.
    - "%1$d" is non-standard in printf-type functions.
    - "\%" is an undefined character escape sequence.
    - text after #endif is not allowed.
    - invalid inner-style forward declaration.
    - >? and <? operators, and their >?= and <?= cousins.
  
    Additionally, check for constructor/destructor style violations and reference
    members, as it is very convenient to do so while checking for
    gcc-2 compliance.
  
    Args:
      filename: The name of the current file.
      clean_lines: A CleansedLines instance containing the file.
      linenum: The number of the line to check.
      nesting_state: A _NestingState instance which maintains information about
                     the current stack of nested blocks being parsed.
      error: A callable to which errors are reported, which takes 4 arguments:
             filename, line number, error level, and message
    """
  
    # Remove comments from the line, but leave in strings for now.
    line = clean_lines.lines[linenum]
  
    if Search(r'printf\s*\(.*".*%[-+ ]?\d*q', line):
      error(filename, linenum, 'runtime/printf_format', 3,
            '%q in format strings is deprecated.  Use %ll instead.')
  
    if Search(r'printf\s*\(.*".*%\d+\$', line):
      error(filename, linenum, 'runtime/printf_format', 2,
            '%N$ formats are unconventional.  Try rewriting to avoid them.')
  
    # Remove escaped backslashes before looking for undefined escapes.
    line = line.replace('\\\\', '')
  
    if Search(r'("|\').*\\(%|\[|\(|{)', line):
      error(filename, linenum, 'build/printf_format', 3,
            '%, [, (, and { are undefined character escapes.  Unescape them.')
  
    # For the rest, work with both comments and strings removed.
    line = clean_lines.elided[linenum]
  
    if Search(r'\b(const|volatile|void|char|short|int|long'
              r'|float|double|signed|unsigned'
              r'|schar|u?int8|u?int16|u?int32|u?int64)'
              r'\s+(register|static|extern|typedef)\b',
              line):
      error(filename, linenum, 'build/storage_class', 5,
            'Storage class (static, extern, typedef, etc) should be first.')
  
    if Match(r'\s*#\s*endif\s*[^/\s]+', line):
      error(filename, linenum, 'build/endif_comment', 5,
            'Uncommented text after #endif is non-standard.  Use a comment.')
  
    if Match(r'\s*class\s+(\w+\s*::\s*)+\w+\s*;', line):
      error(filename, linenum, 'build/forward_decl', 5,
            'Inner-style forward declarations are invalid.  Remove this line.')
  
    if Search(r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?',
              line):
      error(filename, linenum, 'build/deprecated', 3,
            '>? and <? (max and min) operators are non-standard and deprecated.')
  
    if Search(r'^\s*const\s*string\s*&\s*\w+\s*;', line):
      # TODO(unknown): Could it be expanded safely to arbitrary references,
      # without triggering too many false positives? The first
      # attempt triggered 5 warnings for mostly benign code in the regtest, hence
      # the restriction.
      # Here's the original regexp, for the reference:
      # type_name = r'\w+((\s*::\s*\w+)|(\s*<\s*\w+?\s*>))?'
      # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;'
      error(filename, linenum, 'runtime/member_string_references', 2,
            'const string& members are dangerous. It is much better to use '
            'alternatives, such as pointers or simple constants.')
  
    # Everything else in this function operates on class declarations.
    # Return early if the top of the nesting stack is not a class, or if
    # the class head is not completed yet.
    classinfo = nesting_state.InnermostClass()
    if not classinfo or not classinfo.seen_open_brace:
      return
  
    # The class may have been declared with namespace or classname qualifiers.
    # The constructor and destructor will not have those qualifiers.
    base_classname = classinfo.name.split('::')[-1]
  
    # Look for single-argument constructors that aren't marked explicit.
    # Technically a valid construct, but against style.
    args = Match(r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)'
                 % re.escape(base_classname),
                 line)
    if (args and
        args.group(1) != 'void' and
        not Match(r'(const\s+)?%s(\s+const)?\s*(?:<\w+>\s*)?&'
                  % re.escape(base_classname), args.group(1).strip())):
      error(filename, linenum, 'runtime/explicit', 5,
            'Single-argument constructors should be marked explicit.')
function_tokens: def CheckForNonStandardConstructs ( filename , clean_lines , linenum , nesting_state , error ) : # Remove comments from the line, but leave in strings for now. line = clean_lines . lines [ linenum ] if Search ( r'printf\s*\(.*".*%[-+ ]?\d*q' , line ) : error ( filename , linenum , 'runtime/printf_format' , 3 , '%q in format strings is deprecated.  Use %ll instead.' ) if Search ( r'printf\s*\(.*".*%\d+\$' , line ) : error ( filename , linenum , 'runtime/printf_format' , 2 , '%N$ formats are unconventional.  Try rewriting to avoid them.' ) # Remove escaped backslashes before looking for undefined escapes. line = line . replace ( '\\\\' , '' ) if Search ( r'("|\').*\\(%|\[|\(|{)' , line ) : error ( filename , linenum , 'build/printf_format' , 3 , '%, [, (, and { are undefined character escapes.  Unescape them.' ) # For the rest, work with both comments and strings removed. line = clean_lines . elided [ linenum ] if Search ( r'\b(const|volatile|void|char|short|int|long' r'|float|double|signed|unsigned' r'|schar|u?int8|u?int16|u?int32|u?int64)' r'\s+(register|static|extern|typedef)\b' , line ) : error ( filename , linenum , 'build/storage_class' , 5 , 'Storage class (static, extern, typedef, etc) should be first.' ) if Match ( r'\s*#\s*endif\s*[^/\s]+' , line ) : error ( filename , linenum , 'build/endif_comment' , 5 , 'Uncommented text after #endif is non-standard.  Use a comment.' ) if Match ( r'\s*class\s+(\w+\s*::\s*)+\w+\s*;' , line ) : error ( filename , linenum , 'build/forward_decl' , 5 , 'Inner-style forward declarations are invalid.  Remove this line.' ) if Search ( r'(\w+|[+-]?\d+(\.\d*)?)\s*(<|>)\?=?\s*(\w+|[+-]?\d+)(\.\d*)?' , line ) : error ( filename , linenum , 'build/deprecated' , 3 , '>? and <? (max and min) operators are non-standard and deprecated.' ) if Search ( r'^\s*const\s*string\s*&\s*\w+\s*;' , line ) : # TODO(unknown): Could it be expanded safely to arbitrary references, # without triggering too many false positives? The first # attempt triggered 5 warnings for mostly benign code in the regtest, hence # the restriction. # Here's the original regexp, for the reference: # type_name = r'\w+((\s*::\s*\w+)|(\s*<\s*\w+?\s*>))?' # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;' error ( filename , linenum , 'runtime/member_string_references' , 2 , 'const string& members are dangerous. It is much better to use ' 'alternatives, such as pointers or simple constants.' ) # Everything else in this function operates on class declarations. # Return early if the top of the nesting stack is not a class, or if # the class head is not completed yet. classinfo = nesting_state . InnermostClass ( ) if not classinfo or not classinfo . seen_open_brace : return # The class may have been declared with namespace or classname qualifiers. # The constructor and destructor will not have those qualifiers. base_classname = classinfo . name . split ( '::' ) [ - 1 ] # Look for single-argument constructors that aren't marked explicit. # Technically a valid construct, but against style. args = Match ( r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)' % re . escape ( base_classname ) , line ) if ( args and args . group ( 1 ) != 'void' and not Match ( r'(const\s+)?%s(\s+const)?\s*(?:<\w+>\s*)?&' % re . escape ( base_classname ) , args . group ( 1 ) . strip ( ) ) ) : error ( filename , linenum , 'runtime/explicit' , 5 , 'Single-argument constructors should be marked explicit.' )