Skip to content

Commit

Permalink
Merge branch 'trunk' into proposal-while-loops
Browse files Browse the repository at this point in the history
  • Loading branch information
jonmeow committed Mar 19, 2021
2 parents a4ac336 + b2d761a commit 578a386
Show file tree
Hide file tree
Showing 98 changed files with 1,478 additions and 10,590 deletions.
6 changes: 6 additions & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@ build --host_crosstool_top=@bazel_cc_toolchain
build:force_local_bootstrap --repo_env=CARBON_FORCE_LOCAL_BOOTSTRAP_BUILD=1

build:fuzzer --features=fuzzer

# Force actions to have a UTF-8 language encoding.
# TODO: Need to investigate what this should be on Windows, but at least for
# Linux and macOS this seems strictly better than the Bazel default of just
# `en_US`.
build --action_env=LANG=en_US.UTF-8
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@

# VSCode creates this directory in ways that are hard to prevent.
/.vscode/

# Directories created by clangd
/.cache/clangd

# Compilation database used by clangd
compile_commands.json
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ repos:
- id: check-executables-have-shebangs
- id: check-merge-conflict
- id: check-symlinks
exclude: '^website/jekyll/site/_includes$'
exclude: '^(website/jekyll/site/_includes|bazel-(clang-toolchain|execroot))$'
- id: check-yaml
- id: detect-private-key
- id: end-of-file-fixer
Expand Down
19 changes: 3 additions & 16 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,13 @@ workspace(name = "carbon")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

# We want to use LLVM via an external CMake build, so pull in the Bazel
# infrastructure that provides direct CMake interfacing support.
http_archive(
name = "rules_foreign_cc",
strip_prefix = "rules_foreign_cc-main",
url = "https://github.com/bazelbuild/rules_foreign_cc/archive/main.zip",
)

# Add Bazel's python rules.
http_archive(
name = "rules_python",
sha256 = "b6d46438523a3ec0f3cead544190ee13223a52f6a6765a29eae7b7cc24cc83a0",
url = "https://github.com/bazelbuild/rules_python/releases/download/0.1.0/rules_python-0.1.0.tar.gz",
)

# Set up necessary dependencies for working with the foreign C++ rules.
load("@rules_foreign_cc//:workspace_definitions.bzl", "rules_foreign_cc_dependencies")

rules_foreign_cc_dependencies()

# Bootstrap a Clang and LLVM toolchain.
load("//bazel/cc_toolchains:clang_bootstrap.bzl", "bootstrap_clang_toolchain")

Expand Down Expand Up @@ -69,8 +56,8 @@ llvm_zlib_system(name = "llvm_zlib")
# Until then, this is pulling from that pull request's commit.
http_archive(
name = "rules_m4",
strip_prefix = "rules_m4-add-extra-copts",
sha256 = "4d34917214e8890ad770bdf0c319c41c9201fffd770938b41a1d641d4b27e05c",
strip_prefix = "rules_m4-add-extra-copts",
urls = ["https://github.com/chandlerc/rules_m4/archive/add-extra-copts.zip"],
)

Expand All @@ -87,8 +74,8 @@ m4_register_toolchains(extra_copts = ["-w"])
# Until then, this is pulling from that pull request's commit.
http_archive(
name = "rules_flex",
strip_prefix = "rules_flex-add-extra-copts",
sha256 = "fd97c3ae23926507be1b95158a683cd41c628d201e852a325d38b5e9f821b752",
strip_prefix = "rules_flex-add-extra-copts",
urls = ["https://github.com/chandlerc/rules_flex/archive/add-extra-copts.zip"],
)

Expand All @@ -105,8 +92,8 @@ flex_register_toolchains(extra_copts = ["-w"])
# Until then, this is pulling from that pull request's commit.
http_archive(
name = "rules_bison",
strip_prefix = "rules_bison-add-extra-copts",
sha256 = "c6e926f15214d903966dc950d759ec69116db67f148be114c119e4def0551eaa",
strip_prefix = "rules_bison-add-extra-copts",
urls = ["https://github.com/chandlerc/rules_bison/archive/add-extra-copts.zip"],
)

