Merge remote-tracking branch 'origin/3.6'

Conflicts:
    src/libs/3rdparty/modeling/qmt/model_widgets_ui/classmembersedit.cpp
    src/plugins/git/gitplugin.cpp

Change-Id: I78a21510d484b655e01141a3543e08ee2123f9cd
This commit is contained in:
Eike Ziller
2015-11-23 14:25:38 +01:00
132 changed files with 6287 additions and 2315 deletions

View File

@@ -64,7 +64,11 @@
To show the file encoding of the current file on the editor toolbar (4), To show the file encoding of the current file on the editor toolbar (4),
select \uicontrol Tools > \uicontrol Options > \uicontrol {Text Editor} > 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 \note Other convenient ways of navigating in \QC are provided by the
\l{Searching with the Locator}{locator}, \l{Keyboard Shortcuts} \l{Searching with the Locator}{locator}, \l{Keyboard Shortcuts}

View File

@@ -26,7 +26,7 @@
\contentspage {Qt Creator Manual} \contentspage {Qt Creator Manual}
\previouspage creator-usability.html \previouspage creator-usability.html
\page creator-coding.html \page creator-coding.html
\nextpage creator-modeling.html \nextpage creator-editor-functions.html
\title Coding \title Coding
@@ -34,12 +34,6 @@
\list \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} \li \l{Writing Code}
Writing, editing, and navigating in source code are core tasks in 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 to use for opening the file. If your files do not match the
predefined MIME types, you can edit the MIME types. predefined MIME types, you can edit the MIME types.
\li \l{Comparing Files} \li \l{Modeling}
You can use a diff editor to compare two versions of a file and You can use the experimental model editor to create Universal
view the differences side-by-side in the \uicontrol Edit mode. Modeling Language (UML) style models with structured diagrams and
store them in XML format.
\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 \endlist

View File

@@ -24,7 +24,7 @@
/*! /*!
\contentspage {Qt Creator Manual} \contentspage {Qt Creator Manual}
\previouspage creator-modeling.html \previouspage creator-coding.html
\page creator-editor-functions.html \page creator-editor-functions.html
\nextpage creator-coding-navigating.html \nextpage creator-coding-navigating.html
@@ -93,4 +93,23 @@
\endlist \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
*/ */

View File

@@ -26,7 +26,7 @@
\contentspage {Qt Creator Manual} \contentspage {Qt Creator Manual}
\previouspage creator-editor-fakevim.html \previouspage creator-editor-fakevim.html
\page creator-mime-types.html \page creator-mime-types.html
\nextpage creator-building-running.html \nextpage creator-modeling.html
\title Editing MIME Types \title Editing MIME Types

View File

