diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index 06655b0960a..8c2d6265909 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -240,6 +240,9 @@ void Document::startSkippingBlocks(unsigned start) void Document::stopSkippingBlocks(unsigned stop) { + if (_skippedBlocks.isEmpty()) + return; + unsigned start = _skippedBlocks.back().begin(); if (start > stop) _skippedBlocks.removeLast(); // Ignore this block, it's invalid. diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 01d4e13b4eb..e130aa1bd54 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -159,8 +159,12 @@ bool LookupContext::maybeValidSymbol(Symbol *symbol, QList LookupContext::resolve(Name *name, const QList &visibleScopes, ResolveMode mode) const { + QList candidates; + + if (!name) + return candidates; + if (QualifiedNameId *q = name->asQualifiedNameId()) { - QList candidates; QList scopes = visibleScopes; for (unsigned i = 0; i < q->nameCount(); ++i) { Name *name = q->nameAt(i); @@ -210,7 +214,6 @@ QList LookupContext::resolve(Name *name, const QList &visible return candidates; } - QList candidates; if (Identifier *id = identifier(name)) { for (int scopeIndex = 0; scopeIndex < visibleScopes.size(); ++scopeIndex) { Scope *scope = visibleScopes.at(scopeIndex); diff --git a/src/libs/cplusplus/OverviewModel.cpp b/src/libs/cplusplus/OverviewModel.cpp index 0855bcbd8f6..1bef20f36d3 100644 --- a/src/libs/cplusplus/OverviewModel.cpp +++ b/src/libs/cplusplus/OverviewModel.cpp @@ -171,7 +171,7 @@ QVariant OverviewModel::data(const QModelIndex &index, int role) const if (! symbol->isScopedSymbol() || symbol->isFunction()) { QString type = _overview.prettyType(symbol->type()); if (! type.isEmpty()) { - if (symbol->type() && ! symbol->type()->isFunctionType()) + if (! symbol->type()->isFunctionType()) name += QLatin1String(": "); name += type; } diff --git a/src/plugins/coreplugin/editormanager/openeditorsview.cpp b/src/plugins/coreplugin/editormanager/openeditorsview.cpp index 8c8e07d0ab1..fb32507bb5d 100644 --- a/src/plugins/coreplugin/editormanager/openeditorsview.cpp +++ b/src/plugins/coreplugin/editormanager/openeditorsview.cpp @@ -80,7 +80,6 @@ OpenEditorsWidget::OpenEditorsWidget() OpenEditorsWidget::~OpenEditorsWidget() { - } void OpenEditorsWidget::updateCurrentItem(Core::IEditor *editor) diff --git a/src/plugins/coreplugin/manhattanstyle.cpp b/src/plugins/coreplugin/manhattanstyle.cpp index 2bd86a68888..5e6084e04b7 100644 --- a/src/plugins/coreplugin/manhattanstyle.cpp +++ b/src/plugins/coreplugin/manhattanstyle.cpp @@ -314,6 +314,7 @@ void ManhattanStyle::polish(QWidget *widget) if (qobject_cast(widget)) { widget->setAttribute(Qt::WA_Hover); widget->setMaximumHeight(StyleHelper::navigationWidgetHeight() - 2); + widget->setAttribute(Qt::WA_Hover); } else if (qobject_cast(widget)) { widget->setAttribute(Qt::WA_Hover); @@ -325,8 +326,10 @@ void ManhattanStyle::polish(QWidget *widget) widget->setMinimumHeight(StyleHelper::navigationWidgetHeight()); else if (qobject_cast(widget)) widget->setFixedHeight(StyleHelper::navigationWidgetHeight() + 2); - else if (qobject_cast(widget)) + else if (qobject_cast(widget)) { widget->setMaximumHeight(StyleHelper::navigationWidgetHeight() - 2); + widget->setAttribute(Qt::WA_Hover); + } } } @@ -338,6 +341,8 @@ void ManhattanStyle::unpolish(QWidget *widget) widget->setAttribute(Qt::WA_Hover, false); else if (qobject_cast(widget)) widget->setAttribute(Qt::WA_Hover, false); + else if (qobject_cast(widget)) + widget->setAttribute(Qt::WA_Hover, false); } } @@ -517,15 +522,12 @@ void ManhattanStyle::drawPrimitive(PrimitiveElement element, const QStyleOption painter->drawLine(rect.topRight(), rect.bottomRight()); painter->drawLine(rect.bottomLeft(), rect.bottomRight()); } - #ifndef Q_WS_MAC - else if (option->state & State_Enabled && - option->state & State_MouseOver) { + else if (option->state & State_Enabled && + option->state & State_MouseOver) { QColor lighter(255, 255, 255, 35); painter->fillRect(rect, lighter); - painter->drawLine(rect.topRight(), rect.bottomRight()); } -#endif - } + } } break; @@ -676,11 +678,11 @@ void ManhattanStyle::drawPrimitive(PrimitiveElement element, const QStyleOption imagePainter.setBrush(option->palette.mid().color()); imagePainter.setPen(option->palette.mid().color()); } else { - QColor shadow(0, 0, 0, 50); + QColor shadow(0, 0, 0, 100); imagePainter.translate(0, 1); imagePainter.setPen(shadow); imagePainter.setBrush(shadow); - QColor foreGround(255, 255, 255, 220); + QColor foreGround(255, 255, 255, 210); imagePainter.drawPolygon(a); imagePainter.translate(0, -1); imagePainter.setPen(foreGround); @@ -1018,17 +1020,21 @@ void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOpti // Draw tool button QLinearGradient grad(option->rect.topRight(), option->rect.bottomRight()); - grad.setColorAt(0, Qt::transparent); - grad.setColorAt(0.4, QColor(255, 255, 255, 30)); - grad.setColorAt(1, Qt::transparent); + grad.setColorAt(0, QColor(255, 255, 255, 20)); + grad.setColorAt(0.4, QColor(255, 255, 255, 60)); + grad.setColorAt(0.7, QColor(255, 255, 255, 50)); + grad.setColorAt(1, QColor(255, 255, 255, 40)); painter->setPen(QPen(grad, 0)); painter->drawLine(rect.topRight(), rect.bottomRight()); - grad.setColorAt(0, Qt::transparent); - grad.setColorAt(0.4, QColor(0, 0, 0, 30)); - grad.setColorAt(1, Qt::transparent); + grad.setColorAt(0, QColor(0, 0, 0, 20)); + grad.setColorAt(0.4, QColor(0, 0, 0, 70)); + grad.setColorAt(0.7, QColor(0, 0, 0, 70)); + grad.setColorAt(1, QColor(0, 0, 0, 40)); painter->setPen(QPen(grad, 0)); painter->drawLine(rect.topRight() - QPoint(1,0), rect.bottomRight() - QPoint(1,0)); - drawPrimitive(PE_PanelButtonTool, option, painter, widget); + QStyleOption toolbutton = *option; + toolbutton.rect.adjust(0, 0, -2, 0); + drawPrimitive(PE_PanelButtonTool, &toolbutton, painter, widget); // Draw arrow int menuButtonWidth = 12; @@ -1042,11 +1048,14 @@ void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOpti QStyleOption arrowOpt = *option; arrowOpt.rect = arrowRect; QPalette pal = option->palette; - pal.setBrush(QPalette::All, QPalette::ButtonText, StyleHelper::panelTextColor()); - arrowOpt.palette = pal; - - drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget); - + if (styleHint(SH_ComboBox_Popup, option, widget)) { + arrowOpt.rect.translate(0, -3); + drawPrimitive(PE_IndicatorArrowUp, &arrowOpt, painter, widget); + arrowOpt.rect.translate(0, 6); + drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget); + } else { + drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, painter, widget); + } painter->restore(); } break; diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index d66e590593b..b0eb63ffe35 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -593,8 +593,6 @@ Symbol *CPPEditor::findDefinition(Symbol *symbol) { if (symbol->isFunction()) return 0; // symbol is a function definition. - else if (! symbol->type()) - return 0; Function *funTy = symbol->type()->asFunctionType(); if (! funTy) diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp index 3959d953f92..8f371bb2870 100644 --- a/src/plugins/cppeditor/cpphoverhandler.cpp +++ b/src/plugins/cppeditor/cpphoverhandler.cpp @@ -165,6 +165,9 @@ static QString buildHelpId(const FullySpecifiedType &type, } } + if (! name) + return QString(); + Overview overview; overview.setShowArgumentNames(false); overview.setShowReturnTypes(false); diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp index c2db0bd1b7d..f9ea3b0bbe9 100644 --- a/src/plugins/cpptools/cppcodecompletion.cpp +++ b/src/plugins/cpptools/cppcodecompletion.cpp @@ -200,7 +200,7 @@ FunctionArgumentWidget::FunctionArgumentWidget() setParent(m_popupFrame); setFocusPolicy(Qt::NoFocus); - QVBoxLayout *layout = new QVBoxLayout(); + QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(this); layout->setMargin(0); m_popupFrame->setLayout(layout); @@ -578,8 +578,6 @@ bool CppCodeCompletion::completeFunction(FullySpecifiedType exprTy, QSet signatures; foreach (TypeOfExpression::Result p, resolvedTypes) { FullySpecifiedType ty = p.first; - if (! ty) - continue; if (Function *fun = ty->asFunctionType()) { if (TextEditor::CompletionItem item = toCompletionItem(fun)) { QString signature; @@ -602,7 +600,7 @@ bool CppCodeCompletion::completeFunction(FullySpecifiedType exprTy, bool CppCodeCompletion::completeMember(const QList &results, const LookupContext &context) { - if (results.isEmpty() || ! results.first().first) + if (results.isEmpty()) return false; TypeOfExpression::Result result = results.first(); @@ -898,10 +896,7 @@ bool CppCodeCompletion::completeConstructors(Class *klass) for (unsigned i = 0; i < klass->memberCount(); ++i) { Symbol *member = klass->memberAt(i); - FullySpecifiedType memberTy = member->type(); - if (! memberTy) - continue; - else if (! memberTy->isFunctionType()) + if (! member->type()->isFunctionType()) continue; else if (! member->identity()) continue; @@ -935,12 +930,8 @@ bool CppCodeCompletion::completeQtMethod(CPlusPlus::FullySpecifiedType, QSet signatures; foreach (TypeOfExpression::Result p, results) { FullySpecifiedType ty = p.first; - if (! ty) - continue; - if (ReferenceType *refTy = ty->asReferenceType()) ty = refTy->elementType(); - if (PointerType *ptrTy = ty->asPointerType()) ty = ptrTy->elementType(); else @@ -1125,15 +1116,13 @@ void CppCodeCompletion::complete(const TextEditor::CompletionItem &item) extraChars += QLatin1Char('('); // If the function takes no arguments, automatically place the closing parenthesis - if (function->argumentCount() == 0 || (function->argumentCount() == 1 && - function->argumentAt(0)->type() && + if (function->argumentCount() == 0 || (function->argumentCount() == 1 && function->argumentAt(0)->type()->isVoidType())) { extraChars += QLatin1Char(')'); // If the function doesn't return anything, automatically place the semicolon, // unless we're doing a scope completion (then it might be function definition). - FullySpecifiedType retTy = function->returnType(); - if (retTy && retTy->isVoidType() && m_completionOperator != T_COLON_COLON) { + if (function->returnType()->isVoidType() && m_completionOperator != T_COLON_COLON) { extraChars += QLatin1Char(';'); } } diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index c7e1d3fc5da..c28c216138e 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -69,6 +69,7 @@ #include #include #include +#include using namespace CppTools; using namespace CppTools::Internal; @@ -454,6 +455,12 @@ CppModelManager::CppModelManager(QObject *parent) ProjectExplorer::SessionManager *session = m_projectExplorer->session(); QTC_ASSERT(session, return); + m_updateEditorSelectionsTimer = new QTimer(this); + m_updateEditorSelectionsTimer->setInterval(500); + m_updateEditorSelectionsTimer->setSingleShot(true); + connect(m_updateEditorSelectionsTimer, SIGNAL(timeout()), + this, SLOT(updateEditorSelections())); + connect(session, SIGNAL(projectAdded(ProjectExplorer::Project*)), this, SLOT(onProjectAdded(ProjectExplorer::Project*))); @@ -717,8 +724,8 @@ void CppModelManager::onDocumentUpdated(Document::Ptr doc) continue; else if (lines.contains(m.line())) continue; - else if (lines.size() == MAX_SELECTION_COUNT) - break; // we're done. + //else if (lines.size() == MAX_SELECTION_COUNT) + //break; // we're done. lines.insert(m.line()); @@ -740,12 +747,42 @@ void CppModelManager::onDocumentUpdated(Document::Ptr doc) sel.cursor = c; selections.append(sel); } - ed->setExtraSelections(TextEditor::BaseTextEditor::CodeWarningsSelection, selections); + + QList todo; + foreach (Editor e, todo) { + if (e.widget != ed) + todo.append(e); + } + + Editor e; + e.widget = ed; + e.selections = selections; + todo.append(e); + m_todo = todo; + postEditorUpdate(); break; } } } +void CppModelManager::postEditorUpdate() +{ + m_updateEditorSelectionsTimer->start(500); +} + +void CppModelManager::updateEditorSelections() +{ + foreach (Editor ed, m_todo) { + if (! ed.widget) + continue; + + ed.widget->setExtraSelections(TextEditor::BaseTextEditor::CodeWarningsSelection, + ed.selections); + } + + m_todo.clear(); +} + void CppModelManager::onProjectAdded(ProjectExplorer::Project *) { QMutexLocker locker(&mutex); diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index 361c714fee7..4713c29d61b 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -41,6 +41,8 @@ #include #include #include +#include +#include namespace Core { class ICore; @@ -49,6 +51,7 @@ class IEditor; namespace TextEditor { class ITextEditor; +class BaseTextEditor; } namespace ProjectExplorer { @@ -86,6 +89,9 @@ public: void emitDocumentUpdated(CPlusPlus::Document::Ptr doc); + void stopEditorSelectionsUpdate() + { m_updateEditorSelectionsTimer->stop(); } + Q_SIGNALS: void projectPathChanged(const QString &projectPath); @@ -102,6 +108,8 @@ private Q_SLOTS: void onAboutToRemoveProject(ProjectExplorer::Project *project); void onSessionUnloaded(); void onProjectAdded(ProjectExplorer::Project *project); + void postEditorUpdate(); + void updateEditorSelections(); private: QMap buildWorkingCopyList(); @@ -163,6 +171,15 @@ private: enum { MAX_SELECTION_COUNT = 5 }; + + struct Editor { + QPointer widget; + QList selections; + }; + + QList m_todo; + + QTimer *m_updateEditorSelectionsTimer; }; } // namespace Internal diff --git a/src/plugins/cpptools/cpptoolseditorsupport.cpp b/src/plugins/cpptools/cpptoolseditorsupport.cpp index 5a907a2d175..ab6fe3532cc 100644 --- a/src/plugins/cpptools/cpptoolseditorsupport.cpp +++ b/src/plugins/cpptools/cpptoolseditorsupport.cpp @@ -35,6 +35,7 @@ #include "cppmodelmanager.h" #include +#include #include @@ -68,12 +69,14 @@ void CppEditorSupport::setTextEditor(TextEditor::ITextEditor *textEditor) updateDocument(); } -QString CppEditorSupport::contents() const +QString CppEditorSupport::contents() { if (! _textEditor) return QString(); + else if (! _cachedContents.isEmpty()) + _cachedContents = _textEditor->contents(); - return _textEditor->contents(); + return _cachedContents; } int CppEditorSupport::updateDocumentInterval() const @@ -83,7 +86,20 @@ void CppEditorSupport::setUpdateDocumentInterval(int updateDocumentInterval) { _updateDocumentInterval = updateDocumentInterval; } void CppEditorSupport::updateDocument() -{ _updateDocumentTimer->start(_updateDocumentInterval); } +{ + if (TextEditor::BaseTextEditor *edit = qobject_cast(_textEditor->widget())) { + const QList selections = + edit->extraSelections(TextEditor::BaseTextEditor::CodeWarningsSelection); + + if (! selections.isEmpty()) + edit->setExtraSelections(TextEditor::BaseTextEditor::CodeWarningsSelection, + QList()); + + _modelManager->stopEditorSelectionsUpdate(); + } + + _updateDocumentTimer->start(_updateDocumentInterval); +} void CppEditorSupport::updateDocumentNow() { @@ -91,7 +107,9 @@ void CppEditorSupport::updateDocumentNow() _updateDocumentTimer->start(_updateDocumentInterval); } else { _updateDocumentTimer->stop(); + QStringList sourceFiles(_textEditor->file()->fileName()); + _cachedContents = _textEditor->contents(); _documentParser = _modelManager->refreshSourceFiles(sourceFiles); } } diff --git a/src/plugins/cpptools/cpptoolseditorsupport.h b/src/plugins/cpptools/cpptoolseditorsupport.h index 2bce101e523..6e136c2d852 100644 --- a/src/plugins/cpptools/cpptoolseditorsupport.h +++ b/src/plugins/cpptools/cpptoolseditorsupport.h @@ -65,7 +65,7 @@ public: int updateDocumentInterval() const; void setUpdateDocumentInterval(int updateDocumentInterval); - QString contents() const; + QString contents(); private Q_SLOTS: void updateDocument(); @@ -79,6 +79,7 @@ private: QTimer *_updateDocumentTimer; int _updateDocumentInterval; QFuture _documentParser; + QString _cachedContents; }; } // namespace Internal diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index b75994f366d..8a9c201dc5d 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -2225,56 +2225,79 @@ unsigned NestedNameSpecifierAST::lastToken() const return class_or_namespace_name->lastToken(); } -NewDeclaratorAST *NewDeclaratorAST::clone(MemoryPool *pool) const +NewPlacementAST *NewPlacementAST::clone(MemoryPool *pool) const { - NewDeclaratorAST *ast = new (pool) NewDeclaratorAST; - if (ptr_operators) - ast->ptr_operators = ptr_operators->clone(pool); - if (declarator) - ast->declarator = declarator->clone(pool); + NewPlacementAST *ast = new (pool) NewPlacementAST; + ast->lparen_token = lparen_token; + if (expression_list) + ast->expression_list = expression_list->clone(pool); + ast->rparen_token = rparen_token; return ast; } -void NewDeclaratorAST::accept0(ASTVisitor *visitor) +void NewPlacementAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { - for (PtrOperatorAST *ptr_op = ptr_operators; ptr_op; - ptr_op = static_cast(ptr_op->next)) { - accept(ptr_op, visitor); + for (ExpressionListAST *it = expression_list; it; it = it->next) { + accept(it->expression, visitor); } - - accept(declarator, visitor); } visitor->endVisit(this); } -unsigned NewDeclaratorAST::firstToken() const +unsigned NewPlacementAST::firstToken() const { - return ptr_operators->firstToken(); + return lparen_token; } -unsigned NewDeclaratorAST::lastToken() const +unsigned NewPlacementAST::lastToken() const { - if (declarator) - return declarator->lastToken(); + return rparen_token + 1; +} - for (PtrOperatorAST *it = ptr_operators; it; it = it->next) { - if (! it->next) - return it->lastToken(); +NewArrayDeclaratorAST *NewArrayDeclaratorAST::clone(MemoryPool *pool) const +{ + NewArrayDeclaratorAST *ast = new (pool) NewArrayDeclaratorAST; + ast->lbracket_token = lbracket_token; + if (expression) + ast->expression = expression->clone(pool); + ast->rbracket_token = rbracket_token; + if (next) + ast->next = next->clone(pool); + return ast; +} + +void NewArrayDeclaratorAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + accept(next, visitor); } + visitor->endVisit(this); +} - return 0; +unsigned NewArrayDeclaratorAST::firstToken() const +{ + return lbracket_token; +} + +unsigned NewArrayDeclaratorAST::lastToken() const +{ + return rbracket_token + 1; } NewExpressionAST *NewExpressionAST::clone(MemoryPool *pool) const { NewExpressionAST *ast = new (pool) NewExpressionAST; + ast->scope_token = scope_token; ast->new_token = new_token; - if (expression) - ast->expression = expression->clone(pool); + if (new_placement) + ast->new_placement = new_placement->clone(pool); + ast->lparen_token = lparen_token; if (type_id) ast->type_id = type_id->clone(pool); + ast->rparen_token = rparen_token; if (new_type_id) ast->new_type_id = new_type_id->clone(pool); if (new_initializer) @@ -2285,7 +2308,7 @@ NewExpressionAST *NewExpressionAST::clone(MemoryPool *pool) const void NewExpressionAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { - accept(expression, visitor); + accept(new_placement, visitor); accept(type_id, visitor); accept(new_type_id, visitor); accept(new_initializer, visitor); @@ -2302,15 +2325,8 @@ unsigned NewExpressionAST::firstToken() const unsigned NewExpressionAST::lastToken() const { - if (new_initializer) - return new_initializer->lastToken(); - else if (new_type_id) - return new_type_id->lastToken(); - else if (type_id) - return type_id->lastToken(); - else if (expression) - return expression->lastToken(); - else if (new_token) + // ### FIXME + if (new_token) return new_token + 1; else if (scope_token) return scope_token + 1; @@ -2363,12 +2379,13 @@ TypeIdAST *TypeIdAST::clone(MemoryPool *pool) const NewTypeIdAST *NewTypeIdAST::clone(MemoryPool *pool) const { NewTypeIdAST *ast = new (pool) NewTypeIdAST; + if (type_specifier) ast->type_specifier = type_specifier->clone(pool); - if (new_initializer) - ast->new_initializer = new_initializer->clone(pool); - if (new_declarator) - ast->new_declarator = new_declarator->clone(pool); + if (ptr_operators) + ast->ptr_operators = ptr_operators->clone(pool); + if (new_array_declarators) + ast->new_array_declarators = new_array_declarators->clone(pool); return ast; } @@ -2377,8 +2394,13 @@ void NewTypeIdAST::accept0(ASTVisitor *visitor) if (visitor->visit(this)) { for (SpecifierAST *spec = type_specifier; spec; spec = spec->next) accept(spec, visitor); - accept(new_initializer, visitor); - accept(new_declarator, visitor); + + for (PtrOperatorAST *it = ptr_operators; it; it = it->next) + accept(it, visitor); + + for (NewArrayDeclaratorAST *it = new_array_declarators; it; it = it->next) + accept(it, visitor); + } visitor->endVisit(this); } @@ -2390,15 +2412,19 @@ unsigned NewTypeIdAST::firstToken() const unsigned NewTypeIdAST::lastToken() const { - if (new_declarator) - return new_declarator->lastToken(); - else if (new_initializer) - return new_initializer->lastToken(); - for (SpecifierAST *it = type_specifier; it; it = it->next) { + for (NewArrayDeclaratorAST *it = new_array_declarators; it; it = it->next) { if (! it->next) return it->lastToken(); } + for (PtrOperatorAST *it = ptr_operators; it; it = it->next) { + if (it->next) + return it->lastToken(); + } + + if (type_specifier) + return type_specifier->lastToken(); + // ### assert? return 0; } diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index 26f0a6692b5..78e45ce328f 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -152,7 +152,8 @@ public: virtual NestedDeclaratorAST *asNestedDeclarator() { return 0; } virtual NestedExpressionAST *asNestedExpression() { return 0; } virtual NestedNameSpecifierAST *asNestedNameSpecifier() { return 0; } - virtual NewDeclaratorAST *asNewDeclarator() { return 0; } + virtual NewPlacementAST *asNewPlacement() { return 0; } + virtual NewArrayDeclaratorAST *asNewArrayDeclarator() { return 0; } virtual NewExpressionAST *asNewExpression() { return 0; } virtual NewInitializerAST *asNewInitializer() { return 0; } virtual NewTypeIdAST *asNewTypeId() { return 0; } @@ -1440,20 +1441,42 @@ protected: virtual void accept0(ASTVisitor *visitor); }; -class CPLUSPLUS_EXPORT NewDeclaratorAST: public AST +class CPLUSPLUS_EXPORT NewPlacementAST: public AST { public: - PtrOperatorAST *ptr_operators; - NewDeclaratorAST *declarator; + unsigned lparen_token; + ExpressionListAST *expression_list; + unsigned rparen_token; public: - virtual NewDeclaratorAST *asNewDeclarator() + virtual NewPlacementAST *asNewPlacement() { return this; } virtual unsigned firstToken() const; virtual unsigned lastToken() const; - virtual NewDeclaratorAST *clone(MemoryPool *pool) const; + virtual NewPlacementAST *clone(MemoryPool *pool) const; + +protected: + virtual void accept0(ASTVisitor *visitor); +}; + +class CPLUSPLUS_EXPORT NewArrayDeclaratorAST: public AST +{ +public: + unsigned lbracket_token; + ExpressionAST *expression; + unsigned rbracket_token; + NewArrayDeclaratorAST *next; + +public: + virtual NewArrayDeclaratorAST *asNewArrayDeclarator() + { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + + virtual NewArrayDeclaratorAST *clone(MemoryPool *pool) const; protected: virtual void accept0(ASTVisitor *visitor); @@ -1464,9 +1487,14 @@ class CPLUSPLUS_EXPORT NewExpressionAST: public ExpressionAST public: unsigned scope_token; unsigned new_token; - ExpressionAST *expression; + NewPlacementAST *new_placement; + + unsigned lparen_token; ExpressionAST *type_id; + unsigned rparen_token; + NewTypeIdAST *new_type_id; + NewInitializerAST *new_initializer; public: @@ -1506,8 +1534,8 @@ class CPLUSPLUS_EXPORT NewTypeIdAST: public AST { public: SpecifierAST *type_specifier; - NewInitializerAST *new_initializer; - NewDeclaratorAST *new_declarator; + PtrOperatorAST *ptr_operators; + NewArrayDeclaratorAST *new_array_declarators; public: virtual NewTypeIdAST *asNewTypeId() diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h index 92fa70e55bd..3ab1fc66e9a 100644 --- a/src/shared/cplusplus/ASTVisitor.h +++ b/src/shared/cplusplus/ASTVisitor.h @@ -144,7 +144,8 @@ public: virtual bool visit(NestedDeclaratorAST *) { return true; } virtual bool visit(NestedExpressionAST *) { return true; } virtual bool visit(NestedNameSpecifierAST *) { return true; } - virtual bool visit(NewDeclaratorAST *) { return true; } + virtual bool visit(NewPlacementAST *) { return true; } + virtual bool visit(NewArrayDeclaratorAST *) { return true; } virtual bool visit(NewExpressionAST *) { return true; } virtual bool visit(NewInitializerAST *) { return true; } virtual bool visit(NewTypeIdAST *) { return true; } @@ -248,7 +249,8 @@ public: virtual void endVisit(NestedDeclaratorAST *) { } virtual void endVisit(NestedExpressionAST *) { } virtual void endVisit(NestedNameSpecifierAST *) { } - virtual void endVisit(NewDeclaratorAST *) { } + virtual void endVisit(NewPlacementAST *) { } + virtual void endVisit(NewArrayDeclaratorAST *) { } virtual void endVisit(NewExpressionAST *) { } virtual void endVisit(NewInitializerAST *) { } virtual void endVisit(NewTypeIdAST *) { } diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h index b4f5283a748..140b0820c0f 100644 --- a/src/shared/cplusplus/ASTfwd.h +++ b/src/shared/cplusplus/ASTfwd.h @@ -121,8 +121,9 @@ class NamespaceAliasDefinitionAST; class NestedDeclaratorAST; class NestedExpressionAST; class NestedNameSpecifierAST; -class NewDeclaratorAST; +class NewArrayDeclaratorAST; class NewExpressionAST; +class NewPlacementAST; class NewInitializerAST; class NewTypeIdAST; class NumericLiteralAST; diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h index 31b01bfd815..2909c0775ab 100644 --- a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h +++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h @@ -108,6 +108,7 @@ class QualifiedNameId; class FullySpecifiedType; class TypeVisitor; class Type; +class UndefinedType; class VoidType; class IntegerType; class FloatType; diff --git a/src/shared/cplusplus/CheckExpression.cpp b/src/shared/cplusplus/CheckExpression.cpp index e26a19ba805..a2b6c68677a 100644 --- a/src/shared/cplusplus/CheckExpression.cpp +++ b/src/shared/cplusplus/CheckExpression.cpp @@ -214,8 +214,9 @@ bool CheckExpression::visit(TemplateIdAST *ast) bool CheckExpression::visit(NewExpressionAST *ast) { - FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); - FullySpecifiedType typeIdTy = semantic()->check(ast->type_id, _scope); + // ### FIXME + //FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); + //FullySpecifiedType typeIdTy = semantic()->check(ast->type_id, _scope); // ### process new-typeid // ### process new-initializer return false; @@ -319,8 +320,8 @@ bool CheckExpression::visit(QtMethodAST *ast) Scope dummy; FullySpecifiedType methTy = semantic()->check(ast->declarator, FullySpecifiedType(), &dummy, &name); - Function *fty = 0; - if (! methTy || 0 == (fty = methTy->asFunctionType())) + Function *fty = methTy->asFunctionType(); + if (! fty) translationUnit()->warning(ast->firstToken(), "expected a function declarator"); else { for (unsigned i = 0; i < fty->argumentCount(); ++i) { diff --git a/src/shared/cplusplus/CheckSpecifier.cpp b/src/shared/cplusplus/CheckSpecifier.cpp index 20a3662e7b8..fddfd525689 100644 --- a/src/shared/cplusplus/CheckSpecifier.cpp +++ b/src/shared/cplusplus/CheckSpecifier.cpp @@ -200,30 +200,30 @@ bool CheckSpecifier::visit(SimpleSpecifierAST *ast) break; case T_CHAR: - if (_fullySpecifiedType.type()) + if (_fullySpecifiedType) translationUnit()->error(ast->specifier_token, "duplicate data type in declaration"); _fullySpecifiedType.setType(control()->integerType(IntegerType::Char)); break; case T_WCHAR_T: - if (_fullySpecifiedType.type()) + if (_fullySpecifiedType) translationUnit()->error(ast->specifier_token, "duplicate data type in declaration"); _fullySpecifiedType.setType(control()->integerType(IntegerType::WideChar)); break; case T_BOOL: - if (_fullySpecifiedType.type()) + if (_fullySpecifiedType) translationUnit()->error(ast->specifier_token, "duplicate data type in declaration"); _fullySpecifiedType.setType(control()->integerType(IntegerType::Bool)); break; case T_SHORT: - if (Type *tp = _fullySpecifiedType.type()) { + if (_fullySpecifiedType) { IntegerType *intType = control()->integerType(IntegerType::Int); - if (tp != intType) + if (_fullySpecifiedType.type() != intType) translationUnit()->error(ast->specifier_token, "duplicate data type in declaration"); } @@ -231,7 +231,8 @@ bool CheckSpecifier::visit(SimpleSpecifierAST *ast) break; case T_INT: - if (Type *tp = _fullySpecifiedType.type()) { + if (_fullySpecifiedType) { + Type *tp = _fullySpecifiedType.type(); IntegerType *shortType = control()->integerType(IntegerType::Short); IntegerType *longType = control()->integerType(IntegerType::Long); IntegerType *longLongType = control()->integerType(IntegerType::LongLong); @@ -244,7 +245,8 @@ bool CheckSpecifier::visit(SimpleSpecifierAST *ast) break; case T_LONG: - if (Type *tp = _fullySpecifiedType.type()) { + if (_fullySpecifiedType) { + Type *tp = _fullySpecifiedType.type(); IntegerType *intType = control()->integerType(IntegerType::Int); IntegerType *longType = control()->integerType(IntegerType::Long); FloatType *doubleType = control()->floatType(FloatType::Double); @@ -263,16 +265,16 @@ bool CheckSpecifier::visit(SimpleSpecifierAST *ast) break; case T_FLOAT: - if (_fullySpecifiedType.type()) + if (_fullySpecifiedType) translationUnit()->error(ast->specifier_token, "duplicate data type in declaration"); _fullySpecifiedType.setType(control()->floatType(FloatType::Float)); break; case T_DOUBLE: - if (Type *tp = _fullySpecifiedType.type()) { + if (_fullySpecifiedType) { IntegerType *longType = control()->integerType(IntegerType::Long); - if (tp == longType) { + if (_fullySpecifiedType.type() == longType) { _fullySpecifiedType.setType(control()->floatType(FloatType::LongDouble)); break; } @@ -283,7 +285,7 @@ bool CheckSpecifier::visit(SimpleSpecifierAST *ast) break; case T_VOID: - if (_fullySpecifiedType.type()) + if (_fullySpecifiedType) translationUnit()->error(ast->specifier_token, "duplicate data type in declaration"); _fullySpecifiedType.setType(control()->voidType()); diff --git a/src/shared/cplusplus/CoreTypes.h b/src/shared/cplusplus/CoreTypes.h index 42895f4dba3..f859fbf300b 100644 --- a/src/shared/cplusplus/CoreTypes.h +++ b/src/shared/cplusplus/CoreTypes.h @@ -61,6 +61,23 @@ CPLUSPLUS_BEGIN_HEADER CPLUSPLUS_BEGIN_NAMESPACE +class CPLUSPLUS_EXPORT UndefinedType : public Type +{ +public: + static UndefinedType *instance() + { + static UndefinedType t; + return &t; + } + + virtual bool isEqualTo(const Type *other) const + { return this == other; } + +protected: + virtual void accept0(TypeVisitor *) + { } +}; + class CPLUSPLUS_EXPORT VoidType: public Type { public: diff --git a/src/shared/cplusplus/FullySpecifiedType.cpp b/src/shared/cplusplus/FullySpecifiedType.cpp index 71dec2934bc..0afcdd0d754 100644 --- a/src/shared/cplusplus/FullySpecifiedType.cpp +++ b/src/shared/cplusplus/FullySpecifiedType.cpp @@ -52,18 +52,22 @@ #include "FullySpecifiedType.h" #include "Type.h" +#include "CoreTypes.h" CPLUSPLUS_BEGIN_NAMESPACE FullySpecifiedType::FullySpecifiedType(Type *type) : _type(type), _flags(0) -{ } +{ + if (! type) + _type = UndefinedType::instance(); +} FullySpecifiedType::~FullySpecifiedType() { } bool FullySpecifiedType::isValid() const -{ return _type != 0; } +{ return _type != UndefinedType::instance(); } Type *FullySpecifiedType::type() const { return _type; } @@ -177,7 +181,7 @@ Type &FullySpecifiedType::operator*() { return *_type; } FullySpecifiedType::operator bool() const -{ return _type != 0; } +{ return _type != UndefinedType::instance(); } const Type &FullySpecifiedType::operator*() const { return *_type; } diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index bfd2d6696a4..c5dacb08114 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -3104,37 +3104,91 @@ bool Parser::parseUnaryExpression(ExpressionAST *&node) return parsePostfixExpression(node); } +// new-placement ::= T_LPAREN expression-list T_RPAREN +bool Parser::parseNewPlacement(NewPlacementAST *&node) +{ + if (LA() == T_LPAREN) { + unsigned lparen_token = consumeToken(); + ExpressionListAST *expression_list = 0; + if (parseExpressionList(expression_list) && expression_list && LA() == T_RPAREN) { + unsigned rparen_token = consumeToken(); + NewPlacementAST *ast = new (_pool) NewPlacementAST; + ast->lparen_token = lparen_token; + ast->expression_list = expression_list; + ast->rparen_token = rparen_token; + node = ast; + return true; + } + } + + return false; +} + +// new-expression ::= T_COLON_COLON? T_NEW new-placement.opt +// new-type-id new-initializer.opt +// new-expression ::= T_COLON_COLON? T_NEW new-placement.opt +// T_LPAREN type-id T_RPAREN new-initializer.opt bool Parser::parseNewExpression(ExpressionAST *&node) { - if (LA() == T_NEW || (LA() == T_COLON_COLON && LA(2) == T_NEW)) { - NewExpressionAST *ast = new (_pool) NewExpressionAST; + if (! (LA() == T_NEW || (LA() == T_COLON_COLON && LA(2) == T_NEW))) + return false; - if (LA() == T_COLON_COLON) - ast->scope_token = consumeToken(); + NewExpressionAST *ast = new (_pool) NewExpressionAST; + if (LA() == T_COLON_COLON) + ast->scope_token = consumeToken(); - ast->new_token = consumeToken(); + ast->new_token = consumeToken(); - if (LA() == T_LPAREN) { - consumeToken(); - parseExpression(ast->expression); - if (LA() == T_RPAREN) - consumeToken(); + NewPlacementAST *new_placement = 0; + + if (parseNewPlacement(new_placement)) { + unsigned after_new_placement = cursor(); + + NewTypeIdAST *new_type_id = 0; + if (parseNewTypeId(new_type_id)) { + ast->new_placement = new_placement; + ast->new_type_id = new_type_id; + parseNewInitializer(ast->new_initializer); + // recognized new-placement.opt new-type-id new-initializer.opt + node = ast; + return true; } + rewind(after_new_placement); if (LA() == T_LPAREN) { - consumeToken(); - parseTypeId(ast->type_id); - if (LA() == T_RPAREN) - consumeToken(); - } else { - parseNewTypeId(ast->new_type_id); + unsigned lparen_token = consumeToken(); + ExpressionAST *type_id = 0; + if (parseTypeId(type_id) && LA() == T_RPAREN) { + ast->new_placement = new_placement; + ast->lparen_token = lparen_token; + ast->type_id = type_id; + ast->rparen_token = consumeToken(); + parseNewInitializer(ast->new_initializer); + node = ast; + return true; + } } - - parseNewInitializer(ast->new_initializer); - node = ast; - return true; } - return false; + + rewind(ast->new_token + 1); + + if (LA() == T_LPAREN) { + unsigned lparen_token = consumeToken(); + ExpressionAST *type_id = 0; + if (parseTypeId(type_id) && LA() == T_RPAREN) { + ast->lparen_token = lparen_token; + ast->type_id = type_id; + ast->rparen_token = consumeToken(); + parseNewInitializer(ast->new_initializer); + node = ast; + return true; + } + } + + parseNewTypeId(ast->new_type_id); + parseNewInitializer(ast->new_initializer); + node = ast; + return true; } bool Parser::parseNewTypeId(NewTypeIdAST *&node) @@ -3145,27 +3199,26 @@ bool Parser::parseNewTypeId(NewTypeIdAST *&node) NewTypeIdAST *ast = new (_pool) NewTypeIdAST; ast->type_specifier = typeSpec; - parseNewDeclarator(ast->new_declarator); + PtrOperatorAST **ptrop_it = &ast->ptr_operators; + while (parsePtrOperator(*ptrop_it)) + ptrop_it = &(*ptrop_it)->next; + NewArrayDeclaratorAST **it = &ast->new_array_declarators; + while (parseNewArrayDeclarator(*it)) + it = &(*it)->next; node = ast; return true; } -bool Parser::parseNewDeclarator(NewDeclaratorAST *&node) + +bool Parser::parseNewArrayDeclarator(NewArrayDeclaratorAST *&node) { - NewDeclaratorAST *ast = new (_pool) NewDeclaratorAST; - - PtrOperatorAST **ptr_operators_tail = &ast->ptr_operators; - while (parsePtrOperator(*ptr_operators_tail)) - ptr_operators_tail = &(*ptr_operators_tail)->next; - - while (LA() == T_LBRACKET) { // ### create the AST - consumeToken(); - ExpressionAST *expression = 0; - parseExpression(expression); - unsigned rbracket_token = 0; - match(T_RBRACKET, &rbracket_token); - } + if (LA() != T_LBRACKET) + return false; + NewArrayDeclaratorAST *ast = new (_pool) NewArrayDeclaratorAST; + ast->lbracket_token = consumeToken(); + parseExpression(ast->expression); + match(T_RBRACKET, &ast->rbracket_token); node = ast; return true; } diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h index e6a29d199e2..fbd2e7194f9 100644 --- a/src/shared/cplusplus/Parser.h +++ b/src/shared/cplusplus/Parser.h @@ -150,8 +150,9 @@ public: bool parseNestedNameSpecifierOpt(NestedNameSpecifierAST *&name, bool acceptTemplateId); bool parseNamespace(DeclarationAST *&node); bool parseNamespaceAliasDefinition(DeclarationAST *&node); - bool parseNewDeclarator(NewDeclaratorAST *&node); + bool parseNewArrayDeclarator(NewArrayDeclaratorAST *&node); bool parseNewExpression(ExpressionAST *&node); + bool parseNewPlacement(NewPlacementAST *&node); bool parseNewInitializer(NewInitializerAST *&node); bool parseNewTypeId(NewTypeIdAST *&node); bool parseOperator(OperatorAST *&node); diff --git a/src/shared/cplusplus/PrettyPrinter.cpp b/src/shared/cplusplus/PrettyPrinter.cpp index d6c604c3abb..8c00791ade1 100644 --- a/src/shared/cplusplus/PrettyPrinter.cpp +++ b/src/shared/cplusplus/PrettyPrinter.cpp @@ -764,15 +764,11 @@ bool PrettyPrinter::visit(NestedNameSpecifierAST *ast) return false; } -bool PrettyPrinter::visit(NewDeclaratorAST *ast) +bool PrettyPrinter::visit(NewArrayDeclaratorAST *ast) { - for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) { - accept(it); - if (it->next) - out << ' '; - } - if (ast->declarator) - accept(ast->declarator); + out << '['; + accept(ast->expression); + out << ']'; return false; } @@ -782,25 +778,32 @@ bool PrettyPrinter::visit(NewExpressionAST *ast) out << "::"; out << "new"; out << ' '; - if (ast->expression) { - accept(ast->expression); - if (ast->type_id) - out << ' '; - } - if (ast->type_id) { + accept(ast->new_placement); + if (ast->new_placement) + out << ' '; + if (ast->lparen_token) { + out << '('; accept(ast->type_id); - if (ast->new_type_id) - out << ' '; - } - if (ast->new_type_id) { + out << ')'; + } else { accept(ast->new_type_id); - if (ast->new_initializer) - out << ' '; } accept(ast->new_initializer); return false; } +bool PrettyPrinter::visit(NewPlacementAST *ast) +{ + out << '('; + for (ExpressionListAST *it = ast->expression_list; it; it = it->next) { + accept(it->expression); + if (it->next) + out << ", "; + } + out << ')'; + return false; +} + bool PrettyPrinter::visit(NewInitializerAST *ast) { out << '('; @@ -812,18 +815,16 @@ bool PrettyPrinter::visit(NewInitializerAST *ast) bool PrettyPrinter::visit(NewTypeIdAST *ast) { for (SpecifierAST *it = ast->type_specifier; it; it = it->next) { + if (it != ast->type_specifier) + out << ' '; accept(it); - if (it->next) - out << ' '; } - if (ast->type_specifier) - out << ' '; - if (ast->new_initializer) { - accept(ast->new_initializer); - if (ast->new_declarator) - out << ' '; + for (PtrOperatorAST *it = ast->ptr_operators; it; it = it->next) { + accept(it); + } + for (NewArrayDeclaratorAST *it = ast->new_array_declarators; it; it = it->next) { + accept(it); } - accept(ast->new_declarator); return false; } diff --git a/src/shared/cplusplus/PrettyPrinter.h b/src/shared/cplusplus/PrettyPrinter.h index c69ea2cf544..f20b8e360d6 100644 --- a/src/shared/cplusplus/PrettyPrinter.h +++ b/src/shared/cplusplus/PrettyPrinter.h @@ -106,7 +106,8 @@ protected: virtual bool visit(NestedDeclaratorAST *ast); virtual bool visit(NestedExpressionAST *ast); virtual bool visit(NestedNameSpecifierAST *ast); - virtual bool visit(NewDeclaratorAST *ast); + virtual bool visit(NewArrayDeclaratorAST *ast); + virtual bool visit(NewPlacementAST *ast); virtual bool visit(NewExpressionAST *ast); virtual bool visit(NewInitializerAST *ast); virtual bool visit(NewTypeIdAST *ast); diff --git a/src/shared/cplusplus/Scope.cpp b/src/shared/cplusplus/Scope.cpp index efb6a369aec..200406b6bb5 100644 --- a/src/shared/cplusplus/Scope.cpp +++ b/src/shared/cplusplus/Scope.cpp @@ -217,7 +217,7 @@ void Scope::enterSymbol(Symbol *symbol) Symbol *Scope::lookat(Identifier *id) const { - if (! _hash) + if (! _hash || ! id) return 0; const unsigned h = id->hashCode() % _hashSize; diff --git a/src/shared/cplusplus/Type.cpp b/src/shared/cplusplus/Type.cpp index 52d51b57bdb..b88b0afab48 100644 --- a/src/shared/cplusplus/Type.cpp +++ b/src/shared/cplusplus/Type.cpp @@ -63,6 +63,9 @@ Type::Type() Type::~Type() { } +bool Type::isUndefinedType() const +{ return this == UndefinedType::instance(); } + bool Type::isVoidType() const { return asVoidType() != 0; } diff --git a/src/shared/cplusplus/Type.h b/src/shared/cplusplus/Type.h index dd22c982c24..320555b40cf 100644 --- a/src/shared/cplusplus/Type.h +++ b/src/shared/cplusplus/Type.h @@ -67,6 +67,7 @@ public: Type(); virtual ~Type(); + bool isUndefinedType() const; bool isVoidType() const; bool isIntegerType() const; bool isFloatType() const; diff --git a/tests/auto/cplusplus/ast/tst_ast.cpp b/tests/auto/cplusplus/ast/tst_ast.cpp index 689da076ea1..e4ef03211d0 100644 --- a/tests/auto/cplusplus/ast/tst_ast.cpp +++ b/tests/auto/cplusplus/ast/tst_ast.cpp @@ -42,6 +42,8 @@ private slots: // expressions void simple_name(); void template_id(); + void new_expression_1(); + void new_expression_2(); // statements void if_statement(); @@ -91,6 +93,59 @@ void tst_AST::template_id() QCOMPARE(ast->asTemplateId()->greater_token, 4U); } +void tst_AST::new_expression_1() +{ + QSharedPointer unit(parseExpression("\n" +"new char" + )); + + AST *ast = unit->ast(); + QVERIFY(ast != 0); + + NewExpressionAST *expr = ast->asNewExpression(); + QVERIFY(expr != 0); + + QCOMPARE(expr->scope_token, 0U); + QCOMPARE(expr->new_token, 1U); + QVERIFY(expr->new_placement == 0); + QCOMPARE(expr->lparen_token, 0U); + QVERIFY(expr->type_id == 0); + QCOMPARE(expr->rparen_token, 0U); + QVERIFY(expr->new_type_id != 0); + QVERIFY(expr->new_initializer == 0); + + QVERIFY(expr->new_type_id->type_specifier != 0); + QVERIFY(expr->new_type_id->ptr_operators == 0); + QVERIFY(expr->new_type_id->new_array_declarators == 0); +} + +void tst_AST::new_expression_2() +{ + QSharedPointer unit(parseStatement("\n" +"::new(__p) _Tp(__val);" + )); + + AST *ast = unit->ast(); + QVERIFY(ast != 0); + + ExpressionStatementAST *stmt = ast->asExpressionStatement(); + QVERIFY(stmt != 0); + QVERIFY(stmt->expression != 0); + QVERIFY(stmt->semicolon_token != 0); + + NewExpressionAST *expr = stmt->expression->asNewExpression(); + QVERIFY(expr != 0); + + QCOMPARE(expr->scope_token, 1U); + QCOMPARE(expr->new_token, 2U); + QVERIFY(expr->new_placement != 0); + QCOMPARE(expr->lparen_token, 0U); + QVERIFY(expr->type_id == 0); + QCOMPARE(expr->rparen_token, 0U); + QVERIFY(expr->new_type_id != 0); + QVERIFY(expr->new_initializer != 0); +} + void tst_AST::if_statement() { QSharedPointer unit(parseStatement("if (a) b;"));