Mercurial > hg > CbC > CbC_llvm
diff clang-tools-extra/clangd/Selection.cpp @ 221:79ff65ed7e25
LLVM12 Original
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 15 Jun 2021 19:15:29 +0900 |
parents | 0572611fdcc8 |
children | 5f17cb93ff66 |
line wrap: on
line diff
--- a/clang-tools-extra/clangd/Selection.cpp Tue Jun 15 19:13:43 2021 +0900 +++ b/clang-tools-extra/clangd/Selection.cpp Tue Jun 15 19:15:29 2021 +0900 @@ -35,21 +35,26 @@ namespace clangd { namespace { using Node = SelectionTree::Node; -using ast_type_traits::DynTypedNode; // Measure the fraction of selections that were enabled by recovery AST. -void recordMetrics(const SelectionTree &S) { +void recordMetrics(const SelectionTree &S, const LangOptions &Lang) { + if (!trace::enabled()) + return; + const char *LanguageLabel = Lang.CPlusPlus ? "C++" : Lang.ObjC ? "ObjC" : "C"; static constexpr trace::Metric SelectionUsedRecovery( - "selection_recovery", trace::Metric::Distribution); + "selection_recovery", trace::Metric::Distribution, "language"); + static constexpr trace::Metric RecoveryType( + "selection_recovery_type", trace::Metric::Distribution, "language"); const auto *Common = S.commonAncestor(); for (const auto *N = Common; N; N = N->Parent) { - if (N->ASTNode.get<RecoveryExpr>()) { - SelectionUsedRecovery.record(1); // used recovery ast. + if (const auto *RE = N->ASTNode.get<RecoveryExpr>()) { + SelectionUsedRecovery.record(1, LanguageLabel); // used recovery ast. + RecoveryType.record(RE->isTypeDependent() ? 0 : 1, LanguageLabel); return; } } if (Common) - SelectionUsedRecovery.record(0); // unused. + SelectionUsedRecovery.record(0, LanguageLabel); // unused. } // An IntervalSet maintains a set of disjoint subranges of an array. @@ -77,8 +82,8 @@ // Removes the elements of Claim from the set, modifying or removing ranges // that overlap it. // Returns the continuous subranges of Claim that were actually removed. - llvm::SmallVector<llvm::ArrayRef<T>, 4> erase(llvm::ArrayRef<T> Claim) { - llvm::SmallVector<llvm::ArrayRef<T>, 4> Out; + llvm::SmallVector<llvm::ArrayRef<T>> erase(llvm::ArrayRef<T> Claim) { + llvm::SmallVector<llvm::ArrayRef<T>> Out; if (Claim.empty()) return Out; @@ -217,14 +222,26 @@ SelFirst, AllSpelledTokens.end(), [&](const syntax::Token &Tok) { return SM.getFileOffset(Tok.location()) < SelEnd; }); + auto Sel = llvm::makeArrayRef(SelFirst, SelLimit); + // Find which of these are preprocessed to nothing and should be ignored. + std::vector<bool> PPIgnored(Sel.size(), false); + for (const syntax::TokenBuffer::Expansion &X : + Buf.expansionsOverlapping(Sel)) { + if (X.Expanded.empty()) { + for (const syntax::Token &Tok : X.Spelled) { + if (&Tok >= SelFirst && &Tok < SelLimit) + PPIgnored[&Tok - SelFirst] = true; + } + } + } // Precompute selectedness and offset for selected spelled tokens. - for (const syntax::Token *T = SelFirst; T < SelLimit; ++T) { - if (shouldIgnore(*T)) + for (unsigned I = 0; I < Sel.size(); ++I) { + if (shouldIgnore(Sel[I]) || PPIgnored[I]) continue; SpelledTokens.emplace_back(); Tok &S = SpelledTokens.back(); - S.Offset = SM.getFileOffset(T->location()); - if (S.Offset >= SelBegin && S.Offset + T->length() <= SelEnd) + S.Offset = SM.getFileOffset(Sel[I].location()); + if (S.Offset >= SelBegin && S.Offset + Sel[I].length() <= SelEnd) S.Selected = SelectionTree::Complete; else S.Selected = SelectionTree::Partial; @@ -464,6 +481,10 @@ bool TraverseTypeLoc(TypeLoc X) { return traverseNode(&X, [&] { return Base::TraverseTypeLoc(X); }); } + bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &X) { + return traverseNode(&X, + [&] { return Base::TraverseTemplateArgumentLoc(X); }); + } bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc X) { return traverseNode( &X, [&] { return Base::TraverseNestedNameSpecifierLoc(X); }); @@ -472,6 +493,9 @@ return traverseNode( X, [&] { return Base::TraverseConstructorInitializer(X); }); } + bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &X) { + return traverseNode(&X, [&] { return Base::TraverseCXXBaseSpecifier(X); }); + } // Stmt is the same, but this form allows the data recursion optimization. bool dataTraverseStmtPre(Stmt *X) { if (!X || isImplicit(X)) @@ -586,6 +610,10 @@ bool canSafelySkipNode(const DynTypedNode &N) { SourceRange S = N.getSourceRange(); if (auto *TL = N.get<TypeLoc>()) { + // FIXME: TypeLoc::getBeginLoc()/getEndLoc() are pretty fragile + // heuristics. We should consider only pruning critical TypeLoc nodes, to + // be more robust. + // DeclTypeTypeLoc::getSourceRange() is incomplete, which would lead to // failing // to descend into the child expression. @@ -597,6 +625,10 @@ // rid of this patch. if (auto DT = TL->getAs<DecltypeTypeLoc>()) S.setEnd(DT.getUnderlyingExpr()->getEndLoc()); + // AttributedTypeLoc may point to the attribute's range, NOT the modified + // type's range. + if (auto AT = TL->getAs<AttributedTypeLoc>()) + S = AT.getModifiedLoc().getSourceRange(); } if (!SelChecker.mayHit(S)) { dlog("{1}skip: {0}", printNodeToString(N, PrintPolicy), indent()); @@ -807,7 +839,7 @@ .printToString(SM)); Nodes = SelectionVisitor::collect(AST, Tokens, PrintPolicy, Begin, End, FID); Root = Nodes.empty() ? nullptr : &Nodes.front(); - recordMetrics(*this); + recordMetrics(*this, AST.getLangOpts()); dlog("Built selection tree\n{0}", *this); }