LexicallyOrderedRecursiveASTVisitor.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- LexicallyOrderedRecursiveASTVisitor.h - ----------------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file defines the LexicallyOrderedRecursiveASTVisitor interface, which
  15. // recursively traverses the entire AST in a lexical order.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_CLANG_AST_LEXICALLYORDEREDRECURSIVEASTVISITOR_H
  19. #define LLVM_CLANG_AST_LEXICALLYORDEREDRECURSIVEASTVISITOR_H
  20. #include "clang/AST/RecursiveASTVisitor.h"
  21. #include "clang/Basic/LLVM.h"
  22. #include "clang/Basic/SourceManager.h"
  23. #include "llvm/Support/SaveAndRestore.h"
  24. namespace clang {
  25. /// A RecursiveASTVisitor subclass that guarantees that AST traversal is
  26. /// performed in a lexical order (i.e. the order in which declarations are
  27. /// written in the source).
  28. ///
  29. /// RecursiveASTVisitor doesn't guarantee lexical ordering because there are
  30. /// some declarations, like Objective-C @implementation declarations
  31. /// that might be represented in the AST differently to how they were written
  32. /// in the source.
  33. /// In particular, Objective-C @implementation declarations may contain
  34. /// non-Objective-C declarations, like functions:
  35. ///
  36. /// @implementation MyClass
  37. ///
  38. /// - (void) method { }
  39. /// void normalFunction() { }
  40. ///
  41. /// @end
  42. ///
  43. /// Clang's AST stores these declarations outside of the @implementation
  44. /// declaration, so the example above would be represented using the following
  45. /// AST:
  46. /// |-ObjCImplementationDecl ... MyClass
  47. /// | `-ObjCMethodDecl ... method
  48. /// | ...
  49. /// `-FunctionDecl ... normalFunction
  50. /// ...
  51. ///
  52. /// This class ensures that these declarations are traversed before the
  53. /// corresponding TraverseDecl for the @implementation returns. This ensures
  54. /// that the lexical parent relationship between these declarations and the
  55. /// @implementation is preserved while traversing the AST. Note that the
  56. /// current implementation doesn't mix these declarations with the declarations
  57. /// contained in the @implementation, so the traversal of all of the
  58. /// declarations in the @implementation still doesn't follow the lexical order.
  59. template <typename Derived>
  60. class LexicallyOrderedRecursiveASTVisitor
  61. : public RecursiveASTVisitor<Derived> {
  62. using BaseType = RecursiveASTVisitor<Derived>;
  63. public:
  64. LexicallyOrderedRecursiveASTVisitor(const SourceManager &SM) : SM(SM) {}
  65. bool TraverseObjCImplementationDecl(ObjCImplementationDecl *D) {
  66. // Objective-C @implementation declarations should not trigger early exit
  67. // until the additional decls are traversed as their children are not
  68. // lexically ordered.
  69. bool Result = BaseType::TraverseObjCImplementationDecl(D);
  70. return TraverseAdditionalLexicallyNestedDeclarations() ? Result : false;
  71. }
  72. bool TraverseObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
  73. bool Result = BaseType::TraverseObjCCategoryImplDecl(D);
  74. return TraverseAdditionalLexicallyNestedDeclarations() ? Result : false;
  75. }
  76. bool TraverseDeclContextHelper(DeclContext *DC) {
  77. if (!DC)
  78. return true;
  79. for (auto I = DC->decls_begin(), E = DC->decls_end(); I != E;) {
  80. Decl *Child = *I;
  81. if (BaseType::canIgnoreChildDeclWhileTraversingDeclContext(Child)) {
  82. ++I;
  83. continue;
  84. }
  85. if (!isa<ObjCImplementationDecl>(Child) &&
  86. !isa<ObjCCategoryImplDecl>(Child)) {
  87. if (!BaseType::getDerived().TraverseDecl(Child))
  88. return false;
  89. ++I;
  90. continue;
  91. }
  92. // Gather declarations that follow the Objective-C implementation
  93. // declarations but are lexically contained in the implementation.
  94. LexicallyNestedDeclarations.clear();
  95. for (++I; I != E; ++I) {
  96. Decl *Sibling = *I;
  97. if (!SM.isBeforeInTranslationUnit(Sibling->getBeginLoc(),
  98. Child->getEndLoc()))
  99. break;
  100. if (!BaseType::canIgnoreChildDeclWhileTraversingDeclContext(Sibling))
  101. LexicallyNestedDeclarations.push_back(Sibling);
  102. }
  103. if (!BaseType::getDerived().TraverseDecl(Child))
  104. return false;
  105. }
  106. return true;
  107. }
  108. Stmt::child_range getStmtChildren(Stmt *S) { return S->children(); }
  109. SmallVector<Stmt *, 8> getStmtChildren(CXXOperatorCallExpr *CE) {
  110. SmallVector<Stmt *, 8> Children(CE->children());
  111. bool Swap;
  112. // Switch the operator and the first operand for all infix and postfix
  113. // operations.
  114. switch (CE->getOperator()) {
  115. case OO_Arrow:
  116. case OO_Call:
  117. case OO_Subscript:
  118. Swap = true;
  119. break;
  120. case OO_PlusPlus:
  121. case OO_MinusMinus:
  122. // These are postfix unless there is exactly one argument.
  123. Swap = Children.size() != 2;
  124. break;
  125. default:
  126. Swap = CE->isInfixBinaryOp();
  127. break;
  128. }
  129. if (Swap && Children.size() > 1)
  130. std::swap(Children[0], Children[1]);
  131. return Children;
  132. }
  133. private:
  134. bool TraverseAdditionalLexicallyNestedDeclarations() {
  135. // FIXME: Ideally the gathered declarations and the declarations in the
  136. // @implementation should be mixed and sorted to get a true lexical order,
  137. // but right now we only care about getting the correct lexical parent, so
  138. // we can traverse the gathered nested declarations after the declarations
  139. // in the decl context.
  140. assert(!BaseType::getDerived().shouldTraversePostOrder() &&
  141. "post-order traversal is not supported for lexically ordered "
  142. "recursive ast visitor");
  143. for (Decl *D : LexicallyNestedDeclarations) {
  144. if (!BaseType::getDerived().TraverseDecl(D))
  145. return false;
  146. }
  147. return true;
  148. }
  149. const SourceManager &SM;
  150. llvm::SmallVector<Decl *, 8> LexicallyNestedDeclarations;
  151. };
  152. } // end namespace clang
  153. #endif // LLVM_CLANG_AST_LEXICALLYORDEREDRECURSIVEASTVISITOR_H
  154. #ifdef __GNUC__
  155. #pragma GCC diagnostic pop
  156. #endif