Expand Down
1 change: 1 addition & 0 deletions bazel-clang-toolchain
1 change: 1 addition & 0 deletions bazel-execroot
19 changes: 11 additions & 8 deletions compile_flags.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,35 +43,38 @@
-iquote
bazel-bin
-iquote
bazel-carbon-lang/external/llvm-project
bazel-execroot/external/llvm-project
-iquote
bazel-bin/external/llvm-project
-iquote
bazel-carbon-lang/external/llvm_terminfo
bazel-execroot/external/llvm_terminfo
-iquote
bazel-bin/external/llvm_terminfo
-iquote
bazel-carbon-lang/external/llvm_zlib
bazel-execroot/external/llvm_zlib
-iquote
bazel-bin/external/llvm_zlib
-iquote
bazel-carbon-lang/external/bazel_tools
bazel-execroot/external/bazel_tools
-iquote
bazel-bin/external/bazel_tools
-Ibazel-bin/external/llvm-project/llvm/_virtual_includes/gtest_internal_headers
-Ibazel-execroot/external/llvm-project/llvm/utils/unittest/googletest/src
-isystem
bazel-carbon-lang/external/llvm-project/llvm/include
bazel-execroot/external/llvm-project/llvm/include
-isystem
bazel-bin/external/llvm-project/llvm/include
-isystem
bazel-carbon-lang/external/llvm-project/llvm/utils/unittest/googlemock/include
bazel-execroot/external/llvm-project/llvm/utils/unittest/googlemock/include
-isystem
bazel-bin/external/llvm-project/llvm/utils/unittest/googlemock/include
-isystem
bazel-carbon-lang/external/llvm-project/llvm/utils/unittest/googletest/include
bazel-execroot/external/llvm-project/llvm/utils/unittest/googletest/include
-isystem
bazel-bin/external/llvm-project/llvm/utils/unittest/googletest/include
-std=c++17
-nostdinc++
-isystem
bazel-clang-toolchain/include/c++/v1
-no-canonical-prefixes
-Wno-builtin-macro-redefined
-D__DATE__="redacted"
Expand Down
21 changes: 21 additions & 0 deletions diagnostics/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,32 @@ cc_library(
deps = ["@llvm-project//llvm:Support"],
)

cc_library(
name = "null_diagnostics",
hdrs = ["null_diagnostics.h"],
deps = [
":diagnostic_emitter",
"@llvm-project//llvm:Support",
],
)

cc_library(
name = "mocks",
testonly = 1,
hdrs = ["mocks.h"],
deps = [
":diagnostic_emitter",
"@llvm-project//llvm:Support",
"@llvm-project//llvm:gmock",
],
)

