Skip to main content
aboutsummaryrefslogblamecommitdiffstats
blob: bb3cacde61970f55469b11d8bffb8a09bf29c0e8 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                                                                
                                                                





                                                                        
                                                     
                               
                                                                                 

                                                     
                            
                       
                         
                       
 
                                                    
                                               
                                                               

                                                      

                                                   

                                                           
                                             
                                             
                                                             
                                                          
                                                        
                                               
                                           
                                                                      
                                                                       
                                                                  
                                                                   
                                                          
                                                                      
                                                                 

                                                                           


                                                                         
                                                        
   
                                                        
                                         


                                                                         
                                                           

                                          
                                                                      




                                                                    
 






                                                                          
 
                                          
                             
                                           



                                                
                                                 



                                                             

                                                                       
                                              



                                                                                
                                                                               









                                                                                                                                                  

                                              

                                                                     
                                 

                                                       


                                                                

                                    
 


                                                                        
                                             






                                                                        
                                             
 


                                                                                              
 


                                                                                                   
 






                                                                                       



                                        
                                                                       
                                                                            
         
 

                                                
                                                                                                                 

                                                                                         
                                                                                                         
                                                                     


                                                                                                           
                                            
                                                             




                                                                                                                
                                                     

                                                                                                                









                                                                                                                    
                                            
                 



                                        



                                                       

                                                                                                    

                                                                                         
                                            
                                                                              





                                                                                                      
                                                                                        





                                                                                                                       

                                 


                                                                
                 


                                        









                                                       
                                                                                  



                                                                               


                                        
                                                                   
                                                                                    
                                                            
                                                                                              

                 
 





                                                                                              

           
                                                                            

                                                              


                                                                                
                                                                                 





                                                                               
                                 

                                                                    


                         
 
/*******************************************************************************
 * Copyright (c) 2009, 2016 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
 *     Sergey Prigogin (Google)
 *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashSet;
import java.util.Stack;

import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;

/**
 * Visitor to resolve AST ambiguities in the right order
 */
final class CPPASTAmbiguityResolver extends ASTVisitor {
	private int fSkipInitializers= 0;
	/*
	 * The current nesting level of class definitions.
	 * Used to handle processing of method bodies, which are deferred
	 * until the end of the outermost class definition.
	 */
	private int fClassNestingLevel= 0;
	private HashSet<IASTDeclaration> fRepopulate= new HashSet<>();
	/*
	 * Nodes that have been deferred for later processing.
	 * Currently used only for method bodies.
	 */
	private Deque<IASTNode> fDeferredNodes = new ArrayDeque<>();

	/*
	 * Used by visit(IASTDeclaration) to determine whether it should
	 * process a function declaration now instead of deferring it
	 * to later. There is a stack of them because, thanks to local
	 * classes, function definitions can be nested inside each other.
	 */
	private Stack<IASTFunctionDefinition> fProcessNow = new Stack<>();

	public CPPASTAmbiguityResolver() {
		super(false);
		includeInactiveNodes= true;
		shouldVisitAmbiguousNodes= true;
		shouldVisitDeclarations= true;
		shouldVisitDeclSpecifiers= true;
		shouldVisitInitializers= true;
		shouldVisitTranslationUnit= true;
	}

	@Override
	public int visit(ASTAmbiguousNode astAmbiguousNode) {
		IASTNode node= astAmbiguousNode.resolveAmbiguity(this);
		if (node instanceof IASTDeclarator) {
			while (node != null) {
				if (node instanceof IASTDeclaration) {
					fRepopulate.add((IASTDeclaration) node);
					break;
				}
				if (node instanceof IASTParameterDeclaration) {
					// If the parameter declaration belongs to a function declaration or
					// function definition we need to update the scope.
					IASTNode parent= node.getParent();
					if (parent instanceof IASTDeclarator) {
						IASTDeclarator dtor= (IASTDeclarator) parent;
						if (dtor == ASTQueries.findTypeRelevantDeclarator(dtor) &&
								ASTQueries.findOutermostDeclarator(dtor).getParent() instanceof IASTDeclaration) {
							repopulateScope((IASTParameterDeclaration) node);
						}
					}
					break;
				}
				if (node instanceof IASTExpression) {
					break;
				}
				node= node.getParent();
			}
		} else if (node instanceof IASTDeclaration) {
			repopulateScope((IASTDeclaration) node);
		}
		return PROCESS_SKIP;
	}

