# Not Reached in Chromium Chromiumでは[NOTREACHED()](https://source.chromium.org/chromium/chromium/src/+/main:base/notreached.h;l=40-47;drc=ce0a8f95eebf9d9d65ffe6aee25e3a1780b9982f)というマクロがある。 到達しないはずのところに入れておくことで実装を強固にできるマクロだが、どういう挙動をするのか確認してみる。 ## 実装の確認 ```cpp= #if CHECK_WILL_STREAM() || BUILDFLAG(ENABLE_LOG_ERROR_NOT_REACHED) #define NOTREACHED() \ LOGGING_CHECK_FUNCTION_IMPL(::logging::NotReachedError::NotReached(), false) #else #define NOTREACHED() \ (true) ? ::logging::NotReachedError::TriggerNotReached() \ : EAT_CHECK_STREAM_PARAMS() #endif ``` [CHECKマクロ](https://github.com/elkurin/elkurin-daily-notes/blob/main/docs/day2.md)のときに読んだキモい書き方がありね。 これはunreachableなコードの中に書いておくことで、もしそこを通ったらエラーを出してくれる。 [logging::NoReachedError](https://source.chromium.org/chromium/chromium/src/+/main:base/check.h;l=131;drc=ce0a8f95eebf9d9d65ffe6aee25e3a1780b9982f)は[CheckError](https://source.chromium.org/chromium/chromium/src/+/main:base/check.h;l=63;drc=8e78783dc1f7007bad46d657c9f332614e240fd8)型のひとつで、[destruct](https://source.chromium.org/chromium/chromium/src/+/main:base/check.cc;l=259;drc=8e78783dc1f7007bad46d657c9f332614e240fd8)時にエラーログを履く。FATALならImmediateCrashまでつながる。 FATALなどは[LogSeverity](https://source.chromium.org/chromium/chromium/src/+/main:base/logging.h;l=359;drc=8e78783dc1f7007bad46d657c9f332614e240fd8)で管理されており、弱い方から順にINFO,WARNING,ERROR,FATALとついている。 ```cpp= constexpr LogSeverity LOGGING_INFO = 0; constexpr LogSeverity LOGGING_WARNING = 1; constexpr LogSeverity LOGGING_ERROR = 2; constexpr LogSeverity LOGGING_FATAL = 3; constexpr LogSeverity LOGGING_NUM_SEVERITIES = 4; ``` ERRORまではログを履くだけで、FATALは上記で確認したようにCrashまでする。 NoReachedErrorはLOGを出すときは[NotReached](https://source.chromium.org/chromium/chromium/src/+/main:base/check.h;l=133;drc=ce0a8f95eebf9d9d65ffe6aee25e3a1780b9982f)が呼ばれ、出さないときは[TriggerNotReached](https://source.chromium.org/chromium/chromium/src/+/main:base/check.h;l=138;drc=ce0a8f95eebf9d9d65ffe6aee25e3a1780b9982f)を呼んでlog messageはEAT_CHECK_STREAM_PARAMS()でダミーに流して消滅する。 NotReachedを確認するとどうやら[kNotReachedIsFatal](https://source.chromium.org/chromium/chromium/src/+/main:base/features.cc;l=24;drc=8e78783dc1f7007bad46d657c9f332614e240fd8)というフラグがあるらしい。 これはNOTREACHED()に来たときにLogSeverityをどうするかを定めることができるフラグで、EnableされてるならFATALにしてクラッシュまでする。 Chromiumではdisable by default。 ### NOTIMPLEMENTED 亜種として[NOTIMPLEMENTED](https://source.chromium.org/chromium/chromium/src/+/main:base/notreached.h;l=76-94;drc=ce0a8f95eebf9d9d65ffe6aee25e3a1780b9982f)というのもある。 名前の通り未実装の関数を通るときに出すエラー。 [NotImplemented](https://source.chromium.org/chromium/chromium/src/+/main:base/check.cc;l=247;drc=8e78783dc1f7007bad46d657c9f332614e240fd8)というCheckError型を持ち、シンプルにERRORレベルのログを出す。このときに流すのは  `Not implemented reached in __PRETTY_FUNCTION__`。 ## NOTREACHEDの使用例 どういうときに使うかというと、例えばswitch文でよく見る。 以下のケースはちゃんとすべてのケースで`return`が呼ばれているか、実装を確かめるために使われている。 ```cpp= gfx::Size ToTransformedSize(const gfx::Size& size, Transform transform) { switch (transform) { case Transform::NORMAL: case Transform::ROTATE_180: case Transform::FLIPPED: case Transform::FLIPPED_ROTATE_180: return size; case Transform::ROTATE_90: case Transform::ROTATE_270: case Transform::FLIPPED_ROTATE_90: case Transform::FLIPPED_ROTATE_270: return gfx::Size(size.height(), size.width()); } NOTREACHED(); } ``` 以下のケースでは`uint32_t`の型の中で取りうる値が限られているときに、それ以外が来たら落としている。 ```cpp= ui::ZOrderLevel AuraTopLevelZOrderLevel(uint32_t z_order_level) { switch (z_order_level) { case ZAURA_TOPLEVEL_Z_ORDER_LEVEL_NORMAL: return ui::ZOrderLevel::kNormal; case ZAURA_TOPLEVEL_Z_ORDER_LEVEL_FLOATING_WINDOW: return ui::ZOrderLevel::kFloatingWindow; case ZAURA_TOPLEVEL_Z_ORDER_LEVEL_FLOATING_UI_ELEMENT: return ui::ZOrderLevel::kFloatingUIElement; case ZAURA_TOPLEVEL_Z_ORDER_LEVEL_SECURITY_SURFACE: return ui::ZOrderLevel::kSecuritySurface; } NOTREACHED(); return ui::ZOrderLevel::kNormal; } ``` そもそも`uint32_t`ではなくenumとかにしたほうが良いが、そうできないケースもある。 このコードはwaylandのプロトコルを実装しており、仕様上uint32_tでしか選択肢形式の値や整数っぽい値を送ることができない。 他にもplatformごとに来てはいけないコードパスが違ったり、overrideしたクラスの方で制御したいときなどいろんなケースがある。 ## std::unrechable ところで似た名前で[std::unrechable](https://cpprefjp.github.io/reference/utility/unreachable.html)を見つけた。 役割は全然NOTREACHEDと違う。 std::unrechableをつけることによってここには来ないということをコンパイルに教えているだけで、コンパイル最適化時にいい感じにできること及び開発者が挙動を置いやすくていいという役割であって、std::unreachableにきうるコードをコンパイル失敗させたり、実行時にエラーが出たりするわけではない。 これはC++23で定義されたばかりなので、最適化についてもこれからに期待っぽい。