public IASTDeclaration getPrimaryDeclaration() {
    // first check if we already know it
    if (declarations != null) {
      for (IASTDeclarator dtor : declarations) {
        if (dtor == null) {
          break;
        }
        dtor = ASTQueries.findOutermostDeclarator(dtor);
        IASTDeclaration decl = (IASTDeclaration) dtor.getParent();
        if (decl.getParent() instanceof ICPPASTCompositeTypeSpecifier) return decl;
      }
    }
    if (definition != null) {
      IASTDeclarator dtor = ASTQueries.findOutermostDeclarator(definition);
      IASTDeclaration decl = (IASTDeclaration) dtor.getParent();
      if (decl.getParent() instanceof ICPPASTCompositeTypeSpecifier) return decl;
    }

    final char[] myName = getASTName().getLookupKey();
    ICPPClassScope scope = (ICPPClassScope) getScope();
    ICPPASTCompositeTypeSpecifier compSpec =
        (ICPPASTCompositeTypeSpecifier) ASTInternal.getPhysicalNodeOfScope(scope);
    if (compSpec != null) {
      IASTDeclaration[] members = compSpec.getMembers();
      for (IASTDeclaration member : members) {
        if (member instanceof IASTSimpleDeclaration) {
          IASTDeclarator[] dtors = ((IASTSimpleDeclaration) member).getDeclarators();
          for (IASTDeclarator dtor : dtors) {
            IASTName name = ASTQueries.findInnermostDeclarator(dtor).getName();
            if (CharArrayUtils.equals(name.getLookupKey(), myName)
                && name.resolveBinding() == this) {
              return member;
            }
          }
        } else if (member instanceof IASTFunctionDefinition) {
          final IASTFunctionDeclarator declarator =
              ((IASTFunctionDefinition) member).getDeclarator();
          IASTName name = ASTQueries.findInnermostDeclarator(declarator).getName();
          if (CharArrayUtils.equals(name.getLookupKey(), myName) && name.resolveBinding() == this) {
            return member;
          }
        }
      }
    }
    return null;
  }
 /*
  * @see org.eclipse.cdt.core.dom.ast.ASTVisitor#leave(org.eclipse.cdt.core.dom.ast.IASTDeclaration)
  */
 @Override
 public int leave(IASTDeclaration node) {
   super.leave(node);
   boolean isTemplateDecl = isTemplateDecl(node);
   final int endOffset = isTemplateDecl ? getEndOffset(node.getParent()) : getEndOffset(node);
   if (node instanceof IASTFunctionDefinition) {
     final int nodeType;
     if (inClassBody()) {
       nodeType = isTemplateDecl ? ICElement.C_TEMPLATE_METHOD : ICElement.C_METHOD;
     } else {
       nodeType = isTemplateDecl ? ICElement.C_TEMPLATE_FUNCTION : ICElement.C_FUNCTION;
     }
     assert getCurrentContainer().getTypeCode() == nodeType;
     pop(endOffset);
   } else if (node instanceof IASTSimpleDeclaration) {
     IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) node;
     IASTDeclSpecifier declSpec = simpleDecl.getDeclSpecifier();
     boolean isCompositeType = false;
     if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
       isCompositeType = true;
       ICPPASTCompositeTypeSpecifier compositeTypeSpec = (ICPPASTCompositeTypeSpecifier) declSpec;
       final int nodeType;
       switch (compositeTypeSpec.getKey()) {
         case IASTCompositeTypeSpecifier.k_struct:
           nodeType = isTemplateDecl ? ICElement.C_TEMPLATE_STRUCT : ICElement.C_STRUCT;
           break;
         case IASTCompositeTypeSpecifier.k_union:
           nodeType = isTemplateDecl ? ICElement.C_TEMPLATE_UNION : ICElement.C_UNION;
           break;
         case ICPPASTCompositeTypeSpecifier.k_class:
           nodeType = isTemplateDecl ? ICElement.C_TEMPLATE_CLASS : ICElement.C_CLASS;
           break;
         default:
           assert false : "Unexpected composite type specifier"; // $NON-NLS-1$
           return PROCESS_CONTINUE;
       }
       assert getCurrentContainer().getTypeCode() == nodeType;
       pop(isTemplateDecl ? endOffset : getEndOffset(declSpec));
     } else if (declSpec instanceof IASTEnumerationSpecifier) {
       isCompositeType = true;
       assert getCurrentContainer().getTypeCode() == ICElement.C_ENUMERATION;
       pop(getEndOffset(declSpec));
     }
     if (isCompositeType) {
       IASTDeclarator[] declarators = simpleDecl.getDeclarators();
       for (int i = 0; i < declarators.length; i++) {
         IASTDeclarator declarator = declarators[i];
         final String nodeName = getDeclaratorName(declarator);
         final int declStartOffset = getStartOffset(declarator);
         final int declEndOffset = getEndOffset(declarator);
         if (declSpec.getStorageClass() == IASTDeclSpecifier.sc_typedef) {
           push(ICElement.C_TYPEDEF, nodeName, declStartOffset);
           pop(declEndOffset);
         } else if (declarator instanceof IASTFunctionDeclarator
             && !hasNestedPointerOperators(declarator)) {
           final int nodeType;
           if (inClassBody()) {
             nodeType =
                 isTemplateDecl
                     ? ICElement.C_TEMPLATE_METHOD_DECLARATION
                     : ICElement.C_METHOD_DECLARATION;
           } else {
             nodeType =
                 isTemplateDecl
                     ? ICElement.C_TEMPLATE_FUNCTION_DECLARATION
                     : ICElement.C_FUNCTION_DECLARATION;
           }
           push(nodeType, nodeName, declStartOffset);
           pop(declEndOffset);
         } else if (declarator != null) {
           final int nodeType;
           if (inClassBody()) {
             nodeType = ICElement.C_FIELD;
           } else {
             if (declSpec.getStorageClass() == IASTDeclSpecifier.sc_extern) {
               nodeType = ICElement.C_VARIABLE_DECLARATION;
             } else {
               nodeType = isTemplateDecl ? ICElement.C_TEMPLATE_VARIABLE : ICElement.C_VARIABLE;
             }
           }
           push(nodeType, nodeName, declStartOffset);
           pop(declEndOffset);
         }
       }
     }
   } else if (node instanceof IASTASMDeclaration) {
     // ignored
   } else if (node instanceof ICPPASTVisibilityLabel) {
     // ignored
   } else if (node instanceof ICPPASTNamespaceDefinition) {
     // handled below
   } else if (node instanceof ICPPASTNamespaceAlias) {
     // ignored
   } else if (node instanceof ICPPASTUsingDeclaration) {
     // handled in visit
   } else if (node instanceof ICPPASTUsingDirective) {
     // handled in visit
   } else if (node instanceof ICPPASTLinkageSpecification) {
     // declarations get flattened
   } else if (node instanceof ICPPASTTemplateDeclaration) {
     // handled at child declaration level
   } else if (node instanceof ICPPASTTemplateSpecialization) {
     // ignored
   } else if (node instanceof ICPPASTExplicitTemplateInstantiation) {
     // ignored
   } else if (node instanceof IASTProblemDeclaration) {
     // ignored
   }
   return PROCESS_CONTINUE;
 }