mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-29 03:45:35 +02:00
Computation of naming type, bug 292232.
This commit is contained in:
parent
2b5ba96a39
commit
67fe42e072
2 changed files with 105 additions and 5 deletions
|
@ -106,4 +106,55 @@ public class AccessControlTests extends AST2BaseTest {
|
|||
AccessAssertionHelper ah= new AccessAssertionHelper(code);
|
||||
ah.assertNotAccessible("a = 0", 1);
|
||||
}
|
||||
|
||||
// class A0 {
|
||||
// public:
|
||||
// enum Ex {e1};
|
||||
// };
|
||||
//
|
||||
// class A : public A0 {
|
||||
// class B {
|
||||
// void test() {
|
||||
// Ex a; // we compute 'B' as the naming type, whereas it should be 'A'
|
||||
// }
|
||||
// };
|
||||
// };
|
||||
public void testEnclosingAsNamingClass_292232() throws Exception {
|
||||
final String code = getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
AccessAssertionHelper ah= new AccessAssertionHelper(code);
|
||||
ah.assertAccessible("Ex a;", 2);
|
||||
}
|
||||
|
||||
// // Example from C++-specification 11.2-3
|
||||
// class B {
|
||||
// public:
|
||||
// int mi;
|
||||
// static int si;
|
||||
// };
|
||||
// class D : private B {};
|
||||
// class DD : public D {
|
||||
// void f();
|
||||
// };
|
||||
//
|
||||
// void DD::f() {
|
||||
// mi=3; // private
|
||||
// si=3; // private
|
||||
// B b;
|
||||
// b.mi=4;
|
||||
// b.si=4;
|
||||
// B* bp;
|
||||
// bp->mi=5;
|
||||
// }
|
||||
public void testEnclosingAsNamingClass_292232a() throws Exception {
|
||||
final String code = getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
AccessAssertionHelper ah= new AccessAssertionHelper(code);
|
||||
ah.assertNotAccessible("mi=3;", 2);
|
||||
ah.assertNotAccessible("si=3;", 2);
|
||||
ah.assertAccessible("mi=4;", 2);
|
||||
ah.assertAccessible("si=4;", 2);
|
||||
ah.assertAccessible("mi=5;", 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -55,7 +55,9 @@ public class AccessContext {
|
|||
/**
|
||||
* A class through which the bindings are accessed (11.2.4).
|
||||
*/
|
||||
private ICPPClassType namingClass;
|
||||
private boolean isUnqualifiedLookup;
|
||||
private ICPPClassType namingClass; // depends on the binding for which we check the access
|
||||
private ICPPClassType firstCandidateForNamingClass; // the first candidate is independent of the binding for which we do the access-check
|
||||
private DOMException initializationException;
|
||||
|
||||
public AccessContext(IASTName name) {
|
||||
|
@ -77,7 +79,8 @@ public class AccessContext {
|
|||
if (!(owner instanceof ICPPClassType)) {
|
||||
return true; // The binding is not a class member.
|
||||
}
|
||||
if (!Initialize()) {
|
||||
ICPPClassType accessOwner= (ICPPClassType) owner;
|
||||
if (!initialize(accessOwner)) {
|
||||
return true; // Assume visibility if anything goes wrong.
|
||||
}
|
||||
if (namingClass == null) {
|
||||
|
@ -93,20 +96,25 @@ public class AccessContext {
|
|||
/**
|
||||
* @return <code>true</code> if initialization succeeded.
|
||||
*/
|
||||
private boolean Initialize() {
|
||||
private boolean initialize(ICPPClassType accessOwner) {
|
||||
if (context == null) {
|
||||
if (initializationException != null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
namingClass = getNamingClass(name);
|
||||
context = getContext(name);
|
||||
firstCandidateForNamingClass= getFirstCandidateForNamingClass(name);
|
||||
} catch (DOMException e) {
|
||||
CCorePlugin.log(e);
|
||||
initializationException = e;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
try {
|
||||
namingClass = getNamingClass(accessOwner);
|
||||
} catch (DOMException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -198,8 +206,10 @@ public class AccessContext {
|
|||
return false;
|
||||
}
|
||||
|
||||
private static ICPPClassType getNamingClass(IASTName name) throws DOMException {
|
||||
private ICPPClassType getFirstCandidateForNamingClass(IASTName name) throws DOMException {
|
||||
LookupData data = new LookupData(name);
|
||||
isUnqualifiedLookup= !data.qualified();
|
||||
|
||||
ICPPScope scope= CPPSemantics.getLookupScope(name, data);
|
||||
while (scope != null && !(scope instanceof ICPPClassScope)) {
|
||||
scope = CPPSemantics.getParentScope(scope, data.tu);
|
||||
|
@ -210,6 +220,45 @@ public class AccessContext {
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
private ICPPClassType getNamingClass(ICPPClassType accessOwner) throws DOMException {
|
||||
ICPPClassType classType = firstCandidateForNamingClass;
|
||||
if (classType != null && isUnqualifiedLookup) {
|
||||
IBinding owner = classType.getOwner();
|
||||
while (owner instanceof ICPPClassType && !derivesFrom(classType, accessOwner, CPPSemantics.MAX_INHERITANCE_DEPTH)) {
|
||||
classType= (ICPPClassType) owner;
|
||||
owner= classType.getOwner();
|
||||
}
|
||||
}
|
||||
return classType;
|
||||
}
|
||||
|
||||
private static boolean derivesFrom(ICPPClassType derived, ICPPClassType target, int maxdepth) {
|
||||
if (derived == target || derived.isSameType(target)) {
|
||||
return true;
|
||||
}
|
||||
if (maxdepth > 0) {
|
||||
try {
|
||||
for (ICPPBase cppBase : derived.getBases()) {
|
||||
try {
|
||||
IBinding base= cppBase.getBaseClass();
|
||||
if (base instanceof ICPPClassType) {
|
||||
ICPPClassType tbase= (ICPPClassType) base;
|
||||
if (tbase.isSameType(target)) {
|
||||
return true;
|
||||
}
|
||||
if (derivesFrom(tbase, target, maxdepth - 1))
|
||||
return true;
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
}
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static IBinding[] getContext(IASTName name) throws DOMException {
|
||||
IBinding[] accessibilityContext = IBinding.EMPTY_BINDING_ARRAY;
|
||||
for (IBinding binding = CPPVisitor.findEnclosingFunctionOrClass(name);
|
||||
|
|
Loading…
Add table
Reference in a new issue