libv8 5.0.71.48.3 → 5.1.281.59.0beta3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/ext/libv8/location.rb +12 -9
  4. data/ext/libv8/patcher.rb +1 -1
  5. data/ext/libv8/paths.rb +1 -1
  6. data/lib/libv8/version.rb +1 -1
  7. data/patches/0001-Build-standalone-static-library.patch +26 -0
  8. data/patches/{disable-building-tests.patch → 0002-Disable-building-tests.patch} +17 -5
  9. data/patches/0003-Use-the-fPIC-flag-for-the-static-library.patch +25 -0
  10. data/spec/location_spec.rb +1 -1
  11. data/vendor/depot_tools/.gitignore +1 -0
  12. data/vendor/depot_tools/PRESUBMIT.py +3 -1
  13. data/vendor/depot_tools/README +1 -6
  14. data/vendor/depot_tools/apply_issue.py +6 -0
  15. data/vendor/depot_tools/bootstrap/win/README.md +2 -2
  16. data/vendor/depot_tools/bootstrap/win/git.template.bat +1 -1
  17. data/vendor/depot_tools/bootstrap/win/win_tools.bat +12 -11
  18. data/vendor/depot_tools/codereview.settings +1 -1
  19. data/vendor/depot_tools/cpplint.py +353 -592
  20. data/vendor/depot_tools/fetch.py +10 -3
  21. data/vendor/depot_tools/fetch_configs/infra.py +4 -2
  22. data/vendor/depot_tools/fetch_configs/ios_internal.py +49 -0
  23. data/vendor/depot_tools/gclient.py +33 -7
  24. data/vendor/depot_tools/gclient_scm.py +14 -11
  25. data/vendor/depot_tools/gclient_utils.py +14 -3
  26. data/vendor/depot_tools/git-gs +3 -3
  27. data/vendor/depot_tools/git_cache.py +8 -4
  28. data/vendor/depot_tools/git_cl.py +221 -98
  29. data/vendor/depot_tools/git_footers.py +76 -39
  30. data/vendor/depot_tools/git_map_branches.py +12 -10
  31. data/vendor/depot_tools/infra/config/cq.cfg +0 -11
  32. data/vendor/depot_tools/infra/config/recipes.cfg +1 -1
  33. data/vendor/depot_tools/presubmit_canned_checks.py +31 -19
  34. data/vendor/depot_tools/presubmit_support.py +0 -13
  35. data/vendor/depot_tools/recipe_modules/bot_update/resources/bot_update.py +19 -2
  36. data/vendor/depot_tools/recipe_modules/depot_tools/api.py +4 -0
  37. data/vendor/depot_tools/recipe_modules/depot_tools/example.expected/basic.json +49 -0
  38. data/vendor/depot_tools/recipe_modules/depot_tools/example.expected/win.json +49 -0
  39. data/vendor/depot_tools/recipe_modules/depot_tools/example.py +38 -0
  40. data/vendor/depot_tools/recipe_modules/gclient/api.py +1 -0
  41. data/vendor/depot_tools/recipe_modules/gclient/config.py +19 -0
  42. data/vendor/depot_tools/recipe_modules/gclient/example.expected/basic.json +1 -0
  43. data/vendor/depot_tools/recipe_modules/gclient/example.expected/revision.json +1 -0
  44. data/vendor/depot_tools/recipe_modules/gclient/example.expected/tryserver.json +1 -0
  45. data/vendor/depot_tools/recipe_modules/gclient/example.py +3 -0
  46. data/vendor/depot_tools/recipe_modules/git_cl/api.py +22 -6
  47. data/vendor/depot_tools/recipe_modules/git_cl/example.expected/basic.json +27 -9
  48. data/vendor/depot_tools/recipe_modules/git_cl/example.py +9 -7
  49. data/vendor/depot_tools/recipe_modules/presubmit/api.py +5 -2
  50. data/vendor/depot_tools/recipe_modules/tryserver/__init__.py +1 -0
  51. data/vendor/depot_tools/recipe_modules/tryserver/api.py +31 -0
  52. data/vendor/depot_tools/recipe_modules/tryserver/example.expected/basic_tags.json +59 -0
  53. data/vendor/depot_tools/recipe_modules/tryserver/example.expected/with_rietveld_patch.json +26 -0
  54. data/vendor/depot_tools/recipe_modules/tryserver/example.expected/with_rietveld_patch_new.json +26 -0
  55. data/vendor/depot_tools/recipe_modules/tryserver/example.py +32 -3
  56. data/vendor/depot_tools/roll_dep.py +6 -2
  57. data/vendor/depot_tools/third_party/upload.py +17 -9
  58. data/vendor/depot_tools/update_depot_tools +11 -0
  59. data/vendor/depot_tools/update_depot_tools.bat +11 -0
  60. data/vendor/depot_tools/win_toolchain/get_toolchain_if_necessary.py +52 -9
  61. data/vendor/depot_tools/win_toolchain/package_from_installed.py +64 -57
  62. metadata +12 -10
  63. data/patches/build-standalone-static-library.patch +0 -14
  64. data/patches/fPIC-for-static.patch +0 -13
  65. data/vendor/depot_tools/git-lkgr +0 -208
  66. data/vendor/depot_tools/hammer +0 -28
  67. data/vendor/depot_tools/hammer.bat +0 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e0556cfcdb9a5a566c15fd47b0b74a1d20881606
4
- data.tar.gz: 5cc39182c89e7f0e7185227b3861f7f3c71d19fb
3
+ metadata.gz: 41cbaf11fa4edba84e871c58099ed8243019b2b1
4
+ data.tar.gz: 958c801dae727821359a0004ebac3b35b654e527
5
5
  SHA512:
6
- metadata.gz: 786c7ce66fd644d92104dceacf45421898bf1f26802e79bb0775ec3b4ce0f0f64f9a76ee7e8d7460decf359bc9dd8774646cb6b579a82d60f1760d5c21e975c4
7
- data.tar.gz: 7ea6c6a4013e5239bbfdd902c1c805c68608017cd41d47f0e018385a1e21eb17cab88986bc2640ef5fa032654f3283d859a538c150cd93d537f55481b9fec60b
6
+ metadata.gz: 3ee57388f66c9f06452560879ab5bc7fec7fb58a76a36eebf36d18de8f25dcd54b0c1eec391dbfb50d1cae63a7bc898a7fc91121bd704a6bd341499d2c72a48f
7
+ data.tar.gz: 3837b26a28511330199c8f31e1296ff6d1eab8bd018415b606e53cb9e1978e7eec059ef932f10600a4514cb5937f0e2efcff4a75887bd2e848768b46bc03f854
@@ -1,5 +1,9 @@
1
1
  ### Unreleased
2
2
 
3
+ ### 5.0.71.48.4, 5.0.71.48.5 - 2016-05-13:
4
+
5
+ * Enable the -fPIC flag for ARM
6
+
3
7
  ### 5.0.71.48.2, 5.0.71.48.3 - 2016-05-13:
4
8
 
5
9
  * Upgrade upstream v8 version to 5.0.71.45
@@ -26,21 +26,24 @@ module Libv8
26
26
  verify_installation!
27
27
  return exit_status
28
28
  end
29
+
29
30
  def configure(context = MkmfContext.new)
30
- context.incflags.insert 0, Libv8::Paths.include_paths.map{|p| "-I#{p}"}.join(" ") + " "
31
+ context.incflags.insert 0, Libv8::Paths.include_paths.map{ |p| "-I#{p}" }.join(" ") + " "
31
32
  context.ldflags.insert 0, Libv8::Paths.object_paths.join(" ") + " "
32
33
  end
33
34
 
34
35
  def verify_installation!
35
36
  include_paths = Libv8::Paths.include_paths
36
- unless include_paths.detect { |p| Pathname(p).join('include/v8.h').exist? }
37
- fail HeaderNotFound, "Unable to locate 'include/v8.h' in the libv8 header paths: #{include_paths.inspect}"
37
+ unless include_paths.detect { |p| Pathname(p).join('v8.h').exist? }
38
+ fail HeaderNotFound, "Unable to locate 'v8.h' in the libv8 header paths: #{include_paths.inspect}"
38
39
  end
39
40
  Libv8::Paths.object_paths.each do |p|
40
41
  fail ArchiveNotFound, p unless File.exist? p
41
42
  end
42
43
  end
44
+
43
45
  class HeaderNotFound < StandardError; end
46
+
44
47
  class ArchiveNotFound < StandardError
45
48
  def initialize(filename)
46
49
  super "libv8 did not install properly, expected binary v8 archive '#{filename}'to exist, but it was not found"
@@ -59,14 +62,14 @@ module Libv8
59
62
  class NotFoundError < StandardError
60
63
  def initialize(*args)
61
64
  super(<<-EOS)
62
- By using --with-system-v8, you have chosen to use the version
63
- of V8 found on your system and *not* the one that is bundled with
64
- the libv8 rubygem.
65
+ By using --with-system-v8, you have chosen to use the version
66
+ of V8 found on your system and *not* the one that is bundled with
67
+ the libv8 rubygem.
65
68
 
66
- However, your system version of v8 could not be located.
69
+ However, your system version of v8 could not be located.
67
70
 
68
- Please make sure your system version of v8 that is compatible
69
- with #{Libv8::VERSION} installed. You may need to use the
71
+ Please make sure your system version of v8 that is compatible
72
+ with #{Libv8::VERSION} installed. You may need to use the
70
73
  --with-v8-dir option if it is installed in a non-standard location
71
74
  EOS
72
75
  end
@@ -6,7 +6,7 @@ module Libv8
6
6
 
7
7
  def patch!
8
8
  File.open(".applied_patches", File::RDWR|File::CREAT) do |f|
9
- available_patches = Dir.glob(File.join(PATCH_DIRECTORY, '*.patch'))
9
+ available_patches = Dir.glob(File.join(PATCH_DIRECTORY, '*.patch')).sort
10
10
  applied_patches = f.readlines.map(&:chomp)
11
11
 
12
12
  (available_patches - applied_patches).each do |patch|
@@ -7,7 +7,7 @@ module Libv8
7
7
  module_function
8
8
 
9
9
  def include_paths
10
- [Shellwords.escape(vendored_source_path)]
10
+ [Shellwords.escape(File.join(vendored_source_path, 'include'))]
11
11
  end
12
12
 
13
13
  def object_paths
@@ -1,3 +1,3 @@
1
1
  module Libv8
2
- VERSION = "5.0.71.48.3"
2
+ VERSION = "5.1.281.59.0beta3"
3
3
  end
