OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [config/] [sh/] [symbian-cxx.c] - Blame information for rev 297

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 282 jeremybenn
/* Routines for C++ support for GCC for a Symbian OS targeted SH backend.
2
   Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
3
   Contributed by RedHat.
4
   Most of this code is stolen from i386/winnt.c.
5
 
6
   This file is part of GCC.
7
 
8
   GCC is free software; you can redistribute it and/or modify it
9
   under the terms of the GNU General Public License as published
10
   by the Free Software Foundation; either version 3, or (at your
11
   option) any later version.
12
 
13
   GCC is distributed in the hope that it will be useful, but WITHOUT
14
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16
   License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with GCC; see the file COPYING3.  If not see
20
   <http://www.gnu.org/licenses/>.  */
21
 
22
#include "config.h"
23
#include "system.h"
24
#include "coretypes.h"
25
#include "tm.h"
26
#include "rtl.h"
27
#include "output.h"
28
#include "flags.h"
29
#include "tree.h"
30
#include "expr.h"
31
#include "tm_p.h"
32
#include "cp/cp-tree.h" /* We need access to the OVL_... macros.  */
33
#include "toplev.h"
34
#include "sh-symbian.h"
35
 
36
 
37
/* Return the type that we should use to determine if DECL is
38
   imported or exported.  */
39
 
40
tree
41
sh_symbian_associated_type (tree decl)
42
{
43
  tree t = NULL_TREE;
44
 
45
  if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
46
  /* Methods now inherit their dllimport/dllexport attributes correctly
47
     so there is no need to check their class.  In fact it is wrong to
48
     check their class since a method can remain unexported from an
49
     exported class.  */
50
    return t;
51
 
52
  /* Otherwise we can just take the DECL_CONTEXT as normal.  */
53
  if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
54
    t = DECL_CONTEXT (decl);
55
 
56
  return t;
57
}
58
 
59
 
60
/* Return nonzero if DECL is a dllimport'd object.  */
61
 
62
bool
63
sh_symbian_is_dllimported (tree decl)
64
{
65
  tree imp;
66
 
67
  if (   TREE_CODE (decl) != VAR_DECL
68
      && TREE_CODE (decl) != FUNCTION_DECL)
69
    return false;
70
 
71
  imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
72
  if (imp)
73
    return true;
74
 
75
  /* Class members get the dllimport status of their class.  */
76
  imp = sh_symbian_associated_type (decl);
77
  if (! imp)
78
    return false;
79
 
80
  imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (imp));
81
  if (!imp)
82
    return false;
83
 
84
  /* Don't mark defined functions as dllimport.  If the definition itself
85
     was marked with dllimport, then sh_symbian_handle_dll_attribute reports
86
     an error. This handles the case when the definition overrides an
87
     earlier declaration.  */
88
  if (TREE_CODE (decl) ==  FUNCTION_DECL
89
      && DECL_INITIAL (decl)
90
      && ! DECL_DECLARED_INLINE_P (decl))
91
    {
92
      /* Don't warn about artificial methods.  */
93
      if (!DECL_ARTIFICIAL (decl))
94
        warning (OPT_Wattributes, "function %q+D is defined after prior "
95
                 "declaration as dllimport: attribute ignored",
96
                 decl);
97
      return false;
98
    }
99
 
100
  /* We ignore the dllimport attribute for inline member functions.
101
     This differs from MSVC behavior which treats it like GNUC
102
     'extern inline' extension.   */
103
  else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl))
104
    {
105
      if (extra_warnings)
106
        warning (OPT_Wattributes, "inline function %q+D is declared as "
107
                 "dllimport: attribute ignored",
108
                 decl);
109
      return false;
110
    }
111
 
112
  /*  Don't allow definitions of static data members in dllimport
113
      class.  Just ignore the attribute for vtable data.  */
114
  else if (TREE_CODE (decl) == VAR_DECL
115
           && TREE_STATIC (decl)
116
           && TREE_PUBLIC (decl)
117
           && !DECL_EXTERNAL (decl))
