Inferno
0.2
|
00001 #ifndef IDENTIFIER_TRACKER 00002 #define IDENTIFIER_TRACKER 00003 00004 #include "clang/Parse/Action.h" 00005 #include "rc_hold.hpp" 00006 //#include "tree/cpptree.hpp" 00007 00008 // Semantic. 00009 class DeclSpec; 00010 class ObjCDeclSpec; 00011 class AttributeList; 00012 struct FieldDeclarator; 00013 // Parse. 00014 class Selector; 00015 // Lex. 00016 class Token; 00017 00018 00019 class IdentifierTracker 00020 { 00021 // The scope tree is made up of these. Each one represents an object, user type 00022 // or compound statement. II is null if no name; parent is null if in global (root) 00023 // scope. A TNode t should only have other TNodes pointing to it if it is a scope. 00024 // Example: 00025 // class C { void F() { struct S { int X; }; } }; 00026 // has parent pointers as: X -> S -> F -> C -> (NULL) 00027 // F has no identifier info, since it's name is not relevent to scopes (anonymous scope) 00028 // All should have valid node pointers (TODO fill in for compound statements) 00029 // C, F, S should have clang scope cs filled in. 00030 // TODO use Scope and Identifier instead of Node everywhere 00031 struct TNode 00032 { 00033 shared_ptr<TNode> parent; 00034 shared_ptr<Node> node; 00035 clang::Scope *cs; // Note: this is the *corresponding* scope, not the containing scope. 00036 // Eg given struct A { int B; }; then A->cs is the struct scope and B->cs is NULL 00037 clang::IdentifierInfo *II; 00038 }; 00039 00040 // Our best effort to determine the current scope 00041 stack< shared_ptr<TNode> > scope_stack; 00042 00043 // Every TNode we ever create goes in this list, and is never deleted. 00044 deque< shared_ptr<TNode> > tnodes; 00045 00046 // Parser can "warn" us that the next clang::Scope we see will correspond to 00047 // the supplied node (a Record node in fact). 00048 stack< shared_ptr<Node> > next_record; 00049 00050 // Enter a new scope - clang doesn't tell us when to do this, so we deduce from 00051 // calls to Add. 00052 shared_ptr<TNode> Find( shared_ptr<Node> node ); 00053 void PushScope( clang::Scope *S, shared_ptr<TNode> ts ); 00054 void NewScope( clang::Scope *S ); 00055 string ToString( shared_ptr<TNode> ts ); 00056 bool IsIdentical( shared_ptr<TNode> current, shared_ptr<TNode> ident ); 00057 int IsMatch( const clang::IdentifierInfo *II, shared_ptr<TNode> current, shared_ptr<TNode> ident, bool recurse ); 00058 00059 shared_ptr<Node> global; 00060 00061 public: 00062 IdentifierTracker( shared_ptr<Node> g ); 00063 00064 /// Associate supplied node with supplied identifier and scope. Will remain 00065 /// until the scope is popped. S must be current scope due to implementation. 00066 void Add( clang::IdentifierInfo *II, shared_ptr<Node> node, clang::Scope *S ); 00067 00068 /// Push a scope based on supplied Inferno tree Node 00069 void PushScope( clang::Scope *S, shared_ptr<Node> n ); 00070 00071 /// Let identifier tracker know we saw a scope. We must do this before calling other functions so we 00072 /// catch all the scope changes that are not communicated to us any other way. 00073 void SeenScope( clang::Scope *S ); 00074 00075 /// ActOnPopScope - When a scope is popped, if any typedefs are now 00076 /// out-of-scope, they are removed from the clang::IdentifierInfo::FETokenInfo field. 00077 virtual void PopScope(clang::Scope *S); 00078 00079 // Extract the Declaration for the clang::Identifier. Where the identifier is differently declared 00080 // in nested scopes, we get the one that applies currently (which is the innermost one) 00081 // Optionally: Can specify a C++ scope, which must match exactly (NULL, falls back to current scope) 00082 // Can ask for the corresponding decl node for the found node 00083 // Can turn off recursion so only a direct match allowed 00084 shared_ptr<Node> Get( const clang::IdentifierInfo *II, shared_ptr<Node> iscope = shared_ptr<Node>(), bool recurse = true ); 00085 00086 // Version that just results NULL if identifier has not been added yet 00087 shared_ptr<Node> TryGet( const clang::IdentifierInfo *II, shared_ptr<Node> iscope = shared_ptr<Node>(), bool recurse = true ); 00088 00089 // Indicate that the next Add() call will have the supplied node as parent. 00090 // Omit to clear (eg after the struct) 00091 void SetNextRecord( shared_ptr<Node> n = shared_ptr<Node>() ) 00092 { 00093 TRACE("next record is %p\n", n.get() ); 00094 00095 if( n ) 00096 next_record.push(n); 00097 else 00098 { 00099 ASSERT( !next_record.empty() ); 00100 next_record.pop(); 00101 } 00102 } 00103 00104 shared_ptr<Node> GetCurrent() 00105 { 00106 return scope_stack.top()->node; 00107 } 00108 }; 00109 00110 #endif