1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 350345: Resolving explicit type conversions

This commit is contained in:
Markus Schorn 2011-09-28 14:51:27 +02:00
parent 8382397625
commit 794aaa995e
9 changed files with 167 additions and 80 deletions

View file

@ -87,6 +87,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
@ -2551,9 +2552,12 @@ public class AST2CPPTests extends AST2BaseTest {
ICPPConstructor T1_ctor = (ICPPConstructor) col.getName(6)
.resolveBinding();
ICPPClassType T1 = (ICPPClassType) col.getName(0).resolveBinding();
assertInstances(col, T1_ctor, 1);
assertInstances(col, T1, 3);
assertInstances(col, T1_ctor, 2);
assertInstances(col, T1, 2);
ICPPASTFunctionCallExpression fc= (ICPPASTFunctionCallExpression) col.getName(4).getParent().getParent();
IBinding ctor2 = fc.getImplicitNames()[0].resolveBinding();
assertSame(T1_ctor, ctor2);
}
// struct S { int i; };

View file

@ -49,6 +49,7 @@ import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
@ -1725,8 +1726,13 @@ public class AST2TemplateTests extends AST2BaseTest {
ICPPConstructor ctor = (ICPPConstructor) col.getName(2).resolveBinding();
ICPPFunction f = (ICPPFunction) col.getName(5).resolveBinding();
ICPPSpecialization spec = (ICPPSpecialization) col.getName(11).resolveBinding();
assertSame(spec.getSpecializedBinding(), ctor);
final IASTName typeConversion = col.getName(11);
ICPPSpecialization spec = (ICPPSpecialization) typeConversion.resolveBinding();
assertSame(ctor.getOwner(), spec.getSpecializedBinding());
final ICPPASTFunctionCallExpression fcall = (ICPPASTFunctionCallExpression) typeConversion.getParent().getParent();
final IBinding ctorSpec = fcall.getImplicitNames()[0].resolveBinding();
assertSame(ctor, (((ICPPSpecialization) ctorSpec).getSpecializedBinding()));
assertSame(f, col.getName(10).resolveBinding());
}
@ -1750,8 +1756,13 @@ public class AST2TemplateTests extends AST2BaseTest {
ICPPConstructor ctor = (ICPPConstructor) col.getName(3).resolveBinding();
ICPPMethod add = (ICPPMethod) col.getName(9).resolveBinding();
ICPPSpecialization spec = (ICPPSpecialization) col.getName(20).resolveBinding();
assertSame(spec.getSpecializedBinding(), ctor);
final IASTName typeConversion = col.getName(20);
ICPPSpecialization spec = (ICPPSpecialization) typeConversion.resolveBinding();
assertSame(ctor.getOwner(), spec.getSpecializedBinding());
final ICPPASTFunctionCallExpression fcall = (ICPPASTFunctionCallExpression) typeConversion.getParent().getParent();
final IBinding ctorSpec = fcall.getImplicitNames()[0].resolveBinding();
assertSame(ctor, (((ICPPSpecialization) ctorSpec).getSpecializedBinding()));
assertSame(add, col.getName(19).resolveBinding());
}
@ -1772,8 +1783,13 @@ public class AST2TemplateTests extends AST2BaseTest {
ICPPConstructor ctor = (ICPPConstructor) col.getName(2).resolveBinding();
ICPPMethod add = (ICPPMethod) col.getName(7).resolveBinding();
ICPPSpecialization spec = (ICPPSpecialization) col.getName(17).resolveBinding();
assertSame(spec.getSpecializedBinding(), ctor);
final IASTName typeConversion = col.getName(17);
ICPPSpecialization spec = (ICPPSpecialization) typeConversion.resolveBinding();
assertSame(ctor.getOwner(), spec.getSpecializedBinding());
final ICPPASTFunctionCallExpression fcall = (ICPPASTFunctionCallExpression) typeConversion.getParent().getParent();
final IBinding ctorSpec = fcall.getImplicitNames()[0].resolveBinding();
assertSame(ctor, (((ICPPSpecialization) ctorSpec).getSpecializedBinding()));
assertSame(add, col.getName(16).resolveBinding());
}

View file

