summaryrefslogtreecommitdiff
path: root/chromium/tools/clang
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-11-18 16:35:47 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-11-18 15:45:54 +0000
commit32f5a1c56531e4210bc4cf8d8c7825d66e081888 (patch)
treeeeeec6822f4d738d8454525233fd0e2e3a659e6d /chromium/tools/clang
parent99677208ff3b216fdfec551fbe548da5520cd6fb (diff)
downloadqtwebengine-chromium-32f5a1c56531e4210bc4cf8d8c7825d66e081888.tar.gz
BASELINE: Update Chromium to 87.0.4280.67
Change-Id: Ib157360be8c2ffb2c73125751a89f60e049c1d54 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/tools/clang')
-rw-r--r--chromium/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp28
-rw-r--r--chromium/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt93
-rw-r--r--chromium/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt16
-rwxr-xr-xchromium/tools/clang/scripts/build.py53
-rwxr-xr-xchromium/tools/clang/scripts/update.py4
-rwxr-xr-xchromium/tools/clang/scripts/upload_revision.py14
-rw-r--r--chromium/tools/clang/trace_annotator/CMakeLists.txt26
-rw-r--r--chromium/tools/clang/trace_annotator/README.md109
-rw-r--r--chromium/tools/clang/trace_annotator/TraceAnnotator.cpp208
9 files changed, 519 insertions, 32 deletions
diff --git a/chromium/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp b/chromium/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
index 27b3fbb196e..61836c65bcb 100644
--- a/chromium/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
+++ b/chromium/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
@@ -673,6 +673,20 @@ AST_MATCHER(clang::FieldDecl, overlapsOtherDeclsWithinRecordDecl) {
return has_sibling_with_overlapping_location;
}
+// Matches RecordDecl if
+// 1) it has a FieldDecl that matches the InnerMatcher
+// or
+// 2) it has a FieldDecl that hasType of a RecordDecl that matches the
+// InnerMatcher (this recurses to any depth).
+AST_MATCHER_P(clang::RecordDecl,
+ hasNestedFieldDecl,
+ clang::ast_matchers::internal::Matcher<clang::FieldDecl>,
+ InnerMatcher) {
+ auto matcher = recordDecl(has(fieldDecl(anyOf(
+ InnerMatcher, hasType(recordDecl(hasNestedFieldDecl(InnerMatcher)))))));
+ return matcher.matches(Node, Finder, Builder);
+}
+
// Rewrites |SomeClass* field| (matched as "affectedFieldDecl") into
// |CheckedPtr<SomeClass> field| and for each file rewritten in such way adds an
// |#include "base/memory/checked_ptr.h"|.
@@ -1041,6 +1055,20 @@ int main(int argc, const char* argv[]) {
match_finder.addMatcher(char_ptr_field_decl_matcher,
&char_ptr_field_decl_writer);
+ // See the testcases in tests/gen-global-destructor-test.cc.
+ auto global_destructor_matcher = varDecl(
+ allOf(hasGlobalStorage(),
+ hasType(recordDecl(hasNestedFieldDecl(field_decl_matcher)))));
+ FilteredExprWriter global_destructor_writer(&output_helper,
+ "global-destructor");
+ match_finder.addMatcher(global_destructor_matcher, &global_destructor_writer);
+
+ // Matches fields in unions - see the testcases in tests/gen-unions-test.cc.
+ auto union_field_decl_matcher = fieldDecl(
+ allOf(field_decl_matcher, hasParent(decl(recordDecl(isUnion())))));
+ FilteredExprWriter union_field_decl_writer(&output_helper, "union");
+ match_finder.addMatcher(union_field_decl_matcher, &union_field_decl_writer);
+
// Prepare and run the tool.
std::unique_ptr<clang::tooling::FrontendActionFactory> factory =
clang::tooling::newFrontendActionFactory(&match_finder, &output_helper);
diff --git a/chromium/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt b/chromium/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt
index 9f18a75980d..0c5bb35d34d 100644
--- a/chromium/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt
+++ b/chromium/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt
@@ -155,8 +155,20 @@ device::BluetoothDevice::adapter_
vr::LocationBarState::vector_icon
vr::OmniboxSuggestion::icon
+# Populated manually - assigned to |auto*| in ranged loop on an array
+# initializer literal comprising of those pointers.
+DownloadItemView::discard_button_
+DownloadItemView::open_now_button_
+DownloadItemView::save_button_
+DownloadItemView::scan_button_
+
# Populated manually - other compile-time reasons
logging::CheckOpResult::message_ # cyclic #include
+views::internal::ClassPropertySetter::property_ # passed to templated param T*
+
+#######
+# CheckedPtr2/MTECheckedPtr-specific sections
+#######
# Populated manually - these pointers are assigned invalid address (with top
# bits sets), which CheckedPtr is unable to handle, leading to run-time crashes.
@@ -165,3 +177,84 @@ blink::(anonymous namespace)::ThreadMarker::creating_thread_
blink::ControlKey::name_
performance_manager::frame_priority::BoostingVoteAggregator::Edge::src_
performance_manager::frame_priority::BoostingVoteAggregator::Edge::dst_
+
+# Populated manually - these pointers crash due to a mismatching tag.
+# Under investigation.
+base::internal::UnretainedWrapper::ptr_
+blink::NGPhysicalContainerFragment::buffer_
+blink::DisplayItem::client_
+cc::FrameSequenceMetrics::throughput_ukm_reporter_
+cc::(anonymous namespace)::RasterTaskImpl::tile_tracing_id_
+content::MediaPlayerId::render_frame_host
+content::RenderViewImpl::webview_
+mojo::core::WatcherDispatcher::last_watch_to_block_arming_
+net::IOBuffer::data_
+safe_browsing::RemoteSafeBrowsingDatabaseManager::ClientRequest::client_
+
+# Populated manually - this pointer crashes, because assigned address appears
+# unallocated.
+x11::ReadBuffer::fds
+
+#######
+# End of CheckedPtr2/MTECheckedPtr-specific sections
+#######
+
+#######
+# BackupRefPtr-specific sections
+#######
+
+# Populated manually - std::is_trivially_destructible static_assert failure
+blink::HTMLElementEquivalent::tag_name_
+blink::PrerendererClient::client_
+blink::weakness_marking_test::EphemeronCallbacksCounter::count_holder_
+sql::recover::InnerPageDecoder::db_reader_
+sql::recover::LeafPageDecoder::db_reader_
+WTF::ListHashSet::head_
+WTF::ListHashSet::tail_
+
+# Populated manually - exit-time destructor
+gpu::GpuControlList::Conditions::devices
+gpu::GpuControlList::Conditions::driver_info
+gpu::GpuControlList::Conditions::gl_strings
+gpu::GpuControlList::Conditions::machine_model_info
+gpu::GpuControlList::Conditions::intel_gpu_series_list
+gpu::GpuControlList::Conditions::more
+gpu::GpuControlList::Entry::features
+gpu::GpuControlList::Entry::disabled_extensions
+gpu::GpuControlList::Entry::disabled_webgl_extensions
+gpu::GpuControlList::Entry::cr_bugs
+gpu::GpuControlList::Entry::exceptions
+media::ListElementInfo::id_info_
+media::SupportedTypeInfo::codecs
+tracing::(anonymous namespace)::AllowlistEntry::arg_name_filter
+net::(anonymous namespace)::CTRequiredPolicy::roots
+net::(anonymous namespace)::CTRequiredPolicy::exceptions
+net::HttpCache::Transaction::SetRequest(const net::NetLogWithSource &)::(anonymous struct)::search
+net::TransportSecurityStateSource::Pinset::accepted_pins
+net::TransportSecurityStateSource::Pinset::rejected_pins
+net::TransportSecurityStateSource::expect_ct_report_uris
+net::TransportSecurityStateSource::pinsets
+WTF::StaticSingleton::InstanceStorage::pointer_
+
+# Populated manually - attempt to use a deleted function (union's destructor is
+# deleted, because an inner struct has CheckedPtr field)
+flags_ui::FeatureEntry::(anonymous union)::(anonymous struct)::feature
+ui::NativeTheme::MenuSeparatorExtraParams::paint_rect
+
+# Populated manually - flexible array with non-trivial destruction
+blink::ShapeResultView::(anonymous struct)::alignment
+
+# Populated manually - these pointers crash, because a base class ctor accesses
+# child class ptr fields before they're initialized.
+blink::CacheEntry::next_
+blink::CacheEntry::prev_
+WTF::LruCache::next_
+WTF::LruCache::prev_
+
+# Populated manually - these pointers crash, due to use-after-move.
+gpu::gles2::PassthroughProgramCache::ProgramCacheValue::program_cache_
+gpu::gles2::ProgramCache::ScopedCacheUse::cache_
+
+#######
+# End of BackupRefPtr-specific sections
+#######
diff --git a/chromium/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt b/chromium/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt
index 62e16dc46c9..2bbcada8bbc 100644
--- a/chromium/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt
+++ b/chromium/tools/clang/rewrite_raw_ptr_fields/manual-paths-to-ignore.txt
@@ -24,6 +24,22 @@ base/android/linker/
tools/
net/tools/
+# Exclude code that only runs inside a renderer process - renderer
+# processes are excluded for now from the MiraclePtr project scope,
+# because they are sensitive to performance regressions (to a much higher
+# degree than, say, the Browser process).
+#
+# Note that some renderer-only directories are already excluded
+# elsewhere - for example "v8/" is excluded in another part of this
+# file.
+#
+# Also, note that isInThirdPartyLocation AST matcher in
+# RewriteRawPtrFields.cpp explicitly includes third_party/blink
+# (because it is in the same git repository as the rest of Chromium),
+# but we go ahead and exclude it below.
+/renderer/ # (e.g. //content/renderer/ or //components/visitedlink/renderer/).
+third_party/blink/
+
# Exclude paths in separate repositories - i.e. in directories that
# 1. Contain a ".git" subdirectory
# 2. And hasn't been excluded via "third_party/" substring in their path
diff --git a/chromium/tools/clang/scripts/build.py b/chromium/tools/clang/scripts/build.py
index 78ab2b8ddbd..3d009d1d496 100755
--- a/chromium/tools/clang/scripts/build.py
+++ b/chromium/tools/clang/scripts/build.py
@@ -52,22 +52,12 @@ BUG_REPORT_URL = ('https://crbug.com and run'
win_sdk_dir = None
-dia_dll = None
def GetWinSDKDir():
- """Get the location of the current SDK. Sets dia_dll as a side-effect."""
+ """Get the location of the current SDK."""
global win_sdk_dir
- global dia_dll
if win_sdk_dir:
return win_sdk_dir
- # Bump after VC updates.
- DIA_DLL = {
- '2013': 'msdia120.dll',
- '2015': 'msdia140.dll',
- '2017': 'msdia140.dll',
- '2019': 'msdia140.dll',
- }
-
# Don't let vs_toolchain overwrite our environment.
environ_bak = os.environ
@@ -85,8 +75,6 @@ def GetWinSDKDir():
vs_path = os.environ['GYP_MSVS_OVERRIDE_PATH']
dia_path = os.path.join(vs_path, 'DIA SDK', 'bin', 'amd64')
- dia_dll = os.path.join(dia_path, DIA_DLL[msvs_version])
-
os.environ = environ_bak
return win_sdk_dir
@@ -130,11 +118,6 @@ def CopyFile(src, dst):
shutil.copy(src, dst)
-def CopyDiaDllTo(target_dir):
- GetWinSDKDir()
- CopyFile(dia_dll, target_dir)
-
-
def CopyDirectoryContents(src, dst):
"""Copy the files from directory src to dst."""
dst = os.path.realpath(dst) # realpath() in case dst ends in /..
@@ -253,7 +236,7 @@ def AddGnuWinToPath():
return
gnuwin_dir = os.path.join(LLVM_BUILD_TOOLS_DIR, 'gnuwin')
- GNUWIN_VERSION = '13'
+ GNUWIN_VERSION = '14'
GNUWIN_STAMP = os.path.join(gnuwin_dir, 'stamp')
if ReadStampFile(GNUWIN_STAMP) == GNUWIN_VERSION:
print('GNU Win tools already up to date.')
@@ -307,6 +290,28 @@ def AddZlibToPath():
return zlib_dir
+def DownloadRPMalloc():
+ """Download rpmalloc."""
+ rpmalloc_dir = os.path.join(LLVM_BUILD_TOOLS_DIR, 'rpmalloc')
+ if os.path.exists(rpmalloc_dir):
+ RmTree(rpmalloc_dir)
+
+ # Using rpmalloc bc1923f rather than the latest release (1.4.1) because
+ # it contains the fix for https://github.com/mjansson/rpmalloc/pull/186
+ # which would cause lld to deadlock.
+ # The zip file was created and uploaded as follows:
+ # $ mkdir rpmalloc
+ # $ curl -L https://github.com/mjansson/rpmalloc/archive/bc1923f436539327707b08ef9751a7a87bdd9d2f.tar.gz \
+ # | tar -C rpmalloc --strip-components=1 -xzf -
+ # $ GZIP=-9 tar vzcf rpmalloc-bc1923f.tgz rpmalloc
+ # $ gsutil.py cp -n -a public-read rpmalloc-bc1923f.tgz \
+ # gs://chromium-browser-clang/tools/
+ zip_name = 'rpmalloc-bc1923f.tgz'
+ DownloadAndUnpack(CDS_URL + '/tools/' + zip_name, LLVM_BUILD_TOOLS_DIR)
+ rpmalloc_dir = rpmalloc_dir.replace('\\', '/')
+ return rpmalloc_dir
+
+
def MaybeDownloadHostGcc(args):
"""Download a modern GCC host compiler on Linux."""
if not sys.platform.startswith('linux') or args.gcc_toolchain:
@@ -543,6 +548,8 @@ def main():
'-DLLVM_INCLUDE_GO_TESTS=OFF',
# TODO(crbug.com/1113475): Update binutils.
'-DENABLE_X86_RELAX_RELOCATIONS=NO',
+ # See crbug.com/1126219: Use native symbolizer instead of DIA
+ '-DLLVM_ENABLE_DIA_SDK=OFF',
]
if args.gcc_toolchain:
@@ -584,6 +591,10 @@ def main():
cxxflags.append('-I' + zlib_dir)
ldflags.append('-LIBPATH:' + zlib_dir)
+ # Use rpmalloc. For faster ThinLTO linking.
+ rpmalloc_dir = DownloadRPMalloc()
+ base_cmake_args.append('-DLLVM_INTEGRATED_CRT_ALLOC=' + rpmalloc_dir)
+
if sys.platform != 'win32':
# libxml2 is required by the Win manifest merging tool used in cross-builds.
base_cmake_args.append('-DLLVM_ENABLE_LIBXML2=FORCE_ON')
@@ -661,8 +672,6 @@ def main():
if sys.platform == 'darwin':
# TODO(crbug.com/731375): Run check-all on Darwin too.
test_targets = [ 'check-llvm', 'check-clang', 'check-builtins' ]
- if sys.platform == 'win32':
- CopyDiaDllTo(os.path.join(LLVM_BOOTSTRAP_DIR, 'bin'))
RunCommand(['ninja'] + test_targets, msvc_arch='x64')
RunCommand(['ninja', 'install'], msvc_arch='x64')
@@ -1061,8 +1070,6 @@ def main():
RunCommand(['ninja', '-C', LLVM_BUILD_DIR, 'cr-check-all'], msvc_arch='x64')
if args.run_tests:
- if sys.platform == 'win32':
- CopyDiaDllTo(os.path.join(LLVM_BUILD_DIR, 'bin'))
test_targets = [ 'check-all' ]
if sys.platform == 'darwin':
# TODO(thakis): Run check-all on Darwin too, https://crbug.com/959361
diff --git a/chromium/tools/clang/scripts/update.py b/chromium/tools/clang/scripts/update.py
index b1018321ec3..4759ce18686 100755
--- a/chromium/tools/clang/scripts/update.py
+++ b/chromium/tools/clang/scripts/update.py
@@ -38,8 +38,8 @@ import zipfile
# https://chromium.googlesource.com/chromium/src/+/master/docs/updating_clang.md
# Reverting problematic clang rolls is safe, though.
# This is the output of `git describe` and is usable as a commit-ish.
-CLANG_REVISION = 'llvmorg-12-init-3492-ga1caa302'
-CLANG_SUB_REVISION = 1
+CLANG_REVISION = 'llvmorg-12-init-5035-gd0abc757'
+CLANG_SUB_REVISION = 3
PACKAGE_VERSION = '%s-%s' % (CLANG_REVISION, CLANG_SUB_REVISION)
RELEASE_VERSION = '12.0.0'
diff --git a/chromium/tools/clang/scripts/upload_revision.py b/chromium/tools/clang/scripts/upload_revision.py
index 8eb81b3a368..f20cb6abb38 100755
--- a/chromium/tools/clang/scripts/upload_revision.py
+++ b/chromium/tools/clang/scripts/upload_revision.py
@@ -30,18 +30,18 @@ CHROMIUM_DIR = os.path.abspath(os.path.join(THIS_DIR, '..', '..', '..'))
COMMIT_FOOTER = \
'''
Bug: TODO
-Cq-Include-Trybots: chromium/try:mac_chromium_asan_rel_ng
+Cq-Include-Trybots: chromium/try:chromeos-amd64-generic-cfi-thin-lto-rel
+Cq-Include-Trybots: chromium/try:dawn-win10-x86-deps-rel
+Cq-Include-Trybots: chromium/try:linux-chromeos-dbg
+Cq-Include-Trybots: chromium/try:linux_angle_deqp_rel_ng
Cq-Include-Trybots: chromium/try:linux_chromium_cfi_rel_ng
Cq-Include-Trybots: chromium/try:linux_chromium_chromeos_asan_rel_ng
-Cq-Include-Trybots: chromium/try:linux_chromium_msan_rel_ng
Cq-Include-Trybots: chromium/try:linux_chromium_chromeos_msan_rel_ng
-Cq-Include-Trybots: chromium/try:linux-chromeos-dbg,win-asan
-Cq-Include-Trybots: chromium/try:chromeos-amd64-generic-cfi-thin-lto-rel
Cq-Include-Trybots: chromium/try:linux_chromium_compile_dbg_32_ng
-Cq-Include-Trybots: chromium/try:win7-rel,win-angle-deqp-rel-32
-Cq-Include-Trybots: chromium/try:linux_angle_deqp_rel_ng
+Cq-Include-Trybots: chromium/try:linux_chromium_msan_rel_ng
+Cq-Include-Trybots: chromium/try:mac-arm64-rel,mac_chromium_asan_rel_ng
Cq-Include-Trybots: chromium/try:win-angle-deqp-rel-64
-Cq-Include-Trybots: chromium/try:dawn-win10-x86-deps-rel
+Cq-Include-Trybots: chromium/try:win-asan,win7-rel,win-angle-deqp-rel-32
Cq-Include-Trybots: chrome/try:iphone-device,ipad-device
Cq-Include-Trybots: chrome/try:linux-chromeos-chrome
Cq-Include-Trybots: chrome/try:win-chrome,win64-chrome,mac-chrome
diff --git a/chromium/tools/clang/trace_annotator/CMakeLists.txt b/chromium/tools/clang/trace_annotator/CMakeLists.txt
new file mode 100644
index 00000000000..6f59011b79b
--- /dev/null
+++ b/chromium/tools/clang/trace_annotator/CMakeLists.txt
@@ -0,0 +1,26 @@
+set(LLVM_LINK_COMPONENTS
+ BitReader
+ MCParser
+ Option
+ )
+
+add_llvm_executable(trace_annotator
+ TraceAnnotator.cpp
+ )
+
+target_link_libraries(trace_annotator
+ clangAST
+ clangASTMatchers
+ clangAnalysis
+ clangBasic
+ clangDriver
+ clangEdit
+ clangFrontend
+ clangLex
+ clangParse
+ clangSema
+ clangSerialization
+ clangTooling
+ )
+
+cr_install(TARGETS trace_annotator RUNTIME DESTINATION bin)
diff --git a/chromium/tools/clang/trace_annotator/README.md b/chromium/tools/clang/trace_annotator/README.md
new file mode 100644
index 00000000000..2e2aa4e418c
--- /dev/null
+++ b/chromium/tools/clang/trace_annotator/README.md
@@ -0,0 +1,109 @@
+# Trace Annotator Tool
+
+## Introduction
+
+A tool to annotate functions with ```c++ TRACE_EVENT```. This tool serves two
+workflows:
+
+* Debugging: bulk add traces to all functions in a directory and after finding
+ the bug remove the traces.
+* Adding traces to code: bulk add traces to all functions in a directory,
+ review the changes carefully and create a patch.
+
+The goal of this tool is to transfer a function:
+```c++
+int foo(int bar, int baz) {
+ return 42;
+}
+```
+into:
+```c++
+int foo(int bar, int baz) {
+ TRACE_EVENT0("test", "foo");
+ return 42;
+}
+```
+
+In future also argument tracing is to be supported.
+
+This document is based on //docs/clang_tool_refactoring.md
+
+## Building
+
+The following might take approx. 2 hours depending on your computer.
+
+* Make a new checkout of chromium (suggested, but optional).
+* From chromium/src:
+* ```shell cr build all``` To make sure all files have been generated.
+* ```shell cp -R third_party/llvm-build ~```
+* ```shell tools/clang/scripts/build.py --bootstrap --without-android
+ --without-fuchsia --extra-tools trace_annotator```
+ * TODO how to build with plugin 'find-bad-constructs'?
+* ```shell cp -R ~/llvm-build third_party``` This should enable goma support
+ again.
+
+### Rebuild just the tool:
+
+* ```shell cd third_party/llvm-build/Release+Asserts```
+* ```shell ninja trace_annotator```
+
+Beware that running ```shell gclient sync``` might overwrite the build and
+another full build might be necessary. A backup of the binary from
+//third_party/llvm-build/Release+Asserts/bin/trace_annotator might be useful.
+
+## Testing
+
+* ```shell tools/clang/scripts/test_tool.py --apply-edits trace_annotator```
+
+## Running
+
+* Chrome plugins are not supported yet, run: ```shell gn args out/Debug/``` and
+ add: ```clang_use_chrome_plugins = false``` option.
+* Make sure you have up to date compilation database:
+ * To generate it run: ```shell tools/clang/scripts/generate_compdb.py -p
+ out/Debug/ > out/Debug/compile_commands.json```
+ * These are the compiler options for individual files (needed to use the
+ right version of C++, right library paths...).
+
+* ```shell DIR="net"; \
+ git checkout $DIR && tools/clang/scripts/run_tool.py --tool trace_annotator -p out/Debug/ $DIR \
+ | tools/clang/scripts/extract_edits.py \
+ | tools/clang/scripts/apply_edits.py -p out/Debug $DIR \
+ && git cl format $DIR```
+
+* Consult documentation of ```//tools/clang/scripts/run_tool.py``` for more
+ options.
+
+### Suggestion:
+
+Do not run the tool on //base or anything that has to do with tracing or
+synchronization. Or at least do not submit the resulting patch.
+
+### Debugging workflow suggestion:
+
+* Do some changes.
+* ```shell git add . ; git commit```
+* Run the tool.
+* ```shell git add . ; git commit```
+* Do some more changes (including fixing a bug).
+* ```shell git add . ; git commit```
+* ```shell git rebase -i``` and follow the help.
+
+### Creating tracing patch suggestion:
+
+* Run the tool.
+* Double check all generated code.
+* Add method annotations for methods that are hidden by compiler options (e.g.,
+ if you are on unix then the code in ```c++ #ifdef OS_WIN``` will not be
+ annotated.
+
+## TODO
+
+* Add options:
+ * Whether to add "do not submit" comment (in upper case).
+ * Function name formatting (without namespace(s) / getQualifiedNameAsString /
+ with namespaces but without template tags).
+ * Category name.
+ * Make tracing of function arguments.
+* Standalone build of the tool (outside of //third_party to avoid overwriting
+ by ```shell gclient sync```).
diff --git a/chromium/tools/clang/trace_annotator/TraceAnnotator.cpp b/chromium/tools/clang/trace_annotator/TraceAnnotator.cpp
new file mode 100644
index 00000000000..c1ef48dc838
--- /dev/null
+++ b/chromium/tools/clang/trace_annotator/TraceAnnotator.cpp
@@ -0,0 +1,208 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This implements a Clang tool to annotate methods with tracing. It should be
+// run using the tools/clang/scripts/run_tool.py helper as described in
+// README.md
+
+#include <string>
+#include <vector>
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace clang::ast_matchers;
+using clang::tooling::CommonOptionsParser;
+using clang::tooling::Replacement;
+using clang::tooling::Replacements;
+
+namespace {
+
+class FunctionDefCallback : public MatchFinder::MatchCallback {
+ public:
+ explicit FunctionDefCallback(std::vector<Replacement>* replacements)
+ : replacements_(replacements) {}
+
+ void run(const MatchFinder::MatchResult& result) override;
+
+ private:
+ std::vector<Replacement>* const replacements_;
+};
+
+class TraceAnnotator {
+ public:
+ explicit TraceAnnotator(std::vector<Replacement>* replacements)
+ : function_def_callback_(replacements) {}
+
+ void SetupMatchers(MatchFinder* match_finder);
+
+ private:
+ FunctionDefCallback function_def_callback_;
+};
+
+// Given:
+// template <typename T, typename T2> void foo(T t, T2 t2) {}; // N1 and N4
+// template <typename T2> void foo<int, T2>(int t, T2 t) {}; // N2
+// template <> void foo<int, char>(int t, char t2) {}; // N3
+// void foo() {
+// // This creates implicit template specialization (N4) out of the
+// // explicit template definition (N1).
+// foo<bool, double>(true, 1.23);
+// }
+// with the following AST nodes:
+// FunctionTemplateDecl foo
+// |-FunctionDecl 0x191da68 foo 'void (T, T2)' // N1
+// `-FunctionDecl 0x194bf08 foo 'void (bool, double)' // N4
+// FunctionTemplateDecl foo
+// `-FunctionDecl foo 'void (int, T2)' // N2
+// FunctionDecl foo 'void (int, char)' // N3
+//
+// Matches AST node N4, but not AST nodes N1, N2 nor N3.
+AST_MATCHER(clang::FunctionDecl, isImplicitFunctionTemplateSpecialization) {
+ switch (Node.getTemplateSpecializationKind()) {
+ case clang::TSK_ImplicitInstantiation:
+ return true;
+ case clang::TSK_Undeclared:
+ case clang::TSK_ExplicitSpecialization:
+ case clang::TSK_ExplicitInstantiationDeclaration:
+ case clang::TSK_ExplicitInstantiationDefinition:
+ return false;
+ }
+}
+
+AST_POLYMORPHIC_MATCHER(isInMacroLocation,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(clang::Decl,
+ clang::Stmt,
+ clang::TypeLoc)) {
+ return Node.getBeginLoc().isMacroID();
+}
+
+void TraceAnnotator::SetupMatchers(MatchFinder* match_finder) {
+ const clang::ast_matchers::DeclarationMatcher function_call =
+ functionDecl(
+ has(compoundStmt().bind("function body")),
+ /* Avoid matching the following cases: */
+ unless(anyOf(
+ /* Do not match implicit function template specializations to
+ avoid conflicting edits. */
+ isImplicitFunctionTemplateSpecialization(),
+ /* Do not match constexpr functions. */
+ isConstexpr(), isDefaulted(),
+ /* Do not match ctor/dtor. */
+ cxxConstructorDecl(), cxxDestructorDecl(),
+ /* Tracing macros can be tricky (e.g., QuicUint128Impl comparison
+ operators). */
+ isInMacroLocation(), has(compoundStmt(isInMacroLocation())),
+ /* Do not trace lambdas (no name, possbly tracking more parameters
+ than intended because of [&]). */
+ hasParent(cxxRecordDecl(isLambda())))))
+ .bind("function");
+ match_finder->addMatcher(function_call, &function_def_callback_);
+}
+
+// Returns a string containing the qualified name of the function. Does not
+// output template parameters of the function or in case of methods of the
+// associated class (as opposed to |function->getQualifiedNameAsString|).
+std::string getFunctionName(const clang::FunctionDecl* function) {
+ std::string qualified_name;
+ // Add namespace(s) to the name.
+ if (auto* name_space = llvm::dyn_cast<clang::NamespaceDecl>(
+ function->getEnclosingNamespaceContext())) {
+ qualified_name += name_space->getQualifiedNameAsString();
+ qualified_name += "::";
+ }
+ // If the function is a method, add class name (without templates).
+ if (auto* method = llvm::dyn_cast<clang::CXXMethodDecl>(function)) {
+ qualified_name += method->getParent()->getNameAsString();
+ qualified_name += "::";
+ }
+ // Add function name (without templates).
+ qualified_name += function->getNameAsString();
+ return qualified_name;
+}
+
+void FunctionDefCallback::run(const MatchFinder::MatchResult& result) {
+ const clang::FunctionDecl* function =
+ result.Nodes.getNodeAs<clang::FunctionDecl>("function");
+ // Using this instead of |function->getBody| prevents conflicts with parameter
+ // names in headers and implementations.
+ const clang::CompoundStmt* function_body =
+ result.Nodes.getNodeAs<clang::CompoundStmt>("function body");
+ clang::CharSourceRange range =
+ clang::CharSourceRange::getTokenRange(function_body->getBeginLoc());
+
+ const char kReplacementTextTemplate[] = R"( TRACE_EVENT0("test", "{0}"); )";
+ std::string function_name = getFunctionName(function);
+ std::string replacement_text =
+ llvm::formatv(kReplacementTextTemplate, function_name).str();
+
+ const char kAnnotationTemplate[] = " { {0}";
+ std::string annotation =
+ llvm::formatv(kAnnotationTemplate, replacement_text).str();
+
+ replacements_->push_back(
+ Replacement(*result.SourceManager, range, annotation));
+}
+
+} // namespace
+
+static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
+
+int main(int argc, const char* argv[]) {
+ llvm::cl::OptionCategory category("TraceAnnotator Tool");
+ CommonOptionsParser options(argc, argv, category);
+ clang::tooling::ClangTool tool(options.getCompilations(),
+ options.getSourcePathList());
+
+ std::vector<Replacement> replacements;
+ TraceAnnotator converter(&replacements);
+ MatchFinder match_finder;
+ converter.SetupMatchers(&match_finder);
+
+ std::unique_ptr<clang::tooling::FrontendActionFactory> frontend_factory =
+ clang::tooling::newFrontendActionFactory(&match_finder);
+ int result = tool.run(frontend_factory.get());
+ if (result != 0)
+ return result;
+
+ if (replacements.empty())
+ return 0;
+
+ // Each replacement line should have the following format:
+ // r:<file path>:<offset>:<length>:<replacement text>
+ // Only the <replacement text> field can contain embedded ":" characters.
+ // TODO(dcheng): Use a more clever serialization. Ideally we'd use the YAML
+ // serialization and then use clang-apply-replacements, but that would require
+ // copying and pasting a larger amount of boilerplate for all Chrome clang
+ // tools.
+
+ // Keep a set of files where we have already added base_tracing include.
+ std::set<std::string> include_added_to;
+
+ llvm::outs() << "==== BEGIN EDITS ====\n";
+ for (const auto& r : replacements) {
+ // Add base_tracing import if necessary.
+ if (include_added_to.find(r.getFilePath().str()) ==
+ include_added_to.end()) {
+ include_added_to.insert(r.getFilePath().str());
+ // Add also copyright so that |test-expected.cc| passes presubmit.
+ llvm::outs() << "include-user-header:::" << r.getFilePath()
+ << ":::-1:::-1:::base/trace_event/base_tracing.h"
+ << "\n";
+ }
+ // Add the actual replacement.
+ llvm::outs() << "r:::" << r.getFilePath() << ":::" << r.getOffset()
+ << ":::" << r.getLength() << ":::" << r.getReplacementText()
+ << "\n";
+ }
+ llvm::outs() << "==== END EDITS ====\n";
+
+ return 0;
+}