	@Override
	public int visit(IASTDeclSpecifier declSpec) {
		if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
			fClassNestingLevel++;
		}
		return PROCESS_CONTINUE;
	}

	@Override
	public int leave(IASTDeclSpecifier declSpec) {
		if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
			fClassNestingLevel--;

			// Resolve class type definitions, such that the scope is available
			// during ambiguity resolution.
			((ICPPASTCompositeTypeSpecifier) declSpec).getName().resolveBinding();

			// Trigger computation of implicit members.
			if (declSpec instanceof CPPASTCompositeTypeSpecifier)
				((CPPASTCompositeTypeSpecifier) declSpec).setAmbiguitiesResolved();

			// If we are leaving the outermost class, process the bodies of
			// methods of the class and its nested classes.
			if (fClassNestingLevel == 0) {
				while (!fDeferredNodes.isEmpty()) {
					fDeferredNodes.removeFirst().accept(this);
				}
			}
		}
		return PROCESS_CONTINUE;
	}

	private boolean shouldProcessNow(IASTFunctionDefinition func) {
		return !fProcessNow.isEmpty() && fProcessNow.peek() == func;
	}

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

			// Visit the declarator first, it may contain ambiguous template arguments needed
			// for associating the template declarations.
			ICPPASTFunctionDeclarator fdecl = (ICPPASTFunctionDeclarator) fdef.getDeclarator();
			fSkipInitializers++; // Initializers may refer to class members declared later.
			fdecl.accept(this);
			fSkipInitializers--;
			fdef.getDeclSpecifier().accept(this);
			IASTTypeId trailingReturnType = fdecl.getTrailingReturnType();
			if (trailingReturnType != null) {
				// Visit initializers inside the trailing return type that were skipped earlier.
				trailingReturnType.accept(this);
			}
			if (fClassNestingLevel > 0) {
				// If this is a method defined inline inside a class declaration, defer visiting
				// the remaining parts of the method (notably the body) until the end of the
				// class declaration has been reached.
				fDeferredNodes.add(decl);
			} else {
				// Otherwise, visit the remaining parts of the method now. To avoid duplicating
				// code in CPPASTFunctionDefinition.accept(), call accept() on the entire
				// definition, but push the function definition onto fProcessNow to avoid recursion.
				fProcessNow.push(fdef);
				decl.accept(this);
				fProcessNow.pop();
			}
			return PROCESS_SKIP;
		}
		return PROCESS_CONTINUE;
	}

	@Override
	public int leave(IASTDeclaration declaration) {
		if (fRepopulate.remove(declaration)) {
			repopulateScope(declaration);
		}
		// We need to create class bindings for all definitions and for the specializations.
		// Otherwise, name resolution cannot access members or correct specialization.
		if (declaration instanceof IASTSimpleDeclaration) {
			IASTSimpleDeclaration sdecl= (IASTSimpleDeclaration) declaration;
			IASTName name= null;
			IASTDeclSpecifier declspec = sdecl.getDeclSpecifier();
			if (declspec instanceof IASTCompositeTypeSpecifier) {
				// Definition of a class[template[specialization]]
				name= ((IASTCompositeTypeSpecifier) declspec).getName().getLastName();
			} else if (declspec instanceof ICPPASTElaboratedTypeSpecifier
					&& sdecl.getDeclarators().length == 0) {
				ASTNodeProperty prop = declaration.getPropertyInParent();
				if (prop == ICPPASTTemplateDeclaration.OWNED_DECLARATION
						|| prop == ICPPASTTemplateSpecialization.OWNED_DECLARATION) {
					ICPPASTElaboratedTypeSpecifier elab= (ICPPASTElaboratedTypeSpecifier) declspec;
					if (!elab.isFriend()) {
						// Declaration of a class template specialization.
						name= elab.getName().getLastName();
					}
				}
			}
			if (name instanceof ICPPASTTemplateId) {
				name.resolveBinding();
			}
		}
		return PROCESS_CONTINUE;
	}

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

		return PROCESS_CONTINUE;
	}

	@Override
	public int leave(IASTTranslationUnit tu) {
		// As deferred method bodies are processed at the end of outermost
		// class definitions, there should be none left when the end of
		// the translation unit is reached.
		assert fDeferredNodes.isEmpty();
		assert fProcessNow.isEmpty();
		return PROCESS_CONTINUE;
	}

	private void repopulateScope(IASTDeclaration declaration) {
		IScope scope= CPPVisitor.getContainingNonTemplateScope(declaration);
		if (scope instanceof ICPPASTInternalScope) {
			CPPSemantics.populateCache((ICPPASTInternalScope) scope, declaration);
		}
	}

	private void repopulateScope(IASTParameterDeclaration declaration) {
		IScope scope= CPPVisitor.getContainingNonTemplateScope(declaration);
		if (scope instanceof ICPPASTInternalScope) {
			CPPSemantics.populateCache((ICPPASTInternalScope) scope, declaration);
		}
	}

	/**
	 * If 'node' has been deferred for later processing, process it now.
	 */
	public void resolvePendingAmbiguities(IASTNode node) {
		for (IASTNode deferredNode : fDeferredNodes) {
			if (deferredNode == node) {
				// Temporarily set the class nesting level to 0,
				// to prevent the node just being deferred again.
				int classNestingLevel = fClassNestingLevel;
				fClassNestingLevel = 0;
				try {
					deferredNode.accept(this);
				} finally {
					fClassNestingLevel = classNestingLevel;
				}
				fDeferredNodes.remove(deferredNode);
				break;
			}
		}
	}
}

Back to the top