OCLint.6.RecursiveASTVisitor-class-from-clangAST-library
作者:互联网
RecursiveASTVisitor class from clangAST library
1. What's RecursiveASTVisitor?
RecursiveASTVisitor class is defined at the file ${LLVM_PROJECT_PATH}/clang/include/clang/AST/RecursiveASTVisitor.h.
2. Macros in RecursiveASTVisitor
There are many macros in the RecursiveASTVisitor.h file:
StmtNodes.inc, TypeNodes.inc, TypeLocNodes.def, DeclNodes.inc, OMP.inc, AttrVisitor.inc
2.1 TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE)
If this class(RecursiveASTVisitor) and Derived class have the same "Traverse##NAME" function, then
convert '*this' into Derived type and call "Traverse##NAME" function with 'VAR' and 'QUEUE'.
If not, convert '*this' into Derived type and call "Traverse##NAME" function with 'VAR'.
1 // Traverse the given statement. If the most-derived traverse function takes a 2 // data recursion queue, pass it on; otherwise, discard it. Note that the 3 // first branch of this conditional must compile whether or not the derived 4 // class can take a queue, so if we're taking the second arm, make the first 5 // arm call our function rather than the derived class version. 6 #define TRAVERSE_STMT_BASE(NAME, CLASS, VAR, QUEUE) \ 7 (::clang::detail::has_same_member_pointer_type< \ 8 decltype(&RecursiveASTVisitor::Traverse##NAME), \ 9 decltype(&Derived::Traverse##NAME)>::value \ 10 ? static_cast<std::conditional_t< \ 11 ::clang::detail::has_same_member_pointer_type< \ 12 decltype(&RecursiveASTVisitor::Traverse##NAME), \ 13 decltype(&Derived::Traverse##NAME)>::value, \ 14 Derived &, RecursiveASTVisitor &>>(*this) \ 15 .Traverse##NAME(static_cast<CLASS *>(VAR), QUEUE) \ 16 : getDerived().Traverse##NAME(static_cast<CLASS *>(VAR)))
2.2 STMT(CLASS, PARENT) and StmtNodes.inc
Using the StmtNodes.inc file and STMT() macro define the Traverse##CLASS() function.
2.2.1 CLASS
The 'CLASS' would be any statement: BreakStmt, CXXCatchStmt, CXXForRangeStmt, CXXTryStmt,
CapturedStmt, CompoundStmt, ContinueStmt, CoroutineBodyStmt, DeclStmt, DoStmt, ForStmt,
GotoStmt, IfStmt, IndirectGotoStmt, MSDependentExistsStmt, NullStmt, ObjCAtCatchStmt, ObjCAtFinallyStmt,
ObjCAtSynchronizedStmt, ObjCAtThrowStmt, ObjCAtTryStmt, ObjCAutoreleasePoolStmt,
ObjCForCollectionStmt, ReturnStmt, CaseStmt, DefaultStmt, AttributedStmt, LabelStmt, WhileStmt, ... ...
1 // Declare Traverse*() for all concrete Stmt classes. 2 #define ABSTRACT_STMT(STMT) 3 #define STMT(CLASS, PARENT) \ 4 bool Traverse##CLASS(CLASS *S, DataRecursionQueue *Queue = nullptr); 5 #include "clang/AST/StmtNodes.inc"
2.3 Define the WalkUpFrom##Class() and Visit##CLASS() functions
By defining the WalkUpFrom##CLASS() and Visit##CLASS() functions to provide the defualt implementations for
RecursiveASTVisitor class. The values of 'CLASS' are the same as "2.2.1 CLASS".
1 // Define WalkUpFrom*() and empty Visit*() for all Stmt classes. 2 bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); } 3 bool VisitStmt(Stmt *S) { return true; } 4 #define STMT(CLASS, PARENT) \ 5 bool WalkUpFrom##CLASS(CLASS *S) { \ 6 TRY_TO(WalkUpFrom##PARENT(S)); \ 7 TRY_TO(Visit##CLASS(S)); \ 8 return true; \ 9 } \ 10 bool Visit##CLASS(CLASS *S) { return true; } 11 #include "clang/AST/StmtNodes.inc"
3. Traversal
3.1 Type Traversal
3.2 TypeLoc Traversal
3.3 Decl Traversal
3.4 Stmt Traversal
4. Preprocessing this file
The file contains a lot of macros, we will preprocess this file to get the preprocessed file.
// LLVM_PROJECT_PATH is the root path of llvm project.
//
// Using `export LLVM_PROJECT_PATH = ` to declare this env.
clang --trace-includes -D__cplusplus=201402L
-I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/v1/
-I${LLVM_PROJECT_PATH}/clang/include/
-I${LLVM_PROJECT_PATH}/.build_RelWithDebInfo/tools/clang/include/
-I${LLVM_PROJECT_PATH}/.build_RelWithDebInfo/include/
-I${LLVM_PROJECT_PATH}/llvm/include/
-E RecursiveASTVisitor.h -o tmp.ii
4.1 Delete the Blank Line
- Open your code in Visual Studio Code.
- From Edit Menu, select Replace or use a short cut key ( command + Option + F on Mac or Ctrl + H on Windows)
- In the find box type ^(\s)*$\n.
- Leave the replace box empty.
- Make sure the 'Use Regular Expression' is selected.
- Select the 'Replace All' button.
4.2 Delete the Linemarker
The linemarker line is like the following:
# 163 "/LLVM/llvm-project/.build_RelWithDebInfo/tools/clang/include/clang/AST/DeclNodes.inc"
To delete the linemarker, as the "4.1 Delete the Blank Line" section, we replace the regex in step 3 with "^#(.)+$\n".
4.3 Delete the header files
Delete the codes from including header files.
The result of preprocessing RecursiveASTVisitor.h using clang -E is at https://gist.github.com/vitonzhangtt/8a1434c22d956bad8cd52259fc7044b0.
Reference
1. clang::RecursiveASTVisitor< Derived > Class Template Reference
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each node.
https://clang.llvm.org/doxygen/classclang_1_1RecursiveASTVisitor.html
标签:OCLint.6,Traverse,clangAST,##,clang,RecursiveASTVisitor,CLASS,inc 来源: https://www.cnblogs.com/cwgk/p/16454754.html