mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Single version for pragma-once files, tracking loaded non-pragma-once versions.
This commit is contained in:
parent
d69c979ada
commit
4e1d937050
23 changed files with 313 additions and 274 deletions
|
@ -507,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, null);
|
||||
fLocationMap.popContext(i2);
|
||||
// add a comment before the include
|
||||
fLocationMap.encounteredComment(4,6,false);
|
||||
|
||||
assertEquals("pre1", fLocationMap.getCurrentFilePath());
|
||||
fLocationMap.popContext(i1, null);
|
||||
fLocationMap.popContext(i1);
|
||||
assertEquals(FN, fLocationMap.getCurrentFilePath());
|
||||
fLocationMap.popContext(pre2, null);
|
||||
fLocationMap.popContext(pre2);
|
||||
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, null);
|
||||
fLocationMap.popContext(pre1, null);
|
||||
fLocationMap.popContext(i3);
|
||||
fLocationMap.popContext(pre1);
|
||||
assertEquals(FN, fLocationMap.getCurrentFilePath());
|
||||
|
||||
|
||||
|
|
|
@ -1116,7 +1116,7 @@ public class IndexBugsTests extends BaseTestCase {
|
|||
// #endif
|
||||
|
||||
// #ifndef _h1
|
||||
// #include "header1.h" // is inactive, but must be resolved, h1 is not significant
|
||||
// #include "header1.h" // is inactive, but must be resolved
|
||||
// #endif
|
||||
|
||||
// #include "header1.h"
|
||||
|
@ -1127,7 +1127,7 @@ public class IndexBugsTests extends BaseTestCase {
|
|||
|
||||
// #include "header2.h"
|
||||
// #ifndef _h1
|
||||
// #include "header1.h" // inactive and not resolved because header1.h is internally included.
|
||||
// #include "header1.h" // inactive but resolved.
|
||||
// #endif
|
||||
public void testIncludeGuardsOutsideOfHeader_Bug167100() throws Exception {
|
||||
final IIndexManager indexManager = CCorePlugin.getIndexManager();
|
||||
|
@ -1152,26 +1152,15 @@ public class IndexBugsTests extends BaseTestCase {
|
|||
assertEquals(1, names.length);
|
||||
assertEquals(f4.getFullPath().toString(), names[0].getFile().getLocation().getFullPath());
|
||||
|
||||
IIndexFile[] idxFiles= index.getFiles(ILinkage.CPP_LINKAGE_ID,
|
||||
IndexLocationFactory.getWorkspaceIFL(f2));
|
||||
IIndexFile[] idxFiles= index.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(f5));
|
||||
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());
|
||||
assertFalse(includes[1].isResolved());
|
||||
// includes[1].isResolved()); May or may not be resolved.
|
||||
} finally {
|
||||
index.releaseReadLock();
|
||||
}
|
||||
|
@ -1725,8 +1714,7 @@ public class IndexBugsTests extends BaseTestCase {
|
|||
// #endif
|
||||
|
||||
// #include "a.h"
|
||||
public void _testStrangeIncludeStrategy_Bug249884() throws Exception {
|
||||
// TODO(197989) Should work again once the significant macro dictionary is used.
|
||||
public void testStrangeIncludeStrategy_Bug249884() throws Exception {
|
||||
String[] contents= getContentsForTest(3);
|
||||
final IIndexManager indexManager = CCorePlugin.getIndexManager();
|
||||
IFile ah= TestSourceReader.createFile(fCProject.getProject(), "a.h", contents[0]);
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.dom.ast;
|
||||
|
||||
import org.eclipse.cdt.core.parser.ISignificantMacros;
|
||||
|
||||
|
||||
/**
|
||||
* This interface represent a preprocessor #include statement.
|
||||
|
@ -63,4 +65,12 @@ public interface IASTPreprocessorIncludeStatement extends IASTPreprocessorStatem
|
|||
* @since 5.1
|
||||
*/
|
||||
public boolean isResolvedByHeuristics();
|
||||
|
||||
/**
|
||||
* Returns the list of versions of the target file, each of which is
|
||||
* identified by its significant macros, that had been included
|
||||
* in this translation-unit prior to this statement.
|
||||
* @noreference This method is not intended to be referenced by clients.
|
||||
*/
|
||||
public ISignificantMacros[] getLoadedVersions();
|
||||
}
|
||||
|
|
|
@ -37,9 +37,4 @@ public interface IFileNomination {
|
|||
* Returns whether pragma once semantics has been detected when parsing the translation unit.
|
||||
*/
|
||||
public boolean hasPragmaOnceSemantics() throws CoreException;
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public boolean isComplete();
|
||||
}
|
||||
|
|
|
@ -37,11 +37,6 @@ public interface ISignificantMacros {
|
|||
* 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);
|
||||
|
|
|
@ -74,7 +74,6 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
|
|||
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);
|
||||
|
@ -465,7 +464,6 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
|
|||
assertNotFrozen();
|
||||
if (sigMacros != null)
|
||||
fSignificantMacros= sigMacros;
|
||||
fComplete= true;
|
||||
}
|
||||
|
||||
public boolean hasPragmaOnceSemantics() {
|
||||
|
@ -477,10 +475,6 @@ public abstract class ASTTranslationUnit extends ASTNode implements IASTTranslat
|
|||
fPragmaOnceSemantics= value;
|
||||
}
|
||||
|
||||
public boolean isComplete() {
|
||||
return fComplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts exclusive access
|
||||
* @throws InterruptedException
|
||||
|
|
|
@ -34,10 +34,19 @@ import org.eclipse.core.runtime.CoreException;
|
|||
public interface IWritableIndex extends IIndex {
|
||||
|
||||
static class IncludeInformation {
|
||||
public IASTPreprocessorIncludeStatement fStatement;
|
||||
public IIndexFileLocation fLocation;
|
||||
public final IASTPreprocessorIncludeStatement fStatement;
|
||||
public final IIndexFileLocation fLocation;
|
||||
public final ISignificantMacros fSignificantMacros;
|
||||
public final boolean fIsContext;
|
||||
public IIndexFragmentFile fTargetFile;
|
||||
public boolean fIsContext= false;
|
||||
|
||||
public IncludeInformation(IASTPreprocessorIncludeStatement stmt,
|
||||
IIndexFileLocation location, ISignificantMacros sig, boolean isContext) {
|
||||
fStatement= stmt;
|
||||
fSignificantMacros= sig;
|
||||
fLocation= location;
|
||||
fIsContext= isContext;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -34,6 +35,7 @@ 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.FileVersion;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.InclusionKind;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContentProvider;
|
||||
import org.eclipse.cdt.internal.core.pdom.ASTFilePathResolver;
|
||||
|
@ -86,7 +88,8 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
|
|||
}
|
||||
|
||||
@Override
|
||||
public void resetPragmaOnceTracking() {
|
||||
public void resetForTranslationUnit() {
|
||||
super.resetForTranslationUnit();
|
||||
fPragmaOnce.clear();
|
||||
}
|
||||
|
||||
|
@ -128,11 +131,11 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
|
|||
List<IIndexMacro> macros= new ArrayList<IIndexMacro>();
|
||||
List<ICPPUsingDirective> directives= new ArrayList<ICPPUsingDirective>();
|
||||
Map<IIndexFileLocation, IFileNomination> newPragmaOnce= new HashMap<IIndexFileLocation, IFileNomination>();
|
||||
collectFileContent(file, null, newPragmaOnce, files, macros, directives, null);
|
||||
LinkedHashSet<IIndexFile> preLoaded= new LinkedHashSet<IIndexFile>();
|
||||
collectFileContent(file, null, newPragmaOnce, preLoaded, 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);
|
||||
return new InternalFileContent(path, macros, directives, files, toList(preLoaded));
|
||||
} catch (NeedToParseException e) {
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +145,7 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
|
|||
|
||||
// Skip large files
|
||||
if (fFileSizeLimit > 0 && fPathResolver.getFileSize(path) > fFileSizeLimit) {
|
||||
return new InternalFileContent(path, InclusionKind.SKIP_FILE, null);
|
||||
return new InternalFileContent(path, InclusionKind.SKIP_FILE);
|
||||
}
|
||||
|
||||
if (fFallBackFactory != null) {
|
||||
|
@ -182,10 +185,11 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
|
|||
return null;
|
||||
}
|
||||
|
||||
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 {
|
||||
private boolean collectFileContent(IIndexFile file, IIndexFile stopAt,
|
||||
Map<IIndexFileLocation, IFileNomination> newPragmaOnce,
|
||||
LinkedHashSet<IIndexFile> preLoaded, List<IIndexFile> files,
|
||||
List<IIndexMacro> macros, List<ICPPUsingDirective> usingDirectives,
|
||||
Set<IIndexFile> preventRecursion) throws CoreException, NeedToParseException {
|
||||
if (file.equals(stopAt))
|
||||
return true;
|
||||
|
||||
|
@ -218,6 +222,9 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
|
|||
}
|
||||
|
||||
files.add(file);
|
||||
if (!file.hasPragmaOnceSemantics()) {
|
||||
preLoaded.add(file);
|
||||
}
|
||||
int udx= 0;
|
||||
for (Object d : pds) {
|
||||
if (d instanceof IIndexMacro) {
|
||||
|
@ -231,7 +238,7 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
|
|||
for (; udx < uds.length && uds[udx].getPointOfDeclaration() <= offset; udx++) {
|
||||
usingDirectives.add(uds[udx]);
|
||||
}
|
||||
if (collectFileContent(includedFile, stopAt, newPragmaOnce, files, macros, usingDirectives, preventRecursion))
|
||||
if (collectFileContent(includedFile, stopAt, newPragmaOnce, preLoaded, files, macros, usingDirectives, preventRecursion))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -274,8 +281,9 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
|
|||
List<IIndexFile> filesIncluded= new ArrayList<IIndexFile>();
|
||||
ArrayList<IIndexMacro> macros= new ArrayList<IIndexMacro>();
|
||||
ArrayList<ICPPUsingDirective> directives= new ArrayList<ICPPUsingDirective>();
|
||||
LinkedHashSet<IIndexFile> preLoaded= new LinkedHashSet<IIndexFile>();
|
||||
try {
|
||||
if (!collectFileContent(contextFile, targetFile, newPragmaOnce,
|
||||
if (!collectFileContent(contextFile, targetFile, newPragmaOnce, preLoaded,
|
||||
filesIncluded, macros, directives, new HashSet<IIndexFile>())) {
|
||||
return null;
|
||||
}
|
||||
|
@ -285,15 +293,22 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv
|
|||
|
||||
// Report pragma once inclusions.
|
||||
fPragmaOnce.putAll(newPragmaOnce);
|
||||
List<String> newPragmaOncePaths = toPathList(newPragmaOnce.keySet());
|
||||
return new InternalFileContent(GAP, macros, directives, new ArrayList<IIndexFile>(filesIncluded),
|
||||
newPragmaOncePaths);
|
||||
return new InternalFileContent(GAP, macros, directives, filesIncluded, toList(preLoaded));
|
||||
} catch (CoreException e) {
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<FileVersion> toList(LinkedHashSet<IIndexFile> preLoaded) throws CoreException {
|
||||
List<FileVersion> result= new ArrayList<InternalFileContent.FileVersion>(preLoaded.size());
|
||||
for (IIndexFile file : preLoaded) {
|
||||
String path= fPathResolver.getASTPath(file.getLocation());
|
||||
result.add(new FileVersion(path, file.getSignificantMacros()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private IIndexFile findContext(IIndexFile file) throws CoreException {
|
||||
final HashSet<IIndexFile> ifiles= new HashSet<IIndexFile>();
|
||||
ifiles.add(file);
|
||||
|
|
|
@ -85,7 +85,7 @@ public class WritableCIndex extends CIndex implements IWritableIndex {
|
|||
for (IncludeInformation include : includes) {
|
||||
if (include.fLocation != null) {
|
||||
include.fTargetFile= addFile(linkageID, include.fLocation,
|
||||
include.fStatement.getSignificantMacros());
|
||||
include.fSignificantMacros);
|
||||
}
|
||||
}
|
||||
((IWritableIndexFragment) indexFragment).addFileContent(file, includes, macros, names, resolver, lock);
|
||||
|
|
|
@ -256,6 +256,8 @@ class ASTPragmaOperator extends ASTPragma {
|
|||
}
|
||||
|
||||
class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreprocessorIncludeStatement {
|
||||
private static final ISignificantMacros[] NO_VERSIONS = {};
|
||||
|
||||
private final ASTPreprocessorName fName;
|
||||
private final String fPath;
|
||||
private final boolean fIsResolved;
|
||||
|
@ -263,8 +265,8 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
|
|||
private final boolean fFoundByHeuristics;
|
||||
private final IFileNomination fNominationDelegate;
|
||||
private boolean fPragmaOnce;
|
||||
private boolean fComplete;
|
||||
private ISignificantMacros fSignificantMacros;
|
||||
private ISignificantMacros[] fLoadedVersions = NO_VERSIONS;
|
||||
|
||||
public ASTInclusionStatement(IASTTranslationUnit parent,
|
||||
int startNumber, int nameStartNumber, int nameEndNumber, int endNumber,
|
||||
|
@ -339,11 +341,14 @@ class ASTInclusionStatement extends ASTPreprocessorNode implements IASTPreproces
|
|||
assert sig != null;
|
||||
assert fNominationDelegate == null;
|
||||
fSignificantMacros= sig;
|
||||
fComplete= true;
|
||||
}
|
||||
|
||||
public boolean isComplete() {
|
||||
return fComplete;
|
||||
public void setLoadedVersions(ISignificantMacros[] versions) {
|
||||
fLoadedVersions= versions;
|
||||
}
|
||||
|
||||
public ISignificantMacros[] getLoadedVersions() {
|
||||
return fLoadedVersions;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,11 +48,13 @@ import org.eclipse.cdt.core.parser.ParseError;
|
|||
import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayIntMap;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayMap;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
||||
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.FileVersion;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent.InclusionKind;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.Lexer.LexerOptions;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.MacroDefinitionParser.InvalidMacroDefinitionException;
|
||||
|
@ -130,10 +132,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
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> {
|
||||
|
@ -145,7 +143,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
final InternalFileContent fc;
|
||||
IFileNomination once= fFileContentProvider.isIncludedWithPragmaOnceSemantics(path);
|
||||
if (once != null) {
|
||||
fc= new InternalFileContent(path, InclusionKind.SKIP_FILE, once);
|
||||
fc= new InternalFileContent(path, InclusionKind.SKIP_FILE);
|
||||
} else {
|
||||
fc= fFileContentProvider.getContentForInclusion(path, fMacroDictionaryFacade);
|
||||
}
|
||||
|
@ -292,12 +290,12 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
|
||||
ILocationCtx ctx= fLocationMap.pushTranslationUnit(filePath, fRootContent.getSource());
|
||||
fRootLexer= new Lexer(fRootContent.getSource(), fLexOptions, this, this);
|
||||
fRootContext= fCurrentContext= new ScannerContext(ctx, null, fRootLexer, true);
|
||||
fRootContext= fCurrentContext= new ScannerContext(ctx, null, fRootLexer);
|
||||
if (info instanceof IExtendedScannerInfo) {
|
||||
final IExtendedScannerInfo einfo= (IExtendedScannerInfo) info;
|
||||
fPreIncludedFiles= new String[][] { einfo.getMacroFiles(), einfo.getIncludeFiles() };
|
||||
}
|
||||
fFileContentProvider.resetPragmaOnceTracking();
|
||||
fFileContentProvider.resetForTranslationUnit();
|
||||
detectIncludeGuard(filePath, fRootContent.getSource(), fRootContext);
|
||||
}
|
||||
|
||||
|
@ -307,9 +305,11 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
IFileNomination nom= fLocationMap.reportPragmaOnceSemantics(ctx.getLocationCtx());
|
||||
fFileContentProvider.reportPragmaOnceSemantics(filePath, nom);
|
||||
ctx.internalModification(guard);
|
||||
ctx.internalModification(filePath.toCharArray());
|
||||
ctx.setPragmaOnce(true);
|
||||
return guard;
|
||||
}
|
||||
} else {
|
||||
ctx.trackSignificantMacros();
|
||||
}
|
||||
if (ctx != fRootContext) {
|
||||
if (fLog.isTracing(TRACE_NO_GUARD)) {
|
||||
if (fTracedGuards == null)
|
||||
|
@ -460,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), false);
|
||||
fCurrentContext= new ScannerContext(ctx, fCurrentContext, new Lexer(buffer, fLexOptions, this, this));
|
||||
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, null);
|
||||
fLocationMap.popContext(locationCtx);
|
||||
fCurrentContext= fCurrentContext.getParent();
|
||||
assert fCurrentContext == fRootContext;
|
||||
} catch (OffsetLimitReachedException e) {
|
||||
|
@ -477,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), false);
|
||||
fCurrentContext= new ScannerContext(ctx, fCurrentContext, new Lexer(buffer, fLexOptions, this, this));
|
||||
}
|
||||
fPreIncludedFiles= null;
|
||||
}
|
||||
|
@ -806,8 +806,14 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
}
|
||||
return ppToken;
|
||||
}
|
||||
|
||||
final ILocationCtx locationCtx = fCurrentContext.getLocationCtx();
|
||||
fLocationMap.popContext(locationCtx, fCurrentContext.getSignificantMacros());
|
||||
ASTInclusionStatement inc = locationCtx.getInclusionStatement();
|
||||
if (inc != null) {
|
||||
completeInclusion(inc);
|
||||
}
|
||||
fLocationMap.popContext(locationCtx);
|
||||
|
||||
fCurrentContext.propagateSignificantMacros();
|
||||
fCurrentContext= fCurrentContext.getParent();
|
||||
assert fCurrentContext != null;
|
||||
|
@ -860,6 +866,20 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
}
|
||||
}
|
||||
|
||||
private void completeInclusion(ASTInclusionStatement inc) {
|
||||
final ISignificantMacros sig;
|
||||
CharArrayObjectMap<char[]> sigMacros= fCurrentContext.getSignificantMacros();
|
||||
if (sigMacros == null || sigMacros.isEmpty()) {
|
||||
sig = ISignificantMacros.NONE;
|
||||
} else {
|
||||
sig = new SignificantMacros(sigMacros);
|
||||
}
|
||||
inc.setSignificantMacros(sig);
|
||||
if (!inc.hasPragmaOnceSemantics()) {
|
||||
fFileContentProvider.addLoadedVersions(inc.getPath(), fCurrentContext.getLoadedVersionCount(), sig);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkNumber(Token number, final boolean isFloat) {
|
||||
final char[] image= number.getCharImage();
|
||||
boolean hasExponent = false;
|
||||
|
@ -1345,17 +1365,17 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
return;
|
||||
}
|
||||
|
||||
String path= null;
|
||||
boolean reported= false;
|
||||
boolean isHeuristic= false;
|
||||
IFileNomination nominationDelegate= null;
|
||||
|
||||
final String includeDirective = new String(headerName);
|
||||
if (!active) {
|
||||
// #ifndef GUARD
|
||||
// #include "file.h"
|
||||
// #endif
|
||||
// Inactive include
|
||||
String path= null;
|
||||
boolean isHeuristic= false;
|
||||
IFileNomination nominationDelegate= null;
|
||||
|
||||
if (externGuard != null) {
|
||||
// #ifndef GUARD
|
||||
// #include "file.h"
|
||||
// #endif
|
||||
// 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,
|
||||
|
@ -1365,92 +1385,90 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
if (nominationDelegate != null) {
|
||||
path= resolved.fLocation;
|
||||
isHeuristic= resolved.fHeuristic;
|
||||
fCurrentContext.undoSignificance(externGuard);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final InternalFileContent fi= findInclusion(includeDirective, userInclude, include_next,
|
||||
getCurrentFilename(), createCodeReaderTester);
|
||||
if (fi != null) {
|
||||
path= fi.getFileLocation();
|
||||
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) {
|
||||
reported= true;
|
||||
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), 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.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 {
|
||||
final int len = headerName.length + 2;
|
||||
StringBuilder name= new StringBuilder(len);
|
||||
name.append(userInclude ? '"' : '<');
|
||||
name.append(headerName);
|
||||
name.append(userInclude ? '"' : '>');
|
||||
|
||||
final char[] nameChars= new char[len];
|
||||
name.getChars(0, len, nameChars, 0);
|
||||
handleProblem(IProblem.PREPROCESSOR_INCLUSION_NOT_FOUND, nameChars, poundOffset, condEndOffset);
|
||||
}
|
||||
}
|
||||
|
||||
if (!reported) {
|
||||
fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1],
|
||||
condEndOffset, headerName, path, userInclude, active, isHeuristic, nominationDelegate);
|
||||
return;
|
||||
}
|
||||
|
||||
// Active include
|
||||
final InternalFileContent fi= findInclusion(includeDirective, userInclude, include_next,
|
||||
getCurrentFilename(), createCodeReaderTester);
|
||||
if (fi == null) {
|
||||
// Unresolved active include
|
||||
final int len = headerName.length + 2;
|
||||
StringBuilder name= new StringBuilder(len);
|
||||
name.append(userInclude ? '"' : '<');
|
||||
name.append(headerName);
|
||||
name.append(userInclude ? '"' : '>');
|
||||
|
||||
final char[] nameChars= new char[len];
|
||||
name.getChars(0, len, nameChars, 0);
|
||||
handleProblem(IProblem.PREPROCESSOR_INCLUSION_NOT_FOUND, nameChars, poundOffset, condEndOffset);
|
||||
// Inactive, found in index, skipped, or unresolved.
|
||||
fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1],
|
||||
condEndOffset, headerName, null, userInclude, active, false, null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Resolved active include
|
||||
final String path= fi.getFileLocation();
|
||||
final boolean isHeuristic= fi.isFoundByHeuristics();
|
||||
final boolean pragmaOnceContext= fCurrentContext.isPragmaOnce();
|
||||
|
||||
IFileNomination nominationDelegate= null;
|
||||
ASTInclusionStatement stmt= null;
|
||||
List<ISignificantMacros> loadedVerisons = null;
|
||||
switch (fi.getKind()) {
|
||||
case FOUND_IN_INDEX:
|
||||
// Pulled in from index
|
||||
nominationDelegate= fi.getFilesIncluded().get(0);
|
||||
try {
|
||||
ISignificantMacros sm = nominationDelegate.getSignificantMacros();
|
||||
fCurrentContext.addSignificantMacros(sm);
|
||||
if (pragmaOnceContext && !nominationDelegate.hasPragmaOnceSemantics())
|
||||
loadedVerisons= fFileContentProvider.getLoadedVersions(path);
|
||||
} catch (CoreException e) {
|
||||
}
|
||||
|
||||
processInclusionFromIndex(poundOffset, path, fi);
|
||||
break;
|
||||
case USE_SOURCE:
|
||||
// Will be parsed
|
||||
AbstractCharArray source= fi.getSource();
|
||||
if (source != null) {
|
||||
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));
|
||||
fctx.setFoundOnPath(fi.getFoundOnPath(), includeDirective);
|
||||
detectIncludeGuard(path, source, fctx);
|
||||
fCurrentContext= fctx;
|
||||
fLocationMap.parsingFile(fFileContentProvider, fi);
|
||||
stmt= ctx.getInclusionStatement();
|
||||
if (!fCurrentContext.isPragmaOnce()) {
|
||||
// Track the loaded version count, even in a non-pragma-once context.
|
||||
loadedVerisons= fFileContentProvider.getLoadedVersions(path);
|
||||
fctx.setLoadedVersionCount(loadedVerisons.size());
|
||||
}
|
||||
}
|
||||
fLocationMap.parsingFile(fFileContentProvider, fi);
|
||||
break;
|
||||
|
||||
case SKIP_FILE:
|
||||
// Already included or fast parsing mode.
|
||||
break;
|
||||
}
|
||||
if (stmt == null) {
|
||||
// Inactive, found in index, skipped, or unresolved.
|
||||
stmt= fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1],
|
||||
condEndOffset, headerName, path, userInclude, active, isHeuristic, nominationDelegate);
|
||||
}
|
||||
// In a pragma once context store loaded versions of this non-pragma-once include
|
||||
if (pragmaOnceContext && loadedVerisons != null && !loadedVerisons.isEmpty()) {
|
||||
stmt.setLoadedVersions(loadedVerisons.toArray(new ISignificantMacros[loadedVerisons.size()]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1460,8 +1478,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
addMacroDefinition(macro);
|
||||
fCurrentContext.internalModification(macro.getNameCharArray());
|
||||
}
|
||||
for (String pragOncePath : fi.getPragmaOncePaths()) {
|
||||
fCurrentContext.internalModification(pragOncePath.toCharArray());
|
||||
for (FileVersion version : fi.getNonPragmaOnceVersions()) {
|
||||
fFileContentProvider.addLoadedVersions(version.fPath, Integer.MAX_VALUE, version.fSigMacros);
|
||||
}
|
||||
fLocationMap.skippedFile(fLocationMap.getSequenceNumberForOffset(offset), fi);
|
||||
}
|
||||
|
@ -1553,8 +1571,7 @@ 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 (isIfndef) {
|
||||
if (IncludeGuardDetection.detectIncludeEndif(lexer)) {
|
||||
fExternIncludeGuard= namechars;
|
||||
}
|
||||
|
@ -1599,8 +1616,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
|
||||
if (cond.canHaveActiveBranch(withinExpansion)) {
|
||||
char[] macro= IncludeGuardDetection.detectIfNotDefinedIncludeEndif(lexer);
|
||||
if (macro != null && !fCurrentContext.hasInternalModification(macro)
|
||||
&& !fCurrentContext.isSignificant(macro)) {
|
||||
if (macro != null) {
|
||||
fExternIncludeGuard= macro;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,4 +30,8 @@ public interface ILocationCtx {
|
|||
*/
|
||||
ILocationCtx getParent();
|
||||
|
||||
/**
|
||||
* Returns inclusion statement that created this context, or <code>null</code>.
|
||||
*/
|
||||
ASTInclusionStatement getInclusionStatement();
|
||||
}
|
||||
|
|
|
@ -13,11 +13,11 @@ 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;
|
||||
import org.eclipse.cdt.core.parser.FileContent;
|
||||
import org.eclipse.cdt.core.parser.ISignificantMacros;
|
||||
|
||||
/**
|
||||
* Instructs the preprocessor on how to handle a file-inclusion.
|
||||
|
@ -39,13 +39,21 @@ public class InternalFileContent extends FileContent {
|
|||
USE_SOURCE
|
||||
}
|
||||
|
||||
public static class FileVersion {
|
||||
public final String fPath;
|
||||
public final ISignificantMacros fSigMacros;
|
||||
public FileVersion(String path, ISignificantMacros sig) {
|
||||
fPath= path;
|
||||
fSigMacros= sig;
|
||||
}
|
||||
}
|
||||
|
||||
private final InclusionKind fKind;
|
||||
private final AbstractCharArray fSource;
|
||||
private final List<IIndexMacro> fMacroDefinitions;
|
||||
private final List<ICPPUsingDirective> fUsingDirectives;
|
||||
private final String fFileLocation;
|
||||
private final IFileNomination fPragmaOnceNomination;
|
||||
private final List<String> fNewPragmaOncePaths;
|
||||
private final List<FileVersion> fNonPragmaOnceFiles;
|
||||
private boolean fHeuristic;
|
||||
private boolean fIsSource= false;
|
||||
private List<IIndexFile> fFiles;
|
||||
|
@ -55,11 +63,10 @@ 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, IFileNomination once) throws IllegalArgumentException {
|
||||
public InternalFileContent(String fileLocation, InclusionKind kind) throws IllegalArgumentException {
|
||||
if (fileLocation == null || kind != InclusionKind.SKIP_FILE) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
@ -68,8 +75,7 @@ public class InternalFileContent extends FileContent {
|
|||
fMacroDefinitions= null;
|
||||
fUsingDirectives= null;
|
||||
fSource= null;
|
||||
fPragmaOnceNomination= once;
|
||||
fNewPragmaOncePaths= null;
|
||||
fNonPragmaOnceFiles= null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -85,8 +91,7 @@ public class InternalFileContent extends FileContent {
|
|||
fSource= content;
|
||||
fMacroDefinitions= null;
|
||||
fUsingDirectives= null;
|
||||
fPragmaOnceNomination= null;
|
||||
fNewPragmaOncePaths= null;
|
||||
fNonPragmaOnceFiles= null;
|
||||
if (fFileLocation == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
@ -97,19 +102,17 @@ 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<String> newPragmaOncePaths) {
|
||||
List<IIndexFile> files, List<FileVersion> nonPragmaOnceVersions) {
|
||||
fKind= InclusionKind.FOUND_IN_INDEX;
|
||||
fFileLocation= fileLocation;
|
||||
fSource= null;
|
||||
fUsingDirectives= usingDirectives;
|
||||
fMacroDefinitions= macroDefinitions;
|
||||
fFiles= files;
|
||||
fPragmaOnceNomination= null;
|
||||
fNewPragmaOncePaths= newPragmaOncePaths;
|
||||
fNonPragmaOnceFiles= nonPragmaOnceVersions;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -167,8 +170,8 @@ public class InternalFileContent extends FileContent {
|
|||
return fFiles;
|
||||
}
|
||||
|
||||
public List<String> getPragmaOncePaths() {
|
||||
return fNewPragmaOncePaths;
|
||||
public List<FileVersion> getNonPragmaOnceVersions() {
|
||||
return fNonPragmaOnceFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -198,10 +201,6 @@ public class InternalFileContent extends FileContent {
|
|||
fFoundOnPath= isp;
|
||||
}
|
||||
|
||||
public IFileNomination getPragmaOnceNomination() {
|
||||
return fPragmaOnceNomination;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is slow. Use only for debugging.
|
||||
*/
|
||||
|
|
|
@ -12,13 +12,17 @@
|
|||
package org.eclipse.cdt.internal.core.parser.scanner;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
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.ISignificantMacros;
|
||||
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
|
||||
import org.eclipse.cdt.internal.core.dom.IIncludeFileResolutionHeuristics;
|
||||
import org.eclipse.cdt.internal.core.parser.IMacroDictionary;
|
||||
|
@ -30,6 +34,7 @@ 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>();
|
||||
private final Map<String, List<ISignificantMacros>> fLoadedVersions= new HashMap<String, List<ISignificantMacros>>();
|
||||
|
||||
/**
|
||||
* Checks whether the specified inclusion exists.
|
||||
|
@ -65,8 +70,9 @@ public abstract class InternalFileContentProvider extends IncludeFileContentProv
|
|||
return null;
|
||||
}
|
||||
|
||||
public void resetPragmaOnceTracking() {
|
||||
public void resetForTranslationUnit() {
|
||||
fPragmaOnce.clear();
|
||||
fLoadedVersions.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,4 +102,26 @@ public abstract class InternalFileContentProvider extends IncludeFileContentProv
|
|||
public final void setIncludeResolutionHeuristics(IIncludeFileResolutionHeuristics heuristics) {
|
||||
fIncludeResolutionHeuristics= heuristics;
|
||||
}
|
||||
|
||||
public List<ISignificantMacros> getLoadedVersions(String path) {
|
||||
List<ISignificantMacros> result = fLoadedVersions.get(path);
|
||||
return result == null ? Collections.<ISignificantMacros>emptyList() : result;
|
||||
}
|
||||
|
||||
public void addLoadedVersions(String path, int reduceVersions, ISignificantMacros sig) {
|
||||
List<ISignificantMacros> list= fLoadedVersions.get(path);
|
||||
if (list == null || reduceVersions == 0) {
|
||||
fLoadedVersions.put(path, Collections.singletonList(sig));
|
||||
} else if (!list.contains(sig)) {
|
||||
if (list.size() == 1) {
|
||||
ISignificantMacros first = list.get(0);
|
||||
list= new ArrayList<ISignificantMacros>(2);
|
||||
list.add(first);
|
||||
fLoadedVersions.put(path, list);
|
||||
} else if (reduceVersions > 0 && reduceVersions < list.size()) {
|
||||
list.subList(reduceVersions, list.size()).clear();
|
||||
}
|
||||
list.add(sig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -259,4 +259,9 @@ class LocationCtxContainer extends LocationCtx {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<synthetic>"; //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,4 +131,9 @@ class LocationCtxFile extends LocationCtxContainer {
|
|||
public boolean isSourceFile() {
|
||||
return fIsSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return fFilename;
|
||||
}
|
||||
}
|
|
@ -105,4 +105,9 @@ class LocationCtxMacroExpansion extends LocationCtx {
|
|||
public ASTPreprocessorName[] getNestedMacroReferences() {
|
||||
return fLocationMap.getNestedMacroReferences((ASTMacroExpansion) fExpansionName.getParent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Expansion of " + fExpansionName.toString(); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
|
|
@ -209,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, CharArrayObjectMap<char[]> sigMacros) {
|
||||
public void popContext(ILocationCtx locationCtx) {
|
||||
assert fCurrentContext == locationCtx;
|
||||
final LocationCtx child= fCurrentContext;
|
||||
final LocationCtx parent= (LocationCtx) fCurrentContext.getParent();
|
||||
|
@ -218,18 +218,6 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -242,7 +230,7 @@ public class LocationMap implements ILocationResolver {
|
|||
* @param userInclude <code>true</code> when specified with double-quotes.
|
||||
* @param active <code>true</code> when include appears in active code.
|
||||
*/
|
||||
public void encounterPoundInclude(int startOffset, int nameOffset, int nameEndOffset, int endOffset,
|
||||
public ASTInclusionStatement encounterPoundInclude(int startOffset, int nameOffset, int nameEndOffset, int endOffset,
|
||||
char[] name, String filename, boolean userInclude, boolean active, boolean heuristic,
|
||||
IFileNomination nominationDelegate) {
|
||||
startOffset= getSequenceNumberForOffset(startOffset);
|
||||
|
@ -252,6 +240,7 @@ public class LocationMap implements ILocationResolver {
|
|||
final ASTInclusionStatement inc = new ASTInclusionStatement(fTranslationUnit, startOffset, nameOffset,
|
||||
nameEndOffset, endOffset, name, filename, userInclude, active, heuristic, nominationDelegate);
|
||||
fDirectives.add(inc);
|
||||
return inc;
|
||||
}
|
||||
|
||||
public void encounteredComment(int offset, int endOffset, boolean isBlockComment) {
|
||||
|
|
|
@ -59,29 +59,22 @@ final class ScannerContext {
|
|||
private CharArraySet fInternalModifications;
|
||||
private CharArrayObjectMap<char[]> fSignificantMacros;
|
||||
private boolean fPragmaOnce;
|
||||
private int fLoadedVersionCount;
|
||||
|
||||
|
||||
/**
|
||||
* @param ctx
|
||||
* @param parent context to be used after this context is done.
|
||||
*/
|
||||
public ScannerContext(ILocationCtx ctx, ScannerContext parent, Lexer lexer,
|
||||
boolean trackSignificantMacros) {
|
||||
public ScannerContext(ILocationCtx ctx, ScannerContext parent, Lexer lexer) {
|
||||
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, null, false);
|
||||
this(ctx, parent, (Lexer) null);
|
||||
fTokens= tokens.first();
|
||||
fInactiveState= CodeState.eSkipInactive; // no branches in result of macro expansion
|
||||
}
|
||||
|
@ -323,8 +316,17 @@ final class ScannerContext {
|
|||
fFoundViaDirective= viaDirective;
|
||||
}
|
||||
|
||||
public void setPragmaOnce() {
|
||||
fPragmaOnce= true;
|
||||
public void trackSignificantMacros() {
|
||||
fInternalModifications= new CharArraySet(5);
|
||||
fSignificantMacros= new CharArrayObjectMap<char[]>(5);
|
||||
}
|
||||
|
||||
public void setPragmaOnce(boolean val) {
|
||||
fPragmaOnce= val;
|
||||
}
|
||||
|
||||
public boolean isPragmaOnce() {
|
||||
return fPragmaOnce;
|
||||
}
|
||||
|
||||
public void internalModification(char[] macroName) {
|
||||
|
@ -332,13 +334,7 @@ final class ScannerContext {
|
|||
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());
|
||||
|
@ -346,8 +342,6 @@ final class ScannerContext {
|
|||
}
|
||||
|
||||
public void significantMacroDefined(char[] macroName) {
|
||||
if (fPragmaOnce)
|
||||
return;
|
||||
if (fInternalModifications != null && !fInternalModifications.containsKey(macroName)) {
|
||||
addSignificantMacroDefined(macroName);
|
||||
}
|
||||
|
@ -362,20 +356,11 @@ final class ScannerContext {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -408,15 +393,6 @@ final class ScannerContext {
|
|||
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;
|
||||
|
@ -440,12 +416,22 @@ final class ScannerContext {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
public boolean visitIncluded(char[] path) {
|
||||
if (!fInternalModifications.containsKey(path)) {
|
||||
fSignificantMacros.put(path, SignificantMacros.INCLUDED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public int getLoadedVersionCount() {
|
||||
return fLoadedVersionCount;
|
||||
}
|
||||
|
||||
public void setLoadedVersionCount(int count) {
|
||||
fLoadedVersionCount= count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (fParent == null)
|
||||
return fLocationCtx.toString();
|
||||
|
||||
return fParent.toString() + "\n" + fLocationCtx.toString(); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,10 +30,8 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
|||
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);
|
||||
|
@ -64,8 +62,6 @@ public class SignificantMacros implements ISignificantMacros {
|
|||
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);
|
||||
}
|
||||
|
@ -120,11 +116,6 @@ public class SignificantMacros implements ISignificantMacros {
|
|||
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)
|
||||
|
@ -164,10 +155,6 @@ public class SignificantMacros implements ISignificantMacros {
|
|||
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;
|
||||
|
|
|
@ -488,6 +488,7 @@ abstract public class PDOMWriter {
|
|||
IIndexFileLocation location = fileKey.getLocation();
|
||||
ISignificantMacros significantMacros = fileKey.getSignificantMacros();
|
||||
IIndexFragmentFile oldFile = index.getWritableFile(linkageID, location, significantMacros);
|
||||
// mstodo this is wrong, see correct implementation in PDOMFile.clear().
|
||||
if (oldFile != null) {
|
||||
IIndexInclude[] includedBy = index.findIncludedBy(oldFile);
|
||||
if (includedBy.length > 0) {
|
||||
|
@ -513,18 +514,26 @@ abstract public class PDOMWriter {
|
|||
}
|
||||
}
|
||||
|
||||
IncludeInformation[] includeInfos= new IncludeInformation[lists.fIncludes.size()];
|
||||
List<IncludeInformation> includeInfos= new ArrayList<IncludeInformation>();
|
||||
for (int i= 0; i < lists.fIncludes.size(); i++) {
|
||||
final IASTPreprocessorIncludeStatement include = lists.fIncludes.get(i);
|
||||
final IncludeInformation info= includeInfos[i]= new IncludeInformation();
|
||||
info.fStatement= include;
|
||||
if (include.isResolved()) {
|
||||
info.fLocation= fResolver.resolveASTPath(include.getPath());
|
||||
info.fIsContext= include.isActive() &&
|
||||
(data.fContextIncludes.contains(include) || clearedContexts.contains(info.fLocation));
|
||||
final IASTPreprocessorIncludeStatement stmt = lists.fIncludes.get(i);
|
||||
if (!stmt.isResolved()) {
|
||||
includeInfos.add(new IncludeInformation(stmt, null, ISignificantMacros.NONE, false));
|
||||
} else {
|
||||
IIndexFileLocation targetLoc = fResolver.resolveASTPath(stmt.getPath());
|
||||
ISignificantMacros mainSig= stmt.getSignificantMacros();
|
||||
for (ISignificantMacros sig : stmt.getLoadedVersions()) {
|
||||
if (!sig.equals(mainSig)) {
|
||||
includeInfos.add(new IncludeInformation(stmt, targetLoc, sig, false));
|
||||
}
|
||||
}
|
||||
final boolean isContext = stmt.isActive() &&
|
||||
(data.fContextIncludes.contains(stmt) || clearedContexts.contains(targetLoc));
|
||||
includeInfos.add(new IncludeInformation(stmt, targetLoc, mainSig, isContext));
|
||||
}
|
||||
}
|
||||
index.setFileContent(file, linkageID, includeInfos, macros, names, fResolver, lock);
|
||||
IncludeInformation[] includeInfoArray= includeInfos.toArray(new IncludeInformation[includeInfos.size()]);
|
||||
index.setFileContent(file, linkageID, includeInfoArray, macros, names, fResolver, lock);
|
||||
}
|
||||
file.setTimestamp(fResolver.getLastModified(location));
|
||||
file.setEncodingHashcode(fResolver.getEncoding(location).hashCode());
|
||||
|
|
|
@ -865,11 +865,6 @@ public class PDOMFile implements IIndexFragmentFile {
|
|||
return sigMacros;
|
||||
}
|
||||
|
||||
|
||||
public boolean isComplete() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean hasContent() throws CoreException {
|
||||
return getTimestamp() != -1;
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ public class ProjectIndexerInputAdapter extends IndexerInputAdapter {
|
|||
public String getASTPath(IIndexFileLocation ifl) {
|
||||
IPath path= IndexLocationFactory.getAbsolutePath(ifl);
|
||||
if (path != null) {
|
||||
return path.toString();
|
||||
return path.toOSString();
|
||||
}
|
||||
return ifl.getURI().getPath();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue