深入研究Clang(六) Clang Lexer代碼閱讀筆記之Preprocesser

深入研究Clang(六) Clang Lexer代碼閱讀筆記之Preprocesser

來自專欄 深入研究Clangclang/include/clang/Lex/Preprocesser.h

這個文件是包含clang::Preprocesser類的定義的頭文件。它是類C語言(C、C++、Object C)的預處理的頭文件。也就是說,類C語言的預處理都會用到此處的代碼。

  1. 00082 /// rief Context in which macro name is used.
  2. 00083 enum MacroUse {
  3. 00084 MU_Other = 0, // other than #define or #undef
  4. 00085 MU_Define = 1, // macro name specified in #define
  5. 00086 MU_Undef = 2 // macro name specified in #undef
  6. 00087 };

這個枚舉很簡單,就是通過枚舉值來確定到底使用了哪些宏。除了define和undef之外,其他的都分類到MU_Other類別下邊了。

  1. 00089 /// rief Engages in a tight little dance with the lexer to efficiently
  2. 00090 /// preprocess tokens.
  3. 00091 ///
  4. 00092 /// Lexers know only about tokens within a single source file, and dont
  5. 00093 /// know anything about preprocessor-level issues like the #include stack,
  6. 00094 /// token expansion, etc.
  7. 00095 class Preprocessor : public RefCountedBase<Preprocessor> {
  8. 00096 IntrusiveRefCntPtr<PreprocessorOptions> PPOpts;
  9. 00097 DiagnosticsEngine *Diags;
  10. 00098 LangOptions &LangOpts;
  11. 00099 const TargetInfo *Target;
  12. 00100 FileManager &FileMgr;
  13. 00101 SourceManager &SourceMgr;
  14. 00102 std::unique_ptr<ScratchBuffer> ScratchBuf;
  15. 00103 HeaderSearch &HeaderInfo;
  16. 00104 ModuleLoader &TheModuleLoader;

這裡可以看到Preprocessor的類的定義,而它是模板類RefCountedBase<Preprocessor>的子類。同時可以看看這幾個類的幾個成員變數,DiagnosticsEngine-診斷引擎,LangOptions-接收的編譯選項,TargetInfo-存儲目標信息,FileManager-文件管理器,SourceManager-源碼管理器,ModuleLoader-module載入器。

  1. 00118 /// Identifiers for builtin macros and other builtins.
  2. 00119 IdentifierInfo *Ident__LINE__, *Ident__FILE__; // __LINE__, __FILE__
  3. 00120 IdentifierInfo *Ident__DATE__, *Ident__TIME__; // __DATE__, __TIME__
  4. 00121 IdentifierInfo *Ident__INCLUDE_LEVEL__; // __INCLUDE_LEVEL__
  5. 00122 IdentifierInfo *Ident__BASE_FILE__; // __BASE_FILE__
  6. 00123 IdentifierInfo *Ident__TIMESTAMP__; // __TIMESTAMP__
  7. 00124 IdentifierInfo *Ident__COUNTER__; // __COUNTER__
  8. 00125 IdentifierInfo *Ident_Pragma, *Ident__pragma; // _Pragma, __pragma
  9. 00126 IdentifierInfo *Ident__identifier; // __identifier
  10. 00127 IdentifierInfo *Ident__VA_ARGS__; // __VA_ARGS__
  11. 00128 IdentifierInfo *Ident__has_feature; // __has_feature
  12. 00129 IdentifierInfo *Ident__has_extension; // __has_extension
  13. 00130 IdentifierInfo *Ident__has_builtin; // __has_builtin
  14. 00131 IdentifierInfo *Ident__has_attribute; // __has_attribute
  15. 00132 IdentifierInfo *Ident__has_include; // __has_include
  16. 00133 IdentifierInfo *Ident__has_include_next; // __has_include_next
  17. 00134 IdentifierInfo *Ident__has_warning; // __has_warning
  18. 00135 IdentifierInfo *Ident__is_identifier; // __is_identifier
  19. 00136 IdentifierInfo *Ident__building_module; // __building_module
  20. 00137 IdentifierInfo *Ident__MODULE__; // __MODULE__
  21. 00138 IdentifierInfo *Ident__has_cpp_attribute; // __has_cpp_attribute

另外Preprocesser類中包含了使用IdentifierInfo指針所保存的內建宏以及其他的內建的標示符。所以如果要修改或者擴展內建宏或者其他內建標示符,這裡也是必須要修改的地方。

  1. 00148 // State that is set before the preprocessor begins.
  2. 00149 bool KeepComments : 1;
  3. 00150 bool KeepMacroComments : 1;
  4. 00151 bool SuppressIncludeNotFoundError : 1;
  5. 00152
  6. 00153 // State that changes while the preprocessor runs:
  7. 00154 bool InMacroArgs : 1; // True if parsing fn macro invocation args.
  8. 00155
  9. 00156 /// Whether the preprocessor owns the header search object.
  10. 00157 bool OwnsHeaderSearch : 1;
  11. 00158
  12. 00159 /// True if macro expansion is disabled.
  13. 00160 bool DisableMacroExpansion : 1;
  14. 00161
  15. 00162 /// Temporarily disables DisableMacroExpansion (i.e. enables expansion)
  16. 00163 /// when parsing preprocessor directives.
  17. 00164 bool MacroExpansionInDirectivesOverride : 1;
  18. 00165
  19. 00166 class ResetMacroExpansionHelper;
  20. 00167
  21. 00168 /// rief Whether we have already loaded macros from the external source.
  22. 00169 mutable bool ReadMacrosFromExternalSource : 1;
  23. 00170
  24. 00171 /// rief True if pragmas are enabled.
  25. 00172 bool PragmasEnabled : 1;
  26. 00173
  27. 00174 /// rief True if the current build action is a preprocessing action.
  28. 00175 bool PreprocessedOutput : 1;

另外在Preprocesser類中,還出現了一部分這樣的代碼,這種給成員變數制定位域的形式還是第一次見到,一度讓我以為是要給成員變數賦值。這種使用位域節省空間的方式,在結構體中比在類中稍微常見點,為了節省空間,在這麼大的類中使用還是第一次見。:後面的數字是為了指定一定的bit位去保存變數的值。其中,這裡裡面還有一個更特殊的一行代碼:

  1. 00168 /// rief Whether we have already loaded macros from the external source.
  2. 00169 mutable bool ReadMacrosFromExternalSource : 1;

這個成員變數,不僅僅用到了位域,還用到了mutable。一般使用mutable修飾變數,是為了在const成員函數中可以修改這個成員變數。

2014-12-01


推薦閱讀:

TAG:LLVM | Clang | ChrisLattner |