diff options
Diffstat (limited to 'tools/libclang/CIndex.cpp')
-rw-r--r-- | tools/libclang/CIndex.cpp | 1403 |
1 files changed, 838 insertions, 565 deletions
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 50d56fc..46ba3d5 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -51,8 +51,9 @@ using namespace clang; using namespace clang::cxcursor; using namespace clang::cxstring; +using namespace clang::cxtu; -static CXTranslationUnit MakeCXTranslationUnit(ASTUnit *TU) { +CXTranslationUnit cxtu::MakeCXTranslationUnit(ASTUnit *TU) { if (!TU) return 0; CXTranslationUnit D = new CXTranslationUnitImpl(); @@ -117,10 +118,10 @@ CXSourceRange cxloc::translateSourceRange(const SourceManager &SM, // location accordingly. SourceLocation EndLoc = R.getEnd(); if (EndLoc.isValid() && EndLoc.isMacroID()) - EndLoc = SM.getInstantiationRange(EndLoc).second; + EndLoc = SM.getExpansionRange(EndLoc).second; if (R.isTokenRange() && !EndLoc.isInvalid() && EndLoc.isFileID()) { unsigned Length = Lexer::MeasureTokenLength(EndLoc, SM, LangOpts); - EndLoc = EndLoc.getFileLocWithOffset(Length); + EndLoc = EndLoc.getLocWithOffset(Length); } CXSourceRange Result = { { (void *)&SM, (void *)&LangOpts }, @@ -141,7 +142,6 @@ public: TypeLocVisitKind, OverloadExprPartsKind, DeclRefExprPartsKind, LabelRefVisitKind, ExplicitTemplateArgsVisitKind, - NestedNameSpecifierVisitKind, NestedNameSpecifierLocVisitKind, DeclarationNameInfoVisitKind, MemberRefVisitKind, SizeOfPackExprPartsKind }; @@ -161,7 +161,7 @@ public: static bool classof(VisitorJob *VJ) { return true; } }; -typedef llvm::SmallVector<VisitorJob, 10> VisitorWorkList; +typedef SmallVector<VisitorJob, 10> VisitorWorkList; // Cursor visitor. class CursorVisitor : public DeclVisitor<CursorVisitor, bool>, @@ -184,11 +184,6 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>, /// \brief The opaque client data, to be passed along to the visitor. CXClientData ClientData; - // MaxPCHLevel - the maximum PCH level of declarations that we will pass on - // to the visitor. Declarations with a PCH level greater than this value will - // be suppressed. - unsigned MaxPCHLevel; - /// \brief Whether we should visit the preprocessing record entries last, /// after visiting other declarations. bool VisitPreprocessorLast; @@ -203,8 +198,8 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>, DeclContext::decl_iterator DE_current; // Cache of pre-allocated worklists for data-recursion walk of Stmts. - llvm::SmallVector<VisitorWorkList*, 5> WorkListFreeList; - llvm::SmallVector<VisitorWorkList*, 5> WorkListCache; + SmallVector<VisitorWorkList*, 5> WorkListFreeList; + SmallVector<VisitorWorkList*, 5> WorkListCache; using DeclVisitor<CursorVisitor, bool>::Visit; using TypeLocVisitor<CursorVisitor, bool>::Visit; @@ -239,12 +234,11 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>, public: CursorVisitor(CXTranslationUnit TU, CXCursorVisitor Visitor, CXClientData ClientData, - unsigned MaxPCHLevel, bool VisitPreprocessorLast, SourceRange RegionOfInterest = SourceRange()) : TU(TU), AU(static_cast<ASTUnit*>(TU->TUData)), Visitor(Visitor), ClientData(ClientData), - MaxPCHLevel(MaxPCHLevel), VisitPreprocessorLast(VisitPreprocessorLast), + VisitPreprocessorLast(VisitPreprocessorLast), RegionOfInterest(RegionOfInterest), DI_current(0) { Parent.kind = CXCursor_NoDeclFound; @@ -256,7 +250,7 @@ public: ~CursorVisitor() { // Free the pre-allocated worklists for data-recursion. - for (llvm::SmallVectorImpl<VisitorWorkList*>::iterator + for (SmallVectorImpl<VisitorWorkList*>::iterator I = WorkListCache.begin(), E = WorkListCache.end(); I != E; ++I) { delete *I; } @@ -267,8 +261,10 @@ public: bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false); - std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator> - getPreprocessedEntities(); + bool visitPreprocessedEntitiesInRegion(); + + template<typename InputIterator> + bool visitPreprocessedEntities(InputIterator First, InputIterator Last); bool VisitChildren(CXCursor Parent); @@ -327,35 +323,15 @@ public: bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL); // Type visitors - bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL); - bool VisitBuiltinTypeLoc(BuiltinTypeLoc TL); - bool VisitTypedefTypeLoc(TypedefTypeLoc TL); - bool VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL); +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc); +#include "clang/AST/TypeLocNodes.def" + bool VisitTagTypeLoc(TagTypeLoc TL); - bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL); - bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL); - bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL); - bool VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL); - bool VisitParenTypeLoc(ParenTypeLoc TL); - bool VisitPointerTypeLoc(PointerTypeLoc TL); - bool VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL); - bool VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL); - bool VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL); - bool VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL); - bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false); bool VisitArrayTypeLoc(ArrayTypeLoc TL); - bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL); - // FIXME: Implement visitors here when the unimplemented TypeLocs get - // implemented - bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL); - bool VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL); - bool VisitTypeOfTypeLoc(TypeOfTypeLoc TL); - bool VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL); - bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL); - bool VisitDependentTemplateSpecializationTypeLoc( - DependentTemplateSpecializationTypeLoc TL); - bool VisitElaboratedTypeLoc(ElaboratedTypeLoc TL); - + bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false); + // Data-recursive visitor functions. bool IsInRegionOfInterest(CXCursor C); bool RunVisitorWorkList(VisitorWorkList &WL); @@ -390,10 +366,9 @@ bool CursorVisitor::Visit(CXCursor Cursor, bool CheckedRegionOfInterest) { if (clang_isDeclaration(Cursor.kind)) { Decl *D = getCursorDecl(Cursor); assert(D && "Invalid declaration cursor"); - if (D->getPCHLevel() > MaxPCHLevel) - return false; - - if (D->isImplicit()) + // Ignore implicit declarations, unless it's an objc method because + // currently we should report implicit methods for properties when indexing. + if (D->isImplicit() && !isa<ObjCMethodDecl>(D)) return false; } @@ -419,65 +394,53 @@ bool CursorVisitor::Visit(CXCursor Cursor, bool CheckedRegionOfInterest) { return false; } -std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator> -CursorVisitor::getPreprocessedEntities() { +bool CursorVisitor::visitPreprocessedEntitiesInRegion() { PreprocessingRecord &PPRec = *AU->getPreprocessor().getPreprocessingRecord(); + if (RegionOfInterest.isValid()) { + SourceRange MappedRange = AU->mapRangeToPreamble(RegionOfInterest); + std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator> + Entities = PPRec.getPreprocessedEntitiesInRange(MappedRange); + return visitPreprocessedEntities(Entities.first, Entities.second); + } + bool OnlyLocalDecls = !AU->isMainFileAST() && AU->getOnlyLocalDecls(); - if (OnlyLocalDecls && RegionOfInterest.isValid()) { - // If we would only look at local declarations but we have a region of - // interest, check whether that region of interest is in the main file. - // If not, we should traverse all declarations. - // FIXME: My kingdom for a proper binary search approach to finding - // cursors! - std::pair<FileID, unsigned> Location - = AU->getSourceManager().getDecomposedInstantiationLoc( - RegionOfInterest.getBegin()); - if (Location.first != AU->getSourceManager().getMainFileID()) - OnlyLocalDecls = false; - } - - PreprocessingRecord::iterator StartEntity, EndEntity; - if (OnlyLocalDecls) { - StartEntity = AU->pp_entity_begin(); - EndEntity = AU->pp_entity_end(); - } else { - StartEntity = PPRec.begin(); - EndEntity = PPRec.end(); - } - - // There is no region of interest; we have to walk everything. - if (RegionOfInterest.isInvalid()) - return std::make_pair(StartEntity, EndEntity); - - // Find the file in which the region of interest lands. - SourceManager &SM = AU->getSourceManager(); - std::pair<FileID, unsigned> Begin - = SM.getDecomposedInstantiationLoc(RegionOfInterest.getBegin()); - std::pair<FileID, unsigned> End - = SM.getDecomposedInstantiationLoc(RegionOfInterest.getEnd()); - - // The region of interest spans files; we have to walk everything. - if (Begin.first != End.first) - return std::make_pair(StartEntity, EndEntity); + if (OnlyLocalDecls) + return visitPreprocessedEntities(PPRec.local_begin(), PPRec.local_end()); + + return visitPreprocessedEntities(PPRec.begin(), PPRec.end()); +} + +template<typename InputIterator> +bool CursorVisitor::visitPreprocessedEntities(InputIterator First, + InputIterator Last) { + for (; First != Last; ++First) { + if (MacroExpansion *ME = dyn_cast<MacroExpansion>(*First)) { + if (Visit(MakeMacroExpansionCursor(ME, TU))) + return true; + + continue; + } + + if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*First)) { + if (Visit(MakeMacroDefinitionCursor(MD, TU))) + return true; + + continue; + } - ASTUnit::PreprocessedEntitiesByFileMap &ByFileMap - = AU->getPreprocessedEntitiesByFile(); - if (ByFileMap.empty()) { - // Build the mapping from files to sets of preprocessed entities. - for (PreprocessingRecord::iterator E = StartEntity; E != EndEntity; ++E) { - std::pair<FileID, unsigned> P - = SM.getDecomposedInstantiationLoc((*E)->getSourceRange().getBegin()); + if (InclusionDirective *ID = dyn_cast<InclusionDirective>(*First)) { + if (Visit(MakeInclusionDirectiveCursor(ID, TU))) + return true; - ByFileMap[P.first].push_back(*E); + continue; } } - return std::make_pair(ByFileMap[Begin.first].begin(), - ByFileMap[Begin.first].end()); + return false; } /// \brief Visit the children of the given cursor. @@ -529,7 +492,7 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) { for (ASTUnit::top_level_iterator TL = CXXUnit->top_level_begin(), TLEnd = CXXUnit->top_level_end(); TL != TLEnd; ++TL) { - if (Visit(MakeCXCursor(*TL, tu), true)) + if (Visit(MakeCXCursor(*TL, tu, RegionOfInterest), true)) return true; } } else if (VisitDeclContext( @@ -539,33 +502,8 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) { } // Walk the preprocessing record. - if (CXXUnit->getPreprocessor().getPreprocessingRecord()) { - // FIXME: Once we have the ability to deserialize a preprocessing record, - // do so. - PreprocessingRecord::iterator E, EEnd; - for (llvm::tie(E, EEnd) = getPreprocessedEntities(); E != EEnd; ++E) { - if (MacroExpansion *ME = dyn_cast<MacroExpansion>(*E)) { - if (Visit(MakeMacroExpansionCursor(ME, tu))) - return true; - - continue; - } - - if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) { - if (Visit(MakeMacroDefinitionCursor(MD, tu))) - return true; - - continue; - } - - if (InclusionDirective *ID = dyn_cast<InclusionDirective>(*E)) { - if (Visit(MakeInclusionDirectiveCursor(ID, tu))) - return true; - - continue; - } - } - } + if (CXXUnit->getPreprocessor().getPreprocessingRecord()) + visitPreprocessedEntitiesInRegion(); } return false; @@ -578,7 +516,15 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) { } } } - + + if (Cursor.kind == CXCursor_IBOutletCollectionAttr) { + IBOutletCollectionAttr *A = + cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(Cursor)); + if (const ObjCInterfaceType *InterT = A->getInterface()->getAs<ObjCInterfaceType>()) + return Visit(cxcursor::MakeCursorObjCClassRef(InterT->getInterface(), + A->getInterfaceLoc(), TU)); + } + // Nothing to visit at the moment. return false; } @@ -589,7 +535,7 @@ bool CursorVisitor::VisitBlockDecl(BlockDecl *B) { return true; if (Stmt *Body = B->getBody()) - return Visit(MakeCXCursor(Body, StmtParent, TU)); + return Visit(MakeCXCursor(Body, StmtParent, TU, RegionOfInterest)); return false; } @@ -629,7 +575,7 @@ bool CursorVisitor::VisitDeclContext(DeclContext *DC) { Decl *D = *I; if (D->getLexicalDeclContext() != DC) continue; - CXCursor Cursor = MakeCXCursor(D, TU); + CXCursor Cursor = MakeCXCursor(D, TU, RegionOfInterest); const llvm::Optional<bool> &V = shouldVisitCursor(Cursor); if (!V.hasValue()) continue; @@ -727,7 +673,7 @@ bool CursorVisitor::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) { if (Expr *Init = D->getInitExpr()) - return Visit(MakeCXCursor(Init, StmtParent, TU)); + return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest)); return false; } @@ -794,7 +740,7 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) { if (ND->doesThisDeclarationHaveABody() && !ND->isLateTemplateParsed()) { if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(ND)) { // Find the initializers that were written in the source. - llvm::SmallVector<CXXCtorInitializer *, 4> WrittenInits; + SmallVector<CXXCtorInitializer *, 4> WrittenInits; for (CXXConstructorDecl::init_iterator I = Constructor->init_begin(), IEnd = Constructor->init_end(); I != IEnd; ++I) { @@ -822,12 +768,12 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) { // Visit the initializer value. if (Expr *Initializer = Init->getInit()) - if (Visit(MakeCXCursor(Initializer, ND, TU))) + if (Visit(MakeCXCursor(Initializer, ND, TU, RegionOfInterest))) return true; } } - if (Visit(MakeCXCursor(ND->getBody(), StmtParent, TU))) + if (Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest))) return true; } @@ -839,7 +785,7 @@ bool CursorVisitor::VisitFieldDecl(FieldDecl *D) { return true; if (Expr *BitWidth = D->getBitWidth()) - return Visit(MakeCXCursor(BitWidth, StmtParent, TU)); + return Visit(MakeCXCursor(BitWidth, StmtParent, TU, RegionOfInterest)); return false; } @@ -849,7 +795,7 @@ bool CursorVisitor::VisitVarDecl(VarDecl *D) { return true; if (Expr *Init = D->getInit()) - return Visit(MakeCXCursor(Init, StmtParent, TU)); + return Visit(MakeCXCursor(Init, StmtParent, TU, RegionOfInterest)); return false; } @@ -860,7 +806,7 @@ bool CursorVisitor::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) if (Expr *DefArg = D->getDefaultArgument()) - return Visit(MakeCXCursor(DefArg, StmtParent, TU)); + return Visit(MakeCXCursor(DefArg, StmtParent, TU, RegionOfInterest)); return false; } @@ -902,12 +848,12 @@ bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) { for (ObjCMethodDecl::param_iterator P = ND->param_begin(), PEnd = ND->param_end(); P != PEnd; ++P) { - if (Visit(MakeCXCursor(*P, TU))) + if (Visit(MakeCXCursor(*P, TU, RegionOfInterest))) return true; } if (ND->isThisDeclarationADefinition() && - Visit(MakeCXCursor(ND->getBody(), StmtParent, TU))) + Visit(MakeCXCursor(ND->getBody(), StmtParent, TU, RegionOfInterest))) return true; return false; @@ -938,7 +884,7 @@ bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) { // in the current DeclContext. If any fall within the // container's lexical region, stash them into a vector // for later processing. - llvm::SmallVector<Decl *, 24> DeclsInContainer; + SmallVector<Decl *, 24> DeclsInContainer; SourceLocation EndLoc = D->getSourceRange().getEnd(); SourceManager &SM = AU->getSourceManager(); if (EndLoc.isValid()) { @@ -979,9 +925,9 @@ bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) { ContainerDeclsSort(SM)); // Now visit the decls. - for (llvm::SmallVectorImpl<Decl*>::iterator I = DeclsInContainer.begin(), + for (SmallVectorImpl<Decl*>::iterator I = DeclsInContainer.begin(), E = DeclsInContainer.end(); I != E; ++I) { - CXCursor Cursor = MakeCXCursor(*I, TU); + CXCursor Cursor = MakeCXCursor(*I, TU, RegionOfInterest); const llvm::Optional<bool> &V = shouldVisitCursor(Cursor); if (!V.hasValue()) continue; @@ -1043,12 +989,12 @@ bool CursorVisitor::VisitObjCPropertyDecl(ObjCPropertyDecl *PD) { // the @interface. if (ObjCMethodDecl *MD = prevDecl->getGetterMethodDecl()) if (MD->isSynthesized() && MD->getLexicalDeclContext() == CDecl) - if (Visit(MakeCXCursor(MD, TU))) + if (Visit(MakeCXCursor(MD, TU, RegionOfInterest))) return true; if (ObjCMethodDecl *MD = prevDecl->getSetterMethodDecl()) if (MD->isSynthesized() && MD->getLexicalDeclContext() == CDecl) - if (Visit(MakeCXCursor(MD, TU))) + if (Visit(MakeCXCursor(MD, TU, RegionOfInterest))) return true; return false; @@ -1110,10 +1056,9 @@ bool CursorVisitor::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) { } bool CursorVisitor::VisitObjCClassDecl(ObjCClassDecl *D) { - for (ObjCClassDecl::iterator C = D->begin(), CEnd = D->end(); C != CEnd; ++C) - if (Visit(MakeCursorObjCClassRef(C->getInterface(), C->getLocation(), TU))) + if (Visit(MakeCursorObjCClassRef(D->getForwardInterfaceDecl(), + D->getForwardDecl()->getLocation(), TU))) return true; - return false; } @@ -1254,7 +1199,7 @@ bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS, bool CursorVisitor::VisitNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) { - llvm::SmallVector<NestedNameSpecifierLoc, 4> Qualifiers; + SmallVector<NestedNameSpecifierLoc, 4> Qualifiers; for (; Qualifier; Qualifier = Qualifier.getPrefix()) Qualifiers.push_back(Qualifier); @@ -1302,7 +1247,7 @@ bool CursorVisitor::VisitTemplateParameters( for (TemplateParameterList::const_iterator P = Params->begin(), PEnd = Params->end(); P != PEnd; ++P) { - if (Visit(MakeCXCursor(*P, TU))) + if (Visit(MakeCXCursor(*P, TU, RegionOfInterest))) return true; } @@ -1359,12 +1304,12 @@ bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) { case TemplateArgument::Declaration: if (Expr *E = TAL.getSourceDeclExpression()) - return Visit(MakeCXCursor(E, StmtParent, TU)); + return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest)); return false; case TemplateArgument::Expression: if (Expr *E = TAL.getSourceExpression()) - return Visit(MakeCXCursor(E, StmtParent, TU)); + return Visit(MakeCXCursor(E, StmtParent, TU, RegionOfInterest)); return false; case TemplateArgument::Template: @@ -1414,6 +1359,7 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { case BuiltinType::Long: case BuiltinType::LongLong: case BuiltinType::Int128: + case BuiltinType::Half: case BuiltinType::Float: case BuiltinType::Double: case BuiltinType::LongDouble: @@ -1455,6 +1401,9 @@ bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { } bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) { + if (TL.isDefinition()) + return Visit(MakeCXCursor(TL.getDecl(), TU, RegionOfInterest)); + return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU)); } @@ -1510,6 +1459,10 @@ bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { return Visit(TL.getPointeeLoc()); } +bool CursorVisitor::VisitAttributedTypeLoc(AttributedTypeLoc TL) { + return Visit(TL.getModifiedLoc()); +} + bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType) { if (!SkipResultType && Visit(TL.getResultLoc())) @@ -1517,7 +1470,7 @@ bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL, for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I) if (Decl *D = TL.getArg(I)) - if (Visit(MakeCXCursor(D, TU))) + if (Visit(MakeCXCursor(D, TU, RegionOfInterest))) return true; return false; @@ -1528,7 +1481,7 @@ bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) { return true; if (Expr *Size = TL.getSizeExpr()) - return Visit(MakeCXCursor(Size, StmtParent, TU)); + return Visit(MakeCXCursor(Size, StmtParent, TU, RegionOfInterest)); return false; } @@ -1599,13 +1552,49 @@ bool CursorVisitor::VisitPackExpansionTypeLoc(PackExpansionTypeLoc TL) { return Visit(TL.getPatternLoc()); } +bool CursorVisitor::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { + if (Expr *E = TL.getUnderlyingExpr()) + return Visit(MakeCXCursor(E, StmtParent, TU)); + + return false; +} + +bool CursorVisitor::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { + return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU)); +} + +bool CursorVisitor::VisitAtomicTypeLoc(AtomicTypeLoc TL) { + return Visit(TL.getValueLoc()); +} + +#define DEFAULT_TYPELOC_IMPL(CLASS, PARENT) \ +bool CursorVisitor::Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { \ + return Visit##PARENT##Loc(TL); \ +} + +DEFAULT_TYPELOC_IMPL(Complex, Type) +DEFAULT_TYPELOC_IMPL(ConstantArray, ArrayType) +DEFAULT_TYPELOC_IMPL(IncompleteArray, ArrayType) +DEFAULT_TYPELOC_IMPL(VariableArray, ArrayType) +DEFAULT_TYPELOC_IMPL(DependentSizedArray, ArrayType) +DEFAULT_TYPELOC_IMPL(DependentSizedExtVector, Type) +DEFAULT_TYPELOC_IMPL(Vector, Type) +DEFAULT_TYPELOC_IMPL(ExtVector, VectorType) +DEFAULT_TYPELOC_IMPL(FunctionProto, FunctionType) +DEFAULT_TYPELOC_IMPL(FunctionNoProto, FunctionType) +DEFAULT_TYPELOC_IMPL(Record, TagType) +DEFAULT_TYPELOC_IMPL(Enum, TagType) +DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParm, Type) +DEFAULT_TYPELOC_IMPL(SubstTemplateTypeParmPack, Type) +DEFAULT_TYPELOC_IMPL(Auto, Type) + bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) { // Visit the nested-name-specifier, if present. if (NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc()) if (VisitNestedNameSpecifierLoc(QualifierLoc)) return true; - if (D->isDefinition()) { + if (D->isCompleteDefinition()) { for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), E = D->bases_end(); I != E; ++I) { if (Visit(cxcursor::MakeCursorCXXBaseSpecifier(I, TU))) @@ -1642,7 +1631,7 @@ DEF_JOB(StmtVisit, Stmt, StmtVisitKind) DEF_JOB(MemberExprParts, MemberExpr, MemberExprPartsKind) DEF_JOB(DeclRefExprParts, DeclRefExpr, DeclRefExprPartsKind) DEF_JOB(OverloadExprParts, OverloadExpr, OverloadExprPartsKind) -DEF_JOB(ExplicitTemplateArgsVisit, ExplicitTemplateArgumentList, +DEF_JOB(ExplicitTemplateArgsVisit, ASTTemplateArgumentListInfo, ExplicitTemplateArgsVisitKind) DEF_JOB(SizeOfPackExprParts, SizeOfPackExpr, SizeOfPackExprPartsKind) #undef DEF_JOB @@ -1687,27 +1676,6 @@ public: SourceLocation getLoc() const { return SourceLocation::getFromPtrEncoding(data[1]); } }; -class NestedNameSpecifierVisit : public VisitorJob { -public: - NestedNameSpecifierVisit(NestedNameSpecifier *NS, SourceRange R, - CXCursor parent) - : VisitorJob(parent, VisitorJob::NestedNameSpecifierVisitKind, - NS, R.getBegin().getPtrEncoding(), - R.getEnd().getPtrEncoding()) {} - static bool classof(const VisitorJob *VJ) { - return VJ->getKind() == VisitorJob::NestedNameSpecifierVisitKind; - } - NestedNameSpecifier *get() const { - return static_cast<NestedNameSpecifier*>(data[0]); - } - SourceRange getSourceRange() const { - SourceLocation A = - SourceLocation::getFromRawEncoding((unsigned)(uintptr_t) data[1]); - SourceLocation B = - SourceLocation::getFromRawEncoding((unsigned)(uintptr_t) data[2]); - return SourceRange(A, B); - } -}; class NestedNameSpecifierLocVisit : public VisitorJob { public: @@ -1809,9 +1777,8 @@ public: private: void AddDeclarationNameInfo(Stmt *S); - void AddNestedNameSpecifier(NestedNameSpecifier *NS, SourceRange R); void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier); - void AddExplicitTemplateArgs(const ExplicitTemplateArgumentList *A); + void AddExplicitTemplateArgs(const ASTTemplateArgumentListInfo *A); void AddMemberRef(FieldDecl *D, SourceLocation L); void AddStmt(Stmt *S); void AddDecl(Decl *D, bool isFirst = true); @@ -1825,11 +1792,6 @@ void EnqueueVisitor::AddDeclarationNameInfo(Stmt *S) { // statement we are visiting. WL.push_back(DeclarationNameInfoVisit(S, Parent)); } -void EnqueueVisitor::AddNestedNameSpecifier(NestedNameSpecifier *N, - SourceRange R) { - if (N) - WL.push_back(NestedNameSpecifierVisit(N, R, Parent)); -} void EnqueueVisitor::AddNestedNameSpecifierLoc(NestedNameSpecifierLoc Qualifier) { @@ -1846,10 +1808,10 @@ void EnqueueVisitor::AddDecl(Decl *D, bool isFirst) { WL.push_back(DeclVisit(D, Parent, isFirst)); } void EnqueueVisitor:: - AddExplicitTemplateArgs(const ExplicitTemplateArgumentList *A) { + AddExplicitTemplateArgs(const ASTTemplateArgumentListInfo *A) { if (A) WL.push_back(ExplicitTemplateArgsVisit( - const_cast<ExplicitTemplateArgumentList*>(A), Parent)); + const_cast<ASTTemplateArgumentListInfo*>(A), Parent)); } void EnqueueVisitor::AddMemberRef(FieldDecl *D, SourceLocation L) { if (D) @@ -2114,7 +2076,7 @@ void EnqueueVisitor::VisitSizeOfPackExpr(SizeOfPackExpr *E) { } void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, Stmt *S) { - EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU)).Visit(S); + EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S); } bool CursorVisitor::IsInRegionOfInterest(CXCursor C) { @@ -2142,13 +2104,14 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) { continue; // For now, perform default visitation for Decls. - if (Visit(MakeCXCursor(D, TU, cast<DeclVisit>(&LI)->isFirst()))) + if (Visit(MakeCXCursor(D, TU, RegionOfInterest, + cast<DeclVisit>(&LI)->isFirst()))) return true; continue; } case VisitorJob::ExplicitTemplateArgsVisitKind: { - const ExplicitTemplateArgumentList *ArgList = + const ASTTemplateArgumentListInfo *ArgList = cast<ExplicitTemplateArgsVisit>(&LI)->get(); for (const TemplateArgumentLoc *Arg = ArgList->getTemplateArgs(), *ArgEnd = Arg + ArgList->NumTemplateArgs; @@ -2174,14 +2137,7 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) { } continue; } - - case VisitorJob::NestedNameSpecifierVisitKind: { - NestedNameSpecifierVisit *V = cast<NestedNameSpecifierVisit>(&LI); - if (VisitNestedNameSpecifier(V->get(), V->getSourceRange())) - return true; - continue; - } - + case VisitorJob::NestedNameSpecifierLocVisitKind: { NestedNameSpecifierLocVisit *V = cast<NestedNameSpecifierLocVisit>(&LI); if (VisitNestedNameSpecifierLoc(V->get())) @@ -2207,7 +2163,7 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) { continue; // Update the current cursor. - CXCursor Cursor = MakeCXCursor(S, StmtParent, TU); + CXCursor Cursor = MakeCXCursor(S, StmtParent, TU, RegionOfInterest); if (!IsInRegionOfInterest(Cursor)) continue; switch (Visitor(Cursor, Parent, ClientData)) { @@ -2313,6 +2269,47 @@ bool CursorVisitor::Visit(Stmt *S) { return result; } +namespace { +typedef llvm::SmallVector<SourceRange, 4> RefNamePieces; +RefNamePieces buildPieces(unsigned NameFlags, bool IsMemberRefExpr, + const DeclarationNameInfo &NI, + const SourceRange &QLoc, + const ASTTemplateArgumentListInfo *TemplateArgs = 0){ + const bool WantQualifier = NameFlags & CXNameRange_WantQualifier; + const bool WantTemplateArgs = NameFlags & CXNameRange_WantTemplateArgs; + const bool WantSinglePiece = NameFlags & CXNameRange_WantSinglePiece; + + const DeclarationName::NameKind Kind = NI.getName().getNameKind(); + + RefNamePieces Pieces; + + if (WantQualifier && QLoc.isValid()) + Pieces.push_back(QLoc); + + if (Kind != DeclarationName::CXXOperatorName || IsMemberRefExpr) + Pieces.push_back(NI.getLoc()); + + if (WantTemplateArgs && TemplateArgs) + Pieces.push_back(SourceRange(TemplateArgs->LAngleLoc, + TemplateArgs->RAngleLoc)); + + if (Kind == DeclarationName::CXXOperatorName) { + Pieces.push_back(SourceLocation::getFromRawEncoding( + NI.getInfo().CXXOperatorName.BeginOpNameLoc)); + Pieces.push_back(SourceLocation::getFromRawEncoding( + NI.getInfo().CXXOperatorName.EndOpNameLoc)); + } + + if (WantSinglePiece) { + SourceRange R(Pieces.front().getBegin(), Pieces.back().getEnd()); + Pieces.clear(); + Pieces.push_back(R); + } + + return Pieces; +} +} + //===----------------------------------------------------------------------===// // Misc. API hooks. //===----------------------------------------------------------------------===// @@ -2369,7 +2366,7 @@ CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx, FileSystemOptions FileSystemOpts; FileSystemOpts.WorkingDir = CXXIdx->getWorkingDirectory(); - llvm::IntrusiveRefCntPtr<Diagnostic> Diags; + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags; ASTUnit *TU = ASTUnit::LoadFromASTFile(ast_filename, Diags, FileSystemOpts, CXXIdx->getOnlyLocalDecls(), 0, 0, true); @@ -2378,9 +2375,7 @@ CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx, unsigned clang_defaultEditingTranslationUnitOptions() { return CXTranslationUnit_PrecompiledPreamble | - CXTranslationUnit_CacheCompletionResults | - CXTranslationUnit_CXXPrecompiledPreamble | - CXTranslationUnit_CXXChainedPCH; + CXTranslationUnit_CacheCompletionResults; } CXTranslationUnit @@ -2426,24 +2421,21 @@ static void clang_parseTranslationUnit_Impl(void *UserData) { CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx); bool PrecompilePreamble = options & CXTranslationUnit_PrecompiledPreamble; - bool CompleteTranslationUnit - = ((options & CXTranslationUnit_Incomplete) == 0); + // FIXME: Add a flag for modules. + TranslationUnitKind TUKind + = (options & CXTranslationUnit_Incomplete)? TU_Prefix : TU_Complete; bool CacheCodeCompetionResults = options & CXTranslationUnit_CacheCompletionResults; - bool CXXPrecompilePreamble - = options & CXTranslationUnit_CXXPrecompiledPreamble; - bool CXXChainedPCH - = options & CXTranslationUnit_CXXChainedPCH; // Configure the diagnostics. DiagnosticOptions DiagOpts; - llvm::IntrusiveRefCntPtr<Diagnostic> + llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(CompilerInstance::createDiagnostics(DiagOpts, num_command_line_args, command_line_args)); // Recover resources if we crash before exiting this function. - llvm::CrashRecoveryContextCleanupRegistrar<Diagnostic, - llvm::CrashRecoveryContextReleaseRefCleanup<Diagnostic> > + llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, + llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > DiagCleanup(Diags.getPtr()); llvm::OwningPtr<std::vector<ASTUnit::RemappedFile> > @@ -2454,7 +2446,7 @@ static void clang_parseTranslationUnit_Impl(void *UserData) { std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get()); for (unsigned I = 0; I != num_unsaved_files; ++I) { - llvm::StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length); + StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length); const llvm::MemoryBuffer *Buffer = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename); RemappedFiles->push_back(std::make_pair(unsaved_files[I].Filename, @@ -2517,10 +2509,8 @@ static void clang_parseTranslationUnit_Impl(void *UserData) { RemappedFiles->size(), /*RemappedFilesKeepOriginalName=*/true, PrecompilePreamble, - CompleteTranslationUnit, + TUKind, CacheCodeCompetionResults, - CXXPrecompilePreamble, - CXXChainedPCH, NestedMacroExpansions)); if (NumErrors != Diags->getClient()->getNumErrors()) { @@ -2651,7 +2641,7 @@ static void clang_reparseTranslationUnit_Impl(void *UserData) { std::vector<ASTUnit::RemappedFile> > RemappedCleanup(RemappedFiles.get()); for (unsigned I = 0; I != num_unsaved_files; ++I) { - llvm::StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length); + StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length); const llvm::MemoryBuffer *Buffer = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename); RemappedFiles->push_back(std::make_pair(unsaved_files[I].Filename, @@ -2691,7 +2681,7 @@ CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) { } CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) { - CXCursor Result = { CXCursor_TranslationUnit, { 0, 0, TU } }; + CXCursor Result = { CXCursor_TranslationUnit, 0, { 0, 0, TU } }; return Result; } @@ -2722,9 +2712,9 @@ CXSourceLocation clang_getLocation(CXTranslationUnit tu, bool Logging = ::getenv("LIBCLANG_LOGGING"); ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData); + ASTUnit::ConcurrencyCheck Check(*CXXUnit); const FileEntry *File = static_cast<const FileEntry *>(file); - SourceLocation SLoc - = CXXUnit->getSourceManager().getLocation(File, line, column); + SourceLocation SLoc = CXXUnit->getLocation(File, line, column); if (SLoc.isInvalid()) { if (Logging) llvm::errs() << "clang_getLocation(\"" << File->getName() @@ -2747,14 +2737,8 @@ CXSourceLocation clang_getLocationForOffset(CXTranslationUnit tu, return clang_getNullLocation(); ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu->TUData); - SourceLocation Start - = CXXUnit->getSourceManager().getLocation( - static_cast<const FileEntry *>(file), - 1, 1); - if (Start.isInvalid()) return clang_getNullLocation(); - - SourceLocation SLoc = Start.getFileLocWithOffset(offset); - + SourceLocation SLoc + = CXXUnit->getLocation(static_cast<const FileEntry *>(file), offset); if (SLoc.isInvalid()) return clang_getNullLocation(); return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc); @@ -2774,6 +2758,19 @@ CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) { begin.int_data, end.int_data }; return Result; } + +unsigned clang_equalRanges(CXSourceRange range1, CXSourceRange range2) +{ + return range1.ptr_data[0] == range2.ptr_data[0] + && range1.ptr_data[1] == range2.ptr_data[1] + && range1.begin_int_data == range2.begin_int_data + && range1.end_int_data == range2.end_int_data; +} + +int clang_Range_isNull(CXSourceRange range) { + return clang_equalRanges(range, clang_getNullRange()); +} + } // end: extern "C" static void createNullLocation(CXFile *file, unsigned *line, @@ -2790,11 +2787,11 @@ static void createNullLocation(CXFile *file, unsigned *line, } extern "C" { -void clang_getInstantiationLocation(CXSourceLocation location, - CXFile *file, - unsigned *line, - unsigned *column, - unsigned *offset) { +void clang_getExpansionLocation(CXSourceLocation location, + CXFile *file, + unsigned *line, + unsigned *column, + unsigned *offset) { SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); if (!location.ptr_data[0] || Loc.isInvalid()) { @@ -2804,11 +2801,11 @@ void clang_getInstantiationLocation(CXSourceLocation location, const SourceManager &SM = *static_cast<const SourceManager*>(location.ptr_data[0]); - SourceLocation InstLoc = SM.getInstantiationLoc(Loc); + SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc); // Check that the FileID is invalid on the expansion location. // This can manifest in invalid code. - FileID fileID = SM.getFileID(InstLoc); + FileID fileID = SM.getFileID(ExpansionLoc); bool Invalid = false; const SrcMgr::SLocEntry &sloc = SM.getSLocEntry(fileID, &Invalid); if (!sloc.isFile() || Invalid) { @@ -2819,11 +2816,48 @@ void clang_getInstantiationLocation(CXSourceLocation location, if (file) *file = (void *)SM.getFileEntryForSLocEntry(sloc); if (line) - *line = SM.getInstantiationLineNumber(InstLoc); + *line = SM.getExpansionLineNumber(ExpansionLoc); if (column) - *column = SM.getInstantiationColumnNumber(InstLoc); + *column = SM.getExpansionColumnNumber(ExpansionLoc); if (offset) - *offset = SM.getDecomposedLoc(InstLoc).second; + *offset = SM.getDecomposedLoc(ExpansionLoc).second; +} + +void clang_getPresumedLocation(CXSourceLocation location, + CXString *filename, + unsigned *line, + unsigned *column) { + SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); + + if (!location.ptr_data[0] || Loc.isInvalid()) { + if (filename) + *filename = createCXString(""); + if (line) + *line = 0; + if (column) + *column = 0; + } + else { + const SourceManager &SM = + *static_cast<const SourceManager*>(location.ptr_data[0]); + PresumedLoc PreLoc = SM.getPresumedLoc(Loc); + + if (filename) + *filename = createCXString(PreLoc.getFilename()); + if (line) + *line = PreLoc.getLine(); + if (column) + *column = PreLoc.getColumn(); + } +} + +void clang_getInstantiationLocation(CXSourceLocation location, + CXFile *file, + unsigned *line, + unsigned *column, + unsigned *offset) { + // Redirect to new API. + clang_getExpansionLocation(location, file, line, column, offset); } void clang_getSpellingLocation(CXSourceLocation location, @@ -2845,7 +2879,7 @@ void clang_getSpellingLocation(CXSourceLocation location, SM.getFileEntryForID(SM.getDecomposedLoc(SimpleSpellingLoc).first)) SpellLoc = SimpleSpellingLoc; else - SpellLoc = SM.getInstantiationLoc(SpellLoc); + SpellLoc = SM.getExpansionLoc(SpellLoc); } std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc); @@ -2927,7 +2961,7 @@ unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file) { //===----------------------------------------------------------------------===// static Decl *getDeclFromExpr(Stmt *E) { - if (CastExpr *CE = dyn_cast<CastExpr>(E)) + if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) return getDeclFromExpr(CE->getSubExpr()); if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E)) @@ -2943,7 +2977,7 @@ static Decl *getDeclFromExpr(Stmt *E) { if (CallExpr *CE = dyn_cast<CallExpr>(E)) return getDeclFromExpr(CE->getCallee()); - if (CXXConstructExpr *CE = llvm::dyn_cast<CXXConstructExpr>(E)) + if (CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E)) if (!CE->isElidable()) return CE->getConstructor(); if (ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(E)) @@ -2963,6 +2997,9 @@ static Decl *getDeclFromExpr(Stmt *E) { } static SourceLocation getLocationFromExpr(Expr *E) { + if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) + return getLocationFromExpr(CE->getSubExpr()); + if (ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E)) return /*FIXME:*/Msg->getLeftLoc(); if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) @@ -2985,7 +3022,6 @@ unsigned clang_visitChildren(CXCursor parent, CXCursorVisitor visitor, CXClientData client_data) { CursorVisitor CursorVis(getCursorTU(parent), visitor, client_data, - getCursorASTUnit(parent)->getMaxPCHLevel(), false); return CursorVis.VisitChildren(parent); } @@ -3030,7 +3066,7 @@ unsigned clang_visitChildrenWithBlock(CXCursor parent, static CXString getDeclSpelling(Decl *D) { NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D); if (!ND) { - if (ObjCPropertyImplDecl *PropImpl =llvm::dyn_cast<ObjCPropertyImplDecl>(D)) + if (ObjCPropertyImplDecl *PropImpl =dyn_cast<ObjCPropertyImplDecl>(D)) if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl()) return createCXString(Property->getIdentifier()->getName()); @@ -3165,6 +3201,11 @@ CXString clang_getCursorSpelling(CXCursor C) { if (clang_isDeclaration(C.kind)) return getDeclSpelling(getCursorDecl(C)); + if (C.kind == CXCursor_AnnotateAttr) { + AnnotateAttr *AA = cast<AnnotateAttr>(cxcursor::getCursorAttr(C)); + return createCXString(AA->getAnnotation()); + } + return createCXString(""); } @@ -3176,7 +3217,7 @@ CXString clang_getCursorDisplayName(CXCursor C) { if (!D) return createCXString(""); - PrintingPolicy &Policy = getCursorContext(C).PrintingPolicy; + PrintingPolicy Policy = getCursorContext(C).getPrintingPolicy(); if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) D = FunTmpl->getTemplatedDecl(); @@ -3314,10 +3355,86 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("LabelRef"); case CXCursor_OverloadedDeclRef: return createCXString("OverloadedDeclRef"); - case CXCursor_UnexposedExpr: - return createCXString("UnexposedExpr"); + case CXCursor_IntegerLiteral: + return createCXString("IntegerLiteral"); + case CXCursor_FloatingLiteral: + return createCXString("FloatingLiteral"); + case CXCursor_ImaginaryLiteral: + return createCXString("ImaginaryLiteral"); + case CXCursor_StringLiteral: + return createCXString("StringLiteral"); + case CXCursor_CharacterLiteral: + return createCXString("CharacterLiteral"); + case CXCursor_ParenExpr: + return createCXString("ParenExpr"); + case CXCursor_UnaryOperator: + return createCXString("UnaryOperator"); + case CXCursor_ArraySubscriptExpr: + return createCXString("ArraySubscriptExpr"); + case CXCursor_BinaryOperator: + return createCXString("BinaryOperator"); + case CXCursor_CompoundAssignOperator: + return createCXString("CompoundAssignOperator"); + case CXCursor_ConditionalOperator: + return createCXString("ConditionalOperator"); + case CXCursor_CStyleCastExpr: + return createCXString("CStyleCastExpr"); + case CXCursor_CompoundLiteralExpr: + return createCXString("CompoundLiteralExpr"); + case CXCursor_InitListExpr: + return createCXString("InitListExpr"); + case CXCursor_AddrLabelExpr: + return createCXString("AddrLabelExpr"); + case CXCursor_StmtExpr: + return createCXString("StmtExpr"); + case CXCursor_GenericSelectionExpr: + return createCXString("GenericSelectionExpr"); + case CXCursor_GNUNullExpr: + return createCXString("GNUNullExpr"); + case CXCursor_CXXStaticCastExpr: + return createCXString("CXXStaticCastExpr"); + case CXCursor_CXXDynamicCastExpr: + return createCXString("CXXDynamicCastExpr"); + case CXCursor_CXXReinterpretCastExpr: + return createCXString("CXXReinterpretCastExpr"); + case CXCursor_CXXConstCastExpr: + return createCXString("CXXConstCastExpr"); + case CXCursor_CXXFunctionalCastExpr: + return createCXString("CXXFunctionalCastExpr"); + case CXCursor_CXXTypeidExpr: + return createCXString("CXXTypeidExpr"); + case CXCursor_CXXBoolLiteralExpr: + return createCXString("CXXBoolLiteralExpr"); + case CXCursor_CXXNullPtrLiteralExpr: + return createCXString("CXXNullPtrLiteralExpr"); + case CXCursor_CXXThisExpr: + return createCXString("CXXThisExpr"); + case CXCursor_CXXThrowExpr: + return createCXString("CXXThrowExpr"); + case CXCursor_CXXNewExpr: + return createCXString("CXXNewExpr"); + case CXCursor_CXXDeleteExpr: + return createCXString("CXXDeleteExpr"); + case CXCursor_UnaryExpr: + return createCXString("UnaryExpr"); + case CXCursor_ObjCStringLiteral: + return createCXString("ObjCStringLiteral"); + case CXCursor_ObjCEncodeExpr: + return createCXString("ObjCEncodeExpr"); + case CXCursor_ObjCSelectorExpr: + return createCXString("ObjCSelectorExpr"); + case CXCursor_ObjCProtocolExpr: + return createCXString("ObjCProtocolExpr"); + case CXCursor_ObjCBridgedCastExpr: + return createCXString("ObjCBridgedCastExpr"); case CXCursor_BlockExpr: return createCXString("BlockExpr"); + case CXCursor_PackExpansionExpr: + return createCXString("PackExpansionExpr"); + case CXCursor_SizeOfPackExpr: + return createCXString("SizeOfPackExpr"); + case CXCursor_UnexposedExpr: + return createCXString("UnexposedExpr"); case CXCursor_DeclRefExpr: return createCXString("DeclRefExpr"); case CXCursor_MemberRefExpr: @@ -3328,8 +3445,66 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("ObjCMessageExpr"); case CXCursor_UnexposedStmt: return createCXString("UnexposedStmt"); + case CXCursor_DeclStmt: + return createCXString("DeclStmt"); case CXCursor_LabelStmt: return createCXString("LabelStmt"); + case CXCursor_CompoundStmt: + return createCXString("CompoundStmt"); + case CXCursor_CaseStmt: + return createCXString("CaseStmt"); + case CXCursor_DefaultStmt: + return createCXString("DefaultStmt"); + case CXCursor_IfStmt: + return createCXString("IfStmt"); + case CXCursor_SwitchStmt: + return createCXString("SwitchStmt"); + case CXCursor_WhileStmt: + return createCXString("WhileStmt"); + case CXCursor_DoStmt: + return createCXString("DoStmt"); + case CXCursor_ForStmt: + return createCXString("ForStmt"); + case CXCursor_GotoStmt: + return createCXString("GotoStmt"); + case CXCursor_IndirectGotoStmt: + return createCXString("IndirectGotoStmt"); + case CXCursor_ContinueStmt: + return createCXString("ContinueStmt"); + case CXCursor_BreakStmt: + return createCXString("BreakStmt"); + case CXCursor_ReturnStmt: + return createCXString("ReturnStmt"); + case CXCursor_AsmStmt: + return createCXString("AsmStmt"); + case CXCursor_ObjCAtTryStmt: + return createCXString("ObjCAtTryStmt"); + case CXCursor_ObjCAtCatchStmt: + return createCXString("ObjCAtCatchStmt"); + case CXCursor_ObjCAtFinallyStmt: + return createCXString("ObjCAtFinallyStmt"); + case CXCursor_ObjCAtThrowStmt: + return createCXString("ObjCAtThrowStmt"); + case CXCursor_ObjCAtSynchronizedStmt: + return createCXString("ObjCAtSynchronizedStmt"); + case CXCursor_ObjCAutoreleasePoolStmt: + return createCXString("ObjCAutoreleasePoolStmt"); + case CXCursor_ObjCForCollectionStmt: + return createCXString("ObjCForCollectionStmt"); + case CXCursor_CXXCatchStmt: + return createCXString("CXXCatchStmt"); + case CXCursor_CXXTryStmt: + return createCXString("CXXTryStmt"); + case CXCursor_CXXForRangeStmt: + return createCXString("CXXForRangeStmt"); + case CXCursor_SEHTryStmt: + return createCXString("SEHTryStmt"); + case CXCursor_SEHExceptStmt: + return createCXString("SEHExceptStmt"); + case CXCursor_SEHFinallyStmt: + return createCXString("SEHFinallyStmt"); + case CXCursor_NullStmt: + return createCXString("NullStmt"); case CXCursor_InvalidFile: return createCXString("InvalidFile"); case CXCursor_InvalidCode: @@ -3348,6 +3523,12 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("attribute(iboutlet)"); case CXCursor_IBOutletCollectionAttr: return createCXString("attribute(iboutletcollection)"); + case CXCursor_CXXFinalAttr: + return createCXString("attribute(final)"); + case CXCursor_CXXOverrideAttr: + return createCXString("attribute(override)"); + case CXCursor_AnnotateAttr: + return createCXString("attribute(annotate)"); case CXCursor_PreprocessingDirective: return createCXString("preprocessing directive"); case CXCursor_MacroDefinition: @@ -3392,6 +3573,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("ObjCSynthesizeDecl"); case CXCursor_ObjCDynamicDecl: return createCXString("ObjCDynamicDecl"); + case CXCursor_CXXAccessSpecifier: + return createCXString("CXXAccessSpecifier"); } llvm_unreachable("Unhandled CXCursorKind"); @@ -3400,18 +3583,35 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { struct GetCursorData { SourceLocation TokenBeginLoc; + bool PointsAtMacroArgExpansion; CXCursor &BestCursor; - GetCursorData(SourceLocation tokenBegin, CXCursor &outputCursor) - : TokenBeginLoc(tokenBegin), BestCursor(outputCursor) { } + GetCursorData(SourceManager &SM, + SourceLocation tokenBegin, CXCursor &outputCursor) + : TokenBeginLoc(tokenBegin), BestCursor(outputCursor) { + PointsAtMacroArgExpansion = SM.isMacroArgExpansion(tokenBegin); + } }; -enum CXChildVisitResult GetCursorVisitor(CXCursor cursor, - CXCursor parent, - CXClientData client_data) { +static enum CXChildVisitResult GetCursorVisitor(CXCursor cursor, + CXCursor parent, + CXClientData client_data) { GetCursorData *Data = static_cast<GetCursorData *>(client_data); CXCursor *BestCursor = &Data->BestCursor; + // If we point inside a macro argument we should provide info of what the + // token is so use the actual cursor, don't replace it with a macro expansion + // cursor. + if (cursor.kind == CXCursor_MacroExpansion && Data->PointsAtMacroArgExpansion) + return CXChildVisit_Recurse; + + if (clang_isDeclaration(cursor.kind)) { + // Avoid having the implicit methods override the property decls. + if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(getCursorDecl(cursor))) + if (MD->isImplicit()) + return CXChildVisit_Break; + } + if (clang_isExpression(cursor.kind) && clang_isDeclaration(BestCursor->kind)) { Decl *D = getCursorDecl(*BestCursor); @@ -3431,14 +3631,12 @@ enum CXChildVisitResult GetCursorVisitor(CXCursor cursor, // clang_getCursor() to point at the constructor. if (clang_isExpression(BestCursor->kind) && isa<CXXTemporaryObjectExpr>(getCursorExpr(*BestCursor)) && - cursor.kind == CXCursor_TypeRef) - return CXChildVisit_Recurse; - - // Don't override a preprocessing cursor with another preprocessing - // cursor; we want the outermost preprocessing cursor. - if (clang_isPreprocessing(cursor.kind) && - clang_isPreprocessing(BestCursor->kind)) + cursor.kind == CXCursor_TypeRef) { + // Keep the cursor pointing at CXXTemporaryObjectExpr but also mark it + // as having the actual point on the type reference. + *BestCursor = getTypeRefedCallExprCursor(*BestCursor); return CXChildVisit_Recurse; + } *BestCursor = cursor; return CXChildVisit_Recurse; @@ -3451,31 +3649,10 @@ CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) { ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData); ASTUnit::ConcurrencyCheck Check(*CXXUnit); - // Translate the given source location to make it point at the beginning of - // the token under the cursor. SourceLocation SLoc = cxloc::translateSourceLocation(Loc); - - // Guard against an invalid SourceLocation, or we may assert in one - // of the following calls. - if (SLoc.isInvalid()) - return clang_getNullCursor(); + CXCursor Result = cxcursor::getCursor(TU, SLoc); bool Logging = getenv("LIBCLANG_LOGGING"); - SLoc = Lexer::GetBeginningOfToken(SLoc, CXXUnit->getSourceManager(), - CXXUnit->getASTContext().getLangOptions()); - - CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound); - if (SLoc.isValid()) { - // FIXME: Would be great to have a "hint" cursor, then walk from that - // hint cursor upward until we find a cursor whose source range encloses - // the region of interest, rather than starting from the translation unit. - GetCursorData ResultData(SLoc, Result); - CXCursor Parent = clang_getTranslationUnitCursor(TU); - CursorVisitor CursorVis(TU, GetCursorVisitor, &ResultData, - Decl::MaxPCHLevel, true, SourceLocation(SLoc)); - CursorVis.VisitChildren(Parent); - } - if (Logging) { CXFile SearchFile; unsigned SearchLine, SearchColumn; @@ -3485,10 +3662,9 @@ CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) { const char *IsDef = clang_isCursorDefinition(Result)? " (Definition)" : ""; CXSourceLocation ResultLoc = clang_getCursorLocation(Result); - clang_getInstantiationLocation(Loc, &SearchFile, &SearchLine, &SearchColumn, - 0); - clang_getInstantiationLocation(ResultLoc, &ResultFile, &ResultLine, - &ResultColumn, 0); + clang_getExpansionLocation(Loc, &SearchFile, &SearchLine, &SearchColumn, 0); + clang_getExpansionLocation(ResultLoc, &ResultFile, &ResultLine, + &ResultColumn, 0); SearchFileName = clang_getFileName(SearchFile); ResultFileName = clang_getFileName(ResultFile); KindSpelling = clang_getCursorKindSpelling(Result.kind); @@ -3510,8 +3686,8 @@ CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) { = clang_getCursorKindSpelling(Definition.kind); CXFile DefinitionFile; unsigned DefinitionLine, DefinitionColumn; - clang_getInstantiationLocation(DefinitionLoc, &DefinitionFile, - &DefinitionLine, &DefinitionColumn, 0); + clang_getExpansionLocation(DefinitionLoc, &DefinitionFile, + &DefinitionLine, &DefinitionColumn, 0); CXString DefinitionFileName = clang_getFileName(DefinitionFile); fprintf(stderr, " -> %s(%s:%d:%d)\n", clang_getCString(DefinitionKindSpelling), @@ -3694,8 +3870,6 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) { Decl *D = getCursorDecl(C); SourceLocation Loc = D->getLocation(); - if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D)) - Loc = Class->getClassLoc(); // FIXME: Multiple variables declared in a single declaration // currently lack the information needed to correctly determine their // ranges when accounting for the type-specifier. We use context @@ -3711,6 +3885,37 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) { } // end extern "C" +CXCursor cxcursor::getCursor(CXTranslationUnit TU, SourceLocation SLoc) { + assert(TU); + + // Guard against an invalid SourceLocation, or we may assert in one + // of the following calls. + if (SLoc.isInvalid()) + return clang_getNullCursor(); + + ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData); + + // Translate the given source location to make it point at the beginning of + // the token under the cursor. + SLoc = Lexer::GetBeginningOfToken(SLoc, CXXUnit->getSourceManager(), + CXXUnit->getASTContext().getLangOptions()); + + CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound); + if (SLoc.isValid()) { + // FIXME: Would be great to have a "hint" cursor, then walk from that + // hint cursor upward until we find a cursor whose source range encloses + // the region of interest, rather than starting from the translation unit. + GetCursorData ResultData(CXXUnit->getSourceManager(), SLoc, Result); + CXCursor Parent = clang_getTranslationUnitCursor(TU); + CursorVisitor CursorVis(TU, GetCursorVisitor, &ResultData, + /*VisitPreprocessorLast=*/true, + SourceLocation(SLoc)); + CursorVis.VisitChildren(Parent); + } + + return Result; +} + static SourceRange getRawCursorExtent(CXCursor C) { if (clang_isReference(C.kind)) { switch (C.kind) { @@ -3756,17 +3961,29 @@ static SourceRange getRawCursorExtent(CXCursor C) { if (clang_isStatement(C.kind)) return getCursorStmt(C)->getSourceRange(); + if (clang_isAttribute(C.kind)) + return getCursorAttr(C)->getRange(); + if (C.kind == CXCursor_PreprocessingDirective) return cxcursor::getCursorPreprocessingDirective(C); - if (C.kind == CXCursor_MacroExpansion) - return cxcursor::getCursorMacroExpansion(C)->getSourceRange(); + if (C.kind == CXCursor_MacroExpansion) { + ASTUnit *TU = getCursorASTUnit(C); + SourceRange Range = cxcursor::getCursorMacroExpansion(C)->getSourceRange(); + return TU->mapRangeFromPreamble(Range); + } - if (C.kind == CXCursor_MacroDefinition) - return cxcursor::getCursorMacroDefinition(C)->getSourceRange(); + if (C.kind == CXCursor_MacroDefinition) { + ASTUnit *TU = getCursorASTUnit(C); + SourceRange Range = cxcursor::getCursorMacroDefinition(C)->getSourceRange(); + return TU->mapRangeFromPreamble(Range); + } - if (C.kind == CXCursor_InclusionDirective) - return cxcursor::getCursorInclusionDirective(C)->getSourceRange(); + if (C.kind == CXCursor_InclusionDirective) { + ASTUnit *TU = getCursorASTUnit(C); + SourceRange Range = cxcursor::getCursorInclusionDirective(C)->getSourceRange(); + return TU->mapRangeFromPreamble(Range); + } if (C.kind >= CXCursor_FirstDecl && C.kind <= CXCursor_LastDecl) { Decl *D = cxcursor::getCursorDecl(C); @@ -3847,7 +4064,7 @@ CXCursor clang_getCursorReferenced(CXCursor C) { if (ObjCForwardProtocolDecl *Protocols = dyn_cast<ObjCForwardProtocolDecl>(D)) return MakeCursorOverloadedDeclRef(Protocols, D->getLocation(), tu); - if (ObjCPropertyImplDecl *PropImpl =llvm::dyn_cast<ObjCPropertyImplDecl>(D)) + if (ObjCPropertyImplDecl *PropImpl =dyn_cast<ObjCPropertyImplDecl>(D)) if (ObjCPropertyDecl *Property = PropImpl->getPropertyDecl()) return MakeCXCursor(Property, tu); @@ -3857,8 +4074,12 @@ CXCursor clang_getCursorReferenced(CXCursor C) { if (clang_isExpression(C.kind)) { Expr *E = getCursorExpr(C); Decl *D = getDeclFromExpr(E); - if (D) - return MakeCXCursor(D, tu); + if (D) { + CXCursor declCursor = MakeCXCursor(D, tu); + declCursor = getSelectorIdentifierCursor(getSelectorIdentifierIndex(C), + declCursor); + return declCursor; + } if (OverloadExpr *Ovl = dyn_cast_or_null<OverloadExpr>(E)) return MakeCursorOverloadedDeclRef(Ovl, tu); @@ -3981,6 +4202,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) { case Decl::StaticAssert: case Decl::Block: case Decl::Label: // FIXME: Is this right?? + case Decl::ClassScopeFunctionSpecialization: return C; // Declaration kinds that don't make any sense here, but are @@ -4171,8 +4393,8 @@ unsigned clang_getNumOverloadedDecls(CXCursor C) { Decl *D = Storage.get<Decl*>(); if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) return Using->shadow_size(); - if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D)) - return Classes->size(); + if (isa<ObjCClassDecl>(D)) + return 1; if (ObjCForwardProtocolDecl *Protocols =dyn_cast<ObjCForwardProtocolDecl>(D)) return Protocols->protocol_size(); @@ -4202,10 +4424,8 @@ CXCursor clang_getOverloadedDecl(CXCursor cursor, unsigned index) { std::advance(Pos, index); return MakeCXCursor(cast<UsingShadowDecl>(*Pos)->getTargetDecl(), TU); } - if (ObjCClassDecl *Classes = dyn_cast<ObjCClassDecl>(D)) - return MakeCXCursor(Classes->begin()[index].getInterface(), TU); - + return MakeCXCursor(Classes->getForwardInterfaceDecl(), TU); if (ObjCForwardProtocolDecl *Protocols = dyn_cast<ObjCForwardProtocolDecl>(D)) return MakeCXCursor(Protocols->protocol_begin()[index], TU); @@ -4233,6 +4453,54 @@ void clang_getDefinitionSpellingAndExtent(CXCursor C, *endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc()); } + +CXSourceRange clang_getCursorReferenceNameRange(CXCursor C, unsigned NameFlags, + unsigned PieceIndex) { + RefNamePieces Pieces; + + switch (C.kind) { + case CXCursor_MemberRefExpr: + if (MemberExpr *E = dyn_cast<MemberExpr>(getCursorExpr(C))) + Pieces = buildPieces(NameFlags, true, E->getMemberNameInfo(), + E->getQualifierLoc().getSourceRange()); + break; + + case CXCursor_DeclRefExpr: + if (DeclRefExpr *E = dyn_cast<DeclRefExpr>(getCursorExpr(C))) + Pieces = buildPieces(NameFlags, false, E->getNameInfo(), + E->getQualifierLoc().getSourceRange(), + E->getExplicitTemplateArgsOpt()); + break; + + case CXCursor_CallExpr: + if (CXXOperatorCallExpr *OCE = + dyn_cast<CXXOperatorCallExpr>(getCursorExpr(C))) { + Expr *Callee = OCE->getCallee(); + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Callee)) + Callee = ICE->getSubExpr(); + + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Callee)) + Pieces = buildPieces(NameFlags, false, DRE->getNameInfo(), + DRE->getQualifierLoc().getSourceRange()); + } + break; + + default: + break; + } + + if (Pieces.empty()) { + if (PieceIndex == 0) + return clang_getCursorExtent(C); + } else if (PieceIndex < Pieces.size()) { + SourceRange R = Pieces[PieceIndex]; + if (R.isValid()) + return cxloc::translateSourceRange(getCursorContext(C), R); + } + + return clang_getNullRange(); +} + void clang_enableStackTraces(void) { llvm::sys::PrintStackTraceOnErrorSignal(); } @@ -4273,7 +4541,7 @@ CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) { case CXToken_Literal: { // We have stashed the starting pointer in the ptr_data field. Use it. const char *Text = static_cast<const char *>(CXTok.ptr_data); - return createCXString(llvm::StringRef(Text, CXTok.int_data[2])); + return createCXString(StringRef(Text, CXTok.int_data[2])); } case CXToken_Punctuation: @@ -4289,9 +4557,9 @@ CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) { SourceLocation Loc = SourceLocation::getFromRawEncoding(CXTok.int_data[1]); std::pair<FileID, unsigned> LocInfo - = CXXUnit->getSourceManager().getDecomposedLoc(Loc); + = CXXUnit->getSourceManager().getDecomposedSpellingLoc(Loc); bool Invalid = false; - llvm::StringRef Buffer + StringRef Buffer = CXXUnit->getSourceManager().getBufferData(LocInfo.first, &Invalid); if (Invalid) return createCXString(""); @@ -4317,28 +4585,13 @@ CXSourceRange clang_getTokenExtent(CXTranslationUnit TU, CXToken CXTok) { SourceLocation::getFromRawEncoding(CXTok.int_data[1])); } -void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, - CXToken **Tokens, unsigned *NumTokens) { - if (Tokens) - *Tokens = 0; - if (NumTokens) - *NumTokens = 0; - - ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData); - if (!CXXUnit || !Tokens || !NumTokens) - return; - - ASTUnit::ConcurrencyCheck Check(*CXXUnit); - - SourceRange R = cxloc::translateCXSourceRange(Range); - if (R.isInvalid()) - return; - +static void getTokens(ASTUnit *CXXUnit, SourceRange Range, + SmallVectorImpl<CXToken> &CXTokens) { SourceManager &SourceMgr = CXXUnit->getSourceManager(); std::pair<FileID, unsigned> BeginLocInfo - = SourceMgr.getDecomposedLoc(R.getBegin()); + = SourceMgr.getDecomposedLoc(Range.getBegin()); std::pair<FileID, unsigned> EndLocInfo - = SourceMgr.getDecomposedLoc(R.getEnd()); + = SourceMgr.getDecomposedLoc(Range.getEnd()); // Cannot tokenize across files. if (BeginLocInfo.first != EndLocInfo.first) @@ -4346,7 +4599,7 @@ void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, // Create a lexer bool Invalid = false; - llvm::StringRef Buffer + StringRef Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid); if (Invalid) return; @@ -4358,7 +4611,6 @@ void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, // Lex tokens until we hit the end of the range. const char *EffectiveBufferEnd = Buffer.data() + EndLocInfo.second; - llvm::SmallVector<CXToken, 32> CXTokens; Token Tok; bool previousWasAt = false; do { @@ -4403,6 +4655,27 @@ void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, CXTokens.push_back(CXTok); previousWasAt = Tok.is(tok::at); } while (Lex.getBufferLocation() <= EffectiveBufferEnd); +} + +void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range, + CXToken **Tokens, unsigned *NumTokens) { + if (Tokens) + *Tokens = 0; + if (NumTokens) + *NumTokens = 0; + + ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData); + if (!CXXUnit || !Tokens || !NumTokens) + return; + + ASTUnit::ConcurrencyCheck Check(*CXXUnit); + + SourceRange R = cxloc::translateCXSourceRange(Range); + if (R.isInvalid()) + return; + + SmallVector<CXToken, 32> CXTokens; + getTokens(CXXUnit, R, CXTokens); if (CXTokens.empty()) return; @@ -4445,6 +4718,16 @@ class AnnotateTokensWorker { SourceLocation GetTokenLoc(unsigned tokI) { return SourceLocation::getFromRawEncoding(Tokens[tokI].int_data[1]); } + bool isFunctionMacroToken(unsigned tokI) const { + return Tokens[tokI].int_data[3] != 0; + } + SourceLocation getFunctionMacroTokenLoc(unsigned tokI) const { + return SourceLocation::getFromRawEncoding(Tokens[tokI].int_data[3]); + } + + void annotateAndAdvanceTokens(CXCursor, RangeComparisonResult, SourceRange); + void annotateAndAdvanceFunctionMacroTokens(CXCursor, RangeComparisonResult, + SourceRange); public: AnnotateTokensWorker(AnnotateTokensData &annotated, @@ -4453,8 +4736,7 @@ public: : Annotated(annotated), Tokens(tokens), Cursors(cursors), NumTokens(numTokens), TokIdx(0), PreprocessingTokIdx(0), AnnotateVis(tu, - AnnotateTokensVisitor, this, - Decl::MaxPCHLevel, true, RegionOfInterest), + AnnotateTokensVisitor, this, true, RegionOfInterest), SrcMgr(static_cast<ASTUnit*>(tu->TUData)->getSourceManager()), HasContextSensitiveKeywords(false) { } @@ -4497,6 +4779,65 @@ void AnnotateTokensWorker::AnnotateTokens(CXCursor parent) { } } +/// \brief It annotates and advances tokens with a cursor until the comparison +//// between the cursor location and the source range is the same as +/// \arg compResult. +/// +/// Pass RangeBefore to annotate tokens with a cursor until a range is reached. +/// Pass RangeOverlap to annotate tokens inside a range. +void AnnotateTokensWorker::annotateAndAdvanceTokens(CXCursor updateC, + RangeComparisonResult compResult, + SourceRange range) { + while (MoreTokens()) { + const unsigned I = NextToken(); + if (isFunctionMacroToken(I)) + return annotateAndAdvanceFunctionMacroTokens(updateC, compResult, range); + + SourceLocation TokLoc = GetTokenLoc(I); + if (LocationCompare(SrcMgr, TokLoc, range) == compResult) { + Cursors[I] = updateC; + AdvanceToken(); + continue; + } + break; + } +} + +/// \brief Special annotation handling for macro argument tokens. +void AnnotateTokensWorker::annotateAndAdvanceFunctionMacroTokens( + CXCursor updateC, + RangeComparisonResult compResult, + SourceRange range) { + assert(MoreTokens()); + assert(isFunctionMacroToken(NextToken()) && + "Should be called only for macro arg tokens"); + + // This works differently than annotateAndAdvanceTokens; because expanded + // macro arguments can have arbitrary translation-unit source order, we do not + // advance the token index one by one until a token fails the range test. + // We only advance once past all of the macro arg tokens if all of them + // pass the range test. If one of them fails we keep the token index pointing + // at the start of the macro arg tokens so that the failing token will be + // annotated by a subsequent annotation try. + + bool atLeastOneCompFail = false; + + unsigned I = NextToken(); + for (; I < NumTokens && isFunctionMacroToken(I); ++I) { + SourceLocation TokLoc = getFunctionMacroTokenLoc(I); + if (TokLoc.isFileID()) + continue; // not macro arg token, it's parens or comma. + if (LocationCompare(SrcMgr, TokLoc, range) == compResult) { + if (clang_isInvalid(clang_getCursorKind(Cursors[I]))) + Cursors[I] = updateC; + } else + atLeastOneCompFail = true; + } + + if (!atLeastOneCompFail) + TokIdx = I; // All of the tokens were handled, advance beyond all of them. +} + enum CXChildVisitResult AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) { CXSourceLocation Loc = clang_getCursorLocation(cursor); @@ -4584,7 +4925,7 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) { SourceLocation TokLoc = GetTokenLoc(I); switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) { case RangeBefore: - assert(0 && "Infeasible"); + llvm_unreachable("Infeasible"); case RangeAfter: break; case RangeOverlap: @@ -4611,12 +4952,6 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) { const enum CXCursorKind cursorK = clang_getCursorKind(cursor); if (cursorK >= CXCursor_FirstDecl && cursorK <= CXCursor_LastDecl) { Decl *D = cxcursor::getCursorDecl(cursor); - // Don't visit synthesized ObjC methods, since they have no syntatic - // representation in the source. - if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { - if (MD->isSynthesized()) - return CXChildVisit_Continue; - } SourceLocation StartLoc; if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) { @@ -4654,20 +4989,7 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) { (clang_isInvalid(K) || K == CXCursor_TranslationUnit) ? clang_getNullCursor() : parent; - while (MoreTokens()) { - const unsigned I = NextToken(); - SourceLocation TokLoc = GetTokenLoc(I); - switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) { - case RangeBefore: - Cursors[I] = updateC; - AdvanceToken(); - continue; - case RangeAfter: - case RangeOverlap: - break; - } - break; - } + annotateAndAdvanceTokens(updateC, RangeBefore, cursorRange); // Avoid having the cursor of an expression "overwrite" the annotation of the // variable declaration that it belongs to. @@ -4692,46 +5014,19 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) { VisitChildren(cursor); const unsigned AfterChildren = NextToken(); - // Adjust 'Last' to the last token within the extent of the cursor. - while (MoreTokens()) { - const unsigned I = NextToken(); - SourceLocation TokLoc = GetTokenLoc(I); - switch (LocationCompare(SrcMgr, TokLoc, cursorRange)) { - case RangeBefore: - assert(0 && "Infeasible"); - case RangeAfter: - break; - case RangeOverlap: - Cursors[I] = updateC; - AdvanceToken(); - continue; - } - break; - } - const unsigned Last = NextToken(); + // Scan the tokens that are at the end of the cursor, but are not captured + // but the child cursors. + annotateAndAdvanceTokens(cursor, RangeOverlap, cursorRange); // Scan the tokens that are at the beginning of the cursor, but are not // capture by the child cursors. - - // For AST elements within macros, rely on a post-annotate pass to - // to correctly annotate the tokens with cursors. Otherwise we can - // get confusing results of having tokens that map to cursors that really - // are expanded by an instantiation. - if (L.isMacroID()) - cursor = clang_getNullCursor(); - for (unsigned I = BeforeChildren; I != AfterChildren; ++I) { if (!clang_isInvalid(clang_getCursorKind(Cursors[I]))) break; Cursors[I] = cursor; } - // Scan the tokens that are at the end of the cursor, but are not captured - // but the child cursors. - for (unsigned I = AfterChildren; I != Last; ++I) - Cursors[I] = cursor; - TokIdx = Last; return CXChildVisit_Continue; } @@ -4742,6 +5037,74 @@ static enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor, } namespace { + +/// \brief Uses the macro expansions in the preprocessing record to find +/// and mark tokens that are macro arguments. This info is used by the +/// AnnotateTokensWorker. +class MarkMacroArgTokensVisitor { + SourceManager &SM; + CXToken *Tokens; + unsigned NumTokens; + unsigned CurIdx; + +public: + MarkMacroArgTokensVisitor(SourceManager &SM, + CXToken *tokens, unsigned numTokens) + : SM(SM), Tokens(tokens), NumTokens(numTokens), CurIdx(0) { } + + CXChildVisitResult visit(CXCursor cursor, CXCursor parent) { + if (cursor.kind != CXCursor_MacroExpansion) + return CXChildVisit_Continue; + + SourceRange macroRange = getCursorMacroExpansion(cursor)->getSourceRange(); + if (macroRange.getBegin() == macroRange.getEnd()) + return CXChildVisit_Continue; // it's not a function macro. + + for (; CurIdx < NumTokens; ++CurIdx) { + if (!SM.isBeforeInTranslationUnit(getTokenLoc(CurIdx), + macroRange.getBegin())) + break; + } + + if (CurIdx == NumTokens) + return CXChildVisit_Break; + + for (; CurIdx < NumTokens; ++CurIdx) { + SourceLocation tokLoc = getTokenLoc(CurIdx); + if (!SM.isBeforeInTranslationUnit(tokLoc, macroRange.getEnd())) + break; + + setFunctionMacroTokenLoc(CurIdx, SM.getMacroArgExpandedLocation(tokLoc)); + } + + if (CurIdx == NumTokens) + return CXChildVisit_Break; + + return CXChildVisit_Continue; + } + +private: + SourceLocation getTokenLoc(unsigned tokI) { + return SourceLocation::getFromRawEncoding(Tokens[tokI].int_data[1]); + } + + void setFunctionMacroTokenLoc(unsigned tokI, SourceLocation loc) { + // The third field is reserved and currently not used. Use it here + // to mark macro arg expanded tokens with their expanded locations. + Tokens[tokI].int_data[3] = loc.getRawEncoding(); + } +}; + +} // end anonymous namespace + +static CXChildVisitResult +MarkMacroArgTokensVisitorDelegate(CXCursor cursor, CXCursor parent, + CXClientData client_data) { + return static_cast<MarkMacroArgTokensVisitor*>(client_data)->visit(cursor, + parent); +} + +namespace { struct clang_annotateTokens_Data { CXTranslationUnit TU; ASTUnit *CXXUnit; @@ -4751,6 +5114,73 @@ namespace { }; } +static void annotatePreprocessorTokens(CXTranslationUnit TU, + SourceRange RegionOfInterest, + AnnotateTokensData &Annotated) { + ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData); + + SourceManager &SourceMgr = CXXUnit->getSourceManager(); + std::pair<FileID, unsigned> BeginLocInfo + = SourceMgr.getDecomposedLoc(RegionOfInterest.getBegin()); + std::pair<FileID, unsigned> EndLocInfo + = SourceMgr.getDecomposedLoc(RegionOfInterest.getEnd()); + + if (BeginLocInfo.first != EndLocInfo.first) + return; + + StringRef Buffer; + bool Invalid = false; + Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid); + if (Buffer.empty() || Invalid) + return; + + Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first), + CXXUnit->getASTContext().getLangOptions(), + Buffer.begin(), Buffer.data() + BeginLocInfo.second, + Buffer.end()); + Lex.SetCommentRetentionState(true); + + // Lex tokens in raw mode until we hit the end of the range, to avoid + // entering #includes or expanding macros. + while (true) { + Token Tok; + Lex.LexFromRawLexer(Tok); + + reprocess: + if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) { + // We have found a preprocessing directive. Gobble it up so that we + // don't see it while preprocessing these tokens later, but keep track + // of all of the token locations inside this preprocessing directive so + // that we can annotate them appropriately. + // + // FIXME: Some simple tests here could identify macro definitions and + // #undefs, to provide specific cursor kinds for those. + SmallVector<SourceLocation, 32> Locations; + do { + Locations.push_back(Tok.getLocation()); + Lex.LexFromRawLexer(Tok); + } while (!Tok.isAtStartOfLine() && !Tok.is(tok::eof)); + + using namespace cxcursor; + CXCursor Cursor + = MakePreprocessingDirectiveCursor(SourceRange(Locations.front(), + Locations.back()), + TU); + for (unsigned I = 0, N = Locations.size(); I != N; ++I) { + Annotated[Locations[I].getRawEncoding()] = Cursor; + } + + if (Tok.isAtStartOfLine()) + goto reprocess; + + continue; + } + + if (Tok.is(tok::eof)) + break; + } +} + // This gets run a separate thread to avoid stack blowout. static void clang_annotateTokensImpl(void *UserData) { CXTranslationUnit TU = ((clang_annotateTokens_Data*)UserData)->TU; @@ -4770,65 +5200,19 @@ static void clang_annotateTokensImpl(void *UserData) { // A mapping from the source locations found when re-lexing or traversing the // region of interest to the corresponding cursors. AnnotateTokensData Annotated; - + // Relex the tokens within the source range to look for preprocessing // directives. - SourceManager &SourceMgr = CXXUnit->getSourceManager(); - std::pair<FileID, unsigned> BeginLocInfo - = SourceMgr.getDecomposedLoc(RegionOfInterest.getBegin()); - std::pair<FileID, unsigned> EndLocInfo - = SourceMgr.getDecomposedLoc(RegionOfInterest.getEnd()); + annotatePreprocessorTokens(TU, RegionOfInterest, Annotated); - llvm::StringRef Buffer; - bool Invalid = false; - if (BeginLocInfo.first == EndLocInfo.first && - ((Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid)),true) && - !Invalid) { - Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first), - CXXUnit->getASTContext().getLangOptions(), - Buffer.begin(), Buffer.data() + BeginLocInfo.second, - Buffer.end()); - Lex.SetCommentRetentionState(true); - - // Lex tokens in raw mode until we hit the end of the range, to avoid - // entering #includes or expanding macros. - while (true) { - Token Tok; - Lex.LexFromRawLexer(Tok); - - reprocess: - if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) { - // We have found a preprocessing directive. Gobble it up so that we - // don't see it while preprocessing these tokens later, but keep track - // of all of the token locations inside this preprocessing directive so - // that we can annotate them appropriately. - // - // FIXME: Some simple tests here could identify macro definitions and - // #undefs, to provide specific cursor kinds for those. - llvm::SmallVector<SourceLocation, 32> Locations; - do { - Locations.push_back(Tok.getLocation()); - Lex.LexFromRawLexer(Tok); - } while (!Tok.isAtStartOfLine() && !Tok.is(tok::eof)); - - using namespace cxcursor; - CXCursor Cursor - = MakePreprocessingDirectiveCursor(SourceRange(Locations.front(), - Locations.back()), - TU); - for (unsigned I = 0, N = Locations.size(); I != N; ++I) { - Annotated[Locations[I].getRawEncoding()] = Cursor; - } - - if (Tok.isAtStartOfLine()) - goto reprocess; - - continue; - } - - if (Tok.is(tok::eof)) - break; - } + if (CXXUnit->getPreprocessor().getPreprocessingRecord()) { + // Search and mark tokens that are macro argument expansions. + MarkMacroArgTokensVisitor Visitor(CXXUnit->getSourceManager(), + Tokens, NumTokens); + CursorVisitor MacroArgMarker(TU, + MarkMacroArgTokensVisitorDelegate, &Visitor, + true, RegionOfInterest); + MacroArgMarker.visitPreprocessedEntitiesInRegion(); } // Annotate all of the source locations in the region of interest that map to @@ -4888,44 +5272,10 @@ static void clang_annotateTokensImpl(void *UserData) { Tokens[I].int_data[0] = CXToken_Keyword; continue; } - - if (Cursors[I].kind == CXCursor_CXXMethod) { - IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data); - if (CXXMethodDecl *Method - = dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(Cursors[I]))) { - if ((Method->hasAttr<FinalAttr>() || - Method->hasAttr<OverrideAttr>()) && - Method->getLocation().getRawEncoding() != Tokens[I].int_data[1] && - llvm::StringSwitch<bool>(II->getName()) - .Case("final", true) - .Case("override", true) - .Default(false)) - Tokens[I].int_data[0] = CXToken_Keyword; - } - continue; - } - - if (Cursors[I].kind == CXCursor_ClassDecl || - Cursors[I].kind == CXCursor_StructDecl || - Cursors[I].kind == CXCursor_ClassTemplate) { - IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data); - if (II->getName() == "final") { - // We have to be careful with 'final', since it could be the name - // of a member class rather than the context-sensitive keyword. - // So, check whether the cursor associated with this - Decl *D = getCursorDecl(Cursors[I]); - if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(D)) { - if ((Record->hasAttr<FinalAttr>()) && - Record->getIdentifier() != II) - Tokens[I].int_data[0] = CXToken_Keyword; - } else if (ClassTemplateDecl *ClassTemplate - = dyn_cast_or_null<ClassTemplateDecl>(D)) { - CXXRecordDecl *Record = ClassTemplate->getTemplatedDecl(); - if ((Record->hasAttr<FinalAttr>()) && - Record->getIdentifier() != II) - Tokens[I].int_data[0] = CXToken_Keyword; - } - } + + if (Cursors[I].kind == CXCursor_CXXFinalAttr || + Cursors[I].kind == CXCursor_CXXOverrideAttr) { + Tokens[I].int_data[0] = CXToken_Keyword; continue; } } @@ -5122,62 +5472,6 @@ CXCursor clang_getCursorLexicalParent(CXCursor cursor) { return clang_getNullCursor(); } -static void CollectOverriddenMethods(DeclContext *Ctx, - ObjCMethodDecl *Method, - llvm::SmallVectorImpl<ObjCMethodDecl *> &Methods) { - if (!Ctx) - return; - - // If we have a class or category implementation, jump straight to the - // interface. - if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(Ctx)) - return CollectOverriddenMethods(Impl->getClassInterface(), Method, Methods); - - ObjCContainerDecl *Container = dyn_cast<ObjCContainerDecl>(Ctx); - if (!Container) - return; - - // Check whether we have a matching method at this level. - if (ObjCMethodDecl *Overridden = Container->getMethod(Method->getSelector(), - Method->isInstanceMethod())) - if (Method != Overridden) { - // We found an override at this level; there is no need to look - // into other protocols or categories. - Methods.push_back(Overridden); - return; - } - - if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { - for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), - PEnd = Protocol->protocol_end(); - P != PEnd; ++P) - CollectOverriddenMethods(*P, Method, Methods); - } - - if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) { - for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(), - PEnd = Category->protocol_end(); - P != PEnd; ++P) - CollectOverriddenMethods(*P, Method, Methods); - } - - if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) { - for (ObjCInterfaceDecl::protocol_iterator P = Interface->protocol_begin(), - PEnd = Interface->protocol_end(); - P != PEnd; ++P) - CollectOverriddenMethods(*P, Method, Methods); - - for (ObjCCategoryDecl *Category = Interface->getCategoryList(); - Category; Category = Category->getNextClassCategory()) - CollectOverriddenMethods(Category, Method, Methods); - - // We only look into the superclass if we haven't found anything yet. - if (Methods.empty()) - if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) - return CollectOverriddenMethods(Super, Method, Methods); - } -} - void clang_getOverriddenCursors(CXCursor cursor, CXCursor **overridden, unsigned *num_overridden) { @@ -5188,45 +5482,12 @@ void clang_getOverriddenCursors(CXCursor cursor, if (!overridden || !num_overridden) return; - if (!clang_isDeclaration(cursor.kind)) - return; - - Decl *D = getCursorDecl(cursor); - if (!D) - return; + SmallVector<CXCursor, 8> Overridden; + cxcursor::getOverriddenCursors(cursor, Overridden); - // Handle C++ member functions. - CXTranslationUnit TU = getCursorTU(cursor); - if (CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) { - *num_overridden = CXXMethod->size_overridden_methods(); - if (!*num_overridden) - return; - - *overridden = new CXCursor [*num_overridden]; - unsigned I = 0; - for (CXXMethodDecl::method_iterator - M = CXXMethod->begin_overridden_methods(), - MEnd = CXXMethod->end_overridden_methods(); - M != MEnd; (void)++M, ++I) - (*overridden)[I] = MakeCXCursor(const_cast<CXXMethodDecl*>(*M), TU); - return; - } - - ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D); - if (!Method) - return; - - // Handle Objective-C methods. - llvm::SmallVector<ObjCMethodDecl *, 4> Methods; - CollectOverriddenMethods(Method->getDeclContext(), Method, Methods); - - if (Methods.empty()) - return; - - *num_overridden = Methods.size(); - *overridden = new CXCursor [Methods.size()]; - for (unsigned I = 0, N = Methods.size(); I != N; ++I) - (*overridden)[I] = MakeCXCursor(Methods[I], TU); + *num_overridden = Overridden.size(); + *overridden = new CXCursor [Overridden.size()]; + std::copy(Overridden.begin(), Overridden.end(), *overridden); } void clang_disposeOverriddenCursors(CXCursor *overridden) { @@ -5274,7 +5535,6 @@ unsigned clang_CXXMethod_isVirtual(CXCursor C) { Method = dyn_cast_or_null<CXXMethodDecl>(D); return (Method && Method->isVirtual()) ? 1 : 0; } - } // end: extern "C" //===----------------------------------------------------------------------===// @@ -5289,7 +5549,7 @@ CXType clang_getIBOutletCollectionType(CXCursor C) { IBOutletCollectionAttr *A = cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(C)); - return cxtype::MakeCXType(A->getInterFace(), cxcursor::getCursorTU(C)); + return cxtype::MakeCXType(A->getInterface(), cxcursor::getCursorTU(C)); } } // end: extern "C" @@ -5347,6 +5607,12 @@ const char *clang_getTUResourceUsageName(CXTUResourceUsageKind kind) { case CXTUResourceUsage_PreprocessingRecord: str = "Preprocessor: PreprocessingRecord"; break; + case CXTUResourceUsage_SourceManager_DataStructures: + str = "SourceManager: data structures and tables"; + break; + case CXTUResourceUsage_Preprocessor_HeaderSearch: + str = "Preprocessor: header search tables"; + break; } return str; } @@ -5399,9 +5665,13 @@ CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU) { createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_SourceManager_Membuffer_Malloc, (unsigned long) srcBufs.malloc_bytes); - createCXTUResourceUsageEntry(*entries, + createCXTUResourceUsageEntry(*entries, CXTUResourceUsage_SourceManager_Membuffer_MMap, (unsigned long) srcBufs.mmap_bytes); + createCXTUResourceUsageEntry(*entries, + CXTUResourceUsage_SourceManager_DataStructures, + (unsigned long) astContext.getSourceManager() + .getDataStructureSizes()); // How much memory is being used by the ExternalASTSource? if (ExternalASTSource *esrc = astContext.getExternalSource()) { @@ -5428,6 +5698,9 @@ CXTUResourceUsage clang_getCXTUResourceUsage(CXTranslationUnit TU) { pRec->getTotalMemory()); } + createCXTUResourceUsageEntry(*entries, + CXTUResourceUsage_Preprocessor_HeaderSearch, + pp.getHeaderSearchInfo().getTotalMemory()); CXTUResourceUsage usage = { (void*) entries.get(), (unsigned) entries->size(), |