Skip to content

Commit 88dd1ae

Browse files
committed
issue #10640 copydoc on template function causes warning: @copybrief or @copydoc target not found
1 parent e477e70 commit 88dd1ae

File tree

8 files changed

+76
-36
lines changed

8 files changed

+76
-36
lines changed

src/classdef.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4115,6 +4115,7 @@ void ClassDefImpl::addMembersToTemplateInstance(const ClassDef *cd,const Argumen
41154115
mmd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine());
41164116
mmd->setMemberSpecifiers(md->getMemberSpecifiers());
41174117
mmd->setMemberGroupId(md->getMemberGroupId());
4118+
mmd->setArtificial(true);
41184119
insertMember(imd.get());
41194120
//printf("Adding member=%s %s%s to class %s templSpec %s\n",
41204121
// imd->typeString(),qPrint(imd->name()),imd->argsString(),

src/docparser.cpp

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -392,12 +392,16 @@ bool DocParser::findDocsForMemberOrCompound(const QCString &commandName,
392392
QCString *pBrief,
393393
const Definition **pDef)
394394
{
395-
//printf("findDocsForMemberOrCompound(%s)\n",commandName);
395+
AUTO_TRACE("commandName={}",commandName);
396396
*pDoc="";
397397
*pBrief="";
398398
*pDef=nullptr;
399399
QCString cmdArg=commandName;
400-
if (cmdArg.isEmpty()) return FALSE;
400+
if (cmdArg.isEmpty())
401+
{
402+
AUTO_TRACE_EXIT("empty");
403+
return false;
404+
}
401405

402406
const FileDef *fd=nullptr;
403407
const GroupDef *gd=nullptr;
@@ -408,15 +412,17 @@ bool DocParser::findDocsForMemberOrCompound(const QCString &commandName,
408412
*pDoc=gd->documentation();
409413
*pBrief=gd->briefDescription();
410414
*pDef=gd;
411-
return TRUE;
415+
AUTO_TRACE_EXIT("group");
416+
return true;
412417
}
413418
pd = Doxygen::pageLinkedMap->find(cmdArg);
414419
if (pd) // page
415420
{
416421
*pDoc=pd->documentation();
417422
*pBrief=pd->briefDescription();
418423
*pDef=pd;
419-
return TRUE;
424+
AUTO_TRACE_EXIT("page");
425+
return true;
420426
}
421427
bool ambig;
422428
fd = findFileDef(Doxygen::inputNameLinkedMap,cmdArg,ambig);
@@ -425,7 +431,8 @@ bool DocParser::findDocsForMemberOrCompound(const QCString &commandName,
425431
*pDoc=fd->documentation();
426432
*pBrief=fd->briefDescription();
427433
*pDef=fd;
428-
return TRUE;
434+
AUTO_TRACE_EXIT("file");
435+
return true;
429436
}
430437

431438
// for symbols we need to normalize the separator, so A#B, or A\B, or A.B becomes A::B
@@ -475,16 +482,17 @@ bool DocParser::findDocsForMemberOrCompound(const QCString &commandName,
475482
GetDefInput input(
476483
context.context.find('.')==-1 ? context.context : QCString(), // find('.') is a hack to detect files
477484
name,
478-
args.isEmpty() ? QCString() : args);
485+
args);
479486
input.checkCV=true;
480487
GetDefResult result = getDefs(input);
481-
//printf("found=%d context=%s name=%s\n",found,qPrint(context.context),qPrint(name));
488+
//printf("found=%d context=%s name=%s\n",result.found,qPrint(context.context),qPrint(name));
482489
if (result.found && result.md)
483490
{
484491
*pDoc=result.md->documentation();
485492
*pBrief=result.md->briefDescription();
486493
*pDef=result.md;
487-
return TRUE;
494+
AUTO_TRACE_EXIT("member");
495+
return true;
488496
}
489497

490498
int scopeOffset=static_cast<int>(context.context.length());
@@ -504,15 +512,17 @@ bool DocParser::findDocsForMemberOrCompound(const QCString &commandName,
504512
*pDoc=cd->documentation();
505513
*pBrief=cd->briefDescription();
506514
*pDef=cd;
507-
return TRUE;
515+
AUTO_TRACE_EXIT("class");
516+
return true;
508517
}
509518
const NamespaceDef *nd = Doxygen::namespaceLinkedMap->find(fullName);
510519
if (nd) // namespace
511520
{
512521
*pDoc=nd->documentation();
513522
*pBrief=nd->briefDescription();
514523
*pDef=nd;
515-
return TRUE;
524+
AUTO_TRACE_EXIT("namespace");
525+
return true;
516526
}
517527
if (scopeOffset==0)
518528
{
@@ -525,7 +535,7 @@ bool DocParser::findDocsForMemberOrCompound(const QCString &commandName,
525535
}
526536
} while (scopeOffset>=0);
527537

528-
538+
AUTO_TRACE_EXIT("not found");
529539
return FALSE;
530540
}
531541

