| 1 | // |
| 2 | // Function.cpp |
| 3 | // |
| 4 | // Library: CppParser |
| 5 | // Package: SymbolTable |
| 6 | // Module: Function |
| 7 | // |
| 8 | // Copyright (c) 2006, Applied Informatics Software Engineering GmbH. |
| 9 | // and Contributors. |
| 10 | // |
| 11 | // SPDX-License-Identifier: BSL-1.0 |
| 12 | // |
| 13 | |
| 14 | |
| 15 | #include "Poco/CppParser/Function.h" |
| 16 | #include "Poco/CppParser/Parameter.h" |
| 17 | #include "Poco/CppParser/NameSpace.h" |
| 18 | #include "Poco/CppParser/Struct.h" |
| 19 | #include "Poco/CppParser/Utility.h" |
| 20 | #include "Poco/String.h" |
| 21 | #include <sstream> |
| 22 | #include <cctype> |
| 23 | #include <cstddef> |
| 24 | |
| 25 | |
| 26 | namespace Poco { |
| 27 | namespace CppParser { |
| 28 | |
| 29 | |
| 30 | Function::Function(const std::string& decl, NameSpace* pNameSpace): |
| 31 | Decl(decl, pNameSpace), |
| 32 | _flags(0), |
| 33 | _retParam() |
| 34 | { |
| 35 | if (hasAttr(decl, "static" )) |
| 36 | _flags |= FN_STATIC; |
| 37 | if (hasAttr(decl, "virtual" )) |
| 38 | _flags |= FN_VIRTUAL; |
| 39 | if (hasAttr(decl, "inline" )) |
| 40 | _flags |= FN_INLINE; |
| 41 | if (hasAttr(decl, "template" )) |
| 42 | _flags |= FN_TEMPLATE; |
| 43 | |
| 44 | if (isMethod() || isFunction()) |
| 45 | { |
| 46 | // parse the decl |
| 47 | std::size_t pos = decl.rfind(name()); |
| 48 | _retParam = decl.substr(0, pos-1); |
| 49 | // eliminate static, virtual, inline, template |
| 50 | _retParam = replace(_retParam, "static " , "" ); |
| 51 | _retParam = replace(_retParam, "virtual " , "" ); |
| 52 | _retParam = replace(_retParam, "inline " , "" ); |
| 53 | if (_flags & FN_TEMPLATE) |
| 54 | { |
| 55 | std::size_t pos2 = _retParam.find(">" ); |
| 56 | poco_assert (pos2 != std::string::npos); |
| 57 | _retParam = _retParam.substr(pos2+1); |
| 58 | } |
| 59 | Poco::trimInPlace(_retParam); |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | |
| 64 | Function::~Function() |
| 65 | { |
| 66 | for (Parameters::iterator it = _params.begin(); it != _params.end(); ++it) |
| 67 | { |
| 68 | delete *it; |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | |
| 73 | void Function::addParameter(Parameter* pParam) |
| 74 | { |
| 75 | _params.push_back(pParam); |
| 76 | } |
| 77 | |
| 78 | |
| 79 | Function::Iterator Function::begin() const |
| 80 | { |
| 81 | return _params.begin(); |
| 82 | } |
| 83 | |
| 84 | |
| 85 | Function::Iterator Function::end() const |
| 86 | { |
| 87 | return _params.end(); |
| 88 | } |
| 89 | |
| 90 | |
| 91 | void Function::makeInline() |
| 92 | { |
| 93 | _flags |= FN_INLINE; |
| 94 | } |
| 95 | |
| 96 | |
| 97 | void Function::makeConst() |
| 98 | { |
| 99 | _flags |= FN_CONST; |
| 100 | } |
| 101 | |
| 102 | |
| 103 | void Function::makePureVirtual() |
| 104 | { |
| 105 | _flags |= FN_PURE_VIRTUAL; |
| 106 | } |
| 107 | |
| 108 | |
| 109 | void Function::makeFinal() |
| 110 | { |
| 111 | _flags |= FN_FINAL; |
| 112 | } |
| 113 | |
| 114 | |
| 115 | void Function::makeOverride() |
| 116 | { |
| 117 | _flags |= FN_OVERRIDE; |
| 118 | } |
| 119 | |
| 120 | |
| 121 | void Function::makeNoexcept() |
| 122 | { |
| 123 | _flags |= FN_NOEXCEPT; |
| 124 | } |
| 125 | |
| 126 | |
| 127 | void Function::makeDefault() |
| 128 | { |
| 129 | _flags |= FN_DEFAULT; |
| 130 | } |
| 131 | |
| 132 | |
| 133 | void Function::makeDelete() |
| 134 | { |
| 135 | _flags |= FN_DELETE; |
| 136 | } |
| 137 | |
| 138 | |
| 139 | bool Function::isConstructor() const |
| 140 | { |
| 141 | return name() == nameSpace()->name(); |
| 142 | } |
| 143 | |
| 144 | |
| 145 | bool Function::isDestructor() const |
| 146 | { |
| 147 | return name()[0] == '~'; |
| 148 | } |
| 149 | |
| 150 | |
| 151 | bool Function::isMethod() const |
| 152 | { |
| 153 | return !isConstructor() && !isDestructor() && nameSpace()->kind() == Symbol::SYM_STRUCT; |
| 154 | } |
| 155 | |
| 156 | |
| 157 | bool Function::isFunction() const |
| 158 | { |
| 159 | return nameSpace()->kind() == Symbol::SYM_NAMESPACE; |
| 160 | } |
| 161 | |
| 162 | |
| 163 | int Function::countParameters() const |
| 164 | { |
| 165 | return (int) _params.size(); |
| 166 | } |
| 167 | |
| 168 | |
| 169 | Symbol::Kind Function::kind() const |
| 170 | { |
| 171 | return Symbol::SYM_FUNCTION; |
| 172 | } |
| 173 | |
| 174 | |
| 175 | std::string Function::signature() const |
| 176 | { |
| 177 | std::string signature(declaration()); |
| 178 | if (signature.compare(0, 8, "virtual " ) == 0) |
| 179 | signature.erase(0, 8); |
| 180 | else if (signature.compare(0, 7, "static " ) == 0) |
| 181 | signature.erase(0, 8); |
| 182 | if (signature.compare(0, 7, "inline " ) == 0) |
| 183 | signature.erase(0, 7); |
| 184 | signature += "(" ; |
| 185 | bool isFirst = true; |
| 186 | for (Iterator it = begin(); it != end(); ++it) |
| 187 | { |
| 188 | if (isFirst) |
| 189 | isFirst = false; |
| 190 | else |
| 191 | signature += ", " ; |
| 192 | std::string arg = (*it)->declaration(); |
| 193 | std::string::size_type pos = arg.size() - 1; |
| 194 | while (pos > 0 && !std::isspace(arg[pos])) --pos; |
| 195 | while (pos > 0 && std::isspace(arg[pos])) --pos; |
| 196 | signature.append(arg, 0, pos + 1); |
| 197 | } |
| 198 | signature += ")" ; |
| 199 | if (_flags & FN_CONST) |
| 200 | signature += " const" ; |
| 201 | return signature; |
| 202 | } |
| 203 | |
| 204 | |
| 205 | bool Function::isVirtual() const |
| 206 | { |
| 207 | if (_flags & FN_VIRTUAL) |
| 208 | { |
| 209 | return true; |
| 210 | } |
| 211 | else if (isDestructor()) |
| 212 | { |
| 213 | Struct* pClass = dynamic_cast<Struct*>(nameSpace()); |
| 214 | return pClass && pClass->hasVirtualDestructor(); |
| 215 | } |
| 216 | else return getOverridden() != 0; |
| 217 | } |
| 218 | |
| 219 | |
| 220 | Function* Function::getOverridden() const |
| 221 | { |
| 222 | if (isMethod() && !(_flags & FN_STATIC)) |
| 223 | { |
| 224 | Struct* pClass = dynamic_cast<Struct*>(nameSpace()); |
| 225 | if (pClass) |
| 226 | { |
| 227 | for (Struct::BaseIterator it = pClass->baseBegin(); it != pClass->baseEnd(); ++it) |
| 228 | { |
| 229 | if (it->pClass) |
| 230 | { |
| 231 | Function* pOverridden = it->pClass->findFunction(signature()); |
| 232 | if (pOverridden && pOverridden->isVirtual()) |
| 233 | return pOverridden; |
| 234 | } |
| 235 | } |
| 236 | } |
| 237 | } |
| 238 | return 0; |
| 239 | } |
| 240 | |
| 241 | |
| 242 | std::string Function::toString() const |
| 243 | { |
| 244 | std::ostringstream ostr; |
| 245 | ostr << Decl::toString() << "(\n" ; |
| 246 | for (Iterator it = begin(); it != end(); ++it) |
| 247 | { |
| 248 | ostr << "\t" << (*it)->toString() << "\n" ; |
| 249 | } |
| 250 | ostr << ");" ; |
| 251 | return ostr.str(); |
| 252 | } |
| 253 | |
| 254 | |
| 255 | } } // namespace Poco::CppParser |
| 256 | |