diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Index')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp | 6 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/IndexBody.cpp | 102 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp | 390 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp | 86 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp | 69 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp | 29 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp | 171 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/IndexingContext.h | 10 | ||||
-rw-r--r-- | contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp | 143 |
9 files changed, 841 insertions, 165 deletions
diff --git a/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp b/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp index ee066cc..e568c83 100644 --- a/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp +++ b/contrib/llvm/tools/clang/lib/Index/CommentToXML.cpp @@ -592,10 +592,10 @@ void CommentASTToXMLConverter::formatTextOfDeclaration( unsigned Offset = 0; unsigned Length = Declaration.size(); - bool IncompleteFormat = false; + format::FormatStyle Style = format::getLLVMStyle(); + Style.FixNamespaceComments = false; tooling::Replacements Replaces = - reformat(format::getLLVMStyle(), StringDecl, - tooling::Range(Offset, Length), "xmldecl.xd", &IncompleteFormat); + reformat(Style, StringDecl, tooling::Range(Offset, Length), "xmldecl.xd"); auto FormattedStringDecl = applyAllReplacements(StringDecl, Replaces); if (static_cast<bool>(FormattedStringDecl)) { Declaration = *FormattedStringDecl; diff --git a/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp b/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp index 3aa0152..6bbd381 100644 --- a/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp +++ b/contrib/llvm/tools/clang/lib/Index/IndexBody.cpp @@ -22,6 +22,10 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> { SmallVector<Stmt*, 16> StmtStack; typedef RecursiveASTVisitor<BodyIndexer> base; + + Stmt *getParentStmt() const { + return StmtStack.size() < 2 ? nullptr : StmtStack.end()[-2]; + } public: BodyIndexer(IndexingContext &indexCtx, const NamedDecl *Parent, const DeclContext *DC) @@ -146,6 +150,53 @@ public: Parent, ParentDC, Roles, Relations, E); } + bool indexDependentReference( + const Expr *E, const Type *T, const DeclarationNameInfo &NameInfo, + llvm::function_ref<bool(const NamedDecl *ND)> Filter) { + if (!T) + return true; + const TemplateSpecializationType *TST = + T->getAs<TemplateSpecializationType>(); + if (!TST) + return true; + TemplateName TN = TST->getTemplateName(); + const ClassTemplateDecl *TD = + dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()); + if (!TD) + return true; + CXXRecordDecl *RD = TD->getTemplatedDecl(); + if (!RD->hasDefinition()) + return true; + RD = RD->getDefinition(); + std::vector<const NamedDecl *> Symbols = + RD->lookupDependentName(NameInfo.getName(), Filter); + // FIXME: Improve overload handling. + if (Symbols.size() != 1) + return true; + SourceLocation Loc = NameInfo.getLoc(); + if (Loc.isInvalid()) + Loc = E->getLocStart(); + SmallVector<SymbolRelation, 4> Relations; + SymbolRoleSet Roles = getRolesForRef(E, Relations); + return IndexCtx.handleReference(Symbols[0], Loc, Parent, ParentDC, Roles, + Relations, E); + } + + bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { + const DeclarationNameInfo &Info = E->getMemberNameInfo(); + return indexDependentReference( + E, E->getBaseType().getTypePtrOrNull(), Info, + [](const NamedDecl *D) { return D->isCXXInstanceMember(); }); + } + + bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { + const DeclarationNameInfo &Info = E->getNameInfo(); + const NestedNameSpecifier *NNS = E->getQualifier(); + return indexDependentReference( + E, NNS->getAsType(), Info, + [](const NamedDecl *D) { return !D->isCXXInstanceMember(); }); + } + bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) { if (D.isFieldDesignator() && D.getField()) @@ -178,7 +229,32 @@ public: SymbolRoleSet Roles{}; SmallVector<SymbolRelation, 2> Relations; addCallRole(Roles, Relations); - if (E->isImplicit()) + Stmt *Containing = getParentStmt(); + + auto IsImplicitProperty = [](const PseudoObjectExpr *POE) -> bool { + const auto *E = POE->getSyntacticForm(); + if (const auto *BinOp = dyn_cast<BinaryOperator>(E)) + E = BinOp->getLHS(); + const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(E); + if (!PRE) + return false; + if (PRE->isExplicitProperty()) + return false; + if (const ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter()) { + // Class properties that are explicitly defined using @property + // declarations are represented implicitly as there is no ivar for + // class properties. + if (Getter->isClassMethod() && + Getter->getCanonicalDecl()->findPropertyDecl()) + return false; + } + return true; + }; + bool IsPropCall = Containing && isa<PseudoObjectExpr>(Containing); + // Implicit property message sends are not 'implicit'. + if ((E->isImplicit() || IsPropCall) && + !(IsPropCall && + IsImplicitProperty(cast<PseudoObjectExpr>(Containing)))) Roles |= (unsigned)SymbolRole::Implicit; if (isDynamic(E)) { @@ -194,9 +270,27 @@ public: } bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { - if (E->isExplicitProperty()) + if (E->isClassReceiver()) + IndexCtx.handleReference(E->getClassReceiver(), E->getReceiverLocation(), + Parent, ParentDC); + if (E->isExplicitProperty()) { + SmallVector<SymbolRelation, 2> Relations; + SymbolRoleSet Roles = getRolesForRef(E, Relations); return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(), - Parent, ParentDC, SymbolRoleSet(), {}, E); + Parent, ParentDC, Roles, Relations, E); + } else if (const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter()) { + // Class properties that are explicitly defined using @property + // declarations are represented implicitly as there is no ivar for class + // properties. + if (Getter->isClassMethod()) { + if (const auto *PD = Getter->getCanonicalDecl()->findPropertyDecl()) { + SmallVector<SymbolRelation, 2> Relations; + SymbolRoleSet Roles = getRolesForRef(E, Relations); + return IndexCtx.handleReference(PD, E->getLocation(), Parent, + ParentDC, Roles, Relations, E); + } + } + } // No need to do a handleReference for the objc method, because there will // be a message expr as part of PseudoObjectExpr. @@ -269,7 +363,7 @@ public: const Decl *D = *I; if (!D) continue; - if (!IndexCtx.isFunctionLocalDecl(D)) + if (!isFunctionLocalSymbol(D)) IndexCtx.indexTopLevelDecl(D); } diff --git a/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp b/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp index 3b4f3f8..c5230c0 100644 --- a/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Index/IndexDecl.cpp @@ -14,6 +14,13 @@ using namespace clang; using namespace index; +#define TRY_DECL(D,CALL_EXPR) \ + do { \ + if (!IndexCtx.shouldIndex(D)) return true; \ + if (!CALL_EXPR) \ + return false; \ + } while (0) + #define TRY_TO(CALL_EXPR) \ do { \ if (!CALL_EXPR) \ @@ -45,6 +52,33 @@ public: return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition(); } + void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc, + const NamedDecl *Parent, + const DeclContext *DC) { + const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo(); + switch (TALoc.getArgument().getKind()) { + case TemplateArgument::Expression: + IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC); + break; + case TemplateArgument::Type: + IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC); + break; + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(), + Parent, DC); + if (const TemplateDecl *TD = TALoc.getArgument() + .getAsTemplateOrTemplatePattern() + .getAsTemplateDecl()) { + if (const NamedDecl *TTD = TD->getTemplatedDecl()) + IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC); + } + break; + default: + break; + } + } + void handleDeclarator(const DeclaratorDecl *D, const NamedDecl *Parent = nullptr, bool isIBType = false) { @@ -75,6 +109,17 @@ public: } } } + } else { + // Index the default parameter value for function definitions. + if (const auto *FD = dyn_cast<FunctionDecl>(D)) { + if (FD->isThisDeclarationADefinition()) { + for (const auto *PV : FD->parameters()) { + if (PV->hasDefaultArg() && !PV->hasUninstantiatedDefaultArg() && + !PV->hasUnparsedDefaultArg()) + IndexCtx.indexBody(PV->getDefaultArg(), D); + } + } + } } } @@ -98,8 +143,29 @@ public: if (MethodLoc.isInvalid()) MethodLoc = D->getLocation(); - if (!IndexCtx.handleDecl(D, MethodLoc, (unsigned)SymbolRole::Dynamic, Relations)) - return false; + SourceLocation AttrLoc; + + // check for (getter=/setter=) + if (AssociatedProp) { + bool isGetter = !D->param_size(); + AttrLoc = isGetter ? + AssociatedProp->getGetterNameLoc(): + AssociatedProp->getSetterNameLoc(); + } + + SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic; + if (D->isImplicit()) { + if (AttrLoc.isValid()) { + MethodLoc = AttrLoc; + } else { + Roles |= (SymbolRoleSet)SymbolRole::Implicit; + } + } else if (AttrLoc.isValid()) { + IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()), + D->getDeclContext(), 0); + } + + TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations)); IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D); bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>(); for (const auto *I : D->parameters()) { @@ -116,10 +182,52 @@ public: return true; } - bool VisitFunctionDecl(const FunctionDecl *D) { - if (D->isDeleted()) - return true; + /// Gather the declarations which the given declaration \D overrides in a + /// pseudo-override manner. + /// + /// Pseudo-overrides occur when a class template specialization declares + /// a declaration that has the same name as a similar declaration in the + /// non-specialized template. + void + gatherTemplatePseudoOverrides(const NamedDecl *D, + SmallVectorImpl<SymbolRelation> &Relations) { + if (!IndexCtx.getLangOpts().CPlusPlus) + return; + const auto *CTSD = + dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext()); + if (!CTSD) + return; + llvm::PointerUnion<ClassTemplateDecl *, + ClassTemplatePartialSpecializationDecl *> + Template = CTSD->getSpecializedTemplateOrPartial(); + if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) { + const CXXRecordDecl *Pattern = CTD->getTemplatedDecl(); + bool TypeOverride = isa<TypeDecl>(D); + for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) { + if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND)) + ND = CTD->getTemplatedDecl(); + if (ND->isImplicit()) + continue; + // Types can override other types. + if (!TypeOverride) { + if (ND->getKind() != D->getKind()) + continue; + } else if (!isa<TypeDecl>(ND)) + continue; + if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { + const auto *DFD = cast<FunctionDecl>(D); + // Function overrides are approximated using the number of parameters. + if (FD->getStorageClass() != DFD->getStorageClass() || + FD->getNumParams() != DFD->getNumParams()) + continue; + } + Relations.emplace_back( + SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND); + } + } + } + bool VisitFunctionDecl(const FunctionDecl *D) { SymbolRoleSet Roles{}; SmallVector<SymbolRelation, 4> Relations; if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) { @@ -130,12 +238,19 @@ public: Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I); } } + gatherTemplatePseudoOverrides(D, Relations); + if (const auto *Base = D->getPrimaryTemplate()) + Relations.push_back( + SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), + Base->getTemplatedDecl())); - if (!IndexCtx.handleDecl(D, Roles, Relations)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations)); handleDeclarator(D); if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { + IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(), + Ctor->getParent(), Ctor->getDeclContext()); + // Constructor initializers. for (const auto *Init : Ctor->inits()) { if (Init->isWritten()) { @@ -146,6 +261,18 @@ public: IndexCtx.indexBody(Init->getInit(), D, D); } } + } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) { + if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) { + IndexCtx.handleReference(Dtor->getParent(), + TypeNameInfo->getTypeLoc().getLocStart(), + Dtor->getParent(), Dtor->getDeclContext()); + } + } + // Template specialization arguments. + if (const ASTTemplateArgumentListInfo *TemplateArgInfo = + D->getTemplateSpecializationArgsAsWritten()) { + for (const auto &Arg : TemplateArgInfo->arguments()) + handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext()); } if (D->isThisDeclarationADefinition()) { @@ -158,16 +285,24 @@ public: } bool VisitVarDecl(const VarDecl *D) { - if (!IndexCtx.handleDecl(D)) - return false; + SmallVector<SymbolRelation, 4> Relations; + gatherTemplatePseudoOverrides(D, Relations); + TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); handleDeclarator(D); IndexCtx.indexBody(D->getInit(), D); return true; } + bool VisitDecompositionDecl(const DecompositionDecl *D) { + for (const auto *Binding : D->bindings()) + TRY_DECL(Binding, IndexCtx.handleDecl(Binding)); + return Base::VisitDecompositionDecl(D); + } + bool VisitFieldDecl(const FieldDecl *D) { - if (!IndexCtx.handleDecl(D)) - return false; + SmallVector<SymbolRelation, 4> Relations; + gatherTemplatePseudoOverrides(D, Relations); + TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); handleDeclarator(D); if (D->isBitField()) IndexCtx.indexBody(D->getBitWidth(), D); @@ -178,17 +313,10 @@ public: bool VisitObjCIvarDecl(const ObjCIvarDecl *D) { if (D->getSynthesize()) { - // For synthesized ivars, use the location of the ObjC implementation, - // not the location of the property. - // Otherwise the header file containing the @interface will have different - // indexing contents based on whether the @implementation was present or - // not in the translation unit. - return IndexCtx.handleDecl(D, - cast<Decl>(D->getDeclContext())->getLocation(), - (unsigned)SymbolRole::Implicit); + // handled in VisitObjCPropertyImplDecl + return true; } - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D)); handleDeclarator(D); return true; } @@ -199,16 +327,18 @@ public: } bool VisitEnumConstantDecl(const EnumConstantDecl *D) { - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D)); IndexCtx.indexBody(D->getInitExpr(), D); return true; } bool VisitTypedefNameDecl(const TypedefNameDecl *D) { - if (!IndexCtx.handleDecl(D)) - return false; - IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); + if (!D->isTransparentTag()) { + SmallVector<SymbolRelation, 4> Relations; + gatherTemplatePseudoOverrides(D, Relations); + TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); + IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); + } return true; } @@ -216,26 +346,33 @@ public: // Non-free standing tags are handled in indexTypeSourceInfo. if (D->isFreeStanding()) { if (D->isThisDeclarationADefinition()) { - IndexCtx.indexTagDecl(D); + SmallVector<SymbolRelation, 4> Relations; + gatherTemplatePseudoOverrides(D, Relations); + IndexCtx.indexTagDecl(D, Relations); } else { auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext()); + SmallVector<SymbolRelation, 1> Relations; + gatherTemplatePseudoOverrides(D, Relations); return IndexCtx.handleReference(D, D->getLocation(), Parent, D->getLexicalDeclContext(), - SymbolRoleSet()); + SymbolRoleSet(), Relations); } } return true; } bool handleReferencedProtocols(const ObjCProtocolList &ProtList, - const ObjCContainerDecl *ContD) { + const ObjCContainerDecl *ContD, + SourceLocation SuperLoc) { ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); for (ObjCInterfaceDecl::protocol_iterator I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { SourceLocation Loc = *LI; ObjCProtocolDecl *PD = *I; - TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, - SymbolRoleSet(), + SymbolRoleSet roles{}; + if (Loc == SuperLoc) + roles |= (SymbolRoleSet)SymbolRole::Implicit; + TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles, SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD})); } return true; @@ -243,13 +380,27 @@ public: bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { if (D->isThisDeclarationADefinition()) { - TRY_TO(IndexCtx.handleDecl(D)); + TRY_DECL(D, IndexCtx.handleDecl(D)); + SourceLocation SuperLoc = D->getSuperClassLoc(); if (auto *SuperD = D->getSuperClass()) { - TRY_TO(IndexCtx.handleReference(SuperD, D->getSuperClassLoc(), D, D, - SymbolRoleSet(), + bool hasSuperTypedef = false; + if (auto *TInfo = D->getSuperClassTInfo()) { + if (auto *TT = TInfo->getType()->getAs<TypedefType>()) { + if (auto *TD = TT->getDecl()) { + hasSuperTypedef = true; + TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D, + SymbolRoleSet())); + } + } + } + SymbolRoleSet superRoles{}; + if (hasSuperTypedef) + superRoles |= (SymbolRoleSet)SymbolRole::Implicit; + TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles, SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D})); } - TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D)); + TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, + SuperLoc)); TRY_TO(IndexCtx.indexDeclContext(D)); } else { return IndexCtx.handleReference(D, D->getLocation(), nullptr, @@ -260,8 +411,9 @@ public: bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { if (D->isThisDeclarationADefinition()) { - TRY_TO(IndexCtx.handleDecl(D)); - TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D)); + TRY_DECL(D, IndexCtx.handleDecl(D)); + TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, + /*superLoc=*/SourceLocation())); TRY_TO(IndexCtx.indexDeclContext(D)); } else { return IndexCtx.handleReference(D, D->getLocation(), nullptr, @@ -278,15 +430,18 @@ public: if (Class->isImplicitInterfaceDecl()) IndexCtx.handleDecl(Class); - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D)); - // Index the ivars first to make sure the synthesized ivars are indexed - // before indexing the methods that can reference them. - for (const auto *IvarI : D->ivars()) - IndexCtx.indexDecl(IvarI); + // Visit implicit @synthesize property implementations first as their + // location is reported at the name of the @implementation block. This + // serves no purpose other than to simplify the FileCheck-based tests. + for (const auto *I : D->property_impls()) { + if (I->getLocation().isInvalid()) + IndexCtx.indexDecl(I); + } for (const auto *I : D->decls()) { - if (!isa<ObjCIvarDecl>(I)) + if (!isa<ObjCPropertyImplDecl>(I) || + cast<ObjCPropertyImplDecl>(I)->getLocation().isValid()) IndexCtx.indexDecl(I); } @@ -294,6 +449,8 @@ public: } bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { + if (!IndexCtx.shouldIndex(D)) + return true; const ObjCInterfaceDecl *C = D->getClassInterface(); if (!C) return true; @@ -305,7 +462,8 @@ public: if (!CategoryLoc.isValid()) CategoryLoc = D->getLocation(); TRY_TO(IndexCtx.handleDecl(D, CategoryLoc)); - TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D)); + TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, + /*superLoc=*/SourceLocation())); TRY_TO(IndexCtx.indexDeclContext(D)); return true; } @@ -321,8 +479,7 @@ public: SourceLocation CategoryLoc = D->getCategoryNameLoc(); if (!CategoryLoc.isValid()) CategoryLoc = D->getLocation(); - if (!IndexCtx.handleDecl(D, CategoryLoc)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc)); IndexCtx.indexDeclContext(D); return true; } @@ -344,8 +501,7 @@ public: if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) handleObjCMethod(MD, D); - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D)); if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>()) IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D, D->getLexicalDeclContext(), false, true); @@ -355,43 +511,74 @@ public: bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { ObjCPropertyDecl *PD = D->getPropertyDecl(); - if (!IndexCtx.handleReference(PD, D->getLocation(), - /*Parent=*/cast<NamedDecl>(D->getDeclContext()), - D->getDeclContext(), SymbolRoleSet(), {}, - /*RefE=*/nullptr, D)) - return false; + auto *Container = cast<ObjCImplDecl>(D->getDeclContext()); + SourceLocation Loc = D->getLocation(); + SymbolRoleSet Roles = 0; + SmallVector<SymbolRelation, 1> Relations; + + if (ObjCIvarDecl *ID = D->getPropertyIvarDecl()) + Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID}); + if (Loc.isInvalid()) { + Loc = Container->getLocation(); + Roles |= (SymbolRoleSet)SymbolRole::Implicit; + } + TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations)); if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) return true; - assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); - - if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { - if (!IvarD->getSynthesize()) - IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr, - D->getDeclContext(), SymbolRoleSet()); - } - auto *ImplD = cast<ObjCImplDecl>(D->getDeclContext()); + assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); + SymbolRoleSet AccessorMethodRoles = + SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit); if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { if (MD->isPropertyAccessor() && - !hasUserDefined(MD, ImplD)) - IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD); + !hasUserDefined(MD, Container)) + IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container); } if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { if (MD->isPropertyAccessor() && - !hasUserDefined(MD, ImplD)) - IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD); + !hasUserDefined(MD, Container)) + IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container); + } + if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { + if (IvarD->getSynthesize()) { + // For synthesized ivars, use the location of its name in the + // corresponding @synthesize. If there isn't one, use the containing + // @implementation's location, rather than the property's location, + // otherwise the header file containing the @interface will have different + // indexing contents based on whether the @implementation was present or + // not in the translation unit. + SymbolRoleSet IvarRoles = 0; + SourceLocation IvarLoc = D->getPropertyIvarDeclLoc(); + if (D->getLocation().isInvalid()) { + IvarLoc = Container->getLocation(); + IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; + } else if (D->getLocation() == IvarLoc) { + IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; + } + TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles)); + } else { + IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr, + D->getDeclContext(), SymbolRoleSet()); + } } return true; } bool VisitNamespaceDecl(const NamespaceDecl *D) { - if (!IndexCtx.handleDecl(D)) - return false; + TRY_DECL(D, IndexCtx.handleDecl(D)); IndexCtx.indexDeclContext(D); return true; } + bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { + TRY_DECL(D, IndexCtx.handleDecl(D)); + IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); + IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D, + D->getLexicalDeclContext()); + return true; + } + bool VisitUsingDecl(const UsingDecl *D) { const DeclContext *DC = D->getDeclContext()->getRedeclContext(); const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); @@ -408,8 +595,12 @@ public: const DeclContext *DC = D->getDeclContext()->getRedeclContext(); const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); - IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, - D->getLexicalDeclContext()); + // NNS for the local 'using namespace' directives is visited by the body + // visitor. + if (!D->getParentFunctionOrMethod()) + IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, + D->getLexicalDeclContext()); + return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(), D->getLocation(), Parent, D->getLexicalDeclContext(), @@ -420,13 +611,61 @@ public: ClassTemplateSpecializationDecl *D) { // FIXME: Notify subsequent callbacks if info comes from implicit // instantiation. - if (D->isThisDeclarationADefinition()) - IndexCtx.indexTagDecl(D); + llvm::PointerUnion<ClassTemplateDecl *, + ClassTemplatePartialSpecializationDecl *> + Template = D->getSpecializedTemplateOrPartial(); + const Decl *SpecializationOf = + Template.is<ClassTemplateDecl *>() + ? (Decl *)Template.get<ClassTemplateDecl *>() + : Template.get<ClassTemplatePartialSpecializationDecl *>(); + if (!D->isThisDeclarationADefinition()) + IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); + IndexCtx.indexTagDecl( + D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), + SpecializationOf)); + if (TypeSourceInfo *TSI = D->getTypeAsWritten()) + IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr, + D->getLexicalDeclContext()); + return true; + } + + static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) { + if (!D) + return false; + // We want to index the template parameters only once when indexing the + // canonical declaration. + if (const auto *FD = dyn_cast<FunctionDecl>(D)) + return FD->getCanonicalDecl() == FD; + else if (const auto *TD = dyn_cast<TagDecl>(D)) + return TD->getCanonicalDecl() == TD; + else if (const auto *VD = dyn_cast<VarDecl>(D)) + return VD->getCanonicalDecl() == VD; return true; } bool VisitTemplateDecl(const TemplateDecl *D) { // FIXME: Template parameters. + + // Index the default values for the template parameters. + const NamedDecl *Parent = D->getTemplatedDecl(); + if (D->getTemplateParameters() && + shouldIndexTemplateParameterDefaultValue(Parent)) { + const TemplateParameterList *Params = D->getTemplateParameters(); + for (const NamedDecl *TP : *Params) { + if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) { + if (TTP->hasDefaultArgument()) + IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent); + } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) { + if (NTTP->hasDefaultArgument()) + IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent); + } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) { + if (TTPD->hasDefaultArgument()) + handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent, + /*DC=*/nullptr); + } + } + } + return Visit(D->getTemplatedDecl()); } @@ -451,6 +690,13 @@ public: bool VisitImportDecl(const ImportDecl *D) { return IndexCtx.importedModule(D); } + + bool VisitStaticAssertDecl(const StaticAssertDecl *D) { + IndexCtx.indexBody(D->getAssertExpr(), + dyn_cast<NamedDecl>(D->getDeclContext()), + D->getLexicalDeclContext()); + return true; + } }; } // anonymous namespace diff --git a/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp b/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp index 84984fc..0dc3720 100644 --- a/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp +++ b/contrib/llvm/tools/clang/lib/Index/IndexSymbol.cpp @@ -49,6 +49,41 @@ static void checkForIBOutlets(const Decl *D, SymbolPropertySet &PropSet) { } } +bool index::isFunctionLocalSymbol(const Decl *D) { + assert(D); + + if (isa<ParmVarDecl>(D)) + return true; + + if (isa<TemplateTemplateParmDecl>(D)) + return true; + + if (isa<ObjCTypeParamDecl>(D)) + return true; + + if (isa<UsingDirectiveDecl>(D)) + return false; + if (!D->getParentFunctionOrMethod()) + return false; + + if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { + switch (ND->getFormalLinkage()) { + case NoLinkage: + case InternalLinkage: + return true; + case VisibleNoLinkage: + case UniqueExternalLinkage: + case ModuleInternalLinkage: + llvm_unreachable("Not a sema linkage"); + case ModuleLinkage: + case ExternalLinkage: + return false; + } + } + + return true; +} + SymbolInfo index::getSymbolInfo(const Decl *D) { assert(D); SymbolInfo Info; @@ -57,6 +92,10 @@ SymbolInfo index::getSymbolInfo(const Decl *D) { Info.Properties = SymbolPropertySet(); Info.Lang = SymbolLanguage::C; + if (isFunctionLocalSymbol(D)) { + Info.Properties |= (unsigned)SymbolProperty::Local; + } + if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { switch (TD->getTagKind()) { case TTK_Struct: @@ -94,10 +133,13 @@ SymbolInfo index::getSymbolInfo(const Decl *D) { } else if (auto *VD = dyn_cast<VarDecl>(D)) { Info.Kind = SymbolKind::Variable; - if (isa<CXXRecordDecl>(D->getDeclContext())) { + if (isa<ParmVarDecl>(D)) { + Info.Kind = SymbolKind::Parameter; + } else if (isa<CXXRecordDecl>(D->getDeclContext())) { Info.Kind = SymbolKind::StaticProperty; Info.Lang = SymbolLanguage::CXX; } + if (isa<VarTemplatePartialSpecializationDecl>(D)) { Info.Lang = SymbolLanguage::CXX; Info.Properties |= (unsigned)SymbolProperty::Generic; @@ -147,10 +189,18 @@ SymbolInfo index::getSymbolInfo(const Decl *D) { Info.Lang = SymbolLanguage::ObjC; break; case Decl::ObjCCategory: - case Decl::ObjCCategoryImpl: + case Decl::ObjCCategoryImpl: { Info.Kind = SymbolKind::Extension; Info.Lang = SymbolLanguage::ObjC; + const ObjCInterfaceDecl *ClsD = nullptr; + if (auto *CatD = dyn_cast<ObjCCategoryDecl>(D)) + ClsD = CatD->getClassInterface(); + else + ClsD = cast<ObjCCategoryImplDecl>(D)->getClassInterface(); + if (isUnitTestCase(ClsD)) + Info.Properties |= (unsigned)SymbolProperty::UnitTest; break; + } case Decl::ObjCMethod: if (cast<ObjCMethodDecl>(D)->isInstanceMethod()) { const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D); @@ -253,6 +303,10 @@ SymbolInfo index::getSymbolInfo(const Decl *D) { Info.Kind = SymbolKind::TypeAlias; Info.Lang = SymbolLanguage::CXX; break; + case Decl::Binding: + Info.Kind = SymbolKind::Variable; + Info.Lang = SymbolLanguage::CXX; + break; default: break; } @@ -272,14 +326,20 @@ SymbolInfo index::getSymbolInfo(const Decl *D) { if (Info.Properties & (unsigned)SymbolProperty::Generic) Info.Lang = SymbolLanguage::CXX; + if (auto *attr = D->getExternalSourceSymbolAttr()) { + if (attr->getLanguage() == "Swift") + Info.Lang = SymbolLanguage::Swift; + } + return Info; } -void index::applyForEachSymbolRole(SymbolRoleSet Roles, - llvm::function_ref<void(SymbolRole)> Fn) { +bool index::applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles, + llvm::function_ref<bool(SymbolRole)> Fn) { #define APPLY_FOR_ROLE(Role) \ if (Roles & (unsigned)SymbolRole::Role) \ - Fn(SymbolRole::Role) + if (!Fn(SymbolRole::Role)) \ + return false; APPLY_FOR_ROLE(Declaration); APPLY_FOR_ROLE(Definition); @@ -299,8 +359,19 @@ void index::applyForEachSymbolRole(SymbolRoleSet Roles, APPLY_FOR_ROLE(RelationAccessorOf); APPLY_FOR_ROLE(RelationContainedBy); APPLY_FOR_ROLE(RelationIBTypeOf); + APPLY_FOR_ROLE(RelationSpecializationOf); #undef APPLY_FOR_ROLE + + return true; +} + +void index::applyForEachSymbolRole(SymbolRoleSet Roles, + llvm::function_ref<void(SymbolRole)> Fn) { + applyForEachSymbolRoleInterruptible(Roles, [&](SymbolRole r) -> bool { + Fn(r); + return true; + }); } void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) { @@ -329,6 +400,7 @@ void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) { case SymbolRole::RelationAccessorOf: OS << "RelAcc"; break; case SymbolRole::RelationContainedBy: OS << "RelCont"; break; case SymbolRole::RelationIBTypeOf: OS << "RelIBType"; break; + case SymbolRole::RelationSpecializationOf: OS << "RelSpecialization"; break; } }); } @@ -378,6 +450,7 @@ StringRef index::getSymbolKindString(SymbolKind K) { case SymbolKind::Constructor: return "constructor"; case SymbolKind::Destructor: return "destructor"; case SymbolKind::ConversionFunction: return "coversion-func"; + case SymbolKind::Parameter: return "param"; } llvm_unreachable("invalid symbol kind"); } @@ -398,6 +471,7 @@ StringRef index::getSymbolLanguageString(SymbolLanguage K) { case SymbolLanguage::C: return "C"; case SymbolLanguage::ObjC: return "ObjC"; case SymbolLanguage::CXX: return "C++"; + case SymbolLanguage::Swift: return "Swift"; } llvm_unreachable("invalid symbol language kind"); } @@ -415,6 +489,7 @@ void index::applyForEachSymbolProperty(SymbolPropertySet Props, APPLY_FOR_PROPERTY(IBAnnotated); APPLY_FOR_PROPERTY(IBOutletCollection); APPLY_FOR_PROPERTY(GKInspectable); + APPLY_FOR_PROPERTY(Local); #undef APPLY_FOR_PROPERTY } @@ -434,6 +509,7 @@ void index::printSymbolProperties(SymbolPropertySet Props, raw_ostream &OS) { case SymbolProperty::IBAnnotated: OS << "IB"; break; case SymbolProperty::IBOutletCollection: OS << "IBColl"; break; case SymbolProperty::GKInspectable: OS << "GKI"; break; + case SymbolProperty::Local: OS << "local"; break; } }); } diff --git a/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp b/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp index 38bbb30..ae27ebe 100644 --- a/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp +++ b/contrib/llvm/tools/clang/lib/Index/IndexTypeSourceInfo.cpp @@ -40,18 +40,36 @@ public: bool shouldWalkTypesOfTypeLocs() const { return false; } - bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { - return IndexCtx.handleReference(TL.getTypedefNameDecl(), TL.getNameLoc(), - Parent, ParentDC, SymbolRoleSet(), - Relations); - } - #define TRY_TO(CALL_EXPR) \ do { \ if (!CALL_EXPR) \ return false; \ } while (0) + bool VisitTypedefTypeLoc(TypedefTypeLoc TL) { + SourceLocation Loc = TL.getNameLoc(); + TypedefNameDecl *ND = TL.getTypedefNameDecl(); + if (ND->isTransparentTag()) { + TagDecl *Underlying = ND->getUnderlyingType()->getAsTagDecl(); + return IndexCtx.handleReference(Underlying, Loc, Parent, + ParentDC, SymbolRoleSet(), Relations); + } + if (IsBase) { + TRY_TO(IndexCtx.handleReference(ND, Loc, + Parent, ParentDC, SymbolRoleSet())); + if (auto *CD = TL.getType()->getAsCXXRecordDecl()) { + TRY_TO(IndexCtx.handleReference(CD, Loc, Parent, ParentDC, + (unsigned)SymbolRole::Implicit, + Relations)); + } + } else { + TRY_TO(IndexCtx.handleReference(ND, Loc, + Parent, ParentDC, SymbolRoleSet(), + Relations)); + } + return true; + } + bool traverseParamVarHelper(ParmVarDecl *D) { TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); if (D->getTypeSourceInfo()) @@ -123,6 +141,34 @@ public: return true; } + bool VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { + const DependentNameType *DNT = TL.getTypePtr(); + const NestedNameSpecifier *NNS = DNT->getQualifier(); + const Type *T = NNS->getAsType(); + if (!T) + return true; + const TemplateSpecializationType *TST = + T->getAs<TemplateSpecializationType>(); + if (!TST) + return true; + TemplateName TN = TST->getTemplateName(); + const ClassTemplateDecl *TD = + dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()); + if (!TD) + return true; + CXXRecordDecl *RD = TD->getTemplatedDecl(); + if (!RD->hasDefinition()) + return true; + RD = RD->getDefinition(); + DeclarationName Name(DNT->getIdentifier()); + std::vector<const NamedDecl *> Symbols = RD->lookupDependentName( + Name, [](const NamedDecl *ND) { return isa<TypeDecl>(ND); }); + if (Symbols.size() != 1) + return true; + return IndexCtx.handleReference(Symbols[0], TL.getNameLoc(), Parent, + ParentDC, SymbolRoleSet(), Relations); + } + bool TraverseStmt(Stmt *S) { IndexCtx.indexBody(S, Parent, ParentDC); return true; @@ -166,7 +212,7 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, if (!DC) DC = Parent->getLexicalDeclContext(); - SourceLocation Loc = NNS.getSourceRange().getBegin(); + SourceLocation Loc = NNS.getLocalBeginLoc(); switch (NNS.getNestedNameSpecifier()->getKind()) { case NestedNameSpecifier::Identifier: @@ -190,11 +236,14 @@ void IndexingContext::indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, } } -void IndexingContext::indexTagDecl(const TagDecl *D) { - if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D)) +void IndexingContext::indexTagDecl(const TagDecl *D, + ArrayRef<SymbolRelation> Relations) { + if (!shouldIndex(D)) + return; + if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D)) return; - if (handleDecl(D)) { + if (handleDecl(D, /*Roles=*/SymbolRoleSet(), Relations)) { if (D->isThisDeclarationADefinition()) { indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); if (auto CXXRD = dyn_cast<CXXRecordDecl>(D)) { diff --git a/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp b/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp index d744293..84d3120 100644 --- a/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp +++ b/contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp @@ -13,6 +13,7 @@ #include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Serialization/ASTReader.h" using namespace clang; using namespace clang::index; @@ -173,4 +174,32 @@ void index::indexASTUnit(ASTUnit &Unit, IndexCtx.setASTContext(Unit.getASTContext()); DataConsumer->initialize(Unit.getASTContext()); indexTranslationUnit(Unit, IndexCtx); + DataConsumer->finish(); +} + +void index::indexTopLevelDecls(ASTContext &Ctx, ArrayRef<const Decl *> Decls, + std::shared_ptr<IndexDataConsumer> DataConsumer, + IndexingOptions Opts) { + IndexingContext IndexCtx(Opts, *DataConsumer); + IndexCtx.setASTContext(Ctx); + + DataConsumer->initialize(Ctx); + for (const Decl *D : Decls) + IndexCtx.indexTopLevelDecl(D); + DataConsumer->finish(); +} + +void index::indexModuleFile(serialization::ModuleFile &Mod, + ASTReader &Reader, + std::shared_ptr<IndexDataConsumer> DataConsumer, + IndexingOptions Opts) { + ASTContext &Ctx = Reader.getContext(); + IndexingContext IndexCtx(Opts, *DataConsumer); + IndexCtx.setASTContext(Ctx); + DataConsumer->initialize(Ctx); + + for (const Decl *D :Reader.getModuleFileLevelDecls(Mod)) { + IndexCtx.indexTopLevelDecl(D); + } + DataConsumer->finish(); } diff --git a/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp b/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp index 6dd6c0c..addee69 100644 --- a/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp +++ b/contrib/llvm/tools/clang/lib/Index/IndexingContext.cpp @@ -17,6 +17,21 @@ using namespace clang; using namespace index; +static bool isGeneratedDecl(const Decl *D) { + if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>()) { + return attr->getGeneratedDeclaration(); + } + return false; +} + +bool IndexingContext::shouldIndex(const Decl *D) { + return !isGeneratedDecl(D); +} + +const LangOptions &IndexingContext::getLangOpts() const { + return Ctx->getLangOpts(); +} + bool IndexingContext::shouldIndexFunctionLocalSymbols() const { return IndexOpts.IndexFunctionLocals; } @@ -24,9 +39,7 @@ bool IndexingContext::shouldIndexFunctionLocalSymbols() const { bool IndexingContext::handleDecl(const Decl *D, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) { - return handleDeclOccurrence(D, D->getLocation(), /*IsRef=*/false, - cast<Decl>(D->getDeclContext()), Roles, Relations, - nullptr, nullptr, D->getDeclContext()); + return handleDecl(D, D->getLocation(), Roles, Relations); } bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc, @@ -35,9 +48,14 @@ bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc, const DeclContext *DC) { if (!DC) DC = D->getDeclContext(); + + const Decl *OrigD = D; + if (isa<ObjCPropertyImplDecl>(D)) { + D = cast<ObjCPropertyImplDecl>(D)->getPropertyDecl(); + } return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC), Roles, Relations, - nullptr, nullptr, DC); + nullptr, OrigD, DC); } bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, @@ -47,7 +65,7 @@ bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc, ArrayRef<SymbolRelation> Relations, const Expr *RefE, const Decl *RefD) { - if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D)) + if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D)) return true; if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D)) @@ -97,34 +115,6 @@ bool IndexingContext::importedModule(const ImportDecl *ImportD) { return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset); } -bool IndexingContext::isFunctionLocalDecl(const Decl *D) { - assert(D); - - if (isa<TemplateTemplateParmDecl>(D)) - return true; - - if (isa<ObjCTypeParamDecl>(D)) - return true; - - if (!D->getParentFunctionOrMethod()) - return false; - - if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { - switch (ND->getFormalLinkage()) { - case NoLinkage: - case VisibleNoLinkage: - case InternalLinkage: - return true; - case UniqueExternalLinkage: - llvm_unreachable("Not a sema linkage"); - case ExternalLinkage: - return false; - } - } - - return true; -} - bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) { TemplateSpecializationKind TKind = TSK_Undeclared; if (const ClassTemplateSpecializationDecl * @@ -134,6 +124,16 @@ bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) { TKind = FD->getTemplateSpecializationKind(); } else if (auto *VD = dyn_cast<VarDecl>(D)) { TKind = VD->getTemplateSpecializationKind(); + } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) { + if (RD->getInstantiatedFromMemberClass()) + TKind = RD->getTemplateSpecializationKind(); + } else if (const auto *ED = dyn_cast<EnumDecl>(D)) { + if (ED->getInstantiatedFromMemberEnum()) + TKind = ED->getTemplateSpecializationKind(); + } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D) || + isa<EnumConstantDecl>(D)) { + if (const auto *Parent = dyn_cast<Decl>(D->getDeclContext())) + return isTemplateImplicitInstantiation(Parent); } switch (TKind) { case TSK_Undeclared: @@ -161,6 +161,16 @@ bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) { return true; } +static const CXXRecordDecl * +getDeclContextForTemplateInstationPattern(const Decl *D) { + if (const auto *CTSD = + dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext())) + return CTSD->getTemplateInstantiationPattern(); + else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext())) + return RD->getInstantiatedFromMemberClass(); + return nullptr; +} + static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) { if (const ClassTemplateSpecializationDecl * SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) { @@ -169,6 +179,28 @@ static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) { return FD->getTemplateInstantiationPattern(); } else if (auto *VD = dyn_cast<VarDecl>(D)) { return VD->getTemplateInstantiationPattern(); + } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) { + return RD->getInstantiatedFromMemberClass(); + } else if (const auto *ED = dyn_cast<EnumDecl>(D)) { + return ED->getInstantiatedFromMemberEnum(); + } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) { + const auto *ND = cast<NamedDecl>(D); + if (const CXXRecordDecl *Pattern = + getDeclContextForTemplateInstationPattern(ND)) { + for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) { + if (BaseND->isImplicit()) + continue; + if (BaseND->getKind() == ND->getKind()) + return BaseND; + } + } + } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) { + if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) { + if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) { + for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName())) + return BaseECD; + } + } } return nullptr; } @@ -197,6 +229,12 @@ static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, AST return false; } +/// Whether the given NamedDecl should be skipped because it has no name. +static bool shouldSkipNamelessDecl(const NamedDecl *ND) { + return ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) && + !isa<ObjCCategoryDecl>(ND); +} + static const Decl *adjustParent(const Decl *Parent) { if (!Parent) return nullptr; @@ -211,8 +249,8 @@ static const Decl *adjustParent(const Decl *Parent) { } else if (auto RD = dyn_cast<RecordDecl>(Parent)) { if (RD->isAnonymousStructOrUnion()) continue; - } else if (auto FD = dyn_cast<FieldDecl>(Parent)) { - if (FD->getDeclName().isEmpty()) + } else if (auto ND = dyn_cast<NamedDecl>(Parent)) { + if (shouldSkipNamelessDecl(ND)) continue; } return Parent; @@ -222,13 +260,60 @@ static const Decl *adjustParent(const Decl *Parent) { static const Decl *getCanonicalDecl(const Decl *D) { D = D->getCanonicalDecl(); if (auto TD = dyn_cast<TemplateDecl>(D)) { - D = TD->getTemplatedDecl(); - assert(D->isCanonicalDecl()); + if (auto TTD = TD->getTemplatedDecl()) { + D = TTD; + assert(D->isCanonicalDecl()); + } } return D; } +static bool shouldReportOccurrenceForSystemDeclOnlyMode( + bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) { + if (!IsRef) + return true; + + auto acceptForRelation = [](SymbolRoleSet roles) -> bool { + bool accept = false; + applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool { + switch (r) { + case SymbolRole::RelationChildOf: + case SymbolRole::RelationBaseOf: + case SymbolRole::RelationOverrideOf: + case SymbolRole::RelationExtendedBy: + case SymbolRole::RelationAccessorOf: + case SymbolRole::RelationIBTypeOf: + accept = true; + return false; + case SymbolRole::Declaration: + case SymbolRole::Definition: + case SymbolRole::Reference: + case SymbolRole::Read: + case SymbolRole::Write: + case SymbolRole::Call: + case SymbolRole::Dynamic: + case SymbolRole::AddressOf: + case SymbolRole::Implicit: + case SymbolRole::RelationReceivedBy: + case SymbolRole::RelationCalledBy: + case SymbolRole::RelationContainedBy: + case SymbolRole::RelationSpecializationOf: + return true; + } + llvm_unreachable("Unsupported SymbolRole value!"); + }); + return accept; + }; + + for (auto &Rel : Relations) { + if (acceptForRelation(Rel.Roles)) + return true; + } + + return false; +} + bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc, bool IsRef, const Decl *Parent, SymbolRoleSet Roles, @@ -238,9 +323,7 @@ bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc, const DeclContext *ContainerDC) { if (D->isImplicit() && !isa<ObjCMethodDecl>(D)) return true; - if (!isa<NamedDecl>(D) || - (cast<NamedDecl>(D)->getDeclName().isEmpty() && - !isa<TagDecl>(D) && !isa<ObjCCategoryDecl>(D))) + if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D))) return true; SourceManager &SM = Ctx->getSourceManager(); @@ -264,7 +347,7 @@ bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc, case IndexingOptions::SystemSymbolFilterKind::None: return true; case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly: - if (IsRef) + if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations)) return true; break; case IndexingOptions::SystemSymbolFilterKind::All: @@ -286,7 +369,7 @@ bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc, if (IsRef) Roles |= (unsigned)SymbolRole::Reference; - else if (isDeclADefinition(D, ContainerDC, *Ctx)) + else if (isDeclADefinition(OrigD, ContainerDC, *Ctx)) Roles |= (unsigned)SymbolRole::Definition; else Roles |= (unsigned)SymbolRole::Declaration; @@ -313,12 +396,12 @@ bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc, }; if (Parent) { - if (IsRef) { + if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) { addRelation(SymbolRelation{ (unsigned)SymbolRole::RelationContainedBy, Parent }); - } else if (!cast<DeclContext>(Parent)->isFunctionOrMethod()) { + } else { addRelation(SymbolRelation{ (unsigned)SymbolRole::RelationChildOf, Parent diff --git a/contrib/llvm/tools/clang/lib/Index/IndexingContext.h b/contrib/llvm/tools/clang/lib/Index/IndexingContext.h index dd1dd32..566651c 100644 --- a/contrib/llvm/tools/clang/lib/Index/IndexingContext.h +++ b/contrib/llvm/tools/clang/lib/Index/IndexingContext.h @@ -48,6 +48,10 @@ public: void setASTContext(ASTContext &ctx) { Ctx = &ctx; } + bool shouldIndex(const Decl *D); + + const LangOptions &getLangOpts() const; + bool shouldSuppressRefs() const { return false; } @@ -58,7 +62,6 @@ public: return false; } - static bool isFunctionLocalDecl(const Decl *D); static bool isTemplateImplicitInstantiation(const Decl *D); bool handleDecl(const Decl *D, SymbolRoleSet Roles = SymbolRoleSet(), @@ -72,7 +75,7 @@ public: bool handleReference(const NamedDecl *D, SourceLocation Loc, const NamedDecl *Parent, const DeclContext *DC, - SymbolRoleSet Roles, + SymbolRoleSet Roles = SymbolRoleSet(), ArrayRef<SymbolRelation> Relations = None, const Expr *RefE = nullptr, const Decl *RefD = nullptr); @@ -81,7 +84,8 @@ public: bool indexDecl(const Decl *D); - void indexTagDecl(const TagDecl *D); + void indexTagDecl(const TagDecl *D, + ArrayRef<SymbolRelation> Relations = None); void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent, const DeclContext *DC = nullptr, diff --git a/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp b/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp index 58f61c3..21054b0 100644 --- a/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp +++ b/contrib/llvm/tools/clang/lib/Index/USRGeneration.cpp @@ -46,6 +46,15 @@ static bool printLoc(llvm::raw_ostream &OS, SourceLocation Loc, return false; } +static StringRef GetExternalSourceContainer(const NamedDecl *D) { + if (!D) + return StringRef(); + if (auto *attr = D->getExternalSourceSymbolAttr()) { + return attr->getDefinedIn(); + } + return StringRef(); +} + namespace { class USRGenerator : public ConstDeclVisitor<USRGenerator> { SmallVectorImpl<char> &Buf; @@ -79,7 +88,8 @@ public: void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D); void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); void VisitClassTemplateDecl(const ClassTemplateDecl *D); - void VisitObjCContainerDecl(const ObjCContainerDecl *CD); + void VisitObjCContainerDecl(const ObjCContainerDecl *CD, + const ObjCCategoryDecl *CatD = nullptr); void VisitObjCMethodDecl(const ObjCMethodDecl *MD); void VisitObjCPropertyDecl(const ObjCPropertyDecl *D); void VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D); @@ -116,6 +126,8 @@ public: return D->getParentFunctionOrMethod() != nullptr; } + void GenExtSymbolContainer(const NamedDecl *D); + /// Generate the string component containing the location of the /// declaration. bool GenLoc(const Decl *D, bool IncludeOffset); @@ -127,13 +139,16 @@ public: /// itself. /// Generate a USR for an Objective-C class. - void GenObjCClass(StringRef cls) { - generateUSRForObjCClass(cls, Out); + void GenObjCClass(StringRef cls, StringRef ExtSymDefinedIn, + StringRef CategoryContextExtSymbolDefinedIn) { + generateUSRForObjCClass(cls, Out, ExtSymDefinedIn, + CategoryContextExtSymbolDefinedIn); } /// Generate a USR for an Objective-C class category. - void GenObjCCategory(StringRef cls, StringRef cat) { - generateUSRForObjCCategory(cls, cat, Out); + void GenObjCCategory(StringRef cls, StringRef cat, + StringRef clsExt, StringRef catExt) { + generateUSRForObjCCategory(cls, cat, Out, clsExt, catExt); } /// Generate a USR fragment for an Objective-C property. @@ -142,8 +157,8 @@ public: } /// Generate a USR for an Objective-C protocol. - void GenObjCProtocol(StringRef prot) { - generateUSRForObjCProtocol(prot, Out); + void GenObjCProtocol(StringRef prot, StringRef ext) { + generateUSRForObjCProtocol(prot, Out, ext); } void VisitType(QualType T); @@ -204,7 +219,11 @@ void USRGenerator::VisitFunctionDecl(const FunctionDecl *D) { if (ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) return; + const unsigned StartSize = Buf.size(); VisitDeclContext(D->getDeclContext()); + if (Buf.size() == StartSize) + GenExtSymbolContainer(D); + bool IsTemplate = false; if (FunctionTemplateDecl *FunTmpl = D->getDescribedFunctionTemplate()) { IsTemplate = true; @@ -310,7 +329,7 @@ void USRGenerator::VisitVarDecl(const VarDecl *D) { // For a template specialization, mangle the template arguments. if (const VarTemplateSpecializationDecl *Spec = dyn_cast<VarTemplateSpecializationDecl>(D)) { - const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs(); + const TemplateArgumentList &Args = Spec->getTemplateArgs(); Out << '>'; for (unsigned I = 0, N = Args.size(); I != N; ++I) { Out << '#'; @@ -367,7 +386,16 @@ void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) { IgnoreResults = true; return; } - Visit(ID); + auto getCategoryContext = [](const ObjCMethodDecl *D) -> + const ObjCCategoryDecl * { + if (auto *CD = dyn_cast<ObjCCategoryDecl>(D->getDeclContext())) + return CD; + if (auto *ICD = dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) + return ICD->getCategoryDecl(); + return nullptr; + }; + auto *CD = getCategoryContext(D); + VisitObjCContainerDecl(ID, CD); } // Ideally we would use 'GenObjCMethod', but this is such a hot path // for Objective-C code that we don't want to use @@ -376,13 +404,15 @@ void USRGenerator::VisitObjCMethodDecl(const ObjCMethodDecl *D) { << DeclarationName(D->getSelector()); } -void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D) { +void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D, + const ObjCCategoryDecl *CatD) { switch (D->getKind()) { default: llvm_unreachable("Invalid ObjC container."); case Decl::ObjCInterface: case Decl::ObjCImplementation: - GenObjCClass(D->getName()); + GenObjCClass(D->getName(), GetExternalSourceContainer(D), + GetExternalSourceContainer(CatD)); break; case Decl::ObjCCategory: { const ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D); @@ -402,7 +432,9 @@ void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D) { GenLoc(CD, /*IncludeOffset=*/true); } else - GenObjCCategory(ID->getName(), CD->getName()); + GenObjCCategory(ID->getName(), CD->getName(), + GetExternalSourceContainer(ID), + GetExternalSourceContainer(CD)); break; } @@ -417,12 +449,16 @@ void USRGenerator::VisitObjCContainerDecl(const ObjCContainerDecl *D) { IgnoreResults = true; return; } - GenObjCCategory(ID->getName(), CD->getName()); + GenObjCCategory(ID->getName(), CD->getName(), + GetExternalSourceContainer(ID), + GetExternalSourceContainer(CD)); break; } - case Decl::ObjCProtocol: - GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName()); + case Decl::ObjCProtocol: { + const ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(D); + GenObjCProtocol(PD->getName(), GetExternalSourceContainer(PD)); break; + } } } @@ -452,6 +488,8 @@ void USRGenerator::VisitTagDecl(const TagDecl *D) { ShouldGenerateLocation(D) && GenLoc(D, /*IncludeOffset=*/isLocal(D))) return; + GenExtSymbolContainer(D); + D = D->getCanonicalDecl(); VisitDeclContext(D->getDeclContext()); @@ -521,7 +559,7 @@ void USRGenerator::VisitTagDecl(const TagDecl *D) { // For a class template specialization, mangle the template arguments. if (const ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(D)) { - const TemplateArgumentList &Args = Spec->getTemplateInstantiationArgs(); + const TemplateArgumentList &Args = Spec->getTemplateArgs(); Out << '>'; for (unsigned I = 0, N = Args.size(); I != N; ++I) { Out << '#'; @@ -544,6 +582,12 @@ void USRGenerator::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { GenLoc(D, /*IncludeOffset=*/true); } +void USRGenerator::GenExtSymbolContainer(const NamedDecl *D) { + StringRef Container = GetExternalSourceContainer(D); + if (!Container.empty()) + Out << "@M@" << Container; +} + bool USRGenerator::GenLoc(const Decl *D, bool IncludeOffset) { if (generatedLoc) return IgnoreResults; @@ -654,7 +698,6 @@ void USRGenerator::VisitType(QualType T) { case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: - case BuiltinType::OCLNDRange: case BuiltinType::OCLReserveID: case BuiltinType::OCLSampler: IgnoreResults = true; @@ -768,7 +811,13 @@ void USRGenerator::VisitType(QualType T) { T = InjT->getInjectedSpecializationType(); continue; } - + if (const auto *VT = T->getAs<VectorType>()) { + Out << (T->isExtVectorType() ? ']' : '['); + Out << VT->getNumElements(); + T = VT->getElementType(); + continue; + } + // Unhandled type. Out << ' '; break; @@ -867,12 +916,34 @@ void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) { // USR generation functions. //===----------------------------------------------------------------------===// -void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS) { +static void combineClassAndCategoryExtContainers(StringRef ClsSymDefinedIn, + StringRef CatSymDefinedIn, + raw_ostream &OS) { + if (ClsSymDefinedIn.empty() && CatSymDefinedIn.empty()) + return; + if (CatSymDefinedIn.empty()) { + OS << "@M@" << ClsSymDefinedIn << '@'; + return; + } + OS << "@CM@" << CatSymDefinedIn << '@'; + if (ClsSymDefinedIn != CatSymDefinedIn) { + OS << ClsSymDefinedIn << '@'; + } +} + +void clang::index::generateUSRForObjCClass(StringRef Cls, raw_ostream &OS, + StringRef ExtSymDefinedIn, + StringRef CategoryContextExtSymbolDefinedIn) { + combineClassAndCategoryExtContainers(ExtSymDefinedIn, + CategoryContextExtSymbolDefinedIn, OS); OS << "objc(cs)" << Cls; } void clang::index::generateUSRForObjCCategory(StringRef Cls, StringRef Cat, - raw_ostream &OS) { + raw_ostream &OS, + StringRef ClsSymDefinedIn, + StringRef CatSymDefinedIn) { + combineClassAndCategoryExtContainers(ClsSymDefinedIn, CatSymDefinedIn, OS); OS << "objc(cy)" << Cls << '@' << Cat; } @@ -891,10 +962,25 @@ void clang::index::generateUSRForObjCProperty(StringRef Prop, bool isClassProp, OS << (isClassProp ? "(cpy)" : "(py)") << Prop; } -void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS) { +void clang::index::generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS, + StringRef ExtSymDefinedIn) { + if (!ExtSymDefinedIn.empty()) + OS << "@M@" << ExtSymDefinedIn << '@'; OS << "objc(pl)" << Prot; } +void clang::index::generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS, + StringRef ExtSymDefinedIn) { + if (!ExtSymDefinedIn.empty()) + OS << "@M@" << ExtSymDefinedIn; + OS << "@E@" << EnumName; +} + +void clang::index::generateUSRForEnumConstant(StringRef EnumConstantName, + raw_ostream &OS) { + OS << '@' << EnumConstantName; +} + bool clang::index::generateUSRForDecl(const Decl *D, SmallVectorImpl<char> &Buf) { if (!D) @@ -911,21 +997,30 @@ bool clang::index::generateUSRForDecl(const Decl *D, bool clang::index::generateUSRForMacro(const MacroDefinitionRecord *MD, const SourceManager &SM, SmallVectorImpl<char> &Buf) { + if (!MD) + return true; + return generateUSRForMacro(MD->getName()->getName(), MD->getLocation(), + SM, Buf); + +} + +bool clang::index::generateUSRForMacro(StringRef MacroName, SourceLocation Loc, + const SourceManager &SM, + SmallVectorImpl<char> &Buf) { // Don't generate USRs for things with invalid locations. - if (!MD || MD->getLocation().isInvalid()) + if (MacroName.empty() || Loc.isInvalid()) return true; llvm::raw_svector_ostream Out(Buf); // Assume that system headers are sane. Don't put source location // information into the USR if the macro comes from a system header. - SourceLocation Loc = MD->getLocation(); bool ShouldGenerateLocation = !SM.isInSystemHeader(Loc); Out << getUSRSpacePrefix(); if (ShouldGenerateLocation) printLoc(Out, Loc, SM, /*IncludeOffset=*/true); Out << "@macro@"; - Out << MD->getName()->getName(); + Out << MacroName; return false; } |