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




























                                                                                         
                                                 
                                                      
                                                        






                                                                           

                                                                                          


                                           
                               
                                              



                                                  
                                           

                                                                                                          
                                           



                                                       
                                      


                                                         
                                          


                                                                
                                                 


                                                    
                                     

         
           

                                                                                                     
                                                 



                                                               









                                                                                                       
                                                  







                                                                                        








                                                                                                                              
                                                                                                                                 






                                                                                                        
                                 



                                                                                                                         
                         
 


                                                                                             

         


                                                                                                   
                                        
                                                                        
                                                                                                                     
                                                                                           
                                                                       










                                                                                                   
                                                                               
                                             


                            







                                                                                                                    
                                                        

                                             
                                             

                 
                                                                                     
                                                             
                                                                                
                                                                
                                             






                                                                                      

                                                                                       




                                                                                                                      
 
/*******************************************************************************
 * Copyright (c) 2007, 2014 IBM Corporation 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:
 *     Andrew Ferguson (Symbian) - initial API and implementation
 *     Markus Schorn (Wind River Systems)
 *     Sergey Prigogin (Google)
 *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;

import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;

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.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;

/**
 * Helps analysis of the class declaration for user declared members relevant for deciding
 * which implicit bindings to declare.
 *
 * @see chapter 12 of the ISO specification
 */
final class ImplicitsAnalysis {
	private final ICPPClassType classType;
	private boolean hasConstructor;
	private boolean hasCopyConstructor;
	private boolean hasCopyAssignmentOperator;
	private boolean hasDestructor;
	private boolean hasNonStaticFields;

	ImplicitsAnalysis(ICPPASTCompositeTypeSpecifier compositeTypeSpecifier, ICPPClassType classType) {
		this.classType = classType;
		analyzeMembers(compositeTypeSpecifier);
	}

	public boolean hasUserDeclaredConstructor() {
		return hasConstructor;
	}

	public boolean hasUserDeclaredCopyConstructor() {
		return hasCopyConstructor;
	}

	public boolean hasUserDeclaredCopyAssignmentOperator() {
		return hasCopyAssignmentOperator;
	}

	public boolean hasUserDeclaredDestructor() {
		return hasDestructor;
	}

	/**
	 * Returns the number of implicit methods to declare not counting the inherited constructors.
	 */
	public int getImplicitsToDeclareCount() {
		return (!hasDestructor ? 1 : 0)
			+ (!hasConstructor ? 1 : 0)
			+ (!hasCopyConstructor ? 1 : 0)
			+ (!hasCopyAssignmentOperator ? 1 : 0);
	}

	private void analyzeMembers(ICPPASTCompositeTypeSpecifier compositeTypeSpecifier) {
		IASTDeclaration[] members = compositeTypeSpecifier.getMembers();
		char[] name = compositeTypeSpecifier.getName().getLookupKey();
        for (IASTDeclaration member : members) {
    		IASTDeclarator dcltor = null;
    		IASTDeclSpecifier spec = null;
			if (member instanceof IASTSimpleDeclaration) {
			    IASTDeclarator[] dtors = ((IASTSimpleDeclaration) member).getDeclarators();
			    if (dtors.length != 1)
			    	continue;
			    dcltor = dtors[0];
			    spec = ((IASTSimpleDeclaration) member).getDeclSpecifier();
			} else if (member instanceof IASTFunctionDefinition) {
			    dcltor = ((IASTFunctionDefinition) member).getDeclarator();
			    spec = ((IASTFunctionDefinition) member).getDeclSpecifier();
			}

			if (!(dcltor instanceof ICPPASTFunctionDeclarator))
				continue;

			char[] declName= ASTQueries.findInnermostDeclarator(dcltor).getName().getLookupKey();

			if (spec instanceof IASTSimpleDeclSpecifier &&
					((IASTSimpleDeclSpecifier) spec).getType() == IASTSimpleDeclSpecifier.t_unspecified) {
				if (CharArrayUtils.equals(declName, name)) {
					hasConstructor = true;
					IASTParameterDeclaration[] params = ((ICPPASTFunctionDeclarator) dcltor).getParameters();
		        	if (params.length != 0 && hasTypeReferenceToClassType(params[0])
		        			&& parametersHaveInitializers(params, 1)) {
		        		hasCopyConstructor = true;
		        	}
				} else if (declName.length != 0 && declName[0] == '~' &&
						CharArrayUtils.equals(declName, 1, name.length, name)) {
					hasDestructor = true;
				}
			} else if (CharArrayUtils.equals(declName, OverloadableOperator.ASSIGN.toCharArray())) {
				IASTParameterDeclaration[] params = ((ICPPASTFunctionDeclarator) dcltor).getParameters();
	        	if (params.length == 1 && hasTypeReferenceToClassType(params[0]))
	        		hasCopyAssignmentOperator = true;
			}

			if (hasCopyConstructor && hasDestructor && hasCopyAssignmentOperator)
				break;
        }
	}

	private boolean hasTypeReferenceToClassType(IASTParameterDeclaration decl) {
		if (decl instanceof ICPPASTParameterDeclaration) {
			IType t = CPPVisitor.createType((ICPPASTParameterDeclaration) decl, false);
			if (t != null) {
				t = SemanticUtil.getNestedType(t, TDEF);
				if (t instanceof ICPPReferenceType && !((ICPPReferenceType) t).isRValueReference()) {
					t = SemanticUtil.getNestedType(t, TDEF|REF|CVTYPE);
					return classType.isSameType(t);
				}
			}
		}
		return false;
	}

	/**
	 * Checks whether all parameters starting at offset have initializers.
	 */
	private boolean parametersHaveInitializers(IASTParameterDeclaration[] params, int offset) {
		for (int i = offset; i < params.length; i++) {
			if (params[i].getDeclarator().getInitializer() == null)
				return false;
		}
		return true;
	}

	public boolean isDefaultConstructorConstexpr() {
		// The following condition is stronger than necessary. It is sufficient if the class doesn't contain
		// non-static fields that don't have constexpr default constructors.
		// TODO(sprigogin): Relax the condition in accordance with [dcl.constexpr] 7.1.5-4.
		if (hasNonStaticFields)
			return false;

		ICPPBase[] bases = classType.getBases();
		for (ICPPBase base : bases) {
			if (base.isVirtual())
				return false;
		}

		ICPPClassType[] baseClasses = ClassTypeHelper.getAllBases(classType);
		for (ICPPClassType baseClass : baseClasses) {
			ICPPConstructor ctor = getDefaultConstructor(baseClass);
			if (ctor == null || !ctor.isConstexpr())
				return false;
		}
		return true;
	}

	/**
	 * Returns a user-defined or implicit default constructor for the given class.
	 */
	private static ICPPConstructor getDefaultConstructor(ICPPClassType classType) {
		for (ICPPConstructor ctor : classType.getConstructors()) {
			if (ClassTypeHelper.getMethodKind(classType, ctor) == ClassTypeHelper.MethodKind.DEFAULT_CTOR)
				return ctor;
		}
		return null;
	}
}

Back to the top