Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: a918e8ca50efcff8b3428d06936a7b12c113e343 (plain) (tree)




























                                                                                  
                                                               















                                                                          
                                          































































































                                                                                                                 
/*******************************************************************************
 * Copyright (c) 2009 Wind River Systems, Inc. and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Markus Schorn - initial API and implementation
 *******************************************************************************/ 
package org.eclipse.cdt.internal.core.dom.parser.cpp;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;

/**
 * Visitor to resolve ast ambiguities in the right order
 */
public final class CPPASTAmbiguityResolver extends ASTVisitor {
	private static class ClassContext {
		ArrayList<IASTNode> fDeferredNodes;
		final IASTNode fNode;
		public ClassContext(IASTNode node) {
			fNode= node;
		}
		public void deferNode(IASTNode node) {
			if (fDeferredNodes == null)
				fDeferredNodes= new ArrayList<IASTNode>();
			fDeferredNodes.add(node);
		}
	}
	private LinkedList<ClassContext> fContextStack;
	private ClassContext fCurrentContext;
	private boolean fSkipInitializers;
	
	public CPPASTAmbiguityResolver() {
		super(false);
		shouldVisitAmbiguousNodes= true;
		shouldVisitDeclarations= true;
		shouldVisitDeclSpecifiers= true;
		shouldVisitInitializers= true;
	}

	@Override
	public int visit(ASTAmbiguousNode astAmbiguousNode) {
		astAmbiguousNode.resolveAmbiguity(this);
		return PROCESS_SKIP;
	}
	
	@Override
	public int visit(IASTDeclSpecifier declSpec) {
		if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
			if (fCurrentContext != null) {
				// defer visiting nested classes until the outer class body has been visited.
				fCurrentContext.deferNode(declSpec);
				return PROCESS_SKIP;
			}
			pushContext();
			fCurrentContext= new ClassContext(declSpec);
		}
		return PROCESS_CONTINUE;
	}

	@Override
	public int leave(IASTDeclSpecifier declSpec) {
		if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
			assert fCurrentContext != null;
			assert fCurrentContext.fNode == declSpec;
			if (fCurrentContext != null) {
				final List<IASTNode> deferredNodes = fCurrentContext.fDeferredNodes;
				fCurrentContext= null;
				if (deferredNodes != null) {
					for (IASTNode node : deferredNodes) {
						node.accept(this);
					}
				}
				popContext();
			}
		}
		return PROCESS_CONTINUE;
	}

	private void pushContext() {
		if (fCurrentContext==null) {
			if (fContextStack != null && !fContextStack.isEmpty()) {
				fContextStack.addLast(null);
			}
		} else {
			if (fContextStack == null) {
				fContextStack= new LinkedList<ClassContext>();
			}
			fContextStack.addLast(fCurrentContext);
		}
	}

	private void popContext() {
		if (fContextStack == null || fContextStack.isEmpty()) {
			fCurrentContext= null;
		} else {
			fCurrentContext= fContextStack.removeLast();
		}
	}

	@Override
	public int visit(IASTDeclaration decl) {
		if (decl instanceof IASTFunctionDefinition) {
			final IASTFunctionDefinition fdef= (IASTFunctionDefinition) decl;

			// visit the declarator first, it may contain ambiguous template arguments needed 
			// for associating the template declarations.
			fSkipInitializers= true;
			CPPVisitor.findOutermostDeclarator(fdef.getDeclarator()).accept(this);
			fSkipInitializers= false;
			
			if (fCurrentContext != null) {
				// defer visiting the body of the function until the class body has been visited.
				fdef.getDeclSpecifier().accept(this);
				fCurrentContext.deferNode(decl);
				return PROCESS_SKIP;
			}
		} 
		return PROCESS_CONTINUE;
	}

	@Override
	public int visit(IASTInitializer initializer) {
		if (fSkipInitializers)
			return PROCESS_SKIP;

		return PROCESS_CONTINUE;
	}
}

Back to the top