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
|
* @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());
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,16 +1323,21 @@ 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
|
||||||
specName = ((IASTElaboratedTypeSpecifier)declSpec).getName();
|
if (!declSpec.isFriend()) {
|
||||||
|
if (declarators.length == 0 || scopeKind == EScopeKind.eGlobal
|
||||||
|
|| scopeKind == EScopeKind.eNamespace) {
|
||||||
|
specName = ((IASTElaboratedTypeSpecifier) declSpec).getName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
|
} else if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
|
||||||
ICPPASTCompositeTypeSpecifier compSpec = (ICPPASTCompositeTypeSpecifier) declSpec;
|
ICPPASTCompositeTypeSpecifier compSpec = (ICPPASTCompositeTypeSpecifier) declSpec;
|
||||||
|
@ -1355,18 +1349,7 @@ public class CPPSemantics {
|
||||||
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) {
|
||||||
IASTEnumerationSpecifier enumeration = (IASTEnumerationSpecifier) declSpec;
|
IASTEnumerationSpecifier enumeration = (IASTEnumerationSpecifier) declSpec;
|
||||||
specName = enumeration.getName();
|
specName = enumeration.getName();
|
||||||
|
@ -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();
|
||||||
|
@ -1400,14 +1401,29 @@ public class CPPSemantics {
|
||||||
IASTName alias = ((ICPPASTNamespaceAlias) declaration).getAlias();
|
IASTName alias = ((ICPPASTNamespaceAlias) declaration).getAlias();
|
||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
|
addNonSimpleElabSpec((ICPPASTElaboratedTypeSpecifier) declSpec);
|
||||||
return PROCESS_CONTINUE;
|
}
|
||||||
}
|
}
|
||||||
|
// Visit nested class definitions and parameter declarations
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@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;
|
return PROCESS_SKIP;
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue