mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Bug 508338 - Friend class declaration hides the real one in outer
namespace Change-Id: I3808c74b5b64505b07b8bb1e1a482d7a4c292dfe
This commit is contained in:
parent
2236ada9fd
commit
83bd6f7ed4
5 changed files with 100 additions and 6 deletions
|
@ -2320,4 +2320,14 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti
|
|||
ICPPMethod[] pureVirtuals = SemanticQueries.getPureVirtualMethods((ICPPClassType) type, null);
|
||||
assertEquals(0, pureVirtuals.length);
|
||||
}
|
||||
|
||||
|
||||
// class A {
|
||||
// friend class B;
|
||||
// };
|
||||
|
||||
// B* b;
|
||||
public void testFriendClassDeclaration_508338() throws Exception {
|
||||
getProblemFromFirstIdentifier("B*");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,4 +163,40 @@ public class IndexMultiFileTest extends IndexBindingResolutionTestBase {
|
|||
public void testExplicitSpecialization_494359() throws Exception {
|
||||
checkBindings();
|
||||
}
|
||||
|
||||
// test1.h
|
||||
// namespace ns {
|
||||
//
|
||||
// struct C {
|
||||
// friend class B;
|
||||
// };
|
||||
//
|
||||
// }
|
||||
|
||||
// test2.h
|
||||
// class B {};
|
||||
//
|
||||
// namespace ns {
|
||||
//
|
||||
// struct A {
|
||||
// operator B();
|
||||
// };
|
||||
//
|
||||
// }
|
||||
//
|
||||
// void waldo(B);
|
||||
|
||||
// confuser.cpp
|
||||
// #include "test1.h"
|
||||
|
||||
// test.cpp *
|
||||
// #include "test1.h"
|
||||
// #include "test2.h"
|
||||
//
|
||||
// void test(ns::A a) {
|
||||
// waldo(a);
|
||||
// }
|
||||
public void testFriendClassDeclaration_508338() throws Exception {
|
||||
checkBindings();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.eclipse.cdt.internal.core.dom.parser.c.ICInternalBinding;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.c.ICInternalFunction;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalFunction;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||
import org.eclipse.cdt.internal.core.index.IIndexFragment;
|
||||
import org.eclipse.cdt.internal.core.index.IndexFileSet;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
|
||||
|
@ -263,4 +264,15 @@ public class ASTInternal {
|
|||
}
|
||||
return binding != null;
|
||||
}
|
||||
|
||||
public static boolean hasNonFriendDeclaration(ICPPInternalBinding binding) {
|
||||
if (binding.getDefinition() != null)
|
||||
return true;
|
||||
for (IASTNode node : binding.getDeclarations()) {
|
||||
if (!CPPVisitor.isNameOfFriendDeclaration(node))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -463,10 +463,11 @@ public class CPPVisitor extends ASTQueries {
|
|||
name = name.getLastName();
|
||||
}
|
||||
if (parent instanceof IASTSimpleDeclaration) {
|
||||
IASTDeclarator[] dtors = ((IASTSimpleDeclaration) parent).getDeclarators();
|
||||
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) ((IASTSimpleDeclaration) parent).getDeclSpecifier();
|
||||
IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) parent;
|
||||
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) simpleDeclaration.getDeclSpecifier();
|
||||
IASTDeclarator[] dtors = simpleDeclaration.getDeclarators();
|
||||
isFriend = declSpec.isFriend() && dtors.length == 0;
|
||||
if (dtors.length > 0 || isFriend) {
|
||||
if (dtors.length != 0 || isFriend) {
|
||||
binding = CPPSemantics.resolveBinding(name);
|
||||
mustBeSimple = !isFriend;
|
||||
} else {
|
||||
|
@ -558,6 +559,29 @@ public class CPPVisitor extends ASTQueries {
|
|||
return binding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given name is the name of a friend declaration.
|
||||
*
|
||||
* @param name the name to check
|
||||
* @return {@code true} if {@code name} is the name of a friend declaration
|
||||
*/
|
||||
public static boolean isNameOfFriendDeclaration(IASTNode name) {
|
||||
if (name.getPropertyInParent() == ICPPASTQualifiedName.SEGMENT_NAME) {
|
||||
ICPPASTQualifiedName qName = (ICPPASTQualifiedName) name.getParent();
|
||||
if (name != qName.getLastName())
|
||||
return false;
|
||||
name = qName;
|
||||
}
|
||||
if (name.getPropertyInParent() != ICPPASTElaboratedTypeSpecifier.TYPE_NAME)
|
||||
return false;
|
||||
ICPPASTElaboratedTypeSpecifier typeSpec = (ICPPASTElaboratedTypeSpecifier) name.getParent();
|
||||
if (typeSpec.getPropertyInParent() != IASTSimpleDeclaration.DECL_SPECIFIER)
|
||||
return false;
|
||||
IASTSimpleDeclaration declaration = (IASTSimpleDeclaration) typeSpec.getParent();
|
||||
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) declaration.getDeclSpecifier();
|
||||
return declSpec.isFriend() && declaration.getDeclarators().length == 0;
|
||||
}
|
||||
|
||||
public static void markRedeclaration(final ICPPInternalBinding ib) {
|
||||
// Mark the other declarations as problem and create the binding
|
||||
final IASTNode[] decls = ib.getDeclarations();
|
||||
|
|
|
@ -109,6 +109,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMember;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPExecution;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalEnumerator;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||
|
@ -699,10 +700,21 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (binding instanceof ICPPClassTemplate) {
|
||||
pdomBinding= new PDOMCPPClassTemplate(this, parent, (ICPPClassTemplate) binding);
|
||||
} else if (binding instanceof ICPPClassType) {
|
||||
pdomBinding= new PDOMCPPClassType(this, parent, (ICPPClassType) binding);
|
||||
// 11.3-11 [class.friend]
|
||||
// For a friend class declaration, if there is no prior declaration, the class that is specified
|
||||
// belongs to the innermost enclosing non-class scope, but if it is subsequently referenced, its
|
||||
// name is not found by name lookup until a matching declaration is provided in the innermost
|
||||
// enclosing nonclass scope.
|
||||
// See http://bugs.eclipse.org/508338
|
||||
if (!(binding instanceof ICPPInternalBinding)
|
||||
|| ASTInternal.hasNonFriendDeclaration((ICPPInternalBinding) binding)) {
|
||||
if (binding instanceof ICPPClassTemplate) {
|
||||
pdomBinding= new PDOMCPPClassTemplate(this, parent, (ICPPClassTemplate) binding);
|
||||
} else {
|
||||
pdomBinding= new PDOMCPPClassType(this, parent, (ICPPClassType) binding);
|
||||
}
|
||||
}
|
||||
} else if (binding instanceof ICPPVariableTemplate) {
|
||||
pdomBinding = new PDOMCPPVariableTemplate(this, parent, (ICPPVariableTemplate) binding);
|
||||
} else if (binding instanceof ICPPVariable) {
|
||||
|
|
Loading…
Add table
Reference in a new issue