Skip to content

Commit

Permalink
Refactoring: improve argv/argc handling for libclang API
Browse files Browse the repository at this point in the history
  • Loading branch information
doxygen committed Apr 23, 2023
1 parent f0f758a commit 04804e1
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 41 deletions.
52 changes: 24 additions & 28 deletions src/clangparser.cpp
Expand Up @@ -2,6 +2,7 @@
#include "settings.h"
#include <cstdio>
#include <cstdint>
#include <vector>
#include <mutex>

#if USE_LIBCLANG
Expand Down Expand Up @@ -74,7 +75,7 @@ class ClangTUParser::Private
CXIndex index = 0;
uint32_t curToken = 0;
DetectedLang detectedLang = DetectedLang::Cpp;
uint32_t numFiles = 0;
size_t numFiles = 0;
std::vector<QCString> sources;
std::vector<CXUnsavedFile> ufs;
std::vector<CXCursor> cursors;
Expand Down Expand Up @@ -124,7 +125,6 @@ void ClangTUParser::parse()
p->index = clang_createIndex(0, 0);
p->curToken = 0;
p->cursors.clear();
int argc=0;
size_t clang_option_len = 0;
std::vector<clang::tooling::CompileCommand> command;
if (p->parser.database()!=nullptr)
Expand All @@ -137,26 +137,22 @@ void ClangTUParser::parse()
clang_option_len = command[command.size()-1].CommandLine.size();
}
}
char **argv = static_cast<char**>(malloc(sizeof(char*)*
(4+Doxygen::inputPaths.size()+
includePath.size()+
clangOptions.size()+
clang_option_len)));
std::vector<char *> argv;
if (!command.empty() )
{
std::vector<std::string> options = command[command.size()-1].CommandLine;
// copy each compiler option used from the database. Skip the first which is compiler exe.
for (auto option = options.begin()+1; option != options.end(); option++)
{
argv[argc++] = qstrdup(option->c_str());
argv.push_back(qstrdup(option->c_str()));
}
// user specified options
for (size_t i=0;i<clangOptions.size();i++)
{
argv[argc++]=qstrdup(clangOptions[i].c_str());
argv.push_back(qstrdup(clangOptions[i].c_str()));
}
// this extra addition to argv is accounted for as we are skipping the first entry in
argv[argc++]=qstrdup("-w"); // finally, turn off warnings.
argv.push_back(qstrdup("-w")); // finally, turn off warnings.
}
else
{
Expand All @@ -166,24 +162,24 @@ void ClangTUParser::parse()
for (const std::string &path : Doxygen::inputPaths)
{
QCString inc = QCString("-I")+path.data();
argv[argc++]=qstrdup(inc.data());
argv.push_back(qstrdup(inc.data()));
//printf("argv[%d]=%s\n",argc,argv[argc]);
}
}
// add external include paths
for (size_t i=0;i<includePath.size();i++)
{
QCString inc = QCString("-I")+includePath[i].c_str();
argv[argc++]=qstrdup(inc.data());
argv.push_back(qstrdup(inc.data()));
}
// user specified options
for (size_t i=0;i<clangOptions.size();i++)
{
argv[argc++]=qstrdup(clangOptions[i].c_str());
argv.push_back(qstrdup(clangOptions[i].c_str()));
}
// extra options
argv[argc++]=qstrdup("-ferror-limit=0");
argv[argc++]=qstrdup("-x");
argv.push_back(qstrdup("-ferror-limit=0"));
argv.push_back(qstrdup("-x"));

// Since we can be presented with a .h file that can contain C/C++ or
// Objective C code and we need to configure the parser before knowing this,
Expand All @@ -210,18 +206,18 @@ void ClangTUParser::parse()
}
switch (p->detectedLang)
{
case DetectedLang::Cpp: argv[argc++]=qstrdup("c++"); break;
case DetectedLang::ObjC: argv[argc++]=qstrdup("objective-c"); break;
case DetectedLang::ObjCpp: argv[argc++]=qstrdup("objective-c++"); break;
case DetectedLang::Cpp: argv.push_back(qstrdup("c++")); break;
case DetectedLang::ObjC: argv.push_back(qstrdup("objective-c")); break;
case DetectedLang::ObjCpp: argv.push_back(qstrdup("objective-c++")); break;
}

