рдпрд╣ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдХреНрд▓реИрдВрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд▓рдЧрдЗрди рдХреИрд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рдП рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЪрд░рдгреЛрдВ рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдП:
- рдкрд░реНрдпрд╛рд╡рд░рдг рдХреА рд╕реНрдерд╛рдкрдирд╛
- рдПрдХ рдореВрд▓ рдкреНрд▓рдЧрдЗрди рдмрдирд╛рдирд╛
- рдкреНрд▓рдЧрдЗрди рд╡рд┐рдХрд╛рд╕ рдХреЗ рд▓рд┐рдП рдПрдХ Xcode рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдирд╛
- рд╕рддрд░реНрдХ рдкреАрдврд╝реА
- рддреНрд░реБрдЯрд┐ рдкреАрдврд╝реА
- Xcode рдореЗрдВ рдкреНрд▓рдЧрдЗрди рдПрдХреАрдХрд░рдг
- рдСрдирд▓рд╛рдЗрди рдЪреЗрддрд╛рд╡рдирд┐рдпрд╛рдБ рдФрд░ рддреНрд░реБрдЯрд┐ рд╕реБрдЭрд╛рд╡
рдЯреАрдПрд▓, рдбреЙ
рддреИрдпрд╛рд░ рдкреНрд▓рдЧрдЗрди
рдпрд╣рд╛рдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛
рд╣реИредрдкреНрд░рд╡рд┐рд╖реНрдЯрд┐
рдмреНрд▓рдбрдореИрдЬрд┐рдХ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЗ рджреМрд░рд╛рди
, рдореИрдВрдиреЗ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ рдХрд┐ рдмреАрдПрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рдЕрд░реНрде рд╕рдВрдмрдВрдзреА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрдХрд░рдг рд╣реЛрдирд╛ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рд╕рдВрдкрддреНрддрд┐ рдХреЛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ
lazy
рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдЗрд╕реЗ @dynamic рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдпрд╛
lazy
рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХрдВрдЯреЗрдирд░ рд╡рд░реНрдЧ рдЗрдВрдЬреЗрдХреНрд╢рди рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдореИрдВ рдЗрд╕ рдирд┐рд╖реНрдХрд░реНрд╖ рдкрд░ рдкрд╣реБрдВрдЪрд╛ рдХрд┐ рдореБрдЭреЗ
рдПрдПрд╕рдЯреА рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдФрд░ рдЗрд╕рд▓рд┐рдП рдореБрдЭреЗ рдПрдХ рдкреВрд░реНрдг рдкрд╛рд░реНрд╕рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдореИрдВрдиреЗ рд╡рд┐рднрд┐рдиреНрди рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА:
рдлреНрд▓реЗрдХреНрд╕ +
рдмрд╛рдЗрд╕рди ,
рд▓рд┐рдмрдХреНрд▓реИрдВрдЧ , рд▓реЗрдХрд┐рди рдЕрдВрдд рдореЗрдВ рдореИрдВрдиреЗ
рдХреНрд▓реИрдВрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд▓рдЧрдЗрди рд▓рд┐рдЦрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред
рдкрд░реАрдХреНрд╖рдг рдкреНрд▓рдЧрдЗрди рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓рдХреНрд╖реНрдп рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдП рд╣реИрдВ:
- рд╡рд┐рдХрд╛рд╕ рдХреЗ рд▓рд┐рдП Xcode рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ
- рд░реЛрдЬрдорд░реНрд░рд╛ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рддреИрдпрд╛рд░ рдХрд┐рдП рдЧрдП рдкреНрд▓рдЧрдЗрди рдХреЛ Xcode рдореЗрдВ рдПрдХреАрдХреГрдд рдХрд░реЗрдВ
- рдкреНрд▓рдЧрдЗрди рдЪреЗрддрд╛рд╡рдиреА рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рддреНрд░реБрдЯрд┐рдпреЛрдВ рдФрд░ рдЗрдВрдЯрд░реИрдХреНрдЯрд┐рд╡ рд╕рдВрдХреЗрдд рджрд┐рдЦрд╛ (Xcode рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ)
рдкрд░реАрдХреНрд╖рдг рдкреНрд▓рдЧрдЗрди рдХреЗ рд▓рд┐рдП рд╕реБрд╡рд┐рдзрд╛рдПрдБ:
- рдпрджрд┐ рдХреНрд▓рд╛рд╕ рдХрд╛ рдирд╛рдо рд▓реЛрдЕрд░рдХреЗрд╕ рдЕрдХреНрд╖рд░ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ рддреЛ рдПрдХ рдЪреЗрддрд╛рд╡рдиреА рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ
- рдпрджрд┐ рд╡рд░реНрдЧ рдирд╛рдо рдореЗрдВ рдПрдХ рдЕрдВрдбрд░рд╕реНрдХреЛрд░ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдПрдХ рддреНрд░реБрдЯрд┐ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИ
- рд╕реБрдзрд╛рд░ рдХреЗ рд▓рд┐рдП рд╕реБрдЭрд╛рд╡ рджреЗрдВ
рдкрд░реНрдпрд╛рд╡рд░рдг рдХреА рд╕реНрдерд╛рдкрдирд╛
рдкреНрд▓рдЧрдЗрди рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рд╕реНрд░реЛрдд рд╕реЗ рд╕рдВрдХрд▓рд┐рдд llvm / clang рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА
cd /opt sudo mkdir llvm sudo chown `whoami` llvm cd llvm export LLVM_HOME=`pwd`
рдореЗрд░реА рдорд╢реАрди рдкрд░ рдХреНрд▓реИрдВрдЧ рдХрд╛ рд╡рд░реНрддрдорд╛рди рд╕рдВрд╕реНрдХрд░рдг 3.3.1 рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЙрдкрдпреБрдХреНрдд рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ:
git clone -b release_33 https://github.com/llvm-mirror/llvm.git llvm git clone -b release_33 https://github.com/llvm-mirror/clang.git llvm/tools/clang git clone -b release_33 https://github.com/llvm-mirror/clang-tools-extra.git llvm/tools/clang/tools/extra git clone -b release_33 https://github.com/llvm-mirror/compiler-rt.git llvm/projects/compiler-rt mkdir llvm_build cd llvm_build cmake ../llvm -DCMAKE_BUILD_TYPE:STRING=Release make -j`sysctl -n hw.logicalcpu`
рдПрдХ рдмреБрдирд┐рдпрд╛рджреА рдкреНрд▓рдЧрдЗрди рдмрдирд╛рдирд╛
рдкреНрд▓рдЧрдЗрди рдХреЗ рд▓рд┐рдП рдПрдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдмрдирд╛рдПрдБ
cd $LLVM_HOME mkdir toy_clang_plugin; cd toy_clang_plugin
рд╣рдорд╛рд░рд╛ рдкреНрд▓рдЧрдЗрди рдХреНрд▓реИрдВрдЧ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЗ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ рдФрд░ рдЗрд╕рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рдВрд░рдЪрдирд╛ рд╣реИ:
ToyClangPlugin.exports CMakeLists.txt ToyClangPlugin.cpp
рд╣рдо рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ:
рд╡рд┐рдзрд╛рдирд╕рднрд╛ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдбреЗрдЯрд╛:
CMakeLists.txt cmake_minimum_required (VERSION 2.6) project (ToyClangPlugin) set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) set( LLVM_HOME /opt/llvm ) set( LLVM_SRC_DIR ${LLVM_HOME}/llvm ) set( CLANG_SRC_DIR ${LLVM_HOME}/llvm/tools/clang ) set( LLVM_BUILD_DIR ${LLVM_HOME}/llvm_build ) set( CLANG_BUILD_DIR ${LLVM_HOME}/llvm_build/tools/clang) add_definitions (-D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS) add_definitions (-D_GNU_SOURCE -DHAVE_CLANG_CONFIG_H) set (CMAKE_CXX_COMPILER "${LLVM_BUILD_DIR}/bin/clang++") set (CMAKE_CC_COMPILER "${LLVM_BUILD_DIR}/bin/clang") set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -fno-common -Woverloaded-virtual -Wcast-qual -fno-strict-aliasing -pedantic -Wno-long-long -Wall -Wno-unused-parameter -Wwrite-strings -fno-exceptions -fno-rtti") set (CMAKE_MODULE_LINKER_FLAGS "-Wl,-flat_namespace -Wl,-undefined -Wl,suppress") set (LLVM_LIBS LLVMJIT LLVMX86CodeGen LLVMX86AsmParser LLVMX86Disassembler LLVMExecutionEngine LLVMAsmPrinter LLVMSelectionDAG LLVMX86AsmPrinter LLVMX86Info LLVMMCParser LLVMCodeGen LLVMX86Utils LLVMScalarOpts LLVMInstCombine LLVMTransformUtils LLVMipa LLVMAnalysis LLVMTarget LLVMCore LLVMMC LLVMSupport LLVMBitReader LLVMOption ) macro(add_clang_plugin name) set (srcs ${ARGN}) include_directories( "${LLVM_SRC_DIR}/include" "${CLANG_SRC_DIR}/include" "${LLVM_BUILD_DIR}/include" "${CLANG_BUILD_DIR}/include" ) link_directories( "${LLVM_BUILD_DIR}/lib" ) add_library( ${name} SHARED ${srcs} ) if (SYMBOL_FILE) set_target_properties( ${name} PROPERTIES LINK_FlAGS "-exported_symbols_list ${SYMBOL_FILE}") endif() foreach (clang_lib ${CLANG_LIBS}) target_link_libraries( ${name} ${clang_lib} ) endforeach() foreach (llvm_lib ${LLVM_LIBS}) target_link_libraries( ${name} ${llvm_lib} ) endforeach() foreach (user_lib ${USER_LIBS}) target_link_libraries( ${name} ${user_lib} ) endforeach() endmacro(add_clang_plugin) set(SYMBOL_FILE ToyClangPlugin.exports) set (CLANG_LIBS clang clangFrontend clangAST clangAnalysis clangBasic clangCodeGen clangDriver clangFrontendTool clangLex clangParse clangSema clangEdit clangSerialization clangStaticAnalyzerCheckers clangStaticAnalyzerCore clangStaticAnalyzerFrontend ) set (USER_LIBS pthread curses ) add_clang_plugin(ToyClangPlugin ToyClangPlugin.cpp ) set_target_properties(ToyClangPlugin PROPERTIES LINKER_LANGUAGE CXX PREFIX "")
рдЕрдм рд╣рдо `CMakeLists.txt` рдкрд░ рдЖрдзрд╛рд░рд┐рдд рдПрдХ Xcode рдкреНрд░реЛрдЬреЗрдХреНрдЯ рддреИрдпрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ
mkdir build; cd build cmake -G Xcode .. open ToyClangPlugin.xcodeproj
рд╕рдлрд▓ рд╣реЛрдиреЗ рдкрд░ 'ALL_BUILD' рдЪрд▓рд╛рдПрдВ, рд╕рдорд╛рдкреНрдд рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдпрд╣рд╛рдВ рд╣реЛрдЧреА: `lib / Debug / ToyCLangPlugin.dylib`ред
RecursiveASTVisitor
рдПрдПрд╕рдЯреА рдореЙрдбреНрдпреВрд▓ рдПрдХ
RecursiveASTVisitor рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдПрдХ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдЯреНрд░реА рдХреЛ рдкрд╛рд░ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдмреНрдпрд╛рдЬ рдХреА рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рджреЗрдирд╛ рдФрд░ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд╣реИред
рдПрдХ рдЫреЛрдЯреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд░реВрдк рдореЗрдВ, рд╕рд╛рдордиреЗ рдЖрдиреЗ рд╡рд╛рд▓реА рд╕рднреА рдХрдХреНрд╖рд╛рдУрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реЗрдВ:
class ToyClassVisitor : public RecursiveASTVisitor<ToyClassVisitor> { public: bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *declaration) { printf("ObjClass: %s\n", declaration->getNameAsString().c_str()); return true; } }; class ToyConsumer : public ASTConsumer { public: void HandleTranslationUnit(ASTContext &context) { visitor.TraverseDecl(context.getTranslationUnitDecl()); } private: ToyClassVisitor visitor; };
рдПрдХ рдкрд░реАрдХреНрд╖рдг рд╡рд░реНрдЧ рдмрдирд╛рдПрдВ рдФрд░ рдкреНрд▓рдЧрдЗрди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВ
#import <Foundation/Foundation.h> @interface ToyObject : NSObject @end @implementation ToyObject @end
рдкреНрд▓рдЧрдЗрди рд▓реЙрдиреНрдЪ
/opt/llvm/toy_clang_plugin/build $ $LLVM_HOME/llvm_build/bin/clang ../test.m \ -Xclang -load \ -Xclang lib/Debug/ToyClangPlugin.dylib \ -Xclang -plugin \ -Xclang ToyClangPlugin
рдЖрдЙрдЯрдкреБрдЯ рдХрдХреНрд╖рд╛рдУрдВ рдХреА рдПрдХ рд╡рд┐рд╢рд╛рд▓ рд╕реВрдЪреА рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред
рдЕрд▓рд░реНрдЯ рдЬрдирд░реЗрд╢рди
рдпрджрд┐ рдХрдХреНрд╖рд╛ рдХрд╛ рдирд╛рдо рд▓реЛрдЕрд░рдХреЗрд╕ рдЕрдХреНрд╖рд░ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдПрдХ рдЪреЗрддрд╛рд╡рдиреА рджрд┐рдЦрд╛рдИ рджреЗрдЧреАред
рдЕрд▓рд░реНрдЯ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╕рдВрджрд░реНрдн рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
class ToyClassVisitor : public RecursiveASTVisitor<ToyClassVisitor> { private: ASTContext *context; public: void setContext(ASTContext &context) { this->context = &context; }
рд╡рд░реНрдЧ рдХрд╛ рдирд╛рдо рд╕рддреНрдпрд╛рдкрди:
bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *declaration) { checkForLowercasedName(declaration); return true; }
рдЕрдм рдЖрдкрдХреЛ "рдЦрд░рд╛рдм" рдирд╛рдо рдХреЗ рд╕рд╛рде рдПрдХ рд╡рд░реНрдЧ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
@interface bad_ToyObject : NSObject @end @implementation bad_ToyObject @end
рдФрд░ рдкреНрд▓рдЧрдЗрди рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВ
/opt/llvm/toy_clang_plugin/build $ $LLVM_HOME/llvm_build/bin/clang ../test.m \ -Xclang -load \ -Xclang lib/Debug/ToyClangPlugin.dylib \ -Xclang -plugin \ -Xclang ToyClangPlugin ../test.m:11:12: warning: Class name should not start with lowercase letter @interface bad_ToyObject : NSObject ^ 1 warning generated.
рддреНрд░реБрдЯрд┐ рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛
рдпрджрд┐ рд╡рд░реНрдЧ рдирд╛рдо рдореЗрдВ рдПрдХ рдЕрдВрдбрд░рд╕реНрдХреЛрд░ ('_') рд╣реИ, рддреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдПрдХ рддреНрд░реБрдЯрд┐ рджрд┐рдЦрд╛рдИ рджреЗрдЧреАред
void checkForUnderscoreInName(ObjCInterfaceDecl *declaration) { size_t underscorePos = declaration->getName().find('_'); if (underscorePos != StringRef::npos) { DiagnosticsEngine &diagEngine = context->getDiagnostics(); unsigned diagID = diagEngine.getCustomDiagID(DiagnosticsEngine::Error, "Class name with `_` forbidden"); SourceLocation location = declaration->getLocation().getLocWithOffset(underscorePos); diagEngine.Report(location, diagID); } } bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *declaration) {
рд▓реЙрдиреНрдЪ рдХреЗ рдмрд╛рдж рдЖрдЙрдЯрдкреБрдЯ
/opt/llvm/toy_clang_plugin/build $ $LLVM_HOME/llvm_build/bin/clang ../test.m \ -Xclang -load \ -Xclang lib/Debug/ToyClangPlugin.dylib \ -Xclang -plugin \ -Xclang ToyClangPlugin ../test.m:11:15: error: Class name with `_` forbidden @interface bad_ToyObject : NSObject ^ 1 error generated.
рдкрд╣рд▓реА рдЬрд╛рдВрдЪ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рдПрдХ рддреНрд░реБрдЯрд┐ рдФрд░ рдЪреЗрддрд╛рд╡рдиреА рджреЛрдиреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рд░рджреНрдж рдХрд░реЗрдВ
/opt/llvm/toy_clang_plugin/build $ $LLVM_HOME/llvm_build/bin/clang ../test.m \ -Xclang -load \ -Xclang lib/Debug/ToyClangPlugin.dylib \ -Xclang -plugin \ -Xclang ToyClangPlugin ../test.m:11:12: warning: Class name should not start with lowercase letter @interface bad_ToyObject : NSObject ^ ../test.m:11:15: error: Class name with `_` forbidden @interface bad_ToyObject : NSObject ^ 1 warning and 1 error generated.
Xcode рдПрдХреАрдХрд░рдг
рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рд╕рд┐рд╕реНрдЯрдо (рд╕рд┐рд╕реНрдЯрдо рджреНрд╡рд╛рд░рд╛, рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдПрдХреНрд╕рдХреЛрдб рдбрд┐рд▓реАрд╡рд░реА рд╕реЗ рдХреНрд▓реИрдВрдЧ) рдХреНрд▓реИрдВрдЧ рдкреНрд▓рдЧрдЗрдиреНрд╕ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдХрд╕реНрдЯрдо рдХрдВрдкрд╛рдЗрд▓рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХреНрд╕рдХреЛрдб рдХрд╛ рдереЛрдбрд╝рд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
рдЗрд╕ рд╕рдВрдЧреНрд░рд╣ рдХреЛ рдЕрдирдЬрд╝рд┐рдк
рдХрд░реЗрдВ рдФрд░ рдирд┐рдореНрди рдХрдорд╛рдВрдб рдЪрд▓рд╛рдПрдБ:
sudo mv HackedClang.xcplugin `xcode-select -print-path`/../PlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-ins sudo mv HackedBuildSystem.xcspec `xcode-select -print-path`/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications
рдпреЗ рд╣реИрдХреНрд╕ Xcode рдореЗрдВ рдПрдХ рдирдпрд╛ рд╕рдВрдХрд▓рдХ рдЬреЛрдбрд╝ рджреЗрдВрдЧреЗ рдФрд░ рдЙрдиреНрд╣реЗрдВ OSX рдФрд░ iPhoneSimulator рдХреЗ рд▓рд┐рдП рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВрдЧреЗред
Xcode рдХреЛ рдкреБрдирд░рд╛рд░рдВрдн рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк рд╕реВрдЪреА рдореЗрдВ рдирдпрд╛ рдХреНрд▓реИрдВрдЧ рджреЗрдЦреЗрдВрдЧреЗ

рдПрдХ рдирдИ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рдПрдВ рдФрд░ 'рд╕реЗрдЯрд┐рдВрдЧ рдмрдирд╛рдПрдБ' рдореЗрдВ рд╣рдорд╛рд░реЗ рдХрд╕реНрдЯрдо рдХреНрд▓реИрдВрдЧ рдХрд╛ рдЪрдпрди рдХрд░реЗрдВред
рдкреНрд▓рдЧрдЗрди рдХреЛ рд╕рдХреНрд╖рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ 'рдЕрдиреНрдп C рдлреНрд▓реИрдЧ' рдореЗрдВ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛
-Xclang -load -Xclang /opt/llvm/toy_clang_plugin/build/lib/Debug/ToyClangPlugin.dylib -Xclang -add-plugin -Xclang ToyClangPlugin

рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╣рд╛рдВ рд╣рдо `-dd-plugin` рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рдЕрдкрдиреЗ` ASTAction` рдХреЛ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдФрд░ рдореМрдЬреВрджрд╛ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдирд╣реАрдВ рдХрд░рддреЗред
рдЖрдкрдХреЛ рдЗрд╕ рдЕрд╕реЗрдВрдмрд▓реА рдХреЗ рд▓рд┐рдП рдореЙрдбреНрдпреВрд▓ рдХреЛ рдЕрдХреНрд╖рдо рдХрд░рдирд╛ рд╣реЛрдЧрд╛:

рдЗрд╕ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рд╣рдорд╛рд░рд╛ `test.m` рдЬреЛрдбрд╝реЗрдВ рдпрд╛ рдкреНрд▓рдЧрдЗрди рдорд╛рдирджрдВрдб рд╕реЗ рдореЗрд▓ рдЦрд╛рдиреЗ рд╡рд╛рд▓реЗ рдирд╛рдореЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдирдпрд╛ рд╡рд░реНрдЧ рдмрдирд╛рдПрдВред
рдЕрд╕реЗрдВрдмрд▓реА рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдЪреЗрддрд╛рд╡рдирд┐рдпреЛрдВ рдФрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЕрдзрд┐рдХ рдкрд░рд┐рдЪрд┐рдд рд░реВрдк рдореЗрдВ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:

рдкрд░рд╕реНрдкрд░ рд╕рдВрдХреЗрдд
рдЕрдм рдпрд╣ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдФрд░ рдЪреЗрддрд╛рд╡рдирд┐рдпреЛрдВ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрдВрдЯрд░реЗрдХреНрдЯрд┐рд╡ рдпреБрдХреНрддрд┐рдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рд▓рд╛рдпрдХ рд╣реИред
void checkForLowercasedName(ObjCInterfaceDecl *declaration) { StringRef name = declaration->getName(); char c = name[0]; if (isLowercase(c)) { std::string tempName = name; tempName[0] = toUppercase(c); StringRef replacement(tempName); SourceLocation nameStart = declaration->getLocation(); SourceLocation nameEnd = nameStart.getLocWithOffset(name.size()); FixItHint fixItHint = FixItHint::CreateReplacement(SourceRange(nameStart, nameEnd), replacement); DiagnosticsEngine &diagEngine = context->getDiagnostics(); unsigned diagID = diagEngine.getCustomDiagID(DiagnosticsEngine::Warning, "Class name should not start with lowercase letter"); SourceLocation location = declaration->getLocation(); diagEngine.Report(location, diagID).AddFixItHint(fixItHint); } } void checkForUnderscoreInName(ObjCInterfaceDecl *declaration) { StringRef name = declaration->getName(); size_t underscorePos = name.find('_'); if (underscorePos != StringRef::npos) { std::string tempName = name; std::string::iterator end_pos = std::remove(tempName.begin(), tempName.end(), '_'); tempName.erase(end_pos, tempName.end()); StringRef replacement(tempName); SourceLocation nameStart = declaration->getLocation(); SourceLocation nameEnd = nameStart.getLocWithOffset(name.size()); FixItHint fixItHint = FixItHint::CreateReplacement(SourceRange(nameStart, nameEnd), replacement); DiagnosticsEngine &diagEngine = context->getDiagnostics(); unsigned diagID = diagEngine.getCustomDiagID(DiagnosticsEngine::Error, "Class name with `_` forbidden"); SourceLocation location = declaration->getLocation().getLocWithOffset(underscorePos); diagEngine.Report(location, diagID).AddFixItHint(fixItHint); } }
рдкреНрд▓рдЧрдЗрди рдХрд╛ рдкреБрдирд░реНрдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдВ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЛ рдЪрд▓рд╛рдПрдВ


рдирд┐рд╖реНрдХрд░реНрд╖
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрд▓реИрдВрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд▓рдЧрдЗрди рдмрдирд╛рдирд╛ рдПрдХ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рд╕рд░рд▓ рдХрд╛рд░реНрдп рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рд▓рд┐рдП Xcode рдХреЗ рд╕рд╛рде рдЧрдВрджреЗ рд╣реИрдХреНрд╕ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдФрд░ рдЖрдкрдХреЛ рдЕрдкрдирд╛ рдХреНрд▓реИрдВрдЧ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЙрддреНрдкрд╛рджрди рдореЗрдВ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╕реНрдЯрдо рдХрдВрдкрд╛рдЗрд▓рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рд╕рд▓рд╛рд╣ рдирд╣реАрдВ рджреВрдВрдЧрд╛ред Apple рдХреНрд▓реИрдВрдЧ рдХрд╛ рдПрдХ рдкреИрдЪ рд╕рдВрд╕реНрдХрд░рдг рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд╣рдо рдпрд╣ рдирд╣реАрдВ рдЬрд╛рди рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЕрдВрддрд░ рдХреНрдпрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХреНрд╕рдХреЛрдб рдХреЗ рд▓рд┐рдП рдХреНрд▓реИрдВрдЧ рдкреНрд▓рдЧрдЗрди рдХреЛ рдЗрд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдкреНрд░рдпрд╛рд╕ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЬреЛ рдЗрд╕реЗ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдирд╣реАрдВ рдмрдирд╛рддрд╛ рд╣реИред
рдПрдХ рдФрд░ рд╕рдорд╕реНрдпрд╛ рд╣реИ рдХрд┐ рдЖрдк рд╡рд┐рдХрд╛рд╕ рдХреЗ рджреМрд░рд╛рди рд╕рд╛рдордирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ - рдПрдХ рдЕрд╕реНрдерд┐рд░ рдФрд░ рд▓рдЧрд╛рддрд╛рд░ рдмрджрд▓рддреЗ рдПрдкреАрдЖрдИред
рдЖрдк рдЕрдкрдиреЗ рд╕рд┐рд╕реНрдЯрдо рдкрд░ рд╕рдорд╛рди рдкреНрд▓рдЧрдЗрдиреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдХреГрдкрдпрд╛ рдЕрдиреНрдп рд▓реЛрдЧреЛрдВ рдХреЛ рдРрд╕реЗ рднрд╛рд░реА рдЯреБрдХрдбрд╝реЛрдВ рдкрд░ рдирд┐рд░реНрднрд░ рд░рд╣рдиреЗ рдХреЗ рд▓рд┐рдП рдордЬрдмреВрд░ рди рдХрд░реЗрдВред
рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдХреЛрдИ рдЯрд┐рдкреНрдкрдгреА, рдкреНрд░рд╢реНрди рдпрд╛ рд╕реБрдЭрд╛рд╡ рд╣реИ, рддреЛ
рдЯреНрд╡рд┐рдЯрд░ рдкрд░ рд▓рд┐рдЦреЗрдВ,
GitHub рдпрд╛ рдмрд╕ рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдпрд╣рд╛рдВ рдЫреЛрдбрд╝ рджреЗрдВред
рд╣реИрдкреНрдкреА рд╣реИрдХрд┐рдВрдЧ!