118
    {
119
      if (!DECL_VIRTUAL_P (decl))
120
        error ("definition of static data member %q+D of dllimport'd class",
121
               decl);
122
      return false;
123
    }
124
 
125
  /* Since we can't treat a pointer to a dllimport'd symbol as a
126
     constant address, we turn off the attribute on C++ virtual
127
     methods to allow creation of vtables using thunks.  Don't mark
128
     artificial methods either (in sh_symbian_associated_type, only
129
     COMDAT artificial method get import status from class context).  */
130
  else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
131
           && (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl)))
132
    return false;
133
 
134
  return true;
135
}
136
 
137
 
138
/* This code implements a specification for exporting the vtable and rtti of
139
   classes that have members with the dllexport or dllexport attributes.
140
   This specification is defined here:
141
 
142
     http://www.armdevzone.com/EABI/exported_class.txt
143
 
144
   Basically it says that a class's vtable and rtti should be exported if
145
   the following rules apply:
146
 
147
   - If it has any non-inline non-pure virtual functions,
148
     at least one of these need to be declared dllimport
149
     OR any of the constructors is declared dllimport.
150
 
151
   AND
152
 
153
   - The class has an inline constructor/destructor and
154
     a key-function (placement of vtable uniquely defined) that
155
     is defined in this translation unit.
156
 
157
   The specification also says that for classes which will have their
158
   vtables and rtti exported that their base class(es) might also need a
159
   similar exporting if:
160
 
161
   - Every base class needs to have its vtable & rtti exported
162
     as well, if the following the conditions hold true:
163
     + The base class has a non-inline declared non-pure virtual function
164
     + The base class is polymorphic (has or inherits any virtual functions)
165
       or the base class has any virtual base classes.  */
166
 
167
/* Decide if a base class of a class should
168
   also have its vtable and rtti exported.  */
169
 
170
static void
171
sh_symbian_possibly_export_base_class (tree base_class)
172
{
173
  VEC(tree,gc) *method_vec;
174
  int len;
175
 
176
  if (! (TYPE_CONTAINS_VPTR_P (base_class)))
177
    return;
178
 
179
  method_vec = CLASSTYPE_METHOD_VEC (base_class);
180
  len = method_vec ? VEC_length (tree, method_vec) : 0;
181
 
182
  for (;len --;)
183
    {
184
      tree member = VEC_index (tree, method_vec, len);
185
 
186
      if (! member)
187
        continue;
188
 
189
      for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
190
        {
191
          if (TREE_CODE (member) != FUNCTION_DECL)
192
            continue;
193
 
194
          if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
195
            continue;
196
 
197
          if (! DECL_VIRTUAL_P (member))
198
            continue;
199
 
200
          if (DECL_PURE_VIRTUAL_P (member))
201
            continue;
202
 
203
          if (DECL_DECLARED_INLINE_P (member))
204
            continue;
205
 
206
          break;
207
        }
208
 
209
      if (member)
210
        break;
211
    }
212
 
213
  if (len < 0)
214
    return;
215
 
216
  /* FIXME: According to the spec this base class should be exported, but
217
     a) how do we do this ? and
218
     b) it does not appear to be necessary for compliance with the Symbian
219
        OS which so far is the only consumer of this code.  */
220
#if SYMBIAN_DEBUG
221
  print_node_brief (stderr, "", base_class, 0);
222
  fprintf (stderr, " EXPORTed [base class of exported class]\n");
223
#endif
224
}
225
 
226
/* Add the named attribute to the given node.  Copes with both DECLs and
227
   TYPEs.  Will only add the attribute if it is not already present.  */
228
 
229
static void
230
sh_symbian_add_attribute (tree node, const char *attr_name)
231
{
232
  tree attrs;
233
  tree attr;
234
 
235
  attrs = DECL_P (node) ? DECL_ATTRIBUTES (node) : TYPE_ATTRIBUTES (node);
236
 
237
  if (lookup_attribute (attr_name, attrs) != NULL_TREE)
238
    return;
239
 
240
  attr = get_identifier (attr_name);
241
 
242
  if (DECL_P (node))
243
    DECL_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
244
  else
245
    TYPE_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);
