diff options
author | dim <dim@FreeBSD.org> | 2013-12-22 00:07:40 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-12-22 00:07:40 +0000 |
commit | 952eddef9aff85b1e92626e89baaf7a360e2ac85 (patch) | |
tree | df8df0b0067b381eab470a3b8f28d14a552a6340 /tools/libclang | |
parent | ea266cad53e3d49771fa38103913d3ec7a166694 (diff) | |
download | FreeBSD-src-952eddef9aff85b1e92626e89baaf7a360e2ac85.zip FreeBSD-src-952eddef9aff85b1e92626e89baaf7a360e2ac85.tar.gz |
Vendor import of clang release_34 branch r197841 (effectively, 3.4 RC3):
https://llvm.org/svn/llvm-project/cfe/branches/release_34@197841
Diffstat (limited to 'tools/libclang')
-rw-r--r-- | tools/libclang/CIndex.cpp | 318 | ||||
-rw-r--r-- | tools/libclang/CIndexCodeCompletion.cpp | 22 | ||||
-rw-r--r-- | tools/libclang/CIndexHigh.cpp | 2 | ||||
-rw-r--r-- | tools/libclang/CIndexUSRs.cpp | 848 | ||||
-rw-r--r-- | tools/libclang/CIndexer.cpp | 87 | ||||
-rw-r--r-- | tools/libclang/CIndexer.h | 15 | ||||
-rw-r--r-- | tools/libclang/CMakeLists.txt | 22 | ||||
-rw-r--r-- | tools/libclang/CXComment.cpp | 1094 | ||||
-rw-r--r-- | tools/libclang/CXComment.h | 12 | ||||
-rw-r--r-- | tools/libclang/CXCompilationDatabase.cpp | 37 | ||||
-rw-r--r-- | tools/libclang/CXCursor.cpp | 14 | ||||
-rw-r--r-- | tools/libclang/CXSourceLocation.cpp | 41 | ||||
-rw-r--r-- | tools/libclang/CXTranslationUnit.h | 7 | ||||
-rw-r--r-- | tools/libclang/CXType.cpp | 70 | ||||
-rw-r--r-- | tools/libclang/IndexBody.cpp | 4 | ||||
-rw-r--r-- | tools/libclang/IndexDecl.cpp | 15 | ||||
-rw-r--r-- | tools/libclang/Indexing.cpp | 44 | ||||
-rw-r--r-- | tools/libclang/IndexingContext.cpp | 25 | ||||
-rw-r--r-- | tools/libclang/IndexingContext.h | 35 | ||||
-rw-r--r-- | tools/libclang/Makefile | 10 | ||||
-rw-r--r-- | tools/libclang/RecursiveASTVisitor.h | 170 | ||||
-rw-r--r-- | tools/libclang/SimpleFormatContext.h | 75 | ||||
-rw-r--r-- | tools/libclang/libclang.exports | 5 |
23 files changed, 720 insertions, 2252 deletions
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index a43c1ab..f53e5c1 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -22,13 +22,14 @@ #include "CXTranslationUnit.h" #include "CXType.h" #include "CursorVisitor.h" -#include "SimpleFormatContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/Version.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Index/CommentToXML.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Lexer.h" #include "clang/Lex/PreprocessingRecord.h" @@ -42,7 +43,6 @@ #include "llvm/Support/Format.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Mutex.h" -#include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Program.h" #include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/Signals.h" @@ -68,8 +68,7 @@ CXTranslationUnit cxtu::MakeCXTranslationUnit(CIndexer *CIdx, ASTUnit *AU) { D->StringPool = new cxstring::CXStringPool(); D->Diagnostics = 0; D->OverridenCursorsPool = createOverridenCXCursorsPool(); - D->FormatContext = 0; - D->FormatInMemoryUniqueId = 0; + D->CommentToXML = 0; return D; } @@ -308,8 +307,8 @@ bool CursorVisitor::visitDeclsFromFileRegion(FileID File, bool VisitedAtLeastOnce = false; DeclContext *CurDC = 0; - SmallVector<Decl *, 16>::iterator DIt = Decls.begin(); - for (SmallVector<Decl *, 16>::iterator DE = Decls.end(); DIt != DE; ++DIt) { + SmallVectorImpl<Decl *>::iterator DIt = Decls.begin(); + for (SmallVectorImpl<Decl *>::iterator DE = Decls.end(); DIt != DE; ++DIt) { Decl *D = *DIt; if (D->getSourceRange().isInvalid()) continue; @@ -426,6 +425,9 @@ bool CursorVisitor::visitPreprocessedEntities(InputIterator First, continue; PreprocessedEntity *PPE = *First; + if (!PPE) + continue; + if (MacroExpansion *ME = dyn_cast<MacroExpansion>(PPE)) { if (Visit(MakeMacroExpansionCursor(ME, TU))) return true; @@ -528,9 +530,10 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) { if (Cursor.kind == CXCursor_IBOutletCollectionAttr) { const IBOutletCollectionAttr *A = cast<IBOutletCollectionAttr>(cxcursor::getCursorAttr(Cursor)); - if (const ObjCInterfaceType *InterT = A->getInterface()->getAs<ObjCInterfaceType>()) - return Visit(cxcursor::MakeCursorObjCClassRef(InterT->getInterface(), - A->getInterfaceLoc(), TU)); + if (const ObjCObjectType *ObjT = A->getInterface()->getAs<ObjCObjectType>()) + return Visit(cxcursor::MakeCursorObjCClassRef( + ObjT->getInterface(), + A->getInterfaceLoc()->getTypeLoc().getLocStart(), TU)); } // If pointing inside a macro definition, check if the token is an identifier @@ -698,8 +701,9 @@ bool CursorVisitor::VisitClassTemplatePartialSpecializationDecl( return true; // Visit the partial specialization arguments. - const TemplateArgumentLoc *TemplateArgs = D->getTemplateArgsAsWritten(); - for (unsigned I = 0, N = D->getNumTemplateArgsAsWritten(); I != N; ++I) + const ASTTemplateArgumentListInfo *Info = D->getTemplateArgsAsWritten(); + const TemplateArgumentLoc *TemplateArgs = Info->getTemplateArgs(); + for (unsigned I = 0, N = Info->NumTemplateArgs; I != N; ++I) if (VisitTemplateArgumentLoc(TemplateArgs[I])) return true; @@ -743,18 +747,9 @@ bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) { } /// \brief Compare two base or member initializers based on their source order. -static int CompareCXXCtorInitializers(const void* Xp, const void *Yp) { - CXXCtorInitializer const * const *X - = static_cast<CXXCtorInitializer const * const *>(Xp); - CXXCtorInitializer const * const *Y - = static_cast<CXXCtorInitializer const * const *>(Yp); - - if ((*X)->getSourceOrder() < (*Y)->getSourceOrder()) - return -1; - else if ((*X)->getSourceOrder() > (*Y)->getSourceOrder()) - return 1; - else - return 0; +static int CompareCXXCtorInitializers(CXXCtorInitializer *const *X, + CXXCtorInitializer *const *Y) { + return (*X)->getSourceOrder() - (*Y)->getSourceOrder(); } bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) { @@ -1543,6 +1538,10 @@ bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) { return false; } +bool CursorVisitor::VisitDecayedTypeLoc(DecayedTypeLoc TL) { + return Visit(TL.getOriginalLoc()); +} + bool CursorVisitor::VisitTemplateSpecializationTypeLoc( TemplateSpecializationTypeLoc TL) { // Visit the template name. @@ -1795,6 +1794,7 @@ public: } }; class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void> { + friend class OMPClauseEnqueue; VisitorWorkList &WL; CXCursor Parent; public: @@ -1846,6 +1846,8 @@ public: void VisitPseudoObjectExpr(const PseudoObjectExpr *E); void VisitOpaqueValueExpr(const OpaqueValueExpr *E); void VisitLambdaExpr(const LambdaExpr *E); + void VisitOMPExecutableDirective(const OMPExecutableDirective *D); + void VisitOMPParallelDirective(const OMPParallelDirective *D); private: void AddDeclarationNameInfo(const Stmt *S); @@ -1856,6 +1858,7 @@ private: void AddDecl(const Decl *D, bool isFirst = true); void AddTypeLoc(TypeSourceInfo *TI); void EnqueueChildren(const Stmt *S); + void EnqueueChildren(const OMPClause *S); }; } // end anonyous namespace @@ -1904,6 +1907,52 @@ void EnqueueVisitor::EnqueueChildren(const Stmt *S) { VisitorWorkList::iterator I = WL.begin() + size, E = WL.end(); std::reverse(I, E); } +namespace { +class OMPClauseEnqueue : public ConstOMPClauseVisitor<OMPClauseEnqueue> { + EnqueueVisitor *Visitor; + /// \brief Process clauses with list of variables. + template <typename T> + void VisitOMPClauseList(T *Node); +public: + OMPClauseEnqueue(EnqueueVisitor *Visitor) : Visitor(Visitor) { } +#define OPENMP_CLAUSE(Name, Class) \ + void Visit##Class(const Class *C); +#include "clang/Basic/OpenMPKinds.def" +}; + +void OMPClauseEnqueue::VisitOMPDefaultClause(const OMPDefaultClause *C) { } + +template<typename T> +void OMPClauseEnqueue::VisitOMPClauseList(T *Node) { + for (typename T::varlist_const_iterator I = Node->varlist_begin(), + E = Node->varlist_end(); + I != E; ++I) + Visitor->AddStmt(*I); +} + +void OMPClauseEnqueue::VisitOMPPrivateClause(const OMPPrivateClause *C) { + VisitOMPClauseList(C); +} +void OMPClauseEnqueue::VisitOMPFirstprivateClause( + const OMPFirstprivateClause *C) { + VisitOMPClauseList(C); +} +void OMPClauseEnqueue::VisitOMPSharedClause(const OMPSharedClause *C) { + VisitOMPClauseList(C); +} +} + +void EnqueueVisitor::EnqueueChildren(const OMPClause *S) { + unsigned size = WL.size(); + OMPClauseEnqueue Visitor(this); + Visitor.Visit(S); + if (size == WL.size()) + return; + // Now reverse the entries we just added. This will match the DFS + // ordering performed by the worklist. + VisitorWorkList::iterator I = WL.begin() + size, E = WL.end(); + std::reverse(I, E); +} void EnqueueVisitor::VisitAddrLabelExpr(const AddrLabelExpr *E) { WL.push_back(LabelRefVisit(E->getLabel(), E->getLabelLoc(), Parent)); } @@ -2027,7 +2076,6 @@ void EnqueueVisitor::VisitDeclStmt(const DeclStmt *S) { } void EnqueueVisitor::VisitDesignatedInitExpr(const DesignatedInitExpr *E) { AddStmt(E->getInit()); - typedef DesignatedInitExpr::Designator Designator; for (DesignatedInitExpr::const_reverse_designators_iterator D = E->designators_rbegin(), DEnd = E->designators_rend(); D != DEnd; ++D) { @@ -2182,6 +2230,19 @@ void EnqueueVisitor::VisitPseudoObjectExpr(const PseudoObjectExpr *E) { Visit(E->getSyntacticForm()); } +void EnqueueVisitor::VisitOMPExecutableDirective( + const OMPExecutableDirective *D) { + EnqueueChildren(D); + for (ArrayRef<OMPClause *>::iterator I = D->clauses().begin(), + E = D->clauses().end(); + I != E; ++I) + EnqueueChildren(*I); +} + +void EnqueueVisitor::VisitOMPParallelDirective(const OMPParallelDirective *D) { + VisitOMPExecutableDirective(D); +} + void CursorVisitor::EnqueueWorkList(VisitorWorkList &WL, const Stmt *S) { EnqueueVisitor(WL, MakeCXCursor(S, StmtParent, TU,RegionOfInterest)).Visit(S); } @@ -2198,8 +2259,7 @@ bool CursorVisitor::IsInRegionOfInterest(CXCursor C) { bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) { while (!WL.empty()) { // Dequeue the worklist item. - VisitorJob LI = WL.back(); - WL.pop_back(); + VisitorJob LI = WL.pop_back_val(); // Set the Parent field, then back to its old value once we're done. SetParentRAII SetParent(Parent, StmtParent, LI.getParent()); @@ -2363,9 +2423,10 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) { for (LambdaExpr::capture_iterator C = E->explicit_capture_begin(), CEnd = E->explicit_capture_end(); C != CEnd; ++C) { - if (C->capturesThis()) + // FIXME: Lambda init-captures. + if (!C->capturesVariable()) continue; - + if (Visit(MakeCursorVariableRef(C->getCapturedVar(), C->getLocation(), TU))) @@ -2481,10 +2542,6 @@ static void fatal_error_handler(void *user_data, const std::string& reason, extern "C" { CXIndex clang_createIndex(int excludeDeclarationsFromPCH, int displayDiagnostics) { - // Disable pretty stack trace functionality, which will otherwise be a very - // poor citizen of the world and set up all sorts of signal handlers. - llvm::DisablePrettyStackTrace = true; - // We use crash recovery to make some of our APIs more reliable, implicitly // enable it. llvm::CrashRecoveryContext::Enable(); @@ -2540,9 +2597,13 @@ void clang_toggleCrashRecovery(unsigned isEnabled) { CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx, const char *ast_filename) { - if (!CIdx) + if (!CIdx || !ast_filename) return 0; + LOG_FUNC_SECTION { + *Log << ast_filename; + } + CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx); FileSystemOptions FileSystemOpts; @@ -2842,7 +2903,7 @@ void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) { delete CTUnit->StringPool; delete static_cast<CXDiagnosticSetImpl *>(CTUnit->Diagnostics); disposeOverridenCXCursorsPool(CTUnit->OverridenCursorsPool); - delete CTUnit->FormatContext; + delete CTUnit->CommentToXML; delete CTUnit; } } @@ -2995,15 +3056,12 @@ int clang_getFileUniqueID(CXFile file, CXFileUniqueID *outID) { if (!file || !outID) return 1; -#ifdef LLVM_ON_WIN32 - return 1; // inodes not supported on windows. -#else FileEntry *FEnt = static_cast<FileEntry *>(file); - outID->data[0] = FEnt->getDevice(); - outID->data[1] = FEnt->getInode(); + const llvm::sys::fs::UniqueID &ID = FEnt->getUniqueID(); + outID->data[0] = ID.getDevice(); + outID->data[1] = ID.getFile(); outID->data[2] = FEnt->getModificationTime(); return 0; -#endif } } // end: extern "C" @@ -3289,6 +3347,10 @@ CXString clang_getCursorSpelling(CXCursor C) { return cxstring::createDup(AA->getLabel()); } + if (C.kind == CXCursor_PackedAttr) { + return cxstring::createRef("packed"); + } + return cxstring::createEmpty(); } @@ -3706,6 +3768,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("attribute(annotate)"); case CXCursor_AsmLabelAttr: return cxstring::createRef("asm label"); + case CXCursor_PackedAttr: + return cxstring::createRef("attribute(packed)"); case CXCursor_PreprocessingDirective: return cxstring::createRef("preprocessing directive"); case CXCursor_MacroDefinition: @@ -3754,6 +3818,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return cxstring::createRef("CXXAccessSpecifier"); case CXCursor_ModuleImportDecl: return cxstring::createRef("ModuleImport"); + case CXCursor_OMPParallelDirective: + return cxstring::createRef("OMPParallelDirective"); } llvm_unreachable("Unhandled CXCursorKind"); @@ -4111,6 +4177,12 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) { return cxloc::translateSourceLocation(getCursorContext(C), L); } + if (clang_isAttribute(C.kind)) { + SourceLocation L + = cxcursor::getCursorAttr(C)->getLocation(); + return cxloc::translateSourceLocation(getCursorContext(C), L); + } + if (!clang_isDeclaration(C.kind)) return clang_getNullLocation(); @@ -4521,7 +4593,9 @@ CXCursor clang_getCursorDefinition(CXCursor C) { return clang_getNullCursor(); } - case Decl::Var: { + case Decl::Var: + case Decl::VarTemplateSpecialization: + case Decl::VarTemplatePartialSpecialization: { // Ask the variable if it has a definition. if (const VarDecl *Def = cast<VarDecl>(D)->getDefinition()) return MakeCXCursor(Def, TU); @@ -4543,6 +4617,13 @@ CXCursor clang_getCursorDefinition(CXCursor C) { return clang_getNullCursor(); } + case Decl::VarTemplate: { + if (VarDecl *Def = + cast<VarTemplateDecl>(D)->getTemplatedDecl()->getDefinition()) + return MakeCXCursor(cast<VarDecl>(Def)->getDescribedVarTemplate(), TU); + return clang_getNullCursor(); + } + case Decl::Using: return MakeCursorOverloadedDeclRef(cast<UsingDecl>(D), D->getLocation(), TU); @@ -5171,6 +5252,11 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) { HasContextSensitiveKeywords = true; } } + + // Don't override a property annotation with its getter/setter method. + if (cursor.kind == CXCursor_ObjCInstanceMethodDecl && + parent.kind == CXCursor_ObjCPropertyDecl) + return CXChildVisit_Continue; if (clang_isPreprocessing(cursor.kind)) { // Items in the preprocessing record are kept separate from items in @@ -5678,8 +5764,9 @@ CXLinkageKind clang_getCursorLinkage(CXCursor cursor) { const Decl *D = cxcursor::getCursorDecl(cursor); if (const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D)) - switch (ND->getLinkage()) { - case NoLinkage: return CXLinkage_NoLinkage; + switch (ND->getLinkageInternal()) { + case NoLinkage: + case VisibleNoLinkage: return CXLinkage_NoLinkage; case InternalLinkage: return CXLinkage_Internal; case UniqueExternalLinkage: return CXLinkage_UniqueExternal; case ExternalLinkage: return CXLinkage_External; @@ -5743,25 +5830,33 @@ static CXLanguageKind getDeclLanguage(const Decl *D) { } extern "C" { + +static CXAvailabilityKind getCursorAvailabilityForDecl(const Decl *D) { + if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted()) + return CXAvailability_Available; -enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) { - if (clang_isDeclaration(cursor.kind)) - if (const Decl *D = cxcursor::getCursorDecl(cursor)) { - if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted()) - return CXAvailability_Available; - - switch (D->getAvailability()) { - case AR_Available: - case AR_NotYetIntroduced: - return CXAvailability_Available; + switch (D->getAvailability()) { + case AR_Available: + case AR_NotYetIntroduced: + if (const EnumConstantDecl *EnumConst = dyn_cast<EnumConstantDecl>(D)) + return getCursorAvailabilityForDecl( + cast<Decl>(EnumConst->getDeclContext())); + return CXAvailability_Available; - case AR_Deprecated: - return CXAvailability_Deprecated; + case AR_Deprecated: + return CXAvailability_Deprecated; - case AR_Unavailable: - return CXAvailability_NotAvailable; - } - } + case AR_Unavailable: + return CXAvailability_NotAvailable; + } + + llvm_unreachable("Unknown availability kind!"); +} + +enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) { + if (clang_isDeclaration(cursor.kind)) + if (const Decl *D = cxcursor::getCursorDecl(cursor)) + return getCursorAvailabilityForDecl(D); return CXAvailability_Available; } @@ -5785,34 +5880,20 @@ static CXVersion convertVersion(VersionTuple In) { return Out; } - -int clang_getCursorPlatformAvailability(CXCursor cursor, - int *always_deprecated, - CXString *deprecated_message, - int *always_unavailable, - CXString *unavailable_message, - CXPlatformAvailability *availability, - int availability_size) { - if (always_deprecated) - *always_deprecated = 0; - if (deprecated_message) - *deprecated_message = cxstring::createEmpty(); - if (always_unavailable) - *always_unavailable = 0; - if (unavailable_message) - *unavailable_message = cxstring::createEmpty(); - - if (!clang_isDeclaration(cursor.kind)) - return 0; - - const Decl *D = cxcursor::getCursorDecl(cursor); - if (!D) - return 0; - + +static int getCursorPlatformAvailabilityForDecl(const Decl *D, + int *always_deprecated, + CXString *deprecated_message, + int *always_unavailable, + CXString *unavailable_message, + CXPlatformAvailability *availability, + int availability_size) { + bool HadAvailAttr = false; int N = 0; for (Decl::attr_iterator A = D->attr_begin(), AEnd = D->attr_end(); A != AEnd; ++A) { if (DeprecatedAttr *Deprecated = dyn_cast<DeprecatedAttr>(*A)) { + HadAvailAttr = true; if (always_deprecated) *always_deprecated = 1; if (deprecated_message) @@ -5821,6 +5902,7 @@ int clang_getCursorPlatformAvailability(CXCursor cursor, } if (UnavailableAttr *Unavailable = dyn_cast<UnavailableAttr>(*A)) { + HadAvailAttr = true; if (always_unavailable) *always_unavailable = 1; if (unavailable_message) { @@ -5830,6 +5912,7 @@ int clang_getCursorPlatformAvailability(CXCursor cursor, } if (AvailabilityAttr *Avail = dyn_cast<AvailabilityAttr>(*A)) { + HadAvailAttr = true; if (N < availability_size) { availability[N].Platform = cxstring::createDup(Avail->getPlatform()->getName()); @@ -5842,9 +5925,51 @@ int clang_getCursorPlatformAvailability(CXCursor cursor, ++N; } } + + if (!HadAvailAttr) + if (const EnumConstantDecl *EnumConst = dyn_cast<EnumConstantDecl>(D)) + return getCursorPlatformAvailabilityForDecl( + cast<Decl>(EnumConst->getDeclContext()), + always_deprecated, + deprecated_message, + always_unavailable, + unavailable_message, + availability, + availability_size); return N; } + +int clang_getCursorPlatformAvailability(CXCursor cursor, + int *always_deprecated, + CXString *deprecated_message, + int *always_unavailable, + CXString *unavailable_message, + CXPlatformAvailability *availability, + int availability_size) { + if (always_deprecated) + *always_deprecated = 0; + if (deprecated_message) + *deprecated_message = cxstring::createEmpty(); + if (always_unavailable) + *always_unavailable = 0; + if (unavailable_message) + *unavailable_message = cxstring::createEmpty(); + + if (!clang_isDeclaration(cursor.kind)) + return 0; + + const Decl *D = cxcursor::getCursorDecl(cursor); + if (!D) + return 0; + + return getCursorPlatformAvailabilityForDecl(D, always_deprecated, + deprecated_message, + always_unavailable, + unavailable_message, + availability, + availability_size); +} void clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability) { clang_disposeString(availability->Platform); @@ -5974,6 +6099,19 @@ unsigned clang_Cursor_getObjCDeclQualifiers(CXCursor C) { return Result; } +unsigned clang_Cursor_isObjCOptional(CXCursor C) { + if (!clang_isDeclaration(C.kind)) + return 0; + + const Decl *D = getCursorDecl(C); + if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) + return PD->getPropertyImplementation() == ObjCPropertyDecl::Optional; + if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) + return MD->getImplementationControl() == ObjCMethodDecl::Optional; + + return 0; +} + unsigned clang_Cursor_isVariadic(CXCursor C) { if (!clang_isDeclaration(C.kind)) return 0; @@ -6114,6 +6252,20 @@ CXFile clang_Module_getTopLevelHeader(CXTranslationUnit TU, //===----------------------------------------------------------------------===// extern "C" { +unsigned clang_CXXMethod_isPureVirtual(CXCursor C) { + if (!clang_isDeclaration(C.kind)) + return 0; + + const CXXMethodDecl *Method = 0; + const Decl *D = cxcursor::getCursorDecl(C); + if (const 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->isVirtual() && Method->isPure()) ? 1 : 0; +} + unsigned clang_CXXMethod_isStatic(CXCursor C) { if (!clang_isDeclaration(C.kind)) return 0; diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp index f79de29..865bb58 100644 --- a/tools/libclang/CIndexCodeCompletion.cpp +++ b/tools/libclang/CIndexCodeCompletion.cpp @@ -27,10 +27,12 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/Sema/Sema.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Atomic.h" #include "llvm/Support/CrashRecoveryContext.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Program.h" #include "llvm/Support/Timer.h" @@ -271,7 +273,7 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults { /// \brief Temporary files that should be removed once we have finished /// with the code-completion results. - std::vector<llvm::sys::Path> TemporaryFiles; + std::vector<std::string> TemporaryFiles; /// \brief Temporary buffers that will be deleted once we have finished with /// the code-completion results. @@ -340,7 +342,7 @@ AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() { delete [] Results; for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I) - TemporaryFiles[I].eraseFromDisk(); + llvm::sys::fs::remove(TemporaryFiles[I]); for (unsigned I = 0, N = TemporaryBuffers.size(); I != N; ++I) delete TemporaryBuffers[I]; @@ -561,15 +563,13 @@ namespace { AllocatedResults.Contexts = getContextsForContextKind(contextKind, S); AllocatedResults.Selector = ""; - if (Context.getNumSelIdents() > 0) { - for (unsigned i = 0; i < Context.getNumSelIdents(); i++) { - IdentifierInfo *selIdent = Context.getSelIdents()[i]; - if (selIdent != NULL) { - StringRef selectorString = Context.getSelIdents()[i]->getName(); - AllocatedResults.Selector += selectorString; - } - AllocatedResults.Selector += ":"; - } + ArrayRef<IdentifierInfo *> SelIdents = Context.getSelIdents(); + for (ArrayRef<IdentifierInfo *>::iterator I = SelIdents.begin(), + E = SelIdents.end(); + I != E; ++I) { + if (IdentifierInfo *selIdent = *I) + AllocatedResults.Selector += selIdent->getName(); + AllocatedResults.Selector += ":"; } QualType baseType = Context.getBaseType(); diff --git a/tools/libclang/CIndexHigh.cpp b/tools/libclang/CIndexHigh.cpp index 2a55af5..c772dbb 100644 --- a/tools/libclang/CIndexHigh.cpp +++ b/tools/libclang/CIndexHigh.cpp @@ -36,7 +36,7 @@ static void getTopOverriddenMethods(CXTranslationUnit TU, return; } - for (SmallVector<CXCursor, 8>::iterator + for (SmallVectorImpl<CXCursor>::iterator I = Overridden.begin(), E = Overridden.end(); I != E; ++I) getTopOverriddenMethods(TU, cxcursor::getCursorDecl(*I), Methods); } diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp index a911ce5..2b43c5b 100644 --- a/tools/libclang/CIndexUSRs.cpp +++ b/tools/libclang/CIndexUSRs.cpp @@ -14,787 +14,13 @@ #include "CIndexer.h" #include "CXCursor.h" #include "CXString.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/DeclVisitor.h" -#include "clang/Frontend/ASTUnit.h" +#include "clang/Index/USRGeneration.h" #include "clang/Lex/PreprocessingRecord.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" using namespace clang; - -//===----------------------------------------------------------------------===// -// USR generation. -//===----------------------------------------------------------------------===// - -namespace { -class USRGenerator : public ConstDeclVisitor<USRGenerator> { - OwningPtr<SmallString<128> > OwnedBuf; - SmallVectorImpl<char> &Buf; - llvm::raw_svector_ostream Out; - bool IgnoreResults; - ASTContext *Context; - bool generatedLoc; - - llvm::DenseMap<const Type *, unsigned> TypeSubstitutions; - -public: - explicit USRGenerator(ASTContext *Ctx = 0, SmallVectorImpl<char> *extBuf = 0) - : OwnedBuf(extBuf ? 0 : new SmallString<128>()), - Buf(extBuf ? *extBuf : *OwnedBuf.get()), - Out(Buf), - IgnoreResults(false), - Context(Ctx), - generatedLoc(false) - { - // Add the USR space prefix. - Out << "c:"; - } - - StringRef str() { - return Out.str(); - } - - USRGenerator* operator->() { return this; } - - template <typename T> - llvm::raw_svector_ostream &operator<<(const T &x) { - Out << x; - return Out; - } - - bool ignoreResults() const { return IgnoreResults; } - - // Visitation methods from generating USRs from AST elements. - void VisitDeclContext(const DeclContext *D); - void VisitFieldDecl(const FieldDecl *D); - void VisitFunctionDecl(const FunctionDecl *D); - void VisitNamedDecl(const NamedDecl *D); - void VisitNamespaceDecl(const NamespaceDecl *D); - void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D); - void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); - void VisitClassTemplateDecl(const ClassTemplateDecl *D); - void VisitObjCContainerDecl(const ObjCContainerDecl *CD); - void VisitObjCMethodDecl(const ObjCMethodDecl *MD); - void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); - void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); - void VisitTagDecl(const TagDecl *D); - void VisitTypedefDecl(const TypedefDecl *D); - void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D); - void VisitVarDecl(const VarDecl *D); - void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D); - void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D); - void VisitLinkageSpecDecl(const LinkageSpecDecl *D) { - IgnoreResults = true; - } - void VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { - IgnoreResults = true; - } - void VisitUsingDecl(const UsingDecl *D) { - IgnoreResults = true; - } - void VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { - IgnoreResults = true; - } - void VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { - IgnoreResults = true; - } - - /// Generate the string component containing the location of the - /// declaration. - bool GenLoc(const Decl *D); - - /// String generation methods used both by the visitation methods - /// and from other clients that want to directly generate USRs. These - /// methods do not construct complete USRs (which incorporate the parents - /// of an AST element), but only the fragments concerning the AST element - /// itself. - - /// Generate a USR for an Objective-C class. - void GenObjCClass(StringRef cls); - /// Generate a USR for an Objective-C class category. - void GenObjCCategory(StringRef cls, StringRef cat); - /// Generate a USR fragment for an Objective-C instance variable. The - /// complete USR can be created by concatenating the USR for the - /// encompassing class with this USR fragment. - void GenObjCIvar(StringRef ivar); - /// Generate a USR fragment for an Objective-C method. - void GenObjCMethod(StringRef sel, bool isInstanceMethod); - /// Generate a USR fragment for an Objective-C property. - void GenObjCProperty(StringRef prop); - /// Generate a USR for an Objective-C protocol. - void GenObjCProtocol(StringRef prot); - - void VisitType(QualType T); - void VisitTemplateParameterList(const TemplateParameterList *Params); - void VisitTemplateName(TemplateName Name); - void VisitTemplateArgument(const TemplateArgument &Arg); - - /// Emit a Decl's name using NamedDecl::printName() and return true if - /// the decl had no name. - bool EmitDeclName(const NamedDecl *D); -}; - -} // end anonymous namespace - -//===----------------------------------------------------------------------===// -// Generating USRs from ASTS. -//===----------------------------------------------------------------------===// - -bool USRGenerator::EmitDeclName(const NamedDecl *D) { - Out.flush(); - const unsigned startSize = Buf.size(); - D->printName(Out); - Out.flush(); - const unsigned endSize = Buf.size(); - return startSize == endSize; -} - -static inline bool ShouldGenerateLocation(const NamedDecl *D) { - return D->getLinkage() != ExternalLinkage; -} - -void USRGenerator::VisitDeclContext(const DeclContext *DC) { - if (const NamedDecl *D = dyn_cast<NamedDecl>(DC)) - Visit(D); -} - -void USRGenerator::VisitFieldDecl(const FieldDecl *D) { - // The USR for an ivar declared in a class extension is based on the - // ObjCInterfaceDecl, not the ObjCCategoryDecl. - if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D)) - Visit(ID); - else - VisitDeclContext(D->getDeclContext()); - Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@"); - if (EmitDeclName(D)) { - // Bit fields can be anonymous. - IgnoreResults = true; - return; - } -} - -void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) { - if (ShouldGenerateLocation(D) && GenLoc(D)) - return; - - VisitDeclContext(D->getDeclContext()); - if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) { - Out << "@FT@"; - VisitTemplateParameterList(FunTmpl->getTemplateParameters()); - } else - Out << "@F@"; - D->printName(Out); - - ASTContext &Ctx = *Context; - if (!Ctx.getLangOpts().CPlusPlus || D->isExternC()) - return; - - if (const TemplateArgumentList * - SpecArgs = D->getTemplateSpecializationArgs()) { - Out << '<'; - for (unsigned I = 0, N = SpecArgs->size(); I != N; ++I) { - Out << '#'; - VisitTemplateArgument(SpecArgs->get(I)); - } - Out << '>'; - } - - // Mangle in type information for the arguments. - for (FunctionDecl::param_const_iterator I = D->param_begin(), - E = D->param_end(); - I != E; ++I) { - Out << '#'; - if (ParmVarDecl *PD = *I) - VisitType(PD->getType()); - } - if (D->isVariadic()) - Out << '.'; - Out << '#'; - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { - if (MD->isStatic()) - Out << 'S'; - if (unsigned quals = MD->getTypeQualifiers()) - Out << (char)('0' + quals); - } -} - -void USRGenerator::VisitNamedDecl(const NamedDecl *D) { - VisitDeclContext(D->getDeclContext()); - Out << "@"; - - if (EmitDeclName(D)) { - // The string can be empty if the declaration has no name; e.g., it is - // the ParmDecl with no name for declaration of a function pointer type, - // e.g.: void (*f)(void *); - // In this case, don't generate a USR. - IgnoreResults = true; - } -} - -void USRGenerator::VisitVarDecl(const VarDecl *D) { - // VarDecls can be declared 'extern' within a function or method body, - // but their enclosing DeclContext is the function, not the TU. We need - // to check the storage class to correctly generate the USR. - if (ShouldGenerateLocation(D) && GenLoc(D)) - return; - - VisitDeclContext(D->getDeclContext()); - - // Variables always have simple names. - StringRef s = D->getName(); - - // The string can be empty if the declaration has no name; e.g., it is - // the ParmDecl with no name for declaration of a function pointer type, e.g.: - // void (*f)(void *); - // In this case, don't generate a USR. - if (s.empty()) - IgnoreResults = true; - else - Out << '@' << s; -} - -void USRGenerator::VisitNonTypeTemplateParmDecl( - const NonTypeTemplateParmDecl *D) { - GenLoc(D); - return; -} - -void USRGenerator::VisitTemplateTemplateParmDecl( - const TemplateTemplateParmDecl *D) { - GenLoc(D); - return; -} - -void USRGenerator::VisitNamespaceDecl(const NamespaceDecl *D) { - if (D->isAnonymousNamespace()) { - Out << "@aN"; - return; - } - - VisitDeclContext(D->getDeclContext()); - if (!IgnoreResults) - Out << "@N@" << D->getName(); -} - -void USRGenerator::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { - VisitFunctionDecl(D->getTemplatedDecl()); -} - -void USRGenerator::VisitClassTemplateDecl(const ClassTemplateDecl *D) { - VisitTagDecl(D->getTemplatedDecl()); -} - -void USRGenerator::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { - VisitDeclContext(D->getDeclContext()); - if (!IgnoreResults) - Out << "@NA@" << D->getName(); -} - -void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) { - const DeclContext *container = D->getDeclContext(); - if (const ObjCProtocolDecl *pd = dyn_cast<ObjCProtocolDecl>(container)) { - Visit(pd); - } - else { - // The USR for a method declared in a class extension or category is based on - // the ObjCInterfaceDecl, not the ObjCCategoryDecl. - const ObjCInterfaceDecl *ID = D->getClassInterface(); - if (!ID) { - IgnoreResults = true; - return; - } - Visit(ID); - } - // Ideally we would use 'GenObjCMethod', but this is such a hot path - // for Objective-C code that we don't want to use - // DeclarationName::getAsString(). - Out << (D->isInstanceMethod() ? "(im)" : "(cm)"); - DeclarationName N(D->getSelector()); - N.printName(Out); -} - -void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D) { - switch (D->getKind()) { - default: - llvm_unreachable("Invalid ObjC container."); - case Decl::ObjCInterface: - case Decl::ObjCImplementation: - GenObjCClass(D->getName()); - break; - case Decl::ObjCCategory: { - const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D); - const ObjCInterfaceDecl *ID = CD->getClassInterface(); - if (!ID) { - // Handle invalid code where the @interface might not - // have been specified. - // FIXME: We should be able to generate this USR even if the - // @interface isn't available. - IgnoreResults = true; - return; - } - // Specially handle class extensions, which are anonymous categories. - // We want to mangle in the location to uniquely distinguish them. - if (CD->IsClassExtension()) { - Out << "objc(ext)" << ID->getName() << '@'; - GenLoc(CD); - } - else - GenObjCCategory(ID->getName(), CD->getName()); - - break; - } - case Decl::ObjCCategoryImpl: { - const ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D); - const ObjCInterfaceDecl *ID = CD->getClassInterface(); - if (!ID) { - // Handle invalid code where the @interface might not - // have been specified. - // FIXME: We should be able to generate this USR even if the - // @interface isn't available. - IgnoreResults = true; - return; - } - GenObjCCategory(ID->getName(), CD->getName()); - break; - } - case Decl::ObjCProtocol: - GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName()); - break; - } -} - -void USRGenerator::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { - // The USR for a property declared in a class extension or category is based - // on the ObjCInterfaceDecl, not the ObjCCategoryDecl. - if (const ObjCInterfaceDecl *ID = Context->getObjContainingInterface(D)) - Visit(ID); - else - Visit(cast<Decl>(D->getDeclContext())); - GenObjCProperty(D->getName()); -} - -void USRGenerator::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { - if (ObjCPropertyDecl *PD = D->getPropertyDecl()) { - VisitObjCPropertyDecl(PD); - return; - } - - IgnoreResults = true; -} - -void USRGenerator::VisitTagDecl(const TagDecl *D) { - // Add the location of the tag decl to handle resolution across - // translation units. - if (ShouldGenerateLocation(D) && GenLoc(D)) - return; - - D = D->getCanonicalDecl(); - VisitDeclContext(D->getDeclContext()); - - bool AlreadyStarted = false; - if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) { - if (ClassTemplateDecl *ClassTmpl = CXXRecord->getDescribedClassTemplate()) { - AlreadyStarted = true; - - switch (D->getTagKind()) { - case TTK_Interface: - case TTK_Struct: Out << "@ST"; break; - case TTK_Class: Out << "@CT"; break; - case TTK_Union: Out << "@UT"; break; - case TTK_Enum: llvm_unreachable("enum template"); - } - VisitTemplateParameterList(ClassTmpl->getTemplateParameters()); - } else if (const ClassTemplatePartialSpecializationDecl *PartialSpec - = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) { - AlreadyStarted = true; - - switch (D->getTagKind()) { - case TTK_Interface: - case TTK_Struct: Out << "@SP"; break; - case TTK_Class: Out << "@CP"; break; - case TTK_Union: Out << "@UP"; break; - case TTK_Enum: llvm_unreachable("enum partial specialization"); - } - VisitTemplateParameterList(PartialSpec->getTemplateParameters()); - } - } - - if (!AlreadyStarted) { - switch (D->getTagKind()) { - case TTK_Interface: - case TTK_Struct: Out << "@S"; break; - case TTK_Class: Out << "@C"; break; - case TTK_Union: Out << "@U"; break; - case TTK_Enum: Out << "@E"; break; - } - } - - Out << '@'; - Out.flush(); - assert(Buf.size() > 0); - const unsigned off = Buf.size() - 1; - - if (EmitDeclName(D)) { - if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) { - Buf[off] = 'A'; - Out << '@' << *TD; - } - else - Buf[off] = 'a'; - } - - // For a class template specialization, mangle the template arguments. - if (const ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(D)) { - const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs(); - Out << '>'; - for (unsigned I = 0, N = Args.size(); I != N; ++I) { - Out << '#'; - VisitTemplateArgument(Args.get(I)); - } - } -} - -void USRGenerator::VisitTypedefDecl(const TypedefDecl *D) { - if (ShouldGenerateLocation(D) && GenLoc(D)) - return; - const DeclContext *DC = D->getDeclContext(); - if (const NamedDecl *DCN = dyn_cast<NamedDecl>(DC)) - Visit(DCN); - Out << "@T@"; - Out << D->getName(); -} - -void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { - GenLoc(D); - return; -} - -bool USRGenerator::GenLoc(const Decl *D) { - if (generatedLoc) - return IgnoreResults; - generatedLoc = true; - - // Guard against null declarations in invalid code. - if (!D) { - IgnoreResults = true; - return true; - } - - // Use the location of canonical decl. - D = D->getCanonicalDecl(); - - const SourceManager &SM = Context->getSourceManager(); - SourceLocation L = D->getLocStart(); - if (L.isInvalid()) { - IgnoreResults = true; - return true; - } - L = SM.getExpansionLoc(L); - const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(L); - const FileEntry *FE = SM.getFileEntryForID(Decomposed.first); - if (FE) { - Out << llvm::sys::path::filename(FE->getName()); - } - else { - // This case really isn't interesting. - IgnoreResults = true; - return true; - } - // Use the offest into the FileID to represent the location. Using - // a line/column can cause us to look back at the original source file, - // which is expensive. - Out << '@' << Decomposed.second; - return IgnoreResults; -} - -void USRGenerator::VisitType(QualType T) { - // This method mangles in USR information for types. It can possibly - // just reuse the naming-mangling logic used by codegen, although the - // requirements for USRs might not be the same. - ASTContext &Ctx = *Context; - - do { - T = Ctx.getCanonicalType(T); - Qualifiers Q = T.getQualifiers(); - unsigned qVal = 0; - if (Q.hasConst()) - qVal |= 0x1; - if (Q.hasVolatile()) - qVal |= 0x2; - if (Q.hasRestrict()) - qVal |= 0x4; - if(qVal) - Out << ((char) ('0' + qVal)); - - // Mangle in ObjC GC qualifiers? - - if (const PackExpansionType *Expansion = T->getAs<PackExpansionType>()) { - Out << 'P'; - T = Expansion->getPattern(); - } - - if (const BuiltinType *BT = T->getAs<BuiltinType>()) { - unsigned char c = '\0'; - switch (BT->getKind()) { - case BuiltinType::Void: - c = 'v'; break; - case BuiltinType::Bool: - c = 'b'; break; - case BuiltinType::Char_U: - case BuiltinType::UChar: - c = 'c'; break; - case BuiltinType::Char16: - c = 'q'; break; - case BuiltinType::Char32: - c = 'w'; break; - case BuiltinType::UShort: - c = 's'; break; - case BuiltinType::UInt: - c = 'i'; break; - case BuiltinType::ULong: - c = 'l'; break; - case BuiltinType::ULongLong: - c = 'k'; break; - case BuiltinType::UInt128: - c = 'j'; break; - case BuiltinType::Char_S: - case BuiltinType::SChar: - c = 'C'; break; - case BuiltinType::WChar_S: - case BuiltinType::WChar_U: - c = 'W'; break; - case BuiltinType::Short: - c = 'S'; break; - case BuiltinType::Int: - c = 'I'; break; - case BuiltinType::Long: - c = 'L'; break; - case BuiltinType::LongLong: - c = 'K'; break; - case BuiltinType::Int128: - c = 'J'; break; - case BuiltinType::Half: - c = 'h'; break; - case BuiltinType::Float: - c = 'f'; break; - case BuiltinType::Double: - c = 'd'; break; - case BuiltinType::LongDouble: - c = 'D'; break; - case BuiltinType::NullPtr: - c = 'n'; break; -#define BUILTIN_TYPE(Id, SingletonId) -#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id: -#include "clang/AST/BuiltinTypes.def" - case BuiltinType::Dependent: - case BuiltinType::OCLImage1d: - case BuiltinType::OCLImage1dArray: - case BuiltinType::OCLImage1dBuffer: - case BuiltinType::OCLImage2d: - case BuiltinType::OCLImage2dArray: - case BuiltinType::OCLImage3d: - case BuiltinType::OCLEvent: - case BuiltinType::OCLSampler: - IgnoreResults = true; - return; - case BuiltinType::ObjCId: - c = 'o'; break; - case BuiltinType::ObjCClass: - c = 'O'; break; - case BuiltinType::ObjCSel: - c = 'e'; break; - } - Out << c; - return; - } - - // If we have already seen this (non-built-in) type, use a substitution - // encoding. - llvm::DenseMap<const Type *, unsigned>::iterator Substitution - = TypeSubstitutions.find(T.getTypePtr()); - if (Substitution != TypeSubstitutions.end()) { - Out << 'S' << Substitution->second << '_'; - return; - } else { - // Record this as a substitution. - unsigned Number = TypeSubstitutions.size(); - TypeSubstitutions[T.getTypePtr()] = Number; - } - - if (const PointerType *PT = T->getAs<PointerType>()) { - Out << '*'; - T = PT->getPointeeType(); - continue; - } - if (const ReferenceType *RT = T->getAs<ReferenceType>()) { - Out << '&'; - T = RT->getPointeeType(); - continue; - } - if (const FunctionProtoType *FT = T->getAs<FunctionProtoType>()) { - Out << 'F'; - VisitType(FT->getResultType()); - for (FunctionProtoType::arg_type_iterator - I = FT->arg_type_begin(), E = FT->arg_type_end(); I!=E; ++I) { - VisitType(*I); - } - if (FT->isVariadic()) - Out << '.'; - return; - } - if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) { - Out << 'B'; - T = BT->getPointeeType(); - continue; - } - if (const ComplexType *CT = T->getAs<ComplexType>()) { - Out << '<'; - T = CT->getElementType(); - continue; - } - if (const TagType *TT = T->getAs<TagType>()) { - Out << '$'; - VisitTagDecl(TT->getDecl()); - return; - } - if (const TemplateTypeParmType *TTP = T->getAs<TemplateTypeParmType>()) { - Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); - return; - } - if (const TemplateSpecializationType *Spec - = T->getAs<TemplateSpecializationType>()) { - Out << '>'; - VisitTemplateName(Spec->getTemplateName()); - Out << Spec->getNumArgs(); - for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) - VisitTemplateArgument(Spec->getArg(I)); - return; - } - - // Unhandled type. - Out << ' '; - break; - } while (true); -} - -void USRGenerator::VisitTemplateParameterList( - const TemplateParameterList *Params) { - if (!Params) - return; - Out << '>' << Params->size(); - for (TemplateParameterList::const_iterator P = Params->begin(), - PEnd = Params->end(); - P != PEnd; ++P) { - Out << '#'; - if (isa<TemplateTypeParmDecl>(*P)) { - if (cast<TemplateTypeParmDecl>(*P)->isParameterPack()) - Out<< 'p'; - Out << 'T'; - continue; - } - - if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { - if (NTTP->isParameterPack()) - Out << 'p'; - Out << 'N'; - VisitType(NTTP->getType()); - continue; - } - - TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); - if (TTP->isParameterPack()) - Out << 'p'; - Out << 't'; - VisitTemplateParameterList(TTP->getTemplateParameters()); - } -} - -void USRGenerator::VisitTemplateName(TemplateName Name) { - if (TemplateDecl *Template = Name.getAsTemplateDecl()) { - if (TemplateTemplateParmDecl *TTP - = dyn_cast<TemplateTemplateParmDecl>(Template)) { - Out << 't' << TTP->getDepth() << '.' << TTP->getIndex(); - return; - } - - Visit(Template); - return; - } - - // FIXME: Visit dependent template names. -} - -void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) { - switch (Arg.getKind()) { - case TemplateArgument::Null: - break; - - case TemplateArgument::Declaration: - Visit(Arg.getAsDecl()); - break; - - case TemplateArgument::NullPtr: - break; - - case TemplateArgument::TemplateExpansion: - Out << 'P'; // pack expansion of... - // Fall through - case TemplateArgument::Template: - VisitTemplateName(Arg.getAsTemplateOrTemplatePattern()); - break; - - case TemplateArgument::Expression: - // FIXME: Visit expressions. - break; - - case TemplateArgument::Pack: - Out << 'p' << Arg.pack_size(); - for (TemplateArgument::pack_iterator P = Arg.pack_begin(), PEnd = Arg.pack_end(); - P != PEnd; ++P) - VisitTemplateArgument(*P); - break; - - case TemplateArgument::Type: - VisitType(Arg.getAsType()); - break; - - case TemplateArgument::Integral: - Out << 'V'; - VisitType(Arg.getIntegralType()); - Out << Arg.getAsIntegral(); - break; - } -} - -//===----------------------------------------------------------------------===// -// General purpose USR generation methods. -//===----------------------------------------------------------------------===// - -void USRGenerator::GenObjCClass(StringRef cls) { - Out << "objc(cs)" << cls; -} - -void USRGenerator::GenObjCCategory(StringRef cls, StringRef cat) { - Out << "objc(cy)" << cls << '@' << cat; -} - -void USRGenerator::GenObjCIvar(StringRef ivar) { - Out << '@' << ivar; -} - -void USRGenerator::GenObjCMethod(StringRef meth, bool isInstanceMethod) { - Out << (isInstanceMethod ? "(im)" : "(cm)") << meth; -} - -void USRGenerator::GenObjCProperty(StringRef prop) { - Out << "(py)" << prop; -} - -void USRGenerator::GenObjCProtocol(StringRef prot) { - Out << "objc(pl)" << prot; -} +using namespace clang::index; //===----------------------------------------------------------------------===// // API hooks. @@ -805,17 +31,7 @@ static inline StringRef extractUSRSuffix(StringRef s) { } bool cxcursor::getDeclCursorUSR(const Decl *D, SmallVectorImpl<char> &Buf) { - // Don't generate USRs for things with invalid locations. - if (!D || D->getLocStart().isInvalid()) - return true; - - USRGenerator UG(&D->getASTContext(), &Buf); - UG->Visit(D); - - if (UG->ignoreResults()) - return true; - - return false; + return generateUSRForDecl(D, Buf); } extern "C" { @@ -857,12 +73,10 @@ CXString clang_getCursorUSR(CXCursor C) { if (!buf) return cxstring::createEmpty(); - { - USRGenerator UG(&cxcursor::getCursorASTUnit(C)->getASTContext(), - &buf->Data); - UG << "macro@" - << cxcursor::getCursorMacroDefinition(C)->getName()->getNameStart(); - } + buf->Data += getUSRSpacePrefix(); + buf->Data += "macro@"; + buf->Data += + cxcursor::getCursorMacroDefinition(C)->getName()->getNameStart(); buf->Data.push_back('\0'); return createCXString(buf); } @@ -871,46 +85,52 @@ CXString clang_getCursorUSR(CXCursor C) { } CXString clang_constructUSR_ObjCIvar(const char *name, CXString classUSR) { - USRGenerator UG; - UG << extractUSRSuffix(clang_getCString(classUSR)); - UG->GenObjCIvar(name); - return cxstring::createDup(UG.str()); + SmallString<128> Buf(getUSRSpacePrefix()); + llvm::raw_svector_ostream OS(Buf); + OS << extractUSRSuffix(clang_getCString(classUSR)); + generateUSRForObjCIvar(name, OS); + return cxstring::createDup(OS.str()); } CXString clang_constructUSR_ObjCMethod(const char *name, unsigned isInstanceMethod, CXString classUSR) { - USRGenerator UG; - UG << extractUSRSuffix(clang_getCString(classUSR)); - UG->GenObjCMethod(name, isInstanceMethod); - return cxstring::createDup(UG.str()); + SmallString<128> Buf(getUSRSpacePrefix()); + llvm::raw_svector_ostream OS(Buf); + OS << extractUSRSuffix(clang_getCString(classUSR)); + generateUSRForObjCMethod(name, isInstanceMethod, OS); + return cxstring::createDup(OS.str()); } CXString clang_constructUSR_ObjCClass(const char *name) { - USRGenerator UG; - UG->GenObjCClass(name); - return cxstring::createDup(UG.str()); + SmallString<128> Buf(getUSRSpacePrefix()); + llvm::raw_svector_ostream OS(Buf); + generateUSRForObjCClass(name, OS); + return cxstring::createDup(OS.str()); } CXString clang_constructUSR_ObjCProtocol(const char *name) { - USRGenerator UG; - UG->GenObjCProtocol(name); - return cxstring::createDup(UG.str()); + SmallString<128> Buf(getUSRSpacePrefix()); + llvm::raw_svector_ostream OS(Buf); + generateUSRForObjCProtocol(name, OS); + return cxstring::createDup(OS.str()); } CXString clang_constructUSR_ObjCCategory(const char *class_name, const char *category_name) { - USRGenerator UG; - UG->GenObjCCategory(class_name, category_name); - return cxstring::createDup(UG.str()); + SmallString<128> Buf(getUSRSpacePrefix()); + llvm::raw_svector_ostream OS(Buf); + generateUSRForObjCCategory(class_name, category_name, OS); + return cxstring::createDup(OS.str()); } CXString clang_constructUSR_ObjCProperty(const char *property, CXString classUSR) { - USRGenerator UG; - UG << extractUSRSuffix(clang_getCString(classUSR)); - UG->GenObjCProperty(property); - return cxstring::createDup(UG.str()); + SmallString<128> Buf(getUSRSpacePrefix()); + llvm::raw_svector_ostream OS(Buf); + OS << extractUSRSuffix(clang_getCString(classUSR)); + generateUSRForObjCProperty(property, OS); + return cxstring::createDup(OS.str()); } } // end extern "C" diff --git a/tools/libclang/CIndexer.cpp b/tools/libclang/CIndexer.cpp index d89e0a4..91154cc 100644 --- a/tools/libclang/CIndexer.cpp +++ b/tools/libclang/CIndexer.cpp @@ -43,11 +43,13 @@ using namespace clang; -std::string CIndexer::getClangResourcesPath() { +const std::string &CIndexer::getClangResourcesPath() { // Did we already compute the path? if (!ResourcesPath.empty()) - return ResourcesPath.str(); - + return ResourcesPath; + + SmallString<128> LibClangPath; + // Find the location where this library lives (libclang.dylib). #ifdef LLVM_ON_WIN32 MEMORY_BASIC_INFORMATION mbi; @@ -66,85 +68,20 @@ std::string CIndexer::getClangResourcesPath() { #endif #endif - llvm::sys::Path LibClangPath(path); - LibClangPath.eraseComponent(); + LibClangPath += llvm::sys::path::parent_path(path); #else // This silly cast below avoids a C++ warning. Dl_info info; if (dladdr((void *)(uintptr_t)clang_createTranslationUnit, &info) == 0) llvm_unreachable("Call to dladdr() failed"); - - llvm::sys::Path LibClangPath(info.dli_fname); - + // We now have the CIndex directory, locate clang relative to it. - LibClangPath.eraseComponent(); + LibClangPath += llvm::sys::path::parent_path(info.dli_fname); #endif - - LibClangPath.appendComponent("clang"); - LibClangPath.appendComponent(CLANG_VERSION_STRING); - - // Cache our result. - ResourcesPath = LibClangPath; - return LibClangPath.str(); -} -static llvm::sys::Path GetTemporaryPath() { - // FIXME: This is lame; sys::Path should provide this function (in particular, - // it should know how to find the temporary files dir). - std::string Error; - const char *TmpDir = ::getenv("TMPDIR"); - if (!TmpDir) - TmpDir = ::getenv("TEMP"); - if (!TmpDir) - TmpDir = ::getenv("TMP"); - if (!TmpDir) - TmpDir = "/tmp"; - llvm::sys::Path P(TmpDir); - P.appendComponent("remap"); - if (P.makeUnique(false, &Error)) - return llvm::sys::Path(""); + llvm::sys::path::append(LibClangPath, "clang", CLANG_VERSION_STRING); - // FIXME: Grumble, makeUnique sometimes leaves the file around!? PR3837. - P.eraseFromDisk(false, 0); - - return P; -} - -bool clang::RemapFiles(unsigned num_unsaved_files, - struct CXUnsavedFile *unsaved_files, - std::vector<std::string> &RemapArgs, - std::vector<llvm::sys::Path> &TemporaryFiles) { - for (unsigned i = 0; i != num_unsaved_files; ++i) { - // Write the contents of this unsaved file into the temporary file. - llvm::sys::Path SavedFile(GetTemporaryPath()); - if (SavedFile.empty()) - return true; - - std::string ErrorInfo; - llvm::raw_fd_ostream OS(SavedFile.c_str(), ErrorInfo, - llvm::raw_fd_ostream::F_Binary); - if (!ErrorInfo.empty()) - return true; - - OS.write(unsaved_files[i].Contents, unsaved_files[i].Length); - OS.close(); - if (OS.has_error()) { - SavedFile.eraseFromDisk(); - OS.clear_error(); - return true; - } - - // Remap the file. - std::string RemapArg = unsaved_files[i].Filename; - RemapArg += ';'; - RemapArg += SavedFile.str(); - RemapArgs.push_back("-Xclang"); - RemapArgs.push_back("-remap-file"); - RemapArgs.push_back("-Xclang"); - RemapArgs.push_back(RemapArg); - TemporaryFiles.push_back(SavedFile); - } - - return false; + // Cache our result. + ResourcesPath = LibClangPath.str(); + return ResourcesPath; } - diff --git a/tools/libclang/CIndexer.h b/tools/libclang/CIndexer.h index 08162c5..95d8115 100644 --- a/tools/libclang/CIndexer.h +++ b/tools/libclang/CIndexer.h @@ -37,7 +37,7 @@ class CIndexer { bool DisplayDiagnostics; unsigned Options; // CXGlobalOptFlags. - llvm::sys::Path ResourcesPath; + std::string ResourcesPath; public: CIndexer() : OnlyLocalDecls(false), DisplayDiagnostics(false), @@ -62,20 +62,9 @@ public: } /// \brief Get the path of the clang resource files. - std::string getClangResourcesPath(); + const std::string &getClangResourcesPath(); }; - /** - * \brief Given a set of "unsaved" files, create temporary files and - * construct the clang -cc1 argument list needed to perform the remapping. - * - * \returns true if an error occurred. - */ - bool RemapFiles(unsigned num_unsaved_files, - struct CXUnsavedFile *unsaved_files, - std::vector<std::string> &RemapArgs, - std::vector<llvm::sys::Path> &TemporaryFiles); - /// \brief Return the current size to request for "safety". unsigned GetSafetyThreadStackSize(); diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt index c5a975b..b7bde69 100644 --- a/tools/libclang/CMakeLists.txt +++ b/tools/libclang/CMakeLists.txt @@ -39,11 +39,11 @@ set(SOURCES Indexing.cpp IndexingContext.cpp IndexingContext.h - SimpleFormatContext.h ../../include/clang-c/Index.h ) set(LIBRARIES + clangIndex clangARCMigrate clangRewriteCore clangRewriteFrontend @@ -56,7 +56,6 @@ set(LIBRARIES clangLex clangTooling clangBasic - clangFormat ) set(GENERATED_HEADERS @@ -70,6 +69,8 @@ set(GENERATED_HEADERS ClangStmtNodes ) +set(EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/libclang.exports) + if( LLVM_ENABLE_PIC ) set(SHARED_LIBRARY TRUE) add_clang_library(libclang ${SOURCES}) @@ -92,11 +93,17 @@ if( LLVM_ENABLE_PIC ) if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(LIBCLANG_LINK_FLAGS - "-Wl,-compatibility_version -Wl,1 -Wl,-dead_strip") + " -Wl,-compatibility_version -Wl,1 -Wl,-dead_strip") + if (DEFINED ${LLVM_SUBMIT_VERSION}) + set(LIBCLANG_LINK_FLAGS + "${LIBCLANG_LINK_FLAGS} -Wl,-current_version -Wl,${LLVM_SUBMIT_VERSION}.${LLVM_SUBMIT_SUBVERSION}") + endif() + + set_property(TARGET libclang APPEND_STRING PROPERTY + LINK_FLAGS ${LIBCLANG_LINK_FLAGS}) set_target_properties(libclang PROPERTIES - LINK_FLAGS "${LIBCLANG_LINK_FLAGS}" - INSTALL_NAME_DIR "@executable_path/../lib") + INSTALL_NAME_DIR "@rpath") endif() @@ -105,7 +112,10 @@ else() set(LIBCLANG_STATIC_TARGET_NAME libclang) endif() -if( NOT BUILD_SHARED_LIBS AND NOT WIN32 ) +option(LIBCLANG_BUILD_STATIC + "Build libclang as a static library (in addition to a shared one)" OFF) + +if( (NOT LLVM_ENABLE_PIC OR LIBCLANG_BUILD_STATIC) AND NOT WIN32 ) add_clang_library(${LIBCLANG_STATIC_TARGET_NAME} STATIC ${SOURCES}) target_link_libraries(${LIBCLANG_STATIC_TARGET_NAME} ${LIBRARIES}) add_dependencies(${LIBCLANG_STATIC_TARGET_NAME} ${GENERATED_HEADERS} clang-headers) diff --git a/tools/libclang/CXComment.cpp b/tools/libclang/CXComment.cpp index 1c127e1..2c4f269 100644 --- a/tools/libclang/CXComment.cpp +++ b/tools/libclang/CXComment.cpp @@ -15,17 +15,11 @@ #include "CXComment.h" #include "CXCursor.h" #include "CXString.h" -#include "SimpleFormatContext.h" -#include "clang/AST/CommentCommandTraits.h" -#include "clang/AST/CommentVisitor.h" #include "clang/AST/Decl.h" -#include "clang/AST/PrettyPrinter.h" -#include "clang/Format/Format.h" -#include "clang/Lex/Lexer.h" +#include "clang/Index/CommentToXML.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" #include <climits> using namespace clang; @@ -268,7 +262,7 @@ unsigned clang_ParamCommandComment_isParamIndexValid(CXComment CXC) { unsigned clang_ParamCommandComment_getParamIndex(CXComment CXC) { const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC); - if (!PCC || !PCC->isParamIndexValid()) + if (!PCC || !PCC->isParamIndexValid() || PCC->isVarArgParam()) return ParamCommandComment::InvalidParamIndex; return PCC->getParamIndex(); @@ -350,499 +344,23 @@ CXString clang_VerbatimLineComment_getText(CXComment CXC) { return cxstring::createRef(VLC->getText()); } -} // end extern "C" - //===----------------------------------------------------------------------===// -// Helpers for converting comment AST to HTML. +// Converting comments to XML. //===----------------------------------------------------------------------===// -namespace { - -/// This comparison will sort parameters with valid index by index and -/// invalid (unresolved) parameters last. -class ParamCommandCommentCompareIndex { -public: - bool operator()(const ParamCommandComment *LHS, - const ParamCommandComment *RHS) const { - unsigned LHSIndex = UINT_MAX; - unsigned RHSIndex = UINT_MAX; - if (LHS->isParamIndexValid()) - LHSIndex = LHS->getParamIndex(); - if (RHS->isParamIndexValid()) - RHSIndex = RHS->getParamIndex(); - - return LHSIndex < RHSIndex; - } -}; - -/// This comparison will sort template parameters in the following order: -/// \li real template parameters (depth = 1) in index order; -/// \li all other names (depth > 1); -/// \li unresolved names. -class TParamCommandCommentComparePosition { -public: - bool operator()(const TParamCommandComment *LHS, - const TParamCommandComment *RHS) const { - // Sort unresolved names last. - if (!LHS->isPositionValid()) - return false; - if (!RHS->isPositionValid()) - return true; - - if (LHS->getDepth() > 1) - return false; - if (RHS->getDepth() > 1) - return true; - - // Sort template parameters in index order. - if (LHS->getDepth() == 1 && RHS->getDepth() == 1) - return LHS->getIndex(0) < RHS->getIndex(0); - - // Leave all other names in source order. - return true; - } -}; - -/// Separate parts of a FullComment. -struct FullCommentParts { - /// Take a full comment apart and initialize members accordingly. - FullCommentParts(const FullComment *C, - const CommandTraits &Traits); - - const BlockContentComment *Brief; - const BlockContentComment *Headerfile; - const ParagraphComment *FirstParagraph; - const BlockCommandComment *Returns; - SmallVector<const ParamCommandComment *, 8> Params; - SmallVector<const TParamCommandComment *, 4> TParams; - SmallVector<const BlockContentComment *, 8> MiscBlocks; -}; - -FullCommentParts::FullCommentParts(const FullComment *C, - const CommandTraits &Traits) : - Brief(NULL), Headerfile(NULL), FirstParagraph(NULL), Returns(NULL) { - for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); - I != E; ++I) { - const Comment *Child = *I; - if (!Child) - continue; - switch (Child->getCommentKind()) { - case Comment::NoCommentKind: - continue; - - case Comment::ParagraphCommentKind: { - const ParagraphComment *PC = cast<ParagraphComment>(Child); - if (PC->isWhitespace()) - break; - if (!FirstParagraph) - FirstParagraph = PC; - - MiscBlocks.push_back(PC); - break; - } - - case Comment::BlockCommandCommentKind: { - const BlockCommandComment *BCC = cast<BlockCommandComment>(Child); - const CommandInfo *Info = Traits.getCommandInfo(BCC->getCommandID()); - if (!Brief && Info->IsBriefCommand) { - Brief = BCC; - break; - } - if (!Headerfile && Info->IsHeaderfileCommand) { - Headerfile = BCC; - break; - } - if (!Returns && Info->IsReturnsCommand) { - Returns = BCC; - break; - } - MiscBlocks.push_back(BCC); - break; - } - - case Comment::ParamCommandCommentKind: { - const ParamCommandComment *PCC = cast<ParamCommandComment>(Child); - if (!PCC->hasParamName()) - break; - - if (!PCC->isDirectionExplicit() && !PCC->hasNonWhitespaceParagraph()) - break; - - Params.push_back(PCC); - break; - } - - case Comment::TParamCommandCommentKind: { - const TParamCommandComment *TPCC = cast<TParamCommandComment>(Child); - if (!TPCC->hasParamName()) - break; - - if (!TPCC->hasNonWhitespaceParagraph()) - break; - - TParams.push_back(TPCC); - break; - } - - case Comment::VerbatimBlockCommentKind: - MiscBlocks.push_back(cast<BlockCommandComment>(Child)); - break; - - case Comment::VerbatimLineCommentKind: { - const VerbatimLineComment *VLC = cast<VerbatimLineComment>(Child); - const CommandInfo *Info = Traits.getCommandInfo(VLC->getCommandID()); - if (!Info->IsDeclarationCommand) - MiscBlocks.push_back(VLC); - break; - } - - case Comment::TextCommentKind: - case Comment::InlineCommandCommentKind: - case Comment::HTMLStartTagCommentKind: - case Comment::HTMLEndTagCommentKind: - case Comment::VerbatimBlockLineCommentKind: - case Comment::FullCommentKind: - llvm_unreachable("AST node of this kind can't be a child of " - "a FullComment"); - } - } - - // Sort params in order they are declared in the function prototype. - // Unresolved parameters are put at the end of the list in the same order - // they were seen in the comment. - std::stable_sort(Params.begin(), Params.end(), - ParamCommandCommentCompareIndex()); - - std::stable_sort(TParams.begin(), TParams.end(), - TParamCommandCommentComparePosition()); -} - -void PrintHTMLStartTagComment(const HTMLStartTagComment *C, - llvm::raw_svector_ostream &Result) { - Result << "<" << C->getTagName(); - - if (C->getNumAttrs() != 0) { - for (unsigned i = 0, e = C->getNumAttrs(); i != e; i++) { - Result << " "; - const HTMLStartTagComment::Attribute &Attr = C->getAttr(i); - Result << Attr.Name; - if (!Attr.Value.empty()) - Result << "=\"" << Attr.Value << "\""; - } - } - - if (!C->isSelfClosing()) - Result << ">"; - else - Result << "/>"; -} - -class CommentASTToHTMLConverter : - public ConstCommentVisitor<CommentASTToHTMLConverter> { -public: - /// \param Str accumulator for HTML. - CommentASTToHTMLConverter(const FullComment *FC, - SmallVectorImpl<char> &Str, - const CommandTraits &Traits) : - FC(FC), Result(Str), Traits(Traits) - { } - - // Inline content. - void visitTextComment(const TextComment *C); - void visitInlineCommandComment(const InlineCommandComment *C); - void visitHTMLStartTagComment(const HTMLStartTagComment *C); - void visitHTMLEndTagComment(const HTMLEndTagComment *C); - - // Block content. - void visitParagraphComment(const ParagraphComment *C); - void visitBlockCommandComment(const BlockCommandComment *C); - void visitParamCommandComment(const ParamCommandComment *C); - void visitTParamCommandComment(const TParamCommandComment *C); - void visitVerbatimBlockComment(const VerbatimBlockComment *C); - void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C); - void visitVerbatimLineComment(const VerbatimLineComment *C); - - void visitFullComment(const FullComment *C); - - // Helpers. - - /// Convert a paragraph that is not a block by itself (an argument to some - /// command). - void visitNonStandaloneParagraphComment(const ParagraphComment *C); - - void appendToResultWithHTMLEscaping(StringRef S); - -private: - const FullComment *FC; - /// Output stream for HTML. - llvm::raw_svector_ostream Result; - - const CommandTraits &Traits; -}; -} // end unnamed namespace - -void CommentASTToHTMLConverter::visitTextComment(const TextComment *C) { - appendToResultWithHTMLEscaping(C->getText()); -} - -void CommentASTToHTMLConverter::visitInlineCommandComment( - const InlineCommandComment *C) { - // Nothing to render if no arguments supplied. - if (C->getNumArgs() == 0) - return; - - // Nothing to render if argument is empty. - StringRef Arg0 = C->getArgText(0); - if (Arg0.empty()) - return; - - switch (C->getRenderKind()) { - case InlineCommandComment::RenderNormal: - for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) { - appendToResultWithHTMLEscaping(C->getArgText(i)); - Result << " "; - } - return; - - case InlineCommandComment::RenderBold: - assert(C->getNumArgs() == 1); - Result << "<b>"; - appendToResultWithHTMLEscaping(Arg0); - Result << "</b>"; - return; - case InlineCommandComment::RenderMonospaced: - assert(C->getNumArgs() == 1); - Result << "<tt>"; - appendToResultWithHTMLEscaping(Arg0); - Result<< "</tt>"; - return; - case InlineCommandComment::RenderEmphasized: - assert(C->getNumArgs() == 1); - Result << "<em>"; - appendToResultWithHTMLEscaping(Arg0); - Result << "</em>"; - return; - } -} - -void CommentASTToHTMLConverter::visitHTMLStartTagComment( - const HTMLStartTagComment *C) { - PrintHTMLStartTagComment(C, Result); -} - -void CommentASTToHTMLConverter::visitHTMLEndTagComment( - const HTMLEndTagComment *C) { - Result << "</" << C->getTagName() << ">"; -} - -void CommentASTToHTMLConverter::visitParagraphComment( - const ParagraphComment *C) { - if (C->isWhitespace()) - return; - - Result << "<p>"; - for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); - I != E; ++I) { - visit(*I); - } - Result << "</p>"; -} - -void CommentASTToHTMLConverter::visitBlockCommandComment( - const BlockCommandComment *C) { - const CommandInfo *Info = Traits.getCommandInfo(C->getCommandID()); - if (Info->IsBriefCommand) { - Result << "<p class=\"para-brief\">"; - visitNonStandaloneParagraphComment(C->getParagraph()); - Result << "</p>"; - return; - } - if (Info->IsReturnsCommand) { - Result << "<p class=\"para-returns\">" - "<span class=\"word-returns\">Returns</span> "; - visitNonStandaloneParagraphComment(C->getParagraph()); - Result << "</p>"; - return; - } - // We don't know anything about this command. Just render the paragraph. - visit(C->getParagraph()); -} - -void CommentASTToHTMLConverter::visitParamCommandComment( - const ParamCommandComment *C) { - if (C->isParamIndexValid()) { - Result << "<dt class=\"param-name-index-" - << C->getParamIndex() - << "\">"; - appendToResultWithHTMLEscaping(C->getParamName(FC)); - } else { - Result << "<dt class=\"param-name-index-invalid\">"; - appendToResultWithHTMLEscaping(C->getParamNameAsWritten()); - } - Result << "</dt>"; - - if (C->isParamIndexValid()) { - Result << "<dd class=\"param-descr-index-" - << C->getParamIndex() - << "\">"; - } else - Result << "<dd class=\"param-descr-index-invalid\">"; - - visitNonStandaloneParagraphComment(C->getParagraph()); - Result << "</dd>"; -} - -void CommentASTToHTMLConverter::visitTParamCommandComment( - const TParamCommandComment *C) { - if (C->isPositionValid()) { - if (C->getDepth() == 1) - Result << "<dt class=\"tparam-name-index-" - << C->getIndex(0) - << "\">"; - else - Result << "<dt class=\"tparam-name-index-other\">"; - appendToResultWithHTMLEscaping(C->getParamName(FC)); - } else { - Result << "<dt class=\"tparam-name-index-invalid\">"; - appendToResultWithHTMLEscaping(C->getParamNameAsWritten()); - } - - Result << "</dt>"; - - if (C->isPositionValid()) { - if (C->getDepth() == 1) - Result << "<dd class=\"tparam-descr-index-" - << C->getIndex(0) - << "\">"; - else - Result << "<dd class=\"tparam-descr-index-other\">"; - } else - Result << "<dd class=\"tparam-descr-index-invalid\">"; - - visitNonStandaloneParagraphComment(C->getParagraph()); - Result << "</dd>"; -} - -void CommentASTToHTMLConverter::visitVerbatimBlockComment( - const VerbatimBlockComment *C) { - unsigned NumLines = C->getNumLines(); - if (NumLines == 0) - return; - - Result << "<pre>"; - for (unsigned i = 0; i != NumLines; ++i) { - appendToResultWithHTMLEscaping(C->getText(i)); - if (i + 1 != NumLines) - Result << '\n'; - } - Result << "</pre>"; -} - -void CommentASTToHTMLConverter::visitVerbatimBlockLineComment( - const VerbatimBlockLineComment *C) { - llvm_unreachable("should not see this AST node"); -} - -void CommentASTToHTMLConverter::visitVerbatimLineComment( - const VerbatimLineComment *C) { - Result << "<pre>"; - appendToResultWithHTMLEscaping(C->getText()); - Result << "</pre>"; -} - -void CommentASTToHTMLConverter::visitFullComment(const FullComment *C) { - FullCommentParts Parts(C, Traits); - - bool FirstParagraphIsBrief = false; - if (Parts.Headerfile) - visit(Parts.Headerfile); - if (Parts.Brief) - visit(Parts.Brief); - else if (Parts.FirstParagraph) { - Result << "<p class=\"para-brief\">"; - visitNonStandaloneParagraphComment(Parts.FirstParagraph); - Result << "</p>"; - FirstParagraphIsBrief = true; - } - - for (unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) { - const Comment *C = Parts.MiscBlocks[i]; - if (FirstParagraphIsBrief && C == Parts.FirstParagraph) - continue; - visit(C); - } - - if (Parts.TParams.size() != 0) { - Result << "<dl>"; - for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i) - visit(Parts.TParams[i]); - Result << "</dl>"; - } - - if (Parts.Params.size() != 0) { - Result << "<dl>"; - for (unsigned i = 0, e = Parts.Params.size(); i != e; ++i) - visit(Parts.Params[i]); - Result << "</dl>"; - } - - if (Parts.Returns) - visit(Parts.Returns); - - Result.flush(); -} - -void CommentASTToHTMLConverter::visitNonStandaloneParagraphComment( - const ParagraphComment *C) { - if (!C) - return; - - for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); - I != E; ++I) { - visit(*I); - } -} - -void CommentASTToHTMLConverter::appendToResultWithHTMLEscaping(StringRef S) { - for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) { - const char C = *I; - switch (C) { - case '&': - Result << "&"; - break; - case '<': - Result << "<"; - break; - case '>': - Result << ">"; - break; - case '"': - Result << """; - break; - case '\'': - Result << "'"; - break; - case '/': - Result << "/"; - break; - default: - Result << C; - break; - } - } -} - -extern "C" { - CXString clang_HTMLTagComment_getAsString(CXComment CXC) { const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC); if (!HTC) return cxstring::createNull(); - SmallString<128> HTML; - CommentASTToHTMLConverter Converter(0, HTML, getCommandTraits(CXC)); - Converter.visit(HTC); - return cxstring::createDup(HTML.str()); + CXTranslationUnit TU = CXC.TranslationUnit; + if (!TU->CommentToXML) + TU->CommentToXML = new clang::index::CommentToXMLConverter(); + + SmallString<128> Text; + TU->CommentToXML->convertHTMLTagNodeToText( + HTC, Text, cxtu::getASTUnit(TU)->getASTContext()); + return cxstring::createDup(Text.str()); } CXString clang_FullComment_getAsHTML(CXComment CXC) { @@ -850,596 +368,28 @@ CXString clang_FullComment_getAsHTML(CXComment CXC) { if (!FC) return cxstring::createNull(); + CXTranslationUnit TU = CXC.TranslationUnit; + if (!TU->CommentToXML) + TU->CommentToXML = new clang::index::CommentToXMLConverter(); + SmallString<1024> HTML; - CommentASTToHTMLConverter Converter(FC, HTML, getCommandTraits(CXC)); - Converter.visit(FC); + TU->CommentToXML + ->convertCommentToHTML(FC, HTML, cxtu::getASTUnit(TU)->getASTContext()); return cxstring::createDup(HTML.str()); } -} // end extern "C" - -namespace { -class CommentASTToXMLConverter : - public ConstCommentVisitor<CommentASTToXMLConverter> { -public: - /// \param Str accumulator for XML. - CommentASTToXMLConverter(const FullComment *FC, - SmallVectorImpl<char> &Str, - const CommandTraits &Traits, - const SourceManager &SM, - SimpleFormatContext &SFC, - unsigned FUID) : - FC(FC), Result(Str), Traits(Traits), SM(SM), - FormatRewriterContext(SFC), - FormatInMemoryUniqueId(FUID) { } - - // Inline content. - void visitTextComment(const TextComment *C); - void visitInlineCommandComment(const InlineCommandComment *C); - void visitHTMLStartTagComment(const HTMLStartTagComment *C); - void visitHTMLEndTagComment(const HTMLEndTagComment *C); - - // Block content. - void visitParagraphComment(const ParagraphComment *C); - - void appendParagraphCommentWithKind(const ParagraphComment *C, - StringRef Kind); - - void visitBlockCommandComment(const BlockCommandComment *C); - void visitParamCommandComment(const ParamCommandComment *C); - void visitTParamCommandComment(const TParamCommandComment *C); - void visitVerbatimBlockComment(const VerbatimBlockComment *C); - void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C); - void visitVerbatimLineComment(const VerbatimLineComment *C); - - void visitFullComment(const FullComment *C); - - // Helpers. - void appendToResultWithXMLEscaping(StringRef S); - - void formatTextOfDeclaration(const DeclInfo *DI, - SmallString<128> &Declaration); - -private: - const FullComment *FC; - - /// Output stream for XML. - llvm::raw_svector_ostream Result; - - const CommandTraits &Traits; - const SourceManager &SM; - SimpleFormatContext &FormatRewriterContext; - unsigned FormatInMemoryUniqueId; -}; - -void getSourceTextOfDeclaration(const DeclInfo *ThisDecl, - SmallVectorImpl<char> &Str) { - ASTContext &Context = ThisDecl->CurrentDecl->getASTContext(); - const LangOptions &LangOpts = Context.getLangOpts(); - llvm::raw_svector_ostream OS(Str); - PrintingPolicy PPolicy(LangOpts); - PPolicy.PolishForDeclaration = true; - PPolicy.TerseOutput = true; - ThisDecl->CurrentDecl->print(OS, PPolicy, - /*Indentation*/0, /*PrintInstantiation*/false); -} - -void CommentASTToXMLConverter::formatTextOfDeclaration( - const DeclInfo *DI, - SmallString<128> &Declaration) { - // FIXME. formatting API expects null terminated input string. - // There might be more efficient way of doing this. - std::string StringDecl = Declaration.str(); - - // Formatter specific code. - // Form a unique in memory buffer name. - SmallString<128> filename; - filename += "xmldecl"; - filename += llvm::utostr(FormatInMemoryUniqueId); - filename += ".xd"; - FileID ID = FormatRewriterContext.createInMemoryFile(filename, StringDecl); - SourceLocation Start = - FormatRewriterContext.Sources.getLocForStartOfFile(ID).getLocWithOffset(0); - unsigned Length = Declaration.size(); - - std::vector<CharSourceRange> - Ranges(1, CharSourceRange::getCharRange(Start, Start.getLocWithOffset(Length))); - ASTContext &Context = DI->CurrentDecl->getASTContext(); - const LangOptions &LangOpts = Context.getLangOpts(); - Lexer Lex(ID, FormatRewriterContext.Sources.getBuffer(ID), - FormatRewriterContext.Sources, LangOpts); - tooling::Replacements Replace = - reformat(format::getLLVMStyle(), Lex, FormatRewriterContext.Sources, Ranges); - applyAllReplacements(Replace, FormatRewriterContext.Rewrite); - Declaration = FormatRewriterContext.getRewrittenText(ID); -} - -} // end unnamed namespace - -void CommentASTToXMLConverter::visitTextComment(const TextComment *C) { - appendToResultWithXMLEscaping(C->getText()); -} - -void CommentASTToXMLConverter::visitInlineCommandComment(const InlineCommandComment *C) { - // Nothing to render if no arguments supplied. - if (C->getNumArgs() == 0) - return; - - // Nothing to render if argument is empty. - StringRef Arg0 = C->getArgText(0); - if (Arg0.empty()) - return; - - switch (C->getRenderKind()) { - case InlineCommandComment::RenderNormal: - for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) { - appendToResultWithXMLEscaping(C->getArgText(i)); - Result << " "; - } - return; - case InlineCommandComment::RenderBold: - assert(C->getNumArgs() == 1); - Result << "<bold>"; - appendToResultWithXMLEscaping(Arg0); - Result << "</bold>"; - return; - case InlineCommandComment::RenderMonospaced: - assert(C->getNumArgs() == 1); - Result << "<monospaced>"; - appendToResultWithXMLEscaping(Arg0); - Result << "</monospaced>"; - return; - case InlineCommandComment::RenderEmphasized: - assert(C->getNumArgs() == 1); - Result << "<emphasized>"; - appendToResultWithXMLEscaping(Arg0); - Result << "</emphasized>"; - return; - } -} - -void CommentASTToXMLConverter::visitHTMLStartTagComment(const HTMLStartTagComment *C) { - Result << "<rawHTML><![CDATA["; - PrintHTMLStartTagComment(C, Result); - Result << "]]></rawHTML>"; -} - -void CommentASTToXMLConverter::visitHTMLEndTagComment(const HTMLEndTagComment *C) { - Result << "<rawHTML></" << C->getTagName() << "></rawHTML>"; -} - -void CommentASTToXMLConverter::visitParagraphComment(const ParagraphComment *C) { - appendParagraphCommentWithKind(C, StringRef()); -} - -void CommentASTToXMLConverter::appendParagraphCommentWithKind( - const ParagraphComment *C, - StringRef ParagraphKind) { - if (C->isWhitespace()) - return; - - if (ParagraphKind.empty()) - Result << "<Para>"; - else - Result << "<Para kind=\"" << ParagraphKind << "\">"; - - for (Comment::child_iterator I = C->child_begin(), E = C->child_end(); - I != E; ++I) { - visit(*I); - } - Result << "</Para>"; -} - -void CommentASTToXMLConverter::visitBlockCommandComment(const BlockCommandComment *C) { - StringRef ParagraphKind; - - switch (C->getCommandID()) { - case CommandTraits::KCI_attention: - case CommandTraits::KCI_author: - case CommandTraits::KCI_authors: - case CommandTraits::KCI_bug: - case CommandTraits::KCI_copyright: - case CommandTraits::KCI_date: - case CommandTraits::KCI_invariant: - case CommandTraits::KCI_note: - case CommandTraits::KCI_post: - case CommandTraits::KCI_pre: - case CommandTraits::KCI_remark: - case CommandTraits::KCI_remarks: - case CommandTraits::KCI_sa: - case CommandTraits::KCI_see: - case CommandTraits::KCI_since: - case CommandTraits::KCI_todo: - case CommandTraits::KCI_version: - case CommandTraits::KCI_warning: - ParagraphKind = C->getCommandName(Traits); - default: - break; - } - - appendParagraphCommentWithKind(C->getParagraph(), ParagraphKind); -} - -void CommentASTToXMLConverter::visitParamCommandComment(const ParamCommandComment *C) { - Result << "<Parameter><Name>"; - appendToResultWithXMLEscaping(C->isParamIndexValid() ? C->getParamName(FC) - : C->getParamNameAsWritten()); - Result << "</Name>"; - - if (C->isParamIndexValid()) - Result << "<Index>" << C->getParamIndex() << "</Index>"; - - Result << "<Direction isExplicit=\"" << C->isDirectionExplicit() << "\">"; - switch (C->getDirection()) { - case ParamCommandComment::In: - Result << "in"; - break; - case ParamCommandComment::Out: - Result << "out"; - break; - case ParamCommandComment::InOut: - Result << "in,out"; - break; - } - Result << "</Direction><Discussion>"; - visit(C->getParagraph()); - Result << "</Discussion></Parameter>"; -} - -void CommentASTToXMLConverter::visitTParamCommandComment( - const TParamCommandComment *C) { - Result << "<Parameter><Name>"; - appendToResultWithXMLEscaping(C->isPositionValid() ? C->getParamName(FC) - : C->getParamNameAsWritten()); - Result << "</Name>"; - - if (C->isPositionValid() && C->getDepth() == 1) { - Result << "<Index>" << C->getIndex(0) << "</Index>"; - } - - Result << "<Discussion>"; - visit(C->getParagraph()); - Result << "</Discussion></Parameter>"; -} - -void CommentASTToXMLConverter::visitVerbatimBlockComment( - const VerbatimBlockComment *C) { - unsigned NumLines = C->getNumLines(); - if (NumLines == 0) - return; - - switch (C->getCommandID()) { - case CommandTraits::KCI_code: - Result << "<Verbatim xml:space=\"preserve\" kind=\"code\">"; - break; - default: - Result << "<Verbatim xml:space=\"preserve\" kind=\"verbatim\">"; - break; - } - for (unsigned i = 0; i != NumLines; ++i) { - appendToResultWithXMLEscaping(C->getText(i)); - if (i + 1 != NumLines) - Result << '\n'; - } - Result << "</Verbatim>"; -} - -void CommentASTToXMLConverter::visitVerbatimBlockLineComment( - const VerbatimBlockLineComment *C) { - llvm_unreachable("should not see this AST node"); -} - -void CommentASTToXMLConverter::visitVerbatimLineComment( - const VerbatimLineComment *C) { - Result << "<Verbatim xml:space=\"preserve\" kind=\"verbatim\">"; - appendToResultWithXMLEscaping(C->getText()); - Result << "</Verbatim>"; -} - -void CommentASTToXMLConverter::visitFullComment(const FullComment *C) { - FullCommentParts Parts(C, Traits); - - const DeclInfo *DI = C->getDeclInfo(); - StringRef RootEndTag; - if (DI) { - switch (DI->getKind()) { - case DeclInfo::OtherKind: - RootEndTag = "</Other>"; - Result << "<Other"; - break; - case DeclInfo::FunctionKind: - RootEndTag = "</Function>"; - Result << "<Function"; - switch (DI->TemplateKind) { - case DeclInfo::NotTemplate: - break; - case DeclInfo::Template: - Result << " templateKind=\"template\""; - break; - case DeclInfo::TemplateSpecialization: - Result << " templateKind=\"specialization\""; - break; - case DeclInfo::TemplatePartialSpecialization: - llvm_unreachable("partial specializations of functions " - "are not allowed in C++"); - } - if (DI->IsInstanceMethod) - Result << " isInstanceMethod=\"1\""; - if (DI->IsClassMethod) - Result << " isClassMethod=\"1\""; - break; - case DeclInfo::ClassKind: - RootEndTag = "</Class>"; - Result << "<Class"; - switch (DI->TemplateKind) { - case DeclInfo::NotTemplate: - break; - case DeclInfo::Template: - Result << " templateKind=\"template\""; - break; - case DeclInfo::TemplateSpecialization: - Result << " templateKind=\"specialization\""; - break; - case DeclInfo::TemplatePartialSpecialization: - Result << " templateKind=\"partialSpecialization\""; - break; - } - break; - case DeclInfo::VariableKind: - RootEndTag = "</Variable>"; - Result << "<Variable"; - break; - case DeclInfo::NamespaceKind: - RootEndTag = "</Namespace>"; - Result << "<Namespace"; - break; - case DeclInfo::TypedefKind: - RootEndTag = "</Typedef>"; - Result << "<Typedef"; - break; - case DeclInfo::EnumKind: - RootEndTag = "</Enum>"; - Result << "<Enum"; - break; - } - - { - // Print line and column number. - SourceLocation Loc = DI->CurrentDecl->getLocation(); - std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); - FileID FID = LocInfo.first; - unsigned FileOffset = LocInfo.second; - - if (!FID.isInvalid()) { - if (const FileEntry *FE = SM.getFileEntryForID(FID)) { - Result << " file=\""; - appendToResultWithXMLEscaping(FE->getName()); - Result << "\""; - } - Result << " line=\"" << SM.getLineNumber(FID, FileOffset) - << "\" column=\"" << SM.getColumnNumber(FID, FileOffset) - << "\""; - } - } - - // Finish the root tag. - Result << ">"; - - bool FoundName = false; - if (const NamedDecl *ND = dyn_cast<NamedDecl>(DI->CommentDecl)) { - if (DeclarationName DeclName = ND->getDeclName()) { - Result << "<Name>"; - std::string Name = DeclName.getAsString(); - appendToResultWithXMLEscaping(Name); - FoundName = true; - Result << "</Name>"; - } - } - if (!FoundName) - Result << "<Name><anonymous></Name>"; - - { - // Print USR. - SmallString<128> USR; - cxcursor::getDeclCursorUSR(DI->CommentDecl, USR); - if (!USR.empty()) { - Result << "<USR>"; - appendToResultWithXMLEscaping(USR); - Result << "</USR>"; - } - } - } else { - // No DeclInfo -- just emit some root tag and name tag. - RootEndTag = "</Other>"; - Result << "<Other><Name>unknown</Name>"; - } - - if (Parts.Headerfile) { - Result << "<Headerfile>"; - visit(Parts.Headerfile); - Result << "</Headerfile>"; - } - - { - // Pretty-print the declaration. - Result << "<Declaration>"; - SmallString<128> Declaration; - getSourceTextOfDeclaration(DI, Declaration); - formatTextOfDeclaration(DI, Declaration); - appendToResultWithXMLEscaping(Declaration); - - Result << "</Declaration>"; - } - - bool FirstParagraphIsBrief = false; - if (Parts.Brief) { - Result << "<Abstract>"; - visit(Parts.Brief); - Result << "</Abstract>"; - } else if (Parts.FirstParagraph) { - Result << "<Abstract>"; - visit(Parts.FirstParagraph); - Result << "</Abstract>"; - FirstParagraphIsBrief = true; - } - - if (Parts.TParams.size() != 0) { - Result << "<TemplateParameters>"; - for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i) - visit(Parts.TParams[i]); - Result << "</TemplateParameters>"; - } - - if (Parts.Params.size() != 0) { - Result << "<Parameters>"; - for (unsigned i = 0, e = Parts.Params.size(); i != e; ++i) - visit(Parts.Params[i]); - Result << "</Parameters>"; - } - - if (Parts.Returns) { - Result << "<ResultDiscussion>"; - visit(Parts.Returns); - Result << "</ResultDiscussion>"; - } - - if (DI->CommentDecl->hasAttrs()) { - const AttrVec &Attrs = DI->CommentDecl->getAttrs(); - for (unsigned i = 0, e = Attrs.size(); i != e; i++) { - const AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attrs[i]); - if (!AA) { - if (const DeprecatedAttr *DA = dyn_cast<DeprecatedAttr>(Attrs[i])) { - if (DA->getMessage().empty()) - Result << "<Deprecated/>"; - else { - Result << "<Deprecated>"; - appendToResultWithXMLEscaping(DA->getMessage()); - Result << "</Deprecated>"; - } - } - else if (const UnavailableAttr *UA = dyn_cast<UnavailableAttr>(Attrs[i])) { - if (UA->getMessage().empty()) - Result << "<Unavailable/>"; - else { - Result << "<Unavailable>"; - appendToResultWithXMLEscaping(UA->getMessage()); - Result << "</Unavailable>"; - } - } - continue; - } - - // 'availability' attribute. - Result << "<Availability"; - StringRef Distribution; - if (AA->getPlatform()) { - Distribution = AvailabilityAttr::getPrettyPlatformName( - AA->getPlatform()->getName()); - if (Distribution.empty()) - Distribution = AA->getPlatform()->getName(); - } - Result << " distribution=\"" << Distribution << "\">"; - VersionTuple IntroducedInVersion = AA->getIntroduced(); - if (!IntroducedInVersion.empty()) { - Result << "<IntroducedInVersion>" - << IntroducedInVersion.getAsString() - << "</IntroducedInVersion>"; - } - VersionTuple DeprecatedInVersion = AA->getDeprecated(); - if (!DeprecatedInVersion.empty()) { - Result << "<DeprecatedInVersion>" - << DeprecatedInVersion.getAsString() - << "</DeprecatedInVersion>"; - } - VersionTuple RemovedAfterVersion = AA->getObsoleted(); - if (!RemovedAfterVersion.empty()) { - Result << "<RemovedAfterVersion>" - << RemovedAfterVersion.getAsString() - << "</RemovedAfterVersion>"; - } - StringRef DeprecationSummary = AA->getMessage(); - if (!DeprecationSummary.empty()) { - Result << "<DeprecationSummary>"; - appendToResultWithXMLEscaping(DeprecationSummary); - Result << "</DeprecationSummary>"; - } - if (AA->getUnavailable()) - Result << "<Unavailable/>"; - Result << "</Availability>"; - } - } - - { - bool StartTagEmitted = false; - for (unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) { - const Comment *C = Parts.MiscBlocks[i]; - if (FirstParagraphIsBrief && C == Parts.FirstParagraph) - continue; - if (!StartTagEmitted) { - Result << "<Discussion>"; - StartTagEmitted = true; - } - visit(C); - } - if (StartTagEmitted) - Result << "</Discussion>"; - } - - Result << RootEndTag; - - Result.flush(); -} - -void CommentASTToXMLConverter::appendToResultWithXMLEscaping(StringRef S) { - for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) { - const char C = *I; - switch (C) { - case '&': - Result << "&"; - break; - case '<': - Result << "<"; - break; - case '>': - Result << ">"; - break; - case '"': - Result << """; - break; - case '\'': - Result << "'"; - break; - default: - Result << C; - break; - } - } -} - -extern "C" { - CXString clang_FullComment_getAsXML(CXComment CXC) { const FullComment *FC = getASTNodeAs<FullComment>(CXC); if (!FC) return cxstring::createNull(); - ASTContext &Context = FC->getDeclInfo()->CurrentDecl->getASTContext(); + CXTranslationUnit TU = CXC.TranslationUnit; - SourceManager &SM = cxtu::getASTUnit(TU)->getSourceManager(); - - if (!TU->FormatContext) { - TU->FormatContext = new SimpleFormatContext(Context.getLangOpts()); - } else if ((TU->FormatInMemoryUniqueId % 1000) == 0) { - // Delete after some number of iterators, so the buffers don't grow - // too large. - delete TU->FormatContext; - TU->FormatContext = new SimpleFormatContext(Context.getLangOpts()); - } + if (!TU->CommentToXML) + TU->CommentToXML = new clang::index::CommentToXMLConverter(); SmallString<1024> XML; - CommentASTToXMLConverter Converter(FC, XML, getCommandTraits(CXC), SM, - *TU->FormatContext, - TU->FormatInMemoryUniqueId++); - Converter.visit(FC); + TU->CommentToXML + ->convertCommentToXML(FC, XML, cxtu::getASTUnit(TU)->getASTContext()); return cxstring::createDup(XML.str()); } diff --git a/tools/libclang/CXComment.h b/tools/libclang/CXComment.h index 0780a65..1e2561d 100644 --- a/tools/libclang/CXComment.h +++ b/tools/libclang/CXComment.h @@ -27,20 +27,20 @@ namespace comments { namespace cxcomment { -inline CXComment createCXComment(const comments::Comment *C, - CXTranslationUnit TU) { +static inline CXComment createCXComment(const comments::Comment *C, + CXTranslationUnit TU) { CXComment Result; Result.ASTNode = C; Result.TranslationUnit = TU; return Result; } -inline const comments::Comment *getASTNode(CXComment CXC) { +static inline const comments::Comment *getASTNode(CXComment CXC) { return static_cast<const comments::Comment *>(CXC.ASTNode); } template<typename T> -inline const T *getASTNodeAs(CXComment CXC) { +static inline const T *getASTNodeAs(CXComment CXC) { const comments::Comment *C = getASTNode(CXC); if (!C) return NULL; @@ -48,11 +48,11 @@ inline const T *getASTNodeAs(CXComment CXC) { return dyn_cast<T>(C); } -inline ASTContext &getASTContext(CXComment CXC) { +static inline ASTContext &getASTContext(CXComment CXC) { return cxtu::getASTUnit(CXC.TranslationUnit)->getASTContext(); } -inline comments::CommandTraits &getCommandTraits(CXComment CXC) { +static inline comments::CommandTraits &getCommandTraits(CXComment CXC) { return getASTContext(CXC).getCommentCommandTraits(); } diff --git a/tools/libclang/CXCompilationDatabase.cpp b/tools/libclang/CXCompilationDatabase.cpp index e35ac27..433caec 100644 --- a/tools/libclang/CXCompilationDatabase.cpp +++ b/tools/libclang/CXCompilationDatabase.cpp @@ -1,6 +1,7 @@ #include "clang-c/CXCompilationDatabase.h" #include "CXString.h" #include "clang/Tooling/CompilationDatabase.h" +#include <cstdio> using namespace clang; using namespace clang::tooling; @@ -135,5 +136,41 @@ clang_CompileCommand_getArg(CXCompileCommand CCmd, unsigned Arg) return cxstring::createRef(Cmd->CommandLine[Arg].c_str()); } +unsigned +clang_CompileCommand_getNumMappedSources(CXCompileCommand CCmd) +{ + if (!CCmd) + return 0; + + return static_cast<CompileCommand *>(CCmd)->MappedSources.size(); +} + +CXString +clang_CompileCommand_getMappedSourcePath(CXCompileCommand CCmd, unsigned I) +{ + if (!CCmd) + return cxstring::createNull(); + + CompileCommand *Cmd = static_cast<CompileCommand *>(CCmd); + + if (I >= Cmd->MappedSources.size()) + return cxstring::createNull(); + + return cxstring::createRef(Cmd->MappedSources[I].first.c_str()); +} + +CXString +clang_CompileCommand_getMappedSourceContent(CXCompileCommand CCmd, unsigned I) +{ + if (!CCmd) + return cxstring::createNull(); + + CompileCommand *Cmd = static_cast<CompileCommand *>(CCmd); + + if (I >= Cmd->MappedSources.size()) + return cxstring::createNull(); + + return cxstring::createRef(Cmd->MappedSources[I].second.c_str()); +} } // end: extern "C" diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index 2cdb71b..c75c061 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -18,6 +18,7 @@ #include "CXString.h" #include "CXType.h" #include "clang-c/Index.h" +#include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" @@ -48,6 +49,7 @@ static CXCursorKind GetCursorKind(const Attr *A) { case attr::Override: return CXCursor_CXXOverrideAttr; case attr::Annotate: return CXCursor_AnnotateAttr; case attr::AsmLabel: return CXCursor_AsmLabelAttr; + case attr::Packed: return CXCursor_PackedAttr; } return CXCursor_UnexposedAttr; @@ -75,7 +77,7 @@ CXCursor cxcursor::MakeCXCursor(const Decl *D, CXTranslationUnit TU, RegionOfInterest.getBegin() == RegionOfInterest.getEnd()) { SmallVector<SourceLocation, 16> SelLocs; cast<ObjCMethodDecl>(D)->getSelectorLocs(SelLocs); - SmallVector<SourceLocation, 16>::iterator + SmallVectorImpl<SourceLocation>::iterator I=std::find(SelLocs.begin(), SelLocs.end(),RegionOfInterest.getBegin()); if (I != SelLocs.end()) SelectorIdIndex = I - SelLocs.begin(); @@ -216,6 +218,7 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::CXXBindTemporaryExprClass: case Stmt::CXXDefaultArgExprClass: case Stmt::CXXDefaultInitExprClass: + case Stmt::CXXStdInitializerListExprClass: case Stmt::CXXScalarValueInitExprClass: case Stmt::CXXUuidofExprClass: case Stmt::ChooseExprClass: @@ -231,6 +234,7 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::ParenListExprClass: case Stmt::PredefinedExprClass: case Stmt::ShuffleVectorExprClass: + case Stmt::ConvertVectorExprClass: case Stmt::UnaryExprOrTypeTraitExprClass: case Stmt::UnaryTypeTraitExprClass: case Stmt::VAArgExprClass: @@ -492,7 +496,7 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, RegionOfInterest.getBegin() == RegionOfInterest.getEnd()) { SmallVector<SourceLocation, 16> SelLocs; cast<ObjCMessageExpr>(S)->getSelectorLocs(SelLocs); - SmallVector<SourceLocation, 16>::iterator + SmallVectorImpl<SourceLocation>::iterator I=std::find(SelLocs.begin(), SelLocs.end(),RegionOfInterest.getBegin()); if (I != SelLocs.end()) SelectorIdIndex = I - SelLocs.begin(); @@ -504,6 +508,10 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::MSDependentExistsStmtClass: K = CXCursor_UnexposedStmt; break; + case Stmt::OMPParallelDirectiveClass: + K = CXCursor_OMPParallelDirective; + break; + } CXCursor C = { K, 0, { Parent, S, TU } }; @@ -836,7 +844,7 @@ void cxcursor::getOverriddenCursors(CXCursor cursor, SmallVector<const NamedDecl *, 8> OverDecls; D->getASTContext().getOverriddenMethods(D, OverDecls); - for (SmallVector<const NamedDecl *, 8>::iterator + for (SmallVectorImpl<const NamedDecl *>::iterator I = OverDecls.begin(), E = OverDecls.end(); I != E; ++I) { overridden.push_back(MakeCXCursor(*I, TU)); } diff --git a/tools/libclang/CXSourceLocation.cpp b/tools/libclang/CXSourceLocation.cpp index b7c7622..7371177 100644 --- a/tools/libclang/CXSourceLocation.cpp +++ b/tools/libclang/CXSourceLocation.cpp @@ -124,6 +124,8 @@ CXSourceLocation clang_getLocation(CXTranslationUnit TU, unsigned column) { if (!TU || !file) return clang_getNullLocation(); + if (line == 0 || column == 0) + return clang_getNullLocation(); LogRef Log = Logger::make(LLVM_FUNCTION_NAME); ASTUnit *CXXUnit = cxtu::getASTUnit(TU); @@ -209,6 +211,17 @@ int clang_Location_isInSystemHeader(CXSourceLocation location) { return SM.isInSystemHeader(Loc); } +int clang_Location_isFromMainFile(CXSourceLocation location) { + const SourceLocation Loc = + SourceLocation::getFromRawEncoding(location.int_data); + if (Loc.isInvalid()) + return 0; + + const SourceManager &SM = + *static_cast<const SourceManager*>(location.ptr_data[0]); + return SM.isWrittenInMainFile(Loc); +} + void clang_getExpansionLocation(CXSourceLocation location, CXFile *file, unsigned *line, @@ -255,7 +268,7 @@ void clang_getPresumedLocation(CXSourceLocation location, CXString *filename, unsigned *line, unsigned *column) { - + if (!isASTUnitSourceLocation(location)) { // Other SourceLocation implementations do not support presumed locations // at this time. @@ -265,20 +278,22 @@ void clang_getPresumedLocation(CXSourceLocation location, SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); - if (!location.ptr_data[0] || Loc.isInvalid()) + if (!location.ptr_data[0] || Loc.isInvalid()) { createNullLocation(filename, line, column); - else { - const SourceManager &SM = - *static_cast<const SourceManager*>(location.ptr_data[0]); - PresumedLoc PreLoc = SM.getPresumedLoc(Loc); - - if (filename) - *filename = cxstring::createRef(PreLoc.getFilename()); - if (line) - *line = PreLoc.getLine(); - if (column) - *column = PreLoc.getColumn(); + return; } + + const SourceManager &SM = + *static_cast<const SourceManager *>(location.ptr_data[0]); + PresumedLoc PreLoc = SM.getPresumedLoc(Loc); + if (PreLoc.isInvalid()) { + createNullLocation(filename, line, column); + return; + } + + if (filename) *filename = cxstring::createRef(PreLoc.getFilename()); + if (line) *line = PreLoc.getLine(); + if (column) *column = PreLoc.getColumn(); } void clang_getInstantiationLocation(CXSourceLocation location, diff --git a/tools/libclang/CXTranslationUnit.h b/tools/libclang/CXTranslationUnit.h index bdc171c..c0014c0 100644 --- a/tools/libclang/CXTranslationUnit.h +++ b/tools/libclang/CXTranslationUnit.h @@ -20,7 +20,9 @@ namespace clang { class ASTUnit; class CIndexer; - class SimpleFormatContext; +namespace index { +class CommentToXMLConverter; +} // namespace index } // namespace clang struct CXTranslationUnitImpl { @@ -29,8 +31,7 @@ struct CXTranslationUnitImpl { clang::cxstring::CXStringPool *StringPool; void *Diagnostics; void *OverridenCursorsPool; - clang::SimpleFormatContext *FormatContext; - unsigned FormatInMemoryUniqueId; + clang::index::CommentToXMLConverter *CommentToXML; }; namespace clang { diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp index 1482415..1e2cb18 100644 --- a/tools/libclang/CXType.cpp +++ b/tools/libclang/CXType.cpp @@ -85,7 +85,11 @@ static CXTypeKind GetTypeKind(QualType T) { TKCASE(FunctionNoProto); TKCASE(FunctionProto); TKCASE(ConstantArray); + TKCASE(IncompleteArray); + TKCASE(VariableArray); + TKCASE(DependentSizedArray); TKCASE(Vector); + TKCASE(MemberPointer); default: return CXType_Unexposed; } @@ -107,6 +111,11 @@ CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) { else if (Ctx.isObjCSelType(UnqualT)) TK = CXType_ObjCSel; } + + /* Handle decayed types as the original type */ + if (const DecayedType *DT = T->getAs<DecayedType>()) { + return MakeCXType(DT->getOriginalType(), TU); + } } if (TK == CXType_Invalid) TK = GetTypeKind(T); @@ -357,6 +366,9 @@ CXType clang_getPointeeType(CXType CT) { case Type::ObjCObjectPointer: T = cast<ObjCObjectPointerType>(TP)->getPointeeType(); break; + case Type::MemberPointer: + T = cast<MemberPointerType>(TP)->getPointeeType(); + break; default: T = QualType(); break; @@ -466,7 +478,11 @@ CXString clang_getTypeKindSpelling(enum CXTypeKind K) { TKIND(FunctionNoProto); TKIND(FunctionProto); TKIND(ConstantArray); + TKIND(IncompleteArray); + TKIND(VariableArray); + TKIND(DependentSizedArray); TKIND(Vector); + TKIND(MemberPointer); } #undef TKIND return cxstring::createRef(s); @@ -498,12 +514,13 @@ CXCallingConv clang_getFunctionTypeCallingConv(CXType X) { if (const FunctionType *FD = T->getAs<FunctionType>()) { #define TCALLINGCONV(X) case CC_##X: return CXCallingConv_##X switch (FD->getCallConv()) { - TCALLINGCONV(Default); TCALLINGCONV(C); TCALLINGCONV(X86StdCall); TCALLINGCONV(X86FastCall); TCALLINGCONV(X86ThisCall); TCALLINGCONV(X86Pascal); + TCALLINGCONV(X86_64Win64); + TCALLINGCONV(X86_64SysV); TCALLINGCONV(AAPCS); TCALLINGCONV(AAPCS_VFP); TCALLINGCONV(PnaclCall); @@ -590,6 +607,15 @@ CXType clang_getElementType(CXType CT) { case Type::ConstantArray: ET = cast<ConstantArrayType> (TP)->getElementType(); break; + case Type::IncompleteArray: + ET = cast<IncompleteArrayType> (TP)->getElementType(); + break; + case Type::VariableArray: + ET = cast<VariableArrayType> (TP)->getElementType(); + break; + case Type::DependentSizedArray: + ET = cast<DependentSizedArrayType> (TP)->getElementType(); + break; case Type::Vector: ET = cast<VectorType> (TP)->getElementType(); break; @@ -633,6 +659,15 @@ CXType clang_getArrayElementType(CXType CT) { case Type::ConstantArray: ET = cast<ConstantArrayType> (TP)->getElementType(); break; + case Type::IncompleteArray: + ET = cast<IncompleteArrayType> (TP)->getElementType(); + break; + case Type::VariableArray: + ET = cast<VariableArrayType> (TP)->getElementType(); + break; + case Type::DependentSizedArray: + ET = cast<DependentSizedArrayType> (TP)->getElementType(); + break; default: break; } @@ -677,6 +712,17 @@ long long clang_Type_getAlignOf(CXType T) { return Ctx.getTypeAlignInChars(QT).getQuantity(); } +CXType clang_Type_getClassType(CXType CT) { + QualType ET = QualType(); + QualType T = GetQualType(CT); + const Type *TP = T.getTypePtrOrNull(); + + if (TP && TP->getTypeClass() == Type::MemberPointer) { + ET = QualType(cast<MemberPointerType> (TP)->getClass(), 0); + } + return MakeCXType(ET, GetTU(CT)); +} + long long clang_Type_getSizeOf(CXType T) { if (T.kind == CXType_Invalid) return CXTypeLayoutError_Invalid; @@ -733,11 +779,13 @@ long long clang_Type_getOffsetOf(CXType PT, const char *S) { return CXTypeLayoutError_Invalid; const RecordDecl *RD = dyn_cast_or_null<RecordDecl>(cxcursor::getCursorDecl(PC)); - if (!RD) + if (!RD || RD->isInvalidDecl()) return CXTypeLayoutError_Invalid; RD = RD->getDefinition(); if (!RD) return CXTypeLayoutError_Incomplete; + if (RD->isInvalidDecl()) + return CXTypeLayoutError_Invalid; QualType RT = GetQualType(PT); if (RT->isIncompleteType()) return CXTypeLayoutError_Incomplete; @@ -768,6 +816,24 @@ long long clang_Type_getOffsetOf(CXType PT, const char *S) { return CXTypeLayoutError_InvalidFieldName; } +enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T) { + QualType QT = GetQualType(T); + if (QT.isNull()) + return CXRefQualifier_None; + const FunctionProtoType *FD = QT->getAs<FunctionProtoType>(); + if (!FD) + return CXRefQualifier_None; + switch (FD->getRefQualifier()) { + case RQ_None: + return CXRefQualifier_None; + case RQ_LValue: + return CXRefQualifier_LValue; + case RQ_RValue: + return CXRefQualifier_RValue; + } + return CXRefQualifier_None; +} + unsigned clang_Cursor_isBitField(CXCursor C) { if (!clang_isDeclaration(C.kind)) return 0; diff --git a/tools/libclang/IndexBody.cpp b/tools/libclang/IndexBody.cpp index 02ab885..e08a346 100644 --- a/tools/libclang/IndexBody.cpp +++ b/tools/libclang/IndexBody.cpp @@ -153,9 +153,11 @@ public: if (C.capturesThis()) return true; - if (IndexCtx.shouldIndexFunctionLocalSymbols()) + if (C.capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols()) IndexCtx.handleReference(C.getCapturedVar(), C.getLocation(), Parent, ParentDC); + + // FIXME: Lambda init-captures. return true; } diff --git a/tools/libclang/IndexDecl.cpp b/tools/libclang/IndexDecl.cpp index 756001c..89feb96 100644 --- a/tools/libclang/IndexDecl.cpp +++ b/tools/libclang/IndexDecl.cpp @@ -22,6 +22,15 @@ public: explicit IndexingDeclVisitor(IndexingContext &indexCtx) : IndexCtx(indexCtx) { } + /// \brief Returns true if the given method has been defined explicitly by the + /// user. + static bool hasUserDefined(const ObjCMethodDecl *D, + const ObjCImplDecl *Container) { + const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(), + D->isInstanceMethod()); + return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition(); + } + void handleDeclarator(const DeclaratorDecl *D, const NamedDecl *Parent = 0) { if (!Parent) Parent = D; @@ -234,12 +243,14 @@ public: } if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { - if (MD->isPropertyAccessor()) + if (MD->isPropertyAccessor() && + !hasUserDefined(MD, cast<ObjCImplDecl>(D->getDeclContext()))) IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(), D->getLexicalDeclContext()); } if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { - if (MD->isPropertyAccessor()) + if (MD->isPropertyAccessor() && + !hasUserDefined(MD, cast<ObjCImplDecl>(D->getDeclContext()))) IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(), D->getLexicalDeclContext()); } diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp index 15786ac..99fcdb6 100644 --- a/tools/libclang/Indexing.cpp +++ b/tools/libclang/Indexing.cpp @@ -31,6 +31,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/MutexGuard.h" +#include <cstdio> using namespace clang; using namespace cxtu; @@ -88,25 +89,23 @@ public: /// #3 is identified as the location of "#ifdef CAKE" /// class PPRegion { - ino_t ino; + llvm::sys::fs::UniqueID UniqueID; time_t ModTime; - dev_t dev; unsigned Offset; public: - PPRegion() : ino(), ModTime(), dev(), Offset() {} - PPRegion(dev_t dev, ino_t ino, unsigned offset, time_t modTime) - : ino(ino), ModTime(modTime), dev(dev), Offset(offset) {} + PPRegion() : UniqueID(0, 0), ModTime(), Offset() {} + PPRegion(llvm::sys::fs::UniqueID UniqueID, unsigned offset, time_t modTime) + : UniqueID(UniqueID), ModTime(modTime), Offset(offset) {} - ino_t getIno() const { return ino; } - dev_t getDev() const { return dev; } + const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; } unsigned getOffset() const { return Offset; } time_t getModTime() const { return ModTime; } bool isInvalid() const { return *this == PPRegion(); } friend bool operator==(const PPRegion &lhs, const PPRegion &rhs) { - return lhs.dev == rhs.dev && lhs.ino == rhs.ino && - lhs.Offset == rhs.Offset && lhs.ModTime == rhs.ModTime; + return lhs.UniqueID == rhs.UniqueID && lhs.Offset == rhs.Offset && + lhs.ModTime == rhs.ModTime; } }; @@ -122,16 +121,17 @@ namespace llvm { template <> struct DenseMapInfo<PPRegion> { static inline PPRegion getEmptyKey() { - return PPRegion(0, 0, unsigned(-1), 0); + return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-1), 0); } static inline PPRegion getTombstoneKey() { - return PPRegion(0, 0, unsigned(-2), 0); + return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-2), 0); } static unsigned getHashValue(const PPRegion &S) { llvm::FoldingSetNodeID ID; - ID.AddInteger(S.getIno()); - ID.AddInteger(S.getDev()); + const llvm::sys::fs::UniqueID &UniqueID = S.getUniqueID(); + ID.AddInteger(UniqueID.getFile()); + ID.AddInteger(UniqueID.getDevice()); ID.AddInteger(S.getOffset()); ID.AddInteger(S.getModTime()); return ID.ComputeHash(); @@ -208,9 +208,10 @@ private: PPRegion getRegion(SourceLocation Loc, FileID FID, const FileEntry *FE) { SourceLocation RegionLoc = PPRec.findConditionalDirectiveRegionLoc(Loc); if (RegionLoc.isInvalid()) { - if (isParsedOnceInclude(FE)) - return PPRegion(FE->getDevice(), FE->getInode(), 0, - FE->getModificationTime()); + if (isParsedOnceInclude(FE)) { + const llvm::sys::fs::UniqueID &ID = FE->getUniqueID(); + return PPRegion(ID, 0, FE->getModificationTime()); + } return PPRegion(); } @@ -221,14 +222,15 @@ private: llvm::tie(RegionFID, RegionOffset) = SM.getDecomposedLoc(RegionLoc); if (RegionFID != FID) { - if (isParsedOnceInclude(FE)) - return PPRegion(FE->getDevice(), FE->getInode(), 0, - FE->getModificationTime()); + if (isParsedOnceInclude(FE)) { + const llvm::sys::fs::UniqueID &ID = FE->getUniqueID(); + return PPRegion(ID, 0, FE->getModificationTime()); + } return PPRegion(); } - return PPRegion(FE->getDevice(), FE->getInode(), RegionOffset, - FE->getModificationTime()); + const llvm::sys::fs::UniqueID &ID = FE->getUniqueID(); + return PPRegion(ID, RegionOffset, FE->getModificationTime()); } bool isParsedOnceInclude(const FileEntry *FE) { diff --git a/tools/libclang/IndexingContext.cpp b/tools/libclang/IndexingContext.cpp index 14b430c..41ed6ea 100644 --- a/tools/libclang/IndexingContext.cpp +++ b/tools/libclang/IndexingContext.cpp @@ -10,6 +10,7 @@ #include "IndexingContext.h" #include "CIndexDiagnostic.h" #include "CXTranslationUnit.h" +#include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/Frontend/ASTUnit.h" @@ -93,17 +94,19 @@ AttrListInfo::AttrListInfo(const Decl *D, IndexingContext &IdxCtx) const IBOutletCollectionAttr * IBAttr = cast<IBOutletCollectionAttr>(IBInfo.A); + SourceLocation InterfaceLocStart = + IBAttr->getInterfaceLoc()->getTypeLoc().getLocStart(); IBInfo.IBCollInfo.attrInfo = &IBInfo; - IBInfo.IBCollInfo.classLoc = IdxCtx.getIndexLoc(IBAttr->getInterfaceLoc()); + IBInfo.IBCollInfo.classLoc = IdxCtx.getIndexLoc(InterfaceLocStart); IBInfo.IBCollInfo.objcClass = 0; IBInfo.IBCollInfo.classCursor = clang_getNullCursor(); QualType Ty = IBAttr->getInterface(); - if (const ObjCInterfaceType *InterTy = Ty->getAs<ObjCInterfaceType>()) { - if (const ObjCInterfaceDecl *InterD = InterTy->getInterface()) { + if (const ObjCObjectType *ObjectTy = Ty->getAs<ObjCObjectType>()) { + if (const ObjCInterfaceDecl *InterD = ObjectTy->getInterface()) { IdxCtx.getEntityInfo(InterD, IBInfo.ClassInfo, SA); IBInfo.IBCollInfo.objcClass = &IBInfo.ClassInfo; - IBInfo.IBCollInfo.classCursor = MakeCursorObjCClassRef(InterD, - IBAttr->getInterfaceLoc(), IdxCtx.CXTU); + IBInfo.IBCollInfo.classCursor = + MakeCursorObjCClassRef(InterD, InterfaceLocStart, IdxCtx.CXTU); } } } @@ -210,11 +213,13 @@ bool IndexingContext::isFunctionLocalDecl(const Decl *D) { return false; if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { - switch (ND->getLinkage()) { + switch (ND->getFormalLinkage()) { case NoLinkage: + case VisibleNoLinkage: case InternalLinkage: return true; case UniqueExternalLinkage: + llvm_unreachable("Not a sema linkage"); case ExternalLinkage: return false; } @@ -378,14 +383,14 @@ bool IndexingContext::handleFunction(const FunctionDecl *D) { isContainer = false; } - DeclInfo DInfo(!D->isFirstDeclaration(), isDef, isContainer); + DeclInfo DInfo(!D->isFirstDecl(), isDef, isContainer); if (isSkipped) DInfo.flags |= CXIdxDeclFlag_Skipped; return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } bool IndexingContext::handleVar(const VarDecl *D) { - DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(), + DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(), /*isContainer=*/false); return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } @@ -412,13 +417,13 @@ bool IndexingContext::handleTagDecl(const TagDecl *D) { if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(D)) return handleCXXRecordDecl(CXXRD, D); - DeclInfo DInfo(!D->isFirstDeclaration(), D->isThisDeclarationADefinition(), + DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(), D->isThisDeclarationADefinition()); return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } bool IndexingContext::handleTypedefName(const TypedefNameDecl *D) { - DeclInfo DInfo(!D->isFirstDeclaration(), /*isDefinition=*/true, + DeclInfo DInfo(!D->isFirstDecl(), /*isDefinition=*/true, /*isContainer=*/false); return handleDecl(D, D->getLocation(), getCursor(D), DInfo); } diff --git a/tools/libclang/IndexingContext.h b/tools/libclang/IndexingContext.h index 62873be..3437d55 100644 --- a/tools/libclang/IndexingContext.h +++ b/tools/libclang/IndexingContext.h @@ -270,14 +270,6 @@ public: } }; -struct RefFileOccurence { - const FileEntry *File; - const Decl *Dcl; - - RefFileOccurence(const FileEntry *File, const Decl *Dcl) - : File(File), Dcl(Dcl) { } -}; - class IndexingContext { ASTContext *Ctx; CXClientData ClientData; @@ -294,6 +286,7 @@ class IndexingContext { ContainerMapTy ContainerMap; EntityMapTy EntityMap; + typedef std::pair<const FileEntry *, const Decl *> RefFileOccurence; llvm::DenseSet<RefFileOccurence> RefFileOccurences; std::deque<DeclGroupRef> TUDeclsInObjCContainer; @@ -524,29 +517,3 @@ inline T *ScratchAlloc::allocate() { } }} // end clang::cxindex - -namespace llvm { - /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and - /// DenseSets. - template <> - struct DenseMapInfo<clang::cxindex::RefFileOccurence> { - static inline clang::cxindex::RefFileOccurence getEmptyKey() { - return clang::cxindex::RefFileOccurence(0, 0); - } - - static inline clang::cxindex::RefFileOccurence getTombstoneKey() { - return clang::cxindex::RefFileOccurence((const clang::FileEntry *)~0, - (const clang::Decl *)~0); - } - - static unsigned getHashValue(clang::cxindex::RefFileOccurence S) { - typedef std::pair<const clang::FileEntry *, const clang::Decl *> PairTy; - return DenseMapInfo<PairTy>::getHashValue(PairTy(S.File, S.Dcl)); - } - - static bool isEqual(clang::cxindex::RefFileOccurence LHS, - clang::cxindex::RefFileOccurence RHS) { - return LHS.File == RHS.File && LHS.Dcl == RHS.Dcl; - } - }; -} diff --git a/tools/libclang/Makefile b/tools/libclang/Makefile index f33f345..43ecbd1 100644 --- a/tools/libclang/Makefile +++ b/tools/libclang/Makefile @@ -16,21 +16,21 @@ LINK_LIBS_IN_SHARED = 1 SHARED_LIBRARY = 1 include $(CLANG_LEVEL)/../../Makefile.config -LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc -USEDLIBS = clangFrontend.a clangDriver.a \ +LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser bitreader support mc option +USEDLIBS = clangIndex.a clangFrontend.a clangDriver.a \ clangTooling.a \ clangSerialization.a \ clangParse.a clangSema.a \ clangARCMigrate.a clangRewriteFrontend.a clangRewriteCore.a \ clangAnalysis.a clangEdit.a \ clangAST.a clangLex.a clangBasic.a \ - clangFormat.a + clangFormat.a include $(CLANG_LEVEL)/Makefile # Add soname to the library. -ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux FreeBSD GNU)) - LDFLAGS += -Wl,-soname,lib$(LIBRARYNAME)$(SHLIBEXT) +ifeq ($(HOST_OS), $(filter $(HOST_OS), Linux FreeBSD GNU GNU/kFreeBSD)) + LLVMLibsOptions += -Wl,-soname,lib$(LIBRARYNAME)$(SHLIBEXT) endif ##===----------------------------------------------------------------------===## diff --git a/tools/libclang/RecursiveASTVisitor.h b/tools/libclang/RecursiveASTVisitor.h index e45545e..3ad5acb 100644 --- a/tools/libclang/RecursiveASTVisitor.h +++ b/tools/libclang/RecursiveASTVisitor.h @@ -27,6 +27,7 @@ #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenMP.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" @@ -394,6 +395,7 @@ private: // These are helper methods used by more than one Traverse* method. bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); bool TraverseClassInstantiations(ClassTemplateDecl *D); + bool TraverseVariableInstantiations(VarTemplateDecl *D); bool TraverseFunctionInstantiations(FunctionTemplateDecl *D) ; bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, unsigned Count); @@ -404,6 +406,13 @@ private: bool TraverseDeclContextHelper(DeclContext *DC); bool TraverseFunctionHelper(FunctionDecl *D); bool TraverseVarHelper(VarDecl *D); + bool TraverseOMPClause(OMPClause *C); +#define OPENMP_CLAUSE(Name, Class) \ + bool Visit##Class(Class *C); +#include "clang/Basic/OpenMPKinds.def" + /// \brief Process clauses with list of variables. + template <typename T> + void VisitOMPClauseList(T *Node); typedef SmallVector<Stmt *, 16> StmtsTy; typedef SmallVector<StmtsTy *, 4> QueuesTy; @@ -502,7 +511,7 @@ bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) { } } - for (SmallVector<Stmt *, 8>::reverse_iterator + for (SmallVectorImpl<Stmt *>::reverse_iterator RI = StmtsToEnqueu.rbegin(), RE = StmtsToEnqueu.rend(); RI != RE; ++RI) Queue.push_back(*RI); @@ -786,6 +795,10 @@ DEF_TRAVERSE_TYPE(MemberPointerType, { TRY_TO(TraverseType(T->getPointeeType())); }) +DEF_TRAVERSE_TYPE(DecayedType, { + TRY_TO(TraverseType(T->getOriginalType())); + }) + DEF_TRAVERSE_TYPE(ConstantArrayType, { TRY_TO(TraverseType(T->getElementType())); }) @@ -992,6 +1005,10 @@ DEF_TRAVERSE_TYPELOC(MemberPointerType, { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) +DEF_TRAVERSE_TYPELOC(DecayedType, { + TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); + }) + template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) { // This isn't available for ArrayType, but is for the ArrayTypeLoc. @@ -1405,6 +1422,57 @@ DEF_TRAVERSE_DECL(ClassTemplateDecl, { // it was instantiated, and thus should not be traversed. }) +// A helper method for traversing the implicit instantiations of a +// class template. +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseVariableInstantiations( + VarTemplateDecl *D) { + VarTemplateDecl::spec_iterator end = D->spec_end(); + for (VarTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) { + VarTemplateSpecializationDecl *SD = *it; + + switch (SD->getSpecializationKind()) { + // Visit the implicit instantiations with the requested pattern. + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + TRY_TO(TraverseDecl(SD)); + break; + + // We don't need to do anything on an explicit instantiation + // or explicit specialization because there will be an explicit + // node for it elsewhere. + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + case TSK_ExplicitSpecialization: + break; + } + } + + return true; +} + +DEF_TRAVERSE_DECL( + VarTemplateDecl, + { + VarDecl *TempDecl = D->getTemplatedDecl(); + TRY_TO(TraverseDecl(TempDecl)); + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); + + // By default, we do not traverse the instantiations of + // variable templates since they do not appear in the user code. The + // following code optionally traverses them. + // + // We only traverse the variable instantiations when we see the canonical + // declaration of the template, to ensure we only visit them once. + if (getDerived().shouldVisitTemplateInstantiations() && + D == D->getCanonicalDecl()) + TRY_TO(TraverseVariableInstantiations(D)); + + // Note that getInstantiatedFromMemberTemplate() is just a link + // from a template instantiation back to the template from which + // it was instantiated, and thus should not be traversed. +}) + // A helper method for traversing the instantiations of a // function while skipping its specializations. template<typename Derived> @@ -1582,7 +1650,8 @@ DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, { } // The args that remains unspecialized. TRY_TO(TraverseTemplateArgumentLocsHelper( - D->getTemplateArgsAsWritten(), D->getNumTemplateArgsAsWritten())); + D->getTemplateArgsAsWritten()->getTemplateArgs(), + D->getTemplateArgsAsWritten()->NumTemplateArgs)); // Don't need the ClassTemplatePartialSpecializationHelper, even // though that's our parent class -- we already visit all the @@ -1731,6 +1800,44 @@ DEF_TRAVERSE_DECL(VarDecl, { TRY_TO(TraverseVarHelper(D)); }) +DEF_TRAVERSE_DECL(VarTemplateSpecializationDecl, { + // For implicit instantiations, we don't want to + // recurse at all, since the instatiated class isn't written in + // the source code anywhere. + if (TypeSourceInfo *TSI = D->getTypeAsWritten()) + TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); + + if (!getDerived().shouldVisitTemplateInstantiations() && + D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) + // Returning from here skips traversing the + // declaration context of the VarTemplateSpecializationDecl + // (embedded in the DEF_TRAVERSE_DECL() macro). + return true; +}) + +DEF_TRAVERSE_DECL(VarTemplatePartialSpecializationDecl, + { + // The partial specialization. + if (TemplateParameterList *TPL = D->getTemplateParameters()) { + for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); + I != E; ++I) { + TRY_TO(TraverseDecl(*I)); + } + } + // The args that remains unspecialized. + TRY_TO(TraverseTemplateArgumentLocsHelper( + D->getTemplateArgsAsWritten()->getTemplateArgs(), + D->getTemplateArgsAsWritten()->NumTemplateArgs)); + + // Don't need the VarTemplatePartialSpecializationHelper, even + // though that's our parent class -- we already visit all the + // template args here. + TRY_TO(TraverseVarHelper(D)); + + // Instantiations will have been visited with the primary + // template. +}) + DEF_TRAVERSE_DECL(ImplicitParamDecl, { TRY_TO(TraverseVarHelper(D)); }) @@ -2039,6 +2146,8 @@ DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { // Walk only the visible parts of lambda expressions. template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { + TRY_TO(WalkUpFromLambdaExpr(S)); + for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(), CEnd = S->explicit_capture_end(); C != CEnd; ++C) { @@ -2095,6 +2204,7 @@ DEF_TRAVERSE_STMT(CXXDefaultInitExpr, { }) DEF_TRAVERSE_STMT(CXXDeleteExpr, { }) DEF_TRAVERSE_STMT(ExprWithCleanups, { }) DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { }) +DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, { }) DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo()) @@ -2132,6 +2242,7 @@ DEF_TRAVERSE_STMT(ParenExpr, { }) DEF_TRAVERSE_STMT(ParenListExpr, { }) DEF_TRAVERSE_STMT(PredefinedExpr, { }) DEF_TRAVERSE_STMT(ShuffleVectorExpr, { }) +DEF_TRAVERSE_STMT(ConvertVectorExpr, { }) DEF_TRAVERSE_STMT(StmtExpr, { }) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); @@ -2191,6 +2302,61 @@ DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, { }) // Traverse OpenCL: AsType, Convert. DEF_TRAVERSE_STMT(AsTypeExpr, { }) +// OpenMP directives. +DEF_TRAVERSE_STMT(OMPParallelDirective, { + ArrayRef<OMPClause *> Clauses = S->clauses(); + for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end(); + I != E; ++I) + if (!TraverseOMPClause(*I)) return false; +}) + +// OpenMP clauses. +template<typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { + if (!C) return true; + switch (C->getClauseKind()) { +#define OPENMP_CLAUSE(Name, Class) \ + case OMPC_##Name: \ + return getDerived().Visit##Class(static_cast<Class*>(C)); +#include "clang/Basic/OpenMPKinds.def" + default: break; + } + return true; +} + +template<typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPDefaultClause(OMPDefaultClause *C) { + return true; +} + +template<typename Derived> +template<typename T> +void RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { + for (typename T::varlist_iterator I = Node->varlist_begin(), + E = Node->varlist_end(); + I != E; ++I) + TraverseStmt(*I); +} + +template<typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) { + VisitOMPClauseList(C); + return true; +} + +template<typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause( + OMPFirstprivateClause *C) { + VisitOMPClauseList(C); + return true; +} + +template<typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPSharedClause(OMPSharedClause *C) { + VisitOMPClauseList(C); + return true; +} + // FIXME: look at the following tricky-seeming exprs to see if we // need to recurse on anything. These are ones that have methods // returning decls or qualtypes or nestednamespecifier -- though I'm diff --git a/tools/libclang/SimpleFormatContext.h b/tools/libclang/SimpleFormatContext.h deleted file mode 100644 index 016d0b6..0000000 --- a/tools/libclang/SimpleFormatContext.h +++ /dev/null @@ -1,75 +0,0 @@ -//===--- SimpleFormatContext.h ----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -/// \file -/// -/// \brief Defines a utility class for use of clang-format in libclang -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_SIMPLE_FORM_CONTEXT_H -#define LLVM_CLANG_SIMPLE_FORM_CONTEXT_H - -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/DiagnosticOptions.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/LangOptions.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Rewrite/Core/Rewriter.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" - -namespace clang { - -/// \brief A small class to be used by libclang clients to format -/// a declaration string in memory. This object is instantiated once -/// and used each time a formatting is needed. -class SimpleFormatContext { -public: - SimpleFormatContext(LangOptions Options) - : DiagOpts(new DiagnosticOptions()), - Diagnostics(new DiagnosticsEngine(new DiagnosticIDs, - DiagOpts.getPtr())), - Files((FileSystemOptions())), - Sources(*Diagnostics, Files), - Rewrite(Sources, Options) { - Diagnostics->setClient(new IgnoringDiagConsumer, true); - } - - ~SimpleFormatContext() { } - - FileID createInMemoryFile(StringRef Name, StringRef Content) { - const llvm::MemoryBuffer *Source = - llvm::MemoryBuffer::getMemBuffer(Content); - const FileEntry *Entry = - Files.getVirtualFile(Name, Source->getBufferSize(), 0); - Sources.overrideFileContents(Entry, Source, true); - assert(Entry != NULL); - return Sources.createFileID(Entry, SourceLocation(), SrcMgr::C_User); - } - - std::string getRewrittenText(FileID ID) { - std::string Result; - llvm::raw_string_ostream OS(Result); - Rewrite.getEditBuffer(ID).write(OS); - OS.flush(); - return Result; - } - - IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; - IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics; - FileManager Files; - SourceManager Sources; - Rewriter Rewrite; -}; - -} // end namespace clang - -#endif diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index 0c9912e..9bf26c9 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -2,6 +2,7 @@ clang_CXCursorSet_contains clang_CXCursorSet_insert clang_CXIndex_getGlobalOptions clang_CXIndex_setGlobalOptions +clang_CXXMethod_isPureVirtual clang_CXXMethod_isStatic clang_CXXMethod_isVirtual clang_Cursor_getArgument @@ -19,6 +20,7 @@ clang_Cursor_getReceiverType clang_Cursor_isBitField clang_Cursor_isDynamicCall clang_Cursor_isNull +clang_Cursor_isObjCOptional clang_Cursor_isVariadic clang_Cursor_getModule clang_Module_getASTFile @@ -59,8 +61,10 @@ clang_TParamCommandComment_isParamPositionValid clang_TParamCommandComment_getDepth clang_TParamCommandComment_getIndex clang_Type_getAlignOf +clang_Type_getClassType clang_Type_getSizeOf clang_Type_getOffsetOf +clang_Type_getCXXRefQualifier clang_VerbatimBlockLineComment_getText clang_VerbatimLineComment_getText clang_HTMLTagComment_getAsString @@ -253,6 +257,7 @@ clang_isVirtualBase clang_isVolatileQualifiedType clang_loadDiagnostics clang_Location_isInSystemHeader +clang_Location_isFromMainFile clang_parseTranslationUnit clang_remap_dispose clang_remap_getFilenames |