Update from https://crrev.com/305340
Added a few #includes of base/compiler_specific.h for upstream cleanup.
Changed callers for cc::BeginFrameArgs and cc::RendererSettings API
changes.
Review URL: https://codereview.chromium.org/754433003
diff --git a/tools/android/checkstyle/checkstyle.py b/tools/android/checkstyle/checkstyle.py
index c8ad04f..0c260bb 100644
--- a/tools/android/checkstyle/checkstyle.py
+++ b/tools/android/checkstyle/checkstyle.py
@@ -13,7 +13,7 @@
os.path.join(os.path.dirname(__file__),
os.pardir, os.pardir, os.pardir))
CHECKSTYLE_ROOT = os.path.join(CHROMIUM_SRC, 'third_party', 'checkstyle',
- 'checkstyle-5.9-all.jar')
+ 'checkstyle-6.1-all.jar')
def RunCheckstyle(input_api, output_api, style_file):
diff --git a/tools/android/checkstyle/chromium-style-5.0.xml b/tools/android/checkstyle/chromium-style-5.0.xml
index 46b19e9..c43f779 100644
--- a/tools/android/checkstyle/chromium-style-5.0.xml
+++ b/tools/android/checkstyle/chromium-style-5.0.xml
@@ -91,7 +91,7 @@
</module>
<module name="LineLength">
<property name="severity" value="error"/>
- <property name="ignorePattern" value="^import.*$" />
+ <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
<property name="max" value="100"/>
</module>
<module name="LeftCurly">
@@ -138,6 +138,17 @@
<property name="allowLineBreaks" value="true"/>
<property name="tokens" value="SEMI, DOT, POST_DEC, POST_INC"/>
</module>
+ <module name="GenericWhitespace">
+ <property name="severity" value="error"/>
+ <message key="ws.followed"
+ value="GenericWhitespace ''{0}'' is followed by whitespace."/>
+ <message key="ws.preceded"
+ value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
+ <message key="ws.illegalFollow"
+ value="GenericWhitespace ''{0}'' should followed by whitespace."/>
+ <message key="ws.notPreceded"
+ value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
+ </module>
<module name="EmptyStatement">
<property name="severity" value="error"/>
</module>
@@ -166,22 +177,22 @@
</module>
<!-- TODO(aurimas): make OperatorWrap into an error once all the warnings are fixed. -->
<module name="OperatorWrap">
- <property name="severity" value="warning"/>
+ <property name="severity" value="error"/>
<property name="option" value="NL" />
<property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR " />
</module>
<module name="OperatorWrap">
- <property name="severity" value="warning"/>
+ <property name="severity" value="error"/>
<property name="option" value="eol"/>
<property name="tokens" value="ASSIGN"/>
</module>
<module name="SeparatorWrap">
- <property name="severity" value="warning"/>
+ <property name="severity" value="error"/>
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
- <property name="severity" value="warning"/>
+ <property name="severity" value="error"/>
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
diff --git a/tools/clang/plugins/ChromeClassTester.cpp b/tools/clang/plugins/ChromeClassTester.cpp
index c8bc543..7e36653 100644
--- a/tools/clang/plugins/ChromeClassTester.cpp
+++ b/tools/clang/plugins/ChromeClassTester.cpp
@@ -206,7 +206,7 @@
// Enum type with _LAST members where _LAST doesn't mean last enum value.
ignored_record_names_.insert("ServerFieldType");
- // Used heavily in ui_unittests and once in views_unittests. Fixing this
+ // Used heavily in ui_base_unittests and once in views_unittests. Fixing this
// isn't worth the overhead of an additional library.
ignored_record_names_.insert("TestAnimationDelegate");
diff --git a/tools/clang/plugins/FindBadConstructsConsumer.cpp b/tools/clang/plugins/FindBadConstructsConsumer.cpp
index 0a230e0..f08ca71 100644
--- a/tools/clang/plugins/FindBadConstructsConsumer.cpp
+++ b/tools/clang/plugins/FindBadConstructsConsumer.cpp
@@ -724,28 +724,37 @@
the_end(record->field_end());
SourceLocation weak_ptr_factory_location; // Invalid initially.
for (; iter != the_end; ++iter) {
- // If we enter the loop but have already seen a matching WeakPtrFactory,
- // it means there is at least one member after the factory.
- if (weak_ptr_factory_location.isValid()) {
- diagnostic().Report(weak_ptr_factory_location,
- diag_weak_ptr_factory_order_);
- }
const TemplateSpecializationType* template_spec_type =
iter->getType().getTypePtr()->getAs<TemplateSpecializationType>();
+ bool param_is_weak_ptr_factory_to_self = false;
if (template_spec_type) {
const TemplateDecl* template_decl =
template_spec_type->getTemplateName().getAsTemplateDecl();
- if (template_decl && template_spec_type->getNumArgs() >= 1) {
+ if (template_decl && template_spec_type->getNumArgs() == 1) {
if (template_decl->getNameAsString().compare("WeakPtrFactory") == 0 &&
GetNamespace(template_decl) == "base") {
+ // Only consider WeakPtrFactory members which are specialized for the
+ // owning class.
const TemplateArgument& arg = template_spec_type->getArg(0);
if (arg.getAsType().getTypePtr()->getAsCXXRecordDecl() ==
record->getTypeForDecl()->getAsCXXRecordDecl()) {
- weak_ptr_factory_location = iter->getLocation();
+ if (!weak_ptr_factory_location.isValid()) {
+ // Save the first matching WeakPtrFactory member for the
+ // diagnostic.
+ weak_ptr_factory_location = iter->getLocation();
+ }
+ param_is_weak_ptr_factory_to_self = true;
}
}
}
}
+ // If we've already seen a WeakPtrFactory<OwningType> and this param is not
+ // one of those, it means there is at least one member after a factory.
+ if (weak_ptr_factory_location.isValid() &&
+ !param_is_weak_ptr_factory_to_self) {
+ diagnostic().Report(weak_ptr_factory_location,
+ diag_weak_ptr_factory_order_);
+ }
}
}
diff --git a/tools/clang/plugins/tests/weak_ptr_factory.cpp b/tools/clang/plugins/tests/weak_ptr_factory.cpp
index 79c23b4..50de97c 100644
--- a/tools/clang/plugins/tests/weak_ptr_factory.cpp
+++ b/tools/clang/plugins/tests/weak_ptr_factory.cpp
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "weak_ptr_factory.h"
+
namespace should_succeed {
class OnlyMember {
@@ -27,6 +28,13 @@
base::WeakPtrFactory<FirstFactoryRefersToOtherType> factory_;
};
+class TwoFactories {
+ bool bool_member_;
+ int int_member_;
+ base::WeakPtrFactory<TwoFactories> factory1_;
+ base::WeakPtrFactory<TwoFactories> factory2_;
+};
+
} // namespace should_succeed
namespace should_fail {
@@ -42,6 +50,13 @@
int int_member_;
};
+class TwoFactoriesOneBad {
+ bool bool_member_;
+ base::WeakPtrFactory<TwoFactoriesOneBad> factory1_;
+ int int_member_;
+ base::WeakPtrFactory<TwoFactoriesOneBad> factory2_;
+};
+
} // namespace should_fail
int main() {
diff --git a/tools/clang/plugins/tests/weak_ptr_factory.txt b/tools/clang/plugins/tests/weak_ptr_factory.txt
index f9c2c0a..820b7db 100644
--- a/tools/clang/plugins/tests/weak_ptr_factory.txt
+++ b/tools/clang/plugins/tests/weak_ptr_factory.txt
@@ -1,7 +1,10 @@
-weak_ptr_factory.cpp:35:38: warning: [chromium-style] WeakPtrFactory members which refer to their outer class must be the last member in the outer class definition.
+weak_ptr_factory.cpp:43:38: warning: [chromium-style] WeakPtrFactory members which refer to their outer class must be the last member in the outer class definition.
base::WeakPtrFactory<FactoryFirst> factory_;
^
-weak_ptr_factory.cpp:41:39: warning: [chromium-style] WeakPtrFactory members which refer to their outer class must be the last member in the outer class definition.
+weak_ptr_factory.cpp:49:39: warning: [chromium-style] WeakPtrFactory members which refer to their outer class must be the last member in the outer class definition.
base::WeakPtrFactory<FactoryMiddle> factory_;
^
-2 warnings generated.
+weak_ptr_factory.cpp:55:44: warning: [chromium-style] WeakPtrFactory members which refer to their outer class must be the last member in the outer class definition.
+ base::WeakPtrFactory<TwoFactoriesOneBad> factory1_;
+ ^
+3 warnings generated.
diff --git a/tools/clang/rewrite_scoped_refptr/CMakeLists.txt b/tools/clang/rewrite_scoped_refptr/CMakeLists.txt
index 9b0184d..aa47400 100644
--- a/tools/clang/rewrite_scoped_refptr/CMakeLists.txt
+++ b/tools/clang/rewrite_scoped_refptr/CMakeLists.txt
@@ -2,6 +2,7 @@
BitReader
MCParser
Option
+ X86AsmParser
)
add_llvm_executable(rewrite_scoped_refptr
diff --git a/tools/clang/rewrite_scoped_refptr/RewriteScopedRefptr.cpp b/tools/clang/rewrite_scoped_refptr/RewriteScopedRefptr.cpp
index fe9d860..e11d5f9 100644
--- a/tools/clang/rewrite_scoped_refptr/RewriteScopedRefptr.cpp
+++ b/tools/clang/rewrite_scoped_refptr/RewriteScopedRefptr.cpp
@@ -22,6 +22,7 @@
#include "clang/Tooling/Refactoring.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/support/TargetSelect.h"
using namespace clang::ast_matchers;
using clang::tooling::CommonOptionsParser;
@@ -255,6 +256,10 @@
static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
int main(int argc, const char* argv[]) {
+ // TODO(dcheng): Clang tooling should do this itself.
+ // http://llvm.org/bugs/show_bug.cgi?id=21627
+ llvm::InitializeNativeTarget();
+ llvm::InitializeNativeTargetAsmParser();
llvm::cl::OptionCategory category("Remove scoped_refptr conversions");
CommonOptionsParser options(argc, argv, category);
clang::tooling::ClangTool tool(options.getCompilations(),
diff --git a/tools/clang/scripts/generate_win_compdb.py b/tools/clang/scripts/generate_win_compdb.py
new file mode 100755
index 0000000..32f5f75
--- /dev/null
+++ b/tools/clang/scripts/generate_win_compdb.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+# Copyright 2014 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.
+
+"""
+Clang tools on Windows are still a bit busted. The tooling can't handle
+backslashes in paths, doesn't understand how to read .rsp files, etc. In
+addition, ninja generates compile commands prefixed with the ninja msvc helper,
+which also confuses clang. This script generates a compile DB that should mostly
+work until clang tooling can be improved upstream.
+"""
+
+import os
+import re
+import json
+import shlex
+import subprocess
+import sys
+
+
+_NINJA_MSVC_WRAPPER = re.compile('ninja -t msvc -e .+? -- ')
+_RSP_RE = re.compile(r' (@(.+?\.rsp)) ')
+
+
+def _ProcessEntry(e):
+ # Strip off the ninja -t msvc wrapper.
+ e['command'] = _NINJA_MSVC_WRAPPER.sub('', e['command'])
+
+ # Prepend --driver-mode=cl to the command's arguments.
+ # Escape backslashes so shlex doesn't try to interpret them.
+ escaped_command = e['command'].replace('\\', '\\\\')
+ split_command = shlex.split(escaped_command)
+ e['command'] = ' '.join(
+ split_command[:1] + ['--driver-mode=cl'] + split_command[1:])
+
+ # Expand the contents of the response file, if any.
+ # http://llvm.org/bugs/show_bug.cgi?id=21634
+ try:
+ match = _RSP_RE.search(e['command'])
+ rsp_path = os.path.join(e['directory'], match.group(2))
+ rsp_contents = file(rsp_path).read()
+ e['command'] = ''.join([
+ e['command'][:match.start(1)],
+ rsp_contents,
+ e['command'][match.end(1):]])
+ except IOError:
+ pass
+
+ # TODO(dcheng): This should be implemented in Clang tooling.
+ # http://llvm.org/bugs/show_bug.cgi?id=19687
+ # Finally, use slashes instead of backslashes to avoid bad escaping by the
+ # tooling. This should really only matter for command, but we do it for all
+ # keys for consistency.
+ e['directory'] = e['directory'].replace('\\', '/')
+ e['command'] = e['command'].replace('\\', '/')
+ e['file'] = e['file'].replace('\\', '/')
+
+ return e
+
+
+def main(argv):
+ # First, generate the compile database.
+ print 'Generating compile DB with ninja...'
+ compile_db_as_json = subprocess.check_output(shlex.split(
+ 'ninja -C out/Debug -t compdb cc cxx objc objcxx'))
+
+ compile_db = json.loads(compile_db_as_json)
+ print 'Read in %d entries from the compile db' % len(compile_db)
+ compile_db = [_ProcessEntry(e) for e in compile_db]
+ original_length = len(compile_db)
+
+ # Filter out NaCl stuff. The clang tooling chokes on them.
+ compile_db = [e for e in compile_db if '_nacl.cc.pdb' not in e['command']
+ and '_nacl_win64.cc.pdb' not in e['command']]
+ print 'Filtered out %d entries...' % (original_length - len(compile_db))
+ f = file('out/Debug/compile_commands.json', 'w')
+ f.write(json.dumps(compile_db, indent=2))
+ print 'Done!'
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/tools/clang/scripts/run_tool.py b/tools/clang/scripts/run_tool.py
index 61417e4..3725ca3 100755
--- a/tools/clang/scripts/run_tool.py
+++ b/tools/clang/scripts/run_tool.py
@@ -9,6 +9,9 @@
If you want to run the tool across all Chromium code:
run_tool.py <tool> <path/to/compiledb>
+If you want to include all files mentioned in the compilation database:
+run_tool.py <tool> <path/to/compiledb> --all
+
If you only want to run the tool across just chrome/browser and content/browser:
run_tool.py <tool> <path/to/compiledb> chrome/browser content/browser
@@ -37,6 +40,7 @@
import collections
import functools
+import json
import multiprocessing
import os.path
import pipes
@@ -67,6 +71,20 @@
return [os.path.realpath(p) for p in output.splitlines()]
+def _GetFilesFromCompileDB(build_directory):
+ """ Gets the list of files mentioned in the compilation database.
+
+ Args:
+ build_directory: Directory that contains the compile database.
+ """
+ compiledb_path = os.path.join(build_directory, 'compile_commands.json')
+ with open(compiledb_path, 'rb') as compiledb_file:
+ json_commands = json.load(compiledb_file)
+
+ return [os.path.join(entry['directory'], entry['file'])
+ for entry in json_commands]
+
+
def _ExtractEditsFromStdout(build_directory, stdout):
"""Extracts generated list of edits from the tool's stdout.
@@ -295,7 +313,10 @@
if not os.path.isfile(clang_format_diff_path) or sys.platform == 'win32':
clang_format_diff_path = None
- filenames = frozenset(_GetFilesFromGit(argv[2:]))
+ if len(argv) == 3 and argv[2] == '--all':
+ filenames = frozenset(_GetFilesFromCompileDB(argv[1]))
+ else:
+ filenames = frozenset(_GetFilesFromGit(argv[2:]))
# Filter out files that aren't C/C++/Obj-C/Obj-C++.
extensions = frozenset(('.c', '.cc', '.m', '.mm'))
dispatcher = _CompilerDispatcher(argv[0], argv[1],
diff --git a/tools/clang/scripts/update.sh b/tools/clang/scripts/update.sh
index e576cac..ad534ad 100755
--- a/tools/clang/scripts/update.sh
+++ b/tools/clang/scripts/update.sh
@@ -704,7 +704,8 @@
--platform=android-14 \
--install-dir="${LLVM_BUILD_DIR}/android-toolchain" \
--system=linux-x86_64 \
- --stl=stlport
+ --stl=stlport \
+ --toolchain=arm-linux-androideabi-4.9
# Android NDK r9d copies a broken unwind.h into the toolchain, see
# http://crbug.com/357890
diff --git a/tools/clang/translation_unit/CMakeLists.txt b/tools/clang/translation_unit/CMakeLists.txt
new file mode 100644
index 0000000..9b4fd8b
--- /dev/null
+++ b/tools/clang/translation_unit/CMakeLists.txt
@@ -0,0 +1,26 @@
+set(LLVM_LINK_COMPONENTS
+ BitReader
+ MCParser
+ Option
+ )
+
+add_llvm_executable(translation_unit
+ TranslationUnitGenerator.cpp
+ )
+
+target_link_libraries(translation_unit
+ clangAST
+ clangASTMatchers
+ clangAnalysis
+ clangBasic
+ clangDriver
+ clangEdit
+ clangFrontend
+ clangLex
+ clangParse
+ clangSema
+ clangSerialization
+ clangTooling
+ )
+
+cr_install(TARGETS translation_unit RUNTIME DESTINATION bin)
diff --git a/tools/clang/translation_unit/TranslationUnitGenerator.cpp b/tools/clang/translation_unit/TranslationUnitGenerator.cpp
new file mode 100644
index 0000000..df9eaeb
--- /dev/null
+++ b/tools/clang/translation_unit/TranslationUnitGenerator.cpp
@@ -0,0 +1,218 @@
+// Copyright (c) 2014 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 generate compilation information that is
+// sufficient to recompile the code with clang. For each compilation unit, all
+// source files which are necessary for compiling it are determined. For each
+// compilation unit, a file is created containing a list of all file paths of
+// included files.
+
+#include <assert.h>
+#include <unistd.h>
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <set>
+#include <stack>
+#include <string>
+#include <vector>
+
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Refactoring.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/CommandLine.h"
+
+using clang::tooling::CommonOptionsParser;
+using std::set;
+using std::stack;
+using std::string;
+using std::vector;
+
+namespace {
+// Set of preprocessor callbacks used to record files included.
+class IncludeFinderPPCallbacks : public clang::PPCallbacks {
+ public:
+ IncludeFinderPPCallbacks(clang::SourceManager* source_manager,
+ string* main_source_file,
+ set<string>* source_file_paths)
+ : source_manager_(source_manager),
+ main_source_file_(main_source_file),
+ source_file_paths_(source_file_paths) {}
+ void FileChanged(clang::SourceLocation /*loc*/,
+ clang::PPCallbacks::FileChangeReason reason,
+ clang::SrcMgr::CharacteristicKind /*file_type*/,
+ clang::FileID /*prev_fid*/) override;
+ void AddFile(const string& path);
+ void InclusionDirective(clang::SourceLocation hash_loc,
+ const clang::Token& include_tok,
+ llvm::StringRef file_name,
+ bool is_angled,
+ clang::CharSourceRange range,
+ const clang::FileEntry* file,
+ llvm::StringRef search_path,
+ llvm::StringRef relative_path,
+ const clang::Module* imported) override;
+ void EndOfMainFile() override;
+
+ private:
+ clang::SourceManager* const source_manager_;
+ string* const main_source_file_;
+ set<string>* const source_file_paths_;
+ // The path of the file that was last referenced by an inclusion directive,
+ // normalized for includes that are relative to a different source file.
+ string last_inclusion_directive_;
+ // The stack of currently parsed files. top() gives the current file.
+ stack<string> current_files_;
+};
+
+void IncludeFinderPPCallbacks::FileChanged(
+ clang::SourceLocation /*loc*/,
+ clang::PPCallbacks::FileChangeReason reason,
+ clang::SrcMgr::CharacteristicKind /*file_type*/,
+ clang::FileID /*prev_fid*/) {
+ if (reason == clang::PPCallbacks::EnterFile) {
+ if (!last_inclusion_directive_.empty()) {
+ current_files_.push(last_inclusion_directive_);
+ } else {
+ current_files_.push(
+ source_manager_->getFileEntryForID(source_manager_->getMainFileID())
+ ->getName());
+ }
+ } else if (reason == ExitFile) {
+ current_files_.pop();
+ }
+ // Other reasons are not interesting for us.
+}
+
+void IncludeFinderPPCallbacks::AddFile(const string& path) {
+ source_file_paths_->insert(path);
+}
+
+void IncludeFinderPPCallbacks::InclusionDirective(
+ clang::SourceLocation hash_loc,
+ const clang::Token& include_tok,
+ llvm::StringRef file_name,
+ bool is_angled,
+ clang::CharSourceRange range,
+ const clang::FileEntry* file,
+ llvm::StringRef search_path,
+ llvm::StringRef relative_path,
+ const clang::Module* imported) {
+ if (!file)
+ return;
+
+ assert(!current_files_.top().empty());
+ const clang::DirectoryEntry* const search_path_entry =
+ source_manager_->getFileManager().getDirectory(search_path);
+ const clang::DirectoryEntry* const current_file_parent_entry =
+ source_manager_->getFileManager()
+ .getFile(current_files_.top().c_str())
+ ->getDir();
+
+ // If the include file was found relatively to the current file's parent
+ // directory or a search path, we need to normalize it. This is necessary
+ // because llvm internalizes the path by which an inode was first accessed,
+ // and always returns that path afterwards. If we do not normalize this
+ // we will get an error when we replay the compilation, as the virtual
+ // file system is not aware of inodes.
+ if (search_path_entry == current_file_parent_entry) {
+ string parent =
+ llvm::sys::path::parent_path(current_files_.top().c_str()).str();
+
+ // If the file is a top level file ("file.cc"), we normalize to a path
+ // relative to "./".
+ if (parent.empty() || parent == "/")
+ parent = ".";
+
+ // Otherwise we take the literal path as we stored it for the current
+ // file, and append the relative path.
+ last_inclusion_directive_ = parent + "/" + relative_path.str();
+ } else if (!search_path.empty()) {
+ last_inclusion_directive_ = string(search_path) + "/" + relative_path.str();
+ } else {
+ last_inclusion_directive_ = file_name.str();
+ }
+ AddFile(last_inclusion_directive_);
+}
+
+void IncludeFinderPPCallbacks::EndOfMainFile() {
+ const clang::FileEntry* main_file =
+ source_manager_->getFileEntryForID(source_manager_->getMainFileID());
+ assert(*main_source_file_ == main_file->getName());
+ AddFile(main_file->getName());
+}
+
+class CompilationIndexerAction : public clang::PreprocessorFrontendAction {
+ public:
+ CompilationIndexerAction() {}
+ void ExecuteAction() override;
+
+ // Runs the preprocessor over the translation unit.
+ // This triggers the PPCallbacks we register to intercept all required
+ // files for the compilation.
+ void Preprocess();
+ void EndSourceFileAction() override;
+
+ private:
+ // Set up the state extracted during the compilation, and run Clang over the
+ // input.
+ string main_source_file_;
+ // Maps file names to their contents as read by Clang's source manager.
+ set<string> source_file_paths_;
+};
+
+void CompilationIndexerAction::ExecuteAction() {
+ vector<clang::FrontendInputFile> inputs =
+ getCompilerInstance().getFrontendOpts().Inputs;
+ assert(inputs.size() == 1);
+ main_source_file_ = inputs[0].getFile();
+
+ Preprocess();
+}
+
+void CompilationIndexerAction::Preprocess() {
+ clang::Preprocessor& preprocessor = getCompilerInstance().getPreprocessor();
+ preprocessor.addPPCallbacks(llvm::make_unique<IncludeFinderPPCallbacks>(
+ &getCompilerInstance().getSourceManager(),
+ &main_source_file_,
+ &source_file_paths_));
+ preprocessor.IgnorePragmas();
+ preprocessor.SetSuppressIncludeNotFoundError(true);
+ preprocessor.EnterMainSourceFile();
+ clang::Token token;
+ do {
+ preprocessor.Lex(token);
+ } while (token.isNot(clang::tok::eof));
+}
+
+void CompilationIndexerAction::EndSourceFileAction() {
+ std::ofstream out(main_source_file_ + ".filepaths");
+ for (string path : source_file_paths_) {
+ out << path << std::endl;
+ }
+}
+} // namespace
+
+static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage);
+
+int main(int argc, const char* argv[]) {
+ llvm::cl::OptionCategory category("TranslationUnitGenerator Tool");
+ CommonOptionsParser options(argc, argv, category);
+ std::unique_ptr<clang::tooling::FrontendActionFactory> frontend_factory =
+ clang::tooling::newFrontendActionFactory<CompilationIndexerAction>();
+ clang::tooling::ClangTool tool(options.getCompilations(),
+ options.getSourcePathList());
+ // This clang tool does not actually produce edits, but run_tool.py expects
+ // this. So we just print an empty edit block.
+ llvm::outs() << "==== BEGIN EDITS ====\n";
+ llvm::outs() << "==== END EDITS ====\n";
+ return tool.run(frontend_factory.get());
+}
diff --git a/tools/clang/translation_unit/test_files/binomial.h b/tools/clang/translation_unit/test_files/binomial.h
new file mode 100644
index 0000000..c67b273
--- /dev/null
+++ b/tools/clang/translation_unit/test_files/binomial.h
@@ -0,0 +1,12 @@
+// Copyright (c) 2014 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.
+//
+#ifndef TOOLS_CLANG_TRANSLATION_UNIT_TEST_FILES_BINOMIAL_H_
+#define TOOLS_CLANG_TRANSLATION_UNIT_TEST_FILES_BINOMIAL_H_
+
+int binomial(int n, int k) {
+ return k > 0 ? binomial(n - 1, k - 1) * n / k : 1;
+}
+
+#endif // TOOLS_CLANG_TRANSLATION_UNIT_TEST_FILES_BINOMIAL_H_
diff --git a/tools/clang/translation_unit/test_files/test.cc b/tools/clang/translation_unit/test_files/test.cc
new file mode 100644
index 0000000..e735f55
--- /dev/null
+++ b/tools/clang/translation_unit/test_files/test.cc
@@ -0,0 +1,16 @@
+// Copyright (c) 2014 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.
+
+#include "test.h"
+
+#include "binomial.h"
+
+// Notice that "binomial.h" is included both here and in the "test.h" file.
+// The tool should however print the path to this header file only once.
+
+int main() {
+ // Just some nonesense calculations.
+ int result = calculateNumberOfWaysToDistributeNItemsAmongKPersons(10, 5);
+ return result + binomial(42, 1);
+}
diff --git a/tools/clang/translation_unit/test_files/test.cc.filepaths.expected b/tools/clang/translation_unit/test_files/test.cc.filepaths.expected
new file mode 100644
index 0000000..3dc4421
--- /dev/null
+++ b/tools/clang/translation_unit/test_files/test.cc.filepaths.expected
@@ -0,0 +1,3 @@
+./binomial.h
+./test.cc
+./test.h
diff --git a/tools/clang/translation_unit/test_files/test.h b/tools/clang/translation_unit/test_files/test.h
new file mode 100644
index 0000000..8cc20ce
--- /dev/null
+++ b/tools/clang/translation_unit/test_files/test.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2014 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.
+
+#ifndef TOOLS_CLANG_TRANSLATION_UNIT_TEST_FILES_TEST_H_
+#define TOOLS_CLANG_TRANSLATION_UNIT_TEST_FILES_TEST_H_
+
+#include "binomial.h"
+
+// Number of ways to distribute n items of the same thing to k persons; each
+// person should get at least one item.
+int calculateNumberOfWaysToDistributeNItemsAmongKPersons(int n, int k) {
+ return binomial(n - 1, k - 1);
+}
+
+#endif // TOOLS_CLANG_TRANSLATION_UNIT_TEST_FILES_TEST_H_
diff --git a/tools/clang/translation_unit/test_translation_unit.py b/tools/clang/translation_unit/test_translation_unit.py
new file mode 100755
index 0000000..eb5cce8
--- /dev/null
+++ b/tools/clang/translation_unit/test_translation_unit.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+# Copyright (c) 2014 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.
+
+"""Test for TranslationUnitGenerator tool."""
+
+import difflib
+import glob
+import json
+import ntpath
+import os
+import os.path
+import subprocess
+import sys
+
+
+def _GenerateCompileCommands(files):
+ """Returns a JSON string containing a compilation database for the input."""
+ return json.dumps([{'directory': '.',
+ 'command': 'clang++ -fsyntax-only -std=c++11 -c %s' % f,
+ 'file': f} for f in files], indent=2)
+
+
+def _NumberOfTestsToString(tests):
+ """Returns an English sentence describing the number of tests."""
+ return "%d test%s" % (tests, 's' if tests != 1 else '')
+
+
+# Before running this test script, please build the translation_unit clang tool
+# first. This is explained here:
+# https://code.google.com/p/chromium/wiki/ClangToolRefactoring
+def main():
+ tools_clang_directory = os.path.dirname(os.path.dirname(
+ os.path.realpath(__file__)))
+ tools_clang_scripts_directory = os.path.join(tools_clang_directory, 'scripts')
+ test_directory_for_tool = os.path.join(
+ tools_clang_directory, 'translation_unit', 'test_files')
+ compile_database = os.path.join(test_directory_for_tool,
+ 'compile_commands.json')
+ source_files = glob.glob(os.path.join(test_directory_for_tool, '*.cc'))
+
+ # Generate a temporary compilation database to run the tool over.
+ with open(compile_database, 'w') as f:
+ f.write(_GenerateCompileCommands(source_files))
+
+ args = ['python',
+ os.path.join(tools_clang_scripts_directory, 'run_tool.py'),
+ 'translation_unit',
+ test_directory_for_tool]
+ args.extend(source_files)
+ run_tool = subprocess.Popen(args, stdout=subprocess.PIPE)
+ stdout, _ = run_tool.communicate()
+ if run_tool.returncode != 0:
+ print 'run_tool failed:\n%s' % stdout
+ sys.exit(1)
+
+ passed = 0
+ failed = 0
+ for actual in source_files:
+ actual += '.filepaths'
+ expected = actual + '.expected'
+ print '[ RUN ] %s' % os.path.relpath(actual)
+ expected_output = actual_output = None
+ with open(expected, 'r') as f:
+ expected_output = f.readlines()
+ with open(actual, 'r') as f:
+ actual_output = f.readlines()
+ has_same_filepaths = True
+ for expected_line, actual_line in zip(expected_output, actual_output):
+ if ntpath.basename(expected_line) != ntpath.basename(actual_line):
+ sys.stdout.write(ntpath.basename(expected_line))
+ sys.stdout.write(ntpath.basename(actual_line))
+ has_same_filepaths = False
+ break
+ if not has_same_filepaths:
+ failed += 1
+ for line in difflib.unified_diff(expected_output, actual_output,
+ fromfile=os.path.relpath(expected),
+ tofile=os.path.relpath(actual)):
+ sys.stdout.write(line)
+ print '[ FAILED ] %s' % os.path.relpath(actual)
+ # Don't clean up the file on failure, so the results can be referenced
+ # more easily.
+ continue
+ print '[ OK ] %s' % os.path.relpath(actual)
+ passed += 1
+ os.remove(actual)
+
+ if failed == 0:
+ os.remove(compile_database)
+
+ print '[==========] %s ran.' % _NumberOfTestsToString(len(source_files))
+ if passed > 0:
+ print '[ PASSED ] %s.' % _NumberOfTestsToString(passed)
+ if failed > 0:
+ print '[ FAILED ] %s.' % _NumberOfTestsToString(failed)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/tools/valgrind/chrome_tests.py b/tools/valgrind/chrome_tests.py
index 8f5432f..677cb63 100755
--- a/tools/valgrind/chrome_tests.py
+++ b/tools/valgrind/chrome_tests.py
@@ -470,6 +470,9 @@
def TestUIBaseUnit(self):
return self.SimpleTest("chrome", "ui_base_unittests")
+ def TestUIChromeOS(self):
+ return self.SimpleTest("chrome", "ui_chromeos_unittests")
+
def TestURL(self):
return self.SimpleTest("chrome", "url_unittests")
@@ -712,6 +715,7 @@
"sync_integration_tests": TestSyncIntegration,
"sync_integration": TestSyncIntegration,
"ui_base_unit": TestUIBaseUnit, "ui_base_unittests": TestUIBaseUnit,
+ "ui_chromeos": TestUIChromeOS, "ui_chromeos_unittests": TestUIChromeOS,
"unit": TestUnit, "unit_tests": TestUnit,
"url": TestURL, "url_unittests": TestURL,
"views": TestViews, "views_unittests": TestViews,
diff --git a/tools/valgrind/gtest_exclude/base_unittests.gtest.txt b/tools/valgrind/gtest_exclude/base_unittests.gtest.txt
index aa85c27..74a4ac5 100644
--- a/tools/valgrind/gtest_exclude/base_unittests.gtest.txt
+++ b/tools/valgrind/gtest_exclude/base_unittests.gtest.txt
@@ -27,3 +27,6 @@
# Crashes under Valgrind, see http://crbug.com/355436
OutOfMemoryHandledTest.Unchecked*
+
+# Fail under Valgrind, see http://crbug.com/431702
+ProcMapsTest.ReadProcMaps
diff --git a/tools/valgrind/gtest_exclude/components_unittests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/components_unittests.gtest-drmemory_win32.txt
new file mode 100644
index 0000000..a8edd28
--- /dev/null
+++ b/tools/valgrind/gtest_exclude/components_unittests.gtest-drmemory_win32.txt
@@ -0,0 +1,3 @@
+# http://crbug.com/435320
+MetricsServiceTest.InitialStabilityLogAfterCrash
+MetricsServiceTest.InitialStabilityLogAtProviderRequest
diff --git a/tools/valgrind/gtest_exclude/content_unittests.gtest.txt b/tools/valgrind/gtest_exclude/content_unittests.gtest.txt
index 3376b22..03eb062 100644
--- a/tools/valgrind/gtest_exclude/content_unittests.gtest.txt
+++ b/tools/valgrind/gtest_exclude/content_unittests.gtest.txt
@@ -10,3 +10,6 @@
# http://crbug.com/430391
WebDataConsumerHandleImplTest.*
+
+# http://crbug.com/435441
+PluginLoaderPosixTest.*