[PATCH 2/5] make the typebuilder aware of pointer-to-membertypes, fix inappropriate locking

Floris Ruijter flo.ruijt at hotmail.com
Sat Feb 5 04:21:36 UTC 2011


	this includes an edit to a test to test for p2m types too now
---
 languages/cpp/cppduchain/CMakeLists.txt         |    1 +
 languages/cpp/cppduchain/cpptypes.h             |    1 +
 languages/cpp/cppduchain/expressionvisitor.cpp  |   71 ++++++++------
 languages/cpp/cppduchain/ptrtomembertype.cpp    |  118 +++++++++++++++++++++++
 languages/cpp/cppduchain/ptrtomembertype.h      |   78 +++++++++++++++
 languages/cpp/cppduchain/tests/test_duchain.cpp |    1 +
 languages/cpp/cppduchain/type_visitor.cpp       |   40 +++++---
 languages/cpp/cppduchain/typebuilder.cpp        |   10 ++
 languages/cpp/cppduchain/typebuilder.h          |    1 +
 9 files changed, 277 insertions(+), 44 deletions(-)
 create mode 100644 languages/cpp/cppduchain/ptrtomembertype.cpp
 create mode 100644 languages/cpp/cppduchain/ptrtomembertype.h

diff --git a/languages/cpp/cppduchain/CMakeLists.txt b/languages/cpp/cppduchain/CMakeLists.txt
index 7eba67f..5f27b8f 100644
--- a/languages/cpp/cppduchain/CMakeLists.txt
+++ b/languages/cpp/cppduchain/CMakeLists.txt
@@ -26,6 +26,7 @@ set(kdevcppduchain_LIB_SRCS
     cppeditorintegrator.cpp
     dumpchain.cpp
     cpptypes.cpp
+    ptrtomembertype.cpp
     dumptypes.cpp
     environmentmanager.cpp
     cppduchain.cpp
diff --git a/languages/cpp/cppduchain/cpptypes.h b/languages/cpp/cppduchain/cpptypes.h
index 87645e9..ccf4848 100644
--- a/languages/cpp/cppduchain/cpptypes.h
+++ b/languages/cpp/cppduchain/cpptypes.h
@@ -36,6 +36,7 @@
 #include "cppduchainexport.h"
 #include <language/duchain/types/alltypes.h>
 #include <language/duchain/types/typesystem.h>
+#include "ptrtomembertype.h"
 
 namespace KDevelop
 {
diff --git a/languages/cpp/cppduchain/expressionvisitor.cpp b/languages/cpp/cppduchain/expressionvisitor.cpp
index 7e73477..af75b1e 100644
--- a/languages/cpp/cppduchain/expressionvisitor.cpp
+++ b/languages/cpp/cppduchain/expressionvisitor.cpp
@@ -1178,6 +1178,8 @@ void ExpressionVisitor::createDelayedType( AST* node , bool expression ) {
       if(fail || !constructedType) {
         DefaultVisitor::visitInitDeclarator(node);
         return;
+      } else {
+        visitNodes(this,node->declarator->ptr_ops);
       }
 
       DeclarationPointer chosenFunction;
@@ -1225,19 +1227,19 @@ void ExpressionVisitor::createDelayedType( AST* node , bool expression ) {
 
     visit(node->parameter_declaration_clause);
     visit(node->exception_spec);
+    {
+      LOCKDUCHAIN;
+      if( node->array_dimensions && oldLastType ) {
+        ArrayType::Ptr p( new ArrayType() );
+        p->setElementType( oldLastType );
 
-    LOCKDUCHAIN;
-    if( node->array_dimensions && oldLastType ) {
-      ArrayType::Ptr p( new ArrayType() );
-      p->setElementType( oldLastType );
-
-      m_lastType = p.cast<AbstractType>();
-      m_lastInstance = Instance(false);
-    }else{
-      m_lastType = oldLastType;
-      m_lastInstance = oldLastInstance;
+        m_lastType = p.cast<AbstractType>();
+        m_lastInstance = Instance(false);
+      }else{
+        m_lastType = oldLastType;
+        m_lastInstance = oldLastInstance;
+      }
     }
-
     visitNodes(this, node->ptr_ops);
   }
 
@@ -1262,7 +1264,7 @@ void ExpressionVisitor::createDelayedType( AST* node , bool expression ) {
     m_lastType = lastType;
     m_lastInstance = instance;
 
-    LOCKDUCHAIN;
+//    LOCKDUCHAIN;
     visit(node->ptr_op);
   }
 
@@ -1296,35 +1298,46 @@ void ExpressionVisitor::createDelayedType( AST* node , bool expression ) {
 
     if( !m_lastType ) {
       problem(node, "Pointer-operator used without type");
-      return;
+//      return;
     }
 
     if( m_lastInstance ) {
       problem(node, "Pointer-operator used on an instance instead of a type");
-      return;
+//      return;
     }
 
-    LOCKDUCHAIN;
-
-    static IndexedString ref("&");
-    static IndexedString ptr("*");
+//    LOCKDUCHAIN;
+    
+    ///pointer-to-member
+    if(node->op==0){
+      PtrToMemberType::Ptr p( new PtrToMemberType() );
+      p->setBaseType( m_lastType );
+      p->setModifiers(TypeBuilder::parseConstVolatile(m_session, node->cv));
+      visit( node->mem_ptr->class_type );
+      p->setClassType( m_lastType );
+      m_lastType = p.cast<AbstractType>();
+    } else {
+      
+      static IndexedString ref("&");
+      static IndexedString ptr("*");
 
-    IndexedString op = m_session->token_stream->token(node->op).symbol();
+      IndexedString op = m_session->token_stream->token(node->op).symbol();
 
 
-    if(op == ptr) {
+      if(op == ptr) {
 
-      PointerType::Ptr p( new PointerType() );
-      p->setBaseType( m_lastType );
-      p->setModifiers(TypeBuilder::parseConstVolatile(m_session, node->cv));
+        PointerType::Ptr p( new PointerType() );
+        p->setBaseType( m_lastType );
+        p->setModifiers(TypeBuilder::parseConstVolatile(m_session, node->cv));
 
-      m_lastType = p.cast<AbstractType>();
-    }else{
-      ReferenceType::Ptr p( new ReferenceType() );
-      p->setBaseType( m_lastType );
-      p->setModifiers(TypeBuilder::parseConstVolatile(m_session, node->cv));
+        m_lastType = p.cast<AbstractType>();
+      }else{
+        ReferenceType::Ptr p( new ReferenceType() );
+        p->setBaseType( m_lastType );
+        p->setModifiers(TypeBuilder::parseConstVolatile(m_session, node->cv));
 
-      m_lastType = p.cast<AbstractType>();
+        m_lastType = p.cast<AbstractType>();
+      }
     }
     m_lastInstance = Instance(false);
   }
diff --git a/languages/cpp/cppduchain/ptrtomembertype.cpp b/languages/cpp/cppduchain/ptrtomembertype.cpp
new file mode 100644
index 0000000..d7b6b3e
--- /dev/null
+++ b/languages/cpp/cppduchain/ptrtomembertype.cpp
@@ -0,0 +1,118 @@
+/* This file is part of KDevelop
+ *    Copyright 2006 Roberto Raggi <roberto at kdevelop.org>
+ *    Copyright 2006-2008 Hamish Rodda <rodda at kde.org>
+ *    Copyright 2007-2008 David Nolden <david.nolden.kdevelop at art-master.de>
+ *    Copyright 2010 Floris Ruijter <flo.ruijt at hotmail.com> , adaption of pointertype by above-mentioned authors
+ *
+ *   This library is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU Library General Public
+ *   License version 2 as published by the Free Software Foundation.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *   Library General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Library General Public License
+ *   along with this library; see the file COPYING.LIB.  If not, write to
+ *   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *   Boston, MA 02110-1301, USA.
+ */
+#include "ptrtomembertype.h"
+
+#include <language/duchain/indexedstring.h>
+#include <language/duchain/repositories/typerepository.h>
+#include <language/duchain/types/typesystemdata.h>
+#include <language/duchain/types/typeregister.h>
+#include <language/duchain/types/typesystem.h>
+#include <language/duchain/types/typesystemdata.h>
+
+namespace Cpp {
+/// Private data structure for PtrToMemberType
+using namespace KDevelop;
+class KDEVCPPDUCHAIN_EXPORT PtrToMemberTypeData : public KDevelop::PointerTypeData {
+public:
+/// Constructor
+  PtrToMemberTypeData()
+      : m_classType ( 0 ) {}
+/// Copy constructor. \param rhs data to copy
+  PtrToMemberTypeData ( const PtrToMemberTypeData& rhs )
+      : PointerTypeData ( rhs )
+      , m_classType ( rhs.m_classType ) {}
+/// Type of data at which the pointer points
+  KDevelop::IndexedType m_classType;
+};
+
+REGISTER_TYPE ( PtrToMemberType );
+
+PtrToMemberType::PtrToMemberType ( const PtrToMemberType& rhs )
+    : PointerType ( copyData<PtrToMemberType> ( *rhs.d_func() ) ) {
+}
+
+PtrToMemberType::PtrToMemberType ( PtrToMemberTypeData& data )
+    : PointerType ( data ) {
+}
+
+PtrToMemberType::PtrToMemberType()
+    : PointerType ( createData<PtrToMemberType>() ) {
+}
+
+AbstractType* PtrToMemberType::clone() const {
+  return new PtrToMemberType ( *this );
+}
+
+
+bool PtrToMemberType::equals ( const AbstractType* _rhs ) const {
+  if ( this == _rhs )
+    return true;
+
+  if ( !PointerType::equals ( _rhs ) )
+    return false;
+
+  Q_ASSERT ( KDevelop::fastCast<const PtrToMemberType*> ( _rhs ) );
+
+  const PtrToMemberType* rhs = static_cast<const PtrToMemberType*> ( _rhs );
+
+  return d_func()->m_classType == rhs->d_func()->m_classType;
+}
+
+void PtrToMemberType::accept0 ( TypeVisitor *v ) const {
+  BaseType::accept0 ( v );
+  if ( v->visit ( this ) )
+    acceptType ( d_func()->m_classType.abstractType(), v );
+  v->endVisit ( this );
+}
+
+void PtrToMemberType::exchangeTypes ( TypeExchanger* exchanger ) {
+  BaseType::exchangeTypes ( exchanger );
+  d_func_dynamic()->m_classType = exchanger->exchange ( d_func()->m_classType.abstractType() )->indexed();
+}
+
+PtrToMemberType::~PtrToMemberType() {
+}
+
+AbstractType::Ptr PtrToMemberType::ClassType() const {
+  return d_func()->m_classType.abstractType();
+}
+
+void PtrToMemberType::setClassType ( AbstractType::Ptr type ) {
+  d_func_dynamic()->m_classType = type->indexed();
+}
+
+QString PtrToMemberType::toString() const {
+  QString baseString  = ( baseType()  ? baseType()->toString()  : "<notype>" );
+  QString classString = ( ClassType() ? ClassType()->toString() : "<notype>" );
+  return QString ( "%1 %2::*" ).arg ( baseString,classString ) + AbstractType::toString ( true );
+}
+
+AbstractType::WhichType PtrToMemberType::whichType() const {
+  return TypePointer; //a bit of a kludge, ptr-to-member is unique.
+}
+
+uint PtrToMemberType::hash() const {
+  return PointerType::hash() + d_func()->m_classType.hash() * 17  ;
+}
+
+}
+
+// kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on
diff --git a/languages/cpp/cppduchain/ptrtomembertype.h b/languages/cpp/cppduchain/ptrtomembertype.h
new file mode 100644
index 0000000..e82869c
--- /dev/null
+++ b/languages/cpp/cppduchain/ptrtomembertype.h
@@ -0,0 +1,78 @@
+/* This file is part of KDevelop
+ *    Copyright 2006 Roberto Raggi <roberto at kdevelop.org>
+ *    Copyright 2006-2008 Hamish Rodda <rodda at kde.org>
+ *    Copyright 2007-2008 David Nolden <david.nolden.kdevelop at art-master.de>
+ *    Copyright 2010 Floris Ruijter <flo.ruijt at hotmail.com> , adaption of pointertype by above-mentioned authors
+ * 
+ *   This library is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU Library General Public
+ *   License version 2 as published by the Free Software Foundation.
+ * 
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *   Library General Public License for more details.
+ * 
+ *   You should have received a copy of the GNU Library General Public License
+ *   along with this library; see the file COPYING.LIB.  If not, write to
+ *   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *   Boston, MA 02110-1301, USA.
+ */
+#ifndef PTRTOMEMBERTYPE_H
+#define PTRTOMEMBERTYPE_H
+
+#include <language/duchain/types/pointertype.h>
+#include <language/duchain/types/structuretype.h>
+#include "cppduchainexport.h"
+namespace Cpp {
+class PtrToMemberTypeData;
+class KDEVCPPDUCHAIN_EXPORT PtrToMemberType : public KDevelop::PointerType
+{
+  public:
+    typedef TypePtr<PtrToMemberType> Ptr;
+    typedef PointerType BaseType;
+    
+    /// Default constructor
+    PtrToMemberType ();
+    /// Copy constructor. \param rhs type to copy
+    PtrToMemberType(const PtrToMemberType& rhs);
+    /// Constructor using raw data. \param data internal data.
+    PtrToMemberType(PtrToMemberTypeData& data);
+    /// Destructor
+    virtual ~PtrToMemberType();
+    
+    /**
+      * sets the class type, ie. the B of A B::* foo
+      *
+      * \param ClassType : B
+      */
+    void setClassType(AbstractType::Ptr type);
+    
+    AbstractType::Ptr ClassType () const;
+    
+    virtual QString toString() const;
+    
+    virtual uint hash() const;
+    
+    virtual WhichType whichType() const;
+    
+    virtual AbstractType* clone() const;
+    
+    virtual bool equals(const AbstractType* rhs) const;
+    
+    virtual void exchangeTypes( KDevelop::TypeExchanger* exchanger );
+    
+    enum {
+        Identity = 42 ///TODO check uniqueness
+      };
+      
+      typedef PtrToMemberTypeData Data;
+      
+    protected:
+      virtual void accept0 (KDevelop::TypeVisitor *v) const;
+      
+      TYPE_DECLARE_DATA(PtrToMemberType)
+      
+    };
+}
+#endif // PTRTOMEMBERTYPE_H
\ No newline at end of file
diff --git a/languages/cpp/cppduchain/tests/test_duchain.cpp b/languages/cpp/cppduchain/tests/test_duchain.cpp
index 97327fb..e9789a0 100644
--- a/languages/cpp/cppduchain/tests/test_duchain.cpp
+++ b/languages/cpp/cppduchain/tests/test_duchain.cpp
@@ -499,6 +499,7 @@ void TestDUChain::testIntegralTypes()
   //Even if reference/pointer types have an invalid target, they should still preserve the pointer
   QVERIFY(AbstractType::Ptr(new ReferenceType)->toString().endsWith("&"));
   QVERIFY(AbstractType::Ptr(new PointerType)->toString().endsWith("*"));
+  QVERIFY(AbstractType::Ptr(new PtrToMemberType)->toString().endsWith("::*"));
 
 }
 
diff --git a/languages/cpp/cppduchain/type_visitor.cpp b/languages/cpp/cppduchain/type_visitor.cpp
index cf00e6c..3d7c5ae 100644
--- a/languages/cpp/cppduchain/type_visitor.cpp
+++ b/languages/cpp/cppduchain/type_visitor.cpp
@@ -58,22 +58,32 @@ void TypeASTVisitor::run(TypeIdAST *node)
         do
           {
             PtrOperatorAST* ptrOp = it->element;
-            if (ptrOp && ptrOp->op) { ///@todo check ordering, eventually walk the chain in reversed order
-              IndexedString op = m_session->token_stream->token(ptrOp->op).symbol();
-              static IndexedString ref("&");
-              static IndexedString ptr("*");
-              if (!op.isEmpty()) {
-                if (op == ref) {
-                  ReferenceType::Ptr pointer(new ReferenceType());
-                  pointer->setModifiers(TypeBuilder::parseConstVolatile(m_session, ptrOp->cv));
-                  pointer->setBaseType(m_type);
-                  m_type = pointer.cast<AbstractType>();
-                } else if (op == ptr) {
-                  PointerType::Ptr pointer(new PointerType());
-                  pointer->setModifiers(TypeBuilder::parseConstVolatile(m_session, ptrOp->cv));
-                  pointer->setBaseType(m_type);
-                  m_type = pointer.cast<AbstractType>();
+            if (ptrOp){
+              if(ptrOp->op) { ///@todo check ordering, eventually walk the chain in reversed order
+                IndexedString op = m_session->token_stream->token(ptrOp->op).symbol();
+                static IndexedString ref("&");
+                static IndexedString ptr("*");
+                if (!op.isEmpty()) {
+                  if (op == ref) {
+                    ReferenceType::Ptr pointer(new ReferenceType());
+                    pointer->setModifiers(TypeBuilder::parseConstVolatile(m_session, ptrOp->cv));
+                    pointer->setBaseType(m_type);
+                    m_type = pointer.cast<AbstractType>();
+                  } else if (op == ptr) {
+                    PointerType::Ptr pointer(new PointerType());
+                    pointer->setModifiers(TypeBuilder::parseConstVolatile(m_session, ptrOp->cv));
+                    pointer->setBaseType(m_type);
+                    m_type = pointer.cast<AbstractType>();
+                  }
                 }
+              } else{ ///ptr-to-member
+                PtrToMemberType::Ptr pointer(new PtrToMemberType);
+                pointer->setModifiers(TypeBuilder::parseConstVolatile(m_session, ptrOp->cv));
+                pointer->setBaseType(m_type);
+                PtrToMemberAST * ast=ptrOp->mem_ptr;
+                visit(ast);
+                pointer->setClassType(m_type);
+                m_type=pointer.cast<AbstractType>();
               }
             }
             it = it->next;
diff --git a/languages/cpp/cppduchain/typebuilder.cpp b/languages/cpp/cppduchain/typebuilder.cpp
index 73723b2..994cc3d 100644
--- a/languages/cpp/cppduchain/typebuilder.cpp
+++ b/languages/cpp/cppduchain/typebuilder.cpp
@@ -594,6 +594,16 @@ void TypeBuilder::visitPtrOperator(PtrOperatorAST* node)
     closeType();
 }
 
+void TypeBuilder::visitPtrToMember(PtrToMemberAST *node)
+{
+  PtrToMemberType::Ptr pointer(new PtrToMemberType);
+  pointer->setBaseType(lastType());
+  ContextBuilder::visitPtrToMember(node);
+  pointer->setClassType(lastType());
+  openType(pointer);
+  closeType();
+}
+
 FunctionType* TypeBuilder::openFunction(DeclaratorAST *node)
 {
   FunctionType* functionType = new FunctionType();
diff --git a/languages/cpp/cppduchain/typebuilder.h b/languages/cpp/cppduchain/typebuilder.h
index 7fff507..b81c853 100644
--- a/languages/cpp/cppduchain/typebuilder.h
+++ b/languages/cpp/cppduchain/typebuilder.h
@@ -60,6 +60,7 @@ protected:
   virtual void visitTypedef(TypedefAST*);
   virtual void visitFunctionDeclaration(FunctionDefinitionAST*);
   virtual void visitPtrOperator(PtrOperatorAST*);
+  virtual void visitPtrToMember(PtrToMemberAST*);
   virtual void visitUsing(UsingAST *);
   virtual void visitParameterDeclaration(ParameterDeclarationAST*);
   virtual void visitTemplateParameter(TemplateParameterAST *);
-- 
1.7.2.3


--=-jnTU9w3TPwGq4NfAnuZF
Content-Disposition: attachment; filename*0=0003-fixup-the-usebuilder-the-codegenerator-and-the-ducha.pat; filename*1=ch
Content-Type: text/x-patch; name="0003-fixup-the-usebuilder-the-codegenerator-and-the-ducha.patch"; charset="UTF-8"
Content-Transfer-Encoding: 7bit



More information about the KDevelop-devel mailing list