@@ -24,9 +24,9 @@
/*! /*!
\contentspage {Qt Creator Manual} \contentspage {Qt Creator Manual}
\previouspage creator-coding.html \previouspage creator-mime-types.html
\page creator-modeling.html \page creator-modeling.html
\nextpage creator-editor-functions.html \nextpage creator-building-running.html
\title Modeling \title Modeling

View File

@@ -29,7 +29,7 @@
For more information about the supported device groups and reference devices, For more information about the supported device groups and reference devices,
see \l{http://doc.qt.io/QtForDeviceCreation/qtee-supported-platforms.html} 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. {Qt for Device Creation} documentation.
\section2 Mobile Devices \section2 Mobile Devices

View File

@@ -24,7 +24,7 @@
/*! /*!
\contentspage {Qt Creator Manual} \contentspage {Qt Creator Manual}
\previouspage creator-mime-types.html \previouspage creator-modeling.html
\page creator-building-running.html \page creator-building-running.html
\nextpage creator-building-targets.html \nextpage creator-building-targets.html

View File

@@ -72,11 +72,11 @@
\endlist \endlist
\li \b {\l{Coding}} \li \b {\l{Coding}}
\list \list
\li \l{Modeling}
\li \l{Writing Code} \li \l{Writing Code}
\li \l{Finding} \li \l{Finding}
\li \l{Refactoring} \li \l{Refactoring}
\li \l{Configuring the Editor} \li \l{Configuring the Editor}
\li \l{Modeling}
\endlist \endlist
\row \row
\li \inlineimage creator_buildingrunning.png \li \inlineimage creator_buildingrunning.png
@@ -113,7 +113,6 @@
\li \l{Known Issues} \li \l{Known Issues}
\li \l{Glossary} \li \l{Glossary}
\endlist \endlist
\li
\row \row
\li {4,1} \note To report bugs and suggestions to the Qt Bug \li {4,1} \note To report bugs and suggestions to the Qt Bug
Tracker, select \uicontrol {Help > Report Bug}. Tracker, select \uicontrol {Help > Report Bug}.
@@ -194,7 +193,6 @@
\endlist \endlist
\li \l{Coding} \li \l{Coding}
\list \list
\li \l{Modeling}
\li \l{Writing Code} \li \l{Writing Code}
\list \list
\li \l{Working in Edit Mode} \li \l{Working in Edit Mode}
@@ -221,6 +219,7 @@
\li \l{Using FakeVim Mode} \li \l{Using FakeVim Mode}
\endlist \endlist
\li \l{Editing MIME Types} \li \l{Editing MIME Types}
\li \l{Modeling}
\endlist \endlist
\li \l{Building and Running} \li \l{Building and Running}
\list \list

View File

@@ -25,7 +25,7 @@
/*! /*!
\contentspage {Qt Creator Manual} \contentspage {Qt Creator Manual}
\previouspage creator-using-qt-quick-designer.html \previouspage qmldesigner-connections.html
\page quick-components.html \page quick-components.html
\nextpage quick-buttons.html \nextpage quick-buttons.html

View File

@@ -31,7 +31,7 @@
\contentspage {Qt Creator Manual} \contentspage {Qt Creator Manual}
\previouspage qmldesigner-pathview-editor.html \previouspage qmldesigner-pathview-editor.html
\page qmldesigner-connections.html \page qmldesigner-connections.html
\nextpage quick-export-to-qml.html \nextpage quick-components.html
\title Adding Connections \title Adding Connections

View File

@@ -26,7 +26,7 @@
\contentspage {Qt Creator Manual} \contentspage {Qt Creator Manual}
\previouspage creator-quick-ui-forms.html \previouspage creator-quick-ui-forms.html
\page creator-using-qt-quick-designer.html \page creator-using-qt-quick-designer.html
\nextpage quick-components.html \nextpage qmldesigner-pathview-editor.html
\title Using Qt Quick Designer \title Using Qt Quick Designer

View File

@@ -29,7 +29,7 @@
/*! /*!
\contentspage {Qt Creator Manual} \contentspage {Qt Creator Manual}
\previouspage creator-qtquick-designer-extensions.html \previouspage creator-using-qt-quick-designer.html
\page qmldesigner-pathview-editor.html \page qmldesigner-pathview-editor.html
\nextpage qmldesigner-connections.html \nextpage qmldesigner-connections.html

View File

@@ -1034,9 +1034,8 @@ class DumperBase:
# We cannot use str(addr) as it yields rubbish for char pointers # We cannot use str(addr) as it yields rubbish for char pointers
# that might trigger Unicode encoding errors. # that might trigger Unicode encoding errors.
#return addr.cast(lookupType("void").pointer()) #return addr.cast(lookupType("void").pointer())
# We do not use "hex(...)" as it (sometimes?) adds a "L" suffix.
try: try:
return "0x%x" % toInteger(addr) return "0x%x" % toInteger(hex(addr), 16)
except: except:
warn("CANNOT CONVERT TYPE: %s" % type(addr)) warn("CANNOT CONVERT TYPE: %s" % type(addr))
try: try:

View File

@@ -8,7 +8,7 @@
"trDisplayCategory": "Application", "trDisplayCategory": "Application",
"icon": "3dapplication.png", "icon": "3dapplication.png",
"featuresRequired": [ "QtSupport.Wizards.FeatureQtCanvas3d" ], "featuresRequired": [ "QtSupport.Wizards.FeatureQtCanvas3d" ],
"enabled": "${JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}", "enabled": "%{JS: [ %{Plugins} ].indexOf('QmakeProjectManager') >= 0}",
"options": "options":
[ [

View File

@@ -5,7 +5,7 @@
"category": "H.Project", "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.", "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", "trDisplayName": "Qt Quick UI",
"trDisplayCategory": "Application", "trDisplayCategory": "Other Project",
"icon": "../../qmake/qtquickapplication/qml_wizard.png", "icon": "../../qmake/qtquickapplication/qml_wizard.png",
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}", "enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
"featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick.Controls.1.3", "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQt" ], "featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick.Controls.1.3", "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQt" ],

View File

@@ -5,7 +5,7 @@
"category": "H.Project", "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.", "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", "trDisplayName": "Qt Quick Controls UI",
"trDisplayCategory": "Application", "trDisplayCategory": "Other Project",
"icon": "../../qmake/qtquickapplication/qml_wizard.png", "icon": "../../qmake/qtquickapplication/qml_wizard.png",
"enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}", "enabled": "%{JS: [ %{Plugins} ].indexOf('QmlProjectManager') >= 0}",
"featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick.Controls.1.3", "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQt" ], "featuresRequired": [ "QtSupport.Wizards.FeatureQtQuick.Controls.1.3", "QtSupport.Wizards.FeatureQtQuickProject", "QtSupport.Wizards.FeatureQt" ],

View File

@@ -1390,10 +1390,6 @@ Deploying local Qt libraries is incompatible with Android 5.</source>
<source>Core plugin is disabled.</source> <source>Core plugin is disabled.</source>
<translation>Базовый модуль отключён.</translation> <translation>Базовый модуль отключён.</translation>
</message> </message>
<message>
<source>No valid theme &quot;%1&quot;</source>
<translation>Подходящая тема «%1» не обнаружена</translation>
</message>
</context> </context>
<context> <context>
<name>ApplicationWindowSpecifics</name> <name>ApplicationWindowSpecifics</name>
@@ -5382,6 +5378,10 @@ Continue?</source>
</context> </context>
<context> <context>
<name>Core::Internal::CorePlugin</name> <name>Core::Internal::CorePlugin</name>
<message>
<source>No themes found in installation.</source>
<translation>Темы не установлены.</translation>
</message>
<message> <message>
<source>The current date (ISO).</source> <source>The current date (ISO).</source>
<translation>Текущая дата (ISO).</translation> <translation>Текущая дата (ISO).</translation>
@@ -8285,26 +8285,6 @@ In addition, Shift+Enter inserts an escape character at the cursor position and
<source>Form</source> <source>Form</source>
<translation></translation> <translation></translation>
</message> </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> <message>
<source>Pre-compiled Headers</source> <source>Pre-compiled Headers</source>
<translation>Прекомпилированные заголовки</translation> <translation>Прекомпилированные заголовки</translation>
@@ -8318,8 +8298,20 @@ In addition, Shift+Enter inserts an escape character at the cursor position and
<translation>Игнорировать прекомпилированные заголовки</translation> <translation>Игнорировать прекомпилированные заголовки</translation>
</message> </message>
<message> <message>
<source>Headers</source> <source>&lt;i&gt;Activate the Clang Code Model plugin to enable the options here.&lt;/i&gt;</source>
<translation>Заголовочные</translation> <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> </message>
</context> </context>
<context> <context>
@@ -10437,14 +10429,6 @@ Flags: %3</source>
<source>Changes the font size in the debugger views when the font size in the main editor changes.</source> <source>Changes the font size in the debugger views when the font size in the main editor changes.</source>
<translation>Менять размер шрифта в окне отладчика при изменении его в основном окне редактора.</translation> <translation>Менять размер шрифта в окне отладчика при изменении его в основном окне редактора.</translation>
</message> </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> <message>
<source>Switch to previous mode on debugger exit</source> <source>Switch to previous mode on debugger exit</source>
<translation>Переключаться в предыдущий режим при завершении отладчика</translation> <translation>Переключаться в предыдущий режим при завершении отладчика</translation>
@@ -11364,10 +11348,6 @@ Qt Creator не может подключиться к нему.</translation>
<source>Use Tooltips in Stack View when Debugging</source> <source>Use Tooltips in Stack View when Debugging</source>
<translation>Подсказки в обзоре стека при отладке</translation> <translation>Подсказки в обзоре стека при отладке</translation>
</message> </message>
<message>
<source>List Source Files</source>
<translation>Показать файлы исходников</translation>
</message>
<message> <message>
<source>Skip Known Frames</source> <source>Skip Known Frames</source>
<translation>Пропустить известные кадры</translation> <translation>Пропустить известные кадры</translation>
@@ -22142,6 +22122,10 @@ Ids must begin with a lowercase letter.</source>
</context> </context>
<context> <context>
<name>ProjectExplorer::Internal::DependenciesWidget</name> <name>ProjectExplorer::Internal::DependenciesWidget</name>
<message>
<source>Synchronize configuration</source>
<translation>Синхронизировать конфигурацию</translation>
</message>
<message> <message>
<source>Synchronize active kit, build, and deploy configuration between projects.</source> <source>Synchronize active kit, build, and deploy configuration between projects.</source>
<translation>Сихронизировать у проектов текущий комплект и конфигурации сборки и установки.</translation> <translation>Сихронизировать у проектов текущий комплект и конфигурации сборки и установки.</translation>
@@ -34043,7 +34027,7 @@ with a password, which you can enter below.</source>
<context> <context>
<name>TextEditor::FindInFiles</name> <name>TextEditor::FindInFiles</name>
<message> <message>
<source>Files on File System</source> <source>Files in File System</source>
<translation>Файлы в системе</translation> <translation>Файлы в системе</translation>
</message> </message>
<message> <message>
@@ -38740,6 +38724,10 @@ should a repository require SSH-authentication (see documentation on SSH and the
</context> </context>
<context> <context>
<name>WinRt::Internal::WinRtDebugSupport</name> <name>WinRt::Internal::WinRtDebugSupport</name>
<message>
<source>Not enough free ports for QML debugging.</source>
<translation>Недостаточно свободных портов для отладки QML.</translation>
</message>
<message> <message>
<source>The WinRT debugging helper is missing from your Qt Creator installation. It was assumed to be located at %1</source> <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> <translation>Помощник отладчика WinRT отсутствует в составе установки вашего Qt Creator. Предполагается, что он находится в %1</translation>

View File

@@ -3349,7 +3349,7 @@ public:
DeclarationAST *declaration; DeclarationAST *declaration;
public: // annotations public: // annotations
Scope *symbol; Template *symbol;
public: public:
TemplateDeclarationAST() TemplateDeclarationAST()

View File

@@ -1917,19 +1917,9 @@ bool Bind::visit(SimpleDeclarationAST *ast)
methodKey = methodKeyForInvokableToken(tokenKind(ast->qt_invokable_token)); methodKey = methodKeyForInvokableToken(tokenKind(ast->qt_invokable_token));
// unsigned qt_invokable_token = ast->qt_invokable_token; // unsigned qt_invokable_token = ast->qt_invokable_token;
const ExpressionAST *declTypeExpression = 0;
bool isTypedef = false;
FullySpecifiedType type; FullySpecifiedType type;
for (SpecifierListAST *it = ast->decl_specifier_list; it; it = it->next) { for (SpecifierListAST *it = ast->decl_specifier_list; it; it = it->next) {
type = this->specifier(it->value, type); 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; 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"); translationUnit()->error(location(declaratorId->name, ast->firstToken()), "auto-initialized variable must have an initializer");
else if (initializer) else if (initializer)
decl->setInitializer(asStringLiteral(initializer)); decl->setInitializer(asStringLiteral(initializer));
} else if (declTy.isDecltype()) {
decl->setInitializer(asStringLiteral(declTypeExpression));
} }
if (_scope->isClass()) { if (_scope->isClass()) {
@@ -2367,15 +2355,11 @@ bool Bind::visit(ParameterDeclarationAST *ast)
bool Bind::visit(TemplateDeclarationAST *ast) bool Bind::visit(TemplateDeclarationAST *ast)
{ {
Scope *scope = 0; Template *templ = control()->newTemplate(ast->firstToken(), 0);
if (ast->less_token) templ->setStartOffset(tokenAt(ast->firstToken()).utf16charsBegin());
scope = control()->newTemplate(ast->firstToken(), 0); templ->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
else ast->symbol = templ;
scope = control()->newExplicitInstantiation(ast->firstToken(), 0); Scope *previousScope = switchScope(templ);
scope->setStartOffset(tokenAt(ast->firstToken()).utf16charsBegin());
scope->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd());
ast->symbol = scope;
Scope *previousScope = switchScope(scope);
for (DeclarationListAST *it = ast->template_parameter_list; it; it = it->next) { for (DeclarationListAST *it = ast->template_parameter_list; it; it = it->next) {
this->declaration(it->value); this->declaration(it->value);
@@ -2384,17 +2368,12 @@ bool Bind::visit(TemplateDeclarationAST *ast)
this->declaration(ast->declaration); this->declaration(ast->declaration);
(void) switchScope(previousScope); (void) switchScope(previousScope);
Symbol *decl = 0; if (Symbol *decl = templ->declaration()) {
if (Template *templ = scope->asTemplate()) templ->setSourceLocation(decl->sourceLocation(), translationUnit());
decl = templ->declaration(); templ->setName(decl->name());
else if (ExplicitInstantiation *inst = scope->asExplicitInstantiation())
decl = inst->declaration();
if (decl) {
scope->setSourceLocation(decl->sourceLocation(), translationUnit());
scope->setName(decl->name());
} }
_scope->addMember(scope); _scope->addMember(templ);
return false; return false;
} }
@@ -3039,7 +3018,6 @@ bool Bind::visit(TypeofSpecifierAST *ast)
bool Bind::visit(DecltypeSpecifierAST *ast) bool Bind::visit(DecltypeSpecifierAST *ast)
{ {
_type = this->expression(ast->expression); _type = this->expression(ast->expression);
_type.setDecltype(true);
return false; return false;
} }

View File

@@ -112,7 +112,6 @@ class Function;
class Namespace; class Namespace;
class NamespaceAlias; class NamespaceAlias;
class Template; class Template;
class ExplicitInstantiation;
class BaseClass; class BaseClass;
class Block; class Block;
class Class; class Class;

View File

@@ -366,16 +366,9 @@ public:
Template *newTemplate(unsigned sourceLocation, const Name *name) Template *newTemplate(unsigned sourceLocation, const Name *name)
{ {
Template *templ = new Template(translationUnit, sourceLocation, name); Template *ns = new Template(translationUnit, sourceLocation, name);
symbols.push_back(templ); symbols.push_back(ns);
return templ; return ns;
}
ExplicitInstantiation *newExplicitInstantiation(unsigned sourceLocation, const Name *name)
{
ExplicitInstantiation *inst = new ExplicitInstantiation(translationUnit, sourceLocation, name);
symbols.push_back(inst);
return inst;
} }
NamespaceAlias *newNamespaceAlias(unsigned sourceLocation, const Name *name) 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) Template *Control::newTemplate(unsigned sourceLocation, const Name *name)
{ return d->newTemplate(sourceLocation, 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) NamespaceAlias *Control::newNamespaceAlias(unsigned sourceLocation, const Name *name)
{ return d->newNamespaceAlias(sourceLocation, name); } { return d->newNamespaceAlias(sourceLocation, name); }

View File

@@ -120,9 +120,6 @@ public:
/// Creates a new Template symbol. /// Creates a new Template symbol.
Template *newTemplate(unsigned sourceLocation, const Name *name = 0); 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. /// Creates a new Namespace symbol.
NamespaceAlias *newNamespaceAlias(unsigned sourceLocation, const Name *name = 0); NamespaceAlias *newNamespaceAlias(unsigned sourceLocation, const Name *name = 0);

View File

@@ -100,12 +100,6 @@ bool FullySpecifiedType::isAuto() const
void FullySpecifiedType::setAuto(bool isAuto) void FullySpecifiedType::setAuto(bool isAuto)
{ f._isAuto = isAuto; } { f._isAuto = isAuto; }
bool FullySpecifiedType::isDecltype() const
{ return f._isDecltype; }
void FullySpecifiedType::setDecltype(bool isDecltype)
{ f._isDecltype = isDecltype; }
bool FullySpecifiedType::isRegister() const bool FullySpecifiedType::isRegister() const
{ return f._isRegister; } { return f._isRegister; }

View File

@@ -58,9 +58,6 @@ public:
bool isAuto() const; bool isAuto() const;
void setAuto(bool isAuto); void setAuto(bool isAuto);
bool isDecltype() const;
void setDecltype(bool isDecltype);
bool isRegister() const; bool isRegister() const;
void setRegister(bool isRegister); void setRegister(bool isRegister);
@@ -128,7 +125,6 @@ private:
// storage class specifiers // storage class specifiers
unsigned _isFriend: 1; unsigned _isFriend: 1;
unsigned _isAuto: 1; unsigned _isAuto: 1;
unsigned _isDecltype: 1;
unsigned _isRegister: 1; unsigned _isRegister: 1;
unsigned _isStatic: 1; unsigned _isStatic: 1;
unsigned _isExtern: 1; unsigned _isExtern: 1;

View File

@@ -218,17 +218,6 @@ bool Matcher::match(const Template *type, const Template *otherType)
return true; 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) bool Matcher::match(const ForwardClassDeclaration *type, const ForwardClassDeclaration *otherType)
{ {
if (type == otherType) if (type == otherType)

View File

@@ -61,7 +61,6 @@ public:
virtual bool match(const Enum *type, const Enum *otherType); virtual bool match(const Enum *type, const Enum *otherType);
virtual bool match(const Namespace *type, const Namespace *otherType); virtual bool match(const Namespace *type, const Namespace *otherType);
virtual bool match(const Template *type, const Template *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 ForwardClassDeclaration *type, const ForwardClassDeclaration *otherType);
virtual bool match(const Class *type, const Class *otherType); virtual bool match(const Class *type, const Class *otherType);
virtual bool match(const ObjCClass *type, const ObjCClass *otherType); virtual bool match(const ObjCClass *type, const ObjCClass *otherType);

View File

@@ -100,7 +100,7 @@ public:
TemplateArgumentIterator firstTemplateArgument() const { return _templateArguments.begin(); } TemplateArgumentIterator firstTemplateArgument() const { return _templateArguments.begin(); }
TemplateArgumentIterator lastTemplateArgument() const { return _templateArguments.end(); } TemplateArgumentIterator lastTemplateArgument() const { return _templateArguments.end(); }
bool isSpecialization() const { return _isSpecialization; } 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 // when we try to find correct specialization for instantiation
void setIsSpecialization(bool isSpecialization) { _isSpecialization = isSpecialization; } void setIsSpecialization(bool isSpecialization) { _isSpecialization = isSpecialization; }

View File

@@ -1789,6 +1789,11 @@ bool Parser::parseEnumSpecifier(SpecifierListAST *&node)
if (_languageFeatures.cxx11Enabled && (LA() == T_CLASS || LA() == T_STRUCT)) if (_languageFeatures.cxx11Enabled && (LA() == T_CLASS || LA() == T_STRUCT))
ast->key_token = consumeToken(); ast->key_token = consumeToken();
if (tok().isKeyword()) {
error(cursor(), "expected identifier before '%s'", tok().spell());
return false;
}
parseName(ast->name); parseName(ast->name);
if (_languageFeatures.cxx11Enabled && LA() == T_COLON) { if (_languageFeatures.cxx11Enabled && LA() == T_COLON) {

View File

@@ -215,7 +215,7 @@ unsigned SymbolTable::symbolCount() const
Symbol *SymbolTable::symbolAt(unsigned index) const Symbol *SymbolTable::symbolAt(unsigned index) const
{ {
if (! _symbols || index >= symbolCount()) if (! _symbols)
return 0; return 0;
return _symbols[index]; return _symbols[index];
} }

View File

@@ -361,9 +361,6 @@ bool Symbol::isNamespace() const
bool Symbol::isTemplate() const bool Symbol::isTemplate() const
{ return asTemplate() != 0; } { return asTemplate() != 0; }
bool Symbol::isExplicitInstantiation() const
{ return asExplicitInstantiation() != 0; }
bool Symbol::isClass() const bool Symbol::isClass() const
{ return asClass() != 0; } { return asClass() != 0; }

View File

@@ -135,7 +135,7 @@ public:
/// Returns true if this Symbol is an Enum. /// Returns true if this Symbol is an Enum.
bool isEnum() const; bool isEnum() const;
/// Returns true if this Symbol is a Function. /// Returns true if this Symbol is an Function.
bool isFunction() const; bool isFunction() const;
/// Returns true if this Symbol is a Namespace. /// Returns true if this Symbol is a Namespace.
@@ -144,9 +144,6 @@ public:
/// Returns true if this Symbol is a Template. /// Returns true if this Symbol is a Template.
bool isTemplate() const; bool isTemplate() const;
/// Returns true if this Symbol is an ExplicitInstantiation.
bool isExplicitInstantiation() const;
/// Returns true if this Symbol is a Class. /// Returns true if this Symbol is a Class.
bool isClass() const; bool isClass() const;
@@ -206,7 +203,6 @@ public:
virtual const Function *asFunction() const { return 0; } virtual const Function *asFunction() const { return 0; }
virtual const Namespace *asNamespace() const { return 0; } virtual const Namespace *asNamespace() const { return 0; }
virtual const Template *asTemplate() 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 NamespaceAlias *asNamespaceAlias() const { return 0; }
virtual const Class *asClass() const { return 0; } virtual const Class *asClass() const { return 0; }
virtual const Block *asBlock() const { return 0; } virtual const Block *asBlock() const { return 0; }
@@ -233,7 +229,6 @@ public:
virtual Function *asFunction() { return 0; } virtual Function *asFunction() { return 0; }
virtual Namespace *asNamespace() { return 0; } virtual Namespace *asNamespace() { return 0; }
virtual Template *asTemplate() { return 0; } virtual Template *asTemplate() { return 0; }
virtual ExplicitInstantiation *asExplicitInstantiation() { return 0; }
virtual NamespaceAlias *asNamespaceAlias() { return 0; } virtual NamespaceAlias *asNamespaceAlias() { return 0; }
virtual Class *asClass() { return 0; } virtual Class *asClass() { return 0; }
virtual Block *asBlock() { return 0; } virtual Block *asBlock() { return 0; }

View File

@@ -51,7 +51,6 @@ public:
virtual bool visit(Function *) { return true; } virtual bool visit(Function *) { return true; }
virtual bool visit(Namespace *) { return true; } virtual bool visit(Namespace *) { return true; }
virtual bool visit(Template *) { return true; } virtual bool visit(Template *) { return true; }
virtual bool visit(ExplicitInstantiation *) { return true; }
virtual bool visit(Class *) { return true; } virtual bool visit(Class *) { return true; }
virtual bool visit(Block *) { return true; } virtual bool visit(Block *) { return true; }
virtual bool visit(ForwardClassDeclaration *) { return true; } virtual bool visit(ForwardClassDeclaration *) { return true; }

View File

@@ -481,12 +481,10 @@ void Enum::visitSymbol0(SymbolVisitor *visitor)
Template::Template(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name) Template::Template(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
: Scope(translationUnit, sourceLocation, name) : Scope(translationUnit, sourceLocation, name)
, _isExplicitInstantiation(false)
{ } { }
Template::Template(Clone *clone, Subst *subst, Template *original) Template::Template(Clone *clone, Subst *subst, Template *original)
: Scope(clone, subst, original) : Scope(clone, subst, original)
, _isExplicitInstantiation(original->_isExplicitInstantiation)
{ } { }
Template::~Template() Template::~Template()
@@ -539,56 +537,6 @@ bool Template::match0(const Type *otherType, Matcher *matcher) const
return false; 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) Namespace::Namespace(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
: Scope(translationUnit, sourceLocation, name) : Scope(translationUnit, sourceLocation, name)
, _isInline(false) , _isInline(false)

View File

@@ -423,41 +423,8 @@ protected:
virtual void visitSymbol0(SymbolVisitor *visitor); virtual void visitSymbol0(SymbolVisitor *visitor);
virtual void accept0(TypeVisitor *visitor); virtual void accept0(TypeVisitor *visitor);
virtual bool match0(const Type *otherType, Matcher *matcher) const; 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 class CPLUSPLUS_EXPORT Namespace: public Scope, public Type
{ {

View File

@@ -125,12 +125,6 @@ void CloneType::visit(Template *type)
_type = templ; _type = templ;
} }
void CloneType::visit(ExplicitInstantiation *type)
{
ExplicitInstantiation *inst = _clone->symbol(type, _subst)->asExplicitInstantiation();
_type = inst;
}
void CloneType::visit(Class *type) void CloneType::visit(Class *type)
{ {
Class *klass = _clone->symbol(type, _subst)->asClass(); 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); SymbolSubstPair symbolSubstPair = std::make_pair(symbol, subst);
auto it = _cache.find(symbolSubstPair); auto it = _cache.find(symbolSubstPair);
if (it != _cache.end()) if (it != _cache.end()) {
if (it->second->enclosingScope() == symbol->enclosingScope())
return it->second; return it->second;
}
Symbol *r = 0; Symbol *r = 0;
std::swap(_subst, subst); std::swap(_subst, subst);
@@ -297,14 +293,6 @@ bool CloneSymbol::visit(Template *symbol)
return false; 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) bool CloneSymbol::visit(Class *symbol)
{ {
Class *klass = new Class(_clone, _subst, symbol); Class *klass = new Class(_clone, _subst, symbol);

View File

@@ -85,7 +85,6 @@ protected:
virtual void visit(Function *type); virtual void visit(Function *type);
virtual void visit(Namespace *type); virtual void visit(Namespace *type);
virtual void visit(Template *type); virtual void visit(Template *type);
virtual void visit(ExplicitInstantiation *type);
virtual void visit(Class *type); virtual void visit(Class *type);
virtual void visit(Enum *type); virtual void visit(Enum *type);
virtual void visit(ForwardClassDeclaration *type); virtual void visit(ForwardClassDeclaration *type);
@@ -153,7 +152,6 @@ protected:
virtual bool visit(Function *symbol); virtual bool visit(Function *symbol);
virtual bool visit(Namespace *symbol); virtual bool visit(Namespace *symbol);
virtual bool visit(Template *symbol); virtual bool visit(Template *symbol);
virtual bool visit(ExplicitInstantiation *symbol);
virtual bool visit(Class *symbol); virtual bool visit(Class *symbol);
virtual bool visit(Block *symbol); virtual bool visit(Block *symbol);
virtual bool visit(ForwardClassDeclaration *symbol); virtual bool visit(ForwardClassDeclaration *symbol);

View File

@@ -68,9 +68,6 @@ bool Type::isNamespaceType() const
bool Type::isTemplateType() const bool Type::isTemplateType() const
{ return asTemplateType() != 0; } { return asTemplateType() != 0; }
bool Type::isExplicitInstantiationType() const
{ return asExplicitInstantiationType() != 0; }
bool Type::isClassType() const bool Type::isClassType() const
{ return asClassType() != 0; } { return asClassType() != 0; }

View File

@@ -43,7 +43,6 @@ public:
bool isFunctionType() const; bool isFunctionType() const;
bool isNamespaceType() const; bool isNamespaceType() const;
bool isTemplateType() const; bool isTemplateType() const;
bool isExplicitInstantiationType() const;
bool isClassType() const; bool isClassType() const;
bool isEnumType() const; bool isEnumType() const;
bool isForwardClassDeclarationType() const; bool isForwardClassDeclarationType() const;
@@ -65,7 +64,6 @@ public:
virtual const Function *asFunctionType() const { return 0; } virtual const Function *asFunctionType() const { return 0; }
virtual const Namespace *asNamespaceType() const { return 0; } virtual const Namespace *asNamespaceType() const { return 0; }
virtual const Template *asTemplateType() 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 Class *asClassType() const { return 0; }
virtual const Enum *asEnumType() const { return 0; } virtual const Enum *asEnumType() const { return 0; }
virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const { return 0; } virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const { return 0; }
@@ -87,7 +85,6 @@ public:
virtual Function *asFunctionType() { return 0; } virtual Function *asFunctionType() { return 0; }
virtual Namespace *asNamespaceType() { return 0; } virtual Namespace *asNamespaceType() { return 0; }
virtual Template *asTemplateType() { return 0; } virtual Template *asTemplateType() { return 0; }
virtual ExplicitInstantiation *asExplicitInstantiationType() { return 0; }
virtual Class *asClassType() { return 0; } virtual Class *asClassType() { return 0; }
virtual Enum *asEnumType() { return 0; } virtual Enum *asEnumType() { return 0; }
virtual ForwardClassDeclaration *asForwardClassDeclarationType() { return 0; } virtual ForwardClassDeclaration *asForwardClassDeclarationType() { return 0; }

View File

@@ -51,7 +51,6 @@ public:
virtual void visit(Function *) {} virtual void visit(Function *) {}
virtual void visit(Namespace *) {} virtual void visit(Namespace *) {}
virtual void visit(Template *) {} virtual void visit(Template *) {}
virtual void visit(ExplicitInstantiation *) {}
virtual void visit(Class *) {} virtual void visit(Class *) {}
virtual void visit(Enum *) {} virtual void visit(Enum *) {}
virtual void visit(ForwardClassDeclaration *) {} virtual void visit(ForwardClassDeclaration *) {}

View File

@@ -490,7 +490,8 @@ QList<MClassMember> ClassMembersEdit::parse(const QString &text, bool *ok)
member.setProperties(member.properties() | MClassMember::PropertyQslot); member.setProperties(member.properties() | MClassMember::PropertyQslot);
word = cursor.readWord().toLower(); word = cursor.readWord().toLower();
} else if (word == QStringLiteral("invokable") || word == QStringLiteral("qInvokable")) { } 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(":")) { } else if (word == QStringLiteral(":")) {
word = cursor.readWord().toLower(); word = cursor.readWord().toLower();
} else { } else {

View File

@@ -53,5 +53,28 @@ enum class DiagnosticSeverity // one to one mapping of the clang enum numbers
Error = 3, Error = 3,
Fatal = 4 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 #endif // CLANGBACKENDIPC_GLOBAL_H

View File

@@ -379,7 +379,7 @@ FullySpecifiedType SubstitutionMap::apply(const Name *name, Rewrite *) const
} }
UseMinimalNames::UseMinimalNames(LookupScope *target) UseMinimalNames::UseMinimalNames(ClassOrNamespace *target)
: _target(target) : _target(target)
{ {

View File

@@ -89,13 +89,13 @@ private:
class CPLUSPLUS_EXPORT UseMinimalNames: public Substitution class CPLUSPLUS_EXPORT UseMinimalNames: public Substitution
{ {
public: public:
UseMinimalNames(LookupScope *target); UseMinimalNames(ClassOrNamespace *target);
virtual ~UseMinimalNames(); virtual ~UseMinimalNames();
virtual FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const; virtual FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const;
private: private:
LookupScope *_target; ClassOrNamespace *_target;
}; };
class CPLUSPLUS_EXPORT UseQualifiedNames: public UseMinimalNames class CPLUSPLUS_EXPORT UseQualifiedNames: public UseMinimalNames

View File

@@ -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();
}

View File

@@ -28,41 +28,36 @@
** **
****************************************************************************/ ****************************************************************************/
#ifndef TYPERESOLVER_H #ifndef CPLUSPLUS_DEPRECATEDGENTEMPLATEINSTANCE_H
#define TYPERESOLVER_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 { namespace CPlusPlus {
class TypeResolver class CPLUSPLUS_EXPORT DeprecatedGenTemplateInstance
{ {
public: public:
TypeResolver(CreateBindings &factory) : _factory(factory) {} typedef QList< QPair<const Identifier *, FullySpecifiedType> > Substitution;
void resolve(FullySpecifiedType *type, Scope **scope, LookupScope *binding);
static QList<LookupItem> resolveDeclInitializer( public:
CreateBindings &factory, const Declaration *decl, static FullySpecifiedType instantiate(const Name *className, Symbol *candidate, QSharedPointer<Control> control);
const QSet<const Declaration *> &declarationsBeingResolved,
const Identifier *id = 0);
private: private:
NamedType *getNamedType(FullySpecifiedType& type) const; DeprecatedGenTemplateInstance(QSharedPointer<Control> control, const Substitution &substitution);
FullySpecifiedType gen(Symbol *symbol);
QList<LookupItem> getNamedTypeItems(const Name *name, Scope *scope, private:
LookupScope *binding) const; QSharedPointer<Control> _control;
const Substitution _substitution;
static QList<LookupItem> typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope);
static bool isTypedefWithName(const Declaration *declaration, const Name *name);
bool findTypedef(const QList<LookupItem>& namedTypeItems, FullySpecifiedType *type,
Scope **scope, QSet<Symbol *>& visited);
CreateBindings &_factory;
// binding has to be remembered in case of resolving typedefs for templates
LookupScope *_binding;
}; };
} // namespace CPlusPlus } // namespace CPlusPlus
#endif // TYPERESOLVER_H #endif // CPLUSPLUS_DEPRECATEDGENTEMPLATEINSTANCE_H