@@ -0,0 +1,26 @@
1
+ From 91326a79ff71b9f856585bf8dfdc112527801e68 Mon Sep 17 00:00:00 2001
2
+ From: Petko Bordjukov <bordjukov@gmail.com>
3
+ Date: Fri, 10 Jun 2016 08:51:08 +0300
4
+ Subject: [PATCH 1/3] Build standalone static library
5
+
6
+ ---
7
+ build/standalone.gypi | 3 +++
8
+ 1 file changed, 3 insertions(+)
9
+
10
+ diff --git a/build/standalone.gypi b/build/standalone.gypi
11
+ index 6c88409..4f10909 100644
12
+ --- a/build/standalone.gypi
13
+ +++ b/build/standalone.gypi
14
+ @@ -471,6 +471,9 @@
15
+ }], # fastbuild!=0
16
+ ],
17
+ 'target_conditions': [
18
+ + ['_type=="static_library"', {
19
+ + 'standalone_static_library': 1,
20
+ + }],
21
+ ['v8_code == 0', {
22
+ 'defines!': [
23
+ 'DEBUG',
24
+ --
25
+ 2.8.3
26
+
@@ -1,18 +1,27 @@
1
+ From a27a92cbe9db50bceedfffeb43d12345209e4d75 Mon Sep 17 00:00:00 2001
2
+ From: Petko Bordjukov <bordjukov@gmail.com>
3
+ Date: Fri, 10 Jun 2016 08:57:29 +0300
4
+ Subject: [PATCH 2/3] Disable building tests
5
+
6
+ ---
7
+ Makefile | 6 ++----
8
+ build/all.gyp | 27 ---------------------------
9
+ 2 files changed, 2 insertions(+), 31 deletions(-)
10
+
1
11
  diff --git a/Makefile b/Makefile
2
- index 4fb6ee0..549ae58 100644
12
+ index a0c08a6..10b2924 100644
3
13
  --- a/Makefile
4
14
  +++ b/Makefile
5
- @@ -251,11 +251,9 @@ NACL_ARCHES = nacl_ia32 nacl_x64
15
+ @@ -258,11 +258,9 @@ NACL_ARCHES = nacl_ia32 nacl_x64
6
16
  GYPFILES = third_party/icu/icu.gypi third_party/icu/icu.gyp \
7
17
  build/shim_headers.gypi build/features.gypi build/standalone.gypi \
8
18
  build/toolchain.gypi build/all.gyp build/mac/asan.gyp \
9
19
  - test/cctest/cctest.gyp test/fuzzer/fuzzer.gyp \
10
20
  - test/unittests/unittests.gyp tools/gyp/v8.gyp \
11
21
  - tools/parser-shell.gyp testing/gmock.gyp testing/gtest.gyp \
12
- - buildtools/third_party/libc++abi/libc++abi.gyp \
13
- - buildtools/third_party/libc++/libc++.gyp samples/samples.gyp \
14
22
  + tools/gyp/v8.gyp tools/parser-shell.gyp \
15
- + buildtools/third_party/libc++abi/libc++abi.gyp \
23
+ buildtools/third_party/libc++abi/libc++abi.gyp \
24
+ - buildtools/third_party/libc++/libc++.gyp samples/samples.gyp \
16
25
  + buildtools/third_party/libc++/libc++.gyp \
17
26
  src/third_party/vtune/v8vtune.gyp src/d8.gyp
18
27
 
@@ -63,3 +72,6 @@ index feaf4fe..96820a0 100644
63
72
  ]
64
73
  }
65
74
  ]
75
+ --
76
+ 2.8.3
77
+
@@ -0,0 +1,25 @@
1
+ From 8c92844ee381fc2074204dd52ca3668e3c6fe89f Mon Sep 17 00:00:00 2001
2
+ From: Petko Bordjukov <bordjukov@gmail.com>
3
+ Date: Fri, 10 Jun 2016 08:58:29 +0300
4
+ Subject: [PATCH 3/3] Use the -fPIC flag for the static library
5
+
6
+ ---
7
+ build/standalone.gypi | 2 +-
8
+ 1 file changed, 1 insertion(+), 1 deletion(-)
9
+
10
+ diff --git a/build/standalone.gypi b/build/standalone.gypi
11
+ index 4f10909..3a67af3 100644
12
+ --- a/build/standalone.gypi
13
+ +++ b/build/standalone.gypi
14
+ @@ -728,7 +728,7 @@
15
+ [ 'visibility=="hidden" and v8_enable_backtrace==0', {
16
+ 'cflags': [ '-fvisibility=hidden' ],
17
+ }],
18
+ - [ 'component=="shared_library"', {
19
+ + [ 'component=="shared_library" or component=="static_library" and (v8_target_arch=="x64" or v8_target_arch=="arm64" or v8_target_arch=="arm")', {
20
+ 'cflags': [ '-fPIC', ],
21
+ }],
22
+ [ 'clang==0 and coverage==1', {
23
+ --
24
+ 2.8.3
25
+
@@ -60,7 +60,7 @@ describe "libv8 locations" do
60
60
  end
61
61
 
62
62
  it "prepends its own incflags before any pre-existing ones" do
63
- expect(@context.incflags).to eql "-I/foo\\ bar/v8 -I/usr/include -I/usr/local/include"
63
+ expect(@context.incflags).to eql "-I/foo\\ bar/v8/include -I/usr/include -I/usr/local/include"
64
64
  end
65
65
 
66
66
  it "prepends the locations of any libv8 objects on the the ldflags" do
@@ -43,6 +43,7 @@
43
43
  /tags
44
44
 
45
45
  # Ignore unittest related files.
46
+ /testing_support/_infra
46
47
  /testing_support/_rietveld
47
48
  /tests/git-svn-submodule/
48
49
  /tests/subversion_config/README.txt
@@ -25,7 +25,9 @@ def CommonChecks(input_api, output_api, tests_to_black_list):
25
25
  r'^recipes\.py$',
26
26
  r'^site-packages-py[0-9]\.[0-9][\/\\].+',
27
27
  r'^svn_bin[\/\\].+',
28
- r'^testing_support[\/\\]_rietveld[\/\\].+']
28
+ r'^testing_support[\/\\]_rietveld[\/\\].+',
29
+ r'^testing_support[\/\\]_infra[\/\\].+',
30
+ ]
29
31
  if os.path.exists('.gitignore'):
30
32
  with open('.gitignore') as fh:
31
33
  lines = [l.strip() for l in fh.readlines()]
@@ -3,7 +3,7 @@ This package contains tools for working with Chromium development.
3
3
  The "gclient" wrapper knows how to keep this repository updated to
4
4
  the latest versions of these tools as found at:
5
5
 
6
- http://src.chromium.org/svn/trunk/tools/depot_tools
6
+ https://chromium.googlesource.com/chromium/tools/depot_tools/+/master/gclient.py
7
7
 
8
8
  This package contains:
9
9
 
@@ -25,11 +25,6 @@ This package contains:
25
25
  More info at:
26
26
  http://code.google.com/p/gclient/
27
27
 
28
- hammer
29
- A wrapper script for building Chromium with the SCons software
30
- construction tool. More info at:
31
- http://www.scons.org/
32
-
33
28
  Note: svn and python will be installed automatically if not accessible (on
34
29
  Windows only).
35
30
 
@@ -92,6 +92,10 @@ def _get_arg_parser():
92
92
  help='Don\'t patch specified file(s).')
93
93
  parser.add_option('-d', '--ignore_deps', action='store_true',
94
94
  help='Don\'t run gclient sync on DEPS changes.')
95
+ parser.add_option('--extra_patchlevel', type='int',
96
+ help='Number of directories the patch level number should '
97
+ 'be incremented (useful for patches from repos with '
98
+ 'different directory hierarchies).')
95
99
 
96
100
  auth.add_auth_options(parser)
97
101
  return parser
@@ -255,6 +259,8 @@ def main():
255
259
  if patch.filename not in options.blacklist]
256
260
  for patch in patchset.patches:
257
261
  print(patch)
262
+ if options.extra_patchlevel:
263
+ patch.patchlevel += options.extra_patchlevel
258
264
  full_dir = os.path.abspath(options.root_dir)
259
265
  scm_type = scm.determine_scm(full_dir)
260
266
  if scm_type == 'svn':
@@ -53,14 +53,14 @@ than the rest of this README.
53
53
 
54
54
  ### Python
55
55
 
56
- Python installs are sourced from https://src.chromium.org/viewvc/chrome/trunk/tools/ .
56
+ Python installs are sourced from gs://chrome-infra/python276_bin.zip .
57
57
 
58
58
  The process to create them is sort-of-documented in the README of the python
59
59
  zip file.
60
60
 
61
61
  ### Subversion
62
62
 
63
- Subversion installs are sourced from https://src.chromium.org/viewvc/chrome/trunk/tools/ .
63
+ Subversion installs are sourced from gs://chrome-infra/svn_bin.zip .
64
64
 
65
65
  There will likely never be an update to SVN in `depot_tools` from the current
66
66
  version.
@@ -1,5 +1,5 @@
1
1
  @echo off
2
2
  setlocal
3
3
  if not defined EDITOR set EDITOR=notepad
4
- set PATH=%~dp0GIT_BIN_DIR\cmd;%PATH%
4
+ set PATH=%~dp0GIT_BIN_DIR\cmd;%~dp0;%PATH%
5
5
  "%~dp0GIT_BIN_DIR\GIT_PROGRAM" %*
@@ -9,7 +9,7 @@
9
9
  :: Sadly, we can't use SETLOCAL here otherwise it ERRORLEVEL is not correctly
10
10
  :: returned.
11
11
 
12
- set WIN_TOOLS_ROOT_URL=https://src.chromium.org/svn/trunk/tools
12
+ set CHROME_INFRA_URL=https://storage.googleapis.com/chrome-infra/
13
13
  :: It used to be %~dp0 but ADODB.Stream may fail to write to this directory if
14
14
  :: the directory DACL is set to elevated integrity level.
15
15
  set ZIP_DIR=%TEMP%
@@ -35,10 +35,11 @@ goto :GIT_CHECK
35
35
  :PY27_INSTALL
36
36
  echo Installing python 2.7.6...
37
37
  :: Cleanup python directory if it was existing.
38
+ set PYTHON_URL=%CHROME_INFRA_URL%python276_bin.zip
38
39
  if exist "%WIN_TOOLS_ROOT_DIR%\python276_bin\." rd /q /s "%WIN_TOOLS_ROOT_DIR%\python276_bin"
39
40
  if exist "%ZIP_DIR%\python276.zip" del "%ZIP_DIR%\python276.zip"
40
- echo Fetching from %WIN_TOOLS_ROOT_URL%/third_party/python276_bin.zip
41
- cscript //nologo //e:jscript "%~dp0get_file.js" %WIN_TOOLS_ROOT_URL%/third_party/python276_bin.zip "%ZIP_DIR%\python276_bin.zip"
41
+ echo Fetching from %PYTHON_URL%
42
+ cscript //nologo //e:jscript "%~dp0get_file.js" %PYTHON_URL% "%ZIP_DIR%\python276_bin.zip"
42
43
  if errorlevel 1 goto :PYTHON_FAIL
43
44
  :: Will create python276_bin\...
44
45
  cscript //nologo //e:jscript "%~dp0unzip.js" "%ZIP_DIR%\python276_bin.zip" "%WIN_TOOLS_ROOT_DIR%"
@@ -52,7 +53,7 @@ goto :GIT_CHECK
52
53
 
53
54
  :PYTHON_FAIL
54
55
  echo ... Failed to checkout python automatically.
55
- echo You should get the "prebaked" version at %WIN_TOOLS_ROOT_URL%/third_party/
56
+ echo You should get the "prebaked" version at %PYTHON_URL%
56
57
  set ERRORLEVEL=1
57
58
  goto :END
58
59
 
@@ -67,13 +68,13 @@ set FIND_EXE=%SYSTEMROOT%\System32\find.exe
67
68
  reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | %FIND_EXE% /i "x86" > NUL && (set OS_BITS=32) || (set OS_BITS=64)
68
69
 
69
70
  if not exist "%WIN_TOOLS_ROOT_DIR%\.git_bleeding_edge" (
70
- set GIT_VERSION=2.7.4
71
+ set GIT_VERSION=2.8.3
71
72
  ) else (
72
- set GIT_VERSION=2.8.1
73
+ set GIT_VERSION=2.8.3
73
74
  )
74
75
  set GIT_VERSION=%GIT_VERSION%-%OS_BITS%
75
76
 
76
- set GIT_FETCH_URL=https://storage.googleapis.com/chrome-infra/PortableGit-%GIT_VERSION%-bit.7z.exe
77
+ set GIT_FETCH_URL=%CHROME_INFRA_URL%PortableGit-%GIT_VERSION%-bit.7z.exe
77
78
  set GIT_DOWNLOAD_PATH=%ZIP_DIR%\git.7z.exe
78
79
  set GIT_BIN_DIR=git-%GIT_VERSION%_bin
79
80
  set GIT_INST_DIR=%WIN_TOOLS_ROOT_DIR%\%GIT_BIN_DIR%
@@ -190,9 +191,10 @@ goto :END
190
191
  :SVN_INSTALL
191
192
  echo Installing subversion ...
192
193
  :: svn is not accessible; check it out and create 'proxy' files.
194
+ set SVN_URL=%CHROME_INFRA_URL%svn_bin.zip
193
195
  if exist "%ZIP_DIR%\svn.zip" del "%ZIP_DIR%\svn.zip"
194
- echo Fetching from %WIN_TOOLS_ROOT_URL%/third_party/svn_bin.zip
195
- cscript //nologo //e:jscript "%~dp0get_file.js" %WIN_TOOLS_ROOT_URL%/third_party/svn_bin.zip "%ZIP_DIR%\svn.zip"
196
+ echo Fetching from %SVN_URL%
197
+ cscript //nologo //e:jscript "%~dp0get_file.js" %SVN_URL% "%ZIP_DIR%\svn.zip"
196
198
  if errorlevel 1 goto :SVN_FAIL
197
199
  :: Cleanup svn directory if it was existing.
198
200
  if exist "%WIN_TOOLS_ROOT_DIR%\svn\." rd /q /s "%WIN_TOOLS_ROOT_DIR%\svn"
@@ -210,13 +212,12 @@ goto :END
210
212
 
211
213
  :SVN_FAIL
212
214
  echo ... Failed to checkout svn automatically.
213
- echo You should get the "prebaked" version at %WIN_TOOLS_ROOT_URL%/third_party/
215
+ echo You should get the "prebaked" version at %SVN_URL%
214
216
  set ERRORLEVEL=1
215
217
  goto :END
216
218
 
217
219
 
218
220
  :returncode
219
- set WIN_TOOLS_ROOT_URL=
220
221
  set WIN_TOOLS_ROOT_DIR=
221
222
  exit /b %ERRORLEVEL%
222
223
 
@@ -1,5 +1,5 @@
1
1
  # This file is used by gcl to get repository specific information.
2
2
  CODE_REVIEW_SERVER: codereview.chromium.org
3
3
  CC_LIST: chromium-reviews@chromium.org
4
- VIEW_VC: http://src.chromium.org/viewvc/chrome?view=rev&revision=
4
+ VIEW_VC: https://chromium.googlesource.com/chromium/tools/depot_tools/+/
5
5
  PROJECT: depot_tools
@@ -60,7 +60,7 @@ Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
60
60
  <file> [file] ...
61
61
 
62
62
  The style guidelines this tries to follow are those in
63
- http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
63
+ https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
64
64
 
65
65
  Every problem is given a confidence score from 1-5, with 5 meaning we are
66
66
  certain of the problem, and 1 meaning it could be a legitimate construct.
@@ -177,6 +177,8 @@ Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
177
177
  _ERROR_CATEGORIES = [
178
178
  'build/class',
179
179
  'build/c++11',
180
+ 'build/c++14',
181
+ 'build/c++tr1',
180
182
  'build/deprecated',
181
183
  'build/endif_comment',
182
184
  'build/explicit_make_pair',
@@ -196,7 +198,6 @@ _ERROR_CATEGORIES = [
196
198
  'readability/check',
197
199
  'readability/constructors',
198
200
  'readability/fn_size',
199
- 'readability/function',
200
201
  'readability/inheritance',
201
202
  'readability/multiline_comment',
202
203
  'readability/multiline_string',
@@ -227,6 +228,7 @@ _ERROR_CATEGORIES = [
227
228
  'whitespace/comma',
228
229
  'whitespace/comments',
229
230
  'whitespace/empty_conditional_body',
231
+ 'whitespace/empty_if_body',
230
232
  'whitespace/empty_loop_body',
231
233
  'whitespace/end_of_line',
232
234
  'whitespace/ending_newline',
@@ -245,6 +247,7 @@ _ERROR_CATEGORIES = [
245
247
  # compatibility they may still appear in NOLINT comments.
246
248
  _LEGACY_ERROR_CATEGORIES = [
247
249
  'readability/streams',
250
+ 'readability/function',
248
251
  ]
249
252
 
250
253
  # The default state of the category filter. This is overridden by the --filter=
@@ -253,6 +256,16 @@ _LEGACY_ERROR_CATEGORIES = [
253
256
  # All entries here should start with a '-' or '+', as in the --filter= flag.
254
257
  _DEFAULT_FILTERS = ['-build/include_alpha']
255
258
 
259
+ # The default list of categories suppressed for C (not C++) files.
260
+ _DEFAULT_C_SUPPRESSED_CATEGORIES = [
261
+ 'readability/casting',
262
+ ]
263
+
264
+ # The default list of categories suppressed for Linux Kernel files.
265
+ _DEFAULT_KERNEL_SUPPRESSED_CATEGORIES = [
266
+ 'whitespace/tab',
267
+ ]
268
+
256
269
  # We used to check for high-bit characters, but after much discussion we
257
270
  # decided those were OK, as long as they were in UTF-8 and didn't represent
258
271
  # hard-coded international strings, which belong in a separate i18n file.
@@ -346,6 +359,7 @@ _CPP_HEADERS = frozenset([
346
359
  'random',
347
360
  'ratio',
348
361
  'regex',
362
+ 'scoped_allocator',
349
363
  'set',
350
364
  'sstream',
351
365
  'stack',
@@ -393,6 +407,19 @@ _CPP_HEADERS = frozenset([
393
407
  'cwctype',
394
408
  ])
395
409
 
410
+ # Type names
411
+ _TYPES = re.compile(
412
+ r'^(?:'
413
+ # [dcl.type.simple]
414
+ r'(char(16_t|32_t)?)|wchar_t|'
415
+ r'bool|short|int|long|signed|unsigned|float|double|'
416
+ # [support.types]
417
+ r'(ptrdiff_t|size_t|max_align_t|nullptr_t)|'
418
+ # [cstdint.syn]
419
+ r'(u?int(_fast|_least)?(8|16|32|64)_t)|'
420
+ r'(u?int(max|ptr)_t)|'
421
+ r')$')
422
+
396
423
 
397
424
  # These headers are excluded from [build/include] and [build/include_order]
398
425
  # checks:
@@ -402,16 +429,18 @@ _CPP_HEADERS = frozenset([
402
429
  _THIRD_PARTY_HEADERS_PATTERN = re.compile(
403
430
  r'^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$')
404
431
 
432
+ # Pattern for matching FileInfo.BaseName() against test file name
433
+ _TEST_FILE_SUFFIX = r'(_test|_unittest|_regtest)$'
434
+
435
+ # Pattern that matches only complete whitespace, possibly across multiple lines.
436
+ _EMPTY_CONDITIONAL_BODY_PATTERN = re.compile(r'^\s*$', re.DOTALL)
405
437
 
406
438
  # Assertion macros. These are defined in base/logging.h and
407
- # testing/base/gunit.h. Note that the _M versions need to come first
408
- # for substring matching to work.
439
+ # testing/base/public/gunit.h.
409
440
  _CHECK_MACROS = [
410
441
  'DCHECK', 'CHECK',
411
- 'EXPECT_TRUE_M', 'EXPECT_TRUE',
412
- 'ASSERT_TRUE_M', 'ASSERT_TRUE',
413
- 'EXPECT_FALSE_M', 'EXPECT_FALSE',
414
- 'ASSERT_FALSE_M', 'ASSERT_FALSE',
442
+ 'EXPECT_TRUE', 'ASSERT_TRUE',
443
+ 'EXPECT_FALSE', 'ASSERT_FALSE',
415
444
  ]
416
445
 
417
446
  # Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE
@@ -424,16 +453,12 @@ for op, replacement in [('==', 'EQ'), ('!=', 'NE'),
424
453
  _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement
425
454
  _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement
426
455
  _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement
427
- _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement
428
- _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement
429
456
 
430
457
  for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'),
431
458
  ('>=', 'LT'), ('>', 'LE'),
432
459
  ('<=', 'GT'), ('<', 'GE')]:
433
460
  _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement
434
461
  _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement
435
- _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement
436
- _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement
437
462
 
438
463
  # Alternative tokens and their replacements. For full list, see section 2.5
439
464
  # Alternative tokens [lex.digraph] in the C++ standard.
@@ -482,6 +507,12 @@ _MATCH_ASM = re.compile(r'^\s*(?:asm|_asm|__asm|__asm__)'
482
507
  r'(?:\s+(volatile|__volatile__))?'
483
508
  r'\s*[{(]')
484
509
 
510
+ # Match strings that indicate we're working on a C (not C++) file.
511
+ _SEARCH_C_FILE = re.compile(r'\b(?:LINT_C_FILE|'
512
+ r'vim?:\s*.*(\s*|:)filetype=c(\s*|:|$))')
513
+
514
+ # Match string that indicates we're working on a Linux Kernel file.
515
+ _SEARCH_KERNEL_FILE = re.compile(r'\b(?:LINT_KERNEL_FILE)')
485
516
 
486
517
  _regexp_compile_cache = {}
487
518
 
@@ -501,8 +532,13 @@ _line_length = 80
501
532
  # This is set by --extensions flag.
502
533
  _valid_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh'])
503
534
 
535
+ # {str, bool}: a map from error categories to booleans which indicate if the
536
+ # category should be suppressed for every line.
537
+ _global_error_suppressions = {}
538
+
539
+
504
540
  def ParseNolintSuppressions(filename, raw_line, linenum, error):
505
- """Updates the global list of error-suppressions.
541
+ """Updates the global list of line error-suppressions.
506
542
 
507
543
  Parses any NOLINT comments on the current line, updating the global
508
544
  error_suppressions store. Reports an error if the NOLINT comment
@@ -533,24 +569,45 @@ def ParseNolintSuppressions(filename, raw_line, linenum, error):
533
569
  'Unknown NOLINT error category: %s' % category)
534
570
 
535
571
 
572
+ def ProcessGlobalSuppresions(lines):
573
+ """Updates the list of global error suppressions.
574
+
575
+ Parses any lint directives in the file that have global effect.
576
+
577
+ Args:
578
+ lines: An array of strings, each representing a line of the file, with the
579
+ last element being empty if the file is terminated with a newline.
580
+ """
581
+ for line in lines:
582
+ if _SEARCH_C_FILE.search(line):
583
+ for category in _DEFAULT_C_SUPPRESSED_CATEGORIES:
584
+ _global_error_suppressions[category] = True
585
+ if _SEARCH_KERNEL_FILE.search(line):
586
+ for category in _DEFAULT_KERNEL_SUPPRESSED_CATEGORIES:
587
+ _global_error_suppressions[category] = True
588
+
589
+
536
590
  def ResetNolintSuppressions():
537
591
  """Resets the set of NOLINT suppressions to empty."""
538
592
  _error_suppressions.clear()
593
+ _global_error_suppressions.clear()
539
594
 
540
595
 
541
596
  def IsErrorSuppressedByNolint(category, linenum):
542
597
  """Returns true if the specified error category is suppressed on this line.
543
598
 
544
599
  Consults the global error_suppressions map populated by
545
- ParseNolintSuppressions/ResetNolintSuppressions.
600
+ ParseNolintSuppressions/ProcessGlobalSuppresions/ResetNolintSuppressions.
546
601
 
547
602
  Args:
548
603
  category: str, the category of the error.
549
604
  linenum: int, the current line number.
550
605
  Returns:
551
- bool, True iff the error should be suppressed due to a NOLINT comment.
606
+ bool, True iff the error should be suppressed due to a NOLINT comment or
607
+ global suppression.
552
608
  """
553
- return (linenum in _error_suppressions.get(category, set()) or
609
+ return (_global_error_suppressions.get(category, False) or
610
+ linenum in _error_suppressions.get(category, set()) or
554
611
  linenum in _error_suppressions.get(None, set()))
555
612
 
556
613
 
@@ -589,6 +646,11 @@ def Search(pattern, s):
589
646
  return _regexp_compile_cache[pattern].search(s)
590
647
 
591
648
 
649
+ def _IsSourceExtension(s):
650
+ """File extension (excluding dot) matches a source file extension."""
651
+ return s in ('c', 'cc', 'cpp', 'cxx')
652
+
653
+
592
654
  class _IncludeState(object):
593
655
  """Tracks line numbers for includes, and the order in which includes appear.
594
656
 
@@ -944,6 +1006,9 @@ class _FunctionState(object):
944
1006
  filename: The name of the current file.
945
1007
  linenum: The number of the line to check.
946
1008
  """
1009
+ if not self.in_a_function:
1010
+ return
1011
+
947
1012
  if Match(r'T(EST|est)', self.current_function):
948
1013
  base_trigger = self._TEST_TRIGGER
949
1014
  else:
@@ -1058,7 +1123,7 @@ class FileInfo(object):
1058
1123
 
1059
1124
  def IsSource(self):
1060
1125
  """File has a source file extension."""
1061
- return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx')
1126
+ return _IsSourceExtension(self.Extension()[1:])
1062
1127
 
1063
1128
 
1064
1129
  def _ShouldPrintError(category, confidence, linenum):
@@ -1204,8 +1269,18 @@ def CleanseRawStrings(raw_lines):
1204
1269
  while delimiter is None:
1205
1270
  # Look for beginning of a raw string.
1206
1271
  # See 2.14.15 [lex.string] for syntax.
1207
- matched = Match(r'^(.*)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
1208
- if matched:
1272
+ #
1273
+ # Once we have matched a raw string, we check the prefix of the
1274
+ # line to make sure that the line is not part of a single line
1275
+ # comment. It's done this way because we remove raw strings
1276
+ # before removing comments as opposed to removing comments
1277
+ # before removing raw strings. This is because there are some
1278
+ # cpplint checks that requires the comments to be preserved, but
1279
+ # we don't want to check comments that are inside raw strings.
1280
+ matched = Match(r'^(.*?)\b(?:R|u8R|uR|UR|LR)"([^\s\\()]*)\((.*)$', line)
1281
+ if (matched and
1282
+ not Match(r'^([^\'"]|\'(\\.|[^\'])*\'|"(\\.|[^"])*")*//',
1283
+ matched.group(1))):
1209
1284
  delimiter = ')' + matched.group(2) + '"'
1210
1285
 
1211
1286
  end = matched.group(3).find(delimiter)
@@ -1776,11 +1851,11 @@ def CheckHeaderFileIncluded(filename, include_state, error):
1776
1851
  """Logs an error if a .cc file does not include its header."""
1777
1852
 
1778
1853
  # Do not check test files
1779
- if filename.endswith('_test.cc') or filename.endswith('_unittest.cc'):
1854
+ fileinfo = FileInfo(filename)
1855
+ if Search(_TEST_FILE_SUFFIX, fileinfo.BaseName()):
1780
1856
  return
1781
1857
 
1782
- fileinfo = FileInfo(filename)
1783
- headerfile = filename[0:len(filename) - 2] + 'h'
1858
+ headerfile = filename[0:len(filename) - len(fileinfo.Extension())] + '.h'
1784
1859
  if not os.path.exists(headerfile):
1785
1860
  return
1786
1861
  headername = FileInfo(headerfile).RepositoryName()
@@ -1997,7 +2072,8 @@ def IsForwardClassDeclaration(clean_lines, linenum):
1997
2072
  class _BlockInfo(object):
1998
2073
  """Stores information about a generic block of code."""
1999
2074
 
2000
- def __init__(self, seen_open_brace):
2075
+ def __init__(self, linenum, seen_open_brace):
2076
+ self.starting_linenum = linenum
2001
2077
  self.seen_open_brace = seen_open_brace
2002
2078
  self.open_parentheses = 0
2003
2079
  self.inline_asm = _NO_ASM
@@ -2046,17 +2122,16 @@ class _BlockInfo(object):
2046
2122
  class _ExternCInfo(_BlockInfo):
2047
2123
  """Stores information about an 'extern "C"' block."""
2048
2124
 
2049
- def __init__(self):
2050
- _BlockInfo.__init__(self, True)
2125
+ def __init__(self, linenum):
2126
+ _BlockInfo.__init__(self, linenum, True)
2051
2127
 
2052
2128
 
2053
2129
  class _ClassInfo(_BlockInfo):
2054
2130
  """Stores information about a class."""
2055
2131
 
2056
2132
  def __init__(self, name, class_or_struct, clean_lines, linenum):
2057
- _BlockInfo.__init__(self, False)
2133
+ _BlockInfo.__init__(self, linenum, False)
2058
2134
  self.name = name
2059
- self.starting_linenum = linenum
2060
2135
  self.is_derived = False
2061
2136
  self.check_namespace_indentation = True
2062
2137
  if class_or_struct == 'struct':
@@ -2124,9 +2199,8 @@ class _NamespaceInfo(_BlockInfo):
2124
2199
  """Stores information about a namespace."""
2125
2200
 
2126
2201
  def __init__(self, name, linenum):
2127
- _BlockInfo.__init__(self, False)
2202
+ _BlockInfo.__init__(self, linenum, False)
2128
2203
  self.name = name or ''
2129
- self.starting_linenum = linenum
2130
2204
  self.check_namespace_indentation = True
2131
2205
 
2132
2206
  def CheckEnd(self, filename, clean_lines, linenum, error):
@@ -2145,7 +2219,7 @@ class _NamespaceInfo(_BlockInfo):
2145
2219
  # deciding what these nontrivial things are, so this check is
2146
2220
  # triggered by namespace size only, which works most of the time.
2147
2221
  if (linenum - self.starting_linenum < 10
2148
- and not Match(r'};*\s*(//|/\*).*\bnamespace\b', line)):
2222
+ and not Match(r'^\s*};*\s*(//|/\*).*\bnamespace\b', line)):
2149
2223
  return
2150
2224
 
2151
2225
  # Look for matching comment at end of namespace.
@@ -2162,18 +2236,18 @@ class _NamespaceInfo(_BlockInfo):
2162
2236
  # expected namespace.
2163
2237
  if self.name:
2164
2238
  # Named namespace
2165
- if not Match((r'};*\s*(//|/\*).*\bnamespace\s+' + re.escape(self.name) +
2166
- r'[\*/\.\\\s]*$'),
2239
+ if not Match((r'^\s*};*\s*(//|/\*).*\bnamespace\s+' +
2240
+ re.escape(self.name) + r'[\*/\.\\\s]*$'),
2167
2241
  line):
2168
2242
  error(filename, linenum, 'readability/namespace', 5,
2169
2243
  'Namespace should be terminated with "// namespace %s"' %
2170
2244
  self.name)
2171
2245
  else:
2172
2246
  # Anonymous namespace
2173
- if not Match(r'};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
2247
+ if not Match(r'^\s*};*\s*(//|/\*).*\bnamespace[\*/\.\\\s]*$', line):
2174
2248
  # If "// namespace anonymous" or "// anonymous namespace (more text)",
2175
2249
  # mention "// anonymous namespace" as an acceptable form
2176
- if Match(r'}.*\b(namespace anonymous|anonymous namespace)\b', line):
2250
+ if Match(r'^\s*}.*\b(namespace anonymous|anonymous namespace)\b', line):
2177
2251
  error(filename, linenum, 'readability/namespace', 5,
2178
2252
  'Anonymous namespace should be terminated with "// namespace"'
2179
2253
  ' or "// anonymous namespace"')
@@ -2512,9 +2586,9 @@ class NestingState(object):
2512
2586
  if not self.SeenOpenBrace():
2513
2587
  self.stack[-1].seen_open_brace = True
2514
2588
  elif Match(r'^extern\s*"[^"]*"\s*\{', line):
2515
- self.stack.append(_ExternCInfo())
2589
+ self.stack.append(_ExternCInfo(linenum))
2516
2590
  else:
2517
- self.stack.append(_BlockInfo(True))
2591
+ self.stack.append(_BlockInfo(linenum, True))
2518
2592
  if _MATCH_ASM.match(line):
2519
2593
  self.stack[-1].inline_asm = _BLOCK_ASM
2520
2594
 
@@ -2626,7 +2700,8 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum,
2626
2700
  r'\s+(register|static|extern|typedef)\b',
2627
2701
  line):
2628
2702
  error(filename, linenum, 'build/storage_class', 5,
2629
- 'Storage class (static, extern, typedef, etc) should be first.')
2703
+ 'Storage-class specifier (static, extern, typedef, etc) should be '
2704
+ 'at the beginning of the declaration.')
2630
2705
 
2631
2706
  if Match(r'\s*#\s*endif\s*[^/\s]+', line):
2632
2707
  error(filename, linenum, 'build/endif_comment', 5,
@@ -2665,9 +2740,7 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum,
2665
2740
  base_classname = classinfo.name.split('::')[-1]
2666
2741
 
2667
2742
  # Look for single-argument constructors that aren't marked explicit.
2668
- # Technically a valid construct, but against style. Also look for
2669
- # non-single-argument constructors which are also technically valid, but
2670
- # strongly suggest something is wrong.
2743
+ # Technically a valid construct, but against style.
2671
2744
  explicit_constructor_match = Match(
2672
2745
  r'\s+(?:inline\s+)?(explicit\s+)?(?:inline\s+)?%s\s*'
2673
2746
  r'\(((?:[^()]|\([^()]*\))*)\)'
@@ -2728,10 +2801,6 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum,
2728
2801
  if noarg_constructor:
2729
2802
  error(filename, linenum, 'runtime/explicit', 5,
2730
2803
  'Zero-parameter constructors should not be marked explicit.')
2731
- else:
2732
- error(filename, linenum, 'runtime/explicit', 0,
2733
- 'Constructors that require multiple arguments '
2734
- 'should not be marked explicit.')
2735
2804
 
2736
2805
 
2737
2806
  def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
@@ -2786,6 +2855,7 @@ def CheckSpacingForFunctionCall(filename, clean_lines, linenum, error):
2786
2855
  error(filename, linenum, 'whitespace/parens', 2,
2787
2856
  'Extra space after (')
2788
2857
  if (Search(r'\w\s+\(', fncall) and
2858
+ not Search(r'_{0,2}asm_{0,2}\s+_{0,2}volatile_{0,2}\s+\(', fncall) and
2789
2859
  not Search(r'#\s*define|typedef|using\s+\w+\s*=', fncall) and
2790
2860
  not Search(r'\w\s+\((\w+::)*\*\w+\)\(', fncall) and
2791
2861
  not Search(r'\bcase\s+\(', fncall)):
@@ -2844,7 +2914,7 @@ def CheckForFunctionLengths(filename, clean_lines, linenum,
2844
2914
  """Reports for long function bodies.
2845
2915
 
2846
2916
  For an overview why this is done, see:
2847
- http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
2917
+ https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
2848
2918
 
2849
2919
  Uses a simplistic algorithm assuming other style guidelines
2850
2920
  (especially spacing) are followed.
@@ -2923,9 +2993,7 @@ def CheckComment(line, filename, linenum, next_line_start, error):
2923
2993
  commentpos = line.find('//')
2924
2994
  if commentpos != -1:
2925
2995
  # Check if the // may be in quotes. If so, ignore it
2926
- # Comparisons made explicit for clarity -- pylint: disable=g-explicit-bool-comparison
2927
- if (line.count('"', 0, commentpos) -
2928
- line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes
2996
+ if re.sub(r'\\.', '', line[0:commentpos]).count('"') % 2 == 0:
2929
2997
  # Allow one space for new scopes, two spaces otherwise:
2930
2998
  if (not (Match(r'^.*{ *//', line) and next_line_start == commentpos) and
2931
2999
  ((commentpos >= 1 and
@@ -3174,8 +3242,8 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
3174
3242
  # macro context and don't do any checks. This avoids false
3175
3243
  # positives.
3176
3244
  #
3177
- # Note that && is not included here. Those are checked separately
3178
- # in CheckRValueReference
3245
+ # Note that && is not included here. This is because there are too
3246
+ # many false positives due to RValue references.
3179
3247
  match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line)
3180
3248
  if match:
3181
3249
  error(filename, linenum, 'whitespace/operators', 3,
@@ -3209,7 +3277,7 @@ def CheckOperatorSpacing(filename, clean_lines, linenum, error):
3209
3277
  #
3210
3278
  # We also allow operators following an opening parenthesis, since
3211
3279
  # those tend to be macros that deal with operators.
3212
- match = Search(r'(operator|[^\s(<])(?:L|UL|ULL|l|ul|ull)?<<([^\s,=<])', line)
3280
+ match = Search(r'(operator|[^\s(<])(?:L|UL|LL|ULL|l|ul|ll|ull)?<<([^\s,=<])', line)
3213
3281
  if (match and not (match.group(1).isdigit() and match.group(2).isdigit()) and
3214
3282
  not (match.group(1) == 'operator' and match.group(2) == ';')):
3215
3283
  error(filename, linenum, 'whitespace/operators', 3,
@@ -3313,22 +3381,90 @@ def CheckCommaSpacing(filename, clean_lines, linenum, error):
3313
3381
  'Missing space after ;')
3314
3382
 
3315
3383
 
3316
- def CheckBracesSpacing(filename, clean_lines, linenum, error):
3384
+ def _IsType(clean_lines, nesting_state, expr):
3385
+ """Check if expression looks like a type name, returns true if so.
3386
+
3387
+ Args:
3388
+ clean_lines: A CleansedLines instance containing the file.
3389
+ nesting_state: A NestingState instance which maintains information about
3390
+ the current stack of nested blocks being parsed.
3391
+ expr: The expression to check.
3392
+ Returns:
3393
+ True, if token looks like a type.
3394
+ """
3395
+ # Keep only the last token in the expression
3396
+ last_word = Match(r'^.*(\b\S+)$', expr)
3397
+ if last_word:
3398
+ token = last_word.group(1)
3399
+ else:
3400
+ token = expr
3401
+
3402
+ # Match native types and stdint types
3403
+ if _TYPES.match(token):
3404
+ return True
3405
+
3406
+ # Try a bit harder to match templated types. Walk up the nesting
3407
+ # stack until we find something that resembles a typename
3408
+ # declaration for what we are looking for.
3409
+ typename_pattern = (r'\b(?:typename|class|struct)\s+' + re.escape(token) +
3410
+ r'\b')
3411
+ block_index = len(nesting_state.stack) - 1
3412
+ while block_index >= 0:
3413
+ if isinstance(nesting_state.stack[block_index], _NamespaceInfo):
3414
+ return False
3415
+
3416
+ # Found where the opening brace is. We want to scan from this
3417
+ # line up to the beginning of the function, minus a few lines.
3418
+ # template <typename Type1, // stop scanning here
3419
+ # ...>
3420
+ # class C
3421
+ # : public ... { // start scanning here
3422
+ last_line = nesting_state.stack[block_index].starting_linenum
3423
+
3424
+ next_block_start = 0
3425
+ if block_index > 0:
3426
+ next_block_start = nesting_state.stack[block_index - 1].starting_linenum
3427
+ first_line = last_line
3428
+ while first_line >= next_block_start:
3429
+ if clean_lines.elided[first_line].find('template') >= 0:
3430
+ break
3431
+ first_line -= 1
3432
+ if first_line < next_block_start:
3433
+ # Didn't find any "template" keyword before reaching the next block,
3434
+ # there are probably no template things to check for this block
3435
+ block_index -= 1
3436
+ continue
3437
+
3438
+ # Look for typename in the specified range
3439
+ for i in xrange(first_line, last_line + 1, 1):
3440
+ if Search(typename_pattern, clean_lines.elided[i]):
3441
+ return True
3442
+ block_index -= 1
3443
+
3444
+ return False
3445
+
3446
+
3447
+ def CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error):
3317
3448
  """Checks for horizontal spacing near commas.
3318
3449
 
3319
3450
  Args:
3320
3451
  filename: The name of the current file.
3321
3452
  clean_lines: A CleansedLines instance containing the file.
3322
3453
  linenum: The number of the line to check.
3454
+ nesting_state: A NestingState instance which maintains information about
3455
+ the current stack of nested blocks being parsed.
3323
3456
  error: The function to call with any errors found.
3324
3457
  """
3325
3458
  line = clean_lines.elided[linenum]
3326
3459
 
3327
3460
  # Except after an opening paren, or after another opening brace (in case of
3328
3461
  # an initializer list, for instance), you should have spaces before your
3329
- # braces. And since you should never have braces at the beginning of a line,
3330
- # this is an easy test.
3462
+ # braces when they are delimiting blocks, classes, namespaces etc.
3463
+ # And since you should never have braces at the beginning of a line,
3464
+ # this is an easy test. Except that braces used for initialization don't
3465
+ # follow the same rule; we often don't want spaces before those.
3331
3466
  match = Match(r'^(.*[^ ({>]){', line)
3467
+
3332
3468
  if match:
3333
3469
  # Try a bit harder to check for brace initialization. This
3334
3470
  # happens in one of the following forms:
@@ -3358,6 +3494,7 @@ def CheckBracesSpacing(filename, clean_lines, linenum, error):
3358
3494
  # There is a false negative with this approach if people inserted
3359
3495
  # spurious semicolons, e.g. "if (cond){};", but we will catch the
3360
3496
  # spurious semicolon with a separate check.
3497
+ leading_text = match.group(1)
3361
3498
  (endline, endlinenum, endpos) = CloseExpression(
3362
3499
  clean_lines, linenum, len(match.group(1)))
3363
3500
  trailing_text = ''
@@ -3366,7 +3503,11 @@ def CheckBracesSpacing(filename, clean_lines, linenum, error):
3366
3503
  for offset in xrange(endlinenum + 1,
3367
3504
  min(endlinenum + 3, clean_lines.NumLines() - 1)):
3368
3505
  trailing_text += clean_lines.elided[offset]
3369
- if not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text):
3506
+ # We also suppress warnings for `uint64_t{expression}` etc., as the style
3507
+ # guide recommends brace initialization for integral types to avoid
3508
+ # overflow/truncation.
3509
+ if (not Match(r'^[\s}]*[{.;,)<>\]:]', trailing_text)
3510
+ and not _IsType(clean_lines, nesting_state, leading_text)):
3370
3511
  error(filename, linenum, 'whitespace/braces', 5,
3371
3512
  'Missing space before {')
3372
3513
 
@@ -3410,405 +3551,6 @@ def IsDecltype(clean_lines, linenum, column):
3410
3551
  return False
3411
3552
 
3412
3553
 
3413
- def IsTemplateParameterList(clean_lines, linenum, column):
3414
- """Check if the token ending on (linenum, column) is the end of template<>.
3415
-
3416
- Args:
3417
- clean_lines: A CleansedLines instance containing the file.
3418
- linenum: the number of the line to check.
3419
- column: end column of the token to check.
3420
- Returns:
3421
- True if this token is end of a template parameter list, False otherwise.
3422
- """
3423
- (_, startline, startpos) = ReverseCloseExpression(
3424
- clean_lines, linenum, column)
3425
- if (startpos > -1 and
3426
- Search(r'\btemplate\s*$', clean_lines.elided[startline][0:startpos])):
3427
- return True
3428
- return False
3429
-
3430
-
3431
- def IsRValueType(typenames, clean_lines, nesting_state, linenum, column):
3432
- """Check if the token ending on (linenum, column) is a type.
3433
-
3434
- Assumes that text to the right of the column is "&&" or a function
3435
- name.
3436
-
3437
- Args:
3438
- typenames: set of type names from template-argument-list.
3439
- clean_lines: A CleansedLines instance containing the file.
3440
- nesting_state: A NestingState instance which maintains information about
3441
- the current stack of nested blocks being parsed.
3442
- linenum: the number of the line to check.
3443
- column: end column of the token to check.
3444
- Returns:
3445
- True if this token is a type, False if we are not sure.
3446
- """
3447
- prefix = clean_lines.elided[linenum][0:column]
3448
-
3449
- # Get one word to the left. If we failed to do so, this is most
3450
- # likely not a type, since it's unlikely that the type name and "&&"
3451
- # would be split across multiple lines.
3452
- match = Match(r'^(.*)(\b\w+|[>*)&])\s*$', prefix)
3453
- if not match:
3454
- return False
3455
-
3456
- # Check text following the token. If it's "&&>" or "&&," or "&&...", it's
3457
- # most likely a rvalue reference used inside a template.
3458
- suffix = clean_lines.elided[linenum][column:]
3459
- if Match(r'&&\s*(?:[>,]|\.\.\.)', suffix):
3460
- return True
3461
-
3462
- # Check for known types and end of templates:
3463
- # int&& variable
3464
- # vector<int>&& variable
3465
- #
3466
- # Because this function is called recursively, we also need to
3467
- # recognize pointer and reference types:
3468
- # int* Function()
3469
- # int& Function()
3470
- if (match.group(2) in typenames or
3471
- match.group(2) in ['char', 'char16_t', 'char32_t', 'wchar_t', 'bool',
3472
- 'short', 'int', 'long', 'signed', 'unsigned',
3473
- 'float', 'double', 'void', 'auto', '>', '*', '&']):
3474
- return True
3475
-
3476
- # If we see a close parenthesis, look for decltype on the other side.
3477
- # decltype would unambiguously identify a type, anything else is
3478
- # probably a parenthesized expression and not a type.
3479
- if match.group(2) == ')':
3480
- return IsDecltype(
3481
- clean_lines, linenum, len(match.group(1)) + len(match.group(2)) - 1)
3482
-
3483
- # Check for casts and cv-qualifiers.
3484
- # match.group(1) remainder
3485
- # -------------- ---------
3486
- # const_cast< type&&
3487
- # const type&&
3488
- # type const&&
3489
- if Search(r'\b(?:const_cast\s*<|static_cast\s*<|dynamic_cast\s*<|'
3490
- r'reinterpret_cast\s*<|\w+\s)\s*$',
3491
- match.group(1)):
3492
- return True
3493
-
3494
- # Look for a preceding symbol that might help differentiate the context.
3495
- # These are the cases that would be ambiguous:
3496
- # match.group(1) remainder
3497
- # -------------- ---------
3498
- # Call ( expression &&
3499
- # Declaration ( type&&
3500
- # sizeof ( type&&
3501
- # if ( expression &&
3502
- # while ( expression &&
3503
- # for ( type&&
3504
- # for( ; expression &&
3505
- # statement ; type&&
3506
- # block { type&&
3507
- # constructor { expression &&
3508
- start = linenum
3509
- line = match.group(1)
3510
- match_symbol = None
3511
- while start >= 0:
3512
- # We want to skip over identifiers and commas to get to a symbol.
3513
- # Commas are skipped so that we can find the opening parenthesis
3514
- # for function parameter lists.
3515
- match_symbol = Match(r'^(.*)([^\w\s,])[\w\s,]*$', line)
3516
- if match_symbol:
3517
- break
3518
- start -= 1
3519
- line = clean_lines.elided[start]
3520
-
3521
- if not match_symbol:
3522
- # Probably the first statement in the file is an rvalue reference
3523
- return True
3524
-
3525
- if match_symbol.group(2) == '}':
3526
- # Found closing brace, probably an indicate of this:
3527
- # block{} type&&
3528
- return True
3529
-
3530
- if match_symbol.group(2) == ';':
3531
- # Found semicolon, probably one of these:
3532
- # for(; expression &&
3533
- # statement; type&&
3534
-
3535
- # Look for the previous 'for(' in the previous lines.
3536
- before_text = match_symbol.group(1)
3537
- for i in xrange(start - 1, max(start - 6, 0), -1):
3538
- before_text = clean_lines.elided[i] + before_text
3539
- if Search(r'for\s*\([^{};]*$', before_text):
3540
- # This is the condition inside a for-loop
3541
- return False
3542
-
3543
- # Did not find a for-init-statement before this semicolon, so this
3544
- # is probably a new statement and not a condition.
3545
- return True
3546
-
3547
- if match_symbol.group(2) == '{':
3548
- # Found opening brace, probably one of these:
3549
- # block{ type&& = ... ; }
3550
- # constructor{ expression && expression }
3551
-
3552
- # Look for a closing brace or a semicolon. If we see a semicolon
3553
- # first, this is probably a rvalue reference.
3554
- line = clean_lines.elided[start][0:len(match_symbol.group(1)) + 1]
3555
- end = start
3556
- depth = 1
3557
- while True:
3558
- for ch in line:
3559
- if ch == ';':
3560
- return True
3561
- elif ch == '{':
3562
- depth += 1
3563
- elif ch == '}':
3564
- depth -= 1
3565
- if depth == 0:
3566
- return False
3567
- end += 1
3568
- if end >= clean_lines.NumLines():
3569
- break
3570
- line = clean_lines.elided[end]
3571
- # Incomplete program?
3572
- return False
3573
-
3574
- if match_symbol.group(2) == '(':
3575
- # Opening parenthesis. Need to check what's to the left of the
3576
- # parenthesis. Look back one extra line for additional context.
3577
- before_text = match_symbol.group(1)
3578
- if linenum > 1:
3579
- before_text = clean_lines.elided[linenum - 1] + before_text
3580
- before_text = match_symbol.group(1)
3581
-
3582
- # Patterns that are likely to be types:
3583
- # [](type&&
3584
- # for (type&&
3585
- # sizeof(type&&
3586
- # operator=(type&&
3587
- #
3588
- if Search(r'(?:\]|\bfor|\bsizeof|\boperator\s*\S+\s*)\s*$', before_text):
3589
- return True
3590
-
3591
- # Patterns that are likely to be expressions:
3592
- # if (expression &&
3593
- # while (expression &&
3594
- # : initializer(expression &&
3595
- # , initializer(expression &&
3596
- # ( FunctionCall(expression &&
3597
- # + FunctionCall(expression &&
3598
- # + (expression &&
3599
- #
3600
- # The last '+' represents operators such as '+' and '-'.
3601
- if Search(r'(?:\bif|\bwhile|[-+=%^(<!?:,&*]\s*)$', before_text):
3602
- return False
3603
-
3604
- # Something else. Check that tokens to the left look like
3605
- # return_type function_name
3606
- match_func = Match(r'^(.*\S.*)\s+\w(?:\w|::)*(?:<[^<>]*>)?\s*$',
3607
- match_symbol.group(1))
3608
- if match_func:
3609
- # Check for constructors, which don't have return types.
3610
- if Search(r'\b(?:explicit|inline)$', match_func.group(1)):
3611
- return True
3612
- implicit_constructor = Match(r'\s*(\w+)\((?:const\s+)?(\w+)', prefix)
3613
- if (implicit_constructor and
3614
- implicit_constructor.group(1) == implicit_constructor.group(2)):
3615
- return True
3616
- return IsRValueType(typenames, clean_lines, nesting_state, linenum,
3617
- len(match_func.group(1)))
3618
-
3619
- # Nothing before the function name. If this is inside a block scope,
3620
- # this is probably a function call.
3621
- return not (nesting_state.previous_stack_top and
3622
- nesting_state.previous_stack_top.IsBlockInfo())
3623
-
3624
- if match_symbol.group(2) == '>':
3625
- # Possibly a closing bracket, check that what's on the other side
3626
- # looks like the start of a template.
3627
- return IsTemplateParameterList(
3628
- clean_lines, start, len(match_symbol.group(1)))
3629
-
3630
- # Some other symbol, usually something like "a=b&&c". This is most
3631
- # likely not a type.
3632
- return False
3633
-
3634
-
3635
- def IsDeletedOrDefault(clean_lines, linenum):
3636
- """Check if current constructor or operator is deleted or default.
3637
-
3638
- Args:
3639
- clean_lines: A CleansedLines instance containing the file.
3640
- linenum: The number of the line to check.
3641
- Returns:
3642
- True if this is a deleted or default constructor.
3643
- """
3644
- open_paren = clean_lines.elided[linenum].find('(')
3645
- if open_paren < 0:
3646
- return False
3647
- (close_line, _, close_paren) = CloseExpression(
3648
- clean_lines, linenum, open_paren)
3649
- if close_paren < 0:
3650
- return False
3651
- return Match(r'\s*=\s*(?:delete|default)\b', close_line[close_paren:])
3652
-
3653
-
3654
- def IsRValueAllowed(clean_lines, linenum, typenames):
3655
- """Check if RValue reference is allowed on a particular line.
3656
-
3657
- Args:
3658
- clean_lines: A CleansedLines instance containing the file.
3659
- linenum: The number of the line to check.
3660
- typenames: set of type names from template-argument-list.
3661
- Returns:
3662
- True if line is within the region where RValue references are allowed.
3663
- """
3664
- # Allow region marked by PUSH/POP macros
3665
- for i in xrange(linenum, 0, -1):
3666
- line = clean_lines.elided[i]
3667
- if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line):
3668
- if not line.endswith('PUSH'):
3669
- return False
3670
- for j in xrange(linenum, clean_lines.NumLines(), 1):
3671
- line = clean_lines.elided[j]
3672
- if Match(r'GOOGLE_ALLOW_RVALUE_REFERENCES_(?:PUSH|POP)', line):
3673
- return line.endswith('POP')
3674
-
3675
- # Allow operator=
3676
- line = clean_lines.elided[linenum]
3677
- if Search(r'\boperator\s*=\s*\(', line):
3678
- return IsDeletedOrDefault(clean_lines, linenum)
3679
-
3680
- # Allow constructors
3681
- match = Match(r'\s*(?:[\w<>]+::)*([\w<>]+)\s*::\s*([\w<>]+)\s*\(', line)
3682
- if match and match.group(1) == match.group(2):
3683
- return IsDeletedOrDefault(clean_lines, linenum)
3684
- if Search(r'\b(?:explicit|inline)\s+[\w<>]+\s*\(', line):
3685
- return IsDeletedOrDefault(clean_lines, linenum)
3686
-
3687
- if Match(r'\s*[\w<>]+\s*\(', line):
3688
- previous_line = 'ReturnType'
3689
- if linenum > 0:
3690
- previous_line = clean_lines.elided[linenum - 1]
3691
- if Match(r'^\s*$', previous_line) or Search(r'[{}:;]\s*$', previous_line):
3692
- return IsDeletedOrDefault(clean_lines, linenum)
3693
-
3694
- # Reject types not mentioned in template-argument-list
3695
- while line:
3696
- match = Match(r'^.*?(\w+)\s*&&(.*)$', line)
3697
- if not match:
3698
- break
3699
- if match.group(1) not in typenames:
3700
- return False
3701
- line = match.group(2)
3702
-
3703
- # All RValue types that were in template-argument-list should have
3704
- # been removed by now. Those were allowed, assuming that they will
3705
- # be forwarded.
3706
- #
3707
- # If there are no remaining RValue types left (i.e. types that were
3708
- # not found in template-argument-list), flag those as not allowed.
3709
- return line.find('&&') < 0
3710
-
3711
-
3712
- def GetTemplateArgs(clean_lines, linenum):
3713
- """Find list of template arguments associated with this function declaration.
3714
-
3715
- Args:
3716
- clean_lines: A CleansedLines instance containing the file.
3717
- linenum: Line number containing the start of the function declaration,
3718
- usually one line after the end of the template-argument-list.
3719
- Returns:
3720
- Set of type names, or empty set if this does not appear to have
3721
- any template parameters.
3722
- """
3723
- # Find start of function
3724
- func_line = linenum
3725
- while func_line > 0:
3726
- line = clean_lines.elided[func_line]
3727
- if Match(r'^\s*$', line):
3728
- return set()
3729
- if line.find('(') >= 0:
3730
- break
3731
- func_line -= 1
3732
- if func_line == 0:
3733
- return set()
3734
-
3735
- # Collapse template-argument-list into a single string
3736
- argument_list = ''
3737
- match = Match(r'^(\s*template\s*)<', clean_lines.elided[func_line])
3738
- if match:
3739
- # template-argument-list on the same line as function name
3740
- start_col = len(match.group(1))
3741
- _, end_line, end_col = CloseExpression(clean_lines, func_line, start_col)
3742
- if end_col > -1 and end_line == func_line:
3743
- start_col += 1 # Skip the opening bracket
3744
- argument_list = clean_lines.elided[func_line][start_col:end_col]
3745
-
3746
- elif func_line > 1:
3747
- # template-argument-list one line before function name
3748
- match = Match(r'^(.*)>\s*$', clean_lines.elided[func_line - 1])
3749
- if match:
3750
- end_col = len(match.group(1))
3751
- _, start_line, start_col = ReverseCloseExpression(
3752
- clean_lines, func_line - 1, end_col)
3753
- if start_col > -1:
3754
- start_col += 1 # Skip the opening bracket
3755
- while start_line < func_line - 1:
3756
- argument_list += clean_lines.elided[start_line][start_col:]
3757
- start_col = 0
3758
- start_line += 1
3759
- argument_list += clean_lines.elided[func_line - 1][start_col:end_col]
3760
-
3761
- if not argument_list:
3762
- return set()
3763
-
3764
- # Extract type names
3765
- typenames = set()
3766
- while True:
3767
- match = Match(r'^[,\s]*(?:typename|class)(?:\.\.\.)?\s+(\w+)(.*)$',
3768
- argument_list)
3769
- if not match:
3770
- break
3771
- typenames.add(match.group(1))
3772
- argument_list = match.group(2)
3773
- return typenames
3774
-
3775
-
3776
- def CheckRValueReference(filename, clean_lines, linenum, nesting_state, error):
3777
- """Check for rvalue references.
3778
-
3779
- Args:
3780
- filename: The name of the current file.
3781
- clean_lines: A CleansedLines instance containing the file.
3782
- linenum: The number of the line to check.
3783
- nesting_state: A NestingState instance which maintains information about
3784
- the current stack of nested blocks being parsed.
3785
- error: The function to call with any errors found.
3786
- """
3787
- # Find lines missing spaces around &&.
3788
- # TODO(unknown): currently we don't check for rvalue references
3789
- # with spaces surrounding the && to avoid false positives with
3790
- # boolean expressions.
3791
- line = clean_lines.elided[linenum]
3792
- match = Match(r'^(.*\S)&&', line)
3793
- if not match:
3794
- match = Match(r'(.*)&&\S', line)
3795
- if (not match) or '(&&)' in line or Search(r'\boperator\s*$', match.group(1)):
3796
- return
3797
-
3798
- # Either poorly formed && or an rvalue reference, check the context
3799
- # to get a more accurate error message. Mostly we want to determine
3800
- # if what's to the left of "&&" is a type or not.
3801
- typenames = GetTemplateArgs(clean_lines, linenum)
3802
- and_pos = len(match.group(1))
3803
- if IsRValueType(typenames, clean_lines, nesting_state, linenum, and_pos):
3804
- if not IsRValueAllowed(clean_lines, linenum, typenames):
3805
- error(filename, linenum, 'build/c++11', 3,
3806
- 'RValue references are an unapproved C++ feature.')
3807
- else:
3808
- error(filename, linenum, 'whitespace/operators', 3,
3809
- 'Missing spaces around &&')
3810
-
3811
-
3812
3554
  def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error):
3813
3555
  """Checks for additional blank line issues related to sections.
3814
3556
 
@@ -3906,10 +3648,13 @@ def CheckBraces(filename, clean_lines, linenum, error):
3906
3648
  # used for brace initializers inside function calls. We don't detect this
3907
3649
  # perfectly: we just don't complain if the last non-whitespace character on
3908
3650
  # the previous non-blank line is ',', ';', ':', '(', '{', or '}', or if the
3909
- # previous line starts a preprocessor block.
3651
+ # previous line starts a preprocessor block. We also allow a brace on the
3652
+ # following line if it is part of an array initialization and would not fit
3653
+ # within the 80 character limit of the preceding line.
3910
3654
  prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0]
3911
3655
  if (not Search(r'[,;:}{(]\s*$', prevline) and
3912
- not Match(r'\s*#', prevline)):
3656
+ not Match(r'\s*#', prevline) and
3657
+ not (GetLineWidth(prevline) > _line_length - 2 and '[]' in prevline)):
3913
3658
  error(filename, linenum, 'whitespace/braces', 4,
3914
3659
  '{ should almost always be at the end of the previous line')
3915
3660
 
@@ -4085,13 +3830,14 @@ def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
4085
3830
  # In addition to macros, we also don't want to warn on
4086
3831
  # - Compound literals
4087
3832
  # - Lambdas
4088
- # - alignas specifier with anonymous structs:
3833
+ # - alignas specifier with anonymous structs
3834
+ # - decltype
4089
3835
  closing_brace_pos = match.group(1).rfind(')')
4090
3836
  opening_parenthesis = ReverseCloseExpression(
4091
3837
  clean_lines, linenum, closing_brace_pos)
4092
3838
  if opening_parenthesis[2] > -1:
4093
3839
  line_prefix = opening_parenthesis[0][0:opening_parenthesis[2]]
4094
- macro = Search(r'\b([A-Z_]+)\s*$', line_prefix)
3840
+ macro = Search(r'\b([A-Z_][A-Z0-9_]*)\s*$', line_prefix)
4095
3841
  func = Match(r'^(.*\])\s*$', line_prefix)
4096
3842
  if ((macro and
4097
3843
  macro.group(1) not in (
@@ -4100,6 +3846,7 @@ def CheckTrailingSemicolon(filename, clean_lines, linenum, error):
4100
3846
  'LOCKS_EXCLUDED', 'INTERFACE_DEF')) or
4101
3847
  (func and not Search(r'\boperator\s*\[\s*\]', func.group(1))) or
4102
3848
  Search(r'\b(?:struct|union)\s+alignas\s*$', line_prefix) or
3849
+ Search(r'\bdecltype$', line_prefix) or
4103
3850
  Search(r'\s+=\s*$', line_prefix)):
4104
3851
  match = None
4105
3852
  if (match and
@@ -4159,7 +3906,7 @@ def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
4159
3906
  line = clean_lines.elided[linenum]
4160
3907
  matched = Match(r'\s*(for|while|if)\s*\(', line)
4161
3908
  if matched:
4162
- # Find the end of the conditional expression
3909
+ # Find the end of the conditional expression.
4163
3910
  (end_line, end_linenum, end_pos) = CloseExpression(
4164
3911
  clean_lines, linenum, line.find('('))
4165
3912
 
@@ -4174,6 +3921,75 @@ def CheckEmptyBlockBody(filename, clean_lines, linenum, error):
4174
3921
  error(filename, end_linenum, 'whitespace/empty_loop_body', 5,
4175
3922
  'Empty loop bodies should use {} or continue')
4176
3923
 
3924
+ # Check for if statements that have completely empty bodies (no comments)
3925
+ # and no else clauses.
3926
+ if end_pos >= 0 and matched.group(1) == 'if':
3927
+ # Find the position of the opening { for the if statement.
3928
+ # Return without logging an error if it has no brackets.
3929
+ opening_linenum = end_linenum
3930
+ opening_line_fragment = end_line[end_pos:]
3931
+ # Loop until EOF or find anything that's not whitespace or opening {.
3932
+ while not Search(r'^\s*\{', opening_line_fragment):
3933
+ if Search(r'^(?!\s*$)', opening_line_fragment):
3934
+ # Conditional has no brackets.
3935
+ return
3936
+ opening_linenum += 1
3937
+ if opening_linenum == len(clean_lines.elided):
3938
+ # Couldn't find conditional's opening { or any code before EOF.
3939
+ return
3940
+ opening_line_fragment = clean_lines.elided[opening_linenum]
3941
+ # Set opening_line (opening_line_fragment may not be entire opening line).
3942
+ opening_line = clean_lines.elided[opening_linenum]
3943
+
3944
+ # Find the position of the closing }.
3945
+ opening_pos = opening_line_fragment.find('{')
3946
+ if opening_linenum == end_linenum:
3947
+ # We need to make opening_pos relative to the start of the entire line.
3948
+ opening_pos += end_pos
3949
+ (closing_line, closing_linenum, closing_pos) = CloseExpression(
3950
+ clean_lines, opening_linenum, opening_pos)
3951
+ if closing_pos < 0:
3952
+ return
3953
+
3954
+ # Now construct the body of the conditional. This consists of the portion
3955
+ # of the opening line after the {, all lines until the closing line,
3956
+ # and the portion of the closing line before the }.
3957
+ if (clean_lines.raw_lines[opening_linenum] !=
3958
+ CleanseComments(clean_lines.raw_lines[opening_linenum])):
3959
+ # Opening line ends with a comment, so conditional isn't empty.
3960
+ return
3961
+ if closing_linenum > opening_linenum:
3962
+ # Opening line after the {. Ignore comments here since we checked above.
3963
+ body = list(opening_line[opening_pos+1:])
3964
+ # All lines until closing line, excluding closing line, with comments.
3965
+ body.extend(clean_lines.raw_lines[opening_linenum+1:closing_linenum])
3966
+ # Closing line before the }. Won't (and can't) have comments.
3967
+ body.append(clean_lines.elided[closing_linenum][:closing_pos-1])
3968
+ body = '\n'.join(body)
3969
+ else:
3970
+ # If statement has brackets and fits on a single line.
3971
+ body = opening_line[opening_pos+1:closing_pos-1]
3972
+
3973
+ # Check if the body is empty
3974
+ if not _EMPTY_CONDITIONAL_BODY_PATTERN.search(body):
3975
+ return
3976
+ # The body is empty. Now make sure there's not an else clause.
3977
+ current_linenum = closing_linenum
3978
+ current_line_fragment = closing_line[closing_pos:]
3979
+ # Loop until EOF or find anything that's not whitespace or else clause.
3980
+ while Search(r'^\s*$|^(?=\s*else)', current_line_fragment):
3981
+ if Search(r'^(?=\s*else)', current_line_fragment):
3982
+ # Found an else clause, so don't log an error.
3983
+ return
3984
+ current_linenum += 1
3985
+ if current_linenum == len(clean_lines.elided):
3986
+ break
3987
+ current_line_fragment = clean_lines.elided[current_linenum]
3988
+
3989
+ # The body is empty and there's no else clause until EOF or other code.
3990
+ error(filename, end_linenum, 'whitespace/empty_if_body', 4,
3991
+ ('If statement had no body and no else clause'))
3992
+
4177
3993
 
4178
3994
  def FindCheckMacro(line):
4179
3995
  """Find a replaceable CHECK-like macro.
@@ -4393,6 +4209,7 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
4393
4209
  # raw strings,
4394
4210
  raw_lines = clean_lines.lines_without_raw_strings
4395
4211
  line = raw_lines[linenum]
4212
+ prev = raw_lines[linenum - 1] if linenum > 0 else ''
4396
4213
 
4397
4214
  if line.find('\t') != -1:
4398
4215
  error(filename, linenum, 'whitespace/tab', 1,
@@ -4416,19 +4233,24 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
4416
4233
  cleansed_line = clean_lines.elided[linenum]
4417
4234
  while initial_spaces < len(line) and line[initial_spaces] == ' ':
4418
4235
  initial_spaces += 1
4419
- if line and line[-1].isspace():
4420
- error(filename, linenum, 'whitespace/end_of_line', 4,
4421
- 'Line ends in whitespace. Consider deleting these extra spaces.')
4422
4236
  # There are certain situations we allow one space, notably for
4423
4237
  # section labels, and also lines containing multi-line raw strings.
4424
- elif ((initial_spaces == 1 or initial_spaces == 3) and
4425
- not Match(scope_or_label_pattern, cleansed_line) and
4426
- not (clean_lines.raw_lines[linenum] != line and
4427
- Match(r'^\s*""', line))):
4238
+ # We also don't check for lines that look like continuation lines
4239
+ # (of lines ending in double quotes, commas, equals, or angle brackets)
4240
+ # because the rules for how to indent those are non-trivial.
4241
+ if (not Search(r'[",=><] *$', prev) and
4242
+ (initial_spaces == 1 or initial_spaces == 3) and
4243
+ not Match(scope_or_label_pattern, cleansed_line) and
4244
+ not (clean_lines.raw_lines[linenum] != line and
4245
+ Match(r'^\s*""', line))):
4428
4246
  error(filename, linenum, 'whitespace/indent', 3,
4429
4247
  'Weird number of spaces at line-start. '
4430
4248
  'Are you using a 2-space indent?')
4431
4249
 
4250
+ if line and line[-1].isspace():
4251
+ error(filename, linenum, 'whitespace/end_of_line', 4,
4252
+ 'Line ends in whitespace. Consider deleting these extra spaces.')
4253
+
4432
4254
  # Check if the line is a header guard.
4433
4255
  is_header_guard = False
4434
4256
  if file_extension == 'h':
@@ -4447,14 +4269,10 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
4447
4269
  # developers fault.
4448
4270
  if (not line.startswith('#include') and not is_header_guard and
4449
4271
  not Match(r'^\s*//.*http(s?)://\S*$', line) and
4272
+ not Match(r'^\s*//\s*[^\s]*$', line) and
4450
4273
  not Match(r'^// \$Id:.*#[0-9]+ \$$', line)):
4451
4274
  line_width = GetLineWidth(line)
4452
- extended_length = int((_line_length * 1.25))
4453
- if line_width > extended_length:
4454
- error(filename, linenum, 'whitespace/line_length', 4,
4455
- 'Lines should very rarely be longer than %i characters' %
4456
- extended_length)
4457
- elif line_width > _line_length:
4275
+ if line_width > _line_length:
4458
4276
  error(filename, linenum, 'whitespace/line_length', 2,
4459
4277
  'Lines should be <= %i characters long' % _line_length)
4460
4278
 
@@ -4479,9 +4297,8 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
4479
4297
  CheckOperatorSpacing(filename, clean_lines, linenum, error)
4480
4298
  CheckParenthesisSpacing(filename, clean_lines, linenum, error)
4481
4299
  CheckCommaSpacing(filename, clean_lines, linenum, error)
4482
- CheckBracesSpacing(filename, clean_lines, linenum, error)
4300
+ CheckBracesSpacing(filename, clean_lines, linenum, nesting_state, error)
4483
4301
  CheckSpacingForFunctionCall(filename, clean_lines, linenum, error)
4484
- CheckRValueReference(filename, clean_lines, linenum, nesting_state, error)
4485
4302
  CheckCheck(filename, clean_lines, linenum, error)
4486
4303
  CheckAltTokens(filename, clean_lines, linenum, error)
4487
4304
  classinfo = nesting_state.InnermostClass()
@@ -4525,23 +4342,6 @@ def _DropCommonSuffixes(filename):
4525
4342
  return os.path.splitext(filename)[0]
4526
4343
 
4527
4344
 
4528
- def _IsTestFilename(filename):
4529
- """Determines if the given filename has a suffix that identifies it as a test.
4530
-
4531
- Args:
4532
- filename: The input filename.
4533
-
4534
- Returns:
4535
- True if 'filename' looks like a test, False otherwise.
4536
- """
4537
- if (filename.endswith('_test.cc') or
4538
- filename.endswith('_unittest.cc') or
4539
- filename.endswith('_regtest.cc')):
4540
- return True
4541
- else:
4542
- return False
4543
-
4544
-
4545
4345
  def _ClassifyInclude(fileinfo, include, is_system):
4546
4346
  """Figures out what kind of header 'include' is.
4547
4347
 
@@ -4756,6 +4556,9 @@ _RE_PATTERN_REF_PARAM = re.compile(
4756
4556
  _RE_PATTERN_CONST_REF_PARAM = (
4757
4557
  r'(?:.*\s*\bconst\s*&\s*' + _RE_PATTERN_IDENT +
4758
4558
  r'|const\s+' + _RE_PATTERN_TYPE + r'\s*&\s*' + _RE_PATTERN_IDENT + r')')
4559
+ # Stream types.
4560
+ _RE_PATTERN_REF_STREAM_PARAM = (
4561
+ r'(?:.*stream\s*&\s*' + _RE_PATTERN_IDENT + r')')
4759
4562
 
4760
4563
 
4761
4564
  def CheckLanguage(filename, clean_lines, linenum, file_extension,
@@ -4912,7 +4715,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
4912
4715
  and line[-1] != '\\'):
4913
4716
  error(filename, linenum, 'build/namespaces', 4,
4914
4717
  'Do not use unnamed namespaces in header files. See '
4915
- 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
4718
+ 'https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
4916
4719
  ' for more information.')
4917
4720
 
4918
4721
 
@@ -4933,9 +4736,13 @@ def CheckGlobalStatic(filename, clean_lines, linenum, error):
4933
4736
 
4934
4737
  # Check for people declaring static/global STL strings at the top level.
4935
4738
  # This is dangerous because the C++ language does not guarantee that
4936
- # globals with constructors are initialized before the first access.
4739
+ # globals with constructors are initialized before the first access, and
4740
+ # also because globals can be destroyed when some threads are still running.
4741
+ # TODO(unknown): Generalize this to also find static unique_ptr instances.
4742
+ # TODO(unknown): File bugs for clang-tidy to find these.
4937
4743
  match = Match(
4938
- r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)',
4744
+ r'((?:|static +)(?:|const +))(?::*std::)?string( +const)? +'
4745
+ r'([a-zA-Z0-9_:]+)\b(.*)',
4939
4746
  line)
4940
4747
 
4941
4748
  # Remove false positives:
@@ -4955,15 +4762,20 @@ def CheckGlobalStatic(filename, clean_lines, linenum, error):
4955
4762
  # matching identifiers.
4956
4763
  # string Class::operator*()
4957
4764
  if (match and
4958
- not Search(r'\bstring\b(\s+const)?\s*\*\s*(const\s+)?\w', line) and
4765
+ not Search(r'\bstring\b(\s+const)?\s*[\*\&]\s*(const\s+)?\w', line) and
4959
4766
  not Search(r'\boperator\W', line) and
4960
- not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(3))):
4961
- error(filename, linenum, 'runtime/string', 4,
4962
- 'For a static/global string constant, use a C style string instead: '
4963
- '"%schar %s[]".' %
4964
- (match.group(1), match.group(2)))
4767
+ not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)*\s*\(([^"]|$)', match.group(4))):
4768
+ if Search(r'\bconst\b', line):
4769
+ error(filename, linenum, 'runtime/string', 4,
4770
+ 'For a static/global string constant, use a C style string '
4771
+ 'instead: "%schar%s %s[]".' %
4772
+ (match.group(1), match.group(2) or '', match.group(3)))
4773
+ else:
4774
+ error(filename, linenum, 'runtime/string', 4,
4775
+ 'Static/global string variables are not permitted.')
4965
4776
 
4966
- if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line):
4777
+ if (Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line) or
4778
+ Search(r'\b([A-Za-z0-9_]*_)\(CHECK_NOTNULL\(\1\)\)', line)):
4967
4779
  error(filename, linenum, 'runtime/init', 4,
4968
4780
  'You seem to be initializing a member variable with itself.')
4969
4781
 
@@ -5208,7 +5020,8 @@ def CheckForNonConstReference(filename, clean_lines, linenum,
5208
5020
 
5209
5021
  decls = ReplaceAll(r'{[^}]*}', ' ', line) # exclude function body
5210
5022
  for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls):
5211
- if not Match(_RE_PATTERN_CONST_REF_PARAM, parameter):
5023
+ if (not Match(_RE_PATTERN_CONST_REF_PARAM, parameter) and
5024
+ not Match(_RE_PATTERN_REF_STREAM_PARAM, parameter)):
5212
5025
  error(filename, linenum, 'runtime/references', 2,
5213
5026
  'Is this a non-const reference? '
5214
5027
  'If so, make const or use a pointer: ' +
@@ -5231,7 +5044,7 @@ def CheckCasts(filename, clean_lines, linenum, error):
5231
5044
  # Parameterless conversion functions, such as bool(), are allowed as they are
5232
5045
  # probably a member operator declaration or default constructor.
5233
5046
  match = Search(
5234
- r'(\bnew\s+|\S<\s*(?:const\s+)?)?\b'
5047
+ r'(\bnew\s+(?:const\s+)?|\S<\s*(?:const\s+)?)?\b'
5235
5048
  r'(int|float|double|bool|char|int32|uint32|int64|uint64)'
5236
5049
  r'(\([^)].*)', line)
5237
5050
  expecting_function = ExpectingFunctionArgs(clean_lines, linenum)
@@ -5372,63 +5185,12 @@ def CheckCStyleCast(filename, clean_lines, linenum, cast_type, pattern, error):
5372
5185
  if context.endswith(' operator++') or context.endswith(' operator--'):
5373
5186
  return False
5374
5187
 
5375
- # A single unnamed argument for a function tends to look like old
5376
- # style cast. If we see those, don't issue warnings for deprecated
5377
- # casts, instead issue warnings for unnamed arguments where
5378
- # appropriate.
5379
- #
5380
- # These are things that we want warnings for, since the style guide
5381
- # explicitly require all parameters to be named:
5382
- # Function(int);
5383
- # Function(int) {
5384
- # ConstMember(int) const;
5385
- # ConstMember(int) const {
5386
- # ExceptionMember(int) throw (...);
5387
- # ExceptionMember(int) throw (...) {
5388
- # PureVirtual(int) = 0;
5389
- # [](int) -> bool {
5390
- #
5391
- # These are functions of some sort, where the compiler would be fine
5392
- # if they had named parameters, but people often omit those
5393
- # identifiers to reduce clutter:
5394
- # (FunctionPointer)(int);
5395
- # (FunctionPointer)(int) = value;
5396
- # Function((function_pointer_arg)(int))
5397
- # Function((function_pointer_arg)(int), int param)
5398
- # <TemplateArgument(int)>;
5399
- # <(FunctionPointerTemplateArgument)(int)>;
5188
+ # A single unnamed argument for a function tends to look like old style cast.
5189
+ # If we see those, don't issue warnings for deprecated casts.
5400
5190
  remainder = line[match.end(0):]
5401
5191
  if Match(r'^\s*(?:;|const\b|throw\b|final\b|override\b|[=>{),]|->)',
5402
5192
  remainder):
5403
- # Looks like an unnamed parameter.
5404
-
5405
- # Don't warn on any kind of template arguments.
5406
- if Match(r'^\s*>', remainder):
5407
- return False
5408
-
5409
- # Don't warn on assignments to function pointers, but keep warnings for
5410
- # unnamed parameters to pure virtual functions. Note that this pattern
5411
- # will also pass on assignments of "0" to function pointers, but the
5412
- # preferred values for those would be "nullptr" or "NULL".
5413
- matched_zero = Match(r'^\s=\s*(\S+)\s*;', remainder)
5414
- if matched_zero and matched_zero.group(1) != '0':
5415
- return False
5416
-
5417
- # Don't warn on function pointer declarations. For this we need
5418
- # to check what came before the "(type)" string.
5419
- if Match(r'.*\)\s*$', line[0:match.start(0)]):
5420
- return False
5421
-
5422
- # Don't warn if the parameter is named with block comments, e.g.:
5423
- # Function(int /*unused_param*/);
5424
- raw_line = clean_lines.raw_lines[linenum]
5425
- if '/*' in raw_line:
5426
- return False
5427
-
5428
- # Passed all filters, issue warning here.
5429
- error(filename, linenum, 'readability/function', 3,
5430
- 'All parameters should be named in a function')
5431
- return True
5193
+ return False
5432
5194
 
5433
5195
  # At this point, all that should be left is actual casts.
5434
5196
  error(filename, linenum, 'readability/casting', 4,
@@ -5557,13 +5319,13 @@ def FilesBelongToSameModule(filename_cc, filename_h):
5557
5319
  string: the additional prefix needed to open the header file.
5558
5320
  """
5559
5321
 
5560
- if not filename_cc.endswith('.cc'):
5322
+ fileinfo = FileInfo(filename_cc)
5323
+ if not fileinfo.IsSource():
5561
5324
  return (False, '')
5562
- filename_cc = filename_cc[:-len('.cc')]
5563
- if filename_cc.endswith('_unittest'):
5564
- filename_cc = filename_cc[:-len('_unittest')]
5565
- elif filename_cc.endswith('_test'):
5566
- filename_cc = filename_cc[:-len('_test')]
5325
+ filename_cc = filename_cc[:-len(fileinfo.Extension())]
5326
+ matched_test_suffix = Search(_TEST_FILE_SUFFIX, fileinfo.BaseName())
5327
+ if matched_test_suffix:
5328
+ filename_cc = filename_cc[:-len(matched_test_suffix.group(1))]
5567
5329
  filename_cc = filename_cc.replace('/public/', '/')
5568
5330
  filename_cc = filename_cc.replace('/internal/', '/')
5569
5331
 
@@ -5727,31 +5489,6 @@ def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error):
5727
5489
  ' OR use pair directly OR if appropriate, construct a pair directly')
5728
5490
 
5729
5491
 
5730
- def CheckDefaultLambdaCaptures(filename, clean_lines, linenum, error):
5731
- """Check that default lambda captures are not used.
5732
-
5733
- Args:
5734
- filename: The name of the current file.
5735
- clean_lines: A CleansedLines instance containing the file.
5736
- linenum: The number of the line to check.
5737
- error: The function to call with any errors found.
5738
- """
5739
- line = clean_lines.elided[linenum]
5740
-
5741
- # A lambda introducer specifies a default capture if it starts with "[="
5742
- # or if it starts with "[&" _not_ followed by an identifier.
5743
- match = Match(r'^(.*)\[\s*(?:=|&[^\w])', line)
5744
- if match:
5745
- # Found a potential error, check what comes after the lambda-introducer.
5746
- # If it's not open parenthesis (for lambda-declarator) or open brace
5747
- # (for compound-statement), it's not a lambda.
5748
- line, _, pos = CloseExpression(clean_lines, linenum, len(match.group(1)))
5749
- if pos >= 0 and Match(r'^\s*[{(]', line[pos:]):
5750
- error(filename, linenum, 'build/c++11',
5751
- 4, # 4 = high confidence
5752
- 'Default lambda captures are an unapproved C++ feature.')
5753
-
5754
-
5755
5492
  def CheckRedundantVirtual(filename, clean_lines, linenum, error):
5756
5493
  """Check if line contains a redundant "virtual" function-specifier.
5757
5494
 
@@ -5950,7 +5687,6 @@ def ProcessLine(filename, file_extension, clean_lines, line,
5950
5687
  CheckPosixThreading(filename, clean_lines, line, error)
5951
5688
  CheckInvalidIncrement(filename, clean_lines, line, error)
5952
5689
  CheckMakePairUsesDeduction(filename, clean_lines, line, error)
5953
- CheckDefaultLambdaCaptures(filename, clean_lines, line, error)
5954
5690
  CheckRedundantVirtual(filename, clean_lines, line, error)
5955
5691
  CheckRedundantOverrideOrFinal(filename, clean_lines, line, error)
5956
5692
  for check_fn in extra_check_functions:
@@ -5967,8 +5703,14 @@ def FlagCxx11Features(filename, clean_lines, linenum, error):
5967
5703
  """
5968
5704
  line = clean_lines.elided[linenum]
5969
5705
 
5970
- # Flag unapproved C++11 headers.
5971
5706
  include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
5707
+
5708
+ # Flag unapproved C++ TR1 headers.
5709
+ if include and include.group(1).startswith('tr1/'):
5710
+ error(filename, linenum, 'build/c++tr1', 5,
5711
+ ('C++ TR1 headers such as <%s> are unapproved.') % include.group(1))
5712
+
5713
+ # Flag unapproved C++11 headers.
5972
5714
  if include and include.group(1) in ('cfenv',
5973
5715
  'condition_variable',
5974
5716
  'fenv.h',
@@ -6002,6 +5744,25 @@ def FlagCxx11Features(filename, clean_lines, linenum, error):
6002
5744
  'they may let you use it.') % top_name)
6003
5745
 
6004
5746
 
5747
+ def FlagCxx14Features(filename, clean_lines, linenum, error):
5748
+ """Flag those C++14 features that we restrict.
5749
+
5750
+ Args:
5751
+ filename: The name of the current file.
5752
+ clean_lines: A CleansedLines instance containing the file.
5753
+ linenum: The number of the line to check.
5754
+ error: The function to call with any errors found.
5755
+ """
5756
+ line = clean_lines.elided[linenum]
5757
+
5758
+ include = Match(r'\s*#\s*include\s+[<"]([^<"]+)[">]', line)
5759
+
5760
+ # Flag unapproved C++14 headers.
5761
+ if include and include.group(1) in ('scoped_allocator', 'shared_mutex'):
5762
+ error(filename, linenum, 'build/c++14', 5,
5763
+ ('<%s> is an unapproved C++14 header.') % include.group(1))
5764
+
5765
+
6005
5766
  def ProcessFileData(filename, file_extension, lines, error,
6006
5767
  extra_check_functions=[]):
6007
5768
  """Performs lint checks and reports any errors to the given error function.
@@ -6027,7 +5788,7 @@ def ProcessFileData(filename, file_extension, lines, error,
6027
5788
  ResetNolintSuppressions()
6028
5789
 
6029
5790
  CheckForCopyright(filename, lines, error)
6030
-
5791
+ ProcessGlobalSuppresions(lines)
6031
5792
  RemoveMultiLineComments(filename, lines, error)
6032
5793
  clean_lines = CleansedLines(lines)
6033
5794
 
@@ -6044,7 +5805,7 @@ def ProcessFileData(filename, file_extension, lines, error,
6044
5805
  CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error)
6045
5806
 
6046
5807
  # Check that the .cc file has included its header if it exists.
6047
- if file_extension == 'cc':
5808
+ if _IsSourceExtension(file_extension):
6048
5809
  CheckHeaderFileIncluded(filename, include_state, error)
6049
5810
 
6050
5811
  # We check here rather than inside ProcessLine so that we see raw