@Override
 public ICPPClassType[] getNestedClasses(IASTNode point) {
   IScope scope = getCompositeScope();
   if (scope instanceof ICPPClassSpecializationScope) {
     return ((ICPPClassSpecializationScope) scope).getNestedClasses(point);
   }
   try {
     PDOMClassUtil.NestedClassCollector visitor = new PDOMClassUtil.NestedClassCollector();
     PDOMCPPClassScope.acceptViaCache(this, visitor, false);
     return visitor.getNestedClasses();
   } catch (CoreException e) {
     CCorePlugin.log(e);
     return ICPPClassType.EMPTY_CLASS_ARRAY;
   }
 }
 @Override
 public ICPPMethod[] getDeclaredMethods(IASTNode point) {
   IScope scope = getCompositeScope();
   if (scope instanceof ICPPClassSpecializationScope) {
     return ((ICPPClassSpecializationScope) scope).getDeclaredMethods(point);
   }
   try {
     PDOMClassUtil.MethodCollector methods = new PDOMClassUtil.MethodCollector(false);
     PDOMCPPClassScope.acceptViaCache(this, methods, false);
     return methods.getMethods();
   } catch (CoreException e) {
     CCorePlugin.log(e);
     return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
   }
 }
 @Override
 public ICPPField[] getDeclaredFields(IASTNode point) {
   IScope scope = getCompositeScope();
   if (scope instanceof ICPPClassSpecializationScope) {
     return ((ICPPClassSpecializationScope) scope).getDeclaredFields(point);
   }
   try {
     PDOMClassUtil.FieldCollector visitor = new PDOMClassUtil.FieldCollector();
     PDOMCPPClassScope.acceptViaCache(this, visitor, false);
     return visitor.getFields();
   } catch (CoreException e) {
     CCorePlugin.log(e);
     return ICPPField.EMPTY_CPPFIELD_ARRAY;
   }
 }
  @Override
  public IBinding specializeMember(IBinding original, IASTNode point) {
    if (specializationMap == null) {
      final Long key = record + PDOMCPPLinkage.CACHE_INSTANCE_SCOPE;
      Object cached = getPDOM().getCachedResult(key);
      if (cached != null) {
        specializationMap = (ObjectMap) cached;
      } else {
        final ObjectMap newMap = new ObjectMap(2);
        try {
          PDOMClassUtil.NestedClassCollector visitor = new PDOMClassUtil.NestedClassCollector();
          PDOMCPPClassScope.acceptViaCache(this, visitor, false);
          final ICPPClassType[] nested = visitor.getNestedClasses();
          for (ICPPClassType classType : nested) {
            if (classType instanceof ICPPSpecialization) {
              newMap.put(((ICPPSpecialization) classType).getSpecializedBinding(), classType);
            }
          }
        } catch (CoreException e) {
          CCorePlugin.log(e);
        }
        specializationMap = (ObjectMap) getPDOM().putCachedResult(key, newMap, false);
      }
    }
    Set<IBinding> set;
    synchronized (specializationMap) {
      IBinding result = (IBinding) specializationMap.get(original);
      if (result != null) return result;
      set = fInProgress.get();
      if (set == null) {
        set = new HashSet<IBinding>();
        fInProgress.set(set);
      }
      if (!set.add(original)) return RecursionResolvingBinding.createFor(original, point);
    }
    IBinding newSpec = CPPTemplates.createSpecialization(this, original, point);
    set.remove(original);

    synchronized (specializationMap) {
      IBinding oldSpec = (IBinding) specializationMap.put(original, newSpec);
      if (oldSpec != null) {
        specializationMap.put(original, oldSpec);
        return oldSpec;
      }
    }
    return newSpec;
  }
 @Override
 public void accept(IPDOMVisitor visitor) throws CoreException {
   PDOMCPPClassScope.acceptViaCache(this, visitor, false);
 }