summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/editors/creator-coding-edit-mode.qdoc6
-rw-r--r--doc/src/editors/creator-coding.qdoc23
-rw-r--r--doc/src/editors/creator-editors-writing-code.qdoc21
-rw-r--r--doc/src/editors/creator-mime-types.qdoc2
-rw-r--r--doc/src/editors/creator-modeling.qdoc4
-rw-r--r--doc/src/overview/creator-target-platforms.qdocinc2
-rw-r--r--doc/src/projects/creator-projects-building-running.qdoc2
-rw-r--r--doc/src/qtcreator.qdoc5
-rw-r--r--doc/src/qtquick/qtquick-components.qdoc2
-rw-r--r--doc/src/qtquick/qtquick-connection-editor.qdoc2
-rw-r--r--doc/src/qtquick/qtquick-designer.qdoc2
-rw-r--r--doc/src/qtquick/qtquick-pathview-editor.qdoc2
-rw-r--r--share/qtcreator/debugger/dumper.py3
-rw-r--r--share/qtcreator/templates/wizards/projects/qmake/qtcanvas3dapplication/wizard.json2
-rw-r--r--share/qtcreator/templates/wizards/projects/qmlproject/qtquickapplication/wizard.json2
-rw-r--r--share/qtcreator/templates/wizards/projects/qmlproject/qtquickcontrolsapplication/wizard.json2
-rw-r--r--share/qtcreator/translations/qtcreator_ru.ts66
-rw-r--r--src/libs/3rdparty/cplusplus/AST.h2
-rw-r--r--src/libs/3rdparty/cplusplus/Bind.cpp40
-rw-r--r--src/libs/3rdparty/cplusplus/CPlusPlusForwardDeclarations.h1
-rw-r--r--src/libs/3rdparty/cplusplus/Control.cpp16
-rw-r--r--src/libs/3rdparty/cplusplus/Control.h3
-rw-r--r--src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp6
-rw-r--r--src/libs/3rdparty/cplusplus/FullySpecifiedType.h4
-rw-r--r--src/libs/3rdparty/cplusplus/Matcher.cpp11
-rw-r--r--src/libs/3rdparty/cplusplus/Matcher.h1
-rw-r--r--src/libs/3rdparty/cplusplus/Names.h2
-rw-r--r--src/libs/3rdparty/cplusplus/Parser.cpp5
-rw-r--r--src/libs/3rdparty/cplusplus/Scope.cpp2
-rw-r--r--src/libs/3rdparty/cplusplus/Symbol.cpp3
-rw-r--r--src/libs/3rdparty/cplusplus/Symbol.h7
-rw-r--r--src/libs/3rdparty/cplusplus/SymbolVisitor.h1
-rw-r--r--src/libs/3rdparty/cplusplus/Symbols.cpp52
-rw-r--r--src/libs/3rdparty/cplusplus/Symbols.h33
-rw-r--r--src/libs/3rdparty/cplusplus/Templates.cpp20
-rw-r--r--src/libs/3rdparty/cplusplus/Templates.h2
-rw-r--r--src/libs/3rdparty/cplusplus/Type.cpp3
-rw-r--r--src/libs/3rdparty/cplusplus/Type.h3
-rw-r--r--src/libs/3rdparty/cplusplus/TypeVisitor.h1
-rw-r--r--src/libs/3rdparty/modeling/qmt/model_widgets_ui/classmembersedit.cpp3
-rw-r--r--src/libs/clangbackendipc/clangbackendipc_global.h23
-rw-r--r--src/libs/cplusplus/CppRewriter.cpp2
-rw-r--r--src/libs/cplusplus/CppRewriter.h4
-rw-r--r--src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp430
-rw-r--r--src/libs/cplusplus/DeprecatedGenTemplateInstance.h (renamed from src/libs/cplusplus/TypeResolver.h)45
-rw-r--r--src/libs/cplusplus/FindUsages.cpp2
-rw-r--r--src/libs/cplusplus/LookupContext.cpp1363
-rw-r--r--src/libs/cplusplus/LookupContext.h209
-rw-r--r--src/libs/cplusplus/LookupItem.cpp4
-rw-r--r--src/libs/cplusplus/LookupItem.h8
-rw-r--r--src/libs/cplusplus/ResolveExpression.cpp415
-rw-r--r--src/libs/cplusplus/ResolveExpression.h15
-rw-r--r--src/libs/cplusplus/TypeOfExpression.cpp8
-rw-r--r--src/libs/cplusplus/TypeOfExpression.h14
-rw-r--r--src/libs/cplusplus/TypeResolver.cpp262
-rw-r--r--src/libs/cplusplus/cplusplus-lib.pri4
-rw-r--r--src/libs/cplusplus/cplusplus.qbs2
-rw-r--r--src/libs/qmljs/qmljsfindexportedcpptypes.cpp2
-rw-r--r--src/libs/qmljs/qmljsinterpreter.cpp5
-rw-r--r--src/libs/sqlite/utf8string.cpp5
-rw-r--r--src/libs/sqlite/utf8string.h1
-rw-r--r--src/libs/ssh/sshkeygenerator.cpp3
-rw-r--r--src/libs/timeline/qml/CategoryLabel.qml1
-rw-r--r--src/libs/timeline/qml/TimelineLabels.qml2
-rw-r--r--src/libs/utils/pathchooser.cpp4
-rw-r--r--src/plugins/baremetal/gdbserverprovider.cpp2
-rw-r--r--src/plugins/clangcodemodel/clangutils.cpp20
-rw-r--r--src/plugins/cppeditor/cppeditor.cpp2
-rw-r--r--src/plugins/cppeditor/cppelementevaluator.cpp12
-rw-r--r--src/plugins/cppeditor/cppfollowsymbolundercursor.cpp3
-rw-r--r--src/plugins/cppeditor/cppfunctiondecldeflink.cpp4
-rw-r--r--src/plugins/cppeditor/cppinsertvirtualmethods.cpp16
-rw-r--r--src/plugins/cppeditor/cppquickfixes.cpp24
-rw-r--r--src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp4
-rw-r--r--src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp16
-rw-r--r--src/plugins/cpptools/cppchecksymbols.cpp30
-rw-r--r--src/plugins/cpptools/cppchecksymbols.h6
-rw-r--r--src/plugins/cpptools/cppcompletion_test.cpp520
-rw-r--r--src/plugins/cpptools/cppcompletionassist.cpp76
-rw-r--r--src/plugins/cpptools/cppcompletionassist.h8
-rw-r--r--src/plugins/cpptools/cpptoolsreuse.cpp2
-rw-r--r--src/plugins/cpptools/symbolfinder.cpp16
-rw-r--r--src/plugins/cpptools/symbolfinder.h3
-rw-r--r--src/plugins/genericprojectmanager/genericprojectnodes.cpp3
-rw-r--r--src/plugins/mercurial/mercurialclient.h2
-rw-r--r--src/plugins/projectexplorer/abi.cpp13
-rw-r--r--src/plugins/projectexplorer/customwizard/customwizard.cpp39
-rw-r--r--src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp3
-rw-r--r--src/plugins/qmldesigner/qmldesignerextension/pathtool/pathitem.cpp2
-rw-r--r--src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp14
-rw-r--r--src/shared/json/json.cpp1
m---------src/shared/qbs0
-rw-r--r--src/tools/clangbackend/clangbackendmain.cpp3
-rw-r--r--src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri15
-rw-r--r--src/tools/clangbackend/ipcsource/clangstring.cpp7
-rw-r--r--src/tools/clangbackend/ipcsource/clangstring.h2
-rw-r--r--src/tools/clangbackend/ipcsource/cursor.cpp351
-rw-r--r--src/tools/clangbackend/ipcsource/cursor.h129
-rw-r--r--src/tools/clangbackend/ipcsource/diagnostic.cpp2
-rw-r--r--src/tools/clangbackend/ipcsource/highlightinginformation.cpp304
-rw-r--r--src/tools/clangbackend/ipcsource/highlightinginformation.h86
-rw-r--r--src/tools/clangbackend/ipcsource/highlightinginformations.cpp79
-rw-r--r--src/tools/clangbackend/ipcsource/highlightinginformations.h74
-rw-r--r--src/tools/clangbackend/ipcsource/highlightinginformationsiterator.h99
-rw-r--r--src/tools/clangbackend/ipcsource/skippedsourceranges.cpp101
-rw-r--r--src/tools/clangbackend/ipcsource/skippedsourceranges.h63
-rw-r--r--src/tools/clangbackend/ipcsource/sourcelocation.cpp38
-rw-r--r--src/tools/clangbackend/ipcsource/sourcelocation.h21
-rw-r--r--src/tools/clangbackend/ipcsource/sourcerange.cpp30
-rw-r--r--src/tools/clangbackend/ipcsource/sourcerange.h11
-rw-r--r--src/tools/clangbackend/ipcsource/translationunit.cpp54
-rw-r--r--src/tools/clangbackend/ipcsource/translationunit.h18
-rw-r--r--src/tools/clangbackend/ipcsource/type.cpp157
-rw-r--r--src/tools/clangbackend/ipcsource/type.h87
-rw-r--r--src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.cpp50
-rw-r--r--tests/auto/cplusplus/ast/tst_ast.cpp24
-rw-r--r--tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp143
-rw-r--r--tests/auto/cplusplus/lookup/tst_lookup.cpp6
-rw-r--r--tests/auto/cplusplus/semantic/tst_semantic.cpp31
-rw-r--r--tests/system/suite_WELP/tst_WELP04/test.py2
-rw-r--r--tests/unit/unittest/clangstringtest.cpp9
-rw-r--r--tests/unit/unittest/cursortest.cpp819
-rw-r--r--tests/unit/unittest/data/cursor.cpp129
-rw-r--r--tests/unit/unittest/data/cursor.h42
-rw-r--r--tests/unit/unittest/data/highlightinginformations.cpp385
-rw-r--r--tests/unit/unittest/data/highlightinginformations.h0
-rw-r--r--tests/unit/unittest/data/skippedsourceranges.cpp19
-rw-r--r--tests/unit/unittest/highlightinginformationstest.cpp902
-rw-r--r--tests/unit/unittest/skippedsourcerangestest.cpp159
-rw-r--r--tests/unit/unittest/sourcelocationtest.cpp40
-rw-r--r--tests/unit/unittest/sourcerangetest.cpp47
-rw-r--r--tests/unit/unittest/unittest.pro5
132 files changed, 6279 insertions, 2307 deletions
diff --git a/doc/src/editors/creator-coding-edit-mode.qdoc b/doc/src/editors/creator-coding-edit-mode.qdoc
index f80aec704d..4693ae1ac4 100644
--- a/doc/src/editors/creator-coding-edit-mode.qdoc
+++ b/doc/src/editors/creator-coding-edit-mode.qdoc
@@ -64,7 +64,11 @@
To show the file encoding of the current file on the editor toolbar (4),
select \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} >
- \uicontrol Display > \uicontrol {Display file encoding}.
+ \uicontrol Display > \uicontrol {Display file encoding}. To change the
+ encoding, click it on the toolbar and select new encoding in the
+ \uicontrol {Text Encoding} dialog. To reload the file with the selected
+ encoding, select \uicontrol {Reload with Encoding}. To save the file with
+ the new encoding, select \uicontrol {Save with Encoding}.
\note Other convenient ways of navigating in \QC are provided by the
\l{Searching with the Locator}{locator}, \l{Keyboard Shortcuts}
diff --git a/doc/src/editors/creator-coding.qdoc b/doc/src/editors/creator-coding.qdoc
index 49e6480982..9fcb5e18a8 100644
--- a/doc/src/editors/creator-coding.qdoc
+++ b/doc/src/editors/creator-coding.qdoc
@@ -26,7 +26,7 @@
\contentspage {Qt Creator Manual}
\previouspage creator-usability.html
\page creator-coding.html
- \nextpage creator-modeling.html
+ \nextpage creator-editor-functions.html
\title Coding
@@ -34,12 +34,6 @@
\list
- \li \l{Modeling}
-
- You can use the experimental model editor to create Universal
- Modeling Language (UML) style models with structured diagrams and
- store them in XML format.
-
\li \l{Writing Code}
Writing, editing, and navigating in source code are core tasks in
@@ -85,18 +79,11 @@
to use for opening the file. If your files do not match the
predefined MIME types, you can edit the MIME types.
- \li \l{Comparing Files}
-
- You can use a diff editor to compare two versions of a file and
- view the differences side-by-side in the \uicontrol Edit mode.
-
- \li \l{Parsing C++ Files}
+ \li \l{Modeling}
- An experimental Clang code model plugin enables you to replace the
- built-in \QC code model with the Clang code model. Clang is a C
- language family front end for LLVM. Clang provides you with more
- accurate information than the built-in code model but can be slower
- to use for large projects.
+ You can use the experimental model editor to create Universal
+ Modeling Language (UML) style models with structured diagrams and
+ store them in XML format.
\endlist
diff --git a/doc/src/editors/creator-editors-writing-code.qdoc b/doc/src/editors/creator-editors-writing-code.qdoc
index d30e89716a..78d1ece352 100644
--- a/doc/src/editors/creator-editors-writing-code.qdoc
+++ b/doc/src/editors/creator-editors-writing-code.qdoc
@@ -24,7 +24,7 @@
/*!
\contentspage {Qt Creator Manual}
- \previouspage creator-modeling.html
+ \previouspage creator-coding.html
\page creator-editor-functions.html
\nextpage creator-coding-navigating.html
@@ -93,4 +93,23 @@
\endlist
+ \section1 Related Topics
+
+ \list
+
+ \li \l{Comparing Files}
+
+ You can use a diff editor to compare two versions of a file and
+ view the differences side-by-side in the \uicontrol Edit mode.
+
+ \li \l{Parsing C++ Files}
+
+ An experimental Clang code model plugin enables you to replace the
+ built-in \QC code model with the Clang code model. Clang is a C
+ language family front end for LLVM. Clang provides you with more
+ accurate information than the built-in code model but can be slower
+ to use for large projects.
+
+ \endlist
+
*/
diff --git a/doc/src/editors/creator-mime-types.qdoc b/doc/src/editors/creator-mime-types.qdoc
index e1f7544a4c..c2f8fff8ba 100644
--- a/doc/src/editors/creator-mime-types.qdoc
+++ b/doc/src/editors/creator-mime-types.qdoc
@@ -26,7 +26,7 @@
\contentspage {Qt Creator Manual}
\previouspage creator-editor-fakevim.html
\page creator-mime-types.html
- \nextpage creator-building-running.html
+ \nextpage creator-modeling.html
\title Editing MIME Types
diff --git a/doc/src/editors/creator-modeling.qdoc b/doc/src/editors/creator-modeling.qdoc
index 77f9681a24..36200a11d1 100644
--- a/doc/src/editors/creator-modeling.qdoc
+++ b/doc/src/editors/creator-modeling.qdoc
@@ -24,9 +24,9 @@
/*!
\contentspage {Qt Creator Manual}
- \previouspage creator-coding.html
+ \previouspage creator-mime-types.html
\page creator-modeling.html
- \nextpage creator-editor-functions.html
+ \nextpage creator-building-running.html
\title Modeling
diff --git a/doc/src/overview/creator-target-platforms.qdocinc b/doc/src/overview/creator-target-platforms.qdocinc
index 34cfdc0a2f..812564c93e 100644
--- a/doc/src/overview/creator-target-platforms.qdocinc
+++ b/doc/src/overview/creator-target-platforms.qdocinc
@@ -29,7 +29,7 @@
For more information about the supported device groups and reference devices,
see \l{http://doc.qt.io/QtForDeviceCreation/qtee-supported-platforms.html}
- {Supported Platforms} in the {http://doc.qt.io/QtForDeviceCreation/index.html}
+ {Supported Platforms} in the \l{http://doc.qt.io/QtForDeviceCreation/index.html}
{Qt for Device Creation} documentation.
\section2 Mobile Devices
diff --git a/doc/src/projects/creator-projects-building-running.qdoc b/doc/src/projects/creator-projects-building-running.qdoc
index 047c4764d1..0159b79da3 100644
--- a/doc/src/projects/creator-projects-building-running.qdoc
+++ b/doc/src/projects/creator-projects-building-running.qdoc
@@ -24,7 +24,7 @@
/*!
\contentspage {Qt Creator Manual}
- \previouspage creator-mime-types.html
+ \previouspage creator-modeling.html
\page creator-building-running.html
\nextpage creator-building-targets.html
diff --git a/doc/src/qtcreator.qdoc b/doc/src/qtcreator.qdoc
index 7f33c68dc5..27316fc87c 100644
--- a/doc/src/qtcreator.qdoc
+++ b/doc/src/qtcreator.qdoc
@@ -72,11 +72,11 @@
\endlist
\li \b {\l{Coding}}
\list
- \li \l{Modeling}
\li \l{Writing Code}
\li \l{Finding}
\li \l{Refactoring}
\li \l{Configuring the Editor}
+ \li \l{Modeling}
\endlist
\row
\li \inlineimage creator_buildingrunning.png
@@ -113,7 +113,6 @@
\li \l{Known Issues}
\li \l{Glossary}
\endlist
- \li
\row
\li {4,1} \note To report bugs and suggestions to the Qt Bug
Tracker, select \uicontrol {Help > Report Bug}.
@@ -194,7 +193,6 @@
\endlist
\li \l{Coding}
\list
- \li \l{Modeling}
\li \l{Writing Code}
\list
\li \l{Working in Edit Mode}
@@ -221,6 +219,7 @@
\li \l{Using FakeVim Mode}
\endlist
\li \l{Editing MIME Types}
+ \li \l{Modeling}
\endlist
\li \l{Building and Running}
\list
diff --git a/doc/src/qtquick/qtquick-components.qdoc b/doc/src/qtquick/qtquick-components.qdoc
index 6b946f3de7..86b0a1e36e 100644
--- a/doc/src/qtquick/qtquick-components.qdoc
+++ b/doc/src/qtquick/qtquick-components.qdoc
@@ -25,7 +25,7 @@
/*!
\contentspage {Qt Creator Manual}
- \previouspage creator-using-qt-quick-designer.html
+ \previouspage qmldesigner-connections.html
\page quick-components.html
\nextpage quick-buttons.html
diff --git a/doc/src/qtquick/qtquick-connection-editor.qdoc b/doc/src/qtquick/qtquick-connection-editor.qdoc
index f57dc9be21..a84022136e 100644
--- a/doc/src/qtquick/qtquick-connection-editor.qdoc
+++ b/doc/src/qtquick/qtquick-connection-editor.qdoc
@@ -31,7 +31,7 @@
\contentspage {Qt Creator Manual}
\previouspage qmldesigner-pathview-editor.html
\page qmldesigner-connections.html
- \nextpage quick-export-to-qml.html
+ \nextpage quick-components.html
\title Adding Connections
diff --git a/doc/src/qtquick/qtquick-designer.qdoc b/doc/src/qtquick/qtquick-designer.qdoc
index 6b8e5cb03e..b9da283ba3 100644
--- a/doc/src/qtquick/qtquick-designer.qdoc
+++ b/doc/src/qtquick/qtquick-designer.qdoc
@@ -26,7 +26,7 @@
\contentspage {Qt Creator Manual}
\previouspage creator-quick-ui-forms.html
\page creator-using-qt-quick-designer.html
- \nextpage quick-components.html
+ \nextpage qmldesigner-pathview-editor.html
\title Using Qt Quick Designer
diff --git a/doc/src/qtquick/qtquick-pathview-editor.qdoc b/doc/src/qtquick/qtquick-pathview-editor.qdoc
index 55424c92ef..8e20f3613d 100644
--- a/doc/src/qtquick/qtquick-pathview-editor.qdoc
+++ b/doc/src/qtquick/qtquick-pathview-editor.qdoc
@@ -29,7 +29,7 @@
/*!
\contentspage {Qt Creator Manual}
- \previouspage creator-qtquick-designer-extensions.html
+ \previouspage creator-using-qt-quick-designer.html
\page qmldesigner-pathview-editor.html
\nextpage qmldesigner-connections.html
diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py
index 07fac84980..8a5b51ddca 100644
--- a/share/qtcreator/debugger/dumper.py
+++ b/share/qtcreator/debugger/dumper.py
@@ -1034,9 +1034,8 @@ class DumperBase:
# We cannot use str(addr) as it yields rubbish for char pointers
# that might trigger Unicode encoding errors.
#return addr.cast(lookupType("void").pointer())
- # We do not use "hex(...)" as it (sometimes?) adds a "L" suffix.
try:
- return "0x%x" % toInteger(addr)
+ return "0x%x" % toInteger(hex(addr), 16)
except:
warn("CANNOT CONVERT TYPE: %s" % type(addr))
try:
diff --git a/share/qtcreator/templates/wizards/projects/qmake/qtcanvas3dapplication/wizard.json b/share/qtcreator/templates/wizards/projects/qmake/qtcanvas3dapplication/wizard.json
index c97ae596df..6b3a288347 100644
--- a/share/qtcreator/templates/wizards/projects/qmake/qtcanvas3dapplication/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qmake/qtcanvas3dapplication/wizard.json
@@ -8,7 +8,7 @@
"trDisplayCategory": "Application",
"icon": "3dapplication.png",
"featuresRequired": [ "QtSupport.Wizards.FeatureQtCanvas3d" ],
- "enabled": "${JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}",
+ "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}",
"options":
[
diff --git a/share/qtcreator/templates/wizards/projects/qmlproject/qtquickapplication/wizard.json b/share/qtcreator/templates/wizards/projects/qmlproject/qtquickapplication/wizard.json
index 68476a9357..29a51b8e41 100644
--- a/share/qtcreator/templates/wizards/projects/qmlproject/qtquickapplication/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qmlproject/qtquickapplication/wizard.json
@@ -5,7 +5,7 @@
"category": "H.Project",
"trDescription": "Creates a Qt Quick 2 UI project with a QML entry point. To use it, you need to have a QML runtime environment such as qmlscene set up. Consider using a Qt Quick Application project instead.",
"trDisplayName": "Qt Quick UI",
- "trDisplayCategory": "Application",
+ "trDisplayCategory": "Other Project",
"icon": "../../qmake/qtquickapplication/qml_wizard.png",
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
"featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick.Controls.1.3", "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQt" ],
diff --git a/share/qtcreator/templates/wizards/projects/qmlproject/qtquickcontrolsapplication/wizard.json b/share/qtcreator/templates/wizards/projects/qmlproject/qtquickcontrolsapplication/wizard.json
index 57b5377750..7d601d3dbd 100644
--- a/share/qtcreator/templates/wizards/projects/qmlproject/qtquickcontrolsapplication/wizard.json
+++ b/share/qtcreator/templates/wizards/projects/qmlproject/qtquickcontrolsapplication/wizard.json
@@ -5,7 +5,7 @@
"category": "H.Project",
"trDescription": "Creates a Qt Quick 2 UI project using Qt Quick Controls with a QML entry point. To use it, you need to have a QML runtime environment such as qmlscene set up. Consider using a Qt Quick Controls Application project instead.",
"trDisplayName": "Qt Quick Controls UI",
- "trDisplayCategory": "Application",
+ "trDisplayCategory": "Other Project",
"icon": "../../qmake/qtquickapplication/qml_wizard.png",
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
"featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick.Controls.1.3", "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQt" ],
diff --git a/share/qtcreator/translations/qtcreator_ru.ts b/share/qtcreator/translations/qtcreator_ru.ts
index 51559890fa..2090cf9481 100644
--- a/share/qtcreator/translations/qtcreator_ru.ts
+++ b/share/qtcreator/translations/qtcreator_ru.ts
@@ -1390,10 +1390,6 @@ Deploying local Qt libraries is incompatible with Android 5.</source>
<source>Core plugin is disabled.</source>
<translation>Базовый модуль отключён.</translation>
</message>
- <message>
- <source>No valid theme &quot;%1&quot;</source>
- <translation>Подходящая тема «%1» не обнаружена</translation>
- </message>
</context>
<context>
<name>ApplicationWindowSpecifics</name>
@@ -5383,6 +5379,10 @@ Continue?</source>
<context>
<name>Core::Internal::CorePlugin</name>
<message>
+ <source>No themes found in installation.</source>
+ <translation>Темы не установлены.</translation>
+ </message>
+ <message>
<source>The current date (ISO).</source>
<translation>Текущая дата (ISO).</translation>
</message>
@@ -8286,26 +8286,6 @@ In addition, Shift+Enter inserts an escape character at the cursor position and
<translation></translation>
</message>
<message>
- <source>Code Completion and Semantic Highlighting</source>
- <translation>Дополнение и подсветка кода</translation>
- </message>
- <message>
- <source>C</source>
- <translation>C</translation>
- </message>
- <message>
- <source>C++</source>
- <translation>C++</translation>
- </message>
- <message>
- <source>Objective C</source>
- <translation>Objective C</translation>
- </message>
- <message>
- <source>Objective C++</source>
- <translation>Objective C++</translation>
- </message>
- <message>
<source>Pre-compiled Headers</source>
<translation>Прекомпилированные заголовки</translation>
</message>
@@ -8318,8 +8298,20 @@ In addition, Shift+Enter inserts an escape character at the cursor position and
<translation>Игнорировать прекомпилированные заголовки</translation>
</message>
<message>
- <source>Headers</source>
- <translation>Заголовочные</translation>
+ <source>&lt;i&gt;Activate the Clang Code Model plugin to enable the options here.&lt;/i&gt;</source>
+ <translation>&lt;i&gt;Включите модуль Clang Code Model, чтобы менять настройки.&lt;/i&gt;</translation>
+ </message>
+ <message>
+ <source>Use Clang Code Model</source>
+ <translation>Использовать модель кода Clang</translation>
+ </message>
+ <message>
+ <source>Append additional command line options to Clang, one per line. &lt;i&gt;Use this with care.&lt;/i&gt;</source>
+ <translation>Дополнительные параметры командной строки Clang, по одной на строке.&lt;br&gt;&lt;i&gt;Используйте их с осторожностью.&lt;/i&gt;</translation>
+ </message>
+ <message>
+ <source>Reset Options</source>
+ <translation>Сбросить</translation>
</message>
</context>
<context>
@@ -10438,14 +10430,6 @@ Flags: %3</source>
<translation>Менять размер шрифта в окне отладчика при изменении его в основном окне редактора.</translation>
</message>
<message>
- <source>Populates the source file view automatically. This might slow down debugger startup considerably.</source>
- <translation>Автоматическое заполнение просмотра файлов исходных текстов. Может замедлить процесс запуска отладчика.</translation>
- </message>
- <message>
- <source>Populate source file view automatically</source>
- <translation>Автоматически заполнять представление исходных текстов</translation>
- </message>
- <message>
<source>Switch to previous mode on debugger exit</source>
<translation>Переключаться в предыдущий режим при завершении отладчика</translation>
</message>
@@ -11365,10 +11349,6 @@ Qt Creator не может подключиться к нему.</translation>
<translation>Подсказки в обзоре стека при отладке</translation>
</message>
<message>
- <source>List Source Files</source>
- <translation>Показать файлы исходников</translation>
- </message>
- <message>
<source>Skip Known Frames</source>
<translation>Пропустить известные кадры</translation>
</message>
@@ -22143,6 +22123,10 @@ Ids must begin with a lowercase letter.</source>
<context>
<name>ProjectExplorer::Internal::DependenciesWidget</name>
<message>
+ <source>Synchronize configuration</source>
+ <translation>Синхронизировать конфигурацию</translation>
+ </message>
+ <message>
<source>Synchronize active kit, build, and deploy configuration between projects.</source>
<translation>Сихронизировать у проектов текущий комплект и конфигурации сборки и установки.</translation>
</message>
@@ -34043,7 +34027,7 @@ with a password, which you can enter below.</source>
<context>
<name>TextEditor::FindInFiles</name>
<message>
- <source>Files on File System</source>
+ <source>Files in File System</source>
<translation>Файлы в системе</translation>
</message>
<message>
@@ -38741,6 +38725,10 @@ should a repository require SSH-authentication (see documentation on SSH and the
<context>
<name>WinRt::Internal::WinRtDebugSupport</name>
<message>
+ <source>Not enough free ports for QML debugging.</source>
+ <translation>Недостаточно свободных портов для отладки QML.</translation>
+ </message>
+ <message>
<source>The WinRT debugging helper is missing from your Qt Creator installation. It was assumed to be located at %1</source>
<translation>Помощник отладчика WinRT отсутствует в составе установки вашего Qt Creator. Предполагается, что он находится в %1</translation>
</message>
diff --git a/src/libs/3rdparty/cplusplus/AST.h b/src/libs/3rdparty/cplusplus/AST.h
index 8c3ceca968..bcdf043362 100644
--- a/src/libs/3rdparty/cplusplus/AST.h
+++ b/src/libs/3rdparty/cplusplus/AST.h
@@ -3349,7 +3349,7 @@ public:
DeclarationAST *declaration;
public: // annotations
- Scope *symbol;
+ Template *symbol;
public:
TemplateDeclarationAST()
diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp
index 0deb19dd54..63940d19dd 100644
--- a/src/libs/3rdparty/cplusplus/Bind.cpp
+++ b/src/libs/3rdparty/cplusplus/Bind.cpp
@@ -1917,19 +1917,9 @@ bool Bind::visit(SimpleDeclarationAST *ast)
methodKey = methodKeyForInvokableToken(tokenKind(ast->qt_invokable_token));
// unsigned qt_invokable_token = ast->qt_invokable_token;
- const ExpressionAST *declTypeExpression = 0;
- bool isTypedef = false;
FullySpecifiedType type;
for (SpecifierListAST *it = ast->decl_specifier_list; it; it = it->next) {
type = this->specifier(it->value, type);
- if (type.isTypedef())
- isTypedef = true;
-
- type.setTypedef(isTypedef);
- if (type.isDecltype()) {
- if (DecltypeSpecifierAST *decltypeSpec = it->value->asDecltypeSpecifier())
- declTypeExpression = decltypeSpec->expression;
- }
}
List<Symbol *> **symbolTail = &ast->symbols;
@@ -1985,8 +1975,6 @@ bool Bind::visit(SimpleDeclarationAST *ast)
translationUnit()->error(location(declaratorId->name, ast->firstToken()), "auto-initialized variable must have an initializer");
else if (initializer)
decl->setInitializer(asStringLiteral(initializer));
- } else if (declTy.isDecltype()) {
- decl->setInitializer(asStringLiteral(declTypeExpression));
}
if (_scope->isClass()) {
@@ -2367,15 +2355,11 @@ bool Bind::visit(ParameterDeclarationAST *ast)
bool Bind::visit(TemplateDeclarationAST *ast)
{
- Scope *scope = 0;
- if (ast->less_token)
- scope = control()->newTemplate(ast->firstToken(), 0);
- else
- scope = control()->newExplicitInstantiation(ast->firstToken(), 0);
- scope->setStartOffset(tokenAt(ast->firstToken()).utf16charsBegin());
- scope->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
- ast->symbol = scope;
- Scope *previousScope = switchScope(scope);
+ Template *templ = control()->newTemplate(ast->firstToken(), 0);
+ templ->setStartOffset(tokenAt(ast->firstToken()).utf16charsBegin());
+ templ->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
+ ast->symbol = templ;
+ Scope *previousScope = switchScope(templ);
for (DeclarationListAST *it = ast->template_parameter_list; it; it = it->next) {
this->declaration(it->value);
@@ -2384,17 +2368,12 @@ bool Bind::visit(TemplateDeclarationAST *ast)
this->declaration(ast->declaration);
(void) switchScope(previousScope);
- Symbol *decl = 0;
- if (Template *templ = scope->asTemplate())
- decl = templ->declaration();
- else if (ExplicitInstantiation *inst = scope->asExplicitInstantiation())
- decl = inst->declaration();
- if (decl) {
- scope->setSourceLocation(decl->sourceLocation(), translationUnit());
- scope->setName(decl->name());
+ if (Symbol *decl = templ->declaration()) {
+ templ->setSourceLocation(decl->sourceLocation(), translationUnit());
+ templ->setName(decl->name());
}
- _scope->addMember(scope);
+ _scope->addMember(templ);
return false;
}
@@ -3039,7 +3018,6 @@ bool Bind::visit(TypeofSpecifierAST *ast)
bool Bind::visit(DecltypeSpecifierAST *ast)
{
_type = this->expression(ast->expression);
- _type.setDecltype(true);
return false;
}
diff --git a/src/libs/3rdparty/cplusplus/CPlusPlusForwardDeclarations.h b/src/libs/3rdparty/cplusplus/CPlusPlusForwardDeclarations.h
index 54f9db96da..9b1c5a30cf 100644
--- a/src/libs/3rdparty/cplusplus/CPlusPlusForwardDeclarations.h
+++ b/src/libs/3rdparty/cplusplus/CPlusPlusForwardDeclarations.h
@@ -112,7 +112,6 @@ class Function;
class Namespace;
class NamespaceAlias;
class Template;
-class ExplicitInstantiation;
class BaseClass;
class Block;
class Class;
diff --git a/src/libs/3rdparty/cplusplus/Control.cpp b/src/libs/3rdparty/cplusplus/Control.cpp
index 463a2f88f6..afdd679056 100644
--- a/src/libs/3rdparty/cplusplus/Control.cpp
+++ b/src/libs/3rdparty/cplusplus/Control.cpp
@@ -366,16 +366,9 @@ public:
Template *newTemplate(unsigned sourceLocation, const Name *name)
{
- Template *templ = new Template(translationUnit, sourceLocation, name);
- symbols.push_back(templ);
- return templ;
- }
-
- ExplicitInstantiation *newExplicitInstantiation(unsigned sourceLocation, const Name *name)
- {
- ExplicitInstantiation *inst = new ExplicitInstantiation(translationUnit, sourceLocation, name);
- symbols.push_back(inst);
- return inst;
+ Template *ns = new Template(translationUnit, sourceLocation, name);
+ symbols.push_back(ns);
+ return ns;
}
NamespaceAlias *newNamespaceAlias(unsigned sourceLocation, const Name *name)
@@ -699,9 +692,6 @@ Namespace *Control::newNamespace(unsigned sourceLocation, const Name *name)
Template *Control::newTemplate(unsigned sourceLocation, const Name *name)
{ return d->newTemplate(sourceLocation, name); }
-ExplicitInstantiation *Control::newExplicitInstantiation(unsigned sourceLocation, const Name *name)
-{ return d->newExplicitInstantiation(sourceLocation, name); }
-
NamespaceAlias *Control::newNamespaceAlias(unsigned sourceLocation, const Name *name)
{ return d->newNamespaceAlias(sourceLocation, name); }
diff --git a/src/libs/3rdparty/cplusplus/Control.h b/src/libs/3rdparty/cplusplus/Control.h
index bb2bf9cd10..85b8c3d3d7 100644
--- a/src/libs/3rdparty/cplusplus/Control.h
+++ b/src/libs/3rdparty/cplusplus/Control.h
@@ -120,9 +120,6 @@ public:
/// Creates a new Template symbol.
Template *newTemplate(unsigned sourceLocation, const Name *name = 0);
- /// Creates a new ExplicitInstantiation symbol.
- ExplicitInstantiation *newExplicitInstantiation(unsigned sourceLocation, const Name *name = 0);
-
/// Creates a new Namespace symbol.
NamespaceAlias *newNamespaceAlias(unsigned sourceLocation, const Name *name = 0);
diff --git a/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp b/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp
index ea88140314..f78e4e9338 100644
--- a/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp
+++ b/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp
@@ -100,12 +100,6 @@ bool FullySpecifiedType::isAuto() const
void FullySpecifiedType::setAuto(bool isAuto)
{ f._isAuto = isAuto; }
-bool FullySpecifiedType::isDecltype() const
-{ return f._isDecltype; }
-
-void FullySpecifiedType::setDecltype(bool isDecltype)
-{ f._isDecltype = isDecltype; }
-
bool FullySpecifiedType::isRegister() const
{ return f._isRegister; }
diff --git a/src/libs/3rdparty/cplusplus/FullySpecifiedType.h b/src/libs/3rdparty/cplusplus/FullySpecifiedType.h
index 4c7a21ddc3..8f20018465 100644
--- a/src/libs/3rdparty/cplusplus/FullySpecifiedType.h
+++ b/src/libs/3rdparty/cplusplus/FullySpecifiedType.h
@@ -58,9 +58,6 @@ public:
bool isAuto() const;
void setAuto(bool isAuto);
- bool isDecltype() const;
- void setDecltype(bool isDecltype);
-
bool isRegister() const;
void setRegister(bool isRegister);
@@ -128,7 +125,6 @@ private:
// storage class specifiers
unsigned _isFriend: 1;
unsigned _isAuto: 1;
- unsigned _isDecltype: 1;
unsigned _isRegister: 1;
unsigned _isStatic: 1;
unsigned _isExtern: 1;
diff --git a/src/libs/3rdparty/cplusplus/Matcher.cpp b/src/libs/3rdparty/cplusplus/Matcher.cpp
index 379ed59586..7a3c21cafc 100644
--- a/src/libs/3rdparty/cplusplus/Matcher.cpp
+++ b/src/libs/3rdparty/cplusplus/Matcher.cpp
@@ -218,17 +218,6 @@ bool Matcher::match(const Template *type, const Template *otherType)
return true;
}
-bool Matcher::match(const ExplicitInstantiation *type, const ExplicitInstantiation *otherType)
-{
- if (type == otherType)
- return true;
-
- if (! Matcher::match(type->name(), otherType->name(), this))
- return false;
-
- return true;
-}
-
bool Matcher::match(const ForwardClassDeclaration *type, const ForwardClassDeclaration *otherType)
{
if (type == otherType)
diff --git a/src/libs/3rdparty/cplusplus/Matcher.h b/src/libs/3rdparty/cplusplus/Matcher.h
index 4d2b40b64d..1a9d9d3511 100644
--- a/src/libs/3rdparty/cplusplus/Matcher.h
+++ b/src/libs/3rdparty/cplusplus/Matcher.h
@@ -61,7 +61,6 @@ public:
virtual bool match(const Enum *type, const Enum *otherType);
virtual bool match(const Namespace *type, const Namespace *otherType);
virtual bool match(const Template *type, const Template *otherType);
- virtual bool match(const ExplicitInstantiation *type, const ExplicitInstantiation *otherType);
virtual bool match(const ForwardClassDeclaration *type, const ForwardClassDeclaration *otherType);
virtual bool match(const Class *type, const Class *otherType);
virtual bool match(const ObjCClass *type, const ObjCClass *otherType);
diff --git a/src/libs/3rdparty/cplusplus/Names.h b/src/libs/3rdparty/cplusplus/Names.h
index 7b49190f8e..33f40d523d 100644
--- a/src/libs/3rdparty/cplusplus/Names.h
+++ b/src/libs/3rdparty/cplusplus/Names.h
@@ -100,7 +100,7 @@ public:
TemplateArgumentIterator firstTemplateArgument() const { return _templateArguments.begin(); }
TemplateArgumentIterator lastTemplateArgument() const { return _templateArguments.end(); }
bool isSpecialization() const { return _isSpecialization; }
- // this is temporary solution needed in LookupScope::nestedType
+ // this is temporary solution needed in ClassOrNamespace::nestedType
// when we try to find correct specialization for instantiation
void setIsSpecialization(bool isSpecialization) { _isSpecialization = isSpecialization; }
diff --git a/src/libs/3rdparty/cplusplus/Parser.cpp b/src/libs/3rdparty/cplusplus/Parser.cpp
index 6fccebb015..901f5ac2c1 100644
--- a/src/libs/3rdparty/cplusplus/Parser.cpp
+++ b/src/libs/3rdparty/cplusplus/Parser.cpp
@@ -1789,6 +1789,11 @@ bool Parser::parseEnumSpecifier(SpecifierListAST *&node)
if (_languageFeatures.cxx11Enabled && (LA() == T_CLASS || LA() == T_STRUCT))
ast->key_token = consumeToken();
+
+ if (tok().isKeyword()) {
+ error(cursor(), "expected identifier before '%s'", tok().spell());
+ return false;
+ }
parseName(ast->name);
if (_languageFeatures.cxx11Enabled && LA() == T_COLON) {
diff --git a/src/libs/3rdparty/cplusplus/Scope.cpp b/src/libs/3rdparty/cplusplus/Scope.cpp
index 783eff77ae..406a794c7e 100644
--- a/src/libs/3rdparty/cplusplus/Scope.cpp
+++ b/src/libs/3rdparty/cplusplus/Scope.cpp
@@ -215,7 +215,7 @@ unsigned SymbolTable::symbolCount() const
Symbol *SymbolTable::symbolAt(unsigned index) const
{
- if (! _symbols || index >= symbolCount())
+ if (! _symbols)
return 0;
return _symbols[index];
}
diff --git a/src/libs/3rdparty/cplusplus/Symbol.cpp b/src/libs/3rdparty/cplusplus/Symbol.cpp
index 0ddd4ffbb2..ae20b14bb7 100644
--- a/src/libs/3rdparty/cplusplus/Symbol.cpp
+++ b/src/libs/3rdparty/cplusplus/Symbol.cpp
@@ -361,9 +361,6 @@ bool Symbol::isNamespace() const
bool Symbol::isTemplate() const
{ return asTemplate() != 0; }
-bool Symbol::isExplicitInstantiation() const
-{ return asExplicitInstantiation() != 0; }
-
bool Symbol::isClass() const
{ return asClass() != 0; }
diff --git a/src/libs/3rdparty/cplusplus/Symbol.h b/src/libs/3rdparty/cplusplus/Symbol.h
index cbed45f461..919268b14b 100644
--- a/src/libs/3rdparty/cplusplus/Symbol.h
+++ b/src/libs/3rdparty/cplusplus/Symbol.h
@@ -135,7 +135,7 @@ public:
/// Returns true if this Symbol is an Enum.
bool isEnum() const;
- /// Returns true if this Symbol is a Function.
+ /// Returns true if this Symbol is an Function.
bool isFunction() const;
/// Returns true if this Symbol is a Namespace.
@@ -144,9 +144,6 @@ public:
/// Returns true if this Symbol is a Template.
bool isTemplate() const;
- /// Returns true if this Symbol is an ExplicitInstantiation.
- bool isExplicitInstantiation() const;
-
/// Returns true if this Symbol is a Class.
bool isClass() const;
@@ -206,7 +203,6 @@ public:
virtual const Function *asFunction() const { return 0; }
virtual const Namespace *asNamespace() const { return 0; }
virtual const Template *asTemplate() const { return 0; }
- virtual const ExplicitInstantiation *asExplicitInstantiation() const { return 0; }
virtual const NamespaceAlias *asNamespaceAlias() const { return 0; }
virtual const Class *asClass() const { return 0; }
virtual const Block *asBlock() const { return 0; }
@@ -233,7 +229,6 @@ public:
virtual Function *asFunction() { return 0; }
virtual Namespace *asNamespace() { return 0; }
virtual Template *asTemplate() { return 0; }
- virtual ExplicitInstantiation *asExplicitInstantiation() { return 0; }
virtual NamespaceAlias *asNamespaceAlias() { return 0; }
virtual Class *asClass() { return 0; }
virtual Block *asBlock() { return 0; }
diff --git a/src/libs/3rdparty/cplusplus/SymbolVisitor.h b/src/libs/3rdparty/cplusplus/SymbolVisitor.h
index 5331525e9f..4311672eca 100644
--- a/src/libs/3rdparty/cplusplus/SymbolVisitor.h
+++ b/src/libs/3rdparty/cplusplus/SymbolVisitor.h
@@ -51,7 +51,6 @@ public:
virtual bool visit(Function *) { return true; }
virtual bool visit(Namespace *) { return true; }
virtual bool visit(Template *) { return true; }
- virtual bool visit(ExplicitInstantiation *) { return true; }
virtual bool visit(Class *) { return true; }
virtual bool visit(Block *) { return true; }
virtual bool visit(ForwardClassDeclaration *) { return true; }
diff --git a/src/libs/3rdparty/cplusplus/Symbols.cpp b/src/libs/3rdparty/cplusplus/Symbols.cpp
index 3c632f1cd7..f8a8440c09 100644
--- a/src/libs/3rdparty/cplusplus/Symbols.cpp
+++ b/src/libs/3rdparty/cplusplus/Symbols.cpp
@@ -481,12 +481,10 @@ void Enum::visitSymbol0(SymbolVisitor *visitor)
Template::Template(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
: Scope(translationUnit, sourceLocation, name)
- , _isExplicitInstantiation(false)
{ }
Template::Template(Clone *clone, Subst *subst, Template *original)
: Scope(clone, subst, original)
- , _isExplicitInstantiation(original->_isExplicitInstantiation)
{ }
Template::~Template()
@@ -539,56 +537,6 @@ bool Template::match0(const Type *otherType, Matcher *matcher) const
return false;
}
-ExplicitInstantiation::ExplicitInstantiation(TranslationUnit *translationUnit,
- unsigned sourceLocation, const Name *name)
- : Scope(translationUnit, sourceLocation, name)
-{ }
-
-ExplicitInstantiation::ExplicitInstantiation(Clone *clone, Subst *subst, ExplicitInstantiation *original)
- : Scope(clone, subst, original)
-{ }
-
-ExplicitInstantiation::~ExplicitInstantiation()
-{ }
-
-Symbol *ExplicitInstantiation::declaration() const
-{
- if (isEmpty())
- return 0;
-
- if (Symbol *s = memberAt(memberCount() - 1)) {
- if (s->isClass() || s->isForwardClassDeclaration() ||
- s->isTemplate() || s->isExplicitInstantiation() ||
- s->isFunction() || s->isDeclaration()) {
- return s;
- }
- }
-
- return 0;
-}
-
-FullySpecifiedType ExplicitInstantiation::type() const
-{ return FullySpecifiedType(const_cast<ExplicitInstantiation *>(this)); }
-
-void ExplicitInstantiation::visitSymbol0(SymbolVisitor *visitor)
-{
- if (visitor->visit(this)) {
- for (unsigned i = 0; i < memberCount(); ++i) {
- visitSymbol(memberAt(i), visitor);
- }
- }
-}
-
-void ExplicitInstantiation::accept0(TypeVisitor *visitor)
-{ visitor->visit(this); }
-
-bool ExplicitInstantiation::match0(const Type *otherType, Matcher *matcher) const
-{
- if (const ExplicitInstantiation *otherTy = otherType->asExplicitInstantiationType())
- return matcher->match(this, otherTy);
- return false;
-}
-
Namespace::Namespace(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
: Scope(translationUnit, sourceLocation, name)
, _isInline(false)
diff --git a/src/libs/3rdparty/cplusplus/Symbols.h b/src/libs/3rdparty/cplusplus/Symbols.h
index f2d92c23f2..257bdb8682 100644
--- a/src/libs/3rdparty/cplusplus/Symbols.h
+++ b/src/libs/3rdparty/cplusplus/Symbols.h
@@ -423,41 +423,8 @@ protected:
virtual void visitSymbol0(SymbolVisitor *visitor);
virtual void accept0(TypeVisitor *visitor);
virtual bool match0(const Type *otherType, Matcher *matcher) const;
-
-private:
- bool _isExplicitInstantiation;
};
-class CPLUSPLUS_EXPORT ExplicitInstantiation : public Scope, public Type
-{
-public:
- ExplicitInstantiation(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name);
- ExplicitInstantiation(Clone *clone, Subst *subst, ExplicitInstantiation *original);
- virtual ~ExplicitInstantiation();
-
- Symbol *declaration() const;
-
- // Symbol's interface
- virtual FullySpecifiedType type() const;
-
- virtual const ExplicitInstantiation *asExplicitInstantiation() const
- { return this; }
-
- virtual ExplicitInstantiation *asExplicitInstantiation()
- { return this; }
-
- // Type's interface
- virtual const ExplicitInstantiation *asExplicitInstantiationType() const
- { return this; }
-
- virtual ExplicitInstantiation *asExplicitInstantiationType()
- { return this; }
-
-protected:
- virtual void visitSymbol0(SymbolVisitor *visitor);
- virtual void accept0(TypeVisitor *visitor);
- virtual bool match0(const Type *otherType, Matcher *matcher) const;
-};
class CPLUSPLUS_EXPORT Namespace: public Scope, public Type
{
diff --git a/src/libs/3rdparty/cplusplus/Templates.cpp b/src/libs/3rdparty/cplusplus/Templates.cpp
index 41e462a3b8..3b8ae9a23f 100644
--- a/src/libs/3rdparty/cplusplus/Templates.cpp
+++ b/src/libs/3rdparty/cplusplus/Templates.cpp
@@ -125,12 +125,6 @@ void CloneType::visit(Template *type)
_type = templ;
}
-void CloneType::visit(ExplicitInstantiation *type)
-{
- ExplicitInstantiation *inst = _clone->symbol(type, _subst)->asExplicitInstantiation();
- _type = inst;
-}
-
void CloneType::visit(Class *type)
{
Class *klass = _clone->symbol(type, _subst)->asClass();
@@ -194,8 +188,10 @@ Symbol *CloneSymbol::cloneSymbol(Symbol *symbol, Subst *subst)
SymbolSubstPair symbolSubstPair = std::make_pair(symbol, subst);
auto it = _cache.find(symbolSubstPair);
- if (it != _cache.end())
- return it->second;
+ if (it != _cache.end()) {
+ if (it->second->enclosingScope() == symbol->enclosingScope())
+ return it->second;
+ }
Symbol *r = 0;
std::swap(_subst, subst);
@@ -297,14 +293,6 @@ bool CloneSymbol::visit(Template *symbol)
return false;
}
-bool CloneSymbol::visit(ExplicitInstantiation *symbol)
-{
- ExplicitInstantiation *inst = new ExplicitInstantiation(_clone, _subst, symbol);
- _symbol = inst;
- _control->addSymbol(inst);
- return false;
-}
-
bool CloneSymbol::visit(Class *symbol)
{
Class *klass = new Class(_clone, _subst, symbol);
diff --git a/src/libs/3rdparty/cplusplus/Templates.h b/src/libs/3rdparty/cplusplus/Templates.h
index e39f79a7a6..9db69084f7 100644
--- a/src/libs/3rdparty/cplusplus/Templates.h
+++ b/src/libs/3rdparty/cplusplus/Templates.h
@@ -85,7 +85,6 @@ protected:
virtual void visit(Function *type);
virtual void visit(Namespace *type);
virtual void visit(Template *type);
- virtual void visit(ExplicitInstantiation *type);
virtual void visit(Class *type);
virtual void visit(Enum *type);
virtual void visit(ForwardClassDeclaration *type);
@@ -153,7 +152,6 @@ protected:
virtual bool visit(Function *symbol);
virtual bool visit(Namespace *symbol);
virtual bool visit(Template *symbol);
- virtual bool visit(ExplicitInstantiation *symbol);
virtual bool visit(Class *symbol);
virtual bool visit(Block *symbol);
virtual bool visit(ForwardClassDeclaration *symbol);
diff --git a/src/libs/3rdparty/cplusplus/Type.cpp b/src/libs/3rdparty/cplusplus/Type.cpp
index 69ffb5030a..bad4d42eeb 100644
--- a/src/libs/3rdparty/cplusplus/Type.cpp
+++ b/src/libs/3rdparty/cplusplus/Type.cpp
@@ -68,9 +68,6 @@ bool Type::isNamespaceType() const
bool Type::isTemplateType() const
{ return asTemplateType() != 0; }
-bool Type::isExplicitInstantiationType() const
-{ return asExplicitInstantiationType() != 0; }
-
bool Type::isClassType() const
{ return asClassType() != 0; }
diff --git a/src/libs/3rdparty/cplusplus/Type.h b/src/libs/3rdparty/cplusplus/Type.h
index 2661628f76..958ba15efd 100644
--- a/src/libs/3rdparty/cplusplus/Type.h
+++ b/src/libs/3rdparty/cplusplus/Type.h
@@ -43,7 +43,6 @@ public:
bool isFunctionType() const;
bool isNamespaceType() const;
bool isTemplateType() const;
- bool isExplicitInstantiationType() const;
bool isClassType() const;
bool isEnumType() const;
bool isForwardClassDeclarationType() const;
@@ -65,7 +64,6 @@ public:
virtual const Function *asFunctionType() const { return 0; }
virtual const Namespace *asNamespaceType() const { return 0; }
virtual const Template *asTemplateType() const { return 0; }
- virtual const ExplicitInstantiation *asExplicitInstantiationType() const { return 0; }
virtual const Class *asClassType() const { return 0; }
virtual const Enum *asEnumType() const { return 0; }
virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const { return 0; }
@@ -87,7 +85,6 @@ public:
virtual Function *asFunctionType() { return 0; }
virtual Namespace *asNamespaceType() { return 0; }
virtual Template *asTemplateType() { return 0; }
- virtual ExplicitInstantiation *asExplicitInstantiationType() { return 0; }
virtual Class *asClassType() { return 0; }
virtual Enum *asEnumType() { return 0; }
virtual ForwardClassDeclaration *asForwardClassDeclarationType() { return 0; }
diff --git a/src/libs/3rdparty/cplusplus/TypeVisitor.h b/src/libs/3rdparty/cplusplus/TypeVisitor.h
index 86568dcebc..b3a24b1572 100644
--- a/src/libs/3rdparty/cplusplus/TypeVisitor.h
+++ b/src/libs/3rdparty/cplusplus/TypeVisitor.h
@@ -51,7 +51,6 @@ public:
virtual void visit(Function *) {}
virtual void visit(Namespace *) {}
virtual void visit(Template *) {}
- virtual void visit(ExplicitInstantiation *) {}
virtual void visit(Class *) {}
virtual void visit(Enum *) {}
virtual void visit(ForwardClassDeclaration *) {}
diff --git a/src/libs/3rdparty/modeling/qmt/model_widgets_ui/classmembersedit.cpp b/src/libs/3rdparty/modeling/qmt/model_widgets_ui/classmembersedit.cpp
index 641b303d2b..bb8d11ebdd 100644
--- a/src/libs/3rdparty/modeling/qmt/model_widgets_ui/classmembersedit.cpp
+++ b/src/libs/3rdparty/modeling/qmt/model_widgets_ui/classmembersedit.cpp
@@ -490,7 +490,8 @@ QList<MClassMember> ClassMembersEdit::parse(const QString &text, bool *ok)
member.setProperties(member.properties() | MClassMember::PropertyQslot);
word = cursor.readWord().toLower();
} else if (word == QStringLiteral("invokable") || word == QStringLiteral("qInvokable")) {
- member.setProperties(member.properties() | MClassMember::PropertyQinvokable);
+ member.setProperties(member.getProperties() | MClassMember::PROPERTY_QINVOKABLE);
+ word = cursor.readWord().toLower();
} else if (word == QStringLiteral(":")) {
word = cursor.readWord().toLower();
} else {
diff --git a/src/libs/clangbackendipc/clangbackendipc_global.h b/src/libs/clangbackendipc/clangbackendipc_global.h
index 544a5b15ac..c9851069b5 100644
--- a/src/libs/clangbackendipc/clangbackendipc_global.h
+++ b/src/libs/clangbackendipc/clangbackendipc_global.h
@@ -53,5 +53,28 @@ enum class DiagnosticSeverity // one to one mapping of the clang enum numbers
Error = 3,
Fatal = 4
};
+
+enum class HighlightingType
+{
+ Invalid,
+ Keyword,
+ StringLiteral,
+ NumberLiteral,
+ Comment,
+ Function,
+ VirtualFunction,
+ Type,
+ LocalVariable,
+ Field,
+ GlobalVariable,
+ Enumeration,
+ Operator,
+ Preprocessor,
+ PreprocessorDefinition,
+ PreprocessorExpansion,
+ Label,
+ OutputArgument
+};
+
}
#endif // CLANGBACKENDIPC_GLOBAL_H
diff --git a/src/libs/cplusplus/CppRewriter.cpp b/src/libs/cplusplus/CppRewriter.cpp
index fa66e3b4e3..63eadd912c 100644
--- a/src/libs/cplusplus/CppRewriter.cpp
+++ b/src/libs/cplusplus/CppRewriter.cpp
@@ -379,7 +379,7 @@ FullySpecifiedType SubstitutionMap::apply(const Name *name, Rewrite *) const
}
-UseMinimalNames::UseMinimalNames(LookupScope *target)
+UseMinimalNames::UseMinimalNames(ClassOrNamespace *target)
: _target(target)
{
diff --git a/src/libs/cplusplus/CppRewriter.h b/src/libs/cplusplus/CppRewriter.h
index cb307a9401..cc68f662a5 100644
--- a/src/libs/cplusplus/CppRewriter.h
+++ b/src/libs/cplusplus/CppRewriter.h
@@ -89,13 +89,13 @@ private:
class CPLUSPLUS_EXPORT UseMinimalNames: public Substitution
{
public:
- UseMinimalNames(LookupScope *target);
+ UseMinimalNames(ClassOrNamespace *target);
virtual ~UseMinimalNames();
virtual FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const;
private:
- LookupScope *_target;
+ ClassOrNamespace *_target;
};
class CPLUSPLUS_EXPORT UseQualifiedNames: public UseMinimalNames
diff --git a/src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp b/src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp
new file mode 100644
index 0000000000..e037f87c58
--- /dev/null
+++ b/src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp
@@ -0,0 +1,430 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "DeprecatedGenTemplateInstance.h"
+#include "Overview.h"
+
+#include <cplusplus/Control.h>
+#include <cplusplus/Scope.h>
+#include <cplusplus/Names.h>
+#include <cplusplus/Symbols.h>
+#include <cplusplus/CoreTypes.h>
+#include <cplusplus/Literals.h>
+
+#include <QVarLengthArray>
+#include <QDebug>
+
+using namespace CPlusPlus;
+
+namespace {
+
+class ApplySubstitution
+{
+public:
+ ApplySubstitution(Control *control, Symbol *symbol, const DeprecatedGenTemplateInstance::Substitution &substitution);
+ ~ApplySubstitution();
+
+ inline Control *control() const { return _control; }
+
+ FullySpecifiedType apply(const Name *name);
+ FullySpecifiedType apply(const FullySpecifiedType &type);
+
+ int findSubstitution(const Identifier *id) const;
+ FullySpecifiedType applySubstitution(int index) const;
+
+private:
+ class ApplyToType: protected TypeVisitor
+ {
+ public:
+ ApplyToType(ApplySubstitution *q)
+ : q(q) {}
+
+ FullySpecifiedType operator()(const FullySpecifiedType &ty)
+ {
+ FullySpecifiedType previousType = switchType(ty);
+ accept(ty.type());
+ return switchType(previousType);
+ }
+
+ protected:
+ using TypeVisitor::visit;
+
+ Control *control() const
+ { return q->control(); }
+
+ FullySpecifiedType switchType(const FullySpecifiedType &type)
+ {
+ FullySpecifiedType previousType = _type;
+ _type = type;
+ return previousType;
+ }
+
+ virtual void visit(VoidType *)
+ {
+ // nothing to do
+ }
+
+ virtual void visit(IntegerType *)
+ {
+ // nothing to do
+ }
+
+ virtual void visit(FloatType *)
+ {
+ // nothing to do
+ }
+
+ virtual void visit(PointerToMemberType *)
+ {
+ qDebug() << Q_FUNC_INFO; // ### TODO
+ }
+
+ virtual void visit(PointerType *ptrTy)
+ {
+ _type.setType(control()->pointerType(q->apply(ptrTy->elementType())));
+ }
+
+ virtual void visit(ReferenceType *refTy)
+ {
+ _type.setType(control()->referenceType(q->apply(refTy->elementType()), refTy->isRvalueReference()));
+ }
+
+ virtual void visit(ArrayType *arrayTy)
+ {
+ _type.setType(control()->arrayType(q->apply(arrayTy->elementType()), arrayTy->size()));
+ }
+
+ virtual void visit(NamedType *ty)
+ {
+ FullySpecifiedType n = q->apply(ty->name());
+ _type.setType(n.type());
+ }
+
+ virtual void visit(Function *funTy)
+ {
+ Function *fun = control()->newFunction(/*sourceLocation=*/ 0, funTy->name());
+ fun->setEnclosingScope(funTy->enclosingScope());
+ fun->setConst(funTy->isConst());
+ fun->setVolatile(funTy->isVolatile());
+ fun->setVirtual(funTy->isVirtual());
+ fun->setOverride(funTy->isOverride());
+ fun->setFinal(funTy->isFinal());
+ fun->setAmbiguous(funTy->isAmbiguous());
+ fun->setVariadic(funTy->isVariadic());
+
+ fun->setReturnType(q->apply(funTy->returnType()));
+
+ for (unsigned i = 0, argc = funTy->argumentCount(); i < argc; ++i) {
+ Argument *originalArgument = funTy->argumentAt(i)->asArgument();
+ Argument *arg = control()->newArgument(/*sourceLocation*/ 0,
+ originalArgument->name());
+
+ arg->setType(q->apply(originalArgument->type()));
+ arg->setInitializer(originalArgument->initializer());
+ fun->addMember(arg);
+ }
+
+ _type.setType(fun);
+ }
+
+ virtual void visit(Namespace *)
+ {
+ qDebug() << Q_FUNC_INFO;
+ }
+
+ virtual void visit(Class *)
+ {
+ qDebug() << Q_FUNC_INFO;
+ }
+
+ virtual void visit(Enum *)
+ {
+ qDebug() << Q_FUNC_INFO;
+ }
+
+ virtual void visit(ForwardClassDeclaration *)
+ {
+ qDebug() << Q_FUNC_INFO;
+ }
+
+ virtual void visit(ObjCClass *)
+ {
+ qDebug() << Q_FUNC_INFO;
+ }
+
+ virtual void visit(ObjCProtocol *)
+ {
+ qDebug() << Q_FUNC_INFO;
+ }
+
+ virtual void visit(ObjCMethod *)
+ {
+ qDebug() << Q_FUNC_INFO;
+ }
+
+ virtual void visit(ObjCForwardClassDeclaration *)
+ {
+ qDebug() << Q_FUNC_INFO;
+ }
+
+ virtual void visit(ObjCForwardProtocolDeclaration *)
+ {
+ qDebug() << Q_FUNC_INFO;
+ }
+
+ private:
+ ApplySubstitution *q;
+ FullySpecifiedType _type;
+ QHash<Symbol *, FullySpecifiedType> _processed;
+ };
+
+ class ApplyToName: protected NameVisitor
+ {
+ public:
+ ApplyToName(ApplySubstitution *q): q(q) {}
+
+ FullySpecifiedType operator()(const Name *name)
+ {
+ FullySpecifiedType previousType = switchType(FullySpecifiedType());
+ accept(name);
+ return switchType(previousType);
+ }
+
+ protected:
+ Control *control() const
+ { return q->control(); }
+
+ int findSubstitution(const Identifier *id) const
+ { return q->findSubstitution(id); }
+
+ FullySpecifiedType applySubstitution(int index) const
+ { return q->applySubstitution(index); }
+
+ FullySpecifiedType switchType(const FullySpecifiedType &type)
+ {
+ FullySpecifiedType previousType = _type;
+ _type = type;
+ return previousType;
+ }
+
+ virtual void visit(const Identifier *name)
+ {
+ int index = findSubstitution(name->identifier());
+
+ if (index != -1)
+ _type = applySubstitution(index);
+
+ else
+ _type = control()->namedType(name);
+ }
+
+ virtual void visit(const TemplateNameId *name)
+ {
+ QVarLengthArray<FullySpecifiedType, 8> arguments(name->templateArgumentCount());
+ for (unsigned i = 0; i < name->templateArgumentCount(); ++i) {
+ FullySpecifiedType argTy = name->templateArgumentAt(i);
+ arguments[i] = q->apply(argTy);
+ }
+
+ const TemplateNameId *templId = control()->templateNameId(name->identifier(),
+ name->isSpecialization(),
+ arguments.data(),
+ arguments.size());
+ _type = control()->namedType(templId);
+ }
+
+ const Name *instantiate(const Name *name)
+ {
+ if (! name)
+ return name;
+
+ if (const Identifier *nameId = name->asNameId()) {
+ const Identifier *id = control()->identifier(nameId->chars(), nameId->size());
+ return id;
+
+ } else if (const TemplateNameId *templId = name->asTemplateNameId()) {
+ QVarLengthArray<FullySpecifiedType, 8> arguments(templId->templateArgumentCount());
+ for (unsigned templateArgIndex = 0; templateArgIndex < templId->templateArgumentCount();
+ ++templateArgIndex) {
+ FullySpecifiedType argTy = templId->templateArgumentAt(templateArgIndex);
+ arguments[templateArgIndex] = q->apply(argTy);
+ }
+ const Identifier *id = control()->identifier(templId->identifier()->chars(),
+ templId->identifier()->size());
+ return control()->templateNameId(id, templId->isSpecialization(), arguments.data(),
+ arguments.size());
+
+ } else if (const QualifiedNameId *qq = name->asQualifiedNameId()) {
+ const Name *base = instantiate(qq->base());
+ const Name *name = instantiate(qq->name());
+
+ return control()->qualifiedNameId(base, name);
+
+ } else if (const OperatorNameId *op = name->asOperatorNameId()) {
+ return control()->operatorNameId(op->kind());
+
+ } else if (const ConversionNameId *c = name->asConversionNameId()) {
+ FullySpecifiedType ty = q->apply(c->type());
+ return control()->conversionNameId(ty);
+
+ }
+
+ return 0;
+ }
+
+ virtual void visit(const QualifiedNameId *name)
+ {
+ if (const Name *n = instantiate(name))
+ _type = control()->namedType(n);
+ }
+
+ virtual void visit(const DestructorNameId *name)
+ {
+ Overview oo;
+ qWarning() << "ignored name:" << oo.prettyName(name);
+ }
+
+ virtual void visit(const OperatorNameId *name)
+ {
+ Overview oo;
+ qWarning() << "ignored name:" << oo.prettyName(name);
+ }
+
+ virtual void visit(const ConversionNameId *name)
+ {
+ Overview oo;
+ qWarning() << "ignored name:" << oo.prettyName(name);
+ }
+
+ virtual void visit(const SelectorNameId *name)
+ {
+ Overview oo;
+ qWarning() << "ignored name:" << oo.prettyName(name);
+ }
+
+ private:
+ ApplySubstitution *q;
+ FullySpecifiedType _type;
+ };
+
+public: // attributes
+ Control *_control;
+ Symbol *symbol;
+ DeprecatedGenTemplateInstance::Substitution substitution;
+ ApplyToType applyToType;
+ ApplyToName applyToName;
+};
+
+ApplySubstitution::ApplySubstitution(Control *control, Symbol *symbol,
+ const DeprecatedGenTemplateInstance::Substitution &substitution)
+ : _control(control), symbol(symbol),
+ substitution(substitution),
+ applyToType(this), applyToName(this)
+{ }
+
+ApplySubstitution::~ApplySubstitution()
+{
+}
+
+FullySpecifiedType ApplySubstitution::apply(const Name *name)
+{
+ FullySpecifiedType ty = applyToName(name);
+ return ty;
+}
+
+FullySpecifiedType ApplySubstitution::apply(const FullySpecifiedType &type)
+{
+ FullySpecifiedType ty = applyToType(type);
+ return ty;
+}
+
+int ApplySubstitution::findSubstitution(const Identifier *id) const
+{
+ Q_ASSERT(id != 0);
+
+ for (int index = 0; index < substitution.size(); ++index) {
+ QPair<const Identifier *, FullySpecifiedType> s = substitution.at(index);
+
+ if (id->match(s.first))
+ return index;
+ }
+
+ return -1;
+}
+
+FullySpecifiedType ApplySubstitution::applySubstitution(int index) const
+{
+ Q_ASSERT(index != -1);
+ Q_ASSERT(index < substitution.size());
+
+ return substitution.at(index).second;
+}
+
+} // end of anonymous namespace
+
+DeprecatedGenTemplateInstance::DeprecatedGenTemplateInstance(QSharedPointer<Control> control, const Substitution &substitution)
+ : _control(control),
+ _substitution(substitution)
+{ }
+
+FullySpecifiedType DeprecatedGenTemplateInstance::gen(Symbol *symbol)
+{
+ ApplySubstitution o(_control.data(), symbol, _substitution);
+ return o.apply(symbol->type());
+}
+
+FullySpecifiedType DeprecatedGenTemplateInstance::instantiate(const Name *className, Symbol *candidate,
+ QSharedPointer<Control> control)
+{
+ if (className) {
+ if (const TemplateNameId *templId = className->asTemplateNameId()) {
+ if (Template *templ = candidate->enclosingTemplate()) {
+ DeprecatedGenTemplateInstance::Substitution subst;
+
+ for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) {
+ FullySpecifiedType templArgTy = templId->templateArgumentAt(i);
+
+ if (i < templ->templateParameterCount()) {
+ const Name *templArgName = templ->templateParameterAt(i)->name();
+
+ if (templArgName && templArgName->identifier()) {
+ const Identifier *templArgId = templArgName->identifier();
+ subst.append(qMakePair(templArgId, templArgTy));
+ }
+ }
+ }
+
+ DeprecatedGenTemplateInstance inst(control, subst);
+ return inst.gen(candidate);
+ }
+ }
+ }
+ return candidate->type();
+}
diff --git a/src/libs/cplusplus/TypeResolver.h b/src/libs/cplusplus/DeprecatedGenTemplateInstance.h
index bf25e468c6..9e488478c6 100644
--- a/src/libs/cplusplus/TypeResolver.h
+++ b/src/libs/cplusplus/DeprecatedGenTemplateInstance.h
@@ -28,41 +28,36 @@
**
****************************************************************************/
-#ifndef TYPERESOLVER_H
-#define TYPERESOLVER_H
+#ifndef CPLUSPLUS_DEPRECATEDGENTEMPLATEINSTANCE_H
+#define CPLUSPLUS_DEPRECATEDGENTEMPLATEINSTANCE_H
-#include "LookupContext.h"
+#include <cplusplus/TypeVisitor.h>
+#include <cplusplus/NameVisitor.h>
+#include <cplusplus/FullySpecifiedType.h>
+
+#include <QList>
+#include <QPair>
+#include <QSharedPointer>
namespace CPlusPlus {
-class TypeResolver
+class CPLUSPLUS_EXPORT DeprecatedGenTemplateInstance
{
public:
- TypeResolver(CreateBindings &factory) : _factory(factory) {}
- void resolve(FullySpecifiedType *type, Scope **scope, LookupScope *binding);
- static QList<LookupItem> resolveDeclInitializer(
- CreateBindings &factory, const Declaration *decl,
- const QSet<const Declaration *> &declarationsBeingResolved,
- const Identifier *id = 0);
-
-private:
- NamedType *getNamedType(FullySpecifiedType& type) const;
-
- QList<LookupItem> getNamedTypeItems(const Name *name, Scope *scope,
- LookupScope *binding) const;
+ typedef QList< QPair<const Identifier *, FullySpecifiedType> > Substitution;
- static QList<LookupItem> typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope);
-
- static bool isTypedefWithName(const Declaration *declaration, const Name *name);
+public:
+ static FullySpecifiedType instantiate(const Name *className, Symbol *candidate, QSharedPointer<Control> control);
- bool findTypedef(const QList<LookupItem>& namedTypeItems, FullySpecifiedType *type,
- Scope **scope, QSet<Symbol *>& visited);
+private:
+ DeprecatedGenTemplateInstance(QSharedPointer<Control> control, const Substitution &substitution);
+ FullySpecifiedType gen(Symbol *symbol);
- CreateBindings &_factory;
- // binding has to be remembered in case of resolving typedefs for templates
- LookupScope *_binding;
+private:
+ QSharedPointer<Control> _control;
+ const Substitution _substitution;
};
} // namespace CPlusPlus
-#endif // TYPERESOLVER_H
+#endif // CPLUSPLUS_DEPRECATEDGENTEMPLATEINSTANCE_H
diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp
index b9d34bd00c..0640fab537 100644
--- a/src/libs/cplusplus/FindUsages.cpp
+++ b/src/libs/cplusplus/FindUsages.cpp
@@ -532,7 +532,7 @@ void FindUsages::memInitializer(MemInitializerAST *ast)
if (_currentScope->isFunction()) {
Class *classScope = _currentScope->enclosingClass();
if (! classScope) {
- if (LookupScope *binding = _context.lookupType(_currentScope)) {
+ if (ClassOrNamespace *binding = _context.lookupType(_currentScope)) {
foreach (Symbol *s, binding->symbols()) {
if (Class *k = s->asClass()) {
classScope = k;
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index 401d54f48b..be1968733e 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -32,8 +32,8 @@
#include "ResolveExpression.h"
#include "Overview.h"
+#include "DeprecatedGenTemplateInstance.h"
#include "CppRewriter.h"
-#include "TypeResolver.h"
#include <cplusplus/CoreTypes.h>
#include <cplusplus/Symbols.h>
@@ -41,18 +41,15 @@
#include <cplusplus/Names.h>
#include <cplusplus/Scope.h>
#include <cplusplus/Control.h>
-#include <cplusplus/cppassert.h>
#include <QStack>
#include <QHash>
#include <QVarLengthArray>
#include <QDebug>
-static const bool debug = ! qgetenv("QTC_LOOKUPCONTEXT_DEBUG").isEmpty();
-
-namespace CPlusPlus {
+using namespace CPlusPlus;
-typedef QSet<Internal::LookupScopePrivate *> ProcessedSet;
+static const bool debug = ! qgetenv("QTC_LOOKUPCONTEXT_DEBUG").isEmpty();
static void addNames(const Name *name, QList<const Name *> *names, bool addAllNames = false)
{
@@ -92,6 +89,24 @@ static void path_helper(Symbol *symbol, QList<const Name *> *names)
}
}
+static bool isNestedInstantiationEnclosingTemplate(
+ ClassOrNamespace *nestedClassOrNamespaceInstantiation,
+ ClassOrNamespace *enclosingTemplateClassInstantiation)
+{
+ QList<ClassOrNamespace *> processed;
+ while (enclosingTemplateClassInstantiation
+ && !processed.contains(enclosingTemplateClassInstantiation)) {
+ processed.append(enclosingTemplateClassInstantiation);
+ if (enclosingTemplateClassInstantiation == nestedClassOrNamespaceInstantiation)
+ return false;
+ enclosingTemplateClassInstantiation = enclosingTemplateClassInstantiation->parent();
+ }
+
+ return true;
+}
+
+namespace CPlusPlus {
+
static inline bool compareName(const Name *name, const Name *other)
{
if (name == other)
@@ -121,6 +136,9 @@ bool compareFullyQualifiedName(const QList<const Name *> &path, const QList<cons
return true;
}
+}
+
+namespace CPlusPlus {
namespace Internal {
bool operator==(const FullyQualifiedName &left, const FullyQualifiedName &right)
@@ -142,6 +160,7 @@ uint qHash(const FullyQualifiedName &fullyQualifiedName)
return h;
}
}
+}
/////////////////////////////////////////////////////////////////////
// LookupContext
@@ -163,7 +182,7 @@ LookupContext::LookupContext(Document::Ptr thisDocument,
LookupContext::LookupContext(Document::Ptr expressionDocument,
Document::Ptr thisDocument,
const Snapshot &snapshot,
- CreateBindings::Ptr bindings)
+ QSharedPointer<CreateBindings> bindings)
: _expressionDocument(expressionDocument)
, _thisDocument(thisDocument)
, _snapshot(snapshot)
@@ -216,7 +235,7 @@ static bool symbolIdentical(Symbol *s1, Symbol *s2)
return QByteArray(s1->fileName()) == QByteArray(s2->fileName());
}
-const Name *LookupContext::minimalName(Symbol *symbol, LookupScope *target, Control *control)
+const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target, Control *control)
{
const Name *n = 0;
QList<const Name *> names = LookupContext::fullyQualifiedName(symbol);
@@ -241,7 +260,7 @@ const Name *LookupContext::minimalName(Symbol *symbol, LookupScope *target, Cont
}
QList<LookupItem> LookupContext::lookupByUsing(const Name *name,
- LookupScope *bindingScope) const
+ ClassOrNamespace *bindingScope) const
{
QList<LookupItem> candidates;
// if it is a nameId there can be a using declaration for it
@@ -275,7 +294,7 @@ QList<LookupItem> LookupContext::lookupByUsing(const Name *name,
} else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
foreach (Symbol *s, bindingScope->symbols()) {
if (Scope *scope = s->asScope()) {
- LookupScope *base = lookupType(q->base(), scope);
+ ClassOrNamespace *base = lookupType(q->base(), scope);
if (base)
candidates = lookupByUsing(q->name(), base);
if (!candidates.isEmpty())
@@ -299,14 +318,14 @@ Document::Ptr LookupContext::document(const QString &fileName) const
Snapshot LookupContext::snapshot() const
{ return _snapshot; }
-LookupScope *LookupContext::globalNamespace() const
+ClassOrNamespace *LookupContext::globalNamespace() const
{
return bindings()->globalNamespace();
}
-LookupScope *LookupContext::lookupType(const Name *name, Scope *scope,
- LookupScope *enclosingBinding,
- QSet<const Declaration *> typedefsBeingResolved) const
+ClassOrNamespace *LookupContext::lookupType(const Name *name, Scope *scope,
+ ClassOrNamespace *enclosingBinding,
+ QSet<const Declaration *> typedefsBeingResolved) const
{
if (! scope || ! name) {
return 0;
@@ -314,8 +333,8 @@ LookupScope *LookupContext::lookupType(const Name *name, Scope *scope,
for (unsigned i = 0; i < block->memberCount(); ++i) {
Symbol *m = block->memberAt(i);
if (UsingNamespaceDirective *u = m->asUsingNamespaceDirective()) {
- if (LookupScope *uu = lookupType(u->name(), scope->enclosingNamespace())) {
- if (LookupScope *r = uu->lookupType(name))
+ if (ClassOrNamespace *uu = lookupType(u->name(), scope->enclosingNamespace())) {
+ if (ClassOrNamespace *r = uu->lookupType(name))
return r;
}
} else if (Declaration *d = m->asDeclaration()) {
@@ -348,20 +367,20 @@ LookupScope *LookupContext::lookupType(const Name *name, Scope *scope,
}
// try to find it in block (rare case but has priority before enclosing scope)
// e.g.: void foo() { struct S {}; S s; }
- if (LookupScope *b = bindings()->lookupType(scope, enclosingBinding)) {
- if (LookupScope *lookupScopeNestedInNestedBlock = b->lookupType(name, block))
- return lookupScopeNestedInNestedBlock;
+ if (ClassOrNamespace *b = bindings()->lookupType(scope, enclosingBinding)) {
+ if (ClassOrNamespace *classOrNamespaceNestedInNestedBlock = b->lookupType(name, block))
+ return classOrNamespaceNestedInNestedBlock;
}
// try to find type in enclosing scope(typical case)
- if (LookupScope *found = lookupType(name, scope->enclosingScope()))
+ if (ClassOrNamespace *found = lookupType(name, scope->enclosingScope()))
return found;
- } else if (LookupScope *b = bindings()->lookupType(scope, enclosingBinding)) {
+ } else if (ClassOrNamespace *b = bindings()->lookupType(scope, enclosingBinding)) {
return b->lookupType(name);
} else if (Class *scopeAsClass = scope->asClass()) {
if (scopeAsClass->enclosingScope()->isBlock()) {
- if (LookupScope *b = lookupType(scopeAsClass->name(),
+ if (ClassOrNamespace *b = lookupType(scopeAsClass->name(),
scopeAsClass->enclosingScope(),
enclosingBinding,
typedefsBeingResolved)) {
@@ -373,7 +392,8 @@ LookupScope *LookupContext::lookupType(const Name *name, Scope *scope,
return 0;
}
-LookupScope *LookupContext::lookupType(Symbol *symbol, LookupScope *enclosingBinding) const
+ClassOrNamespace *LookupContext::lookupType(Symbol *symbol,
+ ClassOrNamespace *enclosingBinding) const
{
return bindings()->lookupType(symbol, enclosingBinding);
}
@@ -387,7 +407,7 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
for (; scope; scope = scope->enclosingScope()) {
if (name->identifier() != 0 && scope->isBlock()) {
- bindings()->lookupInScope(name, scope, &candidates);
+ bindings()->lookupInScope(name, scope, &candidates, /*templateId = */ 0, /*binding=*/ 0);
if (! candidates.isEmpty()) {
// it's a local.
@@ -400,7 +420,7 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
for (unsigned i = 0; i < scope->memberCount(); ++i) {
if (UsingNamespaceDirective *u = scope->memberAt(i)->asUsingNamespaceDirective()) {
- if (LookupScope *uu = lookupType(u->name(), scope->enclosingNamespace())) {
+ if (ClassOrNamespace *uu = lookupType(u->name(), scope->enclosingNamespace())) {
candidates = uu->find(name);
if (! candidates.isEmpty())
@@ -409,8 +429,8 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
}
}
- if (LookupScope *bindingScope = bindings()->lookupType(scope)) {
- if (LookupScope *bindingBlock = bindingScope->findBlock(scope->asBlock())) {
+ if (ClassOrNamespace *bindingScope = bindings()->lookupType(scope)) {
+ if (ClassOrNamespace *bindingBlock = bindingScope->findBlock(scope->asBlock())) {
candidates = lookupByUsing(name, bindingBlock);
if (! candidates.isEmpty())
return candidates;
@@ -423,7 +443,7 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
}
} else if (Function *fun = scope->asFunction()) {
- bindings()->lookupInScope(name, fun, &candidates);
+ bindings()->lookupInScope(name, fun, &candidates, /*templateId = */ 0, /*binding=*/ 0);
if (! candidates.isEmpty()) {
// it's an argument or a template parameter.
@@ -435,7 +455,7 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
}
if (fun->name() && fun->name()->isQualifiedNameId()) {
- if (LookupScope *binding = bindings()->lookupType(fun)) {
+ if (ClassOrNamespace *binding = bindings()->lookupType(fun)) {
candidates = binding->find(name);
// try find this name in parent class
@@ -450,13 +470,13 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
// continue, and look at the enclosing scope.
} else if (ObjCMethod *method = scope->asObjCMethod()) {
- bindings()->lookupInScope(name, method, &candidates);
+ bindings()->lookupInScope(name, method, &candidates, /*templateId = */ 0, /*binding=*/ 0);
if (! candidates.isEmpty())
break; // it's a formal argument.
} else if (Template *templ = scope->asTemplate()) {
- bindings()->lookupInScope(name, templ, &candidates);
+ bindings()->lookupInScope(name, templ, &candidates, /*templateId = */ 0, /*binding=*/ 0);
if (! candidates.isEmpty()) {
// it's a template parameter.
@@ -471,7 +491,7 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
|| scope->asClass()
|| (scope->asEnum() && scope->asEnum()->isScoped())) {
- if (LookupScope *bindingScope = bindings()->lookupType(scope)) {
+ if (ClassOrNamespace *bindingScope = bindings()->lookupType(scope)) {
candidates = bindingScope->find(name);
if (! candidates.isEmpty())
@@ -484,9 +504,9 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
// the scope can be defined inside a block, try to find it
if (Block *block = scope->enclosingBlock()) {
- if (LookupScope *b = bindings()->lookupType(block)) {
- if (LookupScope *lookupScopeNestedInNestedBlock = b->lookupType(scope->name(), block))
- candidates = lookupScopeNestedInNestedBlock->find(name);
+ if (ClassOrNamespace *b = bindings()->lookupType(block)) {
+ if (ClassOrNamespace *classOrNamespaceNestedInNestedBlock = b->lookupType(scope->name(), block))
+ candidates = classOrNamespaceNestedInNestedBlock->find(name);
}
}
@@ -494,7 +514,7 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
return candidates;
} else if (scope->isObjCClass() || scope->isObjCProtocol()) {
- if (LookupScope *binding = bindings()->lookupType(scope))
+ if (ClassOrNamespace *binding = bindings()->lookupType(scope))
candidates = binding->find(name);
if (! candidates.isEmpty())
@@ -505,10 +525,10 @@ QList<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const
return candidates;
}
-LookupScope *LookupContext::lookupParent(Symbol *symbol) const
+ClassOrNamespace *LookupContext::lookupParent(Symbol *symbol) const
{
QList<const Name *> fqName = path(symbol);
- LookupScope *binding = globalNamespace();
+ ClassOrNamespace *binding = globalNamespace();
foreach (const Name *name, fqName) {
binding = binding->findType(name);
if (!binding)
@@ -518,193 +538,59 @@ LookupScope *LookupContext::lookupParent(Symbol *symbol) const
return binding;
}
-namespace Internal {
-
-class LookupScopePrivate
-{
-public:
- LookupScopePrivate(LookupScope *q, CreateBindings *factory, LookupScope *parent);
- ~LookupScopePrivate();
-
- typedef std::map<const Name *, LookupScopePrivate *, Name::Compare> Table;
- typedef std::map<const Name *, Declaration *, Name::Compare> TypedefTable;
- typedef std::map<const TemplateNameId *,
- LookupScopePrivate *,
- TemplateNameId::Compare> TemplateNameIdTable;
- typedef QHash<const AnonymousNameId *, LookupScopePrivate *> Anonymouses;
-
- LookupScopePrivate *allocateChild(const Name *name);
-
- void flush();
-
- LookupScope *globalNamespace() const;
-
- Symbol *lookupInScope(const QList<const Name *> &fullName);
-
- LookupScope *findOrCreateType(const Name *name, LookupScopePrivate *origin = 0,
- Class *clazz = 0);
-
- LookupScopePrivate *findOrCreateNestedAnonymousType(const AnonymousNameId *anonymousNameId);
-
- void addTodo(Symbol *symbol);
- void addSymbol(Symbol *symbol);
- void addUnscopedEnum(Enum *e);
- void addTypedef(const Name *identifier, Declaration *d);
- void addUsing(LookupScope *u);
- void addNestedType(const Name *alias, LookupScope *e);
-
- QList<LookupItem> lookup_helper(const Name *name, bool searchInEnclosingScope);
-
- void lookup_helper(const Name *name, LookupScopePrivate *binding,
- QList<LookupItem> *result,
- ProcessedSet *processed);
-
- LookupScope *lookupType_helper(const Name *name, ProcessedSet *processed,
- bool searchInEnclosingScope, LookupScopePrivate *origin);
-
- LookupScope *findBlock_helper(Block *block, ProcessedSet *processed,
- bool searchInEnclosingScope);
-
-private:
- LookupScopePrivate *findNestedType(const Name *name, LookupScopePrivate *origin);
-
- LookupScopePrivate *nestedType(const Name *name, LookupScopePrivate *origin);
-
- LookupScopePrivate *findSpecialization(const TemplateNameId *templId,
- const TemplateNameIdTable &specializations,
- LookupScopePrivate *origin);
-
-public:
- LookupScope *q;
-
- CreateBindings *_factory;
- LookupScopePrivate *_parent;
- QList<Symbol *> _symbols;
- QList<LookupScope *> _usings;
- Table _nestedScopes;
- TypedefTable _typedefs;
- QHash<Block *, LookupScope *> _blocks;
- QList<Enum *> _enums;
- QList<Symbol *> _todo;
- QSharedPointer<Control> _control;
- TemplateNameIdTable _specializations;
- QMap<const TemplateNameId *, LookupScopePrivate *> _instantiations;
- Anonymouses _anonymouses;
- QSet<const AnonymousNameId *> _declaredOrTypedefedAnonymouses;
-
- QHash<Internal::FullyQualifiedName, Symbol *> *_scopeLookupCache;
-
- // it's an instantiation.
- LookupScopePrivate *_instantiationOrigin;
-
- AlreadyConsideredClassContainer<Class> _alreadyConsideredClasses;
- AlreadyConsideredClassContainer<TemplateNameId> _alreadyConsideredTemplates;
- QSet<const Declaration *> _alreadyConsideredTypedefs;
-
- Class *_rootClass;
- const Name *_name;
- bool _hasTypedefs;
-};
-
-class Instantiator
-{
-public:
- Instantiator(Clone &cloner, Subst &subst)
- : _cloner(cloner)
- , _subst(subst)
- {}
- void doInstantiate(LookupScopePrivate *lookupScope, LookupScopePrivate *instantiation);
- LookupScopePrivate *instantiate(LookupScopePrivate *lookupScope, LookupScopePrivate *origin);
-
-private:
- ProcessedSet _alreadyConsideredInstantiations;
- Clone &_cloner;
- Subst &_subst;
-};
-
-LookupScopePrivate::LookupScopePrivate(LookupScope *q, CreateBindings *factory, LookupScope *parent)
- : q(q)
- , _factory(factory)
- , _parent(parent ? parent->d : 0)
+ClassOrNamespace::ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent)
+ : _factory(factory)
+ , _parent(parent)
, _scopeLookupCache(0)
+ , _templateId(0)
, _instantiationOrigin(0)
, _rootClass(0)
, _name(0)
- , _hasTypedefs(false)
{
Q_ASSERT(factory);
}
-LookupScopePrivate::~LookupScopePrivate()
+ClassOrNamespace::~ClassOrNamespace()
{
delete _scopeLookupCache;
}
-LookupScopePrivate *LookupScopePrivate::allocateChild(const Name *name)
+const TemplateNameId *ClassOrNamespace::templateId() const
{
- LookupScope *e = _factory->allocLookupScope(q, name);
- return e->d;
+ return _templateId;
}
-} // namespace Internal
-
-LookupScope::LookupScope(CreateBindings *factory, LookupScope *parent)
- : d(new Internal::LookupScopePrivate(this, factory, parent))
+ClassOrNamespace *ClassOrNamespace::instantiationOrigin() const
{
+ return _instantiationOrigin;
}
-LookupScope::~LookupScope()
+ClassOrNamespace *ClassOrNamespace::parent() const
{
- delete d;
+ return _parent;
}
-LookupScope *LookupScope::instantiationOrigin() const
+QList<ClassOrNamespace *> ClassOrNamespace::usings() const
{
- if (Internal::LookupScopePrivate *i = d->_instantiationOrigin)
- return i->q;
- return 0;
+ const_cast<ClassOrNamespace *>(this)->flush();
+ return _usings;
}
-LookupScope *LookupScope::parent() const
+QList<Enum *> ClassOrNamespace::unscopedEnums() const
{
- if (Internal::LookupScopePrivate *p = d->_parent)
- return p->q;
- return 0;
+ const_cast<ClassOrNamespace *>(this)->flush();
+ return _enums;
}
-QList<LookupScope *> LookupScope::usings() const
+QList<Symbol *> ClassOrNamespace::symbols() const
{
- const_cast<LookupScope *>(this)->d->flush();
- return d->_usings;
+ const_cast<ClassOrNamespace *>(this)->flush();
+ return _symbols;
}
-QList<Enum *> LookupScope::unscopedEnums() const
+ClassOrNamespace *ClassOrNamespace::globalNamespace() const
{
- const_cast<LookupScope *>(this)->d->flush();
- return d->_enums;
-}
-
-QList<Symbol *> LookupScope::symbols() const
-{
- const_cast<LookupScope *>(this)->d->flush();
- return d->_symbols;
-}
-
-QList<LookupItem> LookupScope::find(const Name *name)
-{
- return d->lookup_helper(name, false);
-}
-
-QList<LookupItem> LookupScope::lookup(const Name *name)
-{
- return d->lookup_helper(name, true);
-}
-
-namespace Internal {
-
-LookupScope *LookupScopePrivate::globalNamespace() const
-{
- const LookupScopePrivate *e = this;
+ ClassOrNamespace *e = const_cast<ClassOrNamespace *>(this);
do {
if (! e->_parent)
@@ -713,20 +599,30 @@ LookupScope *LookupScopePrivate::globalNamespace() const
e = e->_parent;
} while (e);
- return e ? e->q : 0;
+ return e;
}
-QList<LookupItem> LookupScopePrivate::lookup_helper(const Name *name, bool searchInEnclosingScope)
+QList<LookupItem> ClassOrNamespace::find(const Name *name)
+{
+ return lookup_helper(name, false);
+}
+
+QList<LookupItem> ClassOrNamespace::lookup(const Name *name)
+{
+ return lookup_helper(name, true);
+}
+
+QList<LookupItem> ClassOrNamespace::lookup_helper(const Name *name, bool searchInEnclosingScope)
{
QList<LookupItem> result;
if (name) {
- if (const QualifiedNameId *qName = name->asQualifiedNameId()) {
- if (! qName->base()) { // e.g. ::std::string
- result = globalNamespace()->find(qName->name());
- } else if (LookupScope *binding = q->lookupType(qName->base())) {
- result = binding->find(qName->name());
+ if (const QualifiedNameId *q = name->asQualifiedNameId()) {
+ if (! q->base()) { // e.g. ::std::string
+ result = globalNamespace()->find(q->name());
+ } else if (ClassOrNamespace *binding = lookupType(q->base())) {
+ result = binding->find(q->name());
QList<const Name *> fullName;
addNames(name, &fullName);
@@ -735,10 +631,10 @@ QList<LookupItem> LookupScopePrivate::lookup_helper(const Name *name, bool searc
// a qualified name. For instance, a nested class which is forward declared
// in the class but defined outside it - we should capture both.
Symbol *match = 0;
- ProcessedSet processed;
- for (LookupScopePrivate *parentBinding = binding->d->_parent;
+ QSet<ClassOrNamespace *> processed;
+ for (ClassOrNamespace *parentBinding = binding->parent();
parentBinding && !match;
- parentBinding = parentBinding->_parent) {
+ parentBinding = parentBinding->parent()) {
if (processed.contains(parentBinding))
break;
processed.insert(parentBinding);
@@ -756,14 +652,14 @@ QList<LookupItem> LookupScopePrivate::lookup_helper(const Name *name, bool searc
return result;
}
- ProcessedSet processed;
- ProcessedSet processedOwnParents;
- LookupScopePrivate *binding = this;
+ QSet<ClassOrNamespace *> processed;
+ QSet<ClassOrNamespace *> processedOwnParents;
+ ClassOrNamespace *binding = this;
do {
if (processedOwnParents.contains(binding))
break;
processedOwnParents.insert(binding);
- lookup_helper(name, binding, &result, &processed);
+ lookup_helper(name, binding, &result, &processed, /*templateId = */ 0);
binding = binding->_parent;
} while (searchInEnclosingScope && binding);
}
@@ -771,60 +667,59 @@ QList<LookupItem> LookupScopePrivate::lookup_helper(const Name *name, bool searc
return result;
}
-void LookupScopePrivate::lookup_helper(
- const Name *name, LookupScopePrivate *binding, QList<LookupItem> *result,
- ProcessedSet *processed)
+void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding,
+ QList<LookupItem> *result,
+ QSet<ClassOrNamespace *> *processed,
+ const TemplateNameId *templateId)
{
- if (!binding || processed->contains(binding))
- return;
- processed->insert(binding);
+ if (binding && ! processed->contains(binding)) {
+ processed->insert(binding);
- binding->flush();
- const Identifier *nameId = name->identifier();
+ const Identifier *nameId = name->identifier();
- foreach (Symbol *s, binding->_symbols) {
- if (s->isFriend())
- continue;
- else if (s->isUsingNamespaceDirective())
- continue;
+ foreach (Symbol *s, binding->symbols()) {
+ if (s->isFriend())
+ continue;
+ else if (s->isUsingNamespaceDirective())
+ continue;
- if (Scope *scope = s->asScope()) {
- if (Class *klass = scope->asClass()) {
- if (const Identifier *id = klass->identifier()) {
- if (nameId && nameId->match(id)) {
- LookupItem item;
- item.setDeclaration(klass);
- item.setBinding(binding->q);
- result->append(item);
+ if (Scope *scope = s->asScope()) {
+ if (Class *klass = scope->asClass()) {
+ if (const Identifier *id = klass->identifier()) {
+ if (nameId && nameId->match(id)) {
+ LookupItem item;
+ item.setDeclaration(klass);
+ item.setBinding(binding);
+ result->append(item);
+ }
}
}
+ _factory->lookupInScope(name, scope, result, templateId, binding);
}
- _factory->lookupInScope(name, scope, result, binding->q);
}
- }
- foreach (Enum *e, binding->_enums)
- _factory->lookupInScope(name, e, result, binding->q);
+ foreach (Enum *e, binding->unscopedEnums())
+ _factory->lookupInScope(name, e, result, templateId, binding);
- foreach (LookupScope *u, binding->_usings)
- lookup_helper(name, u->d, result, processed);
+ foreach (ClassOrNamespace *u, binding->usings())
+ lookup_helper(name, u, result, processed, binding->_templateId);
- Anonymouses::const_iterator cit = binding->_anonymouses.constBegin();
- Anonymouses::const_iterator citEnd = binding->_anonymouses.constEnd();
- for (; cit != citEnd; ++cit) {
- const AnonymousNameId *anonymousNameId = cit.key();
- LookupScopePrivate *a = cit.value();
- if (!binding->_declaredOrTypedefedAnonymouses.contains(anonymousNameId))
- lookup_helper(name, a, result, processed);
+ Anonymouses::const_iterator cit = binding->_anonymouses.constBegin();
+ Anonymouses::const_iterator citEnd = binding->_anonymouses.constEnd();
+ for (; cit != citEnd; ++cit) {
+ const AnonymousNameId *anonymousNameId = cit.key();
+ ClassOrNamespace *a = cit.value();
+ if (!binding->_declaredOrTypedefedAnonymouses.contains(anonymousNameId))
+ lookup_helper(name, a, result, processed, binding->_templateId);
+ }
}
}
-}
-
void CreateBindings::lookupInScope(const Name *name, Scope *scope,
QList<LookupItem> *result,
- LookupScope *binding)
+ const TemplateNameId *templateId,
+ ClassOrNamespace *binding)
{
if (! name) {
return;
@@ -858,7 +753,7 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
if (Q_UNLIKELY(debug)) {
Overview oo;
qDebug() << "Found" << id->chars() << "in"
- << (binding ? oo(binding->d->_name) : QString::fromLatin1("<null>"));
+ << (binding ? oo(binding->_name) : QString::fromLatin1("<null>"));
}
LookupItem item;
@@ -866,7 +761,7 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
item.setBinding(binding);
if (s->asNamespaceAlias() && binding) {
- LookupScope *targetNamespaceBinding = binding->lookupType(name);
+ ClassOrNamespace *targetNamespaceBinding = binding->lookupType(name);
//there can be many namespace definitions
if (targetNamespaceBinding && targetNamespaceBinding->symbols().size() > 0) {
Symbol *resolvedSymbol = targetNamespaceBinding->symbols().first();
@@ -874,19 +769,19 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
}
}
+ if (templateId && (s->isDeclaration() || s->isFunction())) {
+ FullySpecifiedType ty = DeprecatedGenTemplateInstance::instantiate(templateId, s, control());
+ item.setType(ty); // override the type.
+ }
+
// instantiate function template
- if (const TemplateNameId *instantiation = name->asTemplateNameId()) {
- if (Template *specialization = s->asTemplate()) {
- if (Symbol *decl = specialization->declaration()) {
- if (decl->isFunction() || decl->isDeclaration()) {
- Clone cloner(_control.data());
- Subst subst(_control.data());
- initializeSubst(cloner, subst, binding, specialization, instantiation);
- Symbol *instantiatedFunctionTemplate = cloner.symbol(decl, &subst);
- item.setType(instantiatedFunctionTemplate->type()); // override the type
- }
- }
- }
+ if (name->isTemplateNameId() && s->isTemplate() && s->asTemplate()->declaration()
+ && s->asTemplate()->declaration()->isFunction()) {
+ const TemplateNameId *instantiation = name->asTemplateNameId();
+ Template *specialization = s->asTemplate();
+ Symbol *instantiatedFunctionTemplate = instantiateTemplateFunction(instantiation,
+ specialization);
+ item.setType(instantiatedFunctionTemplate->type()); // override the type.
}
result->append(item);
@@ -894,50 +789,51 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope,
}
}
-LookupScope *LookupScope::lookupType(const Name *name)
+ClassOrNamespace *ClassOrNamespace::lookupType(const Name *name)
{
if (! name)
return 0;
- ProcessedSet processed;
- return d->lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ true, d);
+ QSet<ClassOrNamespace *> processed;
+ return lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ true, this);
}
-LookupScope *LookupScope::lookupType(const Name *name, Block *block)
+ClassOrNamespace *ClassOrNamespace::lookupType(const Name *name, Block *block)
{
- d->flush();
+ flush();
- QHash<Block *, LookupScope *>::const_iterator citBlock = d->_blocks.constFind(block);
- if (citBlock != d->_blocks.constEnd()) {
- LookupScope *nestedBlock = citBlock.value();
- ProcessedSet processed;
- if (LookupScope *foundInNestedBlock
- = nestedBlock->d->lookupType_helper(name,
- &processed,
- /*searchInEnclosingScope = */ true,
- nestedBlock->d)) {
+ QHash<Block *, ClassOrNamespace *>::const_iterator citBlock = _blocks.constFind(block);
+ if (citBlock != _blocks.constEnd()) {
+ ClassOrNamespace *nestedBlock = citBlock.value();
+ QSet<ClassOrNamespace *> processed;
+ if (ClassOrNamespace *foundInNestedBlock
+ = nestedBlock->lookupType_helper(name,
+ &processed,
+ /*searchInEnclosingScope = */ true,
+ this)) {
return foundInNestedBlock;
}
}
- for (citBlock = d->_blocks.constBegin(); citBlock != d->_blocks.constEnd(); ++citBlock) {
- if (LookupScope *foundNestedBlock = citBlock.value()->lookupType(name, block))
+ for (citBlock = _blocks.constBegin(); citBlock != _blocks.constEnd(); ++citBlock) {
+ if (ClassOrNamespace *foundNestedBlock = citBlock.value()->lookupType(name, block))
return foundNestedBlock;
}
return 0;
}
-LookupScope *LookupScope::findType(const Name *name)
+ClassOrNamespace *ClassOrNamespace::findType(const Name *name)
{
- ProcessedSet processed;
- return d->lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ true, d);
+ QSet<ClassOrNamespace *> processed;
+ return lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ false, this);
}
-LookupScope *Internal::LookupScopePrivate::findBlock_helper(
- Block *block, ProcessedSet *processed, bool searchInEnclosingScope)
+ClassOrNamespace *ClassOrNamespace::findBlock_helper(Block *block,
+ QSet<ClassOrNamespace *> *processed,
+ bool searchInEnclosingScope)
{
- for (LookupScopePrivate *binding = this; binding; binding = binding->_parent) {
+ for (ClassOrNamespace *binding = this; binding; binding = binding->_parent) {
if (processed->contains(binding))
break;
processed->insert(binding);
@@ -948,8 +844,8 @@ LookupScope *Internal::LookupScopePrivate::findBlock_helper(
return citBlock.value();
for (citBlock = binding->_blocks.begin(); citBlock != end; ++citBlock) {
- if (LookupScope *foundNestedBlock =
- citBlock.value()->d->findBlock_helper(block, processed, false)) {
+ if (ClassOrNamespace *foundNestedBlock =
+ citBlock.value()->findBlock_helper(block, processed, false)) {
return foundNestedBlock;
}
}
@@ -959,20 +855,19 @@ LookupScope *Internal::LookupScopePrivate::findBlock_helper(
return 0;
}
-LookupScope *LookupScope::findBlock(Block *block)
+ClassOrNamespace *ClassOrNamespace::findBlock(Block *block)
{
- ProcessedSet processed;
- return d->findBlock_helper(block, &processed, true);
+ QSet<ClassOrNamespace *> processed;
+ return findBlock_helper(block, &processed, true);
}
-Symbol *Internal::LookupScopePrivate::lookupInScope(const QList<const Name *> &fullName)
+Symbol *ClassOrNamespace::lookupInScope(const QList<const Name *> &fullName)
{
if (!_scopeLookupCache) {
_scopeLookupCache = new QHash<Internal::FullyQualifiedName, Symbol *>;
- flush();
- for (int j = 0; j < _symbols.size(); ++j) {
- if (Scope *scope = _symbols.at(j)->asScope()) {
+ for (int j = 0; j < symbols().size(); ++j) {
+ if (Scope *scope = symbols().at(j)->asScope()) {
for (unsigned i = 0; i < scope->memberCount(); ++i) {
Symbol *s = scope->memberAt(i);
_scopeLookupCache->insert(LookupContext::fullyQualifiedName(s), s);
@@ -984,30 +879,24 @@ Symbol *Internal::LookupScopePrivate::lookupInScope(const QList<const Name *> &f
return _scopeLookupCache->value(fullName, 0);
}
-Class *LookupScope::rootClass() const
-{
- return d->_rootClass;
-}
-
-namespace Internal {
-
-LookupScope *LookupScopePrivate::lookupType_helper(
- const Name *name, ProcessedSet *processed,
- bool searchInEnclosingScope, LookupScopePrivate *origin)
+ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
+ QSet<ClassOrNamespace *> *processed,
+ bool searchInEnclosingScope,
+ ClassOrNamespace *origin)
{
if (Q_UNLIKELY(debug)) {
Overview oo;
qDebug() << "Looking up" << oo(name) << "in" << oo(_name);
}
- if (const QualifiedNameId *qName = name->asQualifiedNameId()) {
+ if (const QualifiedNameId *q = name->asQualifiedNameId()) {
- ProcessedSet innerProcessed;
- if (! qName->base())
- return globalNamespace()->d->lookupType_helper(qName->name(), &innerProcessed, true, origin);
+ QSet<ClassOrNamespace *> innerProcessed;
+ if (! q->base())
+ return globalNamespace()->lookupType_helper(q->name(), &innerProcessed, true, origin);
- if (LookupScope *binding = lookupType_helper(qName->base(), processed, true, origin))
- return binding->d->lookupType_helper(qName->name(), &innerProcessed, false, origin);
+ if (ClassOrNamespace *binding = lookupType_helper(q->base(), processed, true, origin))
+ return binding->lookupType_helper(q->name(), &innerProcessed, false, origin);
return 0;
@@ -1017,32 +906,41 @@ LookupScope *LookupScopePrivate::lookupType_helper(
if (name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) {
flush();
- foreach (Symbol *s, _symbols) {
+ foreach (Symbol *s, symbols()) {
if (Class *klass = s->asClass()) {
if (klass->identifier() && klass->identifier()->match(name->identifier()))
- return q;
+ return this;
}
}
- foreach (Enum *e, _enums) {
+ foreach (Enum *e, unscopedEnums()) {
if (e->identifier() && e->identifier()->match(name->identifier()))
- return q;
+ return this;
}
- if (LookupScopePrivate *e = nestedType(name, origin))
- return e->q;
+ if (ClassOrNamespace *e = nestedType(name, origin))
+ return e;
- foreach (LookupScope *u, _usings) {
- if (LookupScope *r = u->d->lookupType_helper(
- name, processed, /*searchInEnclosingScope =*/ false, origin)) {
- return r;
+ if (_templateId) {
+ if (_usings.size() == 1) {
+ ClassOrNamespace *delegate = _usings.first();
+
+ if (ClassOrNamespace *r = delegate->lookupType_helper(name,
+ processed,
+ /*searchInEnclosingScope = */ true,
+ origin))
+ return r;
+ } else if (Q_UNLIKELY(debug)) {
+ qWarning() << "expected one using declaration. Number of using declarations is:"
+ << _usings.size();
}
}
- if (_instantiationOrigin) {
- if (LookupScope *o = _instantiationOrigin->lookupType_helper(
- name, processed, /*searchInEnclosingScope =*/ true, origin)) {
- return o;
- }
+ foreach (ClassOrNamespace *u, usings()) {
+ if (ClassOrNamespace *r = u->lookupType_helper(name,
+ processed,
+ /*searchInEnclosingScope =*/ false,
+ origin))
+ return r;
}
}
@@ -1053,10 +951,10 @@ LookupScope *LookupScopePrivate::lookupType_helper(
return 0;
}
-static LookupScopePrivate *findSpecializationWithMatchingTemplateArgument(
- const Name *argumentName, LookupScopePrivate *reference)
+static ClassOrNamespace *findSpecializationWithMatchingTemplateArgument(const Name *argumentName,
+ ClassOrNamespace *reference)
{
- foreach (Symbol *s, reference->_symbols) {
+ foreach (Symbol *s, reference->symbols()) {
if (Class *clazz = s->asClass()) {
if (Template *templateSpecialization = clazz->enclosingTemplate()) {
const unsigned argumentCountOfSpecialization
@@ -1076,127 +974,95 @@ static LookupScopePrivate *findSpecializationWithMatchingTemplateArgument(
return 0;
}
-LookupScopePrivate *LookupScopePrivate::findSpecialization(
- const TemplateNameId *templId,
- const TemplateNameIdTable &specializations,
- LookupScopePrivate *origin)
+ClassOrNamespace *ClassOrNamespace::findSpecialization(const TemplateNameId *templId,
+ const TemplateNameIdTable &specializations)
{
+ // we go through all specialization and try to find that one with template argument as pointer
for (TemplateNameIdTable::const_iterator cit = specializations.begin();
cit != specializations.end(); ++cit) {
const TemplateNameId *specializationNameId = cit->first;
const unsigned specializationTemplateArgumentCount
= specializationNameId->templateArgumentCount();
- const unsigned initializationTemplateArgumentCount = templId->templateArgumentCount();
+ const unsigned initializationTemplateArgumentCount
+ = templId->templateArgumentCount();
// for now it works only when we have the same number of arguments in specialization
// and initialization(in future it should be more clever)
- if (specializationTemplateArgumentCount != initializationTemplateArgumentCount)
- continue;
- for (unsigned i = 0; i < initializationTemplateArgumentCount; ++i) {
- const FullySpecifiedType &specializationTemplateArgument
- = specializationNameId->templateArgumentAt(i);
- FullySpecifiedType initializationTemplateArgument = templId->templateArgumentAt(i);
- TypeResolver typeResolver(*_factory);
- Scope *scope = 0;
- typeResolver.resolve(&initializationTemplateArgument, &scope, origin ? origin->q : 0);
- PointerType *specPointer = specializationTemplateArgument.type()->asPointerType();
- // specialization and initialization argument have to be a pointer
- // additionally type of pointer argument of specialization has to be namedType
- if (specPointer && initializationTemplateArgument.type()->isPointerType()
- && specPointer->elementType().type()->isNamedType()) {
- return cit->second;
- }
+ if (specializationTemplateArgumentCount == initializationTemplateArgumentCount) {
+ for (unsigned i = 0; i < initializationTemplateArgumentCount; ++i) {
+ const FullySpecifiedType &specializationTemplateArgument
+ = specializationNameId->templateArgumentAt(i);
+ const FullySpecifiedType &initializationTemplateArgument
+ = templId->templateArgumentAt(i);
+ PointerType *specPointer
+ = specializationTemplateArgument.type()->asPointerType();
+ // specialization and initialization argument have to be a pointer
+ // additionally type of pointer argument of specialization has to be namedType
+ if (specPointer && initializationTemplateArgument.type()->isPointerType()
+ && specPointer->elementType().type()->isNamedType()) {
+ return cit->second;
+ }
- ArrayType *specArray = specializationTemplateArgument.type()->asArrayType();
- if (specArray && initializationTemplateArgument.type()->isArrayType()) {
- if (const NamedType *argumentNamedType
- = specArray->elementType().type()->asNamedType()) {
- if (const Name *argumentName = argumentNamedType->name()) {
- if (LookupScopePrivate *reference
- = findSpecializationWithMatchingTemplateArgument(
- argumentName, cit->second)) {
- return reference;
+ ArrayType *specArray
+ = specializationTemplateArgument.type()->asArrayType();
+ if (specArray && initializationTemplateArgument.type()->isArrayType()) {
+ if (const NamedType *argumentNamedType
+ = specArray->elementType().type()->asNamedType()) {
+ if (const Name *argumentName = argumentNamedType->name()) {
+ if (ClassOrNamespace *reference
+ = findSpecializationWithMatchingTemplateArgument(
+ argumentName, cit->second)) {
+ return reference;
+ }
}
}
}
}
-
- if (const NamedType *specName = specializationTemplateArgument->asNamedType()) {
- if (const NamedType *initName = initializationTemplateArgument->asNamedType()) {
- if (specName->name()->identifier() == initName->name()->identifier())
- return cit->second;
- }
- }
}
}
return 0;
}
-LookupScopePrivate *LookupScopePrivate::findOrCreateNestedAnonymousType(
+ClassOrNamespace *ClassOrNamespace::findOrCreateNestedAnonymousType(
const AnonymousNameId *anonymousNameId)
{
- auto cit = _anonymouses.constFind(anonymousNameId);
+ QHash<const AnonymousNameId *, ClassOrNamespace *>::const_iterator cit
+ = _anonymouses.constFind(anonymousNameId);
if (cit != _anonymouses.constEnd()) {
return cit.value();
} else {
- LookupScopePrivate *newAnonymous = allocateChild(anonymousNameId);
+ ClassOrNamespace *newAnonymous = _factory->allocClassOrNamespace(this);
+ if (Q_UNLIKELY(debug))
+ newAnonymous->_name = anonymousNameId;
_anonymouses[anonymousNameId] = newAnonymous;
return newAnonymous;
}
}
-LookupScopePrivate *LookupScopePrivate::findNestedType(const Name *name, LookupScopePrivate *origin)
-{
- TypedefTable::const_iterator typedefit = _typedefs.find(name);
- if (typedefit != _typedefs.end()) {
- Declaration *decl = typedefit->second;
- if (_alreadyConsideredTypedefs.contains(decl))
- return 0;
- LookupScopePrivate *binding = 0;
- _alreadyConsideredTypedefs.insert(decl);
- if (const NamedType *namedTy = decl->type()->asNamedType()) {
- if (LookupScope *e = q->lookupType(namedTy->name())) {
- binding = e->d;
- } else if (origin) {
- if (LookupScope *e = origin->q->lookupType(namedTy->name()))
- binding = e->d;
- }
- }
- _alreadyConsideredTypedefs.remove(decl);
- if (binding)
- return binding;
- }
-
- auto it = _nestedScopes.find(name);
- if (it != _nestedScopes.end())
- return it->second;
-
- return 0;
-}
-
-LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScopePrivate *origin)
+ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespace *origin)
{
Q_ASSERT(name != 0);
Q_ASSERT(name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId());
- const_cast<LookupScopePrivate *>(this)->flush();
+ const_cast<ClassOrNamespace *>(this)->flush();
if (const AnonymousNameId *anonymousNameId = name->asAnonymousNameId())
return findOrCreateNestedAnonymousType(anonymousNameId);
- LookupScopePrivate *reference = findNestedType(name, origin);
- if (!reference)
+ Table::const_iterator it = _classOrNamespaces.find(name);
+ if (it == _classOrNamespaces.end())
return 0;
- reference->flush();
- LookupScopePrivate *baseTemplateClassReference = reference;
+
+ ClassOrNamespace *reference = it->second;
+ ClassOrNamespace *baseTemplateClassReference = reference;
const TemplateNameId *templId = name->asTemplateNameId();
if (templId) {
- // for "using" we should use the real one LookupScope(it should be the first
+ // for "using" we should use the real one ClassOrNamespace(it should be the first
// one item from usings list)
// we indicate that it is a 'using' by checking number of symbols(it should be 0)
- if (reference->_symbols.count() == 0 && reference->_usings.count() != 0)
- reference = reference->_usings[0]->d;
+ if (reference->symbols().count() == 0 && reference->usings().count() != 0)
+ reference = reference->_usings[0];
// if it is a TemplateNameId it could be a specialization(full or partial) or
// instantiation of one of the specialization(reference->_specialization) or
@@ -1209,12 +1075,15 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope
if (cit != reference->_specializations.end()) {
return cit->second;
} else {
- LookupScopePrivate *newSpecialization = reference->allocateChild(templId);
+ ClassOrNamespace *newSpecialization = _factory->allocClassOrNamespace(reference);
+ if (Q_UNLIKELY(debug))
+ newSpecialization->_name = templId;
reference->_specializations[templId] = newSpecialization;
return newSpecialization;
}
} else {
- auto citInstantiation = reference->_instantiations.constFind(templId);
+ QMap<const TemplateNameId *, ClassOrNamespace *>::const_iterator citInstantiation
+ = reference->_instantiations.constFind(templId);
if (citInstantiation != reference->_instantiations.constEnd())
return citInstantiation.value();
TemplateNameId *nonConstTemplId = const_cast<TemplateNameId *>(templId);
@@ -1227,14 +1096,11 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope
// we found full specialization
reference = cit->second;
} else {
- if (LookupScopePrivate *specialization =
- findSpecialization(templId, specializations, origin)) {
- reference = specialization;
- if (Q_UNLIKELY(debug)) {
- Overview oo;
- qDebug() << "picked specialization" << oo(specialization->_name);
- }
- }
+ ClassOrNamespace *specializationWithPointer
+ = findSpecialization(templId, specializations);
+ if (specializationWithPointer)
+ reference = specializationWithPointer;
+ // TODO: find the best specialization(probably partial) for this instantiation
}
// let's instantiation be instantiation
nonConstTemplId->setIsSpecialization(false);
@@ -1247,7 +1113,7 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope
Class *referenceClass = 0;
QList<const Name *> allBases;
- foreach (Symbol *s, reference->_symbols) {
+ foreach (Symbol *s, reference->symbols()) {
if (Class *clazz = s->asClass()) {
for (unsigned i = 0; i < clazz->baseClassCount(); ++i) {
BaseClass *baseClass = clazz->baseClassAt(i);
@@ -1271,106 +1137,163 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope
if (!name->isTemplateNameId())
_alreadyConsideredClasses.insert(referenceClass);
- QSet<LookupScope *> knownUsings = reference->_usings.toSet();
+ QSet<ClassOrNamespace *> knownUsings = reference->usings().toSet();
// If we are dealling with a template type, more work is required, since we need to
// construct all instantiation data.
if (templId) {
- if (!_factory->expandTemplates())
- return reference;
- Template *templateSpecialization = referenceClass->enclosingTemplate();
- if (!templateSpecialization)
- return reference;
-
- // It gets a bit complicated if the reference is actually a class template because we
- // now must worry about dependent names in base classes.
_alreadyConsideredTemplates.insert(templId);
- const unsigned argumentCountOfInitialization = templId->templateArgumentCount();
- const unsigned argumentCountOfSpecialization
- = templateSpecialization->templateParameterCount();
+ ClassOrNamespace *instantiation = _factory->allocClassOrNamespace(baseTemplateClassReference);
+ if (Q_UNLIKELY(debug))
+ instantiation->_name = templId;
+ instantiation->_templateId = templId;
- Clone cloner(_control.data());
- Subst subst(_control.data());
- _factory->initializeSubst(cloner, subst, origin ? origin->q : 0,
- templateSpecialization, templId);
-
- LookupScopePrivate *instantiation = baseTemplateClassReference->allocateChild(templId);
+ while (!origin->_symbols.isEmpty() && origin->_symbols[0]->isBlock())
+ origin = origin->parent();
instantiation->_instantiationOrigin = origin;
- instantiation->_rootClass = reference->_rootClass;
- Instantiator instantiator(cloner, subst);
- instantiator.doInstantiate(reference, instantiation);
-
- QHash<const Name*, unsigned> templParams;
- for (unsigned i = 0; i < argumentCountOfSpecialization; ++i)
- templParams.insert(templateSpecialization->templateParameterAt(i)->name(), i);
-
- foreach (const Name *baseName, allBases) {
- LookupScope *baseBinding = 0;
-
- if (const Identifier *nameId = baseName->asNameId()) {
- // This is the simple case in which a template parameter is itself a base.
- // Ex.: template <class T> class A : public T {};
- if (templParams.contains(nameId)) {
- const unsigned parameterIndex = templParams.value(nameId);
- if (parameterIndex < argumentCountOfInitialization) {
- const FullySpecifiedType &fullType =
- templId->templateArgumentAt(parameterIndex);
- if (fullType.isValid()) {
- if (NamedType *namedType = fullType.type()->asNamedType())
- baseBinding = q->lookupType(namedType->name());
- }
- }
- }
- if (!baseBinding && subst.contains(baseName)) {
- const FullySpecifiedType &fullType = subst[baseName];
- if (fullType.isValid()) {
- if (NamedType *namedType = fullType.type()->asNamedType())
- baseBinding = q->lookupType(namedType->name());
- }
- }
- } else {
- SubstitutionMap map;
+ // The instantiation should have all symbols, enums, and usings from the reference.
+ instantiation->_enums.append(reference->unscopedEnums());
+ instantiation->_usings.append(reference->usings());
+
+ instantiation->_rootClass = reference->rootClass();
+
+ // It gets a bit complicated if the reference is actually a class template because we
+ // now must worry about dependent names in base classes.
+ if (Template *templateSpecialization = referenceClass->enclosingTemplate()) {
+ const unsigned argumentCountOfInitialization = templId->templateArgumentCount();
+ const unsigned argumentCountOfSpecialization
+ = templateSpecialization->templateParameterCount();
+
+ Subst subst(_control.data());
+ if (_factory->expandTemplates()) {
+ const TemplateNameId *templSpecId
+ = templateSpecialization->name()->asTemplateNameId();
+ const unsigned templSpecArgumentCount = templSpecId ?
+ templSpecId->templateArgumentCount() : 0;
+ Clone cloner(_control.data());
for (unsigned i = 0; i < argumentCountOfSpecialization; ++i) {
- const Name *name = templateSpecialization->templateParameterAt(i)->name();
+ const TypenameArgument *tParam
+ = templateSpecialization->templateParameterAt(i)->asTypenameArgument();
+ if (!tParam)
+ continue;
+ const Name *name = tParam->name();
+ if (!name)
+ continue;
+
FullySpecifiedType ty = (i < argumentCountOfInitialization) ?
templId->templateArgumentAt(i):
- templateSpecialization->templateParameterAt(i)->type();
+ cloner.type(tParam->type(), &subst);
+
+ if (i < templSpecArgumentCount
+ && templSpecId->templateArgumentAt(i)->isPointerType()) {
+ if (PointerType *pointerType = ty->asPointerType())
+ ty = pointerType->elementType();
+ }
- map.bind(name, ty);
+ subst.bind(cloner.name(name, &subst), ty);
}
- SubstitutionEnvironment env;
- env.enter(&map);
- baseName = rewriteName(baseName, &env, _control.data());
+ foreach (Symbol *s, reference->symbols()) {
+ Symbol *clone = cloner.symbol(s, &subst);
+ clone->setEnclosingScope(s->enclosingScope());
+ instantiation->_symbols.append(clone);
+ if (Q_UNLIKELY(debug)) {
+ Overview oo;
+ oo.showFunctionSignatures = true;
+ oo.showReturnTypes = true;
+ oo.showTemplateParameters = true;
+ qDebug() << "cloned" << oo(clone->type());
+ if (Class *klass = clone->asClass()) {
+ const unsigned klassMemberCount = klass->memberCount();
+ for (unsigned i = 0; i < klassMemberCount; ++i){
+ Symbol *klassMemberAsSymbol = klass->memberAt(i);
+ if (klassMemberAsSymbol->isTypedef()) {
+ if (Declaration *declaration = klassMemberAsSymbol->asDeclaration())
+ qDebug() << "Member: " << oo(declaration->type(), declaration->name());
+ }
+ }
+ }
+ }
+ }
+ instantiateNestedClasses(reference, cloner, subst, instantiation);
+ } else {
+ instantiation->_symbols.append(reference->symbols());
+ }
- if (const TemplateNameId *baseTemplId = baseName->asTemplateNameId()) {
- // Another template that uses the dependent name.
- // Ex.: template <class T> class A : public B<T> {};
- if (baseTemplId->identifier() != templId->identifier()) {
- if (LookupScopePrivate *nested = nestedType(baseName, origin))
- baseBinding = nested->q;
+ QHash<const Name*, unsigned> templParams;
+ for (unsigned i = 0; i < argumentCountOfSpecialization; ++i)
+ templParams.insert(templateSpecialization->templateParameterAt(i)->name(), i);
+
+ foreach (const Name *baseName, allBases) {
+ ClassOrNamespace *baseBinding = 0;
+
+ if (const Identifier *nameId = baseName->asNameId()) {
+ // This is the simple case in which a template parameter is itself a base.
+ // Ex.: template <class T> class A : public T {};
+ if (templParams.contains(nameId)) {
+ const unsigned parameterIndex = templParams.value(nameId);
+ if (parameterIndex < argumentCountOfInitialization) {
+ const FullySpecifiedType &fullType =
+ templId->templateArgumentAt(parameterIndex);
+ if (fullType.isValid()) {
+ if (NamedType *namedType = fullType.type()->asNamedType())
+ baseBinding = lookupType(namedType->name());
+ }
+ }
}
- } else if (const QualifiedNameId *qBaseName = baseName->asQualifiedNameId()) {
- // Qualified names in general.
- // Ex.: template <class T> class A : public B<T>::Type {};
- LookupScope *binding = q;
- if (const Name *qualification = qBaseName->base()) {
- const TemplateNameId *baseTemplName = qualification->asTemplateNameId();
- if (!baseTemplName || !compareName(baseTemplName, templateSpecialization->name()))
- binding = q->lookupType(qualification);
+ if (!baseBinding && subst.contains(baseName)) {
+ const FullySpecifiedType &fullType = subst[baseName];
+ if (fullType.isValid()) {
+ if (NamedType *namedType = fullType.type()->asNamedType())
+ baseBinding = lookupType(namedType->name());
+ }
}
- baseName = qBaseName->name();
+ } else {
+ SubstitutionMap map;
+ for (unsigned i = 0; i < argumentCountOfSpecialization; ++i) {
+ const Name *name = templateSpecialization->templateParameterAt(i)->name();
+ FullySpecifiedType ty = (i < argumentCountOfInitialization) ?
+ templId->templateArgumentAt(i):
+ templateSpecialization->templateParameterAt(i)->type();
+
+ map.bind(name, ty);
+ }
+ SubstitutionEnvironment env;
+ env.enter(&map);
+
+ baseName = rewriteName(baseName, &env, _control.data());
+
+ if (const TemplateNameId *baseTemplId = baseName->asTemplateNameId()) {
+ // Another template that uses the dependent name.
+ // Ex.: template <class T> class A : public B<T> {};
+ if (baseTemplId->identifier() != templId->identifier())
+ baseBinding = nestedType(baseName, origin);
+ } else if (const QualifiedNameId *qBaseName = baseName->asQualifiedNameId()) {
+ // Qualified names in general.
+ // Ex.: template <class T> class A : public B<T>::Type {};
+ ClassOrNamespace *binding = this;
+ if (const Name *qualification = qBaseName->base()) {
+ const TemplateNameId *baseTemplName = qualification->asTemplateNameId();
+ if (!baseTemplName || !compareName(baseTemplName, templateSpecialization->name()))
+ binding = lookupType(qualification);
+ }
+ baseName = qBaseName->name();
- if (binding)
- baseBinding = binding->lookupType(baseName);
+ if (binding)
+ baseBinding = binding->lookupType(baseName);
+ }
}
- }
- if (baseBinding && !knownUsings.contains(baseBinding))
- instantiation->addUsing(baseBinding);
+ if (baseBinding && !knownUsings.contains(baseBinding))
+ instantiation->addUsing(baseBinding);
+ }
+ } else {
+ instantiation->_classOrNamespaces = reference->_classOrNamespaces;
+ instantiation->_symbols.append(reference->symbols());
}
+
_alreadyConsideredTemplates.clear(templId);
baseTemplateClassReference->_instantiations[templId] = instantiation;
return instantiation;
@@ -1382,14 +1305,14 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope
// Find the missing bases for regular (non-template) types.
// Ex.: class A : public B<Some>::Type {};
foreach (const Name *baseName, allBases) {
- LookupScope *binding = q;
+ ClassOrNamespace *binding = this;
if (const QualifiedNameId *qBaseName = baseName->asQualifiedNameId()) {
if (const Name *qualification = qBaseName->base())
- binding = q->lookupType(qualification);
+ binding = lookupType(qualification);
else if (binding->parent() != 0)
//if this is global identifier we take global namespace
//Ex: class A{}; namespace NS { class A: public ::A{}; }
- binding = binding->d->globalNamespace();
+ binding = binding->globalNamespace();
else
//if we are in the global scope
continue;
@@ -1397,7 +1320,7 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope
}
if (binding) {
- LookupScope * baseBinding = binding->lookupType(baseName);
+ ClassOrNamespace * baseBinding = binding->lookupType(baseName);
if (baseBinding && !knownUsings.contains(baseBinding))
reference->addUsing(baseBinding);
}
@@ -1407,152 +1330,176 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope
return reference;
}
-LookupScopePrivate *Instantiator::instantiate(LookupScopePrivate *lookupScope,
- LookupScopePrivate *origin)
+
+void ClassOrNamespace::instantiateNestedClasses(ClassOrNamespace *enclosingTemplateClass,
+ Clone &cloner,
+ Subst &subst,
+ ClassOrNamespace *enclosingTemplateClassInstantiation)
{
- lookupScope->flush();
- LookupScopePrivate *instantiation = lookupScope->allocateChild(lookupScope->_name);
- instantiation->_instantiationOrigin = origin;
- doInstantiate(lookupScope, instantiation);
- return instantiation;
+ NestedClassInstantiator nestedClassInstantiator(_factory, cloner, subst);
+ nestedClassInstantiator.instantiate(enclosingTemplateClass, enclosingTemplateClassInstantiation);
}
-void Instantiator::doInstantiate(LookupScopePrivate *lookupScope, LookupScopePrivate *instantiation)
+void ClassOrNamespace::NestedClassInstantiator::instantiate(ClassOrNamespace *enclosingTemplateClass,
+ ClassOrNamespace *enclosingTemplateClassInstantiation)
{
- if (_alreadyConsideredInstantiations.contains(lookupScope))
+ if (_alreadyConsideredNestedClassInstantiations.contains(enclosingTemplateClass))
return;
- _alreadyConsideredInstantiations.insert(lookupScope);
- // The instantiation should have all symbols, enums, and usings from the reference.
- if (instantiation != lookupScope) {
- instantiation->_enums = lookupScope->_enums;
- auto typedefend = lookupScope->_typedefs.end();
- for (auto typedefit = lookupScope->_typedefs.begin();
- typedefit != typedefend;
- ++typedefit) {
- instantiation->_typedefs[typedefit->first] =
- _cloner.symbol(typedefit->second, &_subst)->asDeclaration();
- }
- foreach (LookupScope *usingLookupScope, lookupScope->_usings)
- instantiation->_usings.append(instantiate(usingLookupScope->d, instantiation)->q);
- foreach (Symbol *s, lookupScope->_symbols) {
- Symbol *clone = _cloner.symbol(s, &_subst);
- if (!clone->enclosingScope()) // Not from the cache but just cloned.
- clone->setEnclosingScope(s->enclosingScope());
- instantiation->_symbols.append(clone);
- if (s == instantiation->_rootClass) {
- clone->setName(instantiation->_name);
- instantiation->_rootClass = clone->asClass();
+ _alreadyConsideredNestedClassInstantiations.insert(enclosingTemplateClass);
+ ClassOrNamespace::Table::const_iterator cit = enclosingTemplateClass->_classOrNamespaces.begin();
+ for (; cit != enclosingTemplateClass->_classOrNamespaces.end(); ++cit) {
+ const Name *nestedName = cit->first;
+ ClassOrNamespace *nestedClassOrNamespace = cit->second;
+ ClassOrNamespace *nestedClassOrNamespaceInstantiation = nestedClassOrNamespace;
+
+ if (isInstantiateNestedClassNeeded(nestedClassOrNamespace->_symbols)) {
+ nestedClassOrNamespaceInstantiation = _factory->allocClassOrNamespace(nestedClassOrNamespace);
+ nestedClassOrNamespaceInstantiation->_enums.append(nestedClassOrNamespace->unscopedEnums());
+ nestedClassOrNamespaceInstantiation->_usings.append(nestedClassOrNamespace->usings());
+ nestedClassOrNamespaceInstantiation->_instantiationOrigin = nestedClassOrNamespace;
+
+ foreach (Symbol *s, nestedClassOrNamespace->_symbols) {
+ Symbol *clone = _cloner.symbol(s, &_subst);
+ if (!clone->enclosingScope()) // Not from the cache but just cloned.
+ clone->setEnclosingScope(s->enclosingScope());
+ nestedClassOrNamespaceInstantiation->_symbols.append(clone);
}
- if (Q_UNLIKELY(debug)) {
- Overview oo;
- oo.showFunctionSignatures = true;
- oo.showReturnTypes = true;
- oo.showTemplateParameters = true;
- qDebug() << "cloned" << oo(clone->type());
- if (Class *klass = clone->asClass()) {
- const unsigned klassMemberCount = klass->memberCount();
- for (unsigned i = 0; i < klassMemberCount; ++i){
- Symbol *klassMemberAsSymbol = klass->memberAt(i);
- if (klassMemberAsSymbol->isTypedef()) {
- if (Declaration *declaration = klassMemberAsSymbol->asDeclaration())
- qDebug() << "Member: " << oo(declaration->type(), declaration->name());
- }
- }
+ }
+
+ if (isNestedInstantiationEnclosingTemplate(nestedClassOrNamespaceInstantiation,
+ enclosingTemplateClass)) {
+ nestedClassOrNamespaceInstantiation->_parent = enclosingTemplateClassInstantiation;
+ }
+ instantiate(nestedClassOrNamespace, nestedClassOrNamespaceInstantiation);
+
+ enclosingTemplateClassInstantiation->_classOrNamespaces[nestedName] =
+ nestedClassOrNamespaceInstantiation;
+ }
+ _alreadyConsideredNestedClassInstantiations.remove(enclosingTemplateClass);
+}
+
+bool ClassOrNamespace::NestedClassInstantiator::isInstantiateNestedClassNeeded(const QList<Symbol *> &symbols) const
+{
+ foreach (Symbol *s, symbols) {
+ if (Class *klass = s->asClass()) {
+ int memberCount = klass->memberCount();
+ for (int i = 0; i < memberCount; ++i) {
+ Symbol *memberAsSymbol = klass->memberAt(i);
+ if (Declaration *declaration = memberAsSymbol->asDeclaration()) {
+ if (containsTemplateType(declaration))
+ return true;
+ } else if (Function *function = memberAsSymbol->asFunction()) {
+ if (containsTemplateType(function))
+ return true;
}
}
}
}
- auto cit = lookupScope->_nestedScopes.begin();
- for (; cit != lookupScope->_nestedScopes.end(); ++cit) {
- const Name *nestedName = cit->first;
- LookupScopePrivate *nestedLookupScope = cit->second;
- LookupScopePrivate *nestedInstantiation = instantiate(nestedLookupScope, instantiation);
- nestedInstantiation->_parent = instantiation;
- instantiation->_nestedScopes[nestedName] = nestedInstantiation;
- }
- _alreadyConsideredInstantiations.remove(lookupScope);
+
+ return false;
+}
+
+bool ClassOrNamespace::NestedClassInstantiator::containsTemplateType(Declaration *declaration) const
+{
+ Type *memberType = declaration->type().type();
+ NamedType *namedType = findNamedType(memberType);
+ return namedType && _subst.contains(namedType->name());
+}
+
+bool ClassOrNamespace::NestedClassInstantiator::containsTemplateType(Function *function) const
+{
+ Type *returnType = function->returnType().type();
+ NamedType *namedType = findNamedType(returnType);
+ return namedType && _subst.contains(namedType->name());
+ //TODO: in future we will need also check function arguments, for now returned value is enough
}
-void LookupScopePrivate::flush()
+NamedType *ClassOrNamespace::NestedClassInstantiator::findNamedType(Type *memberType) const
+{
+ if (NamedType *namedType = memberType->asNamedType())
+ return namedType;
+ else if (PointerType *pointerType = memberType->asPointerType())
+ return findNamedType(pointerType->elementType().type());
+ else if (ReferenceType *referenceType = memberType->asReferenceType())
+ return findNamedType(referenceType->elementType().type());
+
+ return 0;
+}
+
+void ClassOrNamespace::flush()
{
if (! _todo.isEmpty()) {
const QList<Symbol *> todo = _todo;
_todo.clear();
foreach (Symbol *member, todo)
- _factory->process(member, q);
+ _factory->process(member, this);
}
}
-void LookupScopePrivate::addSymbol(Symbol *symbol)
+void ClassOrNamespace::addSymbol(Symbol *symbol)
{
_symbols.append(symbol);
}
-void LookupScopePrivate::addTodo(Symbol *symbol)
+void ClassOrNamespace::addTodo(Symbol *symbol)
{
_todo.append(symbol);
}
-void LookupScopePrivate::addUnscopedEnum(Enum *e)
+void ClassOrNamespace::addUnscopedEnum(Enum *e)
{
_enums.append(e);
}
-void LookupScopePrivate::addTypedef(const Name *identifier, Declaration *d)
-{
- _typedefs[identifier] = d;
-}
-
-void LookupScopePrivate::addUsing(LookupScope *u)
+void ClassOrNamespace::addUsing(ClassOrNamespace *u)
{
_usings.append(u);
}
-void LookupScopePrivate::addNestedType(const Name *alias, LookupScope *e)
+void ClassOrNamespace::addNestedType(const Name *alias, ClassOrNamespace *e)
{
- _nestedScopes[alias] = e->d;
+ _classOrNamespaces[alias] = e;
}
-LookupScope *LookupScopePrivate::findOrCreateType(
- const Name *name, LookupScopePrivate *origin, Class *clazz)
+ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name, ClassOrNamespace *origin,
+ Class *clazz)
{
if (! name)
- return q;
+ return this;
if (! origin)
origin = this;
- if (const QualifiedNameId *qName = name->asQualifiedNameId()) {
- if (! qName->base())
- return globalNamespace()->d->findOrCreateType(qName->name(), origin, clazz);
+ if (const QualifiedNameId *q = name->asQualifiedNameId()) {
+ if (! q->base())
+ return globalNamespace()->findOrCreateType(q->name(), origin, clazz);
- return findOrCreateType(qName->base(), origin)->d->findOrCreateType(qName->name(), origin, clazz);
+ return findOrCreateType(q->base(), origin)->findOrCreateType(q->name(), origin, clazz);
} else if (name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) {
- LookupScopePrivate *e = nestedType(name, origin);
+ ClassOrNamespace *e = nestedType(name, origin);
if (! e) {
- e = allocateChild(name);
+ e = _factory->allocClassOrNamespace(this);
e->_rootClass = clazz;
- _nestedScopes[name] = e;
+ if (Q_UNLIKELY(debug))
+ e->_name = name;
+ _classOrNamespaces[name] = e;
}
- return e->q;
+ return e;
}
return 0;
}
-} // namespace Internal
-
CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot)
: _snapshot(snapshot)
, _control(QSharedPointer<Control>(new Control))
, _expandTemplates(false)
- , _depth(0)
{
- _globalNamespace = allocLookupScope(/*parent = */ 0, /*name = */ 0);
- _currentLookupScope = _globalNamespace;
+ _globalNamespace = allocClassOrNamespace(/*parent = */ 0);
+ _currentClassOrNamespace = _globalNamespace;
process(thisDocument);
}
@@ -1562,36 +1509,36 @@ CreateBindings::~CreateBindings()
qDeleteAll(_entities);
}
-LookupScope *CreateBindings::switchCurrentLookupScope(LookupScope *lookupScope)
+ClassOrNamespace *CreateBindings::switchCurrentClassOrNamespace(ClassOrNamespace *classOrNamespace)
{
- LookupScope *previous = _currentLookupScope;
- _currentLookupScope = lookupScope;
+ ClassOrNamespace *previous = _currentClassOrNamespace;
+ _currentClassOrNamespace = classOrNamespace;
return previous;
}
-LookupScope *CreateBindings::globalNamespace() const
+ClassOrNamespace *CreateBindings::globalNamespace() const
{
return _globalNamespace;
}
-LookupScope *CreateBindings::lookupType(Symbol *symbol, LookupScope *enclosingBinding)
+ClassOrNamespace *CreateBindings::lookupType(Symbol *symbol, ClassOrNamespace *enclosingBinding)
{
const QList<const Name *> path = LookupContext::path(symbol);
return lookupType(path, enclosingBinding);
}
-LookupScope *CreateBindings::lookupType(const QList<const Name *> &path,
- LookupScope *enclosingBinding)
+ClassOrNamespace *CreateBindings::lookupType(const QList<const Name *> &path,
+ ClassOrNamespace *enclosingBinding)
{
if (path.isEmpty())
return _globalNamespace;
if (enclosingBinding) {
- if (LookupScope *b = enclosingBinding->lookupType(path.last()))
+ if (ClassOrNamespace *b = enclosingBinding->lookupType(path.last()))
return b;
}
- LookupScope *b = _globalNamespace->lookupType(path.at(0));
+ ClassOrNamespace *b = _globalNamespace->lookupType(path.at(0));
for (int i = 1; b && i < path.size(); ++i)
b = b->findType(path.at(i));
@@ -1599,23 +1546,22 @@ LookupScope *CreateBindings::lookupType(const QList<const Name *> &path,
return b;
}
-void CreateBindings::process(Symbol *s, LookupScope *lookupScope)
+void CreateBindings::process(Symbol *s, ClassOrNamespace *classOrNamespace)
{
- LookupScope *previous = switchCurrentLookupScope(lookupScope);
+ ClassOrNamespace *previous = switchCurrentClassOrNamespace(classOrNamespace);
accept(s);
- (void) switchCurrentLookupScope(previous);
+ (void) switchCurrentClassOrNamespace(previous);
}
void CreateBindings::process(Symbol *symbol)
{
- _currentLookupScope->d->addTodo(symbol);
+ _currentClassOrNamespace->addTodo(symbol);
}
-LookupScope *CreateBindings::allocLookupScope(LookupScope *parent, const Name *name)
+ClassOrNamespace *CreateBindings::allocClassOrNamespace(ClassOrNamespace *parent)
{
- LookupScope *e = new LookupScope(this, parent);
- e->d->_control = control();
- e->d->_name = name;
+ ClassOrNamespace *e = new ClassOrNamespace(this, parent);
+ e->_control = control();
_entities.append(e);
return e;
}
@@ -1639,22 +1585,22 @@ void CreateBindings::process(Document::Ptr doc)
}
}
-LookupScope *CreateBindings::enterLookupScopeBinding(Symbol *symbol)
+ClassOrNamespace *CreateBindings::enterClassOrNamespaceBinding(Symbol *symbol)
{
- LookupScope *entity = _currentLookupScope->d->findOrCreateType(
- symbol->name(), 0, symbol->asClass());
- entity->d->addSymbol(symbol);
+ ClassOrNamespace *entity = _currentClassOrNamespace->findOrCreateType(symbol->name(), 0,
+ symbol->asClass());
+ entity->addSymbol(symbol);
- return switchCurrentLookupScope(entity);
+ return switchCurrentClassOrNamespace(entity);
}
-LookupScope *CreateBindings::enterGlobalLookupScope(Symbol *symbol)
+ClassOrNamespace *CreateBindings::enterGlobalClassOrNamespace(Symbol *symbol)
{
- LookupScope *entity = _globalNamespace->d->findOrCreateType(
- symbol->name(), 0, symbol->asClass());
- entity->d->addSymbol(symbol);
+ ClassOrNamespace *entity = _globalNamespace->findOrCreateType(symbol->name(), 0,
+ symbol->asClass());
+ entity->addSymbol(symbol);
- return switchCurrentLookupScope(entity);
+ return switchCurrentClassOrNamespace(entity);
}
bool CreateBindings::visit(Template *templ)
@@ -1665,40 +1611,34 @@ bool CreateBindings::visit(Template *templ)
return false;
}
-bool CreateBindings::visit(ExplicitInstantiation *inst)
-{
- Q_UNUSED(inst);
- return false;
-}
-
bool CreateBindings::visit(Namespace *ns)
{
- LookupScope *previous = enterLookupScopeBinding(ns);
+ ClassOrNamespace *previous = enterClassOrNamespaceBinding(ns);
for (unsigned i = 0; i < ns->memberCount(); ++i)
process(ns->memberAt(i));
if (ns->isInline() && previous)
- previous->d->addUsing(_currentLookupScope);
+ previous->addUsing(_currentClassOrNamespace);
- _currentLookupScope = previous;
+ _currentClassOrNamespace = previous;
return false;
}
bool CreateBindings::visit(Class *klass)
{
- LookupScope *previous = _currentLookupScope;
- LookupScope *binding = 0;
+ ClassOrNamespace *previous = _currentClassOrNamespace;
+ ClassOrNamespace *binding = 0;
if (klass->name() && klass->name()->isQualifiedNameId())
- binding = _currentLookupScope->lookupType(klass->name());
+ binding = _currentClassOrNamespace->lookupType(klass->name());
if (! binding)
- binding = _currentLookupScope->d->findOrCreateType(klass->name(), 0, klass);
+ binding = _currentClassOrNamespace->findOrCreateType(klass->name(), 0, klass);
- _currentLookupScope = binding;
- _currentLookupScope->d->addSymbol(klass);
+ _currentClassOrNamespace = binding;
+ _currentClassOrNamespace->addSymbol(klass);
for (unsigned i = 0; i < klass->baseClassCount(); ++i)
process(klass->baseClassAt(i));
@@ -1706,15 +1646,15 @@ bool CreateBindings::visit(Class *klass)
for (unsigned i = 0; i < klass->memberCount(); ++i)
process(klass->memberAt(i));
- _currentLookupScope = previous;
+ _currentClassOrNamespace = previous;
return false;
}
bool CreateBindings::visit(ForwardClassDeclaration *klass)
{
if (! klass->isFriend()) {
- LookupScope *previous = enterLookupScopeBinding(klass);
- _currentLookupScope = previous;
+ ClassOrNamespace *previous = enterClassOrNamespaceBinding(klass);
+ _currentClassOrNamespace = previous;
}
return false;
@@ -1723,10 +1663,10 @@ bool CreateBindings::visit(ForwardClassDeclaration *klass)
bool CreateBindings::visit(Enum *e)
{
if (e->isScoped()) {
- LookupScope *previous = enterLookupScopeBinding(e);
- _currentLookupScope = previous;
+ ClassOrNamespace *previous = enterClassOrNamespaceBinding(e);
+ _currentClassOrNamespace = previous;
} else {
- _currentLookupScope->d->addUnscopedEnum(e);
+ _currentClassOrNamespace->addUnscopedEnum(e);
}
return false;
}
@@ -1734,18 +1674,22 @@ bool CreateBindings::visit(Enum *e)
bool CreateBindings::visit(Declaration *decl)
{
if (decl->isTypedef()) {
- _currentLookupScope->d->_hasTypedefs = true;
FullySpecifiedType ty = decl->type();
const Identifier *typedefId = decl->identifier();
if (typedefId && ! (ty.isConst() || ty.isVolatile())) {
- if (ty->isNamedType()) {
- _currentLookupScope->d->addTypedef(typedefId, decl);
+ if (const NamedType *namedTy = ty->asNamedType()) {
+ if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(namedTy->name())) {
+ _currentClassOrNamespace->addNestedType(decl->name(), e);
+ } else if (false) {
+ Overview oo;
+ qDebug() << "found entity not found for" << oo.prettyName(namedTy->name());
+ }
} else if (Class *klass = ty->asClassType()) {
if (const Identifier *nameId = decl->name()->asNameId()) {
- LookupScope *binding
- = _currentLookupScope->d->findOrCreateType(nameId, 0, klass);
- binding->d->addSymbol(klass);
+ ClassOrNamespace *binding
+ = _currentClassOrNamespace->findOrCreateType(nameId, 0, klass);
+ binding->addSymbol(klass);
}
}
}
@@ -1753,7 +1697,7 @@ bool CreateBindings::visit(Declaration *decl)
if (Class *clazz = decl->type()->asClassType()) {
if (const Name *name = clazz->name()) {
if (const AnonymousNameId *anonymousNameId = name->asAnonymousNameId())
- _currentLookupScope->d->_declaredOrTypedefedAnonymouses.insert(anonymousNameId);
+ _currentClassOrNamespace->_declaredOrTypedefedAnonymouses.insert(anonymousNameId);
}
}
return false;
@@ -1761,59 +1705,58 @@ bool CreateBindings::visit(Declaration *decl)
bool CreateBindings::visit(Function *function)
{
- LookupScope *previous = _currentLookupScope;
- LookupScope *binding = lookupType(function, previous);
+ ClassOrNamespace *previous = _currentClassOrNamespace;
+ ClassOrNamespace *binding = lookupType(function, previous);
if (!binding)
return false;
- _currentLookupScope = binding;
+ _currentClassOrNamespace = binding;
for (unsigned i = 0, count = function->memberCount(); i < count; ++i) {
Symbol *s = function->memberAt(i);
if (Block *b = s->asBlock())
visit(b);
}
- _currentLookupScope = previous;
+ _currentClassOrNamespace = previous;
return false;
}
bool CreateBindings::visit(Block *block)
{
- LookupScope *previous = _currentLookupScope;
+ ClassOrNamespace *previous = _currentClassOrNamespace;
- LookupScope *binding = new LookupScope(this, previous);
- binding->d->_control = control();
+ ClassOrNamespace *binding = new ClassOrNamespace(this, previous);
+ binding->_control = control();
- _currentLookupScope = binding;
- _currentLookupScope->d->addSymbol(block);
+ _currentClassOrNamespace = binding;
+ _currentClassOrNamespace->addSymbol(block);
for (unsigned i = 0; i < block->memberCount(); ++i)
// we cannot use lazy processing here, because we have to know
- // does this block contain any other blocks or LookupScopes
- process(block->memberAt(i), _currentLookupScope);
-
- // we add this block to parent LookupScope only if it contains
- // any nested LookupScopes or other blocks(which have to contain
- // nested LookupScopes)
- if (! _currentLookupScope->d->_blocks.empty()
- || ! _currentLookupScope->d->_nestedScopes.empty()
- || ! _currentLookupScope->d->_enums.empty()
- || _currentLookupScope->d->_hasTypedefs
- || ! _currentLookupScope->d->_anonymouses.empty()) {
- previous->d->_blocks[block] = binding;
+ // does this block contain any other blocks or classOrNamespaces
+ process(block->memberAt(i), _currentClassOrNamespace);
+
+ // we add this block to parent ClassOrNamespace only if it contains
+ // any nested ClassOrNamespaces or other blocks(which have to contain
+ // nested ClassOrNamespaces)
+ if (! _currentClassOrNamespace->_blocks.empty()
+ || ! _currentClassOrNamespace->_classOrNamespaces.empty()
+ || ! _currentClassOrNamespace->_enums.empty()
+ || ! _currentClassOrNamespace->_anonymouses.empty()) {
+ previous->_blocks[block] = binding;
_entities.append(binding);
} else {
delete binding;
binding = 0;
}
- _currentLookupScope = previous;
+ _currentClassOrNamespace = previous;
return false;
}
bool CreateBindings::visit(BaseClass *b)
{
- if (LookupScope *base = _currentLookupScope->lookupType(b->name())) {
- _currentLookupScope->d->addUsing(base);
+ if (ClassOrNamespace *base = _currentClassOrNamespace->lookupType(b->name())) {
+ _currentClassOrNamespace->addUsing(base);
} else if (false) {
Overview oo;
qDebug() << "no entity for:" << oo.prettyName(b->name());
@@ -1826,9 +1769,9 @@ bool CreateBindings::visit(UsingDeclaration *u)
if (u->name()) {
if (const QualifiedNameId *q = u->name()->asQualifiedNameId()) {
if (const Identifier *unqualifiedId = q->name()->asNameId()) {
- if (LookupScope *delegate = _currentLookupScope->lookupType(q)) {
- LookupScope *b = _currentLookupScope->d->findOrCreateType(unqualifiedId);
- b->d->addUsing(delegate);
+ if (ClassOrNamespace *delegate = _currentClassOrNamespace->lookupType(q)) {
+ ClassOrNamespace *b = _currentClassOrNamespace->findOrCreateType(unqualifiedId);
+ b->addUsing(delegate);
}
}
}
@@ -1838,8 +1781,8 @@ bool CreateBindings::visit(UsingDeclaration *u)
bool CreateBindings::visit(UsingNamespaceDirective *u)
{
- if (LookupScope *e = _currentLookupScope->lookupType(u->name())) {
- _currentLookupScope->d->addUsing(e);
+ if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(u->name())) {
+ _currentClassOrNamespace->addUsing(e);
} else if (false) {
Overview oo;
qDebug() << "no entity for namespace:" << oo.prettyName(u->name());
@@ -1852,9 +1795,9 @@ bool CreateBindings::visit(NamespaceAlias *a)
if (! a->identifier()) {
return false;
- } else if (LookupScope *e = _currentLookupScope->lookupType(a->namespaceName())) {
+ } else if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(a->namespaceName())) {
if (a->name()->isNameId() || a->name()->isTemplateNameId() || a->name()->isAnonymousNameId())
- _currentLookupScope->d->addNestedType(a->name(), e);
+ _currentClassOrNamespace->addNestedType(a->name(), e);
} else if (false) {
Overview oo;
@@ -1866,7 +1809,7 @@ bool CreateBindings::visit(NamespaceAlias *a)
bool CreateBindings::visit(ObjCClass *klass)
{
- LookupScope *previous = enterGlobalLookupScope(klass);
+ ClassOrNamespace *previous = enterGlobalClassOrNamespace(klass);
process(klass->baseClass());
@@ -1876,14 +1819,14 @@ bool CreateBindings::visit(ObjCClass *klass)
for (unsigned i = 0; i < klass->memberCount(); ++i)
process(klass->memberAt(i));
- _currentLookupScope = previous;
+ _currentClassOrNamespace = previous;
return false;
}
bool CreateBindings::visit(ObjCBaseClass *b)
{
- if (LookupScope *base = _globalNamespace->lookupType(b->name())) {
- _currentLookupScope->d->addUsing(base);
+ if (ClassOrNamespace *base = _globalNamespace->lookupType(b->name())) {
+ _currentClassOrNamespace->addUsing(base);
} else if (false) {
Overview oo;
qDebug() << "no entity for:" << oo.prettyName(b->name());
@@ -1893,14 +1836,14 @@ bool CreateBindings::visit(ObjCBaseClass *b)
bool CreateBindings::visit(ObjCForwardClassDeclaration *klass)
{
- LookupScope *previous = enterGlobalLookupScope(klass);
- _currentLookupScope = previous;
+ ClassOrNamespace *previous = enterGlobalClassOrNamespace(klass);
+ _currentClassOrNamespace = previous;
return false;
}
bool CreateBindings::visit(ObjCProtocol *proto)
{
- LookupScope *previous = enterGlobalLookupScope(proto);
+ ClassOrNamespace *previous = enterGlobalClassOrNamespace(proto);
for (unsigned i = 0; i < proto->protocolCount(); ++i)
process(proto->protocolAt(i));
@@ -1908,14 +1851,14 @@ bool CreateBindings::visit(ObjCProtocol *proto)
for (unsigned i = 0; i < proto->memberCount(); ++i)
process(proto->memberAt(i));
- _currentLookupScope = previous;
+ _currentClassOrNamespace = previous;
return false;
}
bool CreateBindings::visit(ObjCBaseProtocol *b)
{
- if (LookupScope *base = _globalNamespace->lookupType(b->name())) {
- _currentLookupScope->d->addUsing(base);
+ if (ClassOrNamespace *base = _globalNamespace->lookupType(b->name())) {
+ _currentClassOrNamespace->addUsing(base);
} else if (false) {
Overview oo;
qDebug() << "no entity for:" << oo.prettyName(b->name());
@@ -1925,8 +1868,8 @@ bool CreateBindings::visit(ObjCBaseProtocol *b)
bool CreateBindings::visit(ObjCForwardProtocolDeclaration *proto)
{
- LookupScope *previous = enterGlobalLookupScope(proto);
- _currentLookupScope = previous;
+ ClassOrNamespace *previous = enterGlobalClassOrNamespace(proto);
+ _currentClassOrNamespace = previous;
return false;
}
@@ -1935,57 +1878,29 @@ bool CreateBindings::visit(ObjCMethod *)
return false;
}
-FullySpecifiedType CreateBindings::resolveTemplateArgument(Clone &cloner,
- Subst &subst,
- LookupScope *origin,
- const Template *specialization,
- const TemplateNameId *instantiation,
- unsigned index)
-{
- FullySpecifiedType ty;
- CPP_ASSERT(specialization && instantiation, return ty);
-
- const TypenameArgument *tParam = 0;
- if (Symbol *tArgument = specialization->templateParameterAt(index))
- tParam = tArgument->asTypenameArgument();
- if (!tParam)
- return ty;
-
- if (index < instantiation->templateArgumentCount())
- ty = instantiation->templateArgumentAt(index);
- else
- ty = cloner.type(tParam->type(), &subst);
-
- TypeResolver typeResolver(*this);
- Scope *resolveScope = specialization->enclosingScope();
- typeResolver.resolve(&ty, &resolveScope, origin);
- const TemplateNameId *templSpecId = specialization->name()->asTemplateNameId();
- const unsigned templSpecArgumentCount = templSpecId ? templSpecId->templateArgumentCount() : 0;
- if (index < templSpecArgumentCount && templSpecId->templateArgumentAt(index)->isPointerType()) {
- if (PointerType *pointerType = ty->asPointerType())
- ty = pointerType->elementType();
- }
-
- if (const Name *name = tParam->name())
- subst.bind(cloner.name(name, &subst), ty);
- return ty;
-}
-
-void CreateBindings::initializeSubst(Clone &cloner,
- Subst &subst,
- LookupScope *origin,
- const Template *specialization,
- const TemplateNameId *instantiation)
+Symbol *CreateBindings::instantiateTemplateFunction(const TemplateNameId *instantiation,
+ Template *specialization) const
{
+ const unsigned argumentCountOfInitialization = instantiation->templateArgumentCount();
const unsigned argumentCountOfSpecialization = specialization->templateParameterCount();
- if (_depth > 15)
- return;
+ Clone cloner(_control.data());
+ Subst subst(_control.data());
+ for (unsigned i = 0; i < argumentCountOfSpecialization; ++i) {
+ const TypenameArgument *tParam
+ = specialization->templateParameterAt(i)->asTypenameArgument();
+ if (!tParam)
+ continue;
+ const Name *name = tParam->name();
+ if (!name)
+ continue;
- ++_depth;
- for (unsigned i = 0; i < argumentCountOfSpecialization; ++i)
- resolveTemplateArgument(cloner, subst, origin, specialization, instantiation, i);
- --_depth;
+ FullySpecifiedType ty = (i < argumentCountOfInitialization) ?
+ instantiation->templateArgumentAt(i):
+ cloner.type(tParam->type(), &subst);
+
+ subst.bind(cloner.name(name, &subst), ty);
+ }
+ return cloner.symbol(specialization, &subst);
}
-} // namespace CPlusPlus
diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h
index 8410c9000b..5858d80c95 100644
--- a/src/libs/cplusplus/LookupContext.h
+++ b/src/libs/cplusplus/LookupContext.h
@@ -41,7 +41,6 @@
#include <cplusplus/Control.h>
#include <cplusplus/Name.h>
-#include <QEnableSharedFromThis>
#include <QSet>
#include <QMap>
@@ -59,78 +58,158 @@ struct FullyQualifiedName
: fqn(fqn)
{}
};
-class LookupScopePrivate;
-class Instantiator;
} // namespace Internal;
class CreateBindings;
-class CPLUSPLUS_EXPORT LookupScope
+class CPLUSPLUS_EXPORT ClassOrNamespace
{
- Q_DISABLE_COPY(LookupScope)
+ Q_DISABLE_COPY(ClassOrNamespace)
- LookupScope(CreateBindings *factory, LookupScope *parent);
+ ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent);
public:
- ~LookupScope();
+ ~ClassOrNamespace();
- LookupScope *instantiationOrigin() const;
+ const TemplateNameId *templateId() const;
+ ClassOrNamespace *instantiationOrigin() const;
- LookupScope *parent() const;
- QList<LookupScope *> usings() const;
+ ClassOrNamespace *parent() const;
+ QList<ClassOrNamespace *> usings() const;
QList<Enum *> unscopedEnums() const;
QList<Symbol *> symbols() const;
+ ClassOrNamespace *globalNamespace() const;
+
QList<LookupItem> lookup(const Name *name);
QList<LookupItem> find(const Name *name);
- LookupScope *lookupType(const Name *name);
- LookupScope *lookupType(const Name *name, Block *block);
- LookupScope *findType(const Name *name);
- LookupScope *findBlock(Block *block);
+ ClassOrNamespace *lookupType(const Name *name);
+ ClassOrNamespace *lookupType(const Name *name, Block *block);
+ ClassOrNamespace *findType(const Name *name);
+ ClassOrNamespace *findBlock(Block *block);
+
+ Symbol *lookupInScope(const QList<const Name *> &fullName);
- /// The class this LookupScope is based on.
- Class *rootClass() const;
+ /// The class this ClassOrNamespace is based on.
+ Class *rootClass() const { return _rootClass; }
private:
- Internal::LookupScopePrivate *d;
+ typedef std::map<const Name *, ClassOrNamespace *, Name::Compare> Table;
+ typedef std::map<const TemplateNameId *, ClassOrNamespace *, TemplateNameId::Compare> TemplateNameIdTable;
+ typedef QHash<const AnonymousNameId *, ClassOrNamespace *> Anonymouses;
+
+ /// \internal
+ void flush();
+
+ /// \internal
+ ClassOrNamespace *findOrCreateType(const Name *name, ClassOrNamespace *origin = 0,
+ Class *clazz = 0);
+
+ ClassOrNamespace *findOrCreateNestedAnonymousType(const AnonymousNameId *anonymousNameId);
+
+ void addTodo(Symbol *symbol);
+ void addSymbol(Symbol *symbol);
+ void addUnscopedEnum(Enum *e);
+ void addUsing(ClassOrNamespace *u);
+ void addNestedType(const Name *alias, ClassOrNamespace *e);
+
+ QList<LookupItem> lookup_helper(const Name *name, bool searchInEnclosingScope);
+
+ void lookup_helper(const Name *name, ClassOrNamespace *binding,
+ QList<LookupItem> *result,
+ QSet<ClassOrNamespace *> *processed,
+ const TemplateNameId *templateId);
+
+ ClassOrNamespace *lookupType_helper(const Name *name, QSet<ClassOrNamespace *> *processed,
+ bool searchInEnclosingScope, ClassOrNamespace *origin);
+
+ ClassOrNamespace *findBlock_helper(Block *block, QSet<ClassOrNamespace *> *processed,
+ bool searchInEnclosingScope);
+
+ ClassOrNamespace *nestedType(const Name *name, ClassOrNamespace *origin);
+
+ void instantiateNestedClasses(ClassOrNamespace *enclosingTemplateClass,
+ Clone &cloner,
+ Subst &subst,
+ ClassOrNamespace *enclosingTemplateClassInstantiation);
+ ClassOrNamespace *findSpecialization(const TemplateNameId *templId,
+ const TemplateNameIdTable &specializations);
+
+ CreateBindings *_factory;
+ ClassOrNamespace *_parent;
+ QList<Symbol *> _symbols;
+ QList<ClassOrNamespace *> _usings;
+ Table _classOrNamespaces;
+ QHash<Block *, ClassOrNamespace *> _blocks;
+ QList<Enum *> _enums;
+ QList<Symbol *> _todo;
+ QSharedPointer<Control> _control;
+ TemplateNameIdTable _specializations;
+ QMap<const TemplateNameId *, ClassOrNamespace *> _instantiations;
+ Anonymouses _anonymouses;
+ QSet<const AnonymousNameId *> _declaredOrTypedefedAnonymouses;
+
+ QHash<Internal::FullyQualifiedName, Symbol *> *_scopeLookupCache;
+
+ // it's an instantiation.
+ const TemplateNameId *_templateId;
+ ClassOrNamespace *_instantiationOrigin;
+
+ AlreadyConsideredClassContainer<Class> _alreadyConsideredClasses;
+ AlreadyConsideredClassContainer<TemplateNameId> _alreadyConsideredTemplates;
+
+ Class *_rootClass;
+
+ class NestedClassInstantiator
+ {
+ public:
+ NestedClassInstantiator(CreateBindings *factory, Clone &cloner, Subst &subst)
+ : _factory(factory)
+ , _cloner(cloner)
+ , _subst(subst)
+ {}
+ void instantiate(ClassOrNamespace *enclosingTemplateClass,
+ ClassOrNamespace *enclosingTemplateClassInstantiation);
+ private:
+ bool isInstantiateNestedClassNeeded(const QList<Symbol *> &symbols) const;
+ bool containsTemplateType(Declaration *declaration) const;
+ bool containsTemplateType(Function *function) const;
+ NamedType *findNamedType(Type *memberType) const;
+
+ QSet<ClassOrNamespace *> _alreadyConsideredNestedClassInstantiations;
+ CreateBindings *_factory;
+ Clone &_cloner;
+ Subst &_subst;
+ };
+
+public:
+ const Name *_name; // For debug
- friend class Internal::LookupScopePrivate;
- friend class Internal::Instantiator;
friend class CreateBindings;
};
-class CPLUSPLUS_EXPORT CreateBindings
- : protected SymbolVisitor
- , public QEnableSharedFromThis<CreateBindings>
+class CPLUSPLUS_EXPORT CreateBindings: protected SymbolVisitor
{
Q_DISABLE_COPY(CreateBindings)
public:
- typedef QSharedPointer<CreateBindings> Ptr;
-
CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot);
virtual ~CreateBindings();
/// Returns the binding for the global namespace.
- LookupScope *globalNamespace() const;
+ ClassOrNamespace *globalNamespace() const;
/// Finds the binding associated to the given symbol.
- LookupScope *lookupType(Symbol *symbol, LookupScope *enclosingBinding = 0);
- LookupScope *lookupType(const QList<const Name *> &path, LookupScope *enclosingBinding = 0);
+ ClassOrNamespace *lookupType(Symbol *symbol, ClassOrNamespace *enclosingBinding = 0);
+ ClassOrNamespace *lookupType(const QList<const Name *> &path,
+ ClassOrNamespace *enclosingBinding = 0);
/// Returns the Control that must be used to create temporary symbols.
/// \internal
QSharedPointer<Control> control() const
{ return _control; }
- Snapshot &snapshot()
- { return _snapshot; }
-
- /// Adds an expression document in order to keep their symbols and names alive
- void addExpressionDocument(Document::Ptr document)
- { _expressionDocuments.append(document); }
-
bool expandTemplates() const
{ return _expandTemplates; }
void setExpandTemplates(bool expandTemplates)
@@ -140,36 +219,28 @@ public:
/// Store the result in \a results.
/// \internal
void lookupInScope(const Name *name, Scope *scope, QList<LookupItem> *result,
- LookupScope *binding = 0);
+ const TemplateNameId *templateId, ClassOrNamespace *binding);
/// Create bindings for the symbols reachable from \a rootSymbol.
/// \internal
- void process(Symbol *rootSymbol, LookupScope *lookupScope);
+ void process(Symbol *rootSymbol, ClassOrNamespace *classOrNamespace);
- /// Create an empty LookupScope binding with the given \a parent.
+ /// Create an empty ClassOrNamespace binding with the given \a parent.
/// \internal
- LookupScope *allocLookupScope(LookupScope *parent, const Name *name);
-
- FullySpecifiedType resolveTemplateArgument(Clone &cloner, Subst &subst,
- LookupScope *origin,
- const Template *specialization,
- const TemplateNameId *instantiation,
- unsigned index);
- void initializeSubst(Clone &cloner, Subst &subst, LookupScope *origin,
- const Template *specialization, const TemplateNameId *instantiation);
+ ClassOrNamespace *allocClassOrNamespace(ClassOrNamespace *parent);
protected:
using SymbolVisitor::visit;
- /// Change the current LookupScope binding.
- LookupScope *switchCurrentLookupScope(LookupScope *lookupScope);
+ /// Change the current ClassOrNamespace binding.
+ ClassOrNamespace *switchCurrentClassOrNamespace(ClassOrNamespace *classOrNamespace);
- /// Enters the LookupScope binding associated with the given \a symbol.
- LookupScope *enterLookupScopeBinding(Symbol *symbol);
+ /// Enters the ClassOrNamespace binding associated with the given \a symbol.
+ ClassOrNamespace *enterClassOrNamespaceBinding(Symbol *symbol);
- /// Enters a LookupScope binding for the given \a symbol in the global
+ /// Enters a ClassOrNamespace binding for the given \a symbol in the global
/// namespace binding.
- LookupScope *enterGlobalLookupScope(Symbol *symbol);
+ ClassOrNamespace *enterGlobalClassOrNamespace(Symbol *symbol);
/// Creates bindings for the given \a document.
void process(Document::Ptr document);
@@ -178,7 +249,6 @@ protected:
void process(Symbol *root);
virtual bool visit(Template *templ);
- virtual bool visit(ExplicitInstantiation *inst);
virtual bool visit(Namespace *ns);
virtual bool visit(Class *klass);
virtual bool visit(ForwardClassDeclaration *klass);
@@ -201,15 +271,16 @@ protected:
virtual bool visit(ObjCMethod *);
private:
+ Symbol *instantiateTemplateFunction(const TemplateNameId *instantiation,
+ Template *specialization) const;
+
Snapshot _snapshot;
QSharedPointer<Control> _control;
- QList<Document::Ptr> _expressionDocuments;
QSet<Namespace *> _processed;
- QList<LookupScope *> _entities;
- LookupScope *_globalNamespace;
- LookupScope *_currentLookupScope;
+ QList<ClassOrNamespace *> _entities;
+ ClassOrNamespace *_globalNamespace;
+ ClassOrNamespace *_currentClassOrNamespace;
bool _expandTemplates;
- int _depth;
};
class CPLUSPLUS_EXPORT LookupContext
@@ -223,7 +294,7 @@ public:
LookupContext(Document::Ptr expressionDocument,
Document::Ptr thisDocument,
const Snapshot &snapshot,
- CreateBindings::Ptr bindings = CreateBindings::Ptr());
+ QSharedPointer<CreateBindings> bindings = QSharedPointer<CreateBindings>());
LookupContext(const LookupContext &other);
LookupContext &operator = (const LookupContext &other);
@@ -233,25 +304,25 @@ public:
Document::Ptr document(const QString &fileName) const;
Snapshot snapshot() const;
- LookupScope *globalNamespace() const;
+ ClassOrNamespace *globalNamespace() const;
QList<LookupItem> lookup(const Name *name, Scope *scope) const;
- LookupScope *lookupType(const Name *name, Scope *scope,
- LookupScope *enclosingBinding = 0,
+ ClassOrNamespace *lookupType(const Name *name, Scope *scope,
+ ClassOrNamespace *enclosingBinding = 0,
QSet<const Declaration *> typedefsBeingResolved
= QSet<const Declaration *>()) const;
- LookupScope *lookupType(Symbol *symbol,
- LookupScope *enclosingBinding = 0) const;
- LookupScope *lookupParent(Symbol *symbol) const;
+ ClassOrNamespace *lookupType(Symbol *symbol,
+ ClassOrNamespace *enclosingBinding = 0) const;
+ ClassOrNamespace *lookupParent(Symbol *symbol) const;
/// \internal
- CreateBindings::Ptr bindings() const
+ QSharedPointer<CreateBindings> bindings() const
{ return _bindings; }
static QList<const Name *> fullyQualifiedName(Symbol *symbol);
static QList<const Name *> path(Symbol *symbol);
- static const Name *minimalName(Symbol *symbol, LookupScope *target, Control *control);
+ static const Name *minimalName(Symbol *symbol, ClassOrNamespace *target, Control *control);
void setExpandTemplates(bool expandTemplates)
{
@@ -261,7 +332,7 @@ public:
}
private:
- QList<LookupItem> lookupByUsing(const Name *name, LookupScope *bindingScope) const;
+ QList<LookupItem> lookupByUsing(const Name *name, ClassOrNamespace *bindingScope) const;
// The current expression.
Document::Ptr _expressionDocument;
@@ -273,7 +344,7 @@ private:
Snapshot _snapshot;
// Bindings
- CreateBindings::Ptr _bindings;
+ QSharedPointer<CreateBindings> _bindings;
bool m_expandTemplates;
};
diff --git a/src/libs/cplusplus/LookupItem.cpp b/src/libs/cplusplus/LookupItem.cpp
index 4e22389503..0621c1f6e9 100644
--- a/src/libs/cplusplus/LookupItem.cpp
+++ b/src/libs/cplusplus/LookupItem.cpp
@@ -77,10 +77,10 @@ Scope *LookupItem::scope() const
void LookupItem::setScope(Scope *scope)
{ _scope = scope; }
-LookupScope *LookupItem::binding() const
+ClassOrNamespace *LookupItem::binding() const
{ return _binding; }
-void LookupItem::setBinding(LookupScope *binding)
+void LookupItem::setBinding(ClassOrNamespace *binding)
{ _binding = binding; }
bool LookupItem::operator == (const LookupItem &other) const
diff --git a/src/libs/cplusplus/LookupItem.h b/src/libs/cplusplus/LookupItem.h
index 13963b7064..46c7b34716 100644
--- a/src/libs/cplusplus/LookupItem.h
+++ b/src/libs/cplusplus/LookupItem.h
@@ -37,7 +37,7 @@
namespace CPlusPlus {
-class LookupScope;
+class ClassOrNamespace;
class CPLUSPLUS_EXPORT LookupItem
{
@@ -63,8 +63,8 @@ public:
/// Sets this item's scope.
void setScope(Scope *scope);
- LookupScope *binding() const;
- void setBinding(LookupScope *binding);
+ ClassOrNamespace *binding() const;
+ void setBinding(ClassOrNamespace *binding);
bool operator == (const LookupItem &other) const;
bool operator != (const LookupItem &other) const;
@@ -73,7 +73,7 @@ private:
FullySpecifiedType _type;
Scope *_scope;
Symbol *_declaration;
- LookupScope *_binding;
+ ClassOrNamespace *_binding;
};
uint qHash(const CPlusPlus::LookupItem &result);
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 43887b2995..adaac12ab5 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -32,9 +32,9 @@
#include "LookupContext.h"
#include "Overview.h"
+#include "DeprecatedGenTemplateInstance.h"
#include "CppRewriter.h"
#include "TypeOfExpression.h"
-#include "TypeResolver.h"
#include <cplusplus/Control.h>
#include <cplusplus/AST.h>
@@ -75,6 +75,131 @@ static QList<T> removeDuplicates(const QList<T> &results)
return uniqueList;
}
+class TypedefsResolver
+{
+public:
+ TypedefsResolver(const LookupContext &context) : _context(context) {}
+ void resolve(FullySpecifiedType *type, Scope **scope, ClassOrNamespace *binding)
+ {
+ QSet<Symbol *> visited;
+ _binding = binding;
+ // Use a hard limit when trying to resolve typedefs. Typedefs in templates can refer to
+ // each other, each time enhancing the template argument and thus making it impossible to
+ // use an "alreadyResolved" container. FIXME: We might overcome this by resolving the
+ // template parameters.
+ unsigned maxDepth = 15;
+ for (NamedType *namedTy = 0; maxDepth && (namedTy = getNamedType(*type)); --maxDepth) {
+ QList<LookupItem> namedTypeItems = getNamedTypeItems(namedTy->name(), *scope, _binding);
+
+ if (Q_UNLIKELY(debug))
+ qDebug() << "-- we have" << namedTypeItems.size() << "candidates";
+
+ if (!findTypedef(namedTypeItems, type, scope, visited))
+ break;
+ }
+ }
+
+private:
+ NamedType *getNamedType(FullySpecifiedType& type) const
+ {
+ NamedType *namedTy = type->asNamedType();
+ if (! namedTy) {
+ if (PointerType *pointerTy = type->asPointerType())
+ namedTy = pointerTy->elementType()->asNamedType();
+ }
+ return namedTy;
+ }
+
+ QList<LookupItem> getNamedTypeItems(const Name *name, Scope *scope,
+ ClassOrNamespace *binding) const
+ {
+ QList<LookupItem> namedTypeItems = typedefsFromScopeUpToFunctionScope(name, scope);
+ if (namedTypeItems.isEmpty()) {
+ if (binding)
+ namedTypeItems = binding->lookup(name);
+ if (ClassOrNamespace *scopeCon = _context.lookupType(scope))
+ namedTypeItems += scopeCon->lookup(name);
+ }
+
+ return namedTypeItems;
+ }
+
+ /// Return all typedefs with given name from given scope up to function scope.
+ static QList<LookupItem> typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope)
+ {
+ QList<LookupItem> results;
+ if (!scope)
+ return results;
+ Scope *enclosingBlockScope = 0;
+ for (Block *block = scope->asBlock(); block;
+ block = enclosingBlockScope ? enclosingBlockScope->asBlock() : 0) {
+ const unsigned memberCount = block->memberCount();
+ for (unsigned i = 0; i < memberCount; ++i) {
+ Symbol *symbol = block->memberAt(i);
+ if (Declaration *declaration = symbol->asDeclaration()) {
+ if (isTypedefWithName(declaration, name)) {
+ LookupItem item;
+ item.setDeclaration(declaration);
+ item.setScope(block);
+ item.setType(declaration->type());
+ results.append(item);
+ }
+ }
+ }
+ enclosingBlockScope = block->enclosingScope();
+ }
+ return results;
+ }
+
+ static bool isTypedefWithName(const Declaration *declaration, const Name *name)
+ {
+ if (declaration->isTypedef()) {
+ const Identifier *identifier = declaration->name()->identifier();
+ if (name->identifier()->match(identifier))
+ return true;
+ }
+ return false;
+ }
+
+ bool findTypedef(const QList<LookupItem>& namedTypeItems, FullySpecifiedType *type,
+ Scope **scope, QSet<Symbol *>& visited)
+ {
+ bool foundTypedef = false;
+ foreach (const LookupItem &it, namedTypeItems) {
+ Symbol *declaration = it.declaration();
+ if (declaration && declaration->isTypedef()) {
+ if (visited.contains(declaration))
+ break;
+ visited.insert(declaration);
+
+ // continue working with the typedefed type and scope
+ if (type->type()->isPointerType()) {
+ *type = FullySpecifiedType(
+ _context.bindings()->control()->pointerType(declaration->type()));
+ } else if (type->type()->isReferenceType()) {
+ *type = FullySpecifiedType(
+ _context.bindings()->control()->referenceType(
+ declaration->type(),
+ declaration->type()->asReferenceType()->isRvalueReference()));
+ } else {
+ *type = declaration->type();
+ }
+
+ *scope = it.scope();
+ _binding = it.binding();
+ foundTypedef = true;
+ break;
+ }
+ }
+
+ return foundTypedef;
+ }
+
+ const LookupContext &_context;
+ // binding has to be remembered in case of resolving typedefs for templates
+ ClassOrNamespace *_binding;
+};
+
static int evaluateFunctionArgument(const FullySpecifiedType &actualTy,
const FullySpecifiedType &formalTy)
{
@@ -176,7 +301,7 @@ void ResolveExpression::addResults(const QList<LookupItem> &items)
}
void ResolveExpression::addResult(const FullySpecifiedType &ty, Scope *scope,
- LookupScope *binding)
+ ClassOrNamespace *binding)
{
LookupItem item;
item.setType(ty);
@@ -206,7 +331,7 @@ bool ResolveExpression::visit(BinaryExpressionAST *ast)
if (d->core_declarator) {
if (DeclaratorIdAST *declaratorId = d->core_declarator->asDeclaratorId()) {
if (NameAST *nameAST = declaratorId->name) {
- if (LookupScope *binding = baseExpression(_results, T_ARROW)) {
+ if (ClassOrNamespace *binding = baseExpression(_results, T_ARROW)) {
_results.clear();
addResults(binding->lookup(nameAST->name));
}
@@ -487,17 +612,19 @@ bool ResolveExpression::visit(UnaryExpressionAST *ast)
added = true;
} else if (namedTy != 0) {
const Name *starOp = control()->operatorNameId(OperatorNameId::StarOp);
- if (LookupScope *b = _context.lookupType(namedTy->name(), p.scope(), p.binding())) {
+ if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), p.scope(), p.binding())) {
foreach (const LookupItem &r, b->find(starOp)) {
Symbol *overload = r.declaration();
if (Function *funTy = overload->type()->asFunctionType()) {
if (maybeValidPrototype(funTy, 0)) {
- FullySpecifiedType retTy = funTy->returnType().simplified();
- p.setType(retTy);
- p.setScope(funTy->enclosingScope());
- it.setValue(p);
- added = true;
- break;
+ if (Function *proto = instantiate(b->templateId(), funTy)->asFunctionType()) {
+ FullySpecifiedType retTy = proto->returnType().simplified();
+ p.setType(retTy);
+ p.setScope(proto->enclosingScope());
+ it.setValue(p);
+ added = true;
+ break;
+ }
}
}
}
@@ -526,6 +653,48 @@ bool ResolveExpression::visit(QualifiedNameAST *ast)
return false;
}
+namespace {
+
+class DeduceAutoCheck : public ASTVisitor
+{
+public:
+ DeduceAutoCheck(const Identifier *id, TranslationUnit *tu)
+ : ASTVisitor(tu), _id(id), _block(false)
+ {
+ accept(tu->ast());
+ }
+
+ virtual bool preVisit(AST *)
+ {
+ if (_block)
+ return false;
+
+ return true;
+ }
+
+ virtual bool visit(SimpleNameAST *ast)
+ {
+ if (ast->name
+ && ast->name->identifier()
+ && strcmp(ast->name->identifier()->chars(), _id->chars()) == 0) {
+ _block = true;
+ }
+
+ return false;
+ }
+
+ virtual bool visit(MemberAccessAST *ast)
+ {
+ accept(ast->base_expression);
+ return false;
+ }
+
+ const Identifier *_id;
+ bool _block;
+};
+
+} // namespace anonymous
+
bool ResolveExpression::visit(SimpleNameAST *ast)
{
QList<LookupItem> candidates = _context.lookup(ast->name, _scope);
@@ -539,7 +708,7 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
if (item.declaration() == 0)
continue;
- if (item.type().isAuto() || item.type().isDecltype()) {
+ if (item.type().isAuto()) {
const Declaration *decl = item.declaration()->asDeclaration();
if (!decl)
continue;
@@ -548,10 +717,53 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
if (_autoDeclarationsBeingResolved.contains(decl))
continue;
- newCandidates +=
- TypeResolver::resolveDeclInitializer(*_context.bindings(), decl,
- _autoDeclarationsBeingResolved << decl,
- ast->name->identifier());
+ const StringLiteral *initializationString = decl->getInitializer();
+ if (initializationString == 0)
+ continue;
+
+ const QByteArray &initializer =
+ QByteArray::fromRawData(initializationString->chars(),
+ initializationString->size()).trimmed();
+
+ // Skip lambda-function initializers
+ if (initializer.length() > 0 && initializer[0] == '[')
+ continue;
+
+ TypeOfExpression exprTyper;
+ exprTyper.setExpandTemplates(true);
+ Document::Ptr doc = _context.snapshot().document(QString::fromLocal8Bit(decl->fileName()));
+ exprTyper.init(doc, _context.snapshot(), _context.bindings(),
+ QSet<const Declaration* >(_autoDeclarationsBeingResolved) << decl);
+
+ Document::Ptr exprDoc =
+ documentForExpression(exprTyper.preprocessedExpression(initializer));
+ exprDoc->check();
+
+ DeduceAutoCheck deduceAuto(ast->name->identifier(), exprDoc->translationUnit());
+ if (deduceAuto._block)
+ continue;
+
+ const QList<LookupItem> &typeItems = exprTyper(extractExpressionAST(exprDoc), exprDoc,
+ decl->enclosingScope());
+ if (typeItems.empty())
+ continue;
+
+ Clone cloner(_context.bindings()->control().data());
+
+ for (int n = 0; n < typeItems.size(); ++ n) {
+ FullySpecifiedType newType = cloner.type(typeItems[n].type(), 0);
+ if (n == 0) {
+ item.setType(newType);
+ item.setScope(typeItems[n].scope());
+ item.setBinding(typeItems[n].binding());
+ } else {
+ LookupItem newItem(item);
+ newItem.setType(newType);
+ newItem.setScope(typeItems[n].scope());
+ newItem.setBinding(typeItems[n].binding());
+ newCandidates.push_back(newItem);
+ }
+ }
} else {
item.setType(item.declaration()->type());
item.setScope(item.declaration()->enclosingScope());
@@ -661,12 +873,14 @@ bool ResolveExpression::visit(CallAST *ast)
Scope *scope = result.scope();
if (NamedType *namedTy = ty->asNamedType()) {
- if (LookupScope *b = _context.lookupType(namedTy->name(), scope)) {
+ if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
foreach (const LookupItem &r, b->find(functionCallOp)) {
Symbol *overload = r.declaration();
if (Function *funTy = overload->type()->asFunctionType()) {
- if (maybeValidPrototype(funTy, actualArgumentCount))
- addResult(funTy->returnType().simplified(), scope);
+ if (maybeValidPrototype(funTy, actualArgumentCount)) {
+ if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
+ addResult(proto->returnType().simplified(), scope);
+ }
}
}
}
@@ -679,6 +893,14 @@ bool ResolveExpression::visit(CallAST *ast)
// Constructor call
FullySpecifiedType ctorTy = control()->namedType(classTy->name());
addResult(ctorTy, scope);
+ } else if (Template *templateTy = ty->asTemplateType()) {
+ // template function
+ if (Symbol *declaration = templateTy->declaration()) {
+ if (Function *funTy = declaration->asFunction()) {
+ if (maybeValidPrototype(funTy, actualArgumentCount))
+ addResult(funTy->returnType().simplified(), scope);
+ }
+ }
}
}
@@ -694,8 +916,8 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
FullySpecifiedType ty = result.type().simplified();
Scope *scope = result.scope();
- TypeResolver typeResolver(*_context.bindings());
- typeResolver.resolve(&ty, &scope, result.binding());
+ TypedefsResolver typedefsResolver(_context);
+ typedefsResolver.resolve(&ty, &scope, result.binding());
if (PointerType *ptrTy = ty->asPointerType()) {
addResult(ptrTy->elementType().simplified(), scope);
@@ -704,12 +926,13 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
addResult(arrTy->elementType().simplified(), scope);
} else if (NamedType *namedTy = ty->asNamedType()) {
- if (LookupScope *b = _context.lookupType(namedTy->name(), scope)) {
+ if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) {
foreach (const LookupItem &r, b->find(arrayAccessOp)) {
Symbol *overload = r.declaration();
if (Function *funTy = overload->type()->asFunctionType()) {
- // ### TODO: check the actual arguments
- addResult(funTy->returnType().simplified(), scope);
+ if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
+ // ### TODO: check the actual arguments
+ addResult(proto->returnType().simplified(), scope);
}
}
@@ -719,7 +942,7 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
return false;
}
-QList<LookupItem> ResolveExpression::getMembers(LookupScope *binding, const Name *memberName) const
+QList<LookupItem> ResolveExpression::getMembers(ClassOrNamespace *binding, const Name *memberName) const
{
Q_UNUSED(binding);
Q_UNUSED(memberName);
@@ -788,17 +1011,17 @@ bool ResolveExpression::visit(MemberAccessAST *ast)
// Remember the access operator.
const int accessOp = tokenKind(ast->access_token);
- if (LookupScope *binding = baseExpression(baseResults, accessOp))
+ if (ClassOrNamespace *binding = baseExpression(baseResults, accessOp))
addResults(binding->find(memberName));
return false;
}
-LookupScope *ResolveExpression::findClass(const FullySpecifiedType &originalTy, Scope *scope,
- LookupScope *enclosingBinding) const
+ClassOrNamespace *ResolveExpression::findClass(const FullySpecifiedType &originalTy, Scope *scope,
+ ClassOrNamespace *enclosingBinding) const
{
FullySpecifiedType ty = originalTy.simplified();
- LookupScope *binding = 0;
+ ClassOrNamespace *binding = 0;
if (Class *klass = ty->asClassType()) {
if (scope->isBlock())
@@ -816,14 +1039,15 @@ LookupScope *ResolveExpression::findClass(const FullySpecifiedType &originalTy,
return binding;
}
-LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResults,
- int accessOp,
- bool *replacedDotOperator) const
+ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &baseResults,
+ int accessOp,
+ bool *replacedDotOperator) const
{
if (Q_UNLIKELY(debug))
qDebug() << "In ResolveExpression::baseExpression with" << baseResults.size() << "results...";
int i = 0;
- TypeResolver typeResolver(*_context.bindings());
+ Overview oo;
+ TypedefsResolver typedefsResolver(_context);
foreach (const LookupItem &r, baseResults) {
if (!r.type().type() || !r.scope())
@@ -832,55 +1056,80 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu
FullySpecifiedType originalType = ty;
Scope *scope = r.scope();
- if (Q_UNLIKELY(debug))
+ if (Q_UNLIKELY(debug)) {
qDebug("trying result #%d", ++i);
+ qDebug() << "- before typedef resolving we have:" << oo(ty);
+ }
+
+ typedefsResolver.resolve(&ty, &scope, r.binding());
- typeResolver.resolve(&ty, &scope, r.binding());
+ if (Q_UNLIKELY(debug))
+ qDebug() << "- after typedef resolving:" << oo(ty);
if (accessOp == T_ARROW) {
if (PointerType *ptrTy = ty->asPointerType()) {
FullySpecifiedType type = ptrTy->elementType();
- if (LookupScope *binding = findClass(type, scope))
+ if (ClassOrNamespace *binding
+ = findClassForTemplateParameterInExpressionScope(r.binding(),
+ type)) {
+ return binding;
+ }
+ if (ClassOrNamespace *binding = findClass(type, scope))
return binding;
- } else if (LookupScope *binding = findClass(ty, scope, r.binding())) {
- // lookup for overloads of operator->
-
- const OperatorNameId *arrowOp
- = control()->operatorNameId(OperatorNameId::ArrowOp);
- foreach (const LookupItem &r, binding->find(arrowOp)) {
- Symbol *overload = r.declaration();
- if (! overload)
- continue;
- Scope *functionScope = overload->enclosingScope();
+ } else {
+ ClassOrNamespace *binding
+ = findClassForTemplateParameterInExpressionScope(r.binding(),
+ ty);
- if (Function *funTy = overload->type()->asFunctionType()) {
- FullySpecifiedType retTy = funTy->returnType().simplified();
+ if (! binding)
+ binding = findClass(ty, scope, r.binding());
- typeResolver.resolve(&retTy, &functionScope, r.binding());
+ if (binding){
+ // lookup for overloads of operator->
- if (! retTy->isPointerType() && ! retTy->isNamedType())
+ const OperatorNameId *arrowOp
+ = control()->operatorNameId(OperatorNameId::ArrowOp);
+ foreach (const LookupItem &r, binding->find(arrowOp)) {
+ Symbol *overload = r.declaration();
+ if (! overload)
continue;
+ Scope *functionScope = overload->enclosingScope();
+
+ if (overload->type()->isFunctionType()) {
+ FullySpecifiedType overloadTy
+ = instantiate(binding->templateId(), overload);
+ Function *instantiatedFunction = overloadTy->asFunctionType();
+ Q_ASSERT(instantiatedFunction != 0);
+
+ FullySpecifiedType retTy
+ = instantiatedFunction->returnType().simplified();
+
+ typedefsResolver.resolve(&retTy, &functionScope, r.binding());
- if (PointerType *ptrTy = retTy->asPointerType())
- retTy = ptrTy->elementType();
+ if (! retTy->isPointerType() && ! retTy->isNamedType())
+ continue;
- if (LookupScope *retBinding = findClass(retTy, functionScope))
- return retBinding;
+ if (PointerType *ptrTy = retTy->asPointerType())
+ retTy = ptrTy->elementType();
- if (scope != functionScope) {
- if (LookupScope *retBinding = findClass(retTy, scope))
+ if (ClassOrNamespace *retBinding = findClass(retTy, functionScope))
return retBinding;
- }
- if (LookupScope *origin = binding->instantiationOrigin()) {
- foreach (Symbol *originSymbol, origin->symbols()) {
- Scope *originScope = originSymbol->asScope();
- if (originScope && originScope != scope
- && originScope != functionScope) {
- if (LookupScope *retBinding
- = findClass(retTy, originScope))
- return retBinding;
+ if (scope != functionScope) {
+ if (ClassOrNamespace *retBinding = findClass(retTy, scope))
+ return retBinding;
+ }
+
+ if (ClassOrNamespace *origin = binding->instantiationOrigin()) {
+ foreach (Symbol *originSymbol, origin->symbols()) {
+ Scope *originScope = originSymbol->asScope();
+ if (originScope && originScope != scope
+ && originScope != functionScope) {
+ if (ClassOrNamespace *retBinding
+ = findClass(retTy, originScope))
+ return retBinding;
+ }
}
}
}
@@ -894,13 +1143,19 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu
ty = ptrTy->elementType();
}
- LookupScope *enclosingBinding = 0;
- if (LookupScope *binding = r.binding()) {
+ if (ClassOrNamespace *binding
+ = findClassForTemplateParameterInExpressionScope(r.binding(),
+ ty)) {
+ return binding;
+ }
+
+ ClassOrNamespace *enclosingBinding = 0;
+ if (ClassOrNamespace *binding = r.binding()) {
if (binding->instantiationOrigin())
enclosingBinding = binding;
}
- if (LookupScope *binding = findClass(ty, scope, enclosingBinding))
+ if (ClassOrNamespace *binding = findClass(ty, scope, enclosingBinding))
return binding;
}
}
@@ -908,6 +1163,30 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu
return 0;
}
+ClassOrNamespace *ResolveExpression::findClassForTemplateParameterInExpressionScope(
+ ClassOrNamespace *resultBinding,
+ const FullySpecifiedType &ty) const
+{
+ if (resultBinding) {
+ if (ClassOrNamespace *origin = resultBinding->instantiationOrigin()) {
+ foreach (Symbol *originSymbol, origin->symbols()) {
+ if (Scope *originScope = originSymbol->asScope()) {
+ if (ClassOrNamespace *retBinding = findClass(ty, originScope))
+ return retBinding;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+FullySpecifiedType ResolveExpression::instantiate(const Name *className, Symbol *candidate) const
+{
+ return DeprecatedGenTemplateInstance::instantiate(className, candidate,
+ _context.bindings()->control());
+}
+
bool ResolveExpression::visit(PostIncrDecrAST *ast)
{
const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
@@ -921,7 +1200,7 @@ bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
foreach (const LookupItem &result, receiverResults) {
FullySpecifiedType ty = result.type().simplified();
- LookupScope *binding = 0;
+ ClassOrNamespace *binding = 0;
if (ObjCClass *clazz = ty->asObjCClassType()) {
// static access, e.g.:
diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h
index df9ea22020..aee53c40fa 100644
--- a/src/libs/cplusplus/ResolveExpression.h
+++ b/src/libs/cplusplus/ResolveExpression.h
@@ -53,25 +53,26 @@ public:
QList<LookupItem> resolve(ExpressionAST *ast, Scope *scope, bool ref = false);
QList<LookupItem> reference(ExpressionAST *ast, Scope *scope);
- LookupScope *baseExpression(const QList<LookupItem> &baseResults,
+ ClassOrNamespace *baseExpression(const QList<LookupItem> &baseResults,
int accessOp,
bool *replacedDotOperator = 0) const;
const LookupContext &context() const;
protected:
- LookupScope *findClass(const FullySpecifiedType &ty, Scope *scope,
- LookupScope *enclosingBinding = 0) const;
+ ClassOrNamespace *findClass(const FullySpecifiedType &ty, Scope *scope,
+ ClassOrNamespace *enclosingBinding = 0) const;
QList<LookupItem> expression(ExpressionAST *ast);
QList<LookupItem> switchResults(const QList<LookupItem> &symbols);
+ FullySpecifiedType instantiate(const Name *className, Symbol *candidate) const;
- QList<LookupItem> getMembers(LookupScope *binding, const Name *memberName) const;
+ QList<LookupItem> getMembers(ClassOrNamespace *binding, const Name *memberName) const;
void thisObject();
- void addResult(const FullySpecifiedType &ty, Scope *scope, LookupScope *binding = 0);
+ void addResult(const FullySpecifiedType &ty, Scope *scope, ClassOrNamespace *binding = 0);
void addResults(const QList<Symbol *> &symbols);
void addResults(const QList<LookupItem> &items);
@@ -125,6 +126,10 @@ protected:
private:
+ ClassOrNamespace *findClassForTemplateParameterInExpressionScope(
+ ClassOrNamespace *resultBinding,
+ const FullySpecifiedType &ty) const;
+
Scope *_scope;
const LookupContext& _context;
Bind bind;
diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp
index bc0792262a..8d5be1b251 100644
--- a/src/libs/cplusplus/TypeOfExpression.cpp
+++ b/src/libs/cplusplus/TypeOfExpression.cpp
@@ -50,7 +50,7 @@ TypeOfExpression::TypeOfExpression():
}
void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot,
- CreateBindings::Ptr bindings,
+ QSharedPointer<CreateBindings> bindings,
const QSet<const Declaration *> &autoDeclarationsBeingResolved)
{
m_thisDocument = thisDocument;
@@ -62,7 +62,7 @@ void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot
Q_ASSERT(m_bindings.isNull());
m_bindings = bindings;
if (m_bindings.isNull())
- m_bindings = CreateBindings::Ptr(new CreateBindings(thisDocument, snapshot));
+ m_bindings = QSharedPointer<CreateBindings>(new CreateBindings(thisDocument, snapshot));
m_environment.clear();
m_autoDeclarationsBeingResolved = autoDeclarationsBeingResolved;
@@ -105,7 +105,7 @@ QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression,
m_scope = scope;
- m_bindings->addExpressionDocument(document);
+ m_documents.append(document);
m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot, m_bindings);
Q_ASSERT(!m_bindings.isNull());
m_lookupContext.setExpandTemplates(m_expandTemplates);
@@ -122,7 +122,7 @@ QList<LookupItem> TypeOfExpression::reference(ExpressionAST *expression,
m_scope = scope;
- m_bindings->addExpressionDocument(document);
+ m_documents.append(document);
m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot, m_bindings);
Q_ASSERT(!m_bindings.isNull());
m_lookupContext.setExpandTemplates(m_expandTemplates);
diff --git a/src/libs/cplusplus/TypeOfExpression.h b/src/libs/cplusplus/TypeOfExpression.h
index 0308f9a45e..158b3e9815 100644
--- a/src/libs/cplusplus/TypeOfExpression.h
+++ b/src/libs/cplusplus/TypeOfExpression.h
@@ -62,7 +62,7 @@ public:
*/
void init(Document::Ptr thisDocument,
const Snapshot &snapshot,
- CreateBindings::Ptr bindings = CreateBindings::Ptr(),
+ QSharedPointer<CreateBindings> bindings = QSharedPointer<CreateBindings>(),
const QSet<const Declaration *> &autoDeclarationsBeingResolved
= QSet<const Declaration *>());
@@ -135,6 +135,7 @@ public:
}
private:
+
void processEnvironment(Document::Ptr doc, Environment *env,
QSet<QString> *processed) const;
@@ -142,13 +143,20 @@ private:
private:
Document::Ptr m_thisDocument;
Snapshot m_snapshot;
- CreateBindings::Ptr m_bindings;
+ QSharedPointer<CreateBindings> m_bindings;
ExpressionAST *m_ast;
Scope *m_scope;
LookupContext m_lookupContext;
mutable QSharedPointer<Environment> m_environment;
- QSet<const Declaration *> m_autoDeclarationsBeingResolved;
+
bool m_expandTemplates;
+
+ // FIXME: This is a temporary hack to avoid dangling pointers.
+ // Keep the expression documents and thus all the symbols and
+ // their types alive until they are not needed any more.
+ QList<Document::Ptr> m_documents;
+
+ QSet<const Declaration *> m_autoDeclarationsBeingResolved;
};
ExpressionAST CPLUSPLUS_EXPORT *extractExpressionAST(Document::Ptr doc);
diff --git a/src/libs/cplusplus/TypeResolver.cpp b/src/libs/cplusplus/TypeResolver.cpp
deleted file mode 100644
index 1be33f1410..0000000000
--- a/src/libs/cplusplus/TypeResolver.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms and
-** conditions see http://www.qt.io/terms-conditions. For further information
-** use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-****************************************************************************/
-
-#include "TypeResolver.h"
-#include "Overview.h"
-#include "TypeOfExpression.h"
-
-#include <QDebug>
-
-static const bool debug = ! qgetenv("QTC_LOOKUPCONTEXT_DEBUG").isEmpty();
-
-namespace CPlusPlus {
-
-namespace {
-
-class DeduceAutoCheck : public ASTVisitor
-{
-public:
- DeduceAutoCheck(const Identifier *id, TranslationUnit *tu)
- : ASTVisitor(tu), _id(id), _block(false)
- {
- accept(tu->ast());
- }
-
- virtual bool preVisit(AST *)
- {
- if (_block)
- return false;
-
- return true;
- }
-
- virtual bool visit(SimpleNameAST *ast)
- {
- if (ast->name
- && ast->name->identifier()
- && strcmp(ast->name->identifier()->chars(), _id->chars()) == 0) {
- _block = true;
- }
-
- return false;
- }
-
- virtual bool visit(MemberAccessAST *ast)
- {
- accept(ast->base_expression);
- return false;
- }
-
- const Identifier *_id;
- bool _block;
-};
-
-} // namespace anonymous
-
-void TypeResolver::resolve(FullySpecifiedType *type, Scope **scope, LookupScope *binding)
-{
- QSet<Symbol *> visited;
- _binding = binding;
- // Use a hard limit when trying to resolve typedefs. Typedefs in templates can refer to
- // each other, each time enhancing the template argument and thus making it impossible to
- // use an "alreadyResolved" container. FIXME: We might overcome this by resolving the
- // template parameters.
- unsigned maxDepth = 15;
- Overview oo;
- if (Q_UNLIKELY(debug))
- qDebug() << "- before typedef resolving we have:" << oo(*type);
- for (NamedType *namedTy = 0; maxDepth && (namedTy = getNamedType(*type)); --maxDepth) {
- QList<LookupItem> namedTypeItems = getNamedTypeItems(namedTy->name(), *scope, _binding);
-
- if (Q_UNLIKELY(debug))
- qDebug() << "-- we have" << namedTypeItems.size() << "candidates";
-
- if (!findTypedef(namedTypeItems, type, scope, visited))
- break;
- }
- if (Q_UNLIKELY(debug))
- qDebug() << "- after typedef resolving:" << oo(*type);
-}
-
-NamedType *TypeResolver::getNamedType(FullySpecifiedType &type) const
-{
- NamedType *namedTy = type->asNamedType();
- if (! namedTy) {
- if (PointerType *pointerTy = type->asPointerType())
- namedTy = pointerTy->elementType()->asNamedType();
- }
- return namedTy;
-}
-
-QList<LookupItem> TypeResolver::getNamedTypeItems(const Name *name, Scope *scope,
- LookupScope *binding) const
-{
- QList<LookupItem> namedTypeItems = typedefsFromScopeUpToFunctionScope(name, scope);
- if (namedTypeItems.isEmpty()) {
- if (binding)
- namedTypeItems = binding->lookup(name);
- if (LookupScope *scopeCon = _factory.lookupType(scope)) {
- if (scopeCon != binding)
- namedTypeItems += scopeCon->lookup(name);
- }
- }
-
- return namedTypeItems;
-}
-
-/// Return all typedefs with given name from given scope up to function scope.
-QList<LookupItem> TypeResolver::typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope)
-{
- QList<LookupItem> results;
- if (!scope)
- return results;
- Scope *enclosingBlockScope = 0;
- for (Block *block = scope->asBlock(); block;
- block = enclosingBlockScope ? enclosingBlockScope->asBlock() : 0) {
- const unsigned memberCount = block->memberCount();
- for (unsigned i = 0; i < memberCount; ++i) {
- Symbol *symbol = block->memberAt(i);
- if (Declaration *declaration = symbol->asDeclaration()) {
- if (isTypedefWithName(declaration, name)) {
- LookupItem item;
- item.setDeclaration(declaration);
- item.setScope(block);
- item.setType(declaration->type());
- results.append(item);
- }
- }
- }
- enclosingBlockScope = block->enclosingScope();
- if (enclosingBlockScope) {
- // For lambda, step beyond the function to its enclosing block
- if (Function *enclosingFunction = enclosingBlockScope->asFunction()) {
- if (!enclosingFunction->name())
- enclosingBlockScope = enclosingBlockScope->enclosingScope();
- }
- }
- }
- return results;
-}
-
-// Resolves auto and decltype initializer string
-QList<LookupItem> TypeResolver::resolveDeclInitializer(
- CreateBindings &factory, const Declaration *decl,
- const QSet<const Declaration* > &declarationsBeingResolved,
- const Identifier *id)
-{
- const StringLiteral *initializationString = decl->getInitializer();
- if (initializationString == 0)
- return QList<LookupItem>();
-
- const QByteArray &initializer =
- QByteArray::fromRawData(initializationString->chars(),
- initializationString->size()).trimmed();
-
- // Skip lambda-function initializers
- if (initializer.length() > 0 && initializer[0] == '[')
- return QList<LookupItem>();
-
- TypeOfExpression exprTyper;
- exprTyper.setExpandTemplates(true);
- Document::Ptr doc = factory.snapshot().document(QString::fromLocal8Bit(decl->fileName()));
- exprTyper.init(doc, factory.snapshot(), factory.sharedFromThis(), declarationsBeingResolved);
-
- Document::Ptr exprDoc =
- documentForExpression(exprTyper.preprocessedExpression(initializer));
- factory.addExpressionDocument(exprDoc);
- exprDoc->check();
-
- if (id) {
- DeduceAutoCheck deduceAuto(id, exprDoc->translationUnit());
- if (deduceAuto._block)
- return QList<LookupItem>();
- }
-
- return exprTyper(extractExpressionAST(exprDoc), exprDoc, decl->enclosingScope());
-}
-
-bool TypeResolver::isTypedefWithName(const Declaration *declaration, const Name *name)
-{
- if (declaration->isTypedef()) {
- const Identifier *identifier = declaration->name()->identifier();
- if (name->identifier()->match(identifier))
- return true;
- }
- return false;
-}
-
-bool TypeResolver::findTypedef(const QList<LookupItem> &namedTypeItems, FullySpecifiedType *type,
- Scope **scope, QSet<Symbol *> &visited)
-{
- foreach (const LookupItem &it, namedTypeItems) {
- Symbol *declaration = it.declaration();
- if (!declaration)
- continue;
- if (Template *specialization = declaration->asTemplate())
- declaration = specialization->declaration();
- if (!declaration || (!declaration->isTypedef() && !declaration->type().isDecltype()))
- continue;
- if (visited.contains(declaration))
- break;
- visited.insert(declaration);
-
- // continue working with the typedefed type and scope
- if (type->type()->isPointerType()) {
- *type = FullySpecifiedType(
- _factory.control()->pointerType(declaration->type()));
- } else if (type->type()->isReferenceType()) {
- *type = FullySpecifiedType(
- _factory.control()->referenceType(
- declaration->type(),
- declaration->type()->asReferenceType()->isRvalueReference()));
- } else if (declaration->type().isDecltype()) {
- Declaration *decl = declaration->asDeclaration();
- const QList<LookupItem> resolved =
- resolveDeclInitializer(_factory, decl, QSet<const Declaration* >() << decl);
- if (!resolved.isEmpty()) {
- LookupItem item = resolved.first();
- *type = item.type();
- *scope = item.scope();
- _binding = item.binding();
- return true;
- }
- } else {
- *type = it.type();
- }
-
- *scope = it.scope();
- _binding = it.binding();
- return true;
- }
-
- return false;
-}
-
-} // namespace CPlusPlus
diff --git a/src/libs/cplusplus/cplusplus-lib.pri b/src/libs/cplusplus/cplusplus-lib.pri
index ebb5ad07f1..0e5bed22e0 100644
--- a/src/libs/cplusplus/cplusplus-lib.pri
+++ b/src/libs/cplusplus/cplusplus-lib.pri
@@ -36,7 +36,6 @@ HEADERS += \
$$PWD/NamePrettyPrinter.h \
$$PWD/TypeOfExpression.h \
$$PWD/TypePrettyPrinter.h \
- $$PWD/TypeResolver.h \
$$PWD/ResolveExpression.h \
$$PWD/LookupItem.h \
$$PWD/AlreadyConsideredClassContainer.h \
@@ -45,6 +44,7 @@ HEADERS += \
$$PWD/ASTPath.h \
$$PWD/SnapshotSymbolVisitor.h \
$$PWD/SymbolNameVisitor.h \
+ $$PWD/DeprecatedGenTemplateInstance.h \
$$PWD/FindUsages.h \
$$PWD/DependencyTable.h \
$$PWD/PreprocessorClient.h \
@@ -67,7 +67,6 @@ SOURCES += \
$$PWD/NamePrettyPrinter.cpp \
$$PWD/TypeOfExpression.cpp \
$$PWD/TypePrettyPrinter.cpp \
- $$PWD/TypeResolver.cpp \
$$PWD/ResolveExpression.cpp \
$$PWD/LookupItem.cpp \
$$PWD/LookupContext.cpp \
@@ -75,6 +74,7 @@ SOURCES += \
$$PWD/ASTPath.cpp \
$$PWD/SnapshotSymbolVisitor.cpp \
$$PWD/SymbolNameVisitor.cpp \
+ $$PWD/DeprecatedGenTemplateInstance.cpp \
$$PWD/FindUsages.cpp \
$$PWD/DependencyTable.cpp \
$$PWD/PreprocessorClient.cpp \
diff --git a/src/libs/cplusplus/cplusplus.qbs b/src/libs/cplusplus/cplusplus.qbs
index 8ac08217eb..dd4012d633 100644
--- a/src/libs/cplusplus/cplusplus.qbs
+++ b/src/libs/cplusplus/cplusplus.qbs
@@ -96,6 +96,7 @@ QtcLibrary {
"CppRewriter.cpp", "CppRewriter.h",
"cppmodelmanagerbase.cpp", "cppmodelmanagerbase.h",
"DependencyTable.cpp", "DependencyTable.h",
+ "DeprecatedGenTemplateInstance.cpp", "DeprecatedGenTemplateInstance.h",
"ExpressionUnderCursor.cpp", "ExpressionUnderCursor.h",
"FastPreprocessor.cpp", "FastPreprocessor.h",
"FindUsages.cpp", "FindUsages.h",
@@ -116,7 +117,6 @@ QtcLibrary {
"SymbolNameVisitor.cpp", "SymbolNameVisitor.h",
"TypeOfExpression.cpp", "TypeOfExpression.h",
"TypePrettyPrinter.cpp", "TypePrettyPrinter.h",
- "TypeResolver.cpp", "TypeResolver.h",
"cplusplus.qrc",
"findcdbbreakpoint.cpp", "findcdbbreakpoint.h",
"pp-cctype.h",
diff --git a/src/libs/qmljs/qmljsfindexportedcpptypes.cpp b/src/libs/qmljs/qmljsfindexportedcpptypes.cpp
index f7edb410d2..cf1dde0819 100644
--- a/src/libs/qmljs/qmljsfindexportedcpptypes.cpp
+++ b/src/libs/qmljs/qmljsfindexportedcpptypes.cpp
@@ -795,7 +795,7 @@ static void buildContextProperties(
Scope *typeScope = result.scope();
if (!typeScope)
typeScope = scope; // incorrect but may be an ok fallback
- LookupScope *binding = typeOf.context().lookupType(namedType->name(), typeScope);
+ ClassOrNamespace *binding = typeOf.context().lookupType(namedType->name(), typeScope);
if (binding && !binding->symbols().isEmpty()) {
// find the best 'Class' symbol
for (int i = binding->symbols().size() - 1; i >= 0; --i) {
diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index b7f2a915c2..098138eb6d 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -1453,9 +1453,10 @@ void CppQmlTypes::load(const QString &originId, const T &fakeMetaObjects, const
object->setPrototype(proto);
}
}
+
// explicitly instantiate load for list and hash
-template void CppQmlTypes::load< QList<FakeMetaObject::ConstPtr> >(const QString &, const QList<FakeMetaObject::ConstPtr> &, const QString &);
-template void CppQmlTypes::load< QHash<QString, FakeMetaObject::ConstPtr> >(const QString &, const QHash<QString, FakeMetaObject::ConstPtr> &, const QString &);
+template QMLJS_EXPORT void CppQmlTypes::load< QList<FakeMetaObject::ConstPtr> >(const QString &, const QList<FakeMetaObject::ConstPtr> &, const QString &);
+template QMLJS_EXPORT void CppQmlTypes::load< QHash<QString, FakeMetaObject::ConstPtr> >(const QString &, const QHash<QString, FakeMetaObject::ConstPtr> &, const QString &);
QList<const CppComponentValue *> CppQmlTypes::createObjectsForImport(const QString &package, ComponentVersion version)
{
diff --git a/src/libs/sqlite/utf8string.cpp b/src/libs/sqlite/utf8string.cpp
index b4492a9d19..c8cbaea223 100644
--- a/src/libs/sqlite/utf8string.cpp
+++ b/src/libs/sqlite/utf8string.cpp
@@ -158,6 +158,11 @@ bool Utf8String::endsWith(const Utf8String &text) const
return byteArray.endsWith(text.byteArray);
}
+bool Utf8String::isNull() const
+{
+ return byteArray.isNull();
+}
+
bool Utf8String::isEmpty() const
{
return byteArray.isEmpty();
diff --git a/src/libs/sqlite/utf8string.h b/src/libs/sqlite/utf8string.h
index 52c6f46758..c6adfc9371 100644
--- a/src/libs/sqlite/utf8string.h
+++ b/src/libs/sqlite/utf8string.h
@@ -86,6 +86,7 @@ public:
bool startsWith(const char *text) const;
bool startsWith(char character) const;
bool endsWith(const Utf8String &text) const;
+ bool isNull() const;
bool isEmpty() const;
bool hasContent() const;
diff --git a/src/libs/ssh/sshkeygenerator.cpp b/src/libs/ssh/sshkeygenerator.cpp
index 1c6e22db03..6f1800e90d 100644
--- a/src/libs/ssh/sshkeygenerator.cpp
+++ b/src/libs/ssh/sshkeygenerator.cpp
@@ -173,7 +173,7 @@ void SshKeyGenerator::generateOpenSslPublicKeyString(const KeyPtr &key)
void SshKeyGenerator::generateOpenSslPrivateKeyString(const KeyPtr &key)
{
QList<BigInt> params;
- const char *label;
+ const char *label = "";
switch (m_type) {
case Rsa: {
const QSharedPointer<RSA_PrivateKey> rsaKey
@@ -197,6 +197,7 @@ void SshKeyGenerator::generateOpenSslPrivateKeyString(const KeyPtr &key)
case Ecdsa:
params << key.dynamicCast<ECDSA_PrivateKey>()->private_value();
label = "EC PRIVATE KEY";
+ break;
}
DER_Encoder encoder;
diff --git a/src/libs/timeline/qml/CategoryLabel.qml b/src/libs/timeline/qml/CategoryLabel.qml
index 984d23519f..a822ad835d 100644
--- a/src/libs/timeline/qml/CategoryLabel.qml
+++ b/src/libs/timeline/qml/CategoryLabel.qml
@@ -63,6 +63,7 @@ Item {
cursorShape: dragging ? Qt.ClosedHandCursor : Qt.OpenHandCursor
drag.minimumY: dragging ? 0 : -dragOffset // Account for parent change below
drag.maximumY: draggerParent.height - (dragging ? 0 : dragOffset)
+ drag.axis: Drag.YAxis
}
DropArea {
diff --git a/src/libs/timeline/qml/TimelineLabels.qml b/src/libs/timeline/qml/TimelineLabels.qml
index ba3f883a42..c8eb63719b 100644
--- a/src/libs/timeline/qml/TimelineLabels.qml
+++ b/src/libs/timeline/qml/TimelineLabels.qml
@@ -102,7 +102,7 @@ Flickable {
draggerParent: categories
width: 150
height: parent.height
- dragOffset: parent.y
+ dragOffset: loader.y
onDropped: {
categories.moveCategories(sourceIndex, targetIndex);
diff --git a/src/libs/utils/pathchooser.cpp b/src/libs/utils/pathchooser.cpp
index 997f4c2f76..4288979395 100644
--- a/src/libs/utils/pathchooser.cpp
+++ b/src/libs/utils/pathchooser.cpp
@@ -250,6 +250,10 @@ PathChooser::PathChooser(QWidget *parent) :
PathChooser::~PathChooser()
{
+ // Since it is our focusProxy it can receive focus-out and emit the signal
+ // even when the possible ancestor-receiver is in mid of its destruction.
+ disconnect(d->m_lineEdit, &QLineEdit::editingFinished, this, &PathChooser::editingFinished);
+
delete d;
}
diff --git a/src/plugins/baremetal/gdbserverprovider.cpp b/src/plugins/baremetal/gdbserverprovider.cpp
index 5f32c7efbf..cdb88987d4 100644
--- a/src/plugins/baremetal/gdbserverprovider.cpp
+++ b/src/plugins/baremetal/gdbserverprovider.cpp
@@ -67,7 +67,7 @@ GdbServerProvider::GdbServerProvider(const QString &id)
}
GdbServerProvider::GdbServerProvider(const GdbServerProvider &other)
- : m_id(other.m_id)
+ : m_id(createId(other.m_id))
, m_startupMode(other.m_startupMode)
, m_initCommands(other.m_initCommands)
, m_resetCommands(other.m_resetCommands)
diff --git a/src/plugins/clangcodemodel/clangutils.cpp b/src/plugins/clangcodemodel/clangutils.cpp
index fd9064a3f5..28c223d80a 100644
--- a/src/plugins/clangcodemodel/clangutils.cpp
+++ b/src/plugins/clangcodemodel/clangutils.cpp
@@ -41,6 +41,8 @@
#include <cpptools/cppprojects.h>
#include <cpptools/cppworkingcopy.h>
+#include <projectexplorer/projectexplorerconstants.h>
+
#include <utils/qtcassert.h>
#include <QDir>
@@ -122,7 +124,7 @@ public:
optionsBuilder.addToolchainAndProjectDefines();
- optionsBuilder.addResourceDirOptions();
+ optionsBuilder.addPredefinedMacrosAndHeaderPathsOptions();
optionsBuilder.addWrappedQtHeadersIncludePath();
optionsBuilder.addHeaderPathOptions();
optionsBuilder.addProjectConfigFileInclude();
@@ -154,7 +156,21 @@ private:
return false;
}
- void addResourceDirOptions()
+ void addPredefinedMacrosAndHeaderPathsOptions()
+ {
+ if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID)
+ addPredefinedMacrosAndHeaderPathsOptionsForMsvc();
+ else
+ addPredefinedMacrosAndHeaderPathsOptionsForNonMsvc();
+ }
+
+ void addPredefinedMacrosAndHeaderPathsOptionsForMsvc()
+ {
+ add(QLatin1String("-nostdinc"));
+ add(QLatin1String("-undef"));
+ }
+
+ void addPredefinedMacrosAndHeaderPathsOptionsForNonMsvc()
{
static const QString resourceDir = getResourceDir();
if (!resourceDir.isEmpty()) {
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 81c7dc7158..2abdef298b 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -387,7 +387,7 @@ void CppEditorWidget::switchDeclarationDefinition(bool inNextSplit)
} else if (functionDefinitionSymbol) {
const Snapshot snapshot = d->m_modelManager->snapshot();
LookupContext context(d->m_lastSemanticInfo.doc, snapshot);
- LookupScope *binding = context.lookupType(functionDefinitionSymbol);
+ ClassOrNamespace *binding = context.lookupType(functionDefinitionSymbol);
const QList<LookupItem> declarations = context.lookup(functionDefinitionSymbol->name(),
functionDefinitionSymbol->enclosingScope());
diff --git a/src/plugins/cppeditor/cppelementevaluator.cpp b/src/plugins/cppeditor/cppelementevaluator.cpp
index 97b25d723f..6740b935cc 100644
--- a/src/plugins/cppeditor/cppelementevaluator.cpp
+++ b/src/plugins/cppeditor/cppelementevaluator.cpp
@@ -331,10 +331,10 @@ bool CppClass::operator==(const CppClass &other)
void CppClass::lookupBases(Symbol *declaration, const LookupContext &context)
{
- typedef QPair<LookupScope *, CppClass *> Data;
+ typedef QPair<ClassOrNamespace *, CppClass *> Data;
- if (LookupScope *clazz = context.lookupType(declaration)) {
- QSet<LookupScope *> visited;
+ if (ClassOrNamespace *clazz = context.lookupType(declaration)) {
+ QSet<ClassOrNamespace *> visited;
QQueue<Data> q;
q.enqueue(qMakePair(clazz, this));
@@ -342,8 +342,8 @@ void CppClass::lookupBases(Symbol *declaration, const LookupContext &context)
Data current = q.dequeue();
clazz = current.first;
visited.insert(clazz);
- const QList<LookupScope *> &bases = clazz->usings();
- foreach (LookupScope *baseClass, bases) {
+ const QList<ClassOrNamespace *> &bases = clazz->usings();
+ foreach (ClassOrNamespace *baseClass, bases) {
const QList<Symbol *> &symbols = baseClass->symbols();
foreach (Symbol *symbol, symbols) {
if (symbol->isClass() && (
@@ -433,7 +433,7 @@ CppVariable::CppVariable(Symbol *declaration, const LookupContext &context, Scop
}
if (typeName) {
- if (LookupScope *clazz = context.lookupType(typeName, scope)) {
+ if (ClassOrNamespace *clazz = context.lookupType(typeName, scope)) {
if (!clazz->symbols().isEmpty()) {
Overview overview;
Symbol *symbol = clazz->symbols().at(0);
diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
index a166e8d641..407252ca50 100644
--- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
+++ b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp
@@ -38,7 +38,6 @@
#include <cplusplus/ExpressionUnderCursor.h>
#include <cplusplus/ResolveExpression.h>
#include <cplusplus/SimpleLexer.h>
-#include <cplusplus/Templates.h>
#include <cplusplus/TypeOfExpression.h>
#include <cpptools/cppmodelmanager.h>
#include <cpptools/functionutils.h>
@@ -184,7 +183,7 @@ Class *VirtualFunctionHelper::staticClassOfFunctionCallExpression_internal() con
const QList<LookupItem> items = m_typeOfExpression(memberAccessAST->base_expression,
m_expressionDocument, m_scope);
ResolveExpression resolveExpression(m_typeOfExpression.context());
- LookupScope *binding = resolveExpression.baseExpression(items, m_accessTokenKind);
+ ClassOrNamespace *binding = resolveExpression.baseExpression(items, m_accessTokenKind);
if (binding) {
if (Class *klass = binding->rootClass()) {
result = klass;
diff --git a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp
index dfb0b1018a..4c359ed9b6 100644
--- a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp
+++ b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp
@@ -607,7 +607,7 @@ ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targetOffse
SubstitutionEnvironment env;
env.setContext(sourceContext);
env.switchScope(sourceFunction->enclosingScope());
- LookupScope *targetCoN = targetContext.lookupType(targetFunction->enclosingScope());
+ ClassOrNamespace *targetCoN = targetContext.lookupType(targetFunction->enclosingScope());
if (!targetCoN)
targetCoN = targetContext.globalNamespace();
UseMinimalNames q(targetCoN);
@@ -653,7 +653,7 @@ ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targetOffse
SubstitutionEnvironment env;
env.setContext(sourceContext);
env.switchScope(sourceFunction);
- LookupScope *targetCoN = targetContext.lookupType(targetFunction);
+ ClassOrNamespace *targetCoN = targetContext.lookupType(targetFunction);
if (!targetCoN)
targetCoN = targetContext.globalNamespace();
UseMinimalNames q(targetCoN);
diff --git a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp
index 711c1b056d..55ac472eec 100644
--- a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp
+++ b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp
@@ -567,15 +567,15 @@ public:
// Determine base classes
QList<const Class *> baseClasses;
- QQueue<LookupScope *> baseClassQueue;
- QSet<LookupScope *> visitedBaseClasses;
- if (LookupScope *clazz = interface.context().lookupType(m_classAST->symbol))
+ QQueue<ClassOrNamespace *> baseClassQueue;
+ QSet<ClassOrNamespace *> visitedBaseClasses;
+ if (ClassOrNamespace *clazz = interface.context().lookupType(m_classAST->symbol))
baseClassQueue.enqueue(clazz);
while (!baseClassQueue.isEmpty()) {
- LookupScope *clazz = baseClassQueue.dequeue();
+ ClassOrNamespace *clazz = baseClassQueue.dequeue();
visitedBaseClasses.insert(clazz);
- const QList<LookupScope *> bases = clazz->usings();
- foreach (LookupScope *baseClass, bases) {
+ const QList<ClassOrNamespace *> bases = clazz->usings();
+ foreach (ClassOrNamespace *baseClass, bases) {
foreach (Symbol *symbol, baseClass->symbols()) {
Class *base = symbol->asClass();
if (base
@@ -769,7 +769,7 @@ public:
const LookupContext targetContext(headerFile->cppDocument(), snapshot());
const Class *targetClass = m_classAST->symbol;
- LookupScope *targetCoN = targetContext.lookupType(targetClass->enclosingScope());
+ ClassOrNamespace *targetCoN = targetContext.lookupType(targetClass->enclosingScope());
if (!targetCoN)
targetCoN = targetContext.globalNamespace();
UseMinimalNames useMinimalNames(targetCoN);
@@ -866,7 +866,7 @@ public:
implementationDoc->translationUnit()->getPosition(insertPos, &line, &column);
Scope *targetScope = implementationDoc->scopeAt(line, column);
const LookupContext targetContext(implementationDoc, snapshot());
- LookupScope *targetCoN = targetContext.lookupType(targetScope);
+ ClassOrNamespace *targetCoN = targetContext.lookupType(targetScope);
if (!targetCoN)
targetCoN = targetContext.globalNamespace();
diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp
index 176afcb7f9..9ef84adad2 100644
--- a/src/plugins/cppeditor/cppquickfixes.cpp
+++ b/src/plugins/cppeditor/cppquickfixes.cpp
@@ -219,7 +219,7 @@ Class *isMemberFunction(const LookupContext &context, Function *function)
if (!q->base())
return 0;
- if (LookupScope *binding = context.lookupType(q->base(), enclosingScope)) {
+ if (ClassOrNamespace *binding = context.lookupType(q->base(), enclosingScope)) {
foreach (Symbol *s, binding->symbols()) {
if (Class *matchingClass = s->asClass())
return matchingClass;
@@ -257,7 +257,7 @@ Namespace *isNamespaceFunction(const LookupContext &context, Function *function)
if (!q->base())
return 0;
- if (LookupScope *binding = context.lookupType(q->base(), enclosingScope)) {
+ if (ClassOrNamespace *binding = context.lookupType(q->base(), enclosingScope)) {
foreach (Symbol *s, binding->symbols()) {
if (Namespace *matchingNamespace = s->asNamespace())
return matchingNamespace;
@@ -1331,7 +1331,7 @@ void TranslateStringLiteral::match(const CppQuickFixInterface &interface,
for (int i = path.size() - 1; i >= 0; --i) {
if (FunctionDefinitionAST *definition = path.at(i)->asFunctionDefinition()) {
Function *function = definition->symbol;
- LookupScope *b = interface.context().lookupType(function);
+ ClassOrNamespace *b = interface.context().lookupType(function);
if (b) {
// Do we have a tr function?
foreach (const LookupItem &r, b->find(trName)) {
@@ -1592,7 +1592,7 @@ public:
SubstitutionEnvironment env;
env.setContext(context());
env.switchScope(result.first().scope());
- LookupScope *con = typeOfExpression.context().lookupType(scope);
+ ClassOrNamespace *con = typeOfExpression.context().lookupType(scope);
if (!con)
con = typeOfExpression.context().globalNamespace();
UseMinimalNames q(con);
@@ -2284,7 +2284,7 @@ Enum *findEnum(const QList<LookupItem> &results, const LookupContext &ctxt)
if (Enum *e = type->asEnumType())
return e;
if (const NamedType *namedType = type->asNamedType()) {
- if (LookupScope *con = ctxt.lookupType(namedType->name(), result.scope())) {
+ if (ClassOrNamespace *con = ctxt.lookupType(namedType->name(), result.scope())) {
const QList<Enum *> enums = con->unscopedEnums();
const Name *referenceName = namedType->name();
if (const QualifiedNameId *qualifiedName = referenceName->asQualifiedNameId())
@@ -2581,7 +2581,7 @@ public:
Document::Ptr targetDoc = targetFile->cppDocument();
Scope *targetScope = targetDoc->scopeAt(m_loc.line(), m_loc.column());
LookupContext targetContext(targetDoc, snapshot());
- LookupScope *targetCoN = targetContext.lookupType(targetScope);
+ ClassOrNamespace *targetCoN = targetContext.lookupType(targetScope);
if (!targetCoN)
targetCoN = targetContext.globalNamespace();
@@ -3215,7 +3215,7 @@ public:
SubstitutionEnvironment env;
env.setContext(context());
env.switchScope(refFunc);
- LookupScope *targetCoN = context().lookupType(refFunc->enclosingScope());
+ ClassOrNamespace *targetCoN = context().lookupType(refFunc->enclosingScope());
if (!targetCoN)
targetCoN = context().globalNamespace();
UseMinimalNames subs(targetCoN);
@@ -4644,7 +4644,7 @@ QString definitionSignature(const CppQuickFixInterface *assist,
QTC_ASSERT(func, return QString());
LookupContext cppContext(targetFile->cppDocument(), assist->snapshot());
- LookupScope *cppCoN = cppContext.lookupType(scope);
+ ClassOrNamespace *cppCoN = cppContext.lookupType(scope);
if (!cppCoN)
cppCoN = cppContext.globalNamespace();
SubstitutionEnvironment env;
@@ -5125,7 +5125,7 @@ public:
SubstitutionEnvironment env;
env.setContext(context());
env.switchScope(result.first().scope());
- LookupScope *con = typeOfExpression.context().lookupType(scope);
+ ClassOrNamespace *con = typeOfExpression.context().lookupType(scope);
if (!con)
con = typeOfExpression.context().globalNamespace();
UseMinimalNames q(con);
@@ -5724,7 +5724,7 @@ PointerType *determineConvertedType(NamedType *namedType, const LookupContext &c
{
if (!namedType)
return 0;
- if (LookupScope *binding = context.lookupType(namedType->name(), scope)) {
+ if (ClassOrNamespace *binding = context.lookupType(namedType->name(), scope)) {
if (Symbol *objectClassSymbol = skipForwardDeclarations(binding->symbols())) {
if (Class *klass = objectClassSymbol->asClass()) {
for (auto it = klass->memberBegin(), end = klass->memberEnd(); it != end; ++it) {
@@ -5782,7 +5782,7 @@ Class *senderOrReceiverClass(const CppQuickFixInterface &interface,
NamedType *objectType = objectTypeBase->asNamedType();
QTC_ASSERT(objectType, return 0);
- LookupScope *objectClassCON = context.lookupType(objectType->name(), objectPointerScope);
+ ClassOrNamespace *objectClassCON = context.lookupType(objectType->name(), objectPointerScope);
QTC_ASSERT(objectClassCON, return 0);
QTC_ASSERT(!objectClassCON->symbols().isEmpty(), return 0);
@@ -5834,7 +5834,7 @@ bool findConnectReplacement(const CppQuickFixInterface &interface,
// Minimize qualification
Control *control = context.bindings()->control().data();
- LookupScope *functionCON = context.lookupParent(scope);
+ ClassOrNamespace *functionCON = context.lookupParent(scope);
const Name *shortName = LookupContext::minimalName(method, functionCON, control);
if (!shortName->asQualifiedNameId())
shortName = control->qualifiedNameId(classOfMethod->name(), shortName);
diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
index 61828f1631..3b4ba8baf5 100644
--- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
+++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp
@@ -152,8 +152,8 @@ public:
QTC_ASSERT(m_params.staticClass, return 0);
QTC_ASSERT(!m_params.snapshot.isEmpty(), return 0);
- Class *functionsClass = m_finder.findMatchingClassDeclaration(
- m_params.function, m_params.snapshot, &m_params.typeOfExpression->context());
+ Class *functionsClass = m_finder.findMatchingClassDeclaration(m_params.function,
+ m_params.snapshot);
if (!functionsClass)
return 0;
diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
index 956b02b5d9..fbcda2628e 100644
--- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
+++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp
@@ -972,20 +972,6 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_data()
"template<class $T>\n"
"using Foo = Bar<@T>;\n"
);
-
- QTest::newRow("qualifiedNames") << _(
- "struct C\n"
- "{\n"
- " struct Nested { int $member; };\n"
- " void f();\n"
- "};\n"
- "\n"
- "void C::f()\n"
- "{\n"
- " C::Nested object;\n"
- " object.@member;\n"
- "}\n"
- );
}
void CppEditorPlugin::test_FollowSymbolUnderCursor()
@@ -1390,7 +1376,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_data()
"template <class T> struct A { virtual void virt() {} };\n"
"void f(A<int> *l) { l->$@virt(); }\n")
<< (OverrideItemList()
- << OverrideItem(QLatin1String("A<int>::virt"), 1));
+ << OverrideItem(QLatin1String("A::virt"), 1));
/// Check: Static type is nicely resolved, especially for QSharedPointers.
QTest::newRow("QSharedPointer") << _(
diff --git a/src/plugins/cpptools/cppchecksymbols.cpp b/src/plugins/cpptools/cppchecksymbols.cpp
index acf3d5c86f..cbc6baf75e 100644
--- a/src/plugins/cpptools/cppchecksymbols.cpp
+++ b/src/plugins/cpptools/cppchecksymbols.cpp
@@ -669,7 +669,7 @@ bool CheckSymbols::visit(NewExpressionAST *ast)
if (highlightCtorDtorAsType) {
accept(ast->new_type_id);
} else {
- LookupScope *binding = 0;
+ ClassOrNamespace *binding = 0;
NameAST *nameAST = 0;
if (ast->new_type_id) {
for (SpecifierListAST *it = ast->new_type_id->type_specifier_list; it; it = it->next) {
@@ -735,7 +735,7 @@ void CheckSymbols::checkNamespace(NameAST *name)
unsigned line, column;
getTokenStartPosition(name->firstToken(), &line, &column);
- if (LookupScope *b = _context.lookupType(name->name, enclosingScope())) {
+ if (ClassOrNamespace *b = _context.lookupType(name->name, enclosingScope())) {
foreach (Symbol *s, b->symbols()) {
if (s->isNamespace())
return;
@@ -768,14 +768,14 @@ bool CheckSymbols::hasVirtualDestructor(Class *klass) const
return false;
}
-bool CheckSymbols::hasVirtualDestructor(LookupScope *binding) const
+bool CheckSymbols::hasVirtualDestructor(ClassOrNamespace *binding) const
{
- QSet<LookupScope *> processed;
- QList<LookupScope *> todo;
+ QSet<ClassOrNamespace *> processed;
+ QList<ClassOrNamespace *> todo;
todo.append(binding);
while (!todo.isEmpty()) {
- LookupScope *b = todo.takeFirst();
+ ClassOrNamespace *b = todo.takeFirst();
if (b && !processed.contains(b)) {
processed.insert(b);
foreach (Symbol *s, b->symbols()) {
@@ -857,7 +857,7 @@ bool CheckSymbols::visit(QualifiedNameAST *ast)
{
if (ast->name) {
- LookupScope *binding = checkNestedName(ast);
+ ClassOrNamespace *binding = checkNestedName(ast);
if (binding && ast->unqualified_name) {
if (ast->unqualified_name->asDestructorName() != 0) {
@@ -886,9 +886,9 @@ bool CheckSymbols::visit(QualifiedNameAST *ast)
return false;
}
-LookupScope *CheckSymbols::checkNestedName(QualifiedNameAST *ast)
+ClassOrNamespace *CheckSymbols::checkNestedName(QualifiedNameAST *ast)
{
- LookupScope *binding = 0;
+ ClassOrNamespace *binding = 0;
if (ast->name) {
if (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list) {
@@ -954,7 +954,7 @@ bool CheckSymbols::visit(MemInitializerAST *ast)
{
if (FunctionDefinitionAST *enclosingFunction = enclosingFunctionDefinition()) {
if (ast->name && enclosingFunction->symbol) {
- if (LookupScope *binding = _context.lookupType(enclosingFunction->symbol)) {
+ if (ClassOrNamespace *binding = _context.lookupType(enclosingFunction->symbol)) {
foreach (Symbol *s, binding->symbols()) {
if (Class *klass = s->asClass()) {
NameAST *nameAST = ast->name;
@@ -1157,7 +1157,7 @@ void CheckSymbols::addUse(const Result &use)
_usages.append(use);
}
-void CheckSymbols::addType(LookupScope *b, NameAST *ast)
+void CheckSymbols::addType(ClassOrNamespace *b, NameAST *ast)
{
unsigned startToken;
if (!b || !acceptName(ast, &startToken))
@@ -1296,8 +1296,12 @@ bool CheckSymbols::maybeAddFunction(const QList<LookupItem> &candidates, NameAST
isConstructor = isConstructorDeclaration(c);
Function *funTy = c->type()->asFunctionType();
- if (!funTy) // Template function has an overridden type
- funTy = r.type()->asFunctionType();
+ if (!funTy) {
+ //Try to find a template function
+ if (Template * t = r.type()->asTemplateType())
+ if ((c = t->declaration()))
+ funTy = c->type()->asFunctionType();
+ }
if (!funTy || funTy->isAmbiguous())
continue; // TODO: add diagnostic messages and color call-operators calls too?
diff --git a/src/plugins/cpptools/cppchecksymbols.h b/src/plugins/cpptools/cppchecksymbols.h
index 11cde21146..f874c16323 100644
--- a/src/plugins/cpptools/cppchecksymbols.h
+++ b/src/plugins/cpptools/cppchecksymbols.h
@@ -105,7 +105,7 @@ protected:
const QList<Result> &otherUses);
bool hasVirtualDestructor(CPlusPlus::Class *klass) const;
- bool hasVirtualDestructor(CPlusPlus::LookupScope *binding) const;
+ bool hasVirtualDestructor(CPlusPlus::ClassOrNamespace *binding) const;
bool warning(unsigned line, unsigned column, const QString &text, unsigned length = 0);
bool warning(CPlusPlus::AST *ast, const QString &text);
@@ -119,13 +119,13 @@ protected:
void checkNamespace(CPlusPlus::NameAST *name);
void checkName(CPlusPlus::NameAST *ast, CPlusPlus::Scope *scope = 0);
- CPlusPlus::LookupScope *checkNestedName(CPlusPlus::QualifiedNameAST *ast);
+ CPlusPlus::ClassOrNamespace *checkNestedName(CPlusPlus::QualifiedNameAST *ast);
void addUse(const Result &use);
void addUse(unsigned tokenIndex, Kind kind);
void addUse(CPlusPlus::NameAST *name, Kind kind);
- void addType(CPlusPlus::LookupScope *b, CPlusPlus::NameAST *ast);
+ void addType(CPlusPlus::ClassOrNamespace *b, CPlusPlus::NameAST *ast);
bool maybeAddTypeOrStatic(const QList<CPlusPlus::LookupItem> &candidates,
CPlusPlus::NameAST *ast);
diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp
index 02cc06848f..7deb309f58 100644
--- a/src/plugins/cpptools/cppcompletion_test.cpp
+++ b/src/plugins/cpptools/cppcompletion_test.cpp
@@ -328,17 +328,16 @@ void CppToolsPlugin::test_completion()
actualCompletions.sort();
expectedCompletions.sort();
- QEXPECT_FAIL("template_as_base: typedef not available in derived",
- "We can live with that...", Abort);
- QEXPECT_FAIL("template_specialization_with_reference", "test of reverted change", Abort);
- QEXPECT_FAIL("specialization_multiple_arguments", "test of reverted change", Abort);
- QEXPECT_FAIL("specialization_with_default_value", "test of reverted change", Abort);
+ QEXPECT_FAIL("template_as_base: explicit typedef from base", "QTCREATORBUG-14218", Abort);
QEXPECT_FAIL("enum_in_function_in_struct_in_function", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("enum_in_function_in_struct_in_function_cxx11", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("enum_in_function_in_struct_in_function_anon", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("enum_in_class_accessed_in_member_func_cxx11", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("enum_in_class_accessed_in_member_func_inline_cxx11", "QTCREATORBUG-13757", Abort);
- QEXPECT_FAIL("recursive_instantiation_of_template_type", "QTCREATORBUG-14237", Abort);
+ QEXPECT_FAIL("pointer_indirect_specialization", "QTCREATORBUG-14141", Abort);
+ QEXPECT_FAIL("pointer_indirect_specialization_typedef", "QTCREATORBUG-14141", Abort);
+ QEXPECT_FAIL("pointer_indirect_specialization_double_indirection", "QTCREATORBUG-14141", Abort);
+ QEXPECT_FAIL("pointer_indirect_specialization_double_indirection_with_base", "QTCREATORBUG-14141", Abort);
QCOMPARE(actualCompletions, expectedCompletions);
}
@@ -802,21 +801,6 @@ void CppToolsPlugin::test_completion_data()
<< QLatin1String("Data")
<< QLatin1String("dataMember"));
- QTest::newRow("explicit_instantiation") << _(
- "template<class T>\n"
- "struct Foo { T bar; };\n"
- "\n"
- "template class Foo<int>;\n"
- "\n"
- "void func()\n"
- "{\n"
- " Foo<int> foo;\n"
- " @\n"
- "}\n"
- ) << _("foo.") << (QStringList()
- << QLatin1String("Foo")
- << QLatin1String("bar"));
-
QTest::newRow("use_global_identifier_as_base_class: derived as global and base as global") << _(
"struct Global\n"
"{\n"
@@ -1327,28 +1311,21 @@ void CppToolsPlugin::test_completion_data()
<< QLatin1String("Template1"));
QTest::newRow("template_specialization_with_pointer") << _(
- "template <typename T> struct Temp { T variable; };\n"
- "template <typename T> struct Temp<T *> { T *pointer; };\n"
- "void func()\n"
+ "template <typename T>\n"
+ "struct Template\n"
"{\n"
- " Temp<int*> templ;\n"
- " @\n"
- "}"
- ) << _("templ.") << (QStringList()
- << QLatin1String("Temp")
- << QLatin1String("pointer"));
-
- QTest::newRow("template_specialization_with_reference") << _(
- "template <typename T> struct Temp { T variable; };\n"
- "template <typename T> struct Temp<T &> { T reference; };\n"
- "void func()\n"
+ " T variable;\n"
+ "};\n"
+ "template <typename T>\n"
+ "struct Template<T *>\n"
"{\n"
- " Temp<int&> templ;\n"
- " @\n"
- "}"
+ " T *pointer;\n"
+ "};\n"
+ "Template<int*> templ;\n"
+ "@\n"
) << _("templ.") << (QStringList()
- << QLatin1String("Temp")
- << QLatin1String("reference"));
+ << QLatin1String("Template")
+ << QLatin1String("pointer"));
QTest::newRow("typedef_using_templates1") << _(
"namespace NS1\n"
@@ -1572,29 +1549,6 @@ void CppToolsPlugin::test_completion_data()
<< QLatin1String("C")
<< QLatin1String("m"));
- QTest::newRow("type_and_using_declaration: type in nested namespace and using in global") << _(
- "namespace Ns {\n"
- "namespace Nested {\n"
- "struct Foo\n"
- "{\n"
- " void func();\n"
- " int m_bar;\n"
- "};\n"
- "}\n"
- "}\n"
- "\n"
- "using namespace Ns::Nested;\n"
- "\n"
- "namespace Ns\n"
- "{\n"
- "void Foo::func()\n"
- "{\n"
- " @\n"
- "}\n"
- "}\n"
- ) << _("m_") << (QStringList()
- << QLatin1String("m_bar"));
-
QTest::newRow("instantiate_template_with_anonymous_class") << _(
"template <typename T>\n"
"struct S\n"
@@ -2568,21 +2522,6 @@ void CppToolsPlugin::test_completion_data()
) << _("ar") << (QStringList()
<< QLatin1String("arg1"));
- QTest::newRow("local_typedef_access_in_lambda") << _(
- "struct Foo { int bar; };\n"
- "\n"
- "void func()\n"
- "{\n"
- " typedef Foo F;\n"
- " []() {\n"
- " F f;\n"
- " @\n"
- " };\n"
- "}\n"
- ) << _("f.") << (QStringList()
- << QLatin1String("Foo")
- << QLatin1String("bar"));
-
QTest::newRow("default_arguments_for_class_templates_and_base_class_QTCREATORBUG-12605") << _(
"struct Foo { int foo; };\n"
"template <typename T = Foo>\n"
@@ -2689,78 +2628,6 @@ void CppToolsPlugin::test_completion_data()
) << _("s.") << (QStringList()
<< QLatin1String("S"));
- QTest::newRow("partial_specialization") << _(
- "struct b {};\n"
- "template<class X, class Y> struct s { float f; };\n"
- "template<class X> struct s<X, b> { int i; };\n"
- "\n"
- "void f()\n"
- "{\n"
- " s<int, b> var;\n"
- " @\n"
- "}\n"
- ) << _("var.") << (QStringList()
- << QLatin1String("i")
- << QLatin1String("s"));
-
-// QTest::newRow("partial_specialization_with_pointer") << _(
-// "struct b {};\n"
-// "struct a : b {};\n"
-// "template<class X, class Y> struct s { float f; };\n"
-// "template<class X> struct s<X, b*> { int i; };\n"
-// "template<class X> struct s<X, a*> { char j; };\n"
-// "\n"
-// "void f()\n"
-// "{\n"
-// " s<int, a*> var;\n"
-// " @\n"
-// "}\n"
-// ) << _("var.") << (QStringList()
-// << QLatin1String("j")
-// << QLatin1String("s"));
-
- QTest::newRow("partial_specialization_templated_argument") << _(
- "template<class T> struct t {};\n"
- "\n"
- "template<class> struct s { float f; };\n"
- "template<class X> struct s<t<X>> { int i; };\n"
- "\n"
- "void f()\n"
- "{\n"
- " s<t<char>> var;\n"
- " @\n"
- "}\n"
- ) << _("var.") << (QStringList()
- << QLatin1String("i")
- << QLatin1String("s"));
-
- QTest::newRow("specialization_multiple_arguments") << _(
- "class false_type {};\n"
- "class true_type {};\n"
- "template<class T1, class T2> class and_type { false_type f; };\n"
- "template<> class and_type<true_type, true_type> { true_type t; };\n"
- "void func()\n"
- "{\n"
- " and_type<true_type, false_type> a;\n"
- " @;\n"
- "}\n"
- ) << _("a.") << (QStringList()
- << QLatin1String("f")
- << QLatin1String("and_type"));
-
- QTest::newRow("specialization_with_default_value") << _(
- "class Foo {};\n"
- "template<class T1 = Foo> class Temp;\n"
- "template<> class Temp<Foo> { int var; };\n"
- "void func()\n"
- "{\n"
- " Temp<> t;\n"
- " @\n"
- "}\n"
- ) << _("t.") << (QStringList()
- << QLatin1String("var")
- << QLatin1String("Temp"));
-
QTest::newRow("auto_declaration_in_if_condition") << _(
"struct Foo { int bar; };\n"
"void fun() {\n"
@@ -2966,28 +2833,6 @@ void CppToolsPlugin::test_completion_data()
<< QLatin1String("Foo")
<< QLatin1String("bar"));
- QTest::newRow("instantiation_of_indirect_typedef") << _(
- "template<typename _Tp>\n"
- "struct Indirect { _Tp t; };\n"
- "\n"
- "template<typename T>\n"
- "struct Temp\n"
- "{\n"
- " typedef T MyT;\n"
- " typedef Indirect<MyT> indirect;\n"
- "};\n"
- "\n"
- "struct Foo { int bar; };\n"
- "\n"
- "void func()\n"
- "{\n"
- " Temp<Foo>::indirect i;\n"
- " @\n"
- "}\n"
- ) << _("i.t.") << (QStringList()
- << QLatin1String("Foo")
- << QLatin1String("bar"));;
-
QTest::newRow("pointer_indirect_specialization_double_indirection_with_base") << _(
"template<typename _Tp>\n"
"struct Traits { };\n"
@@ -3024,337 +2869,6 @@ void CppToolsPlugin::test_completion_data()
) << _("t.p->") << (QStringList()
<< QLatin1String("Foo")
<< QLatin1String("bar"));
-
- QTest::newRow("recursive_instantiation_of_template_type") << _(
- "template<typename _Tp>\n"
- "struct Temp { typedef _Tp value_type; };\n"
- "\n"
- "struct Foo { int bar; };\n"
- "\n"
- "void func()\n"
- "{\n"
- " Temp<Temp<Foo> >::value_type::value_type *p;\n"
- " @\n"
- "}\n"
- ) << _("p->") << (QStringList()
- << QLatin1String("Foo")
- << QLatin1String("bar"));
-
- QTest::newRow("recursive_instantiation_of_template_type_2") << _(
- "template<typename _Tp>\n"
- "struct Temp { typedef _Tp value_type; };\n"
- "\n"
- "struct Foo { int bar; };\n"
- "\n"
- "void func()\n"
- "{\n"
- " Temp<Temp<Foo>::value_type>::value_type *p;\n"
- " @\n"
- "}\n"
- ) << _("p->") << (QStringList()
- << QLatin1String("Foo")
- << QLatin1String("bar"));
-
- QTest::newRow("template_using_instantiation") << _(
- "template<typename _Tp>\n"
- "using T = _Tp;\n"
- "\n"
- "struct Foo { int bar; };\n"
- "\n"
- "void func()\n"
- "{\n"
- " T<Foo> p;\n"
- " @\n"
- "}\n"
- ) << _("p.") << (QStringList()
- << QLatin1String("Foo")
- << QLatin1String("bar"));
-
- QTest::newRow("nested_template_using_instantiation") << _(
- "struct Parent {\n"
- " template<typename _Tp>\n"
- " using T = _Tp;\n"
- "};\n"
- "\n"
- "struct Foo { int bar; };\n"
- "\n"
- "void func()\n"
- "{\n"
- " Parent::T<Foo> p;\n"
- " @;\n"
- "}\n"
- ) << _("p.") << (QStringList()
- << QLatin1String("Foo")
- << QLatin1String("bar"));
-
- QTest::newRow("nested_template_using_instantiation_in_template_class") << _(
- "template<typename ParentT>\n"
- "struct Parent {\n"
- " template<typename _Tp>\n"
- " using T = _Tp;\n"
- "};\n"
- "\n"
- "struct Foo { int bar; };\n"
- "\n"
- "void func()\n"
- "{\n"
- " Parent<Foo>::T<Foo> p;\n"
- " @;\n"
- "}\n"
- ) << _("p.") << (QStringList()
- << QLatin1String("Foo")
- << QLatin1String("bar"));
-
- QTest::newRow("recursive_nested_template_using_instantiation") << _(
- "struct Foo { int bar; };\n"
- "\n"
- "struct A { typedef Foo value_type; };\n"
- "\n"
- "template<typename T>\n"
- "struct Traits\n"
- "{\n"
- " typedef Foo value_type;\n"
- "\n"
- " template<typename _Tp>\n"
- " using U = T;\n"
- "};\n"
- "\n"
- "template<typename T>\n"
- "struct Temp\n"
- "{\n"
- " typedef Traits<T> TraitsT;\n"
- " typedef typename T::value_type value_type;\n"
- " typedef typename TraitsT::template U<Foo> rebind;\n"
- "};\n"
- "\n"
- "void func()\n"
- "{\n"
- " typename Temp<typename Temp<A>::rebind>::value_type p;\n"
- " @\n"
- "}\n"
- ) << _("p.") << (QStringList()
- << QLatin1String("Foo")
- << QLatin1String("bar"));
-
- QTest::newRow("qualified_name_in_nested_type") << _(
- "template<typename _Tp>\n"
- "struct Temp {\n"
- " struct Nested {\n"
- " typedef typename _Tp::Nested2 N;\n"
- " };\n"
- "};\n"
- "\n"
- "struct Foo {\n"
- " struct Nested2 {\n"
- " int bar;\n"
- " };\n"
- "};\n"
- "\n"
- "void func()\n"
- "{\n"
- " Temp<Foo>::Nested::N p;\n"
- " @;\n"
- "}\n"
- ) << _("p.") << (QStringList()
- << QLatin1String("Nested2")
- << QLatin1String("bar"));
-
- QTest::newRow("simple_decltype_declaration") << _(
- "struct Foo { int bar; };\n"
- "Foo foo;\n"
- "void fun() {\n"
- " decltype(foo) s;\n"
- " @\n"
- "}\n"
- ) << _("s.") << (QStringList()
- << QLatin1String("Foo")
- << QLatin1String("bar"));
-
- QTest::newRow("typedefed_decltype_declaration") << _(
- "struct Foo { int bar; };\n"
- "Foo foo;\n"
- "typedef decltype(foo) TypedefedFooWithDecltype;\n"
- "void fun() {\n"
- " TypedefedFooWithDecltype s;\n"
- " @\n"
- "}\n"
- ) << _("s.") << (QStringList()
- << QLatin1String("Foo")
- << QLatin1String("bar"));
-
- QTest::newRow("nested_instantiation_typedefed_decltype_declaration") << _(
- "template <typename T>\n"
- "struct Temp\n"
- "{\n"
- " struct Nested\n"
- " {\n"
- " static T f();\n"
- " typedef decltype(f()) type;\n"
- " };\n"
- "};\n"
- "\n"
- "struct Foo { int bar; };\n"
- "\n"
- "void fun()\n"
- "{\n"
- " Temp<Foo>::Nested::type s;\n"
- " @\n"
- "}\n"
- ) << _("s.") << (QStringList()
- << QLatin1String("Foo")
- << QLatin1String("bar"));
-
- QTest::newRow("typedefed_decltype_of_template_function") << _(
- "template<typename T>\n"
- "static T f();\n"
- "\n"
- "struct Foo { int bar; };\n"
- "\n"
- "void fun()\n"
- "{\n"
- " decltype(f<Foo>()) s;\n"
- " @\n"
- "}\n"
- ) << _("s.") << (QStringList()
- << QLatin1String("Foo")
- << QLatin1String("bar"));
-
- QTest::newRow("nested_instantiation_typedefed_decltype_declaration_of_template_function") << _(
- "template <typename T, typename D = T>\n"
- "struct Temp\n"
- "{\n"
- " struct Nested\n"
- " {\n"
- " template<typename U> static T* __test(...);\n"
- " typedef decltype(__test<D>(0)) type;\n"
- " };\n"
- "};\n"
- "\n"
- "struct Foo { int bar; };\n"
- "\n"
- "void func()\n"
- "{\n"
- " Temp<Foo>::Nested::type s;\n"
- " @\n"
- "}\n"
- ) << _("s.") << (QStringList()
- << QLatin1String("Foo")
- << QLatin1String("bar"));
-
- QTest::newRow("typedef for templates in namespace") << _(
- "namespace N {\n"
- "\n"
- "struct Data { int x; };\n"
- "template <typename T> struct Foo { T member; };\n"
- "typedef Foo<Data> Bar;\n"
- "\n"
- "} // N\n"
- "\n"
- "\n"
- "void f()\n"
- "{\n"
- " N::Bar o;\n"
- " @\n"
- "}\n"
- ) << _("o.member.") << (QStringList()
- << QLatin1String("Data")
- << QLatin1String("x"));
-
- QTest::newRow("std vector") << _(
- "namespace std\n"
- "{\n"
- "template<typename _Tp>\n"
- "struct allocator\n"
- "{\n"
- " typedef _Tp value_type;\n"
- "\n"
- " template<typename _Tp1>\n"
- " struct rebind\n"
- " { typedef allocator<_Tp1> other; };\n"
- "};\n"
- "\n"
- "template<typename _Alloc, typename _Tp>\n"
- "struct __alloctr_rebind\n"
- "{\n"
- " typedef typename _Alloc::template rebind<_Tp>::other __type;\n"
- "};\n"
- "\n"
- "template<typename _Alloc>\n"
- "struct allocator_traits\n"
- "{\n"
- " typedef typename _Alloc::value_type value_type;\n"
- "\n"
- " template<typename _Tp>\n"
- " using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type;\n"
- "};\n"
- "\n"
- "template<typename _Iterator>\n"
- "struct iterator_traits { };\n"
- "\n"
- "template<typename _Tp>\n"
- "struct iterator_traits<_Tp*>\n"
- "{\n"
- " typedef _Tp* pointer;\n"
- "};\n"
- "} // namespace std\n"
- "\n"
- "namespace __gnu_cxx\n"
- "{\n"
- "template<typename _Alloc>\n"
- "struct __alloc_traits\n"
- "{\n"
- " typedef _Alloc allocator_type;\n"
- " typedef std::allocator_traits<_Alloc> _Base_type;\n"
- " typedef typename _Alloc::value_type value_type;\n"
- "\n"
- " static value_type *_S_pointer_helper(...);\n"
- " typedef decltype(_S_pointer_helper((_Alloc*)0)) __pointer;\n"
- " typedef __pointer pointer;\n"
- "\n"
- " template<typename _Tp>\n"
- " struct rebind\n"
- " { typedef typename _Base_type::template rebind_alloc<_Tp> other; };\n"
- "};\n"
- "\n"
- "template<typename _Iterator, typename _Container>\n"
- "struct __normal_iterator\n"
- "{\n"
- " typedef std::iterator_traits<_Iterator> __traits_type;\n"
- " typedef typename __traits_type::pointer pointer;\n"
- "\n"
- " pointer p;\n"
- "};\n"
- "} // namespace __gnu_cxx\n"
- "\n"
- "namespace std {\n"
- "template<typename _Tp, typename _Alloc>\n"
- "struct _Vector_Base\n"
- "{\n"
- " typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template\n"
- " rebind<_Tp>::other _Tp_alloc_type;\n"
- " typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer\n"
- " pointer;\n"
- "};\n"
- "\n"
- "template<typename _Tp, typename _Alloc = std::allocator<_Tp> >\n"
- "struct vector : protected _Vector_Base<_Tp, _Alloc>\n"
- "{\n"
- " typedef _Vector_Base<_Tp, _Alloc> _Base;\n"
- " typedef typename _Base::pointer pointer;\n"
- " typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator;\n"
- "};\n"
- "} // namespace std\n"
- "\n"
- "struct Foo { int bar; };\n"
- "\n"
- "void func()\n"
- "{\n"
- " std::vector<Foo>::iterator it;\n"
- " @;\n"
- "}\n"
- ) << _("it.p->") << (QStringList()
- << QLatin1String("Foo")
- << QLatin1String("bar"));
}
void CppToolsPlugin::test_completion_member_access_operator()
diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp
index fa7790a915..eec2f2e5fe 100644
--- a/src/plugins/cpptools/cppcompletionassist.cpp
+++ b/src/plugins/cpptools/cppcompletionassist.cpp
@@ -753,8 +753,8 @@ bool canCompleteClassNameAt2ndOr4thConnectArgument(
|| eater.eatConnectOpenParenthesisExpressionCommaAmpersandExpressionComma();
}
-LookupScope *lookupScopeFromLookupItem(const LookupItem &lookupItem,
- const LookupContext &context)
+ClassOrNamespace *classOrNamespaceFromLookupItem(const LookupItem &lookupItem,
+ const LookupContext &context)
{
const Name *name = 0;
@@ -783,7 +783,7 @@ LookupScope *lookupScopeFromLookupItem(const LookupItem &lookupItem,
Class *classFromLookupItem(const LookupItem &lookupItem, const LookupContext &context)
{
- LookupScope *b = lookupScopeFromLookupItem(lookupItem, context);
+ ClassOrNamespace *b = classOrNamespaceFromLookupItem(lookupItem, context);
if (!b)
return 0;
@@ -796,7 +796,7 @@ Class *classFromLookupItem(const LookupItem &lookupItem, const LookupContext &co
const Name *minimalName(Symbol *symbol, Scope *targetScope, const LookupContext &context)
{
- LookupScope *target = context.lookupType(targetScope);
+ ClassOrNamespace *target = context.lookupType(targetScope);
if (!target)
target = context.globalNamespace();
return context.minimalName(symbol, target, context.bindings()->control().data());
@@ -1219,12 +1219,12 @@ bool InternalCppCompletionAssistProcessor::tryObjCCompletion()
ty = ty->asPointerType()->elementType().simplified();
if (NamedType *namedTy = ty->asNamedType()) {
- LookupScope *binding = lookupContext.lookupType(namedTy->name(), item.scope());
+ ClassOrNamespace *binding = lookupContext.lookupType(namedTy->name(), item.scope());
completeObjCMsgSend(binding, false);
}
} else {
if (ObjCClass *clazz = ty->asObjCClassType()) {
- LookupScope *binding = lookupContext.lookupType(clazz->name(), item.scope());
+ ClassOrNamespace *binding = lookupContext.lookupType(clazz->name(), item.scope());
completeObjCMsgSend(binding, true);
}
}
@@ -1273,7 +1273,7 @@ void InternalCppCompletionAssistProcessor::addCompletionItem(Symbol *symbol, int
}
}
-void InternalCppCompletionAssistProcessor::completeObjCMsgSend(LookupScope *binding,
+void InternalCppCompletionAssistProcessor::completeObjCMsgSend(ClassOrNamespace *binding,
bool staticClassAccess)
{
QList<Scope*> memberScopes;
@@ -1542,26 +1542,26 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope)
return !m_completions.isEmpty();
}
- QList<LookupScope *> usingBindings;
- LookupScope *currentBinding = 0;
+ QList<ClassOrNamespace *> usingBindings;
+ ClassOrNamespace *currentBinding = 0;
for (Scope *scope = currentScope; scope; scope = scope->enclosingScope()) {
if (Block *block = scope->asBlock()) {
- if (LookupScope *binding = context.lookupType(scope)) {
+ if (ClassOrNamespace *binding = context.lookupType(scope)) {
for (unsigned i = 0; i < scope->memberCount(); ++i) {
Symbol *member = scope->memberAt(i);
if (member->isEnum()) {
- if (LookupScope *b = binding->findBlock(block))
+ if (ClassOrNamespace *b = binding->findBlock(block))
completeNamespace(b);
}
if (!member->name())
continue;
if (UsingNamespaceDirective *u = member->asUsingNamespaceDirective()) {
- if (LookupScope *b = binding->lookupType(u->name()))
+ if (ClassOrNamespace *b = binding->lookupType(u->name()))
usingBindings.append(b);
} else if (Class *c = member->asClass()) {
if (c->name()->isAnonymousNameId()) {
- if (LookupScope *b = binding->findBlock(block))
+ if (ClassOrNamespace *b = binding->findBlock(block))
completeClass(b);
}
}
@@ -1588,7 +1588,7 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope)
}
for (; currentBinding; currentBinding = currentBinding->parent()) {
- foreach (LookupScope* u, currentBinding->usings())
+ foreach (ClassOrNamespace* u, currentBinding->usings())
usingBindings.append(u);
const QList<Symbol *> symbols = currentBinding->symbols();
@@ -1601,7 +1601,7 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope)
}
}
- foreach (LookupScope *b, usingBindings)
+ foreach (ClassOrNamespace *b, usingBindings)
completeNamespace(b);
addKeywords();
@@ -1624,7 +1624,7 @@ bool InternalCppCompletionAssistProcessor::completeMember(const QList<LookupItem
if (!m_interface->languageFeatures().objCEnabled)
replaceDotForArrow = &m_model->m_replaceDotForArrow;
- if (LookupScope *binding =
+ if (ClassOrNamespace *binding =
resolveExpression.baseExpression(baseResults,
m_model->m_completionOperator,
replaceDotForArrow)) {
@@ -1648,27 +1648,27 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem>
Scope *scope = result.scope();
if (NamedType *namedTy = ty->asNamedType()) {
- if (LookupScope *b = context.lookupType(namedTy->name(), scope)) {
+ if (ClassOrNamespace *b = context.lookupType(namedTy->name(), scope)) {
completeClass(b);
break;
}
} else if (Class *classTy = ty->asClassType()) {
- if (LookupScope *b = context.lookupType(classTy)) {
+ if (ClassOrNamespace *b = context.lookupType(classTy)) {
completeClass(b);
break;
}
// it can be class defined inside a block
if (classTy->enclosingScope()->isBlock()) {
- if (LookupScope *b = context.lookupType(classTy->name(), classTy->enclosingScope())) {
+ if (ClassOrNamespace *b = context.lookupType(classTy->name(), classTy->enclosingScope())) {
completeClass(b);
break;
}
}
} else if (Namespace *nsTy = ty->asNamespaceType()) {
- if (LookupScope *b = context.lookupType(nsTy)) {
+ if (ClassOrNamespace *b = context.lookupType(nsTy)) {
completeNamespace(b);
break;
}
@@ -1676,7 +1676,7 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem>
} else if (Template *templ = ty->asTemplateType()) {
if (!result.binding())
continue;
- if (LookupScope *b = result.binding()->lookupType(templ->name())) {
+ if (ClassOrNamespace *b = result.binding()->lookupType(templ->name())) {
completeClass(b);
break;
}
@@ -1684,16 +1684,16 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem>
} else if (Enum *e = ty->asEnumType()) {
// it can be class defined inside a block
if (e->enclosingScope()->isBlock()) {
- if (LookupScope *b = context.lookupType(e)) {
+ if (ClassOrNamespace *b = context.lookupType(e)) {
Block *block = e->enclosingScope()->asBlock();
- if (LookupScope *bb = b->findBlock(block)) {
+ if (ClassOrNamespace *bb = b->findBlock(block)) {
completeNamespace(bb);
break;
}
}
}
- if (LookupScope *b = context.lookupType(e)) {
+ if (ClassOrNamespace *b = context.lookupType(e)) {
completeNamespace(b);
break;
}
@@ -1704,14 +1704,14 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem>
return !m_completions.isEmpty();
}
-void InternalCppCompletionAssistProcessor::completeNamespace(LookupScope *b)
+void InternalCppCompletionAssistProcessor::completeNamespace(ClassOrNamespace *b)
{
- QSet<LookupScope *> bindingsVisited;
- QList<LookupScope *> bindingsToVisit;
+ QSet<ClassOrNamespace *> bindingsVisited;
+ QList<ClassOrNamespace *> bindingsToVisit;
bindingsToVisit.append(b);
while (!bindingsToVisit.isEmpty()) {
- LookupScope *binding = bindingsToVisit.takeFirst();
+ ClassOrNamespace *binding = bindingsToVisit.takeFirst();
if (!binding || bindingsVisited.contains(binding))
continue;
@@ -1744,14 +1744,14 @@ void InternalCppCompletionAssistProcessor::completeNamespace(LookupScope *b)
}
}
-void InternalCppCompletionAssistProcessor::completeClass(LookupScope *b, bool staticLookup)
+void InternalCppCompletionAssistProcessor::completeClass(ClassOrNamespace *b, bool staticLookup)
{
- QSet<LookupScope *> bindingsVisited;
- QList<LookupScope *> bindingsToVisit;
+ QSet<ClassOrNamespace *> bindingsVisited;
+ QList<ClassOrNamespace *> bindingsToVisit;
bindingsToVisit.append(b);
while (!bindingsToVisit.isEmpty()) {
- LookupScope *binding = bindingsToVisit.takeFirst();
+ ClassOrNamespace *binding = bindingsToVisit.takeFirst();
if (!binding || bindingsVisited.contains(binding))
continue;
@@ -1838,16 +1838,16 @@ bool InternalCppCompletionAssistProcessor::completeQtMethod(const QList<LookupIt
QSet<QString> signatures;
foreach (const LookupItem &lookupItem, results) {
- LookupScope *b = lookupScopeFromLookupItem(lookupItem, context);
+ ClassOrNamespace *b = classOrNamespaceFromLookupItem(lookupItem, context);
if (!b)
continue;
- QList<LookupScope *>todo;
- QSet<LookupScope *> processed;
+ QList<ClassOrNamespace *>todo;
+ QSet<ClassOrNamespace *> processed;
QList<Scope *> scopes;
todo.append(b);
while (!todo.isEmpty()) {
- LookupScope *binding = todo.takeLast();
+ ClassOrNamespace *binding = todo.takeLast();
if (!processed.contains(binding)) {
processed.insert(binding);
@@ -2063,7 +2063,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
Scope *scope = result.scope();
if (NamedType *namedTy = ty->asNamedType()) {
- if (LookupScope *b = context.lookupType(namedTy->name(), scope)) {
+ if (ClassOrNamespace *b = context.lookupType(namedTy->name(), scope)) {
foreach (const LookupItem &r, b->lookup(functionCallOp)) {
Symbol *overload = r.declaration();
FullySpecifiedType overloadTy = overload->type().simplified();
@@ -2145,7 +2145,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
SubstitutionEnvironment env;
env.setContext(context);
env.switchScope(sc);
- LookupScope *targetCoN = context.lookupType(sc);
+ ClassOrNamespace *targetCoN = context.lookupType(sc);
if (!targetCoN)
targetCoN = context.globalNamespace();
UseMinimalNames q(targetCoN);
diff --git a/src/plugins/cpptools/cppcompletionassist.h b/src/plugins/cpptools/cppcompletionassist.h
index 01fd44e5b8..30f8809081 100644
--- a/src/plugins/cpptools/cppcompletionassist.h
+++ b/src/plugins/cpptools/cppcompletionassist.h
@@ -53,7 +53,7 @@
namespace CPlusPlus {
class LookupItem;
-class LookupScope;
+class ClassOrNamespace;
class Function;
class LookupContext;
} // namespace CPlusPlus
@@ -121,7 +121,7 @@ private:
const QString &expression,
int endOfExpression);
- void completeObjCMsgSend(CPlusPlus::LookupScope *binding, bool staticClassAccess);
+ void completeObjCMsgSend(CPlusPlus::ClassOrNamespace *binding, bool staticClassAccess);
bool completeInclude(const QTextCursor &cursor);
void completeInclude(const QString &realPath, const QStringList &suffixes);
void completePreprocessor();
@@ -130,8 +130,8 @@ private:
bool toolTipOnly);
bool completeMember(const QList<CPlusPlus::LookupItem> &results);
bool completeScope(const QList<CPlusPlus::LookupItem> &results);
- void completeNamespace(CPlusPlus::LookupScope *binding);
- void completeClass(CPlusPlus::LookupScope *b, bool staticLookup = true);
+ void completeNamespace(CPlusPlus::ClassOrNamespace *binding);
+ void completeClass(CPlusPlus::ClassOrNamespace *b, bool staticLookup = true);
void addClassMembersToCompletion(CPlusPlus::Scope *scope, bool staticLookup);
enum CompleteQtMethodMode {
CompleteQt4Signals,
diff --git a/src/plugins/cpptools/cpptoolsreuse.cpp b/src/plugins/cpptools/cpptoolsreuse.cpp
index 41031eb839..db9bbb07c1 100644
--- a/src/plugins/cpptools/cpptoolsreuse.cpp
+++ b/src/plugins/cpptools/cpptoolsreuse.cpp
@@ -109,7 +109,7 @@ bool isOwnershipRAIIType(Symbol *symbol, const LookupContext &context)
Declaration *declaration = symbol->asDeclaration();
const NamedType *namedType = declaration->type()->asNamedType();
if (namedType) {
- LookupScope *clazz = context.lookupType(namedType->name(),
+ ClassOrNamespace *clazz = context.lookupType(namedType->name(),
declaration->enclosingScope());
if (clazz && !clazz->symbols().isEmpty()) {
Overview overview;
diff --git a/src/plugins/cpptools/symbolfinder.cpp b/src/plugins/cpptools/symbolfinder.cpp
index 3bc72c00b5..cc5006e63a 100644
--- a/src/plugins/cpptools/symbolfinder.cpp
+++ b/src/plugins/cpptools/symbolfinder.cpp
@@ -151,7 +151,7 @@ Function *SymbolFinder::findMatchingDefinition(Symbol *declaration,
QList<Function *> viableFunctions;
- LookupScope *enclosingType = context.lookupType(declaration);
+ ClassOrNamespace *enclosingType = context.lookupType(declaration);
if (!enclosingType)
continue; // nothing to do
@@ -214,15 +214,13 @@ Function *SymbolFinder::findMatchingDefinition(Symbol *declaration,
return 0;
}
-Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Snapshot &snapshot,
- const LookupContext *context)
+Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Snapshot &snapshot)
{
if (!declaration->identifier())
return 0;
QString declFile = QString::fromUtf8(declaration->fileName(), declaration->fileNameLength());
- const bool useLocalContext = !context;
foreach (const QString &file, fileIterationOrder(declFile, snapshot)) {
Document::Ptr doc = snapshot.document(file);
if (!doc) {
@@ -234,13 +232,9 @@ Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Sna
declaration->identifier()->size()))
continue;
- QScopedPointer<LookupContext> localContext;
- if (useLocalContext) {
- localContext.reset(new LookupContext(doc, snapshot));
- context = localContext.data();
- }
+ LookupContext context(doc, snapshot);
- LookupScope *type = context->lookupType(declaration);
+ ClassOrNamespace *type = context.lookupType(declaration);
if (!type)
continue;
@@ -289,7 +283,7 @@ void SymbolFinder::findMatchingDeclaration(const LookupContext &context,
if (!functionName)
return;
- LookupScope *binding = 0;
+ ClassOrNamespace *binding = 0;
const QualifiedNameId *qName = functionName->asQualifiedNameId();
if (qName) {
if (qName->base())
diff --git a/src/plugins/cpptools/symbolfinder.h b/src/plugins/cpptools/symbolfinder.h
index 45236eb1ad..c1d65f7716 100644
--- a/src/plugins/cpptools/symbolfinder.h
+++ b/src/plugins/cpptools/symbolfinder.h
@@ -61,8 +61,7 @@ public:
bool strict = false);
CPlusPlus::Class *findMatchingClassDeclaration(CPlusPlus::Symbol *declaration,
- const CPlusPlus::Snapshot &snapshot,
- const CPlusPlus::LookupContext *context = 0);
+ const CPlusPlus::Snapshot &snapshot);
void findMatchingDeclaration(const CPlusPlus::LookupContext &context,
CPlusPlus::Function *functionType,
diff --git a/src/plugins/genericprojectmanager/genericprojectnodes.cpp b/src/plugins/genericprojectmanager/genericprojectnodes.cpp
index c58b336587..6683c7443e 100644
--- a/src/plugins/genericprojectmanager/genericprojectnodes.cpp
+++ b/src/plugins/genericprojectmanager/genericprojectnodes.cpp
@@ -68,6 +68,9 @@ QHash<QString, QStringList> sortFilesIntoPaths(const QString &base, const QSet<Q
relativeFilePath.chop(1);
}
+ if (relativeFilePath == QLatin1String("."))
+ relativeFilePath.clear();
+
filesInPath[relativeFilePath].append(absoluteFileName);
}
return filesInPath;
diff --git a/src/plugins/mercurial/mercurialclient.h b/src/plugins/mercurial/mercurialclient.h
index 80c9067e1c..c50aeaeacd 100644
--- a/src/plugins/mercurial/mercurialclient.h
+++ b/src/plugins/mercurial/mercurialclient.h
@@ -75,6 +75,8 @@ public:
const QStringList &extraOptions = QStringList());
void revertAll(const QString &workingDir, const QString &revision = QString(),
const QStringList &extraOptions = QStringList());
+
+public slots:
void view(const QString &source, const QString &id,
const QStringList &extraOptions = QStringList());
diff --git a/src/plugins/projectexplorer/abi.cpp b/src/plugins/projectexplorer/abi.cpp
index 5471287a3f..1d2ceac974 100644
--- a/src/plugins/projectexplorer/abi.cpp
+++ b/src/plugins/projectexplorer/abi.cpp
@@ -483,6 +483,7 @@ Abi Abi::abiFromTargetTriplet(const QString &triple)
} else if (p == QLatin1String("i386") || p == QLatin1String("i486") || p == QLatin1String("i586")
|| p == QLatin1String("i686") || p == QLatin1String("x86")) {
arch = Abi::X86Architecture;
+ width = 32;
} else if (p.startsWith(QLatin1String("arm"))) {
arch = Abi::ArmArchitecture;
width = p.contains(QLatin1String("64")) ? 64 : 32;
@@ -1057,27 +1058,27 @@ void ProjectExplorer::ProjectExplorerPlugin::testAbiFromTargetTriplet_data()
QTest::newRow("i586-pc-mingw32msvc") << int(Abi::X86Architecture)
<< int(Abi::WindowsOS) << int(Abi::WindowsMSysFlavor)
- << int(Abi::PEFormat) << 0;
+ << int(Abi::PEFormat) << 32;
QTest::newRow("i686-linux-gnu") << int(Abi::X86Architecture)
<< int(Abi::LinuxOS) << int(Abi::GenericLinuxFlavor)
- << int(Abi::ElfFormat) << 0;
+ << int(Abi::ElfFormat) << 32;
QTest::newRow("i686-linux-android") << int(Abi::X86Architecture)
<< int(Abi::LinuxOS) << int(Abi::AndroidLinuxFlavor)
- << int(Abi::ElfFormat) << 0;
+ << int(Abi::ElfFormat) << 32;
QTest::newRow("i686-pc-linux-android") << int(Abi::X86Architecture)
<< int(Abi::LinuxOS) << int(Abi::AndroidLinuxFlavor)
- << int(Abi::ElfFormat) << 0;
+ << int(Abi::ElfFormat) << 32;
QTest::newRow("i686-pc-mingw32") << int(Abi::X86Architecture)
<< int(Abi::WindowsOS) << int(Abi::WindowsMSysFlavor)
- << int(Abi::PEFormat) << 0;
+ << int(Abi::PEFormat) << 32;
QTest::newRow("i686-w64-mingw32") << int(Abi::X86Architecture)
<< int(Abi::WindowsOS) << int(Abi::WindowsMSysFlavor)
- << int(Abi::PEFormat) << 0;
+ << int(Abi::PEFormat) << 32;
QTest::newRow("x86_64-pc-msys") << int(Abi::X86Architecture)
<< int(Abi::WindowsOS) << int(Abi::WindowsMSysFlavor)
diff --git a/src/plugins/projectexplorer/customwizard/customwizard.cpp b/src/plugins/projectexplorer/customwizard/customwizard.cpp
index c52bd20eab..fbbe9e7b9e 100644
--- a/src/plugins/projectexplorer/customwizard/customwizard.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizard.cpp
@@ -40,6 +40,7 @@
#include <coreplugin/messagemanager.h>
#include <extensionsystem/pluginmanager.h>
+#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/qtcassert.h>
@@ -358,7 +359,6 @@ CustomWizard *CustomWizard::createWizard(const CustomProjectWizard::CustomWizard
QList<Core::IWizardFactory *> CustomWizard::createWizards()
{
- QList<Core::IWizardFactory *> rc;
QString errorMessage;
QString verboseLog;
const QString templateDirName = Core::ICore::resourcePath() +
@@ -371,29 +371,32 @@ QList<Core::IWizardFactory *> CustomWizard::createWizards()
const QDir templateDir(templateDirName);
if (CustomWizardPrivate::verbose)
- verboseLog = QString::fromLatin1("### CustomWizard: Checking \"%1\"\n").arg(templateDirName);
+ verboseLog += QString::fromLatin1("### CustomWizard: Checking \"%1\"\n").arg(templateDirName);
if (!templateDir.exists()) {
if (CustomWizardPrivate::verbose)
qWarning("Custom project template path %s does not exist.", qPrintable(templateDir.absolutePath()));
- return rc;
+ return QList<Core::IWizardFactory *>();
}
const QDir userTemplateDir(userTemplateDirName);
if (CustomWizardPrivate::verbose)
- verboseLog = QString::fromLatin1("### CustomWizard: Checking \"%1\"\n").arg(userTemplateDirName);
+ verboseLog += QString::fromLatin1("### CustomWizard: Checking \"%1\"\n").arg(userTemplateDirName);
const QDir::Filters filters = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
const QDir::SortFlags sortflags = QDir::Name|QDir::IgnoreCase;
- QList<QFileInfo> dirs = templateDir.entryInfoList(filters, sortflags);
+ QList<QFileInfo> dirs;
if (userTemplateDir.exists()) {
if (CustomWizardPrivate::verbose)
- verboseLog = QString::fromLatin1("### CustomWizard: userTemplateDir \"%1\" found, adding\n").arg(userTemplateDirName);
+ verboseLog += QString::fromLatin1("### CustomWizard: userTemplateDir \"%1\" found, adding\n").arg(userTemplateDirName);
dirs += userTemplateDir.entryInfoList(filters, sortflags);
}
+ dirs += templateDir.entryInfoList(filters, sortflags);
const QString configFile = QLatin1String(configFileC);
// Check and parse config file in each directory.
+ QList<CustomWizardParametersPtr> toCreate;
+
while (!dirs.isEmpty()) {
const QFileInfo dirFi = dirs.takeFirst();
const QDir dir(dirFi.absoluteFilePath());
@@ -403,11 +406,13 @@ QList<Core::IWizardFactory *> CustomWizard::createWizards()
CustomWizardParametersPtr parameters(new CustomWizardParameters);
switch (parameters->parse(dir.absoluteFilePath(configFile), &errorMessage)) {
case CustomWizardParameters::ParseOk:
- parameters->directory = dir.absolutePath();
- if (CustomWizard *w = createWizard(parameters))
- rc.push_back(w);
- else
- qWarning("Custom wizard factory function failed for %s", qPrintable(parameters->id.toString()));
+ if (!Utils::contains(toCreate, [parameters](CustomWizardParametersPtr p) { return parameters->id == p->id; })) {
+ parameters->directory = dir.absolutePath();
+ toCreate.append(parameters);
+ } else {
+ verboseLog += QString::fromLatin1("Customwizard: Ignoring wizard in %1 due to duplicate Id %2.\n")
+ .arg(dir.absolutePath()).arg(parameters->id.toString());
+ }
break;
case CustomWizardParameters::ParseDisabled:
if (CustomWizardPrivate::verbose)
@@ -429,6 +434,18 @@ QList<Core::IWizardFactory *> CustomWizard::createWizards()
}
}
}
+
+ QList<Core::IWizardFactory *> rc;
+ foreach (CustomWizardParametersPtr p, toCreate) {
+ if (CustomWizard *w = createWizard(p)) {
+ rc.push_back(w);
+ } else {
+ qWarning("Custom wizard factory function failed for %s from %s.",
+ qPrintable(p->id.toString()), qPrintable(p->directory));
+ }
+ }
+
+
if (CustomWizardPrivate::verbose) { // Print to output pane for Windows.
qWarning("%s", qPrintable(verboseLog));
Core::MessageManager::write(verboseLog, Core::MessageManager::ModeSwitch);
diff --git a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
index 4df29ac2c9..134893481c 100644
--- a/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
+++ b/src/plugins/qmldesigner/components/navigator/navigatortreemodel.cpp
@@ -568,7 +568,8 @@ static void appendNodeToEndOfTheRow(const ModelNode &modelNode, const ItemRow &n
parentPropertyItem->appendRow(newItemRow.toList());
} else {
QStandardItem *parentDefaultPropertyItem = parentRow.idItem;
- parentDefaultPropertyItem->appendRow(newItemRow.toList());
+ if (parentDefaultPropertyItem)
+ parentDefaultPropertyItem->appendRow(newItemRow.toList());
}
} else { // root node
treeModel->appendRow(newItemRow.toList());
diff --git a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathitem.cpp b/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathitem.cpp
index 7dfb02609c..b984b3da1a 100644
--- a/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathitem.cpp
+++ b/src/plugins/qmldesigner/qmldesignerextension/pathtool/pathitem.cpp
@@ -885,7 +885,7 @@ void PathItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
if (pickedControlPoint.isEditPoint()) {
createEditPointContextMenu(pickedControlPoint, event->screenPos());
} else {
- double t;
+ double t = 0.0;
CubicSegment minimumDistanceSegment = getMinimumDistanceSegment(event->pos(), m_cubicSegments, 20., &t);
if (minimumDistanceSegment.isValid())
createCubicSegmentContextMenu(minimumDistanceSegment, event->screenPos(), t);
diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp
index 8945675e05..96b70100d7 100644
--- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.cpp
@@ -104,16 +104,24 @@ void QmlProfilerTraceTime::setTime(qint64 startTime, qint64 endTime)
void QmlProfilerTraceTime::decreaseStartTime(qint64 time)
{
- if (m_startTime > time) {
+ if (m_startTime > time || m_startTime == -1) {
m_startTime = time;
+ if (m_endTime == -1)
+ m_endTime = m_startTime;
+ else
+ QTC_ASSERT(m_endTime >= m_startTime, m_endTime = m_startTime);
emit timeChanged(time, m_endTime);
}
}
void QmlProfilerTraceTime::increaseEndTime(qint64 time)
{
- if (m_endTime < time) {
+ if (m_endTime < time || m_endTime == -1) {
m_endTime = time;
+ if (m_startTime == -1)
+ m_startTime = m_endTime;
+ else
+ QTC_ASSERT(m_endTime >= m_startTime, m_startTime = m_endTime);
emit timeChanged(m_startTime, time);
}
}
@@ -152,6 +160,8 @@ QmlProfilerModelManager::QmlProfilerModelManager(Utils::FileInProjectFinder *fin
QObject(parent), d(new QmlProfilerModelManagerPrivate(this))
{
d->totalWeight = 0;
+ d->previousProgress = 0;
+ d->progress = 0;
d->availableFeatures = 0;
d->visibleFeatures = 0;
d->recordedFeatures = 0;
diff --git a/src/shared/json/json.cpp b/src/shared/json/json.cpp
index c40aa3dc1f..75d313c9e2 100644
--- a/src/shared/json/json.cpp
+++ b/src/shared/json/json.cpp
@@ -33,6 +33,7 @@
#include <algorithm>
#include <atomic>
+#include <cmath>
#include <iostream>
#include <limits>
#include <string>
diff --git a/src/shared/qbs b/src/shared/qbs
-Subproject 94aaf3b94f9a9d8975349d75966917b4a8e0a43
+Subproject ca3974a0828c029e47f644931386fe6df200fba
diff --git a/src/tools/clangbackend/clangbackendmain.cpp b/src/tools/clangbackend/clangbackendmain.cpp
index 428d55add6..33a6c1660e 100644
--- a/src/tools/clangbackend/clangbackendmain.cpp
+++ b/src/tools/clangbackend/clangbackendmain.cpp
@@ -53,6 +53,9 @@ int main(int argc, char *argv[])
ClangBackEnd::Messages::registerMessages();
+ clang_toggleCrashRecovery(true);
+ clang_enableStackTraces();
+
ClangBackEnd::ClangIpcServer clangIpcServer;
ClangBackEnd::ConnectionServer connectionServer(application.arguments()[1]);
connectionServer.start();
diff --git a/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri b/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri
index 73aa363a95..93131082bf 100644
--- a/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri
+++ b/src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri
@@ -25,7 +25,13 @@ HEADERS += $$PWD/clangipcserver.h \
$$PWD/diagnosticsetiterator.h \
$$PWD/clangfilesystemwatcher.h \
$$PWD/translationunitalreadyexistsexception.h \
- $$PWD/commandlinearguments.h
+ $$PWD/commandlinearguments.h \
+ $$PWD/cursor.h \
+ $$PWD/type.h \
+ $$PWD/highlightinginformations.h \
+ $$PWD/highlightinginformation.h \
+ $$PWD/highlightinginformationsiterator.h \
+ $$PWD/skippedsourceranges.h
SOURCES += $$PWD/clangipcserver.cpp \
$$PWD/codecompleter.cpp \
@@ -51,4 +57,9 @@ SOURCES += $$PWD/clangipcserver.cpp \
$$PWD/fixit.cpp \
$$PWD/clangfilesystemwatcher.cpp \
$$PWD/translationunitalreadyexistsexception.cpp \
- $$PWD/commandlinearguments.cpp
+ $$PWD/commandlinearguments.cpp \
+ $$PWD/cursor.cpp \
+ $$PWD/type.cpp \
+ $$PWD/highlightinginformations.cpp \
+ $$PWD/highlightinginformation.cpp \
+ $$PWD/skippedsourceranges.cpp
diff --git a/src/tools/clangbackend/ipcsource/clangstring.cpp b/src/tools/clangbackend/ipcsource/clangstring.cpp
index 200e834270..5decaf1549 100644
--- a/src/tools/clangbackend/ipcsource/clangstring.cpp
+++ b/src/tools/clangbackend/ipcsource/clangstring.cpp
@@ -61,6 +61,11 @@ ClangString &ClangString::operator=(ClangString &&other)
return *this;
}
+const char *ClangString::cString() const
+{
+ return clang_getCString(cxString);
+}
+
ClangString::ClangString(ClangString &&other)
: cxString(std::move(other.cxString))
{
@@ -70,7 +75,7 @@ ClangString::ClangString(ClangString &&other)
ClangString::operator Utf8String() const
{
- return Utf8String(clang_getCString(cxString), -1);
+ return Utf8String(cString(), -1);
}
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/clangstring.h b/src/tools/clangbackend/ipcsource/clangstring.h
index f18a612282..2db7b8ade0 100644
--- a/src/tools/clangbackend/ipcsource/clangstring.h
+++ b/src/tools/clangbackend/ipcsource/clangstring.h
@@ -51,6 +51,8 @@ public:
operator Utf8String() const;
+ const char *cString() const;
+
bool isNull() const;
private:
diff --git a/src/tools/clangbackend/ipcsource/cursor.cpp b/src/tools/clangbackend/ipcsource/cursor.cpp
new file mode 100644
index 0000000000..7ea5009d4d
--- /dev/null
+++ b/src/tools/clangbackend/ipcsource/cursor.cpp
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "cursor.h"
+
+#include "clangstring.h"
+#include "sourcelocation.h"
+#include "sourcerange.h"
+
+#include <ostream>
+
+namespace ClangBackEnd {
+
+Cursor::Cursor()
+ : cxCursor(clang_getNullCursor())
+{
+}
+
+Cursor::Cursor(CXCursor cxCursor)
+ : cxCursor(cxCursor)
+{
+}
+
+bool Cursor::isNull() const
+{
+ return clang_Cursor_isNull(cxCursor);
+}
+
+bool Cursor::isValid() const
+{
+ return !clang_isInvalid(kind());
+}
+
+bool Cursor::isTranslationUnit() const
+{
+ return clang_isTranslationUnit(kind());
+}
+
+bool Cursor::isDefinition() const
+{
+ return clang_isCursorDefinition(cxCursor);
+}
+
+bool Cursor::isDynamicCall() const
+{
+ return clang_Cursor_isDynamicCall(cxCursor);
+}
+
+bool Cursor::isVirtualMethod() const
+{
+ return clang_CXXMethod_isVirtual(cxCursor);
+}
+
+bool Cursor::isPureVirtualMethod() const
+{
+ return clang_CXXMethod_isPureVirtual(cxCursor);
+}
+
+bool Cursor::isConstantMethod() const
+{
+ return clang_CXXMethod_isConst(cxCursor);
+}
+
+bool Cursor::isStaticMethod() const
+{
+ return clang_CXXMethod_isStatic(cxCursor);
+}
+
+bool Cursor::isCompoundType() const
+{
+ switch (kind()) {
+ case CXCursor_ClassDecl:
+ case CXCursor_StructDecl:
+ case CXCursor_UnionDecl: return true;
+ default: return false;
+ }
+}
+
+bool Cursor::isDeclaration() const
+{
+ return clang_isDeclaration(kind());
+}
+
+bool Cursor::isLocalVariable() const
+{
+ switch (semanticParent().kind()) {
+ case CXCursor_FunctionDecl:
+ case CXCursor_CXXMethod:
+ case CXCursor_Constructor:
+ case CXCursor_Destructor:
+ case CXCursor_ConversionFunction:
+ case CXCursor_FunctionTemplate:
+ case CXCursor_ObjCInstanceMethodDecl: return true;
+ default:
+ return false;
+ }
+}
+
+bool Cursor::hasFinalFunctionAttribute() const
+{
+ bool hasFinal = false;
+
+ visit([&] (Cursor cursor, Cursor /*parent*/) {
+ if (cursor.kind() == CXCursor_CXXFinalAttr) {
+ hasFinal = true;
+ return CXChildVisit_Break;
+ } else {
+ return CXChildVisit_Recurse;
+ }
+ });
+
+ return hasFinal;
+}
+
+bool Cursor::hasFinalClassAttribute() const
+{
+ bool hasFinal = false;
+
+ visit([&] (Cursor cursor, Cursor /*parent*/) {
+ switch (cursor.kind()) {
+ case CXCursor_CXXFinalAttr:
+ hasFinal = true;
+ return CXChildVisit_Break;
+ case CXCursor_CXXMethod:
+ return CXChildVisit_Break;
+ default:
+ return CXChildVisit_Recurse;
+ }
+ });
+
+ return hasFinal;
+}
+
+bool Cursor::isUnexposed() const
+{
+ return clang_isUnexposed(kind());
+}
+
+Utf8String Cursor::unifiedSymbolResolution() const
+{
+ return ClangString(clang_getCursorUSR(cxCursor));
+}
+
+Utf8String Cursor::mangling() const
+{
+ return ClangString(clang_Cursor_getMangling(cxCursor));
+}
+
+ClangString Cursor::spelling() const
+{
+ return ClangString(clang_getCursorSpelling(cxCursor));
+}
+
+Utf8String Cursor::displayName() const
+{
+ return ClangString(clang_getCursorDisplayName(cxCursor));
+}
+
+Utf8String Cursor::briefComment() const
+{
+ return ClangString(clang_Cursor_getBriefCommentText(cxCursor));
+}
+
+Utf8String Cursor::rawComment() const
+{
+ return ClangString(clang_Cursor_getRawCommentText(cxCursor));
+}
+
+int Cursor::argumentCount() const
+{
+ return clang_Cursor_getNumArguments(cxCursor);
+}
+
+Type Cursor::type() const
+{
+ return clang_getCursorType(cxCursor);
+}
+
+Type Cursor::nonPointerTupe() const
+{
+ auto typeResult = type();
+
+ if (typeResult.isPointer())
+ typeResult = typeResult.pointeeType();
+
+ return typeResult;
+}
+
+SourceLocation Cursor::sourceLocation() const
+{
+ return clang_getCursorLocation(cxCursor);
+}
+
+SourceRange Cursor::sourceRange() const
+{
+ return clang_getCursorExtent(cxCursor);
+}
+
+SourceRange Cursor::commentRange() const
+{
+ return clang_Cursor_getCommentRange(cxCursor);
+}
+
+Cursor Cursor::definition() const
+{
+ return clang_getCursorDefinition(cxCursor);
+}
+
+Cursor Cursor::canonical() const
+{
+ return clang_getCanonicalCursor(cxCursor);
+}
+
+Cursor Cursor::referenced() const
+{
+ return clang_getCursorReferenced(cxCursor);
+}
+
+Cursor Cursor::semanticParent() const
+{
+ return clang_getCursorSemanticParent(cxCursor);
+}
+
+Cursor Cursor::lexicalParent() const
+{
+ return clang_getCursorLexicalParent(cxCursor);
+}
+
+Cursor Cursor::functionBaseDeclaration() const
+{
+ auto functionBaseCursor = functionBase();
+
+ if (functionBaseCursor.isValid())
+ return functionBaseCursor.nonPointerTupe().canonical().declaration();
+ else
+ return semanticParent().semanticParent();
+}
+
+Cursor Cursor::functionBase() const
+{
+ Cursor functionBaseCursor;
+
+ visit([&] (Cursor cursor, Cursor /*parentCursor*/) {
+ switch (cursor.kind()) {
+ case CXCursor_DeclRefExpr:
+ functionBaseCursor = cursor; ;
+ return CXChildVisit_Break;
+ default:
+ return CXChildVisit_Recurse;
+ }
+ });
+
+ return functionBaseCursor;
+}
+
+Cursor Cursor::argument(int index) const
+{
+ return clang_Cursor_getArgument(cxCursor, index);
+}
+namespace {
+void collectOutputArguments(const Cursor &callExpression,
+ std::vector<Cursor> &outputArguments)
+{
+ auto callExpressionType = callExpression.referenced().type();
+ auto argumentCount = callExpression.argumentCount();
+ outputArguments.reserve(argumentCount);
+
+ for (int argumentIndex = 0; argumentIndex < argumentCount; ++argumentIndex) {
+ auto argument = callExpression.argument(argumentIndex);
+ auto argumentType = callExpressionType.argument(argumentIndex);
+
+ if (!argument.isUnexposed() && argumentType.isOutputParameter())
+ outputArguments.push_back(callExpression.argument(argumentIndex));
+ }
+}
+}
+
+std::vector<Cursor> Cursor::outputArguments() const
+{
+ std::vector<Cursor> outputArguments;
+
+ if (kind() == CXCursor_CallExpr)
+ collectOutputArguments(*this, outputArguments);
+
+ return outputArguments;
+}
+
+CXCursorKind Cursor::kind() const
+{
+ return clang_getCursorKind(cxCursor);
+}
+
+bool operator==(const Cursor &first, const Cursor &second)
+{
+ return clang_equalCursors(first.cxCursor, second.cxCursor);
+}
+
+void PrintTo(CXCursorKind cursorKind, ::std::ostream *os)
+{
+ ClangString cursorKindSpelling(clang_getCursorKindSpelling(cursorKind));
+ *os << cursorKindSpelling.cString();
+}
+
+void PrintTo(const Cursor &cursor, ::std::ostream*os)
+{
+ if (cursor.isValid()) {
+ ClangString cursorKindSpelling(clang_getCursorKindSpelling(cursor.kind()));
+ *os << cursorKindSpelling.cString() << " ";
+
+ auto identifier = cursor.displayName();
+ if (identifier.hasContent()) {
+ *os << "\""
+ << identifier.constData()
+ << "\": ";
+ }
+
+ PrintTo(cursor.sourceLocation(), os);
+ } else {
+ *os << "Invalid cursor!";
+ }
+}
+
+} // namespace ClangBackEnd
+
diff --git a/src/tools/clangbackend/ipcsource/cursor.h b/src/tools/clangbackend/ipcsource/cursor.h
new file mode 100644
index 0000000000..d4256401e5
--- /dev/null
+++ b/src/tools/clangbackend/ipcsource/cursor.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef CLANGBACKEND_CURSOR_H
+#define CLANGBACKEND_CURSOR_H
+
+#include "type.h"
+
+#include <clang-c/Index.h>
+
+#include <iosfwd>
+
+#include <vector>
+
+class Utf8String;
+
+namespace ClangBackEnd {
+
+class SourceLocation;
+class SourceRange;
+class ClangString;
+
+class Cursor
+{
+ friend class Type;
+ friend bool operator==(const Cursor &first, const Cursor &second);
+public:
+ Cursor();
+ Cursor(CXCursor cxCursor);
+
+ bool isNull() const;
+ bool isValid() const;
+
+ bool isTranslationUnit() const;
+ bool isDefinition() const;
+ bool isDynamicCall() const;
+ bool isVirtualMethod() const;
+ bool isPureVirtualMethod() const;
+ bool isConstantMethod() const;
+ bool isStaticMethod() const;
+ bool isCompoundType() const;
+ bool isDeclaration() const;
+ bool isLocalVariable() const;
+ bool hasFinalFunctionAttribute() const;
+ bool hasFinalClassAttribute() const;
+ bool isUnexposed() const;
+
+ Utf8String unifiedSymbolResolution() const;
+ Utf8String mangling() const;
+ ClangString spelling() const;
+ Utf8String displayName() const;
+ Utf8String briefComment() const;
+ Utf8String rawComment() const;
+ int argumentCount() const;
+
+ Type type() const;
+ Type nonPointerTupe() const;
+
+ SourceLocation sourceLocation() const;
+ SourceRange sourceRange() const;
+ SourceRange commentRange() const;
+
+ Cursor definition() const;
+ Cursor canonical() const;
+ Cursor alias() const;
+ Cursor referenced() const;
+ Cursor semanticParent() const;
+ Cursor lexicalParent() const;
+ Cursor functionBaseDeclaration() const;
+ Cursor functionBase() const;
+ Cursor argument(int index) const;
+ std::vector<Cursor> outputArguments() const;
+
+ CXCursorKind kind() const;
+
+ template <class VisitorCallback>
+ void visit(VisitorCallback visitorCallback) const;
+
+private:
+ CXCursor cxCursor;
+};
+
+template <class VisitorCallback>
+void Cursor::visit(VisitorCallback visitorCallback) const
+{
+ auto visitor = [] (CXCursor cursor, CXCursor parent, CXClientData lambda) -> CXChildVisitResult {
+ auto &visitorCallback = *static_cast<VisitorCallback*>(lambda);
+
+ return visitorCallback(cursor, parent);
+ };
+
+ clang_visitChildren(cxCursor, visitor, &visitorCallback);
+}
+
+bool operator==(const Cursor &first, const Cursor &second);
+
+void PrintTo(CXCursorKind cursorKind, ::std::ostream *os);
+void PrintTo(const Cursor &cursor, ::std::ostream* os);
+} // namespace ClangBackEnd
+
+
+#endif // CLANGBACKEND_CURSOR_H
diff --git a/src/tools/clangbackend/ipcsource/diagnostic.cpp b/src/tools/clangbackend/ipcsource/diagnostic.cpp
index fdb7a0940a..81e519894b 100644
--- a/src/tools/clangbackend/ipcsource/diagnostic.cpp
+++ b/src/tools/clangbackend/ipcsource/diagnostic.cpp
@@ -113,7 +113,7 @@ std::vector<SourceRange> Diagnostic::ranges() const
const SourceRange sourceRange(clang_getDiagnosticRange(cxDiagnostic, index));
if (sourceRange.isValid())
- ranges.push_back(SourceRange(clang_getDiagnosticRange(cxDiagnostic, index)));
+ ranges.push_back(std::move(sourceRange));
}
return ranges;
diff --git a/src/tools/clangbackend/ipcsource/highlightinginformation.cpp b/src/tools/clangbackend/ipcsource/highlightinginformation.cpp
new file mode 100644
index 0000000000..808a0407d1
--- /dev/null
+++ b/src/tools/clangbackend/ipcsource/highlightinginformation.cpp
@@ -0,0 +1,304 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "clangstring.h"
+#include "cursor.h"
+#include "highlightinginformation.h"
+#include "sourcelocation.h"
+#include "sourcerange.h"
+
+#include <cstring>
+#include <ostream>
+
+#include <QDebug>
+
+namespace ClangBackEnd {
+
+HighlightingInformation::HighlightingInformation(const CXCursor &cxCursor,
+ CXToken *cxToken,
+ CXTranslationUnit cxTranslationUnit)
+{
+ const SourceRange sourceRange = clang_getTokenExtent(cxTranslationUnit, *cxToken);
+ const auto start = sourceRange.start();
+ const auto end = sourceRange.end();
+
+ originalCursor = cxCursor;
+ line = start.line();
+ column = start.column();
+ length = end.offset() - start.offset();
+ type = kind(cxToken, originalCursor);
+}
+
+HighlightingInformation::HighlightingInformation(uint line, uint column, uint length, HighlightingType type)
+ : line(line),
+ column(column),
+ length(length),
+ type(type)
+{
+}
+
+bool HighlightingInformation::hasType(HighlightingType type) const
+{
+ return this->type == type;
+}
+
+bool HighlightingInformation::hasFunctionArguments() const
+{
+ return originalCursor.argumentCount() > 0;
+}
+
+QVector<HighlightingInformation> HighlightingInformation::outputFunctionArguments() const
+{
+ QVector<HighlightingInformation> outputFunctionArguments;
+
+ return outputFunctionArguments;
+}
+
+namespace {
+
+bool isFinalFunction(const Cursor &cursor)
+{
+ auto referencedCursor = cursor.referenced();
+ if (referencedCursor.hasFinalFunctionAttribute())
+ return true;
+
+ else return false;
+}
+
+bool isFunctionInFinalClass(const Cursor &cursor)
+{
+ auto functionBase = cursor.functionBaseDeclaration();
+ if (functionBase.isValid() && functionBase.hasFinalClassAttribute())
+ return true;
+
+ return false;
+}
+}
+
+HighlightingType HighlightingInformation::memberReferenceKind(const Cursor &cursor) const
+{
+ if (cursor.isDynamicCall()) {
+ if (isFinalFunction(cursor) || isFunctionInFinalClass(cursor))
+ return HighlightingType::Function;
+ else
+ return HighlightingType::VirtualFunction;
+ }
+
+ return identifierKind(cursor.referenced());
+
+}
+
+HighlightingType HighlightingInformation::referencedTypeKind(const Cursor &cursor) const
+{
+ const Cursor referencedCursor = cursor.referenced();
+
+ switch (referencedCursor.kind()) {
+ case CXCursor_ClassDecl:
+ case CXCursor_StructDecl:
+ case CXCursor_UnionDecl:
+ case CXCursor_TemplateTypeParameter:
+ case CXCursor_TypeAliasDecl: return HighlightingType::Type;
+ case CXCursor_EnumDecl: return HighlightingType::Enumeration;
+ default: return HighlightingType::Invalid;
+ }
+
+ Q_UNREACHABLE();
+}
+
+HighlightingType HighlightingInformation::variableKind(const Cursor &cursor) const
+{
+ if (cursor.isLocalVariable())
+ return HighlightingType::LocalVariable;
+ else
+ return HighlightingType::GlobalVariable;
+}
+
+bool HighlightingInformation::isVirtualMethodDeclarationOrDefinition(const Cursor &cursor) const
+{
+ return cursor.isVirtualMethod()
+ && (originalCursor.isDeclaration() || originalCursor.isDefinition());
+}
+namespace {
+bool isNotFinalFunction(const Cursor &cursor)
+{
+ return !cursor.hasFinalFunctionAttribute();
+}
+
+}
+bool HighlightingInformation::isRealDynamicCall(const Cursor &cursor) const
+{
+
+ return originalCursor.isDynamicCall() && isNotFinalFunction(cursor);
+}
+
+HighlightingType HighlightingInformation::functionKind(const Cursor &cursor) const
+{
+ if (isRealDynamicCall(cursor) || isVirtualMethodDeclarationOrDefinition(cursor))
+ return HighlightingType::VirtualFunction;
+ else
+ return HighlightingType::Function;
+}
+
+HighlightingType HighlightingInformation::identifierKind(const Cursor &cursor) const
+{
+ switch (cursor.kind()) {
+ case CXCursor_Destructor:
+ case CXCursor_Constructor:
+ case CXCursor_FunctionDecl:
+ case CXCursor_CallExpr:
+ case CXCursor_CXXMethod: return functionKind(cursor);
+ case CXCursor_NonTypeTemplateParameter:
+ case CXCursor_ParmDecl: return HighlightingType::LocalVariable;
+ case CXCursor_VarDecl: return variableKind(cursor);
+ case CXCursor_DeclRefExpr: return identifierKind(cursor.referenced());
+ case CXCursor_MemberRefExpr: return memberReferenceKind(cursor);
+ case CXCursor_FieldDecl:
+ case CXCursor_MemberRef:
+ case CXCursor_ObjCIvarDecl:
+ case CXCursor_ObjCPropertyDecl:
+ case CXCursor_ObjCClassMethodDecl:
+ case CXCursor_ObjCInstanceMethodDecl:
+ case CXCursor_ObjCSynthesizeDecl:
+ case CXCursor_ObjCDynamicDecl: return HighlightingType::Field;
+ case CXCursor_TypeRef: return referencedTypeKind(cursor);
+ case CXCursor_ClassDecl:
+ case CXCursor_TemplateTypeParameter:
+ case CXCursor_TemplateTemplateParameter:
+ case CXCursor_UnionDecl:
+ case CXCursor_StructDecl:
+ case CXCursor_TemplateRef:
+ case CXCursor_Namespace:
+ case CXCursor_NamespaceRef:
+ case CXCursor_NamespaceAlias:
+ case CXCursor_TypeAliasDecl:
+ case CXCursor_ClassTemplate:
+ case CXCursor_UnexposedDecl:
+ case CXCursor_CXXStaticCastExpr:
+ case CXCursor_CXXReinterpretCastExpr:
+ case CXCursor_ObjCCategoryDecl:
+ case CXCursor_ObjCCategoryImplDecl:
+ case CXCursor_ObjCImplementationDecl:
+ case CXCursor_ObjCInterfaceDecl:
+ case CXCursor_ObjCProtocolDecl:
+ case CXCursor_ObjCProtocolRef:
+ case CXCursor_ObjCClassRef:
+ case CXCursor_ObjCSuperClassRef: return HighlightingType::Type;
+ case CXCursor_FunctionTemplate: return HighlightingType::Function;
+ case CXCursor_EnumConstantDecl: return HighlightingType::Enumeration;
+ case CXCursor_EnumDecl: return referencedTypeKind(cursor);
+ case CXCursor_PreprocessingDirective: return HighlightingType::Preprocessor;
+ case CXCursor_MacroExpansion: return HighlightingType::PreprocessorExpansion;
+ case CXCursor_MacroDefinition: return HighlightingType::PreprocessorDefinition;
+ case CXCursor_InclusionDirective: return HighlightingType::StringLiteral;
+ case CXCursor_LabelRef:
+ case CXCursor_LabelStmt: return HighlightingType::Label;
+ default: return HighlightingType::Invalid;
+ }
+
+ Q_UNREACHABLE();
+}
+
+namespace {
+HighlightingType literalKind(const Cursor &cursor)
+{
+ switch (cursor.kind()) {
+ case CXCursor_CharacterLiteral:
+ case CXCursor_StringLiteral:
+ case CXCursor_ObjCStringLiteral: return HighlightingType::StringLiteral;
+ case CXCursor_IntegerLiteral:
+ case CXCursor_ImaginaryLiteral:
+ case CXCursor_FloatingLiteral: return HighlightingType::NumberLiteral;
+ default: return HighlightingType::Invalid;
+ }
+
+ Q_UNREACHABLE();
+}
+
+
+HighlightingType punctationKind(const Cursor &cursor)
+{
+ switch (cursor.kind()) {
+ case CXCursor_DeclRefExpr: return HighlightingType::Operator;
+ default: return HighlightingType::Invalid;
+ }
+}
+
+}
+HighlightingType HighlightingInformation::kind(CXToken *cxToken, const Cursor &cursor) const
+{
+ auto cxTokenKind = clang_getTokenKind(*cxToken);
+
+ switch (cxTokenKind) {
+ case CXToken_Keyword: return HighlightingType::Keyword;
+ case CXToken_Punctuation: return punctationKind(cursor);
+ case CXToken_Identifier: return identifierKind(cursor);
+ case CXToken_Comment: return HighlightingType::Comment;
+ case CXToken_Literal: return literalKind(cursor);
+ }
+
+ Q_UNREACHABLE();
+}
+
+void PrintTo(const HighlightingInformation& information, ::std::ostream *os)
+{
+ *os << "type: ";
+ PrintTo(information.type, os);
+ *os << " line: " << information.line
+ << " column: " << information.column
+ << " length: " << information.length;
+}
+
+void PrintTo(HighlightingType highlightingType, std::ostream *os)
+{
+ switch (highlightingType) {
+ case HighlightingType::Invalid: *os << "Invalid"; break;
+ case HighlightingType::Comment: *os << "Comment"; break;
+ case HighlightingType::Keyword: *os << "Keyword"; break;
+ case HighlightingType::StringLiteral: *os << "StringLiteral"; break;
+ case HighlightingType::NumberLiteral: *os << "NumberLiteral"; break;
+ case HighlightingType::Function: *os << "Function"; break;
+ case HighlightingType::VirtualFunction: *os << "VirtualFunction"; break;
+ case HighlightingType::Type: *os << "Type"; break;
+ case HighlightingType::LocalVariable: *os << "LocalVariable"; break;
+ case HighlightingType::GlobalVariable: *os << "GlobalVariable"; break;
+ case HighlightingType::Field: *os << "Field"; break;
+ case HighlightingType::Enumeration: *os << "Enumeration"; break;
+ case HighlightingType::Operator: *os << "Operator"; break;
+ case HighlightingType::Preprocessor: *os << "Preprocessor"; break;
+ case HighlightingType::Label: *os << "Label"; break;
+ case HighlightingType::OutputArgument: *os << "OutputArgument"; break;
+ case HighlightingType::PreprocessorDefinition: *os << "PreprocessorDefinition"; break;
+ case HighlightingType::PreprocessorExpansion: *os << "PreprocessorExpansion"; break;
+ }
+}
+
+
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/highlightinginformation.h b/src/tools/clangbackend/ipcsource/highlightinginformation.h
new file mode 100644
index 0000000000..ee327b6213
--- /dev/null
+++ b/src/tools/clangbackend/ipcsource/highlightinginformation.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef CLANGBACKEND_HIGHLIGHTINGINFORMATION_H
+#define CLANGBACKEND_HIGHLIGHTINGINFORMATION_H
+
+#include <clangbackendipc_global.h>
+
+#include "cursor.h"
+
+#include <clang-c/Index.h>
+
+namespace ClangBackEnd {
+
+class HighlightingInformation
+{
+ friend bool operator==(const HighlightingInformation &first, const HighlightingInformation &second);
+ friend void PrintTo(const HighlightingInformation& highlightingInformation, ::std::ostream *os);
+
+public:
+ HighlightingInformation(const CXCursor &cxCursor, CXToken *cxToken, CXTranslationUnit cxTranslationUnit);
+ HighlightingInformation(uint line, uint column, uint length, HighlightingType type);
+
+ bool hasType(HighlightingType type) const;
+ bool hasFunctionArguments() const;
+ QVector<HighlightingInformation> outputFunctionArguments() const;
+
+private:
+ HighlightingType identifierKind(const Cursor &cursor) const;
+ HighlightingType referencedTypeKind(const Cursor &cursor) const;
+ HighlightingType variableKind(const Cursor &cursor) const;
+ bool isVirtualMethodDeclarationOrDefinition(const Cursor &cursor) const;
+ HighlightingType functionKind(const Cursor &cursor) const;
+ HighlightingType memberReferenceKind(const Cursor &cursor) const;
+ HighlightingType kind(CXToken *cxToken, const Cursor &cursor) const;
+ bool isRealDynamicCall(const Cursor &cursor) const;
+
+private:
+ Cursor originalCursor;
+ uint line;
+ uint column;
+ uint length;
+ HighlightingType type;
+};
+
+void PrintTo(const HighlightingInformation& highlightingInformation, ::std::ostream *os);
+void PrintTo(HighlightingType highlightingType, ::std::ostream *os);
+
+inline bool operator==(const HighlightingInformation &first, const HighlightingInformation &second)
+{
+ return first.line == second.line
+ && first.column == second.column
+ && first.length == second.length
+ && first.type == second.type;
+}
+
+} // namespace ClangBackEnd
+
+#endif // CLANGBACKEND_HIGHLIGHTINGINFORMATION_H
diff --git a/src/tools/clangbackend/ipcsource/highlightinginformations.cpp b/src/tools/clangbackend/ipcsource/highlightinginformations.cpp
new file mode 100644
index 0000000000..f7157768fd
--- /dev/null
+++ b/src/tools/clangbackend/ipcsource/highlightinginformations.cpp
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "highlightinginformations.h"
+
+namespace ClangBackEnd {
+
+HighlightingInformations::HighlightingInformations(CXTranslationUnit cxTranslationUnit, CXToken *tokens, uint tokensCount)
+ : cxTranslationUnit(cxTranslationUnit),
+ cxToken(tokens),
+ cxTokenCount(tokensCount)
+{
+ cxCursor.resize(tokensCount);
+ clang_annotateTokens(cxTranslationUnit, cxToken, cxTokenCount, cxCursor.data());
+}
+
+HighlightingInformations::~HighlightingInformations()
+{
+ clang_disposeTokens(cxTranslationUnit, cxToken, cxTokenCount);
+}
+
+HighlightingInformations::const_iterator HighlightingInformations::begin() const
+{
+ return const_iterator(cxCursor.cbegin(), cxToken, cxTranslationUnit);
+}
+
+HighlightingInformations::const_iterator HighlightingInformations::end() const
+{
+ return const_iterator(cxCursor.cend(), cxToken + cxTokenCount, cxTranslationUnit);
+}
+
+bool HighlightingInformations::isEmpty() const
+{
+ return cxTokenCount == 0;
+}
+
+bool ClangBackEnd::HighlightingInformations::isNull() const
+{
+ return cxToken == nullptr;
+}
+
+uint HighlightingInformations::size() const
+{
+ return cxTokenCount;
+}
+
+HighlightingInformation HighlightingInformations::operator[](size_t index) const
+{
+ return HighlightingInformation(cxCursor[index], cxToken + index, cxTranslationUnit);
+}
+
+} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/highlightinginformations.h b/src/tools/clangbackend/ipcsource/highlightinginformations.h
new file mode 100644
index 0000000000..2c7b8ce9bb
--- /dev/null
+++ b/src/tools/clangbackend/ipcsource/highlightinginformations.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef CLANGBACKEND_HIGHLIGHTINGINFORMATIONS_H
+#define CLANGBACKEND_HIGHLIGHTINGINFORMATIONS_H
+
+#include "highlightinginformationsiterator.h"
+
+#include <clang-c/Index.h>
+
+#include <vector>
+
+namespace ClangBackEnd {
+
+using uint = unsigned int;
+
+class HighlightingInformations
+{
+public:
+ using const_iterator = HighlightingInformationsIterator;
+ using value_type = HighlightingInformation;
+
+public:
+ HighlightingInformations() = default;
+ HighlightingInformations(CXTranslationUnit cxTranslationUnit, CXToken *tokens, uint tokensCount);
+ ~HighlightingInformations();
+
+ bool isEmpty() const;
+ bool isNull() const;
+ uint size() const;
+
+ HighlightingInformation operator[](size_t index) const;
+
+ const_iterator begin() const;
+ const_iterator end() const;
+
+private:
+ CXTranslationUnit cxTranslationUnit = nullptr;
+ CXToken *const cxToken = nullptr;
+ const uint cxTokenCount = 0;
+
+ std::vector<CXCursor> cxCursor;
+};
+
+} // namespace ClangBackEnd
+
+#endif // CLANGBACKEND_HIGHLIGHTINGINFORMATIONS_H
diff --git a/src/tools/clangbackend/ipcsource/highlightinginformationsiterator.h b/src/tools/clangbackend/ipcsource/highlightinginformationsiterator.h
new file mode 100644
index 0000000000..53f540970e
--- /dev/null
+++ b/src/tools/clangbackend/ipcsource/highlightinginformationsiterator.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef HIGHLIGHTINGINFORMATIONSITERATOR_H
+#define HIGHLIGHTINGINFORMATIONSITERATOR_H
+
+#include "highlightinginformation.h"
+
+#include <iterator>
+#include <vector>
+
+#include <clang-c/Index.h>
+
+namespace ClangBackEnd {
+
+using uint = unsigned int;
+
+class DiagnosticSet;
+class Diagnostic;
+
+class HighlightingInformationsIterator : public std::iterator<std::forward_iterator_tag, HighlightingInformation, uint>
+{
+public:
+ HighlightingInformationsIterator(std::vector<CXCursor>::const_iterator cxCursorIterator,
+ CXToken *cxToken,
+ CXTranslationUnit cxTranslationUnit)
+ : cxCursorIterator(cxCursorIterator),
+ cxToken(cxToken),
+ cxTranslationUnit(cxTranslationUnit)
+ {}
+
+ HighlightingInformationsIterator(const HighlightingInformationsIterator &other)
+ : cxCursorIterator(other.cxCursorIterator)
+ {}
+
+ HighlightingInformationsIterator& operator++()
+ {
+ ++cxCursorIterator;
+ ++cxToken;
+
+ return *this;
+ }
+
+ HighlightingInformationsIterator operator++(int)
+ {
+ return HighlightingInformationsIterator(cxCursorIterator++, cxToken++, cxTranslationUnit);
+ }
+
+ bool operator==(HighlightingInformationsIterator other) const
+ {
+ return cxCursorIterator == other.cxCursorIterator;
+ }
+
+ bool operator!=(HighlightingInformationsIterator other) const
+ {
+ return cxCursorIterator != other.cxCursorIterator;
+ }
+
+ HighlightingInformation operator*()
+ {
+ return HighlightingInformation(*cxCursorIterator, cxToken, cxTranslationUnit);
+ }
+
+private:
+ std::vector<CXCursor>::const_iterator cxCursorIterator;
+ CXToken *cxToken;
+ CXTranslationUnit cxTranslationUnit;
+};
+
+} // namespace ClangBackEnd
+
+#endif // HIGHLIGHTINGINFORMATIONSITERATOR_H
diff --git a/src/tools/clangbackend/ipcsource/skippedsourceranges.cpp b/src/tools/clangbackend/ipcsource/skippedsourceranges.cpp
new file mode 100644
index 0000000000..2a39131474
--- /dev/null
+++ b/src/tools/clangbackend/ipcsource/skippedsourceranges.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#include "skippedsourceranges.h"
+
+#include "sourcerangecontainer.h"
+
+#include <QVector>
+
+#include <algorithm>
+
+namespace ClangBackEnd {
+
+SkippedSourceRanges::SkippedSourceRanges(CXTranslationUnit cxTranslationUnit, const char *filePath)
+{
+ cxSkippedSourceRanges = clang_getSkippedRanges(cxTranslationUnit,
+ clang_getFile(cxTranslationUnit,
+ filePath));
+}
+
+SkippedSourceRanges::~SkippedSourceRanges()
+{
+ clang_disposeSourceRangeList(cxSkippedSourceRanges);
+}
+
+SkippedSourceRanges &SkippedSourceRanges::operator=(SkippedSourceRanges &&other)
+{
+ if (this != &other) {
+ cxSkippedSourceRanges = other.cxSkippedSourceRanges;
+ other.cxSkippedSourceRanges = nullptr;
+ }
+
+ return *this;
+}
+
+std::vector<SourceRange> SkippedSourceRanges::sourceRanges() const
+{
+ std::vector<SourceRange> sourceRanges;
+
+ auto sourceRangeCount = cxSkippedSourceRanges->count;
+ sourceRanges.reserve(sourceRangeCount);
+
+ std::copy(cxSkippedSourceRanges->ranges,
+ cxSkippedSourceRanges->ranges + sourceRangeCount,
+ std::back_inserter(sourceRanges));
+
+ return sourceRanges;
+}
+
+QVector<SourceRangeContainer> SkippedSourceRanges::toSourceRangeContainers() const
+{
+ QVector<SourceRangeContainer> sourceRangeContainers;
+
+ auto sourceRanges = this->sourceRanges();
+
+ std::copy(sourceRanges.cbegin(),
+ sourceRanges.cend(),
+ std::back_inserter(sourceRangeContainers));
+
+ return sourceRangeContainers;
+}
+
+ClangBackEnd::SkippedSourceRanges::operator QVector<SourceRangeContainer>() const
+{
+ return toSourceRangeContainers();
+}
+
+SkippedSourceRanges::SkippedSourceRanges(SkippedSourceRanges &&other)
+ : cxSkippedSourceRanges(other.cxSkippedSourceRanges)
+{
+ other.cxSkippedSourceRanges = nullptr;
+}
+
+} // namespace ClangBackEnd
+
diff --git a/src/tools/clangbackend/ipcsource/skippedsourceranges.h b/src/tools/clangbackend/ipcsource/skippedsourceranges.h
new file mode 100644
index 0000000000..8d38bc50c9
--- /dev/null
+++ b/src/tools/clangbackend/ipcsource/skippedsourceranges.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+#ifndef CLANGBACKEND_SKIPPEDSOURCERANGES_H
+#define CLANGBACKEND_SKIPPEDSOURCERANGES_H
+
+#include "sourcerange.h"
+
+namespace ClangBackEnd {
+
+class SourceRangeContainer;
+
+class SkippedSourceRanges
+{
+public:
+ SkippedSourceRanges(CXTranslationUnit TranslationUnit, const char *filePath);
+ ~SkippedSourceRanges();
+
+ SkippedSourceRanges(const SkippedSourceRanges &) = delete;
+ const SkippedSourceRanges &operator=(const SkippedSourceRanges &) = delete;
+
+ SkippedSourceRanges(SkippedSourceRanges &&);
+ SkippedSourceRanges &operator=(SkippedSourceRanges &&);
+
+ std::vector<SourceRange> sourceRanges() const;
+
+ QVector<SourceRangeContainer> toSourceRangeContainers() const;
+
+ operator QVector<SourceRangeContainer>() const;
+
+private:
+ CXSourceRangeList *cxSkippedSourceRanges;
+};
+
+} // namespace ClangBackEnd
+
+#endif // CLANGBACKEND_SKIPPEDSOURCERANGES_H
diff --git a/src/tools/clangbackend/ipcsource/sourcelocation.cpp b/src/tools/clangbackend/ipcsource/sourcelocation.cpp
index 8a7cd0d871..e04f44c7d8 100644
--- a/src/tools/clangbackend/ipcsource/sourcelocation.cpp
+++ b/src/tools/clangbackend/ipcsource/sourcelocation.cpp
@@ -31,6 +31,7 @@
#include "sourcelocation.h"
#include "clangstring.h"
+#include "translationunit.h"
#include <utf8string.h>
@@ -39,6 +40,11 @@
namespace ClangBackEnd {
+SourceLocation::SourceLocation()
+ : cxSourceLocation(clang_getNullLocation())
+{
+}
+
const Utf8String &SourceLocation::filePath() const
{
return filePath_;
@@ -65,6 +71,7 @@ SourceLocationContainer SourceLocation::toSourceLocationContainer() const
}
SourceLocation::SourceLocation(CXSourceLocation cxSourceLocation)
+ : cxSourceLocation(cxSourceLocation)
{
CXFile cxFile;
@@ -77,10 +84,37 @@ SourceLocation::SourceLocation(CXSourceLocation cxSourceLocation)
filePath_ = ClangString(clang_getFileName(cxFile));
}
+SourceLocation::SourceLocation(CXTranslationUnit cxTranslationUnit,
+ const Utf8String &filePath,
+ uint line,
+ uint column)
+ : cxSourceLocation(clang_getLocation(cxTranslationUnit,
+ clang_getFile(cxTranslationUnit,
+ filePath.constData()),
+ line,
+ column)),
+ filePath_(filePath),
+ line_(line)
+{
+}
+
+bool operator==(const SourceLocation &first, const SourceLocation &second)
+{
+ return clang_equalLocations(first.cxSourceLocation, second.cxSourceLocation);
+}
+
+SourceLocation::operator CXSourceLocation() const
+{
+ return cxSourceLocation;
+}
+
void PrintTo(const SourceLocation &sourceLocation, std::ostream *os)
{
- *os << sourceLocation.filePath().constData()
- << ", line: " << sourceLocation.line()
+ auto filePath = sourceLocation.filePath();
+ if (filePath.hasContent())
+ *os << filePath.constData() << ", ";
+
+ *os << "line: " << sourceLocation.line()
<< ", column: "<< sourceLocation.column()
<< ", offset: "<< sourceLocation.offset();
}
diff --git a/src/tools/clangbackend/ipcsource/sourcelocation.h b/src/tools/clangbackend/ipcsource/sourcelocation.h
index 3ee500623b..83ba6c77c9 100644
--- a/src/tools/clangbackend/ipcsource/sourcelocation.h
+++ b/src/tools/clangbackend/ipcsource/sourcelocation.h
@@ -38,13 +38,19 @@
namespace ClangBackEnd {
class SourceLocationContainer;
+class TranslationUnit;
class SourceLocation
{
friend class Diagnostic;
friend class SourceRange;
+ friend class TranslationUnit;
+ friend class Cursor;
+ friend bool operator==(const SourceLocation &first, const SourceLocation &second);
public:
+ SourceLocation();
+
const Utf8String &filePath() const;
uint line() const;
uint column() const;
@@ -54,14 +60,23 @@ public:
private:
SourceLocation(CXSourceLocation cxSourceLocation);
+ SourceLocation(CXTranslationUnit cxTranslationUnit,
+ const Utf8String &filePath,
+ uint line,
+ uint column);
+
+ operator CXSourceLocation() const;
private:
+ CXSourceLocation cxSourceLocation;
Utf8String filePath_;
- uint line_;
- uint column_;
- uint offset_;
+ uint line_ = 0;
+ uint column_ = 0;
+ uint offset_ = 0;
};
+bool operator==(const SourceLocation &first, const SourceLocation &second);
+
void PrintTo(const SourceLocation &sourceLocation, ::std::ostream* os);
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/sourcerange.cpp b/src/tools/clangbackend/ipcsource/sourcerange.cpp
index 7375988b2b..f069edc9cb 100644
--- a/src/tools/clangbackend/ipcsource/sourcerange.cpp
+++ b/src/tools/clangbackend/ipcsource/sourcerange.cpp
@@ -32,6 +32,8 @@
#include <sourcerangecontainer.h>
+#include <ostream>
+
namespace ClangBackEnd {
SourceRange::SourceRange()
@@ -39,6 +41,11 @@ SourceRange::SourceRange()
{
}
+SourceRange::SourceRange(const SourceLocation &start, const SourceLocation &end)
+ : cxSourceRange(clang_getRange(start, end))
+{
+}
+
bool SourceRange::isNull() const
{
return clang_Range_isNull(cxSourceRange);
@@ -65,10 +72,33 @@ SourceRangeContainer SourceRange::toSourceRangeContainer() const
end().toSourceLocationContainer());
}
+ClangBackEnd::SourceRange::operator SourceRangeContainer() const
+{
+ return toSourceRangeContainer();
+}
+
+ClangBackEnd::SourceRange::operator CXSourceRange() const
+{
+ return cxSourceRange;
+}
+
SourceRange::SourceRange(CXSourceRange cxSourceRange)
: cxSourceRange(cxSourceRange)
{
}
+bool operator==(const SourceRange &first, const SourceRange &second)
+{
+ return clang_equalRanges(first.cxSourceRange, second.cxSourceRange);
+}
+
+void PrintTo(const SourceRange &sourceRange, ::std::ostream* os)
+{
+ *os << "[";
+ PrintTo(sourceRange.start(), os);
+ *os << ", ";
+ PrintTo(sourceRange.end(), os);
+ *os << "]";
+}
} // namespace ClangBackEnd
diff --git a/src/tools/clangbackend/ipcsource/sourcerange.h b/src/tools/clangbackend/ipcsource/sourcerange.h
index 3c80e4e040..f9b786cf4a 100644
--- a/src/tools/clangbackend/ipcsource/sourcerange.h
+++ b/src/tools/clangbackend/ipcsource/sourcerange.h
@@ -41,9 +41,14 @@ class SourceRange
{
friend class Diagnostic;
friend class FixIt;
+ friend class Cursor;
+ friend class HighlightingInformation;
+ friend bool operator==(const SourceRange &first, const SourceRange &second);
public:
SourceRange();
+ SourceRange(CXSourceRange cxSourceRange);
+ SourceRange(const SourceLocation &start, const SourceLocation &end);
bool isNull() const;
bool isValid() const;
@@ -53,13 +58,15 @@ public:
SourceRangeContainer toSourceRangeContainer() const;
-private:
- SourceRange(CXSourceRange cxSourceRange);
+ operator CXSourceRange() const;
+ operator SourceRangeContainer() const;
private:
CXSourceRange cxSourceRange;
};
+bool operator==(const SourceRange &first, const SourceRange &second);
+void PrintTo(const SourceRange &sourceRange, ::std::ostream* os);
} // namespace ClangBackEnd
#endif // CLANGBACKEND_SOURCERANGE_H
diff --git a/src/tools/clangbackend/ipcsource/translationunit.cpp b/src/tools/clangbackend/ipcsource/translationunit.cpp
index 88e917010f..8769f7caef 100644
--- a/src/tools/clangbackend/ipcsource/translationunit.cpp
+++ b/src/tools/clangbackend/ipcsource/translationunit.cpp
@@ -30,13 +30,17 @@
#include "translationunit.h"
+#include "cursor.h"
#include "clangstring.h"
#include "codecompleter.h"
#include "commandlinearguments.h"
#include "diagnosticcontainer.h"
#include "diagnosticset.h"
#include "projectpart.h"
+#include "skippedsourceranges.h"
#include "sourcelocation.h"
+#include "sourcerange.h"
+#include "highlightinginformations.h"
#include "translationunitfilenotexitexception.h"
#include "translationunitisnullexception.h"
#include "translationunitparseerrorexception.h"
@@ -245,6 +249,53 @@ void TranslationUnit::setDirtyIfDependencyIsMet(const Utf8String &filePath)
}
}
+SourceLocation TranslationUnit::sourceLocationAt(uint line, uint column) const
+{
+ return SourceLocation(cxTranslationUnit(), filePath(), line, column);
+}
+
+SourceLocation TranslationUnit::sourceLocationAt(const Utf8String &filePath, uint line, uint column) const
+{
+ return SourceLocation(cxTranslationUnit(), filePath, line, column);
+}
+
+SourceRange TranslationUnit::sourceRange(uint fromLine, uint fromColumn, uint toLine, uint toColumn) const
+{
+ return SourceRange(sourceLocationAt(fromLine, fromColumn),
+ sourceLocationAt(toLine, toColumn));
+}
+
+Cursor TranslationUnit::cursorAt(uint line, uint column) const
+{
+ return clang_getCursor(cxTranslationUnit(), sourceLocationAt(line, column));
+}
+
+Cursor TranslationUnit::cursorAt(const Utf8String &filePath, uint line, uint column) const
+{
+ return clang_getCursor(cxTranslationUnit(), sourceLocationAt(filePath, line, column));
+}
+
+Cursor TranslationUnit::cursor() const
+{
+ return clang_getTranslationUnitCursor(cxTranslationUnit());
+}
+
+HighlightingInformations TranslationUnit::highlightingInformationsInRange(const SourceRange &range) const
+{
+ CXToken *cxTokens = 0;
+ uint cxTokensCount = 0;
+ auto translationUnit = cxTranslationUnit();
+
+ clang_tokenize(translationUnit, range, &cxTokens, &cxTokensCount);
+
+ return HighlightingInformations(translationUnit, cxTokens, cxTokensCount);
+}
+
+SkippedSourceRanges TranslationUnit::skippedSourceRanges() const
+{
+ return SkippedSourceRanges(cxTranslationUnit(), d->filePath.constData());
+}
+
void TranslationUnit::checkIfNull() const
{
if (isNull())
@@ -380,7 +431,8 @@ uint TranslationUnit::defaultOptions()
{
return CXTranslationUnit_CacheCompletionResults
| CXTranslationUnit_PrecompiledPreamble
- | CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
+ | CXTranslationUnit_IncludeBriefCommentsInCodeCompletion
+ | CXTranslationUnit_DetailedPreprocessingRecord;
}
uint TranslationUnit::unsavedFilesCount() const
diff --git a/src/tools/clangbackend/ipcsource/translationunit.h b/src/tools/clangbackend/ipcsource/translationunit.h
index e44852e473..fd3831cb3e 100644
--- a/src/tools/clangbackend/ipcsource/translationunit.h
+++ b/src/tools/clangbackend/ipcsource/translationunit.h
@@ -52,8 +52,13 @@ class ProjectPart;
class DiagnosticContainer;
class DiagnosticSet;
class FileContainer;
+class HighlightingInformations;
class TranslationUnits;
class CommandLineArguments;
+class Cursor;
+class SourceLocation;
+class SourceRange;
+class SkippedSourceRanges;
using time_point = std::chrono::steady_clock::time_point;
@@ -111,6 +116,19 @@ public:
CommandLineArguments commandLineArguments() const;
+ SourceLocation sourceLocationAt(uint line, uint column) const;
+ SourceLocation sourceLocationAt(const Utf8String &filePath, uint line, uint column) const;
+
+ SourceRange sourceRange(uint fromLine, uint fromColumn, uint toLine, uint toColumn) const;
+
+ Cursor cursorAt(uint line, uint column) const;
+ Cursor cursorAt(const Utf8String &filePath, uint line, uint column) const;
+ Cursor cursor() const;
+
+ HighlightingInformations highlightingInformationsInRange(const SourceRange &range) const;
+
+ SkippedSourceRanges skippedSourceRanges() const;
+
private:
void checkIfNull() const;
void checkIfFileExists() const;
diff --git a/src/tools/clangbackend/ipcsource/type.cpp b/src/tools/clangbackend/ipcsource/type.cpp
new file mode 100644
index 0000000000..a1f78e44eb
--- /dev/null
+++ b/src/tools/clangbackend/ipcsource/type.cpp
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "type.h"
+
+#include "clangstring.h"
+#include "cursor.h"
+
+#include <utf8string.h>
+
+#include <ostream>
+
+namespace ClangBackEnd {
+
+bool Type::isConstant() const
+{
+ return clang_isConstQualifiedType(cxType);
+}
+
+bool Type::isConstantReference()
+{
+ return isLValueReference() && pointeeType().isConstant();
+}
+
+bool Type::isPointer() const
+{
+ return cxType.kind == CXType_Pointer;
+}
+
+bool Type::isPointerToConstant() const
+{
+ return isPointer() && pointeeType().isConstant();
+}
+
+bool Type::isConstantPointer() const
+{
+ return isPointer() && isConstant();
+}
+
+bool Type::isLValueReference() const
+{
+ return cxType.kind == CXType_LValueReference;
+}
+
+bool Type::isReferencingConstant() const
+{
+ return (isPointer() || isLValueReference()) && pointeeType().isConstant();
+}
+
+bool Type::isOutputParameter() const
+{
+ return (isPointer() || isLValueReference()) && !pointeeType().isConstant();
+}
+
+Utf8String Type::utf8Spelling() const
+{
+ return ClangString(clang_getTypeSpelling(cxType));
+}
+
+ClangString Type::spelling() const
+{
+ return ClangString(clang_getTypeSpelling(cxType));
+}
+
+int Type::argumentCount() const
+{
+ return clang_getNumArgTypes(cxType);
+}
+
+Type Type::alias() const
+{
+ return clang_getTypedefDeclUnderlyingType(clang_getTypeDeclaration(cxType));
+}
+
+Type Type::canonical() const
+{
+ return clang_getCanonicalType(cxType);
+}
+
+Type Type::classType() const
+{
+ return clang_Type_getClassType(cxType);
+}
+
+Type Type::pointeeType() const
+{
+ return clang_getPointeeType(cxType);
+}
+
+Type Type::argument(int index) const
+{
+ return clang_getArgType(cxType, index);
+}
+
+Cursor Type::declaration() const
+{
+ return clang_getTypeDeclaration(cxType);
+}
+
+CXTypeKind Type::kind() const
+{
+ return cxType.kind;
+}
+
+Type::Type(CXType cxType)
+ : cxType(cxType)
+{
+}
+
+bool operator==(Type first, Type second)
+{
+ return clang_equalTypes(first.cxType, second.cxType);
+}
+
+void PrintTo(CXTypeKind typeKind, ::std::ostream* os)
+{
+ ClangString typeKindSpelling(clang_getTypeKindSpelling(typeKind));
+ *os << typeKindSpelling.cString();
+}
+
+void PrintTo(const Type &type, ::std::ostream* os)
+{
+ ClangString typeKindSpelling(clang_getTypeKindSpelling(type.kind()));
+ *os << typeKindSpelling.cString()
+ << ": \"" << type.spelling().cString() << "\"";
+}
+
+
+} // namespace ClangBackEnd
+
diff --git a/src/tools/clangbackend/ipcsource/type.h b/src/tools/clangbackend/ipcsource/type.h
new file mode 100644
index 0000000000..099bfa4e3e
--- /dev/null
+++ b/src/tools/clangbackend/ipcsource/type.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef CLANGBACKEND_TYPE_H
+#define CLANGBACKEND_TYPE_H
+
+#include <clang-c/Index.h>
+
+#include <iosfwd>
+
+class Utf8String;
+
+namespace ClangBackEnd {
+
+class Cursor;
+class ClangString;
+
+class Type
+{
+ friend class Cursor;
+ friend bool operator==(Type first, Type second);
+
+public:
+ bool isConstant() const;
+ bool isConstantReference();
+ bool isPointer() const;
+ bool isPointerToConstant() const;
+ bool isConstantPointer() const;
+ bool isLValueReference() const;
+ bool isReferencingConstant() const;
+ bool isOutputParameter() const;
+
+ Utf8String utf8Spelling() const;
+ ClangString spelling() const;
+ int argumentCount() const;
+
+ Type alias() const;
+ Type canonical() const;
+ Type classType() const;
+ Type pointeeType() const;
+ Type argument(int index) const;
+
+ Cursor declaration() const;
+
+ CXTypeKind kind() const;
+
+private:
+ Type(CXType cxType);
+
+private:
+ CXType cxType;
+};
+
+bool operator==(Type first, Type second);
+
+void PrintTo(CXTypeKind typeKind, ::std::ostream* os);
+void PrintTo(const Type &type, ::std::ostream* os);
+} // namespace ClangBackEnd
+
+#endif // CLANGBACKEND_TYPE_H
diff --git a/src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.cpp b/src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.cpp
index 5c2be00058..3b7e4c52d0 100644
--- a/src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.cpp
+++ b/src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.cpp
@@ -65,12 +65,12 @@ class MkVisitor: protected SymbolVisitor
{
const LookupContext &context;
Overview oo;
- QList<LookupScope *> interfaces;
- QList<LookupScope *> nodes;
+ QList<ClassOrNamespace *> interfaces;
+ QList<ClassOrNamespace *> nodes;
- bool isMiscNode(LookupScope *b) const
+ bool isMiscNode(ClassOrNamespace *b) const
{
- foreach (LookupScope *u, b->usings()) {
+ foreach (ClassOrNamespace *u, b->usings()) {
if (oo(u->symbols().first()->name()) == QLatin1String("AST"))
return true;
}
@@ -78,7 +78,7 @@ class MkVisitor: protected SymbolVisitor
return false;
}
- QString getAcceptFunctionName(LookupScope *b, QString *retType) const
+ QString getAcceptFunctionName(ClassOrNamespace *b, QString *retType) const
{
Q_ASSERT(b != 0);
@@ -131,7 +131,7 @@ public:
<< " Semantic(TranslationUnit *unit): ASTVisitor(unit) { translationUnit(unit->ast()->asTranslationUnit()); }" << std::endl
<< std::endl;
- foreach (LookupScope *b, interfaces) {
+ foreach (ClassOrNamespace *b, interfaces) {
Q_ASSERT(! b->symbols().isEmpty());
Class *klass = 0;
@@ -162,10 +162,10 @@ public:
std::cout << " using ASTVisitor::translationUnit;" << std::endl
<< std::endl;
- QHash<LookupScope *, QList<LookupScope *> > implements;
- foreach (LookupScope *b, nodes) {
- LookupScope *iface = 0;
- foreach (LookupScope *u, b->usings()) {
+ QHash<ClassOrNamespace *, QList<ClassOrNamespace *> > implements;
+ foreach (ClassOrNamespace *b, nodes) {
+ ClassOrNamespace *iface = 0;
+ foreach (ClassOrNamespace *u, b->usings()) {
if (interfaces.contains(u)) {
iface = u;
break;
@@ -175,8 +175,8 @@ public:
implements[iface].append(b);
}
- foreach (LookupScope *iface, interfaces) {
- foreach (LookupScope *b, implements.value(iface)) {
+ foreach (ClassOrNamespace *iface, interfaces) {
+ foreach (ClassOrNamespace *b, implements.value(iface)) {
if (! isMiscNode(b))
continue;
@@ -195,9 +195,9 @@ public:
std::cout << std::endl;
- foreach (LookupScope *iface, interfaces) {
+ foreach (ClassOrNamespace *iface, interfaces) {
std::cout << " // " << qPrintable(oo(iface->symbols().first()->name())) << std::endl;
- foreach (LookupScope *b, implements.value(iface)) {
+ foreach (ClassOrNamespace *b, implements.value(iface)) {
Class *klass = 0;
foreach (Symbol *s, b->symbols())
if ((klass = s->asClass()) != 0)
@@ -212,7 +212,7 @@ public:
}
std::cout << "private:" << std::endl;
- foreach (LookupScope *b, interfaces) {
+ foreach (ClassOrNamespace *b, interfaces) {
Q_ASSERT(! b->symbols().isEmpty());
Class *klass = 0;
@@ -245,7 +245,7 @@ public:
// implementation
- foreach (LookupScope *b, interfaces) {
+ foreach (ClassOrNamespace *b, interfaces) {
Q_ASSERT(! b->symbols().isEmpty());
Class *klass = 0;
@@ -280,9 +280,9 @@ public:
<< std::endl;
}
- foreach (LookupScope *iface, interfaces) {
+ foreach (ClassOrNamespace *iface, interfaces) {
std::cout << "// " << qPrintable(oo(iface->symbols().first()->name())) << std::endl;
- foreach (LookupScope *b, implements.value(iface)) {
+ foreach (ClassOrNamespace *b, implements.value(iface)) {
Class *klass = 0;
foreach (Symbol *s, b->symbols())
if ((klass = s->asClass()) != 0)
@@ -331,7 +331,7 @@ public:
Control *control = context.thisDocument()->control();
const Name *n = control->identifier(name.toLatin1().constData());
- if (LookupScope *bb = context.lookupType(n, klass)) {
+ if (ClassOrNamespace *bb = context.lookupType(n, klass)) {
QString retTy;
QString funcName = getAcceptFunctionName(bb, &retTy);
Q_ASSERT(! funcName.isEmpty());
@@ -350,7 +350,7 @@ public:
continue;
}
- if (LookupScope *ty = context.lookupType(namedTy->name(), klass)) {
+ if (ClassOrNamespace *ty = context.lookupType(namedTy->name(), klass)) {
QString className = oo(ty->symbols().first()->name());
QString baseClassName = className;
if (baseClassName.endsWith(QLatin1String("AST"))) {
@@ -386,9 +386,9 @@ public:
protected:
using SymbolVisitor::visit;
- QList<LookupScope *> baseClasses(LookupScope *b) {
- QList<LookupScope *> usings = b->usings();
- foreach (LookupScope *u, usings)
+ QList<ClassOrNamespace *> baseClasses(ClassOrNamespace *b) {
+ QList<ClassOrNamespace *> usings = b->usings();
+ foreach (ClassOrNamespace *u, usings)
usings += baseClasses(u);
return usings;
}
@@ -398,14 +398,14 @@ protected:
if (! className.endsWith(QLatin1String("AST")))
return false;
- LookupScope *b = context.lookupType(klass);
+ ClassOrNamespace *b = context.lookupType(klass);
Q_ASSERT(b != 0);
const Identifier *accept0 = context.thisDocument()->control()->identifier("accept0");
if (Symbol *s = klass->find(accept0)) {
if (Function *meth = s->type()->asFunctionType()) {
if (! meth->isPureVirtual()) {
- foreach (LookupScope *u, b->usings()) {
+ foreach (ClassOrNamespace *u, b->usings()) {
if (interfaces.contains(u)) {
// qDebug() << oo(klass->name()) << "implements" << oo(u->symbols().first()->name());
} else {
diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp
index a2219e7cfc..aa42b2b3ec 100644
--- a/tests/auto/cplusplus/ast/tst_ast.cpp
+++ b/tests/auto/cplusplus/ast/tst_ast.cpp
@@ -208,6 +208,8 @@ private slots:
void expensiveExpression();
void invalidCode_data();
void invalidCode();
+ void enumDeclaration();
+ void invalidEnumClassDeclaration();
};
void tst_AST::gcc_attributes_1()
@@ -1982,6 +1984,28 @@ void tst_AST::invalidCode()
QVERIFY(diag.errorCount != 0);
}
+void tst_AST::enumDeclaration()
+{
+ QSharedPointer<TranslationUnit> unit(parseStatement(
+ //Unnamed
+ "enum { ENUMERATOR0 };\n"
+ "enum Enum { ENUMERATOR1 };\n"
+ "enum EnumWithBase : int { ENUMERATOR2 };\n"
+ "enum enum : int { ENUMERATOR2a };\n"
+ "enum class EnumClass { ENUMERATOR3 = 10 };\n", true));
+
+ QVERIFY(unit->ast());
+ QCOMPARE(diag.errorCount, 0);
+}
+
+void tst_AST::invalidEnumClassDeclaration()
+{
+ QSharedPointer<TranslationUnit> unit(parseStatement(
+ "enum class operator A { };", true));
+
+ QVERIFY(diag.errorCount != 0);
+}
+
void tst_AST::initTestCase()
{
control.setDiagnosticClient(&diag);
diff --git a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp
index 3a39909e3c..683513f12b 100644
--- a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp
+++ b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp
@@ -115,7 +115,6 @@ public:
// Process source
const Document::Ptr document = createDocument(filePath, source);
- QVERIFY(document);
Snapshot snapshot;
snapshot.insert(document);
@@ -225,8 +224,6 @@ private slots:
void test_checksymbols_infiniteLoop_data();
void test_checksymbols_infiniteLoop();
- void test_checksymbols_infiniteLoop_BUG15141();
-
void test_parentOfBlock();
void findField();
@@ -1173,25 +1170,6 @@ void tst_CheckSymbols::test_checksymbols_infiniteLoop()
TestCase::runCheckSymbols(document1, snapshot);
}
-void tst_CheckSymbols::test_checksymbols_infiniteLoop_BUG15141()
-{
- QByteArray source =
- "template <class R1>\n"
- "struct Base\n"
- "{\n"
- "};\n"
- "\n"
- "template<typename R>\n"
- "struct Derived :\n"
- " Base<\n"
- " typename Derived<typename Base<R>::type>::type,\n"
- " typename Derived<typename Base<R>::type>::type\n"
- " >::type\n"
- "{};\n";
-
- BaseTestCase tc(source);
-}
-
void tst_CheckSymbols::test_parentOfBlock()
{
const QByteArray source = "void C::f()\n"
@@ -1286,8 +1264,13 @@ void tst_CheckSymbols::findField()
source[position] = ' ';
BaseTestCase tc(source);
Use use = tc.findUse(line, column);
-
+ QEXPECT_FAIL("pointer_indirect_specialization", "QTCREATORBUG-14141", Abort);
+ QEXPECT_FAIL("pointer_indirect_specialization_typedef", "QTCREATORBUG-14141", Abort);
+ QEXPECT_FAIL("pointer_indirect_specialization_double_indirection", "QTCREATORBUG-14141", Abort);
+ QEXPECT_FAIL("instantiation_of_pointer_typedef_in_block", "QTCREATORBUG-14141", Abort);
+ QEXPECT_FAIL("pointer_indirect_specialization_double_indirection_with_base", "QTCREATORBUG-14141", Abort);
QEXPECT_FAIL("recursive_instantiation_of_template_type", "QTCREATORBUG-14237", Abort);
+ QEXPECT_FAIL("recursive_instantiation_of_template_type_2", "QTCREATORBUG-14141", Abort);
QVERIFY(use.isValid());
QVERIFY(use.kind == Highlighting::FieldUse);
}
@@ -1364,26 +1347,6 @@ void tst_CheckSymbols::findField_data()
"}\n"
);
- QTest::newRow("instantiation_of_indirect_typedef") << _(
- "template<typename _Tp>\n"
- "struct Indirect { _Tp t; };\n"
- "\n"
- "template<typename T>\n"
- "struct Temp\n"
- "{\n"
- " typedef T MyT;\n"
- " typedef Indirect<MyT> indirect;\n"
- "};\n"
- "\n"
- "struct Foo { int bar; };\n"
- "\n"
- "void func()\n"
- "{\n"
- " Temp<Foo>::indirect i;\n"
- " i.t.@bar;\n"
- "}\n"
- );
-
QTest::newRow("pointer_indirect_specialization_double_indirection") << _(
"template<typename _Tp>\n"
"struct Traits { };\n"
@@ -1475,100 +1438,6 @@ void tst_CheckSymbols::findField_data()
" p->@bar;\n"
"}\n"
);
-
- QTest::newRow("std vector") << _(
- "namespace std\n"
- "{\n"
- "template<typename _Tp>\n"
- "struct allocator\n"
- "{\n"
- " typedef _Tp value_type;\n"
- "\n"
- " template<typename _Tp1>\n"
- " struct rebind\n"
- " { typedef allocator<_Tp1> other; };\n"
- "};\n"
- "\n"
- "template<typename _Alloc, typename _Tp>\n"
- "struct __alloctr_rebind\n"
- "{\n"
- " typedef typename _Alloc::template rebind<_Tp>::other __type;\n"
- "};\n"
- "\n"
- "template<typename _Alloc>\n"
- "struct allocator_traits\n"
- "{\n"
- " typedef typename _Alloc::value_type value_type;\n"
- "\n"
- " template<typename _Tp>\n"
- " using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type;\n"
- "};\n"
- "\n"
- "template<typename _Iterator>\n"
- "struct iterator_traits { };\n"
- "\n"
- "template<typename _Tp>\n"
- "struct iterator_traits<_Tp*>\n"
- "{\n"
- " typedef _Tp* pointer;\n"
- "};\n"
- "} // namespace std\n"
- "\n"
- "namespace __gnu_cxx\n"
- "{\n"
- "template<typename _Alloc>\n"
- "struct __alloc_traits\n"
- "{\n"
- " typedef _Alloc allocator_type;\n"
- " typedef std::allocator_traits<_Alloc> _Base_type;\n"
- " typedef typename _Alloc::value_type value_type;\n"
- "\n"
- " static value_type *_S_pointer_helper(...);\n"
- " typedef decltype(_S_pointer_helper((_Alloc*)0)) __pointer;\n"
- " typedef __pointer pointer;\n"
- "\n"
- " template<typename _Tp>\n"
- " struct rebind\n"
- " { typedef typename _Base_type::template rebind_alloc<_Tp> other; };\n"
- "};\n"
- "\n"
- "template<typename _Iterator, typename _Container>\n"
- "struct __normal_iterator\n"
- "{\n"
- " typedef std::iterator_traits<_Iterator> __traits_type;\n"
- " typedef typename __traits_type::pointer pointer;\n"
- "\n"
- " pointer p;\n"
- "};\n"
- "} // namespace __gnu_cxx\n"
- "\n"
- "namespace std {\n"
- "template<typename _Tp, typename _Alloc>\n"
- "struct _Vector_Base\n"
- "{\n"
- " typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template\n"
- " rebind<_Tp>::other _Tp_alloc_type;\n"
- " typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer\n"
- " pointer;\n"
- "};\n"
- "\n"
- "template<typename _Tp, typename _Alloc = std::allocator<_Tp> >\n"
- "struct vector : protected _Vector_Base<_Tp, _Alloc>\n"
- "{\n"
- " typedef _Vector_Base<_Tp, _Alloc> _Base;\n"
- " typedef typename _Base::pointer pointer;\n"
- " typedef __gnu_cxx::__normal_iterator<pointer, vector> iterator;\n"
- "};\n"
- "} // namespace std\n"
- "\n"
- "struct Foo { int bar; };\n"
- "\n"
- "void func()\n"
- "{\n"
- " std::vector<Foo>::iterator it;\n"
- " it.p->@bar;\n"
- "}\n"
- );
}
QTEST_APPLESS_MAIN(tst_CheckSymbols)
diff --git a/tests/auto/cplusplus/lookup/tst_lookup.cpp b/tests/auto/cplusplus/lookup/tst_lookup.cpp
index deab703a8f..8347749f43 100644
--- a/tests/auto/cplusplus/lookup/tst_lookup.cpp
+++ b/tests/auto/cplusplus/lookup/tst_lookup.cpp
@@ -133,7 +133,7 @@ void tst_Lookup::base_class_defined_1()
const LookupContext ctx(doc, snapshot);
- LookupScope *klass = ctx.lookupType(derivedClass->baseClassAt(0)->name(), derivedClass->enclosingScope());
+ ClassOrNamespace *klass = ctx.lookupType(derivedClass->baseClassAt(0)->name(), derivedClass->enclosingScope());
QVERIFY(klass != 0);
QCOMPARE(klass->symbols().size(), 1);
@@ -272,7 +272,7 @@ void tst_Lookup::simple_class_1()
const LookupContext context(doc, snapshot);
// check class resolving:
- LookupScope *klass = context.lookupType(impl->name(), impl->enclosingScope());
+ ClassOrNamespace *klass = context.lookupType(impl->name(), impl->enclosingScope());
QVERIFY(klass != 0);
QCOMPARE(klass->symbols().size(), 2);
QVERIFY(klass->symbols().contains(iface));
@@ -336,7 +336,7 @@ void tst_Lookup::class_with_baseclass()
const LookupContext context(doc, snapshot);
- LookupScope *objClass = context.lookupType(baseZoo->name(), zooImpl->enclosingScope());
+ ClassOrNamespace *objClass = context.lookupType(baseZoo->name(), zooImpl->enclosingScope());
QVERIFY(objClass != 0);
QVERIFY(objClass->symbols().contains(baseZoo));
diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp
index 4717c5fc22..2011f03e00 100644
--- a/tests/auto/cplusplus/semantic/tst_semantic.cpp
+++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp
@@ -38,6 +38,7 @@
#include <cplusplus/Bind.h>
#include <cplusplus/Control.h>
#include <cplusplus/CoreTypes.h>
+#include <cplusplus/DeprecatedGenTemplateInstance.h>
#include <cplusplus/DiagnosticClient.h>
#include <cplusplus/ExpressionUnderCursor.h>
#include <cplusplus/Literals.h>
@@ -47,7 +48,6 @@
#include <cplusplus/Parser.h>
#include <cplusplus/Scope.h>
#include <cplusplus/Symbols.h>
-#include <cplusplus/Templates.h>
//TESTED_COMPONENT=src/libs/cplusplus
@@ -166,7 +166,6 @@ private slots:
void pointer_to_function_1();
void template_instance_1();
- void explicit_instantiation_1();
void expression_under_cursor_1();
@@ -512,37 +511,17 @@ void tst_Semantic::template_instance_1()
QVERIFY(decl);
FullySpecifiedType templArgs[] = { control->integerType(IntegerType::Int) };
- Clone cloner(control.data());
- Class *clone = cloner.instantiate(templ, templArgs, 1)->asClass();
- QVERIFY(clone);
+ const Name *templId = control->templateNameId(control->identifier("QList"), false, templArgs, 1);
+
+ FullySpecifiedType genTy = DeprecatedGenTemplateInstance::instantiate(templId, decl, control);
Overview oo;
oo.showReturnTypes = true;
- Declaration *clonedDecl = clone->memberAt(0)->asDeclaration();
- const QString genDecl = oo.prettyType(clonedDecl->type());
+ const QString genDecl = oo.prettyType(genTy);
QCOMPARE(genDecl, QString::fromLatin1("void (const int &)"));
}
-void tst_Semantic::explicit_instantiation_1()
-{
- QSharedPointer<Document> doc = document("template class basic_string<char>;");
- QCOMPARE(doc->errorCount, 0U);
- QCOMPARE(doc->globals->memberCount(), 1U);
-
- ExplicitInstantiation *inst = doc->globals->memberAt(0)->asExplicitInstantiation();
- QVERIFY(inst);
-
- ForwardClassDeclaration *fwd = inst->memberAt(0)->asForwardClassDeclaration();
- QVERIFY(fwd);
-
- QVERIFY(inst->name()->match(fwd->name()));
-
- Overview oo;
- const QString name = oo.prettyName(inst->name());
- QCOMPARE(name, QString::fromLatin1("basic_string<char>"));
-}
-
void tst_Semantic::expression_under_cursor_1()
{
const QString plainText = "void *ptr = foo(10, bar";
diff --git a/tests/system/suite_WELP/tst_WELP04/test.py b/tests/system/suite_WELP/tst_WELP04/test.py
index 9cc23275d0..cf10169042 100644
--- a/tests/system/suite_WELP/tst_WELP04/test.py
+++ b/tests/system/suite_WELP/tst_WELP04/test.py
@@ -81,7 +81,7 @@ def main():
replaceEditorContent(searchTutWidget, "embedded device")
test.verify(checkIfObjectExists(getQmlItem("Delegate", welcomePage,
False, "id='delegate' radius='0' caption="
- "'Device Creation with Qt'")),
+ "'Qt for Device Creation'")),
"Verifying: Link to the expected demonstration video exists.")
# exit Qt Creator
invokeMenuItem("File", "Exit")
diff --git a/tests/unit/unittest/clangstringtest.cpp b/tests/unit/unittest/clangstringtest.cpp
index 0467de693d..b7ee1982b9 100644
--- a/tests/unit/unittest/clangstringtest.cpp
+++ b/tests/unit/unittest/clangstringtest.cpp
@@ -42,6 +42,8 @@
namespace {
+using ::testing::StrEq;
+
using ClangBackEnd::ClangString;
TEST(ClangString, ConvertToUtf8String)
@@ -87,4 +89,11 @@ TEST(ClangString, MoveSelfAssigment)
ASSERT_FALSE(text.isNull());
}
+
+TEST(ClangString, SpellingAsCString)
+{
+ ClangString text(CXString{"text", 0});
+
+ ASSERT_THAT(text.cString(), StrEq("text"));
+}
}
diff --git a/tests/unit/unittest/cursortest.cpp b/tests/unit/unittest/cursortest.cpp
new file mode 100644
index 0000000000..e0e18c1308
--- /dev/null
+++ b/tests/unit/unittest/cursortest.cpp
@@ -0,0 +1,819 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include <clangstring.h>
+#include <cursor.h>
+#include <projectpart.h>
+#include <projects.h>
+#include <sourcelocation.h>
+#include <sourcerange.h>
+#include <translationunit.h>
+#include <translationunits.h>
+#include <unsavedfiles.h>
+
+#include <gmock/gmock.h>
+#include <gmock/gmock-matchers.h>
+#include <gtest/gtest.h>
+#include "gtest-qt-printing.h"
+
+using ClangBackEnd::Cursor;
+using ClangBackEnd::TranslationUnit;
+using ClangBackEnd::UnsavedFiles;
+using ClangBackEnd::ProjectPart;
+using ClangBackEnd::TranslationUnits;
+using ClangBackEnd::ClangString;
+using ClangBackEnd::SourceRange;
+
+using testing::IsNull;
+using testing::NotNull;
+using testing::Gt;
+using testing::Contains;
+using testing::EndsWith;
+using testing::AllOf;
+using testing::Not;
+using testing::IsEmpty;
+using testing::StrEq;
+
+namespace {
+
+struct Data {
+ ClangBackEnd::ProjectParts projects;
+ ClangBackEnd::UnsavedFiles unsavedFiles;
+ ClangBackEnd::TranslationUnits translationUnits{projects, unsavedFiles};
+ TranslationUnit translationUnit{Utf8StringLiteral(TESTDATA_DIR"/cursor.cpp"),
+ ProjectPart(Utf8StringLiteral("projectPartId"), {Utf8StringLiteral("-std=c++11")}),
+ {},
+ translationUnits};
+};
+
+class Cursor : public ::testing::Test
+{
+public:
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+protected:
+ static Data *d;
+ const TranslationUnit &translationUnit = d->translationUnit;
+
+
+};
+
+TEST_F(Cursor, CreateNullCursor)
+{
+ ::Cursor cursor;
+
+ ASSERT_TRUE(cursor.isNull());
+}
+
+TEST_F(Cursor, CompareNullCursors)
+{
+ ::Cursor cursor;
+ ::Cursor cursor2;
+
+ ASSERT_THAT(cursor, cursor2);
+}
+
+TEST_F(Cursor, IsNotValid)
+{
+ ::Cursor cursor;
+
+ ASSERT_FALSE(cursor.isValid());
+}
+
+TEST_F(Cursor, IsValid)
+{
+ auto cursor = translationUnit.cursor();
+
+ ASSERT_TRUE(cursor.isValid());
+}
+
+TEST_F(Cursor, IsTranslationUnit)
+{
+ auto cursor = translationUnit.cursor();
+
+ ASSERT_TRUE(cursor.isTranslationUnit());
+}
+
+TEST_F(Cursor, NullCursorIsNotTranslationUnit)
+{
+ ::Cursor cursor;
+
+ ASSERT_FALSE(cursor.isTranslationUnit());
+}
+
+TEST_F(Cursor, UnifiedSymbolResolution)
+{
+ ::Cursor cursor;
+
+ ASSERT_TRUE(cursor.unifiedSymbolResolution().isEmpty());
+}
+
+TEST_F(Cursor, GetCursorAtLocation)
+{
+ auto cursor = translationUnit.cursorAt(3, 6);
+
+ ASSERT_THAT(cursor.unifiedSymbolResolution(), Utf8StringLiteral("c:@F@function#I#"));
+}
+
+TEST_F(Cursor, GetCursoSourceLocation)
+{
+ auto cursor = translationUnit.cursorAt(3, 6);
+
+ ASSERT_THAT(cursor.sourceLocation(), translationUnit.sourceLocationAt(3, 6));
+}
+
+TEST_F(Cursor, GetCursoSourceRange)
+{
+ auto cursor = translationUnit.cursorAt(3, 6);
+
+ ASSERT_THAT(cursor.sourceRange(), SourceRange(translationUnit.sourceLocationAt(3, 1),
+ translationUnit.sourceLocationAt(6, 2)));
+}
+
+TEST_F(Cursor, Mangling)
+{
+ auto cursor = translationUnit.cursorAt(3, 6);
+
+
+ ASSERT_THAT(cursor.mangling(), Utf8StringLiteral("_Z8functioni"));
+}
+
+TEST_F(Cursor, Spelling)
+{
+ auto cursor = translationUnit.cursorAt(3, 6);
+
+
+ ASSERT_THAT(cursor.spelling().cString(), StrEq("function"));
+}
+
+TEST_F(Cursor, DisplayName)
+{
+ auto cursor = translationUnit.cursorAt(3, 6);
+
+
+ ASSERT_THAT(cursor.displayName(), Utf8StringLiteral("function(int)"));
+}
+
+TEST_F(Cursor, BriefComment)
+{
+ auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7);
+
+
+ ASSERT_THAT(cursor.briefComment(), Utf8StringLiteral("A brief comment"));
+}
+
+TEST_F(Cursor, RawComment)
+{
+ auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7);
+
+
+ ASSERT_THAT(cursor.rawComment(), Utf8StringLiteral("/**\n * A brief comment\n */"));
+}
+
+TEST_F(Cursor, CommentRange)
+{
+ auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7);
+
+
+ ASSERT_THAT(cursor.commentRange(),
+ SourceRange(translationUnit.sourceLocationAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 7, 1),
+ translationUnit.sourceLocationAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 9, 4)));
+}
+
+TEST_F(Cursor, IsDefinition)
+{
+ auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7);
+
+ ASSERT_TRUE(cursor.isDefinition());
+}
+
+TEST_F(Cursor, ForwardDeclarationIsNotDefinition)
+{
+ auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 6, 7);
+
+ ASSERT_FALSE(cursor.isDefinition());
+}
+
+TEST_F(Cursor, GetDefinitionOfFowardDeclaration)
+{
+ auto forwardDeclarationcursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 6, 7);
+ auto definitionCursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7);
+
+ ASSERT_THAT(forwardDeclarationcursor.definition(), definitionCursor);
+}
+
+TEST_F(Cursor, CallToMethodeIsNotDynamic)
+{
+ auto cursor = translationUnit.cursorAt(18, 5);
+
+ ASSERT_FALSE(cursor.isDynamicCall());
+}
+
+TEST_F(Cursor, CallToAbstractVirtualMethodeIsDynamic)
+{
+ auto cursor = translationUnit.cursorAt(19, 5);
+
+ ASSERT_TRUE(cursor.isDynamicCall());
+}
+
+TEST_F(Cursor, CanonicalCursor)
+{
+ auto forwardDeclarationcursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 6, 7);
+ auto definitionCursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7);
+
+ ASSERT_THAT(definitionCursor.canonical(), forwardDeclarationcursor);
+}
+
+TEST_F(Cursor, ReferencedCursor)
+{
+ auto functionCallCursor = translationUnit.cursorAt(18, 5);
+ auto functionCursor = translationUnit.cursorAt(16, 17);
+
+ ASSERT_THAT(functionCallCursor.referenced(), functionCursor);
+}
+
+TEST_F(Cursor, IsVirtual)
+{
+ auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 15, 17);
+
+ ASSERT_TRUE(cursor.isVirtualMethod());
+}
+
+TEST_F(Cursor, IsNotPureVirtualOnlyVirtual)
+{
+ auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 15, 17);
+
+ ASSERT_FALSE(cursor.isPureVirtualMethod());
+}
+
+TEST_F(Cursor, IsPureVirtual)
+{
+ auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 16, 17);
+
+ ASSERT_TRUE(cursor.isPureVirtualMethod());
+}
+
+TEST_F(Cursor, ConstantMethod)
+{
+ auto cursor = translationUnit.cursorAt(31, 18);
+
+ ASSERT_TRUE(cursor.isConstantMethod());
+}
+
+TEST_F(Cursor, IsStaticMethod)
+{
+ auto cursor = translationUnit.cursorAt(36, 18);
+
+ ASSERT_TRUE(cursor.isStaticMethod());
+}
+
+TEST_F(Cursor, TypeSpelling)
+{
+ auto cursor = translationUnit.cursorAt(43, 5);
+
+ ASSERT_THAT(cursor.type().utf8Spelling(), Utf8StringLiteral("lint"));
+}
+
+TEST_F(Cursor, CanonicalTypeSpelling)
+{
+ auto cursor = translationUnit.cursorAt(43, 5);
+
+ ASSERT_THAT(cursor.type().canonical().utf8Spelling(), Utf8StringLiteral("long long"));
+}
+
+TEST_F(Cursor, CanonicalTypeCStringSpelling)
+{
+ auto cursor = translationUnit.cursorAt(43, 5);
+
+ auto spelling = cursor.type().canonical().spelling();
+
+ ASSERT_THAT(spelling.cString(), StrEq("long long"));
+}
+
+TEST_F(Cursor, CanonicalTypeIsNotType)
+{
+ auto cursor = translationUnit.cursorAt(43, 5);
+
+ ASSERT_THAT(cursor.type().canonical(), Not(cursor.type()));
+}
+
+TEST_F(Cursor, TypeDeclartionIsAlias)
+{
+ auto declarationCursor = translationUnit.cursorAt(41, 5);
+ auto lintCursor = translationUnit.cursorAt(39, 11);
+
+ ASSERT_THAT(declarationCursor.type().declaration().type(), lintCursor.type());
+}
+
+TEST_F(Cursor, TypeIsConstantWithoutAliasLookup)
+{
+ auto cursor = translationUnit.cursorAt(45, 16);
+
+ ASSERT_TRUE(cursor.type().isConstant());
+}
+
+TEST_F(Cursor, ClassIsCompoundType)
+{
+ auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 10, 7);
+
+ ASSERT_TRUE(cursor.isCompoundType());
+}
+
+TEST_F(Cursor, StructIsCompoundType)
+{
+ auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 28, 8);
+
+ ASSERT_TRUE(cursor.isCompoundType());
+}
+
+TEST_F(Cursor, UnionIsCompoundType)
+{
+ auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 33, 7);
+
+ ASSERT_TRUE(cursor.isCompoundType());
+}
+
+TEST_F(Cursor, IsDeclaration)
+{
+ auto cursor = translationUnit.cursorAt(41, 10);
+
+ ASSERT_TRUE(cursor.isDeclaration());
+}
+
+TEST_F(Cursor, SemanticParent)
+{
+ auto cursor = translationUnit.cursorAt(43, 6);
+ auto expectedSemanticParent = translationUnit.cursorAt(36, 18);
+
+ auto semanticParent = cursor.semanticParent();
+
+ ASSERT_THAT(semanticParent, expectedSemanticParent);
+}
+
+TEST_F(Cursor, IsLocalVariableInMethod)
+{
+ auto cursor = translationUnit.cursorAt(20, 9);
+
+ ASSERT_TRUE(cursor.isLocalVariable());
+}
+
+TEST_F(Cursor, IsLocalVariableInStaticFunction)
+{
+ auto cursor = translationUnit.cursorAt(43, 5);
+
+ ASSERT_TRUE(cursor.isLocalVariable());
+}
+
+TEST_F(Cursor, IsLocalVariableInTemplateFunction)
+{
+ auto cursor = translationUnit.cursorAt(52, 7);
+
+ ASSERT_TRUE(cursor.isLocalVariable());
+}
+
+TEST_F(Cursor, IsLocalVariableInConversionOperator)
+{
+ auto cursor = translationUnit.cursorAt(57, 9);
+
+ ASSERT_TRUE(cursor.isLocalVariable());
+}
+
+TEST_F(Cursor, IsLocalVariableInOperator)
+{
+ auto cursor = translationUnit.cursorAt(62, 9);
+
+ ASSERT_TRUE(cursor.isLocalVariable());
+}
+
+TEST_F(Cursor, IsLocalVariableInConstructor)
+{
+ auto cursor = translationUnit.cursorAt(13, 9);
+
+ ASSERT_TRUE(cursor.isLocalVariable());
+}
+
+TEST_F(Cursor, IsLocalVariableInDestructor)
+{
+ auto cursor = translationUnit.cursorAt(69, 9);
+
+ ASSERT_TRUE(cursor.isLocalVariable());
+}
+
+TEST_F(Cursor, FindFunctionCaller)
+{
+ auto functionCursor = translationUnit.cursorAt(92, 24);
+ auto structCursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 28, 8);
+
+ ASSERT_THAT(functionCursor.functionBaseDeclaration(), structCursor);
+}
+
+TEST_F(Cursor, FindFunctionCallerPointer)
+{
+ auto functionCursor = translationUnit.cursorAt(79, 25);
+ auto structCursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 28, 8);
+
+ ASSERT_THAT(functionCursor.functionBaseDeclaration(), structCursor);
+}
+
+TEST_F(Cursor, FindFunctionCallerThis)
+{
+ auto functionCursor = translationUnit.cursorAt(106, 5);
+ auto structCursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 38, 8);
+
+ ASSERT_THAT(functionCursor.functionBaseDeclaration(), structCursor);
+}
+
+TEST_F(Cursor, NonPointerTypeForValue)
+{
+ auto variableCursor = translationUnit.cursorAt(101, 10);
+ auto variablePointerCursor = translationUnit.cursorAt(100, 11);
+
+ ASSERT_THAT(variableCursor.nonPointerTupe(), variablePointerCursor.nonPointerTupe());
+}
+
+TEST_F(Cursor, HasFinalAttributeInFunction)
+{
+ auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 30, 18);
+
+ ASSERT_TRUE(cursor.hasFinalFunctionAttribute());
+}
+
+TEST_F(Cursor, HasNotFinalAttributeInFunction)
+{
+ auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 15, 17);
+
+ ASSERT_FALSE(cursor.hasFinalFunctionAttribute());
+}
+
+TEST_F(Cursor, HasFinalAttributeInClass)
+{
+ auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 28, 8);
+
+ ASSERT_TRUE(cursor.hasFinalClassAttribute());
+}
+
+TEST_F(Cursor, HasNotFinaAttributeInClass)
+{
+ auto cursor = translationUnit.cursorAt(Utf8StringLiteral(TESTDATA_DIR"/cursor.h"), 38, 8);
+
+ ASSERT_FALSE(cursor.hasFinalClassAttribute());
+}
+
+TEST_F(Cursor, HasOutputValues)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(117, 19);
+ auto outputArgumentExpectedCursor = translationUnit.cursorAt(117, 20);
+
+ auto outputArguments = callExpressionCursor.outputArguments();
+
+ ASSERT_THAT(outputArguments.size(), 1);
+ ASSERT_THAT(outputArguments[0], outputArgumentExpectedCursor);
+}
+
+TEST_F(Cursor, HasOnlyInputValues)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(118, 18);
+
+ auto outputArguments = callExpressionCursor.outputArguments();
+
+ ASSERT_THAT(outputArguments, IsEmpty());
+}
+
+TEST_F(Cursor, ArgumentCountIsZero)
+{
+ auto cursor = translationUnit.cursorAt(121, 23);
+
+ auto count = cursor.type().argumentCount();
+
+ ASSERT_THAT(count, 0);
+}
+
+TEST_F(Cursor, ArgumentCountIsTwo)
+{
+ auto cursor = translationUnit.cursorAt(122, 22);
+
+ auto count = cursor.type().argumentCount();
+
+ ASSERT_THAT(count, 2);
+}
+
+TEST_F(Cursor, ArgumentOneIsValue)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(122, 22);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isConstant());
+ ASSERT_THAT(argument.kind(), CXType_Int);
+}
+
+TEST_F(Cursor, ArgumentTwoIsLValueReference)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(122, 22);
+
+ auto argument = callExpressionCursor.type().argument(1);
+
+ ASSERT_THAT(argument.kind(), CXType_LValueReference);
+}
+
+TEST_F(Cursor, ArgumentTwoIsConstantReference)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(122, 22);
+
+ auto argumentPointee = callExpressionCursor.type().argument(1);
+
+ ASSERT_TRUE(argumentPointee.isConstantReference());
+}
+
+TEST_F(Cursor, CursorArgumentCount)
+{
+ auto cursor = translationUnit.cursorAt(117, 19);
+
+ ASSERT_THAT(cursor.kind(), CXCursor_CallExpr);
+ ASSERT_THAT(cursor.argumentCount(), 4);
+}
+
+TEST_F(Cursor, CursorArgumentInputValue)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(117, 19);
+ auto declarationReferenceExpressionCursor = translationUnit.cursorAt(117, 20);
+
+ ASSERT_THAT(callExpressionCursor.argument(0), declarationReferenceExpressionCursor);
+}
+
+TEST_F(Cursor, IsConstantLValueReference)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(125, 26);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_TRUE(argument.isConstantReference());
+}
+
+TEST_F(Cursor, LValueReferenceIsNotConstantLValueReference)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(124, 21);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isConstantReference());
+}
+
+TEST_F(Cursor, ValueIsNotConstantLValueReference)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(123, 18);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isConstantReference());
+}
+
+TEST_F(Cursor, PointerToConstantNotConstantLValueReference)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(126, 20);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isConstantReference());
+}
+
+TEST_F(Cursor, IsLValueReference)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(124, 21);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_TRUE(argument.isLValueReference());
+}
+
+TEST_F(Cursor, ConstantLValueReferenceIsLValueReference)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(125, 26);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_TRUE(argument.isLValueReference());
+}
+
+TEST_F(Cursor, ValueIsNotLValueReference)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(123, 18);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isLValueReference());
+}
+
+TEST_F(Cursor, PointerIsNotLValueReference)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(126, 20);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isLValueReference());
+}
+
+TEST_F(Cursor, PointerToConstant)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(126, 20);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_TRUE(argument.isPointerToConstant());
+}
+
+TEST_F(Cursor, ValueIsNotPointerToConstant)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(123, 18);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isPointerToConstant());
+}
+
+TEST_F(Cursor, PointerNotPointerToConstant)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(127, 13);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isPointerToConstant());
+}
+
+TEST_F(Cursor, ConstantLValueReferenceIsNotPointerToConstant)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(125, 26);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isPointerToConstant());
+}
+
+TEST_F(Cursor, IsConstantPointer)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(128, 21);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_TRUE(argument.isConstantPointer());
+}
+
+TEST_F(Cursor, PointerToConstantIsNotConstantPointer)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(126, 20);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isConstantPointer());
+}
+
+TEST_F(Cursor, ConstValueIsNotConstantPointer)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(129, 23);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isConstantPointer());
+}
+
+TEST_F(Cursor, PointerToConstantIsReferencingConstant)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(126, 20);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_TRUE(argument.isReferencingConstant());
+}
+
+TEST_F(Cursor, ConstantReferenceIsReferencingConstant)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(125, 26);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_TRUE(argument.isReferencingConstant());
+}
+
+TEST_F(Cursor, LValueReferenceIsNotReferencingConstant)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(124, 21);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isReferencingConstant());
+}
+
+TEST_F(Cursor, ValueIsNotReferencingConstant)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(123, 18);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isReferencingConstant());
+}
+
+TEST_F(Cursor, PointerIsNotRefencingConstant)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(127, 13);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isReferencingConstant());
+}
+
+TEST_F(Cursor, PointerIsOutputParameter)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(127, 13);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_TRUE(argument.isOutputParameter());
+}
+
+TEST_F(Cursor, ConstantReferenceIsNotOutputParameter)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(125, 26);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isOutputParameter());
+}
+
+TEST_F(Cursor, PointerToConstantIsNotOutputParameter)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(126, 20);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isOutputParameter()) << argument.isConstant() << argument.pointeeType().isConstant();
+}
+
+TEST_F(Cursor, ConstantPointerIsNotOutputParameter)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(128, 21);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_TRUE(argument.isOutputParameter());
+}
+
+TEST_F(Cursor, ReferenceIsOutputParameter)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(124, 21);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_TRUE(argument.isOutputParameter());
+}
+
+TEST_F(Cursor, ConstReferenceIsNotOutputParameter)
+{
+ auto callExpressionCursor = translationUnit.cursorAt(125, 26);
+
+ auto argument = callExpressionCursor.type().argument(0);
+
+ ASSERT_FALSE(argument.isOutputParameter());
+}
+
+Data *Cursor::d;
+
+void Cursor::SetUpTestCase()
+{
+ d = new Data;
+}
+
+void Cursor::TearDownTestCase()
+{
+ delete d;
+ d = nullptr;
+}
+
+}
diff --git a/tests/unit/unittest/data/cursor.cpp b/tests/unit/unittest/data/cursor.cpp
new file mode 100644
index 0000000000..a492867dd6
--- /dev/null
+++ b/tests/unit/unittest/data/cursor.cpp
@@ -0,0 +1,129 @@
+#include "cursor.h"
+
+void function(int x)
+{
+
+}
+
+namespace Namespace
+{
+SuperClass::SuperClass(int x) noexcept
+ : y(x)
+{
+ int LocalVariable;
+}
+
+int SuperClass::Method()
+{
+ Method();
+ AbstractVirtualMethod(y);
+ int LocalVariable;
+ return y;
+}
+
+int SuperClass::VirtualMethod(int z)
+{
+ AbstractVirtualMethod(z);
+
+ return y;
+}
+
+bool SuperClass::ConstMethod() const
+{
+ return y;
+}
+
+void SuperClass::StaticMethod()
+{
+ using longint = long long int;
+ using lint = longint;
+
+ lint foo;
+
+ foo = 30;
+
+ const lint bar = 20;
+}
+}
+
+template <class T>
+void TemplateFunction(T LocalVariableParameter)
+{
+ T LocalVariable;
+}
+
+Namespace::SuperClass::operator int() const
+{
+ int LocalVariable;
+}
+
+int Namespace::SuperClass::operator ++() const
+{
+ int LocalVariable;
+
+ return LocalVariable;
+}
+
+Namespace::SuperClass::~SuperClass()
+{
+ int LocalVariable;
+}
+
+void Struct::FinalVirtualMethod()
+{
+
+}
+
+void f1(Struct *FindFunctionCaller)
+{
+ FindFunctionCaller->FinalVirtualMethod();
+}
+
+void f2(){
+ Struct *s = new Struct;
+
+ f1(s);
+}
+
+void f3()
+{
+ auto FindFunctionCaller = Struct();
+
+ FindFunctionCaller.FinalVirtualMethod();
+}
+
+
+void f4()
+{
+ Struct s;
+
+ auto *sPointer = &s;
+ auto sValue = s;
+}
+
+void NonFinalStruct::function()
+{
+ FinalVirtualMethod();
+}
+
+void OutputFunction(int &out, int in = 1, const int &in2=2, int *out2=nullptr);
+void InputFunction(const int &value);
+
+void f5()
+{
+ int OutputValue;
+ int InputValue = 20;
+
+ OutputFunction(OutputValue);
+ InputFunction(InputValue);
+}
+
+void ArgumentCountZero();
+void ArgumentCountTwo(int one, const int &two);
+void IntegerValue(int);
+void LValueReference(int &);
+void ConstLValueReference(const int &);
+void PointerToConst(const int *);
+void Pointer(int *);
+void ConstantPointer(int *const);
+void ConstIntegerValue(const int);
diff --git a/tests/unit/unittest/data/cursor.h b/tests/unit/unittest/data/cursor.h
new file mode 100644
index 0000000000..3e9e9a2bfb
--- /dev/null
+++ b/tests/unit/unittest/data/cursor.h
@@ -0,0 +1,42 @@
+
+
+
+namespace Namespace
+{
+class SuperClass;
+/**
+ * A brief comment
+ */
+class SuperClass
+{
+ SuperClass() = default;
+ SuperClass(int x) noexcept;
+ int Method();
+ virtual int VirtualMethod(int z);
+ virtual int AbstractVirtualMethod(int z) = 0;
+ bool ConstMethod() const;
+ static void StaticMethod();
+ operator int() const;
+ int operator ++() const;
+ ~SuperClass();
+
+private:
+ int y;
+};
+}
+
+struct Struct final
+{
+ virtual void FinalVirtualMethod() final;
+};
+
+union Union
+{
+
+};
+
+struct NonFinalStruct
+{
+ virtual void FinalVirtualMethod() final;
+ void function();
+};
diff --git a/tests/unit/unittest/data/highlightinginformations.cpp b/tests/unit/unittest/data/highlightinginformations.cpp
new file mode 100644
index 0000000000..d651fd65e1
--- /dev/null
+++ b/tests/unit/unittest/data/highlightinginformations.cpp
@@ -0,0 +1,385 @@
+auto *Variable = "Variable";
+auto *u8Variable = u8"Variable";
+auto *rawVariable = R"(Variable)";
+auto Character = 'c';
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+auto integer = 1;
+auto numFloat = 1.2f;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+int function(int x)
+{
+ return x;
+}
+
+struct Foo
+{
+ void memberFunction() {}
+};
+
+int functionDeclaration(int x);
+
+struct Foo2
+{
+ void memberFunction();
+};
+
+void f()
+{
+ function(1);
+}
+
+struct ConversionFunction {
+ operator Foo();
+ operator int();
+};
+
+void TypeReference()
+{
+ Foo foo;
+}
+
+void LocalVariableDeclaration()
+{
+ Foo foo;
+
+ foo.memberFunction();
+}
+
+void LocalVariableFunctionArgument(Foo &foo)
+{
+ foo.memberFunction();
+}
+
+struct Foo3 {
+ int ClassMember;
+
+ void ClassMemberReference()
+ {
+ ClassMember++;
+ }
+};
+
+struct Foo4
+{
+ void MemberFunctionReference();
+
+ void function()
+ {
+ MemberFunctionReference();
+ }
+};
+
+struct Foo5
+{
+ void StaticMethod();
+
+ void function()
+ {
+ Foo5::StaticMethod();
+ }
+};
+
+enum Enumeration
+{
+ Enumerator
+};
+
+void f2()
+{
+ Enumeration enumeration;
+
+ enumeration = Enumerator;
+}
+
+class ForwardReference;
+
+class Class
+{ public:
+ Class();
+ ~Class();
+};
+
+ForwardReference *f3()
+{
+ Class ConstructorReference;
+
+ return 0;
+}
+
+union Union
+{
+
+};
+
+Union UnionDeclarationReference;
+
+
+
+
+
+
+
+
+
+namespace NameSpace {
+struct StructInNameSpace {};
+}
+
+namespace NameSpaceAlias = NameSpace;
+
+NameSpace::StructInNameSpace foo6;
+
+class BaseClass {
+public:
+ virtual void VirtualFunction();
+ virtual void FinalVirtualFunction();
+};
+
+
+void f8()
+{
+ BaseClass NonVirtualFunctionCall;
+ NonVirtualFunctionCall.VirtualFunction();
+
+ BaseClass *NonVirtualFunctionCallPointer = new BaseClass();
+ NonVirtualFunctionCallPointer->VirtualFunction();
+}
+
+class DerivedClass : public BaseClass
+{public:
+ void VirtualFunction() override;
+ void FinalVirtualFunction() final;
+};
+
+void f8(BaseClass *VirtualFunctionCallPointer)
+{
+ VirtualFunctionCallPointer->VirtualFunction();
+}
+
+class FinalClass final : public DerivedClass
+{
+ void FinalClassThisCall();
+};
+
+void f8(DerivedClass *FinalVirtualFunctionCallPointer)
+{
+ FinalVirtualFunctionCallPointer->FinalVirtualFunction();
+}
+
+void f9(BaseClass *NonFinalVirtualFunctionCallPointer)
+{
+ NonFinalVirtualFunctionCallPointer->FinalVirtualFunction();
+}
+
+void f10(FinalClass *ClassFinalVirtualFunctionCallPointer)
+{
+ ClassFinalVirtualFunctionCallPointer->VirtualFunction();
+}
+
+class Operator {
+public:
+ Operator operator+=(const Operator &first);
+};
+
+Operator operator+(const Operator &first, const Operator &second);
+
+void f10()
+{
+ auto PlusOperator = Operator() + Operator();
+ Operator PlusAssignOperator;
+ PlusAssignOperator += Operator();
+}
+
+/* Comment */
+
+#define PreprocessorDefinition Class
+#define MacroDefinition(a,b) ((a)>(b)?(a):(b))
+
+void f11()
+{
+ MacroDefinition(2, 4);
+}
+
+#include "highlightinginformations.h"
+
+void f12() {
+GOTO_LABEL:
+
+ goto GOTO_LABEL;
+}
+
+template <class T>
+void TemplateFunction(T v)
+{
+ T XXXXX = v;
+}
+void TemplateReference()
+{
+ TemplateFunction(1);
+// std::vector<int> TemplateIntance;
+}
+
+
+
+
+template <class T>
+class TemplateFoo {};
+
+
+template <class TemplateTypeParameter = Foo, int NonTypeTemplateParameter = 1, template <class> class TemplateTemplateParameter = TemplateFoo>
+void TemplateFunction(TemplateTypeParameter TemplateParameter)
+{
+ TemplateTypeParameter TemplateTypeParameterReference;
+ auto NonTypeTemplateParameterReference = NonTypeTemplateParameter;
+ TemplateTemplateParameter<TemplateTypeParameter> TemplateTemplateParameterReference;
+}
+
+
+
+void FinalClass::FinalClassThisCall()
+{
+ VirtualFunction();
+}
+
+
+void OutputParameter(int &one, const int &two, int *three=0);
+
+void f12()
+{
+ int One;
+ OutputParameter(One, 2);
+}
+
+#include <highlightinginformations.h>
+
+#define FOREACH(variable, container) \
+ variable; \
+ auto x = container;
+
+#define foreach2 FOREACH
+
+#include <initializer_list>
+
+void f13()
+{
+ auto container = 1;
+ foreach2(int index, container);
+}
+
+class SecondArgumentInMacroExpansionIsField {
+ int container = 1;
+
+ void f()
+ {
+ foreach2(int index, container);
+ }
+};
+
+typedef unsigned uint32;
+
+enum EnumerationType : uint32
+{
+ Other = 0,
+};
+
+
+struct TypeInCast {
+ void function();
+};
+
+void f14()
+{
+ static_cast<void (TypeInCast::*)()>(&TypeInCast::function);
+ reinterpret_cast<void (TypeInCast::*)()>(&TypeInCast::function);
+}
+
+using IntegerAlias = int;
+using SecondIntegerAlias = IntegerAlias;
+using IntegerTypedef = int;
+using Function = void (*)();
+
+
+
+void f15()
+{
+ IntegerAlias integerAlias;
+ SecondIntegerAlias secondIntegerAlias;
+ IntegerTypedef integerTypedef;
+ Function();
+}
+
+class FriendFoo
+{
+public:
+ friend class FooFriend;
+ friend bool operator==(const FriendFoo &first, const FriendFoo &second);
+};
+
+class FieldInitialization
+{
+public:
+ FieldInitialization() :
+ member(0)
+ {}
+
+ int member;
+};
+
+template<class Type>
+void TemplateFunctionCall(Type type)
+{
+ type + type;
+}
+
+void f16()
+{
+ TemplateFunctionCall(1);
+}
+
+
+template <typename T>
+class TemplatedType
+{
+ T value = T();
+};
+
+void f17()
+{
+ TemplatedType<int> TemplatedTypeDeclaration;
+}
diff --git a/tests/unit/unittest/data/highlightinginformations.h b/tests/unit/unittest/data/highlightinginformations.h
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/unit/unittest/data/highlightinginformations.h
diff --git a/tests/unit/unittest/data/skippedsourceranges.cpp b/tests/unit/unittest/data/skippedsourceranges.cpp
new file mode 100644
index 0000000000..775393fced
--- /dev/null
+++ b/tests/unit/unittest/data/skippedsourceranges.cpp
@@ -0,0 +1,19 @@
+#if 0
+
+void f();
+
+#endif
+
+#ifndef BLAH
+class Class
+{
+
+};
+#endif
+
+#ifdef BLAH
+class Class
+{
+
+};
+#endif
diff --git a/tests/unit/unittest/highlightinginformationstest.cpp b/tests/unit/unittest/highlightinginformationstest.cpp
new file mode 100644
index 0000000000..c09f12cc17
--- /dev/null
+++ b/tests/unit/unittest/highlightinginformationstest.cpp
@@ -0,0 +1,902 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include <cursor.h>
+#include <clangbackendipc_global.h>
+#include <clangstring.h>
+#include <projectpart.h>
+#include <projects.h>
+#include <sourcelocation.h>
+#include <sourcerange.h>
+#include <highlightinginformation.h>
+#include <highlightinginformations.h>
+#include <translationunit.h>
+#include <translationunits.h>
+#include <unsavedfiles.h>
+
+#include <gmock/gmock.h>
+#include <gmock/gmock-matchers.h>
+#include <gtest/gtest.h>
+#include "gtest-qt-printing.h"
+
+using ClangBackEnd::Cursor;
+using ClangBackEnd::HighlightingInformation;
+using ClangBackEnd::HighlightingInformations;
+using ClangBackEnd::HighlightingType;
+using ClangBackEnd::TranslationUnit;
+using ClangBackEnd::UnsavedFiles;
+using ClangBackEnd::ProjectPart;
+using ClangBackEnd::TranslationUnits;
+using ClangBackEnd::ClangString;
+using ClangBackEnd::SourceRange;
+
+using testing::PrintToString;
+using testing::IsNull;
+using testing::NotNull;
+using testing::Gt;
+using testing::Contains;
+using testing::EndsWith;
+using testing::AllOf;
+using testing::Not;
+using testing::IsEmpty;
+using testing::SizeIs;
+
+namespace {
+
+MATCHER_P4(IsHighlightingInformation, line, column, length, type,
+ std::string(negation ? "isn't " : "is ")
+ + PrintToString(HighlightingInformation(line, column, length, type))
+ )
+{
+ const HighlightingInformation expected(line, column, length, type);
+
+ return arg == expected;
+}
+
+MATCHER_P(HasType, type,
+ std::string(negation ? "isn't " : "is ")
+ + PrintToString(type)
+ )
+{
+ return arg.hasType(type);
+}
+
+struct Data {
+ ClangBackEnd::ProjectParts projects;
+ ClangBackEnd::UnsavedFiles unsavedFiles;
+ ClangBackEnd::TranslationUnits translationUnits{projects, unsavedFiles};
+ TranslationUnit translationUnit{Utf8StringLiteral(TESTDATA_DIR"/highlightinginformations.cpp"),
+ ProjectPart(Utf8StringLiteral("projectPartId"), {Utf8StringLiteral("-std=c++14")}),
+ {},
+ translationUnits};
+};
+
+class HighlightingInformations : public ::testing::Test
+{
+public:
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+ SourceRange sourceRange(uint line, uint columnEnd) const;
+
+protected:
+ static Data *d;
+ const TranslationUnit &translationUnit = d->translationUnit;
+};
+
+TEST_F(HighlightingInformations, CreateNullInformations)
+{
+ ::HighlightingInformations infos;
+
+ ASSERT_TRUE(infos.isNull());
+}
+
+TEST_F(HighlightingInformations, NullInformationsAreEmpty)
+{
+ ::HighlightingInformations infos;
+
+ ASSERT_TRUE(infos.isEmpty());
+}
+
+TEST_F(HighlightingInformations, IsNotNull)
+{
+ const auto aRange = translationUnit.sourceRange(3, 1, 5, 1);
+
+ const auto infos = translationUnit.highlightingInformationsInRange(aRange);
+
+ ASSERT_FALSE(infos.isNull());
+}
+
+TEST_F(HighlightingInformations, IteratorBeginEnd)
+{
+ const auto aRange = translationUnit.sourceRange(3, 1, 5, 1);
+ const auto infos = translationUnit.highlightingInformationsInRange(aRange);
+
+ const auto endIterator = std::next(infos.begin(), infos.size());
+
+ ASSERT_THAT(infos.end(), endIterator);
+}
+
+TEST_F(HighlightingInformations, Size)
+{
+ const auto range = translationUnit.sourceRange(5, 5, 5, 10);
+
+ const auto infos = translationUnit.highlightingInformationsInRange(range);
+
+ ASSERT_THAT(infos.size(), 1);
+}
+
+TEST_F(HighlightingInformations, DISABLED_Keyword)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(5, 12));
+
+ ASSERT_THAT(infos[0], IsHighlightingInformation(5u, 5u, 6u, HighlightingType::Keyword));
+}
+
+TEST_F(HighlightingInformations, StringLiteral)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(1, 29));
+
+ ASSERT_THAT(infos[4], IsHighlightingInformation(1u, 24u, 10u, HighlightingType::StringLiteral));
+}
+
+TEST_F(HighlightingInformations, Utf8StringLiteral)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(2, 33));
+
+ ASSERT_THAT(infos[4], IsHighlightingInformation(2u, 24u, 12u, HighlightingType::StringLiteral));
+}
+
+TEST_F(HighlightingInformations, RawStringLiteral)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(3, 34));
+
+ ASSERT_THAT(infos[4], IsHighlightingInformation(3u, 24u, 13u, HighlightingType::StringLiteral));
+}
+
+TEST_F(HighlightingInformations, CharacterLiteral)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(4, 28));
+
+ ASSERT_THAT(infos[3], IsHighlightingInformation(4u, 24u, 3u, HighlightingType::StringLiteral));
+}
+
+TEST_F(HighlightingInformations, IntegerLiteral)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(23, 26));
+
+ ASSERT_THAT(infos[3], IsHighlightingInformation(23u, 24u, 1u, HighlightingType::NumberLiteral));
+}
+
+TEST_F(HighlightingInformations, FloatLiteral)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(24, 29));
+
+ ASSERT_THAT(infos[3], IsHighlightingInformation(24u, 24u, 4u, HighlightingType::NumberLiteral));
+}
+
+TEST_F(HighlightingInformations, FunctionDefinition)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(45, 20));
+
+ ASSERT_THAT(infos[1], IsHighlightingInformation(45u, 5u, 8u, HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, MemberFunctionDefinition)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(52, 29));
+
+ ASSERT_THAT(infos[1], IsHighlightingInformation(52u, 10u, 14u, HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, FunctionDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(55, 32));
+
+ ASSERT_THAT(infos[1], IsHighlightingInformation(55u, 5u, 19u, HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, MemberFunctionDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(59, 27));
+
+ ASSERT_THAT(infos[1], IsHighlightingInformation(59u, 10u, 14u, HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, MemberFunctionReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(104, 35));
+
+ ASSERT_THAT(infos[0], IsHighlightingInformation(104u, 9u, 23u, HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, FunctionCall)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(64, 16));
+
+ ASSERT_THAT(infos[0], IsHighlightingInformation(64u, 5u, 8u, HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, TypeConversionFunction)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(68, 20));
+
+ ASSERT_THAT(infos[1], IsHighlightingInformation(68u, 14u, 3u, HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, InbuiltTypeConversionFunction)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(69, 20));
+
+ ASSERT_THAT(infos[1], IsHighlightingInformation(69u, 14u, 3u, HighlightingType::Keyword));
+}
+
+TEST_F(HighlightingInformations, TypeReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(74, 13));
+
+ ASSERT_THAT(infos[0], IsHighlightingInformation(74u, 5u, 3u, HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, LocalVariable)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(79, 13));
+
+ ASSERT_THAT(infos[1], IsHighlightingInformation(79u, 9u, 3u, HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingInformations, LocalVariableDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(79, 13));
+
+ ASSERT_THAT(infos[1], IsHighlightingInformation(79u, 9u, 3u, HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingInformations, LocalVariableReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(81, 26));
+
+ ASSERT_THAT(infos[0], IsHighlightingInformation(81u, 5u, 3u, HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingInformations, LocalVariableFunctionArgumentDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(84, 45));
+
+ ASSERT_THAT(infos[5], IsHighlightingInformation(84u, 41u, 3u, HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingInformations, LocalVariableFunctionArgumentReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(86, 26));
+
+ ASSERT_THAT(infos[0], IsHighlightingInformation(86u, 5u, 3u, HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingInformations, ClassVariableDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(90, 21));
+
+ ASSERT_THAT(infos[1], IsHighlightingInformation(90u, 9u, 11u, HighlightingType::Field));
+}
+
+TEST_F(HighlightingInformations, ClassVariableReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(94, 23));
+
+ ASSERT_THAT(infos[0], IsHighlightingInformation(94u, 9u, 11u, HighlightingType::Field));
+}
+
+TEST_F(HighlightingInformations, StaticMethodDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(110, 25));
+
+ ASSERT_THAT(infos[1], IsHighlightingInformation(110u, 10u, 12u, HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, StaticMethodReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(114, 30));
+
+ ASSERT_THAT(infos[2], IsHighlightingInformation(114u, 15u, 12u, HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, Enumeration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(118, 17));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::Enumeration));
+}
+
+TEST_F(HighlightingInformations, Enumerator)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(120, 15));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Enumeration));
+}
+
+TEST_F(HighlightingInformations, EnumerationReferenceDeclarationType)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(125, 28));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Enumeration));
+}
+
+TEST_F(HighlightingInformations, EnumerationReferenceDeclarationVariable)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(125, 28));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingInformations, EnumerationReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(127, 30));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingInformations, EnumeratorReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(127, 30));
+
+ ASSERT_THAT(infos[2], HasType(HighlightingType::Enumeration));
+}
+
+TEST_F(HighlightingInformations, ClassForwardDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(130, 12));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, ConstructorDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(134, 13));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, DestructorDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(135, 15));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, ClassForwardDeclarationReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(138, 23));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, ClassTypeReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(140, 32));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, ConstructorReferenceVariable)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(140, 32));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingInformations, UnionDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(145, 12));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, UnionDeclarationReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(150, 33));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, GlobalVariable)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(150, 33));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::GlobalVariable));
+}
+
+TEST_F(HighlightingInformations, StructDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(50, 11));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, NameSpace)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(160, 22));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, NameSpaceAlias)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(164, 38));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, NameSpaceReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(166, 35));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, VirtualFunction)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(170, 35));
+
+ ASSERT_THAT(infos[2], HasType(HighlightingType::VirtualFunction));
+}
+
+TEST_F(HighlightingInformations, DISABLED_NonVirtualFunctionCall)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(177, 46));
+
+ ASSERT_THAT(infos[2], HasType(HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, DISABLED_NonVirtualFunctionCallPointer)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(180, 54));
+
+ ASSERT_THAT(infos[2], HasType(HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, VirtualFunctionCallPointer)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(192, 51));
+
+ ASSERT_THAT(infos[2], HasType(HighlightingType::VirtualFunction));
+}
+
+TEST_F(HighlightingInformations, FinalVirtualFunctionCallPointer)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(202, 61));
+
+ ASSERT_THAT(infos[2], HasType(HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, NonFinalVirtualFunctionCallPointer)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(207, 61));
+
+ ASSERT_THAT(infos[2], HasType(HighlightingType::VirtualFunction));
+}
+
+TEST_F(HighlightingInformations, PlusOperator)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(224, 49));
+
+ ASSERT_THAT(infos[6], HasType(HighlightingType::Operator));
+}
+
+TEST_F(HighlightingInformations, PlusAssignOperator)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(226, 24));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::Operator));
+}
+
+TEST_F(HighlightingInformations, Comment)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(229, 14));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Comment));
+}
+
+TEST_F(HighlightingInformations, PreprocessingDirective)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(231, 37));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::Preprocessor));
+}
+
+TEST_F(HighlightingInformations, PreprocessorMacroDefinition)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(231, 37));
+
+ ASSERT_THAT(infos[2], HasType(HighlightingType::PreprocessorDefinition));
+}
+
+TEST_F(HighlightingInformations, PreprocessorFunctionMacroDefinition)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(232, 47));
+
+ ASSERT_THAT(infos[2], HasType(HighlightingType::PreprocessorDefinition));
+}
+
+TEST_F(HighlightingInformations, PreprocessorMacroExpansion)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(236, 27));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::PreprocessorExpansion));
+}
+
+TEST_F(HighlightingInformations, PreprocessorMacroExpansionArgument)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(236, 27));
+
+ ASSERT_THAT(infos[2], HasType(HighlightingType::NumberLiteral));
+}
+
+TEST_F(HighlightingInformations, PreprocessorInclusionDirective)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(239, 18));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::StringLiteral));
+}
+
+TEST_F(HighlightingInformations, GotoLabelStatement)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(242, 12));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Label));
+}
+
+TEST_F(HighlightingInformations, GotoLabelStatementReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(244, 21));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::Label));
+}
+
+TEST_F(HighlightingInformations, TemplateReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(254, 25));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, TemplateTypeParameter)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(265, 135));
+
+ ASSERT_THAT(infos[3], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, TemplateDefaultParameter)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(265, 135));
+
+ ASSERT_THAT(infos[5], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, NonTypeTemplateParameter)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(265, 135));
+
+ ASSERT_THAT(infos[8], HasType(HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingInformations, NonTypeTemplateParameterDefaultArgument)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(265, 135));
+
+ ASSERT_THAT(infos[10], HasType(HighlightingType::NumberLiteral));
+}
+
+TEST_F(HighlightingInformations, TemplateTemplateParameter)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(265, 135));
+
+ ASSERT_THAT(infos[17], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, TemplateTemplateParameterDefaultArgument)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(265, 135));
+
+ ASSERT_THAT(infos[19], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, TemplateFunctionDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(266, 63));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, TemplateTypeParameterReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(268, 58));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, TemplateTypeParameterDeclarationReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(268, 58));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingInformations, NonTypeTemplateParameterReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(269, 71));
+
+ ASSERT_THAT(infos[3], HasType(HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingInformations, NonTypeTemplateParameterReferenceReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(269, 71));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingInformations, TemplateTemplateParameterReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(270, 89));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, TemplateTemplateContainerParameterReference)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(270, 89));
+
+ ASSERT_THAT(infos[2], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, TemplateTemplateParameterReferenceVariable)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(270, 89));
+
+ ASSERT_THAT(infos[4], HasType(HighlightingType::LocalVariable));
+}
+
+TEST_F(HighlightingInformations, ClassFinalVirtualFunctionCallPointer)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(212, 61));
+
+ ASSERT_THAT(infos[2], HasType(HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, ClassFinalVirtualFunctionCall)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(277, 23));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, HasFunctionArguments)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(286, 29));
+
+ ASSERT_TRUE(infos[1].hasFunctionArguments());
+}
+
+TEST_F(HighlightingInformations, NoOutputFunctionArguments)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(285, 13));
+
+ auto outputFunctionArguments = infos[1].outputFunctionArguments();
+
+ ASSERT_THAT(outputFunctionArguments, IsEmpty());
+}
+
+TEST_F(HighlightingInformations, DISABLED_OneOutputFunctionArguments)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(285, 13));
+
+ auto outputFunctionArguments = infos[1].outputFunctionArguments();
+
+ ASSERT_THAT(outputFunctionArguments, SizeIs(1));
+}
+
+TEST_F(HighlightingInformations, PreprocessorInclusionDirectiveWithAngleBrackets )
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(289, 38));
+
+ ASSERT_THAT(infos[3], HasType(HighlightingType::StringLiteral));
+}
+
+TEST_F(HighlightingInformations, ArgumentInMacroExpansionIsKeyword)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(302, 36));
+
+ ASSERT_THAT(infos[2], HasType(HighlightingType::Keyword));
+}
+
+TEST_F(HighlightingInformations, DISABLED_FirstArgumentInMacroExpansionIsLocalVariable)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(302, 36));
+
+ ASSERT_THAT(infos[3], HasType(HighlightingType::Invalid));
+}
+
+TEST_F(HighlightingInformations, DISABLED_SecondArgumentInMacroExpansionIsLocalVariable)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(302, 36));
+
+ ASSERT_THAT(infos[5], HasType(HighlightingType::Invalid));
+}
+
+TEST_F(HighlightingInformations, DISABLED_SecondArgumentInMacroExpansionIsField)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(310, 40));
+
+ ASSERT_THAT(infos[5], HasType(HighlightingType::Invalid));
+}
+
+
+TEST_F(HighlightingInformations, DISABLED_EnumerationType)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(316, 30));
+
+ ASSERT_THAT(infos[3], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, TypeInStaticCast)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(328, 64));
+
+ ASSERT_THAT(infos[4], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, StaticCastIsKeyword)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(328, 64));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Keyword));
+}
+
+TEST_F(HighlightingInformations, StaticCastPunctationIsInvalid)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(328, 64));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::Invalid));
+ ASSERT_THAT(infos[3], HasType(HighlightingType::Invalid));
+ ASSERT_THAT(infos[5], HasType(HighlightingType::Invalid));
+}
+
+TEST_F(HighlightingInformations, TypeInReinterpretCast)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(329, 69));
+
+ ASSERT_THAT(infos[4], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, IntegerAliasDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(333, 41));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, IntegerAlias)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(341, 31));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, SecondIntegerAlias)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(342, 43));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, IntegerTypedef)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(343, 35));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, FunctionAlias)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(344, 16));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, FriendTypeDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(350, 28));
+
+ ASSERT_THAT(infos[2], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, FriendArgumentTypeDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(351, 65));
+
+ ASSERT_THAT(infos[6], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, DISABLED_FriendArgumentDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(351, 65));
+
+ ASSERT_THAT(infos[8], HasType(HighlightingType::Invalid));
+}
+
+TEST_F(HighlightingInformations, FieldInitialization)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(358, 18));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Field));
+}
+
+TEST_F(HighlightingInformations, TemplateFunctionCall)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(372, 29));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Function));
+}
+
+TEST_F(HighlightingInformations, TemplatedType)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(377, 21));
+
+ ASSERT_THAT(infos[1], HasType(HighlightingType::Type));
+}
+
+TEST_F(HighlightingInformations, TemplatedTypeDeclaration)
+{
+ const auto infos = translationUnit.highlightingInformationsInRange(sourceRange(384, 49));
+
+ ASSERT_THAT(infos[0], HasType(HighlightingType::Type));
+}
+
+Data *HighlightingInformations::d;
+
+void HighlightingInformations::SetUpTestCase()
+{
+ d = new Data;
+}
+
+void HighlightingInformations::TearDownTestCase()
+{
+ delete d;
+ d = nullptr;
+}
+
+ClangBackEnd::SourceRange HighlightingInformations::sourceRange(uint line, uint columnEnd) const
+{
+ return translationUnit.sourceRange(line, 1, line, columnEnd);
+}
+
+}
diff --git a/tests/unit/unittest/skippedsourcerangestest.cpp b/tests/unit/unittest/skippedsourcerangestest.cpp
new file mode 100644
index 0000000000..b37b872690
--- /dev/null
+++ b/tests/unit/unittest/skippedsourcerangestest.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include <cursor.h>
+#include <clangstring.h>
+#include <projectpart.h>
+#include <projects.h>
+#include <skippedsourceranges.h>
+#include <sourcelocation.h>
+#include <sourcerange.h>
+#include <translationunit.h>
+#include <translationunits.h>
+#include <unsavedfiles.h>
+
+#include <sourcerangecontainer.h>
+
+#include <QVector>
+
+#include <gmock/gmock.h>
+#include <gmock/gmock-matchers.h>
+#include <gtest/gtest.h>
+#include "gtest-qt-printing.h"
+
+using ClangBackEnd::Cursor;
+using ClangBackEnd::TranslationUnit;
+using ClangBackEnd::UnsavedFiles;
+using ClangBackEnd::ProjectPart;
+using ClangBackEnd::TranslationUnits;
+using ClangBackEnd::ClangString;
+using ClangBackEnd::SourceRange;
+using ClangBackEnd::SkippedSourceRanges;
+
+using testing::IsNull;
+using testing::NotNull;
+using testing::Gt;
+using testing::Contains;
+using testing::EndsWith;
+using testing::AllOf;
+using testing::Not;
+using testing::IsEmpty;
+using testing::SizeIs;
+using testing::PrintToString;
+
+namespace {
+
+MATCHER_P4(IsSourceLocation, filePath, line, column, offset,
+ std::string(negation ? "isn't" : "is")
+ + " source location with file path "+ PrintToString(filePath)
+ + ", line " + PrintToString(line)
+ + ", column " + PrintToString(column)
+ + " and offset " + PrintToString(offset)
+ )
+{
+ if (!arg.filePath().endsWith(filePath)
+ || arg.line() != line
+ || arg.column() != column
+ || arg.offset() != offset) {
+ return false;
+ }
+
+ return true;
+}
+
+struct Data {
+ ClangBackEnd::ProjectParts projects;
+ ClangBackEnd::UnsavedFiles unsavedFiles;
+ ClangBackEnd::TranslationUnits translationUnits{projects, unsavedFiles};
+ Utf8String filePath = Utf8StringLiteral(TESTDATA_DIR"/skippedsourceranges.cpp");
+ TranslationUnit translationUnit{filePath,
+ ProjectPart(Utf8StringLiteral("projectPartId"),
+ {Utf8StringLiteral("-std=c++11"),Utf8StringLiteral("-DBLAH")}),
+ {},
+ translationUnits};
+};
+
+class SkippedSourceRanges : public ::testing::Test
+{
+public:
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+protected:
+ static Data *d;
+ const TranslationUnit &translationUnit = d->translationUnit;
+ const Utf8String &filePath = d->filePath;
+ const ::SkippedSourceRanges skippedSourceRanges{d->translationUnit.skippedSourceRanges()};
+};
+
+Data *SkippedSourceRanges::d;
+
+TEST_F(SkippedSourceRanges, RangeWithZero)
+{
+ auto ranges = skippedSourceRanges.sourceRanges();
+
+ ASSERT_THAT(ranges, SizeIs(2));
+}
+
+TEST_F(SkippedSourceRanges, RangeOne)
+{
+ auto ranges = skippedSourceRanges.sourceRanges();
+
+ ASSERT_THAT(ranges[0].start(), IsSourceLocation(filePath, 1, 2, 1));
+ ASSERT_THAT(ranges[0].end(), IsSourceLocation(filePath, 5, 7, 24));
+}
+
+TEST_F(SkippedSourceRanges, RangeTwo)
+{
+ auto ranges = skippedSourceRanges.sourceRanges();
+
+ ASSERT_THAT(ranges[1].start(), IsSourceLocation(filePath, 7, 2, 27));
+ ASSERT_THAT(ranges[1].end(), IsSourceLocation(filePath, 12, 7, 63));
+}
+
+TEST_F(SkippedSourceRanges, RangeContainerSize)
+{
+ auto ranges = skippedSourceRanges.toSourceRangeContainers();
+
+ ASSERT_THAT(ranges, SizeIs(2));
+}
+
+void SkippedSourceRanges::SetUpTestCase()
+{
+ d = new Data;
+}
+
+void SkippedSourceRanges::TearDownTestCase()
+{
+ delete d;
+ d = nullptr;
+}
+
+}
diff --git a/tests/unit/unittest/sourcelocationtest.cpp b/tests/unit/unittest/sourcelocationtest.cpp
index 9db922c282..9213d9359c 100644
--- a/tests/unit/unittest/sourcelocationtest.cpp
+++ b/tests/unit/unittest/sourcelocationtest.cpp
@@ -50,13 +50,13 @@ using ClangBackEnd::ProjectPart;
using ClangBackEnd::SourceLocation;
using ClangBackEnd::TranslationUnit;
using ClangBackEnd::UnsavedFiles;
+
using testing::EndsWith;
+using testing::Not;
namespace {
-class SourceLocation : public ::testing::Test
-{
-protected:
+struct Data {
ProjectPart projectPart{Utf8StringLiteral("projectPartId")};
ClangBackEnd::ProjectParts projects;
ClangBackEnd::UnsavedFiles unsavedFiles;
@@ -68,7 +68,18 @@ protected:
DiagnosticSet diagnosticSet{translationUnit.diagnostics()};
Diagnostic diagnostic{diagnosticSet.front()};
::SourceLocation sourceLocation{diagnostic.location()};
+};
+class SourceLocation : public ::testing::Test
+{
+public:
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+protected:
+ static Data *d;
+ const ::SourceLocation &sourceLocation = d->sourceLocation;
+ const TranslationUnit &translationUnit = d->translationUnit;
};
TEST_F(SourceLocation, FilePath)
@@ -91,4 +102,27 @@ TEST_F(SourceLocation, Offset)
ASSERT_THAT(sourceLocation.offset(), 18);
}
+TEST_F(SourceLocation, Create)
+{
+ ASSERT_THAT(translationUnit.sourceLocationAt(4, 1), sourceLocation);
+}
+
+TEST_F(SourceLocation, NotEqual)
+{
+ ASSERT_THAT(translationUnit.sourceLocationAt(3, 1), Not(sourceLocation));
+}
+
+Data *SourceLocation::d;
+
+void SourceLocation::SetUpTestCase()
+{
+ d = new Data;
+}
+
+void SourceLocation::TearDownTestCase()
+{
+ delete d;
+ d = nullptr;
+}
+
}
diff --git a/tests/unit/unittest/sourcerangetest.cpp b/tests/unit/unittest/sourcerangetest.cpp
index 771bd49ccf..b517c42380 100644
--- a/tests/unit/unittest/sourcerangetest.cpp
+++ b/tests/unit/unittest/sourcerangetest.cpp
@@ -51,7 +51,9 @@ using ClangBackEnd::UnsavedFiles;
using ClangBackEnd::Diagnostic;
using ClangBackEnd::SourceRange;
using ClangBackEnd::TranslationUnits;
+
using testing::PrintToString;
+using testing::IsEmpty;
namespace {
@@ -73,9 +75,7 @@ MATCHER_P4(IsSourceLocation, filePath, line, column, offset,
return true;
}
-class SourceRange : public ::testing::Test
-{
-protected:
+struct Data {
ProjectPart projectPart{Utf8StringLiteral("projectPartId"), {Utf8StringLiteral("-pedantic")}};
ClangBackEnd::ProjectParts projects;
ClangBackEnd::UnsavedFiles unsavedFiles;
@@ -90,6 +90,20 @@ protected:
::SourceRange sourceRange{diagnostic.ranges().front()};
};
+class SourceRange : public ::testing::Test
+{
+public:
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+protected:
+ static Data *d;
+ const ::SourceRange &sourceRange = d->sourceRange;
+ const Diagnostic &diagnostic = d->diagnostic;
+ const Diagnostic &diagnosticWithFilteredOutInvalidRange = d->diagnosticWithFilteredOutInvalidRange;
+ const TranslationUnit &translationUnit = d->translationUnit;
+};
+
TEST_F(SourceRange, IsNull)
{
::SourceRange sourceRange;
@@ -125,9 +139,34 @@ TEST_F(SourceRange, End)
44u));
}
+TEST_F(SourceRange, Create)
+{
+ ASSERT_THAT(sourceRange, ::SourceRange(sourceRange.start(), sourceRange.end()));
+}
+
+TEST_F(SourceRange, SourceRangeFromTranslationUnit)
+{
+ auto sourceRangeFromTranslationUnit = translationUnit.sourceRange(8u, 5u, 8u, 6u);
+
+ ASSERT_THAT(sourceRangeFromTranslationUnit, sourceRange);
+}
+
TEST_F(SourceRange, InvalidRangeIsFilteredOut)
{
- ASSERT_TRUE(diagnosticWithFilteredOutInvalidRange.ranges().empty());
+ ASSERT_THAT(diagnosticWithFilteredOutInvalidRange.ranges(), IsEmpty());
+}
+
+Data *SourceRange::d;
+
+void SourceRange::SetUpTestCase()
+{
+ d = new Data;
+}
+
+void SourceRange::TearDownTestCase()
+{
+ delete d;
+ d = nullptr;
}
}
diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro
index 193f1caa68..6fe2d25f2e 100644
--- a/tests/unit/unittest/unittest.pro
+++ b/tests/unit/unittest/unittest.pro
@@ -53,7 +53,10 @@ SOURCES += \
translationunittest.cpp \
unsavedfilestest.cpp \
utf8test.cpp \
- senddocumenttrackertest.cpp
+ senddocumenttrackertest.cpp \
+ cursortest.cpp \
+ highlightinginformationstest.cpp \
+ skippedsourcerangestest.cpp
HEADERS += \
gtest-qt-printing.h \