From 43f3e69f33bd50e05d81295e216a85191739c47b Mon Sep 17 00:00:00 2001 From: Kevin Kofler Date: Sep 24 2015 23:23:24 +0000 Subject: Backport upstream crash fixes (abuse of temporaries) (#1266259, kde#347178) * Thu Sep 24 2015 Kevin Kofler - 9:4.7.1-10 - Backport upstream crash fixes (abuse of temporaries) (#1266259, kde#347178) --- diff --git a/kdevelop-4.7.1-fix-temporary-abuse-1.patch b/kdevelop-4.7.1-fix-temporary-abuse-1.patch new file mode 100644 index 0000000..288e72d --- /dev/null +++ b/kdevelop-4.7.1-fix-temporary-abuse-1.patch @@ -0,0 +1,33 @@ +From: Sébastien Lambert +Date: Mon, 22 Jun 2015 20:48:35 +0000 +Subject: Do not use function returning reference to temporary. +X-Git-Url: http://quickgit.kde.org/?p=kdevelop.git&a=commitdiff&h=6ef7b373a2284e24753b6eb249ba68da5d9a2444 +--- +Do not use function returning reference to temporary. + +REVIEW: 124126 +BUG: 347178 +--- + + +--- a/languages/cpp/cppduchain/cpppreprocessenvironment.cpp ++++ b/languages/cpp/cppduchain/cpppreprocessenvironment.cpp +@@ -117,7 +117,7 @@ + rpp::Environment::setMacro(const_cast(&it.ref())); //Do not use our overridden setMacro(..), because addDefinedMacro(..) is not needed(macro-sets should be merged separately) + + for( Cpp::ReferenceCountedStringSet::Iterator it = file->definedMacroNames().iterator(); it; ++it ) { +- m_macroNameSet.insert(it.ref()); ++ m_macroNameSet.insert(*it); + } + + //We don't have to care about efficiency too much here, unDefinedMacros should be a rather small set +@@ -126,7 +126,7 @@ + m->defined = false; + m->m_valueHashValid = false; + rpp::Environment::setMacro(m); //Do not use our overridden setMacro(..), because addDefinedMacro(..) is not needed(macro-sets should be merged separately) +- m_macroNameSet.remove(it.ref()); ++ m_macroNameSet.remove(*it); + } + } + + diff --git a/kdevelop-4.7.1-fix-temporary-abuse-2.patch b/kdevelop-4.7.1-fix-temporary-abuse-2.patch new file mode 100644 index 0000000..ae7ad7f --- /dev/null +++ b/kdevelop-4.7.1-fix-temporary-abuse-2.patch @@ -0,0 +1,1087 @@ +From: Milian Wolff +Date: Thu, 02 Jul 2015 22:17:50 +0000 +Subject: Remove ConvenientIterator::ref usage from oldcpp codebase. +X-Git-Url: http://quickgit.kde.org/?p=kdevelop.git&a=commitdiff&h=2f057e2190112e5e838ad7a04eb04a6fde6f2cde +--- +Remove ConvenientIterator::ref usage from oldcpp codebase. + +This requires some changes, as we cannot take the ptr address of +the macro anymore. Instead, we use them as value classes everywhere. +This may potentially degrade performance, but I don't have the time +to measure it right now with a release build and compare the impact. + +REVIEW: 124237 +--- + + +--- a/languages/cpp/cppduchain/cppduchain.cpp ++++ b/languages/cpp/cppduchain/cppduchain.cpp +@@ -426,17 +426,17 @@ + DUChainReadLocker lock(DUChain::lock()); + //Copy in all macros from the file + for( Cpp::ReferenceCountedMacroSet::Iterator it( file->definedMacros().iterator() ); it; ++it ) { +- if( line == -1 || line > it.ref().sourceLine || file->url() != it.ref().file ) { +- if(!disableMacros.contains( it.ref().name )) ++ if( line == -1 || line > (*it).sourceLine || file->url() != (*it).file ) { ++ if(!disableMacros.contains( (*it).name )) + { +- pp.environment()->setMacro( new rpp::pp_macro(it.ref()) ); ++ pp.environment()->setMacro( *it ); + } + } + } + for( Cpp::ReferenceCountedMacroSet::Iterator it( file->usedMacros().iterator() ); it; ++it ) { +- if( line == -1 || line > it.ref().sourceLine || file->url() != it.ref().file ) { +- if(!disableMacros.contains( it.ref().name )) +- pp.environment()->setMacro( new rpp::pp_macro(it.ref()) ); ++ if( line == -1 || line > (*it).sourceLine || file->url() != (*it).file ) { ++ if(!disableMacros.contains( (*it).name )) ++ pp.environment()->setMacro( *it ); + } + } + } + +--- a/languages/cpp/cppduchain/cpppreprocessenvironment.cpp ++++ b/languages/cpp/cppduchain/cpppreprocessenvironment.cpp +@@ -47,9 +47,9 @@ + + void CppPreprocessEnvironment::removeMacro(const KDevelop::IndexedString& macroName) { + m_macroNameSet.remove(macroName); +- rpp::pp_macro* m = new rpp::pp_macro; +- m->name = macroName; +- m->defined = false; ++ rpp::pp_macro m; ++ m.name = macroName; ++ m.defined = false; + rpp::Environment::setMacro(m); + } + +@@ -57,20 +57,20 @@ + m_strings.erase(str.index()); + } + +-rpp::pp_macro* CppPreprocessEnvironment::retrieveMacro(const KDevelop::IndexedString& name, bool isImportant) const { ++rpp::pp_macro CppPreprocessEnvironment::retrieveMacro(const KDevelop::IndexedString& name, bool isImportant) const { + //note all strings that can be affected by macros + if( !m_environmentFile || (onlyRecordImportantMacroUses && !isImportant) ) + return rpp::Environment::retrieveMacro(name, isImportant); + + //kDebug() << "retrieving macro" << name.str(); + +- rpp::pp_macro* ret = rpp::Environment::retrieveMacro(name, isImportant); ++ const rpp::pp_macro& ret = rpp::Environment::retrieveMacro(name, isImportant); + +- if( !ret || (!m_environmentFile->definedMacroNames().contains(name) && !m_environmentFile->unDefinedMacroNames().contains(name)) ) ++ if( !ret.isValid() || (!m_environmentFile->definedMacroNames().contains(name) && !m_environmentFile->unDefinedMacroNames().contains(name)) ) + m_strings.insert(name.index()); + +- if( ret ) +- m_environmentFile->usingMacro(*ret); ++ if( ret.isValid() ) ++ m_environmentFile->usingMacro(ret); + + return ret; + } +@@ -98,12 +98,13 @@ + * */ + void CppPreprocessEnvironment::merge( const Cpp::ReferenceCountedMacroSet& macros ) { + for( Cpp::ReferenceCountedMacroSet::Iterator it(macros.iterator()); it; ++it ) { +- rpp::Environment::setMacro(const_cast(&it.ref())); //Do not use our overridden setMacro(..), because addDefinedMacro(..) is not needed(macro-sets should be merged separately) ++ const auto& macro = *it; ++ rpp::Environment::setMacro(macro); //Do not use our overridden setMacro(..), because addDefinedMacro(..) is not needed(macro-sets should be merged separately) + +- if( !it.ref().isUndef() ) +- m_macroNameSet.insert(it.ref().name); ++ if( !macro.isUndef() ) ++ m_macroNameSet.insert(macro.name); + else +- m_macroNameSet.remove(it.ref().name); ++ m_macroNameSet.remove(macro.name); + } + } + +@@ -114,7 +115,7 @@ + m_environmentFile->merge(*file); + + for( Cpp::ReferenceCountedMacroSet::Iterator it(addedMacros.iterator()); it; ++it ) +- rpp::Environment::setMacro(const_cast(&it.ref())); //Do not use our overridden setMacro(..), because addDefinedMacro(..) is not needed(macro-sets should be merged separately) ++ rpp::Environment::setMacro(*it); //Do not use our overridden setMacro(..), because addDefinedMacro(..) is not needed(macro-sets should be merged separately) + + for( Cpp::ReferenceCountedStringSet::Iterator it = file->definedMacroNames().iterator(); it; ++it ) { + m_macroNameSet.insert(*it); +@@ -122,47 +123,47 @@ + + //We don't have to care about efficiency too much here, unDefinedMacros should be a rather small set + for( Cpp::ReferenceCountedStringSet::Iterator it = file->unDefinedMacroNames().iterator(); it; ++it ) { +- rpp::pp_macro* m = new rpp::pp_macro(*it); +- m->defined = false; +- m->m_valueHashValid = false; ++ rpp::pp_macro m(*it); ++ m.defined = false; ++ m.m_valueHashValid = false; + rpp::Environment::setMacro(m); //Do not use our overridden setMacro(..), because addDefinedMacro(..) is not needed(macro-sets should be merged separately) + m_macroNameSet.remove(*it); + } + } + +-void CppPreprocessEnvironment::setMacro(rpp::pp_macro* macro) { +- rpp::pp_macro* hadMacro = retrieveStoredMacro(macro->name); ++void CppPreprocessEnvironment::setMacro(const rpp::pp_macro& macro) { ++ const rpp::pp_macro& hadMacro = retrieveStoredMacro(macro.name); + +- if(hadMacro && hadMacro->fixed) { +- if(hadMacro->defineOnOverride && (hadMacro->file.isEmpty() || +- (macro->file.length() >= hadMacro->file.length() && +- memcmp(macro->file.c_str() + (macro->file.length() - hadMacro->file.length()), +- hadMacro->file.c_str(), +- hadMacro->file.length()) == 0))) ++ if(hadMacro.isValid() && hadMacro.fixed) { ++ if(hadMacro.defineOnOverride && (hadMacro.file.isEmpty() || ++ (macro.file.length() >= hadMacro.file.length() && ++ memcmp(macro.file.c_str() + (macro.file.length() - hadMacro.file.length()), ++ hadMacro.file.c_str(), ++ hadMacro.file.length()) == 0))) + { + // We have to define the macro now, as it is being overridden +- rpp::pp_macro* definedMacro = new rpp::pp_macro(*hadMacro); +- definedMacro->defined = true; +- if(!macro->isRepositoryMacro()) +- delete macro; +- macro = definedMacro; ++ rpp::pp_macro definedMacro = hadMacro; ++ definedMacro.defined = true; ++ setMacro(definedMacro, hadMacro); + }else{ + // A fixed macro exists, simply ignore the added macro +- if(!macro->isRepositoryMacro()) +- delete macro; + return; + } + } + ++ setMacro(macro, hadMacro); ++} ++ ++void CppPreprocessEnvironment::setMacro(const rpp::pp_macro& macro, const rpp::pp_macro& hadMacro) { + //kDebug() << "setting macro" << macro->name.str() << "with body" << macro->definition << "is undef:" << macro->isUndef(); + //Note defined macros + if( m_environmentFile ) +- m_environmentFile->addDefinedMacro(*macro, hadMacro); ++ m_environmentFile->addDefinedMacro(macro, hadMacro); + +- if( !macro->isUndef() ) +- m_macroNameSet.insert(macro->name); ++ if( !macro.isUndef() ) ++ m_macroNameSet.insert(macro.name); + else +- m_macroNameSet.remove(macro->name); ++ m_macroNameSet.remove(macro.name); + + rpp::Environment::setMacro(macro); + } + +--- a/languages/cpp/cppduchain/cpppreprocessenvironment.h ++++ b/languages/cpp/cppduchain/cpppreprocessenvironment.h +@@ -37,7 +37,7 @@ + ///@param leaveEnvironmentFile Whether the environment-file should be left untouched + void finishEnvironment(bool leaveEnvironmentFile = false); + +- virtual rpp::pp_macro* retrieveMacro( const KDevelop::IndexedString& name, bool isImportant ) const; ++ virtual rpp::pp_macro retrieveMacro( const KDevelop::IndexedString& name, bool isImportant ) const; + + void setEnvironmentFile( const KSharedPtr& environmentFile ); + KSharedPtr environmentFile() const; +@@ -53,7 +53,7 @@ + ///@param mergeEnvironments Whether the environment-files should also be merged using Cpp::EnvironmentFile::merge + void merge( const Cpp::EnvironmentFile* file, bool mergeEnvironments = false ); + +- virtual void setMacro(rpp::pp_macro* macro); ++ virtual void setMacro(const rpp::pp_macro& macro); + + virtual int type() const; + +@@ -83,6 +83,8 @@ + static void setRecordOnlyImportantString(bool); + + private: ++ void setMacro(const rpp::pp_macro& macro, const rpp::pp_macro& hadMacro); ++ + uint m_identityOffsetRestriction; + bool m_identityOffsetRestrictionEnabled; + bool m_finished; + +--- a/languages/cpp/cppduchain/environmentmanager.cpp ++++ b/languages/cpp/cppduchain/environmentmanager.cpp +@@ -170,7 +170,7 @@ + ret += ", "; + first = false; + +- ret += it.ref().toString(); ++ ret += (*it).toString(); + ++it; + } + return ret; +@@ -232,15 +232,14 @@ + const ReferenceCountedStringSet& conflicts = strings() - d_func()->m_usedMacroNames; + + for( ReferenceCountedStringSet::Iterator it(conflicts.iterator()); it; ++it ) { +- if (!environmentMacroNames.contains(it.ref())) { ++ if (!environmentMacroNames.contains(*it)) { + continue; + } +- rpp::pp_macro* m = cppEnvironment->retrieveStoredMacro( *it ); +- if(m && !m->isUndef()) { +- ++ const rpp::pp_macro& m = cppEnvironment->retrieveStoredMacro( *it ); ++ if(m.isValid() && !m.isUndef()) { + #ifdef DEBUG_LEXERCACHE + if(debugging()) { +- kDebug(9007) << "The environment contains a macro that can affect the cached file, but that should not exist:" << m->name.str(); ++ kDebug(9007) << "The environment contains a macro that can affect the cached file, but that should not exist:" << m.name.str(); + } + #endif + return false; +@@ -254,19 +253,20 @@ + ifDebug( kDebug(9007) << "Count of used macros that need to be verified:" << d_func()->m_usedMacros.set().count() ); + + for ( ReferenceCountedMacroSet::Iterator it( d_func()->m_usedMacros.iterator() ); it; ++it ) { +- rpp::pp_macro* m = cppEnvironment->retrieveStoredMacro( it.ref().name ); +- if ( !m || !(*m == it.ref()) ) { +- if( !m && it.ref().isUndef() ) { +- ifDebug( kDebug( 9007 ) << "Undef-macro" << it.ref().name.str() << "is ok" << m ); ++ const auto& macro = *it; ++ const auto& m = cppEnvironment->retrieveStoredMacro( macro.name ); ++ if ( !m.isValid() || m != macro ) { ++ if( !m.isValid() && macro.isUndef() ) { ++ ifDebug( kDebug( 9007 ) << "Undef-macro" << macro.name.str() << "is ok" << m ); + //It is okay, we did not find a macro, but the used macro is an undef macro + //Q_ASSERT(0); //Undef-macros should not be marked as used + } else { +- ifDebug( kDebug( 9007 ) << "The cached file " << url().str() << " used a macro called \"" << it.ref().name.str() << "\"(from" << it.ref().file.str() << "), but the environment" << (m ? "contains differing macro of that name" : "does not contain that macro") << ", the cached file is not used" ); +- ifDebug( if(m) { kDebug() << "Used macro: " << it.ref().toString() << "from" << it.ref().file.str() << "found:" << m->toString() << "from" << m->file.str(); } ); ++ ifDebug( kDebug( 9007 ) << "The cached file " << url().str() << " used a macro called \"" << macro.name.str() << "\"(from" << macro.file.str() << "), but the environment" << (m ? "contains differing macro of that name" : "does not contain that macro") << ", the cached file is not used" ); ++ ifDebug( if(m) { kDebug() << "Used macro: " << macro.toString() << "from" << macro.file.str() << "found:" << m->toString() << "from" << m->file.str(); } ); + return false; + } + }else{ +- ifDebug( kDebug( 9007 ) << it.ref().name.str() << "match" ); ++ ifDebug( kDebug( 9007 ) << macro.name.str() << "match" ); + } + } + +@@ -329,22 +329,24 @@ + return d_func()->m_contentStartLine; + } + +-void EnvironmentFile::addDefinedMacro( const rpp::pp_macro& macro, const rpp::pp_macro* previousOfSameName ) { ++void EnvironmentFile::addDefinedMacro( const rpp::pp_macro& macro, const rpp::pp_macro& previousOfSameName ) { + ENSURE_WRITE_LOCKED + #ifdef DEBUG_LEXERCACHE + if(debugging()) { + kDebug( 9007 ) << id(this) << "defined macro" << macro.name.str(); + } + #endif +- if( previousOfSameName && d_func()->m_definedMacros.contains(*previousOfSameName) ) +- d_func_dynamic()->m_definedMacros.remove( *previousOfSameName ); ++ if( previousOfSameName.isValid() && d_func()->m_definedMacros.contains(previousOfSameName) ) ++ d_func_dynamic()->m_definedMacros.remove( previousOfSameName ); + else if( d_func()->m_definedMacroNames.contains(macro.name) ) { + //Search if there is already a macro of the same name in the set, and remove it + //This is slow, but should not happen too often + ///@todo maybe give a warning, and find out how this can happen +- for( ReferenceCountedMacroSet::Iterator it( d_func()->m_definedMacros.iterator() ); it; ++it ) +- if( macro.name == it.ref().name ) +- d_func_dynamic()->m_definedMacros.remove(it.ref()); ++ for( ReferenceCountedMacroSet::Iterator it( d_func()->m_definedMacros.iterator() ); it; ++it ) { ++ const auto& m = *it; ++ if( macro.name == m.name ) ++ d_func_dynamic()->m_definedMacros.remove(m); ++ } + } + + if(macro.isUndef()) { +@@ -520,7 +522,7 @@ + Q_ASSERT(backup.set().setIndex() == file.d_func()->m_usedMacros.set().setIndex()); + + for(ReferenceCountedMacroSet::Iterator it( file.d_func()->m_usedMacros.iterator() ); it; ++it) { +- const rpp::pp_macro& macro(it.ref()); ++ const auto& macro = *it; + if( !definedMacroNamesSet.contains(macro.name.index()) && !unDefinedMacroNamesSet.contains(macro.name.index()) ) + addUsedMacros.insert(it.index()); + } +@@ -563,8 +565,7 @@ + if(!affectedMacros.isEmpty()) { + //We have to iterate through all potentially removed macros + for( ReferenceCountedMacroSet::Iterator it( potentiallyRemoveMacros.iterator() ); it; ++it ) { +- const rpp::pp_macro& macro(it.ref()); +- if( affectedMacros.contains( macro.name ) ) ++ if( affectedMacros.contains( (*it).name ) ) + removeDefinedMacros.insert(it.index()); + } + } + +--- a/languages/cpp/cppduchain/environmentmanager.h ++++ b/languages/cpp/cppduchain/environmentmanager.h +@@ -102,7 +102,6 @@ + + + namespace rpp { +- class pp_macro; + class pp_macro; + class Environment; + } +@@ -217,7 +216,7 @@ + void addStrings( const std::set& strings ); + + ///If there previously was a macro defined of the same name, it must be given through previousOfSameName, else it can be zero. +- void addDefinedMacro( const rpp::pp_macro& macro, const rpp::pp_macro* previousOfSameName ); ++ void addDefinedMacro( const rpp::pp_macro& macro, const rpp::pp_macro& previousOfSameName ); + + ///the given macro will only make it into usedMacros() if it was not defined in this file + void usingMacro( const rpp::pp_macro& macro ); + +--- a/languages/cpp/cppduchain/tests/testenvironment.cpp ++++ b/languages/cpp/cppduchain/tests/testenvironment.cpp +@@ -57,16 +57,16 @@ + rpp::pp_macro m1(IndexedString(QString("my1Macro%1").arg(i))); + rpp::pp_macro m2(IndexedString(QString("my2Macro%1").arg(i))); + // define the two in the files +- f1.addDefinedMacro(m1, 0); +- f2.addDefinedMacro(m2, 0); ++ f1.addDefinedMacro(m1, {}); ++ f2.addDefinedMacro(m2, {}); + // undef them in the other file + m1.defined = false; + m2.defined = false; +- f1.addDefinedMacro(m2, 0); +- f2.addDefinedMacro(m1, 0); ++ f1.addDefinedMacro(m2, {}); ++ f2.addDefinedMacro(m1, {}); + // and add some other macros +- f1.addDefinedMacro(rpp::pp_macro(IndexedString(QString("my1UntouchedMacro%1").arg(i))), 0); +- f2.addDefinedMacro(rpp::pp_macro(IndexedString(QString("my2UntouchedMacro%1").arg(i))), 0); ++ f1.addDefinedMacro(rpp::pp_macro(IndexedString(QString("my1UntouchedMacro%1").arg(i))), {}); ++ f2.addDefinedMacro(rpp::pp_macro(IndexedString(QString("my2UntouchedMacro%1").arg(i))), {}); + } + const IndexedString file(QLatin1String("f3")); + QBENCHMARK { + +--- a/languages/cpp/cpplanguagesupport.cpp ++++ b/languages/cpp/cpplanguagesupport.cpp +@@ -721,12 +721,12 @@ + return qMakePair(TopDUContextPointer(), SimpleRange::invalid()); + } + +-QPair CppLanguageSupport::usedMacroForPosition(const KUrl& url, const SimpleCursor& position) { ++QPair CppLanguageSupport::usedMacroForPosition(const KUrl& url, const SimpleCursor& position) { + //Extract the word under the cursor + + QPair, QString> found = cursorIdentifier(url, position); + if(!found.first.second.isValid()) +- return qMakePair(SimpleRange::invalid(), (const rpp::pp_macro*)0); ++ return qMakePair(SimpleRange::invalid(), rpp::pp_macro()); + + IndexedString word(found.first.first); + SimpleRange wordRange(found.first.second); +@@ -735,38 +735,40 @@ + DUChainReadLocker lock(DUChain::lock(), 100); + if(!lock.locked()) { + kDebug(9007) << "Failed to lock the du-chain in time"; +- return qMakePair(SimpleRange::invalid(), (const rpp::pp_macro*)0); ++ return qMakePair(SimpleRange::invalid(), rpp::pp_macro()); + } + + TopDUContext* ctx = standardContext(url, true); + if(word.str().isEmpty() || !ctx || !ctx->parsingEnvironmentFile()) +- return qMakePair(SimpleRange::invalid(), (const rpp::pp_macro*)0); ++ return qMakePair(SimpleRange::invalid(), rpp::pp_macro()); + + Cpp::EnvironmentFilePointer p(dynamic_cast(ctx->parsingEnvironmentFile().data())); + + Q_ASSERT(p); + + if(!p->usedMacroNames().contains(word) && !p->definedMacroNames().contains(word)) +- return qMakePair(SimpleRange::invalid(), (const rpp::pp_macro*)0); ++ return qMakePair(SimpleRange::invalid(), rpp::pp_macro()); + + //We need to do a flat search through all macros here, which really hurts + + Cpp::ReferenceCountedMacroSet::Iterator it = p->usedMacros().iterator(); + + while(it) { +- if(it.ref().name == word && !it.ref().isUndef()) +- return qMakePair(wordRange, &it.ref()); ++ const auto& macro = *it; ++ if(macro.name == word && !macro.isUndef()) ++ return qMakePair(wordRange, macro); + ++it; + } + + it = p->definedMacros().iterator(); + while(it) { +- if(it.ref().name == word && !it.ref().isUndef()) +- return qMakePair(wordRange, &it.ref()); ++ const auto& macro = *it; ++ if(macro.name == word && !macro.isUndef()) ++ return qMakePair(wordRange, macro); + ++it; + } + +- return qMakePair(SimpleRange::invalid(), (const rpp::pp_macro*)0); ++ return qMakePair(SimpleRange::invalid(), rpp::pp_macro()); + } + + SimpleRange CppLanguageSupport::specialLanguageObjectRange(const KUrl& url, const SimpleCursor& position) { +@@ -787,12 +787,12 @@ + return qMakePair(KUrl(import.first->url().str()), SimpleCursor(0,0)); + } + +- QPair m = usedMacroForPosition(url, position); ++ const QPair& m = usedMacroForPosition(url, position); + + if(!m.first.isValid()) + return qMakePair(KUrl(), SimpleCursor::invalid()); + +- return qMakePair(KUrl(m.second->file.str()), SimpleCursor(m.second->sourceLine, 0)); ++ return qMakePair(KUrl(m.second.file.str()), SimpleCursor(m.second.sourceLine, 0)); + } + + QWidget* CppLanguageSupport::specialLanguageObjectNavigationWidget(const KUrl& url, const SimpleCursor& position) { +@@ -813,7 +813,7 @@ + } + } + +- QPair m = usedMacroForPosition(url, position); ++ const QPair& m = usedMacroForPosition(url, position); + if(!m.first.isValid()) + return 0; + +@@ -824,7 +824,7 @@ + QString preprocessedBody; + //Check whether tail contains arguments + QString tail = found.second.trimmed(); ///@todo make this better. +- if(m.second->function_like) { ++ if(m.second.function_like) { + if(tail.endsWith('\\')) + tail.truncate(tail.length() - 1); + //properly support macro expansions when arguments contain newlines +@@ -861,7 +861,7 @@ + preprocessedBody = i->formatSourceWithStyle(style, preprocessedBody, KUrl(), mime); + } + +- return new Cpp::NavigationWidget(*m.second, preprocessedBody); ++ return new Cpp::NavigationWidget(m.second, preprocessedBody); + } + + UIBlockTester::UIBlockTesterThread::UIBlockTesterThread( UIBlockTester& parent ) : QThread(), m_parent( parent ), m_stop(false) { +--- a/languages/cpp/cpplanguagesupport.h ++++ b/languages/cpp/cpplanguagesupport.h +@@ -150,7 +150,7 @@ + + QPair importedContextForPosition(const KUrl& url, const KDevelop::SimpleCursor& position); + +- QPair usedMacroForPosition(const KUrl& url, const KDevelop::SimpleCursor& position); ++ QPair usedMacroForPosition(const KUrl& url, const KDevelop::SimpleCursor& position); + + virtual KDevelop::SimpleRange specialLanguageObjectRange(const KUrl& url, const KDevelop::SimpleCursor& position); + +--- a/languages/cpp/cppparsejob.cpp ++++ b/languages/cpp/cppparsejob.cpp +@@ -229,8 +229,8 @@ + + for(QHash::const_iterator it = defines.constBegin(); it != defines.constEnd(); ++it) + { +- rpp::pp_macro* m = new rpp::pp_macro(IndexedString(it.key())); +- m->setDefinitionText( *it ); ++ rpp::pp_macro m(IndexedString(it.key())); ++ m.setDefinitionText( *it ); + + //Call rpp::Environment::setMacro directly, so we don't add the macro to the environment-file. + //It should be only part of the environment. + +--- a/languages/cpp/parser/rpp/pp-engine.cpp ++++ b/languages/cpp/parser/rpp/pp-engine.cpp +@@ -310,16 +310,16 @@ + + void pp::handle_define (Stream& input) + { +- pp_macro* macro = new pp_macro; +- macro->file = currentFileName(); +- macro->sourceLine = input.originalInputPosition().line; ++ pp_macro macro; ++ macro.file = currentFileName(); ++ macro.sourceLine = input.originalInputPosition().line; + + skip_blanks (input, devnull()); +- macro->name = KDevelop::IndexedString::fromIndex(skip_identifier(input, true)); //@todo make macros utf8 too ++ macro.name = KDevelop::IndexedString::fromIndex(skip_identifier(input, true)); //@todo make macros utf8 too + + if (!input.atEnd() && input == '(') + { +- macro->function_like = true; ++ macro.function_like = true; + + skip_blanks (++input, devnull()); // skip '(' + uint formal = skip_identifier(input); +@@ -327,15 +327,15 @@ + skip_blanks(input, devnull()); + + if (input == '.') { +- macro->variadics = true; ++ macro.variadics = true; + + do { + ++input; + + } while (input == '.'); + } +- if (formal && !macro->variadics) +- macro->formalsList().append( KDevelop::IndexedString::fromIndex(formal) ); ++ if (formal && !macro.variadics) ++ macro.formalsList().append( KDevelop::IndexedString::fromIndex(formal) ); + + + while (!input.atEnd() && input == ',') +@@ -347,7 +347,7 @@ + skip_blanks (input, devnull()); + + if (input == '.') { +- macro->variadics = true; ++ macro.variadics = true; + + do { + ++input; +@@ -355,8 +355,8 @@ + } while (input == '.'); + } + +- if (formal && !macro->variadics) +- macro->formalsList().append( KDevelop::IndexedString::fromIndex(formal) ); ++ if (formal && !macro.variadics) ++ macro.formalsList().append( KDevelop::IndexedString::fromIndex(formal) ); + } + + RETURN_ON_FAIL(input == ')'); +@@ -381,7 +381,7 @@ + if (!input.atEnd() && input == '\n') + { + skip_blanks(++input, devnull()); +- macro->definitionList().append(KDevelop::IndexedString::fromIndex(indexFromCharacter(' '))); ++ macro.definitionList().append(KDevelop::IndexedString::fromIndex(indexFromCharacter(' '))); + continue; + + } else { +@@ -394,24 +394,24 @@ + do { + if (input == '\\' && input.peekNextCharacter() == '"') { + // skip escaped close quote +- macro->definitionList().append(KDevelop::IndexedString::fromIndex(input.current())); ++ macro.definitionList().append(KDevelop::IndexedString::fromIndex(input.current())); + ++input; + if(input.atEnd()) + break; + } +- macro->definitionList().append(KDevelop::IndexedString::fromIndex(input.current())); ++ macro.definitionList().append(KDevelop::IndexedString::fromIndex(input.current())); + ++input; + } while (!input.atEnd() && input != '"' && input != '\n'); + + if(!input.atEnd()) + { +- macro->definitionList().append(KDevelop::IndexedString::fromIndex(input.current())); ++ macro.definitionList().append(KDevelop::IndexedString::fromIndex(input.current())); + ++input; + } + continue; + } + +- macro->definitionList().append(KDevelop::IndexedString::fromIndex(input.current())); ++ macro.definitionList().append(KDevelop::IndexedString::fromIndex(input.current())); + ++input; + } + +@@ -505,8 +505,8 @@ + } + + { +- pp_macro* m = m_environment->retrieveMacro(token_text, true); +- result.set_long( (m && !m->isUndef()) ? 1 : 0); ++ const pp_macro& m = m_environment->retrieveMacro(token_text, true); ++ result.set_long(m.isUndef() ? 0 : 1); + } + + token = next_token(input); // skip '(' +@@ -1009,9 +1009,9 @@ + + if (test_if_level()) + { +- pp_macro* macro = m_environment->retrieveMacro(macro_name, true); ++ const pp_macro& macro = m_environment->retrieveMacro(macro_name, true); + bool value = false; +- if( macro && macro->defined ) ++ if( macro.isValid() && macro.defined ) + value = true; + + if (check_undefined) +@@ -1030,12 +1030,12 @@ + KDevelop::IndexedString macro_name = KDevelop::IndexedString::fromIndex(skip_identifier(input)); + RETURN_ON_FAIL(!macro_name.isEmpty()); + +- pp_macro* macro = new pp_macro; +- macro->file = currentFileName(); +- macro->name = macro_name; +- macro->sourceLine = input.originalInputPosition().line; +- +- macro->defined = false; ++ pp_macro macro; ++ macro.file = currentFileName(); ++ macro.name = macro_name; ++ macro.sourceLine = input.originalInputPosition().line; ++ ++ macro.defined = false; + + m_environment->setMacro(macro); + } + +--- a/languages/cpp/parser/rpp/pp-environment.cpp ++++ b/languages/cpp/parser/rpp/pp-environment.cpp +@@ -40,8 +40,6 @@ + Environment::~Environment() + { + delete m_locationTable; +- foreach(pp_macro* macro, m_ownedMacros) +- delete macro; + } + + LocationTable* Environment::locationTable() const +@@ -58,8 +56,6 @@ + + void Environment::swapMacros( Environment* parentEnvironment ) { + qSwap(m_environment, parentEnvironment->m_environment); +- +- qSwap(m_ownedMacros, parentEnvironment->m_ownedMacros); + } + + void Environment::clearMacro(const KDevelop::IndexedString& name) +@@ -67,34 +63,31 @@ + m_environment.remove(name); + } + +-void Environment::setMacro(pp_macro* macro) ++void Environment::setMacro(const pp_macro& macro) + { +- if(!macro->isRepositoryMacro()) +- m_ownedMacros.append(macro); +- +- m_environment.insert(macro->name, macro); ++ m_environment.insert(macro.name, macro); + } + +-void Environment::insertMacro(pp_macro* macro) ++void Environment::insertMacro(const pp_macro& macro) + { +- m_environment.insert(macro->name, macro); ++ m_environment.insert(macro.name, macro); + } + + const Environment::EnvironmentMap& Environment::environment() const { + return m_environment; + } + +-pp_macro* Environment::retrieveStoredMacro(const KDevelop::IndexedString& name) const ++pp_macro Environment::retrieveStoredMacro(const KDevelop::IndexedString& name) const + { +- return m_environment.value(name, nullptr); ++ return m_environment.value(name); + } + +-pp_macro* Environment::retrieveMacro(const KDevelop::IndexedString& name, bool /*isImportant*/) const ++pp_macro Environment::retrieveMacro(const KDevelop::IndexedString& name, bool /*isImportant*/) const + { + return retrieveStoredMacro(name); + } + +-QList Environment::allMacros() const ++QList Environment::allMacros() const + { + return m_environment.values(); + } + +--- a/languages/cpp/parser/rpp/pp-environment.h ++++ b/languages/cpp/parser/rpp/pp-environment.h +@@ -27,7 +27,7 @@ + + #include + #include +-// #include "pp-macro.h" ++#include "pp-macro.h" + + namespace KDevelop { + class IndexedString; +@@ -35,13 +35,12 @@ + + namespace rpp { + +-class pp_macro; + class LocationTable; + + class KDEVCPPRPP_EXPORT Environment + { + public: +- typedef QHash EnvironmentMap; ++ typedef QHash EnvironmentMap; + + Environment(); + virtual ~Environment(); +@@ -50,19 +49,19 @@ + + //The macro will be owned by the environment object + //Note: Undef-macros are allowed too +- virtual void setMacro(pp_macro* macro); ++ virtual void setMacro(const pp_macro& macro); + + //Inserts a macro that will not be explicitly owned by the Environment, + //without notifying subclasses etc. +- void insertMacro(pp_macro* macro); ++ void insertMacro(const pp_macro& macro); + +- virtual pp_macro* retrieveMacro(const KDevelop::IndexedString& name, bool isImportant) const; ++ virtual pp_macro retrieveMacro(const KDevelop::IndexedString& name, bool isImportant) const; + + //Returns macros that are really stored locally(retrieveMacro may be overridden to perform more complex actions) +- pp_macro* retrieveStoredMacro(const KDevelop::IndexedString& name) const; ++ pp_macro retrieveStoredMacro(const KDevelop::IndexedString& name) const; + + //Returns all currently visible macros +- QList allMacros() const; ++ QList allMacros() const; + + //Swap the macros with the given environment, includign ownership + virtual void swapMacros( Environment* parentEnvironment ); +@@ -76,7 +75,6 @@ + private: + EnvironmentMap m_environment; + +- QVector m_ownedMacros; + LocationTable* m_locationTable; + }; + + +--- a/languages/cpp/parser/rpp/pp-macro-expander.cpp ++++ b/languages/cpp/parser/rpp/pp-macro-expander.cpp +@@ -79,7 +79,7 @@ + + using namespace rpp; + +-pp_frame::pp_frame(pp_macro* __expandingMacro, const QList& __actuals) ++pp_frame::pp_frame(const pp_macro& __expandingMacro, const QList& __actuals) + : depth(0) + , expandingMacro(__expandingMacro) + , actuals(__actuals) +@@ -91,10 +91,8 @@ + if (!m_frame) + return pp_actual(); + +- Q_ASSERT(m_frame->expandingMacro != 0); +- +- const IndexedString* formals = m_frame->expandingMacro->formals(); +- uint formalsSize = m_frame->expandingMacro->formalsSize(); ++ const IndexedString* formals = m_frame->expandingMacro.formals(); ++ uint formalsSize = m_frame->expandingMacro.formalsSize(); + + if(name.isEmpty()) { + KDevelop::ProblemPointer problem(new KDevelop::Problem); +@@ -122,7 +120,7 @@ + return pp_actual(); + } + +-#define RETURN_IF_INPUT_BROKEN if(input.atEnd()) { kDebug() << "too early end while expanding" << macro->name.str(); return; } ++#define RETURN_IF_INPUT_BROKEN if(input.atEnd()) { kDebug() << "too early end while expanding" << macro.name.str(); return; } + + + pp_macro_expander::pp_macro_expander(pp* engine, pp_frame* frame, bool inHeaderSection) +@@ -168,18 +166,20 @@ + //A helper class that temporary hides a macro in the environment + class MacroHider { + public: +- MacroHider(pp_macro* macro, Environment* environment) : m_macro(macro), m_environment(environment) { +- +- m_hideMacro.name = macro->name; ++ MacroHider(const pp_macro& macro, Environment* environment) ++ : m_macro(macro), m_environment(environment) ++ { ++ m_hideMacro.name = macro.name; + m_hideMacro.hidden = true; +- environment->insertMacro(&m_hideMacro); +- } +- ~MacroHider() { ++ environment->insertMacro(m_hideMacro); ++ } ++ ~MacroHider() ++ { + m_environment->insertMacro(m_macro); + } + private: + pp_macro m_hideMacro; +- pp_macro* m_macro; ++ const pp_macro& m_macro; + Environment* m_environment; + }; + +@@ -361,8 +361,8 @@ + // TODO handle inbuilt "defined" etc functions + +- pp_macro* macro = m_engine->environment()->retrieveMacro(name, false); +- +- if (!macro || !macro->defined || macro->hidden || macro->function_like || m_engine->hideNextMacro()) ++ const pp_macro& macro = m_engine->environment()->retrieveMacro(name, false); ++ ++ if (!macro.isValid() || !macro.defined || macro.hidden || macro.function_like || m_engine->hideNextMacro()) + { + static const IndexedString definedIndex = IndexedString("defined"); + m_engine->setHideNextMacro(name == definedIndex); +@@ -402,13 +402,13 @@ + + EnableMacroExpansion enable(output, input.inputPosition()); //Configure the output-stream so it marks all stored input-positions as transformed through a macro + +- if (macro->definitionSize()) { ++ if (macro.definitionSize()) { + //Hide the expanded macro to prevent endless expansion + MacroHider hideMacro(macro, m_engine->environment()); + + pp_macro_expander expand_macro(m_engine); + ///@todo UGLY conversion +- Stream ms((uint*)macro->definition(), macro->definitionSize(), Anchor(input.inputPosition(), true)); ++ Stream ms((uint*)macro.definition(), macro.definitionSize(), Anchor(input.inputPosition(), true)); + ms.setOriginalInputPosition(input.originalInputPosition()); + PreprocessedContents expanded; + { +@@ -437,8 +437,8 @@ + previous = IndexedString::fromIndex(output.peekLastOutput(stepsBack)); + ++stepsBack; + } +- pp_macro* macro = m_engine->environment()->retrieveMacro(previous, false); +- if(!macro || !macro->function_like || !macro->defined || macro->hidden) { ++ const pp_macro& macro = m_engine->environment()->retrieveMacro(previous, false); ++ if(!macro.isValid() || !macro.function_like || !macro.defined || macro.hidden) { + output << input; + ++input; + continue; +@@ -462,12 +462,12 @@ + ++input; + } + +- kDebug() << "too early end while expanding" << macro->name.str(); ++ kDebug() << "too early end while expanding" << macro.name.str(); + return; + } + + pp_macro_expander expand_actual(m_engine, m_frame); +- skip_actual_parameter(input, *macro, actuals, expand_actual); ++ skip_actual_parameter(input, macro, actuals, expand_actual); + + while (!input.atEnd() && input == ',') + { +@@ -484,11 +484,11 @@ + ++input; + } + +- kDebug() << "too early end while expanding" << macro->name.str(); ++ kDebug() << "too early end while expanding" << macro.name.str(); + return; + } + +- skip_actual_parameter(input, *macro, actuals, expand_actual); ++ skip_actual_parameter(input, macro, actuals, expand_actual); + } + + if( input != ')' ) { +@@ -526,7 +526,7 @@ + + if(frame.depth >= maxMacroExpansionDepth) + { +- kDebug() << "reached maximum macro-expansion depth while expanding" << macro->name.str(); ++ kDebug() << "reached maximum macro-expansion depth while expanding" << macro.name.str(); + RETURN_IF_INPUT_BROKEN + + output << input; +@@ -538,7 +538,7 @@ + MacroHider hideMacro(macro, m_engine->environment()); + + ///@todo UGLY conversion +- Stream ms((uint*)macro->definition(), macro->definitionSize(), Anchor(input.inputPosition(), true)); ++ Stream ms((uint*)macro.definition(), macro.definitionSize(), Anchor(input.inputPosition(), true)); + + PreprocessedContents expansion_text; + rpp::LocationTable table; +@@ -559,14 +559,14 @@ + } + } + +-void pp_macro_expander::skip_actual_parameter(Stream& input, rpp::pp_macro& macro, QList< pp_actual >& actuals, pp_macro_expander& expander) ++void pp_macro_expander::skip_actual_parameter(Stream& input, const pp_macro& macro, QList< pp_actual >& actuals, pp_macro_expander& expander) + { + PreprocessedContents actualText; + skip_whitespaces(input, devnull()); + Anchor actualStart = input.inputPosition(); + { + Stream as(&actualText); +- skip_argument_variadics(actuals, ¯o, input, as); ++ skip_argument_variadics(actuals, macro, input, as); + } + trim(actualText); + +@@ -589,7 +589,7 @@ + actuals.append(newActual); + } + +-void pp_macro_expander::skip_argument_variadics (const QList& __actuals, pp_macro *__macro, Stream& input, Stream& output) ++void pp_macro_expander::skip_argument_variadics (const QList& __actuals, const pp_macro& __macro, Stream& input, Stream& output) + { + int first; + +@@ -597,9 +597,9 @@ + first = input.offset(); + skip_argument(input, output); + +- } while ( __macro->variadics ++ } while ( __macro.variadics + && first != input.offset() + && !input.atEnd() + && input == '.' +- && (__actuals.size() + 1) == (int)__macro->formalsSize()); ++ && (__actuals.size() + 1) == (int)__macro.formalsSize()); + } + + +--- a/languages/cpp/parser/rpp/pp-macro-expander.h ++++ b/languages/cpp/parser/rpp/pp-macro-expander.h +@@ -64,10 +64,10 @@ + class pp_frame + { + public: +- pp_frame (pp_macro* __expandingMacro, const QList& __actuals); ++ pp_frame (const pp_macro& __expandingMacro, const QList& __actuals); + + int depth; +- pp_macro* expandingMacro; ++ pp_macro expandingMacro; + QList actuals; + }; + +@@ -83,7 +83,7 @@ + /// If substitute == true, perform only macro parameter substitution and # token processing + void operator()(Stream& input, Stream& output, bool substitute = false, LocationTable* table = 0); + +- void skip_argument_variadics (const QList& __actuals, pp_macro *__macro, ++ void skip_argument_variadics (const QList& __actuals, const pp_macro& __macro, + Stream& input, Stream& output); + + bool in_header_section() const { +@@ -101,7 +101,7 @@ + private: + /// Read actual parameter of @ref macro value from @ref input and append it to @ref actuals + /// @ref expander is a reusable macro expander +- void skip_actual_parameter(rpp::Stream& input, rpp::pp_macro& macro, QList< rpp::pp_actual >& actuals, rpp::pp_macro_expander& expander); ++ void skip_actual_parameter(rpp::Stream& input, const rpp::pp_macro& macro, QList< rpp::pp_actual >& actuals, rpp::pp_macro_expander& expander); + + pp* m_engine; + pp_frame* m_frame; + +--- a/languages/cpp/parser/rpp/pp-macro.cpp ++++ b/languages/cpp/parser/rpp/pp-macro.cpp +@@ -53,6 +53,16 @@ + listsEqual(rhs); + } + ++bool pp_macro::operator!=(const pp_macro& rhs) const ++{ ++ return !(*this == rhs); ++} ++ ++bool pp_macro::isValid() const ++{ ++ return *this != pp_macro(); ++} ++ + void pp_macro::invalidateHash() { + m_valueHashValid = false; + } +@@ -88,18 +98,28 @@ + copyListsFrom(rhs); + } + +-pp_macro::pp_macro(const char* nm) : name(KDevelop::IndexedString(nm, strlen(nm))) +- , sourceLine(-1) +- , defined(true) +- , hidden(false) +- , function_like(false) +- , variadics(false) +- , fixed(false) +- , defineOnOverride(false) +- , m_valueHashValid(false) +- , m_valueHash(0) ++pp_macro& pp_macro::operator=(const pp_macro& rhs) + { +- initializeAppendedLists(); ++ name = rhs.name; ++ file = rhs.file; ++ sourceLine = rhs.sourceLine; ++ defined = rhs.defined; ++ hidden = rhs.hidden; ++ function_like = rhs.function_like; ++ variadics = rhs.variadics; ++ fixed = rhs.fixed; ++ defineOnOverride = rhs.defineOnOverride; ++ m_valueHashValid = true; ++ m_valueHash = rhs.valueHash(); ++ ++ copyListsFrom(rhs); ++ ++ return *this; ++} ++ ++pp_macro::pp_macro(const char* nm) ++ : pp_macro(IndexedString(nm)) ++{ + } + + QString pp_macro::toString() const { + +--- a/languages/cpp/parser/rpp/pp-macro.h ++++ b/languages/cpp/parser/rpp/pp-macro.h +@@ -44,10 +44,12 @@ + + ///@todo enable structure packing + pp_macro(const KDevelop::IndexedString& name = KDevelop::IndexedString()); +- pp_macro(const char* name); ++ explicit pp_macro(const char* name); + pp_macro(const pp_macro& rhs, bool dynamic = true); + ~pp_macro(); +- ++ ++ pp_macro& operator=(const pp_macro& rhs); ++ + uint classSize() const { + return sizeof(pp_macro); + } +@@ -78,6 +80,8 @@ + mutable HashType m_valueHash; //Hash that represents the values of all macros + + bool operator==(const pp_macro& rhs) const; ++ bool operator!=(const pp_macro& rhs) const; ++ bool isValid() const; + + bool isUndef() const { + return !defined; +@@ -171,8 +175,7 @@ + return !appendedListsDynamic(); + } + +- private: +- pp_macro& operator=(const pp_macro& rhs); ++private: + void computeHash() const; + }; + + diff --git a/kdevelop.spec b/kdevelop.spec index 61f8cfe..77a8bcd 100644 --- a/kdevelop.spec +++ b/kdevelop.spec @@ -5,7 +5,7 @@ Name: kdevelop Summary: Integrated Development Environment for C++/C Epoch: 9 Version: 4.7.1 -Release: 9%{?dist} +Release: 10%{?dist} License: GPLv2 URL: http://www.kdevelop.org/ @@ -17,6 +17,11 @@ Patch0: kdevelop-4.5.0-no-rpath.patch # upstreamable patches # upstream patches +# Backport upstream crash fixes (abuse of temporaries) (#1266259, kde#347178): +# 1. Do not use function returning reference to temporary. (Sébastien Lambert) +Patch100: kdevelop-4.7.1-fix-temporary-abuse-1.patch +# 2. Remove ConvenientIterator::ref usage from oldcpp codebase. (Milian Wolff) +Patch101: kdevelop-4.7.1-fix-temporary-abuse-2.patch BuildRequires: boost-devel BuildRequires: desktop-file-utils @@ -89,6 +94,8 @@ Requires: kdevplatform%{?_isa} >= %{kdevplatform_ver} %prep %setup -q -n kdevelop-%{version} %patch0 -p1 -b .no-rpath +%patch100 -p1 -b .temp-abuse-1 +%patch101 -p1 -b .temp-abuse-2 %build mkdir -p %{_target_platform} @@ -156,10 +163,13 @@ update-mime-database %{?fedora:-n} %{_kde4_datadir}/mime &> /dev/null || : %changelog +* Thu Sep 24 2015 Kevin Kofler - 9:4.7.1-10 +- Backport upstream crash fixes (abuse of temporaries) (#1266259, kde#347178) + * Thu Aug 27 2015 Jonathan Wakely - 9:4.7.1-9 - Rebuilt for Boost 1.59 -* Wed Aug 05 2015 Jonathan Wakely 4.7.1-8 +* Wed Aug 05 2015 Jonathan Wakely - 9:4.7.1-8 - Rebuilt for Boost 1.58 * Thu Jul 30 2015 Kevin Kofler - 9:4.7.1-7