summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/moz-patch-stack/0097.patch
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/moz-patch-stack/0097.patch')
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0097.patch2207
1 files changed, 2183 insertions, 24 deletions
diff --git a/third_party/libwebrtc/moz-patch-stack/0097.patch b/third_party/libwebrtc/moz-patch-stack/0097.patch
index 983834acba..56c8dca72b 100644
--- a/third_party/libwebrtc/moz-patch-stack/0097.patch
+++ b/third_party/libwebrtc/moz-patch-stack/0097.patch
@@ -1,27 +1,2186 @@
-From: Andreas Pehrson <apehrson@mozilla.com>
-Date: Wed, 18 Oct 2023 17:21:00 +0000
-Subject: Bug 1859786 - Fix clang-tidy warning in video_capture_impl.cc.
- r=webrtc-reviewers,mjf
+From: Dan Minor <dminor@mozilla.com>
+Date: Thu, 24 Sep 2020 18:28:00 +0000
+Subject: Bug 1665166 - Move media/webrtc/trunk/* to third-party/libwebrtc;
+ r=ng
-clang-tidy says:
- 'auto dataCallBack' can be declared as 'auto *dataCallBack'
-
-Differential Revision: https://phabricator.services.mozilla.com/D191302
-Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/26c84d214137a1b0de0902c7038756964e5786f4
+Differential Revision: https://phabricator.services.mozilla.com/D91317
+Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/57e3c54bd7b9a0203e19ff1df272d24bb551ed29
---
- modules/video_capture/video_capture_impl.cc | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
+ tools/clang/OWNERS | 2 +
+ tools/clang/plugins/ChromeClassTester.cpp | 294 ++++++++++++
+ tools/clang/plugins/ChromeClassTester.h | 84 ++++
+ tools/clang/plugins/FindBadConstructs.cpp | 435 ++++++++++++++++++
+ tools/clang/plugins/Makefile | 19 +
+ tools/clang/plugins/OWNERS | 1 +
+ tools/clang/plugins/README.chromium | 4 +
+ tools/clang/plugins/tests/base_refcounted.cpp | 72 +++
+ tools/clang/plugins/tests/base_refcounted.h | 121 +++++
+ tools/clang/plugins/tests/base_refcounted.txt | 23 +
+ .../clang/plugins/tests/inline_copy_ctor.cpp | 5 +
+ tools/clang/plugins/tests/inline_copy_ctor.h | 12 +
+ .../clang/plugins/tests/inline_copy_ctor.txt | 5 +
+ tools/clang/plugins/tests/inline_ctor.cpp | 25 +
+ tools/clang/plugins/tests/inline_ctor.h | 21 +
+ tools/clang/plugins/tests/inline_ctor.txt | 8 +
+ tools/clang/plugins/tests/missing_ctor.cpp | 23 +
+ tools/clang/plugins/tests/missing_ctor.h | 19 +
+ tools/clang/plugins/tests/missing_ctor.txt | 6 +
+ .../tests/nested_class_inline_ctor.cpp | 5 +
+ .../plugins/tests/nested_class_inline_ctor.h | 22 +
+ .../tests/nested_class_inline_ctor.txt | 8 +
+ .../plugins/tests/overridden_methods.cpp | 38 ++
+ .../clang/plugins/tests/overridden_methods.h | 54 +++
+ .../plugins/tests/overridden_methods.txt | 20 +
+ tools/clang/plugins/tests/test.sh | 72 +++
+ tools/clang/plugins/tests/virtual_methods.cpp | 36 ++
+ tools/clang/plugins/tests/virtual_methods.h | 39 ++
+ tools/clang/plugins/tests/virtual_methods.txt | 8 +
+ tools/clang/scripts/package.sh | 87 ++++
+ tools/clang/scripts/plugin_flags.sh | 24 +
+ tools/clang/scripts/update.py | 34 ++
+ tools/clang/scripts/update.sh | 286 ++++++++++++
+ 33 files changed, 1912 insertions(+)
+ create mode 100644 tools/clang/OWNERS
+ create mode 100644 tools/clang/plugins/ChromeClassTester.cpp
+ create mode 100644 tools/clang/plugins/ChromeClassTester.h
+ create mode 100644 tools/clang/plugins/FindBadConstructs.cpp
+ create mode 100644 tools/clang/plugins/Makefile
+ create mode 100644 tools/clang/plugins/OWNERS
+ create mode 100644 tools/clang/plugins/README.chromium
+ create mode 100644 tools/clang/plugins/tests/base_refcounted.cpp
+ create mode 100644 tools/clang/plugins/tests/base_refcounted.h
+ create mode 100644 tools/clang/plugins/tests/base_refcounted.txt
+ create mode 100644 tools/clang/plugins/tests/inline_copy_ctor.cpp
+ create mode 100644 tools/clang/plugins/tests/inline_copy_ctor.h
+ create mode 100644 tools/clang/plugins/tests/inline_copy_ctor.txt
+ create mode 100644 tools/clang/plugins/tests/inline_ctor.cpp
+ create mode 100644 tools/clang/plugins/tests/inline_ctor.h
+ create mode 100644 tools/clang/plugins/tests/inline_ctor.txt
+ create mode 100644 tools/clang/plugins/tests/missing_ctor.cpp
+ create mode 100644 tools/clang/plugins/tests/missing_ctor.h
+ create mode 100644 tools/clang/plugins/tests/missing_ctor.txt
+ create mode 100644 tools/clang/plugins/tests/nested_class_inline_ctor.cpp
+ create mode 100644 tools/clang/plugins/tests/nested_class_inline_ctor.h
+ create mode 100644 tools/clang/plugins/tests/nested_class_inline_ctor.txt
+ create mode 100644 tools/clang/plugins/tests/overridden_methods.cpp
+ create mode 100644 tools/clang/plugins/tests/overridden_methods.h
+ create mode 100644 tools/clang/plugins/tests/overridden_methods.txt
+ create mode 100755 tools/clang/plugins/tests/test.sh
+ create mode 100644 tools/clang/plugins/tests/virtual_methods.cpp
+ create mode 100644 tools/clang/plugins/tests/virtual_methods.h
+ create mode 100644 tools/clang/plugins/tests/virtual_methods.txt
+ create mode 100755 tools/clang/scripts/package.sh
+ create mode 100755 tools/clang/scripts/plugin_flags.sh
+ create mode 100755 tools/clang/scripts/update.py
+ create mode 100755 tools/clang/scripts/update.sh
-diff --git a/modules/video_capture/video_capture_impl.cc b/modules/video_capture/video_capture_impl.cc
-index 1bddaf824d..15dfb7fe1f 100644
---- a/modules/video_capture/video_capture_impl.cc
-+++ b/modules/video_capture/video_capture_impl.cc
-@@ -134,7 +134,7 @@ int32_t VideoCaptureImpl::DeliverCapturedFrame(VideoFrame& captureFrame) {
-
- UpdateFrameCount(); // frame count used for local frame rate callback.
-
-- for (auto dataCallBack : _dataCallBacks) {
-+ for (auto* dataCallBack : _dataCallBacks) {
- dataCallBack->OnFrame(captureFrame);
- }
-
+diff --git a/tools/clang/OWNERS b/tools/clang/OWNERS
+new file mode 100644
+index 0000000000..d86ef9424a
+--- /dev/null
++++ b/tools/clang/OWNERS
+@@ -0,0 +1,2 @@
++hans@chromium.org
++thakis@chromium.org
+diff --git a/tools/clang/plugins/ChromeClassTester.cpp b/tools/clang/plugins/ChromeClassTester.cpp
+new file mode 100644
+index 0000000000..055866c5c5
+--- /dev/null
++++ b/tools/clang/plugins/ChromeClassTester.cpp
+@@ -0,0 +1,294 @@
++// Copyright (c) 2012 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.
++
++// A general interface for filtering and only acting on classes in Chromium C++
++// code.
++
++#include "ChromeClassTester.h"
++
++#include <sys/param.h>
++
++#include "clang/AST/AST.h"
++#include "clang/Basic/FileManager.h"
++#include "clang/Basic/SourceManager.h"
++
++using namespace clang;
++
++namespace {
++
++bool starts_with(const std::string& one, const std::string& two) {
++ return one.compare(0, two.size(), two) == 0;
++}
++
++std::string lstrip(const std::string& one, const std::string& two) {
++ if (starts_with(one, two))
++ return one.substr(two.size());
++ return one;
++}
++
++bool ends_with(const std::string& one, const std::string& two) {
++ if (two.size() > one.size())
++ return false;
++
++ return one.compare(one.size() - two.size(), two.size(), two) == 0;
++}
++
++} // namespace
++
++ChromeClassTester::ChromeClassTester(CompilerInstance& instance)
++ : instance_(instance),
++ diagnostic_(instance.getDiagnostics()) {
++ BuildBannedLists();
++}
++
++ChromeClassTester::~ChromeClassTester() {}
++
++void ChromeClassTester::HandleTagDeclDefinition(TagDecl* tag) {
++ pending_class_decls_.push_back(tag);
++}
++
++bool ChromeClassTester::HandleTopLevelDecl(DeclGroupRef group_ref) {
++ for (size_t i = 0; i < pending_class_decls_.size(); ++i)
++ CheckTag(pending_class_decls_[i]);
++ pending_class_decls_.clear();
++
++ return true; // true means continue parsing.
++}
++
++void ChromeClassTester::CheckTag(TagDecl* tag) {
++ // We handle class types here where we have semantic information. We can only
++ // check structs/classes/enums here, but we get a bunch of nice semantic
++ // information instead of just parsing information.
++
++ if (CXXRecordDecl* record = dyn_cast<CXXRecordDecl>(tag)) {
++ // If this is a POD or a class template or a type dependent on a
++ // templated class, assume there's no ctor/dtor/virtual method
++ // optimization that we can do.
++ if (record->isPOD() ||
++ record->getDescribedClassTemplate() ||
++ record->getTemplateSpecializationKind() ||
++ record->isDependentType())
++ return;
++
++ if (InBannedNamespace(record))
++ return;
++
++ SourceLocation record_location = record->getInnerLocStart();
++ if (InBannedDirectory(record_location))
++ return;
++
++ // We sadly need to maintain a blacklist of types that violate these
++ // rules, but do so for good reason or due to limitations of this
++ // checker (i.e., we don't handle extern templates very well).
++ std::string base_name = record->getNameAsString();
++ if (IsIgnoredType(base_name))
++ return;
++
++ // We ignore all classes that end with "Matcher" because they're probably
++ // GMock artifacts.
++ if (ends_with(base_name, "Matcher"))
++ return;
++
++ CheckChromeClass(record_location, record);
++ }
++}
++
++void ChromeClassTester::emitWarning(SourceLocation loc,
++ const char* raw_error) {
++ FullSourceLoc full(loc, instance().getSourceManager());
++ std::string err;
++ err = "[chromium-style] ";
++ err += raw_error;
++ DiagnosticsEngine::Level level =
++ diagnostic().getWarningsAsErrors() ?
++ DiagnosticsEngine::Error :
++ DiagnosticsEngine::Warning;
++ unsigned id = diagnostic().getCustomDiagID(level, err);
++ DiagnosticBuilder builder = diagnostic().Report(full, id);
++}
++
++bool ChromeClassTester::InBannedNamespace(const Decl* record) {
++ std::string n = GetNamespace(record);
++ if (!n.empty()) {
++ return std::find(banned_namespaces_.begin(), banned_namespaces_.end(), n)
++ != banned_namespaces_.end();
++ }
++
++ return false;
++}
++
++std::string ChromeClassTester::GetNamespace(const Decl* record) {
++ return GetNamespaceImpl(record->getDeclContext(), "");
++}
++
++bool ChromeClassTester::InImplementationFile(SourceLocation record_location) {
++ std::string filename;
++ if (!GetFilename(record_location, &filename))
++ return false;
++
++ if (ends_with(filename, ".cc") || ends_with(filename, ".cpp") ||
++ ends_with(filename, ".mm")) {
++ return true;
++ }
++
++ return false;
++}
++
++void ChromeClassTester::BuildBannedLists() {
++ banned_namespaces_.push_back("std");
++ banned_namespaces_.push_back("__gnu_cxx");
++ banned_namespaces_.push_back("WebKit");
++
++ banned_directories_.push_back("third_party/");
++ banned_directories_.push_back("native_client/");
++ banned_directories_.push_back("breakpad/");
++ banned_directories_.push_back("courgette/");
++ banned_directories_.push_back("pdf/");
++ banned_directories_.push_back("ppapi/");
++ banned_directories_.push_back("usr/");
++ banned_directories_.push_back("testing/");
++ banned_directories_.push_back("googleurl/");
++ banned_directories_.push_back("v8/");
++ banned_directories_.push_back("dart/");
++ banned_directories_.push_back("sdch/");
++ banned_directories_.push_back("icu4c/");
++ banned_directories_.push_back("frameworks/");
++
++ // Don't check autogenerated headers.
++ // Make puts them below $(builddir_name)/.../gen and geni.
++ // Ninja puts them below OUTPUT_DIR/.../gen
++ // Xcode has a fixed output directory for everything.
++ banned_directories_.push_back("gen/");
++ banned_directories_.push_back("geni/");
++ banned_directories_.push_back("xcodebuild/");
++
++ // You are standing in a mazy of twisty dependencies, all resolved by
++ // putting everything in the header.
++ banned_directories_.push_back("automation/");
++
++ // Don't check system headers.
++ banned_directories_.push_back("/Developer/");
++
++ // Used in really low level threading code that probably shouldn't be out of
++ // lined.
++ ignored_record_names_.insert("ThreadLocalBoolean");
++
++ // A complicated pickle derived struct that is all packed integers.
++ ignored_record_names_.insert("Header");
++
++ // Part of the GPU system that uses multiple included header
++ // weirdness. Never getting this right.
++ ignored_record_names_.insert("Validators");
++
++ // Has a UNIT_TEST only constructor. Isn't *terribly* complex...
++ ignored_record_names_.insert("AutocompleteController");
++ ignored_record_names_.insert("HistoryURLProvider");
++
++ // Because of chrome frame
++ ignored_record_names_.insert("ReliabilityTestSuite");
++
++ // Used over in the net unittests. A large enough bundle of integers with 1
++ // non-pod class member. Probably harmless.
++ ignored_record_names_.insert("MockTransaction");
++
++ // Used heavily in ui_unittests and once in views_unittests. Fixing this
++ // isn't worth the overhead of an additional library.
++ ignored_record_names_.insert("TestAnimationDelegate");
++
++ // Part of our public interface that nacl and friends use. (Arguably, this
++ // should mean that this is a higher priority but fixing this looks hard.)
++ ignored_record_names_.insert("PluginVersionInfo");
++}
++
++std::string ChromeClassTester::GetNamespaceImpl(const DeclContext* context,
++ const std::string& candidate) {
++ switch (context->getDeclKind()) {
++ case Decl::TranslationUnit: {
++ return candidate;
++ }
++ case Decl::Namespace: {
++ const NamespaceDecl* decl = dyn_cast<NamespaceDecl>(context);
++ std::string name_str;
++ llvm::raw_string_ostream OS(name_str);
++ if (decl->isAnonymousNamespace())
++ OS << "<anonymous namespace>";
++ else
++ OS << *decl;
++ return GetNamespaceImpl(context->getParent(),
++ OS.str());
++ }
++ default: {
++ return GetNamespaceImpl(context->getParent(), candidate);
++ }
++ }
++}
++
++bool ChromeClassTester::InBannedDirectory(SourceLocation loc) {
++ std::string filename;
++ if (!GetFilename(loc, &filename)) {
++ // If the filename cannot be determined, simply treat this as a banned
++ // location, instead of going through the full lookup process.
++ return true;
++ }
++
++ // We need to special case scratch space; which is where clang does its
++ // macro expansion. We explicitly want to allow people to do otherwise bad
++ // things through macros that were defined due to third party libraries.
++ if (filename == "<scratch space>")
++ return true;
++
++ // Don't complain about autogenerated protobuf files.
++ if (ends_with(filename, ".pb.h")) {
++ return true;
++ }
++
++ // We need to munge the paths so that they are relative to the repository
++ // srcroot. We first resolve the symlinktastic relative path and then
++ // remove our known srcroot from it if needed.
++ char resolvedPath[MAXPATHLEN];
++ if (realpath(filename.c_str(), resolvedPath)) {
++ filename = resolvedPath;
++ }
++
++ // On linux, chrome is often checked out to /usr/local/google. Due to the
++ // "usr" rule in banned_directories_, all diagnostics would be suppressed
++ // in that case. As a workaround, strip that prefix.
++ filename = lstrip(filename, "/usr/local/google");
++
++ for (std::vector<std::string>::const_iterator it =
++ banned_directories_.begin();
++ it != banned_directories_.end(); ++it) {
++ // If we can find any of the banned path components in this path, then
++ // this file is rejected.
++ size_t index = filename.find(*it);
++ if (index != std::string::npos) {
++ bool matches_full_dir_name = index == 0 || filename[index - 1] == '/';
++ if ((*it)[0] == '/')
++ matches_full_dir_name = true;
++ if (matches_full_dir_name)
++ return true;
++ }
++ }
++
++ return false;
++}
++
++bool ChromeClassTester::IsIgnoredType(const std::string& base_name) {
++ return ignored_record_names_.find(base_name) != ignored_record_names_.end();
++}
++
++bool ChromeClassTester::GetFilename(SourceLocation loc,
++ std::string* filename) {
++ const SourceManager& source_manager = instance_.getSourceManager();
++ SourceLocation spelling_location = source_manager.getSpellingLoc(loc);
++ PresumedLoc ploc = source_manager.getPresumedLoc(spelling_location);
++ if (ploc.isInvalid()) {
++ // If we're in an invalid location, we're looking at things that aren't
++ // actually stated in the source.
++ return false;
++ }
++
++ *filename = ploc.getFilename();
++ return true;
++}
+diff --git a/tools/clang/plugins/ChromeClassTester.h b/tools/clang/plugins/ChromeClassTester.h
+new file mode 100644
+index 0000000000..588ae9cae5
+--- /dev/null
++++ b/tools/clang/plugins/ChromeClassTester.h
+@@ -0,0 +1,84 @@
++// Copyright (c) 2012 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_PLUGINS_CHROMECLASSTESTER_H_
++#define TOOLS_CLANG_PLUGINS_CHROMECLASSTESTER_H_
++
++#include <set>
++#include <vector>
++
++#include "clang/AST/ASTConsumer.h"
++#include "clang/AST/TypeLoc.h"
++#include "clang/Frontend/CompilerInstance.h"
++
++// A class on top of ASTConsumer that forwards classes defined in Chromium
++// headers to subclasses which implement CheckChromeClass().
++class ChromeClassTester : public clang::ASTConsumer {
++ public:
++ explicit ChromeClassTester(clang::CompilerInstance& instance);
++ virtual ~ChromeClassTester();
++
++ // clang::ASTConsumer:
++ virtual void HandleTagDeclDefinition(clang::TagDecl* tag);
++ virtual bool HandleTopLevelDecl(clang::DeclGroupRef group_ref);
++
++ protected:
++ clang::CompilerInstance& instance() { return instance_; }
++ clang::DiagnosticsEngine& diagnostic() { return diagnostic_; }
++
++ // Emits a simple warning; this shouldn't be used if you require printf-style
++ // printing.
++ void emitWarning(clang::SourceLocation loc, const char* error);
++
++ // Utility method for subclasses to check if this class is in a banned
++ // namespace.
++ bool InBannedNamespace(const clang::Decl* record);
++
++ // Utility method for subclasses to determine the namespace of the
++ // specified record, if any. Unnamed namespaces will be identified as
++ // "<anonymous namespace>".
++ std::string GetNamespace(const clang::Decl* record);
++
++ // Utility method for subclasses to check if this class is within an
++ // implementation (.cc, .cpp, .mm) file.
++ bool InImplementationFile(clang::SourceLocation location);
++
++ private:
++ void BuildBannedLists();
++
++ void CheckTag(clang::TagDecl*);
++
++ // Filtered versions of tags that are only called with things defined in
++ // chrome header files.
++ virtual void CheckChromeClass(clang::SourceLocation record_location,
++ clang::CXXRecordDecl* record) = 0;
++
++ // Utility methods used for filtering out non-chrome classes (and ones we
++ // deliberately ignore) in HandleTagDeclDefinition().
++ std::string GetNamespaceImpl(const clang::DeclContext* context,
++ const std::string& candidate);
++ bool InBannedDirectory(clang::SourceLocation loc);
++ bool IsIgnoredType(const std::string& base_name);
++
++ // Attempts to determine the filename for the given SourceLocation.
++ // Returns false if the filename could not be determined.
++ bool GetFilename(clang::SourceLocation loc, std::string* filename);
++
++ clang::CompilerInstance& instance_;
++ clang::DiagnosticsEngine& diagnostic_;
++
++ // List of banned namespaces.
++ std::vector<std::string> banned_namespaces_;
++
++ // List of banned directories.
++ std::vector<std::string> banned_directories_;
++
++ // List of types that we don't check.
++ std::set<std::string> ignored_record_names_;
++
++ // List of decls to check once the current top-level decl is parsed.
++ std::vector<clang::TagDecl*> pending_class_decls_;
++};
++
++#endif // TOOLS_CLANG_PLUGINS_CHROMECLASSTESTER_H_
+diff --git a/tools/clang/plugins/FindBadConstructs.cpp b/tools/clang/plugins/FindBadConstructs.cpp
+new file mode 100644
+index 0000000000..b79a64dbd1
+--- /dev/null
++++ b/tools/clang/plugins/FindBadConstructs.cpp
+@@ -0,0 +1,435 @@
++// Copyright (c) 2012 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 file defines a bunch of recurring problems in the Chromium C++ code.
++//
++// Checks that are implemented:
++// - Constructors/Destructors should not be inlined if they are of a complex
++// class type.
++// - Missing "virtual" keywords on methods that should be virtual.
++// - Non-annotated overriding virtual methods.
++// - Virtual methods with nonempty implementations in their headers.
++// - Classes that derive from base::RefCounted / base::RefCountedThreadSafe
++// should have protected or private destructors.
++
++#include "clang/Frontend/FrontendPluginRegistry.h"
++#include "clang/AST/ASTConsumer.h"
++#include "clang/AST/AST.h"
++#include "clang/AST/CXXInheritance.h"
++#include "clang/AST/TypeLoc.h"
++#include "clang/Basic/SourceManager.h"
++#include "clang/Frontend/CompilerInstance.h"
++#include "llvm/Support/raw_ostream.h"
++
++#include "ChromeClassTester.h"
++
++using namespace clang;
++
++namespace {
++
++bool TypeHasNonTrivialDtor(const Type* type) {
++ if (const CXXRecordDecl* cxx_r = type->getCXXRecordDeclForPointerType())
++ return cxx_r->hasTrivialDestructor();
++
++ return false;
++}
++
++// Returns the underlying Type for |type| by expanding typedefs and removing
++// any namespace qualifiers.
++const Type* UnwrapType(const Type* type) {
++ if (const ElaboratedType* elaborated = dyn_cast<ElaboratedType>(type))
++ return UnwrapType(elaborated->getNamedType().getTypePtr());
++ if (const TypedefType* typedefed = dyn_cast<TypedefType>(type))
++ return UnwrapType(typedefed->desugar().getTypePtr());
++ return type;
++}
++
++// Searches for constructs that we know we don't want in the Chromium code base.
++class FindBadConstructsConsumer : public ChromeClassTester {
++ public:
++ FindBadConstructsConsumer(CompilerInstance& instance,
++ bool check_refcounted_dtors,
++ bool check_virtuals_in_implementations)
++ : ChromeClassTester(instance),
++ check_refcounted_dtors_(check_refcounted_dtors),
++ check_virtuals_in_implementations_(check_virtuals_in_implementations) {
++ }
++
++ virtual void CheckChromeClass(SourceLocation record_location,
++ CXXRecordDecl* record) {
++ bool implementation_file = InImplementationFile(record_location);
++
++ if (!implementation_file) {
++ // Only check for "heavy" constructors/destructors in header files;
++ // within implementation files, there is no performance cost.
++ CheckCtorDtorWeight(record_location, record);
++ }
++
++ if (!implementation_file || check_virtuals_in_implementations_) {
++ bool warn_on_inline_bodies = !implementation_file;
++
++ // Check that all virtual methods are marked accordingly with both
++ // virtual and OVERRIDE.
++ CheckVirtualMethods(record_location, record, warn_on_inline_bodies);
++ }
++
++ if (check_refcounted_dtors_)
++ CheckRefCountedDtors(record_location, record);
++ }
++
++ private:
++ bool check_refcounted_dtors_;
++ bool check_virtuals_in_implementations_;
++
++ // Returns true if |base| specifies one of the Chromium reference counted
++ // classes (base::RefCounted / base::RefCountedThreadSafe). |user_data| is
++ // ignored.
++ static bool IsRefCountedCallback(const CXXBaseSpecifier* base,
++ CXXBasePath& path,
++ void* user_data) {
++ FindBadConstructsConsumer* self =
++ static_cast<FindBadConstructsConsumer*>(user_data);
++
++ const TemplateSpecializationType* base_type =
++ dyn_cast<TemplateSpecializationType>(
++ UnwrapType(base->getType().getTypePtr()));
++ if (!base_type) {
++ // Base-most definition is not a template, so this cannot derive from
++ // base::RefCounted. However, it may still be possible to use with a
++ // scoped_refptr<> and support ref-counting, so this is not a perfect
++ // guarantee of safety.
++ return false;
++ }
++
++ TemplateName name = base_type->getTemplateName();
++ if (TemplateDecl* decl = name.getAsTemplateDecl()) {
++ std::string base_name = decl->getNameAsString();
++
++ // Check for both base::RefCounted and base::RefCountedThreadSafe.
++ if (base_name.compare(0, 10, "RefCounted") == 0 &&
++ self->GetNamespace(decl) == "base") {
++ return true;
++ }
++ }
++ return false;
++ }
++
++ // Prints errors if the destructor of a RefCounted class is public.
++ void CheckRefCountedDtors(SourceLocation record_location,
++ CXXRecordDecl* record) {
++ // Skip anonymous structs.
++ if (record->getIdentifier() == NULL)
++ return;
++
++ CXXBasePaths paths;
++ if (!record->lookupInBases(
++ &FindBadConstructsConsumer::IsRefCountedCallback, this, paths)) {
++ return; // Class does not derive from a ref-counted base class.
++ }
++
++ if (!record->hasUserDeclaredDestructor()) {
++ emitWarning(
++ record_location,
++ "Classes that are ref-counted should have explicit "
++ "destructors that are protected or private.");
++ } else if (CXXDestructorDecl* dtor = record->getDestructor()) {
++ if (dtor->getAccess() == AS_public) {
++ emitWarning(
++ dtor->getInnerLocStart(),
++ "Classes that are ref-counted should not have "
++ "public destructors.");
++ }
++ }
++ }
++
++ // Prints errors if the constructor/destructor weight is too heavy.
++ void CheckCtorDtorWeight(SourceLocation record_location,
++ CXXRecordDecl* record) {
++ // We don't handle anonymous structs. If this record doesn't have a
++ // name, it's of the form:
++ //
++ // struct {
++ // ...
++ // } name_;
++ if (record->getIdentifier() == NULL)
++ return;
++
++ // Count the number of templated base classes as a feature of whether the
++ // destructor can be inlined.
++ int templated_base_classes = 0;
++ for (CXXRecordDecl::base_class_const_iterator it = record->bases_begin();
++ it != record->bases_end(); ++it) {
++ if (it->getTypeSourceInfo()->getTypeLoc().getTypeLocClass() ==
++ TypeLoc::TemplateSpecialization) {
++ ++templated_base_classes;
++ }
++ }
++
++ // Count the number of trivial and non-trivial member variables.
++ int trivial_member = 0;
++ int non_trivial_member = 0;
++ int templated_non_trivial_member = 0;
++ for (RecordDecl::field_iterator it = record->field_begin();
++ it != record->field_end(); ++it) {
++ CountType(it->getType().getTypePtr(),
++ &trivial_member,
++ &non_trivial_member,
++ &templated_non_trivial_member);
++ }
++
++ // Check to see if we need to ban inlined/synthesized constructors. Note
++ // that the cutoffs here are kind of arbitrary. Scores over 10 break.
++ int dtor_score = 0;
++ // Deriving from a templated base class shouldn't be enough to trigger
++ // the ctor warning, but if you do *anything* else, it should.
++ //
++ // TODO(erg): This is motivated by templated base classes that don't have
++ // any data members. Somehow detect when templated base classes have data
++ // members and treat them differently.
++ dtor_score += templated_base_classes * 9;
++ // Instantiating a template is an insta-hit.
++ dtor_score += templated_non_trivial_member * 10;
++ // The fourth normal class member should trigger the warning.
++ dtor_score += non_trivial_member * 3;
++
++ int ctor_score = dtor_score;
++ // You should be able to have 9 ints before we warn you.
++ ctor_score += trivial_member;
++
++ if (ctor_score >= 10) {
++ if (!record->hasUserDeclaredConstructor()) {
++ emitWarning(record_location,
++ "Complex class/struct needs an explicit out-of-line "
++ "constructor.");
++ } else {
++ // Iterate across all the constructors in this file and yell if we
++ // find one that tries to be inline.
++ for (CXXRecordDecl::ctor_iterator it = record->ctor_begin();
++ it != record->ctor_end(); ++it) {
++ if (it->hasInlineBody()) {
++ if (it->isCopyConstructor() &&
++ !record->hasUserDeclaredCopyConstructor()) {
++ emitWarning(record_location,
++ "Complex class/struct needs an explicit out-of-line "
++ "copy constructor.");
++ } else {
++ emitWarning(it->getInnerLocStart(),
++ "Complex constructor has an inlined body.");
++ }
++ }
++ }
++ }
++ }
++
++ // The destructor side is equivalent except that we don't check for
++ // trivial members; 20 ints don't need a destructor.
++ if (dtor_score >= 10 && !record->hasTrivialDestructor()) {
++ if (!record->hasUserDeclaredDestructor()) {
++ emitWarning(
++ record_location,
++ "Complex class/struct needs an explicit out-of-line "
++ "destructor.");
++ } else if (CXXDestructorDecl* dtor = record->getDestructor()) {
++ if (dtor->hasInlineBody()) {
++ emitWarning(dtor->getInnerLocStart(),
++ "Complex destructor has an inline body.");
++ }
++ }
++ }
++ }
++
++ void CheckVirtualMethod(const CXXMethodDecl* method,
++ bool warn_on_inline_bodies) {
++ if (!method->isVirtual())
++ return;
++
++ if (!method->isVirtualAsWritten()) {
++ SourceLocation loc = method->getTypeSpecStartLoc();
++ if (isa<CXXDestructorDecl>(method))
++ loc = method->getInnerLocStart();
++ emitWarning(loc, "Overriding method must have \"virtual\" keyword.");
++ }
++
++ // Virtual methods should not have inline definitions beyond "{}". This
++ // only matters for header files.
++ if (warn_on_inline_bodies && method->hasBody() &&
++ method->hasInlineBody()) {
++ if (CompoundStmt* cs = dyn_cast<CompoundStmt>(method->getBody())) {
++ if (cs->size()) {
++ emitWarning(
++ cs->getLBracLoc(),
++ "virtual methods with non-empty bodies shouldn't be "
++ "declared inline.");
++ }
++ }
++ }
++ }
++
++ bool InTestingNamespace(const Decl* record) {
++ return GetNamespace(record).find("testing") != std::string::npos;
++ }
++
++ bool IsMethodInBannedNamespace(const CXXMethodDecl* method) {
++ if (InBannedNamespace(method))
++ return true;
++ for (CXXMethodDecl::method_iterator i = method->begin_overridden_methods();
++ i != method->end_overridden_methods();
++ ++i) {
++ const CXXMethodDecl* overridden = *i;
++ if (IsMethodInBannedNamespace(overridden))
++ return true;
++ }
++
++ return false;
++ }
++
++ void CheckOverriddenMethod(const CXXMethodDecl* method) {
++ if (!method->size_overridden_methods() || method->getAttr<OverrideAttr>())
++ return;
++
++ if (isa<CXXDestructorDecl>(method) || method->isPure())
++ return;
++
++ if (IsMethodInBannedNamespace(method))
++ return;
++
++ SourceLocation loc = method->getTypeSpecStartLoc();
++ emitWarning(loc, "Overriding method must be marked with OVERRIDE.");
++ }
++
++ // Makes sure there is a "virtual" keyword on virtual methods.
++ //
++ // Gmock objects trigger these for each MOCK_BLAH() macro used. So we have a
++ // trick to get around that. If a class has member variables whose types are
++ // in the "testing" namespace (which is how gmock works behind the scenes),
++ // there's a really high chance we won't care about these errors
++ void CheckVirtualMethods(SourceLocation record_location,
++ CXXRecordDecl* record,
++ bool warn_on_inline_bodies) {
++ for (CXXRecordDecl::field_iterator it = record->field_begin();
++ it != record->field_end(); ++it) {
++ CXXRecordDecl* record_type =
++ it->getTypeSourceInfo()->getTypeLoc().getTypePtr()->
++ getAsCXXRecordDecl();
++ if (record_type) {
++ if (InTestingNamespace(record_type)) {
++ return;
++ }
++ }
++ }
++
++ for (CXXRecordDecl::method_iterator it = record->method_begin();
++ it != record->method_end(); ++it) {
++ if (it->isCopyAssignmentOperator() || isa<CXXConstructorDecl>(*it)) {
++ // Ignore constructors and assignment operators.
++ } else if (isa<CXXDestructorDecl>(*it) &&
++ !record->hasUserDeclaredDestructor()) {
++ // Ignore non-user-declared destructors.
++ } else {
++ CheckVirtualMethod(*it, warn_on_inline_bodies);
++ CheckOverriddenMethod(*it);
++ }
++ }
++ }
++
++ void CountType(const Type* type,
++ int* trivial_member,
++ int* non_trivial_member,
++ int* templated_non_trivial_member) {
++ switch (type->getTypeClass()) {
++ case Type::Record: {
++ // Simplifying; the whole class isn't trivial if the dtor is, but
++ // we use this as a signal about complexity.
++ if (TypeHasNonTrivialDtor(type))
++ (*trivial_member)++;
++ else
++ (*non_trivial_member)++;
++ break;
++ }
++ case Type::TemplateSpecialization: {
++ TemplateName name =
++ dyn_cast<TemplateSpecializationType>(type)->getTemplateName();
++ bool whitelisted_template = false;
++
++ // HACK: I'm at a loss about how to get the syntax checker to get
++ // whether a template is exterened or not. For the first pass here,
++ // just do retarded string comparisons.
++ if (TemplateDecl* decl = name.getAsTemplateDecl()) {
++ std::string base_name = decl->getNameAsString();
++ if (base_name == "basic_string")
++ whitelisted_template = true;
++ }
++
++ if (whitelisted_template)
++ (*non_trivial_member)++;
++ else
++ (*templated_non_trivial_member)++;
++ break;
++ }
++ case Type::Elaborated: {
++ CountType(
++ dyn_cast<ElaboratedType>(type)->getNamedType().getTypePtr(),
++ trivial_member, non_trivial_member, templated_non_trivial_member);
++ break;
++ }
++ case Type::Typedef: {
++ while (const TypedefType* TT = dyn_cast<TypedefType>(type)) {
++ type = TT->getDecl()->getUnderlyingType().getTypePtr();
++ }
++ CountType(type, trivial_member, non_trivial_member,
++ templated_non_trivial_member);
++ break;
++ }
++ default: {
++ // Stupid assumption: anything we see that isn't the above is one of
++ // the 20 integer types.
++ (*trivial_member)++;
++ break;
++ }
++ }
++ }
++};
++
++class FindBadConstructsAction : public PluginASTAction {
++ public:
++ FindBadConstructsAction()
++ : check_refcounted_dtors_(true),
++ check_virtuals_in_implementations_(true) {
++ }
++
++ protected:
++ // Overridden from PluginASTAction:
++ virtual ASTConsumer* CreateASTConsumer(CompilerInstance& instance,
++ llvm::StringRef ref) {
++ return new FindBadConstructsConsumer(
++ instance, check_refcounted_dtors_, check_virtuals_in_implementations_);
++ }
++
++ virtual bool ParseArgs(const CompilerInstance& instance,
++ const std::vector<std::string>& args) {
++ bool parsed = true;
++
++ for (size_t i = 0; i < args.size() && parsed; ++i) {
++ if (args[i] == "skip-refcounted-dtors") {
++ check_refcounted_dtors_ = false;
++ } else if (args[i] == "skip-virtuals-in-implementations") {
++ check_virtuals_in_implementations_ = false;
++ } else {
++ parsed = false;
++ llvm::errs() << "Unknown argument: " << args[i] << "\n";
++ }
++ }
++
++ return parsed;
++ }
++
++ private:
++ bool check_refcounted_dtors_;
++ bool check_virtuals_in_implementations_;
++};
++
++} // namespace
++
++static FrontendPluginRegistry::Add<FindBadConstructsAction>
++X("find-bad-constructs", "Finds bad C++ constructs");
+diff --git a/tools/clang/plugins/Makefile b/tools/clang/plugins/Makefile
+new file mode 100644
+index 0000000000..0cfec71159
+--- /dev/null
++++ b/tools/clang/plugins/Makefile
+@@ -0,0 +1,19 @@
++# This file requires the clang build system, at least for now. So to use this
++# Makefile, you should execute the following commands to copy this directory
++# into a clang checkout:
++#
++# cp -R <this directory> third_party/llvm/tools/clang/tools/chrome-plugin
++# cd third_party/llvm/tools/clang/tools/chrome-plugin
++# make
++
++CLANG_LEVEL := ../..
++LIBRARYNAME = FindBadConstructs
++
++LINK_LIBS_IN_SHARED = 0
++SHARED_LIBRARY = 1
++
++include $(CLANG_LEVEL)/Makefile
++
++ifeq ($(OS),Darwin)
++ LDFLAGS=-Wl,-undefined,dynamic_lookup
++endif
+diff --git a/tools/clang/plugins/OWNERS b/tools/clang/plugins/OWNERS
+new file mode 100644
+index 0000000000..4733a4f06b
+--- /dev/null
++++ b/tools/clang/plugins/OWNERS
+@@ -0,0 +1 @@
++erg@chromium.org
+diff --git a/tools/clang/plugins/README.chromium b/tools/clang/plugins/README.chromium
+new file mode 100644
+index 0000000000..a2ce0ff557
+--- /dev/null
++++ b/tools/clang/plugins/README.chromium
+@@ -0,0 +1,4 @@
++Documentation for this code is:
++
++- http://code.google.com/p/chromium/wiki/Clang
++- http://code.google.com/p/chromium/wiki/WritingClangPlugins
+diff --git a/tools/clang/plugins/tests/base_refcounted.cpp b/tools/clang/plugins/tests/base_refcounted.cpp
+new file mode 100644
+index 0000000000..364a3e888c
+--- /dev/null
++++ b/tools/clang/plugins/tests/base_refcounted.cpp
+@@ -0,0 +1,72 @@
++// Copyright (c) 2012 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 "base_refcounted.h"
++
++#include <cstddef>
++
++namespace {
++
++// Unsafe; should error.
++class AnonymousDerivedProtectedToPublicInImpl
++ : public ProtectedRefCountedDtorInHeader {
++ public:
++ AnonymousDerivedProtectedToPublicInImpl() {}
++ ~AnonymousDerivedProtectedToPublicInImpl() {}
++};
++
++} // namespace
++
++// Unsafe; should error.
++class PublicRefCountedDtorInImpl
++ : public base::RefCounted<PublicRefCountedDtorInImpl> {
++ public:
++ PublicRefCountedDtorInImpl() {}
++ ~PublicRefCountedDtorInImpl() {}
++
++ private:
++ friend class base::RefCounted<PublicRefCountedDtorInImpl>;
++};
++
++class Foo {
++ public:
++ class BarInterface {
++ protected:
++ virtual ~BarInterface() {}
++ };
++
++ typedef base::RefCounted<BarInterface> RefCountedBar;
++ typedef RefCountedBar AnotherTypedef;
++};
++
++class Baz {
++ public:
++ typedef typename Foo::AnotherTypedef MyLocalTypedef;
++};
++
++// Unsafe; should error.
++class UnsafeTypedefChainInImpl : public Baz::MyLocalTypedef {
++ public:
++ UnsafeTypedefChainInImpl() {}
++ ~UnsafeTypedefChainInImpl() {}
++};
++
++int main() {
++ PublicRefCountedDtorInHeader bad;
++ PublicRefCountedDtorInImpl also_bad;
++
++ ProtectedRefCountedDtorInHeader* protected_ok = NULL;
++ PrivateRefCountedDtorInHeader* private_ok = NULL;
++
++ DerivedProtectedToPublicInHeader still_bad;
++ PublicRefCountedThreadSafeDtorInHeader another_bad_variation;
++ AnonymousDerivedProtectedToPublicInImpl and_this_is_bad_too;
++ ImplicitDerivedProtectedToPublicInHeader bad_yet_again;
++ UnsafeTypedefChainInImpl and_again_this_is_bad;
++
++ WebKitPublicDtorInHeader ignored;
++ WebKitDerivedPublicDtorInHeader still_ignored;
++
++ return 0;
++}
+diff --git a/tools/clang/plugins/tests/base_refcounted.h b/tools/clang/plugins/tests/base_refcounted.h
+new file mode 100644
+index 0000000000..1e53215997
+--- /dev/null
++++ b/tools/clang/plugins/tests/base_refcounted.h
+@@ -0,0 +1,121 @@
++// Copyright (c) 2012 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 BASE_REFCOUNTED_H_
++#define BASE_REFCOUNTED_H_
++
++namespace base {
++
++template <typename T>
++class RefCounted {
++ public:
++ RefCounted() {}
++ ~RefCounted() {}
++};
++
++template <typename T>
++class RefCountedThreadSafe {
++ public:
++ RefCountedThreadSafe() {}
++ ~RefCountedThreadSafe() {}
++};
++
++} // namespace base
++
++// Ignore classes whose inheritance tree ends in WebKit's RefCounted base
++// class. Though prone to error, this pattern is very prevalent in WebKit
++// code, so do not issue any warnings.
++namespace WebKit {
++
++template <typename T>
++class RefCounted {
++ public:
++ RefCounted() {}
++ ~RefCounted() {}
++};
++
++} // namespace WebKit
++
++// Unsafe; should error.
++class PublicRefCountedDtorInHeader
++ : public base::RefCounted<PublicRefCountedDtorInHeader> {
++ public:
++ PublicRefCountedDtorInHeader() {}
++ ~PublicRefCountedDtorInHeader() {}
++
++ private:
++ friend class base::RefCounted<PublicRefCountedDtorInHeader>;
++};
++
++// Unsafe; should error.
++class PublicRefCountedThreadSafeDtorInHeader
++ : public base::RefCountedThreadSafe<
++ PublicRefCountedThreadSafeDtorInHeader> {
++ public:
++ PublicRefCountedThreadSafeDtorInHeader() {}
++ ~PublicRefCountedThreadSafeDtorInHeader() {}
++
++ private:
++ friend class base::RefCountedThreadSafe<
++ PublicRefCountedThreadSafeDtorInHeader>;
++};
++
++// Safe; should not have errors.
++class ProtectedRefCountedDtorInHeader
++ : public base::RefCounted<ProtectedRefCountedDtorInHeader> {
++ public:
++ ProtectedRefCountedDtorInHeader() {}
++
++ protected:
++ ~ProtectedRefCountedDtorInHeader() {}
++
++ private:
++ friend class base::RefCounted<ProtectedRefCountedDtorInHeader>;
++};
++
++// Safe; should not have errors.
++class PrivateRefCountedDtorInHeader
++ : public base::RefCounted<PrivateRefCountedDtorInHeader> {
++ public:
++ PrivateRefCountedDtorInHeader() {}
++
++ private:
++ ~PrivateRefCountedDtorInHeader() {}
++ friend class base::RefCounted<PrivateRefCountedDtorInHeader>;
++};
++
++// Unsafe; A grandchild class ends up exposing their parent and grandparent's
++// destructors.
++class DerivedProtectedToPublicInHeader
++ : public ProtectedRefCountedDtorInHeader {
++ public:
++ DerivedProtectedToPublicInHeader() {}
++ ~DerivedProtectedToPublicInHeader() {}
++};
++
++// Unsafe; A grandchild ends up implicitly exposing their parent and
++// grantparent's destructors.
++class ImplicitDerivedProtectedToPublicInHeader
++ : public ProtectedRefCountedDtorInHeader {
++ public:
++ ImplicitDerivedProtectedToPublicInHeader() {}
++};
++
++// Unsafe-but-ignored; should not have errors.
++class WebKitPublicDtorInHeader
++ : public WebKit::RefCounted<WebKitPublicDtorInHeader> {
++ public:
++ WebKitPublicDtorInHeader() {}
++ ~WebKitPublicDtorInHeader() {}
++};
++
++// Unsafe-but-ignored; should not have errors.
++class WebKitDerivedPublicDtorInHeader
++ : public WebKitPublicDtorInHeader {
++ public:
++ WebKitDerivedPublicDtorInHeader() {}
++ ~WebKitDerivedPublicDtorInHeader() {}
++};
++
++#endif // BASE_REFCOUNTED_H_
+diff --git a/tools/clang/plugins/tests/base_refcounted.txt b/tools/clang/plugins/tests/base_refcounted.txt
+new file mode 100644
+index 0000000000..4626424177
+--- /dev/null
++++ b/tools/clang/plugins/tests/base_refcounted.txt
+@@ -0,0 +1,23 @@
++In file included from base_refcounted.cpp:5:
++./base_refcounted.h:45:3: warning: [chromium-style] Classes that are ref-counted should not have public destructors.
++ ~PublicRefCountedDtorInHeader() {}
++ ^
++./base_refcounted.h:57:3: warning: [chromium-style] Classes that are ref-counted should not have public destructors.
++ ~PublicRefCountedThreadSafeDtorInHeader() {}
++ ^
++./base_refcounted.h:94:3: warning: [chromium-style] Classes that are ref-counted should not have public destructors.
++ ~DerivedProtectedToPublicInHeader() {}
++ ^
++./base_refcounted.h:99:1: warning: [chromium-style] Classes that are ref-counted should have explicit destructors that are protected or private.
++class ImplicitDerivedProtectedToPublicInHeader
++^
++base_refcounted.cpp:16:3: warning: [chromium-style] Classes that are ref-counted should not have public destructors.
++ ~AnonymousDerivedProtectedToPublicInImpl() {}
++ ^
++base_refcounted.cpp:26:3: warning: [chromium-style] Classes that are ref-counted should not have public destructors.
++ ~PublicRefCountedDtorInImpl() {}
++ ^
++base_refcounted.cpp:52:3: warning: [chromium-style] Classes that are ref-counted should not have public destructors.
++ ~UnsafeTypedefChainInImpl() {}
++ ^
++7 warnings generated.
+diff --git a/tools/clang/plugins/tests/inline_copy_ctor.cpp b/tools/clang/plugins/tests/inline_copy_ctor.cpp
+new file mode 100644
+index 0000000000..dcd90020c5
+--- /dev/null
++++ b/tools/clang/plugins/tests/inline_copy_ctor.cpp
+@@ -0,0 +1,5 @@
++// Copyright (c) 2012 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 "inline_copy_ctor.h"
+diff --git a/tools/clang/plugins/tests/inline_copy_ctor.h b/tools/clang/plugins/tests/inline_copy_ctor.h
+new file mode 100644
+index 0000000000..619a18392b
+--- /dev/null
++++ b/tools/clang/plugins/tests/inline_copy_ctor.h
+@@ -0,0 +1,12 @@
++// Copyright (c) 2012 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.
++
++struct C {
++ C();
++ ~C();
++
++ static C foo() { return C(); }
++
++ int a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p , q, r, s, t, u, v, w, x;
++};
+diff --git a/tools/clang/plugins/tests/inline_copy_ctor.txt b/tools/clang/plugins/tests/inline_copy_ctor.txt
+new file mode 100644
+index 0000000000..bc4bd8911e
+--- /dev/null
++++ b/tools/clang/plugins/tests/inline_copy_ctor.txt
+@@ -0,0 +1,5 @@
++In file included from inline_copy_ctor.cpp:5:
++./inline_copy_ctor.h:5:1: warning: [chromium-style] Complex class/struct needs an explicit out-of-line copy constructor.
++struct C {
++^
++1 warning generated.
+diff --git a/tools/clang/plugins/tests/inline_ctor.cpp b/tools/clang/plugins/tests/inline_ctor.cpp
+new file mode 100644
+index 0000000000..6a751fb405
+--- /dev/null
++++ b/tools/clang/plugins/tests/inline_ctor.cpp
+@@ -0,0 +1,25 @@
++// Copyright (c) 2011 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 "inline_ctor.h"
++
++#include <string>
++#include <vector>
++
++// We don't warn on classes that are in CPP files.
++class InlineInCPPOK {
++ public:
++ InlineInCPPOK() {}
++ ~InlineInCPPOK() {}
++
++ private:
++ std::vector<int> one_;
++ std::vector<std::string> two_;
++};
++
++int main() {
++ InlineInCPPOK one;
++ InlineCtorsArentOKInHeader two;
++ return 0;
++}
+diff --git a/tools/clang/plugins/tests/inline_ctor.h b/tools/clang/plugins/tests/inline_ctor.h
+new file mode 100644
+index 0000000000..d053b2f57d
+--- /dev/null
++++ b/tools/clang/plugins/tests/inline_ctor.h
+@@ -0,0 +1,21 @@
++// Copyright (c) 2012 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 INLINE_CTOR_H_
++#define INLINE_CTOR_H_
++
++#include <string>
++#include <vector>
++
++class InlineCtorsArentOKInHeader {
++ public:
++ InlineCtorsArentOKInHeader() {}
++ ~InlineCtorsArentOKInHeader() {}
++
++ private:
++ std::vector<int> one_;
++ std::vector<std::string> two_;
++};
++
++#endif // INLINE_CTOR_H_
+diff --git a/tools/clang/plugins/tests/inline_ctor.txt b/tools/clang/plugins/tests/inline_ctor.txt
+new file mode 100644
+index 0000000000..caa0cb4e3b
+--- /dev/null
++++ b/tools/clang/plugins/tests/inline_ctor.txt
+@@ -0,0 +1,8 @@
++In file included from inline_ctor.cpp:5:
++./inline_ctor.h:13:3: warning: [chromium-style] Complex constructor has an inlined body.
++ InlineCtorsArentOKInHeader() {}
++ ^
++./inline_ctor.h:14:3: warning: [chromium-style] Complex destructor has an inline body.
++ ~InlineCtorsArentOKInHeader() {}
++ ^
++2 warnings generated.
+diff --git a/tools/clang/plugins/tests/missing_ctor.cpp b/tools/clang/plugins/tests/missing_ctor.cpp
+new file mode 100644
+index 0000000000..8ee2fb2ac8
+--- /dev/null
++++ b/tools/clang/plugins/tests/missing_ctor.cpp
+@@ -0,0 +1,23 @@
++// Copyright (c) 2011 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 "missing_ctor.h"
++
++#include <string>
++#include <vector>
++
++// We don't warn on classes that use default ctors in cpp files.
++class MissingInCPPOK {
++ public:
++
++ private:
++ std::vector<int> one_;
++ std::vector<std::string> two_;
++};
++
++int main() {
++ MissingInCPPOK one;
++ MissingCtorsArentOKInHeader two;
++ return 0;
++}
+diff --git a/tools/clang/plugins/tests/missing_ctor.h b/tools/clang/plugins/tests/missing_ctor.h
+new file mode 100644
+index 0000000000..1050457a1a
+--- /dev/null
++++ b/tools/clang/plugins/tests/missing_ctor.h
+@@ -0,0 +1,19 @@
++// Copyright (c) 2011 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 MISSING_CTOR_H_
++#define MISSING_CTOR_H_
++
++#include <string>
++#include <vector>
++
++class MissingCtorsArentOKInHeader {
++ public:
++
++ private:
++ std::vector<int> one_;
++ std::vector<std::string> two_;
++};
++
++#endif // MISSING_CTOR_H_
+diff --git a/tools/clang/plugins/tests/missing_ctor.txt b/tools/clang/plugins/tests/missing_ctor.txt
+new file mode 100644
+index 0000000000..301449c4ac
+--- /dev/null
++++ b/tools/clang/plugins/tests/missing_ctor.txt
+@@ -0,0 +1,6 @@
++In file included from missing_ctor.cpp:5:
++./missing_ctor.h:11:1: warning: [chromium-style] Complex class/struct needs an explicit out-of-line constructor.
++class MissingCtorsArentOKInHeader {
++^
++./missing_ctor.h:11:1: warning: [chromium-style] Complex class/struct needs an explicit out-of-line destructor.
++2 warnings generated.
+diff --git a/tools/clang/plugins/tests/nested_class_inline_ctor.cpp b/tools/clang/plugins/tests/nested_class_inline_ctor.cpp
+new file mode 100644
+index 0000000000..aa90a95eb3
+--- /dev/null
++++ b/tools/clang/plugins/tests/nested_class_inline_ctor.cpp
+@@ -0,0 +1,5 @@
++// Copyright (c) 2012 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 "nested_class_inline_ctor.h"
+diff --git a/tools/clang/plugins/tests/nested_class_inline_ctor.h b/tools/clang/plugins/tests/nested_class_inline_ctor.h
+new file mode 100644
+index 0000000000..01cfea9232
+--- /dev/null
++++ b/tools/clang/plugins/tests/nested_class_inline_ctor.h
+@@ -0,0 +1,22 @@
++// Copyright (c) 2012 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 NESTED_CLASS_INLINE_CTOR_H_
++#define NESTED_CLASS_INLINE_CTOR_H_
++
++#include <string>
++#include <vector>
++
++// See crbug.com/136863.
++
++class Foo {
++ class Bar {
++ Bar() {}
++ ~Bar() {}
++
++ std::vector<std::string> a;
++ };
++};
++
++#endif // NESTED_CLASS_INLINE_CTOR_H_
+diff --git a/tools/clang/plugins/tests/nested_class_inline_ctor.txt b/tools/clang/plugins/tests/nested_class_inline_ctor.txt
+new file mode 100644
+index 0000000000..39bd6e1dce
+--- /dev/null
++++ b/tools/clang/plugins/tests/nested_class_inline_ctor.txt
+@@ -0,0 +1,8 @@
++In file included from nested_class_inline_ctor.cpp:5:
++./nested_class_inline_ctor.h:15:5: warning: [chromium-style] Complex constructor has an inlined body.
++ Bar() {}
++ ^
++./nested_class_inline_ctor.h:16:5: warning: [chromium-style] Complex destructor has an inline body.
++ ~Bar() {}
++ ^
++2 warnings generated.
+diff --git a/tools/clang/plugins/tests/overridden_methods.cpp b/tools/clang/plugins/tests/overridden_methods.cpp
+new file mode 100644
+index 0000000000..f572a41733
+--- /dev/null
++++ b/tools/clang/plugins/tests/overridden_methods.cpp
+@@ -0,0 +1,38 @@
++// Copyright (c) 2012 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 "overridden_methods.h"
++
++// Fill in the implementations
++void DerivedClass::SomeMethod() {}
++void DerivedClass::SomeOtherMethod() {}
++void DerivedClass::WebKitModifiedSomething() {}
++
++class ImplementationInterimClass : public BaseClass {
++ public:
++ // Should not warn about pure virtual methods.
++ virtual void SomeMethod() = 0;
++};
++
++class ImplementationDerivedClass : public ImplementationInterimClass,
++ public webkit_glue::WebKitObserverImpl {
++ public:
++ // Should not warn about destructors.
++ virtual ~ImplementationDerivedClass() {}
++ // Should warn.
++ virtual void SomeMethod();
++ // Should not warn if marked as override.
++ virtual void SomeOtherMethod() override;
++ // Should not warn for inline implementations in implementation files.
++ virtual void SomeInlineMethod() {}
++ // Should not warn if overriding a method whose origin is WebKit.
++ virtual void WebKitModifiedSomething();
++ // Should warn if overridden method isn't pure.
++ virtual void SomeNonPureBaseMethod() {}
++};
++
++int main() {
++ DerivedClass something;
++ ImplementationDerivedClass something_else;
++}
+diff --git a/tools/clang/plugins/tests/overridden_methods.h b/tools/clang/plugins/tests/overridden_methods.h
+new file mode 100644
+index 0000000000..150c79913f
+--- /dev/null
++++ b/tools/clang/plugins/tests/overridden_methods.h
+@@ -0,0 +1,54 @@
++// Copyright (c) 2011 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 OVERRIDDEN_METHODS_H_
++#define OVERRIDDEN_METHODS_H_
++
++// Should warn about overriding of methods.
++class BaseClass {
++ public:
++ virtual ~BaseClass() {}
++ virtual void SomeMethod() = 0;
++ virtual void SomeOtherMethod() = 0;
++ virtual void SomeInlineMethod() = 0;
++ virtual void SomeNonPureBaseMethod() {}
++};
++
++class InterimClass : public BaseClass {
++ // Should not warn about pure virtual methods.
++ virtual void SomeMethod() = 0;
++};
++
++namespace WebKit {
++class WebKitObserver {
++ public:
++ virtual void WebKitModifiedSomething() {};
++};
++} // namespace WebKit
++
++namespace webkit_glue {
++class WebKitObserverImpl : WebKit::WebKitObserver {
++ public:
++ virtual void WebKitModifiedSomething() {};
++};
++} // namespace webkit_glue
++
++class DerivedClass : public InterimClass,
++ public webkit_glue::WebKitObserverImpl {
++ public:
++ // Should not warn about destructors.
++ virtual ~DerivedClass() {}
++ // Should warn.
++ virtual void SomeMethod();
++ // Should not warn if marked as override.
++ virtual void SomeOtherMethod() override;
++ // Should warn for inline implementations.
++ virtual void SomeInlineMethod() {}
++ // Should not warn if overriding a method whose origin is WebKit.
++ virtual void WebKitModifiedSomething();
++ // Should warn if overridden method isn't pure.
++ virtual void SomeNonPureBaseMethod() {}
++};
++
++#endif // OVERRIDDEN_METHODS_H_
+diff --git a/tools/clang/plugins/tests/overridden_methods.txt b/tools/clang/plugins/tests/overridden_methods.txt
+new file mode 100644
+index 0000000000..7553ade70e
+--- /dev/null
++++ b/tools/clang/plugins/tests/overridden_methods.txt
+@@ -0,0 +1,20 @@
++In file included from overridden_methods.cpp:5:
++./overridden_methods.h:43:11: warning: [chromium-style] Overriding method must be marked with OVERRIDE.
++ virtual void SomeMethod();
++ ^
++./overridden_methods.h:47:11: warning: [chromium-style] Overriding method must be marked with OVERRIDE.
++ virtual void SomeInlineMethod() {}
++ ^
++./overridden_methods.h:51:11: warning: [chromium-style] Overriding method must be marked with OVERRIDE.
++ virtual void SomeNonPureBaseMethod() {}
++ ^
++overridden_methods.cpp:24:11: warning: [chromium-style] Overriding method must be marked with OVERRIDE.
++ virtual void SomeMethod();
++ ^
++overridden_methods.cpp:28:11: warning: [chromium-style] Overriding method must be marked with OVERRIDE.
++ virtual void SomeInlineMethod() {}
++ ^
++overridden_methods.cpp:32:11: warning: [chromium-style] Overriding method must be marked with OVERRIDE.
++ virtual void SomeNonPureBaseMethod() {}
++ ^
++6 warnings generated.
+diff --git a/tools/clang/plugins/tests/test.sh b/tools/clang/plugins/tests/test.sh
+new file mode 100755
+index 0000000000..262ebbba29
+--- /dev/null
++++ b/tools/clang/plugins/tests/test.sh
+@@ -0,0 +1,72 @@
++#!/bin/bash
++#
++# Copyright (c) 2011 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.
++#
++# Hacky, primitive testing: This runs the style plugin for a set of input files
++# and compares the output with golden result files.
++
++E_BADARGS=65
++E_FAILEDTEST=1
++
++failed_any_test=
++
++# Prints usage information.
++usage() {
++ echo "Usage: $(basename "${0}")" \
++ "<Path to the llvm build dir, usually Release+Asserts>"
++ echo ""
++ echo " Runs all the libFindBadConstructs unit tests"
++ echo ""
++}
++
++# Runs a single test case.
++do_testcase() {
++ local output="$("${CLANG_DIR}"/bin/clang -c -Wno-c++11-extensions \
++ -Xclang -load -Xclang "${CLANG_DIR}"/lib/libFindBadConstructs.${LIB} \
++ -Xclang -plugin -Xclang find-bad-constructs ${1} 2>&1)"
++ local diffout="$(echo "${output}" | diff - "${2}")"
++ if [ "${diffout}" = "" ]; then
++ echo "PASS: ${1}"
++ else
++ failed_any_test=yes
++ echo "FAIL: ${1}"
++ echo "Output of compiler:"
++ echo "${output}"
++ echo "Expected output:"
++ cat "${2}"
++ echo
++ fi
++}
++
++# Validate input to the script.
++if [[ -z "${1}" ]]; then
++ usage
++ exit ${E_BADARGS}
++elif [[ ! -d "${1}" ]]; then
++ echo "${1} is not a directory."
++ usage
++ exit ${E_BADARGS}
++else
++ export CLANG_DIR="${PWD}/${1}"
++ echo "Using clang directory ${CLANG_DIR}..."
++
++ # The golden files assume that the cwd is this directory. To make the script
++ # work no matter what the cwd is, explicitly cd to there.
++ cd "$(dirname "${0}")"
++
++ if [ "$(uname -s)" = "Linux" ]; then
++ export LIB=so
++ elif [ "$(uname -s)" = "Darwin" ]; then
++ export LIB=dylib
++ fi
++fi
++
++for input in *.cpp; do
++ do_testcase "${input}" "${input%cpp}txt"
++done
++
++if [[ "${failed_any_test}" ]]; then
++ exit ${E_FAILEDTEST}
++fi
+diff --git a/tools/clang/plugins/tests/virtual_methods.cpp b/tools/clang/plugins/tests/virtual_methods.cpp
+new file mode 100644
+index 0000000000..a07cbe4875
+--- /dev/null
++++ b/tools/clang/plugins/tests/virtual_methods.cpp
+@@ -0,0 +1,36 @@
++// Copyright (c) 2012 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 "virtual_methods.h"
++
++// Shouldn't warn about method usage in the implementation file.
++class VirtualMethodsInImplementation {
++ public:
++ virtual void MethodIsAbstract() = 0;
++ virtual void MethodHasNoArguments();
++ virtual void MethodHasEmptyDefaultImpl() {}
++ virtual bool ComplainAboutThis() { return true; }
++};
++
++// Stubs to fill in the abstract method
++class ConcreteVirtualMethodsInHeaders : public VirtualMethodsInHeaders {
++ public:
++ virtual void MethodIsAbstract() override {}
++};
++
++class ConcreteVirtualMethodsInImplementation
++ : public VirtualMethodsInImplementation {
++ public:
++ virtual void MethodIsAbstract() override {}
++};
++
++// Fill in the implementations
++void VirtualMethodsInHeaders::MethodHasNoArguments() {}
++void WarnOnMissingVirtual::MethodHasNoArguments() {}
++void VirtualMethodsInImplementation::MethodHasNoArguments() {}
++
++int main() {
++ ConcreteVirtualMethodsInHeaders one;
++ ConcreteVirtualMethodsInImplementation two;
++}
+diff --git a/tools/clang/plugins/tests/virtual_methods.h b/tools/clang/plugins/tests/virtual_methods.h
+new file mode 100644
+index 0000000000..d9fbf96ed3
+--- /dev/null
++++ b/tools/clang/plugins/tests/virtual_methods.h
+@@ -0,0 +1,39 @@
++// Copyright (c) 2011 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 VIRTUAL_METHODS_H_
++#define VIRTUAL_METHODS_H_
++
++// Should warn about virtual method usage.
++class VirtualMethodsInHeaders {
++ public:
++ // Don't complain about these.
++ virtual void MethodIsAbstract() = 0;
++ virtual void MethodHasNoArguments();
++ virtual void MethodHasEmptyDefaultImpl() {}
++
++ // But complain about this:
++ virtual bool ComplainAboutThis() { return true; }
++};
++
++// Complain on missing 'virtual' keyword in overrides.
++class WarnOnMissingVirtual : public VirtualMethodsInHeaders {
++ public:
++ void MethodHasNoArguments() override;
++};
++
++// Don't complain about things in a 'testing' namespace.
++namespace testing {
++struct TestStruct {};
++} // namespace testing
++
++class VirtualMethodsInHeadersTesting : public VirtualMethodsInHeaders {
++ public:
++ // Don't complain about no virtual testing methods.
++ void MethodHasNoArguments();
++ private:
++ testing::TestStruct tester_;
++};
++
++#endif // VIRTUAL_METHODS_H_
+diff --git a/tools/clang/plugins/tests/virtual_methods.txt b/tools/clang/plugins/tests/virtual_methods.txt
+new file mode 100644
+index 0000000000..571d6d667d
+--- /dev/null
++++ b/tools/clang/plugins/tests/virtual_methods.txt
+@@ -0,0 +1,8 @@
++In file included from virtual_methods.cpp:5:
++./virtual_methods.h:17:36: warning: [chromium-style] virtual methods with non-empty bodies shouldn't be declared inline.
++ virtual bool ComplainAboutThis() { return true; }
++ ^
++./virtual_methods.h:23:3: warning: [chromium-style] Overriding method must have "virtual" keyword.
++ void MethodHasNoArguments() override;
++ ^
++2 warnings generated.
+diff --git a/tools/clang/scripts/package.sh b/tools/clang/scripts/package.sh
+new file mode 100755
+index 0000000000..eb345810b9
+--- /dev/null
++++ b/tools/clang/scripts/package.sh
+@@ -0,0 +1,87 @@
++#!/bin/bash
++# Copyright (c) 2012 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 script will check out llvm and clang, and then package the results up
++# to a tgz file.
++
++THIS_DIR="$(dirname "${0}")"
++LLVM_DIR="${THIS_DIR}/../../../third_party/llvm"
++LLVM_BOOTSTRAP_DIR="${THIS_DIR}/../../../third_party/llvm-bootstrap"
++LLVM_BUILD_DIR="${THIS_DIR}/../../../third_party/llvm-build"
++LLVM_BIN_DIR="${LLVM_BUILD_DIR}/Release+Asserts/bin"
++LLVM_LIB_DIR="${LLVM_BUILD_DIR}/Release+Asserts/lib"
++
++echo "Diff in llvm:" | tee buildlog.txt
++svn stat "${LLVM_DIR}" 2>&1 | tee -a buildlog.txt
++svn diff "${LLVM_DIR}" 2>&1 | tee -a buildlog.txt
++echo "Diff in llvm/tools/clang:" | tee -a buildlog.txt
++svn stat "${LLVM_DIR}/tools/clang" 2>&1 | tee -a buildlog.txt
++svn diff "${LLVM_DIR}/tools/clang" 2>&1 | tee -a buildlog.txt
++echo "Diff in llvm/projects/compiler-rt:" | tee -a buildlog.txt
++svn stat "${LLVM_DIR}/projects/compiler-rt" 2>&1 | tee -a buildlog.txt
++svn diff "${LLVM_DIR}/projects/compiler-rt" 2>&1 | tee -a buildlog.txt
++
++echo "Starting build" | tee -a buildlog.txt
++
++set -ex
++
++# Do a clobber build.
++rm -rf "${LLVM_BOOTSTRAP_DIR}"
++rm -rf "${LLVM_BUILD_DIR}"
++"${THIS_DIR}"/update.sh --run-tests --bootstrap --force-local-build 2>&1 | \
++ tee -a buildlog.txt
++
++R=$("${LLVM_BIN_DIR}/clang" --version | \
++ sed -ne 's/clang version .*(trunk \([0-9]*\))/\1/p')
++
++PDIR=clang-$R
++rm -rf $PDIR
++mkdir $PDIR
++mkdir $PDIR/bin
++mkdir $PDIR/lib
++
++# Copy buildlog over.
++cp buildlog.txt $PDIR/
++
++# Copy clang into pdir, symlink clang++ to it.
++cp "${LLVM_BIN_DIR}/clang" $PDIR/bin/
++(cd $PDIR/bin && ln -sf clang clang++ && cd -)
++
++# Copy plugins. Some of the dylibs are pretty big, so copy only the ones we
++# care about.
++if [ "$(uname -s)" = "Darwin" ]; then
++ cp "${LLVM_LIB_DIR}/libFindBadConstructs.dylib" $PDIR/lib
++else
++ cp "${LLVM_LIB_DIR}/libFindBadConstructs.so" $PDIR/lib
++fi
++
++# Copy built-in headers (lib/clang/3.2/include).
++# libcompiler-rt puts all kinds of libraries there too, but we want only ASan.
++if [ "$(uname -s)" = "Darwin" ]; then
++ # Keep only Release+Asserts/lib/clang/3.2/lib/darwin/libclang_rt.asan_osx.a
++ find "${LLVM_LIB_DIR}/clang" -type f -path '*lib/darwin*' | grep -v asan | \
++ xargs rm
++else
++ # Keep only
++ # Release+Asserts/lib/clang/3.2/lib/linux/libclang_rt.{asan,tsan}-x86_64.a
++ # TODO(thakis): Make sure the 32bit version of ASan runtime is kept too once
++ # that's built. TSan runtime exists only for 64 bits.
++ find "${LLVM_LIB_DIR}/clang" -type f -path '*lib/linux*' | \
++ grep -v "asan\|tsan" | xargs rm
++fi
++
++cp -R "${LLVM_LIB_DIR}/clang" $PDIR/lib
++
++tar zcf $PDIR.tgz -C $PDIR bin lib buildlog.txt
++
++if [ "$(uname -s)" = "Darwin" ]; then
++ PLATFORM=Mac
++else
++ PLATFORM=Linux_x64
++fi
++
++echo To upload, run:
++echo gsutil cp -a public-read $PDIR.tgz \
++ gs://chromium-browser-clang/$PLATFORM/$PDIR.tgz
+diff --git a/tools/clang/scripts/plugin_flags.sh b/tools/clang/scripts/plugin_flags.sh
+new file mode 100755
+index 0000000000..217c5c3bd6
+--- /dev/null
++++ b/tools/clang/scripts/plugin_flags.sh
+@@ -0,0 +1,24 @@
++#!/bin/bash
++# Copyright (c) 2012 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 script returns the flags that should be used when GYP_DEFINES contains
++# clang_use_chrome_plugins. The flags are stored in a script so that they can
++# be changed on the bots without requiring a master restart.
++
++THIS_ABS_DIR=$(cd $(dirname $0) && echo $PWD)
++CLANG_LIB_PATH=$THIS_ABS_DIR/../../../third_party/llvm-build/Release+Asserts/lib
++
++if uname -s | grep -q Darwin; then
++ LIBSUFFIX=dylib
++else
++ LIBSUFFIX=so
++fi
++
++echo -Xclang -load -Xclang $CLANG_LIB_PATH/libFindBadConstructs.$LIBSUFFIX \
++ -Xclang -add-plugin -Xclang find-bad-constructs \
++ -Xclang -plugin-arg-find-bad-constructs \
++ -Xclang skip-virtuals-in-implementations \
++ -Xclang -plugin-arg-find-bad-constructs \
++ -Xclang check-cc-directory
+diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
+new file mode 100755
+index 0000000000..bdc781f715
+--- /dev/null
++++ b/tools/clang/scripts/update.py
+@@ -0,0 +1,34 @@
++#!/usr/bin/env python
++# Copyright (c) 2012 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.
++
++"""Windows can't run .sh files, so this is a small python wrapper around
++update.sh.
++"""
++
++import os
++import subprocess
++import sys
++
++
++def main():
++ if sys.platform in ['win32', 'cygwin']:
++ return 0
++
++ # This script is called by gclient. gclient opens its hooks subprocesses with
++ # (stdout=subprocess.PIPE, stderr=subprocess.STDOUT) and then does custom
++ # output processing that breaks printing '\r' characters for single-line
++ # updating status messages as printed by curl and wget.
++ # Work around this by setting stderr of the update.sh process to stdin (!):
++ # gclient doesn't redirect stdin, and while stdin itself is read-only, a
++ # dup()ed sys.stdin is writable, try
++ # fd2 = os.dup(sys.stdin.fileno()); os.write(fd2, 'hi')
++ # TODO: Fix gclient instead, http://crbug.com/95350
++ return subprocess.call(
++ [os.path.join(os.path.dirname(__file__), 'update.sh')] + sys.argv[1:],
++ stderr=os.fdopen(os.dup(sys.stdin.fileno())))
++
++
++if __name__ == '__main__':
++ sys.exit(main())
+diff --git a/tools/clang/scripts/update.sh b/tools/clang/scripts/update.sh
+new file mode 100755
+index 0000000000..e9448236c8
+--- /dev/null
++++ b/tools/clang/scripts/update.sh
+@@ -0,0 +1,286 @@
++#!/usr/bin/env bash
++# Copyright (c) 2012 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 script will check out llvm and clang into third_party/llvm and build it.
++
++# Do NOT CHANGE this if you don't know what you're doing -- see
++# https://code.google.com/p/chromium/wiki/UpdatingClang
++# Reverting problematic clang rolls is safe, though.
++CLANG_REVISION=163674
++
++THIS_DIR="$(dirname "${0}")"
++LLVM_DIR="${THIS_DIR}/../../../third_party/llvm"
++LLVM_BUILD_DIR="${LLVM_DIR}/../llvm-build"
++LLVM_BOOTSTRAP_DIR="${LLVM_DIR}/../llvm-bootstrap"
++CLANG_DIR="${LLVM_DIR}/tools/clang"
++COMPILER_RT_DIR="${LLVM_DIR}/projects/compiler-rt"
++STAMP_FILE="${LLVM_BUILD_DIR}/cr_build_revision"
++
++# ${A:-a} returns $A if it's set, a else.
++LLVM_REPO_URL=${LLVM_URL:-https://llvm.org/svn/llvm-project}
++
++# Die if any command dies.
++set -e
++
++OS="$(uname -s)"
++
++# Parse command line options.
++force_local_build=
++mac_only=
++run_tests=
++bootstrap=
++while [[ $# > 0 ]]; do
++ case $1 in
++ --bootstrap)
++ bootstrap=yes
++ ;;
++ --force-local-build)
++ force_local_build=yes
++ ;;
++ --mac-only)
++ mac_only=yes
++ ;;
++ --run-tests)
++ run_tests=yes
++ ;;
++ --help)
++ echo "usage: $0 [--force-local-build] [--mac-only] [--run-tests] "
++ echo "--bootstrap: First build clang with CC, then with itself."
++ echo "--force-local-build: Don't try to download prebuilt binaries."
++ echo "--mac-only: Do initial download only on Mac systems."
++ echo "--run-tests: Run tests after building. Only for local builds."
++ exit 1
++ ;;
++ esac
++ shift
++done
++
++# --mac-only prevents the initial download on non-mac systems, but if clang has
++# already been downloaded in the past, this script keeps it up to date even if
++# --mac-only is passed in and the system isn't a mac. People who don't like this
++# can just delete their third_party/llvm-build directory.
++if [[ -n "$mac_only" ]] && [[ "${OS}" != "Darwin" ]] &&
++ [[ "$GYP_DEFINES" != *clang=1* ]] && ! [[ -d "${LLVM_BUILD_DIR}" ]]; then
++ exit 0
++fi
++
++# Xcode and clang don't get along when predictive compilation is enabled.
++# http://crbug.com/96315
++if [[ "${OS}" = "Darwin" ]] && xcodebuild -version | grep -q 'Xcode 3.2' ; then
++ XCONF=com.apple.Xcode
++ if [[ "${GYP_GENERATORS}" != "make" ]] && \
++ [ "$(defaults read "${XCONF}" EnablePredictiveCompilation)" != "0" ]; then
++ echo
++ echo " HEARKEN!"
++ echo "You're using Xcode3 and you have 'Predictive Compilation' enabled."
++ echo "This does not work well with clang (http://crbug.com/96315)."
++ echo "Disable it in Preferences->Building (lower right), or run"
++ echo " defaults write ${XCONF} EnablePredictiveCompilation -boolean NO"
++ echo "while Xcode is not running."
++ echo
++ fi
++
++ SUB_VERSION=$(xcodebuild -version | sed -Ene 's/Xcode 3\.2\.([0-9]+)/\1/p')
++ if [[ "${SUB_VERSION}" < 6 ]]; then
++ echo
++ echo " YOUR LD IS BUGGY!"
++ echo "Please upgrade Xcode to at least 3.2.6."
++ echo
++ fi
++fi
++
++
++# Check if there's anything to be done, exit early if not.
++if [[ -f "${STAMP_FILE}" ]]; then
++ PREVIOUSLY_BUILT_REVISON=$(cat "${STAMP_FILE}")
++ if [[ -z "$force_local_build" ]] && \
++ [[ "${PREVIOUSLY_BUILT_REVISON}" = "${CLANG_REVISION}" ]]; then
++ echo "Clang already at ${CLANG_REVISION}"
++ exit 0
++ fi
++fi
++# To always force a new build if someone interrupts their build half way.
++rm -f "${STAMP_FILE}"
++
++# Clobber pch files, since they only work with the compiler version that
++# created them. Also clobber .o files, to make sure everything will be built
++# with the new compiler.
++if [[ "${OS}" = "Darwin" ]]; then
++ XCODEBUILD_DIR="${THIS_DIR}/../../../xcodebuild"
++
++ # Xcode groups .o files by project first, configuration second.
++ if [[ -d "${XCODEBUILD_DIR}" ]]; then
++ echo "Clobbering .o files for Xcode build"
++ find "${XCODEBUILD_DIR}" -name '*.o' -exec rm {} +
++ fi
++fi
++
++if [ -f "${THIS_DIR}/../../../WebKit.gyp" ]; then
++ # We're inside a WebKit checkout.
++ # TODO(thakis): try to unify the directory layout of the xcode- and
++ # make-based builds. http://crbug.com/110455
++ MAKE_DIR="${THIS_DIR}/../../../../../../out"
++else
++ # We're inside a Chromium checkout.
++ MAKE_DIR="${THIS_DIR}/../../../out"
++fi
++
++for CONFIG in Debug Release; do
++ if [[ -d "${MAKE_DIR}/${CONFIG}/obj.target" ||
++ -d "${MAKE_DIR}/${CONFIG}/obj.host" ]]; then
++ echo "Clobbering ${CONFIG} PCH and .o files for make build"
++ if [[ -d "${MAKE_DIR}/${CONFIG}/obj.target" ]]; then
++ find "${MAKE_DIR}/${CONFIG}/obj.target" -name '*.gch' -exec rm {} +
++ find "${MAKE_DIR}/${CONFIG}/obj.target" -name '*.o' -exec rm {} +
++ fi
++ if [[ -d "${MAKE_DIR}/${CONFIG}/obj.host" ]]; then
++ find "${MAKE_DIR}/${CONFIG}/obj.host" -name '*.o' -exec rm {} +
++ fi
++ fi
++
++ # ninja puts its output below ${MAKE_DIR} as well.
++ if [[ -d "${MAKE_DIR}/${CONFIG}/obj" ]]; then
++ echo "Clobbering ${CONFIG} PCH and .o files for ninja build"
++ find "${MAKE_DIR}/${CONFIG}/obj" -name '*.gch' -exec rm {} +
++ find "${MAKE_DIR}/${CONFIG}/obj" -name '*.o' -exec rm {} +
++ find "${MAKE_DIR}/${CONFIG}/obj" -name '*.o.d' -exec rm {} +
++ fi
++
++ if [[ "${OS}" = "Darwin" ]]; then
++ if [[ -d "${XCODEBUILD_DIR}/${CONFIG}/SharedPrecompiledHeaders" ]]; then
++ echo "Clobbering ${CONFIG} PCH files for Xcode build"
++ rm -rf "${XCODEBUILD_DIR}/${CONFIG}/SharedPrecompiledHeaders"
++ fi
++ fi
++done
++
++if [[ -z "$force_local_build" ]]; then
++ # Check if there's a prebuilt binary and if so just fetch that. That's faster,
++ # and goma relies on having matching binary hashes on client and server too.
++ CDS_URL=https://commondatastorage.googleapis.com/chromium-browser-clang
++ CDS_FILE="clang-${CLANG_REVISION}.tgz"
++ CDS_OUT_DIR=$(mktemp -d -t clang_download.XXXXXX)
++ CDS_OUTPUT="${CDS_OUT_DIR}/${CDS_FILE}"
++ if [ "${OS}" = "Linux" ]; then
++ CDS_FULL_URL="${CDS_URL}/Linux_x64/${CDS_FILE}"
++ elif [ "${OS}" = "Darwin" ]; then
++ CDS_FULL_URL="${CDS_URL}/Mac/${CDS_FILE}"
++ fi
++ echo Trying to download prebuilt clang
++ if which curl > /dev/null; then
++ curl -L --fail "${CDS_FULL_URL}" -o "${CDS_OUTPUT}" || \
++ rm -rf "${CDS_OUT_DIR}"
++ elif which wget > /dev/null; then
++ wget "${CDS_FULL_URL}" -O "${CDS_OUTPUT}" || rm -rf "${CDS_OUT_DIR}"
++ else
++ echo "Neither curl nor wget found. Please install one of these."
++ exit 1
++ fi
++ if [ -f "${CDS_OUTPUT}" ]; then
++ rm -rf "${LLVM_BUILD_DIR}/Release+Asserts"
++ mkdir -p "${LLVM_BUILD_DIR}/Release+Asserts"
++ tar -xzf "${CDS_OUTPUT}" -C "${LLVM_BUILD_DIR}/Release+Asserts"
++ echo clang "${CLANG_REVISION}" unpacked
++ echo "${CLANG_REVISION}" > "${STAMP_FILE}"
++ rm -rf "${CDS_OUT_DIR}"
++ exit 0
++ else
++ echo Did not find prebuilt clang at r"${CLANG_REVISION}", building
++ fi
++fi
++
++echo Getting LLVM r"${CLANG_REVISION}" in "${LLVM_DIR}"
++if ! svn co --force "${LLVM_REPO_URL}/llvm/trunk@${CLANG_REVISION}" \
++ "${LLVM_DIR}"; then
++ echo Checkout failed, retrying
++ rm -rf "${LLVM_DIR}"
++ svn co --force "${LLVM_REPO_URL}/llvm/trunk@${CLANG_REVISION}" "${LLVM_DIR}"
++fi
++
++echo Getting clang r"${CLANG_REVISION}" in "${CLANG_DIR}"
++svn co --force "${LLVM_REPO_URL}/cfe/trunk@${CLANG_REVISION}" "${CLANG_DIR}"
++
++echo Getting compiler-rt r"${CLANG_REVISION}" in "${COMPILER_RT_DIR}"
++svn co --force "${LLVM_REPO_URL}/compiler-rt/trunk@${CLANG_REVISION}" \
++ "${COMPILER_RT_DIR}"
++
++# Echo all commands.
++set -x
++
++NUM_JOBS=3
++if [[ "${OS}" = "Linux" ]]; then
++ NUM_JOBS="$(grep -c "^processor" /proc/cpuinfo)"
++elif [ "${OS}" = "Darwin" ]; then
++ NUM_JOBS="$(sysctl -n hw.ncpu)"
++fi
++
++# Build bootstrap clang if requested.
++if [[ -n "${bootstrap}" ]]; then
++ echo "Building bootstrap compiler"
++ mkdir -p "${LLVM_BOOTSTRAP_DIR}"
++ cd "${LLVM_BOOTSTRAP_DIR}"
++ if [[ ! -f ./config.status ]]; then
++ # The bootstrap compiler only needs to be able to build the real compiler,
++ # so it needs no cross-compiler output support. In general, the host
++ # compiler should be as similar to the final compiler as possible, so do
++ # keep --disable-threads & co.
++ ../llvm/configure \
++ --enable-optimized \
++ --enable-targets=host-only \
++ --disable-threads \
++ --disable-pthreads \
++ --without-llvmgcc \
++ --without-llvmgxx
++ MACOSX_DEPLOYMENT_TARGET=10.5 make -j"${NUM_JOBS}"
++ fi
++ if [[ -n "${run_tests}" ]]; then
++ make check-all
++ fi
++ cd -
++ export CC="${PWD}/${LLVM_BOOTSTRAP_DIR}/Release+Asserts/bin/clang"
++ export CXX="${PWD}/${LLVM_BOOTSTRAP_DIR}/Release+Asserts/bin/clang++"
++ echo "Building final compiler"
++fi
++
++# Build clang (in a separate directory).
++# The clang bots have this path hardcoded in built/scripts/slave/compile.py,
++# so if you change it you also need to change these links.
++mkdir -p "${LLVM_BUILD_DIR}"
++cd "${LLVM_BUILD_DIR}"
++if [[ ! -f ./config.status ]]; then
++ ../llvm/configure \
++ --enable-optimized \
++ --disable-threads \
++ --disable-pthreads \
++ --without-llvmgcc \
++ --without-llvmgxx
++fi
++
++MACOSX_DEPLOYMENT_TARGET=10.5 make -j"${NUM_JOBS}"
++cd -
++
++# Build plugin.
++# Copy it into the clang tree and use clang's build system to compile the
++# plugin.
++PLUGIN_SRC_DIR="${THIS_DIR}/../plugins"
++PLUGIN_DST_DIR="${LLVM_DIR}/tools/clang/tools/chrome-plugin"
++PLUGIN_BUILD_DIR="${LLVM_BUILD_DIR}/tools/clang/tools/chrome-plugin"
++rm -rf "${PLUGIN_DST_DIR}"
++cp -R "${PLUGIN_SRC_DIR}" "${PLUGIN_DST_DIR}"
++rm -rf "${PLUGIN_BUILD_DIR}"
++mkdir -p "${PLUGIN_BUILD_DIR}"
++cp "${PLUGIN_SRC_DIR}/Makefile" "${PLUGIN_BUILD_DIR}"
++MACOSX_DEPLOYMENT_TARGET=10.5 make -j"${NUM_JOBS}" -C "${PLUGIN_BUILD_DIR}"
++
++if [[ -n "$run_tests" ]]; then
++ # Run a few tests.
++ "${PLUGIN_SRC_DIR}/tests/test.sh" "${LLVM_BUILD_DIR}/Release+Asserts"
++ cd "${LLVM_BUILD_DIR}"
++ make check-all
++ cd -
++fi
++
++# After everything is done, log success for this revision.
++echo "${CLANG_REVISION}" > "${STAMP_FILE}"