Skip to content

Commit

Permalink
issue #9155: Doxygen crash with NUM_PROC_THREADS>1
Browse files Browse the repository at this point in the history
  • Loading branch information
doxygen committed Feb 27, 2022
1 parent 7167599 commit 66d1936
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 52 deletions.
4 changes: 2 additions & 2 deletions src/code.l
Original file line number Diff line number Diff line change
Expand Up @@ -3734,12 +3734,12 @@ static QCString escapeComment(yyscan_t yyscanner,const char *s)
static bool skipLanguageSpecificKeyword(yyscan_t yyscanner,const char *keyword)
{
struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
static std::unordered_set<std::string> non_cpp_keywords = {
static const std::unordered_set<std::string> non_cpp_keywords = {
"__assume", "__super", "abstract", "function",
"gcnew", "gcroot", "generic", "get",
"internal", "null", "pin_ptr", "raise",
"remove", "self", "set", "transient"};
static std::unordered_set<std::string> non_java_keywords = {
static const std::unordered_set<std::string> non_java_keywords = {
"alignas", "alignof", "and", "and_eq", "asm",
"atomic_cancel", "atomic_commit", "atomic_noexcept", "auto", "bitand",
"bitor", "bool", "char8_t", "char16_t", "char32_t",
Expand Down
11 changes: 3 additions & 8 deletions src/doxygen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8090,11 +8090,8 @@ static void generateFileSources()
{
bool generateSourceFile = fd->generateSourceFile() && !Htags::useHtags && !g_useOutputTemplate;
auto ctx = std::make_shared<SourceContext>(fd.get(),generateSourceFile,*g_outputList);
if (generateSourceFile)
auto processFile = [ctx]()
{
fd->writeSourceHeader(ctx->ol);
}
auto processFile = [ctx]() {
if (ctx->generateSourceFile)
{
msg("Generating code for file %s...\n",qPrint(ctx->fd->docName()));
Expand All @@ -8107,7 +8104,9 @@ static void generateFileSources()
ctx->fd->getAllIncludeFilesRecursively(filesInSameTu);
if (ctx->generateSourceFile) // sources need to be shown in the output
{
ctx->fd->writeSourceHeader(ctx->ol);
ctx->fd->writeSourceBody(ctx->ol,nullptr);
ctx->fd->writeSourceFooter(ctx->ol);
}
else if (!ctx->fd->isReference() && Doxygen::parseSourcesNeeded)
// we needed to parse the sources even if we do not show them
Expand All @@ -8122,10 +8121,6 @@ static void generateFileSources()
for (auto &f : results)
{
auto ctx = f.get();
if (ctx->generateSourceFile)
{
ctx->fd->writeSourceFooter(ctx->ol);
}
}
}
else // single threaded version
Expand Down
70 changes: 30 additions & 40 deletions src/memberdef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3920,23 +3920,15 @@ static QCString stripTrailingReturn(const QCString &trailRet)
return trailRet;
}

static std::mutex g_detectUndocumentedParamsMutex;

void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const
{
QCString returnType = typeString();
bool isPython = getLanguage()==SrcLangExt_Python;
bool isFortran = getLanguage()==SrcLangExt_Fortran;
bool isFortranSubroutine = isFortran && returnType.find("subroutine")!=-1;
// this function is called while parsing the documentation. A member can have multiple
// documentation blocks, which could be handled by multiple threads, hence this guard.
std::lock_guard<std::mutex> lock(g_detectUndocumentedParamsMutex);

bool isVoidReturn = (returnType=="void") || (returnType.right(5)==" void");
if (!isVoidReturn && returnType == "auto")
{
const ArgumentList &defArgList=isDocsForDefinition() ? argumentList() : declArgumentList();
if (!defArgList.trailingReturnType().isEmpty())
{
QCString strippedTrailingReturn = stripTrailingReturn(defArgList.trailingReturnType());
isVoidReturn = (strippedTrailingReturn=="void") || (strippedTrailingReturn.right(5)==" void");
}
}
bool isPython = getLanguage()==SrcLangExt_Python;

if (!m_impl->hasDocumentedParams && hasParamCommand)
{
Expand Down Expand Up @@ -3995,34 +3987,24 @@ void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturn
{
m_impl->hasDocumentedReturnType = TRUE;
}
else if ( // see if return type is documented in a function w/o return type
hasReturnCommand &&
(
isVoidReturn || // void return type
isFortranSubroutine || // fortran subroutine
isConstructor() || // a constructor
isDestructor() // or destructor
)
)
{

warn_doc_error(docFile(),docLine(),"documented empty return type of %s",
qPrint(qualifiedName()));
}
else if ( // see if return needs to documented
m_impl->hasDocumentedReturnType ||
isVoidReturn || // void return type
isFortranSubroutine || // fortran subroutine
isConstructor() || // a constructor
isDestructor() // or destructor
)
{
m_impl->hasDocumentedReturnType = TRUE;
}
}

void MemberDefImpl::warnIfUndocumentedParams() const
{
QCString returnType = typeString();
bool isFortran = getLanguage()==SrcLangExt_Fortran;
bool isFortranSubroutine = isFortran && returnType.find("subroutine")!=-1;

bool isVoidReturn = (returnType=="void") || (returnType.right(5)==" void");
if (!isVoidReturn && returnType == "auto")
{
const ArgumentList &defArgList=isDocsForDefinition() ? argumentList() : declArgumentList();
if (!defArgList.trailingReturnType().isEmpty())
{
QCString strippedTrailingReturn = stripTrailingReturn(defArgList.trailingReturnType());
isVoidReturn = (strippedTrailingReturn=="void") || (strippedTrailingReturn.right(5)==" void");
}
}
if (!Config_getBool(EXTRACT_ALL) &&
Config_getBool(WARN_IF_UNDOCUMENTED) &&
Config_getBool(WARN_NO_PARAMDOC) &&
Expand All @@ -4031,11 +4013,10 @@ void MemberDefImpl::warnIfUndocumentedParams() const
!isReference() &&
!Doxygen::suppressDocWarnings)
{
QCString returnType = typeString();
if (!m_impl->hasDocumentedParams)
{
warn_doc_error(docFile(),docLine(),
"parameters of member %s are not (all) documented",
"parameters of member %s are not documented",
qPrint(qualifiedName()));
}
if (!m_impl->hasDocumentedReturnType &&
Expand All @@ -4045,6 +4026,15 @@ void MemberDefImpl::warnIfUndocumentedParams() const
"return type of member %s is not documented",
qPrint(qualifiedName()));
}
else if (m_impl->hasDocumentedReturnType &&
(isVoidReturn || // void return type
isFortranSubroutine || // fortran subroutine
isConstructor() || // a constructor
isDestructor())) // or destructor
{
warn_doc_error(docFile(),docLine(),"found documented return type of member %s that does not return anything",
qPrint(qualifiedName()));
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4343,8 +4343,8 @@ void addMembersToMemberGroup(MemberList *ml,
*/
int extractClassNameFromType(const QCString &type,int &pos,QCString &name,QCString &templSpec,SrcLangExt lang)
{
static reg::Ex re_norm(R"(\a[\w:]*)");
static reg::Ex re_fortran(R"(\a[\w:()=]*)");
static const reg::Ex re_norm(R"(\a[\w:]*)");
static const reg::Ex re_fortran(R"(\a[\w:()=]*)");
static const reg::Ex *re = &re_norm;

name.resize(0);
Expand Down

0 comments on commit 66d1936

Please sign in to comment.