246
 
247
#if SYMBIAN_DEBUG
248
  fprintf (stderr, "propagate %s attribute", attr_name);
249
  print_node_brief (stderr, " to", node, 0);
250
  fprintf (stderr, "\n");
251
#endif
252
}
253
 
254
/* Add the named attribute to a class and its vtable and rtti.  */
255
 
256
static void
257
sh_symbian_add_attribute_to_class_vtable_and_rtti (tree ctype, const char *attr_name)
258
{
259
  sh_symbian_add_attribute (ctype, attr_name);
260
 
261
  /* If the vtable exists then they need annotating as well.  */
262
  if (CLASSTYPE_VTABLES (ctype))
263
    /* XXX - Do we need to annotate any vtables other than the primary ?  */
264
    sh_symbian_add_attribute (CLASSTYPE_VTABLES (ctype), attr_name);
265
 
266
  /* If the rtti exists then it needs annotating as well.  */
267
  if (TYPE_MAIN_VARIANT (ctype)
268
      && CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))
269
    sh_symbian_add_attribute (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)),
270
                              attr_name);
271
}
272
 
273
/* Decide if a class needs to have an attribute because
274
   one of its member functions has the attribute.  */
275
 
276
static bool
277
sh_symbian_class_needs_attribute (tree ctype, const char *attribute_name)
278
{
279
  VEC(tree,gc) *method_vec;
280
 
281
  method_vec = CLASSTYPE_METHOD_VEC (ctype);
282
 
283
  /* If the key function has the attribute then the class needs it too.  */
284
  if (TYPE_POLYMORPHIC_P (ctype)
285
      && method_vec
286
      && tree_contains_struct [TREE_CODE (ctype), TS_DECL_COMMON] == 1
287
      && lookup_attribute (attribute_name,
288
                           DECL_ATTRIBUTES (VEC_index (tree, method_vec, 0))))
289
    return true;
290
 
291
  /* Check the class's member functions.  */
292
  if (TREE_CODE (ctype) == RECORD_TYPE)
293
    {
294
      unsigned int len;
295
 
296
      len = method_vec ? VEC_length (tree, method_vec) : 0;
297
 
298
      for (;len --;)
299
        {
300
          tree member = VEC_index (tree, method_vec, len);
301
 
302
          if (! member)
303
            continue;
304
 
305
          for (member = OVL_CURRENT (member);
306
               member;
307
               member = OVL_NEXT (member))
308
            {
309
              if (TREE_CODE (member) != FUNCTION_DECL)
310
                continue;
311
 
312
              if (DECL_PURE_VIRTUAL_P (member))
313
                continue;
314
 
315
              if (! DECL_VIRTUAL_P (member))
316
                continue;
317
 
318
              if (lookup_attribute (attribute_name, DECL_ATTRIBUTES (member)))
319
                {
320
#if SYMBIAN_DEBUG
321
                  print_node_brief (stderr, "", ctype, 0);
322
                  fprintf (stderr, " inherits %s because", attribute_name);
323
                  print_node_brief (stderr, "", member, 0);
324
                  fprintf (stderr, " has it.\n");
325
#endif
326
                  return true;
327
                }
328
            }
329
        }
330
    }
331
 
332
#if SYMBIAN_DEBUG
333
  print_node_brief (stderr, "", ctype, 0);
334
  fprintf (stderr, " does not inherit %s\n", attribute_name);
335
#endif
336
  return false;
337
}
338
 
339
/* Decide if a class needs its vtable and rtti exporting.  */
340
 
