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

Bug 303739: Resolving elaborated type specifiers.

This commit is contained in:
Markus Schorn 2010-03-03 13:21:21 +00:00
parent 555761c168
commit 90ceab10d5
5 changed files with 124 additions and 42 deletions

View file

@ -99,6 +99,9 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
* @return the associated name's binding * @return the associated name's binding
*/ */
protected <T> T getBindingFromASTName(String section, int len, Class<T> clazz, Class ... cs) { protected <T> T getBindingFromASTName(String section, int len, Class<T> clazz, Class ... cs) {
if (len < 1) {
len= section.length()+len;
}
IASTName name= findName(section, len); IASTName name= findName(section, len);
assertNotNull("name not found for \""+section+"\"", name); assertNotNull("name not found for \""+section+"\"", name);
assertEquals(section.substring(0, len), name.getRawSignature()); assertEquals(section.substring(0, len), name.getRawSignature());

View file

@ -1175,4 +1175,25 @@ public class IndexCPPBindingResolutionBugs extends IndexBindingResolutionTestBas
getBindingFromASTName("fx(1);", 2, ICPPFunction.class); getBindingFromASTName("fx(1);", 2, ICPPFunction.class);
getBindingFromASTName("fx(1,1);", 2, ICPPFunction.class); getBindingFromASTName("fx(1,1);", 2, ICPPFunction.class);
} }
// struct YetAnotherTest {
// void test();
// friend class InnerClass3;
// class InnerClass3 {
// void f() {
// member=0;
// }
// int member;
// };
// InnerClass3 arr[32];
// };
// #include "a.h"
// void YetAnotherTest::test() {
// arr[0].member=0;
// }
public void testXXXX_Bug303739() throws Exception {
getBindingFromASTName("member=0", -2, ICPPField.class);
}
} }

View file

