| /******************************************************************************* |
| * Copyright (c) 2004, 2015 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Andrew Niefer (IBM Corporation) - initial API and implementation |
| * Markus Schorn (Wind River Systems) |
| * Bryan Wilkinson (QNX) |
| *******************************************************************************/ |
| package org.eclipse.cdt.internal.core.dom.parser.cpp; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.cdt.core.dom.IName; |
| import org.eclipse.cdt.core.dom.ast.EScopeKind; |
| import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTDeclarator; |
| 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.IASTNode; |
| import org.eclipse.cdt.core.dom.ast.IASTStatement; |
| import org.eclipse.cdt.core.dom.ast.IBinding; |
| import org.eclipse.cdt.core.dom.ast.ILabel; |
| import org.eclipse.cdt.core.dom.ast.IScope; |
| import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionScope; |
| import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; |
| import org.eclipse.cdt.core.parser.util.CharArrayUtils; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; |
| |
| /** |
| * Scope of a function, containing labels. |
| */ |
| public class CPPFunctionScope extends CPPScope implements ICPPFunctionScope { |
| private CharArrayObjectMap<ILabel> labels = CharArrayObjectMap.emptyMap(); |
| |
| /** |
| * @param physicalNode |
| */ |
| public CPPFunctionScope(IASTFunctionDeclarator physicalNode) { |
| super(physicalNode); |
| } |
| |
| @Override |
| public EScopeKind getKind() { |
| return EScopeKind.eLocal; |
| } |
| |
| @Override |
| public void addBinding(IBinding binding) { |
| // 3.3.4 only labels have function scope. |
| if (!(binding instanceof ILabel)) |
| return; |
| |
| if (labels == CharArrayObjectMap.EMPTY_MAP) |
| labels = new CharArrayObjectMap<>(2); |
| |
| labels.put(binding.getNameCharArray(), (ILabel) binding); |
| } |
| |
| @Override |
| public IBinding[] find(String name) { |
| char[] n = name.toCharArray(); |
| List<IBinding> bindings = new ArrayList<>(); |
| |
| for (int i = 0; i < labels.size(); i++) { |
| char[] key = labels.keyAt(i); |
| if (CharArrayUtils.equals(key, n)) { |
| bindings.add(labels.get(key)); |
| } |
| } |
| |
| IBinding[] additional = super.find(name); |
| for (IBinding element : additional) { |
| bindings.add(element); |
| } |
| |
| return bindings.toArray(new IBinding[bindings.size()]); |
| } |
| |
| @Override |
| public IScope getParent() { |
| // We can't just resolve the function and get its parent scope, since there are cases where that |
| // could loop because resolving functions requires resolving their parameter types. |
| IASTFunctionDeclarator funcDeclarator = (IASTFunctionDeclarator) getPhysicalNode(); |
| IASTName name = funcDeclarator.getName(); |
| if (name != null) |
| return CPPVisitor.getContainingNonTemplateScope(name.getLastName()); |
| |
| return super.getParent(); |
| } |
| |
| @Override |
| public IScope getBodyScope() { |
| IASTFunctionDeclarator fnDtor = (IASTFunctionDeclarator) getPhysicalNode(); |
| IASTNode parent = fnDtor.getParent(); |
| if (parent instanceof IASTFunctionDefinition) { |
| IASTStatement body = ((IASTFunctionDefinition) parent).getBody(); |
| if (body instanceof IASTCompoundStatement) |
| return ((IASTCompoundStatement) body).getScope(); |
| } |
| return null; |
| } |
| |
| @Override |
| public IName getScopeName() { |
| IASTNode node = getPhysicalNode(); |
| if (node instanceof IASTDeclarator) { |
| return ((IASTDeclarator) node).getName(); |
| } |
| return null; |
| } |
| } |