mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Patch for Victor Mozgin.
Fixes problem with offsets of elements that were created as macro expansions (PR 36463).
This commit is contained in:
parent
35a76e8822
commit
4347f9b681
15 changed files with 279 additions and 30 deletions
|
@ -1,3 +1,7 @@
|
|||
2003-06-17 Victor Mozgin
|
||||
Added MacroTests.java (invocation in AllCoreTests).
|
||||
Added MacroTests.c to resources.
|
||||
|
||||
2003-06-17 Brent Nicolle
|
||||
Added Interface tests of IStructure.java.
|
||||
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Created on Jun 9, 2003
|
||||
* by bnicolle
|
||||
*/
|
||||
package org.eclipse.cdt.core.model.tests;
|
||||
|
||||
import org.eclipse.cdt.core.model.CModelException;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.model.CElement;
|
||||
|
||||
import junit.framework.*;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
|
||||
/**
|
||||
* @author bnicolle
|
||||
*
|
||||
*/
|
||||
public class MacroTests extends IntegratedCModelTest {
|
||||
/**
|
||||
* @param name
|
||||
*/
|
||||
public MacroTests(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.cdt.internal.core.model.IntegratedCModelTest
|
||||
*/
|
||||
public String getSourcefileSubdir() {
|
||||
return "resources/cmodel/";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.cdt.internal.core.model.IntegratedCModelTest
|
||||
*/
|
||||
public String getSourcefileResource() {
|
||||
return "MacroTests.c";
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns a test suite named after this class
|
||||
* containing all its public members named "test*"
|
||||
*/
|
||||
public static Test suite() {
|
||||
TestSuite suite= new TestSuite(MacroTests.class);
|
||||
return suite;
|
||||
}
|
||||
|
||||
|
||||
/* This is a list of elements in the test .c file. It will be used
|
||||
* in a number of places in the tests
|
||||
*/
|
||||
String[] expectedStringList= {"Z", "X", "Y",
|
||||
"SomeName", "", "A::BCD", "DEFA", "DB", "B::SomeName",
|
||||
"PINT", "myPINT", "foobar"};
|
||||
int[] expectedOffsets={ 8,26,39,55,75,89,114,130,152,187,212,227};
|
||||
int[] expectedLengths={ 1, 1, 1, 1, 1, 8, 4, 2, 18, 4, 6, 6};
|
||||
/* This is a list of that the types of the above list of elements is
|
||||
* expected to be.
|
||||
*/
|
||||
int[] expectedTypes= { ICElement.C_MACRO, ICElement.C_MACRO,
|
||||
ICElement.C_MACRO, ICElement.C_STRUCT,
|
||||
ICElement.C_STRUCT, ICElement.C_VARIABLE, ICElement.C_MACRO,
|
||||
ICElement.C_MACRO, ICElement.C_VARIABLE, ICElement.C_MACRO,
|
||||
ICElement.C_VARIABLE, ICElement.C_FUNCTION_DECLARATION};
|
||||
|
||||
|
||||
public void testMacro_0001() throws CModelException {
|
||||
ITranslationUnit myTranslationUnit = getTU();
|
||||
ICElement myElement;
|
||||
Stack missing=new Stack();
|
||||
int x;
|
||||
|
||||
for (x=0;x<expectedStringList.length;x++) {
|
||||
myElement=myTranslationUnit.getElement(expectedStringList[x]);
|
||||
if (myElement==null)
|
||||
missing.push(expectedStringList[x]);
|
||||
else {
|
||||
assertTrue("Expected:" + expectedStringList[x] + " Got:" + myElement.getElementName(),
|
||||
expectedStringList[x].equals(myElement.getElementName()));
|
||||
|
||||
assertTrue("Expected type for '" + expectedStringList[x] + "':" + expectedTypes[x] + " Got:" + myElement.getElementType(),
|
||||
expectedTypes[x] == myElement.getElementType());
|
||||
|
||||
int offset = -1;
|
||||
int length = -1;
|
||||
|
||||
if (myElement instanceof CElement) {
|
||||
CElement elem = (CElement)myElement;
|
||||
offset = elem.getIdStartPos();
|
||||
length = elem.getIdLength();
|
||||
}
|
||||
|
||||
assertTrue("Expected offset for '" + expectedStringList[x] + "':" + expectedOffsets[x] + " Got:" + offset,
|
||||
expectedOffsets[x] == offset);
|
||||
|
||||
assertTrue("Expected length for '" + expectedStringList[x] + "':" + expectedLengths[x] + " Got:" + length,
|
||||
expectedLengths[x] == length);
|
||||
}
|
||||
|
||||
}
|
||||
if (!missing.empty()) {
|
||||
String output=new String("Could not get elements: ");
|
||||
while (!missing.empty())
|
||||
output+=missing.pop() + " ";
|
||||
assertTrue(output, false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ import junit.framework.TestCase;
|
|||
import junit.framework.TestSuite;
|
||||
|
||||
import org.eclipse.cdt.core.model.tests.CModelElementsTests;
|
||||
import org.eclipse.cdt.core.model.tests.MacroTests;
|
||||
|
||||
/**
|
||||
* @author jcamelon
|
||||
|
@ -31,6 +32,7 @@ public class ParserTestSuite extends TestCase {
|
|||
suite.addTestSuite(DOMTests.class);
|
||||
suite.addTestSuite(ParserSymbolTableTest.class);
|
||||
suite.addTestSuite(CModelElementsTests.class);
|
||||
suite.addTestSuite(MacroTests.class);
|
||||
return suite;
|
||||
}
|
||||
|
||||
|
|
|
@ -723,10 +723,10 @@ public class ScannerTestCase extends BaseScannerTest
|
|||
assertNotNull(parms);
|
||||
assertTrue(expansion.size() == 3);
|
||||
assertTrue(((Token) expansion.get(0)).type == IToken.tIDENTIFIER);
|
||||
assertTrue(((Token) expansion.get(0)).image.equals("x"));
|
||||
assertTrue(((Token) expansion.get(0)).getImage().equals("x"));
|
||||
assertTrue(((Token) expansion.get(1)).type == IToken.tPLUS);
|
||||
assertTrue(((Token) expansion.get(2)).type == IToken.tINTEGER);
|
||||
assertTrue(((Token) expansion.get(2)).image.equals("1"));
|
||||
assertTrue(((Token) expansion.get(2)).getImage().equals("1"));
|
||||
|
||||
validateIdentifier("y");
|
||||
validateToken(IToken.tASSIGN);
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
#define Z struct
|
||||
#define X Z
|
||||
#define Y SomeName
|
||||
|
||||
X Y
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
|
||||
X{
|
||||
};
|
||||
|
||||
int A :: BCD = 1;
|
||||
|
||||
#define DEFA B
|
||||
#define DB( x ) x
|
||||
|
||||
int DEFA :: DB(Y) = 1;
|
||||
|
||||
#define PINT const int *
|
||||
|
||||
PINT myPINT;
|
||||
PINT foobar( void );
|
|
@ -26,12 +26,12 @@ public class Name {
|
|||
|
||||
public int getStartOffset()
|
||||
{
|
||||
return nameStart.offset;
|
||||
return nameStart.getOffset();
|
||||
}
|
||||
|
||||
public int getEndOffset()
|
||||
{
|
||||
return nameEnd.offset;
|
||||
return nameEnd.getOffset();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
@ -53,7 +53,7 @@ public class Name {
|
|||
|
||||
public int length()
|
||||
{
|
||||
return getEndOffset() - getStartOffset() + nameEnd.getImage().length();
|
||||
return getEndOffset() - getStartOffset() + nameEnd.getLength();
|
||||
}
|
||||
/**
|
||||
* @return
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
2003-06-20 Victor Mozgin
|
||||
Fixed PR 36463 : Offsets of macros are incorrect.
|
||||
|
||||
2003-06-17 Victor Mozgin
|
||||
Implemented correct handling of nested declarators in CModelBuilder.
|
||||
Added proper support for function pointers as parameters.
|
||||
|
|
|
@ -19,10 +19,43 @@ public interface IScannerContext {
|
|||
public static int INCLUSION = 2;
|
||||
public static int MACROEXPANSION = 3;
|
||||
|
||||
/**
|
||||
* This initializer is used for scanner contexts which are macro expansions.
|
||||
*
|
||||
* @param macroOffset Offset of the expanding macro
|
||||
* @param macroLength Length of the macro identifier
|
||||
* @return
|
||||
*/
|
||||
public IScannerContext initialize(Reader r, String f, int k, IASTInclusion i, int macroOffset, int macroLength);
|
||||
|
||||
public IScannerContext initialize(Reader r, String f, int k, IASTInclusion i);
|
||||
public int read() throws IOException;
|
||||
public String getFilename();
|
||||
|
||||
/**
|
||||
* Returns macro offset (the offset of the top expanded macro).
|
||||
* @return int
|
||||
*/
|
||||
public int getMacroOffset();
|
||||
|
||||
/**
|
||||
* Returns macro length (the length of the top expanded macro identifier).
|
||||
* @return int
|
||||
*/
|
||||
public int getMacroLength();
|
||||
|
||||
/**
|
||||
* Returns the offset.
|
||||
* @return int
|
||||
*/
|
||||
public int getOffset();
|
||||
|
||||
/**
|
||||
* Returns relative offset (relative to the beginning of the ScannerContext).
|
||||
* @return int
|
||||
*/
|
||||
public int getRelativeOffset();
|
||||
|
||||
public Reader getReader();
|
||||
|
||||
public int undoStackSize();
|
||||
|
|
|
@ -36,9 +36,23 @@ public class ContextStack {
|
|||
super();
|
||||
}
|
||||
|
||||
public void updateContext(Reader reader, String filename, int type, IASTInclusion inclusion, ISourceElementRequestor requestor) throws ScannerException {
|
||||
public void updateContext(Reader reader, String filename, int type, IASTInclusion inclusion, ISourceElementRequestor requestor) throws ScannerException {
|
||||
updateContext(reader, filename, type, inclusion, requestor, -1, -1);
|
||||
}
|
||||
|
||||
public void updateContext(Reader reader, String filename, int type, IASTInclusion inclusion, ISourceElementRequestor requestor, int macroOffset, int macroLength) throws ScannerException
|
||||
{
|
||||
// If we expand a macro within a macro, then keep offsets of the top-level one,
|
||||
// as only the top level macro identifier is properly positioned
|
||||
if (type == IScannerContext.MACROEXPANSION) {
|
||||
if (currentContext.getKind() == IScannerContext.MACROEXPANSION) {
|
||||
macroOffset = currentContext.getMacroOffset();
|
||||
macroLength = currentContext.getMacroLength();
|
||||
}
|
||||
}
|
||||
|
||||
undoStack.clear();
|
||||
push( new ScannerContext().initialize(reader, filename, type, null ), requestor );
|
||||
push( new ScannerContext().initialize(reader, filename, type, null, macroOffset, macroLength ), requestor );
|
||||
}
|
||||
|
||||
protected void push( IScannerContext context, ISourceElementRequestor requestor ) throws ScannerException
|
||||
|
|
|
@ -29,7 +29,7 @@ public class MacroDescriptor implements IMacroDescriptor {
|
|||
* definition.
|
||||
* @param tokens An ordered list of tokens that describe the
|
||||
* RHS expansion in the macro definition.
|
||||
* @param sig The complete signature of the macro, as a string.
|
||||
* @param sig The complete signature of the macro, as a string.
|
||||
*/
|
||||
public void initialize( String name, List identifiers, List tokens, String sig )
|
||||
{
|
||||
|
@ -67,7 +67,7 @@ public class MacroDescriptor implements IMacroDescriptor {
|
|||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
|
|
|
@ -59,7 +59,7 @@ public class Name {
|
|||
|
||||
public int length()
|
||||
{
|
||||
return getEndOffset() - getStartOffset() + nameEnd.getImage().length();
|
||||
return getEndOffset() - getStartOffset() + nameEnd.getLength();
|
||||
}
|
||||
/**
|
||||
* @return
|
||||
|
|
|
@ -603,6 +603,8 @@ public class Scanner implements IScanner {
|
|||
} else if (
|
||||
((c >= 'a') && (c <= 'z'))
|
||||
|| ((c >= 'A') && (c <= 'Z')) | (c == '_')) {
|
||||
|
||||
int baseOffset = lastContext.getOffset() - lastContext.undoStackSize() - 1;
|
||||
|
||||
if( madeMistake ) madeMistake = false;
|
||||
// String buffer is slow, we need a better way such as memory mapped files
|
||||
|
@ -630,7 +632,7 @@ public class Scanner implements IScanner {
|
|||
|
||||
if (mapping != null) {
|
||||
if( contextStack.shouldExpandDefinition( POUND_DEFINE + ident ) ) {
|
||||
expandDefinition(ident, mapping);
|
||||
expandDefinition(ident, mapping, baseOffset);
|
||||
c = getChar();
|
||||
continue;
|
||||
}
|
||||
|
@ -1864,7 +1866,7 @@ public class Scanner implements IScanner {
|
|||
buffer.append((char) c);
|
||||
c = getChar(true);
|
||||
}
|
||||
|
||||
|
||||
String parameters = buffer.toString();
|
||||
|
||||
// replace StringTokenizer later -- not performant
|
||||
|
@ -2023,11 +2025,14 @@ public class Scanner implements IScanner {
|
|||
return parameterValues;
|
||||
}
|
||||
|
||||
protected void expandDefinition(String symbol, Object expansion)
|
||||
throws ScannerException {
|
||||
protected void expandDefinition(String symbol, Object expansion, int symbolOffset)
|
||||
throws ScannerException
|
||||
{
|
||||
// All the tokens generated by the macro expansion
|
||||
// will have dimensions (offset and length) equal to the expanding symbol.
|
||||
if (expansion instanceof String ) {
|
||||
String replacementValue = (String) expansion;
|
||||
contextStack.updateContext( new StringReader(replacementValue), (POUND_DEFINE + symbol ), ScannerContext.MACROEXPANSION, null, requestor );
|
||||
contextStack.updateContext( new StringReader(replacementValue), (POUND_DEFINE + symbol ), ScannerContext.MACROEXPANSION, null, requestor, symbolOffset, symbol.length());
|
||||
} else if (expansion instanceof IMacroDescriptor ) {
|
||||
IMacroDescriptor macro = (IMacroDescriptor) expansion;
|
||||
skipOverWhitespace();
|
||||
|
@ -2049,6 +2054,9 @@ public class Scanner implements IScanner {
|
|||
buffer.append((char) c);
|
||||
c = getChar( true );
|
||||
}
|
||||
|
||||
// Position of the closing ')'
|
||||
int endMacroOffset = lastContext.getOffset() - lastContext.undoStackSize() - 1;
|
||||
|
||||
String betweenTheBrackets = buffer.toString().trim();
|
||||
|
||||
|
@ -2141,10 +2149,10 @@ public class Scanner implements IScanner {
|
|||
if (i < (numberOfTokens-1)) // Do not append to the last one
|
||||
buffer.append( " " );
|
||||
}
|
||||
String finalString = buffer.toString();
|
||||
String finalString = buffer.toString();
|
||||
contextStack.updateContext(
|
||||
new StringReader(finalString),
|
||||
POUND_DEFINE + macro.getSignature(), ScannerContext.MACROEXPANSION, null, requestor );
|
||||
POUND_DEFINE + macro.getSignature(), ScannerContext.MACROEXPANSION, null, requestor, symbolOffset, endMacroOffset - symbolOffset + 1 );
|
||||
} else
|
||||
if (throwExceptionOnBadMacroExpansion)
|
||||
throw new ScannerException(
|
||||
|
|
|
@ -21,20 +21,36 @@ public class ScannerContext implements IScannerContext
|
|||
{
|
||||
private Reader reader;
|
||||
private String filename;
|
||||
private int macroOffset = -1;
|
||||
private int macroLength = -1;
|
||||
private int offset;
|
||||
private Stack undo = new Stack();
|
||||
private int kind;
|
||||
|
||||
public ScannerContext(){}
|
||||
public IScannerContext initialize(Reader r, String f, int k, IASTInclusion i)
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.internal.core.parser.IScannerContext#initialize(Reader, String, int, IASTInclusion, int, int)
|
||||
*/
|
||||
public IScannerContext initialize(Reader r, String f, int k, IASTInclusion i, int mO, int mL)
|
||||
{
|
||||
reader = r;
|
||||
filename = f;
|
||||
offset = 0;
|
||||
kind = k;
|
||||
inc = i;
|
||||
inc = i;
|
||||
macroOffset = mO;
|
||||
macroLength = mL;
|
||||
return this;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.internal.core.parser.IScannerContext#initialize(Reader, String, int, IASTInclusion)
|
||||
*/
|
||||
public IScannerContext initialize(Reader r, String f, int k, IASTInclusion i)
|
||||
{
|
||||
return initialize(r, f, k, i, -1, -1);
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
++offset;
|
||||
|
@ -49,15 +65,40 @@ public class ScannerContext implements IScannerContext
|
|||
{
|
||||
return filename;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.internal.core.parser.IScannerContext#getExtension()
|
||||
*/
|
||||
public final int getMacroOffset()
|
||||
{
|
||||
return macroOffset;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.internal.core.parser.IScannerContext#getMacroLength()
|
||||
*/
|
||||
public final int getMacroLength()
|
||||
{
|
||||
return macroLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the offset.
|
||||
* @return int
|
||||
*/
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.internal.core.parser.IScannerContext#getOffset()
|
||||
*/
|
||||
public final int getOffset()
|
||||
{
|
||||
return offset;
|
||||
// All the tokens generated by the macro expansion
|
||||
// will have dimensions (offset and length) equal to the expanding symbol.
|
||||
return (macroOffset < 0) ? offset : macroOffset;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.internal.core.parser.IScannerContext#getRelativeOffset()
|
||||
*/
|
||||
public final int getRelativeOffset()
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reader.
|
||||
|
|
|
@ -20,6 +20,8 @@ public class Token implements IToken {
|
|||
image = i;
|
||||
filename = context.getFilename();
|
||||
offset = context.getOffset() - image.length() - context.undoStackSize();
|
||||
macroOffset = context.getMacroOffset();
|
||||
macroLength = context.getMacroLength();
|
||||
|
||||
if( type == tLSTRING || type == tSTRING || type == tCHAR ){
|
||||
offset--;
|
||||
|
@ -39,13 +41,18 @@ public class Token implements IToken {
|
|||
public int type;
|
||||
public int getType() { return type; }
|
||||
|
||||
public String image;
|
||||
protected String image;
|
||||
public String getImage() { return image; }
|
||||
|
||||
public String filename;
|
||||
public int offset;
|
||||
public int getOffset() { return offset; }
|
||||
public int getLength() { return image.length(); }
|
||||
|
||||
protected int offset;
|
||||
protected int macroOffset = -1;
|
||||
protected int macroLength = -1;
|
||||
// All the tokens generated by the macro expansion
|
||||
// will have dimensions (offset and length) equal to the expanding symbol.
|
||||
public int getOffset() { return (macroOffset < 0) ? offset : macroOffset; }
|
||||
public int getLength() { return (macroLength < 0) ? image.length() : macroLength; }
|
||||
public int getEndOffset() { return getOffset() + getLength(); }
|
||||
|
||||
|
||||
|
|
|
@ -723,10 +723,10 @@ public class ScannerTestCase extends BaseScannerTest
|
|||
assertNotNull(parms);
|
||||
assertTrue(expansion.size() == 3);
|
||||
assertTrue(((Token) expansion.get(0)).type == IToken.tIDENTIFIER);
|
||||
assertTrue(((Token) expansion.get(0)).image.equals("x"));
|
||||
assertTrue(((Token) expansion.get(0)).getImage().equals("x"));
|
||||
assertTrue(((Token) expansion.get(1)).type == IToken.tPLUS);
|
||||
assertTrue(((Token) expansion.get(2)).type == IToken.tINTEGER);
|
||||
assertTrue(((Token) expansion.get(2)).image.equals("1"));
|
||||
assertTrue(((Token) expansion.get(2)).getImage().equals("1"));
|
||||
|
||||
validateIdentifier("y");
|
||||
validateToken(IToken.tASSIGN);
|
||||
|
|
Loading…
Add table
Reference in a new issue