エラーメッセージ定义を掘り下げる
ここではSwiftのコンパイルエラーのメッセージ定义を改めて掘り下げる。
defッセージ定义は.defファイルの中でこのような形で书かれている。
错误(extra_rbrace,none,
“顶级的外部'}'”,()
ERROR
の他にWARNING
AR NOTE
もあるが形は同じである。
そ利用方法に応じて様々な形に変えられる。その変换处理は#define
机能を使って非常に复雑に(どこが走っているかわかりにくい状态で)行われる。
.defファイルには,それぞれ対応する.hファイルがあり,まずはそのペアのつながりで.defファイルがどう利用されるかを见ていく。
.defファイルと.hファイルのペアというの例,例えば
DiagnosticsParse.def
に対して
DiagnosticsParse.h
があるということ。
.defファイルの中身は
#ifndef错误
#定义ERROR(ID,Options,Text,Signature)\
诊断(错误,ID,选项,文本,签名)
#endifそれぞれのメッセージ定义が大量#ifndef DIAG_NO_UNDEF
#如果已定义(DIAG)
#undef DIAG
# 万一
#undef错误
#万一
となっている。ポイントを挙げると
- ファイルの头で,
ERROR
がすでに#define
されているかどうかを确认し,されていない场合には#define
を行い,ERROR
をDIAG
に置き换える设定をする(引数の表记は省略)。 - 一个々のメッセージ定义の后,最后に
DIAG_NO_UNDEF
の状态によりdefine状态の消去を行う。
ちなみに, WARNING
とNOTE
が构造がERROR
と同じなので省いてある,ここから先も同じ。
h .hファイルの中身は
#include“ swift / AST / DiagnosticsCommon.h”#定义DIAG(KIND,ID,Options,Text,Signature)\
外部详细信息:: DiagWithArguments ::类型ID;
#include“ DiagnosticsParse.def”
-
DIAG
が#define
されて,
extern detail::DiagWithArguments::type ID;
になる。 - defの后で.defファイルが
#include
される。
h,この.hファイルを読み込んだ场合は,
ERROR
-> DIAG
-> detail::DiagWith~
という変换がされる。その过程は,
- .hファイル内で
ERROR
は#define
されていないので,.defファイル内でERROR
はDIAG
への#define
が有效になり, - DIAの
DIAG
が.hファイル先头の#define
によりdetail::DiagWith~
に置き换えられる。
となる。
また, DIAG_NO_UNDEF
も#define
されていないので,.defファイルの最后でdefine状态が消される。
Common.hとCommon.def
.hをよく见るとDiagnosticsCommon.hを#include
している。このDiagnosticsCommon.h(とそのペアのDiagnosticsCommon.def)は,コンパイルの中で泛用的に利用されるもの。やっていることは上と同じで
ERROR
-> DIAG
-> detail::DiagWith~
の変换を行い,最后に定义状态を消す。
DiagnosticsAll.def
である。これを见て。ァててていく。
#ifndef错误
#定义ERROR(ID,Options,Text,Signature)\
诊断(错误,ID,选项,文本,签名)
#endif#define DIAG_NO_UNDEF#include“ DiagnosticsCommon.def”
#include“ DiagnosticsParse.def”
#include“ DiagnosticsSema.def”
#include“ DiagnosticsClangImporter.def”
#include“ DiagnosticsSIL.def”
#include“ DiagnosticsIRGen.def”
#include“ DiagnosticsFrontend.def”
#include“ DiagnosticsDriver.def”
#include“ DiagnosticsRefactoring.def” #undef DIAG_NO_UNDEF#如果已定义(DIAG)
#undef DIAG
#万一
#undef错误
んのDiagnosticsAll.def
は全ての.defファイルを読み込むものである。真ん中の#include
の连続で読み込んでいる。
- 先头で
ERROR
が#define
されているか确认し,されていなければERROR
からDIAG
への変换を设定している。 - これは,各.defファイルを読み込む前に
DIAG_NO_UNDEF
を#define
している。これは各.defファイル内でERROR
の#define
を消さないようにするためである。 - 各.defファイル内では,すでに
ERROR
が#define
されている场合は再#define
しないので,このDiagnosticsAll.def
の先头のERROR
の#define
が全体に渡り有效である。 -
DiagnosticsAll.def
ファイルの最后では例によって#define
したものを削除している。
DiagnosticsAll.defを読むところ
DiagnosticsAll.def
のDiagnosticsAll.def
を読むところはどこか。
- /lib/AST/DiagnosticEngine.cpp
- /lib/AST/DiagnosticList.cpp
である。
/lib/AST/DiagnosticEngine.cppについて
DiagnosticsAll.def
を#include
しているところを见ていく。
枚举LocalDiagID:uint32_t
枚举LocalDiagID:uint32_t {
#define DIAG(种类,ID,选项,文本,签名)ID,
#include“ swift / AST / DiagnosticsAll.def”
NumDiags
};
LocalDiagID
という枚举を宣言している。ここではDIAG
からID
を取Di出す#define
をしてからDiagnosticsAll.def
を読みこんでいて
ERROR
-> DIAG
-> ID
のみ
という変换が行われる。
きラー识别文字列によるenumを作って,ひとつひとつに数値を与えていることがわかる。0から顺番に番号が振られて,最后のNumDiags
に个数が入る。
静态StoredDiagnosticInfostoredDiagnosticInfos []
静态StoredDiagnosticInfostoredDiagnosticInfos [] = {
#定义错误(ID,选项,文本,签名)\
StoredDiagnosticInfo(DiagnosticKind :: Error,DiagnosticOptions :: Options),#include“ swift / AST / DiagnosticsAll.def”
};
StoredDiagnosticInfo
の配列を宣言しているStoredDiagnosticInfo
については未开拓者。
ここではERROR
を#define
しているので
ERROR
-> StoredDiagnosticInfo
ここでERROR
が#define
されると,この先でERROR
の上书き#define
はされない。DIAGを経由しないでERROR
を直接料理している。
静态const char * diagnosticStrings []
静态const char * diagnosticStrings [] = {
#define错误(ID,选项,文本,签名),
#include“ swift / AST / DiagnosticsAll.def”
“ ”,
};
ここはText
部分を取り出して配列を作るところ。上と同じようにERROR
の直接料理で,
ERROR
-> Text
のみ
という変换がされる。
/lib/AST/DiagnosticList.cppについて
次にもう一つのほう,DiagnosticList.cppを见ていく。
枚举类swift :: DiagID:uint32_t
枚举类swift :: DiagID:uint32_t {
#定义DIAG(种类,ID,选项,文本,签名)ID,
#include“ swift / AST / DiagnosticsAll.def”
};
ここもエラー识别文字列によるenumを作って,ひとつひとつに数値を与えていることがわかる。
detail :: DiagWithArguments ::类型ID
#定义DIAG(种类,ID,选项,文本,签名)\
detail :: DiagWithArguments :: type ID = {DiagID :: ID};
#include“ swift / AST / DiagnosticsAll.def”
ここも置き换え。
外部细节:: DiagWithArguments ::类型ID = {DiagID :: ID};
に変换される。
このtype
は/include/swift/AST/DiagnosticsCommon.hで
template
结构DiagWithArguments; template
结构DiagWithArguments {
类型定义Diag 类型;
};
と定义されているが深そうなので,一旦切り上げる。
以上,メッセージ定义がどういう形になっていくかを见てきた。当然ここから先も调べる项目は残されている。调べたらまた记事にしたいと思う。
内容に间违いがあった场合,お知らせ下さい。