@ -604,6 +604,10 @@ public class ASTSignatureUtil {
// needSpace=true; // needSpace=true;
// break; // break;
// } // }
if (needSpace) {
result.append(SPACE);
needSpace = false;
}
result.append(((IASTElaboratedTypeSpecifier) declSpec).getName()); result.append(((IASTElaboratedTypeSpecifier) declSpec).getName());
} else if (declSpec instanceof IASTEnumerationSpecifier) { } else if (declSpec instanceof IASTEnumerationSpecifier) {
if (needSpace) { if (needSpace) {

View file

@ -1310,18 +1310,7 @@ public class CPPSemantics {
IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) declaration; IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) declaration;
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) simpleDeclaration.getDeclSpecifier(); ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) simpleDeclaration.getDeclSpecifier();
IASTDeclarator[] declarators = simpleDeclaration.getDeclarators(); IASTDeclarator[] declarators = simpleDeclaration.getDeclarators();
IScope dtorScope= scope; if (!declSpec.isFriend()) {
if (declSpec.isFriend()) {
// Friends are added to an enclosing scope. Here we have to do that, because when this scope is re-populated
// during ambiguity resolution, the enclosing scope is otherwise left as it is (without the friend).
try {
while (dtorScope != null && dtorScope.getKind() == EScopeKind.eClassType)
dtorScope= dtorScope.getParent();
} catch (DOMException e) {
dtorScope= null;
}
}
if (dtorScope != null) {
for (IASTDeclarator declarator : declarators) { for (IASTDeclarator declarator : declarators) {
IASTDeclarator innermost= null; IASTDeclarator innermost= null;
while (declarator != null) { while (declarator != null) {
@ -1334,17 +1323,22 @@ public class CPPSemantics {
} }
if (innermost != null) { if (innermost != null) {
IASTName declaratorName = innermost.getName(); IASTName declaratorName = innermost.getName();
ASTInternal.addName(dtorScope, declaratorName); ASTInternal.addName(scope, declaratorName);
} }
} }
} }
// declSpec // Declaration specifiers defining or declaring a type
IASTName specName = null; IASTName specName = null;
final EScopeKind scopeKind = scope.getKind();
if (declSpec instanceof IASTElaboratedTypeSpecifier) { if (declSpec instanceof IASTElaboratedTypeSpecifier) {
if (declarators.length == 0 || scope.getPhysicalNode() instanceof IASTTranslationUnit) { // 3.3.1.5 Point of declaration
if (!declSpec.isFriend()) {
if (declarators.length == 0 || scopeKind == EScopeKind.eGlobal
|| scopeKind == EScopeKind.eNamespace) {
specName = ((IASTElaboratedTypeSpecifier) declSpec).getName(); specName = ((IASTElaboratedTypeSpecifier) declSpec).getName();
} }
}
} else if (declSpec instanceof ICPPASTCompositeTypeSpecifier) { } else if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
ICPPASTCompositeTypeSpecifier compSpec = (ICPPASTCompositeTypeSpecifier) declSpec; ICPPASTCompositeTypeSpecifier compSpec = (ICPPASTCompositeTypeSpecifier) declSpec;
specName = compSpec.getName(); specName = compSpec.getName();
@ -1354,17 +1348,6 @@ public class CPPSemantics {
IASTDeclaration[] decls = compSpec.getMembers(); IASTDeclaration[] decls = compSpec.getMembers();
for (IASTDeclaration decl : decls) { for (IASTDeclaration decl : decls) {
populateCache(scope, decl); populateCache(scope, decl);
}
} else {
// Collect friends enclosed in nested classes
switch (scope.getKind()) {
case eLocal:
case eGlobal:
case eNamespace:
compSpec.accept(new FriendCollector(scope));
break;
default:
break;
} }
} }
} else if (declSpec instanceof IASTEnumerationSpecifier) { } else if (declSpec instanceof IASTEnumerationSpecifier) {
@ -1386,6 +1369,24 @@ public class CPPSemantics {
ASTInternal.addName(scope, specName); ASTInternal.addName(scope, specName);
} }
} }
// Collect friends and elaborated type specifiers with declarators
// from nested classes
if (declarators.length > 0 || declSpec instanceof ICPPASTCompositeTypeSpecifier) {
switch (scopeKind) {
case eLocal:
case eGlobal:
case eNamespace:
NamespaceTypeCollector visitor = new NamespaceTypeCollector(scope);
declSpec.accept(visitor);
for (IASTDeclarator dtor : declarators) {
dtor.accept(visitor);
}
break;
case eClassType:
case eTemplateDeclaration:
break;
}
}
} else if (declaration instanceof ICPPASTUsingDeclaration) { } else if (declaration instanceof ICPPASTUsingDeclaration) {
ICPPASTUsingDeclaration using = (ICPPASTUsingDeclaration) declaration; ICPPASTUsingDeclaration using = (ICPPASTUsingDeclaration) declaration;
IASTName name = using.getName(); IASTName name = using.getName();
@ -1401,13 +1402,28 @@ public class CPPSemantics {
ASTInternal.addName(scope, alias); ASTInternal.addName(scope, alias);
} else if (declaration instanceof IASTFunctionDefinition) { } else if (declaration instanceof IASTFunctionDefinition) {
IASTFunctionDefinition functionDef = (IASTFunctionDefinition) declaration; IASTFunctionDefinition functionDef = (IASTFunctionDefinition) declaration;
if (!((ICPPASTDeclSpecifier) functionDef.getDeclSpecifier()).isFriend()) { final IASTDeclSpecifier declSpec = functionDef.getDeclSpecifier();
IASTFunctionDeclarator declarator = functionDef.getDeclarator(); IASTFunctionDeclarator declarator = functionDef.getDeclarator();
if (!((ICPPASTDeclSpecifier) declSpec).isFriend()) {
// check the function itself // check the function itself
IASTName declName = ASTQueries.findInnermostDeclarator(declarator).getName(); IASTName declName = ASTQueries.findInnermostDeclarator(declarator).getName();
ASTInternal.addName(scope, declName); ASTInternal.addName(scope, declName);
} }
// Collect elaborated type specifiers and friends
final EScopeKind scopeKind = scope.getKind();
switch (scopeKind) {
case eLocal:
case eGlobal:
case eNamespace:
NamespaceTypeCollector visitor = new NamespaceTypeCollector(scope);
declSpec.accept(visitor);
declarator.accept(visitor);
break;
case eClassType:
case eTemplateDeclaration:
break;
}
} }
} }

