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
26namespace Poco {
27namespace CppParser {
28
29
30Function::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
64Function::~Function()
65{
66 for (Parameters::iterator it = _params.begin(); it != _params.end(); ++it)
67 {
68 delete *it;
69 }
70}
71
72
73void Function::addParameter(Parameter* pParam)
74{
75 _params.push_back(pParam);
76}
77
78
79Function::Iterator Function::begin() const
80{
81 return _params.begin();
82}
83
84
85Function::Iterator Function::end() const
86{
87 return _params.end();
88}
89
90
91void Function::makeInline()
92{
93 _flags |= FN_INLINE;
94}
95
96
97void Function::makeConst()
98{
99 _flags |= FN_CONST;
100}
101
102
103void Function::makePureVirtual()
104{
105 _flags |= FN_PURE_VIRTUAL;
106}
107
108
109void Function::makeFinal()
110{
111 _flags |= FN_FINAL;
112}
113
114
115void Function::makeOverride()
116{
117 _flags |= FN_OVERRIDE;
118}
119
120
121void Function::makeNoexcept()
122{
123 _flags |= FN_NOEXCEPT;
124}
125
126
127void Function::makeDefault()
128{
129 _flags |= FN_DEFAULT;
130}
131
132
133void Function::makeDelete()
134{
135 _flags |= FN_DELETE;
136}
137
138
139bool Function::isConstructor() const
140{
141 return name() == nameSpace()->name();
142}
143
144
145bool Function::isDestructor() const
146{
147 return name()[0] == '~';
148}
149
150
151bool Function::isMethod() const
152{
153 return !isConstructor() && !isDestructor() && nameSpace()->kind() == Symbol::SYM_STRUCT;
154}
155
156
157bool Function::isFunction() const
158{
159 return nameSpace()->kind() == Symbol::SYM_NAMESPACE;
160}
161
162
163int Function::countParameters() const
164{
165 return (int) _params.size();
166}
167
168
169Symbol::Kind Function::kind() const
170{
171 return Symbol::SYM_FUNCTION;
172}
173
174
175std::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
205bool 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
220Function* 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
242std::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