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

Bug 409444 - IllegalArgumentException while indexing

This commit is contained in:
Sergey Prigogin 2013-05-29 21:53:58 -07:00
parent 619e22ea88
commit 51e8509b3e
5 changed files with 89 additions and 27 deletions

View file

@ -2313,4 +2313,13 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
public void testRegression_408314() throws Exception {
checkBindings();
}
// template<typename T> struct A { enum { v = 0 }; };
// template<> struct A<int> { enum { v = 1 }; };
// template<> struct A<int> { enum { v = 1 }; };
// int main() {}
public void testSpecializationRedefinition_409444() throws Exception {
checkBindings();
}
}

View file

@ -15,11 +15,20 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
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.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
@ -64,19 +73,10 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
import org.eclipse.core.runtime.CoreException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Holds common implementation of methods for ICPPClassType implementations that have
* a corresponding textual definition in the source code.
@ -910,7 +910,7 @@ public class ClassTypeHelper {
ICPPClassType specialized = ((ICPPClassSpecialization) classType).getSpecializedBinding();
if (!specialized.equals(member.getOwner())) {
if (!(member instanceof ICPPSpecialization))
throw new IllegalArgumentException(member.getName() + " is not a member of " + specialized.getName()); //$NON-NLS-1$
throw invalidMember(specialized, member);
member = ((ICPPSpecialization) member).getSpecializedBinding();
}
return specialized.getVisibility(member);
@ -920,13 +920,46 @@ public class ClassTypeHelper {
}
}
int visibility = classType.getKey() == ICPPClassType.k_class ?
ICPPClassType.v_private : ICPPClassType.v_public;
ICPPASTCompositeTypeSpecifier classDeclSpec = classType.getCompositeTypeSpecifier();
int visibility = getVisibility(classDeclSpec, member);
if (visibility >= 0)
return visibility;
IASTDeclaration[] hostMembers = classType.getCompositeTypeSpecifier().getMembers();
ICPPMethod[] implicitMethods = getImplicitMethods(classType, null);
for (ICPPMethod implicitMethod : implicitMethods) {
if (member.equals(implicitMethod)) {
return ICPPClassType.v_public;
}
}
// It's possible that we haven't found the member because the class was illegally redefined
// and the member belongs to another definition. Try to search the definition containing
// the member.
if (member instanceof ICPPInternalBinding) {
IASTNode node = ((ICPPInternalBinding) member).getDefinition();
if (node != null) {
IASTName ownerName = CPPVisitor.findDeclarationOwnerDefinition(node, false);
if (ownerName != null && !ownerName.equals(classDeclSpec.getName()) &&
ownerName.getPropertyInParent() == ICPPASTCompositeTypeSpecifier.TYPE_NAME) {
classDeclSpec = (ICPPASTCompositeTypeSpecifier) ownerName.getParent();
visibility = getVisibility(classDeclSpec, member);
if (visibility >= 0)
return visibility;
}
}
}
throw invalidMember(classType, member);
}
private static int getVisibility(ICPPASTCompositeTypeSpecifier classDeclSpec, IBinding member) {
int visibility = classDeclSpec.getKey() == ICPPASTCompositeTypeSpecifier.k_class ?
ICPPClassType.v_private : ICPPClassType.v_public;
IASTDeclaration[] hostMembers = classDeclSpec.getMembers();
for (IASTDeclaration hostMember : hostMembers) {
if (hostMember instanceof ICPPASTVisibilityLabel) {
visibility = ((ICPPASTVisibilityLabel) hostMember).getVisibility();
continue;
}
while (hostMember instanceof ICPPASTTemplateDeclaration) {
hostMember = ((ICPPASTTemplateDeclaration) hostMember).getDeclaration();
@ -970,7 +1003,8 @@ public class ClassTypeHelper {
}
}
} else if (hostMember instanceof IASTFunctionDefinition) {
IASTFunctionDeclarator declarator = ((IASTFunctionDefinition) hostMember).getDeclarator();
IASTDeclarator declarator = ((IASTFunctionDefinition) hostMember).getDeclarator();
declarator = ASTQueries.findInnermostDeclarator(declarator);
IBinding functionBinding = declarator.getName().resolveBinding();
if (member.equals(functionBinding)){
return visibility;
@ -992,13 +1026,14 @@ public class ClassTypeHelper {
}
}
}
ICPPMethod[] implicitMethods = getImplicitMethods(classType, null);
for (ICPPMethod implicitMethod : implicitMethods) {
if (member.equals(implicitMethod)) {
return ICPPClassType.v_public;
}
}
throw new IllegalArgumentException(member.getName() + " is not a member of " + classType.getName()); //$NON-NLS-1$
return -1;
}
private static IllegalArgumentException invalidMember(IBinding classType, IBinding member) {
String name = member.getName();
if (name.isEmpty())
name = "<anonymous>"; //$NON-NLS-1$
return new IllegalArgumentException(name + " is not a member of " + classType.getName()); //$NON-NLS-1$
}
private static Map<String, List<ICPPMethod>> collectPureVirtualMethods(ICPPClassType classType,

View file

@ -2554,6 +2554,14 @@ public class CPPVisitor extends ASTQueries {
* of the above constructs.
*/
public static IBinding findDeclarationOwner(IASTNode node, boolean allowFunction) {
IASTName name = findDeclarationOwnerDefinition(node, allowFunction);
if (name == null)
return null;
return name.resolveBinding();
}
public static IASTName findDeclarationOwnerDefinition(IASTNode node, boolean allowFunction) {
// Search for declaration
boolean isNonSimpleElabDecl= false;
while (!(node instanceof IASTDeclaration) && !(node instanceof ICPPASTLambdaExpression)) {
@ -2605,10 +2613,7 @@ public class CPPVisitor extends ASTQueries {
break;
}
}
if (name == null)
return null;
return name.resolveBinding();
return name;
}
public static boolean doesNotSpecifyType(IASTDeclSpecifier declspec) {

View file

@ -668,6 +668,18 @@ public class PDOMASTAdapter {
return binding;
}
/**
* Retrieves the original binding from an adapter previously returned by
* {@link #getAdapterForAnonymousASTBinding(IBinding)}. If the parameter binding is not
* an adapter, returns the binding itself.
*/
public static IBinding getOriginalForAdaptedBinding(IBinding binding) {
if (binding instanceof AnonymousCPPBinding) {
return ((AnonymousCPPBinding) binding).fDelegate;
}
return binding;
}
/**
* If the name is empty and has no file location, either an adapter
* that has a file location is returned, or <code>null</code> if that

View file

@ -529,6 +529,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
if (bindingOwner instanceof ICPPClassType) {
if (bindingOwner instanceof CPPClosureType)
return ICPPClassType.v_public;
binding = PDOMASTAdapter.getOriginalForAdaptedBinding(binding);
visibility = ((ICPPClassType) bindingOwner).getVisibility(binding);
}
return visibility;