From f3a2795c3bfc892695a46621e6bc97a2742d8766 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Sun, 15 Feb 2015 23:43:26 +0200 Subject: [PATCH] C++: Use correct features for document parsing Task-number: QTCREATORBUG-8007 Change-Id: Ic96aaa433442812a99bac9d16bb9124d66762e8c Reviewed-by: Nikolai Kosjar --- src/libs/3rdparty/cplusplus/Token.h | 6 +++++ src/libs/cplusplus/CppDocument.cpp | 24 ++++++++++++------- src/libs/cplusplus/CppDocument.h | 3 +++ src/plugins/clangcodemodel/pchmanager.cpp | 2 ++ .../cpptools/builtineditordocumentparser.cpp | 3 +++ .../cpptools/builtinindexingsupport.cpp | 8 ++++++- src/plugins/cpptools/cppmodelmanager.cpp | 1 + src/plugins/cpptools/cppprojects.cpp | 24 +++++++++++++++++++ src/plugins/cpptools/cppprojects.h | 4 ++++ src/plugins/cpptools/cppsourceprocessor.cpp | 7 ++++++ src/plugins/cpptools/cppsourceprocessor.h | 2 ++ .../qmakeprojectmanager/qmakeproject.cpp | 2 ++ 12 files changed, 77 insertions(+), 9 deletions(-) diff --git a/src/libs/3rdparty/cplusplus/Token.h b/src/libs/3rdparty/cplusplus/Token.h index 25befabbab6..28836c77726 100644 --- a/src/libs/3rdparty/cplusplus/Token.h +++ b/src/libs/3rdparty/cplusplus/Token.h @@ -396,6 +396,12 @@ public: struct LanguageFeatures { LanguageFeatures() : flags(0) {} + static LanguageFeatures defaultFeatures() + { + LanguageFeatures features; + features.flags = 0xffffffff; // Enable all flags + return features; + } union { unsigned int flags; diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index 57b612e90a3..b19a510bf72 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -283,15 +283,8 @@ Document::Document(const QString &fileName) const QByteArray localFileName = fileName.toUtf8(); const StringLiteral *fileId = _control->stringLiteral(localFileName.constData(), localFileName.size()); - LanguageFeatures features; - features.qtEnabled = true; - features.qtMocRunEnabled = true; - features.qtKeywordsEnabled = true; - features.cxx11Enabled = true; - features.objCEnabled = true; - features.c99Enabled = true; _translationUnit = new TranslationUnit(_control, fileId); - _translationUnit->setLanguageFeatures(features); + _translationUnit->setLanguageFeatures(LanguageFeatures::defaultFeatures()); (void) _control->switchTranslationUnit(_translationUnit); } @@ -596,6 +589,19 @@ void Document::setUtf8Source(const QByteArray &source) _translationUnit->setSource(_source.constBegin(), _source.size()); } +LanguageFeatures Document::languageFeatures() const +{ + if (TranslationUnit *tu = translationUnit()) + return tu->languageFeatures(); + return LanguageFeatures::defaultFeatures(); +} + +void Document::setLanguageFeatures(LanguageFeatures features) +{ + if (TranslationUnit *tu = translationUnit()) + tu->setLanguageFeatures(features); +} + void Document::startSkippingBlocks(unsigned utf16charsOffset) { _skippedBlocks.append(Block(0, 0, utf16charsOffset, 0)); @@ -767,6 +773,7 @@ Document::Ptr Snapshot::preprocessedDocument(const QByteArray &source, newDoc->_lastModified = thisDocument->_lastModified; newDoc->_resolvedIncludes = thisDocument->_resolvedIncludes; newDoc->_unresolvedIncludes = thisDocument->_unresolvedIncludes; + newDoc->setLanguageFeatures(thisDocument->languageFeatures()); } FastPreprocessor pp(*this); @@ -788,6 +795,7 @@ Document::Ptr Snapshot::documentFromSource(const QByteArray &preprocessedCode, newDoc->_unresolvedIncludes = thisDocument->_unresolvedIncludes; newDoc->_definedMacros = thisDocument->_definedMacros; newDoc->_macroUses = thisDocument->_macroUses; + newDoc->setLanguageFeatures(thisDocument->languageFeatures()); } newDoc->setUtf8Source(preprocessedCode); diff --git a/src/libs/cplusplus/CppDocument.h b/src/libs/cplusplus/CppDocument.h index ec2514894ec..9d7b473e42f 100644 --- a/src/libs/cplusplus/CppDocument.h +++ b/src/libs/cplusplus/CppDocument.h @@ -115,6 +115,9 @@ public: void setFingerprint(const QByteArray &fingerprint) { m_fingerprint = fingerprint; } + LanguageFeatures languageFeatures() const; + void setLanguageFeatures(LanguageFeatures features); + void startSkippingBlocks(unsigned utf16charsOffset); void stopSkippingBlocks(unsigned utf16charsOffset); diff --git a/src/plugins/clangcodemodel/pchmanager.cpp b/src/plugins/clangcodemodel/pchmanager.cpp index 0ca6ad40b4d..11cf0abcba3 100644 --- a/src/plugins/clangcodemodel/pchmanager.cpp +++ b/src/plugins/clangcodemodel/pchmanager.cpp @@ -304,6 +304,7 @@ void PchManager::doPchInfoUpdateFuzzy(QFutureInterface &future, projectPart->languageVersion = languageVersions[pch]; projectPart->languageExtensions = languageExtensionsMap[pch]; projectPart->headerPaths = headers[pch].toList(); + projectPart->updateLanguageFeatures(); QList defines = definesPerPCH[pch].toList(); if (!defines.isEmpty()) { @@ -386,6 +387,7 @@ void PchManager::doPchInfoUpdateCustom(QFutureInterface &future, objc |= hasObjCFiles(projectPart); cplusplus |= hasCppFiles(projectPart); } + united->updateLanguageFeatures(); united->headerPaths = headers; QStringList opts = Utils::createClangOptions( united, getPrefixFileKind(objc, cplusplus)); diff --git a/src/plugins/cpptools/builtineditordocumentparser.cpp b/src/plugins/cpptools/builtineditordocumentparser.cpp index 4aea3d3cc05..24ae027bfc4 100644 --- a/src/plugins/cpptools/builtineditordocumentparser.cpp +++ b/src/plugins/cpptools/builtineditordocumentparser.cpp @@ -60,6 +60,7 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy) ProjectPart::HeaderPaths headerPaths; QStringList precompiledHeaders; QString projectConfigFile; + LanguageFeatures features = LanguageFeatures::defaultFeatures(); updateProjectPart(); @@ -75,6 +76,7 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy) projectConfigFile = part->projectConfigFile; if (usePrecompiledHeaders()) precompiledHeaders = part->precompiledHeaders; + features = part->languageFeatures; } if (configFile != m_configFile) { @@ -169,6 +171,7 @@ void BuiltinEditorDocumentParser::update(WorkingCopy workingCopy) sourceProcessor.setGlobalSnapshot(globalSnapshot); sourceProcessor.setWorkingCopy(workingCopy); sourceProcessor.setHeaderPaths(m_headerPaths); + sourceProcessor.setLanguageFeatures(features); sourceProcessor.run(configurationFileName); if (!m_projectConfigFile.isEmpty()) sourceProcessor.run(m_projectConfigFile); diff --git a/src/plugins/cpptools/builtinindexingsupport.cpp b/src/plugins/cpptools/builtinindexingsupport.cpp index a35a5413a96..9d75998816a 100644 --- a/src/plugins/cpptools/builtinindexingsupport.cpp +++ b/src/plugins/cpptools/builtinindexingsupport.cpp @@ -208,6 +208,8 @@ void index(QFutureInterface &future, const ParseParams params) CppModelManager *cmm = CppModelManager::instance(); const ProjectPart::HeaderPaths fallbackHeaderPaths = cmm->headerPaths(); + const CPlusPlus::LanguageFeatures defaultFeatures = + CPlusPlus::LanguageFeatures::defaultFeatures(); for (int i = 0; i < files.size(); ++i) { if (future.isPaused()) future.waitForResume(); @@ -216,6 +218,11 @@ void index(QFutureInterface &future, const ParseParams params) break; const QString fileName = files.at(i); + const QList parts = cmm->projectPart(fileName); + const CPlusPlus::LanguageFeatures languageFeatures = parts.isEmpty() + ? defaultFeatures + : parts.first()->languageFeatures; + sourceProcessor->setLanguageFeatures(languageFeatures); const bool isSourceFile = i < sourceCount; if (isSourceFile) { @@ -226,7 +233,6 @@ void index(QFutureInterface &future, const ParseParams params) processingHeaders = true; } - QList parts = cmm->projectPart(fileName); ProjectPart::HeaderPaths headerPaths = parts.isEmpty() ? fallbackHeaderPaths : parts.first()->headerPaths; diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index cf9858498d5..c7a80656965 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -840,6 +840,7 @@ ProjectPart::Ptr CppModelManager::fallbackProjectPart() const part->languageVersion = ProjectPart::CXX14; part->languageExtensions = ProjectPart::AllExtensions; part->qtVersion = ProjectPart::Qt5; + part->updateLanguageFeatures(); return part; } diff --git a/src/plugins/cpptools/cppprojects.cpp b/src/plugins/cpptools/cppprojects.cpp index 4bea18d691f..03d5bdcbe80 100644 --- a/src/plugins/cpptools/cppprojects.cpp +++ b/src/plugins/cpptools/cppprojects.cpp @@ -108,6 +108,29 @@ void ProjectPart::evaluateToolchain(const ToolChain *tc, } toolchainDefines = tc->predefinedMacros(commandLineFlags); + updateLanguageFeatures(); +} + +void ProjectPart::updateLanguageFeatures() +{ + const bool hasQt = qtVersion != NoQt; + languageFeatures.cxx11Enabled = languageVersion >= CXX11; + languageFeatures.qtEnabled = hasQt; + languageFeatures.qtMocRunEnabled = hasQt; + if (!hasQt) { + languageFeatures.qtKeywordsEnabled = false; + } else { + const QByteArray noKeywordsMacro = "#define QT_NO_KEYWORDS"; + const int noKeywordsIndex = projectDefines.indexOf(noKeywordsMacro); + if (noKeywordsIndex == -1) { + languageFeatures.qtKeywordsEnabled = true; + } else { + const char nextChar = projectDefines.at(noKeywordsIndex + noKeywordsMacro.length()); + // Detect "#define QT_NO_KEYWORDS" and "#define QT_NO_KEYWORDS 1", but exclude + // "#define QT_NO_KEYWORDS_FOO" + languageFeatures.qtKeywordsEnabled = nextChar != '\n' && nextChar != ' '; + } + } } ProjectPart::Ptr ProjectPart::copy() const @@ -198,6 +221,7 @@ void ProjectInfo::finish() QSet incs; foreach (const ProjectPart::Ptr &part, m_projectParts) { + part->updateLanguageFeatures(); // Update header paths foreach (const HeaderPath &hp, part->headerPaths) { if (!incs.contains(hp)) { diff --git a/src/plugins/cpptools/cppprojects.h b/src/plugins/cpptools/cppprojects.h index ebdfd989ce1..f6c78c7852f 100644 --- a/src/plugins/cpptools/cppprojects.h +++ b/src/plugins/cpptools/cppprojects.h @@ -38,6 +38,8 @@ #include #include +#include + #include #include @@ -109,6 +111,7 @@ public: // methods const QStringList &commandLineFlags, const Utils::FileName &sysRoot); + void updateLanguageFeatures(); Ptr copy() const; QString id() const; @@ -127,6 +130,7 @@ public: // fields QStringList precompiledHeaders; LanguageVersion languageVersion; LanguageExtensions languageExtensions; + CPlusPlus::LanguageFeatures languageFeatures; QtVersion qtVersion; ProjectExplorer::ToolChain::WarningFlags warningFlags; bool selectedForBuilding; diff --git a/src/plugins/cpptools/cppsourceprocessor.cpp b/src/plugins/cpptools/cppsourceprocessor.cpp index 8a3e4549b6a..df792c3bcd8 100644 --- a/src/plugins/cpptools/cppsourceprocessor.cpp +++ b/src/plugins/cpptools/cppsourceprocessor.cpp @@ -116,6 +116,7 @@ CppSourceProcessor::CppSourceProcessor(const Snapshot &snapshot, DocumentCallbac : m_snapshot(snapshot), m_documentFinished(documentFinished), m_preprocess(this, &m_env), + m_languageFeatures(LanguageFeatures::defaultFeatures()), m_revision(0), m_defaultCodec(Core::EditorManager::defaultTextCodec()) { @@ -145,6 +146,11 @@ void CppSourceProcessor::setHeaderPaths(const ProjectPart::HeaderPaths &headerPa } } +void CppSourceProcessor::setLanguageFeatures(const LanguageFeatures languageFeatures) +{ + m_languageFeatures = languageFeatures; +} + // Add the given framework path, and expand private frameworks. // // Example: @@ -466,6 +472,7 @@ void CppSourceProcessor::sourceNeeded(unsigned line, const QString &fileName, In Document::Ptr document = Document::create(absoluteFileName); document->setRevision(m_revision); document->setEditorRevision(editorRevision); + document->setLanguageFeatures(m_languageFeatures); foreach (const QString &include, initialIncludes) { m_included.insert(include); Document::Include inc(include, include, 0, IncludeLocal); diff --git a/src/plugins/cpptools/cppsourceprocessor.h b/src/plugins/cpptools/cppsourceprocessor.h index a1b9ac6bc2c..3d8053bf26d 100644 --- a/src/plugins/cpptools/cppsourceprocessor.h +++ b/src/plugins/cpptools/cppsourceprocessor.h @@ -68,6 +68,7 @@ public: void setRevision(unsigned revision); void setWorkingCopy(const CppTools::WorkingCopy &workingCopy); void setHeaderPaths(const ProjectPart::HeaderPaths &headerPaths); + void setLanguageFeatures(CPlusPlus::LanguageFeatures languageFeatures); void setTodo(const QSet &files); void run(const QString &fileName, const QStringList &initialIncludes = QStringList()); @@ -117,6 +118,7 @@ private: CPlusPlus::Environment m_env; CPlusPlus::Preprocessor m_preprocess; ProjectPart::HeaderPaths m_headerPaths; + CPlusPlus::LanguageFeatures m_languageFeatures; CppTools::WorkingCopy m_workingCopy; QSet m_included; CPlusPlus::Document::Ptr m_currentDoc; diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp index 97f46e74d49..92d279d671d 100644 --- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp +++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp @@ -538,6 +538,8 @@ void QmakeProject::updateCppCodeModel() // part->precompiledHeaders templatePart->precompiledHeaders.append(pro->variableValue(PrecompiledHeaderVar)); + templatePart->updateLanguageFeatures(); + ProjectPart::Ptr cppPart = templatePart->copy(); { // C++ files: // part->files