diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java index 554f9fb10cb..ed65bacc85c 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/LocationMapTests.java @@ -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()); diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java index e5a1f740031..733a182d082 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java @@ -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]); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIncludeStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIncludeStatement.java index 48d87122e44..ce8b34b8f2b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIncludeStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTPreprocessorIncludeStatement.java @@ -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(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IFileNomination.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IFileNomination.java index ed11da90a6d..28a91aa36d4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IFileNomination.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IFileNomination.java @@ -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(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ISignificantMacros.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ISignificantMacros.java index 1055359d157..e4182f46133 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ISignificantMacros.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ISignificantMacros.java @@ -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); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java index f338429b4cf..f6f48df2dda 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTTranslationUnit.java @@ -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 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java index bac8d3bb737..e4ba48a1ca2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IWritableIndex.java @@ -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; + } } /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedFileContentProvider.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedFileContentProvider.java index 59ef5536410..aeb87e376bf 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedFileContentProvider.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/IndexBasedFileContentProvider.java @@ -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 macros= new ArrayList(); List directives= new ArrayList(); Map newPragmaOnce= new HashMap(); - collectFileContent(file, null, newPragmaOnce, files, macros, directives, null); + LinkedHashSet preLoaded= new LinkedHashSet(); + collectFileContent(file, null, newPragmaOnce, preLoaded, files, macros, directives, null); // Report pragma once inclusions, only if no exception was thrown. fPragmaOnce.putAll(newPragmaOnce); - List 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 newPragmaOnce, - List files, List macros, - List usingDirectives, Set preventRecursion) - throws CoreException, NeedToParseException { + private boolean collectFileContent(IIndexFile file, IIndexFile stopAt, + Map newPragmaOnce, + LinkedHashSet preLoaded, List files, + List macros, List usingDirectives, + Set 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 filesIncluded= new ArrayList(); ArrayList macros= new ArrayList(); ArrayList directives= new ArrayList(); + LinkedHashSet preLoaded= new LinkedHashSet(); try { - if (!collectFileContent(contextFile, targetFile, newPragmaOnce, + if (!collectFileContent(contextFile, targetFile, newPragmaOnce, preLoaded, filesIncluded, macros, directives, new HashSet())) { return null; } @@ -285,15 +293,22 @@ public final class IndexBasedFileContentProvider extends InternalFileContentProv // Report pragma once inclusions. fPragmaOnce.putAll(newPragmaOnce); - List newPragmaOncePaths = toPathList(newPragmaOnce.keySet()); - return new InternalFileContent(GAP, macros, directives, new ArrayList(filesIncluded), - newPragmaOncePaths); + return new InternalFileContent(GAP, macros, directives, filesIncluded, toList(preLoaded)); } catch (CoreException e) { CCorePlugin.log(e); } return null; } + private List toList(LinkedHashSet preLoaded) throws CoreException { + List result= new ArrayList(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 ifiles= new HashSet(); ifiles.add(file); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java index ce596e117af..b766e82cc74 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/WritableCIndex.java @@ -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); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java index f5e6b0812d4..efbc029a29c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ASTPreprocessorNode.java @@ -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; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java index 1839974653c..14ca437f029 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java @@ -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 { @@ -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 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 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 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; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationCtx.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationCtx.java index ac52538bea4..2d9ac67ff07 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationCtx.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ILocationCtx.java @@ -30,4 +30,8 @@ public interface ILocationCtx { */ ILocationCtx getParent(); + /** + * Returns inclusion statement that created this context, or null. + */ + ASTInclusionStatement getInclusionStatement(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContent.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContent.java index 2eabe13dea5..56534886481 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContent.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContent.java @@ -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 fMacroDefinitions; private final List fUsingDirectives; private final String fFileLocation; - private final IFileNomination fPragmaOnceNomination; - private final List fNewPragmaOncePaths; + private final List fNonPragmaOnceFiles; private boolean fHeuristic; private boolean fIsSource= false; private List 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 null 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 null. */ public InternalFileContent(String fileLocation, List macroDefinitions, List usingDirectives, - List files, List newPragmaOncePaths) { + List files, List 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 getPragmaOncePaths() { - return fNewPragmaOncePaths; + public List 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. */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContentProvider.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContentProvider.java index b373a384f4e..82668c6293b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContentProvider.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/InternalFileContentProvider.java @@ -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 fPragmaOnce= new HashMap(); + private final Map> fLoadedVersions= new HashMap>(); /** * 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 getLoadedVersions(String path) { + List result = fLoadedVersions.get(path); + return result == null ? Collections.emptyList() : result; + } + + public void addLoadedVersions(String path, int reduceVersions, ISignificantMacros sig) { + List 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(2); + list.add(first); + fLoadedVersions.put(path, list); + } else if (reduceVersions > 0 && reduceVersions < list.size()) { + list.subList(reduceVersions, list.size()).clear(); + } + list.add(sig); + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java index 61e76bf99b5..bd4e98ad844 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxContainer.java @@ -259,4 +259,9 @@ class LocationCtxContainer extends LocationCtx { } return result; } + + @Override + public String toString() { + return ""; //$NON-NLS-1$ + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java index 8964b2bf755..a33b6195dbc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxFile.java @@ -131,4 +131,9 @@ class LocationCtxFile extends LocationCtxContainer { public boolean isSourceFile() { return fIsSource; } + + @Override + public String toString() { + return fFilename; + } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java index ed92105bffc..9e37e56a97f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtxMacroExpansion.java @@ -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$ + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java index 8033fadab4c..1e849f2b4f5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationMap.java @@ -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 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 true when specified with double-quotes. * @param active true 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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java index 8123be6e038..256fb07825e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ScannerContext.java @@ -59,29 +59,22 @@ final class ScannerContext { private CharArraySet fInternalModifications; private CharArrayObjectMap 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(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(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 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$ + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/SignificantMacros.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/SignificantMacros.java index 0310031b4cb..a997540fd5b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/SignificantMacros.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/SignificantMacros.java @@ -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 SORTER = new Comparator() { 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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java index 6b1870b07d3..828b879219b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOMWriter.java @@ -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 includeInfos= new ArrayList(); 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()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java index e05129ab740..ede7df54d4a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMFile.java @@ -865,11 +865,6 @@ public class PDOMFile implements IIndexFragmentFile { return sigMacros; } - - public boolean isComplete() { - return true; - } - public boolean hasContent() throws CoreException { return getTimestamp() != -1; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java index 2c712127471..85a503c9141 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/ProjectIndexerInputAdapter.java @@ -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(); }