src/doxygen.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4043,7 +4043,7 @@ static void findUsedClassesForClass(const Entry *root,
40434043
ClassDefMutable *masterCd,
40444044
ClassDefMutable *instanceCd,
40454045
bool isArtificial,
4046-
const std::unique_ptr<ArgumentList> &actualArgs = std::unique_ptr<ArgumentList>(),
4046+
const ArgumentList *actualArgs = nullptr,
40474047
const TemplateNameMap &templateNames = TemplateNameMap()
40484048
)
40494049
{
@@ -4207,7 +4207,7 @@ static void findBaseClassesForClass(
42074207
ClassDefMutable *instanceCd,
42084208
FindBaseClassRelation_Mode mode,
42094209
bool isArtificial,
4210-
const std::unique_ptr<ArgumentList> &actualArgs = std::unique_ptr<ArgumentList>(),
4210+
const ArgumentList *actualArgs = nullptr,
42114211
const TemplateNameMap &templateNames=TemplateNameMap()
42124212
)
42134213
{
@@ -4287,10 +4287,10 @@ static void findTemplateInstanceRelation(const Entry *root,
42874287
AUTO_TRACE_ADD("template root found '{}' templSpec='{}'",templateRoot->name,templSpec);
42884288
std::unique_ptr<ArgumentList> templArgs = stringToArgumentList(root->lang,templSpec);
42894289
findBaseClassesForClass(templateRoot,context,templateClass,instanceClass,
4290-
TemplateInstances,isArtificial,templArgs,templateNames);
4290+
TemplateInstances,isArtificial,templArgs.get(),templateNames);
42914291

42924292
findUsedClassesForClass(templateRoot,context,templateClass,instanceClass,
4293-
isArtificial,templArgs,templateNames);
4293+
isArtificial,templArgs.get(),templateNames);
42944294
}
42954295
}
42964296
else
@@ -4931,7 +4931,7 @@ static void computeTemplateClassRelations()
49314931
}
49324932
}
49334933

