Use AIDL_* errors over libbase logging.

This:
- gives us line numbers in source AIDL files reflecting errors
- makes it possible aidl_parser_fuzzer can detect when we return an
  error but don't provide any output logging

Bug: N/A
Test: aidl_unittest
Change-Id: I0479fd8d87547c1f0b1be754f9b8f6865db3cbef
diff --git a/aidl.cpp b/aidl.cpp
index 830b3ae..a5fbdcc 100644
--- a/aidl.cpp
+++ b/aidl.cpp
@@ -167,7 +167,7 @@
 
   CodeWriterPtr writer = io_delegate.GetCodeWriter(dep_file_name);
   if (!writer) {
-    LOG(ERROR) << "Could not open dependency file: " << dep_file_name;
+    AIDL_ERROR(dep_file_name) << "Could not open dependency file.";
     return false;
   }
 
@@ -244,7 +244,7 @@
   } else if (options.TargetLanguage() == Options::Language::RUST) {
     result += ".rs";
   } else {
-    LOG(FATAL) << "Should not reach here" << endl;
+    AIDL_FATAL("Unknown target language");
     return "";
   }
 
@@ -357,7 +357,7 @@
   bool success = true;
   unique_ptr<LineReader> line_reader = io_delegate.GetLineReader(filename);
   if (!line_reader) {
-    LOG(ERROR) << "cannot open preprocessed file: " << filename;
+    AIDL_ERROR(filename) << "cannot open preprocessed file";
     success = false;
     return success;
   }
@@ -405,8 +405,8 @@
     }
   }
   if (!success) {
-    LOG(ERROR) << filename << ':' << lineno
-               << " malformed preprocessed file line: '" << line << "'";
+    AIDL_ERROR(filename) << " on line " << lineno << " malformed preprocessed file line: '" << line
+                         << "'";
   }
 
   return success;
@@ -573,7 +573,7 @@
   const auto& types = main_parser->ParsedDocument().DefinedTypes();
   const int num_defined_types = types.size();
   for (const auto& defined_type : types) {
-    CHECK(defined_type != nullptr);
+    AIDL_FATAL_IF(defined_type == nullptr, main_parser->FileName());
 
     // Language specific validation
     if (!defined_type->LanguageSpecificCheckValid(*typenames, options.TargetLanguage())) {
@@ -623,7 +623,7 @@
     AidlInterface* interface = defined_type->AsInterface();
     AidlStructuredParcelable* parcelable = defined_type->AsStructuredParcelable();
     AidlEnumDeclaration* enum_decl = defined_type->AsEnumDeclaration();
-    CHECK(!!interface + !!parcelable + !!enum_decl == 1);
+    AIDL_FATAL_IF(!!interface + !!parcelable + !!enum_decl != 1, defined_type);
 
     // Ensure that foo.bar.IFoo is defined in <some_path>/foo/bar/IFoo.aidl
     if (num_defined_types == 1 && !check_filename(input_file_name, *defined_type)) {
@@ -685,8 +685,8 @@
             break;
           }
           default:
-            LOG(FATAL) << "Unrecognized constant type: "
-                       << static_cast<int>(constant->GetValue().GetType());
+            AIDL_FATAL(constant) << "Unrecognized constant type: "
+                                 << static_cast<int>(constant->GetValue().GetType());
             break;
         }
       }
@@ -769,7 +769,7 @@
     }
 
     for (const auto& defined_type : typenames.MainDocument().DefinedTypes()) {
-      CHECK(defined_type != nullptr);
+      AIDL_FATAL_IF(defined_type == nullptr, input_file);
 
       string output_file_name = options.OutputFile();
       // if needed, generate the output file name from the base folder
@@ -804,8 +804,7 @@
         success = rust::GenerateRust(output_file_name, defined_type.get(), typenames, io_delegate,
                                      options);
       } else {
-        LOG(FATAL) << "Should not reach here" << endl;
-        return 1;
+        AIDL_FATAL(input_file) << "Should not reach here.";
       }
       if (!success) {
         return 1;
@@ -861,7 +860,7 @@
 
 static string GetApiDumpPathFor(const AidlDefinedType& defined_type, const Options& options) {
   string package_as_path = Join(Split(defined_type.GetPackage(), "."), OS_PATH_SEPARATOR);
-  CHECK(!options.OutputDir().empty() && options.OutputDir().back() == '/');
+  AIDL_FATAL_IF(options.OutputDir().empty() || options.OutputDir().back() != '/', defined_type);
   return options.OutputDir() + package_as_path + OS_PATH_SEPARATOR + defined_type.GetName() +
          ".aidl";
 }
@@ -912,12 +911,11 @@
   }
 
   // compiler invariants
-
-  // once AIDL_ERROR/AIDL_FATAL are used everywhere instead of std::cerr/LOG, we
-  // can make this assertion in both directions.
-  if (ret == 0) {
-    AIDL_FATAL_IF(AidlErrorLog::hadError(), "Compiler success, but error emitted");
-  }
+  const bool shouldReportError = ret != 0;
+  const bool reportedError = AidlErrorLog::hadError();
+  AIDL_FATAL_IF(shouldReportError != reportedError, AIDL_LOCATION_HERE)
+      << "Compiler returned error " << ret << " but did" << (reportedError ? "" : " not")
+      << " emit error logs";
 
   return ret;
 }
diff --git a/aidl_checkapi.cpp b/aidl_checkapi.cpp
index a0107e4..0f2f4b0 100644
--- a/aidl_checkapi.cpp
+++ b/aidl_checkapi.cpp
@@ -127,7 +127,7 @@
     const auto& old_args = old_m->GetArguments();
     const auto& new_args = new_m->GetArguments();
     // this is guaranteed because arguments are part of AidlMethod::Signature()
