diff --git a/dist/changes-1.2.1 b/dist/changes-1.2.1 new file mode 100644 index 0000000000000000000000000000000000000000..52ee6f6e9611cc29e13d5186a8da77c12714f211 --- /dev/null +++ b/dist/changes-1.2.1 @@ -0,0 +1,28 @@ +The QtCreator 1.2.1 release is a bug fix release and updates translations. + +Below is a list of relevant changes. You can find a complete list of changes +within the logs of Qt Creator's sources. Simply check it out from the public git +repository e.g., + +git clone git://gitorious.org/qt-creator/qt-creator.git +git log --pretty=oneline v1.2.0..v1.2.1 + +Building and Running + * Fixed crash when clicking on the Build Settings tab with an invalid Qt version. + * Fixed crash when removing an active .pro file outside Qt Creator. + +Editor + * Fixed crash when completing function-like arguments + +Debugging + * Fixed problem with GDB debugging after first debugging run + * Fixed display of debugging helper status in some cases + * Disallow starting CDB debugger more than once + * Additional debug output for the CDB debugger + * Make loading debugging helpers more reliable with GDB + * Fixed regression in QVariant dumper + * Removed QtGui dependency from debugging helpers + * Made it possible to build the debugging helpers for Qt 4.4 again + +I18N: + * Fixed Russian translation diff --git a/doc/examples/addressbook-sdk/part7/addressbook.cpp b/doc/examples/addressbook-sdk/part7/addressbook.cpp index de35f5ac738bebdd1a7a75d9055fc8399ef33589..63d52a65a95498f54dd51844ad39ebd9444aa3bf 100644 --- a/doc/examples/addressbook-sdk/part7/addressbook.cpp +++ b/doc/examples/addressbook-sdk/part7/addressbook.cpp @@ -5,9 +5,325 @@ AddressBook::AddressBook(QWidget *parent) : QWidget(parent), ui(new Ui::AddressBook) { ui->setupUi(this); + + nameLine = new QLineEdit; + nameLine = ui->nameLine; + nameLine->setReadOnly(true); + + addressText = new QTextEdit; + addressText = ui->addressText; + addressText->setReadOnly(true); + + addButton = new QPushButton; + addButton = ui->addButton; + + submitButton = new QPushButton; + submitButton = ui->submitButton; + submitButton->hide(); + + cancelButton = new QPushButton; + cancelButton = ui->cancelButton; + cancelButton->hide(); + + nextButton = new QPushButton; + nextButton = ui->nextButton; + nextButton->setEnabled(false); + + previousButton = new QPushButton; + previousButton = ui->previousButton; + previousButton->setEnabled(false); + + editButton = new QPushButton; + editButton = ui->editButton; + editButton->setEnabled(false); + + removeButton = new QPushButton; + removeButton = ui->removeButton; + removeButton->setEnabled(false); + + findButton = new QPushButton; + findButton = ui->findButton; + + dialog = new FindDialog; + + loadButton = new QPushButton; + loadButton = ui->loadButton; + + saveButton = new QPushButton; + saveButton = ui->saveButton; + + connect(addButton, SIGNAL(clicked()), this, + SLOT(addContact())); + connect(submitButton, SIGNAL(clicked()), this, + SLOT(submitContact())); + connect(cancelButton, SIGNAL(clicked()), this, + SLOT(cancel())); + connect(nextButton, SIGNAL(clicked()), this, + SLOT(next())); + connect(previousButton, SIGNAL(clicked()), this, + SLOT(previous())); + connect(editButton, SIGNAL(clicked()), this, + SLOT(editContact())); + connect(removeButton, SIGNAL(clicked()), this, + SLOT(removeContact())); + connect(findButton, SIGNAL(clicked()), this, + SLOT(findContact())); + + setWindowTitle(tr("Simple Address Book")); } AddressBook::~AddressBook() { delete ui; } + +void AddressBook::addContact() +{ + oldName = nameLine->text(); + oldAddress = addressText->toPlainText(); + + nameLine->clear(); + addressText->clear(); + + updateInterface(AddingMode); +} + +void AddressBook::submitContact() +{ + QString name = nameLine->text(); + QString address = addressText->toPlainText(); + + if (name == "" || address == "") { + QMessageBox::information(this, tr("Empty Field"), + tr("Please enter a name and address.")); + } + + if (currentMode == AddingMode) { + + if (!contacts.contains(name)) { + contacts.insert(name, address); + QMessageBox::information(this, tr("Add Successful"), + tr("\"%1\" has been added to your address book.").arg(name)); + } else { + QMessageBox::information(this, tr("Add Unsuccessful"), + tr("Sorry, \"%1\" is already in your address book.").arg(name)); + } + + } else if (currentMode == EditingMode) { + + if (oldName != name) { + if (!contacts.contains(name)) { + QMessageBox::information(this, tr("Edit Successful"), + tr("\"%1\" has been edited in your address book.").arg(oldName)); + contacts.remove(oldName); + contacts.insert(name, address); + } else { + QMessageBox::information(this, tr("Edit Unsuccessful"), + tr("Sorry, \"%1\" is already in your address book.").arg(name)); + } + } else if (oldAddress != address) { + QMessageBox::information(this, tr("Edit Successful"), + tr("\"%1\" has been edited in your address book.").arg(name)); + contacts[name] = address; + } + } + updateInterface(NavigationMode); +} + +void AddressBook::cancel() +{ + nameLine->setText(oldName); + nameLine->setReadOnly(true); + + updateInterface(NavigationMode); +} + +void AddressBook::next() +{ + QString name = nameLine->text(); + QMap<QString, QString>::iterator i = contacts.find(name); + + if (i != contacts.end()) + i++; + if (i == contacts.end()) + i = contacts.begin(); + + nameLine->setText(i.key()); + addressText->setText(i.value()); +} + +void AddressBook::previous() +{ + QString name = nameLine->text(); + QMap<QString, QString>::iterator i = contacts.find(name); + + if (i == contacts.end()) { + nameLine->clear(); + addressText->clear(); + return; + } + + if (i == contacts.begin()) + i = contacts.end(); + + i--; + nameLine->setText(i.key()); + addressText->setText(i.value()); +} + +void AddressBook::editContact() +{ + oldName = nameLine->text(); + oldAddress = addressText->toPlainText(); + + updateInterface(EditingMode); +} + +void AddressBook::removeContact() +{ + QString name = nameLine->text(); + QString address = addressText->toPlainText(); + + if (contacts.contains(name)) { + int button = QMessageBox::question(this, + tr("Confirm Remove"), + tr("Are you sure you want to remove \"%1\"?").arg(name), + QMessageBox::Yes | QMessageBox::No); + + if (button == QMessageBox::Yes) { + previous(); + contacts.remove(name); + + QMessageBox::information(this, tr("Remove Successful"), + tr("\"%1\" has been removed from your address book.").arg(name)); + } + } + + updateInterface(NavigationMode); +} + +void AddressBook::updateInterface(Mode mode) +{ + currentMode = mode; + + switch (currentMode) { + + case AddingMode: + case EditingMode: + + nameLine->setReadOnly(false); + nameLine->setFocus(Qt::OtherFocusReason); + addressText->setReadOnly(false); + + addButton->setEnabled(false); + editButton->setEnabled(false); + removeButton->setEnabled(false); + + nextButton->setEnabled(false); + previousButton->setEnabled(false); + + submitButton->show(); + cancelButton->show(); + break; + + case NavigationMode: + + if (contacts.isEmpty()) { + nameLine->clear(); + addressText->clear(); + } + + nameLine->setReadOnly(true); + addressText->setReadOnly(true); + addButton->setEnabled(true); + + int number = contacts.size(); + editButton->setEnabled(number >= 1); + removeButton->setEnabled(number >= 1); + findButton->setEnabled(number > 2); + nextButton->setEnabled(number > 1); + previousButton->setEnabled(number >1); + + submitButton->hide(); + cancelButton->hide(); + break; + } +} + +void AddressBook::findContact() +{ + dialog->show(); + + if (dialog->exec() == QDialog::Accepted) { + QString contactName = dialog->getFindText(); + + if (contacts.contains(contactName)) { + nameLine->setText(contactName); + addressText->setText(contacts.value(contactName)); + } else { + QMessageBox::information(this, tr("Contact Not Found"), + tr("Sorry, \"%1\" is not in your address book.").arg(contactName)); + return; + } + } + + updateInterface(NavigationMode); +} + +void AddressBook::saveToFile() +{ + QString fileName = QFileDialog::getSaveFileName(this, + tr("Save Address Book"), "", + tr("Address book (*.abk);; AllFiles (*)")); + + if (fileName.isEmpty()) + return; + else { + QFile file(fileName); + + if (!file.open(QIODevice::WriteOnly)) { + QMessageBox::information(this, tr("Unable to open file"), + file.errorString()); + return; + } + + QDataStream out(&file); + out.setVersion(QDataStream::Qt_4_5); + out << contacts; + } +} + +void AddressBook::loadFromFile() +{ + QString fileName = QFileDialog::getOpenFileName(this, + tr("Open Address Book"), "", + tr("Address Book(*.abk);; All Files(*)")); + + if (fileName.isEmpty()) + return; + else { + QFile file(fileName); + + if (!file.open(QIODevice::ReadOnly)) { + QMessageBox::information(this, tr("Unable to open file"), + file.errorString()); + return; + } + + QDataStream in(&file); + in.setVersion(QDataStream::Qt_4_5); + contacts.empty(); // empty existing contacts + in >> contacts; + + if (contacts.isEmpty()) { + QMessagebox::information(this, tr("No contacts in file"), + tr("The file you are attempting to open contains no contacts.")); + } else { + QMap<QString, QString>::iterator i = contacts.begin(); + nameLine->setText(i.key()); + addressText->setText(i.value()); + } + } + + updateInterface(NavigationMode); +} diff --git a/doc/examples/addressbook-sdk/part7/addressbook.h b/doc/examples/addressbook-sdk/part7/addressbook.h index b85a0acddbfc7bc458b2e218cc73089f33cfe543..0e4048a63d77173070f318e06484f7ce1617c0d0 100644 --- a/doc/examples/addressbook-sdk/part7/addressbook.h +++ b/doc/examples/addressbook-sdk/part7/addressbook.h @@ -2,6 +2,11 @@ #define ADDRESSBOOK_H #include <QtGui/QWidget> +#include <QtGui/QPushButton> +#include <QtGui/QLineEdit> +#include <QtGui/QTextEdit> +#include <QtGui/QMessageBox> +#include "finddialog.h" namespace Ui { @@ -14,10 +19,43 @@ class AddressBook : public QWidget public: AddressBook(QWidget *parent = 0); + enum Mode { NavigationMode, AddingMode, EditingMode }; ~AddressBook(); +public slots: + void addContact(); + void submitContact(); + void cancel(); + void editContact(); + void removeContact(); + void next(); + void previous(); + void findContact(); + void saveToFile(); + void loadFromFile(); + private: Ui::AddressBook *ui; + + void updateInterface(Mode mode); + QPushButton *addButton; + QPushButton *submitButton; + QPushButton *cancelButton; + QPushButton *editButton; + QPushButton *removeButton; + QPushButton *nextButton; + QPushButton *previousButton; + QPushButton *findButton; + QPushButton *loadButton; + QPushButton *saveButton; + QLineEdit *nameLine; + QTextEdit *addressText; + + QMap<QString, QString> contacts; + QString oldName; + QString oldAddress; + Mode currentMode; + FindDialog *dialog; }; #endif // ADDRESSBOOK_H diff --git a/doc/examples/addressbook-sdk/part7/addressbook.ui b/doc/examples/addressbook-sdk/part7/addressbook.ui index 7b771cc37b5055068b2ba1a365085b6f66465897..f46c9c396976369327bc8f3ae9ad0c43d03511e5 100644 --- a/doc/examples/addressbook-sdk/part7/addressbook.ui +++ b/doc/examples/addressbook-sdk/part7/addressbook.ui @@ -1,7 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>AddressBook</class> - <widget class="QWidget" name="AddressBook" > - <property name="geometry" > + <widget class="QWidget" name="AddressBook"> + <property name="geometry"> <rect> <x>0</x> <y>0</y> @@ -9,12 +10,137 @@ <height>400</height> </rect> </property> - <property name="windowTitle" > + <property name="windowTitle"> <string>AddressBook</string> </property> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="nameLabel"> + <property name="text"> + <string>Name:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="nameLine"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="addressLabel"> + <property name="text"> + <string>Address:</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QTextEdit" name="addressText"/> + </item> + <item row="1" column="2"> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QPushButton" name="addButton"> + <property name="text"> + <string>Add</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="submitButton"> + <property name="text"> + <string>Submit</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="cancelButton"> + <property name="text"> + <string>Cancel</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="editButton"> + <property name="text"> + <string>Edit</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="removeButton"> + <property name="text"> + <string>Remove</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="findButton"> + <property name="text"> + <string>Find</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="loadButton"> + <property name="toolTip"> + <string>Load contacts from a file</string> + </property> + <property name="text"> + <string>Load...</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="saveButton"> + <property name="toolTip"> + <string>Save contacts to a file</string> + </property> + <property name="text"> + <string>Save...</string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="2" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QPushButton" name="nextButton"> + <property name="text"> + <string>Previous</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="previousButton"> + <property name="text"> + <string>Next</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </item> + </layout> </widget> - <layoutDefault spacing="6" margin="11" /> - <pixmapfunction></pixmapfunction> + <layoutdefault spacing="6" margin="11"/> <resources/> <connections/> </ui> diff --git a/doc/examples/addressbook-sdk/part7/part7.pro b/doc/examples/addressbook-sdk/part7/part7.pro index 9fc496316211066ac2473b95462de208ea143be6..efdbe0bb6e37d30c099a23082140668cca91e7e5 100644 --- a/doc/examples/addressbook-sdk/part7/part7.pro +++ b/doc/examples/addressbook-sdk/part7/part7.pro @@ -1,16 +1,12 @@ -#------------------------------------------------- -# +# ------------------------------------------------- # Project created by QtCreator 2009-07-07T17:10:19 -# -#------------------------------------------------- - +# ------------------------------------------------- TARGET = part7 TEMPLATE = app - - -SOURCES += main.cpp\ - addressbook.cpp - -HEADERS += addressbook.h - -FORMS += addressbook.ui +SOURCES += main.cpp \ + addressbook.cpp \ + finddialog.cpp +HEADERS += addressbook.h \ + finddialog.h +FORMS += addressbook.ui \ + finddialog.ui diff --git a/src/libs/cplusplus/CppBindings.cpp b/src/libs/cplusplus/CppBindings.cpp index 488f8b97cc6048126a20762cd2906a2e5d8ab021..ba5c37754ee68cfa88b630d7793333bc6f939f02 100644 --- a/src/libs/cplusplus/CppBindings.cpp +++ b/src/libs/cplusplus/CppBindings.cpp @@ -82,7 +82,7 @@ NamespaceBinding::~NamespaceBinding() NameId *NamespaceBinding::name() const { if (symbols.size()) { - if (Name *name = symbols.at(0)->name()) { + if (Name *name = symbols.first()->name()) { NameId *nameId = name->asNameId(); Q_ASSERT(nameId != 0); @@ -113,20 +113,100 @@ NamespaceBinding *NamespaceBinding::globalNamespaceBinding() return it; } +Binding *NamespaceBinding::findClassOrNamespaceBinding(Identifier *id) +{ + if (id->isEqualTo(identifier())) + return const_cast<NamespaceBinding *>(this); + + foreach (NamespaceBinding *nestedNamespaceBinding, children) { + if (id->isEqualTo(nestedNamespaceBinding->identifier())) + return nestedNamespaceBinding; + } + + foreach (ClassBinding *classBinding, classBindings) { + if (id->isEqualTo(classBinding->identifier())) + return classBinding; + } + + foreach (NamespaceBinding *u, usings) { + if (Binding *b = u->findClassOrNamespaceBinding(id)) + return b; + } + + if (parent) + return parent->findClassOrNamespaceBinding(id); + + return 0; +} + +ClassBinding *NamespaceBinding::findClassBinding(Name *name) +{ + if (! name) + return 0; + + Identifier *id = name->identifier(); + + foreach (ClassBinding *classBinding, classBindings) { + if (id->isEqualTo(classBinding->identifier())) + return classBinding; + } + + if (parent) + return parent->findClassBinding(name); + + return 0; +} + NamespaceBinding *NamespaceBinding::findNamespaceBinding(Name *name) { if (! name) return anonymousNamespaceBinding; else if (NameId *nameId = name->asNameId()) - return findNamespaceBindingForNameId(nameId); + return findNamespaceBindingForNameId(nameId, /*lookAtParent = */ true); + + else if (const QualifiedNameId *q = name->asQualifiedNameId()) { + NamespaceBinding *current = this; + + for (unsigned i = 0; i < q->nameCount(); ++i) { + NameId *namespaceName = q->nameAt(i)->asNameId(); + if (! namespaceName) + return 0; + + bool lookAtParent = false; + if (i == 0) + lookAtParent = true; + + NamespaceBinding *binding = current->findNamespaceBindingForNameId(namespaceName, lookAtParent); + if (! binding) + return 0; + + current = binding; + } + + return current; + } // invalid binding return 0; } -NamespaceBinding *NamespaceBinding::findNamespaceBindingForNameId(NameId *name) +NamespaceBinding *NamespaceBinding::findNamespaceBindingForNameId(NameId *name, + bool lookAtParentNamespace) { + QSet<NamespaceBinding *> processed; + return findNamespaceBindingForNameId_helper(name, lookAtParentNamespace, &processed); +} + +NamespaceBinding *NamespaceBinding::findNamespaceBindingForNameId_helper(NameId *name, + bool lookAtParentNamespace, + QSet<NamespaceBinding *> *processed) +{ + if (processed->contains(this)) + return 0; + + processed->insert(this); + foreach (NamespaceBinding *binding, children) { Name *bindingName = binding->name(); @@ -139,6 +219,15 @@ NamespaceBinding *NamespaceBinding::findNamespaceBindingForNameId(NameId *name) } } + foreach (NamespaceBinding *u, usings) { + if (NamespaceBinding *b = u->findNamespaceBindingForNameId_helper(name, lookAtParentNamespace, processed)) { + return b; + } + } + + if (lookAtParentNamespace && parent) + return parent->findNamespaceBindingForNameId_helper(name, lookAtParentNamespace, processed); + return 0; } @@ -239,7 +328,7 @@ NamespaceBinding *NamespaceBinding::resolveNamespace(const Location &loc, else if (parent && lookAtParent) return parent->resolveNamespace(loc, name); - } else if (QualifiedNameId *q = name->asQualifiedNameId()) { + } else if (const QualifiedNameId *q = name->asQualifiedNameId()) { if (q->nameCount() == 1) { Q_ASSERT(q->isGlobal()); @@ -295,6 +384,74 @@ QByteArray ClassBinding::qualifiedId() const return s; } +Binding *ClassBinding::findClassOrNamespaceBinding(Identifier *id) +{ + if (id->isEqualTo(identifier())) + return this; + + foreach (ClassBinding *nestedClassBinding, children) { + if (id->isEqualTo(nestedClassBinding->identifier())) + return nestedClassBinding; + } + + foreach (ClassBinding *baseClassBinding, baseClassBindings) { + if (! baseClassBinding) + continue; + else if (Binding *b = baseClassBinding->findClassOrNamespaceBinding(id)) + return b; + } + + if (parent) + return parent->findClassOrNamespaceBinding(id); + + return 0; +} + +ClassBinding *ClassBinding::findClassBinding(Name *name) +{ + if (! name) + return 0; + + if (const QualifiedNameId *q = name->asQualifiedNameId()) { + Binding *currentBinding = this; + + for (unsigned i = 0; i < q->nameCount() - 1; ++i) { + Identifier *id = q->nameAt(i)->identifier(); + if (! id) + return 0; + + Binding *classOrNamespaceBinding = currentBinding->findClassOrNamespaceBinding(id); + + if (! classOrNamespaceBinding) + return 0; + + currentBinding = classOrNamespaceBinding; + } + + if (currentBinding) + return currentBinding->findClassBinding(q->unqualifiedNameId()); + + return 0; + } + + if (Identifier *id = name->identifier()) { + if (id->isEqualTo(identifier())) + return this; + + foreach (ClassBinding *nestedClassBinding, children) { + if (Identifier *nestedClassId = nestedClassBinding->identifier()) { + if (nestedClassId->isEqualTo(id)) + return nestedClassBinding; + } + } + + if (parent) + return parent->findClassBinding(name); + } + + return 0; +} + static int depth; void NamespaceBinding::dump() @@ -339,30 +496,26 @@ ClassBinding::ClassBinding(NamespaceBinding *parent) } ClassBinding::ClassBinding(ClassBinding *parentClass) + : parent(parentClass) { - parent = parentClass->parent; parentClass->children.append(this); } ClassBinding::~ClassBinding() { qDeleteAll(children); } -NameId *ClassBinding::name() const +Name *ClassBinding::name() const { - if (symbols.size()) { - if (Name *name = symbols.at(0)->name()) { - NameId *nameId = name->asNameId(); - return nameId; - } - } + if (symbols.isEmpty()) + return 0; - return 0; + return symbols.first()->name(); } Identifier *ClassBinding::identifier() const { - if (NameId *nameId = name()) - return nameId->identifier(); + if (Name *n = name()) + return n->identifier(); return 0; } @@ -497,7 +650,14 @@ ClassBinding *Binder::findOrCreateClassBinding(Class *classSymbol) ClassBinding *Binder::findClassBinding(Name *name) { - qDebug() << Q_FUNC_INFO; + if (classBinding) { + if (ClassBinding *k = classBinding->findClassBinding(name)) + return k; + } + + if (namespaceBinding) + return namespaceBinding->findClassBinding(name); + return 0; } @@ -540,16 +700,11 @@ bool Binder::visit(Class *classSymbol) ClassBinding *binding = findOrCreateClassBinding(classSymbol); ClassBinding *previousClassBinding = switchClassBinding(binding); -#if 0 for (unsigned i = 0; i < classSymbol->baseClassCount(); ++i) { BaseClass *baseClass = classSymbol->baseClassAt(i); - ClassBinding *baseClassBinding = findClassBinding(baseClass->name()); - - // ### wrong binding->baseClassBindings.append(baseClassBinding); } -#endif for (unsigned i = 0; i < classSymbol->memberCount(); ++i) accept(classSymbol->memberAt(i)); @@ -568,12 +723,10 @@ bool Binder::visit(Block *) } // end of anonymous namespace static NamespaceBinding *find_helper(Namespace *symbol, NamespaceBinding *binding, - QSet<QByteArray> *processed) + QSet<NamespaceBinding *> *processed) { - const QByteArray id = binding->qualifiedId(); - - if (! processed->contains(id)) { - processed->insert(id); + if (binding && ! processed->contains(binding)) { + processed->insert(binding); if (binding->symbols.contains(symbol)) return binding; @@ -582,6 +735,50 @@ static NamespaceBinding *find_helper(Namespace *symbol, NamespaceBinding *bindin if (NamespaceBinding *ns = find_helper(symbol, nestedBinding, processed)) return ns; } + + if (NamespaceBinding *a = find_helper(symbol, binding->anonymousNamespaceBinding, processed)) + return a; + } + + return 0; +} + +static ClassBinding *find_helper(Class *symbol, Binding *binding, + QSet<Binding *> *processed) +{ + if (binding && ! processed->contains(binding)) { + processed->insert(binding); + + if (NamespaceBinding *namespaceBinding = binding->asNamespaceBinding()) { + foreach (ClassBinding *classBinding, namespaceBinding->classBindings) { + if (ClassBinding *c = find_helper(symbol, classBinding, processed)) + return c; + } + + foreach (NamespaceBinding *nestedBinding, namespaceBinding->children) { + if (ClassBinding *c = find_helper(symbol, nestedBinding, processed)) + return c; + } + + if (ClassBinding *a = find_helper(symbol, namespaceBinding->anonymousNamespaceBinding, processed)) + return a; + + } else if (ClassBinding *classBinding = binding->asClassBinding()) { + foreach (Class *klass, classBinding->symbols) { + if (klass == symbol) + return classBinding; + } + + foreach (ClassBinding *nestedClassBinding, classBinding->children) { + if (ClassBinding *c = find_helper(symbol, nestedClassBinding, processed)) + return c; + } + +#if 0 // ### FIXME + if (ClassBinding *a = find_helper(symbol, classBinding->anonymousClassBinding, processed)) + return a; +#endif + } } return 0; @@ -589,7 +786,13 @@ static NamespaceBinding *find_helper(Namespace *symbol, NamespaceBinding *bindin NamespaceBinding *NamespaceBinding::find(Namespace *symbol, NamespaceBinding *binding) { - QSet<QByteArray> processed; + QSet<NamespaceBinding *> processed; + return find_helper(symbol, binding, &processed); +} + +ClassBinding *NamespaceBinding::find(Class *symbol, NamespaceBinding *binding) +{ + QSet<Binding *> processed; return find_helper(symbol, binding, &processed); } diff --git a/src/libs/cplusplus/CppBindings.h b/src/libs/cplusplus/CppBindings.h index 86029e105ba4b34509134f716ce9b2502f489262..be5933e2c204f9c494b4f669563f1ae95b1bbeb3 100644 --- a/src/libs/cplusplus/CppBindings.h +++ b/src/libs/cplusplus/CppBindings.h @@ -80,8 +80,12 @@ public: Binding() {} virtual ~Binding() {} + virtual QByteArray qualifiedId() const = 0; virtual NamespaceBinding *asNamespaceBinding() { return 0; } virtual ClassBinding *asClassBinding() { return 0; } + + virtual ClassBinding *findClassBinding(Name *name) = 0; + virtual Binding *findClassOrNamespaceBinding(Identifier *id) = 0; }; class CPLUSPLUS_EXPORT NamespaceBinding: public Binding @@ -112,16 +116,25 @@ public: Name *name, bool lookAtParent = true); + virtual ClassBinding *findClassBinding(Name *name); + virtual Binding *findClassOrNamespaceBinding(Identifier *id); + /// Helpers. - QByteArray qualifiedId() const; + virtual QByteArray qualifiedId() const; void dump(); virtual NamespaceBinding *asNamespaceBinding() { return this; } static NamespaceBinding *find(Namespace *symbol, NamespaceBinding *binding); + static ClassBinding *find(Class *symbol, NamespaceBinding *binding); private: - NamespaceBinding *findNamespaceBindingForNameId(NameId *name); + NamespaceBinding *findNamespaceBindingForNameId(NameId *name, + bool lookAtParentNamespace); + + NamespaceBinding *findNamespaceBindingForNameId_helper(NameId *name, + bool lookAtParentNamespace, + QSet<NamespaceBinding *> *processed); public: // attributes /// This binding's parent. @@ -152,17 +165,19 @@ public: virtual ClassBinding *asClassBinding() { return this; } /// Returns this binding's name. - NameId *name() const; + Name *name() const; /// Returns this binding's identifier. Identifier *identifier() const; + virtual QByteArray qualifiedId() const; - QByteArray qualifiedId() const; + virtual ClassBinding *findClassBinding(Name *name); + virtual Binding *findClassOrNamespaceBinding(Identifier *id); void dump(); public: // attributes - NamespaceBinding *parent; + Binding *parent; QList<ClassBinding *> children; diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 7f53de1ed5f7466af135c53a0fb983abc794a8c4..51bfef0443f513bfa92373a89d5e70107c459ef5 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -343,9 +343,34 @@ bool ResolveExpression::visit(SizeofExpressionAST *) return false; } -bool ResolveExpression::visit(NumericLiteralAST *) -{ - FullySpecifiedType ty(control()->integerType(IntegerType::Int)); +bool ResolveExpression::visit(NumericLiteralAST *ast) +{ + Type *type = 0; + NumericLiteral *literal = numericLiteral(ast->literal_token); + + if (literal->isChar()) + type = control()->integerType(IntegerType::Char); + else if (literal->isWideChar()) + type = control()->integerType(IntegerType::WideChar); + else if (literal->isInt()) + type = control()->integerType(IntegerType::Int); + else if (literal->isLong()) + type = control()->integerType(IntegerType::Long); + else if (literal->isLongLong()) + type = control()->integerType(IntegerType::LongLong); + else if (literal->isFloat()) + type = control()->floatType(FloatType::Float); + else if (literal->isDouble()) + type = control()->floatType(FloatType::Double); + else if (literal->isLongDouble()) + type = control()->floatType(FloatType::LongDouble); + else + type = control()->integerType(IntegerType::Int); + + FullySpecifiedType ty(type); + if (literal->isUnsigned()) + ty.setUnsigned(true); + addResult(ty); return false; } diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 5be562dcfa23e0aff44f1f171212261142c84d01..35ddf3ace8209aeed273ce2e4e8d2fbff518ad42 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -240,7 +240,7 @@ protected: bool process_primary() { - if ((*_lex)->is(T_INT_LITERAL)) { + if ((*_lex)->is(T_NUMERIC_LITERAL)) { int base = 10; const QByteArray spell = tokenSpell(); if (spell.at(0) == '0') { diff --git a/src/plugins/cppeditor/cpphighlighter.cpp b/src/plugins/cppeditor/cpphighlighter.cpp index 4a60414ba11d7ca0b131f7e7ce6a888bc5a9fbe6..2f016c4d37d6f6c26d535e0c0f4b9cd5362875ff 100644 --- a/src/plugins/cppeditor/cpphighlighter.cpp +++ b/src/plugins/cppeditor/cpphighlighter.cpp @@ -125,7 +125,7 @@ void CppHighlighter::highlightBlock(const QString &text) (tk.isKeyword() || tk.is(T_IDENTIFIER)) && isPPKeyword(tk.text())) setFormat(tk.position(), tk.length(), m_formats[CppPreprocessorFormat]); - else if (tk.is(T_INT_LITERAL) || tk.is(T_FLOAT_LITERAL)) + else if (tk.is(T_NUMERIC_LITERAL)) setFormat(tk.position(), tk.length(), m_formats[CppNumberFormat]); else if (tk.is(T_STRING_LITERAL) || tk.is(T_CHAR_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL) || diff --git a/src/plugins/debugger/cdb/cdbstackframecontext.cpp b/src/plugins/debugger/cdb/cdbstackframecontext.cpp deleted file mode 100644 index f68beb0db3cccc1b114f87a3311be4f9009ce912..0000000000000000000000000000000000000000 --- a/src/plugins/debugger/cdb/cdbstackframecontext.cpp +++ /dev/null @@ -1,354 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** Commercial Usage -** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. -** -** 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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. -** -**************************************************************************/ - -#include "cdbstackframecontext.h" -#include "cdbdebugengine_p.h" -#include "cdbsymbolgroupcontext.h" -#include "cdbdumperhelper.h" -#include "debuggeractions.h" -#include "watchhandler.h" - -#include <QtCore/QDebug> -#include <QtCore/QCoreApplication> - -namespace Debugger { -namespace Internal { - -enum { OwnerNewItem, OwnerSymbolGroup, OwnerDumper }; - -typedef QSharedPointer<CdbDumperHelper> SharedPointerCdbDumperHelper; -typedef QList<WatchData> WatchDataList; - -// Predicates for parametrizing the symbol group -inline bool truePredicate(const WatchData & /* whatever */) { return true; } -inline bool falsePredicate(const WatchData & /* whatever */) { return false; } -inline bool isDumperPredicate(const WatchData &wd) -{ return wd.source == OwnerDumper; } - -// Match an item that is expanded in the watchhandler. -class WatchHandlerExpandedPredicate { -public: - explicit inline WatchHandlerExpandedPredicate(const WatchHandler *wh) : m_wh(wh) {} - inline bool operator()(const WatchData &wd) { return m_wh->isExpandedIName(wd.iname); } -private: - const WatchHandler *m_wh; -}; - -// Match an item by iname -class MatchINamePredicate { -public: - explicit inline MatchINamePredicate(const QString &iname) : m_iname(iname) {} - inline bool operator()(const WatchData &wd) { return wd.iname == m_iname; } -private: - const QString &m_iname; -}; - -// Put a sequence of WatchData into the model for the non-dumper case -class WatchHandlerModelInserter { -public: - explicit WatchHandlerModelInserter(WatchHandler *wh) : m_wh(wh) {} - - inline WatchHandlerModelInserter & operator*() { return *this; } - inline WatchHandlerModelInserter &operator=(const WatchData &wd) { - m_wh->insertData(wd); - return *this; - } - inline WatchHandlerModelInserter &operator++() { return *this; } - -private: - WatchHandler *m_wh; -}; - -// Put a sequence of WatchData into the model for the dumper case. -// Sorts apart a sequence of WatchData using the Dumpers. -// Puts the stuff for which there is no dumper in the model -// as is and sets ownership to symbol group. The rest goes -// to the dumpers. Additionally, checks for items pointing to a -// dumpeable type and inserts a fake dereferenced item and value. -class WatchHandleDumperInserter { -public: - explicit WatchHandleDumperInserter(WatchHandler *wh, - const SharedPointerCdbDumperHelper &dumper); - - inline WatchHandleDumperInserter & operator*() { return *this; } - inline WatchHandleDumperInserter &operator=(WatchData &wd); - inline WatchHandleDumperInserter &operator++() { return *this; } - -private: - bool expandPointerToDumpable(const WatchData &wd, QString *errorMessage); - - const QRegExp m_hexNullPattern; - WatchHandler *m_wh; - const SharedPointerCdbDumperHelper m_dumper; - QList<WatchData> m_dumperResult; -}; - -WatchHandleDumperInserter::WatchHandleDumperInserter(WatchHandler *wh, - const SharedPointerCdbDumperHelper &dumper) : - m_hexNullPattern(QLatin1String("0x0+")), - m_wh(wh), - m_dumper(dumper) -{ - Q_ASSERT(m_hexNullPattern.isValid()); -} - -// Is this a non-null pointer to a dumpeable item with a value -// "0x4343 class QString *" ? - Insert a fake '*' dereferenced item -// and run dumpers on it. If that succeeds, insert the fake items owned by dumpers, -// which will trigger the ignore predicate. -// Note that the symbol context does not create '*' dereferenced items for -// classes (see note in its header documentation). -bool WatchHandleDumperInserter::expandPointerToDumpable(const WatchData &wd, QString *errorMessage) -{ - if (debugCDBWatchHandling) - qDebug() << ">expandPointerToDumpable" << wd.iname; - - bool handled = false; - do { - if (!isPointerType(wd.type)) - break; - const int classPos = wd.value.indexOf(" class "); - if (classPos == -1) - break; - const QString hexAddrS = wd.value.mid(0, classPos); - if (m_hexNullPattern.exactMatch(hexAddrS)) - break; - const QString type = stripPointerType(wd.value.mid(classPos + 7)); - WatchData derefedWd; - derefedWd.setType(type); - derefedWd.setAddress(hexAddrS); - derefedWd.name = QString(QLatin1Char('*')); - derefedWd.iname = wd.iname + QLatin1String(".*"); - derefedWd.source = OwnerDumper; - const CdbDumperHelper::DumpResult dr = m_dumper->dumpType(derefedWd, true, OwnerDumper, &m_dumperResult, errorMessage); - if (dr != CdbDumperHelper::DumpOk) - break; - // Insert the pointer item with 1 additional child + its dumper results - // Note: formal arguments might already be expanded in the symbol group. - WatchData ptrWd = wd; - ptrWd.source = OwnerDumper; - ptrWd.setHasChildren(true); - ptrWd.setChildrenUnneeded(); - m_wh->insertData(ptrWd); - foreach(const WatchData &dwd, m_dumperResult) - m_wh->insertData(dwd); - handled = true; - } while (false); - if (debugCDBWatchHandling) - qDebug() << "<expandPointerToDumpable returns " << handled << *errorMessage; - return handled; -} - -// When querying an item, the queried item is sometimes returned in incomplete form. -// Take over values from source. -static inline void fixDumperResult(const WatchData &source, - QList<WatchData> *result, - bool suppressGrandChildren) -{ - const int size = result->size(); - if (!size) - return; - WatchData &returned = result->front(); - if (returned.iname != source.iname) - return; - if (returned.type.isEmpty()) - returned.setType(source.type); - if (returned.isValueNeeded()) { - if (source.isValueKnown()) { - returned.setValue(source.value); - } else { - // Should not happen - returned.setValue(QCoreApplication::translate("CdbStackFrameContext", "<Unknown>")); - } - } - if (size == 1) - return; - // Fix the children: If the address is missing, we cannot query any further. - const QList<WatchData>::iterator wend = result->end(); - QList<WatchData>::iterator it = result->begin(); - for (++it; it != wend; ++it) { - WatchData &wd = *it; - if (wd.addr.isEmpty() && wd.isSomethingNeeded()) { - wd.setAllUnneeded(); - } else { - // Hack: Suppress endless recursion of the model. To be fixed, - // the model should not query non-visible items. - if (suppressGrandChildren && (wd.isChildrenNeeded() || wd.isHasChildrenNeeded())) - wd.setHasChildren(false); - } - } -} - -WatchHandleDumperInserter &WatchHandleDumperInserter::operator=(WatchData &wd) -{ - if (debugCDBWatchHandling) - qDebug() << "WatchHandleDumperInserter::operator=" << wd.toString(); - // Check pointer to dumpeable, dumpeable, insert accordingly. - QString errorMessage; - if (expandPointerToDumpable(wd, &errorMessage)) { - // Nasty side effect: Modify owner for the ignore predicate - wd.source = OwnerDumper; - return *this; - } - switch (m_dumper->dumpType(wd, true, OwnerDumper, &m_dumperResult, &errorMessage)) { - case CdbDumperHelper::DumpOk: - if (debugCDBWatchHandling) - qDebug() << "dumper triggered"; - // Dumpers omit types for complicated templates - fixDumperResult(wd, &m_dumperResult, false); - // Discard the original item and insert the dumper results - foreach(const WatchData &dwd, m_dumperResult) - m_wh->insertData(dwd); - // Nasty side effect: Modify owner for the ignore predicate - wd.source = OwnerDumper; - break; - case CdbDumperHelper::DumpNotHandled: - case CdbDumperHelper::DumpError: - wd.source = OwnerSymbolGroup; - m_wh->insertData(wd); - break; - } - return *this; -} - -// -----------CdbStackFrameContext -CdbStackFrameContext::CdbStackFrameContext(const QSharedPointer<CdbDumperHelper> &dumper, - CdbSymbolGroupContext *symbolContext) : - m_useDumpers(dumper->isEnabled() && theDebuggerBoolSetting(UseDebuggingHelpers)), - m_dumper(dumper), - m_symbolContext(symbolContext) -{ -} - -bool CdbStackFrameContext::assignValue(const QString &iname, const QString &value, - QString *newValue /* = 0 */, QString *errorMessage) -{ - return m_symbolContext->assignValue(iname, value, newValue, errorMessage); -} - -bool CdbStackFrameContext::populateModelInitially(WatchHandler *wh, QString *errorMessage) -{ - if (debugCDBWatchHandling) - qDebug() << "populateModelInitially dumpers=" << m_useDumpers; - // Recurse down items that are initially expanded in the view, stop processing for - // dumper items. - const bool rc = m_useDumpers ? - CdbSymbolGroupContext::populateModelInitially(m_symbolContext, - WatchHandleDumperInserter(wh, m_dumper), - WatchHandlerExpandedPredicate(wh), - isDumperPredicate, - errorMessage) : - CdbSymbolGroupContext::populateModelInitially(m_symbolContext, - WatchHandlerModelInserter(wh), - WatchHandlerExpandedPredicate(wh), - falsePredicate, - errorMessage); - return rc; -} - -bool CdbStackFrameContext::completeData(const WatchData &incompleteLocal, - WatchHandler *wh, - QString *errorMessage) -{ - if (debugCDBWatchHandling) - qDebug() << ">completeData src=" << incompleteLocal.source << incompleteLocal.toString(); - - // Expand symbol group items, recurse one level from desired item - if (!m_useDumpers) { - return CdbSymbolGroupContext::completeData(m_symbolContext, incompleteLocal, - WatchHandlerModelInserter(wh), - MatchINamePredicate(incompleteLocal.iname), - falsePredicate, - errorMessage); - } - - // Expand artifical dumper items - if (incompleteLocal.source == OwnerDumper) { - QList<WatchData> dumperResult; - const CdbDumperHelper::DumpResult dr = m_dumper->dumpType(incompleteLocal, true, OwnerDumper, &dumperResult, errorMessage); - if (dr == CdbDumperHelper::DumpOk) { - // Hack to stop endless model recursion - const bool suppressGrandChildren = !wh->isExpandedIName(incompleteLocal.iname); - fixDumperResult(incompleteLocal, &dumperResult, suppressGrandChildren); - foreach(const WatchData &dwd, dumperResult) - wh->insertData(dwd); - } else { - const QString msg = QString::fromLatin1("Unable to further expand dumper watch data: '%1' (%2): %3/%4").arg(incompleteLocal.name, incompleteLocal.type).arg(int(dr)).arg(*errorMessage); - qWarning("%s", qPrintable(msg)); - WatchData wd = incompleteLocal; - if (wd.isValueNeeded()) - wd.setValue(QCoreApplication::translate("CdbStackFrameContext", "<Unknown>")); - wd.setAllUnneeded(); - wh->insertData(wd); - } - return true; - } - - // Expand symbol group items, recurse one level from desired item - return CdbSymbolGroupContext::completeData(m_symbolContext, incompleteLocal, - WatchHandleDumperInserter(wh, m_dumper), - MatchINamePredicate(incompleteLocal.iname), - isDumperPredicate, - errorMessage); -} - -CdbStackFrameContext::~CdbStackFrameContext() -{ - delete m_symbolContext; -} - -bool CdbStackFrameContext::editorToolTip(const QString &iname, - QString *value, - QString *errorMessage) -{ - value->clear(); - unsigned long index; - if (!m_symbolContext->lookupPrefix(iname, &index)) { - *errorMessage = QString::fromLatin1("%1 not found.").arg(iname); - return false; - } - const WatchData wd = m_symbolContext->symbolAt(index); - // Check dumpers. Should actually be just one item. - if (m_useDumpers && m_dumper->state() != CdbDumperHelper::Disabled) { - QList<WatchData> result; - if (CdbDumperHelper::DumpOk == m_dumper->dumpType(wd, false, OwnerDumper, &result, errorMessage)) { - foreach (const WatchData &dwd, result) { - if (!value->isEmpty()) - value->append(QLatin1Char('\n')); - value->append(dwd.toToolTip()); - } - return true; - } // Dumped ok - } // has Dumpers - *value = wd.toToolTip(); - return true; -} - -} // namespace Internal -} // namespace Debugger diff --git a/src/shared/cplusplus/Lexer.cpp b/src/shared/cplusplus/Lexer.cpp index f463201f716882e68ce9a9d3816d35ef75275dd9..2229b470bd225707b7c2d501a0f77479d531687b 100644 --- a/src/shared/cplusplus/Lexer.cpp +++ b/src/shared/cplusplus/Lexer.cpp @@ -348,7 +348,7 @@ void Lexer::scan_helper(Token *tok) } } while (_yychar); int yylen = _currentChar - yytext; - tok->kind = T_INT_LITERAL; + tok->kind = T_NUMERIC_LITERAL; if (control()) tok->number = control()->findOrInsertNumericLiteral(yytext, yylen); } else { @@ -702,7 +702,7 @@ void Lexer::scan_helper(Token *tok) } } int yylen = _currentChar - yytext; - tok->kind = T_INT_LITERAL; + tok->kind = T_NUMERIC_LITERAL; if (control()) tok->number = control()->findOrInsertNumericLiteral(yytext, yylen); break; diff --git a/src/shared/cplusplus/Literals.cpp b/src/shared/cplusplus/Literals.cpp index 83457137982902c6e4841bf327dc721f3d219ec4..bf243373ec050e7727b41199d5dd1c0ee97458a7 100644 --- a/src/shared/cplusplus/Literals.cpp +++ b/src/shared/cplusplus/Literals.cpp @@ -105,13 +105,105 @@ StringLiteral::~StringLiteral() { } //////////////////////////////////////////////////////////////////////////////// +enum { + NumericLiteralIsChar, + NumericLiteralIsWideChar, + NumericLiteralIsInt, + NumericLiteralIsFloat, + NumericLiteralIsDouble, + NumericLiteralIsLongDouble, + NumericLiteralIsLong, + NumericLiteralIsLongLong, +}; + NumericLiteral::NumericLiteral(const char *chars, unsigned size) - : Literal(chars, size) -{ } + : Literal(chars, size), _flags(0) +{ + _type = NumericLiteralIsInt; + + if (chars[0] == '\'') { + _type = NumericLiteralIsChar; + } else if (size > 1 && chars[0] == 'L' && chars[1] == '\'') { + _type = NumericLiteralIsWideChar; + } else if (size > 1 && chars[0] == '0' && (chars[1] == 'x' || chars[1] == 'X')) { + _isHex = true; + } else { + const char *begin = chars; + const char *end = begin + size; + + bool done = false; + const char *it = end - 1; + + for (; it != begin - 1 && ! done; --it) { + switch (*it) { + case 'l': case 'L': // long suffix + case 'u': case 'U': // unsigned suffix + case 'f': case 'F': // floating suffix + break; + + default: + done = true; + break; + } // switch + } + + for (const char *dot = it; it != begin - 1; --it) { + if (*dot == '.') + _type = NumericLiteralIsDouble; + } + + for (++it; it != end; ++it) { + if (*it == 'l' || *it == 'L') { + if (_type == NumericLiteralIsDouble) { + _type = NumericLiteralIsLongDouble; + } else if (it + 1 != end && (it[1] == 'l' || it[1] == 'L')) { + ++it; + _type = NumericLiteralIsLongLong; + } else { + _type = NumericLiteralIsLong; + } + } else if (*it == 'f' || *it == 'F') { + _type = NumericLiteralIsFloat; + } else if (*it == 'u' || *it == 'U') { + _isUnsigned = true; + } + } + } +} NumericLiteral::~NumericLiteral() { } +bool NumericLiteral::isHex() const +{ return _isHex; } + +bool NumericLiteral::isUnsigned() const +{ return _isUnsigned; } + +bool NumericLiteral::isChar() const +{ return _type == NumericLiteralIsChar; } + +bool NumericLiteral::isWideChar() const +{ return _type == NumericLiteralIsWideChar; } + +bool NumericLiteral::isInt() const +{ return _type == NumericLiteralIsInt; } + +bool NumericLiteral::isFloat() const +{ return _type == NumericLiteralIsFloat; } + +bool NumericLiteral::isDouble() const +{ return _type == NumericLiteralIsDouble; } + +bool NumericLiteral::isLongDouble() const +{ return _type == NumericLiteralIsLongDouble; } + +bool NumericLiteral::isLong() const +{ return _type == NumericLiteralIsLong; } + +bool NumericLiteral::isLongLong() const +{ return _type == NumericLiteralIsLongLong; } + //////////////////////////////////////////////////////////////////////////////// Identifier::Identifier(const char *chars, unsigned size) : Literal(chars, size) @@ -122,7 +214,9 @@ Identifier::~Identifier() bool Identifier::isEqualTo(const Identifier *other) const { - if (this == other) + if (! other) + return false; + else if (this == other) return true; else if (hashCode() != other->hashCode()) return false; diff --git a/src/shared/cplusplus/Literals.h b/src/shared/cplusplus/Literals.h index da7ed837da458ac4514b4e36eb19ad50402b9129..78a8e3b62ff05afa5424a1cbd82c6a89a89e4732 100644 --- a/src/shared/cplusplus/Literals.h +++ b/src/shared/cplusplus/Literals.h @@ -101,6 +101,29 @@ class CPLUSPLUS_EXPORT NumericLiteral: public Literal public: NumericLiteral(const char *chars, unsigned size); virtual ~NumericLiteral(); + + bool isChar() const; + bool isWideChar() const; + bool isInt() const; + bool isFloat() const; + bool isDouble() const; + bool isLongDouble() const; + bool isLong() const; + bool isLongLong() const; + + bool isUnsigned() const; + bool isHex() const; + +private: + union { + unsigned _flags; + + struct { + unsigned _type : 8; + unsigned _isHex : 1; + unsigned _isUnsigned: 1; + }; + }; }; class CPLUSPLUS_EXPORT Identifier: public Literal diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index 96e7f86cc202e1ef628a74c95acf0eb68a3bcd14..a005f7250bbc7aa67c421cfd8bfa46145dfcb1fb 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -2715,8 +2715,9 @@ bool Parser::parseBoolLiteral(ExpressionAST *&node) bool Parser::parseNumericLiteral(ExpressionAST *&node) { - if (LA() == T_INT_LITERAL || LA() == T_FLOAT_LITERAL || - LA() == T_CHAR_LITERAL || LA() == T_WIDE_CHAR_LITERAL) { + if (LA() == T_NUMERIC_LITERAL || + LA() == T_CHAR_LITERAL || + LA() == T_WIDE_CHAR_LITERAL) { NumericLiteralAST *ast = new (_pool) NumericLiteralAST; ast->literal_token = consumeToken(); node = ast; @@ -2743,10 +2744,9 @@ bool Parser::parsePrimaryExpression(ExpressionAST *&node) case T_WIDE_STRING_LITERAL: return parseStringLiteral(node); - case T_INT_LITERAL: - case T_FLOAT_LITERAL: - case T_CHAR_LITERAL: + case T_CHAR_LITERAL: // ### FIXME don't use NumericLiteral for chars case T_WIDE_CHAR_LITERAL: + case T_NUMERIC_LITERAL: return parseNumericLiteral(node); case T_TRUE: diff --git a/src/shared/cplusplus/Token.cpp b/src/shared/cplusplus/Token.cpp index 37a95d6cd772d4c12bb5986ef1454ad27e25a6bf..bda5ecc5839d243c21c5cfb86f5486c20b2c3231 100644 --- a/src/shared/cplusplus/Token.cpp +++ b/src/shared/cplusplus/Token.cpp @@ -118,8 +118,7 @@ const char *Token::spell() const case T_IDENTIFIER: return identifier->chars(); - case T_INT_LITERAL: - case T_FLOAT_LITERAL: + case T_NUMERIC_LITERAL: case T_CHAR_LITERAL: case T_STRING_LITERAL: case T_AT_STRING_LITERAL: diff --git a/src/shared/cplusplus/Token.h b/src/shared/cplusplus/Token.h index 6774dba3361d8528a0cfa917c5a7b1d4455ca845..99b986c7abb49b1ecea7007e424efbce4b8b1c3a 100644 --- a/src/shared/cplusplus/Token.h +++ b/src/shared/cplusplus/Token.h @@ -64,8 +64,7 @@ enum Kind { T_IDENTIFIER, T_FIRST_LITERAL, - T_INT_LITERAL = T_FIRST_LITERAL, - T_FLOAT_LITERAL, + T_NUMERIC_LITERAL = T_FIRST_LITERAL, T_CHAR_LITERAL, T_WIDE_CHAR_LITERAL, T_STRING_LITERAL, diff --git a/src/shared/cplusplus/TranslationUnit.cpp b/src/shared/cplusplus/TranslationUnit.cpp index db5fbe1c054f13dec469d9dfcf421ff1b0c412ee..64145342b86c6660b26a6ca42a332ae9cc749b25 100644 --- a/src/shared/cplusplus/TranslationUnit.cpp +++ b/src/shared/cplusplus/TranslationUnit.cpp @@ -208,7 +208,7 @@ void TranslationUnit::tokenize() } else { if (! tk.newline && tk.is(T_IDENTIFIER) && tk.identifier == lineId) lex(&tk); - if (! tk.newline && tk.is(T_INT_LITERAL)) { + if (! tk.newline && tk.is(T_NUMERIC_LITERAL)) { unsigned line = (unsigned) strtoul(tk.spell(), 0, 0); lex(&tk); if (! tk.newline && tk.is(T_STRING_LITERAL)) {