diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EnclosingNamesTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EnclosingNamesTest.java
new file mode 100644
index 00000000000..737ead8c376
--- /dev/null
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/EnclosingNamesTest.java
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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.index.tests;
+
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+import junit.framework.TestSuite;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.dom.IPDOMManager;
+import org.eclipse.cdt.core.index.IIndex;
+import org.eclipse.cdt.core.index.IIndexBinding;
+import org.eclipse.cdt.core.index.IIndexName;
+import org.eclipse.cdt.core.index.IndexFilter;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.testplugin.CProjectHelper;
+import org.eclipse.cdt.core.testplugin.CTestPlugin;
+import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
+import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
+import org.eclipse.cdt.internal.core.CCoreInternals;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+
+public class EnclosingNamesTest extends BaseTestCase {
+	private static final IProgressMonitor NPM = new NullProgressMonitor();
+	private ICProject fCProject;
+	protected IIndex fIndex;
+
+	public EnclosingNamesTest(String name) {
+		super(name);
+	}
+
+	public static TestSuite suite() {
+		return suite(EnclosingNamesTest.class);
+	}
+
+	protected void setUp() throws CoreException {
+		fCProject= CProjectHelper.createCCProject("__encNamesTest__", "bin", IPDOMManager.ID_FAST_INDEXER);
+		CCoreInternals.getPDOMManager().reindex(fCProject);
+		fIndex= CCorePlugin.getIndexManager().getIndex(fCProject);
+	}
+
+	protected void tearDown() throws CoreException {
+		if (fCProject != null) {
+			CProjectHelper.delete(fCProject);
+		}
+	}
+
+	protected IProject getProject() {
+		return fCProject.getProject();
+	}
+
+	protected StringBuffer[] getContentsForTest(int blocks) throws IOException {
+		return TestSourceReader.getContentsForTest(
+				CTestPlugin.getDefault().getBundle(), "parser", getClass(), getName(), blocks);
+	}
+
+	protected IFile createFile(IContainer container, String fileName, String contents) throws Exception {
+		return TestSourceReader.createFile(container, new Path(fileName), contents);
+	}
+
+	protected void waitForIndexer() {
+		assertTrue(CCorePlugin.getIndexManager().joinIndexer(10000, NPM));
+	}
+
+	protected Pattern[] getPattern(String qname) {
+		String[] parts= qname.split("::");
+		Pattern[] result= new Pattern[parts.length];
+		for (int i = 0; i < result.length; i++) {
+			result[i]= Pattern.compile(parts[i]);			
+		}
+		return result;
+	}
+
+	protected void waitUntilFileIsIndexed(IFile file, int time) throws Exception {
+		TestSourceReader.waitUntilFileIsIndexed(fIndex, file, time);
+	}
+	
+	// void func();
+	// int var;
+	//
+	// void main() {
+	//    func();
+	//    var=1;
+	// };
+	public void testNestingWithFunction() throws Exception {
+		waitForIndexer();
+		String content= getContentsForTest(1)[0].toString();
+		IFile file= createFile(getProject().getProject(), "test.cpp", content);
+		waitUntilFileIsIndexed(file, 4000);
+		
+		fIndex.acquireReadLock();
+		try {
+			IIndexBinding[] mainBS= fIndex.findBindings(getPattern("main"), true, IndexFilter.ALL, NPM);
+			assertLength(1, mainBS);
+			IIndexBinding mainB= mainBS[0];
+			
+			IIndexName[] names= fIndex.findDefinitions(mainB);
+			assertLength(1, names);
+			IIndexName main= names[0];
+			
+			assertNull(main.getEnclosingDefinition());
+			IIndexName[] enclosed= main.getEnclosedNames();
+			assertLength(2, enclosed);
+			assertName("func", enclosed[0]);
+			assertName("var", enclosed[1]);
+			
+			IIndexName enclosing= enclosed[0].getEnclosingDefinition();
+			assertNotNull(enclosing);
+			assertName("main", enclosing);
+
+			enclosing= enclosed[1].getEnclosingDefinition();
+			assertNotNull(enclosing);
+			assertName("main", enclosing);			
+		}
+		finally {
+			fIndex.releaseReadLock();
+		}
+	}
+
+	private void assertName(String name, IIndexName iname) {
+		assertEquals(name, new String(iname.toCharArray()));
+	}
+
+	private void assertLength(int length, Object[] array) {
+		assertNotNull(array);
+		assertEquals(length, array.length);
+	}
+	
+	// class C {
+	// public:
+	//    void func();
+	//    int var;
+	// };
+	//
+	// void main() {
+	//    C c;
+	//    c.func();
+	//    c.var=1;
+	// };
+	// void C::func() {
+	//    func();
+	//    var=1;
+	// };
+	
+	
+	public void testNestingWithMethod() throws Exception {
+		waitForIndexer();
+		String content= getContentsForTest(1)[0].toString();
+		IFile file= createFile(getProject().getProject(), "test.cpp", content);
+		waitUntilFileIsIndexed(file, 4000);
+		
+		fIndex.acquireReadLock();
+		try {
+			IIndexBinding[] mainBS= fIndex.findBindings(getPattern("main"), true, IndexFilter.ALL, NPM);
+			assertLength(1, mainBS);
+			IIndexBinding mainB= mainBS[0];
+			
+			IIndexName[] names= fIndex.findDefinitions(mainB);
+			assertLength(1, names);
+			IIndexName main= names[0];
+			
+			assertNull(main.getEnclosingDefinition());
+			IIndexName[] enclosed= main.getEnclosedNames();
+			assertLength(3, enclosed);
+			assertName("C", enclosed[0]);
+			assertName("func", enclosed[1]);
+			assertName("var", enclosed[2]);
+			
+			IIndexName enclosing= enclosed[0].getEnclosingDefinition();
+			assertNotNull(enclosing);
+			assertName("main", enclosing);
+
+			enclosing= enclosed[1].getEnclosingDefinition();
+			assertNotNull(enclosing);
+			assertName("main", enclosing);			
+
+			enclosing= enclosed[2].getEnclosingDefinition();
+			assertNotNull(enclosing);
+			assertName("main", enclosing);			
+
+			IIndexBinding funcB= fIndex.findBinding(enclosed[1]);
+			assertNotNull(funcB);
+			names= fIndex.findDefinitions(funcB);
+			assertLength(1, names);
+			IIndexName funcdef= names[0];
+			
+			assertNull(funcdef.getEnclosingDefinition());
+			enclosed= funcdef.getEnclosedNames();
+			assertLength(3, enclosed);
+			assertName("C", enclosed[0]);
+			assertName("func", enclosed[1]);
+			assertName("var", enclosed[2]);
+			
+			enclosing= enclosed[0].getEnclosingDefinition();
+			assertNotNull(enclosing);
+			assertName("func", enclosing);
+
+			enclosing= enclosed[1].getEnclosingDefinition();
+			assertNotNull(enclosing);
+			assertName("func", enclosing);			
+
+			enclosing= enclosed[2].getEnclosingDefinition();
+			assertNotNull(enclosing);
+			assertName("func", enclosing);			
+		}
+		finally {
+			fIndex.releaseReadLock();
+		}
+	}
+
+}
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java
index f3e90ee0dec..37a5d28d69c 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java
@@ -74,8 +74,9 @@ public class IndexBugsTests extends BaseTestCase {
 		return fCProject.getProject();
 	}
 	
