summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt20
-rw-r--r--src/clangparser.cpp35
-rw-r--r--src/commentcnv.l70
-rw-r--r--src/config.xml14
-rw-r--r--src/docparser.cpp2
-rw-r--r--src/dot.cpp2
-rw-r--r--src/index.cpp6
-rw-r--r--src/memberlist.cpp2
-rw-r--r--src/parserintf.h2
-rw-r--r--src/portable.cpp1
-rw-r--r--src/translator_am.h8
-rw-r--r--src/translator_ru.h8
-rw-r--r--src/translator_ua.h8
13 files changed, 145 insertions, 33 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dcf4ef8..2218e82 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -244,6 +244,26 @@ add_library(_doxygen STATIC
)
add_executable(doxygen main.cpp)
+
+if (use_libclang)
+ find_package(LLVM REQUIRED CONFIG)
+ find_package(Clang REQUIRED CONFIG)
+ if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
+ target_compile_features(_doxygen PRIVATE cxx_alignof)
+ target_compile_features(doxygen PRIVATE cxx_alignof)
+ target_compile_options(_doxygen PRIVATE -stdlib=libc++ -std=c++11)
+ target_compile_options(doxygen PRIVATE -stdlib=libc++ -std=c++11)
+ elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
+ target_compile_options(_doxygen PRIVATE -std=c++11)
+ target_compile_options(doxygen PRIVATE -std=c++11)
+ endif()
+ include_directories(${LLVM_INCLUDE_DIRS})
+ add_definitions(${LLVM_DEFINITIONS})
+ llvm_map_components_to_libnames(llvm_libs support core option)
+ target_compile_definitions(doxygen PRIVATE ${LLVM_DEFINITIONS})
+ set(CLANG_LIBS libclang clangTooling ${llvm_libs})
+endif()
+
target_link_libraries(doxygen
_doxygen
doxycfg
diff --git a/src/clangparser.cpp b/src/clangparser.cpp
index 67e754b..77151d6 100644
--- a/src/clangparser.cpp
+++ b/src/clangparser.cpp
@@ -4,6 +4,7 @@
#if USE_LIBCLANG
#include <clang-c/Index.h>
+#include "clang/Tooling/Tooling.h"
#include <qfileinfo.h>
#include <stdlib.h>
#include "message.h"
@@ -160,15 +161,46 @@ void ClangParser::start(const char *fileName,QStrList &filesInTranslationUnit)
static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING);
static QStrList &includePath = Config_getList(INCLUDE_PATH);
static QStrList clangOptions = Config_getList(CLANG_OPTIONS);
+ static QCString clangCompileDatabase = Config_getList(CLANG_COMPILATION_DATABASE_PATH);
if (!clangAssistedParsing) return;
//printf("ClangParser::start(%s)\n",fileName);
p->fileName = fileName;
p->index = clang_createIndex(0, 0);
p->curLine = 1;
p->curToken = 0;
- char **argv = (char**)malloc(sizeof(char*)*(4+Doxygen::inputPaths.count()+includePath.count()+clangOptions.count()));
QDictIterator<void> di(Doxygen::inputPaths);
int argc=0;
+ std::string error;
+ // load a clang compilation database (https://clang.llvm.org/docs/JSONCompilationDatabase.html)
+ // this only needs to be loaded once, and could be refactored to a higher level function
+ static std::unique_ptr<clang::tooling::CompilationDatabase> db =
+ clang::tooling::CompilationDatabase::loadFromDirectory(clangCompileDatabase.data(), error);
+ int clang_option_len = 0;
+ std::vector<clang::tooling::CompileCommand> command;
+ if (strcmp(clangCompileDatabase, "0") != 0) {
+ if (db == nullptr) {
+ // user specified a path, but DB file was not found
+ err("%s using clang compilation database path of: \"%s\"\n", error.c_str(),
+ clangCompileDatabase.data());
+ } else {
+ // check if the file we are parsing is in the DB
+ command = db->getCompileCommands(fileName);
+ if (!command.empty() ) {
+ // it's possible to have multiple entries for the same file, so use the last entry
+ clang_option_len = command[command.size()-1].CommandLine.size();
+ }
+ }
+ }
+ char **argv = (char**)malloc(sizeof(char*)*(4+Doxygen::inputPaths.count()+includePath.count()+clangOptions.count()+clang_option_len));
+ 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++] = strdup(option->c_str());
+ }
+ // this extra addition to argv is accounted for as we are skipping the first entry in
+ argv[argc++]=strdup("-w"); // finally, turn off warnings.
+ } else {
// add include paths for input files
for (di.toFirst();di.current();++di,++argc)
{
@@ -230,6 +262,7 @@ void ClangParser::start(const char *fileName,QStrList &filesInTranslationUnit)
// provide the input and and its dependencies as unsaved files so we can
// pass the filtered versions
argv[argc++]=strdup(fileName);
+ }
static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
//printf("source %s ----------\n%s\n-------------\n\n",
// fileName,p->source.data());
diff --git a/src/commentcnv.l b/src/commentcnv.l
index 6fea6c9..ebee914 100644
--- a/src/commentcnv.l
+++ b/src/commentcnv.l
@@ -89,6 +89,8 @@ static int g_lastBlockContext;
static bool g_pythonDocString;
static int g_nestingCount;
+static bool g_vhdl; // for VHDL old style --! comment
+
static SrcLangExt g_lang;
static bool isFixedForm; // For Fortran
@@ -250,7 +252,7 @@ void replaceComment(int offset);
%%
-<Scan>[^"'!\/\n\\#-,]* { /* eat anything that is not " / , or \n */
+<Scan>[^"'!\/\n\\#,\-]* { /* eat anything that is not " / , or \n */
copyToOutput(yytext,(int)yyleng);
}
<Scan>[,] { /* eat , so we have a nice separator in long initialization lines */
@@ -425,6 +427,7 @@ void replaceComment(int offset);
}
else
{
+ g_vhdl = TRUE;
copyToOutput(yytext,(int)yyleng);
g_nestingCount=0;
g_commentStack.clear(); /* to be on the save side */
@@ -664,7 +667,27 @@ void replaceComment(int offset);
}
}
}
-<CComment>"\n"/[ \t]*[^#] { /* end of Python comment */
+ /* Python an VHDL share CComment, so special attention for ending commments is required */
+<CComment>"\n"/[ \t]*"#" {
+ if (g_lang!=SrcLangExt_VHDL)
+ {
+ REJECT;
+ }
+ else
+ {
+ if (g_vhdl) // inside --! comment
+ {
+ g_vhdl = FALSE;
+ copyToOutput(yytext,(int)yyleng);
+ BEGIN(Scan);
+ }
+ else // C-type comment
+ {
+ REJECT;
+ }
+ }
+ }
+<CComment>"\n"/[ \t]*"-" {
if (g_lang!=SrcLangExt_Python || g_pythonDocString)
{
REJECT;
@@ -674,18 +697,38 @@ void replaceComment(int offset);
copyToOutput(yytext,(int)yyleng);
BEGIN(Scan);
}
- }
-<CComment>"\n"/[ \t]*[^\-] { /* end of VHDL comment */
- if (g_lang!=SrcLangExt_VHDL)
- {
+ }
+<CComment>"\n"/[ \t]*[^ \t#\-] {
+ if (g_lang==SrcLangExt_Python)
+ {
+ if (g_pythonDocString)
+ {
+ REJECT;
+ }
+ else
+ {
+ copyToOutput(yytext,(int)yyleng);
+ BEGIN(Scan);
+ }
+ }
+ else if (g_lang==SrcLangExt_VHDL)
+ {
+ if (g_vhdl) // inside --! comment
+ {
+ g_vhdl = FALSE;
+ copyToOutput(yytext,(int)yyleng);
+ BEGIN(Scan);
+ }
+ else // C-type comment
+ {
+ REJECT;
+ }
+ }
+ else
+ {
REJECT;
- }
- else
- {
- copyToOutput(yytext,(int)yyleng);
- BEGIN(Scan);
- }
- }
+ }
+ }
/* removed for bug 674842 (bug was introduced in rev 768)
<CComment>"'" {
g_charContext = YY_START;
@@ -1001,6 +1044,7 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName)
g_condStack.setAutoDelete(TRUE);
g_commentStack.clear();
g_commentStack.setAutoDelete(TRUE);
+ g_vhdl = FALSE;
printlex(yy_flex_debug, TRUE, __FILE__, fileName);
isFixedForm = FALSE;
diff --git a/src/config.xml b/src/config.xml
index 8bb6add..6cd7997 100644
--- a/src/config.xml
+++ b/src/config.xml
@@ -1637,6 +1637,20 @@ to disable this feature.
]]>
</docs>
</option>
+ <option type='string' id='CLANG_COMPILATION_DATABASE_PATH' setting='USE_LIBCLANG' defval='0'>
+ <docs>
+<![CDATA[
+ If clang assisted parsing is enabled you can provide the clang parser with the
+ path to the <a href="http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html">
+ compilation database</a> used when the files were built. This is equivalent to
+ specifying the "-p" option to a clang tool, such as clang-check. These options
+ will then be pased to the parser.
+
+ @note The availability of this option depends on whether or not doxygen
+ was generated with the `-Duse-libclang=ON` option for CMake.
+ ]]>
+ </docs>
+ </option>
</group>
<group name='Index' docs='Configuration options related to the alphabetical class index'>
<option type='bool' id='ALPHABETICAL_INDEX' defval='1'>
diff --git a/src/docparser.cpp b/src/docparser.cpp
index 2602f78..5bb28ea 100644
--- a/src/docparser.cpp
+++ b/src/docparser.cpp
@@ -543,7 +543,7 @@ static void detectNoDocumentedParams()
}
else if (!g_memberDef->hasDocumentedParams())
{
- bool allDoc=TRUE; // no paramater => all parameters are documented
+ bool allDoc=TRUE; // no parameter => all parameters are documented
if ( // member has parameters
al!=0 && // but the member has a parameter list
al->count()>0 // with at least one parameter (that is not void)
diff --git a/src/dot.cpp b/src/dot.cpp
index 4189748..627989f 100644
--- a/src/dot.cpp
+++ b/src/dot.cpp
@@ -2477,7 +2477,7 @@ void DotGfxHierarchyTable::addClassList(ClassSDict *cl)
}
}
-DotGfxHierarchyTable::DotGfxHierarchyTable() : m_curNodeNumber(0)
+DotGfxHierarchyTable::DotGfxHierarchyTable() : m_curNodeNumber(1)
{
m_rootNodes = new QList<DotNode>;
m_usedNodes = new QDict<DotNode>(1009);
diff --git a/src/index.cpp b/src/index.cpp
index 10c1dcb..9cd1600 100644
--- a/src/index.cpp
+++ b/src/index.cpp
@@ -4122,7 +4122,7 @@ static void writeIndexHierarchyEntries(OutputList &ol,const QList<LayoutNavEntry
{
if (documentedNamespaces>0 && addToIndex)
{
- Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,0,0);
+ Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,lne->baseFile(),0);
Doxygen::indexList->incContentsDepth();
needsClosing=TRUE;
}
@@ -4151,7 +4151,7 @@ static void writeIndexHierarchyEntries(OutputList &ol,const QList<LayoutNavEntry
case LayoutNavEntry::Classes:
if (annotatedClasses>0 && addToIndex)
{
- Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,"annotated",0);
+ Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,lne->baseFile(),0);
Doxygen::indexList->incContentsDepth();
needsClosing=TRUE;
}
@@ -4189,7 +4189,7 @@ static void writeIndexHierarchyEntries(OutputList &ol,const QList<LayoutNavEntry
{
if (documentedHtmlFiles>0 && addToIndex)
{
- Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,0,0);
+ Doxygen::indexList->addContentsItem(TRUE,lne->title(),0,lne->baseFile(),0);
Doxygen::indexList->incContentsDepth();
needsClosing=TRUE;
}
diff --git a/src/memberlist.cpp b/src/memberlist.cpp
index 5349030..e19cead 100644
--- a/src/memberlist.cpp
+++ b/src/memberlist.cpp
@@ -426,6 +426,7 @@ void MemberList::writePlainDeclarations(OutputList &ol,
{
ol.endDoxyAnchor(md->getOutputFileBase(),md->anchor());
}
+ ol.endMemberItem();
if (!md->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
{
DocRoot *rootNode = validatingParseDoc(
@@ -452,7 +453,6 @@ void MemberList::writePlainDeclarations(OutputList &ol,
}
delete rootNode;
}
- ol.endMemberItem();
ol.endMemberDeclaration(md->anchor(),inheritId);
}
md->warnIfUndocumented();
diff --git a/src/parserintf.h b/src/parserintf.h
index cc95ea4..0942106 100644
--- a/src/parserintf.h
+++ b/src/parserintf.h
@@ -96,7 +96,7 @@ class ParserInterface
* is associated (non null in case of an inline fragment
* for a member).
* @param[in] showLineNumbers if set to TRUE and also fileDef is not 0,
- * line numbers will be added to the source fragement
+ * line numbers will be added to the source fragment
* @param[in] searchCtx context under which search data has to be stored.
* @param[in] collectXRefs collect cross-reference relations.
*/
diff --git a/src/portable.cpp b/src/portable.cpp
index 1983fe7..4ad88a4 100644
--- a/src/portable.cpp
+++ b/src/portable.cpp
@@ -180,6 +180,7 @@ int portable_system(const char *command,const char *args,bool commandHasConsole)
}
}
#endif
+ return 1; // we should never get here
}
diff --git a/src/translator_am.h b/src/translator_am.h
index 9e72529..6f5e671 100644
--- a/src/translator_am.h
+++ b/src/translator_am.h
@@ -80,26 +80,26 @@ class TranslatorArmenian : public TranslatorAdapter_1_8_0
{ return "Մանրամասն..."; }
/*! put in the class documentation */
- /* Dosn't use when optimization for C is on. */
+ /* Isn't used when optimization for C is on. */
virtual QCString trListOfAllMembers()
{
return "Բոլոր անդամների ցուցակը";
}
/*! used as the title of the "list of all members" page of a class */
- /* Dosn't use when optimization for C is on. */
+ /* Isn't used when optimization for C is on. */
virtual QCString trMemberList()
{
return "Անդամների ցուցակ";
}
/*! this is the first part of a sentence that is followed by a class name */
- /* Dosn't use when optimization for C is on. */
+ /* Isn't used when optimization for C is on. */
virtual QCString trThisIsTheListOfAllMembers()
{ return "Սա դասի անդամների ամբողջական ցուցակն է "; }
/*! this is the remainder of the sentence after the class name */
- /* Dosn't use when optimization for C is on. */
+ /* Isn't used when optimization for C is on. */
virtual QCString trIncludingInheritedMembers()
{ return ", ներառյալ բոլոր ժառանգված անդամները"; }
diff --git a/src/translator_ru.h b/src/translator_ru.h
index dbc734c..54c0202 100644
--- a/src/translator_ru.h
+++ b/src/translator_ru.h
@@ -83,26 +83,26 @@ class TranslatorRussian : public Translator
{ return "Подробнее..."; }
/*! put in the class documentation */
- /* Dosn't use when optimization for C is on. */
+ /* Isn't used when optimization for C is on. */
virtual QCString trListOfAllMembers()
{
return "Полный список членов класса";
}
/*! used as the title of the "list of all members" page of a class */
- /* Dosn't use when optimization for C is on. */
+ /* Isn't used when optimization for C is on. */
virtual QCString trMemberList()
{
return "Cписок членов класса";
}
/*! this is the first part of a sentence that is followed by a class name */
- /* Dosn't use when optimization for C is on. */
+ /* Isn't used when optimization for C is on. */
virtual QCString trThisIsTheListOfAllMembers()
{ return "Полный список членов класса "; }
/*! this is the remainder of the sentence after the class name */
- /* Dosn't use when optimization for C is on. */
+ /* Isn't used when optimization for C is on. */
virtual QCString trIncludingInheritedMembers()
{ return ", включая наследуемые из базового класса"; }
diff --git a/src/translator_ua.h b/src/translator_ua.h
index eac14aa..034cb1b 100644
--- a/src/translator_ua.h
+++ b/src/translator_ua.h
@@ -76,26 +76,26 @@ class TranslatorUkrainian : public TranslatorAdapter_1_8_4
{ return "Детальніше..."; }
/*! put in the class documentation */
- /* Dosn't use when optimization for C is on. */
+ /* Isn't used when optimization for C is on. */
virtual QCString trListOfAllMembers()
{
return "Список всіх елементів" ;
}
/*! used as the title of the "list of all members" page of a class */
- /* Dosn't use when optimization for C is on. */
+ /* Isn't used when optimization for C is on. */
virtual QCString trMemberList()
{
return "Cписок елементів" ;
}
/*! this is the first part of a sentence that is followed by a class name */
- /* Dosn't use when optimization for C is on. */
+ /* Isn't used when optimization for C is on. */
virtual QCString trThisIsTheListOfAllMembers()
{ return "Повний список елементів"; }
/*! this is the remainder of the sentence after the class name */
- /* Dosn't use when optimization for C is on. */
+ /* Isn't used when optimization for C is on. */
virtual QCString trIncludingInheritedMembers()
{ return ", включаючи всі успадковані елементи"; }