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)) {