-    CHECK(old_args.size() == new_args.size());
+    AIDL_FATAL_IF(old_args.size() != new_args.size(), old_m);
     for (size_t i = 0; i < old_args.size(); i++) {
       const AidlArgument& old_a = *(old_args.at(i));
       const AidlArgument& new_a = *(new_args.at(i));
@@ -317,9 +317,10 @@
 }
 
 bool check_api(const Options& options, const IoDelegate& io_delegate) {
-  CHECK(options.IsStructured());
-  CHECK(options.InputFiles().size() == 2) << "--checkapi requires two inputs "
-                                          << "but got " << options.InputFiles().size();
+  AIDL_FATAL_IF(!options.IsStructured(), AIDL_LOCATION_HERE);
+  AIDL_FATAL_IF(options.InputFiles().size() != 2, AIDL_LOCATION_HERE)
+      << "--checkapi requires two inputs "
+      << "but got " << options.InputFiles().size();
   auto old_tns = load_from_dir(options, io_delegate, options.InputFiles().at(0));
   if (!old_tns.ok()) {
     return false;
diff --git a/aidl_const_expressions.cpp b/aidl_const_expressions.cpp
index 5c7cb3a..5626e40 100644
--- a/aidl_const_expressions.cpp
+++ b/aidl_const_expressions.cpp
@@ -134,7 +134,7 @@
 }
 
 // TODO: factor out all these macros
-#define SHOULD_NOT_REACH() CHECK(false) << LOG(FATAL) << ": should not reach here: "
+#define SHOULD_NOT_REACH() AIDL_FATAL(AIDL_LOCATION_HERE) << "Should not reach."
 #define OPEQ(__y__) (string(op_) == string(__y__))
 #define COMPUTE_UNARY(T, __op__)         \
   if (op == string(#__op__)) {           \
@@ -290,8 +290,8 @@
 AidlConstantValue::Type AidlBinaryConstExpression::UsualArithmeticConversion(Type left,
                                                                              Type right) {
   // These are handled as special cases
-  CHECK(left != Type::STRING && right != Type::STRING);
-  CHECK(left != Type::FLOATING && right != Type::FLOATING);
+  AIDL_FATAL_IF(left == Type::STRING || right == Type::STRING, AIDL_LOCATION_HERE);
+  AIDL_FATAL_IF(left == Type::FLOATING || right == Type::FLOATING, AIDL_LOCATION_HERE);
 
   // Kinds in concern: bool, (u)int[8|32|64]
   if (left == right) return left;  // easy case
@@ -308,7 +308,7 @@
 
 template <typename T>
 T AidlConstantValue::cast() const {
-  CHECK(is_evaluated_ == true);
+  AIDL_FATAL_IF(!is_evaluated_, this);
 
 #define CASE_CAST_T(__type__) return static_cast<T>(static_cast<__type__>(final_value_));
 
@@ -419,7 +419,7 @@
 }
 
 AidlConstantValue* AidlConstantValue::Integral(const AidlLocation& location, const string& value) {
-  CHECK(!value.empty());
+  AIDL_FATAL_IF(value.empty(), location);
 
   Type parsed_type;
   int64_t parsed_value = 0;
@@ -433,7 +433,7 @@
 
 AidlConstantValue* AidlConstantValue::Array(
     const AidlLocation& location, std::unique_ptr<vector<unique_ptr<AidlConstantValue>>> values) {
-  CHECK(values != nullptr) << location;
+  AIDL_FATAL_IF(values == nullptr, location);
   return new AidlConstantValue(location, Type::ARRAY, std::move(values));
 }
 
@@ -583,7 +583,7 @@
       break;
   }
 
-  CHECK(err != 0);
+  AIDL_FATAL_IF(err == 0, this);
   AIDL_ERROR(this) << "Invalid type specifier for " << ToString(final_type_) << ": " << type_string;
   return "";
 }
@@ -715,17 +715,18 @@
     case Type::BINARY:
       return "a binary expression";
     case Type::ERROR:
-      LOG(FATAL) << "aidl internal error: error type failed to halt program";
+      AIDL_FATAL(AIDL_LOCATION_HERE) << "aidl internal error: error type failed to halt program";
       return "";
     default:
-      LOG(FATAL) << "aidl internal error: unknown constant type: " << static_cast<int>(type);
+      AIDL_FATAL(AIDL_LOCATION_HERE)
+          << "aidl internal error: unknown constant type: " << static_cast<int>(type);
       return "";  // not reached
   }
 }
 
 bool AidlUnaryConstExpression::CheckValid() const {
   if (is_evaluated_) return is_valid_;
-  CHECK(unary_ != nullptr);
+  AIDL_FATAL_IF(unary_ == nullptr, this);
 
   is_valid_ = unary_->CheckValid();
   if (!is_valid_) {
@@ -782,8 +783,8 @@
 bool AidlBinaryConstExpression::CheckValid() const {
   bool success = false;
   if (is_evaluated_) return is_valid_;
-  CHECK(left_val_ != nullptr);
-  CHECK(right_val_ != nullptr);
+  AIDL_FATAL_IF(left_val_ == nullptr, this);
+  AIDL_FATAL_IF(right_val_ == nullptr, this);
 
   success = left_val_->CheckValid();
   if (!success) {
@@ -811,8 +812,8 @@
     return is_valid_;
   }
   is_evaluated_ = true;
-  CHECK(left_val_ != nullptr);
-  CHECK(right_val_ != nullptr);
+  AIDL_FATAL_IF(left_val_ == nullptr, type);
+  AIDL_FATAL_IF(right_val_ == nullptr, type);
 
   // Recursively evaluate the binary expression tree
   if (!left_val_->is_evaluated_ || !right_val_->is_evaluated_) {
@@ -926,8 +927,8 @@
       value_(checked_value),
       final_type_(parsed_type),
       final_value_(parsed_value) {
-  CHECK(!value_.empty() || type_ == Type::ERROR) << location;
-  CHECK(type_ == Type::INT8 || type_ == Type::INT32 || type_ == Type::INT64) << location;
+  AIDL_FATAL_IF(value_.empty() && type_ != Type::ERROR, location);
+  AIDL_FATAL_IF(type_ != Type::INT8 && type_ != Type::INT32 && type_ != Type::INT64, location);
 }
 
 AidlConstantValue::AidlConstantValue(const AidlLocation& location, Type type,
@@ -936,7 +937,7 @@
       type_(type),
       value_(checked_value),
       final_type_(type) {
-  CHECK(!value_.empty() || type_ == Type::ERROR) << location;
+  AIDL_FATAL_IF(value_.empty() && type_ != Type::ERROR, location);
   switch (type_) {
     case Type::INT8:
     case Type::INT32:
@@ -957,7 +958,7 @@
       is_valid_(false),
       is_evaluated_(false),
       final_type_(type) {
-  CHECK(type_ == Type::ARRAY);
+  AIDL_FATAL_IF(type_ != Type::ARRAY, location);
 }
 
 AidlUnaryConstExpression::AidlUnaryConstExpression(const AidlLocation& location, const string& op,
diff --git a/aidl_language.cpp b/aidl_language.cpp
index 7c67056..f4596db 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -32,7 +32,7 @@
 #include <android-base/parseint.h>
 #include <android-base/strings.h>
 
-#include "aidl_language_y-module.h"
+#include "aidl_language_y.h"
 #include "logging.h"
 
 #include "aidl.h"
@@ -69,8 +69,8 @@
   return std::find(kJavaKeywords.begin(), kJavaKeywords.end(), str) != kJavaKeywords.end();
 }
 
-inline std::string CapitalizeFirstLetter(const std::string& str) {
-  CHECK(str.size() > 0) << "Input cannot be empty.";
+inline std::string CapitalizeFirstLetter(const AidlNode& context, const std::string& str) {
+  AIDL_FATAL_IF(str.size() <= 0, context) << "Input cannot be empty.";
   std::ostringstream out;
   out << static_cast<char>(toupper(str[0])) << str.substr(1);
   return out.str();
@@ -448,7 +448,7 @@
 }
 
 bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
-  CHECK(!IsResolved());
+  AIDL_FATAL_IF(IsResolved(), this);
   AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(unresolved_name_);
   if (result.is_resolved) {
     fully_qualified_name_ = result.canonical_name;
@@ -801,7 +801,7 @@
   // Copying is not supported if it has type parameters.
   // It doesn't make a problem because only ArrayBase() makes a copy,
   // and it can be called only if a type is not generic.
-  CHECK(!other.IsGeneric());
+  AIDL_FATAL_IF(other.IsGeneric(), AIDL_LOCATION_HERE);
 }
 
 template <typename T>
@@ -887,7 +887,7 @@
     bool duplicated;
     if (IsJavaOnlyImmutable()) {
       success = success && typenames.CanBeJavaOnlyImmutable(v->GetType());
-      duplicated = !fieldnames.emplace(CapitalizeFirstLetter(v->GetName())).second;
+      duplicated = !fieldnames.emplace(CapitalizeFirstLetter(*v, v->GetName())).second;
     } else {
       if (IsFixedSize()) {
         success = success && typenames.CanBeFixedSize(v->GetType());
@@ -1133,7 +1133,7 @@
     AidlMethod* method = local->AsMethod();
     AidlConstantDeclaration* constant = local->AsConstantDeclaration();
 
-    CHECK(method == nullptr || constant == nullptr);
+    AIDL_FATAL_IF(method != nullptr && constant != nullptr, member);
 
     if (method) {
       method->ApplyInterfaceOneway(oneway);
diff --git a/aidl_language.h b/aidl_language.h
index 08bd8f3..ae9bf15 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -86,7 +86,7 @@
 };
 
 #define AIDL_LOCATION_HERE \
-  AidlLocation { __FILE__, {__LINE__, 0}, {__LINE__, 0}, AidlLocation::Source::INTERNAL }
+  (AidlLocation{__FILE__, {__LINE__, 0}, {__LINE__, 0}, AidlLocation::Source::INTERNAL})
 
 std::ostream& operator<<(std::ostream& os, const AidlLocation& l);
 
diff --git a/aidl_language_l.ll b/aidl_language_l.ll
index b0390a6..7646f3f 100644
--- a/aidl_language_l.ll
+++ b/aidl_language_l.ll
@@ -20,7 +20,7 @@
 
 #include "aidl_language.h"
 #include "parser.h"
-#include "aidl_language_y-module.h"
+#include "aidl_language_y.h"
 
 #define YY_USER_ACTION yylloc->columns(yyleng);
 %}
diff --git a/aidl_language_y-module.h b/aidl_language_y-module.h
deleted file mode 100644
index 34b1620..0000000
--- a/aidl_language_y-module.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// generated code prints std::string* which is disallowed
-// by android-base/logging.h
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wuser-defined-warnings"
-#include <aidl_language_y.h>
-#pragma clang diagnostic pop
diff --git a/aidl_language_y.yy b/aidl_language_y.yy
index f081a87..7a37e60 100644
--- a/aidl_language_y.yy
+++ b/aidl_language_y.yy
@@ -17,7 +17,7 @@
 %{
 #include "aidl_language.h"
 #include "parser.h"
-#include "aidl_language_y-module.h"
+#include "aidl_language_y.h"
 #include "logging.h"
 #include <android-base/parseint.h>
 #include <set>
@@ -29,9 +29,9 @@
 int yylex(yy::parser::semantic_type *, yy::parser::location_type *, void *);
 
 AidlLocation loc(const yy::parser::location_type& begin, const yy::parser::location_type& end) {
-  CHECK(begin.begin.filename == begin.end.filename);
-  CHECK(begin.end.filename == end.begin.filename);
-  CHECK(end.begin.filename == end.end.filename);
+  AIDL_FATAL_IF(begin.begin.filename != begin.end.filename, AIDL_LOCATION_HERE);
+  AIDL_FATAL_IF(begin.end.filename != end.begin.filename, AIDL_LOCATION_HERE);
+  AIDL_FATAL_IF(end.begin.filename != end.end.filename, AIDL_LOCATION_HERE);
   AidlLocation::Point begin_point {
     .line = begin.begin.line,
     .column = begin.begin.column,
diff --git a/aidl_to_cpp.cpp b/aidl_to_cpp.cpp
index b7d48b4..006df9f 100644
--- a/aidl_to_cpp.cpp
+++ b/aidl_to_cpp.cpp
@@ -79,24 +79,24 @@
   if (isVector) {
     string element_name;
     if (typenames.IsList(type)) {
-      CHECK(type.GetTypeParameters().size() == 1);
+      AIDL_FATAL_IF(type.GetTypeParameters().size() != 1, type);
       element_name = type.GetTypeParameters().at(0)->GetName();
     } else {
       element_name = type.GetName();
     }
     if (kBuiltinVector.find(element_name) != kBuiltinVector.end()) {
-      CHECK(AidlTypenames::IsBuiltinTypename(element_name));
+      AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(element_name), type);
       if (utf8) {
-        CHECK(element_name == "String");
+        AIDL_FATAL_IF(element_name != "String", type);
         return readMethod ? "Utf8VectorFromUtf16Vector" : "Utf8VectorAsUtf16Vector";
       }
       return kBuiltinVector[element_name];
     }
-    CHECK(!typenames.IsList(type));
+    AIDL_FATAL_IF(typenames.IsList(type), type);
   } else {
     const string& type_name = type.GetName();
     if (kBuiltin.find(type_name) != kBuiltin.end()) {
-      CHECK(AidlTypenames::IsBuiltinTypename(type_name));
+      AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(type_name), type);
       if (type_name == "IBinder" && nullable && readMethod) {
         return "NullableStrongBinder";
       }
@@ -104,13 +104,13 @@
         return "NullableParcelable";
       }
       if (utf8) {
-        CHECK(type_name == "String");
+        AIDL_FATAL_IF(type_name != "String", type);
         return readMethod ? "Utf8FromUtf16" : "Utf8AsUtf16";
       }
       return kBuiltin[type_name];
     }
   }
-  CHECK(!AidlTypenames::IsBuiltinTypename(type.GetName()));
+  AIDL_FATAL_IF(AidlTypenames::IsBuiltinTypename(type.GetName()), type);
   auto definedType = typenames.TryGetDefinedType(type.GetName());
   if (definedType != nullptr && definedType->AsInterface() != nullptr) {
     if (isVector) {
@@ -124,7 +124,7 @@
 
   // The type must be either primitive or interface or parcelable,
   // so it cannot be nullptr.
-  CHECK(definedType != nullptr) << type.GetName() << " is not found.";
+  AIDL_FATAL_IF(definedType == nullptr, type) << type.GetName() << " is not found.";
 
   // Parcelable
   if (isVector) {
@@ -167,15 +167,15 @@
       {"String", "::android::String16"},
       {"void", "void"},
   };
-  CHECK(!typenames.IsList(raw_type) || raw_type.GetTypeParameters().size() == 1);
+  AIDL_FATAL_IF(typenames.IsList(raw_type) && raw_type.GetTypeParameters().size() != 1, raw_type);
   const auto& type = typenames.IsList(raw_type) ? (*raw_type.GetTypeParameters().at(0)) : raw_type;
   const string& aidl_name = type.GetName();
   if (m.find(aidl_name) != m.end()) {
-    CHECK(AidlTypenames::IsBuiltinTypename(aidl_name));
+    AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(aidl_name), raw_type);
     if (aidl_name == "byte" && type.IsArray()) {
       return "uint8_t";
     } else if (raw_type.IsUtf8InCpp()) {
-      CHECK(aidl_name == "String");
+      AIDL_FATAL_IF(aidl_name != "String", type);
       return WrapIfNullable("::std::string", raw_type, typenames);
     }
     return WrapIfNullable(m[aidl_name], raw_type, typenames);
@@ -280,7 +280,7 @@
 
 void AddHeaders(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
                 std::set<std::string>* headers) {
-  CHECK(!typenames.IsList(type) || type.GetTypeParameters().size() == 1);
+  AIDL_FATAL_IF(typenames.IsList(type) && type.GetTypeParameters().size() != 1, type);
   bool isVector = type.IsArray() || typenames.IsList(type);
   bool isNullable = type.IsNullable();
   bool utf8 = type.IsUtf8InCpp();
diff --git a/aidl_to_cpp_common.cpp b/aidl_to_cpp_common.cpp
index 794b2bb..c1953ac 100644
--- a/aidl_to_cpp_common.cpp
+++ b/aidl_to_cpp_common.cpp
@@ -166,7 +166,7 @@
 };
 
 TypeInfo GetTypeInfo(const AidlTypeSpecifier& aidl) {
-  CHECK(aidl.IsResolved()) << aidl.ToString();
+  AIDL_FATAL_IF(!aidl.IsResolved(), aidl) << aidl.ToString();
   const string& aidl_name = aidl.GetName();
 
   TypeInfo info;
diff --git a/aidl_to_java.cpp b/aidl_to_java.cpp
index d7eaffe..3921281 100644
--- a/aidl_to_java.cpp
+++ b/aidl_to_java.cpp
@@ -49,7 +49,7 @@
 
 const string& JavaNameOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames,
                          bool instantiable = false, bool boxing = false) {
-  CHECK(aidl.IsResolved()) << aidl.ToString();
+  AIDL_FATAL_IF(!aidl.IsResolved(), aidl) << aidl.ToString();
 
   if (instantiable) {
     // An instantiable type is used in only out type(not even inout type),
@@ -99,8 +99,8 @@
   if (const AidlEnumDeclaration* enum_decl = typenames.GetEnumDeclaration(aidl);
       enum_decl != nullptr) {
     const string& backing_type_name = enum_decl->GetBackingType().GetName();
-    CHECK(m.find(backing_type_name) != m.end());
-    CHECK(AidlTypenames::IsBuiltinTypename(backing_type_name));
+    AIDL_FATAL_IF(m.find(backing_type_name) == m.end(), enum_decl);
+    AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(backing_type_name), enum_decl);
     if (boxing) {
       return boxing_types[backing_type_name];
     } else {
@@ -111,11 +111,11 @@
   const string& aidl_name = aidl.GetName();
   if (boxing && AidlTypenames::IsPrimitiveTypename(aidl_name)) {
     // Every primitive type must have the corresponding boxing type
-    CHECK(boxing_types.find(aidl_name) != m.end());
+    AIDL_FATAL_IF(boxing_types.find(aidl_name) == m.end(), aidl);
     return boxing_types[aidl_name];
   }
   if (m.find(aidl_name) != m.end()) {
-    CHECK(AidlTypenames::IsBuiltinTypename(aidl_name));
+    AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(aidl_name), aidl);
     return m[aidl_name];
   } else {
     // 'foo.bar.IFoo' in AIDL maps to 'foo.bar.IFoo' in Java
@@ -177,10 +177,10 @@
   };
 
   const string name = AidlBackingTypeName(aidl, typenames);
-  CHECK(name != "void");
+  AIDL_FATAL_IF(name == "void", aidl);
 
   if (!aidl.IsArray() && m.find(name) != m.end()) {
-    CHECK(AidlTypenames::IsBuiltinTypename(name));
+    AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(name), aidl);
     return m[name];
   } else {
     return "null";
@@ -273,7 +273,7 @@
              }
            } else {
              const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
-             CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
+             AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << contained_type << endl;
              if (t->AsParcelable() != nullptr) {
                c.writer << c.parcel << ".writeTypedList(" << c.var << ");\n";
              }
@@ -380,7 +380,7 @@
     found->second(c);
   } else {
     const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
-    CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
+    AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName() << endl;
     if (t->AsInterface() != nullptr) {
       if (!c.type.IsArray()) {
         // Why don't we use writeStrongInterface which does the exact same thing?
@@ -414,7 +414,7 @@
 // Ensures that a variable is initialized to refer to the classloader
 // of the current object and returns the name of the variable.
 static string EnsureAndGetClassloader(CodeGeneratorContext& c) {
-  CHECK(c.is_classloader_created != nullptr);
+  AIDL_FATAL_IF(c.is_classloader_created == nullptr, AIDL_LOCATION_HERE);
   if (!*(c.is_classloader_created)) {
     c.writer << "java.lang.ClassLoader cl = "
              << "(java.lang.ClassLoader)this.getClass().getClassLoader();\n";
@@ -501,7 +501,7 @@
              }
            } else {
              const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
-             CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
+             AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << contained_type << endl;
              if (t->AsParcelable() != nullptr) {
                c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
                         << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
@@ -615,7 +615,7 @@
     found->second(c);
   } else {
     const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
-    CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
+    AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName() << endl;
     if (t->AsInterface() != nullptr) {
       if (!c.type.IsArray()) {
         c.writer << c.var << " = " << c.type.GetName() << ".Stub.asInterface(" << c.parcel
@@ -691,7 +691,7 @@
              }
            } else {
              const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
-             CHECK(t != nullptr) << "Unknown type: " << contained_type << endl;
+             AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << contained_type << endl;
              if (t->AsParcelable() != nullptr) {
                c.writer << c.parcel << ".readTypedList(" << c.var << ", "
                         << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
@@ -762,7 +762,7 @@
     found->second(c);
   } else {
     const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
-    CHECK(t != nullptr) << "Unknown type: " << c.type.GetName() << endl;
+    AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName() << endl;
     if (t->AsParcelable() != nullptr) {
       if (c.type.IsArray()) {
         c.writer << c.parcel << ".readTypedArray(" << c.var << ", " << c.type.GetName()
@@ -820,7 +820,9 @@
     c.writer << c.var << ".toString()";
     return;
   }
-  CHECK(true) << "Unhandled typename: " << name << endl;
+
+  // TODO(b/168261721): turn into a real error
+  // CHECK(true) << "Unhandled typename: " << name << endl;
 }
 
 }  // namespace java
diff --git a/aidl_to_ndk.cpp b/aidl_to_ndk.cpp
index abf54ac..3664e77 100644
--- a/aidl_to_ndk.cpp
+++ b/aidl_to_ndk.cpp
@@ -181,7 +181,7 @@
       {"long", "Int64"},
   };
   auto aparcel_name_it = kAParcelTypeNameMap.find(enum_decl.GetBackingType().GetName());
-  CHECK(aparcel_name_it != kAParcelTypeNameMap.end());
+  AIDL_FATAL_IF(aparcel_name_it == kAParcelTypeNameMap.end(), enum_decl);
   const std::string aparcel_name = aparcel_name_it->second;
 
   const std::string backing_type_name =
@@ -325,7 +325,7 @@
 };
 
 static TypeInfo::Aspect GetTypeAspect(const AidlTypenames& types, const AidlTypeSpecifier& aidl) {
-  CHECK(aidl.IsResolved()) << aidl.ToString();
+  AIDL_FATAL_IF(!aidl.IsResolved(), aidl) << aidl.ToString();
   auto& aidl_name = aidl.GetName();
 
   TypeInfo info;
@@ -350,7 +350,7 @@
 
   if (AidlTypenames::IsBuiltinTypename(aidl_name)) {
     auto it = kNdkTypeInfoMap.find(aidl_name);
-    CHECK(it != kNdkTypeInfoMap.end());
+    AIDL_FATAL_IF(it == kNdkTypeInfoMap.end(), aidl_name);
     info = it->second;
   } else {
     const AidlDefinedType* type = types.TryGetDefinedType(aidl_name);
diff --git a/aidl_to_rust.cpp b/aidl_to_rust.cpp
index 90ce120..61dceee 100644
--- a/aidl_to_rust.cpp
+++ b/aidl_to_rust.cpp
@@ -96,11 +96,12 @@
   };
 
   // If the type is an array/List<T>, get the inner element type
-  CHECK(!type.IsGeneric() || (type.GetName() == "List" && type.GetTypeParameters().size() == 1));
+  AIDL_FATAL_IF(
+      type.IsGeneric() && (type.GetName() != "List" || type.GetTypeParameters().size() != 1), type);
   const auto& element_type = type.IsGeneric() ? (*type.GetTypeParameters().at(0)) : type;
   const string& element_type_name = element_type.GetName();
   if (m.find(element_type_name) != m.end()) {
-    CHECK(AidlTypenames::IsBuiltinTypename(element_type_name));
+    AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(element_type_name), type);
     if (element_type_name == "byte" && type.IsArray()) {
       return "u8";
     } else if (element_type_name == "String" && mode == StorageMode::UNSIZED_ARGUMENT) {
diff --git a/aidl_typenames.cpp b/aidl_typenames.cpp
index a22872d..5b96929 100644
--- a/aidl_typenames.cpp
+++ b/aidl_typenames.cpp
@@ -132,7 +132,7 @@
 }
 
 const AidlDocument& AidlTypenames::MainDocument() const {
-  CHECK(documents_.size() != 0) << "Main document doesn't exist";
+  AIDL_FATAL_IF(documents_.size() == 0, AIDL_LOCATION_HERE) << "Main document doesn't exist";
   return *(documents_[0]);
 }
 
@@ -273,7 +273,7 @@
            type.GetName() == "ParcelFileDescriptor";
   }
   const AidlDefinedType* t = TryGetDefinedType(type.GetName());
-  CHECK(t != nullptr) << "Unrecognized type: '" << type.GetName() << "'";
+  AIDL_FATAL_IF(t == nullptr, type) << "Unrecognized type: '" << type.GetName() << "'";
   // An 'out' field is passed as an argument, so it doesn't make sense if it is immutable.
   return t->AsParcelable() != nullptr && !t->IsJavaOnlyImmutable();
 }
diff --git a/ast_cpp.cpp b/ast_cpp.cpp
index d5bd83e..63f16b0 100644
--- a/ast_cpp.cpp
+++ b/ast_cpp.cpp
@@ -323,7 +323,7 @@
 StatementBlock* SwitchStatement::AddCase(const string& value_expression) {
   auto it = std::find(case_values_.begin(), case_values_.end(), value_expression);
   if (it != case_values_.end()) {
-    LOG(ERROR) << "internal error: duplicate switch case labels";
+    AIDL_ERROR(value_expression) << "Duplicate switch case labels";
     return nullptr;
   }
   StatementBlock* ret = new StatementBlock();
diff --git a/code_writer.cpp b/code_writer.cpp
index 096c895..447b91f 100644
--- a/code_writer.cpp
+++ b/code_writer.cpp
@@ -15,13 +15,14 @@
  */
 #include "code_writer.h"
 
+#include "logging.h"
+
 #include <stdarg.h>
 #include <fstream>
 #include <iostream>
 #include <sstream>
 #include <vector>
 
-#include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 
 namespace android {
@@ -74,7 +75,7 @@
   indent_level_++;
 }
 void CodeWriter::Dedent() {
-  CHECK(indent_level_ > 0);
+  AIDL_FATAL_IF(indent_level_ <= 0, "Mismatched dedent");
 
   indent_level_--;
 }
diff --git a/generate_cpp.cpp b/generate_cpp.cpp
index 6c11d35..e055df6 100644
--- a/generate_cpp.cpp
+++ b/generate_cpp.cpp
@@ -172,7 +172,7 @@
 
 unique_ptr<Declaration> BuildMetaMethodDecl(const AidlMethod& method, const AidlTypenames&,
                                             const Options& options, bool for_interface) {
-  CHECK(!method.IsUserDefined());
+  AIDL_FATAL_IF(method.IsUserDefined(), method);
   if (method.GetName() == kGetInterfaceVersion && options.Version()) {
     std::ostringstream code;
     if (for_interface) {
@@ -394,7 +394,7 @@
                                                     const AidlInterface& interface,
                                                     const AidlMethod& method,
                                                     const Options& options) {
-  CHECK(!method.IsUserDefined());
+  AIDL_FATAL_IF(method.IsUserDefined(), method);
   if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
     const string iface = ClassName(interface, ClassNames::INTERFACE);
     const string proxy = ClassName(interface, ClassNames::CLIENT);
@@ -617,7 +617,7 @@
 bool HandleServerMetaTransaction(const AidlTypenames&, const AidlInterface& interface,
                                  const AidlMethod& method, const Options& options,
                                  StatementBlock* b) {
-  CHECK(!method.IsUserDefined());
+  AIDL_FATAL_IF(method.IsUserDefined(), method);
 
   if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
     std::ostringstream code;
@@ -953,7 +953,7 @@
         break;
       }
       default: {
-        LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
+        AIDL_FATAL(value) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
       }
     }
   }
@@ -1247,10 +1247,10 @@
       header = BuildServerHeader(typenames, interface, options);
       break;
     default:
-      LOG(FATAL) << "aidl internal error";
+      AIDL_FATAL(interface) << "aidl internal error";
   }
   if (!header) {
-    LOG(ERROR) << "aidl internal error: Failed to generate header.";
+    AIDL_ERROR(interface) << "aidl internal error: Failed to generate header.";
     return false;
   }
 
@@ -1317,17 +1317,17 @@
     // Need to write all of the source in the header file, not cpp file.
     source->Write(header_writer.get());
   }
-  CHECK(header_writer->Close());
+  AIDL_FATAL_IF(!header_writer->Close(), header_path);
 
   // TODO(b/111362593): no unecessary files just to have consistent output with interfaces
   const string bp_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::CLIENT);
   unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
   bp_writer->Write("#error TODO(b/111362593) parcelables do not have bp classes");
-  CHECK(bp_writer->Close());
+  AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
   const string bn_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::SERVER);
   unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
   bn_writer->Write("#error TODO(b/111362593) parcelables do not have bn classes");
-  CHECK(bn_writer->Close());
+  AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
 
   unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
   if (parcelable.IsGeneric()) {
@@ -1337,7 +1337,7 @@
   } else {
     source->Write(source_writer.get());
   }
-  CHECK(source_writer->Close());
+  AIDL_FATAL_IF(!source_writer->Close(), output_file);
 
   return true;
 }
@@ -1347,21 +1347,21 @@
   CodeWriterPtr source_writer = io_delegate.GetCodeWriter(filename);
   *source_writer
       << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
-  CHECK(source_writer->Close());
+  AIDL_FATAL_IF(!source_writer->Close(), filename);
 
   // TODO(b/111362593): no unecessary files just to have consistent output with interfaces
   const string header_path = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::RAW);
   unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
   header_writer->Write("#error TODO(b/111362593) parcelables do not have headers");
-  CHECK(header_writer->Close());
+  AIDL_FATAL_IF(!header_writer->Close(), header_path);
   const string bp_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::CLIENT);
   unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
   bp_writer->Write("#error TODO(b/111362593) parcelables do not have bp classes");
-  CHECK(bp_writer->Close());
+  AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
   const string bn_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::SERVER);
   unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
   bn_writer->Write("#error TODO(b/111362593) parcelables do not have bn classes");
-  CHECK(bn_writer->Close());
+  AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
 
   return true;
 }
@@ -1376,21 +1376,21 @@
   const string header_path = options.OutputHeaderDir() + HeaderFile(enum_decl, ClassNames::RAW);
   unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
   header->Write(header_writer.get());
-  CHECK(header_writer->Close());
+  AIDL_FATAL_IF(!header_writer->Close(), header_path);
 
   // TODO(b/111362593): no unnecessary files just to have consistent output with interfaces
   CodeWriterPtr source_writer = io_delegate.GetCodeWriter(filename);
   *source_writer
       << "// This file is intentionally left blank as placeholder for enum declaration.\n";
-  CHECK(source_writer->Close());
+  AIDL_FATAL_IF(!source_writer->Close(), filename);
   const string bp_header = options.OutputHeaderDir() + HeaderFile(enum_decl, ClassNames::CLIENT);
   unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
   bp_writer->Write("#error TODO(b/111362593) enums do not have bp classes");
-  CHECK(bp_writer->Close());
+  AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
   const string bn_header = options.OutputHeaderDir() + HeaderFile(enum_decl, ClassNames::SERVER);
   unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
   bn_writer->Write("#error TODO(b/111362593) enums do not have bn classes");
-  CHECK(bn_writer->Close());
+  AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
 
   return true;
 }
@@ -1417,7 +1417,7 @@
     return GenerateCppInterface(output_file, options, typenames, *interface, io_delegate);
   }
 
-  CHECK(false) << "Unrecognized type sent for cpp generation.";
+  AIDL_FATAL(defined_type) << "Unrecognized type sent for cpp generation.";
   return false;
 }
 
diff --git a/generate_java.cpp b/generate_java.cpp
index 9c918d1..5b998df 100644
--- a/generate_java.cpp
+++ b/generate_java.cpp
@@ -36,8 +36,8 @@
 using std::string;
 
 namespace {
-inline string get_setter_name(const string& variablename) {
-  CHECK(variablename.size() > 0) << "A field name cannot be empty.";
+inline string get_setter_name(const AidlNode& context, const string& variablename) {
+  AIDL_FATAL_IF(variablename.size() <= 0, context) << "A field name cannot be empty.";
   std::ostringstream out;
   out << "set" << static_cast<char>(toupper(variablename[0])) << variablename.substr(1);
   return out.str();
@@ -100,7 +100,7 @@
     return generate_java_interface(filename, interface, typenames, io_delegate, options);
   }
 
-  CHECK(false) << "Unrecognized type sent for java generation.";
+  AIDL_FATAL(defined_type) << "Unrecognized type sent for Java generation.";
   return false;
 }
 
@@ -162,7 +162,7 @@
         out << " = " << variable->ValueString(ConstantValueDecorator);
       }
       out << ";\n";
-      out << "public Builder " << get_setter_name(variable->GetName()) << "("
+      out << "public Builder " << get_setter_name(*variable, variable->GetName()) << "("
           << JavaSignatureOf(variable->GetType(), typenames) << " " << variable->GetName()
           << ") {\n"
           << "  "
@@ -339,7 +339,8 @@
     CreateFromParcelFor(context);
     if (parcel->IsJavaOnlyImmutable()) {
       context.writer.Write("%s.%s(%s);\n", builder_variable.c_str(),
-                           get_setter_name(field->GetName()).c_str(), field_variable_name.c_str());
+                           get_setter_name(*field, field->GetName()).c_str(),
+                           field_variable_name.c_str());
     }
     writer->Close();
     read_or_create_method->statements->Add(std::make_shared<LiteralStatement>(code));
diff --git a/generate_java_binder.cpp b/generate_java_binder.cpp
index b9c7674..3d58ccd 100644
--- a/generate_java_binder.cpp
+++ b/generate_java_binder.cpp
@@ -945,7 +945,7 @@
 static void compute_outline_methods(const AidlInterface* iface,
                                     const std::shared_ptr<StubClass> stub, size_t outline_threshold,
                                     size_t non_outline_count) {
-  CHECK_LE(non_outline_count, outline_threshold);
+  AIDL_FATAL_IF(non_outline_count > outline_threshold, iface);
   // We'll outline (create sub methods) if there are more than min_methods
   // cases.
   stub->transact_outline = iface->GetMethods().size() > outline_threshold;
@@ -1114,7 +1114,7 @@
         break;
       }
       default: {
-        LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
+        AIDL_FATAL(value) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
       }
     }
   }
diff --git a/generate_ndk.cpp b/generate_ndk.cpp
index 779de7e..7617351 100644
--- a/generate_ndk.cpp
+++ b/generate_ndk.cpp
@@ -45,23 +45,23 @@
   const string i_header = options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
   unique_ptr<CodeWriter> i_writer(io_delegate.GetCodeWriter(i_header));
   GenerateInterfaceHeader(*i_writer, types, defined_type, options);
-  CHECK(i_writer->Close());
+  AIDL_FATAL_IF(!i_writer->Close(), i_header);
 
   const string bp_header =
       options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
   unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
   GenerateClientHeader(*bp_writer, types, defined_type, options);
-  CHECK(bp_writer->Close());
+  AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
 
   const string bn_header =
       options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
   unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
   GenerateServerHeader(*bn_writer, types, defined_type, options);
-  CHECK(bn_writer->Close());
+  AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
 
   unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
   GenerateSource(*source_writer, types, defined_type, options);
-  CHECK(source_writer->Close());
+  AIDL_FATAL_IF(!source_writer->Close(), output_file);
 }
 
 void GenerateNdkParcel(const string& output_file, const Options& options,
@@ -79,27 +79,27 @@
   } else {
     GenerateParcelSource(*source_writer, types, defined_type, options);
   }
-  CHECK(source_writer->Close());
-  CHECK(header_writer->Close());
+  (source_writer->Close());
+  AIDL_FATAL_IF(!header_writer->Close(), header_path);
 
   const string bp_header =
       options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
   unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
   *bp_writer << "#error TODO(b/111362593) defined_types do not have bp classes\n";
-  CHECK(bp_writer->Close());
+  AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
 
   const string bn_header =
       options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
   unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
   *bn_writer << "#error TODO(b/111362593) defined_types do not have bn classes\n";
-  CHECK(bn_writer->Close());
+  AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
 }
 
 void GenerateNdkParcelDeclaration(const std::string& filename, const IoDelegate& io_delegate) {
   CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
   *code_writer
       << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
-  CHECK(code_writer->Close());
+  AIDL_FATAL_IF(!code_writer->Close(), filename);
 }
 
 void GenerateNdkEnumDeclaration(const string& output_file, const Options& options,
@@ -109,24 +109,24 @@
       options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
   unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
   GenerateEnumHeader(*header_writer, types, defined_type, options);
-  CHECK(header_writer->Close());
+  AIDL_FATAL_IF(!header_writer->Close(), header_path);
 
   const string bp_header =
       options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
   unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
   *bp_writer << "#error TODO(b/111362593) enums do not have bp classes\n";
-  CHECK(bp_writer->Close());
+  AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
 
   const string bn_header =
       options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
   unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
   *bn_writer << "#error TODO(b/111362593) enums do not have bn classes\n";
-  CHECK(bn_writer->Close());
+  AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
 
   unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
   *source_writer
       << "// This file is intentionally left blank as placeholder for enum declaration.\n";
-  CHECK(source_writer->Close());
+  AIDL_FATAL_IF(!source_writer->Close(), output_file);
 }
 
 void GenerateNdk(const string& output_file, const Options& options, const AidlTypenames& types,
@@ -154,7 +154,7 @@
     return;
   }
 
