//===--- MinimalAction.cpp - Implement the MinimalAction class ------------===// // // The LLVM Compiler Infrastructure // // This file was developed by Chris Lattner and is distributed under // the University of Illinois Open Source License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the MinimalAction interface. // //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" #include "clang/Parse/DeclSpec.h" #include "clang/Parse/Scope.h" using namespace clang; /// TypeNameInfo - A link exists here for each scope that an identifier is /// defined. struct TypeNameInfo { TypeNameInfo *Prev; bool isTypeName; TypeNameInfo(bool istypename, TypeNameInfo *prev) { isTypeName = istypename; Prev = prev; } }; void MinimalAction:: ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { TUScope = S; IdentifierInfo *II; TypeNameInfo *TI; // recognize the ObjC built-in type identifiers. II = &Idents.get("id"); TI = new TypeNameInfo(1, II->getFETokenInfo()); II->setFETokenInfo(TI); II = &Idents.get("SEL"); TI = new TypeNameInfo(1, II->getFETokenInfo()); II->setFETokenInfo(TI); II = &Idents.get("Class"); TI = new TypeNameInfo(1, II->getFETokenInfo()); II->setFETokenInfo(TI); II = &Idents.get("Protocol"); TI = new TypeNameInfo(1, II->getFETokenInfo()); II->setFETokenInfo(TI); } /// isTypeName - This looks at the IdentifierInfo::FETokenInfo field to /// determine whether the name is a type name (objc class name or typedef) or /// not in this scope. Action::DeclTy * MinimalAction::isTypeName(const IdentifierInfo &II, Scope *S) const { if (TypeNameInfo *TI = II.getFETokenInfo()) if (TI->isTypeName) return TI; return 0; } /// ActOnDeclarator - If this is a typedef declarator, we modify the /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is /// popped. Action::DeclTy * MinimalAction::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup) { IdentifierInfo *II = D.getIdentifier(); // If there is no identifier associated with this declarator, bail out. if (II == 0) return 0; TypeNameInfo *weCurrentlyHaveTypeInfo = II->getFETokenInfo(); bool isTypeName = D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef; // this check avoids creating TypeNameInfo objects for the common case. // It does need to handle the uncommon case of shadowing a typedef name with a // non-typedef name. e.g. { typedef int a; a xx; { int a; } } if (weCurrentlyHaveTypeInfo || isTypeName) { TypeNameInfo *TI = new TypeNameInfo(isTypeName, weCurrentlyHaveTypeInfo); II->setFETokenInfo(TI); // Remember that this needs to be removed when the scope is popped. S->AddDecl(II); } return 0; } Action::DeclTy * MinimalAction::ActOnStartClassInterface(SourceLocation AtInterafceLoc, IdentifierInfo *ClassName, SourceLocation ClassLoc, IdentifierInfo *SuperName, SourceLocation SuperLoc, IdentifierInfo **ProtocolNames, unsigned NumProtocols, SourceLocation EndProtoLoc, AttributeList *AttrList) { TypeNameInfo *TI = new TypeNameInfo(1, ClassName->getFETokenInfo()); ClassName->setFETokenInfo(TI); return 0; } /// ActOnForwardClassDeclaration - /// Scope will always be top level file scope. Action::DeclTy * MinimalAction::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, IdentifierInfo **IdentList, unsigned NumElts) { for (unsigned i = 0; i != NumElts; ++i) { TypeNameInfo *TI = new TypeNameInfo(1, IdentList[i]->getFETokenInfo()); IdentList[i]->setFETokenInfo(TI); // Remember that this needs to be removed when the scope is popped. TUScope->AddDecl(IdentList[i]); } return 0; } /// ActOnPopScope - When a scope is popped, if any typedefs are now out-of-scope, /// they are removed from the IdentifierInfo::FETokenInfo field. void MinimalAction::ActOnPopScope(SourceLocation Loc, Scope *S) { for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end(); I != E; ++I) { IdentifierInfo &II = *static_cast(*I); TypeNameInfo *TI = II.getFETokenInfo(); assert(TI && "This decl didn't get pushed??"); if (TI) { TypeNameInfo *Next = TI->Prev; delete TI; II.setFETokenInfo(Next); } } }