Bug 338649

Summary: Extend C++ import for C++11
Product: [Applications] umbrello Reporter: Mark Stanton <mark>
Component: generalAssignee: Umbrello Development Group <umbrello-devel>
Status: CONFIRMED ---    
Severity: wishlist CC: bzk0711, milasudril, okellogg, ralf.habacker
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: Fedora RPMs   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:

Description Mark Stanton 2014-08-29 11:10:03 UTC
That's it, this structure ("enum class") causes the import (of the file it occurs in) to fail.
Version 2.13.3 of Umbrello

Reproducible: Always
Comment 1 Mark Stanton 2014-08-29 11:15:53 UTC
I should have added "C++" to import, sorry.
Comment 2 Oliver Kellogg 2014-08-29 17:40:24 UTC
(In reply to Mark Stanton from comment #1)
> I should have added "C++" to import, sorry.

Changing the title accordingly.
BTW, Umbrello's C++ import does not yet support C++11.
How about rephrasing the PR as a wish, e.g. "Extend C++ import for C++11" or so.
Comment 3 Patric Schmitz 2015-12-14 09:49:16 UTC
Is anyone working on this? I really start liking with umbrello right now, however having the import not working for this C++11 codebase is kind of a bummer. I might try to look into it if noone does already, and I find the time..

Aside question: Will I be able to continuously sync my umbrello representation by reimporting changes sources?
Comment 4 milasudril 2016-01-01 09:38:31 UTC
*** Bug 357372 has been marked as a duplicate of this bug. ***
Comment 5 milasudril 2016-01-01 09:40:16 UTC
I thought libclang would be usable. This way, new features would already be implemented there.
Comment 6 Ralf Habacker 2016-01-03 00:01:02 UTC
(In reply to milasudril from comment #5)
> I thought libclang would be usable. This way, new features would already be implemented there.
It may be usable, but noone has opened a working branch and tried to implement this until now.
Umbrello always used a copy of the kdevelop c++ parser in the past and it seem to be the easiest to also reuse the clang based c++ language plugin from kdevelop (see https://techbase.kde.org/Projects/KDevelop4/ClangRoadmap#Why_Clang) 

Some of the Issues which need to be solved are:
1. umbrello needs to be refactored for running kdevelop clang language plugin
2. clang AST is completly different from kdevelop's c++ parser AST, which requires a rewrite of the AST to uml model binding (currently cpp2uml.cpp)
3. The recently used parser is very tolerant against incomplete c++ code, which is not the case for clang, which needs to be called similar to a compiler building the related source code. Incomplete code may come from missing include pathes or defines only available inside the build system of the imported source code files. This may require to run the parser similar to the coverity scan tools, which runs on top of a configured build system.

Links:
http://milianw.de/blog/katekdevelop-sprint-2014-let-there-be-clang
http://llvm.org/devmtg/2015-04/slides/Funk_Libclang_Integration_KDevelop.pdf
Comment 7 Ralf Habacker 2016-01-18 15:49:30 UTC
(In reply to Ralf Habacker from comment #6)
> 3. The recently used parser is very tolerant against incomplete c++ code,
> which is not the case for clang, which needs to be called similar to a
> compiler building the related source code. Incomplete code may come from
> missing include pathes or defines only available inside the build system of
> the imported source code files. This may require to run the parser similar
> to the coverity scan tools, which runs on top of a configured build system.

If someone will give it a try: For cmake based projects on linux the following receipt can be used to get an AST (based on the hints at http://clang.llvm.org/docs/LibTooling.html)
1. unpack  umbrello source into <umbrello-source-dir>
2. mkdir <umbrello-build-dir>
3. cd <umbrello-build-dir>
4. CC=/usr/bin/clang CXX=/usr/bin/clang++ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON  <umbrello-source-dir>
5. run clang-check -ast-dump -p $PWD <umbrello-source-dir>/umbrello/umlscene.cpp
TranslationUnitDecl 0xf54940 <<invalid sloc>>
|-TypedefDecl 0xf54e80 <<invalid sloc>> __int128_t '__int128'
|-TypedefDecl 0xf54ee0 <<invalid sloc>> __uint128_t 'unsigned __int128'
|-TypedefDecl 0xf552a0 <<invalid sloc>> __builtin_va_list '__va_list_tag [1]'
|-TypedefDecl 0xf55390 </usr/bin/../lib64/clang/3.3/include/stddef.h:34:1, col:26> ptrdiff_t 'long'
|-TypedefDecl 0xf553f0 <line:42:1, col:23> size_t 'unsigned long'
|-TypedefDecl 0xf55450 </usr/include/QtCore/qglobal.h:1044:1, col:21> qint8 'signed char'
.....
Comment 8 Patric Schmitz 2016-01-18 16:43:28 UTC
On 01/03/2016 01:01 AM, Ralf Habacker via KDE Bugzilla wrote:
> ...clang, which needs to be called similar to a compiler
> building the related source code

I actually see this as a major problem. Requiring people to have a full build set up would severely limed the usefulness of the tool. I might not even have complete sourcetree available, but just get a bunch of related cpp files from "somewhere" (a collaborator, some old project which no longer builds, ...) and want to import the classes into umbrello.

If this is a basic limitation to using clang, is this really the way the project should go? Maybe it is possible to separate only the parser parts without the whole semantics and error checking from clang? I have no idea about clang internals I must say.

An alternative could be using some parser generator such as antlr or bison to get a syntax tree? I looked around (for maybe half an hour) some weeks ago but it seemed there is nothing yet which would properly parse c++11/14 syntax..
Comment 9 Ralf Habacker 2016-01-18 22:15:16 UTC
(In reply to Patric Schmitz from comment #8)
> On 01/03/2016 01:01 AM, Ralf Habacker via KDE Bugzilla wrote:
> > ...clang, which needs to be called similar to a compiler
> > building the related source code
> 
> I actually see this as a major problem. Requiring people to have a full
> build set up would severely limed the usefulness of the tool. I might not
> even have complete sourcetree available, but just get a bunch of related cpp
> files from "somewhere" (a collaborator, some old project which no longer
> builds, ...) and want to import the classes into umbrello.
This is the advantage of the recent parser :-)

From recent observations at least all related classes should not be undefined. Here is a simple example with llvm 3.7:
1. Variant
class QFont;
class Test {
public:
    Test(QFont *font) : m_font(font) {}
    QFont *m_font;
};

running  'clang-check test1.cpp -ast-dump  --' returns
TranslationUnitDecl 0xb75da0 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0xb762d8 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
|-TypedefDecl 0xb76338 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
|-TypedefDecl 0xb76718 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list '__va_list_tag [1]'
|-CXXRecordDecl 0xb76768 </home/ralf/src/umbrello-master/unittests/test.cpp:2:1, col:7> col:7 referenced class QFont
`-CXXRecordDecl 0xb76820 <line:4:1, line:10:1> line:4:7 class Test definition
  |-CXXRecordDecl 0xb76930 <col:1, col:7> col:7 implicit referenced class Test
  |-AccessSpecDecl 0xb769c0 <line:5:1, col:7> col:1 public
  |-CXXConstructorDecl 0xbc2060 <line:6:5, col:39> col:5 Test 'void (class QFont *)'
  | |-ParmVarDecl 0xb76a28 <col:10, col:17> col:17 used font 'class QFont *'
  | |-CXXCtorInitializer Field 0xbc2138 'm_font' 'class QFont *'
  | | `-ImplicitCastExpr 0xbc2200 <col:32> 'class QFont *' <LValueToRValue>
  | |   `-DeclRefExpr 0xbc21a8 <col:32> 'class QFont *' lvalue ParmVar 0xb76a28 'font' 'class QFont *'
  | `-CompoundStmt 0xbc2248 <col:38, col:39>
  `-FieldDecl 0xbc2138 <line:8:5, col:12> col:12 m_font 'class QFont *'
-> no errors, complete AST

2. variant, using incomplete class QFont
class QFont;
class Test {
public:
    Test(const &QFont font) : m_font(font) {}
    QFont m_font; 
};

running  'clang-check test2.cpp -ast-dump  --' returns
TranslationUnitDecl 0x15afda0 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x15b02d8 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
|-TypedefDecl 0x15b0338 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
|-TypedefDecl 0x15b0718 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list '__va_list_tag [1]'
|-CXXRecordDecl 0x15b0768 </home/ralf/src/umbrello-master/unittests/test.cpp:2:1, col:7> col:7 referenced class QFont
`-CXXRecordDecl 0x15b0820 <line:4:1, line:11:1> line:4:7 invalid class Test definition
  |-CXXRecordDecl 0x15b0930 <col:1, col:7> col:7 implicit referenced class Test
  |-AccessSpecDecl 0x15b09c0 <line:5:1, col:7> col:1 public
  |-CXXConstructorDecl 0x15fc060 <line:6:5, col:45> col:5 invalid Test 'void (const int &)'
  | |-ParmVarDecl 0x15b0a30 <col:10, col:17> col:17 used invalid QFont 'const int &'
  | `-CompoundStmt 0x15fc618 <col:44, col:45>
  `-FieldDecl 0x15fc4c0 <line:9:5, col:11> col:11 invalid m_font 'class QFont'
> 4 errors generated, incomplete AST.
 
> If this is a basic limitation to using clang, is this really the way the project should go? 
> Maybe it is possible to separate only the parser parts without the whole semantics and error checking from clang? 
I don' know yet; it need to be evaluated
> An alternative could be using some parser generator such as antlr or bison
> to get a syntax tree? 
In theory yes, but ... 
> I looked around (for maybe half an hour) some weeks ago 
> but it seemed there is nothing yet which would properly parse c++11/14  syntax.
switching to such a generated parser requires refactoring (=new write) of the parsed output to UML model mapping.

The third alternative is to extend the recent parser, which is not very complicated. It has good debugging support (see category 'cppparser' in debug dock window) . [1]

Beside the parser stuff there is the need to design how these features should be mapped to the UML model. 
As an example there is the question how 'constexpr' (https://en.wikipedia.org/wiki/C%2B%2B11#constexpr_.E2.80.93_Generalized_constant_expressions) should be modeled ?  
Should it be modeled as stereotype 'constexpr', which requires only little refactoring on cpp import/codegeneration (setup stereotype after creating UMLOperation instance and write out 'constexpr' depending on presence of 'constexpr' stereotype) or as operation attribute similar to 'static', which requires extending the class UMLOperation (setter/getter,xmi save/load, property dialog). 

[1] According to the given example there it is only required to add a new lexer token TOKEN_const_expr and to extend CppTree2Uml::parseFunctionDefinition() to be able to setup the related UMLOperation instance.

My proposal for an implementation of this feature is 
1. Design how the related C+11 features at  https://en.wikipedia.org/wiki/C%2B%2B11 should be modeled in umbrello
2. Implement the required changes in the UML model and properties dialogs
3. Create test cases from the code fragments at https://en.wikipedia.org/wiki/C%2B%2B11 and extend the related lexer, parser  and parser stuff.
Comment 10 Patric Schmitz 2016-01-19 00:43:28 UTC
>> If this is a basic limitation to using clang, is this really the way the project should go? 
>> Maybe it is possible to separate only the parser parts without the whole semantics and error checking from clang? 
> I don' know yet; it need to be evaluated

It seems that clang itself has no means of parsing incomplete code fragments and will fail to produce a syntax tree at all if not all types and symbols can be resolved. This is at least what I get out of this post from Clang Developers:
> http://clang-developers.42468.n3.nabble.com/Lenient-lexing-parsing-of-code-snippets-td4042786.html

There is a GSoC 2014 project mentioned where someone has a similar requirement (for syntax highlighting). Maybe we could look into that, it seems a fuzzy parser has been developed for that project. However I assume we would end up with something comparable to what KDevelop has right now, and could probably also extend the current parser to account for 11/14.

>> An alternative could be using some parser generator...
> ...

> The third alternative is to extend the recent parser, which is not very
> complicated. It has good debugging support (see category 'cppparser' in debug
> dock window) . [1]

Probably the most reasonable way to go about it after all?

> Beside the parser stuff there is the need to design how these features should
> be mapped to the UML model. 
> As an example there is the question how 'constexpr'
> (https://en.wikipedia.org/wiki/C%2B%2B11#constexpr_.E2.80.93_Generalized_constant_expressions)
> should be modeled ?

Hmm in the case of constexpr I don't see why one would want to model this at all. It is a very specific C++ language feature after all and does not really have an equivalent in the UML standard, no? (I don't know either perfectly so I'm not entirely sure about this).
Comment 11 Ralf Habacker 2016-01-19 08:03:25 UTC
(In reply to Patric Schmitz from comment #10)
> >> If this is a basic limitation to using clang, is this really the way the project should go? 
> >> Maybe it is possible to separate only the parser parts without the whole semantics and error checking from clang? 
> > I don' know yet; it need to be evaluated
> 
> It seems that clang itself has no means of parsing incomplete code fragments
> and will fail to produce a syntax tree at all if not all types and symbols
> can be resolved. This is at least what I get out of this post from Clang
> Developers:
> > http://clang-developers.42468.n3.nabble.com/Lenient-lexing-parsing-of-code-snippets-td4042786.html
> There is a GSoC 2014 project mentioned where someone has a similar
> requirement (for syntax highlighting). Maybe we could look into that, it
> seems a fuzzy parser has been developed for that project. 
here is the related git repo https://github.com/kapf/clang-highlight
and a test case https://github.com/kapf/clang-highlight/blob/master/unittests/FuzzyParseTest.cpp
Comment 12 Ralf Habacker 2016-01-26 11:11:57 UTC
(In reply to Patric Schmitz from comment #10)
> >> If this is a basic limitation to using clang, is this really the way the project should go? 
> 
> Probably the most reasonable way to go about it after all?

For now yes
Comment 13 milasudril 2016-04-29 14:03:05 UTC
Doxygen has an option for CLANG_ASSISTED_PARSING since version 1.8.4.
Comment 14 Ralf Habacker 2016-05-28 16:36:32 UTC
Git commit 2de8b562409f8d502d0efe27c316e6ca4e2df1c8 by Ralf Habacker.
Committed on 28/05/2016 at 12:52.
Pushed by habacker into branch 'master'.

Add llvm test case.

M  +19   -0    unittests/CMakeLists.txt
A  +29   -0    unittests/TEST_llvm.cpp     [License: UNKNOWN]  *

The files marked with a * at the end have a non valid license. Please read: http://techbase.kde.org/Policies/Licensing_Policy and use the headers which are listed at that page.


http://commits.kde.org/umbrello/2de8b562409f8d502d0efe27c316e6ca4e2df1c8
Comment 15 Ralf Habacker 2016-05-30 21:30:37 UTC
Git commit d14553de1c33f9f087baa0d59d41223738eaa5d7 by Ralf Habacker.
Committed on 30/05/2016 at 21:30.
Pushed by habacker into branch 'master'.

Add missing license header.

M  +19   -0    unittests/TEST_llvm.cpp

http://commits.kde.org/umbrello/d14553de1c33f9f087baa0d59d41223738eaa5d7
Comment 16 Ralf Habacker 2016-09-09 05:35:02 UTC
Git commit 13a513d629e86e8cc98d750f1d9e5741bbc8791a by Ralf Habacker.
Committed on 09/09/2016 at 05:34.
Pushed by habacker into branch 'master'.

Add c++11 code import test cases.

A  +14   -0    test/import/cxx/cxx11-alternative-function-syntax.h     [License: UNKNOWN]  *
A  +1    -0    test/import/cxx/cxx11-constexpr.cpp     [License: Trivial file]
A  +9    -0    test/import/cxx/cxx11-constexpr.h     [License: UNKNOWN]  *
A  +24   -0    test/import/cxx/cxx11-explicit-overrides-and-final.h     [License: UNKNOWN]  *
A  +4    -0    test/import/cxx/cxx11-extern-template.h     [License: UNKNOWN]  *
A  +21   -0    test/import/cxx/cxx11-initializer-lists.h     [License: UNKNOWN]  *
A  +4    -0    test/import/cxx/cxx11-lambda-functions-and-expressions.h     [License: UNKNOWN]  *
A  +9    -0    test/import/cxx/cxx11-null-pointer-constant.h     [License: UNKNOWN]  *
A  +32   -0    test/import/cxx/cxx11-object-construction-improvement.h     [License: UNKNOWN]  *
A  +12   -0    test/import/cxx/cxx11-range-based-for-loop.h     [License: UNKNOWN]  *
A  +22   -0    test/import/cxx/cxx11-strongly-typed-enumerations.h     [License: UNKNOWN]  *
A  +29   -0    test/import/cxx/cxx11-type-inference.h     [License: UNKNOWN]  *
A  +31   -0    test/import/cxx/cxx11-uniform-initialization.h     [License: UNKNOWN]  *

The files marked with a * at the end have a non valid license. Please read: http://techbase.kde.org/Policies/Licensing_Policy and use the headers which are listed at that page.


http://commits.kde.org/umbrello/13a513d629e86e8cc98d750f1d9e5741bbc8791a
Comment 17 Ralf Habacker 2016-09-11 18:36:58 UTC
umbrello's git master branch got several c++11 related test cases. If someone has interest in umbrello having c++11 support feel free to extend the c++ parser and send patches one by one to this bug or kde review board.  

The parser is located at lib/cppparser/parser.cpp|h. If it is required to add additional abstract syntax tree classes, see  lib/cppparser/ast.cpp|h. After parsing it may be required to assign the newly parsed elements to related uml objects in umbrello/codeimport/kdevcppparser/cpptree2uml.cpp|h
Comment 18 milasudril 2021-04-06 12:48:21 UTC
Any update on this task?
Comment 19 Oliver Kellogg 2021-04-30 19:11:52 UTC
Git commit 464c7132349e4cf10a84fc9e6f3792087a934158 by Oliver Kellogg.
Committed on 30/04/2021 at 19:11.
Pushed by okellogg into branch 'release/21.04'.

Support C++11 "enum class" in C++ Import:

lib/cppparser/ast.{h,cpp} class EnumSpecifierAST
- Add functions setClass, isClass accessing new member m_isClass of type
  bool.
- Add functions setEnumBase, enumBase accessing new member m_enumBase
  of type TypeSpecifierAST::Node.

lib/cppparser/parser.cpp function parseEnumSpecifier
- Add bool isClass initialized to false.
- After consuming Token_enum add int tk initialized to
  m_lexer->lookAhead(0).
- If tk is Token_class or Token_struct then set isClass true and call
  nextToken().
- After call to parseName(name) add variable enumBase of type
  TypeSpecifierAST::Node.
- If m_lexer->lookAhead(0) is ':' then call nextToken() followed by
  parseSimpleTypeSpecifier(enumBase).
- Reassign tk from m_lexer->lookAhead(0) and permit only ';' or '{' as
  its value.
- Remove call to nextToken(), it is postponed to after the assignments
  to `ast'.
- At assignments to `ast' call ast->setClass(isClass) and
  ast->setEnumBase(enumBase).

test/import/cxx/cxx11-strongly-typed-enumerations.h
- Rename second definition of Enum2,Enum3 to Enum4,Enum5 to avoid
  overlap.

M  +12   -0    lib/cppparser/ast.cpp
M  +12   -0    lib/cppparser/ast.h
M  +40   -20   lib/cppparser/parser.cpp
M  +5    -4    test/import/cxx/cxx11-strongly-typed-enumerations.h

https://invent.kde.org/sdk/umbrello/commit/464c7132349e4cf10a84fc9e6f3792087a934158
Comment 20 Oliver Kellogg 2021-05-03 05:02:12 UTC
(In reply to milasudril from comment #18)
> Any update on this task?

A added support for C++11 "enum class" and it is working in a Qt4 based build.
However, on trying to import
https://invent.kde.org/sdk/umbrello/-/blob/master/test/import/cxx/cxx11-strongly-typed-enumerations.h
in a Qt5 based build I get a crash:

Application: Umbrello UML Modeller (umbrello5), signal: Aborted
Content of s_kcrashErrorMessage: [Current thread is 1 (Thread 0x7fc078f12e80 (LWP 9736))]
[KCrash Handler]
#6  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:49
#7  0x00007fc07c02c864 in __GI_abort () at abort.c:79
#8  0x00007fc07c60b10b in qt_message_fatal (message=<synthetic pointer>..., context=...) at global/qlogging.cpp:1914
#9  QMessageLogger::fatal(char const*, ...) const (this=this@entry=0x7fff14653b78, msg=msg@entry=0x7fc07c90aea0 "ASSERT: \"%s\" in file 
%s, line %d") at global/qlogging.cpp:893
#10 0x00007fc07c60a558 in qt_assert(char const*, char const*, int) (assertion=<optimized out>, file=<optimized out>, line=<optimized out
>) at global/qglobal.cpp:3358
#11 0x00000000007b9354 in Lexer::getOffset(QChar const*) const (this=0x7fff14654468, p=0x1852138) at /tools/umbrello-master/lib/cppparse
r/lexer.h:265
#12 0x00000000007bb835 in Lexer::currentPosition() const (this=0x7fff14654468) at /tools/umbrello-master/lib/cppparser/lexer.h:853
#13 0x00000000007b4845 in Lexer::nextToken(Token&, bool) (this=0x7fff14654468, tk=..., stopOnNewline=false) at /tools/umbrello-master/li
b/cppparser/lexer.cpp:255
#14 0x00000000007b660e in Lexer::tokenize() (this=0x7fff14654468) at /tools/umbrello-master/lib/cppparser/lexer.cpp:497
#15 0x00000000007b3e93 in Lexer::setSource(QString const&) (this=0x7fff14654468, source=...) at /tools/umbrello-master/lib/cppparser/lex
er.cpp:143
#16 0x00000000007ab000 in Driver::ParseHelper::ParseHelper(QString const&, bool, Driver*, bool, QString) (this=0x7fff14654420, fileName=
..., force=false, driver=0x10c0260, reportMessages=true, includedFrom=...) at /tools/umbrello-master/lib/cppparser/driver.cpp:321
#17 0x00000000007a0ebc in Driver::parseFile(QString const&, bool, bool, bool) (this=0x10c0260, fileName=..., onlyPreProcess=false, force
=false, macrosGlobal=false) at /tools/umbrello-master/lib/cppparser/driver.cpp:555
#18 0x0000000000777b8e in CppImport::parseFile(QString const&) (this=0x15e51d0, fileName=...) at /tools/umbrello-master/umbrello/codeimp
ort/cppimport.cpp:145
#19 0x0000000000776edd in ClassImport::importFile(QString const&) (this=0x15e51d0, fileName=...) at /tools/umbrello-master/umbrello/code
import/classimport.cpp:120
#20 0x000000000050c44c in CodeImpThread::run() (this=0x10cb250) at /tools/umbrello-master/umbrello/codeimpwizard/codeimpthread.cpp:62
#21 0x0000000000509d8d in CodeImpStatusPage::importCodeFile(bool) (this=0x7fc07000d050, noError=true) at /tools/umbrello-master/umbrello
/codeimpwizard/codeimpstatuspage.cpp:192
#22 0x00000000005098a9 in CodeImpStatusPage::importCode() (this=0x7fc07000d050) at /tools/umbrello-master/umbrello/codeimpwizard/codeimp
statuspage.cpp:161
#23 0x0000000000479103 in CodeImpStatusPage::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (_o=0x7fc07000d050, _c=QMetaOb
ject::InvokeMetaMethod, _id=0, _a=0x7fff14654a40) at /tools/umbrello-master/build/umbrello/libumbrello_autogen/6MVZBMHENV/moc_codeimpsta
tuspage.cpp:114
#24 0x00007fc07c85fc50 in doActivate<false>(QObject*, int, void**) (sender=0x1734400, signal_index=9, argv=argv@entry=0x7fff14654a40) at
 kernel/qobject.cpp:3898
#25 0x00007fc07c858f60 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (sender=sender@entry=0x1734400, m=m@entry=0x7
fc07d99f4e0 <QAbstractButton::staticMetaObject>, local_signal_index=local_signal_index@entry=2, argv=argv@entry=0x7fff14654a40) at kerne
l/qobject.cpp:3946
#26 0x00007fc07d5736a2 in QAbstractButton::clicked(bool) (this=this@entry=0x1734400, _t1=<optimized out>) at .moc/moc_qabstractbutton.cp
p:308
#27 0x00007fc07d57391a in QAbstractButtonPrivate::emitClicked() (this=0x1734440) at widgets/qabstractbutton.cpp:415
#28 0x00007fc07d575970 in QAbstractButtonPrivate::click() (this=0x1734440) at widgets/qabstractbutton.cpp:408
#29 0x00007fc07d575b91 in QAbstractButton::mouseReleaseEvent(QMouseEvent*) (this=0x1734400, e=0x7fff14654fc0) at widgets/qabstractbutton
.cpp:1044
#30 0x00007fc07d4c1b4e in QWidget::event(QEvent*) (this=0x1734400, event=0x7fff14654fc0) at kernel/qwidget.cpp:9019
#31 0x00007fc07d47faff in QApplicationPrivate::notify_helper(QObject*, QEvent*) (this=this@entry=0xbbfc00, receiver=receiver@entry=0x173
4400, e=e@entry=0x7fff14654fc0) at kernel/qapplication.cpp:3632
#32 0x00007fc07d4870cb in QApplication::notify(QObject*, QEvent*) (this=0x7fff14654cf0, receiver=0x1734400, e=0x7fff14654fc0) at kernel/
qapplication.cpp:3076
#33 0x00007fc07c82913a in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x1734400, event=0x7fff14654fc0) at kernel/qcor
eapplication.cpp:1063
#34 0x00007fc07d486103 in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&,
 bool, bool) (receiver=receiver@entry=0x1734400, event=event@entry=0x7fff14654fc0, alienWidget=alienWidget@entry=0x1734400, nativeWidget
=0x16de2d0, buttonDown=<optimized out>, lastMouseReceiver=..., spontaneous=true, onlyDispatchEnterLeave=false) at kernel/qapplication.cp
p:2614
#35 0x00007fc07d4db0dc in QWidgetWindow::handleMouseEvent(QMouseEvent*) (this=0x1655bc0, event=0x7fff14655280) at kernel/qwidgetwindow.c
pp:683
#36 0x00007fc07d4de505 in QWidgetWindow::event(QEvent*) (this=0x1655bc0, event=0x7fff14655280) at kernel/qwidgetwindow.cpp:300
#37 0x00007fc07d47faff in QApplicationPrivate::notify_helper(QObject*, QEvent*) (this=<optimized out>, receiver=0x1655bc0, e=0x7fff14655
280) at kernel/qapplication.cpp:3632
#38 0x00007fc07c82913a in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x1655bc0, event=0x7fff14655280) at kernel/qcor
eapplication.cpp:1063
#39 0x00007fc07cd2aff3 in QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) (e=0x17b0ec0) at kernel/
qguiapplication.cpp:2282
#40 0x00007fc07cd00c5c in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) (flags=flags@entry=...) 
at kernel/qwindowsysteminterface.cpp:1169
#41 0x00007fc076b22c9a in xcbSourceDispatch(GSource*, GSourceFunc, gpointer) (source=source@entry=0xcb96b0) at qxcbeventdispatcher.cpp:1
05
#42 0x00007fc07a9a7817 in g_main_dispatch (context=0x7fc070005000) at ../glib/gmain.c:3337
#43 g_main_context_dispatch (context=0x7fc070005000) at ../glib/gmain.c:4055
#44 0x00007fc07a9a7b98 in g_main_context_iterate (context=context@entry=0x7fc070005000, block=block@entry=1, dispatch=dispatch@entry=1, 
self=<optimized out>) at ../glib/gmain.c:4131
#45 0x00007fc07a9a7c4f in g_main_context_iteration (context=0x7fc070005000, may_block=may_block@entry=1) at ../glib/gmain.c:4196
#46 0x00007fc07c880d30 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (this=0xcc8a20, flags=...) at kerne
l/qeventdispatcher_glib.cpp:423
#47 0x00007fc07c827b7b in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (this=this@entry=0x7fff146555b0, flags=..., flags@entr
y=...) at ../../include/QtCore/../../src/corelib/global/qflags.h:69
#48 0x00007fc07d68ab6a in QDialog::exec() (this=0x16de2d0) at ../../include/QtCore/../../src/corelib/global/qflags.h:121
#49 0x00000000006e9015 in UMLApp::slotImportingWizard() (this=0xd1e1e0) at /tools/umbrello-master/umbrello/uml.cpp:2792
#50 0x000000000048273b in UMLApp::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (_o=0xd1e1e0, _c=QMetaObject::InvokeMetaM
ethod, _id=2, _a=0x7fff146557a0) at /tools/umbrello-master/build/umbrello/libumbrello_autogen/EWIEGA46WW/moc_uml.cpp:483
#51 0x00007fc07c85fc50 in doActivate<false>(QObject*, int, void**) (sender=0x104a0b0, signal_index=4, argv=argv@entry=0x7fff146557a0) at
 kernel/qobject.cpp:3898