-  CHECK(false) << "Unrecognized type sent for NDK cpp generation.";
+  AIDL_FATAL(defined_type) << "Unrecognized type sent for NDK cpp generation.";
 }
 namespace internals {
 
@@ -272,8 +272,9 @@
 static void GenerateConstantDeclarations(CodeWriter& out, const AidlInterface& interface) {
   for (const auto& constant : interface.GetConstantDeclarations()) {
     const AidlConstantValue& value = constant->GetValue();
-    CHECK(value.GetType() != AidlConstantValue::Type::UNARY &&
-          value.GetType() != AidlConstantValue::Type::BINARY);
+    AIDL_FATAL_IF(value.GetType() == AidlConstantValue::Type::UNARY ||
+                      value.GetType() == AidlConstantValue::Type::BINARY,
+                  value);
     if (value.GetType() == AidlConstantValue::Type::STRING) {
       out << "static const char* " << constant->GetName() << ";\n";
     }
@@ -283,8 +284,9 @@
   bool hasIntegralConstant = false;
   for (const auto& constant : interface.GetConstantDeclarations()) {
     const AidlConstantValue& value = constant->GetValue();
-    CHECK(value.GetType() != AidlConstantValue::Type::UNARY &&
-          value.GetType() != AidlConstantValue::Type::BINARY);
+    AIDL_FATAL_IF(value.GetType() == AidlConstantValue::Type::UNARY ||
+                      value.GetType() == AidlConstantValue::Type::BINARY,
+                  value);
     if (value.GetType() == AidlConstantValue::Type::BOOLEAN ||
         value.GetType() == AidlConstantValue::Type::INT8 ||
         value.GetType() == AidlConstantValue::Type::INT32) {
@@ -314,8 +316,9 @@
 
   for (const auto& constant : interface.GetConstantDeclarations()) {
     const AidlConstantValue& value = constant->GetValue();
-    CHECK(value.GetType() != AidlConstantValue::Type::UNARY &&
-          value.GetType() != AidlConstantValue::Type::BINARY);
+    AIDL_FATAL_IF(value.GetType() == AidlConstantValue::Type::UNARY ||
+                      value.GetType() == AidlConstantValue::Type::BINARY,
+                  value);
     if (value.GetType() == AidlConstantValue::Type::STRING) {
       out << "const char* " << clazz << "::" << constant->GetName() << " = "
           << constant->ValueString(ConstantValueDecorator) << ";\n";
diff --git a/generate_rust.cpp b/generate_rust.cpp
index 002abc4..df65bc2 100644
--- a/generate_rust.cpp
+++ b/generate_rust.cpp
@@ -422,7 +422,7 @@
         break;
       }
       default: {
-        LOG(FATAL) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
+        AIDL_FATAL(value) << "Unrecognized constant type: " << static_cast<int>(value.GetType());
       }
     }
     *code_writer << "pub const " << constant->GetName() << ": " << const_type << " = "
@@ -644,7 +644,7 @@
     return GenerateRustInterface(filename, interface, typenames, io_delegate, options);
   }
 
-  CHECK(false) << "Unrecognized type sent for Rust generation.";
+  AIDL_FATAL(filename) << "Unrecognized type sent for Rust generation.";
   return false;
 }
 
diff --git a/io_delegate.cpp b/io_delegate.cpp
index 4b2e00a..c0ee97a 100644
--- a/io_delegate.cpp
+++ b/io_delegate.cpp
@@ -22,6 +22,8 @@
 
 #ifdef _WIN32
 #include <direct.h>
+#include <windows.h>
+#undef ERROR
 #else
 #include <dirent.h>
 #include <sys/stat.h>
@@ -49,7 +51,7 @@
   char buf[4096];
   DWORD path_len = GetFullPathName(path.c_str(), sizeof(buf), buf, nullptr);
   if (path_len <= 0 || path_len >= sizeof(buf)) {
-    LOG(ERROR) << "Failed to GetFullPathName(" << path << ")";
+    AIDL_ERROR(path) << "Failed to GetFullPathName";
     return false;
   }
   *absolute_path = buf;
@@ -59,8 +61,7 @@
 #else
 
   if (path.empty()) {
-    LOG(ERROR) << "Giving up on finding an absolute path to represent the "
-                  "empty string.";
+    AIDL_ERROR(path) << "Giving up on finding an absolute path to represent the empty string.";
     return false;
   }
   if (path[0] == OS_PATH_SEPARATOR) {
@@ -70,8 +71,8 @@
 
   char buf[4096];
   if (getcwd(buf, sizeof(buf)) == nullptr) {
-    LOG(ERROR) << "Path of current working directory does not fit in "
-               << sizeof(buf) << " bytes";
+    AIDL_ERROR(path) << "Path of current working directory does not fit in " << sizeof(buf)
+                     << " bytes";
     return false;
   }
 
@@ -138,8 +139,7 @@
 #endif
     // On darwin when you try to mkdir("/", ...) we get EISDIR.
     if (!success && (errno != EEXIST && errno != EISDIR)) {
-      LOG(ERROR) << "Error while creating " << base_dir << ": "
-                 << strerror(errno);
+      AIDL_ERROR(caller_base_dir) << "Error while creating " << base_dir << ": " << strerror(errno);
       return false;
     }
   }
@@ -201,7 +201,7 @@
 
 #else
 static void add_list_files(const string& dirname, vector<string>* result) {
-  CHECK(result != nullptr);
+  AIDL_FATAL_IF(result == nullptr, dirname);
   std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(dirname.c_str()), closedir);
   if (dir != nullptr) {
     while (struct dirent* ent = readdir(dir.get())) {
diff --git a/logging.h b/logging.h
index e166cef..f6d6da1 100644
--- a/logging.h
+++ b/logging.h
@@ -20,13 +20,6 @@
 
 #include <iostream>
 
-// We must include windows.h before android-base/logging.h on Windows.
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-#include <android-base/logging.h>
-
 // Generic point for printing any error in the AIDL compiler.
 class AidlErrorLog {
  public:
diff --git a/main.cpp b/main.cpp
index 35178cf..69ba060 100644
--- a/main.cpp
+++ b/main.cpp
@@ -30,13 +30,9 @@
 #endif
 
 int main(int argc, char* argv[]) {
-  android::base::InitLogging(argv);
-  LOG(DEBUG) << "aidl starting";
-
   Options options(argc, argv, kDefaultLang);
   if (!options.Ok()) {
-    std::cerr << options.GetErrorMessage();
-    std::cerr << options.GetUsage();
+    AIDL_ERROR(options.GetErrorMessage()) << options.GetUsage();
     return 1;
   }
 
diff --git a/options.cpp b/options.cpp
index 5fb44a4..1018146 100644
--- a/options.cpp
+++ b/options.cpp
@@ -507,8 +507,9 @@
     }
   }
 
-  CHECK(output_dir_.empty() || output_dir_.back() == OS_PATH_SEPARATOR);
-  CHECK(output_header_dir_.empty() || output_header_dir_.back() == OS_PATH_SEPARATOR);
+  AIDL_FATAL_IF(!output_dir_.empty() && output_dir_.back() != OS_PATH_SEPARATOR, output_dir_);
+  AIDL_FATAL_IF(!output_header_dir_.empty() && output_header_dir_.back() != OS_PATH_SEPARATOR,
+                output_header_dir_);
 }
 
 }  // namespace aidl
diff --git a/parser.cpp b/parser.cpp
index 923eebd..f2b9c55 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -15,7 +15,7 @@
  */
 
 #include "parser.h"
-#include "aidl_language_y-module.h"
+#include "aidl_language_y.h"
 #include "logging.h"
 
 void yylex_init(void**);
diff --git a/parser.h b/parser.h
index 23da269..0d39342 100644
--- a/parser.h
+++ b/parser.h
@@ -19,8 +19,8 @@
 #include "aidl_language.h"
 #include "aidl_typenames.h"
 #include "io_delegate.h"
+#include "logging.h"
 #include "options.h"
-#include <android-base/logging.h>
 
 #include <memory>
 #include <string>
@@ -88,7 +88,7 @@
   }
 
   const AidlDocument& ParsedDocument() const {
-    CHECK(!HasError());
+    AIDL_FATAL_IF(HasError(), FileName());
     return *document_;
   }