diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index 55afb59911646128fa35c0a6f9a8d99a43863783..82a092ede1ab9656c55c1b6789ad9c8b4dba62bc 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -2042,7 +2042,7 @@ static QString pathOrDirectoryFor(Node *node, bool dir)
 {
     Utils::FileName path = node->path();
     QString location;
-    FolderNode *folder = dynamic_cast<FolderNode *>(node);
+    FolderNode *folder = node->asFolderNode();
     if (node->nodeType() == VirtualFolderNodeType && folder) {
         // Virtual Folder case
         // If there are files directly below or no subfolders, take the folder path
@@ -2397,7 +2397,8 @@ void ProjectExplorerPluginPrivate::runProjectWithoutDeploy()
 
 void ProjectExplorerPluginPrivate::runProjectContextMenu()
 {
-    ProjectNode *projectNode = dynamic_cast<ProjectNode*>(ProjectTree::currentNode());
+    Node *node = ProjectTree::currentNode();
+    ProjectNode *projectNode = node ? node->asProjectNode() : 0;
     if (projectNode == ProjectTree::currentProject()->rootProjectNode() || !projectNode) {
         m_instance->runProject(ProjectTree::currentProject(), NormalRunMode);
     } else {
@@ -2916,7 +2917,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
     if (currentNode && currentNode->projectNode()) {
         QList<ProjectAction> actions = currentNode->supportedActions(currentNode);
 
-        if (ProjectNode *pn = dynamic_cast<ProjectNode *>(currentNode)) {
+        if (ProjectNode *pn = currentNode->asProjectNode()) {
             if (ProjectTree::currentProject() && pn == ProjectTree::currentProject()->rootProjectNode()) {
                 m_runActionContextMenu->setVisible(true);
             } else {
@@ -2937,7 +2938,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
                 }
             }
         }
-        if (dynamic_cast<FolderNode*>(currentNode)) {
+        if (currentNode->asFolderNode()) {
             // Also handles ProjectNode
             m_addNewFileAction->setEnabled(actions.contains(AddNewFile)
                                               && !ICore::isNewItemDialogRunning());
@@ -2949,7 +2950,7 @@ void ProjectExplorerPluginPrivate::updateContextMenuActions()
             m_addExistingFilesAction->setEnabled(actions.contains(AddExistingFile));
             m_addExistingDirectoryAction->setEnabled(actions.contains(AddExistingDirectory));
             m_renameFileAction->setEnabled(actions.contains(Rename));
-        } else if (dynamic_cast<FileNode*>(currentNode)) {
+        } else if (currentNode->asFileNode()) {
             // Enable and show remove / delete in magic ways:
             // If both are disabled show Remove
             // If both are enabled show both (can't happen atm)
@@ -3050,7 +3051,8 @@ void ProjectExplorerPluginPrivate::addExistingDirectory()
 
 void ProjectExplorerPlugin::addExistingFiles(const QStringList &filePaths)
 {
-    FolderNode *folderNode = dynamic_cast<FolderNode *>(ProjectTree::currentNode());
+    Node *node = ProjectTree::currentNode();
+    FolderNode *folderNode = node ? node->asFolderNode() : 0;
     addExistingFiles(folderNode, filePaths);
 }
 
@@ -3079,8 +3081,13 @@ void ProjectExplorerPlugin::addExistingFiles(FolderNode *folderNode, const QStri
 
 void ProjectExplorerPluginPrivate::removeProject()
 {
-    ProjectNode *subProjectNode = dynamic_cast<ProjectNode*>(ProjectTree::currentNode()->projectNode());
-    ProjectNode *projectNode = dynamic_cast<ProjectNode *>(subProjectNode->parentFolderNode());
+    Node *node = ProjectTree::currentNode();
+    if (!node)
+        return;
+    ProjectNode *subProjectNode = node->projectNode();
+    if (!subProjectNode)
+        return;
+    ProjectNode *projectNode = subProjectNode->parentFolderNode()->asProjectNode();
     if (projectNode) {
         RemoveFileDialog removeFileDialog(subProjectNode->path().toString(), ICore::mainWindow());
         removeFileDialog.setDeleteFileVisible(false);
@@ -3118,7 +3125,7 @@ void ProjectExplorerPluginPrivate::removeFile()
     Node *currentNode = ProjectTree::currentNode();
     QTC_ASSERT(currentNode && currentNode->nodeType() == FileNodeType, return);
 
-    FileNode *fileNode = dynamic_cast<FileNode*>(currentNode);
+    FileNode *fileNode = currentNode->asFileNode();
 
     QString filePath = currentNode->path().toString();
     RemoveFileDialog removeFileDialog(filePath, ICore::mainWindow());
@@ -3147,7 +3154,7 @@ void ProjectExplorerPluginPrivate::deleteFile()
     Node *currentNode = ProjectTree::currentNode();
     QTC_ASSERT(currentNode && currentNode->nodeType() == FileNodeType, return);
 
-    FileNode *fileNode = dynamic_cast<FileNode*>(currentNode);
+    FileNode *fileNode = currentNode->asFileNode();
 
     QString filePath = currentNode->path().toString();
     QMessageBox::StandardButton button =
diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp
index 30210bd15547753545bd9387aa179f8a7d186189..f99e99d2e8c9173f32cab7856fc5ad938a1a238f 100644
--- a/src/plugins/projectexplorer/projectmodels.cpp
+++ b/src/plugins/projectexplorer/projectmodels.cpp
@@ -59,8 +59,8 @@ bool sortNodes(Node *n1, Node *n2)
     const NodeType n2Type = n2->nodeType();
 
     // project files
-    FileNode *file1 = dynamic_cast<FileNode*>(n1);
-    FileNode *file2 = dynamic_cast<FileNode*>(n2);
+    FileNode *file1 = n1->asFileNode();
+    FileNode *file2 = n2->asFileNode();
     if (file1 && file1->fileType() == ProjectFileType) {
         if (file2 && file2->fileType() == ProjectFileType) {
             const QString fileName1 = file1->path().fileName();
@@ -221,7 +221,7 @@ QModelIndex FlatModel::index(int row, int column, const QModelIndex &parent) con
     if (!parent.isValid() && row == 0 && column == 0) { // session
         result = createIndex(0, 0, m_rootNode);
     } else if (parent.isValid() && column == 0) {
-        FolderNode *parentNode = dynamic_cast<FolderNode*>(nodeForIndex(parent));
+        FolderNode *parentNode = nodeForIndex(parent)->asFolderNode();
         Q_ASSERT(parentNode);
         QHash<FolderNode*, QList<Node*> >::const_iterator it = m_childNodes.constFind(parentNode);
         if (it == m_childNodes.constEnd()) {
@@ -270,7 +270,7 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
     QVariant result;
 
     if (Node *node = nodeForIndex(index)) {
-        FolderNode *folderNode = dynamic_cast<FolderNode*>(node);
+        FolderNode *folderNode = node->asFolderNode();
         switch (role) {
         case Qt::DisplayRole: {
             QString name = node->displayName();
@@ -334,11 +334,11 @@ Qt::ItemFlags FlatModel::flags(const QModelIndex &index) const
     if (Node *node = nodeForIndex(index)) {
         if (node == m_rootNode)
             return 0; // no flags for session node...
-        if (!dynamic_cast<ProjectNode *>(node)) {
+        if (!node->asProjectNode()) {
             // either folder or file node
             if (node->supportedActions(node).contains(Rename))
                 f = f | Qt::ItemIsEditable;
-            if (dynamic_cast<FileNode *>(node))
+            if (node->asFileNode())
                 f = f | Qt::ItemIsDragEnabled;
         }
     }
@@ -368,7 +368,7 @@ int FlatModel::rowCount(const QModelIndex &parent) const
     if (!parent.isValid()) {
         rows = 1;
     } else {
-        FolderNode *folderNode = dynamic_cast<FolderNode*>(nodeForIndex(parent));
+        FolderNode *folderNode = nodeForIndex(parent)->asFolderNode();
         if (folderNode && m_childNodes.contains(folderNode))
             rows = m_childNodes.value(folderNode).size();
     }
@@ -385,7 +385,7 @@ bool FlatModel::hasChildren(const QModelIndex &parent) const
     if (!parent.isValid())
         return true;
 
-    FolderNode *folderNode = dynamic_cast<FolderNode*>(nodeForIndex(parent));
+    FolderNode *folderNode = nodeForIndex(parent)->asFolderNode();
     if (!folderNode)
         return false;
 
@@ -402,7 +402,7 @@ bool FlatModel::canFetchMore(const QModelIndex & parent) const
     if (!parent.isValid()) {
         return false;
     } else {
-        if (FolderNode *folderNode = dynamic_cast<FolderNode*>(nodeForIndex(parent)))
+        if (FolderNode *folderNode = nodeForIndex(parent)->asFolderNode())
             return !m_childNodes.contains(folderNode);
         else
             return false;
@@ -472,7 +472,7 @@ void FlatModel::fetchMore(FolderNode *folderNode) const
 
 void FlatModel::fetchMore(const QModelIndex &parent)
 {
-    FolderNode *folderNode = dynamic_cast<FolderNode*>(nodeForIndex(parent));
+    FolderNode *folderNode = nodeForIndex(parent)->asFolderNode();
     Q_ASSERT(folderNode);
 
     fetchMore(folderNode);
@@ -513,7 +513,7 @@ QMimeData *FlatModel::mimeData(const QModelIndexList &indexes) const
     auto data = new Utils::FileDropMimeData;
     foreach (const QModelIndex &index, indexes) {
         Node *node = nodeForIndex(index);
-        if (dynamic_cast<FileNode *>(node))
+        if (node->asFileNode())
             data->addFile(node->path().toString());
     }
     return data;
@@ -600,10 +600,10 @@ FolderNode *FlatModel::visibleFolderNode(FolderNode *node) const
 bool FlatModel::filter(Node *node) const
 {
     bool isHidden = false;
-    if (FolderNode *folderNode = dynamic_cast<FolderNode*>(node)) {
+    if (FolderNode *folderNode = node->asFolderNode()) {
         if (m_filterProjects)
             isHidden = !folderNode->showInSimpleTree();
-    } else if (FileNode *fileNode = dynamic_cast<FileNode*>(node)) {
+    } else if (FileNode *fileNode = node->asFileNode()) {
         if (m_filterGeneratedFiles)
             isHidden = fileNode->isGenerated();
     }
@@ -802,7 +802,7 @@ void FlatModel::aboutToShowInSimpleTreeChanged(FolderNode* node)
     QList<Node *> staleFolders;
     recursiveAddFolderNodesImpl(node, &staleFolders);
     foreach (Node *n, staleFolders)
-        if (FolderNode *fn = dynamic_cast<FolderNode *>(n))
+        if (FolderNode *fn = n->asFolderNode())
             m_childNodes.remove(fn);
 }
 
diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp
index ef435670d491daa5f33d2641672d0f6733cbf698..860a3478442f424afb3246d584406aebe8441d9e 100644
--- a/src/plugins/projectexplorer/projectnodes.cpp
+++ b/src/plugins/projectexplorer/projectnodes.cpp
@@ -198,6 +198,26 @@ void Node::emitNodeUpdated()
         ProjectTree::instance()->emitNodeUpdated(this);
 }
 
+FileNode *Node::asFileNode()
+{
+    return 0;
+}
+
+FolderNode *Node::asFolderNode()
+{
+    return 0;
+}
+
+ProjectNode *Node::asProjectNode()
+{
+    return 0;
+}
+
+SessionNode *Node::asSessionNode()
+{
+    return 0;
+}
+
 void Node::setParentFolderNode(FolderNode *parentFolder)
 {
     m_folderNode = parentFolder;
@@ -235,6 +255,11 @@ bool FileNode::isGenerated() const
     return m_generated;
 }
 
+FileNode *FileNode::asFileNode()
+{
+    return this;
+}
+
 /*!
   \class ProjectExplorer::FolderNode
 
@@ -494,6 +519,11 @@ void FolderNode::removeFolderNodes(const QList<FolderNode*> &subFolders)
     ProjectTree::instance()->emitFoldersRemoved(this);
 }
 
+FolderNode *FolderNode::asFolderNode()
+{
+    return this;
+}
+
 bool FolderNode::showInSimpleTree() const
 {
     return false;
@@ -672,6 +702,11 @@ void ProjectNode::removeProjectNodes(const QList<ProjectNode*> &subProjects)
     }
 }
 
+ProjectNode *ProjectNode::asProjectNode()
+{
+    return this;
+}
+
 
 /*!
   \class ProjectExplorer::SessionNode
@@ -707,6 +742,11 @@ void SessionNode::projectDisplayNameChanged(Node *node)
     ProjectTree::instance()->emitNodeSortKeyChanged(node);
 }
 
+SessionNode *SessionNode::asSessionNode()
+{
+    return this;
+}
+
 QList<ProjectNode*> SessionNode::projectNodes() const
 {
     return m_projectNodes;
diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h
index 57c5dc5299c0f09cf0822ef0e1318f4d2c107bcc..64037a1cdc88c6e7f668da47299f5d5f8f104588 100644
--- a/src/plugins/projectexplorer/projectnodes.h
+++ b/src/plugins/projectexplorer/projectnodes.h
@@ -100,6 +100,7 @@ class FileNode;
 class FileContainerNode;
 class FolderNode;
 class ProjectNode;
+class SessionNode;
 class NodesVisitor;
 class SessionManager;
 
@@ -124,6 +125,11 @@ public:
     void setPathAndLine(const Utils::FileName &path, int line);
     void emitNodeUpdated();
 
+    virtual FileNode *asFileNode();
+    virtual FolderNode *asFolderNode();
+    virtual ProjectNode *asProjectNode();
+    virtual SessionNode *asSessionNode();
+
 protected:
     Node(NodeType nodeType, const Utils::FileName &path, int line = -1);
 
@@ -149,6 +155,8 @@ public:
     FileType fileType() const;
     bool isGenerated() const;
 
+    FileNode *asFileNode();
+
 private:
     // managed by ProjectNode
     friend class FolderNode;
@@ -204,6 +212,7 @@ public:
     void addFolderNodes(const QList<FolderNode*> &subFolders);
     void removeFolderNodes(const QList<FolderNode*> &subFolders);
 
+    FolderNode *asFolderNode();
 
 protected:
     QList<FolderNode*> m_subFolderNodes;
@@ -256,6 +265,8 @@ public:
     void addProjectNodes(const QList<ProjectNode*> &subProjects);
     void removeProjectNodes(const QList<ProjectNode*> &subProjects);
 
+    ProjectNode *asProjectNode();
+
 protected:
     // this is just the in-memory representation, a subclass
     // will add the persistent stuff
@@ -285,6 +296,8 @@ public:
 
     bool showInSimpleTree() const;
     void projectDisplayNameChanged(Node *node);
+
+    SessionNode *asSessionNode();
 protected:
     void addProjectNodes(const QList<ProjectNode*> &projectNodes);
     void removeProjectNodes(const QList<ProjectNode*> &projectNodes);
diff --git a/src/plugins/projectexplorer/projecttree.cpp b/src/plugins/projectexplorer/projecttree.cpp
index 52d40cb1c55d2de81cdfe5b25b3f18e936d0f2b7..3f7e0a1e6f29098e3d05f3cb686d9c3a5ece5d9c 100644
--- a/src/plugins/projectexplorer/projecttree.cpp
+++ b/src/plugins/projectexplorer/projecttree.cpp
@@ -162,7 +162,7 @@ Project *ProjectTree::projectForNode(Node *node)
     if (!node)
         return 0;
 
-    FolderNode *rootProjectNode = dynamic_cast<FolderNode*>(node);
+    FolderNode *rootProjectNode = node->asFolderNode();
     if (!rootProjectNode)
         rootProjectNode = node->parentFolderNode();
 
@@ -310,7 +310,7 @@ void ProjectTree::emitFoldersAboutToBeRemoved(FolderNode *parentFolder, const QL
 
     Node *n = ProjectTree::currentNode();
     while (n) {
-        if (FolderNode *fn = dynamic_cast<FolderNode *>(n)) {
+        if (FolderNode *fn = n->asFolderNode()) {
             if (staleFolders.contains(fn)) {
                 ProjectNode *pn = n->projectNode();
                 // Make sure the node we are switching too isn't going to be removed also
@@ -363,9 +363,10 @@ void ProjectTree::emitFilesAboutToBeRemoved(FolderNode *folder, const QList<File
     if (!isInNodeHierarchy(folder))
         return;
 
-    if (FileNode *fileNode = dynamic_cast<FileNode *>(m_currentNode))
-        if (staleFiles.contains(fileNode))
-            m_resetCurrentNodeFile = true;
+    if (m_currentNode)
+        if (FileNode *fileNode = m_currentNode->asFileNode())
+            if (staleFiles.contains(fileNode))
+                m_resetCurrentNodeFile = true;
 
     emit filesAboutToBeRemoved(folder, staleFiles);
 }
diff --git a/src/plugins/projectexplorer/session.cpp b/src/plugins/projectexplorer/session.cpp
index 7fda8969c46bd82d25e8a3c46313440212596b1e..022d99a99eda3bc32ffd76a3027eeba0cf746e93 100644
--- a/src/plugins/projectexplorer/session.cpp
+++ b/src/plugins/projectexplorer/session.cpp
@@ -563,7 +563,7 @@ Project *SessionManager::projectForNode(Node *node)
     if (!node)
         return 0;
 
-    FolderNode *rootProjectNode = dynamic_cast<FolderNode*>(node);
+    FolderNode *rootProjectNode = node->asFolderNode();
     if (!rootProjectNode)
         rootProjectNode = node->parentFolderNode();
 
diff --git a/src/plugins/qmakeprojectmanager/qmakenodes.cpp b/src/plugins/qmakeprojectmanager/qmakenodes.cpp
index a043805bb265571c1def2dc3627b883056f5ae47..874f3b9bcc73b8609c36e21f8e6f2c7318120c11 100644
--- a/src/plugins/qmakeprojectmanager/qmakenodes.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakenodes.cpp
@@ -932,7 +932,7 @@ QList<ProjectAction> QmakePriFileNode::supportedActions(Node *node) const
         bool addExistingFiles = true;
         if (node->nodeType() == VirtualFolderNodeType) {
             // A virtual folder, we do what the projectexplorer does
-            FolderNode *folder = dynamic_cast<FolderNode *>(node);
+            FolderNode *folder = node->asFolderNode();
             if (folder) {
                 QStringList list;
                 foreach (FolderNode *f, folder->subFolderNodes())
@@ -956,7 +956,7 @@ QList<ProjectAction> QmakePriFileNode::supportedActions(Node *node) const
         break;
     }
 
-    FileNode *fileNode = dynamic_cast<FileNode *>(node);
+    FileNode *fileNode = node->asFileNode();
     if ((fileNode && fileNode->fileType() != ProjectFileType)
             || dynamic_cast<ResourceEditor::ResourceTopLevelNode *>(node))
         actions << Rename;
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp
index c145a00d6df4e8e9c72cadbeafc178a149a4d2b4..f9cc7e8d5a1460b6eeb5d6cdd0a0619d14d29aa0 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanager.cpp
@@ -232,7 +232,8 @@ void QmakeManager::buildFile()
 {
     if (Core::IDocument *currentDocument= Core::EditorManager::currentDocument()) {
         const Utils::FileName file = currentDocument->filePath();
-        FileNode *node  = dynamic_cast<FileNode *>(SessionManager::nodeForFile(file));
+        Node *n = SessionManager::nodeForFile(file);
+        FileNode *node  = n ? n->asFileNode() : 0;
         Project *project = SessionManager::projectForFile(file);
 
         if (project && node)
diff --git a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp
index e5fa4d23639aa6411d1a33f1928a3d77f076ca31..0e0c6fbdb69741fb1ad4556ea58c361b390a3ce1 100644
--- a/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeprojectmanagerplugin.cpp
@@ -329,7 +329,7 @@ void QmakeProjectManagerPlugin::updateContextActions(ProjectExplorer::Node *node
         if (QmakePriFileNode *subPriFileNode = dynamic_cast<QmakePriFileNode *>(node->projectNode()))
             subProjectNode = subPriFileNode->proFileNode();
     }
-    ProjectExplorer::FileNode *fileNode = dynamic_cast<ProjectExplorer::FileNode *>(node);
+    ProjectExplorer::FileNode *fileNode = node ? node->asFileNode() : 0;
     bool buildFilePossible = subProjectNode && fileNode
             && (fileNode->fileType() == ProjectExplorer::SourceType);
 
diff --git a/src/shared/qbs b/src/shared/qbs
index 6b9b900b699f507d0e7914ebca7e56d9f643c07f..9567f37d9f7b5f47caa01ba2d0dca61314d4deb5 160000
--- a/src/shared/qbs
+++ b/src/shared/qbs
@@ -1 +1 @@
-Subproject commit 6b9b900b699f507d0e7914ebca7e56d9f643c07f
+Subproject commit 9567f37d9f7b5f47caa01ba2d0dca61314d4deb5