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 87321b72d84..70b2676acdf 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 @@ -58,6 +58,7 @@ import org.eclipse.cdt.core.dom.ast.IASTNullStatement; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition; +import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorPragmaStatement; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement; import org.eclipse.cdt.core.dom.ast.IASTProblem; @@ -7324,4 +7325,21 @@ public class AST2Tests extends AST2BaseTest { parseAndCheckBindings(code, ParserLanguage.C, true); parseAndCheckBindings(code, ParserLanguage.CPP, true); } + + // #define MACRO + // void funca(){ + // } + // MACRO + public void testEmptyTrailingMacro_303152() throws Exception { + final String code = getAboveComment(); + for (ParserLanguage lang : ParserLanguage.values()) { + IASTTranslationUnit tu= parseAndCheckBindings(code, lang); + IASTPreprocessorMacroExpansion[] expansions = tu.getMacroExpansions(); + assertEquals(1, expansions.length); + IToken t= tu.getSyntax(); + while (t.getNext() != null) + t= t.getNext(); + assertEquals("MACRO", t.getImage()); + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/EndOfFileException.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/EndOfFileException.java index 3e1df3a1166..4545555c373 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/EndOfFileException.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/EndOfFileException.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2002, 2009 IBM Corporation and others. + * Copyright (c) 2002, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,6 +7,7 @@ * * Contributors: * John Camelon (IBM Rational Software) - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.core.parser; @@ -18,16 +19,21 @@ public class EndOfFileException extends Exception { private static final long serialVersionUID= 1607883323361197919L; private final boolean fEndsInactiveCode; + private final int fOffset; - public EndOfFileException() { - fEndsInactiveCode= false; + /** + * @since 5.2 + */ + public EndOfFileException(int offset) { + this(offset, false); } /** - * @since 5.1 + * @since 5.2 */ - public EndOfFileException(boolean endsInactiveCode) { - fEndsInactiveCode= true; + public EndOfFileException(int offset, boolean endsInactiveCode) { + fOffset= offset; + fEndsInactiveCode= endsInactiveCode; } /** @@ -36,4 +42,12 @@ public class EndOfFileException extends Exception { public boolean endsInactiveCode() { return fEndsInactiveCode; } + + /** + * Returns the offset at which the translation unit ends, or -1 if not known. + * @since 5.2 + */ + public int getEndOffset() { + return fOffset; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/OffsetLimitReachedException.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/OffsetLimitReachedException.java index fb5f470b2e1..95069ad46f4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/OffsetLimitReachedException.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/OffsetLimitReachedException.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2002, 2009 IBM Corporation and others. + * Copyright (c) 2002, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -41,6 +41,7 @@ public class OffsetLimitReachedException extends EndOfFileException { private final int fOrigin; public OffsetLimitReachedException(int origin, IToken lastToken) { + super(lastToken != null ? lastToken.getEndOffset() : -1); fOrigin= origin; finalToken= lastToken; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index 8c523178d8d..807e84dcf6a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -194,6 +194,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { private final INodeFactory nodeFactory; private boolean fActiveCode= true; + private int fEndOffset= -1; protected AbstractGNUSourceCodeParser(IScanner scanner, IParserLogService logService, ParserMode parserMode, @@ -268,7 +269,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { return t; } catch (OffsetLimitReachedException olre) { if (mode != ParserMode.COMPLETION_PARSE) - throw new EndOfFileException(); + throw new EndOfFileException(olre.getEndOffset()); createCompletionNode(olre.getFinalToken()); throw olre; } @@ -418,7 +419,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { private final void checkForEOI(IToken t) throws EndOfFileException { final int lt= t.getType(); if (lt == IToken.tINACTIVE_CODE_SEPARATOR || lt == IToken.tINACTIVE_CODE_END) - throw new EndOfFileException(true); + throw new EndOfFileException(t.getOffset(), true); } /** @@ -428,6 +429,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { try { return LA(i); } catch (EndOfFileException e) { + fEndOffset= e.getEndOffset(); return null; } } @@ -448,6 +450,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { try { return LT(i); } catch (EndOfFileException e) { + fEndOffset= e.getEndOffset(); return 0; } } @@ -679,7 +682,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { final int lt= t.getType(); if (lt == IToken.tINACTIVE_CODE_SEPARATOR || lt == IToken.tINACTIVE_CODE_END || lt == IToken.tINACTIVE_CODE_START) { if (!acceptInactiveCodeBoundary(codeBranchNesting)) - throw new EndOfFileException(true); + throw new EndOfFileException(t.getOffset(), true); } } result = consume(); @@ -691,7 +694,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { ++depth; break; case IToken.tEOC: - throw new EndOfFileException(); + throw new EndOfFileException(result.getOffset()); } } return result; @@ -1239,7 +1242,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { protected void parseTranslationUnit() { final IASTTranslationUnit tu= getTranslationUnit(); declarationList(tu, DeclarationOptions.GLOBAL, false, 0); - ((ASTNode) tu).setLength(getEndOffset()); + // Bug 3033152: getEndOffset() is computed off the last node and ignores trailing macros. + final int length= Math.max(getEndOffset(), fEndOffset); + ((ASTNode) tu).setLength(length); } protected final void declarationListInBraces(final IASTDeclarationListOwner tu, int offset, DeclarationOptions options) throws EndOfFileException, BacktrackException { @@ -1312,6 +1317,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { IASTDeclaration declaration= skipProblemDeclaration(offset); addDeclaration(tu, declaration, active); if (!e.endsInactiveCode()) { + fEndOffset= e.getEndOffset(); break; } } finally { @@ -1743,7 +1749,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { open--; break; case IToken.tEOC: - throw new EndOfFileException(); + throw new EndOfFileException(t.getOffset()); default: if (content != null) { 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 b1c02994393..9fcefe8490c 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 @@ -566,7 +566,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { case IToken.tEND_OF_INPUT: if (fContentAssistLimit < 0) { - throw new EndOfFileException(); + throw new EndOfFileException(t1.getOffset()); } int useType= fHandledCompletion ? IToken.tEOC : IToken.tCOMPLETION; int sequenceNumber= fLocationMap.getSequenceNumberForOffset(fContentAssistLimit);