Compile errors when building kde-runtime

Hi all,

a few minutes ago one KDE developer reported that he was not able to
compile kde-runtime (git clone git://anongit.kde.org/kde-runtime) using
clang version 3.1 (http://llvm.org/git/clang.git
f196a90b26479a2c67959c6715491763cbc8ade1) and Qt 4.8. The errors have been
fixed in revision ac48ea95. At least the first ones (the (QHash<>) stuff)
seems to be present for a while, I see a commit 7 month ago that
introduced them to fix build using llvm-gcc on Apple.

I'm not involved in either LLVM nor Nepomuk stuff in any way, but I
thought you might be interested. I'm not on this list, so please keep me
in CC if you have any interesting insight. It may of course be that the
code was wrong, in this case we of course would like to know why.

I'll post the first parts of the errors below, there are lot of
duplications and later errors because of the first problems so I cut them
down.

Greetings,

Eike

error:
/home/sreich/devel/kde/src/KDE/kdebase/runtime/nepomuk/services/storage/datamanagementmodel.h:159:95:
error: expected ')'
error:
/home/sreich/devel/kde/src/KDE/kdebase/runtime/nepomuk/services/storage/datamanagementmodel.h:191:96:
error: expected ')'
error:
/home/sreich/devel/kde/src/KDE/kdebase/runtime/nepomuk/services/storage/datamanagementmodel.h:207:124:
error: expected ')'
error:
/home/sreich/devel/kde/src/KDE/kdebase/runtime/nepomuk/services/storage/datamanagementmodel.h:159:85:
error: expected '>'

/home/sreich/devel/kde/src/KDE/kdebase/runtime/nepomuk/services/storage/resourcemerger.cpp:509:27:
warning: parentheses were disambiguated as a function declarator
[-Wvexing-parse]
    Soprano::Node dateTime( Soprano::LiteralValue(
QDateTime::currentDateTime() ) );
                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/sreich/devel/kde/src/KDE/kdebase/runtime/nepomuk/services/storage/resourcemerger.cpp:509:63:
error: parameter declarator cannot be qualified
    Soprano::Node dateTime( Soprano::LiteralValue(
QDateTime::currentDateTime() ) );
                                                   ~~~~~~~~~~~^
/home/sreich/devel/kde/src/KDE/kdebase/runtime/nepomuk/services/storage/resourcemerger.cpp:510:14:
error: no matching member function for call to 'addStatement'
    m_model->addStatement( newUri, NAO::created(), dateTime, m_graph );
~~~~~~~~~^~~~~~~~~~~~
/home/sreich/devel/kde/install/kdesupport/include/Soprano/../soprano/filtermodel.h:81:26:
note: candidate function not viable: no known conversion from
'Soprano::Node (Soprano::LiteralValue ((*)()))' to
      'const Soprano::Node' for 3rd argument;
        Error::ErrorCode addStatement( const Node& subject, const Node&
predicate, const Node& object, const Node& context = Node() );
                         ^
/home/sreich/devel/kde/install/kdesupport/include/Soprano/../soprano/filtermodel.h:76:34:
note: candidate function not viable: requires 1 argument, but 4 were
provided
        virtual Error::ErrorCode addStatement( const Statement &statement );
                                 ^
/home/sreich/devel/kde/src/KDE/kdebase/runtime/nepomuk/services/storage/resourcemerger.cpp:511:14:
error: no matching member function for call to 'addStatement'
    m_model->addStatement( newUri, NAO::lastModified(), dateTime, m_graph
); ~~~~~~~~~^~~~~~~~~~~~
/home/sreich/devel/kde/install/kdesupport/include/Soprano/../soprano/filtermodel.h:81:26:
note: candidate function not viable: no known conversion from
'Soprano::Node (Soprano::LiteralValue ((*)()))' to
      'const Soprano::Node' for 3rd argument;
        Error::ErrorCode addStatement( const Node& subject, const Node&
predicate, const Node& object, const Node& context = Node() );
                         ^
/home/sreich/devel/kde/install/kdesupport/include/Soprano/../soprano/filtermodel.h:76:34:
note: candidate function not viable: requires 1 argument, but 4 were
provided
        virtual Error::ErrorCode addStatement( const Statement &statement );
                                 ^
/home/sreich/devel/kde/src/KDE/kdebase/runtime/nepomuk/services/storage/resourcemerger.cpp:509:27:
warning: parentheses were disambiguated as a function declarator
[-Wvexing-parse]
    Soprano::Node dateTime( Soprano::LiteralValue(
QDateTime::currentDateTime() ) );
                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/sreich/devel/kde/src/KDE/kdebase/runtime/nepomuk/services/storage/resourcemerger.cpp:509:63:
error: parameter declarator cannot be qualified
    Soprano::Node dateTime( Soprano::LiteralValue(
QDateTime::currentDateTime() ) );
                                                   ~~~~~~~~~~~^
/home/sreich/devel/kde/src/KDE/kdebase/runtime/nepomuk/services/storage/resourcemerger.cpp:510:14:
error: no matching member function for call to 'addStatement'
    m_model->addStatement( newUri, NAO::created(), dateTime, m_graph );
~~~~~~~~~^~~~~~~~~~~~
/home/sreich/devel/kde/install/kdesupport/include/Soprano/../soprano/filtermodel.h:81:26:
note: candidate function not viable: no known conversion from
'Soprano::Node (Soprano::LiteralValue ((*)()))' to
      'const Soprano::Node' for 3rd argument;
        Error::ErrorCode addStatement( const Node& subject, const Node&
predicate, const Node& object, const Node& context = Node() );
                         ^
/home/sreich/devel/kde/install/kdesupport/include/Soprano/../soprano/filtermodel.h:76:34:
note: candidate function not viable: requires 1 argument, but 4 were
provided
        virtual Error::ErrorCode addStatement( const Statement &statement );
                                 ^
/home/sreich/devel/kde/src/KDE/kdebase/runtime/nepomuk/services/storage/resourcemerger.cpp:511:14:
error: no matching member function for call to 'addStatement'
    m_model->addStatement( newUri, NAO::lastModified(), dateTime, m_graph
); ~~~~~~~~~^~~~~~~~~~~~
/home/sreich/devel/kde/install/kdesupport/include/Soprano/../soprano/filtermodel.h:81:26:
note: candidate function not viable: no known conversion from
'Soprano::Node (Soprano::LiteralValue ((*)()))' to
      'const Soprano::Node' for 3rd argument;
        Error::ErrorCode addStatement( const Node& subject, const Node&
predicate, const Node& object, const Node& context = Node() );
                         ^
/home/sreich/devel/kde/install/kdesupport/include/Soprano/../soprano/filtermodel.h:76:34:
note: candidate function not viable: requires 1 argument, but 4 were
provided
        virtual Error::ErrorCode addStatement( const Statement &statement );
                                 ^

reproducible with clang from today's git.

It looks like its the usual “most vexing parse”, with an astonishing cascade of diagnostics caused by it.

It’s a regrettable quirk of C++'s syntax, even has its own wikipedia page <http://en.wikipedia.org/wiki/Most_vexing_parse>.

Basically, this is the problem:

warning: parentheses were disambiguated as a function declarator
[-Wvexing-parse]
Soprano::Node dateTime( Soprano::LiteralValue(
QDateTime::currentDateTime() )

Clang sums it up quite nicely. That declaration declares a function dateTime, which is causing all the problems (failure to find overloads, etc.). An extra pair of parens should make the program mean what you intended (unless there’s something else going on that I missed among the cascade of errors):

Soprano::Node dateTime( Soprano::LiteralValue(QDateTime::currentDateTime() )
to
Soprano::Node dateTime( (Soprano::LiteralValue(QDateTime::currentDateTime()) )

This is one reason why C++11’s “uniform initialization syntax” is a win. It avoids this problem by using braces.

–Sean Silva

Are we smart enough to produce a fixit for this?

Jordy

How about something like this? It’s missing tests and stuff but I hope it’s in the right direction. Comments appreciated.

vexing-parse.txt (1.59 KB)

I wish we could have fixits for /both/ cases, like -Wparentheses (add parentheses OR change '=' to '=='). But in this case the only automatic way to do it is to add 'void' to the parameters for the inner object instead of an empty list. (The usual way would probably be to add a parameter name, but we can't suggest a name, can we?)

IIRC fixits for non-fatal warnings like this and -Wparentheses are supposed to put the "silence warning and nothing else" fixit first, so that -fixit won't change the behavior of the program as seen now. But there was discussion about this a while ago, and in this case the variable declaration /is/ more likely...

Jordy

I wish we could have fixits for /both/ cases, like -Wparentheses (add parentheses OR change '=' to '=='). But in this case the only automatic way to do it is to add 'void' to the parameters for the inner object instead of an empty list. (The usual way would probably be to add a parameter name, but we can't suggest a name, can we?)

IIRC fixits for non-fatal warnings like this and -Wparentheses are supposed to put the "silence warning and nothing else" fixit first, so that -fixit won't change the behavior of the program as seen now. But there was discussion about this a while ago, and in this case the variable declaration /is/ more likely...

For what it's worth, -fixit mode only applies fixits on the warning
itself. Fixits on notes are never automatically applied (as far as I
know/understand) so that's where semantic-changing fixits can be
found, in any order.

Very few warnings have fixits on them directly for this reason.

- David

Sorry for not replying sooner. This warning is definitely missing some notes, but if I understand you correctly fixits are also fine? They won’t be applied but they still offer some useful information about the exact code transformations that are needed to make the warning go away.

One more thing, the text “replace parentheses with an initializer to declare a variable” is copied from DiagnosticSemaKinds.td verbatim. It’s needed in the ParseTentative.cpp which knows nothing about definitions in Sema, so I’m guessing that there’s no better way to solve this than to have the same wording in two places?

I’m not sure you’ve understood the concepts correctly - fixits and notes aren’t alternatives, as such:
Clang emits diagnostics
There are 3 main kinds of diagnostics: warnings, errors, and notes
Notes usually follow warnings or errors and provide extra information
FixIts are associated with a diagnostic (a warning, error, or note).

So if you compile a simple parentheses violation:
int main() { int i; if (i = 3) ; }

You’ll see the following output:

/tmp/webcompile/_1316_0.cc:1:27: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
int main() { int i; if (i = 3) ; }
                        ~~^~~
/tmp/webcompile/_1316_0.cc:1:27: note: place parentheses around the assignment to silence this warning
int main() { int i; if (i = 3) ; }
                          ^
                        (    )
/tmp/webcompile/_1316_0.cc:1:27: note: use '==' to turn this assignment into an equality comparison
int main() { int i; if (i = 3) ; }
                          ^