diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index a0863b741a4..096032fb9ab 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -57,9 +57,11 @@ import org.eclipse.cdt.core.dom.ast.IASTInitializer; import org.eclipse.cdt.core.dom.ast.IASTInitializerList; import org.eclipse.cdt.core.dom.ast.IASTLabelStatement; import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; +import org.eclipse.cdt.core.dom.ast.IASTMacroExpansionLocation; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; import org.eclipse.cdt.core.dom.ast.IASTNullStatement; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; @@ -7426,4 +7428,29 @@ public class AST2Tests extends AST2TestBase { public void testNoRawStringInPlainC_397127() throws Exception { parseAndCheckBindings(getAboveComment(), C, true); } + + // #define X + // int a=X-1;X + public void testMacroReferences_399394() throws Exception { + IASTTranslationUnit tu= parseAndCheckBindings(getAboveComment()); + assertEquals(2, countMacroRefs(tu)); + + IASTSimpleDeclaration decl= getDeclaration(tu, 0); + assertEquals(1, countMacroRefs(decl)); + + IASTEqualsInitializer init= (IASTEqualsInitializer) decl.getDeclarators()[0].getInitializer(); + assertEquals(1, countMacroRefs(init)); + + IASTUnaryExpression expr= (IASTUnaryExpression) init.getInitializerClause(); + assertEquals(0, countMacroRefs(expr)); + } + + private int countMacroRefs(IASTNode node) { + int count = 0; + for (IASTNodeLocation loc : node.getNodeLocations()) { + if (loc instanceof IASTMacroExpansionLocation) + count++; + } + return count; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java index fee6a0479b0..3c62af24107 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/LocationCtx.java @@ -130,7 +130,7 @@ abstract class LocationCtx implements ILocationCtx { * Returns the sequence of file locations spanning the given range. * Assumes that the range starts within this context. */ - public abstract boolean collectLocations(int sequenceNumber, int length, ArrayList sofar); + public abstract void collectLocations(int sequenceNumber, int length, ArrayList sofar); /** * Support for the dependency tree, add inclusion statements found in this context. 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 6323e537149..4e11a04c5fe 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 @@ -32,7 +32,7 @@ class LocationCtxContainer extends LocationCtx { private int fChildSequenceLength; private ArrayList fChildren; - private AbstractCharArray fSource; + private final AbstractCharArray fSource; private int[] fLineOffsets; public LocationCtxContainer(LocationCtxContainer parent, AbstractCharArray source, @@ -138,47 +138,55 @@ class LocationCtxContainer extends LocationCtx { } @Override - public boolean collectLocations(int sequenceNumber, final int length, ArrayList locations) { + public void collectLocations(int sequenceNumber, final int length, ArrayList locations) { + if (length < 1) + return; + final int endSequenceNumber= sequenceNumber + length; if (fChildren != null) { int childIdx= Math.max(0, findChildIdxLessOrEqualThan(sequenceNumber, false)); for (; childIdx < fChildren.size(); childIdx++) { final LocationCtx child= fChildren.get(childIdx); - // create the location between start and the child + // Create the location between start and the child if (sequenceNumber < child.fSequenceNumber) { - // compute offset backwards from the child's offset + // Compute offset backwards from the child's offset in this location final int offset= child.fEndOffsetInParent - (child.fSequenceNumber - sequenceNumber); - // it the child is not affected, we are done. + + // Requested range ends before the child. if (endSequenceNumber <= child.fSequenceNumber) { addFileLocation(offset, endSequenceNumber - sequenceNumber, locations); - return true; + return; } - if (offset < child.fOffsetInParent) + + final int gapLen = child.fOffsetInParent - offset; + if (gapLen > 0) addFileLocation(offset, child.fOffsetInParent - offset, locations); + sequenceNumber= child.fSequenceNumber; + assert sequenceNumber < endSequenceNumber; } - // let the child create locations + // Let the child create locations final int childEndSequenceNumber= child.fSequenceNumber + child.getSequenceLength(); - if (sequenceNumber < childEndSequenceNumber) { - if (child.collectLocations(sequenceNumber, endSequenceNumber - sequenceNumber, locations)) { - return true; - } + if (sequenceNumber < childEndSequenceNumber + || (sequenceNumber == childEndSequenceNumber && !locations.isEmpty())) { + child.collectLocations(sequenceNumber, endSequenceNumber - sequenceNumber, locations); sequenceNumber= childEndSequenceNumber; + if (sequenceNumber >= endSequenceNumber) + return; } } } - // create the location after the last child. + // Create the location after the last child. final int myEndNumber = fSequenceNumber + getSequenceLength(); final int offset= fSource.getLength() - (myEndNumber - sequenceNumber); if (endSequenceNumber <= myEndNumber) { addFileLocation(offset, endSequenceNumber - sequenceNumber, locations); - return true; + } else { + addFileLocation(offset, fSource.getLength() - offset, locations); } - addFileLocation(offset, fSource.getLength() - offset, locations); - return false; } private ArrayList addFileLocation(int offset, int length, ArrayList sofar) { 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 d94e229e8fb..90bba002862 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 @@ -25,7 +25,7 @@ class LocationCtxMacroExpansion extends LocationCtx { private final LocationMap fLocationMap; private final int fLength; private final ImageLocationInfo[] fLocationInfos; - private ASTMacroReferenceName fExpansionName; + private final ASTMacroReferenceName fExpansionName; public LocationCtxMacroExpansion(LocationMap map, LocationCtxContainer parent, int parentOffset, int parentEndOffset, int sequenceNumber, int length, ImageLocationInfo[] imageLocations, ASTMacroReferenceName expansionName) { @@ -45,17 +45,15 @@ class LocationCtxMacroExpansion extends LocationCtx { } @Override - public boolean collectLocations(int start, int length, ArrayList locations) { + public void collectLocations(int start, int length, ArrayList locations) { final int offset= start - fSequenceNumber; assert offset >= 0 && length >= 0; if (offset + length <= fLength) { locations.add(new ASTMacroExpansionLocation(this, offset, length)); - return true; + } else { + locations.add(new ASTMacroExpansionLocation(this, offset, fLength-offset)); } - - locations.add(new ASTMacroExpansionLocation(this, offset, fLength-offset)); - return false; } public ASTMacroExpansion getExpansion() {