1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-29 20:05:35 +02:00

Computation of naming type, bug 292232.

This commit is contained in:
Markus Schorn 2009-10-16 10:03:44 +00:00
parent 2b5ba96a39
commit 67fe42e072
2 changed files with 105 additions and 5 deletions

View file

@ -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);
}
}

View file

@ -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);