341
static bool
342
symbian_export_vtable_and_rtti_p (tree ctype)
343
{
344
  bool inline_ctor_dtor;
345
  bool dllimport_ctor_dtor;
346
  bool dllimport_member;
347
  tree binfo, base_binfo;
348
  VEC(tree,gc) *method_vec;
349
  tree key;
350
  int i;
351
  int len;
352
 
353
  /* Make sure that we are examining a class...  */
354
  if (TREE_CODE (ctype) != RECORD_TYPE)
355
    {
356
#if SYMBIAN_DEBUG
357
      print_node_brief (stderr, "", ctype, 0);
358
      fprintf (stderr, " does NOT need to be EXPORTed [not a class]\n");
359
#endif
360
      return false;
361
    }
362
 
363
  /* If the class does not have a key function it
364
     does not need to have its vtable exported.  */
365
  if ((key = CLASSTYPE_KEY_METHOD (ctype)) == NULL_TREE)
366
    {
367
#if SYMBIAN_DEBUG
368
      print_node_brief (stderr, "", ctype, 0);
369
      fprintf (stderr, " does NOT need to be EXPORTed [no key function]\n");
370
#endif
371
      return false;
372
    }
373
 
374
  /* If the key fn has not been defined
375
     then the class should not be exported.  */
376
  if (! TREE_ASM_WRITTEN (key))
377
    {
378
#if SYMBIAN_DEBUG
379
      print_node_brief (stderr, "", ctype, 0);
380
      fprintf (stderr, " does NOT need to be EXPORTed [key function not defined]\n");
381
#endif
382
      return false;
383
    }
384
 
385
  /* Check the class's member functions.  */
386
  inline_ctor_dtor = false;
387
  dllimport_ctor_dtor = false;
388
  dllimport_member = false;
389
 
390
  method_vec = CLASSTYPE_METHOD_VEC (ctype);
391
  len = method_vec ? VEC_length (tree, method_vec) : 0;
392
 
393
  for (;len --;)
394
    {
395
      tree member = VEC_index (tree, method_vec, len);
396
 
397
      if (! member)
398
        continue;
399
 
400
      for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
401
        {
402
          if (TREE_CODE (member) != FUNCTION_DECL)
403
            continue;
404
 
405
          if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
406
            {
407
              if (DECL_DECLARED_INLINE_P (member)
408
                  /* Ignore C++ backend created inline ctors/dtors.  */
409
                  && (   DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (member)
410
                      || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (member)))
411
                inline_ctor_dtor = true;
412
 
413
              if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
414
                dllimport_ctor_dtor = true;
415
            }
416
          else
417
            {
418
              if (DECL_PURE_VIRTUAL_P (member))
419
                continue;
420
 
421
              if (! DECL_VIRTUAL_P (member))
422
                continue;
423
 
424
              if (DECL_DECLARED_INLINE_P (member))
425
                continue;
426
 
427
              if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
428
                dllimport_member = true;
429
            }
430
        }
431
    }
432
 
433
  if (! dllimport_member && ! dllimport_ctor_dtor)
434
    {
435
#if SYMBIAN_DEBUG
436
      print_node_brief (stderr, "", ctype, 0);
437
      fprintf (stderr,
438
               " does NOT need to be EXPORTed [no non-pure virtuals or ctors/dtors with dllimport]\n");
439
#endif
440
      return false;
441
    }
442
 
443
  if (! inline_ctor_dtor)
444
    {
445
#if SYMBIAN_DEBUG
446
      print_node_brief (stderr, "", ctype, 0);
447
      fprintf (stderr,
448
               " does NOT need to be EXPORTed [no inline ctor/dtor]\n");
449
#endif
450
      return false;
451
    }
452
 
453
#if SYMBIAN_DEBUG
454
  print_node_brief (stderr, "", ctype, 0);
455
  fprintf (stderr, " DOES need to be EXPORTed\n");
456
#endif
457
 
458
  /* Now we must check and possibly export the base classes.  */
459
  for (i = 0, binfo = TYPE_BINFO (ctype);
460
       BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
461
    sh_symbian_possibly_export_base_class (BINFO_TYPE (base_binfo));
462
 
463
  return true;
464
}
465
 
466
/* Possibly override the decision to export class TYPE.  Upon entry
467
   IMPORT_EXPORT will contain 1 if the class is going to be exported,
468
   -1 if it is going to be imported and 0 otherwise.  This function
469
   should return the modified value and perform any other actions
470
   necessary to support the backend's targeted operating system.  */
471
 
472
int
473
sh_symbian_import_export_class (tree ctype, int import_export)
474
{
475
  const char *attr_name = NULL;
476
 
477
  /* If we are exporting the class but it does not have the dllexport
478
     attribute then we may need to add it.  Similarly imported classes
479
     may need the dllimport attribute.  */
480
  switch (import_export)
481
    {
482
    case  1: attr_name = "dllexport"; break;
483
    case -1: attr_name = "dllimport"; break;
484
    default: break;
485
    }
486
 
487
  if (attr_name
488
      && ! lookup_attribute (attr_name, TYPE_ATTRIBUTES (ctype)))
489
    {
490
      if (sh_symbian_class_needs_attribute (ctype, attr_name))
491
        sh_symbian_add_attribute_to_class_vtable_and_rtti (ctype, attr_name);
492
 
493
      /* Classes can be forced to export their
494
         vtable and rtti under certain conditions.  */
495
      if (symbian_export_vtable_and_rtti_p (ctype))
496
        {
497
          sh_symbian_add_attribute_to_class_vtable_and_rtti (ctype, "dllexport");
498
 
499
          /* Make sure that the class and its vtable are exported.  */
500
          import_export = 1;
501
 
502
          if (CLASSTYPE_VTABLES (ctype))
503
            DECL_EXTERNAL (CLASSTYPE_VTABLES (ctype)) = 1;
504
 
505
          /* Check to make sure that if the class has a key method that
506
             it is now on the list of keyed classes.  That way its vtable
507
             will be emitted.  */
508
          if (CLASSTYPE_KEY_METHOD (ctype))
509
            {
510
              tree class;
511
 
512
              for (class = keyed_classes; class; class = TREE_CHAIN (class))
513
                if (class == ctype)
514
                  break;
515
 
516
              if (class == NULL_TREE)
517
                {
518
#if SYMBIAN_DEBUG
519
                  print_node_brief (stderr, "Add node", ctype, 0);
520
                  fprintf (stderr, " to the keyed classes list\n");
521
#endif
522
                  keyed_classes = tree_cons (NULL_TREE, ctype, keyed_classes);
523
                }
524
            }
525
 
526
          /* Make sure that the typeinfo will be emitted as well.  */
527
          if (CLASS_TYPE_P (ctype))
528
            TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))) = 1;
529
        }