#52 0x00007fc07c858f60 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (sender=sender@entry=0x104a0b0, m=m@entry=0x7
fc07d99a0a0 <QAction::staticMetaObject>, local_signal_index=local_signal_index@entry=1, argv=argv@entry=0x7fff146557a0) at kernel/qobjec
t.cpp:3946
#53 0x00007fc07d4791d2 in QAction::triggered(bool) (this=this@entry=0x104a0b0, _t1=<optimized out>) at .moc/moc_qaction.cpp:376
#54 0x00007fc07d47be28 in QAction::activate(QAction::ActionEvent) (this=0x104a0b0, event=<optimized out>) at kernel/qaction.cpp:1161
#55 0x00007fc07d6024e2 in QMenuPrivate::activateCausedStack(QVector<QPointer<QWidget> > const&, QAction*, QAction::ActionEvent, bool) (t
his=this@entry=0x1171d30, causedStack=..., action=action@entry=0x104a0b0, action_e=action_e@entry=QAction::Trigger, self=self@entry=true
) at widgets/qmenu.cpp:1384
#56 0x00007fc07d60a341 in QMenuPrivate::activateAction(QAction*, QAction::ActionEvent, bool) (this=0x1171d30, action=0x104a0b0, action_e
=QAction::Trigger, self=<optimized out>) at widgets/qmenu.cpp:1461
#57 0x00007fc07d4c1b4e in QWidget::event(QEvent*) (this=0x1165cf0, event=0x7fff14655da0) at kernel/qwidget.cpp:9019
#58 0x00007fc07d47faff in QApplicationPrivate::notify_helper(QObject*, QEvent*) (this=this@entry=0xbbfc00, receiver=receiver@entry=0x116
5cf0, e=e@entry=0x7fff14655da0) at kernel/qapplication.cpp:3632
#59 0x00007fc07d4870cb in QApplication::notify(QObject*, QEvent*) (this=0x7fff14655ad0, receiver=0x1165cf0, e=0x7fff14655da0) at kernel/
qapplication.cpp:3076
#60 0x00007fc07c82913a in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x1165cf0, event=0x7fff14655da0) at kernel/qcor
eapplication.cpp:1063
#61 0x00007fc07d486103 in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&,
 bool, bool) (receiver=0x1165cf0, event=event@entry=0x7fff14655da0, alienWidget=0x0, nativeWidget=0x1165cf0, buttonDown=<optimized out>,
 lastMouseReceiver=..., spontaneous=true, onlyDispatchEnterLeave=false) at kernel/qapplication.cpp:2614
