# ubuntu
$ sudo apt install clang
# mac
$ brew install llvm
# download prebuilt clang libraries
$ wget https://github.com/xcalcc/labrador/releases/download/v0.1/clang-11.0.0.tar.xz
$ mkdir clang-prebuilt && cd clang-prebuilt
$ tar Jxf clang-11.0.0.tar.xz
# set CLANG_HOME
$ export CLANG_HOME=/path/to/clang/libraries
$ git clone https://github.com/xcalcc/labrador.git
xsca will be built in build directory, and its components will be installed to $XSCA_HOME
# set XSCA_HOME
$ export XSCA_HOME=/directory/which/contains/components
$ cd labrador
$ mkdir build && cd build
$ cmake -G Ninja ../src
$ ninja
$ ninja install
$ ./xsca -cc1 -emit-llvm test.c
Copy the whole example in src/rules directory to new ruleset name:
$ cd src/rules
$ cp -r example <NEW-RULESET-NAME>
rename files in
Modify
Modify src/rules/CMakeLists.txt to include this new ruleset subdirectory
Modify src/CMakeLists.txt to add the new library to XSCA_LIBS
Modify src/xsca_link.cpp to add new extern and static variable to make sure the library is correct linked and static objects are initialized correctly. Define the new variable in example_checker.cpp. In xsca_link.cpp
extern int __NEW_RULESET_NAME__; // defined in rules/example/example_checker.cpp
static ATTRIBUTE_UNUSED int New_Ruleset_Name = __NEW_RULESET_NAME__;
In example_checker.cpp
int __NEW_RULESET_NAME__; // used in xsca_link.cpp
PPNullHandler
which implements all clang preprocess callbacks but do nothing. New rule needs to overwrite callbacks interfaces to do corresponding check.DeclNullHandler
. AST stmt/expr rule follows check_stmt_example.inc and inherit from StmtNullHandler
. AST type rule follows check_type_example.inc and inherit from TypeNullHandler
.ALL_PP_RULES
macro and include the new PP rule inc file.ALL_DECL_RULES
macro and include the new decl rule inc file.ALL_STMT_RULES
macro and include the new stmt rule inc file.ALL_TYPE_RULES
macro and include the new type rule inc file.XSCA oonly uses virtual functions in the interface with clang, include ASTConsumer
and PPCallbacks
. Inside XSCA, all checkers are composed by template without virtual function for performance consideration.
Each ruleset is implemented as a checker. The checker base class provides 2 virtual functions to return callbacks (ASTConsumer
and PPCallbacks
) to be invoked by clang Lexer and Sema.
CheckerManager
is a singleton to manage all Checker instances and CheckerFactory
instances. In XcalCheckerManager::Initialize()
, all checker are created by CheckerFactory
and added to clang's preprocess callbacks or AST consumers.
CheckerFactory
provides interface to create the Checker instance. It's created and added to CheckerManager by CheckerFactoryRegister.CheckerFactoryRegister
is a static object to create CheckerFactory instance and add to CheckerManager.
XcalChecker
is defined in include/xsca_checker.h. XcalCheckerManager, XcalCheckerFactory and XcalCheckerFactoryRegister is defined in include/xsca_checker_manager.h.
PPCallback
derives from clang::PPCallbacks
which will be invoked by clang Lexer. When interfaces in PPCallbacks
is called, the corresponding handler API will be invoked.
PPNullHandler
implements all clang::PPCallbacks
API but do nothing. This can be the default base class for all PP handlers.
PPListHandler
composes multiple PP handles as a list so that they can be invoked by PPCallbacks
one by one.
XcalPPCallback
is defined in include/pp_callback.h. PPNullHandler is defined in pp_null_handler.h. PPListHandler is defined in pp_list_handler.h
TypeVisitor
implements a general Visit(clang::Type *type)
method, which checks the type class and call individual Visit method on given Type class. In iindividual Visit method, corresponding handler method is called.
TypeNullHandler implements all Visit*
method for types but do nothing. This can be the default base class for all Type checkers.
TypeListHandler
composes multiple Type handlers as a list so that they can be invoked one by one.
XcalTypeVisitor
is defined in include/type_visiotor.h. TypeNullHandler
is defined in type_null_handler.h. TypeListHandler is defined in type_list_handler.h
Similar to TypeVisitor, TypeNullHandler, TypeListHandler. StmtVisitor
will visit the Stmt node ans all it's children.
XcalStmtVisitor
is defined in include/stmt_visiotor.h. StmtNullHandler
is defined in stmt_null_handler.h. StmtListHandler is defined in stmt_list_handler.h
Similar to TypeVisitor, TypeNullHandler, TypeListHandler. DeclVisitor
will visit the Decl node ans call TypeVisitor for TypeDecl and StmtVisitor for FunctionDecl.
XcalDeclVisitor
is defined in include/decl_visiotor.h. DeclNullHandler
is defined in decl_null_handler.h. DeclListHandler is defined in decl_list_handler.h
Interfaces in ASTConsumer
is called by clang Sema and corresponding method in DeclVisitor
is called so that all Handlers can be called.
For preprocess:
Clang Lex --> PPCallbacks --> PPHandler --> individual PP check
For AST:
Clang Sema --> ASTConsumer --> DeclVisitor --> DeclHandler --> individual Decl check
--> (FunctionDecl) StmtVisitor --> StmtHandler --> individual Stmt check
--> (TypeDecl) TypeVisitor --> TypeHandler --> individual Type check