clang  6.0.0svn
LexicallyOrderedRecursiveASTVisitor.h
Go to the documentation of this file.
1 //===--- LexicallyOrderedRecursiveASTVisitor.h - ----------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the LexicallyOrderedRecursiveASTVisitor interface, which
11 // recursively traverses the entire AST in a lexical order.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_AST_LEXICALLY_ORDERED_RECURSIVEASTVISITOR_H
16 #define LLVM_CLANG_AST_LEXICALLY_ORDERED_RECURSIVEASTVISITOR_H
17 
19 #include "clang/Basic/LLVM.h"
21 #include "llvm/Support/SaveAndRestore.h"
22 
23 namespace clang {
24 
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>
61  : public RecursiveASTVisitor<Derived> {
63 
64 public:
66 
68  // Objective-C @implementation declarations should not trigger early exit
69  // until the additional decls are traversed as their children are not
70  // lexically ordered.
71  bool Result = BaseType::TraverseObjCImplementationDecl(D);
72  return TraverseAdditionalLexicallyNestedDeclarations() ? Result : false;
73  }
74 
76  bool Result = BaseType::TraverseObjCCategoryImplDecl(D);
77  return TraverseAdditionalLexicallyNestedDeclarations() ? Result : false;
78  }
79 
81  if (!DC)
82  return true;
83 
84  for (auto I = DC->decls_begin(), E = DC->decls_end(); I != E;) {
85  Decl *Child = *I;
87  ++I;
88  continue;
89  }
90  if (!isa<ObjCImplementationDecl>(Child) &&
91  !isa<ObjCCategoryImplDecl>(Child)) {
92  if (!BaseType::getDerived().TraverseDecl(Child))
93  return false;
94  ++I;
95  continue;
96  }
97  // Gather declarations that follow the Objective-C implementation
98  // declarations but are lexically contained in the implementation.
99  LexicallyNestedDeclarations.clear();
100  for (++I; I != E; ++I) {
101  Decl *Sibling = *I;
102  if (!SM.isBeforeInTranslationUnit(Sibling->getLocStart(),
103  Child->getLocEnd()))
104  break;
106  LexicallyNestedDeclarations.push_back(Sibling);
107  }
108  if (!BaseType::getDerived().TraverseDecl(Child))
109  return false;
110  }
111  return true;
112  }
113 
115 
117  SmallVector<Stmt *, 8> Children(CE->children());
118  bool Swap;
119  // Switch the operator and the first operand for all infix and postfix
120  // operations.
121  switch (CE->getOperator()) {
122  case OO_Arrow:
123  case OO_Call:
124  case OO_Subscript:
125  Swap = true;
126  break;
127  case OO_PlusPlus:
128  case OO_MinusMinus:
129  // These are postfix unless there is exactly one argument.
130  Swap = Children.size() != 2;
131  break;
132  default:
133  Swap = CE->isInfixBinaryOp();
134  break;
135  }
136  if (Swap && Children.size() > 1)
137  std::swap(Children[0], Children[1]);
138  return Children;
139  }
140 
141 private:
142  bool TraverseAdditionalLexicallyNestedDeclarations() {
143  // FIXME: Ideally the gathered declarations and the declarations in the
144  // @implementation should be mixed and sorted to get a true lexical order,
145  // but right now we only care about getting the correct lexical parent, so
146  // we can traverse the gathered nested declarations after the declarations
147  // in the decl context.
149  "post-order traversal is not supported for lexically ordered "
150  "recursive ast visitor");
151  for (Decl *D : LexicallyNestedDeclarations) {
153  return false;
154  }
155  return true;
156  }
157 
158  const SourceManager &SM;
159  llvm::SmallVector<Decl *, 8> LexicallyNestedDeclarations;
160 };
161 
162 } // end namespace clang
163 
164 #endif // LLVM_CLANG_AST_LEXICALLY_ORDERED_RECURSIVEASTVISITOR_H
A call to an overloaded operator written using operator syntax.
Definition: ExprCXX.h:78
Stmt - This represents one statement.
Definition: Stmt.h:66
Defines the SourceManager interface.
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
bool shouldTraversePostOrder() const
Return whether this visitor should traverse post-order.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
llvm::iterator_range< child_iterator > child_range
Definition: Stmt.h:443
SourceLocation getLocEnd() const LLVM_READONLY
Definition: DeclBase.h:412
Derived & getDerived()
Return a reference to the derived class.
SmallVector< Stmt *, 8 > getStmtChildren(CXXOperatorCallExpr *CE)
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument&#39;s dynamic ty...
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
child_range children()
Definition: Expr.h:2363
child_range children()
Definition: Stmt.cpp:226
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
bool canIgnoreChildDeclWhileTraversingDeclContext(const Decl *Child)
The result type of a method or function.
SourceLocation getLocStart() const LLVM_READONLY
Definition: DeclBase.h:408
decl_iterator decls_begin() const
Definition: DeclBase.cpp:1320
bool isInfixBinaryOp() const
Is this written as an infix binary operator?
Definition: ExprCXX.cpp:46
A RecursiveASTVisitor subclass that guarantees that AST traversal is performed in a lexical order (i...
Dataflow Directional Tag Classes.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1252
OverloadedOperatorKind getOperator() const
Returns the kind of overloaded operator that this expression refers to.
Definition: ExprCXX.h:106
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Definition: DeclObjC.h:2571
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration...
Definition: DeclObjC.h:2518
This class handles loading and caching of source files into memory.
decl_iterator decls_end() const
Definition: DeclBase.h:1578