cc_test(
name = "diagnostic_emitter_test",
srcs = ["diagnostic_emitter_test.cpp"],
deps = [
":diagnostic_emitter",
":mocks",
"@llvm-project//llvm:Support",
"@llvm-project//llvm:gmock",
"@llvm-project//llvm:gtest",
Expand Down
100 changes: 78 additions & 22 deletions diagnostics/diagnostic_emitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,63 +23,119 @@ namespace Carbon {
// TODO: turn this into a much more reasonable API when we add some actual
// uses of it.
struct Diagnostic {
struct Location {
// Name of the file or buffer that this diagnostic refers to.
std::string file_name;
// 1-based line number.
int32_t line_number;
// 1-based column number.
int32_t column_number;
};

Location location;
llvm::StringRef short_name;
std::string message;
};

// Receives diagnostics as they are emitted.
class DiagnosticConsumer {
public:
virtual ~DiagnosticConsumer() = default;

// Handle a diagnostic.
virtual auto HandleDiagnostic(const Diagnostic& diagnostic) -> void = 0;
};

// An interface that can translate some representation of a location into a
// diagnostic location.
//
// TODO: Revisit this once the diagnostics machinery is more complete and see
// if we can turn it into a `std::function`.
template <typename LocationT>
class DiagnosticLocationTranslator {
public:
virtual ~DiagnosticLocationTranslator() = default;

[[nodiscard]] virtual auto GetLocation(LocationT loc)
-> Diagnostic::Location = 0;
};

// Manages the creation of reports, the testing if diagnostics are enabled, and
// the collection of reports.
//
// This class is parameterized by a location type, allowing different
// diagnostic clients to provide location information in whatever form is most
// convenient for them, such as a position within a buffer when lexing, a token
// when parsing, or a parse tree node when type-checking, and to allow unit
// tests to be decoupled from any concrete location representation.
template <typename LocationT>
class DiagnosticEmitter {
public:
using Callback = std::function<void(const Diagnostic&)>;

explicit DiagnosticEmitter(Callback callback)
: callback_(std::move(callback)) {}
// The `translator` and `consumer` are required to outlive the diagnostic
// emitter.
explicit DiagnosticEmitter(
DiagnosticLocationTranslator<LocationT>& translator,
DiagnosticConsumer& consumer)
: translator_(&translator), consumer_(&consumer) {}
~DiagnosticEmitter() = default;

// Emits an error unconditionally.
template <typename DiagnosticT>
auto EmitError(DiagnosticT diag) -> void {
callback_({.short_name = DiagnosticT::ShortName, .message = diag.Format()});
auto EmitError(LocationT location, DiagnosticT diag) -> void {
// TODO: Encode the diagnostic kind in the Diagnostic object rather than
// hardcoding an "error: " prefix.
consumer_->HandleDiagnostic({.location = translator_->GetLocation(location),
.short_name = DiagnosticT::ShortName,
.message = "error: " + diag.Format()});
}

// Emits a stateless error unconditionally.
template <typename DiagnosticT>
auto EmitError() -> std::enable_if_t<std::is_empty_v<DiagnosticT>> {
EmitError<DiagnosticT>({});
auto EmitError(LocationT location)
-> std::enable_if_t<std::is_empty_v<DiagnosticT>> {
EmitError<DiagnosticT>(location, {});
}

// Emits a warning if `F` returns true. `F` may or may not be called if the
// warning is disabled.
template <typename DiagnosticT>
auto EmitWarningIf(llvm::function_ref<bool(DiagnosticT&)> f) -> void {
// TODO(kfm): check if this warning is enabled
auto EmitWarningIf(LocationT location,
llvm::function_ref<bool(DiagnosticT&)> f) -> void {
// TODO(kfm): check if this warning is enabled at `location`.
DiagnosticT diag;
if (f(diag)) {
callback_(
{.short_name = DiagnosticT::ShortName, .message = diag.Format()});
// TODO: Encode the diagnostic kind in the Diagnostic object rather than
// hardcoding a "warning: " prefix.
consumer_->HandleDiagnostic(
{.location = translator_->GetLocation(location),
.short_name = DiagnosticT::ShortName,
.message = "warning: " + diag.Format()});
}
}

private:
Callback callback_;
DiagnosticLocationTranslator<LocationT>* translator_;
DiagnosticConsumer* consumer_;
};

inline auto ConsoleDiagnosticEmitter() -> DiagnosticEmitter& {
static auto* emitter = new DiagnosticEmitter(
[](const Diagnostic& d) { llvm::errs() << d.message << "\n"; });
return *emitter;
}
inline auto ConsoleDiagnosticConsumer() -> DiagnosticConsumer& {
struct Consumer : DiagnosticConsumer {
auto HandleDiagnostic(const Diagnostic& d) -> void override {
if (!d.location.file_name.empty()) {
llvm::errs() << d.location.file_name << ":" << d.location.line_number
<< ":" << d.location.column_number << ": ";
}

inline auto NullDiagnosticEmitter() -> DiagnosticEmitter& {
static auto* emitter = new DiagnosticEmitter([](const Diagnostic&) {});
return *emitter;
llvm::errs() << d.message << "\n";
}
};
static auto* consumer = new Consumer;
return *consumer;
}

// CRTP base class for diagnostics with no substitutions.
template <typename Derived>
struct SimpleDiagnostic {
struct Substitutions {};
static auto Format() -> std::string { return Derived::Message.str(); }
};

Expand Down
Loading

0 comments on commit 578a386

Please sign in to comment.