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