View file

@ -12,14 +12,19 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousDeclarator; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousDeclarator;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPASTInternalScope; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPASTInternalScope;
@ -27,13 +32,15 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPASTInternalScope;
/** /**
* Utility class to populate scope with friend declarations hidden in nested classes * Utility class to populate scope with friend declarations hidden in nested classes
*/ */
class FriendCollector extends ASTVisitor { class NamespaceTypeCollector extends ASTVisitor {
private final ICPPASTInternalScope fScope; private final ICPPASTInternalScope fScope;
public FriendCollector(ICPPASTInternalScope scope) { public NamespaceTypeCollector(ICPPASTInternalScope scope) {
fScope= scope; fScope= scope;
shouldVisitDeclarations= true; shouldVisitDeclarations= true;
shouldVisitStatements= true;
shouldVisitParameterDeclarations= true;
} }
@Override @Override
@ -58,20 +65,51 @@ class FriendCollector extends ASTVisitor {
ASTInternal.addName(fScope, declaratorName); ASTInternal.addName(fScope, declaratorName);
} }
} }
return PROCESS_SKIP; } else if (declSpec instanceof ICPPASTElaboratedTypeSpecifier) {
// 3.3.1.5 Point of declaration
if (simpleDeclaration.getDeclarators().length != 0) {
addNonSimpleElabSpec((ICPPASTElaboratedTypeSpecifier) declSpec);
} }
}
if (declSpec instanceof ICPPASTCompositeTypeSpecifier) { // Visit nested class definitions and parameter declarations
return PROCESS_CONTINUE; return PROCESS_CONTINUE;
}
} else if (declaration instanceof IASTFunctionDefinition) { } else if (declaration instanceof IASTFunctionDefinition) {
IASTFunctionDefinition funcDefinition = (IASTFunctionDefinition) declaration; IASTFunctionDefinition funcDefinition = (IASTFunctionDefinition) declaration;
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) funcDefinition.getDeclSpecifier(); ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) funcDefinition.getDeclSpecifier();
if (declSpec.isFriend()) { if (declSpec.isFriend()) {
IASTFunctionDeclarator declarator = funcDefinition.getDeclarator(); IASTFunctionDeclarator declarator = funcDefinition.getDeclarator();
ASTInternal.addName(fScope, declarator.getName()); ASTInternal.addName(fScope, declarator.getName());
} else if (declSpec instanceof ICPPASTElaboratedTypeSpecifier) {
addNonSimpleElabSpec((ICPPASTElaboratedTypeSpecifier) declSpec);
} }
// Visit parameter declarations
return PROCESS_CONTINUE;
} }
return PROCESS_SKIP; return PROCESS_SKIP;
} }
@Override
public int visit(IASTParameterDeclaration declaration) {
IASTDeclSpecifier declSpec = declaration.getDeclSpecifier();
if (declSpec instanceof ICPPASTElaboratedTypeSpecifier) {
addNonSimpleElabSpec((ICPPASTElaboratedTypeSpecifier) declSpec);
}
return PROCESS_SKIP;
}
private void addNonSimpleElabSpec(final ICPPASTElaboratedTypeSpecifier elabSpec) {
if (elabSpec.getKind() != IASTElaboratedTypeSpecifier.k_enum) {
final IASTName name = elabSpec.getName();
if (!(name instanceof ICPPASTQualifiedName)) {
ASTInternal.addName(fScope, name);
}
}
}
@Override
public int visit(IASTStatement statement) {
// Don't visit function bodies
return PROCESS_SKIP;
}
} }