mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-21 21:52:10 +02:00
Bug 568957 - Header indexed with missing significant macros on multiple
headers with pragma once syntax Change-Id: Iada2129ec7bf4f239ffdaa13ca3e33e322aa1025 Signed-off-by: Michael Uhl <Michael.Uhl@NashTech.Com>
This commit is contained in:
parent
27b9002fbc
commit
28589d32a3
3 changed files with 203 additions and 1 deletions
|
@ -14,7 +14,11 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.index.tests;
|
||||
|
||||
import static org.eclipse.cdt.core.testplugin.util.TestSourceReader.createFile;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
|
@ -25,6 +29,7 @@ import org.eclipse.cdt.core.dom.ast.IVariable;
|
|||
import org.eclipse.cdt.core.index.IIndex;
|
||||
import org.eclipse.cdt.core.index.IIndexBinding;
|
||||
import org.eclipse.cdt.core.index.IIndexFile;
|
||||
import org.eclipse.cdt.core.index.IIndexFileLocation;
|
||||
import org.eclipse.cdt.core.index.IIndexInclude;
|
||||
import org.eclipse.cdt.core.index.IndexFilter;
|
||||
import org.eclipse.cdt.core.index.IndexLocationFactory;
|
||||
|
@ -36,11 +41,13 @@ import org.eclipse.cdt.core.testplugin.TestScannerProvider;
|
|||
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
|
||||
import org.eclipse.cdt.internal.core.pdom.indexer.IndexerPreferences;
|
||||
import org.eclipse.core.resources.IFile;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IWorkspaceRunnable;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.junit.Assert;
|
||||
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
|
@ -642,6 +649,143 @@ public class IndexIncludeTest extends IndexTestBase {
|
|||
}
|
||||
}
|
||||
|
||||
// #pragma once
|
||||
// #ifdef ABC
|
||||
// int x = 5;
|
||||
// #endif
|
||||
|
||||
// #pragma once
|
||||
// #include "b.hpp"
|
||||
|
||||
// #pragma once
|
||||
// #include "b.hpp"
|
||||
|
||||
// #include "a1.hpp"
|
||||
// #include "a2.hpp"
|
||||
public void testSignificantMacrosWithPragmeOnceSemantic() throws Exception {
|
||||
waitForIndexer();
|
||||
IProject prj = fProject.getProject();
|
||||
TestScannerProvider.sIncludes = new String[] { prj.getLocation().toOSString() };
|
||||
CharSequence[] contents = getContentsForTest(5);
|
||||
|
||||
IFile b = createFile(prj, "b.hpp", contents[0].toString());
|
||||
IFile a1 = createFile(prj, "a1.hpp", contents[1].toString());
|
||||
IFile a2 = createFile(prj, "a2.hpp", contents[2].toString());
|
||||
|
||||
final IFile main = createFile(prj, "UltimateTest.cpp", contents[3].toString());
|
||||
|
||||
waitUntilFileIsIndexed(fIndex, b);
|
||||
waitUntilFileIsIndexed(fIndex, a1);
|
||||
waitUntilFileIsIndexed(fIndex, a2);
|
||||
waitUntilFileIsIndexed(fIndex, main);
|
||||
|
||||
fIndex.acquireReadLock();
|
||||
try {
|
||||
IIndexFile[] indexFiles = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID,
|
||||
IndexLocationFactory.getWorkspaceIFL(main));
|
||||
|
||||
IIndexFile ultimateTestCppIdx = indexFiles[0];
|
||||
IIndexFile includes[] = new IIndexFile[3];
|
||||
includes[0] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(b))[0];
|
||||
includes[1] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(a1))[0];
|
||||
includes[2] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(a2))[0];
|
||||
|
||||
for (int i = 0; i < includes.length; i++) {
|
||||
IIndexFile include = includes[i];
|
||||
outputUnresolvedIncludes(fIndex, include.getLocation(), ultimateTestCppIdx, new HashSet<IIndexFile>());
|
||||
}
|
||||
} finally {
|
||||
fIndex.releaseReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
// #pragma once
|
||||
// #ifdef ABC
|
||||
// int x = 5;
|
||||
// #endif
|
||||
|
||||
// #pragma once
|
||||
// #include "b.hpp"
|
||||
|
||||
// #pragma once
|
||||
// #include "b.hpp"
|
||||
|
||||
// #pragma once
|
||||
// #include "b.hpp"
|
||||
|
||||
// #pragma once
|
||||
// #include "b.hpp"
|
||||
|
||||
// #include "a1.hpp"
|
||||
// #include "a2.hpp"
|
||||
|
||||
// #include "a3.hpp"
|
||||
// #include "a4.hpp"
|
||||
public void testSignificantMacrosWithPragmeOnceFromIdxSemantic() throws Exception {
|
||||
waitForIndexer();
|
||||
IProject prj = fProject.getProject();
|
||||
TestScannerProvider.sIncludes = new String[] { prj.getLocation().toOSString() };
|
||||
CharSequence[] contents = getContentsForTest(7);
|
||||
|
||||
IFile b = createFile(prj, "b.hpp", contents[0].toString());
|
||||
IFile a1 = createFile(prj, "a1.hpp", contents[1].toString());
|
||||
IFile a2 = createFile(prj, "a2.hpp", contents[2].toString());
|
||||
IFile a3 = createFile(prj, "a3.hpp", contents[3].toString());
|
||||
IFile a4 = createFile(prj, "a4.hpp", contents[4].toString());
|
||||
|
||||
final IFile s1 = createFile(prj, "s1.cpp", contents[5].toString());
|
||||
final IFile s2 = createFile(prj, "s2.cpp", contents[6].toString());
|
||||
|
||||
waitUntilFileIsIndexed(fIndex, b);
|
||||
waitUntilFileIsIndexed(fIndex, a1);
|
||||
waitUntilFileIsIndexed(fIndex, a2);
|
||||
waitUntilFileIsIndexed(fIndex, a3);
|
||||
waitUntilFileIsIndexed(fIndex, a4);
|
||||
waitUntilFileIsIndexed(fIndex, s1);
|
||||
waitUntilFileIsIndexed(fIndex, s2);
|
||||
|
||||
fIndex.acquireReadLock();
|
||||
try {
|
||||
IIndexFile[] indexFiles = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID,
|
||||
IndexLocationFactory.getWorkspaceIFL(s1));
|
||||
|
||||
IIndexFile ultimateTestCppIdx = indexFiles[0];
|
||||
IIndexFile includes[] = new IIndexFile[5];
|
||||
includes[0] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(b))[0];
|
||||
includes[1] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(a1))[0];
|
||||
includes[2] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(a2))[0];
|
||||
includes[3] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(a3))[0];
|
||||
includes[4] = fIndex.getFiles(ILinkage.CPP_LINKAGE_ID, IndexLocationFactory.getWorkspaceIFL(a4))[0];
|
||||
|
||||
for (int i = 0; i < includes.length; i++) {
|
||||
IIndexFile include = includes[i];
|
||||
outputUnresolvedIncludes(fIndex, include.getLocation(), ultimateTestCppIdx, new HashSet<IIndexFile>());
|
||||
}
|
||||
} finally {
|
||||
fIndex.releaseReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
private void outputUnresolvedIncludes(IIndex index, IIndexFileLocation ifl, IIndexFile ifile,
|
||||
Set<IIndexFile> handled) throws CoreException {
|
||||
if (ifile == null) {
|
||||
Assert.fail(ifl.getURI() + " is not indexed");
|
||||
} else if (handled.add(ifile)) {
|
||||
IIndexInclude[] includes = ifile.getIncludes();
|
||||
for (IIndexInclude inc : includes) {
|
||||
if (inc.isActive()) {
|
||||
if (inc.isResolved()) {
|
||||
IIndexFile next = index.resolveInclude(inc);
|
||||
outputUnresolvedIncludes(index, inc.getIncludesLocation(), next, handled);
|
||||
} else {
|
||||
Assert.fail("Unresolved inclusion: " + inc.getFullName() + " in file "
|
||||
+ inc.getIncludedByLocation().getURI());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void standardCheckUpdateIncludes(IFile header, IFile s1, String tag) throws Exception {
|
||||
fIndex.acquireReadLock();
|
||||
try {
|
||||
|
|
|
@ -185,7 +185,13 @@ 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);
|
||||
ISignificantMacros significantMacros = ISignificantMacros.NONE;
|
||||
try {
|
||||
significantMacros = once.getSignificantMacros();
|
||||
} catch (CoreException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
fc = new InternalFileContent(path, InclusionKind.SKIP_PRAGMA_ONCE_FILE, significantMacros);
|
||||
} else {
|
||||
fc = fFileContentProvider.getContentForInclusion(path, fMacroDictionaryFacade);
|
||||
}
|
||||
|
@ -1790,11 +1796,19 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
case SKIP_FILE:
|
||||
// Already included or fast parsing mode.
|
||||
break;
|
||||
|
||||
case SKIP_PRAGMA_ONCE_FILE:
|
||||
fCurrentContext.addSignificantMacros(fi.getSignificantMacros());
|
||||
break;
|
||||
}
|
||||
if (stmt == null) {
|
||||
// Found in index or skipped.
|
||||
stmt = fLocationMap.encounterPoundInclude(poundOffset, nameOffsets[0], nameOffsets[1], condEndOffset,
|
||||
headerName, path, userInclude, active, isHeuristic, nominationDelegate);
|
||||
if (fi.getKind() == InclusionKind.SKIP_PRAGMA_ONCE_FILE) {
|
||||
stmt.setSignificantMacros(fi.getSignificantMacros());
|
||||
stmt.setPragamOnceSemantics(true);
|
||||
}
|
||||
}
|
||||
// In a pragma once context store loaded versions of this non-pragma-once include
|
||||
if (pragmaOnceContext && loadedVerisons != null && !loadedVerisons.isEmpty()) {
|
||||
|
@ -1812,6 +1826,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
|
|||
for (FileVersion version : fi.getNonPragmaOnceVersions()) {
|
||||
fFileContentProvider.addLoadedVersions(version.fPath, Integer.MAX_VALUE, version.fSigMacros);
|
||||
}
|
||||
|
||||
fLocationMap.skippedFile(fLocationMap.getSequenceNumberForOffset(offset), fi);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,11 @@ public class InternalFileContent extends FileContent {
|
|||
* Instruct the preprocessor to skip this inclusion.
|
||||
*/
|
||||
SKIP_FILE,
|
||||
/**
|
||||
* Instruct the preprocessor to skip this inclusion because it has pragma
|
||||
* once semantic and has already been include for current translation unit.
|
||||
*/
|
||||
SKIP_PRAGMA_ONCE_FILE,
|
||||
/**
|
||||
* The file and its dependents are indexed, required information is read
|
||||
* from there.
|
||||
|
@ -67,6 +72,7 @@ public class InternalFileContent extends FileContent {
|
|||
private final long fTimestamp;
|
||||
private final long fFileSize;
|
||||
private final long fReadTime;
|
||||
private final ISignificantMacros fSignificantMacros;
|
||||
|
||||
/**
|
||||
* For skipping include files.
|
||||
|
@ -88,6 +94,33 @@ public class InternalFileContent extends FileContent {
|
|||
fTimestamp = NULL_TIMESTAMP;
|
||||
fFileSize = NULL_FILE_SIZE;
|
||||
fReadTime = 0;
|
||||
fSignificantMacros = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* For skipping include files that have pragma once semantic and have already been include
|
||||
* in the translation unit. Only the significant macros need to be forwarded to includer.
|
||||
* @param fileLocation the location of the file.
|
||||
* @param kind must be {@link InclusionKind#SKIP_FILE}.
|
||||
* @param significantMacros The significant macros this file.
|
||||
* @throws IllegalArgumentException if fileLocation is <code>null</code> or the kind value is illegal for
|
||||
* this constructor.
|
||||
*/
|
||||
public InternalFileContent(String fileLocation, InclusionKind kind, ISignificantMacros significantMacros)
|
||||
throws IllegalArgumentException {
|
||||
if (fileLocation == null || kind != InclusionKind.SKIP_PRAGMA_ONCE_FILE) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
fKind = kind;
|
||||
fFileLocation = fileLocation;
|
||||
fMacroDefinitions = null;
|
||||
fUsingDirectives = null;
|
||||
fSource = null;
|
||||
fNonPragmaOnceFiles = null;
|
||||
fTimestamp = NULL_TIMESTAMP;
|
||||
fFileSize = NULL_FILE_SIZE;
|
||||
fReadTime = 0;
|
||||
fSignificantMacros = significantMacros;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -111,6 +144,7 @@ public class InternalFileContent extends FileContent {
|
|||
fTimestamp = timestamp;
|
||||
fFileSize = fileSize;
|
||||
fReadTime = fileReadTime;
|
||||
fSignificantMacros = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,6 +167,7 @@ public class InternalFileContent extends FileContent {
|
|||
fTimestamp = NULL_TIMESTAMP;
|
||||
fFileSize = NULL_FILE_SIZE;
|
||||
fReadTime = 0;
|
||||
fSignificantMacros = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -154,6 +189,7 @@ public class InternalFileContent extends FileContent {
|
|||
fTimestamp = NULL_TIMESTAMP;
|
||||
fFileSize = NULL_FILE_SIZE;
|
||||
fReadTime = 0;
|
||||
fSignificantMacros = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -274,4 +310,11 @@ public class InternalFileContent extends FileContent {
|
|||
public String toString() {
|
||||
return getSource().toString();
|
||||
}
|
||||
|
||||
public ISignificantMacros getSignificantMacros() {
|
||||
if (fKind != InclusionKind.SKIP_PRAGMA_ONCE_FILE) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return fSignificantMacros;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue