summaryrefslogtreecommitdiffstats
path: root/tools/libclang/CIndex.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/libclang/CIndex.cpp')
-rw-r--r--tools/libclang/CIndex.cpp1131
1 files changed, 1017 insertions, 114 deletions
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 7f32a1c..5117f2c 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -14,6 +14,7 @@
#include "CIndexer.h"
#include "CXCursor.h"
+#include "CXType.h"
#include "CXSourceLocation.h"
#include "CIndexDiagnostic.h"
@@ -29,7 +30,9 @@
#include "clang/Lex/Lexer.h"
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Timer.h"
#include "llvm/System/Program.h"
#include "llvm/System/Signals.h"
@@ -143,10 +146,10 @@ static RangeComparisonResult RangeCompare(SourceManager &SM,
SourceRange R2) {
assert(R1.isValid() && "First range is invalid?");
assert(R2.isValid() && "Second range is invalid?");
- if (R1.getEnd() == R2.getBegin() ||
+ if (R1.getEnd() != R2.getBegin() &&
SM.isBeforeInTranslationUnit(R1.getEnd(), R2.getBegin()))
return RangeBefore;
- if (R2.getEnd() == R1.getBegin() ||
+ if (R2.getEnd() != R1.getBegin() &&
SM.isBeforeInTranslationUnit(R2.getEnd(), R1.getBegin()))
return RangeAfter;
return RangeOverlap;
@@ -158,10 +161,8 @@ static RangeComparisonResult LocationCompare(SourceManager &SM,
SourceLocation L, SourceRange R) {
assert(R.isValid() && "First range is invalid?");
assert(L.isValid() && "Second range is invalid?");
- if (L == R.getBegin())
+ if (L == R.getBegin() || L == R.getEnd())
return RangeOverlap;
- if (L == R.getEnd())
- return RangeAfter;
if (SM.isBeforeInTranslationUnit(L, R.getBegin()))
return RangeBefore;
if (SM.isBeforeInTranslationUnit(R.getEnd(), L))
@@ -284,15 +285,24 @@ public:
// Declaration visitors
bool VisitAttributes(Decl *D);
bool VisitBlockDecl(BlockDecl *B);
+ bool VisitCXXRecordDecl(CXXRecordDecl *D);
bool VisitDeclContext(DeclContext *DC);
bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
bool VisitTypedefDecl(TypedefDecl *D);
bool VisitTagDecl(TagDecl *D);
+ bool VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D);
+ bool VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D);
+ bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
bool VisitEnumConstantDecl(EnumConstantDecl *D);
bool VisitDeclaratorDecl(DeclaratorDecl *DD);
bool VisitFunctionDecl(FunctionDecl *ND);
bool VisitFieldDecl(FieldDecl *D);
bool VisitVarDecl(VarDecl *);
+ bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
+ bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
+ bool VisitClassTemplateDecl(ClassTemplateDecl *D);
+ bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
bool VisitObjCContainerDecl(ObjCContainerDecl *D);
bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
@@ -309,14 +319,28 @@ public:
bool VisitObjCClassDecl(ObjCClassDecl *D);
bool VisitLinkageSpecDecl(LinkageSpecDecl *D);
bool VisitNamespaceDecl(NamespaceDecl *D);
-
+ bool VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
+ bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+ bool VisitUsingDecl(UsingDecl *D);
+ bool VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+ bool VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+
+ // Name visitor
+ bool VisitDeclarationNameInfo(DeclarationNameInfo Name);
+ bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS, SourceRange Range);
+
+ // Template visitors
+ bool VisitTemplateParameters(const TemplateParameterList *Params);
+ bool VisitTemplateName(TemplateName Name, SourceLocation Loc);
+ bool VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL);
+
// Type visitors
- // FIXME: QualifiedTypeLoc doesn't provide any location information
+ bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL);
bool VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
bool VisitTypedefTypeLoc(TypedefTypeLoc TL);
bool VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL);
bool VisitTagTypeLoc(TagTypeLoc TL);
- // FIXME: TemplateTypeParmTypeLoc doesn't provide any location information
+ bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL);
bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
bool VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL);
bool VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
@@ -325,9 +349,9 @@ public:
bool VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL);
bool VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL);
bool VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL);
- bool VisitFunctionTypeLoc(FunctionTypeLoc TL);
+ bool VisitFunctionTypeLoc(FunctionTypeLoc TL, bool SkipResultType = false);
bool VisitArrayTypeLoc(ArrayTypeLoc TL);
- // FIXME: Implement for TemplateSpecializationTypeLoc
+ bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL);
// FIXME: Implement visitors here when the unimplemented TypeLocs get
// implemented
bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL);
@@ -345,6 +369,8 @@ public:
// bool VisitSwitchCase(SwitchCase *S);
// Expression visitors
+ bool VisitDeclRefExpr(DeclRefExpr *E);
+ bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
bool VisitBlockExpr(BlockExpr *B);
bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
bool VisitExplicitCastExpr(ExplicitCastExpr *E);
@@ -352,10 +378,30 @@ public:
bool VisitObjCEncodeExpr(ObjCEncodeExpr *E);
bool VisitOffsetOfExpr(OffsetOfExpr *E);
bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+ bool VisitMemberExpr(MemberExpr *E);
+ // FIXME: AddrLabelExpr (once we have cursors for labels)
+ bool VisitTypesCompatibleExpr(TypesCompatibleExpr *E);
+ bool VisitVAArgExpr(VAArgExpr *E);
+ // FIXME: InitListExpr (for the designators)
+ // FIXME: DesignatedInitExpr
+ bool VisitCXXTypeidExpr(CXXTypeidExpr *E);
+ bool VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { return false; }
+ // FIXME: CXXTemporaryObjectExpr has poor source-location information.
+ // FIXME: CXXScalarValueInitExpr has poor source-location information.
+ // FIXME: CXXNewExpr has poor source-location information
+ bool VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E);
+ // FIXME: UnaryTypeTraitExpr has poor source-location information.
+ bool VisitOverloadExpr(OverloadExpr *E);
+ bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E);
+ // FIXME: CXXUnresolvedConstructExpr has poor source-location information.
+ bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E);
+ bool VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E);
};
} // end anonymous namespace
+static SourceRange getRawCursorExtent(CXCursor C);
+
RangeComparisonResult CursorVisitor::CompareRegionOfInterest(SourceRange R) {
return RangeCompare(TU->getSourceManager(), R, RegionOfInterest);
}
@@ -387,8 +433,7 @@ bool CursorVisitor::Visit(CXCursor Cursor, bool CheckedRegionOfInterest) {
// If we have a range of interest, and this cursor doesn't intersect with it,
// we're done.
if (RegionOfInterest.isValid() && !CheckedRegionOfInterest) {
- SourceRange Range =
- cxloc::translateCXSourceRange(clang_getCursorExtent(Cursor));
+ SourceRange Range = getRawCursorExtent(Cursor);
if (Range.isInvalid() || CompareRegionOfInterest(Range))
return false;
}
@@ -478,10 +523,10 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) {
ASTUnit *CXXUnit = getCursorASTUnit(Cursor);
if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls() &&
RegionOfInterest.isInvalid()) {
- const std::vector<Decl*> &TLDs = CXXUnit->getTopLevelDecls();
- for (std::vector<Decl*>::const_iterator it = TLDs.begin(),
- ie = TLDs.end(); it != ie; ++it) {
- if (Visit(MakeCXCursor(*it, CXXUnit), true))
+ for (ASTUnit::top_level_iterator TL = CXXUnit->top_level_begin(),
+ TLEnd = CXXUnit->top_level_end();
+ TL != TLEnd; ++TL) {
+ if (Visit(MakeCXCursor(*TL, CXXUnit), true))
return true;
}
} else if (VisitDeclContext(
@@ -520,7 +565,10 @@ bool CursorVisitor::VisitBlockDecl(BlockDecl *B) {
if (Visit(B->getSignatureAsWritten()->getTypeLoc()))
return true;
- return Visit(MakeCXCursor(B->getBody(), StmtParent, TU));
+ if (Stmt *Body = B->getBody())
+ return Visit(MakeCXCursor(Body, StmtParent, TU));
+
+ return false;
}
bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
@@ -534,8 +582,7 @@ bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
CXCursor Cursor = MakeCXCursor(D, TU);
if (RegionOfInterest.isValid()) {
- SourceRange Range =
- cxloc::translateCXSourceRange(clang_getCursorExtent(Cursor));
+ SourceRange Range = getRawCursorExtent(Cursor);
if (Range.isInvalid())
continue;
@@ -577,6 +624,67 @@ bool CursorVisitor::VisitTagDecl(TagDecl *D) {
return VisitDeclContext(D);
}
+bool CursorVisitor::VisitClassTemplateSpecializationDecl(
+ ClassTemplateSpecializationDecl *D) {
+ bool ShouldVisitBody = false;
+ switch (D->getSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ // Nothing to visit
+ return false;
+
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ break;
+
+ case TSK_ExplicitSpecialization:
+ ShouldVisitBody = true;
+ break;
+ }
+
+ // Visit the template arguments used in the specialization.
+ if (TypeSourceInfo *SpecType = D->getTypeAsWritten()) {
+ TypeLoc TL = SpecType->getTypeLoc();
+ if (TemplateSpecializationTypeLoc *TSTLoc
+ = dyn_cast<TemplateSpecializationTypeLoc>(&TL)) {
+ for (unsigned I = 0, N = TSTLoc->getNumArgs(); I != N; ++I)
+ if (VisitTemplateArgumentLoc(TSTLoc->getArgLoc(I)))
+ return true;
+ }
+ }
+
+ if (ShouldVisitBody && VisitCXXRecordDecl(D))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitClassTemplatePartialSpecializationDecl(
+ ClassTemplatePartialSpecializationDecl *D) {
+ // FIXME: Visit the "outer" template parameter lists on the TagDecl
+ // before visiting these template parameters.
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ // Visit the partial specialization arguments.
+ const TemplateArgumentLoc *TemplateArgs = D->getTemplateArgsAsWritten();
+ for (unsigned I = 0, N = D->getNumTemplateArgsAsWritten(); I != N; ++I)
+ if (VisitTemplateArgumentLoc(TemplateArgs[I]))
+ return true;
+
+ return VisitCXXRecordDecl(D);
+}
+
+bool CursorVisitor::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+ // Visit the default argument.
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
+ if (TypeSourceInfo *DefArg = D->getDefaultArgumentInfo())
+ if (Visit(DefArg->getTypeLoc()))
+ return true;
+
+ return false;
+}
+
bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {
if (Expr *Init = D->getInitExpr())
return Visit(MakeCXCursor(Init, StmtParent, TU));
@@ -592,9 +700,37 @@ bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {
}
bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
- if (VisitDeclaratorDecl(ND))
- return true;
-
+ if (TypeSourceInfo *TSInfo = ND->getTypeSourceInfo()) {
+ // Visit the function declaration's syntactic components in the order
+ // written. This requires a bit of work.
+ TypeLoc TL = TSInfo->getTypeLoc();
+ FunctionTypeLoc *FTL = dyn_cast<FunctionTypeLoc>(&TL);
+
+ // If we have a function declared directly (without the use of a typedef),
+ // visit just the return type. Otherwise, just visit the function's type
+ // now.
+ if ((FTL && !isa<CXXConversionDecl>(ND) && Visit(FTL->getResultLoc())) ||
+ (!FTL && Visit(TL)))
+ return true;
+
+ // Visit the nested-name-specifier, if present.
+ if (NestedNameSpecifier *Qualifier = ND->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, ND->getQualifierRange()))
+ return true;
+
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(ND->getNameInfo()))
+ return true;
+
+ // FIXME: Visit explicitly-specified template arguments!
+
+ // Visit the function parameters, if we have a function type.
+ if (FTL && VisitFunctionTypeLoc(*FTL, true))
+ return true;
+
+ // FIXME: Attributes?
+ }
+
if (ND->isThisDeclarationADefinition() &&
Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
return true;
@@ -622,6 +758,46 @@ bool CursorVisitor::VisitVarDecl(VarDecl *D) {
return false;
}
+bool CursorVisitor::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+ if (VisitDeclaratorDecl(D))
+ return true;
+
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
+ if (Expr *DefArg = D->getDefaultArgument())
+ return Visit(MakeCXCursor(DefArg, StmtParent, TU));
+
+ return false;
+}
+
+bool CursorVisitor::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ // FIXME: Visit the "outer" template parameter lists on the FunctionDecl
+ // before visiting these template parameters.
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ return VisitFunctionDecl(D->getTemplatedDecl());
+}
+
+bool CursorVisitor::VisitClassTemplateDecl(ClassTemplateDecl *D) {
+ // FIXME: Visit the "outer" template parameter lists on the TagDecl
+ // before visiting these template parameters.
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ return VisitCXXRecordDecl(D->getTemplatedDecl());
+}
+
+bool CursorVisitor::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+ if (VisitTemplateParameters(D->getTemplateParameters()))
+ return true;
+
+ if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited() &&
+ VisitTemplateArgumentLoc(D->getDefaultArgument()))
+ return true;
+
+ return false;
+}
+
bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
if (TypeSourceInfo *TSInfo = ND->getResultTypeSourceInfo())
if (Visit(TSInfo->getTypeLoc()))
@@ -773,10 +949,207 @@ bool CursorVisitor::VisitNamespaceDecl(NamespaceDecl *D) {
return VisitDeclContext(D);
}
+bool CursorVisitor::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = D->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, D->getQualifierRange()))
+ return true;
+
+ return Visit(MakeCursorNamespaceRef(D->getAliasedNamespace(),
+ D->getTargetNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitUsingDecl(UsingDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = D->getTargetNestedNameDecl())
+ if (VisitNestedNameSpecifier(Qualifier, D->getNestedNameRange()))
+ return true;
+
+ // FIXME: Provide a multi-reference of some kind for all of the declarations
+ // that the using declaration refers to. We don't have this kind of cursor
+ // yet.
+
+ return VisitDeclarationNameInfo(D->getNameInfo());
+}
+
+bool CursorVisitor::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = D->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, D->getQualifierRange()))
+ return true;
+
+ return Visit(MakeCursorNamespaceRef(D->getNominatedNamespaceAsWritten(),
+ D->getIdentLocation(), TU));
+}
+
+bool CursorVisitor::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = D->getTargetNestedNameSpecifier())
+ if (VisitNestedNameSpecifier(Qualifier, D->getTargetNestedNameRange()))
+ return true;
+
+ return VisitDeclarationNameInfo(D->getNameInfo());
+}
+
+bool CursorVisitor::VisitUnresolvedUsingTypenameDecl(
+ UnresolvedUsingTypenameDecl *D) {
+ // Visit nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = D->getTargetNestedNameSpecifier())
+ if (VisitNestedNameSpecifier(Qualifier, D->getTargetNestedNameRange()))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitDeclarationNameInfo(DeclarationNameInfo Name) {
+ switch (Name.getName().getNameKind()) {
+ case clang::DeclarationName::Identifier:
+ case clang::DeclarationName::CXXLiteralOperatorName:
+ case clang::DeclarationName::CXXOperatorName:
+ case clang::DeclarationName::CXXUsingDirective:
+ return false;
+
+ case clang::DeclarationName::CXXConstructorName:
+ case clang::DeclarationName::CXXDestructorName:
+ case clang::DeclarationName::CXXConversionFunctionName:
+ if (TypeSourceInfo *TSInfo = Name.getNamedTypeInfo())
+ return Visit(TSInfo->getTypeLoc());
+ return false;
+
+ case clang::DeclarationName::ObjCZeroArgSelector:
+ case clang::DeclarationName::ObjCOneArgSelector:
+ case clang::DeclarationName::ObjCMultiArgSelector:
+ // FIXME: Per-identifier location info?
+ return false;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitNestedNameSpecifier(NestedNameSpecifier *NNS,
+ SourceRange Range) {
+ // FIXME: This whole routine is a hack to work around the lack of proper
+ // source information in nested-name-specifiers (PR5791). Since we do have
+ // a beginning source location, we can visit the first component of the
+ // nested-name-specifier, if it's a single-token component.
+ if (!NNS)
+ return false;
+
+ // Get the first component in the nested-name-specifier.
+ while (NestedNameSpecifier *Prefix = NNS->getPrefix())
+ NNS = Prefix;
+
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Namespace:
+ // FIXME: The token at this source location might actually have been a
+ // namespace alias, but we don't model that. Lame!
+ return Visit(MakeCursorNamespaceRef(NNS->getAsNamespace(), Range.getBegin(),
+ TU));
+
+ case NestedNameSpecifier::TypeSpec: {
+ // If the type has a form where we know that the beginning of the source
+ // range matches up with a reference cursor. Visit the appropriate reference
+ // cursor.
+ Type *T = NNS->getAsType();
+ if (const TypedefType *Typedef = dyn_cast<TypedefType>(T))
+ return Visit(MakeCursorTypeRef(Typedef->getDecl(), Range.getBegin(), TU));
+ if (const TagType *Tag = dyn_cast<TagType>(T))
+ return Visit(MakeCursorTypeRef(Tag->getDecl(), Range.getBegin(), TU));
+ if (const TemplateSpecializationType *TST
+ = dyn_cast<TemplateSpecializationType>(T))
+ return VisitTemplateName(TST->getTemplateName(), Range.getBegin());
+ break;
+ }
+
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ case NestedNameSpecifier::Global:
+ case NestedNameSpecifier::Identifier:
+ break;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitTemplateParameters(
+ const TemplateParameterList *Params) {
+ if (!Params)
+ return false;
+
+ for (TemplateParameterList::const_iterator P = Params->begin(),
+ PEnd = Params->end();
+ P != PEnd; ++P) {
+ if (Visit(MakeCXCursor(*P, TU)))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitTemplateName(TemplateName Name, SourceLocation Loc) {
+ switch (Name.getKind()) {
+ case TemplateName::Template:
+ return Visit(MakeCursorTemplateRef(Name.getAsTemplateDecl(), Loc, TU));
+
+ case TemplateName::OverloadedTemplate:
+ // FIXME: We need a way to return multiple lookup results in a single
+ // cursor.
+ return false;
+
+ case TemplateName::DependentTemplate:
+ // FIXME: Visit nested-name-specifier.
+ return false;
+
+ case TemplateName::QualifiedTemplate:
+ // FIXME: Visit nested-name-specifier.
+ return Visit(MakeCursorTemplateRef(
+ Name.getAsQualifiedTemplateName()->getDecl(),
+ Loc, TU));
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitTemplateArgumentLoc(const TemplateArgumentLoc &TAL) {
+ switch (TAL.getArgument().getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Integral:
+ return false;
+
+ case TemplateArgument::Pack:
+ // FIXME: Implement when variadic templates come along.
+ return false;
+
+ case TemplateArgument::Type:
+ if (TypeSourceInfo *TSInfo = TAL.getTypeSourceInfo())
+ return Visit(TSInfo->getTypeLoc());
+ return false;
+
+ case TemplateArgument::Declaration:
+ if (Expr *E = TAL.getSourceDeclExpression())
+ return Visit(MakeCXCursor(E, StmtParent, TU));
+ return false;
+
+ case TemplateArgument::Expression:
+ if (Expr *E = TAL.getSourceExpression())
+ return Visit(MakeCXCursor(E, StmtParent, TU));
+ return false;
+
+ case TemplateArgument::Template:
+ return VisitTemplateName(TAL.getArgument().getAsTemplate(),
+ TAL.getTemplateNameLoc());
+ }
+
+ return false;
+}
+
bool CursorVisitor::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
return VisitDeclContext(D);
}
+bool CursorVisitor::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ return Visit(TL.getUnqualifiedLoc());
+}
+
bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
ASTContext &Context = TU->getASTContext();
@@ -848,6 +1221,13 @@ bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) {
return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
}
+bool CursorVisitor::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
+ // FIXME: We can't visit the template template parameter, but there's
+ // no context information with which we can match up the depth/index in the
+ // type to the appropriate
+ return false;
+}
+
bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
if (Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU)))
return true;
@@ -892,8 +1272,9 @@ bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
return Visit(TL.getPointeeLoc());
}
-bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
- if (Visit(TL.getResultLoc()))
+bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL,
+ bool SkipResultType) {
+ if (!SkipResultType && Visit(TL.getResultLoc()))
return true;
for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
@@ -914,6 +1295,21 @@ bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) {
return false;
}
+bool CursorVisitor::VisitTemplateSpecializationTypeLoc(
+ TemplateSpecializationTypeLoc TL) {
+ // Visit the template name.
+ if (VisitTemplateName(TL.getTypePtr()->getTemplateName(),
+ TL.getTemplateNameLoc()))
+ return true;
+
+ // Visit the template arguments.
+ for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
+ if (VisitTemplateArgumentLoc(TL.getArgLoc(I)))
+ return true;
+
+ return false;
+}
+
bool CursorVisitor::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
return Visit(MakeCXCursor(TL.getUnderlyingExpr(), StmtParent, TU));
}
@@ -1054,6 +1450,56 @@ bool CursorVisitor::VisitForStmt(ForStmt *S) {
return false;
}
+bool CursorVisitor::VisitDeclRefExpr(DeclRefExpr *E) {
+ // Visit nested-name-specifier, if present.
+ if (NestedNameSpecifier *Qualifier = E->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, E->getQualifierRange()))
+ return true;
+
+ // Visit declaration name.
+ if (VisitDeclarationNameInfo(E->getNameInfo()))
+ return true;
+
+ // Visit explicitly-specified template arguments.
+ if (E->hasExplicitTemplateArgs()) {
+ ExplicitTemplateArgumentList &Args = E->getExplicitTemplateArgs();
+ for (TemplateArgumentLoc *Arg = Args.getTemplateArgs(),
+ *ArgEnd = Arg + Args.NumTemplateArgs;
+ Arg != ArgEnd; ++Arg)
+ if (VisitTemplateArgumentLoc(*Arg))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
+ if (Visit(MakeCXCursor(E->getArg(0), StmtParent, TU)))
+ return true;
+
+ if (Visit(MakeCXCursor(E->getCallee(), StmtParent, TU)))
+ return true;
+
+ for (unsigned I = 1, N = E->getNumArgs(); I != N; ++I)
+ if (Visit(MakeCXCursor(E->getArg(I), StmtParent, TU)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) {
+ if (D->isDefinition()) {
+ for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
+ E = D->bases_end(); I != E; ++I) {
+ if (Visit(cxcursor::MakeCursorCXXBaseSpecifier(I, TU)))
+ return true;
+ }
+ }
+
+ return VisitTagDecl(D);
+}
+
+
bool CursorVisitor::VisitBlockExpr(BlockExpr *B) {
return Visit(B->getBlockDecl());
}
@@ -1077,6 +1523,34 @@ bool CursorVisitor::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
return VisitExpr(E);
}
+bool CursorVisitor::VisitMemberExpr(MemberExpr *E) {
+ // Visit the base expression.
+ if (Visit(MakeCXCursor(E->getBase(), StmtParent, TU)))
+ return true;
+
+ // Visit the nested-name-specifier
+ if (NestedNameSpecifier *Qualifier = E->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, E->getQualifierRange()))
+ return true;
+
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(E->getMemberNameInfo()))
+ return true;
+
+ // Visit the explicitly-specified template arguments, if any.
+ if (E->hasExplicitTemplateArgs()) {
+ for (const TemplateArgumentLoc *Arg = E->getTemplateArgs(),
+ *ArgEnd = Arg + E->getNumTemplateArgs();
+ Arg != ArgEnd;
+ ++Arg) {
+ if (VisitTemplateArgumentLoc(*Arg))
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool CursorVisitor::VisitExplicitCastExpr(ExplicitCastExpr *E) {
if (TypeSourceInfo *TSInfo = E->getTypeInfoAsWritten())
if (Visit(TSInfo->getTypeLoc()))
@@ -1093,6 +1567,143 @@ bool CursorVisitor::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
return VisitExpr(E);
}
+bool CursorVisitor::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
+ return Visit(E->getArgTInfo1()->getTypeLoc()) ||
+ Visit(E->getArgTInfo2()->getTypeLoc());
+}
+
+bool CursorVisitor::VisitVAArgExpr(VAArgExpr *E) {
+ if (Visit(E->getWrittenTypeInfo()->getTypeLoc()))
+ return true;
+
+ return Visit(MakeCXCursor(E->getSubExpr(), StmtParent, TU));
+}
+
+bool CursorVisitor::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
+ if (E->isTypeOperand()) {
+ if (TypeSourceInfo *TSInfo = E->getTypeOperandSourceInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
+ }
+
+ return VisitExpr(E);
+}
+
+bool CursorVisitor::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) {
+ // Visit base expression.
+ if (Visit(MakeCXCursor(E->getBase(), StmtParent, TU)))
+ return true;
+
+ // Visit the nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = E->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, E->getQualifierRange()))
+ return true;
+
+ // Visit the scope type that looks disturbingly like the nested-name-specifier
+ // but isn't.
+ if (TypeSourceInfo *TSInfo = E->getScopeTypeInfo())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ // Visit the name of the type being destroyed.
+ if (TypeSourceInfo *TSInfo = E->getDestroyedTypeInfo())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitOverloadExpr(OverloadExpr *E) {
+ // Visit the nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = E->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, E->getQualifierRange()))
+ return true;
+
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(E->getNameInfo()))
+ return true;
+
+ // Visit the explicitly-specified template arguments.
+ if (const ExplicitTemplateArgumentList *ArgList
+ = E->getOptionalExplicitTemplateArgs()) {
+ for (const TemplateArgumentLoc *Arg = ArgList->getTemplateArgs(),
+ *ArgEnd = Arg + ArgList->NumTemplateArgs;
+ Arg != ArgEnd; ++Arg) {
+ if (VisitTemplateArgumentLoc(*Arg))
+ return true;
+ }
+ }
+
+ // FIXME: We don't have a way to visit all of the declarations referenced
+ // here.
+ return false;
+}
+
+bool CursorVisitor::VisitDependentScopeDeclRefExpr(
+ DependentScopeDeclRefExpr *E) {
+ // Visit the nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = E->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, E->getQualifierRange()))
+ return true;
+
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(E->getNameInfo()))
+ return true;
+
+ // Visit the explicitly-specified template arguments.
+ if (const ExplicitTemplateArgumentList *ArgList
+ = E->getOptionalExplicitTemplateArgs()) {
+ for (const TemplateArgumentLoc *Arg = ArgList->getTemplateArgs(),
+ *ArgEnd = Arg + ArgList->NumTemplateArgs;
+ Arg != ArgEnd; ++Arg) {
+ if (VisitTemplateArgumentLoc(*Arg))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitCXXDependentScopeMemberExpr(
+ CXXDependentScopeMemberExpr *E) {
+ // Visit the base expression, if there is one.
+ if (!E->isImplicitAccess() &&
+ Visit(MakeCXCursor(E->getBase(), StmtParent, TU)))
+ return true;
+
+ // Visit the nested-name-specifier.
+ if (NestedNameSpecifier *Qualifier = E->getQualifier())
+ if (VisitNestedNameSpecifier(Qualifier, E->getQualifierRange()))
+ return true;
+
+ // Visit the declaration name.
+ if (VisitDeclarationNameInfo(E->getMemberNameInfo()))
+ return true;
+
+ // Visit the explicitly-specified template arguments.
+ if (const ExplicitTemplateArgumentList *ArgList
+ = E->getOptionalExplicitTemplateArgs()) {
+ for (const TemplateArgumentLoc *Arg = ArgList->getTemplateArgs(),
+ *ArgEnd = Arg + ArgList->NumTemplateArgs;
+ Arg != ArgEnd; ++Arg) {
+ if (VisitTemplateArgumentLoc(*Arg))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitUnresolvedMemberExpr(UnresolvedMemberExpr *E) {
+ // Visit the base expression, if there is one.
+ if (!E->isImplicitAccess() &&
+ Visit(MakeCXCursor(E->getBase(), StmtParent, TU)))
+ return true;
+
+ return VisitOverloadExpr(E);
+}
+
bool CursorVisitor::VisitObjCMessageExpr(ObjCMessageExpr *E) {
if (TypeSourceInfo *TSInfo = E->getClassReceiverTypeInfo())
if (Visit(TSInfo->getTypeLoc()))
@@ -1107,8 +1718,9 @@ bool CursorVisitor::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
bool CursorVisitor::VisitAttributes(Decl *D) {
- for (const Attr *A = D->getAttrs(); A; A = A->getNext())
- if (Visit(MakeCXCursor(A, D, TU)))
+ for (AttrVec::const_iterator i = D->attr_begin(), e = D->attr_end();
+ i != e; ++i)
+ if (Visit(MakeCXCursor(*i, D, TU)))
return true;
return false;
@@ -1117,6 +1729,10 @@ bool CursorVisitor::VisitAttributes(Decl *D) {
extern "C" {
CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
int displayDiagnostics) {
+ // We use crash recovery to make some of our APIs more reliable, implicitly
+ // enable it.
+ llvm::CrashRecoveryContext::Enable();
+
CIndexer *CIdxr = new CIndexer();
if (excludeDeclarationsFromPCH)
CIdxr->setOnlyLocalDecls();
@@ -1128,6 +1744,8 @@ CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
void clang_disposeIndex(CXIndex CIdx) {
if (CIdx)
delete static_cast<CIndexer *>(CIdx);
+ if (getenv("LIBCLANG_TIMING"))
+ llvm::TimerGroup::printAll(llvm::errs());
}
void clang_setUseExternalASTGeneration(CXIndex CIdx, int value) {
@@ -1145,23 +1763,61 @@ CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,
CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
- return ASTUnit::LoadFromPCHFile(ast_filename, Diags,
+ return ASTUnit::LoadFromASTFile(ast_filename, Diags,
CXXIdx->getOnlyLocalDecls(),
0, 0, true);
}
+unsigned clang_defaultEditingTranslationUnitOptions() {
+ return CXTranslationUnit_PrecompiledPreamble;
+}
+
CXTranslationUnit
clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
const char *source_filename,
int num_command_line_args,
- const char **command_line_args,
+ const char * const *command_line_args,
unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files) {
+ return clang_parseTranslationUnit(CIdx, source_filename,
+ command_line_args, num_command_line_args,
+ unsaved_files, num_unsaved_files,
+ CXTranslationUnit_DetailedPreprocessingRecord);
+}
+
+struct ParseTranslationUnitInfo {
+ CXIndex CIdx;
+ const char *source_filename;
+ const char *const *command_line_args;
+ int num_command_line_args;
+ struct CXUnsavedFile *unsaved_files;
+ unsigned num_unsaved_files;
+ unsigned options;
+ CXTranslationUnit result;
+};
+static void clang_parseTranslationUnit_Impl(void *UserData) {
+ ParseTranslationUnitInfo *PTUI =
+ static_cast<ParseTranslationUnitInfo*>(UserData);
+ CXIndex CIdx = PTUI->CIdx;
+ const char *source_filename = PTUI->source_filename;
+ const char * const *command_line_args = PTUI->command_line_args;
+ int num_command_line_args = PTUI->num_command_line_args;
+ struct CXUnsavedFile *unsaved_files = PTUI->unsaved_files;
+ unsigned num_unsaved_files = PTUI->num_unsaved_files;
+ unsigned options = PTUI->options;
+ PTUI->result = 0;
+
if (!CIdx)
- return 0;
+ return;
CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+ bool PrecompilePreamble = options & CXTranslationUnit_PrecompiledPreamble;
+ bool CompleteTranslationUnit
+ = ((options & CXTranslationUnit_Incomplete) == 0);
+ bool CacheCodeCompetionResults
+ = options & CXTranslationUnit_CacheCompletionResults;
+
// Configure the diagnostics.
DiagnosticOptions DiagOpts;
llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
@@ -1195,8 +1851,13 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
Args.insert(Args.end(), command_line_args,
command_line_args + num_command_line_args);
- Args.push_back("-Xclang");
- Args.push_back("-detailed-preprocessing-record");
+
+ // Do we need the detailed preprocessing record?
+ if (options & CXTranslationUnit_DetailedPreprocessingRecord) {
+ Args.push_back("-Xclang");
+ Args.push_back("-detailed-preprocessing-record");
+ }
+
unsigned NumErrors = Diags->getNumErrors();
#ifdef USE_CRASHTRACER
@@ -1210,7 +1871,10 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
CXXIdx->getOnlyLocalDecls(),
RemappedFiles.data(),
RemappedFiles.size(),
- /*CaptureDiagnostics=*/true));
+ /*CaptureDiagnostics=*/true,
+ PrecompilePreamble,
+ CompleteTranslationUnit,
+ CacheCodeCompetionResults));
if (NumErrors != Diags->getNumErrors()) {
// Make sure to check that 'Unit' is non-NULL.
@@ -1233,7 +1897,8 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
}
}
- return Unit.take();
+ PTUI->result = Unit.take();
+ return;
}
// Build up the arguments for invoking 'clang'.
@@ -1269,7 +1934,7 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
std::vector<llvm::sys::Path> TemporaryFiles;
std::vector<std::string> RemapArgs;
if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
- return 0;
+ return;
// The pointers into the elements of RemapArgs are stable because we
// won't be adding anything to RemapArgs after this point.
@@ -1300,9 +1965,12 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
TemporaryFiles.push_back(DiagnosticsFile);
argv.push_back("-fdiagnostics-binary");
- argv.push_back("-Xclang");
- argv.push_back("-detailed-preprocessing-record");
-
+ // Do we need the detailed preprocessing record?
+ if (options & CXTranslationUnit_DetailedPreprocessingRecord) {
+ argv.push_back("-Xclang");
+ argv.push_back("-detailed-preprocessing-record");
+ }
+
// Add the null terminator.
argv.push_back(NULL);
@@ -1328,7 +1996,7 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
Diags->Report(diag::err_fe_invoking) << AllArgs << ErrMsg;
}
- ASTUnit *ATU = ASTUnit::LoadFromPCHFile(astTmpFile, Diags,
+ ASTUnit *ATU = ASTUnit::LoadFromASTFile(astTmpFile, Diags,
CXXIdx->getOnlyLocalDecls(),
RemappedFiles.data(),
RemappedFiles.size(),
@@ -1373,7 +2041,7 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
// Make the translation unit responsible for destroying all temporary files.
for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
ATU->addTemporaryFile(TemporaryFiles[i]);
- ATU->addTemporaryFile(llvm::sys::Path(ATU->getPCHFileName()));
+ ATU->addTemporaryFile(llvm::sys::Path(ATU->getASTFileName()));
} else {
// Destroy all of the temporary files now; they can't be referenced any
// longer.
@@ -1382,13 +2050,124 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
TemporaryFiles[i].eraseFromDisk();
}
- return ATU;
+ PTUI->result = ATU;
+}
+CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx,
+ const char *source_filename,
+ const char * const *command_line_args,
+ int num_command_line_args,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned num_unsaved_files,
+ unsigned options) {
+ ParseTranslationUnitInfo PTUI = { CIdx, source_filename, command_line_args,
+ num_command_line_args, unsaved_files, num_unsaved_files,
+ options, 0 };
+ llvm::CrashRecoveryContext CRC;
+
+ if (!CRC.RunSafely(clang_parseTranslationUnit_Impl, &PTUI)) {
+ fprintf(stderr, "libclang: crash detected during parsing: {\n");
+ fprintf(stderr, " 'source_filename' : '%s'\n", source_filename);
+ fprintf(stderr, " 'command_line_args' : [");
+ for (int i = 0; i != num_command_line_args; ++i) {
+ if (i)
+ fprintf(stderr, ", ");
+ fprintf(stderr, "'%s'", command_line_args[i]);
+ }
+ fprintf(stderr, "],\n");
+ fprintf(stderr, " 'unsaved_files' : [");
+ for (unsigned i = 0; i != num_unsaved_files; ++i) {
+ if (i)
+ fprintf(stderr, ", ");
+ fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename,
+ unsaved_files[i].Length);
+ }
+ fprintf(stderr, "],\n");
+ fprintf(stderr, " 'options' : %d,\n", options);
+ fprintf(stderr, "}\n");
+
+ return 0;
+ }
+
+ return PTUI.result;
+}
+
+unsigned clang_defaultSaveOptions(CXTranslationUnit TU) {
+ return CXSaveTranslationUnit_None;
+}
+
+int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName,
+ unsigned options) {
+ if (!TU)
+ return 1;
+
+ return static_cast<ASTUnit *>(TU)->Save(FileName);
}
void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) {
- if (CTUnit)
+ if (CTUnit) {
+ // If the translation unit has been marked as unsafe to free, just discard
+ // it.
+ if (static_cast<ASTUnit *>(CTUnit)->isUnsafeToFree())
+ return;
+
delete static_cast<ASTUnit *>(CTUnit);
+ }
+}
+
+unsigned clang_defaultReparseOptions(CXTranslationUnit TU) {
+ return CXReparse_None;
+}
+
+struct ReparseTranslationUnitInfo {
+ CXTranslationUnit TU;
+ unsigned num_unsaved_files;
+ struct CXUnsavedFile *unsaved_files;
+ unsigned options;
+ int result;
+};
+static void clang_reparseTranslationUnit_Impl(void *UserData) {
+ ReparseTranslationUnitInfo *RTUI =
+ static_cast<ReparseTranslationUnitInfo*>(UserData);
+ CXTranslationUnit TU = RTUI->TU;
+ unsigned num_unsaved_files = RTUI->num_unsaved_files;
+ struct CXUnsavedFile *unsaved_files = RTUI->unsaved_files;
+ unsigned options = RTUI->options;
+ (void) options;
+ RTUI->result = 1;
+
+ if (!TU)
+ return;
+
+ llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
+ for (unsigned I = 0; I != num_unsaved_files; ++I) {
+ llvm::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,
+ Buffer));
+ }
+
+ if (!static_cast<ASTUnit *>(TU)->Reparse(RemappedFiles.data(),
+ RemappedFiles.size()))
+ RTUI->result = 0;
}
+int clang_reparseTranslationUnit(CXTranslationUnit TU,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files,
+ unsigned options) {
+ ReparseTranslationUnitInfo RTUI = { TU, num_unsaved_files, unsaved_files,
+ options, 0 };
+ llvm::CrashRecoveryContext CRC;
+
+ if (!CRC.RunSafely(clang_reparseTranslationUnit_Impl, &RTUI)) {
+ fprintf(stderr, "libclang: crash detected during reparsing\n");
+ static_cast<ASTUnit *>(TU)->setUnsafeToFree(true);
+ return 1;
+ }
+
+ return RTUI.result;
+}
+
CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) {
if (!CTUnit)
@@ -1574,18 +2353,8 @@ unsigned clang_visitChildren(CXCursor parent,
CXClientData client_data) {
ASTUnit *CXXUnit = getCursorASTUnit(parent);
- unsigned PCHLevel = Decl::MaxPCHLevel;
-
- // Set the PCHLevel to filter out unwanted decls if requested.
- if (CXXUnit->getOnlyLocalDecls()) {
- PCHLevel = 0;
-
- // If the main input was an AST, bump the level.
- if (CXXUnit->isMainFileAST())
- ++PCHLevel;
- }
-
- CursorVisitor CursorVis(CXXUnit, visitor, client_data, PCHLevel);
+ CursorVisitor CursorVis(CXXUnit, visitor, client_data,
+ CXXUnit->getMaxPCHLevel());
return CursorVis.VisitChildren(parent);
}
@@ -1603,6 +2372,9 @@ static CXString getDeclSpelling(Decl *D) {
// ObjCCategoryImplDecl returns the category name.
return createCXString(CIMP->getIdentifier()->getNameStart());
+ if (isa<UsingDirectiveDecl>(D))
+ return createCXString("");
+
llvm::SmallString<1024> S;
llvm::raw_svector_ostream os(S);
ND->printName(os);
@@ -1629,6 +2401,10 @@ CXString clang_getCursorSpelling(CXCursor C) {
assert(OID && "getCursorSpelling(): Missing protocol decl");
return createCXString(OID->getIdentifier()->getNameStart());
}
+ case CXCursor_CXXBaseSpecifier: {
+ CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
+ return createCXString(B->getType().getAsString());
+ }
case CXCursor_TypeRef: {
TypeDecl *Type = getCursorTypeRef(C).first;
assert(Type && "Missing type decl");
@@ -1636,6 +2412,19 @@ CXString clang_getCursorSpelling(CXCursor C) {
return createCXString(getCursorContext(C).getTypeDeclType(Type).
getAsString());
}
+ case CXCursor_TemplateRef: {
+ TemplateDecl *Template = getCursorTemplateRef(C).first;
+ assert(Template && "Missing template decl");
+
+ return createCXString(Template->getNameAsString());
+ }
+
+ case CXCursor_NamespaceRef: {
+ NamedDecl *NS = getCursorNamespaceRef(C).first;
+ assert(NS && "Missing namespace decl");
+
+ return createCXString(NS->getNameAsString());
+ }
default:
return createCXString("<not implemented>");
@@ -1715,6 +2504,10 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return createCXString("ObjCClassRef");
case CXCursor_TypeRef:
return createCXString("TypeRef");
+ case CXCursor_TemplateRef:
+ return createCXString("TemplateRef");
+ case CXCursor_NamespaceRef:
+ return createCXString("NamespaceRef");
case CXCursor_UnexposedExpr:
return createCXString("UnexposedExpr");
case CXCursor_BlockExpr:
@@ -1757,6 +2550,32 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return createCXString("Namespace");
case CXCursor_LinkageSpec:
return createCXString("LinkageSpec");
+ case CXCursor_CXXBaseSpecifier:
+ return createCXString("C++ base class specifier");
+ case CXCursor_Constructor:
+ return createCXString("CXXConstructor");
+ case CXCursor_Destructor:
+ return createCXString("CXXDestructor");
+ case CXCursor_ConversionFunction:
+ return createCXString("CXXConversion");
+ case CXCursor_TemplateTypeParameter:
+ return createCXString("TemplateTypeParameter");
+ case CXCursor_NonTypeTemplateParameter:
+ return createCXString("NonTypeTemplateParameter");
+ case CXCursor_TemplateTemplateParameter:
+ return createCXString("TemplateTemplateParameter");
+ case CXCursor_FunctionTemplate:
+ return createCXString("FunctionTemplate");
+ case CXCursor_ClassTemplate:
+ return createCXString("ClassTemplate");
+ case CXCursor_ClassTemplatePartialSpecialization:
+ return createCXString("ClassTemplatePartialSpecialization");
+ case CXCursor_NamespaceAlias:
+ return createCXString("NamespaceAlias");
+ case CXCursor_UsingDirective:
+ return createCXString("UsingDirective");
+ case CXCursor_UsingDeclaration:
+ return createCXString("UsingDeclaration");
}
llvm_unreachable("Unhandled CXCursorKind");
@@ -1776,20 +2595,28 @@ CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) {
return clang_getNullCursor();
ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
-
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();
+
+ SLoc = Lexer::GetBeginningOfToken(SLoc, CXXUnit->getSourceManager(),
+ CXXUnit->getASTContext().getLangOptions());
+
CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound);
if (SLoc.isValid()) {
- SourceRange RegionOfInterest(SLoc, SLoc.getFileLocWithOffset(1));
-
// 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.
CXCursor Parent = clang_getTranslationUnitCursor(CXXUnit);
CursorVisitor CursorVis(CXXUnit, GetCursorVisitor, &Result,
- Decl::MaxPCHLevel, RegionOfInterest);
+ Decl::MaxPCHLevel, SourceLocation(SLoc));
CursorVis.VisitChildren(Parent);
}
return Result;
@@ -1873,6 +2700,21 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) {
return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
}
+ case CXCursor_TemplateRef: {
+ std::pair<TemplateDecl *, SourceLocation> P = getCursorTemplateRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_NamespaceRef: {
+ std::pair<NamedDecl *, SourceLocation> P = getCursorNamespaceRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_CXXBaseSpecifier: {
+ // FIXME: Figure out what location to return for a CXXBaseSpecifier.
+ return clang_getNullLocation();
+ }
+
default:
// FIXME: Need a way to enumerate all non-reference cases.
llvm_unreachable("Missed a reference kind");
@@ -1909,67 +2751,68 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) {
return cxloc::translateSourceLocation(getCursorContext(C), Loc);
}
-CXSourceRange clang_getCursorExtent(CXCursor C) {
+} // end extern "C"
+
+static SourceRange getRawCursorExtent(CXCursor C) {
if (clang_isReference(C.kind)) {
switch (C.kind) {
- case CXCursor_ObjCSuperClassRef: {
- std::pair<ObjCInterfaceDecl *, SourceLocation> P
- = getCursorObjCSuperClassRef(C);
- return cxloc::translateSourceRange(P.first->getASTContext(), P.second);
- }
+ case CXCursor_ObjCSuperClassRef:
+ return getCursorObjCSuperClassRef(C).second;
- case CXCursor_ObjCProtocolRef: {
- std::pair<ObjCProtocolDecl *, SourceLocation> P
- = getCursorObjCProtocolRef(C);
- return cxloc::translateSourceRange(P.first->getASTContext(), P.second);
- }
+ case CXCursor_ObjCProtocolRef:
+ return getCursorObjCProtocolRef(C).second;
- case CXCursor_ObjCClassRef: {
- std::pair<ObjCInterfaceDecl *, SourceLocation> P
- = getCursorObjCClassRef(C);
+ case CXCursor_ObjCClassRef:
+ return getCursorObjCClassRef(C).second;
- return cxloc::translateSourceRange(P.first->getASTContext(), P.second);
- }
+ case CXCursor_TypeRef:
+ return getCursorTypeRef(C).second;
- case CXCursor_TypeRef: {
- std::pair<TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
- return cxloc::translateSourceRange(P.first->getASTContext(), P.second);
- }
+ case CXCursor_TemplateRef:
+ return getCursorTemplateRef(C).second;
+
+ case CXCursor_NamespaceRef:
+ return getCursorNamespaceRef(C).second;
+
+ case CXCursor_CXXBaseSpecifier:
+ // FIXME: Figure out what source range to use for a CXBaseSpecifier.
+ return SourceRange();
- default:
- // FIXME: Need a way to enumerate all non-reference cases.
- llvm_unreachable("Missed a reference kind");
+ default:
+ // FIXME: Need a way to enumerate all non-reference cases.
+ llvm_unreachable("Missed a reference kind");
}
}
if (clang_isExpression(C.kind))
- return cxloc::translateSourceRange(getCursorContext(C),
- getCursorExpr(C)->getSourceRange());
+ return getCursorExpr(C)->getSourceRange();
if (clang_isStatement(C.kind))
- return cxloc::translateSourceRange(getCursorContext(C),
- getCursorStmt(C)->getSourceRange());
+ return getCursorStmt(C)->getSourceRange();
- if (C.kind == CXCursor_PreprocessingDirective) {
- SourceRange R = cxcursor::getCursorPreprocessingDirective(C);
- return cxloc::translateSourceRange(getCursorContext(C), R);
- }
+ if (C.kind == CXCursor_PreprocessingDirective)
+ return cxcursor::getCursorPreprocessingDirective(C);
- if (C.kind == CXCursor_MacroInstantiation) {
- SourceRange R = cxcursor::getCursorMacroInstantiation(C)->getSourceRange();
- return cxloc::translateSourceRange(getCursorContext(C), R);
- }
+ if (C.kind == CXCursor_MacroInstantiation)
+ return cxcursor::getCursorMacroInstantiation(C)->getSourceRange();
- if (C.kind == CXCursor_MacroDefinition) {
- SourceRange R = cxcursor::getCursorMacroDefinition(C)->getSourceRange();
- return cxloc::translateSourceRange(getCursorContext(C), R);
- }
+ if (C.kind == CXCursor_MacroDefinition)
+ return cxcursor::getCursorMacroDefinition(C)->getSourceRange();
- if (C.kind < CXCursor_FirstDecl || C.kind > CXCursor_LastDecl)
+ if (C.kind >= CXCursor_FirstDecl && C.kind <= CXCursor_LastDecl)
+ return getCursorDecl(C)->getSourceRange();
+
+ return SourceRange();
+}
+
+extern "C" {
+
+CXSourceRange clang_getCursorExtent(CXCursor C) {
+ SourceRange R = getRawCursorExtent(C);
+ if (R.isInvalid())
return clang_getNullRange();
- Decl *D = getCursorDecl(C);
- return cxloc::translateSourceRange(getCursorContext(C), D->getSourceRange());
+ return cxloc::translateSourceRange(getCursorContext(C), R);
}
CXCursor clang_getCursorReferenced(CXCursor C) {
@@ -2008,6 +2851,18 @@ CXCursor clang_getCursorReferenced(CXCursor C) {
case CXCursor_TypeRef:
return MakeCXCursor(getCursorTypeRef(C).first, CXXUnit);
+ case CXCursor_TemplateRef:
+ return MakeCXCursor(getCursorTemplateRef(C).first, CXXUnit);
+
+ case CXCursor_NamespaceRef:
+ return MakeCXCursor(getCursorNamespaceRef(C).first, CXXUnit);
+
+ case CXCursor_CXXBaseSpecifier: {
+ CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C);
+ return clang_getTypeDeclaration(cxtype::MakeCXType(B->getType(),
+ CXXUnit));
+ }
+
default:
// We would prefer to enumerate all non-reference cursor kinds here.
llvm_unreachable("Unhandled reference cursor kind");
@@ -2118,8 +2973,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
case Decl::ClassTemplate: {
if (RecordDecl *Def = cast<ClassTemplateDecl>(D)->getTemplatedDecl()
->getDefinition())
- return MakeCXCursor(
- cast<CXXRecordDecl>(Def)->getDescribedClassTemplate(),
+ return MakeCXCursor(cast<CXXRecordDecl>(Def)->getDescribedClassTemplate(),
CXXUnit);
return clang_getNullCursor();
}
@@ -2530,8 +3384,7 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
return CXChildVisit_Recurse;
}
- CXSourceRange cursorExtent = clang_getCursorExtent(cursor);
- SourceRange cursorRange = cxloc::translateCXSourceRange(cursorExtent);
+ SourceRange cursorRange = getRawCursorExtent(cursor);
if (cursorRange.isInvalid())
return CXChildVisit_Continue;
@@ -2559,11 +3412,27 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
}
}
+ // If the location of the cursor occurs within a macro instantiation, record
+ // the spelling location of the cursor in our annotation map. We can then
+ // paper over the token labelings during a post-processing step to try and
+ // get cursor mappings for tokens that are the *arguments* of a macro
+ // instantiation.
+ if (L.isMacroID()) {
+ unsigned rawEncoding = SrcMgr.getSpellingLoc(L).getRawEncoding();
+ // Only invalidate the old annotation if it isn't part of a preprocessing
+ // directive. Here we assume that the default construction of CXCursor
+ // results in CXCursor.kind being an initialized value (i.e., 0). If
+ // this isn't the case, we can fix by doing lookup + insertion.
+
+ CXCursor &oldC = Annotated[rawEncoding];
+ if (!clang_isPreprocessing(oldC.kind))
+ oldC = cursor;
+ }
+
const enum CXCursorKind K = clang_getCursorKind(parent);
const CXCursor updateC =
- (clang_isInvalid(K) || K == CXCursor_TranslationUnit ||
- L.isMacroID())
- ? clang_getNullCursor() : parent;
+ (clang_isInvalid(K) || K == CXCursor_TranslationUnit)
+ ? clang_getNullCursor() : parent;
while (MoreTokens()) {
const unsigned I = NextToken();
@@ -2574,7 +3443,6 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
AdvanceToken();
continue;
case RangeAfter:
- return CXChildVisit_Continue;
case RangeOverlap:
break;
}
@@ -2658,11 +3526,9 @@ void clang_annotateTokens(CXTranslationUnit TU,
SourceRange RegionOfInterest;
RegionOfInterest.setBegin(cxloc::translateSourceLocation(
clang_getTokenLocation(TU, Tokens[0])));
-
- SourceLocation End
- = cxloc::translateSourceLocation(clang_getTokenLocation(TU,
- Tokens[NumTokens - 1]));
- RegionOfInterest.setEnd(CXXUnit->getPreprocessor().getLocForEndOfToken(End));
+ RegionOfInterest.setEnd(cxloc::translateSourceLocation(
+ clang_getTokenLocation(TU,
+ Tokens[NumTokens - 1])));
// A mapping from the source locations found when re-lexing or traversing the
// region of interest to the corresponding cursors.
@@ -2811,6 +3677,21 @@ static CXLanguageKind getDeclLanguage(const Decl *D) {
}
extern "C" {
+
+enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) {
+ if (clang_isDeclaration(cursor.kind))
+ if (Decl *D = cxcursor::getCursorDecl(cursor)) {
+ if (D->hasAttr<UnavailableAttr>() ||
+ (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted()))
+ return CXAvailability_Available;
+
+ if (D->hasAttr<DeprecatedAttr>())
+ return CXAvailability_Deprecated;
+ }
+
+ return CXAvailability_Available;
+}
+
CXLanguageKind clang_getCursorLanguage(CXCursor cursor) {
if (clang_isDeclaration(cursor.kind))
return getDeclLanguage(cxcursor::getCursorDecl(cursor));
@@ -2828,13 +3709,35 @@ extern "C" {
unsigned clang_CXXMethod_isStatic(CXCursor C) {
if (!clang_isDeclaration(C.kind))
return 0;
- CXXMethodDecl *D = dyn_cast<CXXMethodDecl>(cxcursor::getCursorDecl(C));
- return (D && D->isStatic()) ? 1 : 0;
+
+ CXXMethodDecl *Method = 0;
+ Decl *D = cxcursor::getCursorDecl(C);
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
+ Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+ else
+ Method = dyn_cast_or_null<CXXMethodDecl>(D);
+ return (Method && Method->isStatic()) ? 1 : 0;
}
} // end: extern "C"
//===----------------------------------------------------------------------===//
+// Attribute introspection.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+CXType clang_getIBOutletCollectionType(CXCursor C) {
+ if (C.kind != CXCursor_IBOutletCollectionAttr)
+ return cxtype::MakeCXType(QualType(), cxcursor::getCursorASTUnit(C));
+
+ IBOutletCollectionAttr *A =
+ cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(C));
+
+ return cxtype::MakeCXType(A->getInterface(), cxcursor::getCursorASTUnit(C));
+}
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
// CXString Operations.
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud