aidl: make abort() on AIDL_FATAL more obvious
Clang's static analyzer was complaining that code could dereference a
NULL pointer. The code looked like:
```
AIDL_FATAL_IF(x == nullptr, ctx) << "foo";
x->bar();
```
Because AidlErrorLog's primary constructor is out-of-line, and there's
potentially a fair amount of complex logic between the call to that and
the call to its destructor, it's helpful to both the optimizer and
static analyzer to make the unconditional abort more obvious.
operator, acts as a sequence point, and the LHS is of class type, so the
destructor won't be run until the end of the containing full expression:
https://en.cppreference.com/w/cpp/language/operator_other &&
https://godbolt.org/z/nfYvcz
This is intended to be no functional change.
Bug: None
Test: TreeHugger
Change-Id: I8f03f0f4d031ef7b28c886dae139d283a4391252
diff --git a/aidl_language.h b/aidl_language.h
index 86bd928..30e3198 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -164,8 +164,17 @@
DISALLOW_COPY_AND_ASSIGN(AidlErrorLog);
};
+// A class used to make it obvious to clang that code is going to abort. This
+// informs static analyses of the aborting behavior of `AIDL_FATAL`, and
+// helps generate slightly faster/smaller code.
+class AidlAbortOnDestruction {
+ public:
+ __attribute__((noreturn)) ~AidlAbortOnDestruction() { abort(); }
+};
+
#define AIDL_ERROR(CONTEXT) ::AidlErrorLog(false /*fatal*/, (CONTEXT)).os_
-#define AIDL_FATAL(CONTEXT) ::AidlErrorLog(true /*fatal*/, (CONTEXT)).os_
+#define AIDL_FATAL(CONTEXT) \
+ (::AidlAbortOnDestruction(), ::AidlErrorLog(true /*fatal*/, (CONTEXT)).os_)
#define AIDL_FATAL_IF(CONDITION, CONTEXT) \
if (CONDITION) AIDL_FATAL(CONTEXT) << "Bad internal state: " << #CONDITION << ": "