250 lines · cpp
1//===-- DemangledNameInfo.cpp ---------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Core/DemangledNameInfo.h"10 11using namespace llvm::itanium_demangle;12 13namespace lldb_private {14 15bool TrackingOutputBuffer::shouldTrack() const {16 if (!isPrintingTopLevelFunctionType())17 return false;18 19 if (isInsideTemplateArgs())20 return false;21 22 if (NameInfo.ArgumentsRange.first > 0)23 return false;24 25 return true;26}27 28bool TrackingOutputBuffer::canFinalize() const {29 if (!isPrintingTopLevelFunctionType())30 return false;31 32 if (isInsideTemplateArgs())33 return false;34 35 if (NameInfo.ArgumentsRange.first == 0)36 return false;37 38 return true;39}40 41void TrackingOutputBuffer::updateBasenameEnd() {42 if (!shouldTrack())43 return;44 45 NameInfo.BasenameRange.second = getCurrentPosition();46}47 48void TrackingOutputBuffer::updateScopeStart() {49 if (!shouldTrack())50 return;51 52 NameInfo.ScopeRange.first = getCurrentPosition();53}54 55void TrackingOutputBuffer::updateScopeEnd() {56 if (!shouldTrack())57 return;58 59 NameInfo.ScopeRange.second = getCurrentPosition();60}61 62void TrackingOutputBuffer::finalizeArgumentEnd() {63 if (!canFinalize())64 return;65 66 NameInfo.ArgumentsRange.second = getCurrentPosition();67}68 69void TrackingOutputBuffer::finalizeQualifiersStart() {70 if (!canFinalize())71 return;72 73 NameInfo.QualifiersRange.first = getCurrentPosition();74}75 76void TrackingOutputBuffer::finalizeQualifiersEnd() {77 if (!canFinalize())78 return;79 80 NameInfo.QualifiersRange.second = getCurrentPosition();81}82 83void TrackingOutputBuffer::finalizeStart() {84 if (!shouldTrack())85 return;86 87 NameInfo.ArgumentsRange.first = getCurrentPosition();88 89 // If nothing has set the end of the basename yet (for example when90 // printing templates), then the beginning of the arguments is the end of91 // the basename.92 if (NameInfo.BasenameRange.second == 0)93 NameInfo.BasenameRange.second = getCurrentPosition();94 95 // There is something between the basename and the start of the function96 // arguments. Assume those are template arguments (which *should* be true for97 // C++ demangled names, but this assumption may change in the future, in98 // which case this needs to be adjusted).99 if (NameInfo.BasenameRange.second != NameInfo.ArgumentsRange.first)100 NameInfo.TemplateArgumentsRange = {NameInfo.BasenameRange.second,101 NameInfo.ArgumentsRange.first};102 103 assert(!shouldTrack());104 assert(canFinalize());105}106 107void TrackingOutputBuffer::finalizeEnd() {108 if (!canFinalize())109 return;110 111 if (NameInfo.ScopeRange.first > NameInfo.ScopeRange.second)112 NameInfo.ScopeRange.second = NameInfo.ScopeRange.first;113 NameInfo.BasenameRange.first = NameInfo.ScopeRange.second;114 115 // We call anything past the FunctionEncoding the "suffix".116 // In practice this would be nodes like `DotSuffix` that wrap117 // a FunctionEncoding.118 NameInfo.SuffixRange.first = getCurrentPosition();119}120 121ScopedOverride<unsigned> TrackingOutputBuffer::enterFunctionTypePrinting() {122 return {FunctionPrintingDepth, FunctionPrintingDepth + 1};123}124 125bool TrackingOutputBuffer::isPrintingTopLevelFunctionType() const {126 return FunctionPrintingDepth == 1;127}128 129void TrackingOutputBuffer::printLeft(const Node &N) {130 switch (N.getKind()) {131 case Node::KFunctionType:132 printLeftImpl(static_cast<const FunctionType &>(N));133 break;134 case Node::KFunctionEncoding:135 printLeftImpl(static_cast<const FunctionEncoding &>(N));136 break;137 case Node::KNestedName:138 printLeftImpl(static_cast<const NestedName &>(N));139 break;140 case Node::KNameWithTemplateArgs:141 printLeftImpl(static_cast<const NameWithTemplateArgs &>(N));142 break;143 default:144 OutputBuffer::printLeft(N);145 }146 147 // Keep updating suffix until we reach the end.148 NameInfo.SuffixRange.second = getCurrentPosition();149}150 151void TrackingOutputBuffer::printRight(const Node &N) {152 switch (N.getKind()) {153 case Node::KFunctionType:154 printRightImpl(static_cast<const FunctionType &>(N));155 break;156 case Node::KFunctionEncoding:157 printRightImpl(static_cast<const FunctionEncoding &>(N));158 break;159 default:160 OutputBuffer::printRight(N);161 }162 163 // Keep updating suffix until we reach the end.164 NameInfo.SuffixRange.second = getCurrentPosition();165}166 167void TrackingOutputBuffer::printLeftImpl(const FunctionType &N) {168 auto Scoped = enterFunctionTypePrinting();169 OutputBuffer::printLeft(N);170}171 172void TrackingOutputBuffer::printRightImpl(const FunctionType &N) {173 auto Scoped = enterFunctionTypePrinting();174 OutputBuffer::printRight(N);175}176 177void TrackingOutputBuffer::printLeftImpl(const FunctionEncoding &N) {178 auto Scoped = enterFunctionTypePrinting();179 180 const Node *Ret = N.getReturnType();181 if (Ret) {182 printLeft(*Ret);183 if (!Ret->hasRHSComponent(*this))184 *this += " ";185 }186 187 updateScopeStart();188 189 N.getName()->print(*this);190}191 192void TrackingOutputBuffer::printRightImpl(const FunctionEncoding &N) {193 auto Scoped = enterFunctionTypePrinting();194 finalizeStart();195 196 printOpen();197 N.getParams().printWithComma(*this);198 printClose();199 200 finalizeArgumentEnd();201 202 const Node *Ret = N.getReturnType();203 204 if (Ret)205 printRight(*Ret);206 207 finalizeQualifiersStart();208 209 auto CVQuals = N.getCVQuals();210 auto RefQual = N.getRefQual();211 auto *Attrs = N.getAttrs();212 auto *Requires = N.getRequires();213 214 if (CVQuals & QualConst)215 *this += " const";216 if (CVQuals & QualVolatile)217 *this += " volatile";218 if (CVQuals & QualRestrict)219 *this += " restrict";220 if (RefQual == FrefQualLValue)221 *this += " &";222 else if (RefQual == FrefQualRValue)223 *this += " &&";224 if (Attrs != nullptr)225 Attrs->print(*this);226 if (Requires != nullptr) {227 *this += " requires ";228 Requires->print(*this);229 }230 231 finalizeQualifiersEnd();232 finalizeEnd();233}234 235void TrackingOutputBuffer::printLeftImpl(const NestedName &N) {236 N.Qual->print(*this);237 *this += "::";238 updateScopeEnd();239 N.Name->print(*this);240 updateBasenameEnd();241}242 243void TrackingOutputBuffer::printLeftImpl(const NameWithTemplateArgs &N) {244 N.Name->print(*this);245 updateBasenameEnd();246 N.TemplateArgs->print(*this);247}248 249} // namespace lldb_private250