4934-
tbi.name = substituteTemplateArgumentsInString(bi.name,tl,templArgs);
4934+
tbi.name = substituteTemplateArgumentsInString(bi.name,tl,templArgs.get());
49354935
// find a documented base class in the correct scope
49364936
if (!findClassRelation(root,cd,tcd,&tbi,actualTemplateNames,DocumentedOnly,FALSE))
49374937
{
@@ -8381,7 +8381,7 @@ static void computeTooltipTexts()
83818381
for (const auto &def : symList)
83828382
{
83838383
DefinitionMutable *dm = toDefinitionMutable(def);
8384-
if (dm && !isSymbolHidden(toDefinition(dm)) && toDefinition(dm)->isLinkableInProject())
8384+
if (dm && !isSymbolHidden(def) && !def->isArtificial() && def->isLinkableInProject())
83858385
{
83868386
auto processTooltip = [dm]() {
83878387
dm->computeTooltip();
@@ -8403,7 +8403,7 @@ static void computeTooltipTexts()
84038403
for (const auto &def : symList)
84048404
{
84058405
DefinitionMutable *dm = toDefinitionMutable(def);
8406-
if (dm && !isSymbolHidden(toDefinition(dm)) && toDefinition(dm)->isLinkableInProject())
8406+
if (dm && !isSymbolHidden(def) && !def->isArtificial() && def->isLinkableInProject())
84078407
{
84088408
dm->computeTooltip();
84098409
}

src/memberdef.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ class MemberDefImpl : public DefinitionMixin<MemberDefMutable>
213213
const ArgumentList &declArgumentList() const override;
214214
const ArgumentList &templateArguments() const override;
215215
const ArgumentLists &definitionTemplateParameterLists() const override;
216+
std::optional<ArgumentList> formalTemplateArguments() const override;
216217
int getMemberGroupId() const override;
217218
MemberGroup *getMemberGroup() const override;
218219
bool fromAnonymousScope() const override;
@@ -301,6 +302,7 @@ class MemberDefImpl : public DefinitionMixin<MemberDefMutable>
301302
void overrideReferencesRelation(bool e) override;
302303
void overrideInlineSource(bool e) override;
303304
void setTemplateMaster(MemberDef *mt) override;
305+
void setFormalTemplateArguments(const ArgumentList &al) override;
304306
void addListReference(Definition *d) override;
305307
void setDocsForDefinition(bool b) override;
306308
void setGroupAlias(const MemberDef *md) override;
@@ -437,6 +439,7 @@ class MemberDefImpl : public DefinitionMixin<MemberDefMutable>
437439
ArgumentList m_tArgList; // template argument list of function template
438440
ArgumentList m_typeConstraints; // type constraints for template parameters
439441
MemberDef *m_templateMaster = nullptr;
442+
std::optional<ArgumentList> m_formalTemplateArguments;
440443
ArgumentLists m_defTmpArgLists; // lists of template argument lists
441444
// (for template functions in nested template classes)
442445

@@ -838,6 +841,8 @@ class MemberDefAliasImpl : public DefinitionAliasMixin<MemberDef>
838841
{ return getMdAlias()->templateArguments(); }
839842
const ArgumentLists &definitionTemplateParameterLists() const override
840843
{ return getMdAlias()->definitionTemplateParameterLists(); }
844+
std::optional<ArgumentList> formalTemplateArguments() const override
845+
{ return getMdAlias()->formalTemplateArguments(); }
841846
int getMemberGroupId() const override
842847
{ return getMdAlias()->getMemberGroupId(); }
843848
MemberGroup *getMemberGroup() const override
@@ -1464,6 +1469,7 @@ MemberDefImpl::MemberDefImpl(const MemberDefImpl &md) : DefinitionMixin(md)
14641469
m_tArgList = md.m_tArgList ;
14651470
m_typeConstraints = md.m_typeConstraints ;
14661471
m_templateMaster = md.m_templateMaster ;
1472+
m_formalTemplateArguments = md.m_formalTemplateArguments ;
14671473
m_defTmpArgLists = md.m_defTmpArgLists ;
14681474
m_metaData = md.m_metaData ;
14691475
m_cachedAnonymousType = md.m_cachedAnonymousType ;
@@ -4327,33 +4333,33 @@ std::unique_ptr<MemberDef> MemberDefImpl::createTemplateInstanceMember(
43274333
// replace formal arguments with actuals
43284334
for (Argument &arg : *actualArgList)
43294335
{
4330-
arg.type = substituteTemplateArgumentsInString(arg.type,formalArgs,actualArgs);
4336+
arg.type = substituteTemplateArgumentsInString(arg.type,formalArgs,actualArgs.get());
43314337
}
43324338
actualArgList->setTrailingReturnType(
4333-
substituteTemplateArgumentsInString(actualArgList->trailingReturnType(),formalArgs,actualArgs));
4339+
substituteTemplateArgumentsInString(actualArgList->trailingReturnType(),formalArgs,actualArgs.get()));
43344340
}
43354341

43364342
QCString methodName=name();
43374343
if (methodName.startsWith("operator ")) // conversion operator
43384344
{
4339-
methodName=substituteTemplateArgumentsInString(methodName,formalArgs,actualArgs);
4345+
methodName=substituteTemplateArgumentsInString(methodName,formalArgs,actualArgs.get());
43404346
}
43414347

43424348
auto imd = createMemberDef(
43434349
getDefFileName(),getDefLine(),getDefColumn(),
4344-
substituteTemplateArgumentsInString(m_type,formalArgs,actualArgs),
4350+
substituteTemplateArgumentsInString(m_type,formalArgs,actualArgs.get()),
43454351
methodName,
4346-
substituteTemplateArgumentsInString(m_args,formalArgs,actualArgs),
4352+
substituteTemplateArgumentsInString(m_args,formalArgs,actualArgs.get()),
43474353
m_exception, m_prot,
43484354
m_virt, m_stat, m_related, m_mtype,
43494355
ArgumentList(), ArgumentList(), ""
43504356
);
43514357
auto mmd = toMemberDefMutable(imd.get());
43524358
mmd->moveArgumentList(std::move(actualArgList));
4353-
mmd->setDefinition(substituteTemplateArgumentsInString(m_def,formalArgs,actualArgs));
4359+
mmd->setDefinition(substituteTemplateArgumentsInString(m_def,formalArgs,actualArgs.get()));
43544360
mmd->setBodyDef(getBodyDef());
43554361
mmd->setBodySegment(getDefLine(),getStartBodyLine(),getEndBodyLine());
4356-
//imd->setBodyMember(this);
4362+
mmd->setFormalTemplateArguments(formalArgs);
43574363

43584364
// TODO: init other member variables (if needed).
43594365
// TODO: reimplemented info
@@ -5598,6 +5604,11 @@ const MemberDef *MemberDefImpl::templateMaster() const
55985604
return m_templateMaster;
55995605
}
56005606

5607+
std::optional<ArgumentList> MemberDefImpl::formalTemplateArguments() const
5608+
{
5609+
return m_formalTemplateArguments;
5610+
}
5611+
56015612
bool MemberDefImpl::isTypedefValCached() const
56025613
{
56035614
return m_isTypedefValCached;
@@ -5817,7 +5828,6 @@ void MemberDefImpl::setExplicitExternal(bool b,const QCString &df,int line,int c
58175828
}
58185829
}
58195830

5820-
58215831
void MemberDefImpl::setDeclFile(const QCString &df,int line,int column)
58225832
{
58235833
m_declFileName = df;
@@ -5856,6 +5866,11 @@ void MemberDefImpl::setTemplateMaster(MemberDef *mt)
58565866
m_isLinkableCached = 0;
58575867
}
58585868

5869+
void MemberDefImpl::setFormalTemplateArguments(const ArgumentList &al)
5870+
{
5871+
m_formalTemplateArguments = al;
5872+
}
5873+
58595874
void MemberDefImpl::setDocsForDefinition(bool b)
58605875
{
58615876
m_docsForDefinition = b;

src/memberdef.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include <vector>
2222
#include <memory>
23+
#include <optional>
2324

2425
#include <sys/types.h>
2526

@@ -231,6 +232,7 @@ class MemberDef : public Definition
231232
virtual const ArgumentList &declArgumentList() const = 0;
232233
virtual const ArgumentList &templateArguments() const = 0;
233234
virtual const ArgumentLists &definitionTemplateParameterLists() const = 0;
235+
virtual std::optional<ArgumentList> formalTemplateArguments() const = 0;
234236

235237
// member group related members
236238
virtual int getMemberGroupId() const = 0;
@@ -390,6 +392,7 @@ class MemberDefMutable : public DefinitionMutable, public MemberDef
390392
virtual void overrideInlineSource(bool e) = 0;
391393

392394
virtual void setTemplateMaster(MemberDef *mt) = 0;
395+
virtual void setFormalTemplateArguments(const ArgumentList &al) = 0;
393396
virtual void addListReference(Definition *d) = 0;
394397
virtual void setDocsForDefinition(bool b) = 0;
395398
virtual void setGroupAlias(const MemberDef *md) = 0;

src/symbolresolver.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ struct SymbolResolver::Private
151151
const Definition *scope, // in
152152
const Definition *d, // in
153153
const QCString &explicitScopePart, // in
154-
const std::unique_ptr<ArgumentList> &actTemplParams, // in
154+
const ArgumentList *actTemplParams, // in
155155
int &minDistance, // input
156156
const ClassDef *&bestMatch, // out
157157
const MemberDef *&bestTypedef, // out
@@ -181,7 +181,7 @@ struct SymbolResolver::Private
181181
const MemberDef **pMemType, // out
182182
QCString *pTemplSpec, // out
183183
QCString *pResolvedType, // out
184-
const std::unique_ptr<ArgumentList> &actTemplParams = std::unique_ptr<ArgumentList>()
184+
const ArgumentList *actTemplParams = nullptr
185185
);
186186

187187
const Definition *followPath(StringUnorderedSet &visitedKeys,
@@ -333,7 +333,7 @@ const ClassDef *SymbolResolver::Private::getResolvedTypeRec(
333333

334334
for (Definition *d : range)
335335
{
336-
getResolvedType(visitedKeys,scope,d,explicitScopePart,actTemplParams,
336+
getResolvedType(visitedKeys,scope,d,explicitScopePart,actTemplParams.get(),
337337
minDistance,bestMatch,bestTypedef,bestTemplSpec,bestResolvedType);
338338
if (minDistance==0) break; // we can stop reaching if we already reached distance 0
339339
}
@@ -567,7 +567,7 @@ void SymbolResolver::Private::getResolvedType(
567567
const Definition *scope, // in
568568
const Definition *d, // in
569569
const QCString &explicitScopePart, // in
570-
const std::unique_ptr<ArgumentList> &actTemplParams, // in
570+
const ArgumentList *actTemplParams, // in
571571
int &minDistance, // inout
572572
const ClassDef *&bestMatch, // out
573573
const MemberDef *&bestTypedef, // out
@@ -803,10 +803,21 @@ void SymbolResolver::Private::getResolvedSymbol(
803803
const MemberDef *md = toMemberDef(d);
804804

805805
bool match = true;
806-
AUTO_TRACE_ADD("member={}",md->name());
806+
AUTO_TRACE_ADD("member={} args={}",md->name(),argListToString(md->argumentList()));
807807
if (md->isCallable() && !args.isEmpty())
808808
{
809-
std::unique_ptr<ArgumentList> argList = stringToArgumentList(md->getLanguage(),args);
809+
QCString actArgs;
810+
if (md->isArtificial() && md->formalTemplateArguments()) // for members of an instatiated template we need to replace
811+
// the formal arguments by the actual ones before matching
812+
// See issue #10640
813+
{
814+
actArgs = substituteTemplateArgumentsInString(args,md->formalTemplateArguments().value(),&md->argumentList());
815+
}
816+
else
817+
{
818+
actArgs = args;
819+
}
820+
std::unique_ptr<ArgumentList> argList = stringToArgumentList(md->getLanguage(),actArgs);
810821
const ArgumentList &mdAl = md->argumentList();
811822
match = matchArguments2(md->getOuterScope(),md->getFileDef(),&mdAl,
812823
scope, md->getFileDef(),argList.get(),
@@ -854,7 +865,7 @@ const ClassDef *SymbolResolver::Private::newResolveTypedef(
854865
const MemberDef **pMemType, // out
855866
QCString *pTemplSpec, // out
856867
QCString *pResolvedType, // out
857-
const std::unique_ptr<ArgumentList> &actTemplParams) // in
868+
const ArgumentList *actTemplParams) // in
858869
{
859870
AUTO_TRACE("md={}",md->qualifiedName());
860871
std::lock_guard<std::recursive_mutex> lock(g_cacheTypedefMutex);

src/util.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4672,7 +4672,7 @@ QCString normalizeNonTemplateArgumentsInString(
46724672
QCString substituteTemplateArgumentsInString(
46734673
const QCString &nm,
46744674
const ArgumentList &formalArgs,
4675-
const std::unique_ptr<ArgumentList> &actualArgs)
4675+
const ArgumentList *actualArgs)
46764676
{
46774677
//printf("substituteTemplateArgumentsInString(name=%s formal=%s actualArg=%s)\n",
46784678
// qPrint(nm),qPrint(argListToString(formalArgs)),actualArgs ? qPrint(argListToString(*actualArgs)): "");
@@ -4692,7 +4692,7 @@ QCString substituteTemplateArgumentsInString(
46924692
size_t l = match.length();
46934693
if (i>p) result += name.substr(p,i-p);
46944694
QCString n(match.str());
4695-
ArgumentList::iterator actIt;
4695+
ArgumentList::const_iterator actIt;
46964696
if (actualArgs)
46974697
{
46984698
actIt = actualArgs->begin();

src/util.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ QCString normalizeNonTemplateArgumentsInString(
286286
QCString substituteTemplateArgumentsInString(
287287
const QCString &name,
288288
const ArgumentList &formalArgs,
289-
const std::unique_ptr<ArgumentList> &actualArgs);
289+
const ArgumentList *actualArgs);
290290

291291
QCString stripTemplateSpecifiersFromScope(const QCString &fullName,
292292
bool parentOnly=TRUE,

0 commit comments

Comments
 (0)