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 | |