View File

@@ -532,7 +532,7 @@ void FindUsages::memInitializer(MemInitializerAST *ast)
if (_currentScope->isFunction()) { if (_currentScope->isFunction()) {
Class *classScope = _currentScope->enclosingClass(); Class *classScope = _currentScope->enclosingClass();
if (! classScope) { if (! classScope) {
if (LookupScope *binding = _context.lookupType(_currentScope)) { if (ClassOrNamespace *binding = _context.lookupType(_currentScope)) {
foreach (Symbol *s, binding->symbols()) { foreach (Symbol *s, binding->symbols()) {
if (Class *k = s->asClass()) { if (Class *k = s->asClass()) {
classScope = k; classScope = k;

File diff suppressed because it is too large Load Diff

View File

@@ -41,7 +41,6 @@
#include <cplusplus/Control.h> #include <cplusplus/Control.h>
#include <cplusplus/Name.h> #include <cplusplus/Name.h>
#include <QEnableSharedFromThis>
#include <QSet> #include <QSet>
#include <QMap> #include <QMap>
@@ -59,78 +58,158 @@ struct FullyQualifiedName
: fqn(fqn) : fqn(fqn)
{} {}
}; };
class LookupScopePrivate;
class Instantiator;
} // namespace Internal; } // namespace Internal;
class CreateBindings; 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: public:
~LookupScope(); ~ClassOrNamespace();
LookupScope *instantiationOrigin() const; const TemplateNameId *templateId() const;
ClassOrNamespace *instantiationOrigin() const;
LookupScope *parent() const; ClassOrNamespace *parent() const;
QList<LookupScope *> usings() const; QList<ClassOrNamespace *> usings() const;
QList<Enum *> unscopedEnums() const; QList<Enum *> unscopedEnums() const;
QList<Symbol *> symbols() const; QList<Symbol *> symbols() const;
ClassOrNamespace *globalNamespace() const;
QList<LookupItem> lookup(const Name *name); QList<LookupItem> lookup(const Name *name);
QList<LookupItem> find(const Name *name); QList<LookupItem> find(const Name *name);
LookupScope *lookupType(const Name *name); ClassOrNamespace *lookupType(const Name *name);
LookupScope *lookupType(const Name *name, Block *block); ClassOrNamespace *lookupType(const Name *name, Block *block);
LookupScope *findType(const Name *name); ClassOrNamespace *findType(const Name *name);
LookupScope *findBlock(Block *block); ClassOrNamespace *findBlock(Block *block);
/// The class this LookupScope is based on. Symbol *lookupInScope(const QList<const Name *> &fullName);
Class *rootClass() const;
/// The class this ClassOrNamespace is based on.
Class *rootClass() const { return _rootClass; }
private: 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; friend class CreateBindings;
}; };
class CPLUSPLUS_EXPORT CreateBindings class CPLUSPLUS_EXPORT CreateBindings: protected SymbolVisitor
: protected SymbolVisitor
, public QEnableSharedFromThis<CreateBindings>
{ {
Q_DISABLE_COPY(CreateBindings) Q_DISABLE_COPY(CreateBindings)
public: public:
typedef QSharedPointer<CreateBindings> Ptr;
CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot); CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot);
virtual ~CreateBindings(); virtual ~CreateBindings();
/// Returns the binding for the global namespace. /// Returns the binding for the global namespace.
LookupScope *globalNamespace() const; ClassOrNamespace *globalNamespace() const;
/// Finds the binding associated to the given symbol. /// Finds the binding associated to the given symbol.
LookupScope *lookupType(Symbol *symbol, LookupScope *enclosingBinding = 0); ClassOrNamespace *lookupType(Symbol *symbol, ClassOrNamespace *enclosingBinding = 0);
LookupScope *lookupType(const QList<const Name *> &path, LookupScope *enclosingBinding = 0); ClassOrNamespace *lookupType(const QList<const Name *> &path,
ClassOrNamespace *enclosingBinding = 0);
/// Returns the Control that must be used to create temporary symbols. /// Returns the Control that must be used to create temporary symbols.
/// \internal /// \internal
QSharedPointer<Control> control() const QSharedPointer<Control> control() const
{ return _control; } { 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 bool expandTemplates() const
{ return _expandTemplates; } { return _expandTemplates; }
void setExpandTemplates(bool expandTemplates) void setExpandTemplates(bool expandTemplates)
@@ -140,36 +219,28 @@ public:
/// Store the result in \a results. /// Store the result in \a results.
/// \internal /// \internal
void lookupInScope(const Name *name, Scope *scope, QList<LookupItem> *result, 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. /// Create bindings for the symbols reachable from \a rootSymbol.
/// \internal /// \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 /// \internal
LookupScope *allocLookupScope(LookupScope *parent, const Name *name); ClassOrNamespace *allocClassOrNamespace(ClassOrNamespace *parent);
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);
protected: protected:
using SymbolVisitor::visit; using SymbolVisitor::visit;
/// Change the current LookupScope binding. /// Change the current ClassOrNamespace binding.
LookupScope *switchCurrentLookupScope(LookupScope *lookupScope); ClassOrNamespace *switchCurrentClassOrNamespace(ClassOrNamespace *classOrNamespace);
/// Enters the LookupScope binding associated with the given \a symbol. /// Enters the ClassOrNamespace binding associated with the given \a symbol.
LookupScope *enterLookupScopeBinding(Symbol *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. /// namespace binding.
LookupScope *enterGlobalLookupScope(Symbol *symbol); ClassOrNamespace *enterGlobalClassOrNamespace(Symbol *symbol);
/// Creates bindings for the given \a document. /// Creates bindings for the given \a document.
void process(Document::Ptr document); void process(Document::Ptr document);
@@ -178,7 +249,6 @@ protected:
void process(Symbol *root); void process(Symbol *root);
virtual bool visit(Template *templ); virtual bool visit(Template *templ);
virtual bool visit(ExplicitInstantiation *inst);
virtual bool visit(Namespace *ns); virtual bool visit(Namespace *ns);
virtual bool visit(Class *klass); virtual bool visit(Class *klass);
virtual bool visit(ForwardClassDeclaration *klass); virtual bool visit(ForwardClassDeclaration *klass);
@@ -201,15 +271,16 @@ protected:
virtual bool visit(ObjCMethod *); virtual bool visit(ObjCMethod *);
private: private:
Symbol *instantiateTemplateFunction(const TemplateNameId *instantiation,
Template *specialization) const;
Snapshot _snapshot; Snapshot _snapshot;
QSharedPointer<Control> _control; QSharedPointer<Control> _control;
QList<Document::Ptr> _expressionDocuments;
QSet<Namespace *> _processed; QSet<Namespace *> _processed;
QList<LookupScope *> _entities; QList<ClassOrNamespace *> _entities;
LookupScope *_globalNamespace; ClassOrNamespace *_globalNamespace;
LookupScope *_currentLookupScope; ClassOrNamespace *_currentClassOrNamespace;
bool _expandTemplates; bool _expandTemplates;
int _depth;
}; };
class CPLUSPLUS_EXPORT LookupContext class CPLUSPLUS_EXPORT LookupContext
@@ -223,7 +294,7 @@ public:
LookupContext(Document::Ptr expressionDocument, LookupContext(Document::Ptr expressionDocument,
Document::Ptr thisDocument, Document::Ptr thisDocument,
const Snapshot &snapshot, const Snapshot &snapshot,
CreateBindings::Ptr bindings = CreateBindings::Ptr()); QSharedPointer<CreateBindings> bindings = QSharedPointer<CreateBindings>());
LookupContext(const LookupContext &other); LookupContext(const LookupContext &other);
LookupContext &operator = (const LookupContext &other); LookupContext &operator = (const LookupContext &other);
@@ -233,25 +304,25 @@ public:
Document::Ptr document(const QString &fileName) const; Document::Ptr document(const QString &fileName) const;
Snapshot snapshot() const; Snapshot snapshot() const;
LookupScope *globalNamespace() const; ClassOrNamespace *globalNamespace() const;
QList<LookupItem> lookup(const Name *name, Scope *scope) const; QList<LookupItem> lookup(const Name *name, Scope *scope) const;
LookupScope *lookupType(const Name *name, Scope *scope, ClassOrNamespace *lookupType(const Name *name, Scope *scope,
LookupScope *enclosingBinding = 0, ClassOrNamespace *enclosingBinding = 0,
QSet<const Declaration *> typedefsBeingResolved QSet<const Declaration *> typedefsBeingResolved
= QSet<const Declaration *>()) const; = QSet<const Declaration *>()) const;
LookupScope *lookupType(Symbol *symbol, ClassOrNamespace *lookupType(Symbol *symbol,
LookupScope *enclosingBinding = 0) const; ClassOrNamespace *enclosingBinding = 0) const;
LookupScope *lookupParent(Symbol *symbol) const; ClassOrNamespace *lookupParent(Symbol *symbol) const;
/// \internal /// \internal
CreateBindings::Ptr bindings() const QSharedPointer<CreateBindings> bindings() const
{ return _bindings; } { return _bindings; }
static QList<const Name *> fullyQualifiedName(Symbol *symbol); static QList<const Name *> fullyQualifiedName(Symbol *symbol);
static QList<const Name *> path(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) void setExpandTemplates(bool expandTemplates)
{ {
@@ -261,7 +332,7 @@ public:
} }
private: private:
QList<LookupItem> lookupByUsing(const Name *name, LookupScope *bindingScope) const; QList<LookupItem> lookupByUsing(const Name *name, ClassOrNamespace *bindingScope) const;
// The current expression. // The current expression.
Document::Ptr _expressionDocument; Document::Ptr _expressionDocument;
@@ -273,7 +344,7 @@ private:
Snapshot _snapshot; Snapshot _snapshot;
// Bindings // Bindings
CreateBindings::Ptr _bindings; QSharedPointer<CreateBindings> _bindings;
bool m_expandTemplates; bool m_expandTemplates;
}; };

View File

@@ -77,10 +77,10 @@ Scope *LookupItem::scope() const
void LookupItem::setScope(Scope *scope) void LookupItem::setScope(Scope *scope)
{ _scope = scope; } { _scope = scope; }
LookupScope *LookupItem::binding() const ClassOrNamespace *LookupItem::binding() const
{ return _binding; } { return _binding; }
void LookupItem::setBinding(LookupScope *binding) void LookupItem::setBinding(ClassOrNamespace *binding)
{ _binding = binding; } { _binding = binding; }
bool LookupItem::operator == (const LookupItem &other) const bool LookupItem::operator == (const LookupItem &other) const

View File

@@ -37,7 +37,7 @@
namespace CPlusPlus { namespace CPlusPlus {
class LookupScope; class ClassOrNamespace;
class CPLUSPLUS_EXPORT LookupItem class CPLUSPLUS_EXPORT LookupItem
{ {
@@ -63,8 +63,8 @@ public:
/// Sets this item's scope. /// Sets this item's scope.
void setScope(Scope *scope); void setScope(Scope *scope);
LookupScope *binding() const; ClassOrNamespace *binding() const;
void setBinding(LookupScope *binding); void setBinding(ClassOrNamespace *binding);
bool operator == (const LookupItem &other) const; bool operator == (const LookupItem &other) const;
bool operator != (const LookupItem &other) const; bool operator != (const LookupItem &other) const;
@@ -73,7 +73,7 @@ private:
FullySpecifiedType _type; FullySpecifiedType _type;
Scope *_scope; Scope *_scope;
Symbol *_declaration; Symbol *_declaration;
LookupScope *_binding; ClassOrNamespace *_binding;
}; };
uint qHash(const CPlusPlus::LookupItem &result); uint qHash(const CPlusPlus::LookupItem &result);

View File

@@ -32,9 +32,9 @@
#include "LookupContext.h" #include "LookupContext.h"
#include "Overview.h" #include "Overview.h"
#include "DeprecatedGenTemplateInstance.h"
#include "CppRewriter.h" #include "CppRewriter.h"
#include "TypeOfExpression.h" #include "TypeOfExpression.h"
#include "TypeResolver.h"
#include <cplusplus/Control.h> #include <cplusplus/Control.h>
#include <cplusplus/AST.h> #include <cplusplus/AST.h>
@@ -75,6 +75,131 @@ static QList<T> removeDuplicates(const QList<T> &results)
return uniqueList; 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, static int evaluateFunctionArgument(const FullySpecifiedType &actualTy,
const FullySpecifiedType &formalTy) const FullySpecifiedType &formalTy)
{ {
@@ -176,7 +301,7 @@ void ResolveExpression::addResults(const QList<LookupItem> &items)
} }
void ResolveExpression::addResult(const FullySpecifiedType &ty, Scope *scope, void ResolveExpression::addResult(const FullySpecifiedType &ty, Scope *scope,
LookupScope *binding) ClassOrNamespace *binding)
{ {
LookupItem item; LookupItem item;
item.setType(ty); item.setType(ty);
@@ -206,7 +331,7 @@ bool ResolveExpression::visit(BinaryExpressionAST *ast)
if (d->core_declarator) { if (d->core_declarator) {
if (DeclaratorIdAST *declaratorId = d->core_declarator->asDeclaratorId()) { if (DeclaratorIdAST *declaratorId = d->core_declarator->asDeclaratorId()) {
if (NameAST *nameAST = declaratorId->name) { if (NameAST *nameAST = declaratorId->name) {
if (LookupScope *binding = baseExpression(_results, T_ARROW)) { if (ClassOrNamespace *binding = baseExpression(_results, T_ARROW)) {
_results.clear(); _results.clear();
addResults(binding->lookup(nameAST->name)); addResults(binding->lookup(nameAST->name));
} }
@@ -487,14 +612,15 @@ bool ResolveExpression::visit(UnaryExpressionAST *ast)
added = true; added = true;
} else if (namedTy != 0) { } else if (namedTy != 0) {
const Name *starOp = control()->operatorNameId(OperatorNameId::StarOp); 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)) { foreach (const LookupItem &r, b->find(starOp)) {
Symbol *overload = r.declaration(); Symbol *overload = r.declaration();
if (Function *funTy = overload->type()->asFunctionType()) { if (Function *funTy = overload->type()->asFunctionType()) {
if (maybeValidPrototype(funTy, 0)) { if (maybeValidPrototype(funTy, 0)) {
FullySpecifiedType retTy = funTy->returnType().simplified(); if (Function *proto = instantiate(b->templateId(), funTy)->asFunctionType()) {
FullySpecifiedType retTy = proto->returnType().simplified();
p.setType(retTy); p.setType(retTy);
p.setScope(funTy->enclosingScope()); p.setScope(proto->enclosingScope());
it.setValue(p); it.setValue(p);
added = true; added = true;
break; break;
@@ -503,6 +629,7 @@ bool ResolveExpression::visit(UnaryExpressionAST *ast)
} }
} }
} }
}
if (!added) if (!added)
it.remove(); it.remove();
} }
@@ -526,6 +653,48 @@ bool ResolveExpression::visit(QualifiedNameAST *ast)
return false; 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) bool ResolveExpression::visit(SimpleNameAST *ast)
{ {
QList<LookupItem> candidates = _context.lookup(ast->name, _scope); QList<LookupItem> candidates = _context.lookup(ast->name, _scope);
@@ -539,7 +708,7 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
if (item.declaration() == 0) if (item.declaration() == 0)
continue; continue;
if (item.type().isAuto() || item.type().isDecltype()) { if (item.type().isAuto()) {
const Declaration *decl = item.declaration()->asDeclaration(); const Declaration *decl = item.declaration()->asDeclaration();
if (!decl) if (!decl)
continue; continue;
@@ -548,10 +717,53 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
if (_autoDeclarationsBeingResolved.contains(decl)) if (_autoDeclarationsBeingResolved.contains(decl))
continue; continue;
newCandidates += const StringLiteral *initializationString = decl->getInitializer();
TypeResolver::resolveDeclInitializer(*_context.bindings(), decl, if (initializationString == 0)
_autoDeclarationsBeingResolved << decl, continue;
ast->name->identifier());
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 { } else {
item.setType(item.declaration()->type()); item.setType(item.declaration()->type());
item.setScope(item.declaration()->enclosingScope()); item.setScope(item.declaration()->enclosingScope());
@@ -661,12 +873,14 @@ bool ResolveExpression::visit(CallAST *ast)
Scope *scope = result.scope(); Scope *scope = result.scope();
if (NamedType *namedTy = ty->asNamedType()) { 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)) { foreach (const LookupItem &r, b->find(functionCallOp)) {
Symbol *overload = r.declaration(); Symbol *overload = r.declaration();
if (Function *funTy = overload->type()->asFunctionType()) { if (Function *funTy = overload->type()->asFunctionType()) {
if (maybeValidPrototype(funTy, actualArgumentCount)) if (maybeValidPrototype(funTy, actualArgumentCount)) {
addResult(funTy->returnType().simplified(), scope); if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
addResult(proto->returnType().simplified(), scope);
}
} }
} }
} }
@@ -679,6 +893,14 @@ bool ResolveExpression::visit(CallAST *ast)
// Constructor call // Constructor call
FullySpecifiedType ctorTy = control()->namedType(classTy->name()); FullySpecifiedType ctorTy = control()->namedType(classTy->name());
addResult(ctorTy, scope); 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(); FullySpecifiedType ty = result.type().simplified();
Scope *scope = result.scope(); Scope *scope = result.scope();
TypeResolver typeResolver(*_context.bindings()); TypedefsResolver typedefsResolver(_context);
typeResolver.resolve(&ty, &scope, result.binding()); typedefsResolver.resolve(&ty, &scope, result.binding());
if (PointerType *ptrTy = ty->asPointerType()) { if (PointerType *ptrTy = ty->asPointerType()) {
addResult(ptrTy->elementType().simplified(), scope); addResult(ptrTy->elementType().simplified(), scope);
@@ -704,12 +926,13 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
addResult(arrTy->elementType().simplified(), scope); addResult(arrTy->elementType().simplified(), scope);
} else if (NamedType *namedTy = ty->asNamedType()) { } 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)) { foreach (const LookupItem &r, b->find(arrayAccessOp)) {
Symbol *overload = r.declaration(); Symbol *overload = r.declaration();
if (Function *funTy = overload->type()->asFunctionType()) { if (Function *funTy = overload->type()->asFunctionType()) {
if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType())
// ### TODO: check the actual arguments // ### TODO: check the actual arguments
addResult(funTy->returnType().simplified(), scope); addResult(proto->returnType().simplified(), scope);
} }
} }
@@ -719,7 +942,7 @@ bool ResolveExpression::visit(ArrayAccessAST *ast)
return false; 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(binding);
Q_UNUSED(memberName); Q_UNUSED(memberName);
@@ -788,17 +1011,17 @@ bool ResolveExpression::visit(MemberAccessAST *ast)
// Remember the access operator. // Remember the access operator.
const int accessOp = tokenKind(ast->access_token); const int accessOp = tokenKind(ast->access_token);
if (LookupScope *binding = baseExpression(baseResults, accessOp)) if (ClassOrNamespace *binding = baseExpression(baseResults, accessOp))
addResults(binding->find(memberName)); addResults(binding->find(memberName));
return false; return false;
} }
LookupScope *ResolveExpression::findClass(const FullySpecifiedType &originalTy, Scope *scope, ClassOrNamespace *ResolveExpression::findClass(const FullySpecifiedType &originalTy, Scope *scope,
LookupScope *enclosingBinding) const ClassOrNamespace *enclosingBinding) const
{ {
FullySpecifiedType ty = originalTy.simplified(); FullySpecifiedType ty = originalTy.simplified();
LookupScope *binding = 0; ClassOrNamespace *binding = 0;
if (Class *klass = ty->asClassType()) { if (Class *klass = ty->asClassType()) {
if (scope->isBlock()) if (scope->isBlock())
@@ -816,14 +1039,15 @@ LookupScope *ResolveExpression::findClass(const FullySpecifiedType &originalTy,
return binding; return binding;
} }
LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResults, ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &baseResults,
int accessOp, int accessOp,
bool *replacedDotOperator) const bool *replacedDotOperator) const
{ {
if (Q_UNLIKELY(debug)) if (Q_UNLIKELY(debug))
qDebug() << "In ResolveExpression::baseExpression with" << baseResults.size() << "results..."; qDebug() << "In ResolveExpression::baseExpression with" << baseResults.size() << "results...";
int i = 0; int i = 0;
TypeResolver typeResolver(*_context.bindings()); Overview oo;
TypedefsResolver typedefsResolver(_context);
foreach (const LookupItem &r, baseResults) { foreach (const LookupItem &r, baseResults) {
if (!r.type().type() || !r.scope()) if (!r.type().type() || !r.scope())
@@ -832,18 +1056,36 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu
FullySpecifiedType originalType = ty; FullySpecifiedType originalType = ty;
Scope *scope = r.scope(); Scope *scope = r.scope();
if (Q_UNLIKELY(debug)) if (Q_UNLIKELY(debug)) {
qDebug("trying result #%d", ++i); qDebug("trying result #%d", ++i);
qDebug() << "- before typedef resolving we have:" << oo(ty);
}
typeResolver.resolve(&ty, &scope, r.binding()); typedefsResolver.resolve(&ty, &scope, r.binding());
if (Q_UNLIKELY(debug))
qDebug() << "- after typedef resolving:" << oo(ty);
if (accessOp == T_ARROW) { if (accessOp == T_ARROW) {
if (PointerType *ptrTy = ty->asPointerType()) { if (PointerType *ptrTy = ty->asPointerType()) {
FullySpecifiedType type = ptrTy->elementType(); 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; return binding;
} else if (LookupScope *binding = findClass(ty, scope, r.binding())) { } else {
ClassOrNamespace *binding
= findClassForTemplateParameterInExpressionScope(r.binding(),
ty);
if (! binding)
binding = findClass(ty, scope, r.binding());
if (binding){
// lookup for overloads of operator-> // lookup for overloads of operator->
const OperatorNameId *arrowOp const OperatorNameId *arrowOp
@@ -854,10 +1096,16 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu
continue; continue;
Scope *functionScope = overload->enclosingScope(); Scope *functionScope = overload->enclosingScope();
if (Function *funTy = overload->type()->asFunctionType()) { if (overload->type()->isFunctionType()) {
FullySpecifiedType retTy = funTy->returnType().simplified(); FullySpecifiedType overloadTy
= instantiate(binding->templateId(), overload);
Function *instantiatedFunction = overloadTy->asFunctionType();
Q_ASSERT(instantiatedFunction != 0);
typeResolver.resolve(&retTy, &functionScope, r.binding()); FullySpecifiedType retTy
= instantiatedFunction->returnType().simplified();
typedefsResolver.resolve(&retTy, &functionScope, r.binding());
if (! retTy->isPointerType() && ! retTy->isNamedType()) if (! retTy->isPointerType() && ! retTy->isNamedType())
continue; continue;
@@ -865,20 +1113,20 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu
if (PointerType *ptrTy = retTy->asPointerType()) if (PointerType *ptrTy = retTy->asPointerType())
retTy = ptrTy->elementType(); retTy = ptrTy->elementType();
if (LookupScope *retBinding = findClass(retTy, functionScope)) if (ClassOrNamespace *retBinding = findClass(retTy, functionScope))
return retBinding; return retBinding;
if (scope != functionScope) { if (scope != functionScope) {
if (LookupScope *retBinding = findClass(retTy, scope)) if (ClassOrNamespace *retBinding = findClass(retTy, scope))
return retBinding; return retBinding;
} }
if (LookupScope *origin = binding->instantiationOrigin()) { if (ClassOrNamespace *origin = binding->instantiationOrigin()) {
foreach (Symbol *originSymbol, origin->symbols()) { foreach (Symbol *originSymbol, origin->symbols()) {
Scope *originScope = originSymbol->asScope(); Scope *originScope = originSymbol->asScope();
if (originScope && originScope != scope if (originScope && originScope != scope
&& originScope != functionScope) { && originScope != functionScope) {
if (LookupScope *retBinding if (ClassOrNamespace *retBinding
= findClass(retTy, originScope)) = findClass(retTy, originScope))
return retBinding; return retBinding;
} }
@@ -887,6 +1135,7 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu
} }
} }
} }
}
} else if (accessOp == T_DOT) { } else if (accessOp == T_DOT) {
if (replacedDotOperator) { if (replacedDotOperator) {
*replacedDotOperator = originalType->isPointerType() || ty->isPointerType(); *replacedDotOperator = originalType->isPointerType() || ty->isPointerType();
@@ -894,13 +1143,19 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu
ty = ptrTy->elementType(); ty = ptrTy->elementType();
} }
LookupScope *enclosingBinding = 0; if (ClassOrNamespace *binding
if (LookupScope *binding = r.binding()) { = findClassForTemplateParameterInExpressionScope(r.binding(),
ty)) {
return binding;
}
ClassOrNamespace *enclosingBinding = 0;
if (ClassOrNamespace *binding = r.binding()) {
if (binding->instantiationOrigin()) if (binding->instantiationOrigin())
enclosingBinding = binding; enclosingBinding = binding;
} }
if (LookupScope *binding = findClass(ty, scope, enclosingBinding)) if (ClassOrNamespace *binding = findClass(ty, scope, enclosingBinding))
return binding; return binding;
} }
} }
@@ -908,6 +1163,30 @@ LookupScope *ResolveExpression::baseExpression(const QList<LookupItem> &baseResu
return 0; 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) bool ResolveExpression::visit(PostIncrDecrAST *ast)
{ {
const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope); const QList<LookupItem> baseResults = resolve(ast->base_expression, _scope);
@@ -921,7 +1200,7 @@ bool ResolveExpression::visit(ObjCMessageExpressionAST *ast)
foreach (const LookupItem &result, receiverResults) { foreach (const LookupItem &result, receiverResults) {
FullySpecifiedType ty = result.type().simplified(); FullySpecifiedType ty = result.type().simplified();
LookupScope *binding = 0; ClassOrNamespace *binding = 0;
if (ObjCClass *clazz = ty->asObjCClassType()) { if (ObjCClass *clazz = ty->asObjCClassType()) {
// static access, e.g.: // static access, e.g.:

View File

@@ -53,25 +53,26 @@ public:
QList<LookupItem> resolve(ExpressionAST *ast, Scope *scope, bool ref = false); QList<LookupItem> resolve(ExpressionAST *ast, Scope *scope, bool ref = false);
QList<LookupItem> reference(ExpressionAST *ast, Scope *scope); QList<LookupItem> reference(ExpressionAST *ast, Scope *scope);
LookupScope *baseExpression(const QList<LookupItem> &baseResults, ClassOrNamespace *baseExpression(const QList<LookupItem> &baseResults,
int accessOp, int accessOp,
bool *replacedDotOperator = 0) const; bool *replacedDotOperator = 0) const;
const LookupContext &context() const; const LookupContext &context() const;
protected: protected:
LookupScope *findClass(const FullySpecifiedType &ty, Scope *scope, ClassOrNamespace *findClass(const FullySpecifiedType &ty, Scope *scope,
LookupScope *enclosingBinding = 0) const; ClassOrNamespace *enclosingBinding = 0) const;
QList<LookupItem> expression(ExpressionAST *ast); QList<LookupItem> expression(ExpressionAST *ast);
QList<LookupItem> switchResults(const QList<LookupItem> &symbols); 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 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<Symbol *> &symbols);
void addResults(const QList<LookupItem> &items); void addResults(const QList<LookupItem> &items);
@@ -125,6 +126,10 @@ protected:
private: private:
ClassOrNamespace *findClassForTemplateParameterInExpressionScope(
ClassOrNamespace *resultBinding,
const FullySpecifiedType &ty) const;
Scope *_scope; Scope *_scope;
const LookupContext& _context; const LookupContext& _context;
Bind bind; Bind bind;

View File

@@ -50,7 +50,7 @@ TypeOfExpression::TypeOfExpression():
} }
void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot, void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot,
CreateBindings::Ptr bindings, QSharedPointer<CreateBindings> bindings,
const QSet<const Declaration *> &autoDeclarationsBeingResolved) const QSet<const Declaration *> &autoDeclarationsBeingResolved)
{ {
m_thisDocument = thisDocument; m_thisDocument = thisDocument;
@@ -62,7 +62,7 @@ void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot
Q_ASSERT(m_bindings.isNull()); Q_ASSERT(m_bindings.isNull());
m_bindings = bindings; m_bindings = bindings;
if (m_bindings.isNull()) if (m_bindings.isNull())
m_bindings = CreateBindings::Ptr(new CreateBindings(thisDocument, snapshot)); m_bindings = QSharedPointer<CreateBindings>(new CreateBindings(thisDocument, snapshot));
m_environment.clear(); m_environment.clear();
m_autoDeclarationsBeingResolved = autoDeclarationsBeingResolved; m_autoDeclarationsBeingResolved = autoDeclarationsBeingResolved;
@@ -105,7 +105,7 @@ QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression,
m_scope = scope; m_scope = scope;
m_bindings->addExpressionDocument(document); m_documents.append(document);
m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot, m_bindings); m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot, m_bindings);
Q_ASSERT(!m_bindings.isNull()); Q_ASSERT(!m_bindings.isNull());
m_lookupContext.setExpandTemplates(m_expandTemplates); m_lookupContext.setExpandTemplates(m_expandTemplates);
@@ -122,7 +122,7 @@ QList<LookupItem> TypeOfExpression::reference(ExpressionAST *expression,
m_scope = scope; m_scope = scope;
m_bindings->addExpressionDocument(document); m_documents.append(document);
m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot, m_bindings); m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot, m_bindings);
Q_ASSERT(!m_bindings.isNull()); Q_ASSERT(!m_bindings.isNull());
m_lookupContext.setExpandTemplates(m_expandTemplates); m_lookupContext.setExpandTemplates(m_expandTemplates);

View File

@@ -62,7 +62,7 @@ public:
*/ */
void init(Document::Ptr thisDocument, void init(Document::Ptr thisDocument,
const Snapshot &snapshot, const Snapshot &snapshot,
CreateBindings::Ptr bindings = CreateBindings::Ptr(), QSharedPointer<CreateBindings> bindings = QSharedPointer<CreateBindings>(),
const QSet<const Declaration *> &autoDeclarationsBeingResolved const QSet<const Declaration *> &autoDeclarationsBeingResolved
= QSet<const Declaration *>()); = QSet<const Declaration *>());
@@ -135,6 +135,7 @@ public:
} }
private: private:
void processEnvironment(Document::Ptr doc, Environment *env, void processEnvironment(Document::Ptr doc, Environment *env,
QSet<QString> *processed) const; QSet<QString> *processed) const;
@@ -142,13 +143,20 @@ private:
private: private:
Document::Ptr m_thisDocument; Document::Ptr m_thisDocument;
Snapshot m_snapshot; Snapshot m_snapshot;
CreateBindings::Ptr m_bindings; QSharedPointer<CreateBindings> m_bindings;
ExpressionAST *m_ast; ExpressionAST *m_ast;
Scope *m_scope; Scope *m_scope;
LookupContext m_lookupContext; LookupContext m_lookupContext;
mutable QSharedPointer<Environment> m_environment; mutable QSharedPointer<Environment> m_environment;
QSet<const Declaration *> m_autoDeclarationsBeingResolved;
bool m_expandTemplates; 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); ExpressionAST CPLUSPLUS_EXPORT *extractExpressionAST(Document::Ptr doc);

View File

@@ -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

View File

@@ -36,7 +36,6 @@ HEADERS += \
$$PWD/NamePrettyPrinter.h \ $$PWD/NamePrettyPrinter.h \
$$PWD/TypeOfExpression.h \ $$PWD/TypeOfExpression.h \
$$PWD/TypePrettyPrinter.h \ $$PWD/TypePrettyPrinter.h \
$$PWD/TypeResolver.h \
$$PWD/ResolveExpression.h \ $$PWD/ResolveExpression.h \
$$PWD/LookupItem.h \ $$PWD/LookupItem.h \
$$PWD/AlreadyConsideredClassContainer.h \ $$PWD/AlreadyConsideredClassContainer.h \
@@ -45,6 +44,7 @@ HEADERS += \
$$PWD/ASTPath.h \ $$PWD/ASTPath.h \
$$PWD/SnapshotSymbolVisitor.h \ $$PWD/SnapshotSymbolVisitor.h \
$$PWD/SymbolNameVisitor.h \ $$PWD/SymbolNameVisitor.h \
$$PWD/DeprecatedGenTemplateInstance.h \
$$PWD/FindUsages.h \ $$PWD/FindUsages.h \
$$PWD/DependencyTable.h \ $$PWD/DependencyTable.h \
$$PWD/PreprocessorClient.h \ $$PWD/PreprocessorClient.h \
@@ -67,7 +67,6 @@ SOURCES += \
$$PWD/NamePrettyPrinter.cpp \ $$PWD/NamePrettyPrinter.cpp \
$$PWD/TypeOfExpression.cpp \ $$PWD/TypeOfExpression.cpp \
$$PWD/TypePrettyPrinter.cpp \ $$PWD/TypePrettyPrinter.cpp \
$$PWD/TypeResolver.cpp \
$$PWD/ResolveExpression.cpp \ $$PWD/ResolveExpression.cpp \
$$PWD/LookupItem.cpp \ $$PWD/LookupItem.cpp \
$$PWD/LookupContext.cpp \ $$PWD/LookupContext.cpp \
@@ -75,6 +74,7 @@ SOURCES += \
$$PWD/ASTPath.cpp \ $$PWD/ASTPath.cpp \
$$PWD/SnapshotSymbolVisitor.cpp \ $$PWD/SnapshotSymbolVisitor.cpp \
$$PWD/SymbolNameVisitor.cpp \ $$PWD/SymbolNameVisitor.cpp \
$$PWD/DeprecatedGenTemplateInstance.cpp \
$$PWD/FindUsages.cpp \ $$PWD/FindUsages.cpp \
$$PWD/DependencyTable.cpp \ $$PWD/DependencyTable.cpp \
$$PWD/PreprocessorClient.cpp \ $$PWD/PreprocessorClient.cpp \

View File

@@ -96,6 +96,7 @@ QtcLibrary {
"CppRewriter.cpp", "CppRewriter.h", "CppRewriter.cpp", "CppRewriter.h",
"cppmodelmanagerbase.cpp", "cppmodelmanagerbase.h", "cppmodelmanagerbase.cpp", "cppmodelmanagerbase.h",
"DependencyTable.cpp", "DependencyTable.h", "DependencyTable.cpp", "DependencyTable.h",
"DeprecatedGenTemplateInstance.cpp", "DeprecatedGenTemplateInstance.h",
"ExpressionUnderCursor.cpp", "ExpressionUnderCursor.h", "ExpressionUnderCursor.cpp", "ExpressionUnderCursor.h",
"FastPreprocessor.cpp", "FastPreprocessor.h", "FastPreprocessor.cpp", "FastPreprocessor.h",
"FindUsages.cpp", "FindUsages.h", "FindUsages.cpp", "FindUsages.h",
@@ -116,7 +117,6 @@ QtcLibrary {
"SymbolNameVisitor.cpp", "SymbolNameVisitor.h", "SymbolNameVisitor.cpp", "SymbolNameVisitor.h",
"TypeOfExpression.cpp", "TypeOfExpression.h", "TypeOfExpression.cpp", "TypeOfExpression.h",
"TypePrettyPrinter.cpp", "TypePrettyPrinter.h", "TypePrettyPrinter.cpp", "TypePrettyPrinter.h",
"TypeResolver.cpp", "TypeResolver.h",
"cplusplus.qrc", "cplusplus.qrc",
"findcdbbreakpoint.cpp", "findcdbbreakpoint.h", "findcdbbreakpoint.cpp", "findcdbbreakpoint.h",
"pp-cctype.h", "pp-cctype.h",

View File

@@ -795,7 +795,7 @@ static void buildContextProperties(
Scope *typeScope = result.scope(); Scope *typeScope = result.scope();
if (!typeScope) if (!typeScope)
typeScope = scope; // incorrect but may be an ok fallback 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()) { if (binding && !binding->symbols().isEmpty()) {
// find the best 'Class' symbol // find the best 'Class' symbol
for (int i = binding->symbols().size() - 1; i >= 0; --i) { for (int i = binding->symbols().size() - 1; i >= 0; --i) {

View File

@@ -1453,9 +1453,10 @@ void CppQmlTypes::load(const QString &originId, const T &fakeMetaObjects, const
object->setPrototype(proto); object->setPrototype(proto);
} }
} }
// explicitly instantiate load for list and hash // explicitly instantiate load for list and hash
template void CppQmlTypes::load< QList<FakeMetaObject::ConstPtr> >(const QString &, const QList<FakeMetaObject::ConstPtr> &, const QString &); template QMLJS_EXPORT 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< QHash<QString, FakeMetaObject::ConstPtr> >(const QString &, const QHash<QString, FakeMetaObject::ConstPtr> &, const QString &);
QList<const CppComponentValue *> CppQmlTypes::createObjectsForImport(const QString &package, ComponentVersion version) QList<const CppComponentValue *> CppQmlTypes::createObjectsForImport(const QString &package, ComponentVersion version)
{ {

View File

@@ -158,6 +158,11 @@ bool Utf8String::endsWith(const Utf8String &text) const
return byteArray.endsWith(text.byteArray); return byteArray.endsWith(text.byteArray);
} }
bool Utf8String::isNull() const
{
return byteArray.isNull();
}
bool Utf8String::isEmpty() const bool Utf8String::isEmpty() const
{ {
return byteArray.isEmpty(); return byteArray.isEmpty();

View File

@@ -86,6 +86,7 @@ public:
bool startsWith(const char *text) const; bool startsWith(const char *text) const;
bool startsWith(char character) const; bool startsWith(char character) const;
bool endsWith(const Utf8String &text) const; bool endsWith(const Utf8String &text) const;
bool isNull() const;
bool isEmpty() const; bool isEmpty() const;
bool hasContent() const; bool hasContent() const;

View File

@@ -173,7 +173,7 @@ void SshKeyGenerator::generateOpenSslPublicKeyString(const KeyPtr &key)
void SshKeyGenerator::generateOpenSslPrivateKeyString(const KeyPtr &key) void SshKeyGenerator::generateOpenSslPrivateKeyString(const KeyPtr &key)
{ {
QList<BigInt> params; QList<BigInt> params;
const char *label; const char *label = "";
switch (m_type) { switch (m_type) {
case Rsa: { case Rsa: {
const QSharedPointer<RSA_PrivateKey> rsaKey const QSharedPointer<RSA_PrivateKey> rsaKey
@@ -197,6 +197,7 @@ void SshKeyGenerator::generateOpenSslPrivateKeyString(const KeyPtr &key)
case Ecdsa: case Ecdsa:
params << key.dynamicCast<ECDSA_PrivateKey>()->private_value(); params << key.dynamicCast<ECDSA_PrivateKey>()->private_value();
label = "EC PRIVATE KEY"; label = "EC PRIVATE KEY";
break;
} }
DER_Encoder encoder; DER_Encoder encoder;

View File

@@ -63,6 +63,7 @@ Item {
cursorShape: dragging ? Qt.ClosedHandCursor : Qt.OpenHandCursor cursorShape: dragging ? Qt.ClosedHandCursor : Qt.OpenHandCursor
drag.minimumY: dragging ? 0 : -dragOffset // Account for parent change below drag.minimumY: dragging ? 0 : -dragOffset // Account for parent change below
drag.maximumY: draggerParent.height - (dragging ? 0 : dragOffset) drag.maximumY: draggerParent.height - (dragging ? 0 : dragOffset)
drag.axis: Drag.YAxis
} }
DropArea { DropArea {

View File

@@ -102,7 +102,7 @@ Flickable {
draggerParent: categories draggerParent: categories
width: 150 width: 150
height: parent.height height: parent.height
dragOffset: parent.y dragOffset: loader.y
onDropped: { onDropped: {
categories.moveCategories(sourceIndex, targetIndex); categories.moveCategories(sourceIndex, targetIndex);

View File

@@ -250,6 +250,10 @@ PathChooser::PathChooser(QWidget *parent) :
PathChooser::~PathChooser() 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; delete d;
} }

View File

@@ -67,7 +67,7 @@ GdbServerProvider::GdbServerProvider(const QString &id)
} }
GdbServerProvider::GdbServerProvider(const GdbServerProvider &other) GdbServerProvider::GdbServerProvider(const GdbServerProvider &other)
: m_id(other.m_id) : m_id(createId(other.m_id))
, m_startupMode(other.m_startupMode) , m_startupMode(other.m_startupMode)
, m_initCommands(other.m_initCommands) , m_initCommands(other.m_initCommands)
, m_resetCommands(other.m_resetCommands) , m_resetCommands(other.m_resetCommands)

View File

@@ -41,6 +41,8 @@
#include <cpptools/cppprojects.h> #include <cpptools/cppprojects.h>
#include <cpptools/cppworkingcopy.h> #include <cpptools/cppworkingcopy.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QDir> #include <QDir>
@@ -122,7 +124,7 @@ public:
optionsBuilder.addToolchainAndProjectDefines(); optionsBuilder.addToolchainAndProjectDefines();
optionsBuilder.addResourceDirOptions(); optionsBuilder.addPredefinedMacrosAndHeaderPathsOptions();
optionsBuilder.addWrappedQtHeadersIncludePath(); optionsBuilder.addWrappedQtHeadersIncludePath();
optionsBuilder.addHeaderPathOptions(); optionsBuilder.addHeaderPathOptions();
optionsBuilder.addProjectConfigFileInclude(); optionsBuilder.addProjectConfigFileInclude();
@@ -154,7 +156,21 @@ private:
return false; 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(); static const QString resourceDir = getResourceDir();
if (!resourceDir.isEmpty()) { if (!resourceDir.isEmpty()) {

View File

@@ -387,7 +387,7 @@ void CppEditorWidget::switchDeclarationDefinition(bool inNextSplit)
} else if (functionDefinitionSymbol) { } else if (functionDefinitionSymbol) {
const Snapshot snapshot = d->m_modelManager->snapshot(); const Snapshot snapshot = d->m_modelManager->snapshot();
LookupContext context(d->m_lastSemanticInfo.doc, 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(), const QList<LookupItem> declarations = context.lookup(functionDefinitionSymbol->name(),
functionDefinitionSymbol->enclosingScope()); functionDefinitionSymbol->enclosingScope());

View File

@@ -331,10 +331,10 @@ bool CppClass::operator==(const CppClass &other)
void CppClass::lookupBases(Symbol *declaration, const LookupContext &context) void CppClass::lookupBases(Symbol *declaration, const LookupContext &context)
{ {
typedef QPair<LookupScope *, CppClass *> Data; typedef QPair<ClassOrNamespace *, CppClass *> Data;
if (LookupScope *clazz = context.lookupType(declaration)) { if (ClassOrNamespace *clazz = context.lookupType(declaration)) {
QSet<LookupScope *> visited; QSet<ClassOrNamespace *> visited;
QQueue<Data> q; QQueue<Data> q;
q.enqueue(qMakePair(clazz, this)); q.enqueue(qMakePair(clazz, this));
@@ -342,8 +342,8 @@ void CppClass::lookupBases(Symbol *declaration, const LookupContext &context)
Data current = q.dequeue(); Data current = q.dequeue();
clazz = current.first; clazz = current.first;
visited.insert(clazz); visited.insert(clazz);
const QList<LookupScope *> &bases = clazz->usings(); const QList<ClassOrNamespace *> &bases = clazz->usings();
foreach (LookupScope *baseClass, bases) { foreach (ClassOrNamespace *baseClass, bases) {
const QList<Symbol *> &symbols = baseClass->symbols(); const QList<Symbol *> &symbols = baseClass->symbols();
foreach (Symbol *symbol, symbols) { foreach (Symbol *symbol, symbols) {
if (symbol->isClass() && ( if (symbol->isClass() && (
@@ -433,7 +433,7 @@ CppVariable::CppVariable(Symbol *declaration, const LookupContext &context, Scop
} }
if (typeName) { if (typeName) {
if (LookupScope *clazz = context.lookupType(typeName, scope)) { if (ClassOrNamespace *clazz = context.lookupType(typeName, scope)) {
if (!clazz->symbols().isEmpty()) { if (!clazz->symbols().isEmpty()) {
Overview overview; Overview overview;
Symbol *symbol = clazz->symbols().at(0); Symbol *symbol = clazz->symbols().at(0);

View File

@@ -38,7 +38,6 @@
#include <cplusplus/ExpressionUnderCursor.h> #include <cplusplus/ExpressionUnderCursor.h>
#include <cplusplus/ResolveExpression.h> #include <cplusplus/ResolveExpression.h>
#include <cplusplus/SimpleLexer.h> #include <cplusplus/SimpleLexer.h>
#include <cplusplus/Templates.h>
#include <cplusplus/TypeOfExpression.h> #include <cplusplus/TypeOfExpression.h>
#include <cpptools/cppmodelmanager.h> #include <cpptools/cppmodelmanager.h>
#include <cpptools/functionutils.h> #include <cpptools/functionutils.h>
@@ -184,7 +183,7 @@ Class *VirtualFunctionHelper::staticClassOfFunctionCallExpression_internal() con
const QList<LookupItem> items = m_typeOfExpression(memberAccessAST->base_expression, const QList<LookupItem> items = m_typeOfExpression(memberAccessAST->base_expression,
m_expressionDocument, m_scope); m_expressionDocument, m_scope);
ResolveExpression resolveExpression(m_typeOfExpression.context()); ResolveExpression resolveExpression(m_typeOfExpression.context());
LookupScope *binding = resolveExpression.baseExpression(items, m_accessTokenKind); ClassOrNamespace *binding = resolveExpression.baseExpression(items, m_accessTokenKind);
if (binding) { if (binding) {
if (Class *klass = binding->rootClass()) { if (Class *klass = binding->rootClass()) {
result = klass; result = klass;

View File

@@ -607,7 +607,7 @@ ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targetOffse
SubstitutionEnvironment env; SubstitutionEnvironment env;
env.setContext(sourceContext); env.setContext(sourceContext);
env.switchScope(sourceFunction->enclosingScope()); env.switchScope(sourceFunction->enclosingScope());
LookupScope *targetCoN = targetContext.lookupType(targetFunction->enclosingScope()); ClassOrNamespace *targetCoN = targetContext.lookupType(targetFunction->enclosingScope());
if (!targetCoN) if (!targetCoN)
targetCoN = targetContext.globalNamespace(); targetCoN = targetContext.globalNamespace();
UseMinimalNames q(targetCoN); UseMinimalNames q(targetCoN);
@@ -653,7 +653,7 @@ ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targetOffse
SubstitutionEnvironment env; SubstitutionEnvironment env;
env.setContext(sourceContext); env.setContext(sourceContext);
env.switchScope(sourceFunction); env.switchScope(sourceFunction);
LookupScope *targetCoN = targetContext.lookupType(targetFunction); ClassOrNamespace *targetCoN = targetContext.lookupType(targetFunction);
if (!targetCoN) if (!targetCoN)
targetCoN = targetContext.globalNamespace(); targetCoN = targetContext.globalNamespace();
UseMinimalNames q(targetCoN); UseMinimalNames q(targetCoN);

View File

@@ -567,15 +567,15 @@ public:
// Determine base classes // Determine base classes
QList<const Class *> baseClasses; QList<const Class *> baseClasses;
QQueue<LookupScope *> baseClassQueue; QQueue<ClassOrNamespace *> baseClassQueue;
QSet<LookupScope *> visitedBaseClasses; QSet<ClassOrNamespace *> visitedBaseClasses;
if (LookupScope *clazz = interface.context().lookupType(m_classAST->symbol)) if (ClassOrNamespace *clazz = interface.context().lookupType(m_classAST->symbol))
baseClassQueue.enqueue(clazz); baseClassQueue.enqueue(clazz);
while (!baseClassQueue.isEmpty()) { while (!baseClassQueue.isEmpty()) {
LookupScope *clazz = baseClassQueue.dequeue(); ClassOrNamespace *clazz = baseClassQueue.dequeue();
visitedBaseClasses.insert(clazz); visitedBaseClasses.insert(clazz);
const QList<LookupScope *> bases = clazz->usings(); const QList<ClassOrNamespace *> bases = clazz->usings();
foreach (LookupScope *baseClass, bases) { foreach (ClassOrNamespace *baseClass, bases) {
foreach (Symbol *symbol, baseClass->symbols()) { foreach (Symbol *symbol, baseClass->symbols()) {
Class *base = symbol->asClass(); Class *base = symbol->asClass();
if (base if (base
@@ -769,7 +769,7 @@ public:
const LookupContext targetContext(headerFile->cppDocument(), snapshot()); const LookupContext targetContext(headerFile->cppDocument(), snapshot());
const Class *targetClass = m_classAST->symbol; const Class *targetClass = m_classAST->symbol;
LookupScope *targetCoN = targetContext.lookupType(targetClass->enclosingScope()); ClassOrNamespace *targetCoN = targetContext.lookupType(targetClass->enclosingScope());
if (!targetCoN) if (!targetCoN)
targetCoN = targetContext.globalNamespace(); targetCoN = targetContext.globalNamespace();
UseMinimalNames useMinimalNames(targetCoN); UseMinimalNames useMinimalNames(targetCoN);
@@ -866,7 +866,7 @@ public:
implementationDoc->translationUnit()->getPosition(insertPos, &line, &column); implementationDoc->translationUnit()->getPosition(insertPos, &line, &column);
Scope *targetScope = implementationDoc->scopeAt(line, column); Scope *targetScope = implementationDoc->scopeAt(line, column);
const LookupContext targetContext(implementationDoc, snapshot()); const LookupContext targetContext(implementationDoc, snapshot());
LookupScope *targetCoN = targetContext.lookupType(targetScope); ClassOrNamespace *targetCoN = targetContext.lookupType(targetScope);
if (!targetCoN) if (!targetCoN)
targetCoN = targetContext.globalNamespace(); targetCoN = targetContext.globalNamespace();

View File

@@ -219,7 +219,7 @@ Class *isMemberFunction(const LookupContext &context, Function *function)
if (!q->base()) if (!q->base())
return 0; return 0;
if (LookupScope *binding = context.lookupType(q->base(), enclosingScope)) { if (ClassOrNamespace *binding = context.lookupType(q->base(), enclosingScope)) {
foreach (Symbol *s, binding->symbols()) { foreach (Symbol *s, binding->symbols()) {
if (Class *matchingClass = s->asClass()) if (Class *matchingClass = s->asClass())
return matchingClass; return matchingClass;
@@ -257,7 +257,7 @@ Namespace *isNamespaceFunction(const LookupContext &context, Function *function)
if (!q->base()) if (!q->base())
return 0; return 0;
if (LookupScope *binding = context.lookupType(q->base(), enclosingScope)) { if (ClassOrNamespace *binding = context.lookupType(q->base(), enclosingScope)) {
foreach (Symbol *s, binding->symbols()) { foreach (Symbol *s, binding->symbols()) {
if (Namespace *matchingNamespace = s->asNamespace()) if (Namespace *matchingNamespace = s->asNamespace())
return matchingNamespace; return matchingNamespace;
@@ -1331,7 +1331,7 @@ void TranslateStringLiteral::match(const CppQuickFixInterface &interface,
for (int i = path.size() - 1; i >= 0; --i) { for (int i = path.size() - 1; i >= 0; --i) {
if (FunctionDefinitionAST *definition = path.at(i)->asFunctionDefinition()) { if (FunctionDefinitionAST *definition = path.at(i)->asFunctionDefinition()) {
Function *function = definition->symbol; Function *function = definition->symbol;
LookupScope *b = interface.context().lookupType(function); ClassOrNamespace *b = interface.context().lookupType(function);
if (b) { if (b) {
// Do we have a tr function? // Do we have a tr function?
foreach (const LookupItem &r, b->find(trName)) { foreach (const LookupItem &r, b->find(trName)) {
@@ -1592,7 +1592,7 @@ public:
SubstitutionEnvironment env; SubstitutionEnvironment env;
env.setContext(context()); env.setContext(context());
env.switchScope(result.first().scope()); env.switchScope(result.first().scope());
LookupScope *con = typeOfExpression.context().lookupType(scope); ClassOrNamespace *con = typeOfExpression.context().lookupType(scope);
if (!con) if (!con)
con = typeOfExpression.context().globalNamespace(); con = typeOfExpression.context().globalNamespace();
UseMinimalNames q(con); UseMinimalNames q(con);
@@ -2284,7 +2284,7 @@ Enum *findEnum(const QList<LookupItem> &results, const LookupContext &ctxt)
if (Enum *e = type->asEnumType()) if (Enum *e = type->asEnumType())
return e; return e;
if (const NamedType *namedType = type->asNamedType()) { 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 QList<Enum *> enums = con->unscopedEnums();
const Name *referenceName = namedType->name(); const Name *referenceName = namedType->name();
if (const QualifiedNameId *qualifiedName = referenceName->asQualifiedNameId()) if (const QualifiedNameId *qualifiedName = referenceName->asQualifiedNameId())
@@ -2581,7 +2581,7 @@ public:
Document::Ptr targetDoc = targetFile->cppDocument(); Document::Ptr targetDoc = targetFile->cppDocument();
Scope *targetScope = targetDoc->scopeAt(m_loc.line(), m_loc.column()); Scope *targetScope = targetDoc->scopeAt(m_loc.line(), m_loc.column());
LookupContext targetContext(targetDoc, snapshot()); LookupContext targetContext(targetDoc, snapshot());
LookupScope *targetCoN = targetContext.lookupType(targetScope); ClassOrNamespace *targetCoN = targetContext.lookupType(targetScope);
if (!targetCoN) if (!targetCoN)
targetCoN = targetContext.globalNamespace(); targetCoN = targetContext.globalNamespace();
@@ -3215,7 +3215,7 @@ public:
SubstitutionEnvironment env; SubstitutionEnvironment env;
env.setContext(context()); env.setContext(context());
env.switchScope(refFunc); env.switchScope(refFunc);
LookupScope *targetCoN = context().lookupType(refFunc->enclosingScope()); ClassOrNamespace *targetCoN = context().lookupType(refFunc->enclosingScope());
if (!targetCoN) if (!targetCoN)
targetCoN = context().globalNamespace(); targetCoN = context().globalNamespace();
UseMinimalNames subs(targetCoN); UseMinimalNames subs(targetCoN);
@@ -4644,7 +4644,7 @@ QString definitionSignature(const CppQuickFixInterface *assist,
QTC_ASSERT(func, return QString()); QTC_ASSERT(func, return QString());
LookupContext cppContext(targetFile->cppDocument(), assist->snapshot()); LookupContext cppContext(targetFile->cppDocument(), assist->snapshot());
LookupScope *cppCoN = cppContext.lookupType(scope); ClassOrNamespace *cppCoN = cppContext.lookupType(scope);
if (!cppCoN) if (!cppCoN)
cppCoN = cppContext.globalNamespace(); cppCoN = cppContext.globalNamespace();
SubstitutionEnvironment env; SubstitutionEnvironment env;
@@ -5125,7 +5125,7 @@ public:
SubstitutionEnvironment env; SubstitutionEnvironment env;
env.setContext(context()); env.setContext(context());
env.switchScope(result.first().scope()); env.switchScope(result.first().scope());
LookupScope *con = typeOfExpression.context().lookupType(scope); ClassOrNamespace *con = typeOfExpression.context().lookupType(scope);
if (!con) if (!con)
con = typeOfExpression.context().globalNamespace(); con = typeOfExpression.context().globalNamespace();
UseMinimalNames q(con); UseMinimalNames q(con);
@@ -5724,7 +5724,7 @@ PointerType *determineConvertedType(NamedType *namedType, const LookupContext &c
{ {
if (!namedType) if (!namedType)
return 0; 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 (Symbol *objectClassSymbol = skipForwardDeclarations(binding->symbols())) {
if (Class *klass = objectClassSymbol->asClass()) { if (Class *klass = objectClassSymbol->asClass()) {
for (auto it = klass->memberBegin(), end = klass->memberEnd(); it != end; ++it) { for (auto it = klass->memberBegin(), end = klass->memberEnd(); it != end; ++it) {
@@ -5782,7 +5782,7 @@ Class *senderOrReceiverClass(const CppQuickFixInterface &interface,
NamedType *objectType = objectTypeBase->asNamedType(); NamedType *objectType = objectTypeBase->asNamedType();
QTC_ASSERT(objectType, return 0); 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, return 0);
QTC_ASSERT(!objectClassCON->symbols().isEmpty(), return 0); QTC_ASSERT(!objectClassCON->symbols().isEmpty(), return 0);
@@ -5834,7 +5834,7 @@ bool findConnectReplacement(const CppQuickFixInterface &interface,
// Minimize qualification // Minimize qualification
Control *control = context.bindings()->control().data(); Control *control = context.bindings()->control().data();
LookupScope *functionCON = context.lookupParent(scope); ClassOrNamespace *functionCON = context.lookupParent(scope);
const Name *shortName = LookupContext::minimalName(method, functionCON, control); const Name *shortName = LookupContext::minimalName(method, functionCON, control);
if (!shortName->asQualifiedNameId()) if (!shortName->asQualifiedNameId())
shortName = control->qualifiedNameId(classOfMethod->name(), shortName); shortName = control->qualifiedNameId(classOfMethod->name(), shortName);

View File

@@ -152,8 +152,8 @@ public:
QTC_ASSERT(m_params.staticClass, return 0); QTC_ASSERT(m_params.staticClass, return 0);
QTC_ASSERT(!m_params.snapshot.isEmpty(), return 0); QTC_ASSERT(!m_params.snapshot.isEmpty(), return 0);
Class *functionsClass = m_finder.findMatchingClassDeclaration( Class *functionsClass = m_finder.findMatchingClassDeclaration(m_params.function,
m_params.function, m_params.snapshot, &m_params.typeOfExpression->context()); m_params.snapshot);
if (!functionsClass) if (!functionsClass)
return 0; return 0;

View File

@@ -972,20 +972,6 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_data()
"template<class $T>\n" "template<class $T>\n"
"using Foo = Bar<@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() void CppEditorPlugin::test_FollowSymbolUnderCursor()
@@ -1390,7 +1376,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_data()
"template <class T> struct A { virtual void virt() {} };\n" "template <class T> struct A { virtual void virt() {} };\n"
"void f(A<int> *l) { l->$@virt(); }\n") "void f(A<int> *l) { l->$@virt(); }\n")
<< (OverrideItemList() << (OverrideItemList()
<< OverrideItem(QLatin1String("A<int>::virt"), 1)); << OverrideItem(QLatin1String("A::virt"), 1));
/// Check: Static type is nicely resolved, especially for QSharedPointers. /// Check: Static type is nicely resolved, especially for QSharedPointers.
QTest::newRow("QSharedPointer") << _( QTest::newRow("QSharedPointer") << _(

View File

@@ -669,7 +669,7 @@ bool CheckSymbols::visit(NewExpressionAST *ast)
if (highlightCtorDtorAsType) { if (highlightCtorDtorAsType) {
accept(ast->new_type_id); accept(ast->new_type_id);
} else { } else {
LookupScope *binding = 0; ClassOrNamespace *binding = 0;
NameAST *nameAST = 0; NameAST *nameAST = 0;
if (ast->new_type_id) { if (ast->new_type_id) {
for (SpecifierListAST *it = ast->new_type_id->type_specifier_list; it; it = it->next) { 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; unsigned line, column;
getTokenStartPosition(name->firstToken(), &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()) { foreach (Symbol *s, b->symbols()) {
if (s->isNamespace()) if (s->isNamespace())
return; return;
@@ -768,14 +768,14 @@ bool CheckSymbols::hasVirtualDestructor(Class *klass) const
return false; return false;
} }
bool CheckSymbols::hasVirtualDestructor(LookupScope *binding) const bool CheckSymbols::hasVirtualDestructor(ClassOrNamespace *binding) const
{ {
QSet<LookupScope *> processed; QSet<ClassOrNamespace *> processed;
QList<LookupScope *> todo; QList<ClassOrNamespace *> todo;
todo.append(binding); todo.append(binding);
while (!todo.isEmpty()) { while (!todo.isEmpty()) {
LookupScope *b = todo.takeFirst(); ClassOrNamespace *b = todo.takeFirst();
if (b && !processed.contains(b)) { if (b && !processed.contains(b)) {
processed.insert(b); processed.insert(b);
foreach (Symbol *s, b->symbols()) { foreach (Symbol *s, b->symbols()) {
@@ -857,7 +857,7 @@ bool CheckSymbols::visit(QualifiedNameAST *ast)
{ {
if (ast->name) { if (ast->name) {
LookupScope *binding = checkNestedName(ast); ClassOrNamespace *binding = checkNestedName(ast);
if (binding && ast->unqualified_name) { if (binding && ast->unqualified_name) {
if (ast->unqualified_name->asDestructorName() != 0) { if (ast->unqualified_name->asDestructorName() != 0) {
@@ -886,9 +886,9 @@ bool CheckSymbols::visit(QualifiedNameAST *ast)
return false; return false;
} }
LookupScope *CheckSymbols::checkNestedName(QualifiedNameAST *ast) ClassOrNamespace *CheckSymbols::checkNestedName(QualifiedNameAST *ast)
{ {
LookupScope *binding = 0; ClassOrNamespace *binding = 0;
if (ast->name) { if (ast->name) {
if (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list) { if (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list) {
@@ -954,7 +954,7 @@ bool CheckSymbols::visit(MemInitializerAST *ast)
{ {
if (FunctionDefinitionAST *enclosingFunction = enclosingFunctionDefinition()) { if (FunctionDefinitionAST *enclosingFunction = enclosingFunctionDefinition()) {
if (ast->name && enclosingFunction->symbol) { if (ast->name && enclosingFunction->symbol) {
if (LookupScope *binding = _context.lookupType(enclosingFunction->symbol)) { if (ClassOrNamespace *binding = _context.lookupType(enclosingFunction->symbol)) {
foreach (Symbol *s, binding->symbols()) { foreach (Symbol *s, binding->symbols()) {
if (Class *klass = s->asClass()) { if (Class *klass = s->asClass()) {
NameAST *nameAST = ast->name; NameAST *nameAST = ast->name;
@@ -1157,7 +1157,7 @@ void CheckSymbols::addUse(const Result &use)
_usages.append(use); _usages.append(use);
} }
void CheckSymbols::addType(LookupScope *b, NameAST *ast) void CheckSymbols::addType(ClassOrNamespace *b, NameAST *ast)
{ {
unsigned startToken; unsigned startToken;
if (!b || !acceptName(ast, &startToken)) if (!b || !acceptName(ast, &startToken))
@@ -1296,8 +1296,12 @@ bool CheckSymbols::maybeAddFunction(const QList<LookupItem> &candidates, NameAST
isConstructor = isConstructorDeclaration(c); isConstructor = isConstructorDeclaration(c);
Function *funTy = c->type()->asFunctionType(); Function *funTy = c->type()->asFunctionType();
if (!funTy) // Template function has an overridden type if (!funTy) {
funTy = r.type()->asFunctionType(); //Try to find a template function
if (Template * t = r.type()->asTemplateType())
if ((c = t->declaration()))
funTy = c->type()->asFunctionType();
}
if (!funTy || funTy->isAmbiguous()) if (!funTy || funTy->isAmbiguous())
continue; // TODO: add diagnostic messages and color call-operators calls too? continue; // TODO: add diagnostic messages and color call-operators calls too?

View File

@@ -105,7 +105,7 @@ protected:
const QList<Result> &otherUses); const QList<Result> &otherUses);
bool hasVirtualDestructor(CPlusPlus::Class *klass) const; 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(unsigned line, unsigned column, const QString &text, unsigned length = 0);
bool warning(CPlusPlus::AST *ast, const QString &text); bool warning(CPlusPlus::AST *ast, const QString &text);
@@ -119,13 +119,13 @@ protected:
void checkNamespace(CPlusPlus::NameAST *name); void checkNamespace(CPlusPlus::NameAST *name);
void checkName(CPlusPlus::NameAST *ast, CPlusPlus::Scope *scope = 0); 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(const Result &use);
void addUse(unsigned tokenIndex, Kind kind); void addUse(unsigned tokenIndex, Kind kind);
void addUse(CPlusPlus::NameAST *name, 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, bool maybeAddTypeOrStatic(const QList<CPlusPlus::LookupItem> &candidates,
CPlusPlus::NameAST *ast); CPlusPlus::NameAST *ast);

View File

@@ -328,17 +328,16 @@ void CppToolsPlugin::test_completion()
actualCompletions.sort(); actualCompletions.sort();
expectedCompletions.sort(); expectedCompletions.sort();
QEXPECT_FAIL("template_as_base: typedef not available in derived", QEXPECT_FAIL("template_as_base: explicit typedef from base", "QTCREATORBUG-14218", Abort);
"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("enum_in_function_in_struct_in_function", "QTCREATORBUG-13757", 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_cxx11", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("enum_in_function_in_struct_in_function_anon", "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_cxx11", "QTCREATORBUG-13757", Abort);
QEXPECT_FAIL("enum_in_class_accessed_in_member_func_inline_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); QCOMPARE(actualCompletions, expectedCompletions);
} }
@@ -802,21 +801,6 @@ void CppToolsPlugin::test_completion_data()
<< QLatin1String("Data") << QLatin1String("Data")
<< QLatin1String("dataMember")); << 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") << _( QTest::newRow("use_global_identifier_as_base_class: derived as global and base as global") << _(
"struct Global\n" "struct Global\n"
"{\n" "{\n"
@@ -1327,29 +1311,22 @@ void CppToolsPlugin::test_completion_data()
<< QLatin1String("Template1")); << QLatin1String("Template1"));
QTest::newRow("template_specialization_with_pointer") << _( QTest::newRow("template_specialization_with_pointer") << _(
"template <typename T> struct Temp { T variable; };\n" "template <typename T>\n"
"template <typename T> struct Temp<T *> { T *pointer; };\n" "struct Template\n"
"void func()\n"
"{\n" "{\n"
" Temp<int*> templ;\n" " T variable;\n"
" @\n" "};\n"
"}" "template <typename T>\n"
"struct Template<T *>\n"
"{\n"
" T *pointer;\n"
"};\n"
"Template<int*> templ;\n"
"@\n"
) << _("templ.") << (QStringList() ) << _("templ.") << (QStringList()
<< QLatin1String("Temp") << QLatin1String("Template")
<< QLatin1String("pointer")); << 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"
"{\n"
" Temp<int&> templ;\n"
" @\n"
"}"
) << _("templ.") << (QStringList()
<< QLatin1String("Temp")
<< QLatin1String("reference"));
QTest::newRow("typedef_using_templates1") << _( QTest::newRow("typedef_using_templates1") << _(
"namespace NS1\n" "namespace NS1\n"
"{\n" "{\n"
@@ -1572,29 +1549,6 @@ void CppToolsPlugin::test_completion_data()
<< QLatin1String("C") << QLatin1String("C")
<< QLatin1String("m")); << 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") << _( QTest::newRow("instantiate_template_with_anonymous_class") << _(
"template <typename T>\n" "template <typename T>\n"
"struct S\n" "struct S\n"
@@ -2568,21 +2522,6 @@ void CppToolsPlugin::test_completion_data()
) << _("ar") << (QStringList() ) << _("ar") << (QStringList()
<< QLatin1String("arg1")); << 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") << _( QTest::newRow("default_arguments_for_class_templates_and_base_class_QTCREATORBUG-12605") << _(
"struct Foo { int foo; };\n" "struct Foo { int foo; };\n"
"template <typename T = Foo>\n" "template <typename T = Foo>\n"
@@ -2689,78 +2628,6 @@ void CppToolsPlugin::test_completion_data()
) << _("s.") << (QStringList() ) << _("s.") << (QStringList()
<< QLatin1String("S")); << 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") << _( QTest::newRow("auto_declaration_in_if_condition") << _(
"struct Foo { int bar; };\n" "struct Foo { int bar; };\n"
"void fun() {\n" "void fun() {\n"
@@ -2966,28 +2833,6 @@ void CppToolsPlugin::test_completion_data()
<< QLatin1String("Foo") << QLatin1String("Foo")
<< QLatin1String("bar")); << 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") << _( QTest::newRow("pointer_indirect_specialization_double_indirection_with_base") << _(
"template<typename _Tp>\n" "template<typename _Tp>\n"
"struct Traits { };\n" "struct Traits { };\n"
@@ -3024,337 +2869,6 @@ void CppToolsPlugin::test_completion_data()
) << _("t.p->") << (QStringList() ) << _("t.p->") << (QStringList()
<< QLatin1String("Foo") << QLatin1String("Foo")
<< QLatin1String("bar")); << 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() void CppToolsPlugin::test_completion_member_access_operator()

View File

@@ -753,7 +753,7 @@ bool canCompleteClassNameAt2ndOr4thConnectArgument(
|| eater.eatConnectOpenParenthesisExpressionCommaAmpersandExpressionComma(); || eater.eatConnectOpenParenthesisExpressionCommaAmpersandExpressionComma();
} }
LookupScope *lookupScopeFromLookupItem(const LookupItem &lookupItem, ClassOrNamespace *classOrNamespaceFromLookupItem(const LookupItem &lookupItem,
const LookupContext &context) const LookupContext &context)
{ {
const Name *name = 0; const Name *name = 0;
@@ -783,7 +783,7 @@ LookupScope *lookupScopeFromLookupItem(const LookupItem &lookupItem,
Class *classFromLookupItem(const LookupItem &lookupItem, const LookupContext &context) Class *classFromLookupItem(const LookupItem &lookupItem, const LookupContext &context)
{ {
LookupScope *b = lookupScopeFromLookupItem(lookupItem, context); ClassOrNamespace *b = classOrNamespaceFromLookupItem(lookupItem, context);
if (!b) if (!b)
return 0; return 0;
@@ -796,7 +796,7 @@ Class *classFromLookupItem(const LookupItem &lookupItem, const LookupContext &co
const Name *minimalName(Symbol *symbol, Scope *targetScope, const LookupContext &context) const Name *minimalName(Symbol *symbol, Scope *targetScope, const LookupContext &context)
{ {
LookupScope *target = context.lookupType(targetScope); ClassOrNamespace *target = context.lookupType(targetScope);
if (!target) if (!target)
target = context.globalNamespace(); target = context.globalNamespace();
return context.minimalName(symbol, target, context.bindings()->control().data()); return context.minimalName(symbol, target, context.bindings()->control().data());
@@ -1219,12 +1219,12 @@ bool InternalCppCompletionAssistProcessor::tryObjCCompletion()
ty = ty->asPointerType()->elementType().simplified(); ty = ty->asPointerType()->elementType().simplified();
if (NamedType *namedTy = ty->asNamedType()) { if (NamedType *namedTy = ty->asNamedType()) {
LookupScope *binding = lookupContext.lookupType(namedTy->name(), item.scope()); ClassOrNamespace *binding = lookupContext.lookupType(namedTy->name(), item.scope());
completeObjCMsgSend(binding, false); completeObjCMsgSend(binding, false);
} }
} else { } else {
if (ObjCClass *clazz = ty->asObjCClassType()) { if (ObjCClass *clazz = ty->asObjCClassType()) {
LookupScope *binding = lookupContext.lookupType(clazz->name(), item.scope()); ClassOrNamespace *binding = lookupContext.lookupType(clazz->name(), item.scope());
completeObjCMsgSend(binding, true); 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) bool staticClassAccess)
{ {
QList<Scope*> memberScopes; QList<Scope*> memberScopes;
@@ -1542,26 +1542,26 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope)
return !m_completions.isEmpty(); return !m_completions.isEmpty();
} }
QList<LookupScope *> usingBindings; QList<ClassOrNamespace *> usingBindings;
LookupScope *currentBinding = 0; ClassOrNamespace *currentBinding = 0;
for (Scope *scope = currentScope; scope; scope = scope->enclosingScope()) { for (Scope *scope = currentScope; scope; scope = scope->enclosingScope()) {
if (Block *block = scope->asBlock()) { 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) { for (unsigned i = 0; i < scope->memberCount(); ++i) {
Symbol *member = scope->memberAt(i); Symbol *member = scope->memberAt(i);
if (member->isEnum()) { if (member->isEnum()) {
if (LookupScope *b = binding->findBlock(block)) if (ClassOrNamespace *b = binding->findBlock(block))
completeNamespace(b); completeNamespace(b);
} }
if (!member->name()) if (!member->name())
continue; continue;
if (UsingNamespaceDirective *u = member->asUsingNamespaceDirective()) { if (UsingNamespaceDirective *u = member->asUsingNamespaceDirective()) {
if (LookupScope *b = binding->lookupType(u->name())) if (ClassOrNamespace *b = binding->lookupType(u->name()))
usingBindings.append(b); usingBindings.append(b);
} else if (Class *c = member->asClass()) { } else if (Class *c = member->asClass()) {
if (c->name()->isAnonymousNameId()) { if (c->name()->isAnonymousNameId()) {
if (LookupScope *b = binding->findBlock(block)) if (ClassOrNamespace *b = binding->findBlock(block))
completeClass(b); completeClass(b);
} }
} }
@@ -1588,7 +1588,7 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope)
} }
for (; currentBinding; currentBinding = currentBinding->parent()) { for (; currentBinding; currentBinding = currentBinding->parent()) {
foreach (LookupScope* u, currentBinding->usings()) foreach (ClassOrNamespace* u, currentBinding->usings())
usingBindings.append(u); usingBindings.append(u);
const QList<Symbol *> symbols = currentBinding->symbols(); 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); completeNamespace(b);
addKeywords(); addKeywords();
@@ -1624,7 +1624,7 @@ bool InternalCppCompletionAssistProcessor::completeMember(const QList<LookupItem
if (!m_interface->languageFeatures().objCEnabled) if (!m_interface->languageFeatures().objCEnabled)
replaceDotForArrow = &m_model->m_replaceDotForArrow; replaceDotForArrow = &m_model->m_replaceDotForArrow;
if (LookupScope *binding = if (ClassOrNamespace *binding =
resolveExpression.baseExpression(baseResults, resolveExpression.baseExpression(baseResults,
m_model->m_completionOperator, m_model->m_completionOperator,
replaceDotForArrow)) { replaceDotForArrow)) {
@@ -1648,27 +1648,27 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem>
Scope *scope = result.scope(); Scope *scope = result.scope();
if (NamedType *namedTy = ty->asNamedType()) { if (NamedType *namedTy = ty->asNamedType()) {
if (LookupScope *b = context.lookupType(namedTy->name(), scope)) { if (ClassOrNamespace *b = context.lookupType(namedTy->name(), scope)) {
completeClass(b); completeClass(b);
break; break;
} }
} else if (Class *classTy = ty->asClassType()) { } else if (Class *classTy = ty->asClassType()) {
if (LookupScope *b = context.lookupType(classTy)) { if (ClassOrNamespace *b = context.lookupType(classTy)) {
completeClass(b); completeClass(b);
break; break;
} }
// it can be class defined inside a block // it can be class defined inside a block
if (classTy->enclosingScope()->isBlock()) { if (classTy->enclosingScope()->isBlock()) {
if (LookupScope *b = context.lookupType(classTy->name(), classTy->enclosingScope())) { if (ClassOrNamespace *b = context.lookupType(classTy->name(), classTy->enclosingScope())) {
completeClass(b); completeClass(b);
break; break;
} }
} }
} else if (Namespace *nsTy = ty->asNamespaceType()) { } else if (Namespace *nsTy = ty->asNamespaceType()) {
if (LookupScope *b = context.lookupType(nsTy)) { if (ClassOrNamespace *b = context.lookupType(nsTy)) {
completeNamespace(b); completeNamespace(b);
break; break;
} }
@@ -1676,7 +1676,7 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem>
} else if (Template *templ = ty->asTemplateType()) { } else if (Template *templ = ty->asTemplateType()) {
if (!result.binding()) if (!result.binding())
continue; continue;
if (LookupScope *b = result.binding()->lookupType(templ->name())) { if (ClassOrNamespace *b = result.binding()->lookupType(templ->name())) {
completeClass(b); completeClass(b);
break; break;
} }
@@ -1684,16 +1684,16 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem>
} else if (Enum *e = ty->asEnumType()) { } else if (Enum *e = ty->asEnumType()) {
// it can be class defined inside a block // it can be class defined inside a block
if (e->enclosingScope()->isBlock()) { if (e->enclosingScope()->isBlock()) {
if (LookupScope *b = context.lookupType(e)) { if (ClassOrNamespace *b = context.lookupType(e)) {
Block *block = e->enclosingScope()->asBlock(); Block *block = e->enclosingScope()->asBlock();
if (LookupScope *bb = b->findBlock(block)) { if (ClassOrNamespace *bb = b->findBlock(block)) {
completeNamespace(bb); completeNamespace(bb);
break; break;
} }
} }
} }
if (LookupScope *b = context.lookupType(e)) { if (ClassOrNamespace *b = context.lookupType(e)) {
completeNamespace(b); completeNamespace(b);
break; break;
} }
@@ -1704,14 +1704,14 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem>
return !m_completions.isEmpty(); return !m_completions.isEmpty();
} }
void InternalCppCompletionAssistProcessor::completeNamespace(LookupScope *b) void InternalCppCompletionAssistProcessor::completeNamespace(ClassOrNamespace *b)
{ {
QSet<LookupScope *> bindingsVisited; QSet<ClassOrNamespace *> bindingsVisited;
QList<LookupScope *> bindingsToVisit; QList<ClassOrNamespace *> bindingsToVisit;
bindingsToVisit.append(b); bindingsToVisit.append(b);
while (!bindingsToVisit.isEmpty()) { while (!bindingsToVisit.isEmpty()) {
LookupScope *binding = bindingsToVisit.takeFirst(); ClassOrNamespace *binding = bindingsToVisit.takeFirst();
if (!binding || bindingsVisited.contains(binding)) if (!binding || bindingsVisited.contains(binding))
continue; 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; QSet<ClassOrNamespace *> bindingsVisited;
QList<LookupScope *> bindingsToVisit; QList<ClassOrNamespace *> bindingsToVisit;
bindingsToVisit.append(b); bindingsToVisit.append(b);
while (!bindingsToVisit.isEmpty()) { while (!bindingsToVisit.isEmpty()) {
LookupScope *binding = bindingsToVisit.takeFirst(); ClassOrNamespace *binding = bindingsToVisit.takeFirst();
if (!binding || bindingsVisited.contains(binding)) if (!binding || bindingsVisited.contains(binding))
continue; continue;
@@ -1838,16 +1838,16 @@ bool InternalCppCompletionAssistProcessor::completeQtMethod(const QList<LookupIt
QSet<QString> signatures; QSet<QString> signatures;
foreach (const LookupItem &lookupItem, results) { foreach (const LookupItem &lookupItem, results) {
LookupScope *b = lookupScopeFromLookupItem(lookupItem, context); ClassOrNamespace *b = classOrNamespaceFromLookupItem(lookupItem, context);
if (!b) if (!b)
continue; continue;
QList<LookupScope *>todo; QList<ClassOrNamespace *>todo;
QSet<LookupScope *> processed; QSet<ClassOrNamespace *> processed;
QList<Scope *> scopes; QList<Scope *> scopes;
todo.append(b); todo.append(b);
while (!todo.isEmpty()) { while (!todo.isEmpty()) {
LookupScope *binding = todo.takeLast(); ClassOrNamespace *binding = todo.takeLast();
if (!processed.contains(binding)) { if (!processed.contains(binding)) {
processed.insert(binding); processed.insert(binding);
@@ -2063,7 +2063,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
Scope *scope = result.scope(); Scope *scope = result.scope();
if (NamedType *namedTy = ty->asNamedType()) { 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)) { foreach (const LookupItem &r, b->lookup(functionCallOp)) {
Symbol *overload = r.declaration(); Symbol *overload = r.declaration();
FullySpecifiedType overloadTy = overload->type().simplified(); FullySpecifiedType overloadTy = overload->type().simplified();
@@ -2145,7 +2145,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q
SubstitutionEnvironment env; SubstitutionEnvironment env;
env.setContext(context); env.setContext(context);
env.switchScope(sc); env.switchScope(sc);
LookupScope *targetCoN = context.lookupType(sc); ClassOrNamespace *targetCoN = context.lookupType(sc);
if (!targetCoN) if (!targetCoN)
targetCoN = context.globalNamespace(); targetCoN = context.globalNamespace();
UseMinimalNames q(targetCoN); UseMinimalNames q(targetCoN);

View File

@@ -53,7 +53,7 @@
namespace CPlusPlus { namespace CPlusPlus {
class LookupItem; class LookupItem;
class LookupScope; class ClassOrNamespace;
class Function; class Function;
class LookupContext; class LookupContext;
} // namespace CPlusPlus } // namespace CPlusPlus
@@ -121,7 +121,7 @@ private:
const QString &expression, const QString &expression,
int endOfExpression); int endOfExpression);
void completeObjCMsgSend(CPlusPlus::LookupScope *binding, bool staticClassAccess); void completeObjCMsgSend(CPlusPlus::ClassOrNamespace *binding, bool staticClassAccess);
bool completeInclude(const QTextCursor &cursor); bool completeInclude(const QTextCursor &cursor);
void completeInclude(const QString &realPath, const QStringList &suffixes); void completeInclude(const QString &realPath, const QStringList &suffixes);
void completePreprocessor(); void completePreprocessor();
@@ -130,8 +130,8 @@ private:
bool toolTipOnly); bool toolTipOnly);
bool completeMember(const QList<CPlusPlus::LookupItem> &results); bool completeMember(const QList<CPlusPlus::LookupItem> &results);
bool completeScope(const QList<CPlusPlus::LookupItem> &results); bool completeScope(const QList<CPlusPlus::LookupItem> &results);
void completeNamespace(CPlusPlus::LookupScope *binding); void completeNamespace(CPlusPlus::ClassOrNamespace *binding);
void completeClass(CPlusPlus::LookupScope *b, bool staticLookup = true); void completeClass(CPlusPlus::ClassOrNamespace *b, bool staticLookup = true);
void addClassMembersToCompletion(CPlusPlus::Scope *scope, bool staticLookup); void addClassMembersToCompletion(CPlusPlus::Scope *scope, bool staticLookup);
enum CompleteQtMethodMode { enum CompleteQtMethodMode {
CompleteQt4Signals, CompleteQt4Signals,

View File

@@ -109,7 +109,7 @@ bool isOwnershipRAIIType(Symbol *symbol, const LookupContext &context)
Declaration *declaration = symbol->asDeclaration(); Declaration *declaration = symbol->asDeclaration();
const NamedType *namedType = declaration->type()->asNamedType(); const NamedType *namedType = declaration->type()->asNamedType();
if (namedType) { if (namedType) {
LookupScope *clazz = context.lookupType(namedType->name(), ClassOrNamespace *clazz = context.lookupType(namedType->name(),
declaration->enclosingScope()); declaration->enclosingScope());
if (clazz && !clazz->symbols().isEmpty()) { if (clazz && !clazz->symbols().isEmpty()) {
Overview overview; Overview overview;

View File

@@ -151,7 +151,7 @@ Function *SymbolFinder::findMatchingDefinition(Symbol *declaration,
QList<Function *> viableFunctions; QList<Function *> viableFunctions;
LookupScope *enclosingType = context.lookupType(declaration); ClassOrNamespace *enclosingType = context.lookupType(declaration);
if (!enclosingType) if (!enclosingType)
continue; // nothing to do continue; // nothing to do
@@ -214,15 +214,13 @@ Function *SymbolFinder::findMatchingDefinition(Symbol *declaration,
return 0; return 0;
} }
Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Snapshot &snapshot, Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Snapshot &snapshot)
const LookupContext *context)
{ {
if (!declaration->identifier()) if (!declaration->identifier())
return 0; return 0;
QString declFile = QString::fromUtf8(declaration->fileName(), declaration->fileNameLength()); QString declFile = QString::fromUtf8(declaration->fileName(), declaration->fileNameLength());
const bool useLocalContext = !context;
foreach (const QString &file, fileIterationOrder(declFile, snapshot)) { foreach (const QString &file, fileIterationOrder(declFile, snapshot)) {
Document::Ptr doc = snapshot.document(file); Document::Ptr doc = snapshot.document(file);
if (!doc) { if (!doc) {
@@ -234,13 +232,9 @@ Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Sna
declaration->identifier()->size())) declaration->identifier()->size()))
continue; continue;
QScopedPointer<LookupContext> localContext; LookupContext context(doc, snapshot);
if (useLocalContext) {
localContext.reset(new LookupContext(doc, snapshot));
context = localContext.data();
}
LookupScope *type = context->lookupType(declaration); ClassOrNamespace *type = context.lookupType(declaration);
if (!type) if (!type)
continue; continue;
@@ -289,7 +283,7 @@ void SymbolFinder::findMatchingDeclaration(const LookupContext &context,
if (!functionName) if (!functionName)
return; return;
LookupScope *binding = 0; ClassOrNamespace *binding = 0;
const QualifiedNameId *qName = functionName->asQualifiedNameId(); const QualifiedNameId *qName = functionName->asQualifiedNameId();
if (qName) { if (qName) {
if (qName->base()) if (qName->base())

View File

@@ -61,8 +61,7 @@ public:
bool strict = false); bool strict = false);
CPlusPlus::Class *findMatchingClassDeclaration(CPlusPlus::Symbol *declaration, CPlusPlus::Class *findMatchingClassDeclaration(CPlusPlus::Symbol *declaration,
const CPlusPlus::Snapshot &snapshot, const CPlusPlus::Snapshot &snapshot);
const CPlusPlus::LookupContext *context = 0);
void findMatchingDeclaration(const CPlusPlus::LookupContext &context, void findMatchingDeclaration(const CPlusPlus::LookupContext &context,
CPlusPlus::Function *functionType, CPlusPlus::Function *functionType,

View File

@@ -68,6 +68,9 @@ QHash<QString, QStringList> sortFilesIntoPaths(const QString &base, const QSet<Q
relativeFilePath.chop(1); relativeFilePath.chop(1);
} }
if (relativeFilePath == QLatin1String("."))
relativeFilePath.clear();
filesInPath[relativeFilePath].append(absoluteFileName); filesInPath[relativeFilePath].append(absoluteFileName);
} }
return filesInPath; return filesInPath;

View File

@@ -75,6 +75,8 @@ public:
const QStringList &extraOptions = QStringList()); const QStringList &extraOptions = QStringList());
void revertAll(const QString &workingDir, const QString &revision = QString(), void revertAll(const QString &workingDir, const QString &revision = QString(),
const QStringList &extraOptions = QStringList()); const QStringList &extraOptions = QStringList());
public slots:
void view(const QString &source, const QString &id, void view(const QString &source, const QString &id,
const QStringList &extraOptions = QStringList()); const QStringList &extraOptions = QStringList());

View File

@@ -483,6 +483,7 @@ Abi Abi::abiFromTargetTriplet(const QString &triple)
} else if (p == QLatin1String("i386") || p == QLatin1String("i486") || p == QLatin1String("i586") } else if (p == QLatin1String("i386") || p == QLatin1String("i486") || p == QLatin1String("i586")
|| p == QLatin1String("i686") || p == QLatin1String("x86")) { || p == QLatin1String("i686") || p == QLatin1String("x86")) {
arch = Abi::X86Architecture; arch = Abi::X86Architecture;
width = 32;
} else if (p.startsWith(QLatin1String("arm"))) { } else if (p.startsWith(QLatin1String("arm"))) {
arch = Abi::ArmArchitecture; arch = Abi::ArmArchitecture;
width = p.contains(QLatin1String("64")) ? 64 : 32; width = p.contains(QLatin1String("64")) ? 64 : 32;
@@ -1057,27 +1058,27 @@ void ProjectExplorer::ProjectExplorerPlugin::testAbiFromTargetTriplet_data()
QTest::newRow("i586-pc-mingw32msvc") << int(Abi::X86Architecture) QTest::newRow("i586-pc-mingw32msvc") << int(Abi::X86Architecture)
<< int(Abi::WindowsOS) << int(Abi::WindowsMSysFlavor) << int(Abi::WindowsOS) << int(Abi::WindowsMSysFlavor)
<< int(Abi::PEFormat) << 0; << int(Abi::PEFormat) << 32;
QTest::newRow("i686-linux-gnu") << int(Abi::X86Architecture) QTest::newRow("i686-linux-gnu") << int(Abi::X86Architecture)
<< int(Abi::LinuxOS) << int(Abi::GenericLinuxFlavor) << int(Abi::LinuxOS) << int(Abi::GenericLinuxFlavor)
<< int(Abi::ElfFormat) << 0; << int(Abi::ElfFormat) << 32;
QTest::newRow("i686-linux-android") << int(Abi::X86Architecture) QTest::newRow("i686-linux-android") << int(Abi::X86Architecture)
<< int(Abi::LinuxOS) << int(Abi::AndroidLinuxFlavor) << int(Abi::LinuxOS) << int(Abi::AndroidLinuxFlavor)
<< int(Abi::ElfFormat) << 0; << int(Abi::ElfFormat) << 32;
QTest::newRow("i686-pc-linux-android") << int(Abi::X86Architecture) QTest::newRow("i686-pc-linux-android") << int(Abi::X86Architecture)
<< int(Abi::LinuxOS) << int(Abi::AndroidLinuxFlavor) << int(Abi::LinuxOS) << int(Abi::AndroidLinuxFlavor)
<< int(Abi::ElfFormat) << 0; << int(Abi::ElfFormat) << 32;
QTest::newRow("i686-pc-mingw32") << int(Abi::X86Architecture) QTest::newRow("i686-pc-mingw32") << int(Abi::X86Architecture)
<< int(Abi::WindowsOS) << int(Abi::WindowsMSysFlavor) << int(Abi::WindowsOS) << int(Abi::WindowsMSysFlavor)
<< int(Abi::PEFormat) << 0; << int(Abi::PEFormat) << 32;
QTest::newRow("i686-w64-mingw32") << int(Abi::X86Architecture) QTest::newRow("i686-w64-mingw32") << int(Abi::X86Architecture)
<< int(Abi::WindowsOS) << int(Abi::WindowsMSysFlavor) << int(Abi::WindowsOS) << int(Abi::WindowsMSysFlavor)
<< int(Abi::PEFormat) << 0; << int(Abi::PEFormat) << 32;
QTest::newRow("x86_64-pc-msys") << int(Abi::X86Architecture) QTest::newRow("x86_64-pc-msys") << int(Abi::X86Architecture)
<< int(Abi::WindowsOS) << int(Abi::WindowsMSysFlavor) << int(Abi::WindowsOS) << int(Abi::WindowsMSysFlavor)

View File

@@ -40,6 +40,7 @@
#include <coreplugin/messagemanager.h> #include <coreplugin/messagemanager.h>
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -358,7 +359,6 @@ CustomWizard *CustomWizard::createWizard(const CustomProjectWizard::CustomWizard
QList<Core::IWizardFactory *> CustomWizard::createWizards() QList<Core::IWizardFactory *> CustomWizard::createWizards()
{ {
QList<Core::IWizardFactory *> rc;
QString errorMessage; QString errorMessage;
QString verboseLog; QString verboseLog;
const QString templateDirName = Core::ICore::resourcePath() + const QString templateDirName = Core::ICore::resourcePath() +
@@ -371,29 +371,32 @@ QList<Core::IWizardFactory *> CustomWizard::createWizards()
const QDir templateDir(templateDirName); const QDir templateDir(templateDirName);
if (CustomWizardPrivate::verbose) 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 (!templateDir.exists()) {
if (CustomWizardPrivate::verbose) if (CustomWizardPrivate::verbose)
qWarning("Custom project template path %s does not exist.", qPrintable(templateDir.absolutePath())); qWarning("Custom project template path %s does not exist.", qPrintable(templateDir.absolutePath()));
return rc; return QList<Core::IWizardFactory *>();
} }
const QDir userTemplateDir(userTemplateDirName); const QDir userTemplateDir(userTemplateDirName);
if (CustomWizardPrivate::verbose) 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::Filters filters = QDir::Dirs|QDir::Readable|QDir::NoDotAndDotDot;
const QDir::SortFlags sortflags = QDir::Name|QDir::IgnoreCase; const QDir::SortFlags sortflags = QDir::Name|QDir::IgnoreCase;
QList<QFileInfo> dirs = templateDir.entryInfoList(filters, sortflags); QList<QFileInfo> dirs;
if (userTemplateDir.exists()) { if (userTemplateDir.exists()) {
if (CustomWizardPrivate::verbose) 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 += userTemplateDir.entryInfoList(filters, sortflags);
} }
dirs += templateDir.entryInfoList(filters, sortflags);
const QString configFile = QLatin1String(configFileC); const QString configFile = QLatin1String(configFileC);
// Check and parse config file in each directory. // Check and parse config file in each directory.
QList<CustomWizardParametersPtr> toCreate;
while (!dirs.isEmpty()) { while (!dirs.isEmpty()) {
const QFileInfo dirFi = dirs.takeFirst(); const QFileInfo dirFi = dirs.takeFirst();
const QDir dir(dirFi.absoluteFilePath()); const QDir dir(dirFi.absoluteFilePath());
@@ -403,11 +406,13 @@ QList<Core::IWizardFactory *> CustomWizard::createWizards()
CustomWizardParametersPtr parameters(new CustomWizardParameters); CustomWizardParametersPtr parameters(new CustomWizardParameters);
switch (parameters->parse(dir.absoluteFilePath(configFile), &errorMessage)) { switch (parameters->parse(dir.absoluteFilePath(configFile), &errorMessage)) {
case CustomWizardParameters::ParseOk: case CustomWizardParameters::ParseOk:
if (!Utils::contains(toCreate, [parameters](CustomWizardParametersPtr p) { return parameters->id == p->id; })) {
parameters->directory = dir.absolutePath(); parameters->directory = dir.absolutePath();
if (CustomWizard *w = createWizard(parameters)) toCreate.append(parameters);
rc.push_back(w); } else {
else verboseLog += QString::fromLatin1("Customwizard: Ignoring wizard in %1 due to duplicate Id %2.\n")
qWarning("Custom wizard factory function failed for %s", qPrintable(parameters->id.toString())); .arg(dir.absolutePath()).arg(parameters->id.toString());
}
break; break;
case CustomWizardParameters::ParseDisabled: case CustomWizardParameters::ParseDisabled:
if (CustomWizardPrivate::verbose) 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. if (CustomWizardPrivate::verbose) { // Print to output pane for Windows.
qWarning("%s", qPrintable(verboseLog)); qWarning("%s", qPrintable(verboseLog));
Core::MessageManager::write(verboseLog, Core::MessageManager::ModeSwitch); Core::MessageManager::write(verboseLog, Core::MessageManager::ModeSwitch);

View File

@@ -568,6 +568,7 @@ static void appendNodeToEndOfTheRow(const ModelNode &modelNode, const ItemRow &n
parentPropertyItem->appendRow(newItemRow.toList()); parentPropertyItem->appendRow(newItemRow.toList());
} else { } else {
QStandardItem *parentDefaultPropertyItem = parentRow.idItem; QStandardItem *parentDefaultPropertyItem = parentRow.idItem;
if (parentDefaultPropertyItem)
parentDefaultPropertyItem->appendRow(newItemRow.toList()); parentDefaultPropertyItem->appendRow(newItemRow.toList());
} }
} else { // root node } else { // root node

View File

@@ -885,7 +885,7 @@ void PathItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
if (pickedControlPoint.isEditPoint()) { if (pickedControlPoint.isEditPoint()) {
createEditPointContextMenu(pickedControlPoint, event->screenPos()); createEditPointContextMenu(pickedControlPoint, event->screenPos());
} else { } else {
double t; double t = 0.0;
CubicSegment minimumDistanceSegment = getMinimumDistanceSegment(event->pos(), m_cubicSegments, 20., &t); CubicSegment minimumDistanceSegment = getMinimumDistanceSegment(event->pos(), m_cubicSegments, 20., &t);
if (minimumDistanceSegment.isValid()) if (minimumDistanceSegment.isValid())
createCubicSegmentContextMenu(minimumDistanceSegment, event->screenPos(), t); createCubicSegmentContextMenu(minimumDistanceSegment, event->screenPos(), t);

View File

@@ -104,16 +104,24 @@ void QmlProfilerTraceTime::setTime(qint64 startTime, qint64 endTime)
void QmlProfilerTraceTime::decreaseStartTime(qint64 time) void QmlProfilerTraceTime::decreaseStartTime(qint64 time)
{ {
if (m_startTime > time) { if (m_startTime > time || m_startTime == -1) {
m_startTime = time; 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); emit timeChanged(time, m_endTime);
} }
} }
void QmlProfilerTraceTime::increaseEndTime(qint64 time) void QmlProfilerTraceTime::increaseEndTime(qint64 time)
{ {
if (m_endTime < time) { if (m_endTime < time || m_endTime == -1) {
m_endTime = time; 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); emit timeChanged(m_startTime, time);
} }
} }
@@ -152,6 +160,8 @@ QmlProfilerModelManager::QmlProfilerModelManager(Utils::FileInProjectFinder *fin
QObject(parent), d(new QmlProfilerModelManagerPrivate(this)) QObject(parent), d(new QmlProfilerModelManagerPrivate(this))
{ {
d->totalWeight = 0; d->totalWeight = 0;
d->previousProgress = 0;
d->progress = 0;
d->availableFeatures = 0; d->availableFeatures = 0;
d->visibleFeatures = 0; d->visibleFeatures = 0;
d->recordedFeatures = 0; d->recordedFeatures = 0;

View File

@@ -33,6 +33,7 @@
#include <algorithm> #include <algorithm>
#include <atomic> #include <atomic>
#include <cmath>
#include <iostream> #include <iostream>
#include <limits> #include <limits>
#include <string> #include <string>

View File

@@ -53,6 +53,9 @@ int main(int argc, char *argv[])
ClangBackEnd::Messages::registerMessages(); ClangBackEnd::Messages::registerMessages();
clang_toggleCrashRecovery(true);
clang_enableStackTraces();
ClangBackEnd::ClangIpcServer clangIpcServer; ClangBackEnd::ClangIpcServer clangIpcServer;
ClangBackEnd::ConnectionServer connectionServer(application.arguments()[1]); ClangBackEnd::ConnectionServer connectionServer(application.arguments()[1]);
connectionServer.start(); connectionServer.start();

View File

@@ -25,7 +25,13 @@ HEADERS += $$PWD/clangipcserver.h \
$$PWD/diagnosticsetiterator.h \ $$PWD/diagnosticsetiterator.h \
$$PWD/clangfilesystemwatcher.h \ $$PWD/clangfilesystemwatcher.h \
$$PWD/translationunitalreadyexistsexception.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 \ SOURCES += $$PWD/clangipcserver.cpp \
$$PWD/codecompleter.cpp \ $$PWD/codecompleter.cpp \
@@ -51,4 +57,9 @@ SOURCES += $$PWD/clangipcserver.cpp \
$$PWD/fixit.cpp \ $$PWD/fixit.cpp \
$$PWD/clangfilesystemwatcher.cpp \ $$PWD/clangfilesystemwatcher.cpp \
$$PWD/translationunitalreadyexistsexception.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

View File

@@ -61,6 +61,11 @@ ClangString &ClangString::operator=(ClangString &&other)
return *this; return *this;
} }
const char *ClangString::cString() const
{
return clang_getCString(cxString);
}
ClangString::ClangString(ClangString &&other) ClangString::ClangString(ClangString &&other)
: cxString(std::move(other.cxString)) : cxString(std::move(other.cxString))
{ {
@@ -70,7 +75,7 @@ ClangString::ClangString(ClangString &&other)
ClangString::operator Utf8String() const ClangString::operator Utf8String() const
{ {
return Utf8String(clang_getCString(cxString), -1); return Utf8String(cString(), -1);
} }
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -51,6 +51,8 @@ public:
operator Utf8String() const; operator Utf8String() const;
const char *cString() const;
bool isNull() const; bool isNull() const;
private: private:

View File

@@ -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

View File

@@ -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

View File

@@ -113,7 +113,7 @@ std::vector<SourceRange> Diagnostic::ranges() const
const SourceRange sourceRange(clang_getDiagnosticRange(cxDiagnostic, index)); const SourceRange sourceRange(clang_getDiagnosticRange(cxDiagnostic, index));
if (sourceRange.isValid()) if (sourceRange.isValid())
ranges.push_back(SourceRange(clang_getDiagnosticRange(cxDiagnostic, index))); ranges.push_back(std::move(sourceRange));
} }
return ranges; return ranges;

View File

@@ -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

Some files were not shown because too many files have changed in this diff Show More