// provide the input and its dependencies as unsaved files so we can
// pass the filtered versions
argv[argc++]=qstrdup(fileName.data());
argv.push_back(qstrdup(fileName.data()));
}
//printf("source %s ----------\n%s\n-------------\n\n",
// fileName,p->source.data());
int numUnsavedFiles = static_cast<int>(p->filesInSameTU.size()+1);
size_t numUnsavedFiles = p->filesInSameTU.size()+1;
p->numFiles = numUnsavedFiles;
p->sources.resize(numUnsavedFiles);
p->ufs.resize(numUnsavedFiles);
Expand All @@ -231,7 +227,7 @@ void ClangTUParser::parse()
p->ufs[0].Contents = p->sources[0].data();
p->ufs[0].Length = p->sources[0].length();
p->fileMapping.insert({fileName.data(),0});
int i=1;
size_t i=1;
for (auto it = p->filesInSameTU.begin();
it != p->filesInSameTU.end() && i<numUnsavedFiles;
++it, i++)
Expand All @@ -244,24 +240,24 @@ void ClangTUParser::parse()
}

// let libclang do the actual parsing
//for (i=0;i<argv.size();i++) printf("Argument %d: %s\n",i,argv[i]);
p->tu = clang_parseTranslationUnit(p->index, 0,
argv, argc, p->ufs.data(), numUnsavedFiles,
argv.data(), static_cast<int>(argv.size()), p->ufs.data(), numUnsavedFiles,
CXTranslationUnit_DetailedPreprocessingRecord);
//printf(" tu=%p\n",p->tu);
// free arguments
for (i=0;i<argc;++i)
for (i=0;i<argv.size();++i)
{
delete[](argv[i]);
qstrfree(argv[i]);
}
free(argv);

if (p->tu)
{
// show any warnings that the compiler produced
int n=clang_getNumDiagnostics(p->tu);
size_t n=clang_getNumDiagnostics(p->tu);
for (i=0; i!=n; ++i)
{
CXDiagnostic diag = clang_getDiagnostic(p->tu, i);
CXDiagnostic diag = clang_getDiagnostic(p->tu, static_cast<unsigned>(i));
CXString string = clang_formatDiagnostic(diag,
clang_defaultDiagnosticDisplayOptions());
err("%s [clang]\n",clang_getCString(string));
Expand Down Expand Up @@ -290,7 +286,7 @@ ClangTUParser::~ClangTUParser()
p->tokens = 0;
p->numTokens = 0;
}
for (uint32_t i=0;i<p->numFiles;i++)
for (size_t i=0;i<p->numFiles;i++)
{
delete[] p->ufs[i].Filename;
}
Expand Down
5 changes: 5 additions & 0 deletions src/qcstring.cpp
Expand Up @@ -425,6 +425,11 @@ char *qstrdup( const char *str )
return strcpy( dst, str );
}

void qstrfree( const char *str )
{
delete[](str);
}

char *qstrncpy( char *dst, const char *src, size_t len )
{
if ( !src )
Expand Down
19 changes: 6 additions & 13 deletions src/qcstring.h
Expand Up @@ -51,25 +51,21 @@ void *qmemmove( void *dst, const void *src, size_t len );
#define qsnprintf snprintf
#endif

char *qstrdup( const char * );

inline uint32_t cstrlen( const char *str )
{ return static_cast<uint32_t>(strlen(str)); }
//! Returns a copy of a string \a s.
//! Note that memory is passed to the caller, use qstrfree() to release.
char *qstrdup( const char *s );
//! Frees the memory allocated using qstrdup().
void qstrfree( const char *s );

//! Returns the length of string \a str, or 0 if a null pointer is passed.
inline uint32_t qstrlen( const char *str )
{ return str ? static_cast<uint32_t>(strlen(str)) : 0; }

inline char *cstrcpy( char *dst, const char *src )
{ return strcpy(dst,src); }

inline char *qstrcpy( char *dst, const char *src )
{ return src ? strcpy(dst, src) : 0; }

char * qstrncpy(char *dst,const char *src, size_t len);

inline int cstrcmp( const char *str1, const char *str2 )
{ return strcmp(str1,str2); }

inline bool qisempty( const char *s)
{ return s==0 || *s==0; }

Expand All @@ -79,9 +75,6 @@ inline int qstrcmp( const char *str1, const char *str2 )
qisempty(str1) ? -1 : 1; // one empty, other non-empty
}

inline int cstrncmp( const char *str1, const char *str2, size_t len )
{ return strncmp(str1,str2,len); }

inline int qstrncmp( const char *str1, const char *str2, size_t len )
{ return (str1 && str2) ? strncmp(str1,str2,len) : // both non-empty
(qisempty(str1) && qisempty(str2)) ? 0 : // both empty
Expand Down

0 comments on commit 04804e1

Please sign in to comment.