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:
parent
555761c168
commit
90ceab10d5
5 changed files with 124 additions and 42 deletions
|
@ -99,6 +99,9 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
|
|||
* @return the associated name's binding
|
||||
*/
|
||||
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);
|
||||
assertNotNull("name not found for \""+section+"\"", name);
|
||||
assertEquals(section.substring(0, len), name.getRawSignature());
|
||||
|
|
|
@ -1175,4 +1175,25 @@ public class IndexCPPBindingResolutionBugs extends IndexBindingResolutionTestBas
|
|||
getBindingFromASTName("fx(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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -604,6 +604,10 @@ public class ASTSignatureUtil {
|
|||
// needSpace=true;
|
||||
// break;
|
||||
// }
|
||||
if (needSpace) {
|
||||
result.append(SPACE);
|
||||
needSpace = false;
|
||||
}
|
||||
result.append(((IASTElaboratedTypeSpecifier) declSpec).getName());
|
||||
} else if (declSpec instanceof IASTEnumerationSpecifier) {
|
||||
if (needSpace) {
|
||||
|
|
|
@ -1310,18 +1310,7 @@ public class CPPSemantics {
|
|||
IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) declaration;
|
||||
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) simpleDeclaration.getDeclSpecifier();
|
||||
IASTDeclarator[] declarators = simpleDeclaration.getDeclarators();
|
||||
IScope dtorScope= scope;
|
||||
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) {
|
||||
if (!declSpec.isFriend()) {
|
||||
for (IASTDeclarator declarator : declarators) {
|
||||
IASTDeclarator innermost= null;
|
||||
while (declarator != null) {
|
||||
|
@ -1334,16 +1323,21 @@ public class CPPSemantics {
|
|||
}
|
||||
if (innermost != null) {
|
||||
IASTName declaratorName = innermost.getName();
|
||||
ASTInternal.addName(dtorScope, declaratorName);
|
||||
ASTInternal.addName(scope, declaratorName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// declSpec
|
||||
|
||||
// Declaration specifiers defining or declaring a type
|
||||
IASTName specName = null;
|
||||
final EScopeKind scopeKind = scope.getKind();
|
||||
if (declSpec instanceof IASTElaboratedTypeSpecifier) {
|
||||
if (declarators.length == 0 || scope.getPhysicalNode() instanceof IASTTranslationUnit) {
|
||||
specName = ((IASTElaboratedTypeSpecifier)declSpec).getName();
|
||||
// 3.3.1.5 Point of declaration
|
||||
if (!declSpec.isFriend()) {
|
||||
if (declarators.length == 0 || scopeKind == EScopeKind.eGlobal
|
||||
|| scopeKind == EScopeKind.eNamespace) {
|
||||
specName = ((IASTElaboratedTypeSpecifier) declSpec).getName();
|
||||
}
|
||||
}
|
||||
} else if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
|
||||
ICPPASTCompositeTypeSpecifier compSpec = (ICPPASTCompositeTypeSpecifier) declSpec;
|
||||
|
@ -1355,18 +1349,7 @@ public class CPPSemantics {
|
|||
for (IASTDeclaration decl : decls) {
|
||||
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) {
|
||||
IASTEnumerationSpecifier enumeration = (IASTEnumerationSpecifier) declSpec;
|
||||
specName = enumeration.getName();
|
||||
|
@ -1386,6 +1369,24 @@ public class CPPSemantics {
|
|||
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) {
|
||||
ICPPASTUsingDeclaration using = (ICPPASTUsingDeclaration) declaration;
|
||||
IASTName name = using.getName();
|
||||
|
@ -1400,14 +1401,29 @@ public class CPPSemantics {
|
|||
IASTName alias = ((ICPPASTNamespaceAlias) declaration).getAlias();
|
||||
ASTInternal.addName(scope, alias);
|
||||
} else if (declaration instanceof IASTFunctionDefinition) {
|
||||
IASTFunctionDefinition functionDef = (IASTFunctionDefinition) declaration;
|
||||
if (!((ICPPASTDeclSpecifier) functionDef.getDeclSpecifier()).isFriend()) {
|
||||
IASTFunctionDeclarator declarator = functionDef.getDeclarator();
|
||||
|
||||
IASTFunctionDefinition functionDef = (IASTFunctionDefinition) declaration;
|
||||
final IASTDeclSpecifier declSpec = functionDef.getDeclSpecifier();
|
||||
IASTFunctionDeclarator declarator = functionDef.getDeclarator();
|
||||
|
||||
if (!((ICPPASTDeclSpecifier) declSpec).isFriend()) {
|
||||
// check the function itself
|
||||
IASTName declName = ASTQueries.findInnermostDeclarator(declarator).getName();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,14 +12,19 @@
|
|||
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.IASTDeclSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
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.IASTFunctionDefinition;
|
||||
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.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.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.IASTAmbiguousDeclarator;
|
||||
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
|
||||
*/
|
||||
class FriendCollector extends ASTVisitor {
|
||||
class NamespaceTypeCollector extends ASTVisitor {
|
||||
|
||||
private final ICPPASTInternalScope fScope;
|
||||
|
||||
public FriendCollector(ICPPASTInternalScope scope) {
|
||||
public NamespaceTypeCollector(ICPPASTInternalScope scope) {
|
||||
fScope= scope;
|
||||
shouldVisitDeclarations= true;
|
||||
shouldVisitStatements= true;
|
||||
shouldVisitParameterDeclarations= true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,20 +65,51 @@ class FriendCollector extends ASTVisitor {
|
|||
ASTInternal.addName(fScope, declaratorName);
|
||||
}
|
||||
}
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
|
||||
if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
} else if (declSpec instanceof ICPPASTElaboratedTypeSpecifier) {
|
||||
// 3.3.1.5 Point of declaration
|
||||
if (simpleDeclaration.getDeclarators().length != 0) {
|
||||
addNonSimpleElabSpec((ICPPASTElaboratedTypeSpecifier) declSpec);
|
||||
}
|
||||
}
|
||||
// Visit nested class definitions and parameter declarations
|
||||
return PROCESS_CONTINUE;
|
||||
} else if (declaration instanceof IASTFunctionDefinition) {
|
||||
IASTFunctionDefinition funcDefinition = (IASTFunctionDefinition) declaration;
|
||||
ICPPASTDeclSpecifier declSpec = (ICPPASTDeclSpecifier) funcDefinition.getDeclSpecifier();
|
||||
if (declSpec.isFriend()) {
|
||||
IASTFunctionDeclarator declarator = funcDefinition.getDeclarator();
|
||||
ASTInternal.addName(fScope, declarator.getName());
|
||||
} else if (declSpec instanceof ICPPASTElaboratedTypeSpecifier) {
|
||||
addNonSimpleElabSpec((ICPPASTElaboratedTypeSpecifier) declSpec);
|
||||
}
|
||||
// Visit parameter declarations
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue