From 90ceab10d5314b987250263ba442d51bbcfcf08e Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Wed, 3 Mar 2010 13:21:21 +0000 Subject: [PATCH] Bug 303739: Resolving elaborated type specifiers. --- .../tests/IndexBindingResolutionTestBase.java | 3 + .../tests/IndexCPPBindingResolutionBugs.java | 21 +++++ .../cdt/core/dom/ast/ASTSignatureUtil.java | 4 + .../parser/cpp/semantics/CPPSemantics.java | 82 +++++++++++-------- ...ector.java => NamespaceTypeCollector.java} | 56 +++++++++++-- 5 files changed, 124 insertions(+), 42 deletions(-) rename core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/{FriendCollector.java => NamespaceTypeCollector.java} (60%) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java index 182dac85f77..dacb2fac63f 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBindingResolutionTestBase.java @@ -99,6 +99,9 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase { * @return the associated name's binding */ protected T getBindingFromASTName(String section, int len, Class 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()); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java index f23cc4b791e..b9f03a65615 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionBugs.java @@ -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); + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTSignatureUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTSignatureUtil.java index fca79f0bb96..b1c80d49470 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTSignatureUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTSignatureUtil.java @@ -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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 0d16e654ce9..ecb3909ec76 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -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; + } } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FriendCollector.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/NamespaceTypeCollector.java similarity index 60% rename from core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FriendCollector.java rename to core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/NamespaceTypeCollector.java index 8f4ed033472..87ce2bc62a3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FriendCollector.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/NamespaceTypeCollector.java @@ -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; } }