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:
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);
|
AccessAssertionHelper ah= new AccessAssertionHelper(code);
|
||||||
ah.assertNotAccessible("a = 0", 1);
|
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).
|
* 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;
|
private DOMException initializationException;
|
||||||
|
|
||||||
public AccessContext(IASTName name) {
|
public AccessContext(IASTName name) {
|
||||||
|
@ -77,7 +79,8 @@ public class AccessContext {
|
||||||
if (!(owner instanceof ICPPClassType)) {
|
if (!(owner instanceof ICPPClassType)) {
|
||||||
return true; // The binding is not a class member.
|
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.
|
return true; // Assume visibility if anything goes wrong.
|
||||||
}
|
}
|
||||||
if (namingClass == null) {
|
if (namingClass == null) {
|
||||||
|
@ -93,20 +96,25 @@ public class AccessContext {
|
||||||
/**
|
/**
|
||||||
* @return <code>true</code> if initialization succeeded.
|
* @return <code>true</code> if initialization succeeded.
|
||||||
*/
|
*/
|
||||||
private boolean Initialize() {
|
private boolean initialize(ICPPClassType accessOwner) {
|
||||||
if (context == null) {
|
if (context == null) {
|
||||||
if (initializationException != null) {
|
if (initializationException != null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
namingClass = getNamingClass(name);
|
|
||||||
context = getContext(name);
|
context = getContext(name);
|
||||||
|
firstCandidateForNamingClass= getFirstCandidateForNamingClass(name);
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
CCorePlugin.log(e);
|
CCorePlugin.log(e);
|
||||||
initializationException = e;
|
initializationException = e;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
namingClass = getNamingClass(accessOwner);
|
||||||
|
} catch (DOMException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,8 +206,10 @@ public class AccessContext {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ICPPClassType getNamingClass(IASTName name) throws DOMException {
|
private ICPPClassType getFirstCandidateForNamingClass(IASTName name) throws DOMException {
|
||||||
LookupData data = new LookupData(name);
|
LookupData data = new LookupData(name);
|
||||||
|
isUnqualifiedLookup= !data.qualified();
|
||||||
|
|
||||||
ICPPScope scope= CPPSemantics.getLookupScope(name, data);
|
ICPPScope scope= CPPSemantics.getLookupScope(name, data);
|
||||||
while (scope != null && !(scope instanceof ICPPClassScope)) {
|
while (scope != null && !(scope instanceof ICPPClassScope)) {
|
||||||
scope = CPPSemantics.getParentScope(scope, data.tu);
|
scope = CPPSemantics.getParentScope(scope, data.tu);
|
||||||
|
@ -210,6 +220,45 @@ public class AccessContext {
|
||||||
return null;
|
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 {
|
private static IBinding[] getContext(IASTName name) throws DOMException {
|
||||||
IBinding[] accessibilityContext = IBinding.EMPTY_BINDING_ARRAY;
|
IBinding[] accessibilityContext = IBinding.EMPTY_BINDING_ARRAY;
|
||||||
for (IBinding binding = CPPVisitor.findEnclosingFunctionOrClass(name);
|
for (IBinding binding = CPPVisitor.findEnclosingFunctionOrClass(name);
|
||||||
|
|
Loading…
Add table
Reference in a new issue