-    protected String readTaggedComment(final String tag) throws IOException {
-    	return TestSourceReader.readTaggedComment(CTestPlugin.getDefault().getBundle(), "parser", getClass(), tag);
+    protected StringBuffer[] getContentsForTest(int blocks) throws IOException {
+    	return TestSourceReader.getContentsForTest(
+    			CTestPlugin.getDefault().getBundle(), "parser", getClass(), getName(), blocks);
     }
     
     protected IFile createFile(IContainer container, String fileName, String contents) throws Exception {
@@ -99,7 +100,6 @@ public class IndexBugsTests extends BaseTestCase {
 		TestSourceReader.waitUntilFileIsIndexed(fIndex, file, time);
 	}
 
-    // {bug162011}
     //  namespace ns162011 {
     //    class Class162011 {
     //      friend void function162011(Class162011); 
@@ -107,7 +107,7 @@ public class IndexBugsTests extends BaseTestCase {
     //    void function162011(Class162011 x){};
     //  }
     public void testBug162011() throws Exception {
-		String content = readTaggedComment("bug162011");
+		String content = getContentsForTest(1)[0].toString();
 		String fileName = "bug162011.cpp";
 		String funcName = "function162011";
 		String nsName = "ns162011";
@@ -247,13 +247,12 @@ public class IndexBugsTests extends BaseTestCase {
 		}
 	}
 
-	// {test164500}
 	// #define macro164500 1
 	// #undef macro164500
 	// #define macro164500 2
 	public void test164500() throws Exception {
 		waitForIndexer();
-		String content= readTaggedComment("test164500");
+		String content= getContentsForTest(1)[0].toString();
 
 		IFile file= TestSourceReader.createFile(fCProject.getProject(), "test164500.cpp", content);
 		TestSourceReader.waitUntilFileIsIndexed(fIndex, file, 4000);
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java
index 813fef12e04..719daa4c9ba 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTNode.java
@@ -7,6 +7,7 @@
  *
  * Contributors:
  * IBM - Initial API and implementation
+ * Markus Schorn (Wind River Systems)
  *******************************************************************************/
 package org.eclipse.cdt.core.dom.ast;
 
@@ -108,4 +109,12 @@ public interface IASTNode {
      */
     public String getRawSignature();
 
+    /**
+     * Returns whether this node contains the given one. The decision is made
+     * purly on location information and therefore the method is fast.
+     * @param node the node to check
+     * @return whether this node contains the given one.
+     * @since 4.0
+     */
+	public boolean contains(IASTNode node);
 }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java
index 36b24b179a0..7c6b79fa1fd 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/index/IIndexName.java
@@ -51,4 +51,20 @@ public interface IIndexName extends IName {
 	 * Returns the length of the name.
 	 */
 	public int getNodeLength();
+	
+	/**
+	 * Returns the name of the definition that contains this name. 
+	 * May return <code>null</code>.
+	 * Currently this is implemented for function and method definitions, only.
+	 */
+	public IIndexName getEnclosingDefinition() throws CoreException;
+	
+	/**
+	 * Returns the names of the references contained in this definition. 
+	 * Returns <code>null</code>, if the name is not a definition.
+	 * 
+	 * Currently the method works with function definitions, only.
+	 */
+	public IIndexName[] getEnclosedNames() throws CoreException;
+
 }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java
index 9f2d687e3af..209e9cba88a 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTNode.java
@@ -7,6 +7,7 @@
  *
  * Contributors:
  * IBM Rational Software - Initial API and implementation
+ * Markus Schorn (Wind River Systems)
  *******************************************************************************/
 package org.eclipse.cdt.internal.core.dom.parser;
 
@@ -112,4 +113,12 @@ public abstract class ASTNode implements IASTNode {
     	return true;
     }
     
+    public boolean contains(IASTNode node) {
+    	if (node instanceof ASTNode) {
+    		ASTNode astNode= (ASTNode) node;
+    		return offset <= astNode.offset && 
+    			astNode.offset+astNode.length <= offset+length;
+    	}
+    	return false;
+    }
 }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java
index e6f1c54b6e3..0b1ba63822a 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java
@@ -35,7 +35,7 @@ public interface IWritableIndex extends IIndex {
 	 */
 	void setFileContent(IIndexFragmentFile sourceFile, 
 			IASTPreprocessorIncludeStatement[] includes, 
-			IASTPreprocessorMacroDefinition[] macros, IASTName[] names) throws CoreException;
+			IASTPreprocessorMacroDefinition[] macros, IASTName[][] names) throws CoreException;
 
 	/**
 	 * Clears the entire index.
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java
index f17787f1d1b..091cfaa3a2e 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndexFragment.java
@@ -41,7 +41,7 @@ public interface IWritableIndexFragment extends IIndexFragment {
 	 */
 	void addFileContent(IIndexFragmentFile sourceFile, 
 			IASTPreprocessorIncludeStatement[] includes, IIndexFragmentFile[] destFiles, 
-			IASTPreprocessorMacroDefinition[] macros, IASTName[] names) throws CoreException;
+			IASTPreprocessorMacroDefinition[] macros, IASTName[][] names) throws CoreException;
 
 	/**
 	 * Acquires a write lock, while giving up a certain amount of read locks.
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java
index 27a290d472c..dd43f620d71 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java
@@ -57,7 +57,7 @@ public class WritableCIndex extends CIndex implements IWritableIndex {
 
 	public void setFileContent(IIndexFragmentFile file, 
 			IASTPreprocessorIncludeStatement[] includes,
-			IASTPreprocessorMacroDefinition[] macros, IASTName[] names) throws CoreException {
+			IASTPreprocessorMacroDefinition[] macros, IASTName[][] names) throws CoreException {
 
 		IIndexFragment indexFragment = file.getIndexFragment();
 		assert isWritableFragment(indexFragment);
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java
index 50fbf929165..0eff27a8552 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java
@@ -64,7 +64,7 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
 
 	private Database db;
 
-	public static final int VERSION = 16;
+	public static final int VERSION = 17;
 	// 0 - the beginning of it all
 	// 1 - first change to kick off upgrades
 	// 2 - added file inclusions
@@ -82,6 +82,7 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
 	// 14 - added timestamps for files (bug 149571)
 	// 15 - fixed offsets for pointer types and qualifier types and PDOMCPPVariable (bug 160540). 
 	// 16 - have PDOMCPPField store type information, and PDOMCPPNamespaceAlias store what it is aliasing
+	// 17 - use single linked list for names in file, adds a link to enclosing defintion name.
 
 	public static final int LINKAGES = Database.DATA_AREA;
 	public static final int FILE_INDEX = Database.DATA_AREA + 4;
@@ -460,7 +461,7 @@ public class PDOM extends PlatformObject implements IIndexFragment, IPDOM {
 		}
 	}
 
-	public void releaseWriteLock() {
+	final public void releaseWriteLock() {
 		releaseWriteLock(0);
 	}
 
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java
index 39f849286a1..797c1375bcf 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/WritablePDOM.java
@@ -19,6 +19,7 @@ import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
 import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
 import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
 import org.eclipse.cdt.internal.core.index.IWritableIndexFragment;
+import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
 import org.eclipse.cdt.internal.core.pdom.dom.PDOMFile;
 import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
 import org.eclipse.core.runtime.CoreException;
@@ -35,22 +36,14 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
 
 	public void addFileContent(IIndexFragmentFile sourceFile, 
 			IASTPreprocessorIncludeStatement[] includes, IIndexFragmentFile[] destFiles,
-			IASTPreprocessorMacroDefinition[] macros, IASTName[] names) throws CoreException {
+			IASTPreprocessorMacroDefinition[] macros, IASTName[][] names) throws CoreException {
 		assert sourceFile.getIndexFragment() == this;
+		assert includes.length == destFiles.length;
 		
 		PDOMFile pdomFile = (PDOMFile) sourceFile;
 		pdomFile.addIncludesTo(destFiles, includes);
 		pdomFile.addMacros(macros);
-		for (int i = 0; i < names.length; i++) {
-			IASTName name= names[i];
-			PDOMLinkage linkage= createLinkage(name.getLinkage().getID());
-			if (linkage == null) {
-				CCorePlugin.log(MessageFormat.format(Messages.WritablePDOM_error_unknownLinkage, new Object[]{name.getLinkage()}));
-			}
-			else {
-				linkage.addName(name, pdomFile);
-			}
-		}
+		pdomFile.addNames(names);
 	}
 
 	public void clearFile(IIndexFragmentFile file) throws CoreException {
@@ -61,4 +54,16 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
 	public void clear() throws CoreException {
 		super.clear();
 	}
+	
+	public PDOMBinding addBinding(IASTName name) throws CoreException {
+		PDOMBinding result= null;
+		PDOMLinkage linkage= createLinkage(name.getLinkage().getID());
+		if (linkage == null) {
+			CCorePlugin.log(MessageFormat.format(Messages.WritablePDOM_error_unknownLinkage, new Object[]{name.getLinkage()}));
+		}
+		else {
+			result= linkage.addBinding(name);
+		}
+		return result;
+	}
 }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java
index 10304ebf51f..918137bfa47 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java
@@ -12,8 +12,10 @@
 package org.eclipse.cdt.internal.core.pdom.dom;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 
+import org.eclipse.cdt.core.dom.ast.IASTName;
 import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
 import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
 import org.eclipse.cdt.core.index.IIndexInclude;
@@ -22,6 +24,7 @@ import org.eclipse.cdt.internal.core.index.IIndexFragment;
 import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
 import org.eclipse.cdt.internal.core.index.IWritableIndexFragment;
 import org.eclipse.cdt.internal.core.pdom.PDOM;
+import org.eclipse.cdt.internal.core.pdom.WritablePDOM;
 import org.eclipse.cdt.internal.core.pdom.db.Database;
 import org.eclipse.cdt.internal.core.pdom.db.IBTreeComparator;
 import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor;
@@ -149,15 +152,6 @@ public class PDOMFile implements IIndexFragmentFile {
 		pdom.getDB().putInt(record + FIRST_NAME, namerec);
 	}
 	
-	public void addName(PDOMName name) throws CoreException {
-		PDOMName firstName = getFirstName();
-		if (firstName != null) {
-			name.setNextInFile(firstName);
-			firstName.setPrevInFile(name);
-		}
-		setFirstName(name);
-	}
-	
 	public PDOMInclude getFirstInclude() throws CoreException {
 		int increc = pdom.getDB().getInt(record + FIRST_INCLUDE);
 		return increc != 0 ? new PDOMInclude(pdom, increc) : null;
@@ -205,6 +199,36 @@ public class PDOMFile implements IIndexFragmentFile {
 		}
 	}
 	
+	public void addNames(IASTName[][] names) throws CoreException {
+		assert getFirstName() == null;
+		HashMap nameCache= new HashMap();
+		PDOMName lastName= null;
+		for (int i = 0; i < names.length; i++) {
+			IASTName[] name = names[i];
+			PDOMName caller= (PDOMName) nameCache.get(name[1]);
+			PDOMName pdomName = createPDOMName(name[0], caller);
+			if (pdomName != null) {
+				nameCache.put(name[0], pdomName);
+				if (lastName == null) {
+					setFirstName(pdomName);
+				}
+				else {
+					lastName.setNextInFile(pdomName);
+				}
+				lastName= pdomName;
+			}
+		}
+	}
+	
+	private PDOMName createPDOMName(IASTName name, PDOMName caller) throws CoreException {
+		PDOMName result= null;
+		PDOMBinding binding= ((WritablePDOM) pdom).addBinding(name);
+		if (binding != null) {
+			result= new PDOMName(pdom, name, this, binding, caller);
+		}
+		return result;
+	}
+
 	public void clear() throws CoreException {
 		// Remove the includes
 		PDOMInclude include = getFirstInclude();
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java
index e8ed93c983e..27fd71cd875 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java
@@ -168,7 +168,7 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IBindingIdent
 		};
 	}
 	
-	public abstract PDOMBinding addName(IASTName name, PDOMFile file) throws CoreException;
+	public abstract PDOMBinding addBinding(IASTName name) throws CoreException;
 	
 	public abstract PDOMBinding adaptBinding(IBinding binding) throws CoreException;
 	
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java
index 6b613d21fba..e7427d6393c 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMName.java
@@ -11,10 +11,13 @@
  *******************************************************************************/
 package org.eclipse.cdt.internal.core.pdom.dom;
 
+import java.util.ArrayList;
+
 import org.eclipse.cdt.core.CCorePlugin;
 import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
 import org.eclipse.cdt.core.dom.ast.IASTName;
 import org.eclipse.cdt.core.index.IIndexFile;
+import org.eclipse.cdt.core.index.IIndexName;
 import org.eclipse.cdt.internal.core.index.IIndexFragment;
 import org.eclipse.cdt.internal.core.index.IIndexFragmentName;
 import org.eclipse.cdt.internal.core.index.IIndexProxyBinding;
@@ -32,23 +35,23 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation {
 	private final int record;
 	
 	private static final int FILE_REC_OFFSET     = 0;
-	private static final int FILE_PREV_OFFSET 	 = 4;
-	private static final int FILE_NEXT_OFFSET	 = 8;
+	private static final int FILE_NEXT_OFFSET	 = 4;
+	private static final int CALLER_REC_OFFSET   = 8;
 	private static final int BINDING_REC_OFFSET  = 12;
 	private static final int BINDING_PREV_OFFSET = 16;
 	private static final int BINDING_NEXT_OFFSET = 20;
 	private static final int NODE_OFFSET_OFFSET  = 24;
-	private static final int NODE_LENGTH_OFFSET  = 28;
-	private static final int FLAGS 				 = 32;
+	private static final int NODE_LENGTH_OFFSET  = 28; // short
+	private static final int FLAGS 				 = 30; // byte
 
-	private static final int RECORD_SIZE = 33;
+	private static final int RECORD_SIZE = 31;
 
 	private static final int IS_DECLARATION = 1;
 	private static final int IS_DEFINITION = 2;
 	private static final int IS_REFERENCE = 3;
 	
 
-	public PDOMName(PDOM pdom, IASTName name, PDOMFile file, PDOMBinding binding) throws CoreException {
+	public PDOMName(PDOM pdom, IASTName name, PDOMFile file, PDOMBinding binding, PDOMName caller) throws CoreException {
 		this.pdom = pdom;
 		Database db = pdom.getDB();
 		record = db.malloc(RECORD_SIZE);
@@ -80,14 +83,15 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation {
 			db.putInt(record + BINDING_REC_OFFSET, binding.getRecord());
 		}
 		
-		// Hook us up the the liked name list from file
 		db.putInt(record + FILE_REC_OFFSET, file.getRecord());
-		file.addName(this);
+		if (caller != null) {
+			db.putInt(record + CALLER_REC_OFFSET, caller.getRecord());
+		}
 
 		// Record our location in the file
 		IASTFileLocation fileloc = name.getFileLocation();
 		db.putInt(record + NODE_OFFSET_OFFSET, fileloc.getNodeOffset());
-		db.putInt(record + NODE_LENGTH_OFFSET, fileloc.getNodeLength());
+		db.putShort(record + NODE_LENGTH_OFFSET, (short) fileloc.getNodeLength());
 	}
 	
 	public PDOMName(PDOM pdom, int nameRecord) {
@@ -147,6 +151,15 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation {
 		int filerec = pdom.getDB().getInt(record + FILE_REC_OFFSET);
 		return filerec != 0 ? new PDOMFile(pdom, filerec) : null;
 	}
+
+	public IIndexName getEnclosingDefinition() throws CoreException {
+		int namerec = getEnclosingDefinitionRecord();
+		return namerec != 0 ? new PDOMName(pdom, namerec) : null;
+	}
+
+	private int getEnclosingDefinitionRecord() throws CoreException {
+		return pdom.getDB().getInt(record + CALLER_REC_OFFSET);
+	}
 	
 	public PDOMName getNextInFile() throws CoreException {
 		return getNameField(FILE_NEXT_OFFSET);
@@ -155,15 +168,7 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation {
 	public void setNextInFile(PDOMName name) throws CoreException {
 		setNameField(FILE_NEXT_OFFSET, name);
 	}
-	
-	public PDOMName getPrevInFile() throws CoreException {
-		return getNameField(FILE_PREV_OFFSET);
-	}
-
-	public void setPrevInFile(PDOMName name) throws CoreException {
-		setNameField(FILE_PREV_OFFSET, name);
-	}
-	
+		
 	public PDOMBinding resolveBinding() {
 		try {
 			int bindingRecord = pdom.getDB().getInt(record + BINDING_REC_OFFSET);
@@ -248,7 +253,7 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation {
 
 	public int getNodeLength() {
 		try {
-			return pdom.getDB().getInt(record + NODE_LENGTH_OFFSET);
+			return pdom.getDB().getShort(record + NODE_LENGTH_OFFSET);
 		} catch (CoreException e) {
 			CCorePlugin.log(e);
 			return 0;
@@ -298,4 +303,16 @@ public class PDOMName implements IIndexFragmentName, IASTFileLocation {
 	public IIndexProxyBinding getBinding() throws CoreException {
 		return getPDOMBinding();
 	}
+
+	public IIndexName[] getEnclosedNames() throws CoreException {
+		ArrayList result= new ArrayList();
+		PDOMName name= getNextInFile();
+		while (name != null) {
+			if (name.getEnclosingDefinitionRecord() == record) {
+				result.add(name);
+			}
+			name= name.getNextInFile();
+		}
+		return (IIndexName[]) result.toArray(new IIndexName[result.size()]);
+	}
 }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java
index ab671442e13..7f0cee55d42 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCLinkage.java
@@ -43,9 +43,7 @@ import org.eclipse.cdt.internal.core.pdom.dom.FindBindingByLinkageConstant;
 import org.eclipse.cdt.internal.core.pdom.dom.FindEquivalentBinding;
 import org.eclipse.cdt.internal.core.pdom.dom.IPDOMMemberOwner;
 import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
-import org.eclipse.cdt.internal.core.pdom.dom.PDOMFile;
 import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
-import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
 import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.Status;
@@ -85,9 +83,7 @@ class PDOMCLinkage extends PDOMLinkage {
 		return new GCCLanguage();
 	}
 
-		
-
-	public PDOMBinding addName(IASTName name, PDOMFile file) throws CoreException {
+	public PDOMBinding addBinding(IASTName name) throws CoreException {
 		if (name == null)
 			return null;
 
@@ -149,10 +145,6 @@ class PDOMCLinkage extends PDOMLinkage {
 		} catch (DOMException e) {
 			throw new CoreException(Util.createStatus(e));
 		}
-
-		if (pdomBinding != null)
-			new PDOMName(pdom, name, file, pdomBinding);
-
 		return pdomBinding;
 	}
 
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java
index 78af27ff078..087ebee6362 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java
@@ -316,7 +316,9 @@ ICPPClassScope, IPDOMMemberOwner {
 		}
 	}
 
-	public void addChild(PDOMNode member) throws CoreException {addMember(member);}
+	public void addChild(PDOMNode member) throws CoreException {
+		addMember(member);
+	}
 
 	public ICPPConstructor[] getConstructors() throws DOMException {
 		// TODO
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java
index b54ac41eefc..df0c7e16fb0 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java
@@ -15,7 +15,6 @@ package org.eclipse.cdt.internal.core.pdom.dom.cpp;
 
 import org.eclipse.cdt.core.CCorePlugin;
 import org.eclipse.cdt.core.dom.ast.DOMException;
-import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
 import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
 import org.eclipse.cdt.core.dom.ast.IASTExpression;
 import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
@@ -69,9 +68,7 @@ import org.eclipse.cdt.internal.core.pdom.dom.FindBindingByLinkageConstant;
 import org.eclipse.cdt.internal.core.pdom.dom.FindEquivalentBinding;
 import org.eclipse.cdt.internal.core.pdom.dom.IPDOMMemberOwner;
 import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
-import org.eclipse.cdt.internal.core.pdom.dom.PDOMFile;
 import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
-import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
 import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
 import org.eclipse.cdt.internal.core.pdom.dom.PDOMNotImplementedError;
 import org.eclipse.core.runtime.CoreException;
@@ -120,8 +117,7 @@ class PDOMCPPLinkage extends PDOMLinkage {
 		return new GPPLanguage();
 	}
 
-
-	public PDOMBinding addName(IASTName name, PDOMFile file) throws CoreException {
+	public PDOMBinding addBinding(IASTName name) throws CoreException {
 		if (name == null || name instanceof ICPPASTQualifiedName)
 			return null;
 
@@ -198,9 +194,6 @@ class PDOMCPPLinkage extends PDOMLinkage {
 
 		// final processing
 		if (pdomBinding != null) {
-			// Add in the name
-			new PDOMName(pdom, name, file, pdomBinding);
-
 			// Check if is a base specifier
 			if (pdomBinding instanceof ICPPClassType && name.getParent() instanceof ICPPASTBaseSpecifier) {
 				ICPPASTBaseSpecifier baseNode = (ICPPASTBaseSpecifier)name.getParent();
@@ -297,8 +290,6 @@ class PDOMCPPLinkage extends PDOMLinkage {
 	}
 
 	private PDOMBinding _resolveBinding(IASTName name) throws CoreException, DOMException {
-		// mstodo revisit
-
 		IBinding origBinding = name.getBinding();	
 		if (origBinding != null)
 			return adaptBinding(origBinding);
@@ -398,7 +389,7 @@ class PDOMCPPLinkage extends PDOMLinkage {
 							PDOMBinding pdomFOB = adaptBinding( (ICompositeType)  type);
 							FindBindingByLinkageConstant visitor = new FindBindingByLinkageConstant(this, name.toCharArray(), PDOMCPPLinkage.CPPFIELD);
 							try {
-								((PDOMBinding)pdomFOB).accept(visitor);
+								pdomFOB.accept(visitor);
 							} catch (CoreException e) {
 								if (e.getStatus().equals(Status.OK_STATUS)) {
 									return visitor.getResult();
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/IndexerASTVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/IndexerASTVisitor.java
new file mode 100644
index 00000000000..bfb1ad253c8
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/IndexerASTVisitor.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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.pdom.indexer;
+
+import org.eclipse.cdt.core.dom.ast.ASTVisitor;
+import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
+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.cpp.ICPPASTQualifiedName;
+
+abstract public class IndexerASTVisitor extends ASTVisitor {
+	private IASTName fDefinitionName;
+	private IASTNode fDefinition;
+
+	public IndexerASTVisitor() {
+		shouldVisitNames = true;
+		shouldVisitDeclarations = true;
+	}
+
+	abstract public void visit(IASTName name, IASTName definitionName);
+
+	final public int visit(IASTName name) {
+		if (!(name instanceof ICPPASTQualifiedName)) {
+			if (fDefinition != null) {
+				if (!fDefinition.contains(name)) {
+					fDefinition= null;
+					fDefinitionName= null;
+				}
+			}
+			if (name != fDefinitionName) {
+				visit(name, fDefinitionName);
+			}
+		}
+		return PROCESS_CONTINUE;
+	}
+
+	public int visit(IASTDeclaration decl) {
+		if (decl instanceof IASTFunctionDefinition) {
+			IASTFunctionDefinition fdef= (IASTFunctionDefinition) decl;
+			fDefinition= decl;
+			fDefinitionName= fdef.getDeclarator().getName();
+			if (fDefinitionName instanceof ICPPASTQualifiedName) {
+				fDefinitionName= ((ICPPASTQualifiedName) fDefinitionName).getLastName();
+			}
+			visit(fDefinitionName, null);
+		}
+		return PROCESS_CONTINUE;
+	}
+}
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java
index f00b1630a7d..db7afcf2603 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/PDOMIndexerTask.java
@@ -14,15 +14,21 @@ package org.eclipse.cdt.internal.core.pdom.indexer;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.eclipse.cdt.core.CCorePlugin;
 import org.eclipse.cdt.core.dom.IPDOMIndexerTask;
+import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
 import org.eclipse.cdt.core.dom.ast.IASTName;
 import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
 import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
 import org.eclipse.cdt.core.index.IIndex;
 import org.eclipse.cdt.core.index.IIndexFile;
 import org.eclipse.cdt.core.index.IIndexInclude;
@@ -240,7 +246,90 @@ public abstract class PDOMIndexerTask implements IPDOMIndexerTask {
 		return fCompletedSources;
 	}
 	
-	protected IIndexFragmentFile addToIndex(IWritableIndex index, String location, ArrayList[] lists) throws CoreException {
+	/**
+	 * Extracts a map of names from the ast and returns an array defining the order in
+	 * which the symbols should be added to the index.
+	 * @since 4.0
+	 */
+	protected String[] extractSymbols(IASTTranslationUnit ast, Set legalPaths, final LinkedHashMap symbolMap) {
+		// includes
+		final String astFilePath = ast.getFilePath();
+		IASTPreprocessorIncludeStatement[] includes = ast.getIncludeDirectives();
+		for (int i = includes.length-1; i >= 0; --i) {
+			IASTPreprocessorIncludeStatement include = includes[i];
+			IASTFileLocation sourceLoc = include.getFileLocation();
+			String path= sourceLoc != null ? sourceLoc.getFileName() : astFilePath; // command-line includes
+			if (legalPaths.contains(path)) {
+				prepareInMap(symbolMap, path);
+				addToMap(symbolMap, 0, path, include);
+			}
+			path= include.getPath();
+			if (legalPaths.contains(path)) {
+				prepareInMap(symbolMap, path);
+			}
+		}
+		if (legalPaths.contains(astFilePath)) {
+			prepareInMap(symbolMap, ast.getFilePath());
+		}
+	
+		// macros
+		IASTPreprocessorMacroDefinition[] macros = ast.getMacroDefinitions();
+		for (int i = 0; i < macros.length; ++i) {
+			IASTPreprocessorMacroDefinition macro = macros[i];
+			IASTFileLocation sourceLoc = macro.getFileLocation();
+			if (sourceLoc != null) { // skip built-ins and command line macros
+				String path = sourceLoc.getFileName();
+				addToMap(symbolMap, 1, path, macro);
+			}
+		}
+			
+		// names
+		ast.accept(new IndexerASTVisitor() {
+			public void visit(IASTName name, IASTName caller) {
+				IASTFileLocation nameLoc = name.getFileLocation();
+				if (nameLoc != null) {
+					addToMap(symbolMap, 2, nameLoc.getFileName(), new IASTName[]{name, caller});
+				}
+			}
+		});
+		
+		Collection temp= symbolMap.keySet();
+		int size= temp.size();
+		String[] result= new String[temp.size()];
+		for (Iterator iter = temp.iterator(); iter.hasNext();) {
+			result[--size]= (String) iter.next();
+		}
+		return result;
+	}
+
+	private void addToMap(HashMap map, int idx, String path, Object thing) {
+		List[] lists= (List[]) map.get(path);
+		if (lists != null) 
+			lists[idx].add(thing);
+	}		
+
+	private boolean prepareInMap(Map map, String path) {
+		if (map.get(path) == null) {
+			Object lists= new ArrayList[]{new ArrayList(), new ArrayList(), new ArrayList()};
+			map.put(path, lists);
+		}
+		return false;
+	}
+
+	protected void prepareIndexInsertion(String path, Map symbolMap) {
+		ArrayList[] arrayLists = ((ArrayList[]) symbolMap.get(path));
+
+		// reverse the includes
+		Collections.reverse(arrayLists[0]);
+		
+		// resolve the names
+		ArrayList names= arrayLists[2];
+		for (int j=0; j<names.size(); j++) {
+			((IASTName[]) names.get(j))[0].resolveBinding();
+		}
+	}
+
+	protected IIndexFragmentFile addToIndex(IWritableIndex index, String location, Map symbolMap) throws CoreException {
 		// Remove the old symbols in the tu
 		Path path= new Path(location);
 		IIndexFragmentFile file= (IIndexFragmentFile) index.getFile(path);
@@ -251,13 +340,14 @@ public abstract class PDOMIndexerTask implements IPDOMIndexerTask {
 			file= index.addFile(path);
 		}
 		file.setTimestamp(path.toFile().lastModified());
+		ArrayList[] lists= (ArrayList[]) symbolMap.get(location);
 		if (lists != null) {
 			ArrayList list= lists[0];
 			IASTPreprocessorIncludeStatement[] includes= (IASTPreprocessorIncludeStatement[]) list.toArray(new IASTPreprocessorIncludeStatement[list.size()]);
 			list= lists[1];
 			IASTPreprocessorMacroDefinition[] macros= (IASTPreprocessorMacroDefinition[]) list.toArray(new IASTPreprocessorMacroDefinition[list.size()]);
 			list= lists[2];
-			IASTName[] names= (IASTName[]) list.toArray(new IASTName[list.size()]);
+			IASTName[][] names= (IASTName[][]) list.toArray(new IASTName[list.size()][]);
 
 			index.setFileContent(file, includes, macros, names);
 		}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/fast/PDOMFastIndexerJob.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/fast/PDOMFastIndexerJob.java
index 20e0ea0a266..eeb55938211 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/fast/PDOMFastIndexerJob.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/fast/PDOMFastIndexerJob.java
@@ -12,22 +12,15 @@
 
 package org.eclipse.cdt.internal.core.pdom.indexer.fast;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedHashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
 
 import org.eclipse.cdt.core.CCorePlugin;
 import org.eclipse.cdt.core.dom.IPDOMIndexer;
 import org.eclipse.cdt.core.dom.IPDOMIndexerTask;
-import org.eclipse.cdt.core.dom.ast.ASTVisitor;
-import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
-import org.eclipse.cdt.core.dom.ast.IASTName;
-import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
-import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
 import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
 import org.eclipse.cdt.core.model.ILanguage;
 import org.eclipse.cdt.core.model.ITranslationUnit;
@@ -92,7 +85,7 @@ abstract class PDOMFastIndexerJob extends PDOMIndexerTask implements IPDOMIndexe
 			return;
 		}
 
-		LinkedHashSet paths= new LinkedHashSet();
+		HashSet paths= new HashSet();
 		paths.add(path.toOSString());
 		codeReaderFactory.setPathCollector(paths);
 		index.acquireReadLock();
@@ -114,71 +107,27 @@ abstract class PDOMFastIndexerJob extends PDOMIndexerTask implements IPDOMIndexe
 		}
 	}
 
-	protected void addSymbols(Collection paths, IASTTranslationUnit ast, IProgressMonitor pm) throws InterruptedException, CoreException {
+	protected void addSymbols(HashSet paths, IASTTranslationUnit ast, IProgressMonitor pm) throws InterruptedException, CoreException {
 		// Add in the includes
-		final HashMap symbolMap= new HashMap();
+		final LinkedHashMap symbolMap= new LinkedHashMap();
+		String[] orderedPaths= extractSymbols(ast, paths, symbolMap);
 		
-		// includes
-		IASTPreprocessorIncludeStatement[] includes = ast.getIncludeDirectives();
-		for (int i = 0; i < includes.length; ++i) {
-			IASTPreprocessorIncludeStatement include = includes[i];
-			IASTFileLocation sourceLoc = include.getFileLocation();
-			String path= sourceLoc != null ? sourceLoc.getFileName() : ast.getFilePath(); // command-line includes
-			addToMap(symbolMap, 0, path, include);
-		}
-	
-		// macros
-		IASTPreprocessorMacroDefinition[] macros = ast.getMacroDefinitions();
-		for (int i = 0; i < macros.length; ++i) {
-			IASTPreprocessorMacroDefinition macro = macros[i];
-			IASTFileLocation sourceLoc = macro.getFileLocation();
-			if (sourceLoc != null) { // skip built-ins and command line macros
-				String path = sourceLoc.getFileName();
-				addToMap(symbolMap, 1, path, macro);
-			}
-		}
-			
-		// names
-		ast.accept(new ASTVisitor() {
-			{
-				shouldVisitNames = true;
-				shouldVisitDeclarations = true;
-			}
-			public int visit(IASTName name) {
-				try {
-					IASTFileLocation nameLoc = name.getFileLocation();
-					if (nameLoc != null) {
-						addToMap(symbolMap, 2, nameLoc.getFileName(), name);
-					}
-					return PROCESS_CONTINUE;
-				} catch (Throwable e) {
-					CCorePlugin.log(e);
-					return ++fErrorCount > MAX_ERRORS ? PROCESS_ABORT : PROCESS_CONTINUE;
-				}
-			}
-		});
-
-		for (Iterator iter = symbolMap.entrySet().iterator(); iter.hasNext();) {
-			Map.Entry entry = (Map.Entry) iter.next();
+		for (int i=0; i<orderedPaths.length; i++) {
 			if (pm.isCanceled()) {
 				return;
 			}
-			String path= (String) entry.getKey();
+			String path= orderedPaths[i];
 			FileInfo info= codeReaderFactory.createFileInfo(path);
 		
 			// file is requested or is not yet indexed.
 			if (info.isRequested() || info.fFile == null) {
-				// resolve the names
-				ArrayList names= ((ArrayList[]) entry.getValue())[2];
-				for (int i=0; i<names.size(); i++) {
-					((IASTName) names.get(i)).resolveBinding();
-				}
+				prepareIndexInsertion(path, symbolMap);
 			}
 			else {
 				if (fTrace) {
 					System.out.println("Indexer: skipping " + path); //$NON-NLS-1$
 				}
-				iter.remove();
+				orderedPaths[i]= null;
 			}
 		}
 
@@ -186,29 +135,31 @@ abstract class PDOMFastIndexerJob extends PDOMIndexerTask implements IPDOMIndexe
 		boolean isFirstAddition= true;
 		index.acquireWriteLock(1);
 		try {
-			for (Iterator iter = paths.iterator(); iter.hasNext();) {
+			for (int i=0; i<orderedPaths.length; i++) {
 				if (pm.isCanceled()) 
 					return;
 				
-				String path = (String) iter.next();
-				FileInfo info= codeReaderFactory.createFileInfo(path);
-				if (info.isRequested()) {
-					info.setRequested(false);
+				String path = orderedPaths[i];
+				if (path != null) {
+					FileInfo info= codeReaderFactory.createFileInfo(path);
+					if (info.isRequested()) {
+						info.setRequested(false);
 
-					if (isFirstRequest) 
-						isFirstRequest= false;
-					else 
-						fTotalSourcesEstimate--;
-				}
-				if (fTrace) {
-					System.out.println("Indexer: adding " + path); //$NON-NLS-1$
-				}
-				info.fFile= addToIndex(index, path, (ArrayList[]) symbolMap.get(path));
+						if (isFirstRequest) 
+							isFirstRequest= false;
+						else 
+							fTotalSourcesEstimate--;
+					}
+					if (fTrace) {
+						System.out.println("Indexer: adding " + path); //$NON-NLS-1$
+					}
+					info.fFile= addToIndex(index, path, symbolMap);
 
-				if (isFirstAddition) 
-					isFirstAddition= false;
-				else
-					fCompletedHeaders++;
+					if (isFirstAddition) 
+						isFirstAddition= false;
+					else
+						fCompletedHeaders++;
+				}
 			}
 		} finally {
 			index.releaseWriteLock(1);
@@ -216,14 +167,6 @@ abstract class PDOMFastIndexerJob extends PDOMIndexerTask implements IPDOMIndexe
 		fCompletedSources++;
 	}
 
-	private void addToMap(HashMap map, int idx, String path, Object thing) {
-		List[] lists= (List[]) map.get(path);
-		if (lists == null) {
-			lists= new ArrayList[]{new ArrayList(), new ArrayList(), new ArrayList()};
-			map.put(path, lists);
-		}
-		lists[idx].add(thing);
-	}		
 
 	protected void parseTUs(List sources, List headers, IProgressMonitor monitor) throws CoreException, InterruptedException {
 		// sources first
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/full/PDOMFullIndexerJob.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/full/PDOMFullIndexerJob.java
index 4f2951541f1..a7f019cd716 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/full/PDOMFullIndexerJob.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/full/PDOMFullIndexerJob.java
@@ -12,22 +12,15 @@
 
 package org.eclipse.cdt.internal.core.pdom.indexer.full;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
-import java.util.List;
 import java.util.Map;
 
 import org.eclipse.cdt.core.CCorePlugin;
 import org.eclipse.cdt.core.dom.IPDOMIndexer;
 import org.eclipse.cdt.core.dom.IPDOMIndexerTask;
-import org.eclipse.cdt.core.dom.ast.ASTVisitor;
-import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
-import org.eclipse.cdt.core.dom.ast.IASTName;
-import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
-import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
 import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
 import org.eclipse.cdt.core.model.ITranslationUnit;
 import org.eclipse.cdt.internal.core.index.IWritableIndex;
@@ -137,74 +130,26 @@ abstract class PDOMFullIndexerJob extends PDOMIndexerTask implements IPDOMIndexe
 	
 	protected void addSymbols(IASTTranslationUnit ast, IProgressMonitor pm) throws InterruptedException, CoreException {
 		// Add in the includes
-		final LinkedHashMap symbolMap= new LinkedHashMap(); // makes bugs reproducible
-		prepareInMap(symbolMap, ast.getFilePath());
+		final LinkedHashMap symbolMap= new LinkedHashMap(); 
+		String[] orderedPaths= extractSymbols(ast, filePathsToParse.keySet(), symbolMap);
 		
-		// includes
-		IASTPreprocessorIncludeStatement[] includes = ast.getIncludeDirectives();
-		for (int i = 0; i < includes.length; ++i) {
-			IASTPreprocessorIncludeStatement include = includes[i];
-			IASTFileLocation sourceLoc = include.getFileLocation();
-			String path= sourceLoc != null ? sourceLoc.getFileName() : ast.getFilePath(); // command-line includes
-			addToMap(symbolMap, 0, path, include);
-			path= include.getPath();
-			if (path != null) {
-				prepareInMap(symbolMap, include.getPath());
-			}
-		}
-	
-		// macros
-		IASTPreprocessorMacroDefinition[] macros = ast.getMacroDefinitions();
-		for (int i = 0; i < macros.length; ++i) {
-			IASTPreprocessorMacroDefinition macro = macros[i];
-			IASTFileLocation sourceLoc = macro.getFileLocation();
-			if (sourceLoc != null) { // skip built-ins and command line macros
-				String path = sourceLoc.getFileName();
-				addToMap(symbolMap, 1, path, macro);
-			}
-		}
-			
-		// names
-		ast.accept(new ASTVisitor() {
-			{
-				shouldVisitNames = true;
-				shouldVisitDeclarations = true;
-			}
-			public int visit(IASTName name) {
-				try {
-					IASTFileLocation nameLoc = name.getFileLocation();
-					if (nameLoc != null) {
-						addToMap(symbolMap, 2, nameLoc.getFileName(), name);
-					}
-					return PROCESS_CONTINUE;
-				} catch (Throwable e) {
-					CCorePlugin.log(e);
-					return ++fErrorCount > MAX_ERRORS ? PROCESS_ABORT : PROCESS_CONTINUE;
-				}
-			}
-		});
-
-		for (Iterator iter = symbolMap.values().iterator(); iter.hasNext();) {
+		for (int i=0; i<orderedPaths.length; i++) {
 			if (pm.isCanceled()) {
 				return;
 			}
-			// resolve the names
-			ArrayList names= ((ArrayList[]) iter.next())[2];
-			for (int i=0; i<names.size(); i++) {
-				((IASTName) names.get(i)).resolveBinding();
-			}
+			String path= orderedPaths[i];
+			prepareIndexInsertion(path, symbolMap);
 		}
 
 		boolean isFirstRequest= true;
 		boolean isFirstAddition= true;
 		index.acquireWriteLock(0);
 		try {
-			for (Iterator iter = symbolMap.entrySet().iterator(); iter.hasNext();) {
+			for (int i=0; i<orderedPaths.length; i++) {
 				if (pm.isCanceled()) 
 					return;
 				
-				Map.Entry entry = (Map.Entry) iter.next();
-				String path= (String) entry.getKey();
+				String path = orderedPaths[i];
 				Boolean required= (Boolean) filePathsToParse.remove(path);
 				if (required != null) {
 					if (required.booleanValue()) {
@@ -217,7 +162,7 @@ abstract class PDOMFullIndexerJob extends PDOMIndexerTask implements IPDOMIndexe
 					if (fTrace) 
 						System.out.println("Indexer: adding " + path); //$NON-NLS-1$
 					
-					addToIndex(index, path, (ArrayList[]) entry.getValue());
+					addToIndex(index, path, symbolMap);
 					
 					if (isFirstAddition) 
 						isFirstAddition= false;
@@ -230,20 +175,4 @@ abstract class PDOMFullIndexerJob extends PDOMIndexerTask implements IPDOMIndexe
 		}
 		fCompletedSources++;
 	}
-
-	private void prepareInMap(Map map, String path) {
-		if (filePathsToParse.get(path) != null) {
-			if (map.get(path) == null) {
-				Object lists= new ArrayList[]{new ArrayList(), new ArrayList(), new ArrayList()};
-				map.put(path, lists);
-			}
-		}
-	}
-			
-	private void addToMap(HashMap map, int idx, String path, Object thing) {
-		List[] lists= (List[]) map.get(path);
-		if (lists != null) {
-			lists[idx].add(thing);
-		}
-	}		
 }