Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 7c3736634e11ebff1b1304f597ee70bac216fff0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*******************************************************************************
 * Copyright (c) 2008, 2009 Wind River Systems, Inc. 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:
 *     Markus Schorn - initial API and implementation
 *******************************************************************************/ 
package org.eclipse.cdt.internal.core.dom.parser;

import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFieldDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.parser.c.CVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;

/**
 * Base class for {@link CVisitor} and {@link CPPVisitor}
 */
public class ASTQueries {
	private static class NameSearch extends ASTVisitor {
		private boolean fFound;

		NameSearch() {
			super(false);
			shouldVisitAmbiguousNodes= true;
			shouldVisitNames= true;
		}

		public void reset() {
			fFound= false;
		}

		public boolean foundName() {
			return fFound;
		}

		@Override
		public int visit(IASTName name) {
			fFound= true;
			return PROCESS_ABORT;
		}

		@Override
		public int visit(ASTAmbiguousNode node) {
			IASTNode[] alternatives= node.getNodes();
			for (IASTNode alt : alternatives) {
				if (!alt.accept(this))
					return PROCESS_ABORT;
			}
			return PROCESS_CONTINUE;
		}
	}
	private static NameSearch NAME_SEARCH= new NameSearch();
	
	/**
	 * Tests whether the given expression can contain ast-names, suitable to be used before ambiguity 
	 * resolution.
	 */
	public static boolean canContainName(IASTExpression expr) {
		if (expr == null)
			return false;
		
		NAME_SEARCH.reset();
		expr.accept(NAME_SEARCH);
		return NAME_SEARCH.foundName();
	}
	
	/** 
	 * Returns the outermost declarator the given <code>declarator</code> nests within, or
	 * <code>declarator</code> itself.
	 */
	public static IASTDeclarator findOutermostDeclarator(IASTDeclarator declarator) {
		IASTDeclarator outermost= null;
		IASTNode candidate= declarator;
		while (candidate instanceof IASTDeclarator) {
			outermost= (IASTDeclarator) candidate;
			candidate= outermost.getParent();
		}
		return outermost;
	}

	/** 
	 * Returns the innermost declarator nested within the given <code>declarator</code>, or
	 * <code>declarator</code> itself.
	 */
	public static IASTDeclarator findInnermostDeclarator(IASTDeclarator declarator) {
		IASTDeclarator innermost= null;
		while (declarator != null) {
			innermost= declarator;
			declarator= declarator.getNestedDeclarator();
		}
		return innermost;
	}

	/**
	 * Searches for the innermost declarator that contributes the the type declared.
	 */
	public static IASTDeclarator findTypeRelevantDeclarator(IASTDeclarator declarator) {
		if (declarator == null)
			return null;
		
		IASTDeclarator result= findInnermostDeclarator(declarator);
		while (result.getPointerOperators().length == 0 
				&& !(result instanceof IASTFieldDeclarator)
				&& !(result instanceof IASTFunctionDeclarator)
				&& !(result instanceof IASTArrayModifier)) {
			final IASTNode parent= result.getParent();
			if (parent instanceof IASTDeclarator) {
				result= (IASTDeclarator) parent;
			} else {
				return result;
			}
		}
		return result;
	}
	
	/**
	 * Extracts the active declarations from an array of declarations.
	 */
	public static IASTDeclaration[] extractActiveDeclarations(final IASTDeclaration[] allDeclarations, final int size) {
		IASTDeclaration[] active;
		if (size == 0) {
			active= IASTDeclaration.EMPTY_DECLARATION_ARRAY;
		} else {
			active= new IASTDeclaration[size];
			int j= 0;
			for (int i = 0; i < size; i++) {
				IASTDeclaration d= allDeclarations[i];
				if (d.isActive()) {
					active[j++]= d;
				}
			}
			active= ArrayUtil.trimAt(IASTDeclaration.class, active, j-1);
		}
		return active;
	}

	public static boolean isSameType(IType type1, IType type2) {
		if (type1 == type2)
			return true;
		if (type1 == null || type2 == null)
			return false;
		return type1.isSameType(type2);
	}
	
	protected static IType isCompatibleArray(IType t1, IType t2) {
		if (t1 instanceof IArrayType && t2 instanceof IArrayType) {
			IArrayType a1 = (IArrayType) t1;
			IArrayType a2 = (IArrayType) t2;
			if (!isSameType(a1.getType(), a2.getType())) {
				return null;
			}
			if (a1.getSize() == null) {
				if (a2.getSize() != null) {
					return a2;
				}
			} else if (a2.getSize() == null) {
				return a1;
			}
		}
		return null;
	}
	
	/**
	 * Check whether 'ancestor' is an ancestor of 'descendant' in the AST. 
	 */
	public static boolean isAncestorOf(IASTNode ancestor, IASTNode descendant) {
		do {
			if (descendant == ancestor)
				return true;
			descendant = descendant.getParent();
		} while (descendant != null);
		return false;
	}
}

Back to the top