1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Copy of branch bug_197989.

This commit is contained in:
Markus Schorn 2011-09-20 13:25:43 +02:00
parent 97e64c95b3
commit d69c979ada
70 changed files with 3020 additions and 1192 deletions

View file

@ -1,13 +1,13 @@
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* Copyright (c) 2004, 2011 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:
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.ast2;
@ -35,6 +35,7 @@ import org.eclipse.cdt.core.parser.ExtendedScannerInfo;
import org.eclipse.cdt.core.parser.IExtendedScannerInfo;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.ScannerInfo;
import org.eclipse.cdt.internal.core.dom.SavedCodeReaderFactory;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
@ -70,9 +71,9 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
String code = "int main() { return BEAST * sizeof( Include ); } "; //$NON-NLS-1$
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "main.cc" : "main.c"; //$NON-NLS-1$ //$NON-NLS-2$
IFile c = importFile(filename, code); //$NON-NLS-1$ //$NON-NLS-2$
IFile c = importFile(filename, code);
IASTTranslationUnit tu = parse(c, scannerInfo); //$NON-NLS-1$
IASTTranslationUnit tu = parse(c, scannerInfo);
IASTFunctionDefinition fd = (IASTFunctionDefinition) tu.getDeclarations()[3];
IASTFileLocation floc = fd.getFileLocation();
assertEquals(floc.getNodeOffset(),
@ -102,11 +103,11 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "blah.cc" : "blah.c"; //$NON-NLS-1$ //$NON-NLS-2$
IFile source = importFile(filename, code); //$NON-NLS-1$
IASTTranslationUnit tu = parse(source); //$NON-NLS-1$
IFile source = importFile(filename, code);
IASTTranslationUnit tu = parse(source);
IASTSimpleDeclaration declaration = (IASTSimpleDeclaration) tu.getDeclarations()[0];
assertSoleFileLocation(declaration.getDeclarators()[0], filename,
code.indexOf("SomeStructure"), "SomeStructure".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
code.indexOf("SomeStructure"), "SomeStructure".length()); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
@ -206,13 +207,13 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "code.cc" : "code.c"; //$NON-NLS-1$ //$NON-NLS-2$
IFile cpp = importFile(filename, code); //$NON-NLS-1$
IASTTranslationUnit tu = parse(cpp); //$NON-NLS-1$
IFile cpp = importFile(filename, code);
IASTTranslationUnit tu = parse(cpp);
IASTDeclaration[] declarations = tu.getDeclarations();
assertEquals(declarations.length, 2);
IASTSimpleDeclaration bar = (IASTSimpleDeclaration) declarations[0];
IASTSimpleDeclaration FOO = (IASTSimpleDeclaration) declarations[1];
assertSoleFileLocation(bar, filename, code.indexOf("int"), code.indexOf(";") + 1); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(bar, filename, code.indexOf("int"), code.indexOf(";") + 1); //$NON-NLS-1$ //$NON-NLS-2$
assertSoleFileLocation(FOO, "foo.h", foo.indexOf("int"), foo.indexOf(";") + 1); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
IASTPreprocessorIncludeStatement[] incs = tu.getIncludeDirectives();
@ -243,8 +244,8 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "code.cc" : "code.c"; //$NON-NLS-1$ //$NON-NLS-2$
IFile cpp = importFile(filename, code); //$NON-NLS-1$
IASTTranslationUnit tu = parse(cpp); //$NON-NLS-1$
IFile cpp = importFile(filename, code);
IASTTranslationUnit tu = parse(cpp);
IASTDeclaration[] declarations = tu.getDeclarations();
assertEquals(declarations.length, 3);
IASTSimpleDeclaration bar = (IASTSimpleDeclaration) declarations[0];
@ -253,21 +254,21 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
assertSoleFileLocation(
bar,
filename,
code.indexOf("int"), code.indexOf("r;") + 2 - code.indexOf("int")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
code.indexOf("int"), code.indexOf("r;") + 2 - code.indexOf("int")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(
FOO,
"foo.h", foo.indexOf("int"), foo.indexOf(";") + 1 - foo.indexOf("int")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
assertSoleFileLocation(
byob,
filename,
code.indexOf("float"), code.indexOf("b;") + 2 - code.indexOf("float")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
code.indexOf("float"), code.indexOf("b;") + 2 - code.indexOf("float")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
IASTPreprocessorIncludeStatement[] incs = tu.getIncludeDirectives();
assertNotNull(incs);
assertEquals(incs.length, 1);
assertSoleFileLocation(
incs[0],
filename,
code.indexOf("#inc"), code.indexOf(".h\"\n") + ".h\"".length() - code.indexOf("#inc")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
code.indexOf("#inc"), code.indexOf(".h\"\n") + ".h\"".length() - code.indexOf("#inc")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
}
@ -278,8 +279,8 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "blah.cc" : "blah.c"; //$NON-NLS-1$ //$NON-NLS-2$
IFile c_file = importFile(filename, c_file_code); //$NON-NLS-1$
IASTTranslationUnit tu = parse(c_file); //$NON-NLS-1$
IFile c_file = importFile(filename, c_file_code);
IASTTranslationUnit tu = parse(c_file);
assertEquals(tu.getDeclarations().length, 0);
IASTPreprocessorMacroDefinition[] macroDefinitions = tu
.getMacroDefinitions();
@ -288,9 +289,9 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
assertSoleFileLocation(
macroDefinitions[0],
filename,
c_file_code.indexOf("#define"), c_file_code.indexOf("4") + 1 - c_file_code.indexOf("#define")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
c_file_code.indexOf("#define"), c_file_code.indexOf("4") + 1 - c_file_code.indexOf("#define")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(macroDefinitions[0].getName(), filename,
c_file_code.indexOf("X"), 1); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
c_file_code.indexOf("X"), 1); //$NON-NLS-1$
assertSoleFileLocation(
macroDefinitions[1],
"blarg.h", h_file_code.indexOf("#define _BLARG_H_"), "#define _BLARG_H_".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
@ -299,17 +300,17 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
"blarg.h", h_file_code.indexOf("e _BLARG_H_") + 2, "_BLARG_H_".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(
macroDefinitions[2],
"blarg.h", h_file_code.indexOf("#define PRINT(s,m) printf(s,m)\r"), "#define PRINT(s,m) printf(s,m)".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
"blarg.h", h_file_code.indexOf("#define PRINT(s,m) printf(s,m)\r"), "#define PRINT(s,m) printf(s,m)".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(macroDefinitions[2].getName(),
"blarg.h", h_file_code.indexOf("PRINT"), "PRINT".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
"blarg.h", h_file_code.indexOf("PRINT"), "PRINT".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(
macroDefinitions[3],
filename,
c_file_code.indexOf("#define POST_INCLUDE"), "#define POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
c_file_code.indexOf("#define POST_INCLUDE"), "#define POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$
assertSoleFileLocation(
macroDefinitions[3].getName(),
filename,
c_file_code.indexOf("POST_INCLUDE"), "POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
c_file_code.indexOf("POST_INCLUDE"), "POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$
}
}
@ -322,7 +323,7 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "source.cc" : "source.c"; //$NON-NLS-1$ //$NON-NLS-2$
IFile f = importFile(filename, cpp_code); //$NON-NLS-1$
IFile f = importFile(filename, cpp_code);
IASTTranslationUnit tu = parse(f);
IASTDeclaration[] declarations = tu.getDeclarations();
IASTPreprocessorIncludeStatement[] includeDirectives = tu
@ -330,7 +331,7 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
assertSoleFileLocation(
includeDirectives[0],
filename,
cpp_code.indexOf("#include \"header1.h\""), "#include \"header1.h\"".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
cpp_code.indexOf("#include \"header1.h\""), "#include \"header1.h\"".length()); //$NON-NLS-1$ //$NON-NLS-2$
assertSoleFileLocation(declarations[0],
"header1.h", 0, "int x;".length()); //$NON-NLS-1$ //$NON-NLS-2$
assertSoleFileLocation(declarations[1],
@ -338,9 +339,9 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
assertSoleFileLocation(
includeDirectives[1],
filename,
cpp_code.indexOf("#include \"header2.h\""), "#include \"header2.h\"".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
cpp_code.indexOf("#include \"header2.h\""), "#include \"header2.h\"".length()); //$NON-NLS-1$ //$NON-NLS-2$
assertSoleFileLocation(declarations[2], filename, cpp_code
.indexOf("int z;"), "int z;".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
.indexOf("int z;"), "int z;".length()); //$NON-NLS-1$ //$NON-NLS-2$
IASTTranslationUnit.IDependencyTree tree = tu.getDependencyTree();
assertEquals(tree.getInclusions().length, 2);
@ -357,8 +358,8 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "blah.cc" : "blah.c"; //$NON-NLS-1$ //$NON-NLS-2$
IFile c_file = importFile(filename, c_file_code); //$NON-NLS-1$
IASTTranslationUnit tu = parse(c_file); //$NON-NLS-1$
IFile c_file = importFile(filename, c_file_code);
IASTTranslationUnit tu = parse(c_file);
assertEquals(tu.getDeclarations().length, 0);
IASTPreprocessorMacroDefinition[] macroDefinitions = tu.getMacroDefinitions();
assertNotNull(macroDefinitions);
@ -366,9 +367,9 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
assertSoleFileLocation(
macroDefinitions[0],
filename,
c_file_code.indexOf("#define"), c_file_code.indexOf("4") + 1 - c_file_code.indexOf("#define")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
c_file_code.indexOf("#define"), c_file_code.indexOf("4") + 1 - c_file_code.indexOf("#define")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(macroDefinitions[0].getName(), filename,
c_file_code.indexOf("X"), 1); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
c_file_code.indexOf("X"), 1); //$NON-NLS-1$
assertSoleFileLocation(
macroDefinitions[1],
"blarg.h", h_file_code.indexOf("#define _BLARG_H_"), "#define _BLARG_H_".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
@ -377,24 +378,24 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
"blarg.h", h_file_code.indexOf("e _BLARG_H_") + 2, "_BLARG_H_".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(
macroDefinitions[2],
"blarg.h", h_file_code.indexOf("#define PRINT(s,m) printf(s,m)\r"), "#define PRINT(s,m) printf(s,m)".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
"blarg.h", h_file_code.indexOf("#define PRINT(s,m) printf(s,m)\r"), "#define PRINT(s,m) printf(s,m)".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(macroDefinitions[2].getName(),
"blarg.h", h_file_code.indexOf("PRINT"), "PRINT".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
"blarg.h", h_file_code.indexOf("PRINT"), "PRINT".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(
macroDefinitions[3],
filename,
c_file_code.indexOf("#define POST_INCLUDE"), "#define POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
c_file_code.indexOf("#define POST_INCLUDE"), "#define POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$
assertSoleFileLocation(
macroDefinitions[3].getName(),
filename,
c_file_code.indexOf("POST_INCLUDE"), "POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
c_file_code.indexOf("POST_INCLUDE"), "POST_INCLUDE".length()); //$NON-NLS-1$ //$NON-NLS-2$
assertSoleFileLocation(
macroDefinitions[4],
"second.h", h_file2_code.indexOf("#define _SECOND_H_"), "#define _SECOND_H_".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
assertSoleFileLocation(
macroDefinitions[5],
filename,
c_file_code.indexOf("#define POST_SECOND"), "#define POST_SECOND".length()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
c_file_code.indexOf("#define POST_SECOND"), "#define POST_SECOND".length()); //$NON-NLS-1$ //$NON-NLS-2$
}
}
@ -411,15 +412,15 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
buffer.append("};\n"); //$NON-NLS-1$
buffer.append("#endif /*_INCLUDE_H_*/\n"); //$NON-NLS-1$
final String inc_file_code = buffer.toString();
IFile include_file = importFile("include.h", inc_file_code); //$NON-NLS-1$ //$NON-NLS-2$
IFile include_file = importFile("include.h", inc_file_code); //$NON-NLS-1$
String[] macros = { imacro_file.getLocation().toOSString() };
String[] includes = { include_file.getLocation().toOSString() };
IExtendedScannerInfo scannerInfo = new ExtendedScannerInfo(Collections.EMPTY_MAP, EMPTY_STRING_ARRAY, macros, includes);
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "main.cc" : "main.c"; //$NON-NLS-1$ //$NON-NLS-2$
IFile code = importFile(filename, "int main() { return BEAST * sizeof( Include ); } "); //$NON-NLS-1$ //$NON-NLS-2$
IASTTranslationUnit tu = parse(code, scannerInfo); //$NON-NLS-1$
IFile code = importFile(filename, "int main() { return BEAST * sizeof( Include ); } "); //$NON-NLS-1$
IASTTranslationUnit tu = parse(code, scannerInfo);
IASTPreprocessorMacroDefinition[] macro_defs = tu.getMacroDefinitions();
assertEquals(macro_defs.length, 2);
IASTPreprocessorMacroDefinition BEAST = macro_defs[0];
@ -443,8 +444,8 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "blah.cc" : "blah.c"; //$NON-NLS-1$ //$NON-NLS-2$
IFile f = importFile(filename, code); //$NON-NLS-1$
IASTTranslationUnit tu = parse(f); //$NON-NLS-1$
IFile f = importFile(filename, code);
IASTTranslationUnit tu = parse(f);
IASTProblem[] prbs = tu.getPreprocessorProblems();
assertEquals(prbs.length, 1);
IASTNodeLocation[] locs = prbs[0].getNodeLocations();
@ -474,16 +475,16 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
buffer.append("};\n"); //$NON-NLS-1$
buffer.append("#endif /*_INCLUDE_H_*/\n"); //$NON-NLS-1$
final String inc_file_code = buffer.toString();
IFile include_file = importFile("include.h", inc_file_code); //$NON-NLS-1$ //$NON-NLS-2$
IFile include_file = importFile("include.h", inc_file_code); //$NON-NLS-1$
String[] macros = { imacro_file.getLocation().toOSString() };
String[] includes = { include_file.getLocation().toOSString() };
IExtendedScannerInfo scannerInfo = new ExtendedScannerInfo(
Collections.EMPTY_MAP, EMPTY_STRING_ARRAY, macros, includes);
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "main.cc" : "main.c"; //$NON-NLS-1$ //$NON-NLS-2$
IFile code = importFile(filename, "int main() { return BEAST * sizeof( Include ); } "); //$NON-NLS-1$ //$NON-NLS-2$
IFile code = importFile(filename, "int main() { return BEAST * sizeof( Include ); } "); //$NON-NLS-1$
IASTTranslationUnit tu = parse(code, scannerInfo); //$NON-NLS-1$
IASTTranslationUnit tu = parse(code, scannerInfo);
IASTPreprocessorMacroDefinition[] macro_defs = tu.getMacroDefinitions();
assertEquals(macro_defs.length, 4);
IASTPreprocessorMacroDefinition BEAST = macro_defs[0];
@ -515,14 +516,14 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
buffer.append("};\n"); //$NON-NLS-1$
buffer.append("#endif /*_INCLUDE_H_*/\n"); //$NON-NLS-1$
final String inc_file_code = buffer.toString();
IFile include_file = importFile("include.h", inc_file_code); //$NON-NLS-1$ //$NON-NLS-2$
IFile include_file = importFile("include.h", inc_file_code); //$NON-NLS-1$
String[] macros = { imacro_file1.getLocation().toOSString(), imacro_file2.getLocation().toOSString() };
String[] includes = { include_file.getLocation().toOSString() };
IExtendedScannerInfo scannerInfo = new ExtendedScannerInfo(Collections.EMPTY_MAP, EMPTY_STRING_ARRAY, macros, includes);
for (ParserLanguage p : ParserLanguage.values()) {
String filename = (p == ParserLanguage.CPP) ? "main.cc" : "main.c"; //$NON-NLS-1$ //$NON-NLS-2$
IFile code = importFile(filename, "int main() { return BEAST * sizeof( Include ); } "); //$NON-NLS-1$ //$NON-NLS-2$
IFile code = importFile(filename, "int main() { return BEAST * sizeof( Include ); } "); //$NON-NLS-1$
IASTTranslationUnit tu = parse(code, scannerInfo);
IASTPreprocessorMacroDefinition[] macro_defs = tu.getMacroDefinitions();
@ -611,4 +612,182 @@ public class DOMLocationInclusionTests extends AST2FileBasePluginTest {
tmpFile.getParentFile().delete();
}
}
// // comment
//
// #ifndef guard
// #define guard
// bla bla
// #if 1
// #endif
// bla bla
// #endif
// //comment
// // comment
//
// #if !defined(guard)
// #define guard
// bla bla
// #if 1
// #endif
// bla bla
// #endif
// //comment
// // comment
//
// #if ((!defined guard))
// #define guard
// bla bla
// #if 1
// #endif
// bla bla
// #endif
// //comment
// // comment
// #pragma once
// // Some comment
//
// #ifndef AN_UNIQUE_INCLUDE_GUARD_H_
// #define AN_UNIQUE_INCLUDE_GUARD_H_
//
// #include <string>
//
// Some code without any macro references
//
// #endif // AN_UNIQUE_INCLUDE_GUARD_H_
public void testPragmaOnceDetection_197989a() throws Exception {
CharSequence[] contents= getContents(5);
int i= 0;
for (CharSequence content : contents) {
String headerName = i + ".h";
IFile base = importFile("base" + headerName, "#include \"" + headerName + "\"");
importFile(headerName, content.toString());
IASTTranslationUnit tu = parse(base, new ScannerInfo());
IASTPreprocessorIncludeStatement[] incs = tu.getIncludeDirectives();
assertTrue(incs.length > 0);
assertTrue(incs[0].hasPragmaOnceSemantics());
}
}
// #ifndef guard
// #define guard2
// #endif
// #if !defined guard
// #define guard2
// #endif
// #if !defined(guard) && !defined(guard2)
// #define guard
// #endif
// #if (0)
// #pragma once
// #endif
// leading
// #ifndef guard
// #define guard2
// #endif
// #ifndef guard
// #define guard2
// #endif
// #ifdef xx
// trailing
// #endif
public void testPragmaOnceDetection_197989b() throws Exception {
CharSequence[] contents= getContents(6);
int i= 0;
for (CharSequence content : contents) {
String headerName = i + ".h";
IFile base = importFile("base" + headerName, "#include \"" + headerName + "\"");
importFile(headerName, content.toString());
IASTTranslationUnit tu = parse(base, new ScannerInfo());
IASTPreprocessorIncludeStatement[] incs = tu.getIncludeDirectives();
assertEquals(1, incs.length);
assertFalse(incs[0].hasPragmaOnceSemantics());
}
}
// // header.h
// #ifdef AH
// #endif
// #ifndef BH
// #endif
// #define h
// #if CH || DH
// #elif EH==1
// #endif
// #define BH
// #define DH 0
// #define EH 1
// #include "header.h"
// #ifdef h // defined in header
// #endif
// #ifdef A
// #ifdef a // inactive
// #endif
// #else
// #ifndef B
// #endif
// #endif
// #if defined C
// #elif ((!((defined(D)))))
// #endif
// #define A
// #define B
// #define AH
// #define h
// #undef u
// #ifdef h // locally defined
// #endif
// #ifndef u // locally undefined
// #endif
public void testSignificantMacros_197989a() throws Exception {
CharSequence[] contents= getContents(2);
IFile h = importFile("header.h", contents[0].toString());
IFile c = importFile("source.c", contents[1].toString());
IASTTranslationUnit tu = parse(c, new ScannerInfo());
IASTPreprocessorIncludeStatement[] incs = tu.getIncludeDirectives();
assertEquals(1, incs.length);
assertEquals("{AH=null,BH=*,CH=null,DH=0,EH=1}",
incs[0].getSignificantMacros().toString());
assertEquals("{A=null,AH=null,B=null,C=null,CH=null,D=null}",
tu.getSignificantMacros().toString());
}
// // header.h
// #if EQ(A,B)
// #endif
// #define EQ(x,y) x==y
// #define A A1
// #define B 1
// #include "header.h"
public void testSignificantMacros_197989b() throws Exception {
CharSequence[] contents= getContents(2);
IFile h = importFile("header.h", contents[0].toString());
IFile c = importFile("source.c", contents[1].toString());
IASTTranslationUnit tu = parse(c, new ScannerInfo());
IASTPreprocessorIncludeStatement[] incs = tu.getIncludeDirectives();
assertEquals(1, incs.length);
assertEquals("{A=A1,A1=null,B=1,EQ=x==y}",
incs[0].getSignificantMacros().toString());
assertEquals("{A1=null}",
tu.getSignificantMacros().toString());
}
}

View file

@ -1,29 +1,29 @@
/*******************************************************************************
* Copyright (c) 2004, 2009 IBM Corporation and others.
* Copyright (c) 2004, 2011 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:
* IBM - Initial API and implementation
* IBM - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.scanner;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.internal.core.parser.IMacroDictionary;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContentProvider;
public class FileCodeReaderFactory extends InternalFileContentProvider {
private static FileCodeReaderFactory instance;
private FileCodeReaderFactory() {}
@Override
public InternalFileContent getContentForInclusion(String path) {
public InternalFileContent getContentForInclusion(String path,
IMacroDictionary macroDictionary) {
return (InternalFileContent) FileContent.createForExternalFileLocation(path);
}

View file

@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.scanner;
@ -37,10 +37,10 @@ import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorUndefStatement;
import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree.IASTInclusionNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.testplugin.CTestPlugin;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
@ -49,8 +49,8 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
import org.eclipse.cdt.internal.core.parser.scanner.CharArray;
import org.eclipse.cdt.internal.core.parser.scanner.ILocationCtx;
import org.eclipse.cdt.internal.core.parser.scanner.ImageLocationInfo;
import org.eclipse.cdt.internal.core.parser.scanner.LocationMap;
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
import org.eclipse.cdt.internal.core.parser.scanner.LocationMap;
public class LocationMapTests extends BaseTestCase {
public class Loc implements IASTFileLocation {
@ -80,6 +80,9 @@ public class LocationMapTests extends BaseTestCase {
public IASTFileLocation asFileLocation() {
return this;
}
public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
return null;
}
}
private static final String FN = "filename";
@ -336,8 +339,8 @@ public class LocationMapTests extends BaseTestCase {
public void testIncludes() {
init(DIGITS);
fLocationMap.encounterPoundInclude(0, 0, 0, 0, "n1".toCharArray(), null, true, false, false);
fLocationMap.encounterPoundInclude(0, 1, 3, 16, "n2".toCharArray(), "f2", false , true, false);
fLocationMap.encounterPoundInclude(0, 0, 0, 0, "n1".toCharArray(), null, true, false, false, null);
fLocationMap.encounterPoundInclude(0, 1, 3, 16, "n2".toCharArray(), "f2", false , true, false, null);
IASTPreprocessorIncludeStatement[] includes= fLocationMap.getIncludeDirectives();
assertEquals(2, includes.length);
checkInclude(includes[0], "", "", "n1", "", true, false, FN, 0, 0, 1, 0, 0);
@ -504,21 +507,21 @@ public class LocationMapTests extends BaseTestCase {
ILocationCtx i2= fLocationMap.pushInclusion(6, 7, 8, 9, new CharArray("c1c2c3c4c5"), "pre11", "pre11".toCharArray(), false, false, false);
assertEquals("pre11", fLocationMap.getCurrentFilePath());
fLocationMap.encounteredComment(2,6,true);
fLocationMap.popContext(i2);
fLocationMap.popContext(i2, null);
// add a comment before the include
fLocationMap.encounteredComment(4,6,false);
assertEquals("pre1", fLocationMap.getCurrentFilePath());
fLocationMap.popContext(i1);
fLocationMap.popContext(i1, null);
assertEquals(FN, fLocationMap.getCurrentFilePath());
fLocationMap.popContext(pre2);
fLocationMap.popContext(pre2, null);
assertEquals(FN, fLocationMap.getCurrentFilePath());
// number [36, 46)
ILocationCtx i3= fLocationMap.pushInclusion(0, 2, 4, 6, new CharArray("d1d2d3d4d5"), "pre2", "pre2".toCharArray(), false, false, false);
assertEquals("pre2", fLocationMap.getCurrentFilePath());
fLocationMap.encounteredComment(0,2,true);
fLocationMap.popContext(i3);
fLocationMap.popContext(pre1);
fLocationMap.popContext(i3, null);
fLocationMap.popContext(pre1, null);
assertEquals(FN, fLocationMap.getCurrentFilePath());

View file

@ -21,6 +21,7 @@ import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexLinkage;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.index.IIndexFragment;
import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
@ -100,13 +101,24 @@ public class EmptyIndexFragment implements IIndexFragment {
return 0;
}
@Deprecated
public IIndexFragmentFile getFile(int linkageID, IIndexFileLocation location)
throws CoreException {
return null;
}
public IIndexFragmentFile getFile(int linkageID, IIndexFileLocation location,
ISignificantMacros sigMacros) throws CoreException {
return null;
}
public IIndexFragmentFile[] getFiles(int linkageID, IIndexFileLocation location)
throws CoreException {
return IIndexFragmentFile.EMPTY_ARRAY;
}
public IIndexFragmentFile[] getFiles(IIndexFileLocation location) throws CoreException {
return new IIndexFragmentFile[0];
return IIndexFragmentFile.EMPTY_ARRAY;
}
public long getLastWriteAccess() {

View file

@ -1116,7 +1116,7 @@ public class IndexBugsTests extends BaseTestCase {
// #endif
// #ifndef _h1
// #include "header1.h"
// #include "header1.h" // is inactive, but must be resolved, h1 is not significant
// #endif
// #include "header1.h"
@ -1127,7 +1127,7 @@ public class IndexBugsTests extends BaseTestCase {
// #include "header2.h"
// #ifndef _h1
// #include "header1.h"
// #include "header1.h" // inactive and not resolved because header1.h is internally included.
// #endif
public void testIncludeGuardsOutsideOfHeader_Bug167100() throws Exception {
final IIndexManager indexManager = CCorePlugin.getIndexManager();
@ -1152,13 +1152,26 @@ public class IndexBugsTests extends BaseTestCase {
assertEquals(1, names.length);
assertEquals(f4.getFullPath().toString(), names[0].getFile().getLocation().getFullPath());
IIndexFile idxFile= index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f5));
IIndexFile[] idxFiles= index.getFiles(ILinkage.CPP_LINKAGE_ID,
IndexLocationFactory.getWorkspaceIFL(f2));
assertEquals(1, idxFiles.length);
IIndexFile idxFile= idxFiles[0];
IIndexInclude[] includes= idxFile.getIncludes();
assertEquals(1, includes.length);
assertFalse(includes[0].isActive());
assertTrue(includes[0].isResolved());
assertEquals("{}", idxFile.getSignificantMacros().toString());
idxFiles= index.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f5));
assertEquals(1, idxFiles.length);
idxFile= idxFiles[0];
includes= idxFile.getIncludes();
assertEquals(2, includes.length);
assertTrue(includes[0].isActive());
assertTrue(includes[0].isResolved());
assertFalse(includes[1].isActive());
assertTrue(includes[1].isResolved());
assertFalse(includes[1].isResolved());
} finally {
index.releaseReadLock();
}
@ -1702,17 +1715,18 @@ public class IndexBugsTests extends BaseTestCase {
// int aOK;
// #endif /* A_H_ */
// #ifndef B_H_
// #define B_H_
// #ifndef A_H_
// #include "a.h"
// #endif
//
// #ifndef B_H_
// #define B_H_
// int bOK;
// #endif
// #include "a.h"
public void testStrangeIncludeStrategy_Bug249884() throws Exception {
public void _testStrangeIncludeStrategy_Bug249884() throws Exception {
// TODO(197989) Should work again once the significant macro dictionary is used.
String[] contents= getContentsForTest(3);
final IIndexManager indexManager = CCorePlugin.getIndexManager();
IFile ah= TestSourceReader.createFile(fCProject.getProject(), "a.h", contents[0]);
@ -2423,4 +2437,4 @@ public class IndexBugsTests extends BaseTestCase {
index.releaseReadLock();
}
}
}
}

View file

@ -37,6 +37,7 @@ import org.eclipse.cdt.internal.core.CCoreInternals;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
import org.eclipse.cdt.internal.core.pdom.CModelListener;
import org.eclipse.cdt.internal.core.pdom.PDOMManager;
import org.eclipse.cdt.internal.core.pdom.indexer.AbstractPDOMIndexer;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ILogListener;
@ -66,6 +67,7 @@ public class BaseTestCase extends TestCase {
CPPASTNameBase.sAllowRecursionBindings= false;
CPPASTNameBase.sAllowNameComputation= false;
CModelListener.sSuppressUpdateOfLastRecentlyUsed= true;
AbstractPDOMIndexer.noFilesUpFront= true;
}
@Override
@ -294,4 +296,4 @@ public class BaseTestCase extends TestCase {
}
assertTrue(indexManager.joinIndexer(10000, npm()));
}
}
}

View file

@ -286,12 +286,12 @@ public class TestSourceReader {
Assert.assertTrue(CCorePlugin.getIndexManager().joinIndexer(timeLeft, new NullProgressMonitor()));
index.acquireReadLock();
try {
IIndexFile pfile= index.getFile(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
if (pfile != null && pfile.getTimestamp() >= file.getLocalTimeStamp()) {
IIndexFile[] files= index.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
if (files.length > 0 && areAllFilesNotOlderThan(files, file.getLocalTimeStamp())) {
return;
}
pfile= index.getFile(ILinkage.C_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
if (pfile != null && pfile.getTimestamp() >= file.getLocalTimeStamp()) {
files= index.getFiles(ILinkage.C_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(file));
if (files.length > 0 && areAllFilesNotOlderThan(files, file.getLocalTimeStamp())) {
return;
}
} finally {
@ -304,7 +304,16 @@ public class TestSourceReader {
Assert.fail("Indexing " + file.getFullPath() + " did not complete in time!");
}
public static IASTTranslationUnit createIndexBasedAST(IIndex index, ICProject project, IFile file) throws CModelException, CoreException {
private static boolean areAllFilesNotOlderThan(IIndexFile[] files, long timestamp) throws CoreException {
for (IIndexFile file : files) {
if (file.getTimestamp() < timestamp) {
return false;
}
}
return true;
}
public static IASTTranslationUnit createIndexBasedAST(IIndex index, ICProject project, IFile file) throws CModelException, CoreException {
ICElement elem= project.findElement(file.getFullPath());
if (elem instanceof ITranslationUnit) {
ITranslationUnit tu= (ITranslationUnit) elem;

View file

@ -12,6 +12,9 @@ org.eclipse.cdt.core/debug/parser/exceptions=false
# Reports scanner activity
org.eclipse.cdt.core/debug/scanner=false
# Reports scanner activity
org.eclipse.cdt.core/debug/scanner/missingIncludeGuards=false
# Reports search activity
org.eclipse.cdt.core/debug/search=false

View file

@ -839,30 +839,31 @@ public class TranslationUnit extends Openable implements ITranslationUnit {
return fileContentsProvider;
}
private static int[] CTX_LINKAGES= {ILinkage.CPP_LINKAGE_ID, ILinkage.C_LINKAGE_ID};
private static final int[] CTX_LINKAGES= { ILinkage.CPP_LINKAGE_ID, ILinkage.C_LINKAGE_ID };
public ITranslationUnit getSourceContextTU(IIndex index, int style) {
if (index != null && (style & AST_CONFIGURE_USING_SOURCE_CONTEXT) != 0) {
try {
fLanguageOfContext= null;
for (int element : CTX_LINKAGES) {
for (int linkageID : CTX_LINKAGES) {
IIndexFile context= null;
final IIndexFileLocation ifl = IndexLocationFactory.getIFL(this);
if (ifl != null) {
IIndexFile indexFile= index.getFile(element, ifl);
if (indexFile != null) {
// bug 199412, when a source-file includes itself the context may recurse.
HashSet<IIndexFile> visited= new HashSet<IIndexFile>();
visited.add(indexFile);
indexFile = getParsedInContext(indexFile);
while (indexFile != null && visited.add(indexFile)) {
context= indexFile;
indexFile= getParsedInContext(indexFile);
for (IIndexFile indexFile : index.getFiles(linkageID, ifl)) {
if (indexFile != null) {
// Bug 199412, when a source-file includes itself the context may recurse.
HashSet<IIndexFile> visited= new HashSet<IIndexFile>();
visited.add(indexFile);
indexFile = getParsedInContext(indexFile);
while (indexFile != null && visited.add(indexFile)) {
context= indexFile;
indexFile= getParsedInContext(indexFile);
}
}
}
if (context != null) {
ITranslationUnit tu= CoreModelUtil.findTranslationUnitForLocation(context.getLocation(), getCProject());
if (tu != null && tu.isSourceUnit()) {
return tu;
if (context != null) {
ITranslationUnit tu= CoreModelUtil.findTranslationUnitForLocation(context.getLocation(), getCProject());
if (tu != null && tu.isSourceUnit()) {
return tu;
}
}
}
}

View file

@ -50,4 +50,13 @@ public interface IASTFileLocation extends IASTNodeLocation {
* @return int representing line number or <code>0</code> if not applicable
*/
public int getEndingLineNumber();
/**
* Returns the inclusion statement that included this file, or <code>null</code> for
* a top-level file.
* Also <code>null</code> when the file location does not belong to an AST node, e.g.
* if it is obtained from a name in the index.
* @since 5.4
*/
public IASTPreprocessorIncludeStatement getContextInclusionStatement();
}

View file

@ -6,20 +6,19 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast;
/**
* This interface represent a preprocessor #include statement.
*
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface IASTPreprocessorIncludeStatement extends
IASTPreprocessorStatement {
public interface IASTPreprocessorIncludeStatement extends IASTPreprocessorStatement, IFileNomination {
/**
* <code>INCLUDE_NAME</code> describes the relationship between an include directive and
* it's name.

View file

@ -16,6 +16,7 @@ import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.core.runtime.IAdaptable;
@ -28,7 +29,7 @@ import org.eclipse.core.runtime.IAdaptable;
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface IASTTranslationUnit extends IASTDeclarationListOwner, IAdaptable {
public interface IASTTranslationUnit extends IASTDeclarationListOwner, IFileNomination, IAdaptable {
/**
* <code>OWNED_DECLARATION</code> represents the relationship between an <code>IASTTranslationUnit</code> and
@ -343,4 +344,16 @@ public interface IASTTranslationUnit extends IASTDeclarationListOwner, IAdaptabl
* @since 5.3
*/
public ITranslationUnit getOriginatingTranslationUnit();
/**
* @since 5.4
* @noreference This method is not intended to be referenced by clients.
*/
public void setSignificantMacros(ISignificantMacros sigMacros);
/**
* @since 5.4
* @noreference This method is not intended to be referenced by clients.
*/
public void setPragmaOnceSemantics(boolean value);
}

View file

@ -0,0 +1,45 @@
/*******************************************************************************
* Copyright (c) 2011 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.core.dom.ast;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.core.runtime.CoreException;
/**
* Interface for constructs that nominate a file for an AST:
* {@link IASTTranslationUnit}, {@link IASTPreprocessorIncludeStatement}, {@link IIndexFile}.
* @since 5.4
* @noimplement This interface is not intended to be implemented by clients.
* @noextend This interface is not intended to be extended by clients.
*/
public interface IFileNomination {
/**
* Returns macros relevant to parsing of the file included by this include statement and their
* definitions at the point of the include.
* <p>
* This method should only be called after the included file has been parsed. The method will
* return {@link ISignificantMacros#NONE}</code> if it is called prematurely.
* @throws CoreException
*/
public ISignificantMacros getSignificantMacros() throws CoreException;
/**
* Returns whether pragma once semantics has been detected when parsing the translation unit.
*/
public boolean hasPragmaOnceSemantics() throws CoreException;
/**
* @return
*/
public boolean isComplete();
}

View file

@ -19,6 +19,7 @@ import java.util.regex.Pattern;
import org.eclipse.cdt.core.dom.IName;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
@ -133,16 +134,53 @@ public interface IIndex {
public long getLastWriteAccess();
/**
* Returns the file-object for the given location and linkage or returns
* <code>null</code> if the file was not indexed in this linkage.
* Returns the file object for the given location and linkage or <code>null</code> if the file
* was not indexed in this linkage.
* <p>
* When a header file is stored in the index in multiple variants for different sets of macro
* definitions, this method will return an arbitrary one of these variants.
* @param location an IIndexFileLocation representing the location of the file
* @return the file in the index or <code>null</code>
* @throws CoreException
* @deprecated Use {@link #getFile(int, IIndexFileLocation, ISignificantMacros)} or
* {@link #getFiles(int, IIndexFileLocation)}.
*/
@Deprecated
public IIndexFile getFile(int linkageID, IIndexFileLocation location) throws CoreException;
/**
* Returns the file-objects for the given location in any linkage.
* Returns the file for the given location, linkage, and significant macros
* May return <code>null</code>, if no such file exists.
*
* @param linkageID the id of the linkage in which the file has been parsed.
* @param location the IIndexFileLocation representing the location of the file
* @param macroDictionary The names and definitions of the macros used to disambiguate between
* variants of the file contents corresponding to different inclusion points.
* @return the file for the location, or <code>null</code> if the file is not present in
* the index
* @throws CoreException
* @since 5.4
*/
IIndexFile getFile(int linkageID, IIndexFileLocation location, ISignificantMacros significantMacros)
throws CoreException;
/**
* Returns the file objects for the given location and linkage.
* Multiple files are returned when a header file is stored in the index in multiple variants
* for different sets of macro definitions.
* This method may only return files that are actually managed by this fragment.
* This method returns files without content, also.
*
* @param linkageID the id of the linkage in which the file has been parsed.
* @param location the IIndexFileLocation representing the location of the file
* @return the files for the location and the linkage.
* @throws CoreException
* @since 5.4
*/
IIndexFile[] getFiles(int linkageID, IIndexFileLocation location) throws CoreException;
/**
* Returns the file objects for the given location in any linkage.
* @param location an IIndexFileLocation representing the location of the file
* @return an array of file-objects.
* @throws CoreException

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2011 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
@ -8,10 +8,13 @@
* Contributors:
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.core.index;
import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.core.runtime.CoreException;
/**
@ -22,7 +25,7 @@ import org.eclipse.core.runtime.CoreException;
*
* @since 4.0
*/
public interface IIndexFile {
public interface IIndexFile extends IFileNomination {
IIndexFile[] EMPTY_FILE_ARRAY = {};
/**
@ -32,6 +35,13 @@ public interface IIndexFile {
*/
IIndexFileLocation getLocation() throws CoreException;
/**
* Returns the significant macros for this version of the file.
* @throws CoreException
* @since 5.4
*/
ISignificantMacros getSignificantMacros() throws CoreException;
/**
* Returns all includes found in this file.
* @return an array of all includes found in this file
@ -69,11 +79,9 @@ public interface IIndexFile {
long getContentsHash() throws CoreException;
/**
* Returns the hash-code of the scanner configuration that was used to parse the file.
* <code>0</code> will be returned in case the hash-code is unknown.
* @return the hash-code of the scanner configuration or <code>0</code>.
* @throws CoreException
* @deprecated Returns 0.
*/
@Deprecated
int getScannerConfigurationHashcode() throws CoreException;
/**
@ -93,7 +101,14 @@ public interface IIndexFile {
* Returns the include that was used to parse this file, may be <code>null</code>.
*/
IIndexInclude getParsedInContext() throws CoreException;
/**
* Returns <code>true</code> if the file is a header with #pragma once statement or an include
* guard, or if it is a source file.
* @since 5.4
*/
public boolean hasPragmaOnceSemantics() throws CoreException;
/**
* Returns the id of the linkage this file was parsed in.
* @since 5.0

View file

@ -54,4 +54,10 @@ public interface IIndexFileSet {
* @noreference This method is not intended to be referenced by clients.
*/
void add(IIndexFile indexFile);
/**
* Removes a file from this set.
* @noreference This method is not intended to be referenced by clients.
*/
void remove(IIndexFile indexFile);
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2008 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2011 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
@ -10,12 +10,39 @@
*******************************************************************************/
package org.eclipse.cdt.core.parser;
import org.eclipse.cdt.internal.core.dom.parser.ParserLogServiceWrapper;
public abstract class AbstractParserLogService implements IParserLogService {
/**
* @since 5.4
*/
public static AbstractParserLogService convert(IParserLogService log) {
if (log instanceof AbstractParserLogService)
return (AbstractParserLogService) log;
return new ParserLogServiceWrapper(log);
}
public void traceLog(String message) {
}
/**
* @param traceOption an option as defined in the .options file.
* @since 5.4
*/
public boolean isTracing(String traceOption) {
return isTracing();
}
/**
* @param traceOption an option as defined in the .options file.
* @since 5.4
*/
public void traceLog(String traceOption, String message) {
traceLog(message);
}
public void errorLog(String message) {
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2010 IBM Corporation and others.
* Copyright (c) 2000, 2011 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
@ -323,6 +323,12 @@ public interface IProblem
*/
public final static int PREPROCESSOR_POUND_WARNING = PREPROCESSOR_RELATED | 0x00E;
/**
* Maximum inclusion depth is exceeded
* @since 5.4
*/
public final static int PREPROCESSOR_EXCEEDS_MAXIMUM_INCLUSION_DEPTH= PREPROCESSOR_RELATED | 0x00F;
/**
* Syntax error, detected by the parser.
*/

View file

@ -0,0 +1,58 @@
/*******************************************************************************
* Copyright (c) 2011 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.core.parser;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.parser.scanner.SignificantMacros;
/**
* Significant macros describe the conditions under which the preprocessor selects
* the same active code branches in a file.
* @since 5.4
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface ISignificantMacros {
interface IVisitor {
/**
* Returns whether to continue the visit.
*/
boolean visitDefined(char[] macro);
/**
* Returns whether to continue the visit.
*/
boolean visitUndefined(char[] macro);
/**
* Returns whether to continue the visit.
*/
boolean visitValue(char[] macro, char[] value);
/**
* Returns whether to continue the visit.
*/
boolean visitIncluded(char[] path);
}
ISignificantMacros NONE = new SignificantMacros(CharArrayUtils.EMPTY);
/**
* Returns whether visitor continued its visit till the end.
*/
boolean accept(IVisitor visitor);
/**
* Returns the significant macros encoded as an array of characters.
*/
char[] encode();
}

View file

@ -19,8 +19,8 @@ import java.util.List;
/**
* @author Doug Schaefer
*/
public class CharArrayObjectMap extends CharTable {
public static final CharArrayObjectMap EMPTY_MAP = new CharArrayObjectMap(0) {
public class CharArrayObjectMap <T> extends CharTable {
public static final CharArrayObjectMap<Object> EMPTY_MAP = new CharArrayObjectMap<Object>(0) {
@Override
public Object clone() { return this; }
@Override
@ -30,6 +30,14 @@ public class CharArrayObjectMap extends CharTable {
throw new UnsupportedOperationException();
}
};
/**
* @since 5.4
*/
@SuppressWarnings("unchecked")
public static <T> CharArrayObjectMap<T> emptyMap() {
return (CharArrayObjectMap<T>) EMPTY_MAP;
}
private Object[] valueTable;
@ -38,40 +46,44 @@ public class CharArrayObjectMap extends CharTable {
valueTable = new Object[capacity()];
}
public Object put(char[] key, int start, int length, Object value) {
public T put(char[] key, int start, int length, T value) {
int i = addIndex(key, start, length);
Object oldvalue = valueTable[i];
@SuppressWarnings("unchecked")
T oldvalue = (T) valueTable[i];
valueTable[i] = value;
return oldvalue;
}
final public Object put(char[] key, Object value) {
final public T put(char[] key, T value) {
return put(key, 0, key.length, value);
}
final public Object get(char[] key, int start, int length) {
@SuppressWarnings("unchecked")
final public T get(char[] key, int start, int length) {
int i = lookup(key, start, length);
if (i >= 0)
return valueTable[i];
return (T) valueTable[i];
return null;
}
final public Object get(char[] key) {
final public T get(char[] key) {
return get(key, 0, key.length);
}
final public Object getAt(int i) {
@SuppressWarnings("unchecked")
final public T getAt(int i) {
if (i < 0 || i > currEntry)
return null;
return valueTable[i];
return (T) valueTable[i];
}
final public Object remove(char[] key, int start, int length) {
final public T remove(char[] key, int start, int length) {
int i = lookup(key, start, length);
if (i < 0)
return null;
Object value = valueTable[i];
@SuppressWarnings("unchecked")
T value = (T) valueTable[i];
if (i < currEntry)
System.arraycopy(valueTable, i + 1, valueTable, i, currEntry - i);
@ -85,7 +97,8 @@ public class CharArrayObjectMap extends CharTable {
@Override
public Object clone() {
CharArrayObjectMap newTable = (CharArrayObjectMap) super.clone();
@SuppressWarnings("unchecked")
CharArrayObjectMap<T> newTable = (CharArrayObjectMap<T>) super.clone();
newTable.valueTable = new Object[capacity()];
System.arraycopy(valueTable, 0, newTable.valueTable, 0, valueTable.length);
@ -149,4 +162,5 @@ public class CharArrayObjectMap extends CharTable {
System.arraycopy(valueTable, 0, values, 0, values.length);
return values;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2011 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
@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
@ -71,7 +72,7 @@ public class ASTInternal {
}
}
public static String getDeclaredInSourceFileOnly(IBinding binding, boolean requireDefinition, PDOMBinding nonLocal) {
public static IASTNode getDeclaredInSourceFileOnly(IBinding binding, boolean requireDefinition, PDOMBinding nonLocal) {
IASTNode[] decls;
IASTNode def;
if (binding instanceof ICPPInternalBinding) {
@ -88,18 +89,19 @@ public class ASTInternal {
if (requireDefinition && def == null) {
return null;
}
String filePath= null;
IASTNode result= null;
if (def != null) {
if ((filePath= isPartOfSource(filePath, def)) == null) {
if (!isPartOfSource(def))
return null;
}
result= def;
}
if (decls != null) {
for (final IASTNode node : decls) {
if (node != null) {
if ((filePath= isPartOfSource(filePath, node)) == null) {
if (!isPartOfSource(node))
return null;
if ((result= resolveConflict(result, node)) == null)
return null;
}
}
}
}
@ -110,23 +112,29 @@ public class ASTInternal {
} catch (CoreException e) {
}
}
return filePath;
return result;
}
private static String isPartOfSource(String filePath, IASTNode decl) {
if (decl instanceof ASTNode) {
if (((ASTNode) decl).isPartOfSourceFile()) {
if (filePath == null)
return decl.getContainingFilename();
if (filePath.equals(decl.getContainingFilename()))
return filePath;
}
}
return null;
private static boolean isPartOfSource(IASTNode decl) {
return decl instanceof ASTNode && ((ASTNode) decl).isPartOfSourceFile();
}
public static String getDeclaredInOneFileOnly(IBinding binding) {
private static IASTNode resolveConflict(IASTNode n1, IASTNode n2) {
if (n1 == null)
return n2;
IASTFileLocation loc1= n1.getFileLocation();
if (loc1 == null)
return n2;
IASTFileLocation loc2= n2.getFileLocation();
if (loc2 != null && loc1.getContextInclusionStatement() != loc2.getContextInclusionStatement())
return null;
return n1;
}
public static IASTNode getDeclaredInOneFileOnly(IBinding binding) {
IASTNode[] decls;
IASTNode def;
if (binding instanceof ICPPInternalBinding) {
@ -140,23 +148,19 @@ public class ASTInternal {
} else {
return null;
}
String filePath= null;
IASTNode result= null;
if (def != null) {
filePath= def.getContainingFilename();
result= def;
}
if (decls != null) {
for (final IASTNode node : decls) {
if (node != null) {
final String fn = node.getContainingFilename();
if (filePath == null) {
filePath= fn;
} else if (!filePath.equals(fn)) {
if ((result= resolveConflict(result, node)) == null)
return null;
}
}
}
}
return filePath;
return result;
}
public static void addDeclaration(IBinding b, IASTNode declaration) {

View file

@ -37,6 +37,7 @@ import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.index.IndexBasedFileContentProvider;
import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
@ -71,6 +72,10 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
private INodeFactory fNodeFactory;
private boolean fForContentAssist;
private ITranslationUnit fOriginatingTranslationUnit;
private ISignificantMacros fSignificantMacros= ISignificantMacros.NONE;
private boolean fPragmaOnceSemantics;
private boolean fComplete;
/** The semaphore controlling exclusive access to the AST. */
private final Semaphore fSemaphore= new Semaphore(1);
@ -367,6 +372,7 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
if (fIndexFileSet != null) {
List<IIndexFile> files= fileContent.getFilesIncluded();
for (IIndexFile indexFile : files) {
fASTFileSet.remove(indexFile);
fIndexFileSet.add(indexFile);
}
}
@ -376,13 +382,14 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
return fIndexFileSet;
}
public void replacingFile(InternalFileContentProvider provider, InternalFileContent fc) {
public void parsingFile(InternalFileContentProvider provider, InternalFileContent fc) {
if (fASTFileSet != null) {
if (provider instanceof IndexBasedFileContentProvider) {
try {
IIndexFile file= ((IndexBasedFileContentProvider) provider).findIndexFile(fc);
if (file != null) {
fASTFileSet.add(file);
for (IIndexFile file : ((IndexBasedFileContentProvider) provider).findIndexFiles(fc)) {
if (!fIndexFileSet.contains(file)) {
fASTFileSet.add(file);
}
}
} catch (CoreException e) {
// Ignore, tracking of replaced files fails.
@ -450,6 +457,30 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
this.fOriginatingTranslationUnit = tu;
}
public ISignificantMacros getSignificantMacros() {
return fSignificantMacros;
}
public void setSignificantMacros(ISignificantMacros sigMacros) {
assertNotFrozen();
if (sigMacros != null)
fSignificantMacros= sigMacros;
fComplete= true;
}
public boolean hasPragmaOnceSemantics() {
return fPragmaOnceSemantics;
}
public void setPragmaOnceSemantics(boolean value) {
assertNotFrozen();
fPragmaOnceSemantics= value;
}
public boolean isComplete() {
return fComplete;
}
/**
* Starts exclusive access
* @throws InterruptedException

View file

@ -200,7 +200,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
private final INodeFactory nodeFactory;
private boolean fActiveCode= true;
private int fEndOffset= -1;
protected AbstractGNUSourceCodeParser(IScanner scanner,
IParserLogService logService, ParserMode parserMode,
@ -435,7 +434,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
try {
return LA(i);
} catch (EndOfFileException e) {
fEndOffset= e.getEndOffset();
return null;
}
}
@ -456,7 +454,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
try {
return LT(i);
} catch (EndOfFileException e) {
fEndOffset= e.getEndOffset();
return 0;
}
}
@ -1281,9 +1278,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
protected void parseTranslationUnit() {
final IASTTranslationUnit tu= getTranslationUnit();
declarationList(tu, DeclarationOptions.GLOBAL, false, 0);
// Bug 3033152: getEndOffset() is computed off the last node and ignores trailing macros.
final int length= Math.max(getEndOffset(), fEndOffset);
((ASTNode) tu).setLength(length);
}
protected final void declarationListInBraces(final IASTDeclarationListOwner tu, int offset, DeclarationOptions options) throws EndOfFileException, BacktrackException {
@ -1356,7 +1350,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
IASTDeclaration declaration= skipProblemDeclaration(offset);
addDeclaration(tu, declaration, active);
if (!e.endsInactiveCode()) {
fEndOffset= e.getEndOffset();
break;
}
} finally {

View file

@ -227,7 +227,7 @@ public class TemplateArgumentDeduction {
ICPPTemplateInstance pInst = (ICPPTemplateInstance) pcheck;
ICPPClassTemplate pTemplate= getPrimaryTemplate(pInst);
if (pTemplate != null) {
ICPPClassType aInst= findBaseInstance((ICPPClassType) argcheck, pTemplate, CPPSemantics.MAX_INHERITANCE_DEPTH);
ICPPClassType aInst= findBaseInstance((ICPPClassType) argcheck, pTemplate);
if (aInst != null && aInst != argcheck) {
par= pcheck;
arg= aInst;
@ -467,10 +467,15 @@ public class TemplateArgumentDeduction {
return result.toArray(new ICPPTemplateArgument[result.size()]);
}
/**
* 14.8.2.1.3 If P is a class and has the form template-id, then A can be a derived class of the deduced A.
*/
private static ICPPClassType findBaseInstance(ICPPClassType a, ICPPClassTemplate pTemplate, int maxdepth) throws DOMException {
private static ICPPClassType findBaseInstance(ICPPClassType a, ICPPClassTemplate pTemplate) throws DOMException {
return findBaseInstance(a, pTemplate, CPPSemantics.MAX_INHERITANCE_DEPTH, new HashSet<Object>());
}
private static ICPPClassType findBaseInstance(ICPPClassType a, ICPPClassTemplate pTemplate, int maxdepth, HashSet<Object> handled) throws DOMException {
if (a instanceof ICPPTemplateInstance) {
final ICPPTemplateInstance inst = (ICPPTemplateInstance) a;
ICPPClassTemplate tmpl= getPrimaryTemplate(inst);
@ -480,8 +485,8 @@ public class TemplateArgumentDeduction {
if (maxdepth-- > 0) {
for (ICPPBase cppBase : a.getBases()) {
IBinding base= cppBase.getBaseClass();
if (base instanceof ICPPClassType) {
final ICPPClassType inst= findBaseInstance((ICPPClassType) base, pTemplate, maxdepth);
if (base instanceof ICPPClassType && handled.add(base)) {
final ICPPClassType inst= findBaseInstance((ICPPClassType) base, pTemplate, maxdepth, handled);
if (inst != null)
return inst;
}

View file

@ -17,13 +17,13 @@ package org.eclipse.cdt.internal.core.index;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import org.eclipse.cdt.core.CCorePlugin;
@ -42,6 +42,7 @@ import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.index.composite.CompositingNotImplementedError;
import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory;
@ -208,6 +209,7 @@ public class CIndex implements IIndex {
return findNames(binding, FIND_REFERENCES);
}
@Deprecated
public IIndexFile getFile(int linkageID, IIndexFileLocation location) throws CoreException {
for (int i = 0; i < fPrimaryFragmentCount; i++) {
IIndexFragmentFile candidate= fFragments[i].getFile(linkageID, location);
@ -218,19 +220,53 @@ public class CIndex implements IIndex {
return null;
}
public IIndexFile getFile(int linkageID, IIndexFileLocation location,
ISignificantMacros significantMacros) throws CoreException {
for (int i = 0; i < fPrimaryFragmentCount; i++) {
IIndexFragmentFile candidate= fFragments[i].getFile(linkageID, location, significantMacros);
if (candidate != null && candidate.hasContent()) {
return candidate;
}
}
return null;
}
public IIndexFile[] getFiles(int linkageID, IIndexFileLocation location) throws CoreException {
if (location == null) {
return IIndexFile.EMPTY_FILE_ARRAY;
}
Set<ISignificantMacros> handled = new HashSet<ISignificantMacros>();
ArrayList<IIndexFragmentFile> result= new ArrayList<IIndexFragmentFile>();
for (int i = 0; i < fPrimaryFragmentCount; i++) {
IIndexFragmentFile[] candidates= fFragments[i].getFiles(linkageID, location);
for (IIndexFragmentFile candidate : candidates) {
if (candidate.hasContent()) {
ISignificantMacros macroKey = candidate.getSignificantMacros();
if (handled.add(macroKey)) {
result.add(candidate);
}
}
}
}
if (result.isEmpty()) {
return IIndexFile.EMPTY_FILE_ARRAY;
}
return result.toArray(new IIndexFile[result.size()]);
}
public IIndexFile[] getFiles(IIndexFileLocation location) throws CoreException {
if (location == null) {
return IIndexFile.EMPTY_FILE_ARRAY;
}
Set<FileContentKey> keys = new HashSet<FileContentKey>();
ArrayList<IIndexFragmentFile> result= new ArrayList<IIndexFragmentFile>();
BitSet linkages= new BitSet();
for (int i = 0; i < fPrimaryFragmentCount; i++) {
IIndexFragmentFile[] candidates= fFragments[i].getFiles(location);
for (IIndexFragmentFile candidate : candidates) {
int linkage= candidate.getLinkageID();
if (!linkages.get(linkage) && candidate.hasContent()) {
result.add(candidate);
linkages.set(linkage);
if (candidate.hasContent()) {
if (keys.add(new FileContentKey(candidate.getLinkageID(), candidate.getLocation(), candidate.getSignificantMacros()))) {
result.add(candidate);
}
}
}
}
@ -241,16 +277,16 @@ public class CIndex implements IIndex {
}
public IIndexFile resolveInclude(IIndexInclude include) throws CoreException {
if (!include.isResolved()) {
return null;
}
IIndexFragmentInclude fragmentInclude = (IIndexFragmentInclude) include;
IIndexFragmentFile result= fragmentInclude.getIncludes();
if (result != null && result.hasContent()) {
if (result == null)
return null;
if (result.hasContent()) {
return result;
}
return getFile(include.getIncludedBy().getLinkageID(), include.getIncludesLocation());
return getFile(result.getLinkageID(), result.getLocation(), result.getSignificantMacros());
}
public IIndexInclude[] findIncludedBy(IIndexFile file) throws CoreException {
@ -289,7 +325,6 @@ public class CIndex implements IIndex {
findIncludedBy(nextLevel, out, depth, handled);
}
public IIndexInclude[] findIncludes(IIndexFile file) throws CoreException {
return findIncludes(file, 0);
}

View file

@ -29,6 +29,7 @@ import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
@ -54,10 +55,20 @@ final public class EmptyCIndex implements IIndex {
return IIndexFragmentName.EMPTY_NAME_ARRAY;
}
@Deprecated
public IIndexFile getFile(int linkageID, IIndexFileLocation location) {
return null;
}
public IIndexFile getFile(int linkageID, IIndexFileLocation location,
ISignificantMacros significantFiles) throws CoreException {
return null;
}
public IIndexFile[] getFiles(int linkageID, IIndexFileLocation location) throws CoreException {
return IIndexFile.EMPTY_FILE_ARRAY;
}
public IIndexFile[] getFiles(IIndexFileLocation location) {
return IIndexFile.EMPTY_FILE_ARRAY;
}

View file

@ -0,0 +1,77 @@
/*******************************************************************************
* Copyright (c) 2011 Google, 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.parser.ISignificantMacros;
/**
* A key that uniquely determines the preprocessed contents of a file.
*/
public class FileContentKey {
private final int linkageID;
private final IIndexFileLocation location;
private final ISignificantMacros significantMacros;
/**
* Creates a file content key.
* @param location the file location.
*/
public FileContentKey(int linkageID, IIndexFileLocation location, ISignificantMacros sigMacros) {
this.linkageID= linkageID;
this.location = location;
this.significantMacros = sigMacros;
}
public int getLinkageID() {
return linkageID;
}
public IIndexFileLocation getLocation() {
return location;
}
public ISignificantMacros getSignificantMacros() {
return significantMacros;
}
@Override
public int hashCode() {
return (linkageID + location.hashCode() * 31) * 31 + significantMacros.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
FileContentKey other = (FileContentKey) obj;
if (linkageID != other.linkageID)
return false;
if (!location.equals(other.location))
return false;
if (!significantMacros.equals(other.significantMacros))
return false;
return true;
}
@SuppressWarnings("nls")
@Override
public String toString() {
return linkageID + ": " + location.getURI().toString() + "[" + significantMacros.hashCode() + "]";
}
}

View file

@ -23,6 +23,7 @@ import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexLinkage;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
@ -92,14 +93,55 @@ public interface IIndexFragment {
* May return <code>null</code>, if no such file exists.
* This method may only return files that are actually managed by this fragment.
* This method returns files without content, also.
* <p>
* When a header file is stored in the index in multiple variants for different sets of macro
* definitions, this method will return an arbitrary one of these variants.
*
* @param linkageID the id of the linkage in which the file has been parsed.
* @param location the IIndexFileLocation representing the location of the file
* @return the file for the location, or <code>null</code> if the file is not present in
* the index
* @throws CoreException
* @deprecated Use {@link #getFile(int, IIndexFileLocation, ISignificantMacros)} or
* {@link #getFiles(int, IIndexFileLocation)}.
*/
@Deprecated
IIndexFragmentFile getFile(int linkageID, IIndexFileLocation location) throws CoreException;
/**
* Returns the file for the given location, linkage, and a set of macro definitions.
* May return <code>null</code>, if no such file exists.
* This method may only return files that are actually managed by this fragment.
* This method returns files without content, also.
*
* @param linkageID the id of the linkage in which the file has been parsed.
* @param location the IIndexFileLocation representing the location of the file
* @param macroDictionary The names and definitions of the macros used to disambiguate between
* variants of the file contents corresponding to different inclusion points.
* @return the file for the location, or <code>null</code> if the file is not present in
* the index
* @throws CoreException
*/
IIndexFragmentFile getFile(int linkageID, IIndexFileLocation location,
ISignificantMacros significantMacros) throws CoreException;
/**
* Returns the files for the given location and linkage.
* Multiple files are returned when a header file is stored in the index in multiple variants
* for different sets of macro definitions.
* This method may only return files that are actually managed by this fragment.
* This method returns files without content, also.
* <p>
* When a header file is stored in the index in multiple variants for different sets of macro
* definitions, this method will return an arbitrary one of these variants.
*
* @param linkageID the id of the linkage in which the file has been parsed.
* @param location the IIndexFileLocation representing the location of the file
* @return the files for the location and the linkage.
* @throws CoreException
*/
IIndexFragmentFile[] getFiles(int linkageID, IIndexFileLocation location) throws CoreException;
/**
* Returns the files in all linkages for the given location.
* This method may only return files that are actually managed by this fragment.

View file

@ -1,15 +1,15 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2011 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
* Andrew Ferguson (Symbian)
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
import org.eclipse.cdt.core.index.IIndexFile;
@ -33,19 +33,18 @@ public interface IIndexFragmentFile extends IIndexFile {
*/
void setContentsHash(long hash) throws CoreException;
/**
* Sets the hash-code of the scanner configuration.
* @param hashcode a hash-code or <code>0</code> if it is unknown.
* @throws CoreException
*/
void setScannerConfigurationHashcode(int hashcode) throws CoreException;
/**
* Sets the hash-code of the file encoding.
* @param hashcode a hash-code or <code>0</code> if it is unknown.
*/
void setEncodingHashcode(int hashcode) throws CoreException;
/**
* Sets the flag that determines whether the file is a header with #pragma once statement
* or an include guard, or it is a source file and parsed only once because of that.
*/
void setPragmaOnceSemantics(boolean value) throws CoreException;
/**
* Returns whether this file contains content in its
* associated fragment. Files without content are inserted to track includes.

View file

@ -25,6 +25,11 @@ public interface IIndexFragmentFileSet {
*/
void add(IIndexFragmentFile fragFile);
/**
* Removes the fragment file from the file-set.
*/
void remove(IIndexFragmentFile fragFile);
/**
* Returns whether the file set contains the given file.
*/

View file

@ -6,9 +6,9 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
@ -20,6 +20,7 @@ import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
import org.eclipse.core.runtime.CoreException;
@ -45,14 +46,15 @@ public interface IWritableIndex extends IIndex {
boolean isWritableFile(IIndexFile file);
/**
* Returns a writable file for the given location and linkage, or null. This method
* returns file-objects without content, also.
* Returns a writable file for the given location, linkage, and the set of macro definitions,
* or null. This method returns file objects without content, also.
*/
IIndexFragmentFile getWritableFile(int linkageID, IIndexFileLocation location) throws CoreException;
IIndexFragmentFile getWritableFile(int linkageID, IIndexFileLocation location,
ISignificantMacros macroDictionary) throws CoreException;
/**
* Returns the writable files for the given location in any linkage. This method
* returns file-objects without content, also.
* returns file objects without content, also.
*/
IIndexFragmentFile[] getWritableFiles(IIndexFileLocation location) throws CoreException;
@ -66,17 +68,24 @@ public interface IWritableIndex extends IIndex {
/**
* Creates a file object for the given location or returns an existing one.
* @param linkageID the id of the linkage in which the file has been parsed.
* @param location the IIndexFileLocation representing the location of the file
* @param macroDictionary The names and definitions of the macros used to disambiguate between
* variants of the file contents corresponding to different inclusion points.
* @return A created or an existing file.
*/
IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException;
IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location,
ISignificantMacros macroDictionary) throws CoreException;
/**
* Creates a uncommitted file object for the given location.
*/
IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location) throws CoreException;
IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location,
ISignificantMacros macroDictionary) throws CoreException;
/**
* Makes an uncommitted file that was created earlier by calling
* {@link #addUncommittedFile(int, IIndexFileLocation)} method visible in the index.
* {@link #addUncommittedFile(int, IIndexFileLocation, ISignificantMacros)} method visible in the index.
*
* @return The file that was updated.
* @throws CoreException

View file

@ -6,9 +6,9 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
******************************************************************************/
package org.eclipse.cdt.internal.core.index;
@ -18,6 +18,7 @@ import java.util.Collection;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
@ -44,23 +45,27 @@ public interface IWritableIndexFragment extends IIndexFragment {
/**
* Creates a file object for the given location and linkage or returns an existing one.
* @param fileLocation an IIndexFileLocation representing the location of the file.
* @param sigMacros the macro definitions at the inclusion point.
* @return the existing IIndexFragmentFile for this location, or a newly created one.
* @throws CoreException
*/
IIndexFragmentFile addFile(int linkageID, IIndexFileLocation fileLocation) throws CoreException;
IIndexFragmentFile addFile(int linkageID, IIndexFileLocation fileLocation,
ISignificantMacros sigMacros) throws CoreException;
/**
* Creates a file object for the given location and linkage. The created file object is not added to
* the file index.
* @param fileLocation an IIndexFileLocation representing the location of the file.
* @param sigMacros the macro definitions at the inclusion point.
* @return a newly created IIndexFragmentFile.
* @throws CoreException
*/
IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation fileLocation) throws CoreException;
IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation fileLocation,
ISignificantMacros sigMacros) throws CoreException;
/**
* Makes an uncommitted file that was created earlier by calling
* {@link #addUncommittedFile(int, IIndexFileLocation)} method visible in the index.
* {@link #addUncommittedFile(int, IIndexFileLocation, ISignificantMacros)} method visible in the index.
*
* @return The file that was updated.
* @throws CoreException

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2010 QNX Software Systems and others.
* Copyright (c) 2005, 2011 QNX Software Systems 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
@ -11,16 +11,20 @@
* Andrew Ferguson (Symbian)
* Anton Leherbauer (Wind River Systems)
* IBM Corporation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.index;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective;
import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IIndexFile;
@ -28,6 +32,7 @@ import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
import org.eclipse.cdt.internal.core.parser.IMacroDictionary;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.InclusionKind;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContentProvider;
@ -37,8 +42,7 @@ import org.eclipse.cdt.internal.core.pdom.AbstractIndexerTask.IndexFileContent;
import org.eclipse.core.runtime.CoreException;
/**
* Code reader factory, that fakes code readers for header files already stored in the
* index.
* Code reader factory, that fakes code readers for header files already stored in the index.
*/
public final class IndexBasedFileContentProvider extends InternalFileContentProvider {
private static final class NeedToParseException extends Exception {}
@ -46,14 +50,15 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
private final IIndex fIndex;
private int fLinkage;
private Set<IIndexFileLocation> fIncludedFiles= new HashSet<IIndexFileLocation>();
/** The fall-back code reader factory used in case a header file is not indexed */
private final InternalFileContentProvider fFallBackFactory;
private final ASTFilePathResolver fPathResolver;
private final AbstractIndexerTask fRelatedIndexerTask;
private boolean fSupportFillGapFromContextToHeader= false;
private boolean fSupportFillGapFromContextToHeader;
private long fFileSizeLimit= 0;
private final Map<IIndexFileLocation, IFileNomination> fPragmaOnce= new HashMap<IIndexFileLocation, IFileNomination>();
public IndexBasedFileContentProvider(IIndex index,
ASTFilePathResolver pathResolver, int linkage, IncludeFileContentProvider fallbackFactory) {
this(index, pathResolver, linkage, fallbackFactory, null);
@ -79,63 +84,65 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
public void setLinkage(int linkageID) {
fLinkage= linkageID;
}
public void cleanupAfterTranslationUnit() {
fIncludedFiles.clear();
}
@Override
public void resetPragmaOnceTracking() {
fPragmaOnce.clear();
}
/**
* Reports detection of pragma once semantics.
*/
@Override
public void reportPragmaOnceSemantics(String filePath, IFileNomination nom) {
fPragmaOnce.put(fPathResolver.resolveIncludeFile(filePath), nom);
}
/**
* Returns whether the given file has been included with pragma once semantics.
*/
@Override
public IFileNomination isIncludedWithPragmaOnceSemantics(String filePath) {
return fPragmaOnce.get(fPathResolver.resolveIncludeFile(filePath));
}
@Override
public boolean getInclusionExists(String path) {
return fPathResolver.doesIncludeFileExist(path);
}
@Override
public void reportTranslationUnitFile(String path) {
IIndexFileLocation ifl= fPathResolver.resolveASTPath(path);
fIncludedFiles.add(ifl);
}
@Override
public Boolean hasFileBeenIncludedInCurrentTranslationUnit(String path) {
IIndexFileLocation ifl= fPathResolver.resolveASTPath(path);
return fIncludedFiles.contains(ifl);
}
@Override
public InternalFileContent getContentForInclusion(String path) {
public InternalFileContent getContentForInclusion(String path, IMacroDictionary macroDictionary) {
IIndexFileLocation ifl= fPathResolver.resolveIncludeFile(path);
if (ifl == null) {
return null;
}
path= fPathResolver.getASTPath(ifl);
// Include files once, only.
if (!fIncludedFiles.add(ifl)) {
return new InternalFileContent(path, InclusionKind.SKIP_FILE);
}
try {
IIndexFile file= fIndex.getFile(fLinkage, ifl);
IIndexFile file = selectIndexFile(macroDictionary, ifl);
if (file != null) {
try {
List<IIndexFile> files= new ArrayList<IIndexFile>();
List<IIndexMacro> macros= new ArrayList<IIndexMacro>();
List<ICPPUsingDirective> directives= new ArrayList<ICPPUsingDirective>();
Set<IIndexFileLocation> ifls= new HashSet<IIndexFileLocation>();
collectFileContent(file, ifls, files, macros, directives, false);
// add included files only, if no exception was thrown
fIncludedFiles.addAll(ifls);
return new InternalFileContent(path, macros, directives, files);
Map<IIndexFileLocation, IFileNomination> newPragmaOnce= new HashMap<IIndexFileLocation, IFileNomination>();
collectFileContent(file, null, newPragmaOnce, files, macros, directives, null);
// Report pragma once inclusions, only if no exception was thrown.
fPragmaOnce.putAll(newPragmaOnce);
List<String> newPragmaOncePaths = toPathList(newPragmaOnce.keySet());
return new InternalFileContent(path, macros, directives, files, newPragmaOncePaths);
} catch (NeedToParseException e) {
}
}
}
} catch (CoreException e) {
CCorePlugin.log(e);
}
// Skip large files
if (fFileSizeLimit > 0 && fPathResolver.getFileSize(path) > fFileSizeLimit) {
return new InternalFileContent(path, InclusionKind.SKIP_FILE);
return new InternalFileContent(path, InclusionKind.SKIP_FILE, null);
}
if (fFallBackFactory != null) {
@ -147,6 +154,26 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
return null;
}
public List<String> toPathList(Collection<IIndexFileLocation> newPragmaOnce) {
List<String> newPragmaOncePaths= new ArrayList<String>(newPragmaOnce.size());
for (IIndexFileLocation l : newPragmaOnce) {
newPragmaOncePaths.add(fPathResolver.getASTPath(l));
}
return newPragmaOncePaths;
}
public IIndexFile selectIndexFile(IMacroDictionary macroDictionary, IIndexFileLocation ifl)
throws CoreException {
if (fRelatedIndexerTask != null)
return fRelatedIndexerTask.selectIndexFile(fLinkage, ifl, macroDictionary);
for (IIndexFile file : fIndex.getFiles(fLinkage, ifl)) {
if (macroDictionary.satisfies(file.getSignificantMacros()))
return file;
}
return null;
}
@Override
public InternalFileContent getContentForInclusion(IIndexFileLocation ifl, String astPath) {
if (fFallBackFactory != null) {
@ -155,42 +182,71 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
return null;
}
private void collectFileContent(IIndexFile file, Set<IIndexFileLocation> ifls, List<IIndexFile> files,
List<IIndexMacro> macros, List<ICPPUsingDirective> usingDirectives, boolean checkIncluded)
private boolean collectFileContent(IIndexFile file, IIndexFile stopAt, Map<IIndexFileLocation, IFileNomination> newPragmaOnce,
List<IIndexFile> files, List<IIndexMacro> macros,
List<ICPPUsingDirective> usingDirectives, Set<IIndexFile> preventRecursion)
throws CoreException, NeedToParseException {
if (file.equals(stopAt))
return true;
IIndexFileLocation ifl= file.getLocation();
if (!ifls.add(ifl) || (checkIncluded && fIncludedFiles.contains(ifl))) {
return;
}
IndexFileContent content;
if (fRelatedIndexerTask != null) {
content= fRelatedIndexerTask.getFileContent(fLinkage, ifl);
if (content == null) {
throw new NeedToParseException();
}
if (newPragmaOnce.containsKey(ifl))
return false;
if (file.hasPragmaOnceSemantics())
newPragmaOnce.put(ifl, file);
if (preventRecursion != null) {
if (fPragmaOnce.containsKey(ifl))
return false;
} else {
content= new IndexFileContent();
content.setPreprocessorDirectives(file.getIncludes(), file.getMacros());
content.setUsingDirectives(file.getUsingDirectives());
preventRecursion= new HashSet<IIndexFile>();
}
if (!preventRecursion.add(file))
return false;
final ICPPUsingDirective[] uds;
final Object[] pds;
if (fRelatedIndexerTask != null) {
IndexFileContent content= fRelatedIndexerTask.getFileContent(fLinkage, ifl, file);
if (content == null)
throw new NeedToParseException();
uds= content.getUsingDirectives();
pds= content.getPreprocessingDirectives();
} else {
uds= file.getUsingDirectives();
pds= IndexFileContent.merge(file.getIncludes(), file.getMacros());
}
files.add(file);
usingDirectives.addAll(Arrays.asList(content.getUsingDirectives()));
Object[] dirs= content.getPreprocessingDirectives();
for (Object d : dirs) {
int udx= 0;
for (Object d : pds) {
if (d instanceof IIndexMacro) {
macros.add((IIndexMacro) d);
} else if (d instanceof IIndexInclude) {
IIndexInclude inc= (IIndexInclude) d;
IIndexFile includedFile= fIndex.resolveInclude((IIndexInclude) d);
if (includedFile != null) {
collectFileContent(includedFile, ifls, files, macros, usingDirectives, true);
// Add in using directives that appear before the inclusion
final int offset= inc.getNameOffset();
for (; udx < uds.length && uds[udx].getPointOfDeclaration() <= offset; udx++) {
usingDirectives.add(uds[udx]);
}
if (collectFileContent(includedFile, stopAt, newPragmaOnce, files, macros, usingDirectives, preventRecursion))
return true;
}
}
}
// Add in remaining using directives
for (; udx < uds.length; udx++) {
usingDirectives.add(uds[udx]);
}
preventRecursion.remove(file);
return false;
}
@Override
public InternalFileContent getContentForContextToHeaderGap(String path) {
public InternalFileContent getContentForContextToHeaderGap(String path,
IMacroDictionary macroDictionary) {
if (!fSupportFillGapFromContextToHeader) {
return null;
}
@ -199,30 +255,39 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
if (ifl == null) {
return null;
}
try {
IIndexFile targetFile= fIndex.getFile(fLinkage, ifl);
// TODO(197989) This is wrong, the dictionary at this point does not relate to the target
// file. We'll have to provide the target file from the outside (i.e. from the indexer
// task.
IIndexFile targetFile = selectIndexFile(macroDictionary, ifl);
if (targetFile == null) {
return null;
}
IIndexFile contextFile= findContext(targetFile);
if (contextFile == targetFile || contextFile == null) {
return null;
}
HashSet<IIndexFile> filesIncluded= new HashSet<IIndexFile>();
Map<IIndexFileLocation, IFileNomination> newPragmaOnce= new HashMap<IIndexFileLocation, IFileNomination>();
List<IIndexFile> filesIncluded= new ArrayList<IIndexFile>();
ArrayList<IIndexMacro> macros= new ArrayList<IIndexMacro>();
ArrayList<ICPPUsingDirective> directives= new ArrayList<ICPPUsingDirective>();
if (!collectFileContentForGap(contextFile, ifl, filesIncluded, macros, directives)) {
try {
if (!collectFileContent(contextFile, targetFile, newPragmaOnce,
filesIncluded, macros, directives, new HashSet<IIndexFile>())) {
return null;
}
} catch (NeedToParseException e) {
return null;
}
// mark the files in the gap as included
for (IIndexFile file : filesIncluded) {
fIncludedFiles.add(file.getLocation());
}
return new InternalFileContent(GAP, macros, directives, new ArrayList<IIndexFile>(filesIncluded));
// Report pragma once inclusions.
fPragmaOnce.putAll(newPragmaOnce);
List<String> newPragmaOncePaths = toPathList(newPragmaOnce.keySet());
return new InternalFileContent(GAP, macros, directives, new ArrayList<IIndexFile>(filesIncluded),
newPragmaOncePaths);
} catch (CoreException e) {
CCorePlugin.log(e);
}
@ -244,56 +309,12 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
return file;
}
private boolean collectFileContentForGap(IIndexFile from, IIndexFileLocation to,
Set<IIndexFile> filesIncluded, List<IIndexMacro> macros,
List<ICPPUsingDirective> directives) throws CoreException {
final IIndexFileLocation ifl= from.getLocation();
if (ifl.equals(to)) {
return true;
}
if (fIncludedFiles.contains(ifl) || !filesIncluded.add(from)) {
return false;
}
final IIndexInclude[] ids= from.getIncludes();
final IIndexMacro[] ms= from.getMacros();
final Object[] dirs= IndexFileContent.merge(ids, ms);
IIndexInclude success= null;
for (Object d : dirs) {
if (d instanceof IIndexMacro) {
macros.add((IIndexMacro) d);
} else if (d instanceof IIndexInclude) {
IIndexFile includedFile= fIndex.resolveInclude((IIndexInclude) d);
if (includedFile != null) {
if (collectFileContentForGap(includedFile, to, filesIncluded, macros, directives)) {
success= (IIndexInclude) d;
break;
}
}
}
}
final ICPPUsingDirective[] uds= from.getUsingDirectives();
if (success == null) {
directives.addAll(Arrays.asList(uds));
return false;
}
final int offset= success.getNameOffset();
for (ICPPUsingDirective ud : uds) {
if (ud.getPointOfDeclaration() > offset)
break;
directives.add(ud);
}
return true;
}
public IIndexFile findIndexFile(InternalFileContent fc) throws CoreException {
public IIndexFile[] findIndexFiles(InternalFileContent fc) throws CoreException {
IIndexFileLocation ifl = fPathResolver.resolveASTPath(fc.getFileLocation());
if (ifl != null) {
return fIndex.getFile(fLinkage, ifl);
return fIndex.getFiles(fLinkage, ifl);
}
return null;
return IIndexFile.EMPTY_FILE_ARRAY;
}
}

View file

@ -40,6 +40,15 @@ public class IndexFileSet implements IIndexFileSet {
subSet.add(fragFile);
}
public void remove(IIndexFile indexFile) {
final IIndexFragmentFile fragFile = (IIndexFragmentFile) indexFile;
final IIndexFragment frag= fragFile.getIndexFragment();
IIndexFragmentFileSet subSet= fSubSets.get(frag);
if (subSet != null) {
subSet.remove(fragFile);
}
}
public boolean containsDeclaration(IIndexBinding binding) {
return containsDeclaration(binding, false);
}
@ -163,6 +172,10 @@ public class IndexFileSet implements IIndexFileSet {
public void add(IIndexFile indexFile) {
Assert.isLegal(false);
}
public void remove(IIndexFile indexFile) {
Assert.isLegal(false);
}
};
}
return fInverse;

View file

@ -18,6 +18,7 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
import org.eclipse.core.runtime.CoreException;
@ -43,20 +44,23 @@ public class WritableCIndex extends CIndex implements IWritableIndex {
return fWritableFragment;
}
public IIndexFragmentFile getWritableFile(int linkageID, IIndexFileLocation location) throws CoreException {
return fWritableFragment.getFile(linkageID, location);
public IIndexFragmentFile getWritableFile(int linkageID, IIndexFileLocation location,
ISignificantMacros macroDictionary) throws CoreException {
return fWritableFragment.getFile(linkageID, location, macroDictionary);
}
public IIndexFragmentFile[] getWritableFiles(IIndexFileLocation location) throws CoreException {
return fWritableFragment.getFiles(location);
}
public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException {
return fWritableFragment.addFile(linkageID, location);
public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location,
ISignificantMacros macroDictionary) throws CoreException {
return fWritableFragment.addFile(linkageID, location, macroDictionary);
}
public IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location) throws CoreException {
return fWritableFragment.addUncommittedFile(linkageID, location);
public IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location,
ISignificantMacros macroDictionary) throws CoreException {
return fWritableFragment.addUncommittedFile(linkageID, location, macroDictionary);
}
public IIndexFragmentFile commitUncommittedFile() throws CoreException {
@ -78,9 +82,10 @@ public class WritableCIndex extends CIndex implements IWritableIndex {
if (!isWritableFragment(indexFragment)) {
assert false : "Attempt to update file of read-only fragment"; //$NON-NLS-1$
} else {
for (IncludeInformation ii : includes) {
if (ii.fLocation != null) {
ii.fTargetFile= addFile(linkageID, ii.fLocation);
for (IncludeInformation include : includes) {
if (include.fLocation != null) {
include.fTargetFile= addFile(linkageID, include.fLocation,
include.fStatement.getSignificantMacros());
}
}
((IWritableIndexFragment) indexFragment).addFileContent(file, includes, macros, names, resolver, lock);

View file

@ -45,7 +45,7 @@ public class CodeReaderFactoryAdapter extends AbstractCodeReaderFactory {
}
public org.eclipse.cdt.core.parser.CodeReader createCodeReaderForInclusion(String path) {
return CodeReaderAdapter.adapt(fDelegate.getContentForInclusion(path));
return CodeReaderAdapter.adapt(fDelegate.getContentForInclusion(path, null));
}
@Override
@ -55,7 +55,7 @@ public class CodeReaderFactoryAdapter extends AbstractCodeReaderFactory {
}
public org.eclipse.cdt.core.parser.CodeReader createCodeReaderForTranslationUnit(String path) {
return CodeReaderAdapter.adapt(fDelegate.getContentForInclusion(path));
return CodeReaderAdapter.adapt(fDelegate.getContentForInclusion(path, null));
}
@Deprecated

View file

@ -27,7 +27,8 @@ public class EmptyFilesProvider extends InternalFileContentProvider {
}
@Override
public InternalFileContent getContentForInclusion(String path) {
public InternalFileContent getContentForInclusion(String path,
IMacroDictionary macroDictionary) {
if (!getInclusionExists(path))
return null;

View file

@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser;
@ -26,7 +26,7 @@ import org.eclipse.core.runtime.CoreException;
public class FileContentProviderAdapter extends InternalFileContentProvider {
/**
* @deprecated avoid using the adapter, its for backwards compatibility, only.
* @deprecated avoid using the adapter, it's for backwards compatibility, only.
*/
@Deprecated
public static InternalFileContentProvider adapt(ICodeReaderFactory fileCreator) {
@ -57,7 +57,7 @@ public class FileContentProviderAdapter extends InternalFileContentProvider {
}
@Override
public InternalFileContent getContentForInclusion(String path) {
public InternalFileContent getContentForInclusion(String path, IMacroDictionary macroDictionary) {
return (InternalFileContent) FileContent.adapt(fDelegate.createCodeReaderForInclusion(path));
}
@ -72,5 +72,4 @@ public class FileContentProviderAdapter extends InternalFileContentProvider {
}
return null;
}
}

View file

@ -0,0 +1,23 @@
/*******************************************************************************
* Copyright (c) 2011 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.parser;
import org.eclipse.cdt.core.parser.ISignificantMacros;
/**
* Interface for accessing the macro dictionary of the preprocessor.
*/
public interface IMacroDictionary {
boolean satisfies(ISignificantMacros significantMacros);
}

View file

@ -30,7 +30,8 @@ public class SavedFilesProvider extends InternalFileContentProvider {
}
@Override
public InternalFileContent getContentForInclusion(String path) {
public InternalFileContent getContentForInclusion(String path,
IMacroDictionary macroDictionary) {
if (!getInclusionExists(path))
return null;

View file

@ -6,7 +6,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
@ -40,11 +40,14 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree.IASTInclusionNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification;
import org.eclipse.core.runtime.CoreException;
/**
* Models various AST-constructs obtained from the preprocessor.
@ -188,7 +191,7 @@ class ASTIfndef extends ASTDirectiveWithCondition implements IASTPreprocessorIfn
}
class ASTIfdef extends ASTDirectiveWithCondition implements IASTPreprocessorIfdefStatement {
ASTMacroReferenceName fMacroRef;
private ASTMacroReferenceName fMacroRef;
public ASTIfdef(IASTTranslationUnit parent, int startNumber, int condNumber, int condEndNumber, boolean taken, IMacroBinding macro) {
super(parent, startNumber, condNumber, condEndNumber, taken);
if (macro != null) {
@ -258,16 +261,24 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
private final boolean fIsResolved;
private final boolean fIsSystemInclude;
private final boolean fFoundByHeuristics;
private final IFileNomination fNominationDelegate;
private boolean fPragmaOnce;
private boolean fComplete;
private ISignificantMacros fSignificantMacros;
public ASTInclusionStatement(IASTTranslationUnit parent,
int startNumber, int nameStartNumber, int nameEndNumber, int endNumber,
char[] headerName, String filePath, boolean userInclude, boolean active, boolean heuristic) {
char[] headerName, String filePath, boolean userInclude, boolean active, boolean heuristic,
IFileNomination nominationDelegate) {
super(parent, IASTTranslationUnit.PREPROCESSOR_STATEMENT, startNumber, endNumber);
fName= new ASTPreprocessorName(this, IASTPreprocessorIncludeStatement.INCLUDE_NAME, nameStartNumber, nameEndNumber, headerName, null);
fName= new ASTPreprocessorName(this, IASTPreprocessorIncludeStatement.INCLUDE_NAME,
nameStartNumber, nameEndNumber, headerName, null);
fPath= filePath == null ? "" : filePath; //$NON-NLS-1$
fIsResolved= filePath != null;
fIsSystemInclude= !userInclude;
fFoundByHeuristics= heuristic;
fSignificantMacros= ISignificantMacros.NONE;
fNominationDelegate= nominationDelegate;
if (!active) {
setInactive();
}
@ -298,6 +309,42 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
public boolean isResolvedByHeuristics() {
return fFoundByHeuristics;
}
public boolean hasPragmaOnceSemantics() {
if (fNominationDelegate != null) {
try {
return fNominationDelegate.hasPragmaOnceSemantics();
} catch (CoreException e) {
}
}
return fPragmaOnce;
}
public void setPragamOnceSemantics(boolean value) {
assert fNominationDelegate == null;
fPragmaOnce= value;
}
public ISignificantMacros getSignificantMacros() {
if (fNominationDelegate != null) {
try {
return fNominationDelegate.getSignificantMacros();
} catch (CoreException e) {
}
}
return fSignificantMacros;
}
public void setSignificantMacros(ISignificantMacros sig) {
assert sig != null;
assert fNominationDelegate == null;
fSignificantMacros= sig;
fComplete= true;
}
public boolean isComplete() {
return fComplete;
}
}
class ASTMacroDefinition extends ASTPreprocessorNode implements IASTPreprocessorObjectStyleMacroDefinition {
@ -579,6 +626,10 @@ class ASTFileLocation implements IASTFileLocation {
public LocationCtxFile getLocationContext() {
return fLocationCtx;
}
public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
return fLocationCtx.getInclusionStatement();
}
}
class ASTMacroExpansion extends ASTPreprocessorNode implements IASTPreprocessorMacroExpansion {
@ -708,6 +759,10 @@ class ASTFileLocationForBuiltins implements IASTFileLocation {
public int getStartingLineNumber() {
return 0;
}
public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
return null;
}
}
@ -723,4 +778,3 @@ class ASTImageLocation extends ASTFileLocationForBuiltins implements IASTImageLo
return fKind;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2010 IBM Corporation and others.
* Copyright (c) 2004, 2011 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
@ -19,12 +19,17 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
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.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.dom.parser.IScannerExtensionConfiguration;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.parser.AbstractParserLogService;
import org.eclipse.cdt.core.parser.EndOfFileException;
import org.eclipse.cdt.core.parser.FileContent;
import org.eclipse.cdt.core.parser.IExtendedScannerInfo;
@ -34,6 +39,7 @@ import org.eclipse.cdt.core.parser.IPreprocessorDirective;
import org.eclipse.cdt.core.parser.IProblem;
import org.eclipse.cdt.core.parser.IScanner;
import org.eclipse.cdt.core.parser.IScannerInfo;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
import org.eclipse.cdt.core.parser.Keywords;
@ -45,6 +51,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.IIncludeFileResolutionHeuristics;
import org.eclipse.cdt.internal.core.parser.EmptyFilesProvider;
import org.eclipse.cdt.internal.core.parser.IMacroDictionary;
import org.eclipse.cdt.internal.core.parser.scanner.ExpressionEvaluator.EvalException;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.InclusionKind;
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
@ -52,6 +59,7 @@ import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.Invali
import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.BranchKind;
import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.CodeState;
import org.eclipse.cdt.internal.core.parser.scanner.ScannerContext.Conditional;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
/**
@ -88,11 +96,45 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
private static final DynamicMacro __DATE__= new DateMacro("__DATE__".toCharArray()); //$NON-NLS-1$
private static final DynamicMacro __TIME__ = new TimeMacro("__TIME__".toCharArray()); //$NON-NLS-1$
private static final DynamicMacro __LINE__ = new LineMacro("__LINE__".toCharArray()); //$NON-NLS-1$
private static final char[] ONCE = "once".toCharArray(); //$NON-NLS-1$
private static final int NO_EXPANSION = 0x01;
private static final int PROTECT_DEFINED = 0x02;
private static final int STOP_AT_NL = 0x04;
private static final int CHECK_NUMBERS = 0x08;
private static final int REPORT_SIGNIFICANT_MACROS = 0x10;
private static final int MAX_INCLUSION_DEPTH = 200;
private static final String TRACE_NO_GUARD = CCorePlugin.PLUGIN_ID + "/debug/scanner/missingIncludeGuards"; //$NON-NLS-1$
private final class MacroDictionary implements IMacroDictionary, ISignificantMacros.IVisitor {
public boolean satisfies(ISignificantMacros significantMacros) {
return significantMacros.accept(this);
}
public boolean visitDefined(char[] macro) {
return isDefined(macro);
}
public boolean visitUndefined(char[] macro) {
return !isDefined(macro);
}
public boolean visitValue(char[] macro, char[] value) {
PreprocessorMacro m = fMacroDictionary.get(macro);
return m != null && CharArrayUtils.equals(m.getExpansion(), value);
}
private boolean isDefined(char[] macro) {
return fMacroDictionary.containsKey(macro);
}
public boolean visitIncluded(char[] path) {
return fFileContentProvider.isIncludedWithPragmaOnceSemantics(new String(path)) != null;
}
}
private interface IIncludeFileTester<T> {
T checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath);
@ -100,7 +142,13 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
final private IIncludeFileTester<InternalFileContent> createCodeReaderTester= new IIncludeFileTester<InternalFileContent>() {
public InternalFileContent checkFile(String path, boolean isHeuristicMatch, IncludeSearchPathElement onPath) {
final InternalFileContent fc= fFileContentProvider.getContentForInclusion(path);
final InternalFileContent fc;
IFileNomination once= fFileContentProvider.isIncludedWithPragmaOnceSemantics(path);
if (once != null) {
fc= new InternalFileContent(path, InclusionKind.SKIP_FILE, once);
} else {
fc= fFileContentProvider.getContentForInclusion(path, fMacroDictionaryFacade);
}
if (fc != null) {
fc.setFoundByHeuristics(isHeuristicMatch);
fc.setFoundOnPath(onPath);
@ -162,7 +210,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
TokenSequence fInputToMacroExpansion= new TokenSequence(false);
TokenSequence fLineInputToMacroExpansion= new TokenSequence(true);
final private IParserLogService fLog;
final private AbstractParserLogService fLog;
final private InternalFileContentProvider fFileContentProvider;
private IIncludeFileResolutionHeuristics fIncludeFileResolutionHeuristics;
@ -184,11 +232,9 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
// state information
private final CharArrayMap<PreprocessorMacro> fMacroDictionary = new CharArrayMap<PreprocessorMacro>(512);
private final IMacroDictionary fMacroDictionaryFacade = new MacroDictionary();
private final LocationMap fLocationMap;
/** Set of already included files */
private final HashSet<String> fAllIncludedFiles= new HashSet<String>();
private final Lexer fRootLexer;
private final ScannerContext fRootContext;
protected ScannerContext fCurrentContext;
@ -200,6 +246,12 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
private Token fLastToken;
private InternalFileContent fRootContent;
private boolean fHandledEndOfTranslationUnit;
// Detection of include guards used around an include directive
private char[] fExternIncludeGuard;
private Set<String> fTracedGuards;
public CPreprocessor(FileContent fileContent, IScannerInfo info, ParserLanguage language,
IParserLogService log, IScannerExtensionConfiguration configuration,
@ -217,7 +269,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
throw new IllegalArgumentException("Illegal file content object"); //$NON-NLS-1$
}
fLog = log;
fLog = AbstractParserLogService.convert(log);
fAdditionalNumericLiteralSuffixes= nonNull(configuration.supportAdditionalNumericLiteralSuffixes());
fLexOptions.fSupportDollarInIdentifiers= configuration.support$InIdentifiers();
fLexOptions.fSupportAtSignInIdentifiers= configuration.supportAtSignInIdentifiers();
@ -239,17 +291,37 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
setupMacroDictionary(configuration, info, language);
ILocationCtx ctx= fLocationMap.pushTranslationUnit(filePath, fRootContent.getSource());
fAllIncludedFiles.add(filePath);
fFileContentProvider.reportTranslationUnitFile(filePath);
fRootLexer= new Lexer(fRootContent.getSource(), fLexOptions, this, this);
fRootContext= fCurrentContext= new ScannerContext(ctx, null, fRootLexer);
fRootContext= fCurrentContext= new ScannerContext(ctx, null, fRootLexer, true);
if (info instanceof IExtendedScannerInfo) {
final IExtendedScannerInfo einfo= (IExtendedScannerInfo) info;
fPreIncludedFiles= new String[][] {einfo.getMacroFiles(), einfo.getIncludeFiles()};
fPreIncludedFiles= new String[][] { einfo.getMacroFiles(), einfo.getIncludeFiles() };
}
fFileContentProvider.resetPragmaOnceTracking();
detectIncludeGuard(filePath, fRootContent.getSource(), fRootContext);
}
private char[] detectIncludeGuard(String filePath, AbstractCharArray source, ScannerContext ctx) {
final char[] guard = IncludeGuardDetection.detectIncludeGuard(source, fLexOptions, fPPKeywords);
if (guard != null) {
IFileNomination nom= fLocationMap.reportPragmaOnceSemantics(ctx.getLocationCtx());
fFileContentProvider.reportPragmaOnceSemantics(filePath, nom);
ctx.internalModification(guard);
ctx.internalModification(filePath.toCharArray());
return guard;
}
if (ctx != fRootContext) {
if (fLog.isTracing(TRACE_NO_GUARD)) {
if (fTracedGuards == null)
fTracedGuards= new HashSet<String>();
if (fTracedGuards.add(filePath))
fLog.traceLog(TRACE_NO_GUARD, "No include guard in " + filePath); //$NON-NLS-1$
}
}
return null;
}
public void setSplitShiftROperator(boolean val) {
public void setSplitShiftROperator(boolean val) {
fSplitShiftRightOperator= val;
}
@ -370,16 +442,17 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
private void beforeFirstFetchToken() {
if (fPreIncludedFiles != null) {
handlePreIncludedFiles();
}
final String location = fLocationMap.getTranslationUnitPath();
InternalFileContent content= fFileContentProvider.getContentForContextToHeaderGap(location);
final String location = fLocationMap.getTranslationUnitPath();
InternalFileContent content= fFileContentProvider.getContentForContextToHeaderGap(location,
fMacroDictionaryFacade);
if (content != null && content.getKind() == InclusionKind.FOUND_IN_INDEX) {
processInclusionFromIndex(0, location, content);
fPreIncludedFiles= null;
} else if (fPreIncludedFiles != null) {
handlePreIncludedFiles();
}
fLocationMap.replacingFile(fFileContentProvider, fRootContent);
fRootContent= null;
fLocationMap.parsingFile(fFileContentProvider, fRootContent);
fRootContent= null;
}
private void handlePreIncludedFiles() {
@ -387,14 +460,14 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
if (imacro != null && imacro.length > 0) {
final char[] buffer= createSyntheticFile(imacro);
ILocationCtx ctx= fLocationMap.pushPreInclusion(new CharArray(buffer), 0, true);
fCurrentContext= new ScannerContext(ctx, fCurrentContext, new Lexer(buffer, fLexOptions, this, this));
fCurrentContext= new ScannerContext(ctx, fCurrentContext, new Lexer(buffer, fLexOptions, this, this), false);
ScannerContext preCtx= fCurrentContext;
try {
while (internalFetchToken(preCtx, CHECK_NUMBERS, false).getType() != IToken.tEND_OF_INPUT) {
// just eat the tokens
}
final ILocationCtx locationCtx = fCurrentContext.getLocationCtx();
fLocationMap.popContext(locationCtx);
fLocationMap.popContext(locationCtx, null);
fCurrentContext= fCurrentContext.getParent();
assert fCurrentContext == fRootContext;
} catch (OffsetLimitReachedException e) {
@ -404,7 +477,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
if (include != null && include.length > 0) {
final char[] buffer= createSyntheticFile(include);
ILocationCtx ctx= fLocationMap.pushPreInclusion(new CharArray(buffer), 0, false);
fCurrentContext= new ScannerContext(ctx, fCurrentContext, new Lexer(buffer, fLexOptions, this, this));
fCurrentContext= new ScannerContext(ctx, fCurrentContext, new Lexer(buffer, fLexOptions, this, this), false);
}
fPreIncludedFiles= null;
}
@ -726,11 +799,17 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
case IToken.tEND_OF_INPUT:
if (fCurrentContext == uptoEndOfCtx || uptoEndOfCtx == null) {
if (fCurrentContext == fRootContext && !fHandledEndOfTranslationUnit
&& (options & STOP_AT_NL) == 0) {
fHandledEndOfTranslationUnit= true;
fLocationMap.endTranslationUnit(ppToken.getEndOffset(), fCurrentContext.getSignificantMacros());
}
return ppToken;
}
final ILocationCtx locationCtx = fCurrentContext.getLocationCtx();
fLocationMap.popContext(locationCtx);
fCurrentContext= fCurrentContext.getParent();
final ILocationCtx locationCtx = fCurrentContext.getLocationCtx();
fLocationMap.popContext(locationCtx, fCurrentContext.getSignificantMacros());
fCurrentContext.propagateSignificantMacros();
fCurrentContext= fCurrentContext.getParent();
assert fCurrentContext != null;
ppToken= fCurrentContext.currentLexerToken();
@ -781,7 +860,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
}
private void checkNumber(Token number, final boolean isFloat) {
private void checkNumber(Token number, final boolean isFloat) {
final char[] image= number.getCharImage();
boolean hasExponent = false;
@ -1151,7 +1230,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
break;
case IPreprocessorDirective.ppPragma:
condOffset= lexer.nextToken().getOffset();
Token pragmaToken= lexer.nextToken();
condOffset= pragmaToken.getOffset();
condEndOffset= lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
// Missing argument
if (condEndOffset < condOffset) {
@ -1160,6 +1240,10 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
if (fCurrentContext.getCodeState() == CodeState.eActive) {
int endOffset= lexer.currentToken().getEndOffset();
fLocationMap.encounterPoundPragma(startOffset, condOffset, condEndOffset, endOffset);
if (CharArrayUtils.equals(ONCE, pragmaToken.getCharImage())) {
IFileNomination nom= fLocationMap.reportPragmaOnceSemantics(fCurrentContext.getLocationCtx());
fFileContentProvider.reportPragmaOnceSemantics(getCurrentFilename(), nom);
}
}
break;
case IPreprocessorDirective.ppIgnore:
@ -1175,16 +1259,12 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
}
private boolean hasFileBeenIncluded(String location) {
Boolean itHas= fFileContentProvider.hasFileBeenIncludedInCurrentTranslationUnit(location);
if (itHas != null) {
return itHas.booleanValue();
}
return fAllIncludedFiles.contains(location);
}
private void executeInclude(final Lexer lexer, int poundOffset, boolean include_next,
boolean active, boolean withinExpansion) throws OffsetLimitReachedException {
// Make sure to clear the extern include guard.
final char[] externGuard= fExternIncludeGuard;
fExternIncludeGuard= null;
if (withinExpansion) {
final char[] name= lexer.currentToken().getCharImage();
final int endOffset = lexer.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
@ -1258,19 +1338,36 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
return;
}
if (active && fCurrentContext.getDepth() == MAX_INCLUSION_DEPTH) {
handleProblem(IProblem.PREPROCESSOR_EXCEEDS_MAXIMUM_INCLUSION_DEPTH,
lexer.getInputChars(poundOffset, condEndOffset), poundOffset, condEndOffset);
return;
}
String path= null;
boolean reported= false;
boolean isHeuristic= false;
IFileNomination nominationDelegate= null;
final String includeDirective = new String(headerName);
if (!active) {
// test if the include is inactive just because it was included before (bug 167100)
final IncludeResolution resolved= findInclusion(includeDirective, userInclude, include_next,
getCurrentFilename(), createPathTester);
if (resolved != null && hasFileBeenIncluded(resolved.fLocation)) {
path= resolved.fLocation;
isHeuristic= resolved.fHeuristic;
// #ifndef GUARD
// #include "file.h"
// #endif
if (externGuard != null) {
// When the extern guard matches we need to resolve the inclusion. We don't actually
// check whether the guard matches.
final IncludeResolution resolved= findInclusion(includeDirective, userInclude, include_next,
getCurrentFilename(), createPathTester);
if (resolved != null) {
nominationDelegate = fFileContentProvider.isIncludedWithPragmaOnceSemantics(resolved.fLocation);
if (nominationDelegate != null) {
path= resolved.fLocation;
isHeuristic= resolved.fHeuristic;
fCurrentContext.undoSignificance(externGuard);
}
}
}
} else {
final InternalFileContent fi= findInclusion(includeDirective, userInclude, include_next,
@ -1280,24 +1377,62 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
isHeuristic= fi.isFoundByHeuristics();
switch (fi.getKind()) {
case FOUND_IN_INDEX:
nominationDelegate= fi.getFilesIncluded().get(0);
if (nominationDelegate != null) {
try {
ISignificantMacros sm = nominationDelegate.getSignificantMacros();
fCurrentContext.addSignificantMacros(sm);
} catch (CoreException e) {
}
}
processInclusionFromIndex(poundOffset, path, fi);
// When the extern guard matches, it is not significant.
if (externGuard != null && fFileContentProvider.isIncludedWithPragmaOnceSemantics(path) != null
&& fMacroDictionary.containsKey(externGuard)) {
List<IIndexMacro> mdefs = fi.getMacroDefinitions();
if (!mdefs.isEmpty() && CharArrayUtils.equals(mdefs.get(0).getNameCharArray(), externGuard)) {
fCurrentContext.undoSignificance(externGuard);
}
}
break;
case USE_SOURCE:
AbstractCharArray source= fi.getSource();
if (source != null && !isCircularInclusion(path)) {
if (source != null) {
reported= true;
fAllIncludedFiles.add(path);
ILocationCtx ctx= fLocationMap.pushInclusion(poundOffset, nameOffsets[0], nameOffsets[1],
condEndOffset, source, path, headerName, userInclude, isHeuristic, fi.isSource());
ScannerContext fctx= new ScannerContext(ctx, fCurrentContext,
new Lexer(source, fLexOptions, this, this));
new Lexer(source, fLexOptions, this, this), true);
fctx.setFoundOnPath(fi.getFoundOnPath(), includeDirective);
char[] guard= detectIncludeGuard(path, source, fctx);
if (guard != null) {
fctx.setPragmaOnce();
// When the extern guard matches, it is not significant.
if (externGuard != null && CharArrayUtils.equals(externGuard, guard)) {
fCurrentContext.undoSignificance(guard);
}
}
fCurrentContext= fctx;
}
fLocationMap.replacingFile(fFileContentProvider, fi);
fLocationMap.parsingFile(fFileContentProvider, fi);
break;
case SKIP_FILE:
nominationDelegate= fi.getPragmaOnceNomination();
if (nominationDelegate != null) {
ISignificantMacros sm= null;
if (nominationDelegate.isComplete()) {
try {
sm = nominationDelegate.getSignificantMacros();
} catch (CoreException e) {
}
}
if (sm != null && fMacroDictionaryFacade.satisfies(sm)) {
fCurrentContext.addSignificantMacros(sm);
} else {
fCurrentContext.addSignificantInclusion(path);
}
}
break;
}
} else {
@ -1315,7 +1450,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
if (!reported) {
fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1],
condEndOffset, headerName, path, userInclude, active, isHeuristic);
condEndOffset, headerName, path, userInclude, active, isHeuristic, nominationDelegate);
}
}
@ -1323,6 +1458,10 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
List<IIndexMacro> mdefs= fi.getMacroDefinitions();
for (IIndexMacro macro : mdefs) {
addMacroDefinition(macro);
fCurrentContext.internalModification(macro.getNameCharArray());
}
for (String pragOncePath : fi.getPragmaOncePaths()) {
fCurrentContext.internalModification(pragOncePath.toCharArray());
}
fLocationMap.skippedFile(fLocationMap.getSequenceNumberForOffset(offset), fi);
}
@ -1346,24 +1485,15 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return headerName;
}
private boolean isCircularInclusion(String filename) {
ILocationCtx checkContext= fCurrentContext.getLocationCtx();
while (checkContext != null) {
if (filename.equals(checkContext.getFilePath())) {
return true;
}
checkContext= checkContext.getParent();
}
return false;
}
private void executeDefine(final Lexer lexer, int startOffset, boolean isActive)
throws OffsetLimitReachedException {
try {
ObjectStyleMacro macrodef = fMacroDefinitionParser.parseMacroDefinition(lexer, this);
if (isActive)
fMacroDictionary.put(macrodef.getNameCharArray(), macrodef);
if (isActive) {
final char[] macroName = macrodef.getNameCharArray();
fMacroDictionary.put(macroName, macrodef);
fCurrentContext.internalModification(macroName);
}
final Token name= fMacroDefinitionParser.getNameToken();
fLocationMap.encounterPoundDefine(startOffset, name.getOffset(), name.getEndOffset(),
@ -1393,6 +1523,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
PreprocessorMacro definition;
if (isActive) {
definition= fMacroDictionary.remove(namechars, 0, namechars.length);
fCurrentContext.internalModification(namechars);
} else {
definition= fMacroDictionary.get(namechars);
}
@ -1422,10 +1553,19 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
handleProblem(IProblem.PREPROCESSOR_DEFINITION_NOT_FOUND, name.getCharImage(), offset, nameEndOffset);
} else {
final char[] namechars= name.getCharImage();
if (isIfndef && !fCurrentContext.hasInternalModification(namechars)
&& !fCurrentContext.isSignificant(namechars)) {
if (IncludeGuardDetection.detectIncludeEndif(lexer)) {
fExternIncludeGuard= namechars;
}
}
macro= fMacroDictionary.get(namechars);
isTaken= (macro == null) == isIfndef;
if (macro == null) {
macro = new UndefinedMacro(namechars);
fCurrentContext.significantMacroUndefined(namechars);
} else {
fCurrentContext.significantMacroDefined(namechars);
}
}
}
@ -1442,7 +1582,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return fCurrentContext.setBranchState(conditional, isTaken, withinExpansion, offset);
}
private CodeState executeIf(Lexer lexer, int startOffset, boolean isElif,
private CodeState executeIf(Lexer lexer, int startOffset, boolean isElif,
boolean withinExpansion) throws OffsetLimitReachedException {
Conditional cond= fCurrentContext.newBranch(isElif ? BranchKind.eElif : BranchKind.eIf, withinExpansion);
if (cond == null) {
@ -1458,6 +1598,12 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
int condEndOffset, endOffset;
if (cond.canHaveActiveBranch(withinExpansion)) {
char[] macro= IncludeGuardDetection.detectIfNotDefinedIncludeEndif(lexer);
if (macro != null && !fCurrentContext.hasInternalModification(macro)
&& !fCurrentContext.isSignificant(macro)) {
fExternIncludeGuard= macro;
}
TokenList condition= new TokenList();
condEndOffset= getTokensWithinPPDirective(true, condition, withinExpansion);
endOffset= lexer.currentToken().getEndOffset();
@ -1469,6 +1615,14 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
fExpressionEvaluator.clearMacrosInDefinedExpression();
isTaken= fExpressionEvaluator.evaluate(condition, fMacroDictionary, fLocationMap);
refs = fExpressionEvaluator.clearMacrosInDefinedExpression();
for (IASTName iastName : refs) {
IBinding mb= iastName.getBinding();
if (mb instanceof UndefinedMacro) {
fCurrentContext.significantMacroUndefined(iastName.toCharArray());
} else {
fCurrentContext.significantMacroDefined(iastName.toCharArray());
}
}
} catch (EvalException e) {
handleProblem(e.getProblemID(), e.getProblemArg(), condOffset, endOffset);
}
@ -1531,7 +1685,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
boolean withinExpansion) throws OffsetLimitReachedException {
final ScannerContext scannerCtx= fCurrentContext;
scannerCtx.clearInactiveCodeMarkerToken();
int options= STOP_AT_NL;
int options= STOP_AT_NL | REPORT_SIGNIFICANT_MACROS;
if (isCondition)
options |= PROTECT_DEFINED;
@ -1545,10 +1699,9 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
case Lexer.tNEWLINE:
break loop;
case IToken.tIDENTIFIER:
if (isCondition && CharArrayUtils.equals(Keywords.cDEFINED, t.getCharImage())) {
t.setType(CPreprocessor.tDEFINED);
options |= NO_EXPANSION;
}
break;
case tDEFINED:
options |= NO_EXPANSION;
break;
case IToken.tLPAREN:
break;
@ -1639,9 +1792,16 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
*/
private boolean expandMacro(final Token identifier, Lexer lexer, int options,
boolean withinExpansion) throws OffsetLimitReachedException {
final boolean reportSignificant = (options & REPORT_SIGNIFICANT_MACROS) != 0;
final char[] name= identifier.getCharImage();
if ((options & PROTECT_DEFINED) != 0 && CharArrayUtils.equals(name, Keywords.cDEFINED)) {
identifier.setType(tDEFINED);
return false;
}
PreprocessorMacro macro= fMacroDictionary.get(name);
if (macro == null) {
if (reportSignificant)
fCurrentContext.significantMacroUndefined(name);
return false;
}
boolean stopAtNewline= (options & STOP_AT_NL) != 0;
@ -1653,6 +1813,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
}
}
if (t.getType() != IToken.tLPAREN) {
if (reportSignificant)
fCurrentContext.significantMacro(macro);
return false;
}
}
@ -1661,7 +1823,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
final MacroExpander expander = withinExpansion ? new MacroExpander(this, fMacroDictionary,
fLocationMap, fLexOptions) : fMacroExpander;
TokenList replacement= expander.expand(input, (options & PROTECT_DEFINED) != 0, macro,
identifier, contentAssist);
identifier, contentAssist,
reportSignificant ? fCurrentContext : null);
final IASTName[] expansions= expander.clearImplicitExpansions();
final ImageLocationInfo[] ili= expander.clearImageLocationInfos();
final Token last= replacement.last();
@ -1679,5 +1842,5 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
return fMacroExpander;
}
return null;
}
}
}

View file

@ -299,11 +299,13 @@ public class ExpressionEvaluator {
if (LA() != IToken.tIDENTIFIER) {
throw new EvalException(IProblem.SCANNER_ILLEGAL_IDENTIFIER, null);
}
PreprocessorMacro macro= fDictionary.get(fTokens.getCharImage());
if (macro != null) {
fMacrosInDefinedExpressions.add(fLocationMap.encounterDefinedExpression(macro, fTokens.getOffset(), fTokens.getEndOffset()));
}
final char[] macroName = fTokens.getCharImage();
PreprocessorMacro macro= fDictionary.get(macroName);
int result= macro != null ? 1 : 0;
if (macro == null)
macro= new UndefinedMacro(macroName);
fMacrosInDefinedExpressions.add(fLocationMap.encounterDefinedExpression(macro, fTokens.getOffset(), fTokens.getEndOffset()));
consume();
if (parenthesis) {
if (LA() != IToken.tRPAREN) {

View file

@ -28,5 +28,5 @@ public interface ISkippedIndexedFilesListener {
/**
* Notifies the listeners that a file is being parsed.
*/
void replacingFile(InternalFileContentProvider fileContentProvider, InternalFileContent fileContent);
void parsingFile(InternalFileContentProvider fileContentProvider, InternalFileContent fileContent);
}

View file

@ -0,0 +1,165 @@
/*******************************************************************************
* Copyright (c) 2011 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.parser.scanner;
import static org.eclipse.cdt.core.parser.OffsetLimitReachedException.ORIGIN_PREPROCESSOR_DIRECTIVE;
import org.eclipse.cdt.core.parser.IPreprocessorDirective;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.Keywords;
import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
import org.eclipse.cdt.core.parser.util.CharArrayIntMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
/**
* Helper class for detecting include guards
*/
public class IncludeGuardDetection {
public static char[] detectIncludeGuard(AbstractCharArray content, Lexer.LexerOptions lexOptions, CharArrayIntMap ppKeywords) {
Lexer l= new Lexer(content, lexOptions, ILexerLog.NULL, null);
char[] guard= findIncludeGuard(l, ppKeywords);
if (guard != null && currentIfSpansFile(l, ppKeywords)) {
return guard;
}
return null;
}
private static char[] findIncludeGuard(Lexer l, CharArrayIntMap ppKeywords) {
try {
if (skipAll(l, Lexer.tNEWLINE).getType() == IToken.tPOUND) {
Token t = l.nextToken();
if (t.getType() == IToken.tIDENTIFIER) {
char[] guard= null;
switch(ppKeywords.get(t.getCharImage())) {
case IPreprocessorDirective.ppIfndef:
// #ifndef GUARD
t= l.nextToken();
if (t.getType() == IToken.tIDENTIFIER) {
guard= t.getCharImage();
}
break;
case IPreprocessorDirective.ppIf:
// #if !defined GUARD
// #if ((!((defined (GUARD)))))
guard = findNotDefined(l);
break;
}
if (guard != null) {
// #define GUARD
l.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
if (skipAll(l, Lexer.tNEWLINE).getType() == IToken.tPOUND
&& checkToken(l.nextToken(), Keywords.cDEFINE)
&& checkToken(l.nextToken(), guard)) {
l.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
return guard;
}
}
}
}
} catch (OffsetLimitReachedException e) {
}
return null;
}
private static char[] findNotDefined(Lexer l) throws OffsetLimitReachedException {
Token t;
if (skipAll(l, IToken.tLPAREN).getType() == IToken.tNOT
&& checkToken(skipAll(l, IToken.tLPAREN), Keywords.cDEFINED)) {
t= l.nextToken(); // only a single parenthesis is allowed
if (t.getType() == IToken.tLPAREN)
t= l.nextToken();
if (t.getType() == IToken.tIDENTIFIER) {
char[] guard= t.getCharImage();
if (skipAll(l, IToken.tRPAREN).getType() == Lexer.tNEWLINE)
return guard;
}
}
return null;
}
private static boolean checkToken(Token t, char[] image) throws OffsetLimitReachedException {
return CharArrayUtils.equals(t.getCharImage(), image);
}
private static boolean currentIfSpansFile(Lexer l, CharArrayIntMap ppKeywords) {
// Check if the #ifndef spans the entire file
try {
int nesting= 1;
while (nesting > 0) {
Token t= l.nextDirective();
if (t.getType() == IToken.tEND_OF_INPUT)
return true;
switch(ppKeywords.get(l.nextToken().getCharImage())) {
case IPreprocessorDirective.ppIf:
case IPreprocessorDirective.ppIfdef:
case IPreprocessorDirective.ppIfndef:
nesting++;
break;
case IPreprocessorDirective.ppEndif:
nesting--;
break;
}
}
l.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
return skipAll(l, Lexer.tNEWLINE).getType() == IToken.tEND_OF_INPUT;
} catch (OffsetLimitReachedException e) {
}
return true;
}
private static Token skipAll(Lexer l, int kind) throws OffsetLimitReachedException {
// Skip empty lines
Token t= l.nextToken();
while (t.getType() == kind)
t= l.nextToken();
return t;
}
public static boolean detectIncludeEndif(Lexer l) {
l.saveState();
try {
return findIncludeEndif(l);
} catch (OffsetLimitReachedException e) {
} finally {
l.restoreState();
}
return false;
}
private static boolean findIncludeEndif(Lexer l) throws OffsetLimitReachedException {
if (skipAll(l, Lexer.tNEWLINE).getType() != IToken.tPOUND)
return false;
if (!checkToken(l.nextToken(), Keywords.cINCLUDE))
return false;
l.consumeLine(ORIGIN_PREPROCESSOR_DIRECTIVE);
if (skipAll(l, Lexer.tNEWLINE).getType() != IToken.tPOUND)
return false;
if (!checkToken(l.nextToken(), Keywords.cENDIF))
return false;
return true;
}
public static char[] detectIfNotDefinedIncludeEndif(Lexer l) {
l.saveState();
try {
char[] guard= findNotDefined(l);
if (guard != null && findIncludeEndif(l))
return guard;
} catch (OffsetLimitReachedException e) {
} finally {
l.restoreState();
}
return null;
}
}

View file

@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.List;
import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDirective;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexMacro;
@ -43,6 +44,8 @@ public class InternalFileContent extends FileContent {
private final List<IIndexMacro> fMacroDefinitions;
private final List<ICPPUsingDirective> fUsingDirectives;
private final String fFileLocation;
private final IFileNomination fPragmaOnceNomination;
private final List<String> fNewPragmaOncePaths;
private boolean fHeuristic;
private boolean fIsSource= false;
private List<IIndexFile> fFiles;
@ -52,10 +55,11 @@ public class InternalFileContent extends FileContent {
* For skipping include files.
* @param fileLocation the location of the file.
* @param kind must be {@link InclusionKind#SKIP_FILE}.
* @param once
* @throws IllegalArgumentException if fileLocation is <code>null</code> or the kind value is illegal for
* this constructor.
*/
public InternalFileContent(String fileLocation, InclusionKind kind) throws IllegalArgumentException {
public InternalFileContent(String fileLocation, InclusionKind kind, IFileNomination once) throws IllegalArgumentException {
if (fileLocation == null || kind != InclusionKind.SKIP_FILE) {
throw new IllegalArgumentException();
}
@ -64,6 +68,8 @@ public class InternalFileContent extends FileContent {
fMacroDefinitions= null;
fUsingDirectives= null;
fSource= null;
fPragmaOnceNomination= once;
fNewPragmaOncePaths= null;
}
/**
@ -79,6 +85,8 @@ public class InternalFileContent extends FileContent {
fSource= content;
fMacroDefinitions= null;
fUsingDirectives= null;
fPragmaOnceNomination= null;
fNewPragmaOncePaths= null;
if (fFileLocation == null) {
throw new IllegalArgumentException();
}
@ -89,16 +97,19 @@ public class InternalFileContent extends FileContent {
* @param fileLocation the location of the file
* @param macroDefinitions a list of macro definitions
* @param files
* @param newPragmaOncePaths
* @throws IllegalArgumentException in case the fileLocation or the macroDefinitions are <code>null</code>.
*/
public InternalFileContent(String fileLocation, List<IIndexMacro> macroDefinitions, List<ICPPUsingDirective> usingDirectives,
List<IIndexFile> files) {
List<IIndexFile> files, List<String> newPragmaOncePaths) {
fKind= InclusionKind.FOUND_IN_INDEX;
fFileLocation= fileLocation;
fSource= null;
fUsingDirectives= usingDirectives;
fMacroDefinitions= macroDefinitions;
fFiles= files;
fPragmaOnceNomination= null;
fNewPragmaOncePaths= newPragmaOncePaths;
}
/**
@ -155,6 +166,10 @@ public class InternalFileContent extends FileContent {
public List<IIndexFile> getFilesIncluded() {
return fFiles;
}
public List<String> getPragmaOncePaths() {
return fNewPragmaOncePaths;
}
/**
* Returns whether this inclusion was found by a heuristics.
@ -183,6 +198,10 @@ public class InternalFileContent extends FileContent {
fFoundOnPath= isp;
}
public IFileNomination getPragmaOnceNomination() {
return fPragmaOnceNomination;
}
/**
* This method is slow. Use only for debugging.
*/

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2009 Wind River Systems, Inc. and others.
* Copyright (c) 2009, 2011 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
@ -7,14 +7,21 @@
*
* Contributors:
* Markus Schorn - initial API and implementation
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
import org.eclipse.cdt.internal.core.dom.IIncludeFileResolutionHeuristics;
import org.eclipse.cdt.internal.core.parser.IMacroDictionary;
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.InclusionKind;
/**
@ -22,20 +29,24 @@ import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.Inclusio
*/
public abstract class InternalFileContentProvider extends IncludeFileContentProvider {
private IIncludeFileResolutionHeuristics fIncludeResolutionHeuristics;
private final Map<String, IFileNomination> fPragmaOnce= new HashMap<String, IFileNomination>();
/**
* Check whether the specified inclusion exists.
* Checks whether the specified inclusion exists.
*/
public boolean getInclusionExists(String path) {
return new File(path).exists();
}
/**
* Create an InclusionContent object for the given location.
* return an inclusion content or <code>null</code> if the location does not exist.
* Creates an InclusionContent object for the given location.
* @param filePath the absolute location of the file.
* @param macroDictionary macros defined at the inclusion point.
* @return Returns an inclusion content, or <code>null</code> if the location does not exist.
* @see InternalFileContent
*/
public abstract InternalFileContent getContentForInclusion(String path);
public abstract InternalFileContent getContentForInclusion(String filePath,
IMacroDictionary macroDictionary);
/**
* Called only when used as a delegate of the index file content provider.
@ -46,28 +57,37 @@ public abstract class InternalFileContentProvider extends IncludeFileContentProv
* Returns a file-content object of kind {@link InclusionKind#FOUND_IN_INDEX}, representing
* the content from the context of the given file up to where the file actually gets included,
* or <code>null</code> if this cannot be done.
* @param filePath the absolute location of the file.
* @param macroDictionary macros defined at the inclusion point.
*/
public InternalFileContent getContentForContextToHeaderGap(String location) {
public InternalFileContent getContentForContextToHeaderGap(String filePath,
IMacroDictionary macroDictionary) {
return null;
}
/**
* Reports the path of the translation unit, such that it is known as included.
*/
public void reportTranslationUnitFile(String filePath) {
public void resetPragmaOnceTracking() {
fPragmaOnce.clear();
}
/**
* Returns whether or not the file has been included, or <code>null</code> if the content provider
* does not track that.
/**
* Reports detection of pragma once semantics.
*/
public Boolean hasFileBeenIncludedInCurrentTranslationUnit(String location) {
return null;
public void reportPragmaOnceSemantics(String file, IFileNomination nomination) {
fPragmaOnce.put(file, nomination);
}
/**
* Returns a strategy for heuristically resolving includes, or <code>null</code> if this shall not
* be done.
* Returns {@link IASTPreprocessorIncludeStatement} or {@link IIndexFile}, in
* case the file has been included using pragma once semantics,
* or <code>null</code> otherwise.
*/
public IFileNomination isIncludedWithPragmaOnceSemantics(String filePath) {
return fPragmaOnce.get(filePath);
}
/**
* Returns a strategy for heuristically resolving includes, or <code>null</code> if this shall
* not be done.
*/
public final IIncludeFileResolutionHeuristics getIncludeHeuristics() {
return fIncludeResolutionHeuristics;

View file

@ -85,10 +85,14 @@ final public class Lexer implements ITokenSequence {
private Token fToken;
private Token fLastToken;
// for the few cases where we have to lookahead more than one character
// For the few cases where we have to lookahead more than one character
private int fMarkOffset;
private int fMarkEndOffset;
private int fMarkPrefetchedChar;
// To store the entire state.
private boolean fMarkInsideIncludeDirective;
private Token fMarkToken;
private Token fMarkLastToken;
public Lexer(char[] input, LexerOptions options, ILexerLog log, Object source) {
this(new CharArray(input), 0, input.length, options, log, source);
@ -1256,4 +1260,22 @@ final public class Lexer implements ITokenSequence {
restorePhase3();
return result;
}
public void saveState() {
fMarkOffset= fOffset;
fMarkEndOffset= fEndOffset;
fMarkPrefetchedChar= fCharPhase3;
fMarkInsideIncludeDirective= fInsideIncludeDirective;
fMarkToken= fToken;
fMarkLastToken= fLastToken;
}
public void restoreState() {
fOffset= fMarkOffset;
fEndOffset= fMarkEndOffset;
fCharPhase3= fMarkPrefetchedChar;
fInsideIncludeDirective= fMarkInsideIncludeDirective;
fToken= fMarkToken;
fLastToken= fMarkLastToken;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2011 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
@ -30,8 +30,12 @@ import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit.IDependencyTree;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFileNomination;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTNodeSpecification;
import org.eclipse.cdt.internal.core.dom.parser.ASTProblem;
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
@ -130,7 +134,7 @@ public class LocationMap implements ILocationResolver {
int nameEndNumber= getSequenceNumberForOffset(nameEndOffset);
int endNumber= getSequenceNumberForOffset(endOffset);
final ASTInclusionStatement inclusionStatement=
new ASTInclusionStatement(fTranslationUnit, startNumber, nameNumber, nameEndNumber, endNumber, name, filename, userInclude, true, heuristic);
new ASTInclusionStatement(fTranslationUnit, startNumber, nameNumber, nameEndNumber, endNumber, name, filename, userInclude, true, heuristic, null);
fDirectives.add(inclusionStatement);
fCurrentContext= new LocationCtxFile((LocationCtxContainer) fCurrentContext, filename, buffer, startOffset, endOffset, endNumber, inclusionStatement, isSource);
fLastChildInsertionOffset= 0;
@ -205,7 +209,7 @@ public class LocationMap implements ILocationResolver {
* Ends the current context.
* @param locationCtx the current context, used to check whether caller and location map are still in sync.
*/
public void popContext(ILocationCtx locationCtx) {
public void popContext(ILocationCtx locationCtx, CharArrayObjectMap<char[]> sigMacros) {
assert fCurrentContext == locationCtx;
final LocationCtx child= fCurrentContext;
final LocationCtx parent= (LocationCtx) fCurrentContext.getParent();
@ -214,6 +218,18 @@ public class LocationMap implements ILocationResolver {
fLastChildInsertionOffset= child.fEndOffsetInParent;
parent.addChildSequenceLength(child.getSequenceLength());
}
if (sigMacros != null && locationCtx instanceof LocationCtxFile) {
ISignificantMacros sig = sigMacros.isEmpty() ? ISignificantMacros.NONE
: new SignificantMacros(sigMacros);
ASTInclusionStatement inc = ((LocationCtxFile) locationCtx).getInclusionStatement();
if (inc != null) {
inc.setSignificantMacros(sig);
} else if (locationCtx == fRootContext) {
if (fTranslationUnit != null) {
fTranslationUnit.setSignificantMacros(sig);
}
}
}
}
/**
@ -227,13 +243,15 @@ public class LocationMap implements ILocationResolver {
* @param active <code>true</code> when include appears in active code.
*/
public void encounterPoundInclude(int startOffset, int nameOffset, int nameEndOffset, int endOffset,
char[] name, String filename, boolean userInclude, boolean active, boolean heuristic) {
char[] name, String filename, boolean userInclude, boolean active, boolean heuristic,
IFileNomination nominationDelegate) {
startOffset= getSequenceNumberForOffset(startOffset);
nameOffset= getSequenceNumberForOffset(nameOffset);
nameEndOffset= getSequenceNumberForOffset(nameEndOffset);
endOffset= getSequenceNumberForOffset(endOffset);
fDirectives.add(new ASTInclusionStatement(fTranslationUnit, startOffset, nameOffset,
nameEndOffset, endOffset, name, filename, userInclude, active, heuristic));
final ASTInclusionStatement inc = new ASTInclusionStatement(fTranslationUnit, startOffset, nameOffset,
nameEndOffset, endOffset, name, filename, userInclude, active, heuristic, nominationDelegate);
fDirectives.add(inc);
}
public void encounteredComment(int offset, int endOffset, boolean isBlockComment) {
@ -743,10 +761,39 @@ public class LocationMap implements ILocationResolver {
}
}
public void replacingFile(InternalFileContentProvider fileContentProvider,
public void parsingFile(InternalFileContentProvider fileContentProvider,
InternalFileContent fileContent) {
for (ISkippedIndexedFilesListener l : fSkippedFilesListeners) {
l.replacingFile(fileContentProvider, fileContent);
l.parsingFile(fileContentProvider, fileContent);
}
}
}
public IFileNomination reportPragmaOnceSemantics(ILocationCtx locationCtx) {
if (locationCtx == fRootContext) {
if (fTranslationUnit != null) {
fTranslationUnit.setPragmaOnceSemantics(true);
}
return fTranslationUnit;
} else if (locationCtx instanceof LocationCtxFile) {
ASTInclusionStatement stmt = ((LocationCtxFile) locationCtx).getInclusionStatement();
if (stmt != null) {
stmt.setPragamOnceSemantics(true);
}
return stmt;
}
return null;
}
public void endTranslationUnit(int endOffset, CharArrayObjectMap<char[]> sigMacros) {
if (fTranslationUnit != null) {
int offset= getSequenceNumberForOffset(endOffset);
((ASTNode) fTranslationUnit).setLength(offset);
if (sigMacros != null) {
ISignificantMacros sig = sigMacros.isEmpty() ? ISignificantMacros.NONE
: new SignificantMacros(sigMacros);
fTranslationUnit.setSignificantMacros(sig);
}
}
}
}

View file

@ -136,6 +136,7 @@ public class MacroExpander {
private String fFixedCurrentFilename;
private int fFixedLineNumber;
private char[] fFixedInput;
private ScannerContext fReportMacros;
public MacroExpander(ILexerLog log, CharArrayMap<PreprocessorMacro> macroDictionary, LocationMap locationMap, LexerOptions lexOptions) {
fDictionary= macroDictionary;
@ -147,8 +148,12 @@ public class MacroExpander {
/**
* Expects that the identifier has been consumed, stores the result in the list provided.
* @param scannerContext
*/
public TokenList expand(ITokenSequence lexer, final boolean isPPCondition, PreprocessorMacro macro, Token identifier, boolean completionMode) throws OffsetLimitReachedException {
public TokenList expand(ITokenSequence lexer, final boolean isPPCondition,
PreprocessorMacro macro, Token identifier, boolean completionMode,
ScannerContext scannerContext) throws OffsetLimitReachedException {
fReportMacros= scannerContext;
fImplicitMacroExpansions.clear();
fImageLocationInfos.clear();
@ -180,6 +185,7 @@ public class MacroExpander {
result= e.getParameterTokens().cloneTokens();
}
postProcessTokens(result);
fReportMacros= null;
return result;
}
@ -193,6 +199,7 @@ public class MacroExpander {
fFixedInput= beforeExpansion.toCharArray();
fFixedCurrentFilename= filePath;
fFixedLineNumber= lineNumber;
fReportMacros= null;
Lexer lexer= new Lexer(fFixedInput, fLexOptions, fLog, this);
try {
@ -240,6 +247,9 @@ public class MacroExpander {
IdentityHashMap<PreprocessorMacro, PreprocessorMacro> forbidden, TokenSource input, TokenList result,
MacroExpansionTracker tracker)
throws OffsetLimitReachedException {
if (fReportMacros != null)
fReportMacros.significantMacro(macro);
if (macro.isFunctionStyle()) {
final int paramCount = macro.getParameterPlaceholderList().length;
final TokenSource[] argInputs= new TokenSource[paramCount];
@ -351,6 +361,13 @@ public class MacroExpander {
protect= true;
} else if (macro == null || (macro.isFunctionStyle() && !input.findLParenthesis())) {
// Tricky: Don't mark function-style macros if you don't find the left parenthesis
if (fReportMacros != null) {
if (macro == null) {
fReportMacros.significantMacroUndefined(image);
} else {
fReportMacros.significantMacro(macro);
}
}
result.append(t);
} else if (forbidden.containsKey(macro)) {
t.setType(CPreprocessor.tEXPANDED_IDENTIFIER); // prevent any further expansion

View file

@ -22,6 +22,7 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElifStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
@ -48,13 +49,14 @@ public class MultiMacroExpansionExplorer extends MacroExpansionExplorer {
fOffset= offset;
fLength= length;
}
public int getNodeOffset() {return fOffset;}
public int getNodeLength() {return fLength;}
public String getFileName() {return fFilePath;}
public int getNodeOffset() { return fOffset; }
public int getNodeLength() { return fLength; }
public String getFileName() { return fFilePath; }
public int getStartingLineNumber() {return 0;}
public int getEndingLineNumber() {return 0;}
public IASTFileLocation asFileLocation() {return this;}
public int getStartingLineNumber() { return 0; }
public int getEndingLineNumber() { return 0; }
public IASTFileLocation asFileLocation() { return this; }
public IASTPreprocessorIncludeStatement getContextInclusionStatement() { return null; }
}
private final char[] fSource;

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2011 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
@ -12,8 +12,12 @@ package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.ArrayList;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArraySet;
/**
* Represents part of the input to the preprocessor. This may be a file or the result of a macro expansion.
@ -43,6 +47,7 @@ final class ScannerContext {
}
private CodeState fInactiveState= CodeState.eSkipInactive;
private final int fDepth;
private final ILocationCtx fLocationCtx;
private final ScannerContext fParent;
private final Lexer fLexer;
@ -51,19 +56,32 @@ final class ScannerContext {
private CodeState fCurrentState= CodeState.eActive;
private IncludeSearchPathElement fFoundOnPath;
private String fFoundViaDirective;
private CharArraySet fInternalModifications;
private CharArrayObjectMap<char[]> fSignificantMacros;
private boolean fPragmaOnce;
/**
* @param ctx
* @param parent context to be used after this context is done.
*/
public ScannerContext(ILocationCtx ctx, ScannerContext parent, Lexer lexer) {
public ScannerContext(ILocationCtx ctx, ScannerContext parent, Lexer lexer,
boolean trackSignificantMacros) {
fLocationCtx= ctx;
fParent= parent;
fLexer= lexer;
fDepth = parent == null ? 0 : parent.fDepth+1;
if (trackSignificantMacros) {
fInternalModifications= new CharArraySet(5);
fSignificantMacros= new CharArrayObjectMap<char[]>(5);
} else {
fInternalModifications= null;
fSignificantMacros= null;
}
}
public ScannerContext(ILocationCtx ctx, ScannerContext parent, TokenList tokens) {
this(ctx, parent, (Lexer) null);
this(ctx, parent, null, false);
fTokens= tokens.first();
fInactiveState= CodeState.eSkipInactive; // no branches in result of macro expansion
}
@ -87,6 +105,13 @@ final class ScannerContext {
return fParent;
}
/**
* Returns the depth of this context, equals the number of parents of this context.
*/
public final int getDepth() {
return fDepth;
}
/**
* Returns the lexer for this context.
*/
@ -297,4 +322,130 @@ final class ScannerContext {
fFoundOnPath= foundOnPath;
fFoundViaDirective= viaDirective;
}
public void setPragmaOnce() {
fPragmaOnce= true;
}
public void internalModification(char[] macroName) {
if (fInternalModifications != null)
fInternalModifications.put(macroName);
}
public boolean hasInternalModification(char[] namechars) {
return fInternalModifications != null && fInternalModifications.containsKey(namechars);
}
public void significantMacro(IMacroBinding macro) {
if (fPragmaOnce)
return;
final char[] macroName= macro.getNameCharArray();
if (fInternalModifications != null && !fInternalModifications.containsKey(macroName)) {
fSignificantMacros.put(macroName, macro.getExpansion());
}
}
public void significantMacroDefined(char[] macroName) {
if (fPragmaOnce)
return;
if (fInternalModifications != null && !fInternalModifications.containsKey(macroName)) {
addSignificantMacroDefined(macroName);
}
}
private void addSignificantMacroDefined(char[] macroName) {
char[] old= fSignificantMacros.put(macroName, SignificantMacros.DEFINED);
if (old != null && old != SignificantMacros.DEFINED) {
// Put back more detailed condition
fSignificantMacros.put(macroName, old);
}
}
public void significantMacroUndefined(char[] macroName) {
if (fPragmaOnce)
return;
if (fInternalModifications != null && !fInternalModifications.containsKey(macroName)) {
fSignificantMacros.put(macroName, SignificantMacros.UNDEFINED);
}
}
public void addSignificantInclusion(String path) {
final char[] inc = path.toCharArray();
if (fInternalModifications != null && !fInternalModifications.containsKey(inc)) {
fSignificantMacros.put(inc, SignificantMacros.INCLUDED);
}
}
public CharArrayObjectMap<char[]> getSignificantMacros() {
return fSignificantMacros;
}
public void propagateSignificantMacros() {
if (fInternalModifications == null)
return;
if (fParent != null) {
final CharArraySet local = fParent.fInternalModifications;
if (local != null) {
final CharArrayObjectMap<char[]> significant = fParent.fSignificantMacros;
for (int i=0; i<fSignificantMacros.size(); i++) {
final char[] name = fSignificantMacros.keyAt(i);
if (!local.containsKey(name)) {
final char[] value= fSignificantMacros.getAt(i);
if (value == SignificantMacros.DEFINED) {
if (!local.containsKey(name)) {
fParent.addSignificantMacroDefined(name);
}
} else {
significant.put(name, value);
}
}
}
local.addAll(fInternalModifications);
}
}
fInternalModifications= null;
fSignificantMacros= null;
}
public boolean isSignificant(char[] macro) {
return fSignificantMacros != null && fSignificantMacros.containsKey(macro);
}
public void undoSignificance(char[] macro) {
if (fSignificantMacros != null)
fSignificantMacros.remove(macro, 0, macro.length);
}
public void addSignificantMacros(ISignificantMacros sm) {
if (fInternalModifications == null)
return;
sm.accept(new ISignificantMacros.IVisitor() {
public boolean visitValue(char[] macro, char[] value) {
if (!fInternalModifications.containsKey(macro)) {
fSignificantMacros.put(macro, value);
}
return true;
}
public boolean visitUndefined(char[] macro) {
if (!fInternalModifications.containsKey(macro)) {
fSignificantMacros.put(macro, SignificantMacros.UNDEFINED);
}
return true;
}
public boolean visitDefined(char[] macro) {
if (!fInternalModifications.containsKey(macro)) {
fSignificantMacros.put(macro, SignificantMacros.DEFINED);
}
return true;
}
public boolean visitIncluded(char[] path) {
if (!fInternalModifications.containsKey(path)) {
fSignificantMacros.put(path, SignificantMacros.INCLUDED);
}
return true;
}
});
}
}

View file

@ -0,0 +1,182 @@
/*******************************************************************************
* Copyright (c) 2011 Google, 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:
* Sergey Prigogin (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.parser.scanner;
import java.util.Arrays;
import java.util.Comparator;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
/**
* A set of static methods to encode Map<String, String> as an array of characters and to decode
* it back.
*
* The map is encoded as:
* <code>&lt;number_of_entries&gt;,&lt;key1&gt;&lt;value1&gt;...&lt;keyN&gt;&lt;valueN&gt;</code>.
* <p>
* Each string is encoded as: <code>&lt;number_of_characters&gt;,&lt;characters&gt;</code>.
* A <code>null</code> string is encoded as a single comma.
*/
public class SignificantMacros implements ISignificantMacros {
public static final char[] UNDEFINED = {};
public static final char[] DEFINED = {};
public static final char[] INCLUDED = {};
private static final int ENCODED_UNDEFINED = Character.MAX_VALUE;
private static final int ENCODED_DEFINED = Character.MAX_VALUE-1;
private static final int ENCODED_INCLUDED = Character.MAX_VALUE-2;
private static final Comparator<Object> SORTER = new Comparator<Object>() {
public int compare(Object o1, Object o2) {
return CharArrayUtils.compare((char[])o1, (char[])o2);
}
};
private final char[] fEncoded;
private int fHash;
public SignificantMacros(char[] encoded) {
assert encoded != null;
fEncoded= encoded;
}
public SignificantMacros(CharArrayObjectMap<char[]> sigMacros) {
fEncoded= encode(sigMacros);
}
private char[] encode(CharArrayObjectMap<char[]> sigMacros) {
StringBuilder buffer= new StringBuilder();
Object[] keys= sigMacros.keyArray();
Arrays.sort(keys, SORTER);
for (Object key : keys) {
char[] name= (char[]) key;
char[] value= sigMacros.get(name);
buffer.append((char) name.length).append(name);
if (value == DEFINED) {
buffer.append((char) ENCODED_DEFINED);
} else if (value == UNDEFINED) {
buffer.append((char) ENCODED_UNDEFINED);
} else if (value == INCLUDED) {
buffer.append((char) ENCODED_INCLUDED);
} else {
buffer.append((char) value.length).append(value);
}
}
int len= buffer.length();
char[] result= new char[len];
buffer.getChars(0, len, result, 0);
return result;
}
@Override
public int hashCode() {
int h = fHash;
if (h == 0) {
char val[] = fEncoded;
int len = fEncoded.length;
for (int i = 0; i < len; i++) {
h = 31*h + val[i];
}
fHash = h;
}
return h;
}
@Override
public boolean equals(Object obj) {
return obj instanceof SignificantMacros
&& hashCode() == obj.hashCode()
&& CharArrayUtils.equals(fEncoded, ((SignificantMacros) obj).fEncoded);
}
public boolean accept(IVisitor visitor) {
final char[] encoded = fEncoded;
final int len = encoded.length;
int i= 0;
while (i < len) {
final int len1 = encoded[i++];
int v= i + len1;
if (v >= len)
break;
char[] macro= extract(encoded, i, len1);
final int len2 = encoded[v++];
switch(len2) {
case ENCODED_UNDEFINED:
i= v;
if (!visitor.visitUndefined(macro))
return false;
break;
case ENCODED_DEFINED:
i= v;
if (!visitor.visitDefined(macro))
return false;
break;
case ENCODED_INCLUDED:
i= v;
if (!visitor.visitIncluded(macro))
return false;
break;
default:
i= v+len2;
if (i > len)
break;
if (!visitor.visitValue(macro, extract(encoded, v, len2)))
return false;
break;
}
}
return true;
}
public char[] extract(final char[] source, int from, final int length) {
char[] value= new char[length];
System.arraycopy(source, from, value, 0, length);
return value;
}
public char[] encode() {
return fEncoded;
}
/**
* For debugging purposes.
*/
@SuppressWarnings("nls")
@Override
public String toString() {
final StringBuilder buf= new StringBuilder();
buf.append('{');
accept(new IVisitor() {
public boolean visitValue(char[] macro, char[] value) {
buf.append(macro).append('=').append(value).append(',');
return true;
}
public boolean visitUndefined(char[] macro) {
buf.append(macro).append('=').append("null,");
return true;
}
public boolean visitIncluded(char[] path) {
buf.append(path).append(',');
return true;
}
public boolean visitDefined(char[] macro) {
buf.append(macro).append('=').append("*,");
return true;
}
});
int buflen = buf.length();
if (buflen > 1)
buf.setLength(buflen-1);
buf.append('}');
return buf.toString();
}
}

View file

@ -56,6 +56,7 @@ import org.eclipse.cdt.core.index.IIndexLocationConverter;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IIndexMacroContainer;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.Linkage;
@ -210,10 +211,11 @@ public class PDOM extends PlatformObject implements IPDOM {
* CDT 8.1 development (versions not supported on teh 8.0.x branch)
* 120.0 - Enumerators in global index, bug 356235
* 120.1 - Specializations of using declarations, bug 357293.
* 121.0 - Multiple variants of included header file, bug 197989.
*/
private static final int MIN_SUPPORTED_VERSION= version(120, 0);
private static final int MAX_SUPPORTED_VERSION= version(120, Short.MAX_VALUE);
private static final int DEFAULT_VERSION = version(120, 1);
private static final int MIN_SUPPORTED_VERSION= version(121, 0);
private static final int MAX_SUPPORTED_VERSION= version(121, Short.MAX_VALUE);
private static final int DEFAULT_VERSION = version(121, 0);
private static int version(int major, int minor) {
return (major << 16) + minor;
@ -419,6 +421,7 @@ public class PDOM extends PlatformObject implements IPDOM {
return fileIndex;
}
@Deprecated
public PDOMFile getFile(int linkageID, IIndexFileLocation location) throws CoreException {
PDOMLinkage linkage= getLinkage(linkageID);
if (linkage == null)
@ -426,8 +429,25 @@ public class PDOM extends PlatformObject implements IPDOM {
return PDOMFile.findFile(linkage, getFileIndex(), location, locationConverter);
}
public PDOMFile getFile(PDOMLinkage linkage, IIndexFileLocation location) throws CoreException {
return PDOMFile.findFile(linkage, getFileIndex(), location, locationConverter);
public PDOMFile getFile(int linkageID, IIndexFileLocation location,
ISignificantMacros macroDictionary) throws CoreException {
PDOMLinkage linkage= getLinkage(linkageID);
if (linkage == null)
return null;
return PDOMFile.findFile(linkage, getFileIndex(), location, locationConverter,
macroDictionary);
}
public PDOMFile getFile(PDOMLinkage linkage, IIndexFileLocation location,
ISignificantMacros macroDictionary) throws CoreException {
return PDOMFile.findFile(linkage, getFileIndex(), location, locationConverter, macroDictionary);
}
public IIndexFragmentFile[] getFiles(int linkageID, IIndexFileLocation location) throws CoreException {
PDOMLinkage linkage= getLinkage(linkageID);
if (linkage == null)
return IIndexFragmentFile.EMPTY_ARRAY;
return PDOMFile.findFiles(linkage, getFileIndex(), location, locationConverter);
}
public IIndexFragmentFile[] getFiles(IIndexFileLocation location) throws CoreException {
@ -436,7 +456,7 @@ public class PDOM extends PlatformObject implements IPDOM {
public IIndexFragmentFile[] getAllFiles() throws CoreException {
final List<PDOMFile> locations = new ArrayList<PDOMFile>();
getFileIndex().accept(new IBTreeVisitor(){
getFileIndex().accept(new IBTreeVisitor() {
public int compare(long record) throws CoreException {
return 0;
}
@ -449,11 +469,12 @@ public class PDOM extends PlatformObject implements IPDOM {
return locations.toArray(new IIndexFragmentFile[locations.size()]);
}
protected IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException {
protected IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location,
ISignificantMacros sigMacros) throws CoreException {
PDOMLinkage linkage= createLinkage(linkageID);
IIndexFragmentFile file = getFile(linkage, location);
IIndexFragmentFile file = getFile(linkage, location, sigMacros);
if (file == null) {
PDOMFile pdomFile = new PDOMFile(linkage, location, linkageID);
PDOMFile pdomFile = new PDOMFile(linkage, location, linkageID, sigMacros);
getFileIndex().insert(pdomFile.getRecord());
file= pdomFile;
fEvent.setHasNewFiles();
@ -1077,7 +1098,7 @@ public class PDOM extends PlatformObject implements IPDOM {
return (PDOMFile) file;
}
return getFile(file.getLinkageID(), file.getLocation());
return getFile(file.getLinkageID(), file.getLocation(), file.getSignificantMacros());
}
public File getPath() {

View file

@ -28,6 +28,11 @@ public class PDOMFileSet implements IIndexFragmentFileSet {
fFileIDs.add(pdomFile.getRecord());
}
public void remove(IIndexFragmentFile fragFile) {
PDOMFile pdomFile= (PDOMFile) fragFile;
fFileIDs.remove(pdomFile.getRecord());
}
public boolean containsFileOfLocalBinding(IIndexFragmentBinding fb) throws CoreException {
PDOMBinding pdomBinding= (PDOMBinding) fb;
return fFileIDs.contains(pdomBinding.getLocalToFileRec());

View file

@ -24,6 +24,7 @@ import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexLinkage;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFileSet;
@ -53,6 +54,7 @@ public class PDOMProxy implements IPDOM {
fLockDebugging= new HashMap<Thread, DebugLockInfo>();
}
}
public synchronized void acquireReadLock() throws InterruptedException {
if (fDelegate != null) {
fDelegate.acquireReadLock();
@ -152,6 +154,7 @@ public class PDOMProxy implements IPDOM {
return 0;
}
@Deprecated
public synchronized IIndexFragmentFile getFile(int linkageID, IIndexFileLocation location) throws CoreException {
if (fDelegate != null)
return fDelegate.getFile(linkageID, location);
@ -159,6 +162,22 @@ public class PDOMProxy implements IPDOM {
return null;
}
public IIndexFragmentFile getFile(int linkageID, IIndexFileLocation location,
ISignificantMacros sigMacros) throws CoreException {
if (fDelegate != null)
return fDelegate.getFile(linkageID, location, sigMacros);
return null;
}
public IIndexFragmentFile[] getFiles(int linkageID, IIndexFileLocation location)
throws CoreException {
if (fDelegate != null)
return fDelegate.getFiles(linkageID, location);
return IIndexFragmentFile.EMPTY_ARRAY;
}
public synchronized IIndexFragmentFile[] getFiles(IIndexFileLocation location) throws CoreException {
if (fDelegate != null)
return fDelegate.getFiles(location);
@ -289,10 +308,12 @@ public class PDOMProxy implements IPDOM {
public Object putCachedResult(Object key, Object value, boolean replace) {
return value;
}
public void clearResultCache() {
if (fDelegate != null)
fDelegate.clearResultCache();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.index.IIndexFragment#getInlineNamespaces()
*/

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2007, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2007, 2011 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
@ -13,7 +13,6 @@
package org.eclipse.cdt.internal.core.pdom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@ -50,8 +49,10 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.parser.IProblem;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.cdt.internal.core.index.FileContentKey;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IWritableIndex;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
@ -70,6 +71,20 @@ import org.eclipse.osgi.util.NLS;
* @since 4.0
*/
abstract public class PDOMWriter {
public static class FileInAST {
public FileInAST(IASTPreprocessorIncludeStatement includeStmt, FileContentKey key) {
fIncludeStatement= includeStmt;
fFileContentKey= key;
}
final IASTPreprocessorIncludeStatement fIncludeStatement;
final FileContentKey fFileContentKey;
@Override
public String toString() {
return fFileContentKey.toString();
}
}
public static int SKIP_ALL_REFERENCES= -1;
public static int SKIP_TYPE_REFERENCES= 1;
public static int SKIP_MACRO_REFERENCES= 2;
@ -77,9 +92,24 @@ abstract public class PDOMWriter {
public static int SKIP_NO_REFERENCES= 0;
private static class Symbols {
ArrayList<IASTName[]> fNames= new ArrayList<IASTName[]>();
ArrayList<IASTPreprocessorStatement> fMacros= new ArrayList<IASTPreprocessorStatement>();
ArrayList<IASTPreprocessorIncludeStatement> fIncludes= new ArrayList<IASTPreprocessorIncludeStatement>();
final ArrayList<IASTName[]> fNames= new ArrayList<IASTName[]>();
final ArrayList<IASTPreprocessorStatement> fMacros= new ArrayList<IASTPreprocessorStatement>();
final ArrayList<IASTPreprocessorIncludeStatement> fIncludes= new ArrayList<IASTPreprocessorIncludeStatement>();
}
private static class Data {
final IASTTranslationUnit fAST;
final FileInAST[] fSelectedFiles;
final IWritableIndex fIndex;
final Map<IASTPreprocessorIncludeStatement, Symbols> fSymbolMap = new HashMap<IASTPreprocessorIncludeStatement, Symbols>();
final Set<IASTPreprocessorIncludeStatement> fContextIncludes = new HashSet<IASTPreprocessorIncludeStatement>();
final List<IStatus> fStati= new ArrayList<IStatus>();
public Data(IASTTranslationUnit ast, FileInAST[] selectedFiles, IWritableIndex index) {
fAST= ast;
fSelectedFiles= selectedFiles;
fIndex= index;
}
}
private boolean fShowProblems;
@ -90,7 +120,6 @@ abstract public class PDOMWriter {
protected final IndexerStatistics fStatistics;
protected final IndexerInputAdapter fResolver;
private IndexerProgress fInfo= new IndexerProgress();
private int fSkipReferences= SKIP_NO_REFERENCES;
public PDOMWriter(IndexerInputAdapter resolver) {
@ -140,39 +169,44 @@ abstract public class PDOMWriter {
*
* When flushIndex is set to <code>false</code>, you must make sure to flush
* the index after your last write operation.
* @since 4.0
*/
public void addSymbols(IASTTranslationUnit ast, IIndexFileLocation[] ifls, IWritableIndex index,
int readlockCount, boolean flushIndex, long fileContentsHash, int configHash,
public void addSymbols(IASTTranslationUnit ast, FileInAST[] selectedFiles, IWritableIndex index,
int readlockCount, boolean flushIndex, long fileContentsHash,
ITodoTaskUpdater taskUpdater, IProgressMonitor pm) throws InterruptedException, CoreException {
if (fShowProblems) {
fShowInclusionProblems= true;
fShowScannerProblems= true;
fShowSyntaxProblems= true;
}
final Map<IIndexFileLocation, Symbols> symbolMap= new HashMap<IIndexFileLocation, Symbols>();
for (IIndexFileLocation ifl : ifls) {
prepareInMap(symbolMap, ifl);
Data info= new Data(ast, selectedFiles, index);
for (FileInAST file : selectedFiles) {
info.fSymbolMap.put(file.fIncludeStatement, new Symbols());
}
ArrayList<IStatus> stati= new ArrayList<IStatus>();
HashSet<IASTPreprocessorIncludeStatement> contextIncludes= new HashSet<IASTPreprocessorIncludeStatement>();
extractSymbols(ast, symbolMap, contextIncludes);
// Extract symbols from AST
extractSymbols(info);
// name resolution
resolveNames(symbolMap, ifls, stati, pm);
// Name resolution
resolveNames(info, pm);
// index update
storeSymbolsInIndex(symbolMap, ifls, ast.getLinkage().getLinkageID(), fileContentsHash,
configHash, contextIncludes, index, readlockCount, flushIndex, stati, pm);
// Index update
storeSymbolsInIndex(info, fileContentsHash, readlockCount, flushIndex, pm);
// Tasks update
if (taskUpdater != null) {
taskUpdater.updateTasks(ast.getComments(), ifls);
Set<IIndexFileLocation> locations= new HashSet<IIndexFileLocation>();
for (FileInAST file : selectedFiles) {
locations.add(file.fFileContentKey.getLocation());
}
taskUpdater.updateTasks(ast.getComments(), locations.toArray(new IIndexFileLocation[locations.size()]));
}
if (!stati.isEmpty()) {
if (!info.fStati.isEmpty()) {
List<IStatus> stati = info.fStati;
String path= null;
if (ifls.length > 0) {
path= ifls[ifls.length - 1].getURI().getPath();
if (selectedFiles.length > 0) {
path= selectedFiles[selectedFiles.length - 1].fFileContentKey.getLocation().getURI().getPath();
} else {
path= ast.getFilePath().toString();
}
@ -190,26 +224,24 @@ abstract public class PDOMWriter {
}
}
private void storeSymbolsInIndex(final Map<IIndexFileLocation, Symbols> symbolMap, IIndexFileLocation[] ifls,
int linkageID, long fileContentsHash, int configHash,
HashSet<IASTPreprocessorIncludeStatement> contextIncludes, IWritableIndex index, int readlockCount,
boolean flushIndex, ArrayList<IStatus> stati, IProgressMonitor pm)
throws InterruptedException, CoreException {
for (int i= 0; i < ifls.length; i++) {
private void storeSymbolsInIndex(final Data data, long fileContentsHash, int readlockCount,
boolean flushIndex, IProgressMonitor pm) throws InterruptedException, CoreException {
final int linkageID= data.fAST.getLinkage().getLinkageID();
for (int i= 0; i < data.fSelectedFiles.length; i++) {
if (pm.isCanceled())
return;
final IIndexFileLocation ifl= ifls[i];
if (ifl != null) {
final FileInAST file= data.fSelectedFiles[i];
if (file != null) {
if (fShowActivity) {
trace("Indexer: adding " + ifl.getURI()); //$NON-NLS-1$
trace("Indexer: adding " + file.fFileContentKey.getLocation().getURI()); //$NON-NLS-1$
}
Throwable th= null;
YieldableIndexLock lock = new YieldableIndexLock(index, readlockCount, flushIndex);
YieldableIndexLock lock = new YieldableIndexLock(data.fIndex, readlockCount, flushIndex);
lock.acquire();
try {
storeFileInIndex(index, ifl, symbolMap, linkageID, fileContentsHash, configHash,
contextIncludes, lock);
IIndexFragmentFile ifile= storeFileInIndex(data, file, linkageID, fileContentsHash, lock);
reportFileWrittenToIndex(file, ifile);
} catch (RuntimeException e) {
th= e;
} catch (StackOverflowError e) {
@ -219,31 +251,27 @@ abstract public class PDOMWriter {
} finally {
// When the caller holds a read-lock, the result cache of the index is never cleared.
// ==> Before releasing the lock for the last time in this ast, we clear the result cache.
if (readlockCount > 0 && i == ifls.length-1) {
index.clearResultCache();
if (readlockCount > 0 && i == data.fSelectedFiles.length-1) {
data.fIndex.clearResultCache();
}
lock.release();
}
if (th != null) {
stati.add(createStatus(NLS.bind(Messages.PDOMWriter_errorWhileParsing,
ifl.getURI().getPath()), th));
}
if (i < ifls.length - 1) {
updateFileCount(0, 0, 1); // update header count
data.fStati.add(createStatus(NLS.bind(Messages.PDOMWriter_errorWhileParsing,
file.fFileContentKey.getLocation().getURI().getPath()), th));
}
fStatistics.fAddToIndexTime += lock.getCumulativeLockTime();
}
}
}
private void resolveNames(final Map<IIndexFileLocation, Symbols> symbolMap, IIndexFileLocation[] ifls,
ArrayList<IStatus> stati, IProgressMonitor pm) {
private void resolveNames(Data data, IProgressMonitor pm) {
long start= System.currentTimeMillis();
for (IIndexFileLocation path : ifls) {
for (FileInAST file : data.fSelectedFiles) {
if (pm.isCanceled()) {
return;
}
Symbols symbols= symbolMap.get(path);
Symbols symbols= data.fSymbolMap.get(file.fIncludeStatement);
final ArrayList<IASTName[]> names= symbols.fNames;
boolean reported= false;
@ -286,8 +314,8 @@ abstract public class PDOMWriter {
}
if (th != null) {
if (!reported) {
stati.add(CCorePlugin.createStatus(NLS.bind(Messages.PDOMWriter_errorResolvingName,
name.toString(), path.getURI().getPath()), th));
data.fStati.add(CCorePlugin.createStatus(NLS.bind(Messages.PDOMWriter_errorResolvingName,
name.toString(), file.fFileContentKey.getLocation().getURI().getPath()), th));
}
reported= true;
j.remove();
@ -298,45 +326,44 @@ abstract public class PDOMWriter {
fStatistics.fResolutionTime += System.currentTimeMillis()-start;
}
private void extractSymbols(IASTTranslationUnit ast, final Map<IIndexFileLocation, Symbols> symbolMap,
Collection<IASTPreprocessorIncludeStatement> contextIncludes) throws CoreException {
final HashSet<IIndexFileLocation> contextIFLs= new HashSet<IIndexFileLocation>();
final IIndexFileLocation astIFL = fResolver.resolveASTPath(ast.getFilePath());
private void extractSymbols(Data data) throws CoreException {
int unresolvedIncludes= 0;
final IASTTranslationUnit ast = data.fAST;
final Map<IASTPreprocessorIncludeStatement, Symbols> symbolMap = data.fSymbolMap;
IASTPreprocessorStatement[] stmts = ast.getAllPreprocessorStatements();
for (final IASTPreprocessorStatement stmt : stmts) {
// includes
// Includes.
if (stmt instanceof IASTPreprocessorIncludeStatement) {
IASTPreprocessorIncludeStatement include= (IASTPreprocessorIncludeStatement) stmt;
final IASTFileLocation astLoc= include.getFileLocation();
final IIndexFileLocation sourceIFL= astLoc != null ? fResolver.resolveASTPath(astLoc.getFileName()) : astIFL; // command-line includes
final boolean updateSource= symbolMap.containsKey(sourceIFL);
IASTPreprocessorIncludeStatement owner = astLoc.getContextInclusionStatement();
final boolean updateSource= symbolMap.containsKey(owner);
if (updateSource) {
addToMap(symbolMap, sourceIFL, include);
addToMap(symbolMap, owner, include);
}
if (include.isActive()) {
if (!include.isResolved()) {
unresolvedIncludes++;
} else if (updateSource) {
// the include was parsed, check if we want to update the included file in the index
final IIndexFileLocation targetIFL= fResolver.resolveASTPath(include.getPath());
if (symbolMap.containsKey(targetIFL) && contextIFLs.add(targetIFL)) {
contextIncludes.add(include);
// The include was parsed, check if we want to update the included file in the index.
if (symbolMap.containsKey(include)) {
data.fContextIncludes.add(include);
}
}
}
} else if (stmt.isActive() && (stmt instanceof IASTPreprocessorUndefStatement || stmt instanceof IASTPreprocessorMacroDefinition)) {
} else if (stmt.isActive() &&
(stmt instanceof IASTPreprocessorUndefStatement || stmt instanceof IASTPreprocessorMacroDefinition)) {
IASTFileLocation sourceLoc = stmt.getFileLocation();
if (sourceLoc != null) { // skip built-ins and command line macros
IIndexFileLocation path2 = fResolver.resolveASTPath(sourceLoc.getFileName());
addToMap(symbolMap, path2, stmt);
IASTPreprocessorIncludeStatement owner = sourceLoc.getContextInclusionStatement();
addToMap(symbolMap, owner, stmt);
}
}
}
// names
// Names.
final IndexerASTVisitor visitor = new IndexerASTVisitor((fSkipReferences & SKIP_IMPLICIT_REFERENCES) == 0) {
@Override
public void visit(IASTName name, IASTName caller) {
@ -348,13 +375,13 @@ abstract public class PDOMWriter {
}
}
// assign a location to anonymous types.
// Assign a location to anonymous types.
name= PDOMASTAdapter.getAdapterIfAnonymous(name);
if (name != null) {
IASTFileLocation nameLoc = name.getFileLocation();
if (nameLoc != null) {
IIndexFileLocation location = fResolver.resolveASTPath(nameLoc.getFileName());
addToMap(symbolMap, location, new IASTName[]{name, caller});
IASTPreprocessorIncludeStatement owner= nameLoc.getContextInclusionStatement();
addToMap(symbolMap, owner, new IASTName[] { name, caller });
}
}
}
@ -368,8 +395,8 @@ abstract public class PDOMWriter {
for (IASTName name : refs) {
IASTFileLocation nameLoc = name.getFileLocation();
if (nameLoc != null) {
IIndexFileLocation location = fResolver.resolveASTPath(nameLoc.getFileName());
addToMap(symbolMap, location, new IASTName[]{name, null});
IASTPreprocessorIncludeStatement owner= nameLoc.getContextInclusionStatement();
addToMap(symbolMap, owner, new IASTName[] { name, null });
}
}
}
@ -426,44 +453,41 @@ abstract public class PDOMWriter {
return false;
}
private void addToMap(Map<IIndexFileLocation, Symbols> map, IIndexFileLocation location, IASTName[] thing) {
Symbols lists= map.get(location);
private void addToMap(Map<IASTPreprocessorIncludeStatement, Symbols> symbolMap, IASTPreprocessorIncludeStatement owner, IASTName[] thing) {
Symbols lists= symbolMap.get(owner);
if (lists != null)
lists.fNames.add(thing);
}
private void addToMap(Map<IIndexFileLocation, Symbols> map, IIndexFileLocation location,
IASTPreprocessorIncludeStatement thing) {
Symbols lists= map.get(location);
private void addToMap(Map<IASTPreprocessorIncludeStatement, Symbols> symbolMap, IASTPreprocessorIncludeStatement owner, IASTPreprocessorIncludeStatement thing) {
Symbols lists= symbolMap.get(owner);
if (lists != null)
lists.fIncludes.add(thing);
}
private void addToMap(Map<IIndexFileLocation, Symbols> map, IIndexFileLocation location,
IASTPreprocessorStatement thing) {
Symbols lists= map.get(location);
private void addToMap(Map<IASTPreprocessorIncludeStatement, Symbols> symbolMap,
IASTPreprocessorIncludeStatement owner, IASTPreprocessorStatement thing) {
Symbols lists= symbolMap.get(owner);
if (lists != null)
lists.fMacros.add(thing);
}
private boolean prepareInMap(Map<IIndexFileLocation, Symbols> map, IIndexFileLocation location) {
if (map.get(location) == null) {
map.put(location, new Symbols());
}
return false;
}
private IIndexFragmentFile storeFileInIndex(IWritableIndex index, IIndexFileLocation location,
Map<IIndexFileLocation, Symbols> symbolMap, int linkageID, long fileContentsHash,
int configHash, Set<IASTPreprocessorIncludeStatement> contextIncludes,
YieldableIndexLock lock) throws CoreException, InterruptedException {
private IIndexFragmentFile storeFileInIndex(Data data, FileInAST astFile, int linkageID,
long fileContentsHash, YieldableIndexLock lock) throws CoreException,
InterruptedException {
final IWritableIndex index = data.fIndex;
Set<IIndexFileLocation> clearedContexts= Collections.emptySet();
IIndexFragmentFile file;
// We create a temporary PDOMFile with zero timestamp, add names to it, then replace contents
// of the old file from the temporary one, then delete the temporary file. The write lock on
// the index can be yielded between adding names to the temporary file, if another thread
// is waiting for a read lock.
IIndexFragmentFile oldFile = index.getWritableFile(linkageID, location);
// We create a temporary PDOMFile with zero timestamp, add names to it, then replace
// contents of the old file from the temporary one, then delete the temporary file.
// The write lock on the index can be yielded between adding names to the temporary file,
// if another thread is waiting for a read lock.
final FileContentKey fileKey = astFile.fFileContentKey;
final IASTPreprocessorIncludeStatement owner= astFile.fIncludeStatement;
IIndexFileLocation location = fileKey.getLocation();
ISignificantMacros significantMacros = fileKey.getSignificantMacros();
IIndexFragmentFile oldFile = index.getWritableFile(linkageID, location, significantMacros);
if (oldFile != null) {
IIndexInclude[] includedBy = index.findIncludedBy(oldFile);
if (includedBy.length > 0) {
@ -473,10 +497,12 @@ abstract public class PDOMWriter {
}
}
}
file= index.addUncommittedFile(linkageID, location);
file= index.addUncommittedFile(linkageID, location, significantMacros);
try {
file.setScannerConfigurationHashcode(configHash);
Symbols lists= symbolMap.get(location);
boolean pragmaOnce= owner != null ? owner.hasPragmaOnceSemantics() : data.fAST.hasPragmaOnceSemantics();
file.setPragmaOnceSemantics(pragmaOnce);
Symbols lists= data.fSymbolMap.get(owner);
if (lists != null) {
IASTPreprocessorStatement[] macros= lists.fMacros.toArray(new IASTPreprocessorStatement[lists.fMacros.size()]);
IASTName[][] names= lists.fNames.toArray(new IASTName[lists.fNames.size()][]);
@ -495,7 +521,7 @@ abstract public class PDOMWriter {
if (include.isResolved()) {
info.fLocation= fResolver.resolveASTPath(include.getPath());
info.fIsContext= include.isActive() &&
(contextIncludes.contains(include) || clearedContexts.contains(info.fLocation));
(data.fContextIncludes.contains(include) || clearedContexts.contains(info.fLocation));
}
}
index.setFileContent(file, linkageID, includeInfos, macros, names, fResolver, lock);
@ -511,34 +537,9 @@ abstract public class PDOMWriter {
}
/**
* Makes a copy of the current progress information and returns it.
* @since 4.0
* Informs the subclass that a file has been stored in the index.
*/
public IndexerProgress getProgressInformation() {
synchronized (fInfo) {
return new IndexerProgress(fInfo);
}
}
/**
* Updates current progress information with the provided delta.
*/
protected final void updateFileCount(int sources, int primaryHeader, int header) {
synchronized (fInfo) {
fInfo.fCompletedSources += sources;
fInfo.fPrimaryHeaderCount += primaryHeader;
fInfo.fCompletedHeaders += header;
}
}
/**
* Updates current progress information with the provided delta.
*/
protected final void incrementRequestedFilesCount(int delta) {
synchronized (fInfo) {
fInfo.fRequestedFilesCount += delta;
}
}
protected abstract void reportFileWrittenToIndex(FileInAST file, IIndexFragmentFile ifile);
private String getLocationInfo(String filename, int lineNumber) {
return " at " + filename + "(" + lineNumber + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

View file

@ -275,7 +275,6 @@ public class TeamPDOMImportOperation implements IWorkspaceRunnable {
IResource r= fc.fFile.getResource();
if (r != null) {
file.setTimestamp(r.getLocalTimeStamp());
file.setScannerConfigurationHashcode(0);
}
}
}

View file

@ -1,14 +1,14 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems, Inc. and others.
* Copyright (c) 2006, 2011 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
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
* Markus Schorn - initial API and implementation
* Andrew Ferguson (Symbian)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom;
@ -18,14 +18,20 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.index.IIndexFileLocation;
import org.eclipse.cdt.core.index.IIndexLocationConverter;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.index.FileContentKey;
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.index.IWritableIndex.IncludeInformation;
import org.eclipse.cdt.internal.core.index.IWritableIndexFragment;
import org.eclipse.cdt.internal.core.pdom.db.BTree;
import org.eclipse.cdt.internal.core.pdom.db.ChunkCache;
import org.eclipse.cdt.internal.core.pdom.db.DBProperties;
@ -45,7 +51,7 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
private ASTFilePathResolver fPathResolver;
private PDOMFile fileBeingUpdated;
private PDOMFile uncommittedFile;
private IIndexFileLocation uncommittedLocation;
private FileContentKey uncommittedKey;
public WritablePDOM(File dbPath, IIndexLocationConverter locationConverter,
Map<String, IPDOMLinkageFactory> linkageFactoryMappings) throws CoreException {
@ -62,39 +68,43 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
}
@Override
public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location) throws CoreException {
if (uncommittedLocation != null && uncommittedLocation.equals(location)) {
public IIndexFragmentFile addFile(int linkageID, IIndexFileLocation location, ISignificantMacros sigMacros) throws CoreException {
if (uncommittedKey != null && uncommittedKey.equals(new FileContentKey(linkageID, location, sigMacros)))
return uncommittedFile;
}
return super.addFile(linkageID, location);
return super.addFile(linkageID, location, sigMacros);
}
public IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location) throws CoreException {
uncommittedLocation = location;
fileBeingUpdated = getFile(linkageID, uncommittedLocation);
public IIndexFragmentFile addUncommittedFile(int linkageID, IIndexFileLocation location,
ISignificantMacros significantMacros) throws CoreException {
uncommittedKey = new FileContentKey(linkageID, location, significantMacros);
fileBeingUpdated = getFile(linkageID, location, significantMacros);
PDOMLinkage linkage= createLinkage(linkageID);
uncommittedFile = new PDOMFile(linkage, location, linkageID);
uncommittedFile = new PDOMFile(linkage, location, linkageID, significantMacros);
return uncommittedFile;
}
public IIndexFragmentFile commitUncommittedFile() throws CoreException {
if (uncommittedFile == null)
return null;
IIndexFragmentFile file;
PDOMFile file;
BTree fileIndex = getFileIndex();
if (fileBeingUpdated == null) {
// New file.
BTree fileIndex = getFileIndex();
fileIndex.insert(uncommittedFile.getRecord());
file = uncommittedFile;
} else {
// Existing file.
// Remove the file from the index before replacing its contents since position of
// the file in the index is content-dependent.
fileIndex.delete(fileBeingUpdated.getRecord());
fileBeingUpdated.replaceContentsFrom(uncommittedFile);
file = fileBeingUpdated;
fileBeingUpdated = null;
}
fEvent.fFilesWritten.add(uncommittedLocation);
fileIndex.insert(file.getRecord()); // Insert the file to the file index.
fEvent.fFilesWritten.add(uncommittedKey.getLocation());
uncommittedFile = null;
uncommittedLocation = null;
uncommittedKey = null;
return file;
}
@ -105,7 +115,7 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
uncommittedFile.delete();
} finally {
uncommittedFile = null;
uncommittedLocation = null;
uncommittedKey = null;
fileBeingUpdated = null;
}
}
@ -137,9 +147,11 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
public void clearFile(IIndexFragmentFile file, Collection<IIndexFileLocation> contextsRemoved)
throws CoreException {
assert file.getIndexFragment() == this;
((PDOMFile) file).clear(contextsRemoved);
fEvent.fClearedFiles.add(file.getLocation());
IIndexFileLocation location = file.getLocation();
PDOMFile pdomFile = (PDOMFile) file;
pdomFile.clear(contextsRemoved);
fEvent.fClearedFiles.add(location);
}
@Override
@ -165,9 +177,9 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
}
/**
* Use the specified location converter to update each internal representation of a file location.
* The file index is rebuilt with the new representations. Individual PDOMFile records are unmoved so
* as to maintain referential integrity with other PDOM records.
* Uses the specified location converter to update each internal representation of a file
* location. The file index is rebuilt with the new representations. Individual PDOMFile records
* are unmoved so as to maintain referential integrity with other PDOM records.
*
* <b>A write-lock must be obtained before calling this method</b>
*
@ -227,16 +239,34 @@ public class WritablePDOM extends PDOM implements IWritableIndexFragment {
return false;
}
public PDOMFile getFileForASTPath(int linkageID, String astPath) throws CoreException {
if (fPathResolver != null && astPath != null) {
IIndexFileLocation location = fPathResolver.resolveASTPath(astPath);
if (location.equals(uncommittedLocation))
return fileBeingUpdated != null ? fileBeingUpdated : uncommittedFile;
return getFile(linkageID, location);
public PDOMFile getFileForASTNode(int linkageID, IASTNode node) throws CoreException {
if (fPathResolver != null && node != null) {
IASTFileLocation loc= node.getFileLocation();
if (loc != null) {
ISignificantMacros sigMacros= getSignificantMacros(node, loc);
if (sigMacros != null) {
IIndexFileLocation location = fPathResolver.resolveASTPath(loc.getFileName());
if (uncommittedKey != null && uncommittedKey.equals(new FileContentKey(linkageID, location, sigMacros)))
return fileBeingUpdated != null ? fileBeingUpdated : uncommittedFile;
return getFile(linkageID, location, sigMacros);
}
}
}
return null;
}
private ISignificantMacros getSignificantMacros(IASTNode node, IASTFileLocation loc) throws CoreException {
IASTPreprocessorIncludeStatement owner= loc.getContextInclusionStatement();
if (owner != null)
return owner.getSignificantMacros();
IASTTranslationUnit tu = node.getTranslationUnit();
if (tu != null)
return tu.getSignificantMacros();
return null;
}
@Override
public boolean hasLastingDefinition(PDOMBinding binding) throws CoreException {
if (fileBeingUpdated == null) {

View file

@ -22,6 +22,7 @@ import org.eclipse.cdt.core.dom.ast.IASTImageLocation;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.ICompositeType;
@ -73,6 +74,10 @@ public class PDOMASTAdapter {
public int getNodeOffset() {
return loc.getNodeOffset();
}
public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
return loc.getContextInclusionStatement();
}
};
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2010 QNX Software Systems and others.
* Copyright (c) 2005, 2011 QNX Software Systems 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
@ -37,12 +37,14 @@ import org.eclipse.cdt.core.index.IIndexInclude;
import org.eclipse.cdt.core.index.IIndexLocationConverter;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.parser.ISignificantMacros;
import org.eclipse.cdt.internal.core.index.IIndexFragment;
import org.eclipse.cdt.internal.core.index.IIndexFragmentFile;
import org.eclipse.cdt.internal.core.index.IIndexFragmentName;
import org.eclipse.cdt.internal.core.index.IWritableIndex.IncludeInformation;
import org.eclipse.cdt.internal.core.index.IWritableIndexFragment;
import org.eclipse.cdt.internal.core.index.IndexFileLocation;
import org.eclipse.cdt.internal.core.parser.scanner.SignificantMacros;
import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.YieldableIndexLock;
import org.eclipse.cdt.internal.core.pdom.db.BTree;
@ -56,28 +58,31 @@ import org.eclipse.core.runtime.Status;
/**
* Represents a file containing names.
*
*
* @author Doug Schaefer
*/
public class PDOMFile implements IIndexFragmentFile {
private final PDOMLinkage fLinkage;
private final long record;
private IIndexFileLocation location; // No need to make volatile, all fields of IIndexFileLocation are final.
private IIndexFileLocation location; // No need to make volatile, all fields of IndexFileLocation are final.
private ISignificantMacros sigMacros; // No need to make volatile, all fields of FileContentsKey are either final or volatile.
private static final int FIRST_NAME = 0;
private static final int FIRST_INCLUDE = 4;
private static final int FIRST_INCLUDED_BY = 8;
private static final int FIRST_MACRO = 12;
private static final int LOCATION_REPRESENTATION = 16;
private static final int LINKAGE_ID= 20;
private static final int TIME_STAMP = 24;
private static final int CONTENT_HASH= 32;
private static final int SCANNER_CONFIG_HASH= 40;
private static final int ENCODING_HASH= 44;
private static final int LAST_USING_DIRECTIVE= 48;
private static final int FIRST_MACRO_REFERENCE= 52;
private static final int FIRST_INCLUDE = FIRST_NAME + Database.PTR_SIZE;
private static final int FIRST_INCLUDED_BY = FIRST_INCLUDE + Database.PTR_SIZE;
private static final int FIRST_MACRO = FIRST_INCLUDED_BY + Database.PTR_SIZE;
private static final int LOCATION_REPRESENTATION = FIRST_MACRO + Database.PTR_SIZE;
private static final int LINKAGE_ID= LOCATION_REPRESENTATION + Database.PTR_SIZE; // size 3
private static final int FLAGS= LINKAGE_ID + 3; // size 1
private static final int TIME_STAMP = FLAGS + 1; // long
private static final int CONTENT_HASH= TIME_STAMP + 8; // long
private static final int ENCODING_HASH= CONTENT_HASH + 8;
private static final int LAST_USING_DIRECTIVE= ENCODING_HASH + 4;
private static final int FIRST_MACRO_REFERENCE= LAST_USING_DIRECTIVE + Database.PTR_SIZE;
private static final int SIGNIFICANT_MACROS= FIRST_MACRO_REFERENCE + Database.PTR_SIZE;
private static final int RECORD_SIZE= SIGNIFICANT_MACROS + Database.PTR_SIZE; // 8*PTR_SIZE + 3+1+8+8+4 = 56
private static final int RECORD_SIZE= 56;
private static final int FLAG_PRAGMA_ONCE_SEMANTICS = 0x01;
public static class Comparator implements IBTreeComparator {
private Database db;
@ -91,10 +96,26 @@ public class PDOMFile implements IIndexFragmentFile {
IString name2 = db.getString(db.getRecPtr(record2 + LOCATION_REPRESENTATION));
int cmp= name1.compare(name2, true);
if (cmp == 0) {
cmp= db.getInt(record1 + LINKAGE_ID) - db.getInt(record2 + LINKAGE_ID);
cmp= db.get3ByteUnsignedInt(record1 + LINKAGE_ID) - db.get3ByteUnsignedInt(record2 + LINKAGE_ID);
if (cmp == 0) {
IString sm1= getString(record1 + SIGNIFICANT_MACROS);
IString sm2= getString(record2 + SIGNIFICANT_MACROS);
if (sm1 == null) {
cmp= sm2 == null ? 0 : -1;
} else if (sm2 == null) {
cmp= 1;
} else {
cmp= sm1.compare(sm2, true);
}
}
}
return cmp;
}
private IString getString(long offset) throws CoreException {
long rec = db.getRecPtr(offset);
return rec != 0 ? db.getString(rec) : null;
}
}
public PDOMFile(PDOMLinkage linkage, long record) {
@ -102,7 +123,7 @@ public class PDOMFile implements IIndexFragmentFile {
this.record = record;
}
public PDOMFile(PDOMLinkage linkage, IIndexFileLocation location, int linkageID) throws CoreException {
public PDOMFile(PDOMLinkage linkage, IIndexFileLocation location, int linkageID, ISignificantMacros macros) throws CoreException {
fLinkage = linkage;
this.location= location;
Database db = fLinkage.getDB();
@ -112,7 +133,8 @@ public class PDOMFile implements IIndexFragmentFile {
throw new CoreException(CCorePlugin.createStatus(Messages.getString("PDOMFile.toInternalProblem") + location.getURI())); //$NON-NLS-1$
IString locationDBString = db.newString(locationString);
db.putRecPtr(record + LOCATION_REPRESENTATION, locationDBString.getRecord());
db.putInt(record + LINKAGE_ID, linkageID);
db.put3ByteUnsignedInt(record + LINKAGE_ID, linkageID);
db.putRecPtr(record + SIGNIFICANT_MACROS, db.newString(macros.encode()).getRecord());
setTimestamp(-1);
}
@ -123,7 +145,7 @@ public class PDOMFile implements IIndexFragmentFile {
public PDOM getPDOM() {
return fLinkage.getPDOM();
}
@Override
public boolean equals(Object obj) {
if (obj == this)
@ -139,7 +161,7 @@ public class PDOMFile implements IIndexFragmentFile {
public final int hashCode() {
return System.identityHashCode(fLinkage.getPDOM()) + (int) (41 * record);
}
/**
* Transfers names, macros and includes from another file to this one and deletes the other file.
* @param sourceFile the file to transfer the local bindings from.
@ -227,7 +249,10 @@ public class PDOMFile implements IIndexFragmentFile {
setTimestamp(sourceFile.getTimestamp());
setEncodingHashcode(sourceFile.getEncodingHashcode());
setContentsHash(sourceFile.getContentsHash());
setScannerConfigurationHashcode(sourceFile.getScannerConfigurationHashcode());
Database db= fLinkage.getDB();
// Transfer the flags.
db.putByte(record + FLAGS, db.getByte(sourceFile.record + FLAGS));
sourceFile.delete();
}
@ -239,9 +264,10 @@ public class PDOMFile implements IIndexFragmentFile {
*/
public void setLocation(IIndexFileLocation location) throws CoreException {
String locationString = fLinkage.getPDOM().getLocationConverter().toInternalFormat(location);
if (locationString == null)
if (locationString == null) {
throw new CoreException(CCorePlugin.createStatus(Messages.getString("PDOMFile.toInternalProblem") + //$NON-NLS-1$
location.getURI()));
}
setInternalLocation(locationString);
}
@ -260,10 +286,10 @@ public class PDOMFile implements IIndexFragmentFile {
db.putRecPtr(record + LOCATION_REPRESENTATION, db.newString(internalLocation).getRecord());
location= null;
}
public int getLinkageID() throws CoreException {
Database db = fLinkage.getDB();
return db.getInt(record + LINKAGE_ID);
return db.get3ByteUnsignedInt(record + LINKAGE_ID);
}
public long getTimestamp() throws CoreException {
@ -287,13 +313,7 @@ public class PDOMFile implements IIndexFragmentFile {
}
public int getScannerConfigurationHashcode() throws CoreException {
Database db = fLinkage.getDB();
return db.getInt(record + SCANNER_CONFIG_HASH);
}
public void setScannerConfigurationHashcode(int hashcode) throws CoreException {
Database db= fLinkage.getDB();
db.putInt(record + SCANNER_CONFIG_HASH, hashcode);
return 0;
}
public int getEncodingHashcode() throws CoreException {
@ -306,6 +326,21 @@ public class PDOMFile implements IIndexFragmentFile {
db.putInt(record + ENCODING_HASH, hashcode);
}
public boolean hasPragmaOnceSemantics() throws CoreException {
return (fLinkage.getDB().getByte(record + FLAGS) & FLAG_PRAGMA_ONCE_SEMANTICS) != 0;
}
public void setPragmaOnceSemantics(boolean value) throws CoreException {
Database db = fLinkage.getDB();
byte flags = db.getByte(record + FLAGS);
if (value) {
flags |= FLAG_PRAGMA_ONCE_SEMANTICS;
} else {
flags &= ~FLAG_PRAGMA_ONCE_SEMANTICS;
}
db.putByte(record + FLAGS, flags);
}
private PDOMName getFirstName() throws CoreException {
long namerec = fLinkage.getDB().getRecPtr(record + FIRST_NAME);
return namerec != 0 ? new PDOMName(fLinkage, namerec) : null;
@ -340,7 +375,7 @@ public class PDOMFile implements IIndexFragmentFile {
long rec = fLinkage.getDB().getRecPtr(record + FIRST_INCLUDED_BY);
return rec != 0 ? new PDOMInclude(fLinkage, rec) : null;
}
public IIndexInclude getParsedInContext() throws CoreException {
return getFirstIncludedBy();
}
@ -515,7 +550,7 @@ public class PDOMFile implements IIndexFragmentFile {
m.delete();
}
setFirstMacroReference(null);
setPragmaOnceSemantics(false);
setTimestamp(-1);
}
@ -527,6 +562,9 @@ public class PDOMFile implements IIndexFragmentFile {
public void delete() throws CoreException {
Database db = fLinkage.getDB();
long locRecord = db.getRecPtr(record + LOCATION_REPRESENTATION);
if (locRecord != 0)
db.getString(locRecord).delete();
locRecord = db.getRecPtr(record + SIGNIFICANT_MACROS);
if (locRecord != 0)
db.getString(locRecord).delete();
@ -539,7 +577,7 @@ public class PDOMFile implements IIndexFragmentFile {
PDOMInclude lastInclude= null;
for (final IncludeInformation info : includeInfos) {
final PDOMFile targetFile= (PDOMFile) info.fTargetFile;
PDOMInclude pdomInclude = new PDOMInclude(fLinkage, info.fStatement, this, targetFile);
assert targetFile == null || targetFile.getIndexFragment() instanceof IWritableIndexFragment;
if (targetFile != null) {
@ -560,7 +598,7 @@ public class PDOMFile implements IIndexFragmentFile {
if (isContext) {
setFirstIncludedBy(include);
include.setNextInIncludedBy(firstIncludedBy);
firstIncludedBy.setPrevInIncludedBy(include);
firstIncludedBy.setPrevInIncludedBy(include);
} else {
PDOMInclude secondIncludedBy= firstIncludedBy.getNextInIncludedBy();
if (secondIncludedBy != null) {
@ -606,13 +644,12 @@ public class PDOMFile implements IIndexFragmentFile {
if (nameOffset >= offset) {
if (nameOffset + name.getNodeLength() <= offset + length) {
result.add(name);
} else if (name.isReference()) {
} else if (name.isReference()) {
// Names are ordered, but callers are inserted before
// their references.
break;
}
}
}
for (PDOMMacro macro= getFirstMacro(); macro != null; macro= macro.getNextMacro()) {
int nameOffset= macro.getNodeOffset();
@ -622,7 +659,7 @@ public class PDOMFile implements IIndexFragmentFile {
if (name != null) {
result.add(name);
}
} else {
} else {
break;
}
}
@ -632,7 +669,7 @@ public class PDOMFile implements IIndexFragmentFile {
if (nameOffset >= offset) {
if (nameOffset + name.getNodeLength() <= offset + length) {
result.add(name);
} else {
} else {
break;
}
}
@ -640,11 +677,53 @@ public class PDOMFile implements IIndexFragmentFile {
return result.toArray(new IIndexName[result.size()]);
}
public static PDOMFile findFile(PDOMLinkage linkage, BTree btree, IIndexFileLocation location,
public static PDOMFile[] findFiles(PDOMLinkage linkage, BTree btree, IIndexFileLocation location,
IIndexLocationConverter strategy) throws CoreException {
String internalRepresentation= strategy.toInternalFormat(location);
if (internalRepresentation != null) {
Finder finder = new Finder(linkage.getDB(), internalRepresentation, linkage.getLinkageID());
Finder finder = new Finder(linkage.getDB(), internalRepresentation, linkage.getLinkageID(), null);
btree.accept(finder);
long[] records= finder.getRecords();
PDOMFile[] result= new PDOMFile[records.length];
for (int i = 0; i < result.length; i++) {
result[i]= new PDOMFile(linkage, records[i]);
}
return result;
}
return null;
}
/**
* When a header file is stored in the index in multiple variants for different sets of macro
* definitions this method will return an arbitrary one of these variants.
*
* @deprecated Use
* {@link #findFile(PDOMLinkage, BTree, IIndexFileLocation, IIndexLocationConverter, ISignificantMacros)}
* or {@link #findFiles(PDOMLinkage, BTree, IIndexFileLocation, IIndexLocationConverter)}
*/
@Deprecated
public static PDOMFile findFile(PDOMLinkage linkage, BTree btree, IIndexFileLocation location,
IIndexLocationConverter strategy) throws CoreException {
return findFile(linkage, btree, location, strategy, null);
}
/**
* Finds the file in index.
*
* @param linkage The linkage of the file.
* @param btree The file index.
* @param location The location of the file.
* @param strategy The index location converter.
* @param macroDictionary The names and definitions of the macros used to disambiguate between
* variants of the file contents corresponding to different inclusion points.
* @return The found file, or <code>null</code> if the matching file was not found.
*/
public static PDOMFile findFile(PDOMLinkage linkage, BTree btree, IIndexFileLocation location,
IIndexLocationConverter strategy, ISignificantMacros macroDictionary) throws CoreException {
String internalRepresentation= strategy.toInternalFormat(location);
if (internalRepresentation != null) {
Finder finder = new Finder(linkage.getDB(), internalRepresentation, linkage.getLinkageID(),
macroDictionary);
btree.accept(finder);
long record= finder.getRecord();
if (record != 0) {
@ -658,7 +737,7 @@ public class PDOMFile implements IIndexFragmentFile {
IIndexLocationConverter strategy) throws CoreException {
String internalRepresentation= strategy.toInternalFormat(location);
if (internalRepresentation != null) {
Finder finder = new Finder(pdom.getDB(), internalRepresentation, -1);
Finder finder = new Finder(pdom.getDB(), internalRepresentation, -1, null);
btree.accept(finder);
long[] records= finder.getRecords();
PDOMFile[] result= new PDOMFile[records.length];
@ -672,12 +751,11 @@ public class PDOMFile implements IIndexFragmentFile {
public static PDOMFile recreateFile(PDOM pdom, final long record) throws CoreException {
final Database db= pdom.getDB();
final int linkageID= db.getInt(record + PDOMFile.LINKAGE_ID);
final int linkageID= db.get3ByteUnsignedInt(record + LINKAGE_ID);
PDOMLinkage linkage= pdom.getLinkage(linkageID);
if (linkage == null)
throw new CoreException(createStatus("Invalid linkage ID in database")); //$NON-NLS-1$
PDOMFile file= new PDOMFile(linkage, record);
return file;
return new PDOMFile(linkage, record);
}
private static class Finder implements IBTreeVisitor {
@ -687,14 +765,17 @@ public class PDOMFile implements IIndexFragmentFile {
private long record;
private long[] records;
private final int linkageID;
private char[] rawSignificantMacros;
/**
* Searches for a file with the given linkage id.
*/
public Finder(Database db, String internalRepresentation, int linkageID) {
public Finder(Database db, String internalRepresentation, int linkageID, ISignificantMacros sigMacros) {
this.db = db;
this.rawKey = internalRepresentation;
this.linkageID= linkageID;
this.rawSignificantMacros = sigMacros == null ? null : sigMacros.encode();
assert linkageID >= 0 || rawSignificantMacros == null;
}
public long[] getRecords() {
@ -706,32 +787,48 @@ public class PDOMFile implements IIndexFragmentFile {
}
return records;
}
public int compare(long record) throws CoreException {
IString name = db.getString(db.getRecPtr(record + PDOMFile.LOCATION_REPRESENTATION));
int cmp= name.compare(rawKey, true);
if (cmp == 0 && linkageID >= 0) {
cmp= db.getInt(record + PDOMFile.LINKAGE_ID) - linkageID;
cmp= db.get3ByteUnsignedInt(record + PDOMFile.LINKAGE_ID) - linkageID;
if (cmp == 0 && rawSignificantMacros != null) {
IString significantMacrosStr = getString(record + SIGNIFICANT_MACROS);
if (significantMacrosStr != null) {
cmp = significantMacrosStr.compare(rawSignificantMacros, true);
} else {
cmp = rawSignificantMacros.length > 0 ? -1 : 0;
}
}
}
return cmp;
}
private IString getString(long offset) throws CoreException {
long rec = db.getRecPtr(offset);
return rec != 0 ? db.getString(rec) : null;
}
public boolean visit(long record) throws CoreException {
if (linkageID >= 0) {
if (rawSignificantMacros != null) {
this.record = record;
return false;
return false;
// Stop searching.
}
if (this.record == 0) {
this.record= record;
} else if (this.records == null) {
this.records= new long[] {this.record, record};
this.records= new long[] { this.record, record };
} else {
long[] cpy= new long[this.records.length + 1];
System.arraycopy(this.records, 0, cpy, 0, this.records.length);
cpy[cpy.length - 1]= record;
this.records= cpy;
}
return linkageID < 0;
// Continue search.
return true;
}
public long getRecord() {
@ -757,7 +854,22 @@ public class PDOMFile implements IIndexFragmentFile {
}
return location;
}
public ISignificantMacros getSignificantMacros() throws CoreException {
if (sigMacros == null) {
Database db= fLinkage.getDB();
final IString encoded = db.getString(db.getRecPtr(record + SIGNIFICANT_MACROS));
sigMacros= encoded == null ? ISignificantMacros.NONE : new SignificantMacros(encoded.getChars());
}
return sigMacros;
}
public boolean isComplete() {
return true;
}
public boolean hasContent() throws CoreException {
return getTimestamp() != -1;
}

View file

@ -256,9 +256,9 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage
}
if (checkIfInSourceOnly) {
String path= ASTInternal.getDeclaredInSourceFileOnly(binding, requireDefinition, glob);
if (path != null) {
return wpdom.getFileForASTPath(getLinkageID(), path);
IASTNode node= ASTInternal.getDeclaredInSourceFileOnly(binding, requireDefinition, glob);
if (node != null) {
return wpdom.getFileForASTNode(getLinkageID(), node);
}
}
}

View file

@ -20,6 +20,7 @@ import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMVisitor;
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.IASTPreprocessorUndefStatement;
import org.eclipse.cdt.core.dom.ast.IMacroBinding;
@ -278,10 +279,6 @@ public class PDOMMacro implements IIndexMacro, IPDOMBinding, IASTFileLocation {
fLinkage.getDB().putRecPtr(fRecord + FILE, file != null ? file.getRecord() : 0);
}
public int getEndingLineNumber() {
return 0;
}
public String getFileName() {
try {
IIndexFile file = getFile();
@ -303,6 +300,14 @@ public class PDOMMacro implements IIndexMacro, IPDOMBinding, IASTFileLocation {
return 0;
}
public int getEndingLineNumber() {
return 0;
}
public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
return null;
}
public IASTFileLocation asFileLocation() {
return this;
}

View file

@ -15,6 +15,7 @@ package org.eclipse.cdt.internal.core.pdom.dom;
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.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexLocationFactory;
@ -216,6 +217,10 @@ public final class PDOMMacroReferenceName implements IIndexFragmentName, IASTFil
return 0;
}
public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
return null;
}
public IASTFileLocation asFileLocation() {
return this;
}

View file

@ -6,9 +6,9 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Doug Schaefer (QNX) - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
* Doug Schaefer (QNX) - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/
package org.eclipse.cdt.internal.core.pdom.dom;
@ -17,6 +17,7 @@ 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.dom.ast.IASTPreprocessorIncludeStatement;
import org.eclipse.cdt.core.index.IIndexFile;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexLocationFactory;
@ -323,6 +324,10 @@ public final class PDOMName implements IIndexFragmentName, IASTFileLocation {
return 0;
}
public IASTPreprocessorIncludeStatement getContextInclusionStatement() {
return null;
}
public IASTFileLocation asFileLocation() {
return this;
}

View file

@ -969,23 +969,23 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
final WritablePDOM wpdom= (WritablePDOM) pdom;
PDOMFile file= null;
if (binding instanceof ICPPUsingDeclaration) {
String path= ASTInternal.getDeclaredInOneFileOnly(binding);
if (path != null) {
file= wpdom.getFileForASTPath(getLinkageID(), path);
IASTNode node= ASTInternal.getDeclaredInOneFileOnly(binding);
if (node != null) {
file= wpdom.getFileForASTNode(getLinkageID(), node);
}
} else if (binding instanceof ICPPNamespaceAlias) {
String path= ASTInternal.getDeclaredInSourceFileOnly(binding, false, glob);
if (path != null) {
file= wpdom.getFileForASTPath(getLinkageID(), path);
IASTNode node= ASTInternal.getDeclaredInSourceFileOnly(binding, false, glob);
if (node != null) {
file= wpdom.getFileForASTNode(getLinkageID(), node);
}
}
if (file == null && !(binding instanceof IIndexBinding)) {
IBinding owner= binding.getOwner();
if (owner instanceof ICPPNamespace) {
if (owner.getNameCharArray().length == 0) {
String path= ASTInternal.getDeclaredInSourceFileOnly(owner, false, glob);
if (path != null) {
file= wpdom.getFileForASTPath(getLinkageID(), path);
IASTNode node= ASTInternal.getDeclaredInSourceFileOnly(owner, false, glob);
if (node != null) {
file= wpdom.getFileForASTNode(getLinkageID(), node);
}
}
}

View file

@ -21,6 +21,9 @@ import org.eclipse.cdt.core.model.ICProject;
* Abstract base class for all indexers.
*/
public abstract class AbstractPDOMIndexer implements IPDOMIndexer {
// For testing purposes
public static boolean noFilesUpFront= false;
protected ICProject project;
protected Properties fProperties= new Properties();
@ -82,11 +85,13 @@ public abstract class AbstractPDOMIndexer implements IPDOMIndexer {
}
public String[] getFilesToParseUpFront() {
String prefSetting= getProperty(IndexerPreferences.KEY_FILES_TO_PARSE_UP_FRONT);
if (prefSetting != null) {
prefSetting= prefSetting.trim();
if (prefSetting.length() > 0) {
return prefSetting.split(","); //$NON-NLS-1$
if (!noFilesUpFront) {
String prefSetting= getProperty(IndexerPreferences.KEY_FILES_TO_PARSE_UP_FRONT);
if (prefSetting != null) {
prefSetting= prefSetting.trim();
if (prefSetting.length() > 0) {
return prefSetting.split(","); //$NON-NLS-1$
}
}
}
return new String[0];

View file

@ -40,7 +40,6 @@ import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
@ -177,16 +176,6 @@ public abstract class PDOMIndexerTask extends AbstractIndexerTask implements IPD
return defaultValue;
}
@Override
protected String getASTPathForParsingUpFront() {
final IProject project = getProject().getProject();
final IPath prjLocation= project.getLocation();
if (prjLocation == null) {
return null;
}
return prjLocation.append(super.getASTPathForParsingUpFront()).toString();
}
@Override
protected AbstractLanguage[] getLanguages(String filename) {
IProject project = getProject().getProject();
@ -406,4 +395,4 @@ public abstract class PDOMIndexerTask extends AbstractIndexerTask implements IPD
}
return super.acceptUrgentTask(urgentTask);
}
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2002, 2008 IBM Corporation and others.
* Copyright (c) 2002, 2011 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
@ -19,6 +19,7 @@ import org.eclipse.cdt.internal.core.model.DebugLogConstants;
import org.eclipse.cdt.internal.core.model.Util;
import org.eclipse.cdt.internal.core.util.ICancelable;
import org.eclipse.cdt.internal.core.util.ICanceler;
import org.eclipse.core.runtime.Platform;
/**
* @author jcamelon
@ -53,6 +54,16 @@ public class ParserLogService extends AbstractParserLogService implements ICance
Util.debugLog( message, topic );
}
@Override
public boolean isTracing(String option) {
return "true".equals(Platform.getDebugOption(option)); //$NON-NLS-1$
}
@Override
public void traceLog(String option, String message) {
if (isTracing(option))
System.out.println(message);
}
@Override
public void errorLog(String message) {