530
    }
531
 
532
  return import_export;
533
}
534
 
535
/* Handle a "dllimport" or "dllexport" attribute;
536
   arguments as in struct attribute_spec.handler.  */
537
 
538
tree
539
sh_symbian_handle_dll_attribute (tree *pnode, tree name, tree args,
540
                                 int flags, bool *no_add_attrs)
541
{
542
  tree thunk;
543
  tree node = *pnode;
544
  const char *attr = IDENTIFIER_POINTER (name);
545
 
546
  /* These attributes may apply to structure and union types being
547
     created, but otherwise should pass to the declaration involved.  */
548
  if (!DECL_P (node))
549
    {
550
      if (flags & ((int) ATTR_FLAG_DECL_NEXT
551
                   | (int) ATTR_FLAG_FUNCTION_NEXT
552
                   | (int) ATTR_FLAG_ARRAY_NEXT))
553
        {
554
          warning (OPT_Wattributes, "%qs attribute ignored", attr);
555
          *no_add_attrs = true;
556
          return tree_cons (name, args, NULL_TREE);
557
        }
558
 
559
      if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
560
        {
561
          warning (OPT_Wattributes, "%qs attribute ignored", attr);
562
          *no_add_attrs = true;
563
        }
564
 
565
      return NULL_TREE;
566
    }
567
 
568
  /* Report error on dllimport ambiguities
569
     seen now before they cause any damage.  */
570
  else if (is_attribute_p ("dllimport", name))
571
    {
572
      if (TREE_CODE (node) == VAR_DECL)
573
        {
574
          if (DECL_INITIAL (node))
575
            {
576
              error ("variable %q+D definition is marked dllimport",
577
                     node);
578
              *no_add_attrs = true;
579
            }
580
 
581
          /* `extern' needn't be specified with dllimport.
582
             Specify `extern' now and hope for the best.  Sigh.  */
583
          DECL_EXTERNAL (node) = 1;
584
          /* Also, implicitly give dllimport'd variables declared within
585
             a function global scope, unless declared static.  */
586
          if (current_function_decl != NULL_TREE && ! TREE_STATIC (node))
587
            TREE_PUBLIC (node) = 1;
588
        }
589
    }
590
 
591
  /* If the node is an overloaded constructor or destructor, then we must
592
     make sure that the attribute is propagated along the overload chain,
593
     as it is these overloaded functions which will be emitted, rather than
594
     the user declared constructor itself.  */
595
  if (TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE
596
      && (DECL_CONSTRUCTOR_P (node) || DECL_DESTRUCTOR_P (node)))
597
    {
598
      tree overload;
599
 
600
      for (overload = OVL_CHAIN (node); overload; overload = OVL_CHAIN (overload))
601
        {
602
          tree node_args;
603
          tree func_args;
604
          tree function = OVL_CURRENT (overload);
605
 
606
          if (! function
607
              || ! DECL_P (function)
608
              || (DECL_CONSTRUCTOR_P (node) && ! DECL_CONSTRUCTOR_P (function))
609
              || (DECL_DESTRUCTOR_P (node)  && ! DECL_DESTRUCTOR_P (function)))
610
            continue;
611
 
612
          /* The arguments must match as well.  */
613
          for (node_args = DECL_ARGUMENTS (node), func_args = DECL_ARGUMENTS (function);
614
               node_args && func_args;
615
               node_args = TREE_CHAIN (node_args), func_args = TREE_CHAIN (func_args))
616
            if (TREE_TYPE (node_args) != TREE_TYPE (func_args))
617
              break;
618
 
619
          if (node_args || func_args)
620
            {
621
              /* We can ignore an extraneous __in_chrg arguments in the node.
622
                 GCC generated destructors, for example, will have this.  */
623
              if ((node_args == NULL_TREE
624
                   || func_args != NULL_TREE)
625
                  && strcmp (IDENTIFIER_POINTER (DECL_NAME (node)), "__in_chrg") != 0)
626
                continue;
627
            }
628
 
629
          sh_symbian_add_attribute (function, attr);
630
 
631
          /* Propagate the attribute to any function thunks as well.  */
632
          for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
633
            if (TREE_CODE (thunk) == FUNCTION_DECL)
634
              sh_symbian_add_attribute (thunk, attr);
635
        }
636
    }
637
 
638
  if (TREE_CODE (node) == FUNCTION_DECL && DECL_VIRTUAL_P (node))
639
    {
640
      /* Propagate the attribute to any thunks of this function.  */
641
      for (thunk = DECL_THUNKS (node); thunk; thunk = TREE_CHAIN (thunk))
642
        if (TREE_CODE (thunk) == FUNCTION_DECL)
643
          sh_symbian_add_attribute (thunk, attr);
644
    }
645
 
646
  /*  Report error if symbol is not accessible at global scope.  */
647
  if (!TREE_PUBLIC (node)
648
      && (   TREE_CODE (node) == VAR_DECL
649
          || TREE_CODE (node) == FUNCTION_DECL))
650
    {
651
      error ("external linkage required for symbol %q+D because of %qE attribute",
652
             node, name);
653
      *no_add_attrs = true;
654
    }
655
 
656
#if SYMBIAN_DEBUG
657
  print_node_brief (stderr, "mark node", node, 0);
658
  fprintf (stderr, " as %s\n", attr);
659
#endif
660
 
661
  return NULL_TREE;
662
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.