#62 0x00007fc07d4dbbee in QWidgetWindow::handleMouseEvent(QMouseEvent*) (this=0x166bb50, event=0x7fff14656060) at kernel/qwidgetwindow.c
pp:580
#63 0x00007fc07d4de505 in QWidgetWindow::event(QEvent*) (this=0x166bb50, event=0x7fff14656060) at kernel/qwidgetwindow.cpp:300
#64 0x00007fc07d47faff in QApplicationPrivate::notify_helper(QObject*, QEvent*) (this=<optimized out>, receiver=0x166bb50, e=0x7fff14656
060) at kernel/qapplication.cpp:3632
#65 0x00007fc07c82913a in QCoreApplication::notifyInternal2(QObject*, QEvent*) (receiver=0x166bb50, event=0x7fff14656060) at kernel/qcor
eapplication.cpp:1063
#66 0x00007fc07cd2aff3 in QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) (e=0x7fbffc00d810) at ke
rnel/qguiapplication.cpp:2282
#67 0x00007fc07cd00c5c in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) (flags=flags@entry=...) 
at kernel/qwindowsysteminterface.cpp:1169
#68 0x00007fc076b22c9a in xcbSourceDispatch(GSource*, GSourceFunc, gpointer) (source=source@entry=0xcb96b0) at qxcbeventdispatcher.cpp:1
05
#69 0x00007fc07a9a7817 in g_main_dispatch (context=0x7fc070005000) at ../glib/gmain.c:3337
#70 g_main_context_dispatch (context=0x7fc070005000) at ../glib/gmain.c:4055
#71 0x00007fc07a9a7b98 in g_main_context_iterate (context=context@entry=0x7fc070005000, block=block@entry=1, dispatch=dispatch@entry=1, 
self=<optimized out>) at ../glib/gmain.c:4131
#72 0x00007fc07a9a7c4f in g_main_context_iteration (context=0x7fc070005000, may_block=may_block@entry=1) at ../glib/gmain.c:4196
#73 0x00007fc07c880d30 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (this=0xcc8a20, flags=...) at kerne
l/qeventdispatcher_glib.cpp:423
#74 0x00007fc07c827b7b in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (this=this@entry=0x7fff14656390, flags=..., flags@entr
y=...) at ../../include/QtCore/../../src/corelib/global/qflags.h:69
#75 0x00007fc07c82fdb0 in QCoreApplication::exec() () at ../../include/QtCore/../../src/corelib/global/qflags.h:121
#76 0x0000000000470710 in main(int, char**) (argc=1, argv=0x7fff14656898) at /tools/umbrello-master/umbrello/main.cpp:240
Comment 21 Oliver Kellogg 2021-05-04 17:57:03 UTC
(In reply to Oliver Kellogg from comment #20)
> (In reply to milasudril from comment #18)
> > Any update on this task?
> 
> A added support for C++11 "enum class" and it is working in a Qt4 based
> build.
> However, on trying to import
> https://invent.kde.org/sdk/umbrello/-/blob/master/test/import/cxx/cxx11-
> strongly-typed-enumerations.h
> in a Qt5 based build I get a crash:
> [...]

I hereby revoke the crash report, it turned out to be a hardware glitch on the build machine.
I tried again on a Windows machine with Cygwin/Qt5/KF5 and the file was imported fine.
Comment 22 Oliver Kellogg 2021-05-09 15:47:38 UTC
Git commit 7d3eb053739413a0eef8c111e0c9a41843227cf2 by Oliver Kellogg.
Committed on 09/05/2021 at 15:47.
Pushed by okellogg into branch 'release/21.04'.

Fix crash reported in https://bugs.kde.org/show_bug.cgi?id=338649#c20
related to multiple calls of m_source.unicode() where the calls return
different address values.
The solution is to call m_source.unicode() only once:

lib/cppparser/lexer.h
- In class Lexer add private member m_src of type const QChar*.

lib/cppparser/lexer.cpp
- In function Lexer::setSource,
  - assign m_source.unicode() to m_src;
  - if m_source.isEmpty() returns true then return without calling
    tokenize().
- In function Lexer::reset initialize m_src to null pointer.
- In function Lexer::offset return m_src + offset.
- In function Lexer::getOffset use m_src in lieu of src.
  This avoids the second call to m_source.unicode() which on newer Qt5
  versions may return a different buffer.

M  +8    -7    lib/cppparser/lexer.cpp
M  +1    -0    lib/cppparser/lexer.h

https://invent.kde.org/sdk/umbrello/commit/7d3eb053739413a0eef8c111e0c9a41843227cf2
Comment 23 Oliver Kellogg 2021-05-13 16:50:23 UTC
Git commit 3041141b10361aedb3c8c06c9ba36b5d25ac6f9a by Oliver Kellogg.
Committed on 13/05/2021 at 16:49.
Pushed by okellogg into branch 'release/21.04'.

lib/cppparser/lexer.{h,cpp} followup to commit 7d3eb05,
> Fix crash [...] related to multiple calls of m_source.unicode() where
> the calls return different address values.
> The solution is to call m_source.unicode() only once: [...]

As detailed by jeremy_k at https://forum.qt.io/post/659243,
the above change does not remove the root cause:
- m_ptr is initially set to m_source.unicode()
- During the import, m_source is modified (e.g. by calls to function
  insertCurrent).
- These modifications invalidate the unicode buffer which is pointed to
  by m_ptr / m_endPtr.
Generally I do not see a significant advantage in using the unicode
buffer in this context.

Changes in class Lexer:
- Remove public functions
  - const CHARTYPE* offset(int offset) const;
  - int getOffset(const QChar* p) const.
- Remove private function
  void setEndPtr(const QChar* c).
- Remove private members m_src, m_ptr, m_endPtr of type `const QChar*`.
- Add private members m_idx, m_endIdx of type int.
  These are used as indexes into m_source.

M  +26   -56   lib/cppparser/lexer.cpp
M  +2    -14   lib/cppparser/lexer.h

https://invent.kde.org/sdk/umbrello/commit/3041141b10361aedb3c8c06c9ba36b5d25ac6f9a
Comment 24 Oliver Kellogg 2021-09-10 05:52:10 UTC
Git commit 0372f89d7995a5fbc557e6c6090208bc54950e88 by Oliver Kellogg.
Committed on 10/09/2021 at 05:51.
Pushed by okellogg into branch 'master'.

Fix for "C++ importer does not recognize 'noexcept' keyword" :

lib/cppparser/keywords.h
- Align INSERT calls as table. Add INSERT("noexcept", Token_noexcept).

lib/cppparser/lexer.h
- In enum Type add Token_noexcept.

lib/cppparser/parser.cpp
- In functions skipUntilDeclaration, skipUntilStatement while-loop
  switch add case Token_noexcept.
- In function parseExceptionSpecification handle the case
  (m_lexer->lookAhead(0) == Token_noexcept).

test/import/cxx/const-methods.h
- Rename file to const-noexcept-methods.h.

test/import/cxx/const-noexcept-methods.h
- Rename class to ConstNoexceptMethodClass.
- Add NoexceptMethod with trailing noexcept.
- Add ConstNoexceptMethod with const noexcept and implementation.
Related: bug 442134

M  +84   -83   lib/cppparser/keywords.h
M  +1    -0    lib/cppparser/lexer.h
M  +15   -2    lib/cppparser/parser.cpp
D  +0    -3    test/import/cxx/const-methods.h
A  +5    -0    test/import/cxx/const-noexcept-methods.h  *

The files marked with a * at the end have a non valid license. Please read: https://community.kde.org/Policies/Licensing_Policy and use the headers which are listed at that page.


https://invent.kde.org/sdk/umbrello/commit/0372f89d7995a5fbc557e6c6090208bc54950e88