01f4d8de2990ac2849440e7fe06bd3507f2c9c2d
[platform/upstream/doxygen.git] / src / memberdef.cpp
1 /******************************************************************************
2  *
3  * Copyright (C) 1997-2015 by Dimitri van Heesch.
4  *
5  * Permission to use, copy, modify, and distribute this software and its
6  * documentation under the terms of the GNU General Public License is hereby
7  * granted. No representations are made about the suitability of this software
8  * for any purpose. It is provided "as is" without express or implied warranty.
9  * See the GNU General Public License for more details.
10  *
11  * Documents produced by Doxygen are derivative works derived from the
12  * input used in their production; they are not affected by this license.
13  *
14  */
15
16 #include <stdio.h>
17 #include <qglobal.h>
18 #include <qregexp.h>
19 #include <assert.h>
20 #include "md5.h"
21 #include "memberdef.h"
22 #include "membername.h"
23 #include "doxygen.h"
24 #include "util.h"
25 #include "code.h"
26 #include "message.h"
27 #include "htmlhelp.h"
28 #include "language.h"
29 #include "outputlist.h"
30 #include "example.h"
31 #include "membergroup.h"
32 #include "groupdef.h"
33 #include "defargs.h"
34 #include "docparser.h"
35 #include "dot.h"
36 #include "searchindex.h"
37 #include "parserintf.h"
38 #include "marshal.h"
39 #include "objcache.h"
40
41 #include "vhdldocgen.h"
42 #include "arguments.h"
43 #include "memberlist.h"
44 #include "namespacedef.h"
45 #include "filedef.h"
46 #include "config.h"
47
48 //-----------------------------------------------------------------------------
49
50 int MemberDef::s_indentLevel = 0;
51
52 //-----------------------------------------------------------------------------
53
54 static QCString addTemplateNames(const QCString &s,const QCString &n,const QCString &t)
55 {
56   QCString result;
57   QCString clRealName=n;
58   int p=0,i;
59   if ((i=clRealName.find('<'))!=-1)
60   {
61     clRealName=clRealName.left(i); // strip template specialization
62   }
63   if ((i=clRealName.findRev("::"))!=-1)
64   {
65     clRealName=clRealName.right(clRealName.length()-i-2);
66   }
67   while ((i=s.find(clRealName,p))!=-1)
68   {
69     result+=s.mid(p,i-p);
70     uint j=clRealName.length()+i;
71     if (s.length()==j || (s.at(j)!='<' && !isId(s.at(j))))
72     { // add template names
73       //printf("Adding %s+%s\n",clRealName.data(),t.data());
74       result+=clRealName+t;
75     }
76     else
77     { // template names already present
78       //printf("Adding %s\n",clRealName.data());
79       result+=clRealName;
80     }
81     p=i+clRealName.length();
82   }
83   result+=s.right(s.length()-p);
84   //printf("addTemplateNames(%s,%s,%s)=%s\n",s.data(),n.data(),t.data(),result.data());
85   return result;
86 }
87
88 // ol.startMemberDocName has already been done before this is called.
89 // when this function returns TRUE, ol.endParameterList will be called.
90 //
91 // typical sequence:
92 //   ol.startMemberDoc
93 //   ol.startMemberDocName
94 //   --- enter writeDefArgumentList
95 //   ol.endMemberDocName
96 //   ol.startParameterList
97 //     ...
98 //     ol.startParameterType(first=TRUE)
99 //     ol.endParameterType
100 //     ol.startParameterName
101 //     ol.endParameterName(last==FALSE)
102 //     ...
103 //     ol.startParameterType(first=FALSE)
104 //     ol.endParamtereType
105 //     ol.startParameterName
106 //     ol.endParameterName(last==TRUE)
107 //     ...
108 //   --- leave writeDefArgumentList with return value TRUE
109 //   ol.endParameterList
110 //   ol.endMemberDoc(hasArgs=TRUE)
111 //
112 //  For an empty list the function should return FALSE, the sequence is
113 //   ol.startMemberDoc
114 //   ol.startMemberDocName
115 //   --- enter writeDefArgumentList
116 //   --- leave writeDefArgumentList with return value FALSE
117 //   ol.endMemberDocName
118 //   ol.endMemberDoc(hasArgs=FALSE);
119 //
120
121 static bool writeDefArgumentList(OutputList &ol,Definition *scope,MemberDef *md)
122 {
123   ArgumentList *defArgList=(md->isDocsForDefinition()) ?
124                              md->argumentList() : md->declArgumentList();
125   //printf("writeDefArgumentList `%s' isDocsForDefinition()=%d\n",md->name().data(),md->isDocsForDefinition());
126   if (defArgList==0 || md->isProperty())
127   {
128     return FALSE; // member has no function like argument list
129   }
130
131   // simple argument list for tcl
132   if (md->getLanguage()==SrcLangExt_Tcl)
133   {
134     if (defArgList->count()==0) return FALSE;
135     ArgumentListIterator ali(*defArgList);
136     Argument *a;
137     ol.endMemberDocName();
138     ol.startParameterList(FALSE);
139     ol.startParameterType(TRUE,0);
140     ol.endParameterType();
141     ol.startParameterName(FALSE);
142     for (;(a=ali.current());++ali)
143     {
144       if (a->defval.isEmpty())
145       {
146         ol.docify(a->name+" ");
147       }
148       else
149       {
150         ol.docify("?"+a->name+"? ");
151       }
152     }
153     ol.endParameterName(TRUE,FALSE,FALSE);
154     return TRUE;
155   }
156
157   if (!md->isDefine()) ol.docify(" ");
158
159   //printf("writeDefArgList(%d)\n",defArgList->count());
160   ol.pushGeneratorState();
161   //ol.disableAllBut(OutputGenerator::Html);
162   bool htmlOn  = ol.isEnabled(OutputGenerator::Html);
163   bool latexOn = ol.isEnabled(OutputGenerator::Latex);
164   {
165     // html and latex
166     if (htmlOn)  ol.enable(OutputGenerator::Html);
167     if (latexOn) ol.enable(OutputGenerator::Latex);
168
169     ol.endMemberDocName();
170     ol.startParameterList(!md->isObjCMethod());
171   }
172   ol.enableAll();
173   ol.disable(OutputGenerator::Html);
174   ol.disable(OutputGenerator::Latex);
175   {
176     // other formats
177     if (!md->isObjCMethod()) ol.docify("("); // start argument list
178     ol.endMemberDocName();
179   }
180   ol.popGeneratorState();
181   //printf("===> name=%s isDefine=%d\n",md->name().data(),md->isDefine());
182
183   QCString cName;
184   if (scope)
185   {
186     cName=scope->name();
187     int il=cName.find('<');
188     int ir=cName.findRev('>');
189     if (il!=-1 && ir!=-1 && ir>il)
190     {
191       cName=cName.mid(il,ir-il+1);
192       //printf("1. cName=%s\n",cName.data());
193     }
194     else if (scope->definitionType()==Definition::TypeClass && ((ClassDef*)scope)->templateArguments())
195     {
196       cName=tempArgListToString(((ClassDef*)scope)->templateArguments(),scope->getLanguage());
197       //printf("2. cName=%s\n",cName.data());
198     }
199     else // no template specifier
200     {
201       cName.resize(0);
202     }
203   }
204   //printf("~~~ %s cName=%s\n",md->name().data(),cName.data());
205
206   bool first=TRUE;
207   bool paramTypeStarted=FALSE;
208   bool isDefine = md->isDefine();
209   ArgumentListIterator ali(*defArgList);
210   Argument *a=ali.current();
211   while (a)
212   {
213     if (isDefine || first)
214     {
215       ol.startParameterType(first,0);
216       paramTypeStarted=TRUE;
217       if (isDefine)
218       {
219         ol.endParameterType();
220         ol.startParameterName(TRUE);
221       }
222     }
223     QRegExp re(")("),res("(.*\\*");
224     int vp=a->type.find(re);
225     int wp=a->type.find(res);
226
227     // use the following to put the function pointer type before the name
228     bool hasFuncPtrType=FALSE;
229
230     if (!a->attrib.isEmpty() && !md->isObjCMethod()) // argument has an IDL attribute
231     {
232       ol.docify(a->attrib+" ");
233     }
234     if (hasFuncPtrType) // argument type is a function pointer
235     {
236       //printf("a->type=`%s' a->name=`%s'\n",a->type.data(),a->name.data());
237       QCString n=a->type.left(vp);
238       if (hasFuncPtrType) n=a->type.left(wp);
239       if (md->isObjCMethod()) { n.prepend("("); n.append(")"); }
240       if (!cName.isEmpty()) n=addTemplateNames(n,scope->name(),cName);
241       linkifyText(TextGeneratorOLImpl(ol),scope,md->getBodyDef(),md,n);
242     }
243     else // non-function pointer type
244     {
245       QCString n=a->type;
246       if (md->isObjCMethod()) { n.prepend("("); n.append(")"); }
247       if (a->type!="...")
248       {
249         if (!cName.isEmpty()) n=addTemplateNames(n,scope->name(),cName);
250         linkifyText(TextGeneratorOLImpl(ol),scope,md->getBodyDef(),md,n);
251       }
252     }
253     if (!isDefine)
254     {
255       if (paramTypeStarted)
256       {
257         ol.endParameterType();
258         paramTypeStarted=FALSE;
259       }
260       ol.startParameterName(defArgList->count()<2);
261     }
262     if (hasFuncPtrType)
263     {
264       ol.docify(a->type.mid(wp,vp-wp));
265     }
266     if (!a->name.isEmpty() || a->type=="...") // argument has a name
267     {
268       //if (!hasFuncPtrType)
269       //{
270       //  ol.docify(" ");
271       //}
272       ol.disable(OutputGenerator::Latex);
273       ol.disable(OutputGenerator::Html);
274       ol.docify(" "); /* man page */
275       if (htmlOn) ol.enable(OutputGenerator::Html);
276       ol.disable(OutputGenerator::Man);
277       ol.startEmphasis();
278       ol.enable(OutputGenerator::Man);
279       if (latexOn) ol.enable(OutputGenerator::Latex);
280       if (a->name.isEmpty()) ol.docify(a->type); else ol.docify(a->name);
281       ol.disable(OutputGenerator::Man);
282       ol.disable(OutputGenerator::Latex);
283       ol.endEmphasis();
284       ol.enable(OutputGenerator::Man);
285       if (latexOn) ol.enable(OutputGenerator::Latex);
286     }
287     if (!a->array.isEmpty())
288     {
289       ol.docify(a->array);
290     }
291     if (hasFuncPtrType) // write the part of the argument type
292                         // that comes after the name
293     {
294       linkifyText(TextGeneratorOLImpl(ol),scope,md->getBodyDef(),
295                   md,a->type.right(a->type.length()-vp));
296     }
297     if (!a->defval.isEmpty()) // write the default value
298     {
299       QCString n=a->defval;
300       if (!cName.isEmpty()) n=addTemplateNames(n,scope->name(),cName);
301       ol.docify(" = ");
302
303       ol.startTypewriter();
304       linkifyText(TextGeneratorOLImpl(ol),scope,md->getBodyDef(),md,n,FALSE,TRUE,TRUE);
305       ol.endTypewriter();
306
307     }
308     ++ali;
309     a=ali.current();
310     if (a)
311     {
312       if (!md->isObjCMethod()) ol.docify(", "); // there are more arguments
313       if (!isDefine)
314       {
315         QCString key;
316         if (md->isObjCMethod() && a->attrib.length()>=2)
317         {
318           //printf("Found parameter keyword %s\n",a->attrib.data());
319           // strip [ and ]
320           key=a->attrib.mid(1,a->attrib.length()-2);
321           if (key!=",") key+=":"; // for normal keywords add colon
322         }
323         ol.endParameterName(FALSE,FALSE,!md->isObjCMethod());
324         if (paramTypeStarted)
325         {
326           ol.endParameterType();
327         }
328         ol.startParameterType(FALSE,key);
329         paramTypeStarted=TRUE;
330       }
331       else // isDefine
332       {
333         ol.endParameterName(FALSE,FALSE,TRUE);
334       }
335     }
336     first=FALSE;
337   }
338   ol.pushGeneratorState();
339   ol.disable(OutputGenerator::Html);
340   ol.disable(OutputGenerator::Latex);
341   if (!md->isObjCMethod()) ol.docify(")"); // end argument list
342   ol.enableAll();
343   if (htmlOn) ol.enable(OutputGenerator::Html);
344   if (latexOn) ol.enable(OutputGenerator::Latex);
345   if (first) ol.startParameterName(defArgList->count()<2);
346   ol.endParameterName(TRUE,defArgList->count()<2,!md->isObjCMethod());
347   ol.popGeneratorState();
348   if (md->extraTypeChars())
349   {
350     ol.docify(md->extraTypeChars());
351   }
352   if (defArgList->constSpecifier)
353   {
354     ol.docify(" const");
355   }
356   if (defArgList->volatileSpecifier)
357   {
358     ol.docify(" volatile");
359   }
360   if (defArgList->refQualifier==RefQualifierLValue)
361   {
362     ol.docify(" &");
363   }
364   else if (defArgList->refQualifier==RefQualifierRValue)
365   {
366     ol.docify(" &&");
367   }
368   if (!defArgList->trailingReturnType.isEmpty())
369   {
370     linkifyText(TextGeneratorOLImpl(ol), // out
371                 scope,                   // scope
372                 md->getBodyDef(),        // fileScope
373                 md,                      // self
374                 defArgList->trailingReturnType, // text
375                 FALSE                    // autoBreak
376                );
377
378   }
379   return TRUE;
380 }
381
382 static void writeExceptionListImpl(
383         OutputList &ol, ClassDef *cd, MemberDef *md, QCString const& exception)
384 {
385   // this is ordinary exception spec - there must be a '('
386   //printf("exception='%s'\n",exception.data());
387   int index = exception.find('(');
388   if (index!=-1)
389   {
390     ol.exceptionEntry(exception.left(index),false);
391     ++index; // paren in second column so skip it here
392     for (int comma = exception.find(',', index); comma!=-1; )
393     {
394       ++comma; // include comma
395       linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),md,
396                   exception.mid(index,comma-index));
397       ol.exceptionEntry(0,false);
398       index=comma;
399       comma = exception.find(',', index);
400     }
401     int close = exception.find(')', index);
402     if (close!=-1)
403     {
404       QCString type=removeRedundantWhiteSpace(exception.mid(index,close-index));
405       linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),md,type);
406       ol.exceptionEntry(0,true);
407     }
408     else
409     {
410       warn(md->getDefFileName(),md->getDefLine(),
411           "missing ) in exception list on member %s",qPrint(md->name()));
412     }
413   }
414   else // Java Exception
415   {
416     ol.docify(" ");
417     linkifyText(TextGeneratorOLImpl(ol),cd,md->getBodyDef(),md,exception);
418   }
419 }
420
421 static void writeExceptionList(OutputList &ol, ClassDef *cd, MemberDef *md)
422 {
423   QCString exception(QCString(md->excpString()).stripWhiteSpace());
424   if ('{'==exception.at(0))
425   {
426     // this is an UNO IDL attribute - need special handling
427     int index = exception.find(';');
428     int oldIndex = 1;
429     while (-1 != index) // there should be no more than 2 (set / get)
430     {
431       // omit '{' and ';' -> "set raises (...)"
432       writeExceptionListImpl(ol,cd,md,exception.mid(oldIndex,index-oldIndex));
433       oldIndex=index+1;
434       index = exception.find(';',oldIndex);
435     }
436     // the rest is now just '}' - omit that
437   }
438   else
439   {
440     writeExceptionListImpl(ol,cd,md,exception);
441   }
442 }
443
444 static void writeTemplatePrefix(OutputList &ol,ArgumentList *al)
445 {
446   ol.docify("template<");
447   ArgumentListIterator ali(*al);
448   Argument *a = ali.current();
449   while (a)
450   {
451     ol.docify(a->type);
452     ol.docify(" ");
453     ol.docify(a->name);
454     if (a->defval.length()!=0)
455     {
456       ol.docify(" = ");
457       ol.docify(a->defval);
458     }
459     ++ali;
460     a=ali.current();
461     if (a) ol.docify(", ");
462   }
463   ol.docify("> ");
464 }
465
466 //-----------------------------------------------------------------------------
467 //-----------------------------------------------------------------------------
468 //-----------------------------------------------------------------------------
469
470 class MemberDefImpl
471 {
472   public:
473     MemberDefImpl();
474    ~MemberDefImpl();
475     void init(Definition *def,const char *t,const char *a,const char *e,
476               Protection p,Specifier v,bool s,Relationship r,
477               MemberType mt,const ArgumentList *tal,
478               const ArgumentList *al
479              );
480
481     ClassDef     *classDef;   // member of or related to
482     FileDef      *fileDef;    // member of file definition
483     NamespaceDef *nspace;     // the namespace this member is in.
484
485     MemberDef  *enumScope;    // the enclosing scope, if this is an enum field
486     bool        livesInsideEnum;
487     MemberDef  *annEnumType;  // the anonymous enum that is the type of this member
488     MemberList *enumFields;   // enumeration fields
489
490     MemberDef  *redefines;    // the members that this member redefines
491     MemberList *redefinedBy;  // the list of members that redefine this one
492
493     MemberDef  *memDef;       // member definition for this declaration
494     MemberDef  *memDec;       // member declaration for this definition
495     ClassDef   *relatedAlso;  // points to class marked by relatedAlso
496
497     ExampleSDict *exampleSDict; // a dictionary of all examples for quick access
498
499     QCString type;            // return actual type
500     QCString accessorType;    // return type that tell how to get to this member
501     ClassDef *accessorClass;  // class that this member accesses (for anonymous types)
502     QCString args;            // function arguments/variable array specifiers
503     QCString def;             // member definition in code (fully qualified name)
504     QCString anc;             // HTML anchor name
505     Specifier virt;           // normal/virtual/pure virtual
506     Protection prot;          // protection type [Public/Protected/Private]
507     QCString decl;            // member declaration in class
508
509     QCString bitfields;       // struct member bitfields
510     QCString read;            // property read accessor
511     QCString write;           // property write accessor
512     QCString exception;       // exceptions that can be thrown
513     QCString initializer;     // initializer
514     QCString extraTypeChars;  // extra type info found after the argument list
515     QCString enumBaseType;    // base type of the enum (C++11)
516     int initLines;            // number of lines in the initializer
517
518     uint64  memSpec;          // The specifiers present for this member
519     MemberType mtype;         // returns the kind of member
520     int maxInitLines;         // when the initializer will be displayed
521     int userInitLines;        // result of explicit \hideinitializer or \showinitializer
522     MemberDef  *annMemb;
523
524     ArgumentList *defArgList;    // argument list of this member definition
525     ArgumentList *declArgList;   // argument list of this member declaration
526
527     ArgumentList *tArgList;      // template argument list of function template
528     ArgumentList *typeConstraints; // type constraints for template parameters
529     MemberDef *templateMaster;
530     QList<ArgumentList> *defTmpArgLists; // lists of template argument lists
531                                          // (for template functions in nested template classes)
532
533     ClassDef *cachedAnonymousType; // if the member has an anonymous compound
534                                    // as its type then this is computed by
535                                    // getClassDefOfAnonymousType() and
536                                    // cached here.
537     SDict<MemberList> *classSectionSDict; // not accessible
538
539     MemberDef *groupAlias;    // Member containing the definition
540     int grpId;                // group id
541     MemberGroup *memberGroup; // group's member definition
542     GroupDef *group;          // group in which this member is in
543     Grouping::GroupPri_t grouppri; // priority of this definition
544     QCString groupFileName;   // file where this grouping was defined
545     int groupStartLine;       // line  "      "      "     "     "
546     MemberDef *groupMember;
547
548     bool isTypedefValCached;
549     ClassDef *cachedTypedefValue;
550     QCString cachedTypedefTemplSpec;
551     QCString cachedResolvedType;
552
553     // inbody documentation
554     //int inbodyLine;
555     //QCString inbodyFile;
556     //QCString inbodyDocs;
557
558     // documentation inheritance
559     MemberDef *docProvider;
560
561     // to store the output file base from tag files
562     QCString explicitOutputFileBase;
563
564     // objective-c
565     bool implOnly; // function found in implementation but not
566                      // in the interface
567     bool hasDocumentedParams;
568     bool hasDocumentedReturnType;
569     bool isDMember;
570     Relationship related;     // relationship of this to the class
571     bool stat;                // is it a static function?
572     bool proto;               // is it a prototype;
573     bool docEnumValues;       // is an enum with documented enum values.
574     bool annScope;            // member is part of an annoymous scope
575     bool annUsed;
576     bool hasCallGraph;
577     bool hasCallerGraph;
578     bool explExt;             // member was explicitly declared external
579     bool tspec;               // member is a template specialization
580     bool groupHasDocs;        // true if the entry that caused the grouping was documented
581     bool docsForDefinition;   // TRUE => documentation block is put before
582                               //         definition.
583                               // FALSE => block is put before declaration.
584     ClassDef *category;
585     MemberDef *categoryRelation;
586 };
587
588 MemberDefImpl::MemberDefImpl() :
589     enumFields(0),
590     redefinedBy(0),
591     exampleSDict(0),
592     defArgList(0),
593     declArgList(0),
594     tArgList(0),
595     typeConstraints(0),
596     defTmpArgLists(0),
597     classSectionSDict(0),
598     category(0),
599     categoryRelation(0)
600 {
601 }
602
603 MemberDefImpl::~MemberDefImpl()
604 {
605   delete redefinedBy;
606   delete exampleSDict;
607   delete enumFields;
608   delete defArgList;
609   delete tArgList;
610   delete typeConstraints;
611   delete defTmpArgLists;
612   delete classSectionSDict;
613   delete declArgList;
614 }
615
616 void MemberDefImpl::init(Definition *def,
617                      const char *t,const char *a,const char *e,
618                      Protection p,Specifier v,bool s,Relationship r,
619                      MemberType mt,const ArgumentList *tal,
620                      const ArgumentList *al
621                     )
622 {
623   classDef=0;
624   fileDef=0;
625   redefines=0;
626   relatedAlso=0;
627   redefinedBy=0;
628   accessorClass=0;
629   nspace=0;
630   memDef=0;
631   memDec=0;
632   group=0;
633   grpId=-1;
634   exampleSDict=0;
635   enumFields=0;
636   enumScope=0;
637   livesInsideEnum=FALSE;
638   defTmpArgLists=0;
639   hasCallGraph = FALSE;
640   hasCallerGraph = FALSE;
641   initLines=0;
642   type=t;
643   if (mt==MemberType_Typedef) type.stripPrefix("typedef ");
644   //  type.stripPrefix("struct ");
645   //  type.stripPrefix("class " );
646   //  type.stripPrefix("union " );
647   type=removeRedundantWhiteSpace(type);
648   args=a;
649   args=removeRedundantWhiteSpace(args);
650   if (type.isEmpty()) decl=def->name()+args; else decl=type+" "+def->name()+args;
651
652   memberGroup=0;
653   virt=v;
654   prot=p;
655   related=r;
656   stat=s;
657   mtype=mt;
658   exception=e;
659   proto=FALSE;
660   annScope=FALSE;
661   memSpec=0;
662   annMemb=0;
663   annUsed=FALSE;
664   annEnumType=0;
665   groupAlias=0;
666   explExt=FALSE;
667   tspec=FALSE;
668   cachedAnonymousType=0;
669   maxInitLines=Config_getInt(MAX_INITIALIZER_LINES);
670   userInitLines=-1;
671   docEnumValues=FALSE;
672   // copy function template arguments (if any)
673   if (tal)
674   {
675     tArgList = tal->deepCopy();
676   }
677   else
678   {
679     tArgList=0;
680   }
681   //printf("new member al=%p\n",al);
682   // copy function definition arguments (if any)
683   if (al)
684   {
685     defArgList = al->deepCopy();
686   }
687   else
688   {
689     defArgList=0;
690   }
691   // convert function declaration arguments (if any)
692   if (!args.isEmpty())
693   {
694     declArgList = new ArgumentList;
695     stringToArgumentList(args,declArgList,&extraTypeChars);
696     //printf("setDeclArgList %s to %s const=%d\n",args.data(),
697     //    argListToString(declArgList).data(),declArgList->constSpecifier);
698   }
699   else
700   {
701     declArgList = 0;
702   }
703   templateMaster = 0;
704   classSectionSDict = 0;
705   docsForDefinition = TRUE;
706   isTypedefValCached = FALSE;
707   cachedTypedefValue = 0;
708   //inbodyLine = -1;
709   implOnly=FALSE;
710   groupMember = 0;
711   hasDocumentedParams = FALSE;
712   hasDocumentedReturnType = FALSE;
713   docProvider = 0;
714   isDMember = def->getDefFileName().right(2).lower()==".d";
715 }
716
717
718 //-----------------------------------------------------------------------------
719 //-----------------------------------------------------------------------------
720 //-----------------------------------------------------------------------------
721
722 /*! Creates a new member definition.
723  *
724  * \param df File containing the definition of this member.
725  * \param dl Line at which the member definition was found.
726  * \param dc Column at which the member definition was found.
727  * \param t  A string representing the type of the member.
728  * \param na A string representing the name of the member.
729  * \param a  A string representing the arguments of the member.
730  * \param e  A string representing the throw clause of the members.
731  * \param p  The protection context of the member, possible values are:
732  *           \c Public, \c Protected, \c Private.
733  * \param v  The degree of `virtualness' of the member, possible values are:
734  *           \c Normal, \c Virtual, \c Pure.
735  * \param s  A boolean that is true iff the member is static.
736  * \param r  The relationship between the class and the member.
737  * \param mt The kind of member. See #MemberType for a list of
738  *           all types.
739  * \param tal The template arguments of this member.
740  * \param al  The arguments of this member. This is a structured form of
741  *            the string past as argument \a a.
742  */
743
744 MemberDef::MemberDef(const char *df,int dl,int dc,
745                      const char *t,const char *na,const char *a,const char *e,
746                      Protection p,Specifier v,bool s,Relationship r,MemberType mt,
747                      const ArgumentList *tal,const ArgumentList *al
748                     ) : Definition(df,dl,dc,removeRedundantWhiteSpace(na)), visited(FALSE)
749 {
750   //printf("MemberDef::MemberDef(%s)\n",na);
751   m_impl = new MemberDefImpl;
752   m_impl->init(this,t,a,e,p,v,s,r,mt,tal,al);
753   number_of_flowkw = 1;
754   m_isLinkableCached    = 0;
755   m_isConstructorCached = 0;
756   m_isDestructorCached  = 0;
757 }
758
759 MemberDef::MemberDef(const MemberDef &md) : Definition(md), visited(FALSE)
760 {
761   m_impl = new MemberDefImpl;
762   m_isLinkableCached    = 0;
763   m_isConstructorCached = 0;
764   m_isDestructorCached  = 0;
765 }
766
767 MemberDef *MemberDef::deepCopy() const
768 {
769   //MemberDef *result = new MemberDef(getDefFileName(),getDefLine(),name());
770   MemberDef *result = new MemberDef(*this);
771   // first copy everything by reference
772   *result->m_impl = *m_impl;
773   // clear pointers owned by object
774   result->m_impl->redefinedBy= 0;
775   result->m_impl->exampleSDict=0;
776   result->m_impl->enumFields=0;
777   result->m_impl->defArgList=0;
778   result->m_impl->tArgList=0;
779   result->m_impl->typeConstraints=0;
780   result->m_impl->defTmpArgLists=0;
781   result->m_impl->classSectionSDict=0;
782   result->m_impl->declArgList=0;
783   // replace pointers owned by the object by deep copies
784   if (m_impl->redefinedBy)
785   {
786     MemberListIterator mli(*m_impl->redefinedBy);
787     MemberDef *md;
788     for (mli.toFirst();(md=mli.current());++mli)
789     {
790       result->insertReimplementedBy(md);
791     }
792   }
793   if (m_impl->exampleSDict)
794   {
795     ExampleSDict::Iterator it(*m_impl->exampleSDict);
796     Example *e;
797     for (it.toFirst();(e=it.current());++it)
798     {
799       result->addExample(e->anchor,e->name,e->file);
800     }
801   }
802   if (m_impl->enumFields)
803   {
804     MemberListIterator mli(*m_impl->enumFields);
805     MemberDef *md;
806     for (mli.toFirst();(md=mli.current());++mli)
807     {
808       result->insertEnumField(md);
809     }
810   }
811   if (m_impl->defArgList)
812   {
813     result->m_impl->defArgList = m_impl->defArgList->deepCopy();
814   }
815   if (m_impl->tArgList)
816   {
817     result->m_impl->tArgList = m_impl->tArgList->deepCopy();
818   }
819   if (m_impl->typeConstraints)
820   {
821     result->m_impl->typeConstraints = m_impl->typeConstraints->deepCopy();
822   }
823   result->setDefinitionTemplateParameterLists(m_impl->defTmpArgLists);
824   if (m_impl->classSectionSDict)
825   {
826     result->m_impl->classSectionSDict = new SDict<MemberList>(7);
827     SDict<MemberList>::IteratorDict it(*m_impl->classSectionSDict);
828     MemberList *ml;
829     for (it.toFirst();(ml=it.current());++it)
830     {
831       result->m_impl->classSectionSDict->append(it.currentKey(),ml);
832     }
833   }
834   if (m_impl->declArgList)
835   {
836     result->m_impl->declArgList = m_impl->declArgList->deepCopy();
837   }
838   return result;
839 }
840
841 void MemberDef::moveTo(Definition *scope)
842 {
843    setOuterScope(scope);
844    if (scope->definitionType()==Definition::TypeClass)
845    {
846      m_impl->classDef = (ClassDef*)scope;
847    }
848    else if (scope->definitionType()==Definition::TypeFile)
849    {
850      m_impl->fileDef = (FileDef*)scope;
851    }
852    else if (scope->definitionType()==Definition::TypeNamespace)
853    {
854      m_impl->nspace = (NamespaceDef*)scope;
855    }
856    m_isLinkableCached = 0;
857    m_isConstructorCached = 0;
858 }
859
860
861 /*! Destroys the member definition. */
862 MemberDef::~MemberDef()
863 {
864   delete m_impl;
865   //printf("%p: ~MemberDef()\n",this);
866   m_impl=0;
867 }
868
869 void MemberDef::setReimplements(MemberDef *md)
870 {
871   m_impl->redefines = md;
872 }
873
874 void MemberDef::insertReimplementedBy(MemberDef *md)
875 {
876   if (m_impl->templateMaster)
877   {
878     m_impl->templateMaster->insertReimplementedBy(md);
879   }
880   if (m_impl->redefinedBy==0) m_impl->redefinedBy = new MemberList(MemberListType_redefinedBy);
881   if (m_impl->redefinedBy->findRef(md)==-1)
882   {
883     m_impl->redefinedBy->inSort(md);
884   }
885 }
886
887 MemberDef *MemberDef::reimplements() const
888 {
889   return m_impl->redefines;
890 }
891
892 MemberList *MemberDef::reimplementedBy() const
893 {
894   return m_impl->redefinedBy;
895 }
896
897 bool MemberDef::isReimplementedBy(ClassDef *cd) const
898 {
899   if (cd && m_impl->redefinedBy)
900   {
901     MemberListIterator mi(*m_impl->redefinedBy);
902     MemberDef *md;
903     for (mi.toFirst();(md=mi.current());++mi)
904     {
905       ClassDef *mcd = md->getClassDef();
906       if (mcd)
907       {
908         if (cd==mcd || cd->isBaseClass(mcd,TRUE))
909         {
910           return TRUE;
911         }
912       }
913     }
914   }
915   return FALSE;
916 }
917
918 void MemberDef::insertEnumField(MemberDef *md)
919 {
920   if (m_impl->enumFields==0) m_impl->enumFields=new MemberList(MemberListType_enumFields);
921   m_impl->enumFields->append(md);
922 }
923
924 bool MemberDef::addExample(const char *anchor,const char *nameStr,
925                            const char *file)
926 {
927   //printf("%s::addExample(%s,%s,%s)\n",name().data(),anchor,nameStr,file);
928   if (m_impl->exampleSDict==0) m_impl->exampleSDict = new ExampleSDict;
929   if (m_impl->exampleSDict->find(nameStr)==0)
930   {
931     //printf("Add reference to example %s to member %s\n",nameStr,name.data());
932     Example *e=new Example;
933     e->anchor=anchor;
934     e->name=nameStr;
935     e->file=file;
936     m_impl->exampleSDict->inSort(nameStr,e);
937     return TRUE;
938   }
939   return FALSE;
940 }
941
942 bool MemberDef::hasExamples()
943 {
944   if (m_impl->exampleSDict==0)
945     return FALSE;
946   else
947     return m_impl->exampleSDict->count()>0;
948 }
949
950 QCString MemberDef::getOutputFileBase() const
951 {
952   static bool separateMemberPages = Config_getBool(SEPARATE_MEMBER_PAGES);
953   static bool inlineSimpleClasses = Config_getBool(INLINE_SIMPLE_STRUCTS);
954   QCString baseName;
955
956   //printf("Member: %s: templateMaster=%p group=%p classDef=%p nspace=%p fileDef=%p\n",
957   //    name().data(),m_impl->templateMaster,m_impl->group,m_impl->classDef,
958   //    m_impl->nspace,m_impl->fileDef);
959   if (!m_impl->explicitOutputFileBase.isEmpty())
960   {
961     return m_impl->explicitOutputFileBase;
962   }
963   else if (m_impl->templateMaster)
964   {
965     return m_impl->templateMaster->getOutputFileBase();
966   }
967   else if (m_impl->group)
968   {
969     baseName=m_impl->group->getOutputFileBase();
970   }
971   else if (m_impl->classDef)
972   {
973     baseName=m_impl->classDef->getOutputFileBase();
974     if (inlineSimpleClasses && m_impl->classDef->isSimple())
975     {
976       return baseName;
977     }
978   }
979   else if (m_impl->nspace && m_impl->nspace->isLinkableInProject())
980   {
981     baseName=m_impl->nspace->getOutputFileBase();
982   }
983   else if (m_impl->fileDef)
984   {
985     baseName=m_impl->fileDef->getOutputFileBase();
986   }
987
988   if (baseName.isEmpty())
989   {
990     warn(getDefFileName(),getDefLine(),
991        "Internal inconsistency: member %s does not belong to any"
992        " container!",qPrint(name())
993       );
994     return "dummy";
995   }
996   else if (separateMemberPages && isDetailedSectionLinkable())
997   {
998     if (getEnumScope()) // enum value, which is part of enum's documentation
999     {
1000       baseName+="_"+getEnumScope()->anchor();
1001     }
1002     else
1003     {
1004       baseName+="_"+anchor();
1005     }
1006   }
1007   return baseName;
1008 }
1009
1010 QCString MemberDef::getReference() const
1011 {
1012   QCString ref = Definition::getReference();
1013   if (!ref.isEmpty())
1014   {
1015     return ref;
1016   }
1017   if (m_impl->templateMaster)
1018   {
1019     return m_impl->templateMaster->getReference();
1020   }
1021   else if (m_impl->group)
1022   {
1023     return m_impl->group->getReference();
1024   }
1025   else if (m_impl->classDef)
1026   {
1027     return m_impl->classDef->getReference();
1028   }
1029   else if (m_impl->nspace)
1030   {
1031     return m_impl->nspace->getReference();
1032   }
1033   else if (m_impl->fileDef)
1034   {
1035     return m_impl->fileDef->getReference();
1036   }
1037   return "";
1038 }
1039
1040 QCString MemberDef::anchor() const
1041 {
1042   QCString result=m_impl->anc;
1043   if (m_impl->groupAlias)     return m_impl->groupAlias->anchor();
1044   if (m_impl->templateMaster) return m_impl->templateMaster->anchor();
1045   if (m_impl->enumScope && m_impl->enumScope!=this) // avoid recursion for C#'s public enum E { E, F }
1046   {
1047     result.prepend(m_impl->enumScope->anchor());
1048   }
1049   if (m_impl->group)
1050   {
1051     if (m_impl->groupMember)
1052     {
1053       result=m_impl->groupMember->anchor();
1054     }
1055     else if (getReference().isEmpty())
1056     {
1057       result.prepend("g");
1058     }
1059   }
1060   return result;
1061 }
1062
1063 void MemberDef::_computeLinkableInProject()
1064 {
1065   static bool extractStatic  = Config_getBool(EXTRACT_STATIC);
1066   m_isLinkableCached = 2; // linkable
1067   //printf("MemberDef::isLinkableInProject(name=%s)\n",name().data());
1068   if (isHidden())
1069   {
1070     //printf("is hidden\n");
1071     m_isLinkableCached = 1;
1072     return;
1073   }
1074   if (m_impl->templateMaster)
1075   {
1076     //printf("has template master\n");
1077     m_isLinkableCached = m_impl->templateMaster->isLinkableInProject() ? 2 : 1;
1078     return;
1079   }
1080   if (name().isEmpty() || name().at(0)=='@')
1081   {
1082     //printf("name invalid\n");
1083     m_isLinkableCached = 1; // not a valid or a dummy name
1084     return;
1085   }
1086   if (!hasDocumentation() || isReference())
1087   {
1088     //printf("no docs or reference\n");
1089     m_isLinkableCached = 1; // no documentation
1090     return;
1091   }
1092   if (m_impl->group && !m_impl->group->isLinkableInProject())
1093   {
1094     //printf("group but group not linkable!\n");
1095     m_isLinkableCached = 1; // group but group not linkable
1096     return;
1097   }
1098   if (!m_impl->group && m_impl->classDef && !m_impl->classDef->isLinkableInProject())
1099   {
1100     //printf("in a class but class not linkable!\n");
1101     m_isLinkableCached = 1; // in class but class not linkable
1102     return;
1103   }
1104   if (!m_impl->group && m_impl->nspace && !m_impl->related && !m_impl->nspace->isLinkableInProject()
1105       && (m_impl->fileDef==0 || !m_impl->fileDef->isLinkableInProject()))
1106   {
1107     //printf("in a namespace but namespace not linkable!\n");
1108     m_isLinkableCached = 1; // in namespace but namespace not linkable
1109     return;
1110   }
1111   if (!m_impl->group && !m_impl->nspace &&
1112       !m_impl->related && !m_impl->classDef &&
1113       m_impl->fileDef && !m_impl->fileDef->isLinkableInProject())
1114   {
1115     //printf("in a file but file not linkable!\n");
1116     m_isLinkableCached = 1; // in file (and not in namespace) but file not linkable
1117     return;
1118   }
1119   if (!protectionLevelVisible(m_impl->prot) && m_impl->mtype!=MemberType_Friend)
1120   {
1121     //printf("private and invisible!\n");
1122     m_isLinkableCached = 1; // hidden due to protection
1123     return;
1124   }
1125   if (m_impl->stat && m_impl->classDef==0 && !extractStatic)
1126   {
1127     //printf("static and invisible!\n");
1128     m_isLinkableCached = 1; // hidden due to staticness
1129     return;
1130   }
1131   //printf("linkable!\n");
1132   return; // linkable!
1133 }
1134
1135 void MemberDef::setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace)
1136 {
1137   Definition::setDocumentation(d,docFile,docLine,stripWhiteSpace);
1138   m_isLinkableCached = 0;
1139 }
1140
1141 void MemberDef::setBriefDescription(const char *b,const char *briefFile,int briefLine)
1142 {
1143   Definition::setBriefDescription(b,briefFile,briefLine);
1144   m_isLinkableCached = 0;
1145 }
1146
1147 void MemberDef::setInbodyDocumentation(const char *d,const char *inbodyFile,int inbodyLine)
1148 {
1149   Definition::setInbodyDocumentation(d,inbodyFile,inbodyLine);
1150   m_isLinkableCached = 0;
1151 }
1152
1153 void MemberDef::setHidden(bool b)
1154 {
1155   Definition::setHidden(b);
1156   m_isLinkableCached = 0;
1157 }
1158
1159 bool MemberDef::isLinkableInProject() const
1160 {
1161   if (m_isLinkableCached==0)
1162   {
1163     MemberDef *that = (MemberDef*)this;
1164     that->_computeLinkableInProject();
1165   }
1166   ASSERT(m_isLinkableCached>0);
1167   return m_isLinkableCached==2;
1168 }
1169
1170 bool MemberDef::isLinkable() const
1171 {
1172   if (m_impl->templateMaster)
1173   {
1174     return m_impl->templateMaster->isLinkable();
1175   }
1176   else
1177   {
1178     return isLinkableInProject() || isReference();
1179   }
1180 }
1181
1182
1183 void MemberDef::setDefinitionTemplateParameterLists(QList<ArgumentList> *lists)
1184 {
1185   if (lists)
1186   {
1187     if (m_impl->defTmpArgLists) delete m_impl->defTmpArgLists;
1188     m_impl->defTmpArgLists = copyArgumentLists(lists);
1189   }
1190 }
1191
1192 void MemberDef::writeLink(OutputList &ol,ClassDef *,NamespaceDef *,
1193                       FileDef *fd,GroupDef *gd,bool onlyText)
1194 {
1195   SrcLangExt lang = getLanguage();
1196   static bool hideScopeNames     = Config_getBool(HIDE_SCOPE_NAMES);
1197   QCString sep = getLanguageSpecificSeparator(lang,TRUE);
1198   QCString n = name();
1199   if (!hideScopeNames)
1200   {
1201     if (m_impl->enumScope && m_impl->livesInsideEnum)
1202     {
1203       n.prepend(m_impl->enumScope->displayName()+sep);
1204     }
1205     if (m_impl->classDef && gd && !isRelated())
1206     {
1207       n.prepend(m_impl->classDef->displayName()+sep);
1208     }
1209     else if (m_impl->nspace && (gd || fd))
1210     {
1211       n.prepend(m_impl->nspace->displayName()+sep);
1212     }
1213   }
1214
1215   if (isObjCMethod())
1216   {
1217     if (isStatic()) ol.docify("+ "); else ol.docify("- ");
1218   }
1219   if (!onlyText && isLinkable()) // write link
1220   {
1221     if (m_impl->mtype==MemberType_EnumValue && getGroupDef()==0 &&          // enum value is not grouped
1222         getEnumScope() && getEnumScope()->getGroupDef()) // but its container is
1223     {
1224       GroupDef *enumValGroup = getEnumScope()->getGroupDef();
1225       ol.writeObjectLink(enumValGroup->getReference(),
1226                          enumValGroup->getOutputFileBase(),
1227                          anchor(),n);
1228     }
1229     else
1230     {
1231       ol.writeObjectLink(getReference(),getOutputFileBase(),anchor(),n);
1232     }
1233   }
1234   else // write only text
1235   {
1236     ol.startBold();
1237     ol.docify(n);
1238     ol.endBold();
1239   }
1240 }
1241
1242 /*! If this member has an anonymous class/struct/union as its type, then
1243  *  this method will return the ClassDef that describes this return type.
1244  */
1245 ClassDef *MemberDef::getClassDefOfAnonymousType()
1246 {
1247   if (m_impl->cachedAnonymousType) return m_impl->cachedAnonymousType;
1248
1249   QCString cname;
1250   if (getClassDef()!=0)
1251   {
1252     cname=getClassDef()->name().copy();
1253   }
1254   else if (getNamespaceDef()!=0)
1255   {
1256     cname=getNamespaceDef()->name().copy();
1257   }
1258   QCString ltype(m_impl->type);
1259   // strip `static' keyword from ltype
1260   //if (ltype.left(7)=="static ") ltype=ltype.right(ltype.length()-7);
1261   // strip `friend' keyword from ltype
1262   ltype.stripPrefix("friend ");
1263   static QRegExp r("@[0-9]+");
1264   int l,i=r.match(ltype,0,&l);
1265   //printf("ltype=`%s' i=%d\n",ltype.data(),i);
1266   // search for the last anonymous scope in the member type
1267   ClassDef *annoClassDef=0;
1268   if (i!=-1) // found anonymous scope in type
1269   {
1270     int il=i-1,ir=i+l;
1271     // extract anonymous scope
1272     while (il>=0 && (isId(ltype.at(il)) || ltype.at(il)==':' || ltype.at(il)=='@')) il--;
1273     if (il>0) il++; else if (il<0) il=0;
1274     while (ir<(int)ltype.length() && (isId(ltype.at(ir)) || ltype.at(ir)==':' || ltype.at(ir)=='@')) ir++;
1275
1276     QCString annName = ltype.mid(il,ir-il);
1277
1278     // if inside a class or namespace try to prepend the scope name
1279     if (!cname.isEmpty() && annName.left(cname.length()+2)!=cname+"::")
1280     {
1281       QCString ts=stripAnonymousNamespaceScope(cname+"::"+annName);
1282       annoClassDef=getClass(ts);
1283     }
1284     // if not found yet, try without scope name
1285     if (annoClassDef==0)
1286     {
1287       QCString ts=stripAnonymousNamespaceScope(annName);
1288       annoClassDef=getClass(ts);
1289     }
1290   }
1291   m_impl->cachedAnonymousType = annoClassDef;
1292   return annoClassDef;
1293 }
1294
1295 /*! This methods returns TRUE iff the brief section (also known as
1296  *  declaration section) is visible in the documentation.
1297  */
1298 bool MemberDef::isBriefSectionVisible() const
1299 {
1300   static bool extractStatic       = Config_getBool(EXTRACT_STATIC);
1301   static bool hideUndocMembers    = Config_getBool(HIDE_UNDOC_MEMBERS);
1302   static bool briefMemberDesc     = Config_getBool(BRIEF_MEMBER_DESC);
1303   static bool repeatBrief         = Config_getBool(REPEAT_BRIEF);
1304   static bool hideFriendCompounds = Config_getBool(HIDE_FRIEND_COMPOUNDS);
1305
1306   //printf("Member %s grpId=%d docs=%s file=%s args=%s\n",
1307   //    name().data(),
1308   //    0,"", //grpId,grpId==-1?"<none>":Doxygen::memberDocDict[grpId]->data(),
1309   //    "", //getFileDef()->name().data(),
1310   //    argsString());
1311
1312   MemberGroupInfo *info = Doxygen::memGrpInfoDict[m_impl->grpId];
1313   //printf("name=%s m_impl->grpId=%d info=%p\n",name().data(),m_impl->grpId,info);
1314   //QCString *pMemGrp = Doxygen::memberDocDict[grpId];
1315   bool hasDocs = hasDocumentation() ||
1316                   // part of a documented member group
1317                  (m_impl->grpId!=-1 && info && !(info->doc.isEmpty() && info->header.isEmpty()));
1318
1319   // only include static members with file/namespace scope if
1320   // explicitly enabled in the config file
1321   bool visibleIfStatic = !(getClassDef()==0 &&
1322                            isStatic() &&
1323                            !extractStatic
1324                           );
1325
1326   // only include members is the are documented or
1327   // HIDE_UNDOC_MEMBERS is NO in the config file
1328   bool visibleIfDocumented = (!hideUndocMembers ||
1329                               hasDocs ||
1330                               isDocumentedFriendClass()
1331                              );
1332
1333   // hide members with no detailed description and brief descriptions
1334   // explicitly disabled.
1335   bool visibleIfEnabled = !(hideUndocMembers &&
1336                             documentation().isEmpty() &&
1337                             !briefMemberDesc &&
1338                             !repeatBrief
1339                            );
1340
1341   // Hide friend (class|struct|union) declarations if HIDE_FRIEND_COMPOUNDS is true
1342   bool visibleIfFriendCompound = !(hideFriendCompounds &&
1343                                    isFriend() &&
1344                                    (m_impl->type=="friend class" ||
1345                                     m_impl->type=="friend struct" ||
1346                                     m_impl->type=="friend union"
1347                                    )
1348                                   );
1349
1350   // only include members that are non-private unless EXTRACT_PRIVATE is
1351   // set to YES or the member is part of a group
1352   bool visibleIfPrivate = (protectionLevelVisible(protection()) ||
1353                            m_impl->mtype==MemberType_Friend
1354                           );
1355
1356   // hide member if it overrides a member in a superclass and has no
1357   // documentation of its own
1358   //bool visibleIfDocVirtual = !reimplements() ||
1359   //                           !Config_getBool(INHERIT_DOCS) ||
1360   //                           hasDocs;
1361
1362   // true if this member is a constructor or destructor
1363   bool cOrDTor = isConstructor() || isDestructor();
1364
1365   // hide default constructors or destructors (no args) without
1366   // documentation
1367   bool visibleIfNotDefaultCDTor = !(cOrDTor &&
1368                                    m_impl->defArgList &&
1369                                    (m_impl->defArgList->isEmpty() ||
1370                                     m_impl->defArgList->getFirst()->type == "void"
1371                                    ) &&
1372                                    !hasDocs
1373                                   );
1374
1375
1376   //printf("visibleIfStatic=%d visibleIfDocumented=%d visibleIfEnabled=%d "
1377   //       "visibleIfPrivate=%d visibltIfNotDefaultCDTor=%d "
1378   //       "visibleIfFriendCompound=%d !annScope=%d\n",
1379   //       visibleIfStatic,visibleIfDocumented,
1380   //       visibleIfEnabled,visibleIfPrivate,visibleIfNotDefaultCDTor,
1381   //       visibleIfFriendCompound,!m_impl->annScope);
1382
1383   bool visible = visibleIfStatic     && visibleIfDocumented      &&
1384                  visibleIfEnabled    && visibleIfPrivate         &&
1385                  /*visibleIfDocVirtual &&*/ visibleIfNotDefaultCDTor &&
1386                  visibleIfFriendCompound &&
1387                  !m_impl->annScope && !isHidden();
1388   //printf("MemberDef::isBriefSectionVisible() %d\n",visible);
1389   return visible;
1390 }
1391
1392 QCString MemberDef::getDeclType() const
1393 {
1394   QCString ltype(m_impl->type);
1395   if (m_impl->mtype==MemberType_Typedef)
1396   {
1397     ltype.prepend("typedef ");
1398   }
1399   if (isAlias())
1400   {
1401     ltype="using";
1402   }
1403   // strip `friend' keyword from ltype
1404   ltype.stripPrefix("friend ");
1405   if (ltype=="@") // rename type from enum values
1406   {
1407     ltype="";
1408   }
1409   else
1410   {
1411     if (isObjCMethod())
1412     {
1413       ltype.prepend("(");
1414       ltype.append(")");
1415     }
1416   }
1417   return ltype;
1418 }
1419
1420 void MemberDef::writeDeclaration(OutputList &ol,
1421                ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,
1422                bool inGroup, ClassDef *inheritedFrom,const char *inheritId)
1423 {
1424   //printf("%s MemberDef::writeDeclaration() inGroup=%d\n",qualifiedName().data(),inGroup);
1425
1426   // hide enum value, since they appear already as part of the enum, unless they
1427   // are explicitly grouped.
1428   if (!inGroup && m_impl->mtype==MemberType_EnumValue) return;
1429
1430
1431   Definition *d=0;
1432   ASSERT (cd!=0 || nd!=0 || fd!=0 || gd!=0); // member should belong to something
1433   if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd;
1434   if (d==gd) // see bug 753608
1435   {
1436     if (getClassDef())          d = getClassDef();
1437     else if (getNamespaceDef()) d = getNamespaceDef();
1438     else if (getFileDef())      d = getFileDef();
1439   }
1440
1441   //_writeTagData(compoundType);
1442   _addToSearchIndex();
1443
1444   QCString cname  = d->name();
1445   QCString cdname = d->displayName();
1446   QCString cfname = getOutputFileBase();
1447
1448   // search for the last anonymous scope in the member type
1449   ClassDef *annoClassDef=getClassDefOfAnonymousType();
1450
1451   ol.startMemberDeclaration();
1452
1453   // start a new member declaration
1454   bool isAnonymous = annoClassDef || m_impl->annMemb || m_impl->annEnumType;
1455   ///printf("startMemberItem for %s\n",name().data());
1456   ol.startMemberItem(anchor(),
1457                      isAnonymous ? 1 : m_impl->tArgList ? 3 : 0,
1458                      inheritId
1459                     );
1460
1461   // If there is no detailed description we need to write the anchor here.
1462   bool detailsVisible = isDetailedSectionLinkable();
1463   bool writeAnchor = (inGroup || m_impl->group==0) &&     // only write anchors for member that have no details and are
1464                      !detailsVisible && !m_impl->annMemb; // rendered inside the group page or are not grouped at all
1465   if (writeAnchor)
1466   {
1467     QCString doxyArgs=argsString();
1468     QCString doxyName=name();
1469     if (!cname.isEmpty())
1470     {
1471       doxyName.prepend(cdname+getLanguageSpecificSeparator(getLanguage()));
1472     }
1473     ol.startDoxyAnchor(cfname,cname,anchor(),doxyName,doxyArgs);
1474   }
1475
1476   if (!detailsVisible)
1477   {
1478     ol.pushGeneratorState();
1479     ol.disable(OutputGenerator::Man);
1480     ol.disable(OutputGenerator::Latex);
1481     ol.docify("\n");
1482     ol.popGeneratorState();
1483   }
1484
1485   if (annoClassDef || m_impl->annMemb)
1486   {
1487     int j;
1488     for (j=0;j<s_indentLevel;j++)
1489     {
1490       ol.writeNonBreakableSpace(3);
1491     }
1492   }
1493
1494   // *** write template lists
1495   if (m_impl->tArgList && getLanguage()==SrcLangExt_Cpp)
1496   {
1497     if (!isAnonymous) ol.startMemberTemplateParams();
1498     writeTemplatePrefix(ol,m_impl->tArgList);
1499     if (!isAnonymous) ol.endMemberTemplateParams(anchor(),inheritId);
1500   }
1501
1502   // *** write type
1503   QCString ltype(m_impl->type);
1504   if (m_impl->mtype==MemberType_Typedef) ltype.prepend("typedef ");
1505   if (isAlias())
1506   {
1507     ltype="using";
1508   }
1509   // strip `friend' keyword from ltype
1510   ltype.stripPrefix("friend ");
1511   static QRegExp r("@[0-9]+");
1512
1513   bool endAnonScopeNeeded=FALSE;
1514   int l,i=r.match(ltype,0,&l);
1515   if (i!=-1) // member has an anonymous type
1516   {
1517     //printf("annoClassDef=%p annMemb=%p scopeName=`%s' anonymous=`%s'\n",
1518     //    annoClassDef,annMemb,cname.data(),ltype.mid(i,l).data());
1519
1520     if (annoClassDef) // type is an anonymous compound
1521     {
1522       int ir=i+l;
1523       //printf("<<<<<<<<<<<<<<\n");
1524       ol.startAnonTypeScope(s_indentLevel++);
1525       annoClassDef->writeDeclaration(ol,m_impl->annMemb,inGroup,inheritedFrom,inheritId);
1526       //printf(">>>>>>>>>>>>>> startMemberItem(2)\n");
1527       ol.startMemberItem(anchor(),2,inheritId);
1528       int j;
1529       for (j=0;j< s_indentLevel-1;j++)
1530       {
1531         ol.writeNonBreakableSpace(3);
1532       }
1533       QCString varName=ltype.right(ltype.length()-ir).stripWhiteSpace();
1534       //printf(">>>>>> ltype=`%s' varName=`%s'\n",ltype.data(),varName.data());
1535       ol.docify("}");
1536       if (varName.isEmpty() && (name().isEmpty() || name().at(0)=='@'))
1537       {
1538         ol.docify(";");
1539       }
1540       else if (!varName.isEmpty() && (varName.at(0)=='*' || varName.at(0)=='&'))
1541       {
1542         ol.docify(" ");
1543         ol.docify(varName);
1544       }
1545       endAnonScopeNeeded=TRUE;
1546     }
1547     else
1548     {
1549       if (getAnonymousEnumType()) // type is an anonymous enum
1550       {
1551         linkifyText(TextGeneratorOLImpl(ol), // out
1552                     d,                       // scope
1553                     getBodyDef(),            // fileScope
1554                     this,                    // self
1555                     ltype.left(i),           // text
1556                     FALSE                    // autoBreak
1557                    );
1558         getAnonymousEnumType()->writeEnumDeclaration(ol,cd,nd,fd,gd);
1559         //ol+=*getAnonymousEnumType()->enumDecl();
1560         linkifyText(TextGeneratorOLImpl(ol),d,m_impl->fileDef,this,ltype.right(ltype.length()-i-l),TRUE);
1561       }
1562       else
1563       {
1564         ltype = ltype.left(i) + " { ... } " + removeAnonymousScopes(ltype.right(ltype.length()-i-l));
1565         linkifyText(TextGeneratorOLImpl(ol), // out
1566                     d,                       // scope
1567                     getBodyDef(),            // fileScope
1568                     this,                    // self
1569                     ltype,                   // text
1570                     FALSE                    // autoBreak
1571                    );
1572       }
1573     }
1574   }
1575   else if (ltype=="@") // rename type from enum values
1576   {
1577     ltype="";
1578   }
1579   else
1580   {
1581     if (isObjCMethod())
1582     {
1583       ltype.prepend("(");
1584       ltype.append(")");
1585     }
1586     linkifyText(TextGeneratorOLImpl(ol), // out
1587                 d,                       // scope
1588                 getBodyDef(),            // fileScope
1589                 this,                    // self
1590                 ltype,                   // text
1591                 FALSE                    // autoBreak
1592                );
1593   }
1594   bool htmlOn = ol.isEnabled(OutputGenerator::Html);
1595   if (htmlOn && !ltype.isEmpty())
1596   {
1597     ol.disable(OutputGenerator::Html);
1598   }
1599   if (!ltype.isEmpty()) ol.docify(" ");
1600   if (htmlOn)
1601   {
1602     ol.enable(OutputGenerator::Html);
1603   }
1604
1605   if (m_impl->annMemb)
1606   {
1607     ol.pushGeneratorState();
1608     ol.disableAllBut(OutputGenerator::Html);
1609     ol.writeNonBreakableSpace(3);
1610     ol.popGeneratorState();
1611   }
1612   else
1613   {
1614     ol.insertMemberAlign(m_impl->tArgList!=0);
1615   }
1616
1617   // *** write name
1618   if (!name().isEmpty() && name().at(0)!='@') // hide anonymous stuff
1619   {
1620     static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
1621     static bool extractStatic  = Config_getBool(EXTRACT_STATIC);
1622     //printf("Member name=`%s gd=%p md->groupDef=%p inGroup=%d isLinkable()=%d hasDocumentation=%d\n",name().data(),gd,getGroupDef(),inGroup,isLinkable(),hasDocumentation());
1623     if (!(name().isEmpty() || name().at(0)=='@') && // name valid
1624         (hasDocumentation() || isReference()) && // has docs
1625         !(m_impl->prot==Private && !extractPrivate && m_impl->mtype!=MemberType_Friend) && // hidden due to protection
1626         !(isStatic() && m_impl->classDef==0 && !extractStatic) // hidden due to static-ness
1627        )
1628     {
1629       if (m_impl->annMemb)
1630       {
1631         //printf("anchor=%s ann_anchor=%s\n",anchor(),annMemb->anchor());
1632         m_impl->annMemb->writeLink(ol,
1633             m_impl->annMemb->getClassDef(),
1634             m_impl->annMemb->getNamespaceDef(),
1635             m_impl->annMemb->getFileDef(),
1636             m_impl->annMemb->getGroupDef()
1637                           );
1638         m_impl->annMemb->setAnonymousUsed();
1639         setAnonymousUsed();
1640       }
1641       else
1642       {
1643         //printf("writeLink %s->%d\n",name.data(),hasDocumentation());
1644         ClassDef *rcd = cd;
1645         if (isReference() && m_impl->classDef) rcd = m_impl->classDef;
1646         writeLink(ol,rcd,nd,fd,gd);
1647       }
1648     }
1649     else if (isDocumentedFriendClass())
1650       // if the member is an undocumented friend declaration for some class,
1651       // then maybe we can link to the class
1652     {
1653       writeLink(ol,getClass(name()),0,0,0);
1654     }
1655     else
1656       // there is a brief member description and brief member
1657       // descriptions are enabled or there is no detailed description.
1658     {
1659       if (m_impl->annMemb)
1660       {
1661         m_impl->annMemb->setAnonymousUsed();
1662         setAnonymousUsed();
1663       }
1664       ClassDef *rcd = cd;
1665       if (isReference() && m_impl->classDef) rcd = m_impl->classDef;
1666       writeLink(ol,rcd,nd,fd,gd,TRUE);
1667     }
1668   }
1669
1670   // add to index
1671   if (isEnumerate() && name().at(0)=='@')
1672   {
1673     // don't add to index
1674   }
1675   else // index member
1676   {
1677     //static bool separateMemPages = Config_getBool(SEPARATE_MEMBER_PAGES);
1678     //QCString cfname = getOutputFileBase();
1679     //QCString cfiname = d->getOutputFileBase();
1680     //Doxygen::indexList->addIndexItem(
1681     //    cname,                                 // level1
1682     //    name(),                                // level2
1683     //    separateMemPages ? cfname : cfiname,   // contRef
1684     //    cfname,                                // memRef
1685     //    anchor(),                              // anchor
1686     //    this);                                 // memberdef
1687     Doxygen::indexList->addIndexItem(d,this);
1688   }
1689
1690   // *** write arguments
1691   if (argsString() && !isObjCMethod())
1692   {
1693     if (!isDefine() && !isTypedef()) ol.writeString(" ");
1694     linkifyText(TextGeneratorOLImpl(ol), // out
1695                 d,                       // scope
1696                 getBodyDef(),            // fileScope
1697                 this,                    // self
1698                 isDefine() ?
1699                    (const char*)substitute(argsString(),",",", ") :
1700                 isTypedef() ?
1701                    (const char*)substitute(argsString(),")(",") (") :
1702                    argsString(),         // text
1703                 m_impl->annMemb,         // autoBreak
1704                 TRUE,                    // external
1705                 FALSE,                   // keepSpaces
1706                 s_indentLevel
1707                );
1708   }
1709   // *** write exceptions
1710   if (excpString())
1711   {
1712     ol.writeString(" ");
1713     ol.docify(excpString());
1714   }
1715
1716   // *** write bitfields
1717   if (!m_impl->bitfields.isEmpty()) // add bitfields
1718   {
1719     linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->bitfields);
1720   }
1721   else if (hasOneLineInitializer()
1722       //!init.isEmpty() && initLines==0 && // one line initializer
1723       //((maxInitLines>0 && userInitLines==-1) || userInitLines>0) // enabled by default or explicitly
1724           ) // add initializer
1725   {
1726     if (!isDefine())
1727     {
1728       //ol.writeString(" = ");
1729       ol.writeString(" ");
1730       linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->initializer.simplifyWhiteSpace());
1731     }
1732     else
1733     {
1734       ol.writeNonBreakableSpace(3);
1735       linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->initializer);
1736     }
1737   }
1738   else if (isAlias()) // using template alias
1739   {
1740     ol.writeString(" = ");
1741     linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->type);
1742   }
1743
1744
1745   if ((isObjCMethod() || isObjCProperty()) && isImplementation())
1746   {
1747     ol.startTypewriter();
1748     ol.docify(" [implementation]");
1749     ol.endTypewriter();
1750   }
1751   
1752   bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
1753
1754   if (isProperty() && (isSettable() || isGettable() ||
1755       isPrivateSettable() || isPrivateGettable() ||
1756       isProtectedSettable() || isProtectedGettable()))
1757   {
1758       ol.writeLatexSpacing();
1759       ol.startTypewriter();
1760       ol.docify(" [");
1761       QStrList sl;
1762       
1763       if (isGettable())             sl.append("get");
1764       if (isProtectedGettable())    sl.append("protected get");
1765       if (isSettable())             sl.append("set");
1766       if (isProtectedSettable())    sl.append("protected set");
1767       if (extractPrivate)
1768       {
1769         if (isPrivateGettable())    sl.append("private get");
1770         if (isPrivateSettable())    sl.append("private set");
1771       }
1772       const char *s=sl.first();
1773       while (s)
1774       {
1775          ol.docify(s);
1776          s=sl.next();
1777          if (s) ol.docify(", ");
1778       }
1779       ol.docify("]");
1780       ol.endTypewriter();
1781   }
1782
1783   if (isEvent() && (isAddable() || isRemovable() || isRaisable()))
1784   {
1785       ol.writeLatexSpacing();
1786       ol.startTypewriter();
1787       ol.docify(" [");
1788       QStrList sl;
1789       if (isAddable())   sl.append("add");
1790       if (isRemovable()) sl.append("remove");
1791       if (isRaisable())  sl.append("raise");
1792       const char *s=sl.first();
1793       while (s)
1794       {
1795          ol.docify(s);
1796          s=sl.next();
1797          if (s) ol.docify(", ");
1798       }
1799       ol.docify("]");
1800       ol.endTypewriter();
1801   }
1802
1803   if (writeAnchor)
1804   {
1805     ol.endDoxyAnchor(cfname,anchor());
1806   }
1807
1808   //printf("endMember %s annoClassDef=%p annEnumType=%p\n",
1809   //    name().data(),annoClassDef,annEnumType);
1810   ol.endMemberItem();
1811   if (endAnonScopeNeeded)
1812   {
1813     ol.endAnonTypeScope(--s_indentLevel);
1814   }
1815
1816   // write brief description
1817   if (!briefDescription().isEmpty() &&
1818       Config_getBool(BRIEF_MEMBER_DESC)
1819       /* && !annMemb */
1820      )
1821   {
1822     DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),
1823                 getOuterScope()?getOuterScope():d,this,briefDescription(),
1824                 TRUE,FALSE,0,TRUE,FALSE);
1825
1826     if (rootNode && !rootNode->isEmpty())
1827     {
1828       ol.startMemberDescription(anchor(),inheritId);
1829       ol.writeDoc(rootNode,getOuterScope()?getOuterScope():d,this);
1830       if (detailsVisible)
1831       {
1832         static bool separateMemberPages = Config_getBool(SEPARATE_MEMBER_PAGES);
1833         ol.pushGeneratorState();
1834         ol.disableAllBut(OutputGenerator::Html);
1835         //ol.endEmphasis();
1836         ol.docify(" ");
1837         if (inheritedFrom ||
1838             separateMemberPages ||
1839             (m_impl->group!=0 && gd==0) ||
1840             (m_impl->nspace!=0 && nd==0)
1841            ) // forward link to the page or group or namespace
1842         {
1843           ol.startTextLink(getOutputFileBase(),anchor());
1844         }
1845         else // local link
1846         {
1847           ol.startTextLink(0,anchor());
1848         }
1849         ol.parseText(theTranslator->trMore());
1850         ol.endTextLink();
1851         //ol.startEmphasis();
1852         ol.popGeneratorState();
1853       }
1854       // for RTF we need to add an extra empty paragraph
1855       ol.pushGeneratorState();
1856       ol.disableAllBut(OutputGenerator::RTF);
1857       ol.startParagraph();
1858       ol.endParagraph();
1859       ol.popGeneratorState();
1860       ol.endMemberDescription();
1861     }
1862     delete rootNode;
1863   }
1864
1865   ol.endMemberDeclaration(anchor(),inheritId);
1866
1867   warnIfUndocumented();
1868 }
1869
1870 bool MemberDef::isDetailedSectionLinkable() const
1871 {
1872   static bool extractAll        = Config_getBool(EXTRACT_ALL);
1873   static bool alwaysDetailedSec = Config_getBool(ALWAYS_DETAILED_SEC);
1874   static bool repeatBrief       = Config_getBool(REPEAT_BRIEF);
1875   static bool briefMemberDesc   = Config_getBool(BRIEF_MEMBER_DESC);
1876   static bool hideUndocMembers  = Config_getBool(HIDE_UNDOC_MEMBERS);
1877   static bool extractStatic     = Config_getBool(EXTRACT_STATIC);
1878
1879   // the member has details documentation for any of the following reasons
1880   bool docFilter =
1881          // treat everything as documented
1882          extractAll ||
1883          // has detailed docs
1884          !documentation().isEmpty() ||
1885          // has inbody docs
1886          !inbodyDocumentation().isEmpty() ||
1887          // is an enum with values that are documented
1888          (m_impl->mtype==MemberType_Enumeration && m_impl->docEnumValues) ||
1889          // is documented enum value
1890          (m_impl->mtype==MemberType_EnumValue && !briefDescription().isEmpty()) ||
1891          // has brief description that is part of the detailed description
1892          (!briefDescription().isEmpty() &&           // has brief docs
1893           (alwaysDetailedSec &&                      // they are visible in
1894            (repeatBrief ||                           // detailed section or
1895             !briefMemberDesc                         // they are explicitly not
1896            )                                         // shown in brief section
1897           )
1898          ) ||
1899          // has a multi-line initialization block
1900          //(initLines>0 && initLines<maxInitLines) ||
1901          (hasMultiLineInitializer() && !hideUndocMembers) ||
1902          // has one or more documented arguments
1903          (m_impl->defArgList!=0 && m_impl->defArgList->hasDocumentation()) ||
1904          // is an attribute or property - need to display that tag
1905          (m_impl->memSpec & (Entry::Attribute|Entry::Property)) ||
1906          // has user comments
1907          Doxygen::userComments
1908          ;
1909
1910   // this is not a global static or global statics should be extracted
1911   bool staticFilter = getClassDef()!=0 || !isStatic() || extractStatic;
1912
1913   // only include members that are non-private unless EXTRACT_PRIVATE is
1914   // set to YES or the member is part of a   group
1915   bool privateFilter = protectionLevelVisible(protection()) || m_impl->mtype==MemberType_Friend;
1916
1917   // member is part of an anonymous scope that is the type of
1918   // another member in the list.
1919   //
1920   //bool inAnonymousScope = !briefDescription().isEmpty() && annUsed;
1921
1922   // hide friend (class|struct|union) member if HIDE_FRIEND_COMPOUNDS
1923   // is true
1924   bool friendCompoundFilter = !(Config_getBool(HIDE_FRIEND_COMPOUNDS) &&
1925                                 isFriend() &&
1926                                 (m_impl->type=="friend class" ||
1927                                  m_impl->type=="friend struct" ||
1928                                  m_impl->type=="friend union"
1929                                 )
1930                                );
1931
1932
1933   bool result = ((docFilter && staticFilter && privateFilter && friendCompoundFilter && !isHidden()));
1934   //printf("%s::isDetailedSectionLinkable: %d\n",name().data(),result);
1935   return result;
1936 }
1937
1938 bool MemberDef::isDetailedSectionVisible(bool inGroup,bool inFile) const
1939 {
1940   static bool separateMemPages = Config_getBool(SEPARATE_MEMBER_PAGES);
1941   static bool inlineSimpleStructs = Config_getBool(INLINE_SIMPLE_STRUCTS);
1942   static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS);
1943   bool groupFilter = getGroupDef()==0 || inGroup || separateMemPages;
1944   bool fileFilter  = getNamespaceDef()==0 || !getNamespaceDef()->isLinkable() || !inFile;
1945   bool simpleFilter = (hasBriefDescription() || !hideUndocMembers) && inlineSimpleStructs &&
1946                       getClassDef()!=0 && getClassDef()->isSimple();
1947
1948   bool visible = isDetailedSectionLinkable() && groupFilter && fileFilter &&
1949                  !isReference();
1950   bool result = visible || simpleFilter;
1951   //printf("%s::isDetailedSectionVisble: %d groupFilter=%d fileFilter=%d\n",
1952   //    name().data(),result,groupFilter,fileFilter);
1953   return result;
1954 }
1955
1956 void MemberDef::getLabels(QStrList &sl,Definition *container) const
1957 {
1958   static bool inlineInfo = Config_getBool(INLINE_INFO);
1959
1960   Specifier lvirt=virtualness();
1961   if ((!isObjCMethod() || isOptional() || isRequired()) &&
1962       (protection()!=Public || lvirt!=Normal ||
1963        isFriend() || isRelated() ||
1964        (isInline() && inlineInfo) ||
1965        isSignal() || isSlot() ||
1966        isStatic() ||
1967        (m_impl->classDef && m_impl->classDef!=container && container->definitionType()==TypeClass) ||
1968        (m_impl->memSpec & ~Entry::Inline)!=0
1969       )
1970      )
1971   {
1972     // write the member specifier list
1973     //ol.writeLatexSpacing();
1974     //ol.startTypewriter();
1975     //ol.docify(" [");
1976     SrcLangExt lang = getLanguage();
1977     bool optVhdl = lang==SrcLangExt_VHDL;
1978     bool extractPrivate = Config_getBool(EXTRACT_PRIVATE);
1979     if (optVhdl)
1980     {
1981       sl.append(VhdlDocGen::trTypeString(getMemberSpecifiers()));
1982     }
1983     else
1984     {
1985       if (isFriend()) sl.append("friend");
1986       else if (isRelated()) sl.append("related");
1987       else
1988       {
1989         if      (Config_getBool(INLINE_INFO) && isInline()) sl.append("inline");
1990         if      (isExplicit())            sl.append("explicit");
1991         if      (isMutable())             sl.append("mutable");
1992         if      (isStatic())              sl.append("static");
1993         if      (isGettable())            sl.append("get");
1994         if      (isProtectedGettable())   sl.append("protected get");
1995         if      (isSettable())            sl.append("set");
1996         if      (isProtectedSettable())   sl.append("protected set");
1997         if (extractPrivate)
1998         {
1999           if    (isPrivateGettable())     sl.append("private get");
2000           if    (isPrivateSettable())     sl.append("private set");
2001         }
2002         if      (isAddable())             sl.append("add");
2003         if      (!isUNOProperty() && isRemovable()) sl.append("remove");
2004         if      (isRaisable())            sl.append("raise");
2005         if      (isReadable())            sl.append("read");
2006         if      (isWritable())            sl.append("write");
2007         if      (isFinal())               sl.append("final");
2008         if      (isAbstract())            sl.append("abstract");
2009         if      (isOverride())            sl.append("override");
2010         if      (isInitonly())            sl.append("initonly");
2011         if      (isSealed())              sl.append("sealed");
2012         if      (isNew())                 sl.append("new");
2013         if      (isOptional())            sl.append("optional");
2014         if      (isRequired())            sl.append("required");
2015
2016         if      (isNonAtomic())           sl.append("nonatomic");
2017         else if (isObjCProperty())        sl.append("atomic");
2018
2019         // mutual exclusive Objective 2.0 property attributes
2020         if      (isAssign())              sl.append("assign");
2021         else if (isCopy())                sl.append("copy");
2022         else if (isRetain())              sl.append("retain");
2023         else if (isWeak())                sl.append("weak");
2024         else if (isStrong())              sl.append("strong");
2025         else if (isUnretained())          sl.append("unsafe_unretained");
2026
2027         if (!isObjCMethod())
2028         {
2029           if      (protection()==Protected) sl.append("protected");
2030           else if (protection()==Private)   sl.append("private");
2031           else if (protection()==Package)   sl.append("package");
2032
2033           if      (lvirt==Virtual)          sl.append("virtual");
2034           else if (lvirt==Pure)             sl.append("pure virtual");
2035           if      (isSignal())              sl.append("signal");
2036           if      (isSlot())                sl.append("slot");
2037           if      (isDefault())             sl.append("default");
2038           if      (isDelete())              sl.append("delete");
2039           if      (isNoExcept())            sl.append("noexcept");
2040           if      (isAttribute())           sl.append("attribute");
2041           if      (isUNOProperty())         sl.append("property");
2042           if      (isReadonly())            sl.append("readonly");
2043           if      (isBound())               sl.append("bound");
2044           if      (isUNOProperty() && isRemovable()) sl.append("removable");
2045           if      (isConstrained())         sl.append("constrained");
2046           if      (isTransient())           sl.append("transient");
2047           if      (isMaybeVoid())           sl.append("maybevoid");
2048           if      (isMaybeDefault())        sl.append("maybedefault");
2049           if      (isMaybeAmbiguous())      sl.append("maybeambiguous");
2050           if      (isPublished())           sl.append("published"); // enum
2051         }
2052         if (isObjCProperty() && isImplementation())
2053         {
2054           sl.append("implementation");
2055         }
2056       }
2057       if (m_impl->classDef &&
2058           container->definitionType()==TypeClass &&
2059           m_impl->classDef!=container &&
2060           !isRelated()
2061          )
2062       {
2063         sl.append("inherited");
2064       }
2065     }
2066   }
2067   else if (isObjCMethod() && isImplementation())
2068   {
2069     sl.append("implementation");
2070   }
2071 }
2072
2073 void MemberDef::_writeCallGraph(OutputList &ol)
2074 {
2075   // write call graph
2076   if (m_impl->hasCallGraph
2077       && (isFunction() || isSlot() || isSignal()) && Config_getBool(HAVE_DOT)
2078      )
2079   {
2080     DotCallGraph callGraph(this,FALSE);
2081     if (callGraph.isTooBig())
2082     {
2083        warn_uncond("Call graph for '%s' not generated, too many nodes. Consider increasing DOT_GRAPH_MAX_NODES.\n",qPrint(qualifiedName()));
2084     }
2085     else if (!callGraph.isTrivial())
2086     {
2087       msg("Generating call graph for function %s\n",qPrint(qualifiedName()));
2088       ol.disable(OutputGenerator::Man);
2089       ol.startCallGraph();
2090       ol.parseText(theTranslator->trCallGraph());
2091       ol.endCallGraph(callGraph);
2092       ol.enableAll();
2093     }
2094   }
2095 }
2096
2097 void MemberDef::_writeCallerGraph(OutputList &ol)
2098 {
2099   if (m_impl->hasCallerGraph
2100       && (isFunction() || isSlot() || isSignal()) && Config_getBool(HAVE_DOT)
2101      )
2102   {
2103     DotCallGraph callerGraph(this, TRUE);
2104     if (callerGraph.isTooBig())
2105     {
2106        warn_uncond("Caller graph for '%s' not generated, too many nodes. Consider increasing DOT_GRAPH_MAX_NODES.\n",qPrint(qualifiedName()));
2107     }
2108     else if (!callerGraph.isTrivial() && !callerGraph.isTooBig())
2109     {
2110       msg("Generating caller graph for function %s\n",qPrint(qualifiedName()));
2111       ol.disable(OutputGenerator::Man);
2112       ol.startCallGraph();
2113       ol.parseText(theTranslator->trCallerGraph());
2114       ol.endCallGraph(callerGraph);
2115       ol.enableAll();
2116     }
2117   }
2118 }
2119
2120 void MemberDef::_writeReimplements(OutputList &ol)
2121 {
2122   MemberDef *bmd=reimplements();
2123   ClassDef *bcd=0;
2124   if (bmd && (bcd=bmd->getClassDef()))
2125   {
2126     // write class that contains a member that is reimplemented by this one
2127     if (bcd->isLinkable())
2128     {
2129       ol.startParagraph();
2130       QCString reimplFromLine;
2131       if (bmd->virtualness()!=Pure && bcd->compoundType()!=ClassDef::Interface)
2132       {
2133         reimplFromLine = theTranslator->trReimplementedFromList(1);
2134       }
2135       else
2136       {
2137         reimplFromLine = theTranslator->trImplementedFromList(1);
2138       }
2139       int markerPos = reimplFromLine.find("@0");
2140       if (markerPos!=-1) // should always pass this.
2141       {
2142         ol.parseText(reimplFromLine.left(markerPos)); //text left from marker
2143         if (bmd->isLinkable()) // replace marker with link
2144         {
2145           //Definition *bd=bmd->group;
2146           //if (bd==0) bd=bcd;
2147           ol.writeObjectLink(bmd->getReference(),bmd->getOutputFileBase(),
2148               bmd->anchor(),bcd->displayName());
2149
2150           //ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(),
2151           //    bmd->anchor(),bcd->name());
2152           if ( bmd->isLinkableInProject() )
2153           {
2154             writePageRef(ol,bmd->getOutputFileBase(),bmd->anchor());
2155           }
2156         }
2157         else
2158         {
2159           ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(),
2160               0,bcd->displayName());
2161           if (bcd->isLinkableInProject()/* && !Config_getBool(PDF_HYPERLINKS)*/ )
2162           {
2163             writePageRef(ol,bcd->getOutputFileBase(),bcd->anchor());
2164           }
2165         }
2166         ol.parseText(reimplFromLine.right(
2167               reimplFromLine.length()-markerPos-2)); // text right from marker
2168
2169       }
2170       else
2171       {
2172         err("translation error: no marker in trReimplementsFromList()\n");
2173       }
2174       ol.endParagraph();
2175     }
2176   }
2177 }
2178
2179 void MemberDef::_writeReimplementedBy(OutputList &ol)
2180 {
2181   MemberList *bml=reimplementedBy();
2182   if (bml)
2183   {
2184     MemberListIterator mli(*bml);
2185     MemberDef *bmd=0;
2186     uint count=0;
2187     ClassDef *bcd=0;
2188     for (mli.toFirst();(bmd=mli.current()) && (bcd=bmd->getClassDef());++mli)
2189     {
2190       // count the members that directly inherit from md and for
2191       // which the member and class are visible in the docs.
2192       if ( bmd->isLinkable() && bcd->isLinkable() )
2193       {
2194         count++;
2195       }
2196     }
2197     if (count>0)
2198     {
2199       mli.toFirst();
2200       // write the list of classes that overwrite this member
2201       ol.startParagraph();
2202
2203       QCString reimplInLine;
2204       if (m_impl->virt==Pure || (m_impl->classDef && m_impl->classDef->compoundType()==ClassDef::Interface))
2205       {
2206         reimplInLine = theTranslator->trImplementedInList(count);
2207       }
2208       else
2209       {
2210         reimplInLine = theTranslator->trReimplementedInList(count);
2211       }
2212       static QRegExp marker("@[0-9]+");
2213       int index=0,newIndex,matchLen;
2214       // now replace all markers in reimplInLine with links to the classes
2215       while ((newIndex=marker.match(reimplInLine,index,&matchLen))!=-1)
2216       {
2217         ol.parseText(reimplInLine.mid(index,newIndex-index));
2218         bool ok;
2219         uint entryIndex = reimplInLine.mid(newIndex+1,matchLen-1).toUInt(&ok);
2220         //bmd=bml->at(entryIndex);
2221
2222         count=0;
2223         // find the entryIndex-th documented entry in the inheritance list.
2224         for (mli.toLast();(bmd=mli.current()) && (bcd=bmd->getClassDef());--mli)
2225         {
2226           if ( bmd->isLinkable() && bcd->isLinkable())
2227           {
2228             if (count==entryIndex) break;
2229             count++;
2230           }
2231         }
2232
2233         if (ok && bcd && bmd) // write link for marker
2234         {
2235           //ol.writeObjectLink(bcd->getReference(),bcd->getOutputFileBase(),
2236           //    bmd->anchor(),bcd->name());
2237           ol.writeObjectLink(bmd->getReference(),bmd->getOutputFileBase(),
2238               bmd->anchor(),bcd->displayName());
2239
2240           if (bmd->isLinkableInProject() )
2241           {
2242             writePageRef(ol,bmd->getOutputFileBase(),bmd->anchor());
2243           }
2244         }
2245         ++mli;
2246         index=newIndex+matchLen;
2247       }
2248       ol.parseText(reimplInLine.right(reimplInLine.length()-index));
2249       ol.endParagraph();
2250     }
2251   }
2252 }
2253
2254 void MemberDef::_writeCategoryRelation(OutputList &ol)
2255 {
2256   if (m_impl->classDef) // this should be a member of a class/category
2257   {
2258     //printf("%s: category %s relation %s class=%s categoryOf=%s\n",
2259     //    name().data(),
2260     //    m_impl->category ? m_impl->category->name().data() : "<none>",
2261     //    m_impl->categoryRelation ? m_impl->categoryRelation->name().data() : "<none>",
2262     //    m_impl->classDef->name().data(),
2263     //    m_impl->classDef->categoryOf() ? m_impl->classDef->categoryOf()->name().data() : "<none>"
2264     //    );
2265     QCString text;
2266     QCString ref;
2267     QCString file;
2268     QCString anc;
2269     QCString name;
2270     int i=-1;
2271     if (m_impl->categoryRelation && m_impl->categoryRelation->isLinkable())
2272     {
2273       if (m_impl->category)
2274       {
2275         // this member is in a normal class and implements method categoryRelation from category
2276         // so link to method 'categoryRelation' with 'provided by category 'category' text.
2277         text = theTranslator->trProvidedByCategory();
2278         name = m_impl->category->displayName();
2279       }
2280       else if (m_impl->classDef->categoryOf())
2281       {
2282         // this member is part of a category so link to the corresponding class member of the class we extend
2283         // so link to method 'categoryRelation' with 'extends class 'classDef->categoryOf()'
2284         text = theTranslator->trExtendsClass();
2285         name = m_impl->classDef->categoryOf()->displayName();
2286       }
2287       i=text.find("@0");
2288       if (i!=-1)
2289       {
2290         MemberDef *md = m_impl->categoryRelation;
2291         ref  = md->getReference();
2292         file = md->getOutputFileBase();
2293         anc  = md->anchor();
2294       }
2295     }
2296     if (i!=-1 && !name.isEmpty())
2297     {
2298       ol.startParagraph();
2299       ol.parseText(text.left(i));
2300       ol.writeObjectLink(ref,file,anc,name);
2301       ol.parseText(text.mid(i+2));
2302       ol.endParagraph();
2303     }
2304   }
2305 }
2306
2307 void MemberDef::_writeExamples(OutputList &ol)
2308 {
2309   // write the list of examples that use this member
2310   if (hasExamples())
2311   {
2312     ol.startSimpleSect(BaseOutputDocInterface::Examples,0,0,theTranslator->trExamples()+": ");
2313     ol.startDescForItem();
2314     writeExample(ol,m_impl->exampleSDict);
2315     ol.endDescForItem();
2316     ol.endSimpleSect();
2317   }
2318 }
2319
2320 void MemberDef::_writeTypeConstraints(OutputList &ol)
2321 {
2322   if (m_impl->typeConstraints)
2323   {
2324     writeTypeConstraints(ol,this,m_impl->typeConstraints);
2325   }
2326 }
2327
2328 void MemberDef::_writeEnumValues(OutputList &ol,Definition *container,
2329                                  const QCString &cfname,const QCString &ciname,
2330                                  const QCString &cname)
2331 {
2332   // For enum, we also write the documented enum values
2333   if (isEnumerate())
2334   {
2335     bool first=TRUE;
2336     MemberList *fmdl=enumFieldList();
2337     //printf("** %s: enum values=%d\n",name().data(),fmdl!=0 ? fmdl->count() : 0);
2338     if (fmdl)
2339     {
2340       MemberListIterator it(*fmdl);
2341       MemberDef *fmd;
2342       for (;(fmd=it.current());++it)
2343       {
2344         //printf("Enum %p: isLinkable()=%d\n",fmd,fmd->isLinkable());
2345         if (fmd->isLinkable())
2346         {
2347           if (first)
2348           {
2349             //ol.startSimpleSect(BaseOutputDocInterface::EnumValues,0,0,theTranslator->trEnumerationValues()+": ");
2350             //ol.startDescForItem();
2351             ol.startDescTable(theTranslator->trEnumerationValues());
2352           }
2353
2354           ol.startDescTableRow();
2355           ol.addIndexItem(fmd->name(),ciname);
2356           ol.addIndexItem(ciname,fmd->name());
2357
2358           //Doxygen::indexList->addIndexItem(
2359           //                       ciname,                                // level1
2360           //                       fmd->name(),                           // level2
2361           //                       separateMemPages ? cfname : cfiname,   // contRef
2362           //                       cfname,                                // memRef
2363           //                       fmd->anchor(),                         // anchor
2364           //                       fmd);                                  // memberdef
2365           Doxygen::indexList->addIndexItem(container,fmd);
2366
2367           //ol.writeListItem();
2368           ol.startDescTableTitle();
2369           ol.startDoxyAnchor(cfname,cname,fmd->anchor(),fmd->name(),fmd->argsString());
2370           first=FALSE;
2371           //ol.startEmphasis();
2372           ol.docify(fmd->name());
2373           //ol.endEmphasis();
2374           ol.disableAllBut(OutputGenerator::Man);
2375           ol.writeString(" ");
2376           ol.enableAll();
2377           ol.endDoxyAnchor(cfname,fmd->anchor());
2378           ol.endDescTableTitle();
2379           //ol.newParagraph();
2380           ol.startDescTableData();
2381
2382           bool hasBrief = !fmd->briefDescription().isEmpty();
2383           bool hasDetails = !fmd->documentation().isEmpty();
2384
2385           if (hasBrief)
2386           {
2387             ol.generateDoc(fmd->briefFile(),fmd->briefLine(),
2388                 getOuterScope()?getOuterScope():container,
2389                 fmd,fmd->briefDescription(),TRUE,FALSE);
2390           }
2391           // FIXME:PARA
2392           //if (!fmd->briefDescription().isEmpty() &&
2393           //    !fmd->documentation().isEmpty())
2394           //{
2395           //  ol.newParagraph();
2396           //}
2397           if (hasDetails)
2398           {
2399             ol.generateDoc(fmd->docFile(),fmd->docLine(),
2400                 getOuterScope()?getOuterScope():container,
2401                 fmd,fmd->documentation()+"\n",TRUE,FALSE);
2402           }
2403           ol.endDescTableData();
2404           ol.endDescTableRow();
2405         }
2406       }
2407     }
2408     if (!first)
2409     {
2410       //ol.endItemList();
2411       ol.endDescTable();
2412       //ol.endDescForItem();
2413       //ol.endSimpleSect();
2414       //ol.writeChar('\n');
2415     }
2416   }
2417 }
2418
2419 QCString MemberDef::displayDefinition() const
2420 {
2421   QCString ldef = definition();
2422   QCString title = name();
2423   if (isEnumerate())
2424   {
2425     if (title.at(0)=='@')
2426     {
2427       ldef = title = "anonymous enum";
2428       if (!m_impl->enumBaseType.isEmpty())
2429       {
2430         ldef+=" : "+m_impl->enumBaseType;
2431       }
2432     }
2433     else
2434     {
2435       ldef.prepend("enum ");
2436     }
2437   }
2438   else if (isEnumValue())
2439   {
2440     if (ldef.at(0)=='@')
2441     {
2442       ldef=ldef.mid(2);
2443     }
2444   }
2445   static QRegExp r("@[0-9]+");
2446   int l,i=r.match(ldef,0,&l);
2447   if (i!=-1) // replace anonymous parts with { ... }
2448   {
2449     int si=ldef.find(' '),pi,ei=i+l;
2450     if (si==-1) si=0;
2451     while ((pi=r.match(ldef,i+l,&l))!=-1)
2452     {
2453       i=pi;
2454       ei=i+l;
2455     }
2456     int ni=ldef.find("::",si);
2457     if (ni>=ei) ei=ni+2;
2458     ldef = ldef.left(si) + " { ... } " + ldef.right(ldef.length()-ei);
2459   }
2460   ClassDef *cd=getClassDef();
2461   if (cd && cd->isObjectiveC())
2462   {
2463     // strip scope name
2464     int ep = ldef.find("::");
2465     if (ep!=-1)
2466     {
2467       int sp=ldef.findRev(' ',ep);
2468       if (sp!=-1)
2469       {
2470         ldef=ldef.left(sp+1)+ldef.mid(ep+2);
2471       }
2472     }
2473     // strip keywords
2474     int dp = ldef.find(':');
2475     if (dp!=-1)
2476     {
2477       ldef=ldef.left(dp+1);
2478     }
2479     l=ldef.length();
2480     //printf("start >%s<\n",ldef.data());
2481     i=l-1;
2482     while (i>=0 && (isId(ldef.at(i)) || ldef.at(i)==':')) i--;
2483     while (i>=0 && isspace((uchar)ldef.at(i))) i--;
2484     if (i>0)
2485     {
2486       // insert braches around the type
2487       QCString tmp("("+ldef.left(i+1)+")"+ldef.mid(i+1));
2488       ldef=tmp;
2489     }
2490     //printf("end   >%s< i=%d\n",ldef.data(),i);
2491     if (isStatic()) ldef.prepend("+ "); else ldef.prepend("- ");
2492   }
2493   SrcLangExt lang = getLanguage();
2494   QCString sep = getLanguageSpecificSeparator(lang,TRUE);
2495   return substitute(ldef,"::",sep);
2496 }
2497
2498 void MemberDef::_writeGroupInclude(OutputList &ol,bool inGroup)
2499 {
2500   // only write out the include file if this is not part of a class or file
2501   // definition
2502   static bool showGroupedMembInc = Config_getBool(SHOW_GROUPED_MEMB_INC);
2503   FileDef *fd = getFileDef();
2504   QCString nm;
2505   if (fd) nm = getFileDef()->docName();
2506   if (inGroup && fd && showGroupedMembInc && !nm.isEmpty())
2507   {
2508     ol.startParagraph();
2509     ol.startTypewriter();
2510     SrcLangExt lang = getLanguage();
2511     bool isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java;
2512     if (isIDLorJava)
2513     {
2514       ol.docify("import ");
2515     }
2516     else
2517     {
2518       ol.docify("#include ");
2519     }
2520
2521     if (isIDLorJava) ol.docify("\""); else ol.docify("<");
2522
2523     if (fd->isLinkable())
2524     {
2525       ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),fd->anchor(),nm);
2526     }
2527     else
2528     {
2529       ol.docify(nm);
2530     }
2531
2532     if (isIDLorJava) ol.docify("\""); else ol.docify(">");
2533
2534     ol.endTypewriter();
2535     ol.endParagraph();
2536   }
2537 }
2538
2539 /*! Writes the "detailed documentation" section of this member to
2540  *  all active output formats.
2541  */
2542 void MemberDef::writeDocumentation(MemberList *ml,
2543                                    int memCount,int memTotal,
2544                                    OutputList &ol,
2545                                    const char *scName,
2546                                    Definition *container,
2547                                    bool inGroup,
2548                                    bool showEnumValues,
2549                                    bool showInline
2550                                   )
2551 {
2552   // if this member is in a group find the real scope name.
2553   bool hasParameterList = FALSE;
2554   bool inFile = container->definitionType()==Definition::TypeFile;
2555   bool hasDocs = isDetailedSectionVisible(inGroup,inFile);
2556
2557   //printf("MemberDef::writeDocumentation(): name=`%s' hasDocs=`%d' containerType=%d inGroup=%d sectionLinkable=%d\n",
2558   //    name().data(),hasDocs,container->definitionType(),inGroup,isDetailedSectionLinkable());
2559
2560   //if ( !hasDocs ) return;
2561   //if (isEnumValue() && !showEnumValues) return;
2562
2563   SrcLangExt lang = getLanguage();
2564   //printf("member=%s lang=%d\n",name().data(),lang);
2565   bool optVhdl = lang==SrcLangExt_VHDL;
2566   QCString sep = getLanguageSpecificSeparator(lang,TRUE);
2567
2568   QCString scopeName = scName;
2569   QCString memAnchor = anchor();
2570   QCString ciname = container->name();
2571   Definition *scopedContainer = container; // see bug 753608
2572   if (container->definitionType()==TypeGroup)
2573   {
2574     if (getClassDef())          { scopeName=getClassDef()->displayName();     scopedContainer=getClassDef(); }
2575     else if (getNamespaceDef()) { scopeName=getNamespaceDef()->displayName(); scopedContainer=getNamespaceDef(); }
2576     else if (getFileDef())      { scopeName=getFileDef()->displayName();      scopedContainer=getFileDef(); }
2577     ciname = ((GroupDef *)container)->groupTitle();
2578   }
2579   else if (container->definitionType()==TypeFile && getNamespaceDef())
2580   { // member is in a namespace, but is written as part of the file documentation
2581     // as well, so we need to make sure its label is unique.
2582     memAnchor.prepend("file_");
2583   }
2584
2585   QCString cname   = container->name();
2586   QCString cfname  = getOutputFileBase();
2587
2588   // get member name
2589   QCString doxyName=name();
2590   // prepend scope if there is any. TODO: make this optional for C only docs
2591   if (!scopeName.isEmpty())
2592   {
2593     doxyName.prepend(scopeName+sep);
2594   }
2595   QCString doxyArgs=argsString();
2596
2597   QCString ldef = definition();
2598   QCString title = name();
2599   //printf("member `%s' def=`%s'\n",name().data(),ldef.data());
2600   if (isEnumerate())
2601   {
2602     if (title.at(0)=='@')
2603     {
2604       ldef = title = "anonymous enum";
2605       if (!m_impl->enumBaseType.isEmpty())
2606       {
2607         ldef+=" : "+m_impl->enumBaseType;
2608       }
2609     }
2610     else
2611     {
2612       ldef.prepend("enum ");
2613     }
2614   }
2615   else if (isEnumValue())
2616   {
2617     if (ldef.at(0)=='@')
2618     {
2619       ldef=ldef.mid(2);
2620     }
2621   }
2622   else if (isFunction())
2623   {
2624     title += "()";
2625   }
2626   int i=0,l;
2627   static QRegExp r("@[0-9]+");
2628
2629   //----------------------------------------
2630
2631   ol.pushGeneratorState();
2632
2633   bool htmlEndLabelTable=FALSE;
2634   QStrList sl;
2635   getLabels(sl,scopedContainer);
2636
2637   if ((isVariable() || isTypedef()) && (i=r.match(ldef,0,&l))!=-1)
2638   {
2639     // find enum type and insert it in the definition
2640     MemberListIterator vmli(*ml);
2641     MemberDef *vmd;
2642     bool found=FALSE;
2643     for ( ; (vmd=vmli.current()) && !found ; ++vmli)
2644     {
2645       if (vmd->isEnumerate() && ldef.mid(i,l)==vmd->name())
2646       {
2647         ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
2648         ol.startMemberDoc(ciname,name(),memAnchor,name(),memCount,memTotal,showInline);
2649         linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,ldef.left(i));
2650         vmd->writeEnumDeclaration(ol,getClassDef(),getNamespaceDef(),getFileDef(),getGroupDef());
2651         linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,ldef.right(ldef.length()-i-l));
2652
2653         found=TRUE;
2654       }
2655     }
2656     if (!found) // anonymous compound
2657     {
2658       //printf("Anonymous compound `%s'\n",cname.data());
2659       ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
2660       ol.startMemberDoc(ciname,name(),memAnchor,name(),memCount,memTotal,showInline);
2661       // search for the last anonymous compound name in the definition
2662       int si=ldef.find(' '),pi,ei=i+l;
2663       if (si==-1) si=0;
2664       while ((pi=r.match(ldef,i+l,&l))!=-1)
2665       {
2666         i=pi;
2667         ei=i+l;
2668       }
2669       // first si characters of ldef contain compound type name
2670       ol.startMemberDocName(isObjCMethod());
2671       ol.docify(ldef.left(si));
2672       ol.docify(" { ... } ");
2673       // last ei characters of ldef contain pointer/reference specifiers
2674       int ni=ldef.find("::",si);
2675       if (ni>=ei) ei=ni+2;
2676       linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,ldef.right(ldef.length()-ei));
2677     }
2678   }
2679   else // not an enum value or anonymous compound
2680   {
2681     ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
2682     ol.startMemberDoc(ciname,name(),memAnchor,title,memCount,memTotal,showInline);
2683
2684     ClassDef *cd=getClassDef();
2685     NamespaceDef *nd=getNamespaceDef();
2686     if (!Config_getBool(HIDE_SCOPE_NAMES))
2687     {
2688       bool first=TRUE;
2689       SrcLangExt lang = getLanguage();
2690       if (m_impl->defTmpArgLists && lang==SrcLangExt_Cpp)
2691         // definition has explicit template parameter declarations
2692       {
2693         QListIterator<ArgumentList> ali(*m_impl->defTmpArgLists);
2694         ArgumentList *tal;
2695         for (ali.toFirst();(tal=ali.current());++ali)
2696         {
2697           if (tal->count()>0)
2698           {
2699             if (!first) ol.docify(" ");
2700             ol.startMemberDocPrefixItem();
2701             writeTemplatePrefix(ol,tal);
2702             ol.endMemberDocPrefixItem();
2703           }
2704         }
2705       }
2706       else // definition gets it template parameters from its class
2707         // (since no definition was found)
2708       {
2709         if (cd && lang==SrcLangExt_Cpp && !isTemplateSpecialization())
2710         {
2711           QList<ArgumentList> tempParamLists;
2712           cd->getTemplateParameterLists(tempParamLists);
2713           //printf("#tempParamLists=%d\n",tempParamLists.count());
2714           QListIterator<ArgumentList> ali(tempParamLists);
2715           ArgumentList *tal;
2716           for (ali.toFirst();(tal=ali.current());++ali)
2717           {
2718             if (tal->count()>0)
2719             {
2720               if (!first) ol.docify(" ");
2721               ol.startMemberDocPrefixItem();
2722               writeTemplatePrefix(ol,tal);
2723               ol.endMemberDocPrefixItem();
2724             }
2725           }
2726         }
2727         if (m_impl->tArgList && lang==SrcLangExt_Cpp) // function template prefix
2728         {
2729           ol.startMemberDocPrefixItem();
2730           writeTemplatePrefix(ol,m_impl->tArgList);
2731           ol.endMemberDocPrefixItem();
2732         }
2733       }
2734     }
2735
2736     if (sl.count()>0)
2737     {
2738       ol.pushGeneratorState();
2739       ol.disableAll();
2740       ol.enable(OutputGenerator::Html);
2741       ol.writeString("<table class=\"mlabels\">\n");
2742       ol.writeString("  <tr>\n");
2743       ol.writeString("  <td class=\"mlabels-left\">\n");
2744       ol.popGeneratorState();
2745       htmlEndLabelTable=TRUE;
2746     }
2747
2748     ol.startMemberDocName(isObjCMethod());
2749     if (cd && cd->isObjectiveC())
2750     {
2751       // strip scope name
2752       int ep = ldef.find("::");
2753       if (ep!=-1)
2754       {
2755         int sp=ldef.findRev(' ',ep);
2756         if (sp!=-1)
2757         {
2758           ldef=ldef.left(sp+1)+ldef.mid(ep+2);
2759         } else {
2760           ldef=ldef.mid(ep+2);
2761         }
2762       }
2763       // strip keywords
2764       int dp = ldef.find(':');
2765       if (dp!=-1)
2766       {
2767         ldef=ldef.left(dp+1);
2768       }
2769       int l=ldef.length();
2770       //printf("start >%s<\n",ldef.data());
2771       int i=l-1;
2772       while (i>=0 && (isId(ldef.at(i)) || ldef.at(i)==':')) i--;
2773       while (i>=0 && isspace((uchar)ldef.at(i))) i--;
2774       if (i>0)
2775       {
2776         // insert braches around the type
2777         QCString tmp("("+ldef.left(i+1)+")"+ldef.mid(i+1));
2778         ldef=tmp;
2779       }
2780       //printf("end   >%s< i=%d\n",ldef.data(),i);
2781       if (isStatic()) ldef.prepend("+ "); else ldef.prepend("- ");
2782     }
2783
2784     if (optVhdl)
2785     {
2786       hasParameterList=VhdlDocGen::writeVHDLTypeDocumentation(this,scopedContainer,ol);
2787     }
2788     else
2789     {
2790       linkifyText(TextGeneratorOLImpl(ol),
2791                   scopedContainer,
2792                   getBodyDef(),
2793                   this,
2794                   substitute(ldef,"::",sep)
2795                  );
2796       Definition *scope = cd;
2797       if (scope==0) scope = nd;
2798       hasParameterList=writeDefArgumentList(ol,scope,this);
2799     }
2800
2801     if (hasOneLineInitializer()) // add initializer
2802     {
2803       if (!isDefine())
2804       {
2805         //ol.docify(" = ");
2806         ol.docify(" ");
2807         QCString init = m_impl->initializer.simplifyWhiteSpace();
2808         linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,init);
2809       }
2810       else
2811       {
2812         ol.writeNonBreakableSpace(3);
2813         linkifyText(TextGeneratorOLImpl(ol),scopedContainer,getBodyDef(),this,m_impl->initializer);
2814       }
2815     }
2816     if (excpString()) // add exception list
2817     {
2818       writeExceptionList(ol,cd,this);
2819       hasParameterList=true; // call endParameterList below
2820     }
2821   }
2822
2823   ol.pushGeneratorState();
2824   ol.disable(OutputGenerator::Html);
2825   if (sl.count()>0)
2826   {
2827     ol.startLabels();
2828     const char *s=sl.first();
2829     while (s)
2830     {
2831       const char *ns = sl.next();
2832       ol.writeLabel(s,ns==0);
2833       s=ns;
2834     }
2835     ol.endLabels();
2836   }
2837   ol.popGeneratorState();
2838
2839   if (hasParameterList)
2840   {
2841     ol.endParameterList();
2842     ol.endMemberDoc(TRUE);
2843   }
2844   else
2845   {
2846     ol.endMemberDocName();
2847     ol.endMemberDoc(FALSE);
2848   }
2849
2850   // for HTML write the labels here
2851   ol.pushGeneratorState();
2852   ol.disableAll();
2853   ol.enable(OutputGenerator::Html);
2854   if (htmlEndLabelTable)
2855   {
2856     ol.writeString("  </td>\n");
2857     ol.writeString("  <td class=\"mlabels-right\">\n");
2858     ol.startLabels();
2859     const char *s=sl.first();
2860     while (s)
2861     {
2862       const char *ns = sl.next();
2863       ol.writeLabel(s,ns==0);
2864       s=ns;
2865     }
2866     ol.endLabels();
2867     ol.writeString("  </td>\n");
2868     ol.writeString("  </tr>\n");
2869     ol.writeString("</table>\n");
2870   }
2871   ol.writeString("</div>");
2872   ol.popGeneratorState();
2873
2874
2875   ol.endDoxyAnchor(cfname,memAnchor);
2876   ol.startIndent();
2877
2878   _writeGroupInclude(ol,inGroup);
2879
2880   /* write multi-line initializer (if any) */
2881   if (hasMultiLineInitializer()
2882       //initLines>0 && ((initLines<maxInitLines && userInitLines==-1) // implicitly enabled
2883       //                || initLines<userInitLines // explicitly enabled
2884       //               )
2885      )
2886   {
2887     //printf("md=%s initLines=%d init=`%s'\n",name().data(),initLines,init.data());
2888     ol.startBold();
2889     if (m_impl->mtype==MemberType_Define)
2890       ol.parseText(theTranslator->trDefineValue());
2891     else
2892       ol.parseText(theTranslator->trInitialValue());
2893     ol.endBold();
2894     ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension());
2895     pIntf->resetCodeParserState();
2896     ol.startCodeFragment();
2897     pIntf->parseCode(ol,scopeName,m_impl->initializer,lang,FALSE,0,getFileDef(),
2898                      -1,-1,TRUE,this,FALSE,this);
2899     ol.endCodeFragment();
2900   }
2901
2902   QCString brief           = briefDescription();
2903   QCString detailed        = documentation();
2904   ArgumentList *docArgList = m_impl->defArgList;
2905   if (m_impl->templateMaster)
2906   {
2907     brief      = m_impl->templateMaster->briefDescription();
2908     detailed   = m_impl->templateMaster->documentation();
2909     docArgList = m_impl->templateMaster->argumentList();
2910   }
2911
2912   /* write brief description */
2913   if (!brief.isEmpty() &&
2914       (Config_getBool(REPEAT_BRIEF) ||
2915        !Config_getBool(BRIEF_MEMBER_DESC)
2916       )
2917      )
2918   {
2919     ol.startParagraph();
2920     ol.generateDoc(briefFile(),briefLine(),
2921                 scopedContainer,this,
2922                 brief,FALSE,FALSE,0,TRUE,FALSE);
2923     ol.endParagraph();
2924   }
2925
2926   /* write detailed description */
2927   if (!detailed.isEmpty() ||
2928       !inbodyDocumentation().isEmpty())
2929   {
2930     // write vhdl inline code with or without option INLINE_SOURCE
2931     if (optVhdl && VhdlDocGen::isMisc(this))
2932     {
2933       VhdlDocGen::writeSource(this,ol,cname);
2934       return;
2935     }
2936     else
2937     {
2938       ol.generateDoc(docFile(),docLine(),scopedContainer,this,detailed+"\n",TRUE,FALSE);
2939     }
2940
2941     if (!inbodyDocumentation().isEmpty())
2942     {
2943       ol.generateDoc(inbodyFile(),inbodyLine(),
2944                   scopedContainer,this,
2945                   inbodyDocumentation()+"\n",TRUE,FALSE);
2946     }
2947   }
2948   else if (!brief.isEmpty() && (Config_getBool(REPEAT_BRIEF) ||
2949         !Config_getBool(BRIEF_MEMBER_DESC)))
2950   {
2951     if (!inbodyDocumentation().isEmpty())
2952     {
2953       ol.generateDoc(inbodyFile(),inbodyLine(),scopedContainer,this,inbodyDocumentation()+"\n",TRUE,FALSE);
2954     }
2955   }
2956
2957
2958   //printf("***** defArgList=%p name=%s docs=%s hasDocs=%d\n",
2959   //     defArgList,
2960   //     defArgList?defArgList->hasDocumentation():-1);
2961   if (docArgList!=0 && docArgList->hasDocumentation())
2962   {
2963     QCString paramDocs;
2964     ArgumentListIterator ali(*docArgList);
2965     Argument *a;
2966     // convert the parameter documentation into a list of @param commands
2967     for (ali.toFirst();(a=ali.current());++ali)
2968     {
2969       if (a->hasDocumentation())
2970       {
2971         QCString direction = extractDirection(a->docs);
2972         paramDocs+="@param"+direction+" "+a->name+" "+a->docs;
2973       }
2974     }
2975     // feed the result to the documentation parser
2976     ol.generateDoc(
2977         docFile(),docLine(),
2978         scopedContainer,
2979         this,         // memberDef
2980         paramDocs,    // docStr
2981         TRUE,         // indexWords
2982         FALSE         // isExample
2983         );
2984
2985   }
2986
2987   _writeEnumValues(ol,scopedContainer,cfname,ciname,cname);
2988   _writeReimplements(ol);
2989   _writeReimplementedBy(ol);
2990   _writeCategoryRelation(ol);
2991   _writeExamples(ol);
2992   _writeTypeConstraints(ol);
2993   writeSourceDef(ol,cname);
2994   writeSourceRefs(ol,cname);
2995   writeSourceReffedBy(ol,cname);
2996   writeInlineCode(ol,cname);
2997   _writeCallGraph(ol);
2998   _writeCallerGraph(ol);
2999
3000   if (Doxygen::userComments)
3001   {
3002     ol.pushGeneratorState();
3003     ol.disableAllBut(OutputGenerator::Html);
3004     QCString cmd = "<? $root=$_SERVER['DOCUMENT_ROOT']; "
3005                    "passthru(\"$root/doxynotes --lookup "+
3006                    getOutputFileBase()+":"+anchor()+"\") ?>";
3007     ol.writeString(cmd);
3008     ol.popGeneratorState();
3009   }
3010
3011   ol.endIndent();
3012
3013   // enable LaTeX again
3014   //if (Config_getBool(EXTRACT_ALL) && !hasDocs) ol.enable(OutputGenerator::Latex);
3015   ol.popGeneratorState();
3016
3017   warnIfUndocumentedParams();
3018 }
3019
3020 // strip scope and field name from the type
3021 // example: "struct N::S.v.c" will become "struct v"
3022 static QCString simplifyTypeForTable(const QCString &s)
3023 {
3024   QCString ts=removeAnonymousScopes(s);
3025   if (ts.right(2)=="::") ts = ts.left(ts.length()-2);
3026   static QRegExp re("[A-Z_a-z0-9]+::");
3027   int i,l;
3028   while ((i=re.match(ts,0,&l))!=-1)
3029   {
3030     ts=ts.left(i)+ts.mid(i+l);
3031   }
3032   i=ts.findRev('.');
3033   if (i!=-1) ts = ts.left(i);
3034   i=ts.findRev('.');
3035   if (i!=-1) ts = ts.right(ts.length()-i-1);
3036   //printf("simplifyTypeForTable(%s)->%s\n",s.data(),ts.data());
3037   return ts;
3038 }
3039
3040 #if 0
3041 /** Returns the type definition corresponding to a member's return type.
3042  *  @param[in]  scope The scope in which to search for the class definition.
3043  *  @param[in]  type  The string representing the member's return type.
3044  *  @param[in]  lang  The programming language in which the class is defined.
3045  *  @param[out] start The string position where the class definition name was found.
3046  *  @param[out] length The length of the class definition's name.
3047  */
3048 static Definition *getClassFromType(Definition *scope,const QCString &type,SrcLangExt lang,int &start,int &length)
3049 {
3050   int pos=0;
3051   int i;
3052   QCString name;
3053   QCString templSpec;
3054   while ((i=extractClassNameFromType(type,pos,name,templSpec,lang))!=-1)
3055   {
3056     ClassDef *cd=0;
3057     MemberDef *md=0;
3058     int l = name.length()+templSpec.length();
3059     if (!templSpec.isEmpty())
3060     {
3061       cd = getResolvedClass(scope,0,name+templSpec,&md);
3062     }
3063     cd = getResolvedClass(scope,0,name);
3064     if (cd)
3065     {
3066       start=i;
3067       length=l;
3068       printf("getClassFromType: type=%s name=%s start=%d length=%d\n",type.data(),name.data(),start,length);
3069       return cd;
3070     }
3071     else if (md)
3072     {
3073       start=i;
3074       length=l;
3075       printf("getClassFromType: type=%s name=%s start=%d length=%d\n",type.data(),name.data(),start,length);
3076       return md;
3077     }
3078     pos=i+l;
3079   }
3080   return 0;
3081 }
3082 #endif
3083
3084 QCString MemberDef::fieldType() const
3085 {
3086   QCString type = m_impl->accessorType;
3087   if (type.isEmpty())
3088   {
3089     type = m_impl->type;
3090   }
3091
3092   if (isTypedef()) type.prepend("typedef ");
3093   return simplifyTypeForTable(type);
3094 }
3095
3096 void MemberDef::writeMemberDocSimple(OutputList &ol, Definition *container)
3097 {
3098   Definition *scope  = getOuterScope();
3099   QCString doxyName  = name();
3100   QCString doxyArgs  = argsString();
3101   QCString memAnchor = anchor();
3102   QCString cfname    = getOutputFileBase();
3103   QCString cname;
3104   if (scope) cname   = scope->name();
3105   if (doxyName.at(0)=='@')
3106   {
3107     doxyName="__unnamed__";
3108   }
3109
3110   ClassDef *cd = m_impl->accessorClass;
3111   //printf("===> %s::anonymous: %s\n",name().data(),cd?cd->name().data():"<none>");
3112
3113   if (container && container->definitionType()==Definition::TypeClass &&
3114       !((ClassDef*)container)->isJavaEnum())
3115   {
3116     ol.startInlineMemberType();
3117     ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs);
3118
3119     QCString ts = fieldType();
3120
3121     if (cd) // cd points to an anonymous struct pointed to by this member
3122       // so we add a link to it from the type column.
3123     {
3124       int i=0;
3125       const char *prefixes[] = { "struct ","union ","class ", 0 };
3126       const char **p = prefixes;
3127       while (*p)
3128       {
3129         int l=qstrlen(*p);
3130         if (ts.left(l)==*p)
3131         {
3132           ol.writeString(*p);
3133           i=l;
3134         }
3135         p++;
3136       }
3137       ol.writeObjectLink(cd->getReference(),
3138           cd->getOutputFileBase(),
3139           cd->anchor(),ts.mid(i));
3140     }
3141     else // use standard auto linking
3142     {
3143       linkifyText(TextGeneratorOLImpl(ol), // out
3144           scope,                   // scope
3145           getBodyDef(),            // fileScope
3146           this,                    // self
3147           ts                       // text
3148           );
3149     }
3150     ol.endDoxyAnchor(cfname,memAnchor);
3151     ol.endInlineMemberType();
3152   }
3153
3154   ol.startInlineMemberName();
3155   ol.docify(doxyName);
3156   if (isVariable() && argsString() && !isObjCMethod())
3157   {
3158     linkifyText(TextGeneratorOLImpl(ol),getOuterScope(),getBodyDef(),this,argsString());
3159   }
3160   if (!m_impl->bitfields.isEmpty()) // add bitfields
3161   {
3162     linkifyText(TextGeneratorOLImpl(ol),getOuterScope(),getBodyDef(),this,m_impl->bitfields);
3163   }
3164   ol.endInlineMemberName();
3165
3166   ol.startInlineMemberDoc();
3167
3168   QCString brief           = briefDescription();
3169   QCString detailed        = documentation();
3170
3171   /* write brief description */
3172   if (!brief.isEmpty())
3173   {
3174     ol.generateDoc(briefFile(),briefLine(),
3175                 getOuterScope()?getOuterScope():container,this,
3176                 brief,FALSE,FALSE,0,TRUE,FALSE);
3177   }
3178
3179   /* write detailed description */
3180   if (!detailed.isEmpty())
3181   {
3182     ol.generateDoc(docFile(),docLine(),
3183                 getOuterScope()?getOuterScope():container,this,
3184                 detailed+"\n",FALSE,FALSE,0,FALSE,FALSE);
3185
3186   }
3187
3188   ol.endInlineMemberDoc();
3189 }
3190
3191 QCString MemberDef::memberTypeName() const
3192 {
3193   switch (m_impl->mtype)
3194   {
3195     case MemberType_Define:      return "macro definition";
3196     case MemberType_Function:    return "function";
3197     case MemberType_Variable:    return "variable";
3198     case MemberType_Typedef:     return "typedef";
3199     case MemberType_Enumeration: return "enumeration";
3200     case MemberType_EnumValue:   return "enumvalue";
3201     case MemberType_Signal:      return "signal";
3202     case MemberType_Slot:        return "slot";
3203     case MemberType_Friend:      return "friend";
3204     case MemberType_DCOP:        return "dcop";
3205     case MemberType_Property:    return "property";
3206     case MemberType_Event:       return "event";
3207     case MemberType_Interface:   return "interface";
3208     case MemberType_Service:     return "service";
3209     default:          return "unknown";
3210   }
3211 }
3212
3213 void MemberDef::warnIfUndocumented()
3214 {
3215   if (m_impl->memberGroup) return;
3216   ClassDef     *cd = getClassDef();
3217   NamespaceDef *nd = getNamespaceDef();
3218   FileDef      *fd = getFileDef();
3219   GroupDef     *gd = getGroupDef();
3220   Definition *d=0;
3221   const char *t=0;
3222   if (cd)
3223     t="class", d=cd;
3224   else if (nd)
3225   {
3226     d=nd;
3227     if (d->getLanguage() == SrcLangExt_Fortran)
3228       t="module";
3229     else
3230       t="namespace";
3231   }
3232   else if (gd)
3233     t="group", d=gd;
3234   else
3235     t="file", d=fd;
3236   static bool extractAll = Config_getBool(EXTRACT_ALL);
3237
3238   //printf("%s:warnIfUndoc: hasUserDocs=%d isFriendClass=%d protection=%d isRef=%d isDel=%d\n",
3239   //    name().data(),
3240   //    hasUserDocumentation(),isFriendClass(),protectionLevelVisible(m_impl->prot),isReference(),isDeleted());
3241   if ((!hasUserDocumentation() && !extractAll) &&
3242       !isFriendClass() &&
3243       name().find('@')==-1 && d && d->name().find('@')==-1 &&
3244       protectionLevelVisible(m_impl->prot) &&
3245       !isReference() && !isDeleted()
3246      )
3247   {
3248     warn_undoc(getDefFileName(),getDefLine(),"Member %s%s (%s) of %s %s is not documented.",
3249          qPrint(name()),qPrint(argsString()),qPrint(memberTypeName()),t,qPrint(d->name()));
3250   }
3251   else if (!isDetailedSectionLinkable())
3252   {
3253     warnIfUndocumentedParams();
3254   }
3255 }
3256
3257
3258 void MemberDef::warnIfUndocumentedParams()
3259 {
3260   if (!Config_getBool(EXTRACT_ALL) &&
3261       Config_getBool(WARN_IF_UNDOCUMENTED) &&
3262       Config_getBool(WARN_NO_PARAMDOC) &&
3263       !isReference() &&
3264       !Doxygen::suppressDocWarnings)
3265   {
3266     if (!hasDocumentedParams())
3267     {
3268       warn_doc_error(getDefFileName(),getDefLine(),
3269           "parameters of member %s are not (all) documented",
3270           qPrint(qualifiedName()));
3271     }
3272     if (!hasDocumentedReturnType() &&
3273         isFunction() && hasDocumentation())
3274     {
3275       warn_doc_error(getDefFileName(),getDefLine(),
3276           "return type of member %s is not documented",
3277           qPrint(qualifiedName()));
3278     }
3279   }
3280 }
3281
3282 bool MemberDef::isFriendClass() const
3283 {
3284   return (isFriend() &&
3285          (m_impl->type=="friend class" || m_impl->type=="friend struct" ||
3286           m_impl->type=="friend union"));
3287 }
3288
3289 bool MemberDef::isDocumentedFriendClass() const
3290 {
3291   ClassDef *fcd=0;
3292   QCString baseName=name();
3293   int i=baseName.find('<');
3294   if (i!=-1) baseName=baseName.left(i);
3295   return (isFriendClass() &&
3296          (fcd=getClass(baseName)) && fcd->isLinkable());
3297 }
3298
3299 bool MemberDef::isDeleted() const
3300 {
3301   return m_impl->defArgList && m_impl->defArgList->isDeleted;
3302 }
3303
3304 bool MemberDef::hasDocumentation() const
3305 {
3306   return Definition::hasDocumentation() ||
3307          (m_impl->mtype==MemberType_Enumeration && m_impl->docEnumValues) ||  // has enum values
3308          (m_impl->defArgList!=0 && m_impl->defArgList->hasDocumentation());   // has doc arguments
3309 }
3310
3311 #if 0
3312 bool MemberDef::hasUserDocumentation() const
3313 {
3314   bool hasDocs = Definition::hasUserDocumentation();
3315   return hasDocs;
3316 }
3317 #endif
3318
3319
3320 void MemberDef::setMemberGroup(MemberGroup *grp)
3321 {
3322   m_impl->memberGroup = grp;
3323 }
3324
3325 bool MemberDef::visibleMemberGroup(bool hideNoHeader)
3326 {
3327   return m_impl->memberGroup!=0 &&
3328           (!hideNoHeader || m_impl->memberGroup->header()!="[NOHEADER]");
3329 }
3330
3331 QCString MemberDef::getScopeString() const
3332 {
3333   QCString result;
3334   if (getClassDef()) result=getClassDef()->displayName();
3335   else if (getNamespaceDef()) result=getNamespaceDef()->displayName();
3336   return result;
3337 }
3338
3339 #if 0
3340 static QCString escapeAnchor(const QCString &anchor)
3341 {
3342   QCString result;
3343   int l = anchor.length(),i;
3344   for (i=0;i<l;i++)
3345   {
3346     char c = anchor.at(i);
3347     if ((c>='a' && c<='z') || (c>='A' && c<='Z'))
3348     {
3349       result+=c;
3350     }
3351     else
3352     {
3353       static char hexStr[]="0123456789ABCDEF";
3354       char escChar[]={ '_', 0, 0, 0 };
3355       escChar[1]=hexStr[c>>4];
3356       escChar[2]=hexStr[c&0xf];
3357       result+=escChar;
3358     }
3359   }
3360   return result;
3361 }
3362 #endif
3363
3364 void MemberDef::setAnchor()
3365 {
3366   QCString memAnchor = name();
3367   if (!m_impl->args.isEmpty()) memAnchor+=m_impl->args;
3368
3369   memAnchor.prepend(definition()); // actually the method name is now included
3370             // twice, which is silly, but we keep it this way for backward
3371             // compatibility.
3372
3373   // include number of template arguments as well,
3374   // to distinguish between two template
3375   // specializations that only differ in the template parameters.
3376   if (m_impl->tArgList)
3377   {
3378     char buf[20];
3379     qsnprintf(buf,20,"%d:",m_impl->tArgList->count());
3380     buf[19]='\0';
3381     memAnchor.prepend(buf);
3382   }
3383
3384   // convert to md5 hash
3385   uchar md5_sig[16];
3386   QCString sigStr(33);
3387   MD5Buffer((const unsigned char *)memAnchor.data(),memAnchor.length(),md5_sig);
3388   //printf("memAnchor=%s\n",memAnchor.data());
3389   MD5SigToString(md5_sig,sigStr.rawData(),33);
3390   m_impl->anc = "a"+sigStr;
3391 }
3392
3393 void MemberDef::setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri,
3394                             const QCString &fileName,int startLine,
3395                             bool hasDocs,MemberDef *member)
3396 {
3397   //printf("%s MemberDef::setGroupDef(%s)\n",name().data(),gd->name().data());
3398   m_impl->group=gd;
3399   m_impl->grouppri=pri;
3400   m_impl->groupFileName=fileName;
3401   m_impl->groupStartLine=startLine;
3402   m_impl->groupHasDocs=hasDocs;
3403   m_impl->groupMember=member;
3404   m_isLinkableCached = 0;
3405 }
3406
3407 void MemberDef::setEnumScope(MemberDef *md,bool livesInsideEnum)
3408 {
3409   m_impl->enumScope=md;
3410   m_impl->livesInsideEnum=livesInsideEnum;
3411   if (md->getGroupDef())
3412   {
3413     m_impl->group=md->getGroupDef();
3414     m_impl->grouppri=md->getGroupPri();
3415     m_impl->groupFileName=md->getGroupFileName();
3416     m_impl->groupStartLine=md->getGroupStartLine();
3417     m_impl->groupHasDocs=md->getGroupHasDocs();
3418     m_isLinkableCached = 0;
3419   }
3420 }
3421
3422 void MemberDef::setMemberClass(ClassDef *cd)
3423 {
3424   m_impl->classDef=cd;
3425   m_isLinkableCached = 0;
3426   m_isConstructorCached = 0;
3427   setOuterScope(cd);
3428 }
3429
3430 void MemberDef::setNamespace(NamespaceDef *nd)
3431 {
3432   m_impl->nspace=nd;
3433   setOuterScope(nd);
3434 }
3435
3436 MemberDef *MemberDef::createTemplateInstanceMember(
3437         ArgumentList *formalArgs,ArgumentList *actualArgs)
3438 {
3439   //printf("  Member %s %s %s\n",typeString(),name().data(),argsString());
3440   ArgumentList *actualArgList = 0;
3441   if (m_impl->defArgList)
3442   {
3443     actualArgList = m_impl->defArgList->deepCopy();
3444
3445     // replace formal arguments with actuals
3446     ArgumentListIterator ali(*actualArgList);
3447     Argument *arg;
3448     for (;(arg=ali.current());++ali)
3449     {
3450       arg->type = substituteTemplateArgumentsInString(arg->type,formalArgs,actualArgs);
3451     }
3452     actualArgList->trailingReturnType =
3453        substituteTemplateArgumentsInString(actualArgList->trailingReturnType,formalArgs,actualArgs);
3454   }
3455
3456   QCString methodName=name();
3457   if (methodName.left(9)=="operator ") // conversion operator
3458   {
3459     methodName=substituteTemplateArgumentsInString(methodName,formalArgs,actualArgs);
3460   }
3461
3462   MemberDef *imd = new MemberDef(
3463                        getDefFileName(),getDefLine(),getDefColumn(),
3464                        substituteTemplateArgumentsInString(m_impl->type,formalArgs,actualArgs),
3465                        methodName,
3466                        substituteTemplateArgumentsInString(m_impl->args,formalArgs,actualArgs),
3467                        m_impl->exception, m_impl->prot,
3468                        m_impl->virt, m_impl->stat, m_impl->related, m_impl->mtype, 0, 0
3469                    );
3470   imd->setArgumentList(actualArgList);
3471   imd->setDefinition(substituteTemplateArgumentsInString(m_impl->def,formalArgs,actualArgs));
3472   imd->setBodyDef(getBodyDef());
3473   imd->setBodySegment(getStartBodyLine(),getEndBodyLine());
3474   //imd->setBodyMember(this);
3475
3476   // TODO: init other member variables (if needed).
3477   // TODO: reimplemented info
3478   return imd;
3479 }
3480
3481 bool MemberDef::hasOneLineInitializer() const
3482 {
3483   //printf("%s: init=%s, initLines=%d maxInitLines=%d userInitLines=%d\n",
3484   //    name().data(),m_impl->initializer.data(),m_impl->initLines,
3485   //    m_impl->maxInitLines,m_impl->userInitLines);
3486   return !m_impl->initializer.isEmpty() && m_impl->initLines==0 && // one line initializer
3487          ((m_impl->maxInitLines>0 && m_impl->userInitLines==-1) || m_impl->userInitLines>0); // enabled by default or explicitly
3488 }
3489
3490 bool MemberDef::hasMultiLineInitializer() const
3491 {
3492   //printf("initLines=%d userInitLines=%d maxInitLines=%d\n",
3493   //    initLines,userInitLines,maxInitLines);
3494   return m_impl->initLines>0 &&
3495          ((m_impl->initLines<m_impl->maxInitLines && m_impl->userInitLines==-1) // implicitly enabled
3496           || m_impl->initLines<m_impl->userInitLines // explicitly enabled
3497          );
3498 }
3499
3500 void MemberDef::setInitializer(const char *initializer)
3501 {
3502   m_impl->initializer=initializer;
3503   int l=m_impl->initializer.length();
3504   int p=l-1;
3505   while (p>=0 && isspace((uchar)m_impl->initializer.at(p))) p--;
3506   m_impl->initializer=m_impl->initializer.left(p+1);
3507   m_impl->initLines=m_impl->initializer.contains('\n');
3508   //printf("%s::setInitializer(%s)\n",name().data(),m_impl->initializer.data());
3509 }
3510
3511 void MemberDef::addListReference(Definition *)
3512 {
3513   static bool optimizeOutputForC = Config_getBool(OPTIMIZE_OUTPUT_FOR_C);
3514   //static bool hideScopeNames     = Config_getBool(HIDE_SCOPE_NAMES);
3515   //static bool optimizeOutputJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA);
3516   //static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN);
3517   SrcLangExt lang = getLanguage();
3518   visited=TRUE;
3519   if (!isLinkableInProject()) return;
3520   QCString memLabel;
3521   if (optimizeOutputForC)
3522   {
3523     memLabel=theTranslator->trGlobal(TRUE,TRUE);
3524   }
3525   else if (lang==SrcLangExt_Fortran)
3526   {
3527     memLabel=theTranslator->trSubprogram(TRUE,TRUE);
3528   }
3529   else
3530   {
3531     memLabel=theTranslator->trMember(TRUE,TRUE);
3532   }
3533   QCString memName = name();
3534   Definition *pd=getOuterScope();
3535   QCString pdName = pd->definitionType()==Definition::TypeClass ?
3536                     ((ClassDef*)pd)->displayName() : pd->name();
3537   QCString sep = getLanguageSpecificSeparator(lang,TRUE);
3538   QCString memArgs;
3539   if (!isRelated()
3540       /* && commented out as a result of bug 597016
3541       (
3542        (!hideScopeNames &&                    // there is a scope
3543         pd && pd!=Doxygen::globalScope)       // and we can show it
3544        ||
3545        (pd=getClassDef())                     // it's a class so we
3546                                               // show the scope anyway
3547       )
3548       */
3549      )
3550   {
3551     if (isObjCMethod())
3552     {
3553       memName = "[" + pd->name() + " " + name() + "]";
3554     }
3555     else
3556     {
3557       if (pd!=Doxygen::globalScope) memName.prepend(pdName+sep);
3558       memArgs = argsString();
3559     }
3560   }
3561   QList<ListItemInfo> *xrefItems = xrefListItems();
3562   if (xrefItems)
3563   {
3564     addRefItem(xrefItems,
3565         qualifiedName()+argsString(), // argsString is needed for overloaded functions (see bug 609624)
3566         memLabel,
3567         getOutputFileBase()+"#"+anchor(),memName,memArgs,pd);
3568   }
3569 }
3570
3571 MemberList *MemberDef::getSectionList(Definition *d) const
3572 {
3573   char key[20];
3574   sprintf(key,"%p",d);
3575   return (d!=0 && m_impl->classSectionSDict) ? m_impl->classSectionSDict->find(key) : 0;
3576 }
3577
3578 void MemberDef::setSectionList(Definition *d, MemberList *sl)
3579 {
3580   //printf("MemberDef::setSectionList(%p,%p) name=%s\n",d,sl,name().data());
3581   char key[20];
3582   sprintf(key,"%p",d);
3583   if (m_impl->classSectionSDict==0)
3584   {
3585     m_impl->classSectionSDict = new SDict<MemberList>(7);
3586   }
3587   m_impl->classSectionSDict->append(key,sl);
3588 }
3589
3590 Specifier MemberDef::virtualness(int count) const
3591 {
3592   if (count>25)
3593   {
3594      warn(getDefFileName(),getDefLine(),
3595        "Internal inconsistency: recursion detected in overload relation for member %s!"
3596        ,qPrint(name())
3597       );
3598      return Normal;
3599   }
3600   Specifier v = m_impl->virt;
3601   MemberDef *rmd = reimplements();
3602   while (rmd && v==Normal)
3603   {
3604     v = rmd->virtualness(count+1)==Normal ? Normal : Virtual;
3605     rmd = rmd->reimplements();
3606   }
3607   return v;
3608 }
3609
3610 void MemberDef::writeTagFile(FTextStream &tagFile)
3611 {
3612   if (!isLinkableInProject()) return;
3613   tagFile << "    <member kind=\"";
3614   switch (m_impl->mtype)
3615   {
3616     case MemberType_Define:      tagFile << "define";      break;
3617     case MemberType_EnumValue:   tagFile << "enumvalue";   break;
3618     case MemberType_Property:    tagFile << "property";    break;
3619     case MemberType_Event:       tagFile << "event";       break;
3620     case MemberType_Variable:    tagFile << "variable";    break;
3621     case MemberType_Typedef:     tagFile << "typedef";     break;
3622     case MemberType_Enumeration: tagFile << "enumeration"; break;
3623     case MemberType_Function:    tagFile << "function";    break;
3624     case MemberType_Signal:      tagFile << "signal";      break;
3625     case MemberType_Friend:      tagFile << "friend";      break;
3626     case MemberType_DCOP:        tagFile << "dcop";        break;
3627     case MemberType_Slot:        tagFile << "slot";        break;
3628     case MemberType_Interface:   tagFile << "interface";   break;
3629     case MemberType_Service:     tagFile << "service";     break;
3630   }
3631   if (m_impl->prot!=Public)
3632   {
3633     tagFile << "\" protection=\"";
3634     if (m_impl->prot==Protected)    tagFile << "protected";
3635     else if (m_impl->prot==Package) tagFile << "package";
3636     else /* Private */              tagFile << "private";
3637   }
3638   if (m_impl->virt!=Normal)
3639   {
3640     tagFile << "\" virtualness=\"";
3641     if (m_impl->virt==Virtual) tagFile << "virtual";
3642     else /* Pure */            tagFile << "pure";
3643   }
3644   if (isStatic())
3645   {
3646     tagFile << "\" static=\"yes";
3647   }
3648   tagFile << "\">" << endl;
3649   if (typeString()!=QCString("@"))
3650   {
3651     tagFile << "      <type>" << convertToXML(typeString()) << "</type>" << endl;
3652   }
3653   tagFile << "      <name>" << convertToXML(name()) << "</name>" << endl;
3654   tagFile << "      <anchorfile>" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension) << "</anchorfile>" << endl;
3655   tagFile << "      <anchor>" << convertToXML(anchor()) << "</anchor>" << endl;
3656   QCString idStr = id();
3657   if (!idStr.isEmpty())
3658   {
3659     tagFile << "      <clangid>" << convertToXML(idStr) << "</clangid>" << endl;
3660   }
3661   tagFile << "      <arglist>" << convertToXML(argsString()) << "</arglist>" << endl;
3662   if (isStrong())
3663   {
3664     MemberList *fmdl=m_impl->enumFields;
3665     if (fmdl)
3666     {
3667       MemberListIterator mli(*fmdl);
3668       MemberDef *fmd;
3669       for (mli.toFirst();(fmd=mli.current());++mli)
3670       {
3671         if (!fmd->isReference())
3672         {
3673           tagFile << "      <enumvalue file=\"" << convertToXML(getOutputFileBase()+Doxygen::htmlFileExtension);
3674           tagFile << "\" anchor=\"" << convertToXML(fmd->anchor());
3675           QCString idStr = fmd->id();
3676           if (!idStr.isEmpty())
3677           {
3678             tagFile << "\" clangid=\"" << convertToXML(idStr);
3679           }
3680           tagFile  << "\">" << convertToXML(fmd->name()) << "</enumvalue>" << endl;
3681         }
3682       }
3683     }
3684   }
3685   writeDocAnchorsToTagFile(tagFile);
3686   tagFile << "    </member>" << endl;
3687 }
3688
3689 void MemberDef::_computeIsConstructor()
3690 {
3691   m_isConstructorCached=1; // FALSE
3692   if (m_impl->classDef)
3693   {
3694     if (m_impl->isDMember) // for D
3695     {
3696       m_isConstructorCached = name()=="this" ? 2 : 1;
3697       return;
3698     }
3699     else if (getLanguage()==SrcLangExt_PHP) // for PHP
3700     {
3701       m_isConstructorCached = name()=="__construct" ? 2 : 1;
3702       return;
3703     }
3704     else if (name()=="__init__" &&
3705              getLanguage()==SrcLangExt_Python) // for Python
3706     {
3707       m_isConstructorCached = 2; // TRUE
3708       return;
3709     }
3710     else if (getLanguage()==SrcLangExt_Tcl) // for Tcl
3711     {
3712       m_isConstructorCached = name()=="constructor" ? 2 : 1;
3713       return;
3714     }
3715     else // for other languages
3716     {
3717       QCString locName = m_impl->classDef->localName();
3718       int i=locName.find('<');
3719       if (i==-1) // not a template class
3720       {
3721         m_isConstructorCached = name()==locName ? 2 : 1;
3722       }
3723       else
3724       {
3725         m_isConstructorCached = name()==locName.left(i) ? 2 : 1;
3726       }
3727       return;
3728     }
3729   }
3730 }
3731
3732 bool MemberDef::isConstructor() const
3733 {
3734   if (m_isConstructorCached==0)
3735   {
3736     MemberDef *that = (MemberDef*)this;
3737     that->_computeIsConstructor();
3738   }
3739   ASSERT(m_isConstructorCached>0);
3740   return m_isConstructorCached==2;
3741
3742 }
3743
3744 void MemberDef::_computeIsDestructor()
3745 {
3746   bool isDestructor;
3747   if (m_impl->isDMember) // for D
3748   {
3749     isDestructor = name()=="~this";
3750   }
3751   else if (getLanguage()==SrcLangExt_PHP) // for PHP
3752   {
3753     isDestructor = name()=="__destruct";
3754   }
3755   else if (getLanguage()==SrcLangExt_Tcl) // for Tcl
3756   {
3757     isDestructor = name()=="destructor";
3758   }
3759   else if (name()=="__del__" &&
3760            getLanguage()==SrcLangExt_Python) // for Python
3761   {
3762     isDestructor=TRUE;
3763   }
3764   else // other languages
3765   {
3766     isDestructor =
3767            (name().find('~')!=-1 || name().find('!')!=-1)  // The ! is for C++/CLI
3768            && name().find("operator")==-1;
3769   }
3770   m_isDestructorCached = isDestructor ? 2 : 1;
3771 }
3772
3773 bool MemberDef::isDestructor() const
3774 {
3775   if (m_isDestructorCached==0)
3776   {
3777     MemberDef *that=(MemberDef*)this;
3778     that->_computeIsDestructor();
3779   }
3780   ASSERT(m_isDestructorCached>0);
3781   return m_isDestructorCached==2;
3782 }
3783
3784 void MemberDef::writeEnumDeclaration(OutputList &typeDecl,
3785      ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd)
3786 {
3787   int enumMemCount=0;
3788
3789   MemberList *fmdl=m_impl->enumFields;
3790   uint numVisibleEnumValues=0;
3791   if (fmdl)
3792   {
3793     MemberListIterator mli(*fmdl);
3794     MemberDef *fmd;
3795     for (mli.toFirst();(fmd=mli.current());++mli)
3796     {
3797       if (fmd->isBriefSectionVisible()) numVisibleEnumValues++;
3798     }
3799   }
3800   if (numVisibleEnumValues==0 && !isBriefSectionVisible())
3801   {
3802     return;
3803   }
3804
3805   QCString n = name();
3806   int i=n.findRev("::");
3807   if (i!=-1) n=n.right(n.length()-i-2); // strip scope (TODO: is this needed?)
3808   if (n[0]!='@') // not an anonymous enum
3809   {
3810     if (isLinkableInProject() || hasDocumentedEnumValues())
3811     {
3812       //_writeTagData(compoundType);
3813       _addToSearchIndex();
3814       writeLink(typeDecl,cd,nd,fd,gd);
3815     }
3816     else
3817     {
3818       typeDecl.startBold();
3819       typeDecl.docify(n);
3820       typeDecl.endBold();
3821     }
3822     typeDecl.writeChar(' ');
3823   }
3824   if (!m_impl->enumBaseType.isEmpty())
3825   {
3826     typeDecl.writeChar(':');
3827     typeDecl.writeChar(' ');
3828     typeDecl.docify(m_impl->enumBaseType);
3829     typeDecl.writeChar(' ');
3830   }
3831
3832   uint enumValuesPerLine = (uint)Config_getInt(ENUM_VALUES_PER_LINE);
3833   if (numVisibleEnumValues>0 && enumValuesPerLine>0)
3834   {
3835     typeDecl.docify("{ ");
3836     if (fmdl)
3837     {
3838       MemberListIterator mli(*fmdl);
3839       MemberDef *fmd=mli.current();
3840       bool fmdVisible = fmd ? fmd->isBriefSectionVisible() : TRUE;
3841       while (fmd)
3842       {
3843         if (fmdVisible)
3844         {
3845           /* in html we start a new line after a number of items */
3846           if (numVisibleEnumValues>enumValuesPerLine
3847               && (enumMemCount%enumValuesPerLine)==0
3848              )
3849           {
3850             typeDecl.pushGeneratorState();
3851             typeDecl.disableAllBut(OutputGenerator::Html);
3852             typeDecl.enable(OutputGenerator::Latex);
3853             typeDecl.lineBreak();
3854             typeDecl.disable(OutputGenerator::Latex);
3855             typeDecl.writeString("&#160;&#160;");
3856             typeDecl.popGeneratorState();
3857           }
3858
3859           if (fmd->hasDocumentation()) // enum value has docs
3860           {
3861             //fmd->_writeTagData(compoundType);
3862             fmd->_addToSearchIndex();
3863             fmd->writeLink(typeDecl,cd,nd,fd,gd);
3864           }
3865           else // no docs for this enum value
3866           {
3867             typeDecl.startBold();
3868             typeDecl.docify(fmd->name());
3869             typeDecl.endBold();
3870           }
3871           if (fmd->hasOneLineInitializer()) // enum value has initializer
3872           {
3873             //typeDecl.writeString(" = ");
3874             typeDecl.writeString(" ");
3875             typeDecl.parseText(fmd->initializer());
3876           }
3877         }
3878
3879         bool prevVisible = fmdVisible;
3880         ++mli;
3881         fmd=mli.current();
3882         if (fmd && (fmdVisible=fmd->isBriefSectionVisible()))
3883         {
3884           typeDecl.writeString(", ");
3885         }
3886         if (prevVisible)
3887         {
3888           typeDecl.disable(OutputGenerator::Man);
3889           typeDecl.writeString("\n"); // to prevent too long lines in LaTeX
3890           typeDecl.enable(OutputGenerator::Man);
3891           enumMemCount++;
3892         }
3893       }
3894       if (numVisibleEnumValues>enumValuesPerLine)
3895       {
3896         typeDecl.pushGeneratorState();
3897         typeDecl.disableAllBut(OutputGenerator::Html);
3898         typeDecl.lineBreak();
3899         typeDecl.popGeneratorState();
3900       }
3901     }
3902     typeDecl.docify(" }");
3903   }
3904 }
3905
3906 void MemberDef::setArgumentList(ArgumentList *al)
3907 {
3908   if (m_impl->defArgList) delete m_impl->defArgList;
3909   m_impl->defArgList = al;
3910 }
3911
3912 void MemberDef::setDeclArgumentList(ArgumentList *al)
3913 {
3914   if (m_impl->declArgList) delete m_impl->declArgList;
3915   m_impl->declArgList = al;
3916 }
3917
3918 void MemberDef::setTypeConstraints(ArgumentList *al)
3919 {
3920   if (al==0) return;
3921   if (m_impl->typeConstraints) delete m_impl->typeConstraints;
3922   m_impl->typeConstraints = new ArgumentList;
3923   m_impl->typeConstraints->setAutoDelete(TRUE);
3924   ArgumentListIterator ali(*al);
3925   Argument *a;
3926   for (;(a=ali.current());++ali)
3927   {
3928     m_impl->typeConstraints->append(new Argument(*a));
3929   }
3930 }
3931
3932 void MemberDef::setType(const char *t)
3933 {
3934   m_impl->type = t;
3935 }
3936
3937 void MemberDef::setAccessorType(ClassDef *cd,const char *t)
3938 {
3939   m_impl->accessorClass = cd;
3940   m_impl->accessorType = t;
3941 }
3942
3943 ClassDef *MemberDef::accessorClass() const
3944 {
3945   return m_impl->accessorClass;
3946 }
3947
3948 void MemberDef::findSectionsInDocumentation()
3949 {
3950   docFindSections(documentation(),this,0,docFile());
3951 }
3952
3953 void MemberDef::enableCallGraph(bool e)
3954 {
3955   m_impl->hasCallGraph=e;
3956   if (e) Doxygen::parseSourcesNeeded = TRUE;
3957 }
3958
3959 void MemberDef::enableCallerGraph(bool e)
3960 {
3961   m_impl->hasCallerGraph=e;
3962   if (e) Doxygen::parseSourcesNeeded = TRUE;
3963 }
3964
3965 #if 0
3966 bool MemberDef::protectionVisible() const
3967 {
3968   return m_impl->prot==Public ||
3969          (m_impl->prot==Private   && Config_getBool(EXTRACT_PRIVATE))   ||
3970          (m_impl->prot==Protected && Config_getBool(EXTRACT_PROTECTED)) ||
3971          (m_impl->prot==Package   && Config_getBool(EXTRACT_PACKAGE));
3972 }
3973 #endif
3974
3975 #if 0
3976 void MemberDef::setInbodyDocumentation(const char *docs,
3977                   const char *docFile,int docLine)
3978 {
3979   m_impl->inbodyDocs = docs;
3980   m_impl->inbodyDocs = m_impl->inbodyDocs.stripWhiteSpace();
3981   m_impl->inbodyLine = docLine;
3982   m_impl->inbodyFile = docFile;
3983 }
3984 #endif
3985
3986 bool MemberDef::isObjCMethod() const
3987 {
3988   if (m_impl->classDef && m_impl->classDef->isObjectiveC() && isFunction()) return TRUE;
3989   return FALSE;
3990 }
3991
3992 bool MemberDef::isObjCProperty() const
3993 {
3994   if (m_impl->classDef && m_impl->classDef->isObjectiveC() && isProperty()) return TRUE;
3995   return FALSE;
3996 }
3997
3998 QCString MemberDef::qualifiedName() const
3999 {
4000   if (isObjCMethod())
4001   {
4002     QCString qm;
4003     if (isStatic()) qm="+"; else qm="-";
4004     qm+="[";
4005     qm+=m_impl->classDef->name()+" ";
4006     qm+=name();
4007     qm+="]";
4008     return qm;
4009   }
4010   else if (m_impl->enumScope && m_impl->enumScope->isStrong())
4011   {
4012     return m_impl->enumScope->qualifiedName()+
4013            getLanguageSpecificSeparator(getLanguage())+
4014            localName();
4015   }
4016   else
4017   {
4018     return Definition::qualifiedName();
4019   }
4020 }
4021
4022 void MemberDef::setTagInfo(TagInfo *ti)
4023 {
4024   if (ti)
4025   {
4026     //printf("%s: Setting tag name=%s anchor=%s\n",name().data(),ti->tagName.data(),ti->anchor.data());
4027     m_impl->anc=ti->anchor;
4028     setReference(ti->tagName);
4029     m_impl->explicitOutputFileBase = stripExtension(ti->fileName);
4030   }
4031 }
4032
4033 QCString MemberDef::objCMethodName(bool localLink,bool showStatic) const
4034 {
4035   QCString qm;
4036   if (showStatic)
4037   {
4038     if (isStatic()) qm="+ "; else qm="- ";
4039   }
4040   qm+=name();
4041   if (!localLink) // link to method of same class
4042   {
4043     qm+=" (";
4044     qm+=m_impl->classDef->name();
4045     qm+=")";
4046   }
4047   return qm;
4048 }
4049
4050 const char *MemberDef::declaration() const
4051 {
4052   return m_impl->decl;
4053 }
4054
4055 const char *MemberDef::definition() const
4056 {
4057   return m_impl->def;
4058 }
4059
4060 const char *MemberDef::extraTypeChars() const
4061 {
4062   return m_impl->extraTypeChars;
4063 }
4064
4065 const char *MemberDef::typeString() const
4066 {
4067   return m_impl->type;
4068 }
4069
4070 const char *MemberDef::argsString() const
4071 {
4072   return m_impl->args;
4073 }
4074
4075 const char *MemberDef::excpString() const
4076 {
4077   return m_impl->exception;
4078 }
4079
4080 const char *MemberDef::bitfieldString() const
4081 {
4082   return m_impl->bitfields;
4083 }
4084
4085 const QCString &MemberDef::initializer() const
4086 {
4087   return m_impl->initializer;
4088 }
4089
4090 int MemberDef::initializerLines() const
4091 {
4092   return m_impl->initLines;
4093 }
4094
4095 uint64 MemberDef::getMemberSpecifiers() const
4096 {
4097   return m_impl->memSpec;
4098 }
4099
4100 ClassDef *MemberDef::getClassDef() const
4101 {
4102   return m_impl->classDef;
4103 }
4104
4105 FileDef  *MemberDef::getFileDef() const
4106 {
4107   return m_impl->fileDef;
4108 }
4109
4110 NamespaceDef* MemberDef::getNamespaceDef() const
4111 {
4112   return m_impl->nspace;
4113 }
4114
4115 const char *MemberDef::getReadAccessor() const
4116 {
4117   return m_impl->read;
4118 }
4119
4120 const char *MemberDef::getWriteAccessor() const
4121 {
4122   return m_impl->write;
4123 }
4124
4125 GroupDef *MemberDef::getGroupDef() const
4126 {
4127   return m_impl->group;
4128 }
4129
4130 Grouping::GroupPri_t MemberDef::getGroupPri() const
4131 {
4132   return m_impl->grouppri;
4133 }
4134
4135 const char *MemberDef::getGroupFileName() const
4136 {
4137   return m_impl->groupFileName;
4138 }
4139
4140 int MemberDef::getGroupStartLine() const
4141 {
4142   return m_impl->groupStartLine;
4143 }
4144
4145 bool MemberDef::getGroupHasDocs() const
4146 {
4147   return m_impl->groupHasDocs;
4148 }
4149
4150 Protection MemberDef::protection() const
4151 {
4152   return m_impl->prot;
4153 }
4154
4155 MemberType MemberDef::memberType() const
4156 {
4157   return m_impl->mtype;
4158 }
4159
4160 bool MemberDef::isSignal() const
4161 {
4162   return m_impl->mtype==MemberType_Signal;
4163 }
4164
4165 bool MemberDef::isSlot() const
4166 {
4167   return m_impl->mtype==MemberType_Slot;
4168 }
4169
4170 bool MemberDef::isVariable() const
4171 {
4172   return m_impl->mtype==MemberType_Variable;
4173 }
4174
4175 bool MemberDef::isEnumerate() const
4176 {
4177   return m_impl->mtype==MemberType_Enumeration;
4178 }
4179
4180 bool MemberDef::isEnumValue() const
4181 {
4182   return m_impl->mtype==MemberType_EnumValue;
4183 }
4184
4185 bool MemberDef::isTypedef() const
4186 {
4187   return m_impl->mtype==MemberType_Typedef;
4188 }
4189
4190 bool MemberDef::isFunction() const
4191 {
4192   return m_impl->mtype==MemberType_Function;
4193 }
4194
4195 bool MemberDef::isFunctionPtr() const
4196 {
4197   return m_impl->mtype==MemberType_Variable && QCString(argsString()).find(")(")!=-1;
4198 }
4199
4200 bool MemberDef::isDefine() const
4201 {
4202   return m_impl->mtype==MemberType_Define;
4203 }
4204
4205 bool MemberDef::isFriend() const
4206 {
4207   return m_impl->mtype==MemberType_Friend;
4208 }
4209
4210 bool MemberDef::isDCOP() const
4211 {
4212   return m_impl->mtype==MemberType_DCOP;
4213 }
4214
4215 bool MemberDef::isProperty() const
4216 {
4217   return m_impl->mtype==MemberType_Property;
4218 }
4219
4220 bool MemberDef::isEvent() const
4221 {
4222   return m_impl->mtype==MemberType_Event;
4223 }
4224
4225 bool MemberDef::isRelated() const
4226 {
4227   return m_impl->related == Related;
4228 }
4229
4230 bool MemberDef::isForeign() const
4231 {
4232   return m_impl->related == Foreign;
4233 }
4234
4235 bool MemberDef::isStatic() const
4236 {
4237   return m_impl->stat;
4238 }
4239
4240 bool MemberDef::isInline() const
4241 {
4242   return (m_impl->memSpec&Entry::Inline)!=0;
4243 }
4244
4245 bool MemberDef::isExplicit() const
4246 {
4247   return (m_impl->memSpec&Entry::Explicit)!=0;
4248 }
4249
4250 bool MemberDef::isMutable() const
4251 {
4252   return (m_impl->memSpec&Entry::Mutable)!=0;
4253 }
4254
4255 bool MemberDef::isGettable() const
4256 {
4257   return (m_impl->memSpec&Entry::Gettable)!=0;
4258 }
4259
4260 bool MemberDef::isPrivateGettable() const
4261 {
4262   return (m_impl->memSpec&Entry::PrivateGettable)!=0;
4263 }
4264
4265 bool MemberDef::isProtectedGettable() const
4266 {
4267   return (m_impl->memSpec&Entry::ProtectedGettable)!=0;
4268 }
4269
4270 bool MemberDef::isSettable() const
4271 {
4272   return (m_impl->memSpec&Entry::Settable)!=0;
4273 }
4274
4275 bool MemberDef::isPrivateSettable() const
4276 {
4277   return (m_impl->memSpec&Entry::PrivateSettable)!=0;
4278 }
4279
4280 bool MemberDef::isProtectedSettable() const
4281 {
4282   return (m_impl->memSpec&Entry::ProtectedSettable)!=0;
4283 }
4284
4285 bool MemberDef::isAddable() const
4286 {
4287   return (m_impl->memSpec&Entry::Addable)!=0;
4288 }
4289
4290 bool MemberDef::isRemovable() const
4291 {
4292   return (m_impl->memSpec&Entry::Removable)!=0;
4293 }
4294
4295 bool MemberDef::isRaisable() const
4296 {
4297   return (m_impl->memSpec&Entry::Raisable)!=0;
4298 }
4299
4300 bool MemberDef::isReadable() const
4301 {
4302   return (m_impl->memSpec&Entry::Readable)!=0;
4303 }
4304
4305 bool MemberDef::isWritable() const
4306 {
4307   return (m_impl->memSpec&Entry::Writable)!=0;
4308 }
4309
4310 bool MemberDef::isFinal() const
4311 {
4312   return (m_impl->memSpec&Entry::Final)!=0;
4313 }
4314
4315 bool MemberDef::isNew() const
4316 {
4317   return (m_impl->memSpec&Entry::New)!=0;
4318 }
4319
4320 bool MemberDef::isSealed() const
4321 {
4322   return (m_impl->memSpec&Entry::Sealed)!=0;
4323 }
4324
4325 bool MemberDef::isOverride() const
4326 {
4327   return (m_impl->memSpec&Entry::Override)!=0;
4328 }
4329
4330 bool MemberDef::isInitonly() const
4331 {
4332   return (m_impl->memSpec&Entry::Initonly)!=0;
4333 }
4334
4335 bool MemberDef::isAbstract() const
4336 {
4337   return (m_impl->memSpec&Entry::Abstract)!=0;
4338 }
4339
4340 bool MemberDef::isOptional() const
4341 {
4342   return (m_impl->memSpec&Entry::Optional)!=0;
4343 }
4344
4345 bool MemberDef::isRequired() const
4346 {
4347   return (m_impl->memSpec&Entry::Required)!=0;
4348 }
4349
4350 bool MemberDef::isNonAtomic() const
4351 {
4352   return (m_impl->memSpec&Entry::NonAtomic)!=0;
4353 }
4354
4355 bool MemberDef::isCopy() const
4356 {
4357   return (m_impl->memSpec&Entry::Copy)!=0;
4358 }
4359
4360 bool MemberDef::isAssign() const
4361 {
4362   return (m_impl->memSpec&Entry::Assign)!=0;
4363 }
4364
4365 bool MemberDef::isRetain() const
4366 {
4367   return (m_impl->memSpec&Entry::Retain)!=0;
4368 }
4369
4370 bool MemberDef::isWeak() const
4371 {
4372   return (m_impl->memSpec&Entry::Weak)!=0;
4373 }
4374
4375 bool MemberDef::isStrong() const
4376 {
4377   return (m_impl->memSpec&Entry::Strong)!=0;
4378 }
4379
4380 bool MemberDef::isStrongEnumValue() const
4381 {
4382   return m_impl->mtype==MemberType_EnumValue &&
4383          m_impl->enumScope &&
4384          m_impl->enumScope->isStrong();
4385 }
4386
4387 bool MemberDef::isUnretained() const
4388 {
4389   return (m_impl->memSpec&Entry::Unretained)!=0;
4390 }
4391
4392 bool MemberDef::isAlias() const
4393 {
4394   return (m_impl->memSpec&Entry::Alias)!=0;
4395 }
4396
4397 bool MemberDef::isDefault() const
4398 {
4399   return (m_impl->memSpec&Entry::Default)!=0;
4400 }
4401
4402 bool MemberDef::isDelete() const
4403 {
4404   return (m_impl->memSpec&Entry::Delete)!=0;
4405 }
4406
4407 bool MemberDef::isNoExcept() const
4408 {
4409   return (m_impl->memSpec&Entry::NoExcept)!=0;
4410 }
4411
4412 bool MemberDef::isAttribute() const
4413 {
4414   return (m_impl->memSpec&Entry::Attribute)!=0;
4415 }
4416
4417 bool MemberDef::isUNOProperty() const
4418 {
4419   return (m_impl->memSpec&Entry::Property)!=0;
4420 }
4421
4422 bool MemberDef::isReadonly() const
4423 {
4424   return (m_impl->memSpec&Entry::Readonly)!=0;
4425 }
4426
4427 bool MemberDef::isBound() const
4428 {
4429   return (m_impl->memSpec&Entry::Bound)!=0;
4430 }
4431
4432 bool MemberDef::isConstrained() const
4433 {
4434   return (m_impl->memSpec&Entry::Constrained)!=0;
4435 }
4436
4437 bool MemberDef::isTransient() const
4438 {
4439   return (m_impl->memSpec&Entry::Transient)!=0;
4440 }
4441
4442 bool MemberDef::isMaybeVoid() const
4443 {
4444   return (m_impl->memSpec&Entry::MaybeVoid)!=0;
4445 }
4446
4447 bool MemberDef::isMaybeDefault() const
4448 {
4449   return (m_impl->memSpec&Entry::MaybeDefault)!=0;
4450 }
4451
4452 bool MemberDef::isMaybeAmbiguous() const
4453 {
4454   return (m_impl->memSpec&Entry::MaybeAmbiguous)!=0;
4455 }
4456
4457 bool MemberDef::isPublished() const
4458 {
4459   return (m_impl->memSpec&Entry::Published)!=0;
4460 }
4461
4462
4463 bool MemberDef::isImplementation() const
4464 {
4465   return m_impl->implOnly;
4466 }
4467
4468 bool MemberDef::isExternal() const
4469 {
4470   return m_impl->explExt;
4471 }
4472
4473 bool MemberDef::isTemplateSpecialization() const
4474 {
4475   return m_impl->tspec;
4476 }
4477
4478 bool MemberDef::hasDocumentedParams() const
4479 {
4480   return m_impl->hasDocumentedParams;
4481 }
4482
4483 bool MemberDef::hasDocumentedReturnType() const
4484 {
4485   return m_impl->hasDocumentedReturnType;
4486 }
4487
4488 bool MemberDef::showInCallGraph() const
4489 {
4490   return isFunction() ||
4491          isSlot() ||
4492          isConstructor() ||
4493          isDestructor() ||
4494          isObjCMethod();
4495 }
4496
4497 ClassDef *MemberDef::relatedAlso() const
4498 {
4499   return m_impl->relatedAlso;
4500 }
4501
4502 bool MemberDef::hasDocumentedEnumValues() const
4503 {
4504   return m_impl->docEnumValues;
4505 }
4506
4507 MemberDef *MemberDef::getAnonymousEnumType() const
4508 {
4509   return m_impl->annEnumType;
4510 }
4511
4512 bool MemberDef::isDocsForDefinition() const
4513 {
4514   return m_impl->docsForDefinition;
4515 }
4516
4517 MemberDef *MemberDef::getEnumScope() const
4518 {
4519   return m_impl->enumScope;
4520 }
4521
4522 bool MemberDef::livesInsideEnum() const
4523 {
4524   return m_impl->livesInsideEnum;
4525 }
4526
4527 MemberList *MemberDef::enumFieldList() const
4528 {
4529   return m_impl->enumFields;
4530 }
4531
4532 ExampleSDict *MemberDef::getExamples() const
4533 {
4534   return m_impl->exampleSDict;
4535 }
4536
4537 bool MemberDef::isPrototype() const
4538 {
4539   return m_impl->proto;
4540 }
4541
4542 ArgumentList *MemberDef::argumentList() const
4543 {
4544   return m_impl->defArgList;
4545 }
4546
4547 ArgumentList *MemberDef::declArgumentList() const
4548 {
4549   return m_impl->declArgList;
4550 }
4551
4552 ArgumentList *MemberDef::templateArguments() const
4553 {
4554   return m_impl->tArgList;
4555 }
4556
4557 QList<ArgumentList> *MemberDef::definitionTemplateParameterLists() const
4558 {
4559   return m_impl->defTmpArgLists;
4560 }
4561
4562 int MemberDef::getMemberGroupId() const
4563 {
4564   return m_impl->grpId;
4565 }
4566
4567 MemberGroup *MemberDef::getMemberGroup() const
4568 {
4569   return m_impl->memberGroup;
4570 }
4571
4572 bool MemberDef::fromAnonymousScope() const
4573 {
4574   return m_impl->annScope;
4575 }
4576
4577 bool MemberDef::anonymousDeclShown() const
4578 {
4579   return m_impl->annUsed;
4580 }
4581
4582 void MemberDef::setAnonymousUsed()
4583 {
4584   m_impl->annUsed = TRUE;
4585 }
4586
4587 bool MemberDef::hasCallGraph() const
4588 {
4589   return m_impl->hasCallGraph;
4590 }
4591
4592 bool MemberDef::hasCallerGraph() const
4593 {
4594   return m_impl->hasCallerGraph;
4595 }
4596
4597 MemberDef *MemberDef::templateMaster() const
4598 {
4599   return m_impl->templateMaster;
4600 }
4601
4602 bool MemberDef::isTypedefValCached() const
4603 {
4604   return m_impl->isTypedefValCached;
4605 }
4606
4607 ClassDef *MemberDef::getCachedTypedefVal() const
4608 {
4609   return m_impl->cachedTypedefValue;
4610 }
4611
4612 QCString MemberDef::getCachedTypedefTemplSpec() const
4613 {
4614   return m_impl->cachedTypedefTemplSpec;
4615 }
4616
4617 QCString MemberDef::getCachedResolvedTypedef() const
4618 {
4619   //printf("MemberDef::getCachedResolvedTypedef()=%s m_impl=%p\n",m_impl->cachedResolvedType.data(),m_impl);
4620   return m_impl->cachedResolvedType;
4621 }
4622
4623 MemberDef *MemberDef::memberDefinition() const
4624 {
4625   return m_impl->memDef;
4626 }
4627
4628 MemberDef *MemberDef::memberDeclaration() const
4629 {
4630   return m_impl->memDec;
4631 }
4632
4633 MemberDef *MemberDef::inheritsDocsFrom() const
4634 {
4635   return m_impl->docProvider;
4636 }
4637
4638 MemberDef *MemberDef::getGroupAlias() const
4639 {
4640   return m_impl->groupAlias;
4641 }
4642
4643 void MemberDef::setMemberType(MemberType t)
4644 {
4645   m_impl->mtype=t;
4646   m_isLinkableCached = 0;
4647 }
4648
4649 void MemberDef::setDefinition(const char *d)
4650 {
4651   m_impl->def=d;
4652 }
4653
4654 void MemberDef::setFileDef(FileDef *fd)
4655 {
4656   m_impl->fileDef=fd;
4657   m_isLinkableCached = 0;
4658   m_isConstructorCached = 0;
4659   m_isDestructorCached = 0;
4660 }
4661
4662 void MemberDef::setProtection(Protection p)
4663 {
4664   m_impl->prot=p;
4665   m_isLinkableCached = 0;
4666 }
4667
4668 void MemberDef::setMemberSpecifiers(uint64 s)
4669 {
4670   m_impl->memSpec=s;
4671 }
4672
4673 void MemberDef::mergeMemberSpecifiers(uint64 s)
4674 {
4675   m_impl->memSpec|=s;
4676 }
4677
4678 void MemberDef::setBitfields(const char *s)
4679 {
4680   m_impl->bitfields = QCString(s).simplifyWhiteSpace();
4681 }
4682
4683 void MemberDef::setMaxInitLines(int lines)
4684 {
4685   if (lines!=-1)
4686   {
4687     m_impl->userInitLines=lines;
4688   }
4689 }
4690
4691 void MemberDef::setExplicitExternal(bool b)
4692 {
4693   m_impl->explExt=b;
4694 }
4695
4696 void MemberDef::setReadAccessor(const char *r)
4697 {
4698   m_impl->read=r;
4699 }
4700
4701 void MemberDef::setWriteAccessor(const char *w)
4702 {
4703   m_impl->write=w;
4704 }
4705
4706 void MemberDef::setTemplateSpecialization(bool b)
4707 {
4708   m_impl->tspec=b;
4709 }
4710
4711 void MemberDef::makeRelated()
4712 {
4713   m_impl->related = Related;
4714   m_isLinkableCached = 0;
4715 }
4716
4717 void MemberDef::makeForeign()
4718 {
4719   m_impl->related = Foreign;
4720   m_isLinkableCached = 0;
4721 }
4722
4723 void MemberDef::setHasDocumentedParams(bool b)
4724 {
4725   m_impl->hasDocumentedParams = b;
4726 }
4727
4728 void MemberDef::setHasDocumentedReturnType(bool b)
4729 {
4730   m_impl->hasDocumentedReturnType = b;
4731 }
4732
4733 void MemberDef::setInheritsDocsFrom(MemberDef *md)
4734 {
4735   m_impl->docProvider = md;
4736 }
4737
4738 void MemberDef::setArgsString(const char *as)
4739 {
4740   m_impl->args = as;
4741 }
4742
4743 void MemberDef::setRelatedAlso(ClassDef *cd)
4744 {
4745   m_impl->relatedAlso=cd;
4746 }
4747
4748 void MemberDef::setEnumClassScope(ClassDef *cd)
4749 {
4750   m_impl->classDef = cd;
4751   m_isLinkableCached = 0;
4752   m_isConstructorCached = 0;
4753 }
4754
4755 void MemberDef::setDocumentedEnumValues(bool value)
4756 {
4757   m_impl->docEnumValues=value;
4758 }
4759
4760 void MemberDef::setAnonymousEnumType(MemberDef *md)
4761 {
4762   m_impl->annEnumType = md;
4763 }
4764
4765 void MemberDef::setPrototype(bool p)
4766 {
4767   m_impl->proto=p;
4768 }
4769
4770 void MemberDef::setMemberGroupId(int id)
4771 {
4772   m_impl->grpId=id;
4773 }
4774
4775 void MemberDef::makeImplementationDetail()
4776 {
4777   m_impl->implOnly=TRUE;
4778 }
4779
4780 void MemberDef::setFromAnonymousScope(bool b)
4781 {
4782   m_impl->annScope=b;
4783 }
4784
4785 void MemberDef::setFromAnonymousMember(MemberDef *m)
4786 {
4787   m_impl->annMemb=m;
4788 }
4789
4790 MemberDef *MemberDef::fromAnonymousMember() const
4791 {
4792   return m_impl->annMemb;
4793 }
4794
4795 void MemberDef::setTemplateMaster(MemberDef *mt)
4796 {
4797   m_impl->templateMaster=mt;
4798   m_isLinkableCached = 0;
4799 }
4800
4801 void MemberDef::setDocsForDefinition(bool b)
4802 {
4803   m_impl->docsForDefinition = b;
4804 }
4805
4806 void MemberDef::setGroupAlias(MemberDef *md)
4807 {
4808   m_impl->groupAlias = md;
4809 }
4810
4811 void MemberDef::invalidateTypedefValCache()
4812 {
4813   m_impl->isTypedefValCached=FALSE;
4814 }
4815
4816 void MemberDef::setMemberDefinition(MemberDef *md)
4817 {
4818   m_impl->memDef=md;
4819 }
4820
4821 void MemberDef::setMemberDeclaration(MemberDef *md)
4822 {
4823   m_impl->memDec=md;
4824 }
4825
4826 ClassDef *MemberDef::category() const
4827 {
4828   return m_impl->category;
4829 }
4830
4831 void MemberDef::setCategory(ClassDef *def)
4832 {
4833   m_impl->category = def;
4834 }
4835
4836 MemberDef *MemberDef::categoryRelation() const
4837 {
4838   return m_impl->categoryRelation;
4839 }
4840
4841 void MemberDef::setCategoryRelation(MemberDef *md)
4842 {
4843   m_impl->categoryRelation = md;
4844 }
4845
4846 void MemberDef::setEnumBaseType(const QCString &type)
4847 {
4848   m_impl->enumBaseType = type;
4849 }
4850
4851 QCString MemberDef::enumBaseType() const
4852 {
4853   return m_impl->enumBaseType;
4854 }
4855
4856
4857 void MemberDef::cacheTypedefVal(ClassDef*val, const QCString & templSpec, const QCString &resolvedType)
4858 {
4859   m_impl->isTypedefValCached=TRUE;
4860   m_impl->cachedTypedefValue=val;
4861   m_impl->cachedTypedefTemplSpec=templSpec;
4862   m_impl->cachedResolvedType=resolvedType;
4863   //printf("MemberDef::cacheTypedefVal=%s m_impl=%p\n",m_impl->cachedResolvedType.data(),m_impl);
4864 }
4865
4866 void MemberDef::copyArgumentNames(MemberDef *bmd)
4867 {
4868   {
4869     ArgumentList *arguments = bmd->argumentList();
4870     if (m_impl->defArgList && arguments)
4871     {
4872       ArgumentListIterator aliDst(*m_impl->defArgList);
4873       ArgumentListIterator aliSrc(*arguments);
4874       Argument *argDst, *argSrc;
4875       for (;(argDst=aliDst.current()) && (argSrc=aliSrc.current());++aliDst,++aliSrc)
4876       {
4877         argDst->name = argSrc->name;
4878       }
4879     }
4880   }
4881   {
4882     ArgumentList *arguments = bmd->declArgumentList();
4883     if (m_impl->declArgList && arguments)
4884     {
4885       ArgumentListIterator aliDst(*m_impl->declArgList);
4886       ArgumentListIterator aliSrc(*arguments);
4887       Argument *argDst, *argSrc;
4888       for (;(argDst=aliDst.current()) && (argSrc=aliSrc.current());++aliDst,++aliSrc)
4889       {
4890         argDst->name = argSrc->name;
4891       }
4892     }
4893   }
4894 }
4895
4896 static void invalidateCachedTypesInArgumentList(ArgumentList *al)
4897 {
4898   if (al)
4899   {
4900     ArgumentListIterator ali(*al);
4901     Argument *a;
4902     for (ali.toFirst();(a=ali.current());++ali)
4903     {
4904       a->canType.resize(0);
4905     }
4906   }
4907 }
4908
4909 void MemberDef::invalidateCachedArgumentTypes()
4910 {
4911   invalidateCachedTypesInArgumentList(m_impl->defArgList);
4912   invalidateCachedTypesInArgumentList(m_impl->declArgList);
4913 }
4914
4915 void MemberDef::addFlowKeyWord()
4916 {
4917   number_of_flowkw++;
4918 }
4919
4920 int MemberDef::numberOfFlowKeyWords()
4921 {
4922   return number_of_flowkw;
4923 }
4924
4925 //----------------
4926
4927 QCString MemberDef::displayName(bool) const
4928 {
4929   return Definition::name();
4930 }
4931
4932 void MemberDef::_addToSearchIndex()
4933 {
4934   // write search index info
4935   if (Doxygen::searchIndex && isLinkableInProject())
4936   {
4937     Doxygen::searchIndex->setCurrentDoc(this,anchor(),FALSE);
4938     QCString ln=localName(),qn=qualifiedName();
4939     Doxygen::searchIndex->addWord(ln,TRUE);
4940     if (ln!=qn)
4941     {
4942       Doxygen::searchIndex->addWord(qn,TRUE);
4943       if (getClassDef())
4944       {
4945         Doxygen::searchIndex->addWord(getClassDef()->displayName(),TRUE);
4946       }
4947       else if (getNamespaceDef())
4948       {
4949         Doxygen::searchIndex->addWord(getNamespaceDef()->displayName(),TRUE);
4950       }
4951     }
4952   }
4953 }
4954
4955
4956
4957 //----------------
4958
4959 static void transferArgumentDocumentation(ArgumentList *decAl,ArgumentList *defAl)
4960 {
4961   if (decAl && defAl)
4962   {
4963     ArgumentListIterator decAli(*decAl);
4964     ArgumentListIterator defAli(*defAl);
4965     Argument *decA,*defA;
4966     for (decAli.toFirst(),defAli.toFirst();
4967         (decA=decAli.current()) && (defA=defAli.current());
4968         ++decAli,++defAli)
4969     {
4970       //printf("Argument decA->name=%s (doc=%s) defA->name=%s (doc=%s)\n",
4971       //    decA->name.data(),decA->docs.data(),
4972       //    defA->name.data(),defA->docs.data()
4973       //      );
4974       if (decA->docs.isEmpty() && !defA->docs.isEmpty())
4975       {
4976         decA->docs = defA->docs.copy();
4977       }
4978       else if (defA->docs.isEmpty() && !decA->docs.isEmpty())
4979       {
4980         defA->docs = decA->docs.copy();
4981       }
4982     }
4983   }
4984 }
4985
4986 void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef)
4987 {
4988   //printf("mdec=%s isPrototype()=%d\n",mdec->name().data(),mdec->isPrototype());
4989   if (
4990       (mdef->isFunction() && !mdef->isStatic() && !mdef->isPrototype()) ||
4991       (mdef->isVariable() && !mdef->isExternal() && !mdef->isStatic())
4992      )
4993   {
4994     //printf("mdef=(%p,%s) mdec=(%p,%s)\n",
4995     //    mdef, mdef ? mdef->name().data() : "",
4996     //    mdec, mdec ? mdec->name().data() : "");
4997
4998     ArgumentList *mdefAl = mdef->argumentList();
4999     ArgumentList *mdecAl = mdec->argumentList();
5000     if (matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),mdefAl,
5001           mdec->getOuterScope(),mdec->getFileDef(),mdecAl,
5002           TRUE
5003           )
5004        ) /* match found */
5005     {
5006       //printf("Found member %s: definition in %s (doc=`%s') and declaration in %s (doc=`%s')\n",
5007       //    mn->memberName(),
5008       //    mdef->getFileDef()->name().data(),mdef->documentation().data(),
5009       //    mdec->getFileDef()->name().data(),mdec->documentation().data()
5010       //    );
5011
5012       // first merge argument documentation
5013       transferArgumentDocumentation(mdecAl,mdefAl);
5014
5015       /* copy documentation between function definition and declaration */
5016       if (!mdec->briefDescription().isEmpty())
5017       {
5018         mdef->setBriefDescription(mdec->briefDescription(),mdec->briefFile(),mdec->briefLine());
5019       }
5020       else if (!mdef->briefDescription().isEmpty())
5021       {
5022         mdec->setBriefDescription(mdef->briefDescription(),mdef->briefFile(),mdef->briefLine());
5023       }
5024       if (!mdef->documentation().isEmpty())
5025       {
5026         //printf("transferring docs mdef->mdec (%s->%s)\n",mdef->argsString(),mdec->argsString());
5027         mdec->setDocumentation(mdef->documentation(),mdef->docFile(),mdef->docLine());
5028         mdec->setDocsForDefinition(mdef->isDocsForDefinition());
5029         if (mdefAl!=0)
5030         {
5031           ArgumentList *mdefAlComb = new ArgumentList;
5032           stringToArgumentList(mdef->argsString(),mdefAlComb);
5033           transferArgumentDocumentation(mdefAl,mdefAlComb);
5034           mdec->setArgumentList(mdefAlComb);
5035         }
5036       }
5037       else if (!mdec->documentation().isEmpty())
5038       {
5039         //printf("transferring docs mdec->mdef (%s->%s)\n",mdec->argsString(),mdef->argsString());
5040         mdef->setDocumentation(mdec->documentation(),mdec->docFile(),mdec->docLine());
5041         mdef->setDocsForDefinition(mdec->isDocsForDefinition());
5042         if (mdecAl!=0)
5043         {
5044           ArgumentList *mdecAlComb = new ArgumentList;
5045           stringToArgumentList(mdec->argsString(),mdecAlComb);
5046           transferArgumentDocumentation(mdecAl,mdecAlComb);
5047           mdef->setDeclArgumentList(mdecAlComb);
5048         }
5049       }
5050       if (!mdef->inbodyDocumentation().isEmpty())
5051       {
5052         mdec->setInbodyDocumentation(mdef->inbodyDocumentation(),mdef->inbodyFile(),mdef->inbodyLine());
5053       }
5054       else if (!mdec->inbodyDocumentation().isEmpty())
5055       {
5056         mdef->setInbodyDocumentation(mdec->inbodyDocumentation(),mdec->inbodyFile(),mdec->inbodyLine());
5057       }
5058       if (mdec->getStartBodyLine()!=-1 && mdef->getStartBodyLine()==-1)
5059       {
5060         //printf("body mdec->mdef %d-%d\n",mdec->getStartBodyLine(),mdef->getEndBodyLine());
5061         mdef->setBodySegment(mdec->getStartBodyLine(),mdec->getEndBodyLine());
5062         mdef->setBodyDef(mdec->getBodyDef());
5063         //mdef->setBodyMember(mdec);
5064       }
5065       else if (mdef->getStartBodyLine()!=-1 && mdec->getStartBodyLine()==-1)
5066       {
5067         //printf("body mdef->mdec %d-%d\n",mdef->getStartBodyLine(),mdec->getEndBodyLine());
5068         mdec->setBodySegment(mdef->getStartBodyLine(),mdef->getEndBodyLine());
5069         mdec->setBodyDef(mdef->getBodyDef());
5070         //mdec->setBodyMember(mdef);
5071       }
5072       mdec->mergeMemberSpecifiers(mdef->getMemberSpecifiers());
5073       mdef->mergeMemberSpecifiers(mdec->getMemberSpecifiers());
5074
5075
5076       // copy group info.
5077       if (mdec->getGroupDef()==0 && mdef->getGroupDef()!=0)
5078       {
5079         mdec->setGroupDef(mdef->getGroupDef(),
5080             mdef->getGroupPri(),
5081             mdef->docFile(),
5082             mdef->docLine(),
5083             mdef->hasDocumentation(),
5084             mdef
5085             );
5086       }
5087       else if (mdef->getGroupDef()==0 && mdec->getGroupDef()!=0)
5088       {
5089         mdef->setGroupDef(mdec->getGroupDef(),
5090             mdec->getGroupPri(),
5091             mdec->docFile(),
5092             mdec->docLine(),
5093             mdec->hasDocumentation(),
5094             mdec
5095             );
5096       }
5097
5098
5099       mdec->mergeRefItems(mdef);
5100       mdef->mergeRefItems(mdec);
5101
5102       mdef->setMemberDeclaration(mdec);
5103       mdec->setMemberDefinition(mdef);
5104
5105       mdef->enableCallGraph(mdec->hasCallGraph() || mdef->hasCallGraph());
5106       mdef->enableCallerGraph(mdec->hasCallerGraph() || mdef->hasCallerGraph());
5107       mdec->enableCallGraph(mdec->hasCallGraph() || mdef->hasCallGraph());
5108       mdec->enableCallerGraph(mdec->hasCallerGraph() || mdef->hasCallerGraph());
5109     }
5110   }
5111 }
5112
5113 QCString MemberDef::briefDescription(bool abbr) const
5114 {
5115   if (m_impl->templateMaster)
5116   {
5117     return m_impl->templateMaster->briefDescription(abbr);
5118   }
5119   else
5120   {
5121     return Definition::briefDescription(abbr);
5122   }
5123 }
5124
5125 QCString MemberDef::documentation() const
5126 {
5127   if (m_impl->templateMaster)
5128   {
5129     return m_impl->templateMaster->documentation();
5130   }
5131   else
5132   {
5133     return Definition::documentation();
5134   }
5135 }
5136
5137 const ArgumentList *MemberDef::typeConstraints() const
5138 {
5139   return m_impl->typeConstraints;
5140 }
5141
5142 bool MemberDef::isFriendToHide() const
5143 {
5144   static bool hideFriendCompounds = Config_getBool(HIDE_FRIEND_COMPOUNDS);
5145   bool isFriendToHide = hideFriendCompounds &&
5146      (m_impl->type=="friend class"  ||
5147       m_impl->type=="friend struct" ||
5148       m_impl->type=="friend union");
5149   return isFriendToHide;
5150 }
5151
5152 bool MemberDef::isNotFriend() const
5153 {
5154   return !(isFriend() && isFriendToHide());
5155 }
5156
5157 bool MemberDef::isFunctionOrSignalSlot() const
5158 {
5159   return isFunction() || isSlot() || isSignal();
5160 }
5161
5162 bool MemberDef::isRelatedOrFriend() const
5163 {
5164   return isRelated() || isForeign() || (isFriend() && !isFriendToHide());
5165 }
5166
5167 bool MemberDef::isReference() const
5168 {
5169   return Definition::isReference() ||
5170          (m_impl->templateMaster && m_impl->templateMaster->isReference());
5171 }
5172