@ -20,6 +20,8 @@ import org.eclipse.core.runtime.CoreException;
* Implementation of problem types.
*/
public class ProblemType implements IProblemType, ISerializableType {
public static final IType UNRESOLVED_NAME = new ProblemType(TYPE_UNRESOLVED_NAME);
private final int fID;
public ProblemType(int id) {

View file

@ -13,21 +13,18 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.prvalueType;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeFromFunctionCall;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeFromReturnType;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromFunctionCall;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromReturnType;
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 static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.*;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.ExpansionOverlapsBoundaryException;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
@ -38,7 +35,6 @@ import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpressionList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionCallExpression;
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.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.parser.IToken;
@ -47,6 +43,7 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.LookupData;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
@ -124,7 +121,17 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
public IASTImplicitName[] getImplicitNames() {
if (implicitNames == null) {
ICPPFunction overload = getOperator();
if (overload == null || overload instanceof CPPImplicitFunction) {
if (overload == null)
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
if (isExplicitTypeConversion() != null) {
CPPASTImplicitName n1 = new CPPASTImplicitName(overload.getNameCharArray(), this);
n1.setOffsetAndLength((ASTNode) functionName);
n1.setBinding(overload);
return implicitNames= new IASTImplicitName[] {n1};
}
if (overload instanceof CPPImplicitFunction) {
if (!(overload instanceof ICPPMethod) || ((ICPPMethod) overload).isImplicit()) {
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
}
@ -190,7 +197,7 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
return false;
}
if (implicits != null && implicits.length > 0 && !implicits[1].accept(action))
if (implicits != null && implicits.length > 1 && !implicits[1].accept(action))
return false;
if (action.shouldVisitExpressions && action.leave(this) == ASTVisitor.PROCESS_ABORT)
@ -217,35 +224,40 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
public ICPPFunction getOperator() {
if (overload == UNINITIALIZED_FUNCTION) {
overload= null;
IType t= functionName.getExpressionType();
t= SemanticUtil.getNestedType(t, TDEF | REF | CVTYPE);
IType t= isExplicitTypeConversion();
if (t != null) {
t = getNestedType(t, TDEF|CVTYPE|REF);
if (t instanceof ICPPClassType && !(t instanceof ICPPUnknownBinding)) {
ICPPClassType cls= (ICPPClassType) t;
LookupData data= CPPSemantics.createLookupData(((IASTIdExpression) functionName).getName());
try {
IBinding b= CPPSemantics.resolveFunction(data, cls.getConstructors(), true);
if (b instanceof ICPPFunction)
overload= (ICPPFunction) b;
} catch (DOMException e) {
}
}
} else {
t= SemanticUtil.getNestedType(functionName.getExpressionType(), TDEF|REF|CVTYPE);
if (t instanceof ICPPClassType) {
overload = CPPSemantics.findOverloadedOperator(this, (ICPPClassType)t);
}
}
}
return overload;
}
public IType getExpressionType() {
if (functionName instanceof IASTIdExpression) {
// Handle misused id-expression in functional type conversions or simple type initializers.
final IBinding binding= ((IASTIdExpression) functionName).getName().resolvePreBinding();
if (binding instanceof ICPPConstructor) {
IBinding owner= binding.getOwner();
if (owner instanceof ICPPClassType) {
return (ICPPClassType) owner;
}
return new ProblemType(ISemanticProblem.TYPE_UNKNOWN_FOR_EXPRESSION);
}
if (binding instanceof IProblemBinding) {
return new ProblemType(ISemanticProblem.TYPE_UNRESOLVED_NAME);
}
if (binding instanceof IType) {
return prvalueType((IType) binding);
// Handle explicit type conversion in functional notation.
IType t= isExplicitTypeConversion();
if (t != null) {
if (t instanceof IProblemBinding) {
return ProblemType.UNRESOLVED_NAME;
}
return prvalueType(t);
}
IType t= SemanticUtil.getNestedType(functionName.getExpressionType(), TDEF|REF|CVTYPE);
t= SemanticUtil.getNestedType(functionName.getExpressionType(), TDEF|REF|CVTYPE);
if (t instanceof ICPPClassType) {
if (overload == UNINITIALIZED_FUNCTION) {
overload = CPPSemantics.findOverloadedOperator(this, (ICPPClassType)t);
@ -268,11 +280,24 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
return new ProblemType(ISemanticProblem.TYPE_UNKNOWN_FOR_EXPRESSION);
}
private IType isExplicitTypeConversion() {
if (functionName instanceof IASTIdExpression) {
final IASTName name = ((IASTIdExpression) functionName).getName();
IBinding b= name.resolvePreBinding();
if (b instanceof IType)
return (IType) b;
}
return null;
}
public boolean isLValue() {
return getValueCategory() == LVALUE;
}
public ValueCategory getValueCategory() {
if (isExplicitTypeConversion() != null)
return PRVALUE;
IType t= functionName.getExpressionType();
if (t instanceof ICPPClassType) {
if (overload == UNINITIALIZED_FUNCTION) {

View file

@ -308,6 +308,15 @@ public class CPPSemantics {
}
}
// Explicit type conversion in functional notation
if (binding instanceof ICPPClassTemplate && data.astName instanceof ICPPASTTemplateId) {
final IASTNode parent = data.astName.getParent();
if (parent instanceof IASTIdExpression &&
parent.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) {
return binding;
}
}
/* 14.6.1-1:
* Within the scope of a class template, when the name of the template is neither qualified nor
* followed by <, it is equivalent to the name followed by the template parameters enclosed in <>.
@ -441,15 +450,15 @@ public class CPPSemantics {
}
} else if (namePropertyInParent == IASTIdExpression.ID_NAME) {
if (binding instanceof IType) {
IASTNode parent= name.getParent().getParent();
if (parent instanceof ICPPASTTemplatedTypeTemplateParameter) {
// default for template template parameter is an id-expression, which is a type.
} else if (parent instanceof ICPPASTUnaryExpression
&& ((ICPPASTUnaryExpression) parent).getOperator() == IASTUnaryExpression.op_sizeofParameterPack) {
// argument of sizeof... can be a type
} else if ((binding instanceof ICPPUnknownType || binding instanceof ITypedef || binding instanceof IEnumeration)
&& convertClassToConstructor(data.astName)) {
// constructor or simple-type constructor
final IASTNode idExpr = name.getParent();
ASTNodeProperty pip = idExpr.getPropertyInParent();
if (pip == ICPPASTTemplatedTypeTemplateParameter.DEFAULT_VALUE) {
// Default for template template parameter is a type.
} else if (pip == IASTFunctionCallExpression.FUNCTION_NAME) {
// Explicit type conversion in functional notation.
} else if (pip == IASTUnaryExpression.OPERAND
&& ((ICPPASTUnaryExpression) idExpr.getParent()).getOperator() == IASTUnaryExpression.op_sizeofParameterPack) {
// Argument of sizeof... can be a type
} else {
binding= new ProblemBinding(data.astName, IProblemBinding.SEMANTIC_INVALID_TYPE,
data.getFoundBindings());
@ -511,20 +520,7 @@ public class CPPSemantics {
if (parent instanceof ICPPASTConstructorChainInitializer) {
return true;
}
if (parent instanceof IASTExpression) {
ASTNodeProperty propInParent= parent.getPropertyInParent();
if (parent instanceof IASTIdExpression) {
parent= parent.getParent();
}
while (parent instanceof IASTUnaryExpression
&& ((IASTUnaryExpression) parent).getOperator() == IASTUnaryExpression.op_bracketedPrimary) {
propInParent = parent.getPropertyInParent();
parent= parent.getParent();
}
if (parent instanceof IASTFunctionCallExpression && propInParent == IASTFunctionCallExpression.FUNCTION_NAME) {
return true;
}
} else if (parent instanceof ICPPASTNamedTypeSpecifier) {
if (parent instanceof ICPPASTNamedTypeSpecifier) {
parent= parent.getParent();
if (parent instanceof IASTTypeId && parent.getParent() instanceof ICPPASTNewExpression) {
IASTDeclarator dtor = ((IASTTypeId) parent).getAbstractDeclarator();
@ -2324,7 +2320,7 @@ public class CPPSemantics {
return result;
}
static IBinding resolveFunction(LookupData data, ICPPFunction[] fns, boolean allowUDC) throws DOMException {
public static IBinding resolveFunction(LookupData data, ICPPFunction[] fns, boolean allowUDC) throws DOMException {
fns= (ICPPFunction[]) ArrayUtil.trim(ICPPFunction.class, fns);
if (fns == null || fns.length == 0)
return null;

View file

@ -605,6 +605,10 @@ public class CPPTemplates {
//functions are instantiated as part of the resolution process
IBinding result= CPPVisitor.createBinding(id);
IASTName templateName = id.getTemplateName();
if (result instanceof ICPPClassTemplate) {
templateName.setBinding(result);
id.setBinding(null);
} else {
if (result instanceof ICPPTemplateInstance) {
templateName.setBinding(((ICPPTemplateInstance) result).getTemplateDefinition());
} else {
@ -612,6 +616,7 @@ public class CPPTemplates {
}
return result;
}
}
IASTNode parentOfName = id.getParent();
boolean isLastName= true;

View file

@ -2189,7 +2189,7 @@ public:
virtual ~Test();
private:
void test();
RetValueType exp();
RetType exp();
};
#endif /* TEST_H_ */
@ -2218,7 +2218,7 @@ Test::Test() {
Test::~Test() {
}
RetValueType Test::exp()
RetType Test::exp()
{
return RetType();
}

View file

@ -23,12 +23,18 @@ import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.texteditor.ITextEditor;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.EScopeKind;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IEnumerator;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.c.ICExternalBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexManager;
@ -36,7 +42,6 @@ import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.internal.ui.viewsupport.CElementLabels;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.internal.core.model.ext.ICElementHandle;
@ -45,6 +50,7 @@ import org.eclipse.cdt.internal.corext.util.CModelUtil;
import org.eclipse.cdt.internal.ui.actions.OpenActionUtil;
import org.eclipse.cdt.internal.ui.util.ExceptionHandler;
import org.eclipse.cdt.internal.ui.util.StatusLineHandler;
import org.eclipse.cdt.internal.ui.viewsupport.CElementLabels;
import org.eclipse.cdt.internal.ui.viewsupport.IndexUI;
public class CallHierarchyUI {
@ -158,6 +164,19 @@ public class CallHierarchyUI {
IASTName name= IndexUI.getSelectedName(editorInput, sel);
if (name != null) {
IBinding binding= name.resolveBinding();
if (!CallHierarchyUI.isRelevantForCallHierarchy(binding)) {
for (IASTNode parent= name; parent != null; parent= parent.getParent()) {
if (parent.getPropertyInParent() == IASTFunctionCallExpression.FUNCTION_NAME) {
ICPPASTFunctionCallExpression fcall= (ICPPASTFunctionCallExpression) parent.getParent();
if (fcall != null) {
IASTImplicitName[] implicit = fcall.getImplicitNames();
if (implicit.length > 0)
binding= implicit[0].resolveBinding();
}
break;
}
}
}
if (CallHierarchyUI.isRelevantForCallHierarchy(binding)) {
if (name.isDefinition()) {
ICElement elem= IndexUI.getCElementForName(project, index, name);
@ -270,8 +289,15 @@ public class CallHierarchyUI {
public static boolean isRelevantForCallHierarchy(IBinding binding) {
if (binding instanceof ICExternalBinding ||
binding instanceof IEnumerator ||
binding instanceof IFunction ||
binding instanceof IVariable) {
binding instanceof IFunction)
return true;
if (binding instanceof IVariable) {
try {
if (binding.getScope().getKind() == EScopeKind.eLocal)
return false;
} catch (DOMException e) {
}
return true;
}
return false;

View file

@ -71,8 +71,10 @@ import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.model.IMethodDeclaration;
import org.eclipse.cdt.core.model.ISourceRange;
import org.eclipse.cdt.core.model.ISourceReference;
import org.eclipse.cdt.core.model.IStructureDeclaration;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
@ -487,6 +489,16 @@ class OpenDeclarationsJob extends Job implements ASTRunnable {
if (uniqueElements.size() == 1) {
target= (ISourceReference) uniqueElements.get(0);
} else {
if (uniqueElements.size() == 2) {
final ICElement e0 = uniqueElements.get(0);
final ICElement e1 = uniqueElements.get(1);
if (e0 instanceof IStructureDeclaration && e1 instanceof IMethodDeclaration) {
target= (ISourceReference) e1;
} else if (e1 instanceof IStructureDeclaration && e0 instanceof IMethodDeclaration) {
target= (ISourceReference) e0;
}
}
if (target == null) {
if (OpenDeclarationsAction.sIsJUnitTest) {
throw new RuntimeException("ambiguous input: " + uniqueElements.size()); //$NON-NLS-1$
}
@ -495,6 +507,7 @@ class OpenDeclarationsJob extends Job implements ASTRunnable {
CEditorMessages.OpenDeclarationsAction_dialog_title, CEditorMessages.OpenDeclarationsAction_selectMessage,
CElementLabels.ALL_DEFAULT | CElementLabels.ALL_FULLY_QUALIFIED | CElementLabels.MF_POST_FILE_QUALIFIED, 0);
}
}
if (target != null) {
ITranslationUnit tu= target.getTranslationUnit();
ISourceRange sourceRange;