1
// This file is part of the AspectC++ compiler 'ac++'.
2
// Copyright (C) 1999-2003 The 'ac++' developers (see aspectc.org)
4
// This program is free software; you can redistribute it and/or
5
// modify it under the terms of the GNU General Public License as
6
// published by the Free Software Foundation; either version 2 of
7
// the License, or (at your option) any later version.
9
// This program is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
// GNU General Public License for more details.
14
// You should have received a copy of the GNU General Public
15
// License along with this program; if not, write to the Free
16
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20
#include "WeaverBase.h"
22
#include "LineDirectiveMgr.h"
25
#include "Puma/ErrorSink.h"
26
#include "Puma/CFunctionInfo.h"
27
#include "Puma/CArgumentInfo.h"
28
#include "Puma/CClassInfo.h"
29
#include "Puma/CTemplateInfo.h"
30
#include "Puma/CTemplateInstance.h"
31
#include "Puma/CTree.h"
32
#include "Puma/MacroUnit.h"
36
using std::stringstream;
42
const WeavePos &WeaverBase::weave_pos (Token *t, WeavePos::Pos p) {
44
// try to insert the position as a new one
45
pair<WPSet::iterator, bool> result = _positions.insert (WeavePos (t, p));
47
// the resulting iterator points either to the new or an existing entry
51
// insert the contents of a generated unit at a given position (with move)
52
void WeaverBase::paste (const WeavePos &pos, Unit *unit) {
53
// return immediately if the there is a problem with macro manipulation
54
if (macro_problem (pos))
57
_commander.addBuffer (unit);
58
Token *first = (Token*)unit->first ();
59
Token *last = (Token*)unit->last ();
60
if (pos._pos == WeavePos::WP_BEFORE) {
61
_commander.move_before (first, last, pos._token);
64
_commander.move (first, last, pos._token);
68
// insert a generated string a given position
69
void WeaverBase::paste (const WeavePos &pos, const string &str) {
70
// return immediately if the string to paste is empty
74
ACUnit *unit = new ACUnit (_err);
75
bool has_nl = (strstr (str.c_str (), "\n") != NULL);
77
_line_mgr.directive (*unit);
78
*unit << str.c_str ();
80
_line_mgr.directive (*unit, (Unit*)pos._token->belonging_to (), pos._token);
85
// replace the text between two positions with some new text
86
void WeaverBase::replace (const WeavePos &from, const WeavePos &to,
92
// replace the text of a syntax tree with some new text
93
void WeaverBase::replace (CTree *node, const string &str) {
94
const WeavePos &from = weave_pos (node->token (), WeavePos::WP_BEFORE);
95
const WeavePos &to = weave_pos (node->end_token (), WeavePos::WP_AFTER);
96
replace (from, to, str);
99
// copy the text between two position to another location
100
void WeaverBase::copy (const WeavePos &from, const WeavePos &to,
101
const WeavePos &dest) {
102
assert (from._pos == WeavePos::WP_BEFORE);
103
assert (to._pos == WeavePos::WP_AFTER);
104
if (macro_problem (from) || macro_problem (to) || macro_problem (dest))
107
if (dest._pos == WeavePos::WP_BEFORE) {
108
_line_mgr.insert ((Unit*)dest._token->belonging_to (), dest._token);
109
_commander.copy_before (from._token, to._token, dest._token);
110
_line_mgr.insert ((Unit*)dest._token->belonging_to (), dest._token);
113
_line_mgr.insert ((Unit*)dest._token->belonging_to (), dest._token, true);
114
_commander.copy (from._token, to._token, dest._token); }
115
_line_mgr.insert ((Unit*)dest._token->belonging_to (), dest._token, true);
118
// copy the text of a syntax tree to another location
119
void WeaverBase::copy (CTree *node, const WeavePos &dest) {
120
const WeavePos &from = weave_pos (node->token (), WeavePos::WP_BEFORE);
121
const WeavePos &to = weave_pos (node->end_token (), WeavePos::WP_AFTER);
122
copy (from, to, dest);
125
// kill the text between two positions
126
void WeaverBase::kill (const WeavePos &from, const WeavePos &to) {
127
// TODO: this should not matter, the code shoud be able to deal with it
128
assert (from._pos == WeavePos::WP_BEFORE);
129
assert (to._pos == WeavePos::WP_AFTER);
130
if (macro_problem (from) || macro_problem (to))
133
bool has_nl = (strstr (from._token->text ().c_str (), "\n") != NULL);
134
if (to._token && from._token != to._token || has_nl)
135
_line_mgr.insert ((Unit*)to._token->belonging_to (), to._token, true);
136
_commander.kill (from._token, to._token);
139
// kill the text of a syntax tree
140
void WeaverBase::kill (CTree *node) {
141
const WeavePos &from = weave_pos (node->token (), WeavePos::WP_BEFORE);
142
const WeavePos &to = weave_pos (node->end_token (), WeavePos::WP_AFTER);
146
bool WeaverBase::commit ()
148
ManipError terror = _commander.valid ();
150
_commander.commit ();
152
_err << terror << endMessage;
156
bool WeaverBase::macro_problem (const WeavePos &pos) {
157
Token *token = pos._token;
158
Unit *unit = (Unit*)token->belonging_to ();
160
if (unit->isMacroExp () &&
161
((pos._pos == WeavePos::WP_BEFORE &&
162
unit->isMacroExp () && !((MacroUnit*)unit)->ExpansionBegin (token)) ||
163
(pos._pos == WeavePos::WP_AFTER &&
164
unit->isMacroExp () && !((MacroUnit*)unit)->ExpansionEnd (token)))) {
165
_err << sev_warning << token->location ()
166
<< "transformation within macro '"
167
<< ((MacroUnit*)unit)->MacroBegin ()->text () << "'" << endMessage;
173
string WeaverBase::protection_string (CProtection::Type prot) {
175
case CProtection::PROT_PRIVATE: return "\nprivate:\n";
176
case CProtection::PROT_PROTECTED: return "\nprotected:\n";
177
case CProtection::PROT_PUBLIC: return "\npublic:\n";
184
bool WeaverBase::needs_this (CFunctionInfo *func)
186
// check if the called function is a method (needs a 'this' pointer)
187
if (func->isMethod () && !func->isStaticMethod ())
189
return !(func->isOperator () &&
190
(strcmp (func->Name (), "operator new") == 0 ||
191
strcmp (func->Name (), "operator new[]") == 0 ||
192
strcmp (func->Name (), "operator delete") == 0 ||
193
strcmp (func->Name (), "operator delete[]") == 0));
198
void WeaverBase::print_tree (ostream &out, CTree *node)
200
if (node->NodeName () == CT_Token::NodeId ())
201
out << node->token ()->text () << " ";
203
for (int s = 0; s < node->Sons (); s++)
204
print_tree (out, node->Son (s));
207
CClassInfo *WeaverBase::cscope(CObjectInfo *obj) {
208
CRecord *crec = obj->ClassScope ();
209
return crec ? crec->ClassInfo () : (CClassInfo*)0;
212
CScopeInfo *WeaverBase::nscope(CObjectInfo *obj) {
213
// template instances are stored in a special scope, better take the template
214
if (obj->TemplateInstance ())
215
obj = obj->TemplateInstance ()->Template ();
217
// functions that are only friend declarations of an assigned scope
218
CScopeInfo *assigned = obj->AssignedScope ();
220
return (assigned->GlobalScope () || assigned->isAnonymous ()) ? 0:assigned;
222
CRecord *crec = obj->ClassScope ();
223
CScopeInfo *qual = obj->QualifiedScope ();
224
CScopeInfo *scope = obj->Scope ();
225
return crec ? (CScopeInfo*)crec : (qual ? qual :
226
((scope->GlobalScope () || scope->isAnonymous ()) ? 0 : scope));
229
void WeaverBase::rename_args (CFunctionInfo *func, const char * new_name) {
230
// first rename the arguments in the argument list
231
for (unsigned arg = 0; arg < func->Arguments (); arg++)
232
rename (func->Argument (arg), new_name, arg);
234
// now rename the argument references in the constructor initialization list
235
if (func->isConstructor () && func->Tree ()) {
236
CTree *init = ((CT_FctDef*)func->Tree ())->CtorInit ();
238
for (unsigned arg = 0; arg < func->Arguments (); arg++)
239
rename_simple_name (func->Argument (arg), new_name, arg, init);
244
void WeaverBase::rename (CArgumentInfo *arg, const string &new_name, int app) {
245
// don't change anything with void arguments
246
if (arg->TypeInfo ()->is_void ())
249
// find the syntax tree node of the argument name
250
CT_ArgDecl *arg_decl = (CT_ArgDecl*)arg->Tree ();
251
CT_Declarator *declarator = (CT_Declarator*)arg_decl->Declarator ();
252
CT_SimpleName *arg_name = name (declarator);
254
// create the new name
256
name << " " << new_name;
257
if (app >= 0) // append an index to the name?
261
if (arg_name->NodeName () != CT_PrivateName::NodeId ()) {
262
replace (arg_name, name.str ());
265
// in the case of an anonymous argument I have to find an insert pos
266
CTree *left = 0, *right = 0;
268
if (declarator->NodeName () == CT_InitDeclarator::NodeId ())
269
right = ((CT_InitDeclarator*)declarator)->Initializer ();
270
else if (declarator->NodeName () == CT_BracedDeclarator::NodeId ())
271
right = declarator->Son (declarator->Sons () - 1);
272
else if (declarator->NodeName () == CT_ArrayDeclarator::NodeId ())
273
right = declarator->Son (1);
274
else if (declarator->NodeName () == CT_FctDeclarator::NodeId ())
275
right = declarator->Son (1);
276
else if (declarator->NodeName () == CT_RefDeclarator::NodeId ())
277
left = declarator->Son (0);
278
else if (declarator->NodeName () == CT_PtrDeclarator::NodeId ())
279
left = declarator->Son (declarator->Sons () - 2);
280
else if (declarator->NodeName () == CT_MembPtrDeclarator::NodeId ())
281
left = declarator->Son (declarator->Sons () - 2);
282
else if (declarator->NodeName () == CT_BitFieldDeclarator::NodeId ())
283
right = declarator->Son (1);
285
_err << sev_fatal << declarator->token ()->location ()
286
<< "unknown declarator type" << endMessage;
290
if (!left && !right) {
291
// no declarator + anonymous => there must be at least a decl spec seq!
292
left = arg_decl->DeclSpecs ();
295
const WeavePos &lp = weave_pos (left->end_token (), WeavePos::WP_AFTER);
296
paste (lp, name.str ());
299
const WeavePos &rp = weave_pos (right->token (), WeavePos::WP_BEFORE);
300
paste (rp, name.str ());
303
_err << sev_fatal << declarator->token ()->location ()
304
<< "found no hook to replace ananymous arg name" << endMessage;
308
void WeaverBase::rename_simple_name (CObjectInfo *renamed_obj,
309
const char *new_name, int app,
311
const char *nodename = node->NodeName ();
312
if (nodename == CT_SimpleName::NodeId ()) {
313
CObjectInfo *obj = ((CT_SimpleName*)node)->Object ();
314
if (obj == renamed_obj) {
315
// create a unit with the new name
316
ACUnit *name_unit = new ACUnit (_err);
317
_commander.addBuffer (name_unit);
318
*name_unit << new_name;
319
if (app >= 0) // append an index to the name?
323
// replace the token with the generated name
324
_commander.replace (node->token (), node->end_token (),
325
(Token*)name_unit->first (), (Token*)name_unit->last ());
329
for (int s = 0; s < node->Sons (); s++)
330
rename_simple_name (renamed_obj, new_name, app, node->Son (s));
333
CT_SimpleName *WeaverBase::is_name (CTree *node) {
334
if (node->NodeName () == CT_QualName::NodeId () ||
335
node->NodeName () == CT_SimpleName::NodeId () ||
336
node->NodeName () == CT_OperatorName::NodeId () ||
337
node->NodeName () == CT_ConversionName::NodeId () ||
338
node->NodeName () == CT_RootQualName::NodeId () ||
339
node->NodeName () == CT_PrivateName::NodeId ())
340
return (CT_SimpleName*)node;
342
return (CT_SimpleName*)0;
345
CT_FctDeclarator *WeaverBase::fct_declarator (CT_Declarator *declarator) {
347
CT_Declarator *next = (CT_Declarator*)declarator->Declarator ();
348
if (declarator->NodeName () == CT_FctDeclarator::NodeId () &&
350
return (CT_FctDeclarator*)declarator;
352
} while (!is_name (declarator));
353
return (CT_FctDeclarator*)0;
356
CT_SimpleName *WeaverBase::name (CT_Declarator *&declarator) {
357
CTree *node = declarator;
358
declarator = (CT_Declarator*)0;
359
while (!is_name (node)) {
360
declarator = (CT_Declarator*)node;
361
node = declarator->Declarator ();
364
return (CT_SimpleName*)node;
367
// return LinkageSpec node for extern "C" <decl> like declarations
368
CTree *WeaverBase::linkage_adjust (CT_Decl *decl) {
369
CT_LinkageSpec *linkage = decl->Linkage ();
370
return (!linkage || linkage->isList ()) ? decl : linkage;