1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-02 22:05:44 +02:00

fixed problem with friend classes not resolving, fixed offset calculations for qualified name nodes

This commit is contained in:
Mike Kucera 2008-04-01 16:58:22 +00:00
parent 427d783899
commit 30a1ab0388
9 changed files with 151 additions and 61 deletions

View file

@ -0,0 +1,53 @@
package org.eclipse.cdt.core.lrparser.tests.cpp;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.lrparser.BaseExtensibleLanguage;
import org.eclipse.cdt.core.dom.lrparser.c99.C99Language;
import org.eclipse.cdt.core.dom.lrparser.cpp.ISOCPPLanguage;
import org.eclipse.cdt.core.lrparser.tests.c99.C99Tests;
import org.eclipse.cdt.core.lrparser.tests.c99.ParseHelper;
import org.eclipse.cdt.core.model.ILanguage;
import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.tests.ast2.AST2CPPTests;
import org.eclipse.cdt.internal.core.parser.ParserException;
public class ISOCPPTests extends AST2CPPTests {
public static TestSuite suite() {
return suite(ISOCPPTests.class);
}
public ISOCPPTests() {
}
public ISOCPPTests(String name) {
super(name);
}
@SuppressWarnings("restriction")
@Override
protected IASTTranslationUnit parse( String code, ParserLanguage lang, @SuppressWarnings("unused") boolean useGNUExtensions, boolean expectNoProblems, @SuppressWarnings("unused") boolean parseComments) throws ParserException {
ILanguage language = lang.isCPP() ? getCPPLanguage() : getC99Language();
return ParseHelper.parse(code, language, expectNoProblems);
}
protected ILanguage getC99Language() {
return C99Language.getDefault();
}
protected ILanguage getCPPLanguage() {
return ISOCPPLanguage.getDefault();
}
public void testBug98704() throws Exception {
// this one gets stuck in infinite loop
}
}

View file

@ -442,7 +442,7 @@ template_opt
-- the ::=? is necessary for example 8.2.1 in the C++ spec to parse correctly -- the ::=? is necessary for example 8.2.1 in the C++ spec to parse correctly
dcolon_opt dcolon_opt
::=? '::' ::=? '::'
/. $Build consumePlaceHolder(); $EndBuild ./ /. $Build consumeToken(); $EndBuild ./ -- need the actual token to compute offsets
| $empty | $empty
/. $Build consumeEmpty(); $EndBuild ./ /. $Build consumeEmpty(); $EndBuild ./

View file

@ -350,7 +350,7 @@ public abstract class BuildASTParserAction {
} }
i++; i++;
} }
return tokens.subList(first, last+1); return tokens.subList(first, last + 1);
} }
@ -407,6 +407,17 @@ public abstract class BuildASTParserAction {
} }
/**
* Gets the current token and places it on the stack for later consumption.
*/
public void consumeToken() {
if(TRACE_ACTIONS) DebugUtil.printMethodTrace();
astStack.push(parser.getRightIToken());
if(TRACE_AST_STACK) System.out.println(astStack);
}
public void consumeTranslationUnit() { public void consumeTranslationUnit() {

View file

@ -157,7 +157,7 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
List<Object> arrayExpressions = astStack.closeScope(); List<Object> arrayExpressions = astStack.closeScope();
IASTTypeId typeId = (IASTTypeId) astStack.pop(); IASTTypeId typeId = (IASTTypeId) astStack.pop();
IASTExpression placement = (IASTExpression) astStack.pop(); // may be null IASTExpression placement = (IASTExpression) astStack.pop(); // may be null
boolean hasDoubleColon = astStack.pop() == PLACE_HOLDER; boolean hasDoubleColon = astStack.pop() != null;
ICPPASTNewExpression newExpression = nodeFactory.newCPPNewExpression(placement, initializer, typeId); ICPPASTNewExpression newExpression = nodeFactory.newCPPNewExpression(placement, initializer, typeId);
newExpression.setIsGlobal(hasDoubleColon); newExpression.setIsGlobal(hasDoubleColon);
@ -220,7 +220,7 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
if(TRACE_ACTIONS) DebugUtil.printMethodTrace(); if(TRACE_ACTIONS) DebugUtil.printMethodTrace();
IASTExpression operand = (IASTExpression) astStack.pop(); IASTExpression operand = (IASTExpression) astStack.pop();
boolean hasDoubleColon = astStack.pop() == PLACE_HOLDER; boolean hasDoubleColon = astStack.pop() != null;
ICPPASTDeleteExpression deleteExpr = nodeFactory.newDeleteExpression(operand); ICPPASTDeleteExpression deleteExpr = nodeFactory.newDeleteExpression(operand);
deleteExpr.setIsGlobal(hasDoubleColon); deleteExpr.setIsGlobal(hasDoubleColon);
@ -305,10 +305,13 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
IASTName name = (IASTName) astStack.pop(); IASTName name = (IASTName) astStack.pop();
boolean isTemplate = astStack.pop() == PLACE_HOLDER; boolean isTemplate = astStack.pop() == PLACE_HOLDER;
LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop(); LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop();
boolean hasDColon = astStack.pop() == PLACE_HOLDER; IToken dColon = (IToken) astStack.pop();
nestedNames.addFirst(name); nestedNames.addFirst(name);
IASTName qualifiedName = createQualifiedName(nestedNames, hasDColon);
int startOffset = dColon == null ? offset(nestedNames.getLast()) : offset(dColon);
int endOffset = endOffset(name);
IASTName qualifiedName = createQualifiedName(nestedNames, startOffset, endOffset, dColon != null);
ICPPASTTypenameExpression typenameExpr = nodeFactory.newCPPTypenameExpression(qualifiedName, expr, isTemplate); ICPPASTTypenameExpression typenameExpr = nodeFactory.newCPPTypenameExpression(qualifiedName, expr, isTemplate);
@ -698,41 +701,46 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
} }
private IASTName createQualifiedName(LinkedList<IASTName> nestedNames, int startOffset, int endOffset, boolean startsWithColonColon) {
return createQualifiedName(nestedNames, startOffset, endOffset, startsWithColonColon, false);
}
/** /**
* Creates a qualified name from a list of names (that must be in reverse order). * Creates a qualified name from a list of names (that must be in reverse order).
*
* @param names List of name nodes in reverse order
*/ */
@SuppressWarnings("restriction") @SuppressWarnings("restriction")
private IASTName createQualifiedName(LinkedList<IASTName> nestedNames, boolean startsWithColonColon) { private IASTName createQualifiedName(LinkedList<IASTName> names, int startOffset, int endOffset, boolean startsWithColonColon, boolean endsWithColonColon) {
if(!startsWithColonColon && nestedNames.size() == 1) // its actually an unqualified name if(!endsWithColonColon && !startsWithColonColon && names.size() == 1)
return nestedNames.get(0); return names.getFirst(); // its actually an unqualified name
int startOffset = offset(nestedNames.getLast());
int endOffset = endOffset(nestedNames.getFirst());
int length = endOffset - startOffset;
// find the tokens that make up the name
List<IToken> nameTokens = tokenOffsetSubList(parser.getRuleTokens(), startOffset, endOffset);
StringBuilder signature = new StringBuilder(startsWithColonColon ? "::" : ""); //$NON-NLS-1$ //$NON-NLS-2$
IToken prev = null;
for(IToken t : nameTokens) {
if(needSpaceBetween(prev, t))
signature.append(' ');
signature.append(t.toString());
prev = t;
}
ICPPASTQualifiedName qualifiedName = nodeFactory.newCPPQualifiedName(); ICPPASTQualifiedName qualifiedName = nodeFactory.newCPPQualifiedName();
qualifiedName.setFullyQualified(startsWithColonColon); qualifiedName.setFullyQualified(startsWithColonColon);
setOffsetAndLength(qualifiedName, startOffset, length); setOffsetAndLength(qualifiedName, startOffset, endOffset - startOffset);
((CPPASTQualifiedName)qualifiedName).setSignature(signature.toString()); for(IASTName name : reverseIterable(names))
for(IASTName name : reverseIterable(nestedNames))
qualifiedName.addName(name); qualifiedName.addName(name);
// compute the signature, find the tokens that make up the name
List<IToken> nameTokens = tokenOffsetSubList(parser.getRuleTokens(), startOffset, endOffset);
StringBuilder sb = new StringBuilder();
IToken prev = null;
for(IToken t : nameTokens) {
if(needSpaceBetween(prev, t))
sb.append(' ');
sb.append(t.toString());
prev = t;
}
((CPPASTQualifiedName)qualifiedName).setSignature(sb.toString());
// there must be a dummy name in the AST after the last double colon, this happens with pointer to member
if(endsWithColonColon) {
IASTName dummyName = nodeFactory.newName();
setOffsetAndLength(dummyName, endOffset, 0);
qualifiedName.addName(dummyName);
}
return qualifiedName; return qualifiedName;
} }
@ -770,15 +778,18 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
astStack.pop(); astStack.pop();
LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop(); LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop();
boolean startsWithColonColon = astStack.pop() == PLACE_HOLDER; IToken dColon = (IToken) astStack.pop();
if(nestedNames.isEmpty() && !startsWithColonColon) { // then its not a qualified name if(nestedNames.isEmpty() && dColon == null) { // then its not a qualified name
return lastName; return lastName;
} }
nestedNames.addFirst(lastName); // the list of names is in reverse order nestedNames.addFirst(lastName); // the list of names is in reverse order
return createQualifiedName(nestedNames, startsWithColonColon); int startOffset = dColon == null ? offset(nestedNames.getLast()) : offset(dColon);
int endOffset = endOffset(lastName);
return createQualifiedName(nestedNames, startOffset, endOffset, dColon != null);
} }
@ -796,14 +807,16 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
IASTName destructorTypeName = (IASTName) astStack.pop(); IASTName destructorTypeName = (IASTName) astStack.pop();
IASTName extraName = hasExtraTypeName ? (IASTName) astStack.pop() : null; IASTName extraName = hasExtraTypeName ? (IASTName) astStack.pop() : null;
LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop(); LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop();
boolean hasDColon = astStack.pop() == PLACE_HOLDER; IToken dColon = (IToken) astStack.pop();
if(hasExtraTypeName) if(hasExtraTypeName)
nestedNames.addFirst(extraName); nestedNames.addFirst(extraName);
nestedNames.addFirst(destructorTypeName); nestedNames.addFirst(destructorTypeName);
IASTName qualifiedName = createQualifiedName(nestedNames, hasDColon); int startOffset = dColon == null ? offset(nestedNames.getLast()) : offset(dColon);
int endOffset = endOffset(destructorTypeName);
IASTName qualifiedName = createQualifiedName(nestedNames, startOffset, endOffset, dColon != null);
setOffsetAndLength(qualifiedName); setOffsetAndLength(qualifiedName);
astStack.push(qualifiedName); astStack.push(qualifiedName);
@ -999,7 +1012,7 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
* @param token Allows subclasses to override this method and use any * @param token Allows subclasses to override this method and use any
* object to determine how to set a specifier. * object to determine how to set a specifier.
*/ */
protected void setSpecifier(IASTDeclSpecifier node, IToken token) { protected void setSpecifier(ICPPASTDeclSpecifier node, IToken token) {
//TODO int kind = asC99Kind(token) //TODO int kind = asC99Kind(token)
int kind = token.getKind(); int kind = token.getKind();
switch(kind){ switch(kind){
@ -1012,37 +1025,38 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
case TK_inline: node.setInline(true); return; case TK_inline: node.setInline(true); return;
case TK_const: node.setConst(true); return; case TK_const: node.setConst(true); return;
case TK_friend: node.setFriend(true); return;
case TK_virtual: node.setVirtual(true); return;
case TK_volatile: node.setVolatile(true); return; case TK_volatile: node.setVolatile(true); return;
case TK_explicit: node.setExplicit(true); return;
} }
if(node instanceof ICPPASTSimpleDeclSpecifier) { if(node instanceof ICPPASTSimpleDeclSpecifier) {
ICPPASTSimpleDeclSpecifier n = (ICPPASTSimpleDeclSpecifier) node; ICPPASTSimpleDeclSpecifier n = (ICPPASTSimpleDeclSpecifier) node;
switch(kind) { switch(kind) {
case TK_void: n.setType(IASTSimpleDeclSpecifier.t_void); break; case TK_void: n.setType(IASTSimpleDeclSpecifier.t_void); return;
case TK_char: n.setType(IASTSimpleDeclSpecifier.t_char); break; case TK_char: n.setType(IASTSimpleDeclSpecifier.t_char); return;
case TK_int: n.setType(IASTSimpleDeclSpecifier.t_int); break; case TK_int: n.setType(IASTSimpleDeclSpecifier.t_int); return;
case TK_float: n.setType(IASTSimpleDeclSpecifier.t_float); break; case TK_float: n.setType(IASTSimpleDeclSpecifier.t_float); return;
case TK_double: n.setType(IASTSimpleDeclSpecifier.t_double); break; case TK_double: n.setType(IASTSimpleDeclSpecifier.t_double); return;
case TK_bool: n.setType(ICPPASTSimpleDeclSpecifier.t_bool); break; case TK_bool: n.setType(ICPPASTSimpleDeclSpecifier.t_bool); return;
case TK_wchar_t: n.setType(ICPPASTSimpleDeclSpecifier.t_wchar_t); break; case TK_wchar_t: n.setType(ICPPASTSimpleDeclSpecifier.t_wchar_t); return;
case TK_signed: n.setSigned(true); break; case TK_signed: n.setSigned(true); return;
case TK_unsigned: n.setUnsigned(true); break; case TK_unsigned: n.setUnsigned(true); return;
case TK_long: n.setLong(true); break; case TK_long: n.setLong(true); return;
case TK_short: n.setShort(true); break; case TK_short: n.setShort(true); return;
case TK_friend: n.setFriend(true); break;
case TK_virtual: n.setVirtual(true); break;
case TK_volatile: n.setVolatile(true); break;
case TK_explicit: n.setExplicit(true); break;
} }
} }
} }
public void consumeDeclarationSpecifiersSimple() { public void consumeDeclarationSpecifiersSimple() {
if(TRACE_ACTIONS) DebugUtil.printMethodTrace(); if(TRACE_ACTIONS) DebugUtil.printMethodTrace();
IASTSimpleDeclSpecifier declSpec = nodeFactory.newCPPSimpleDeclSpecifier(); ICPPASTDeclSpecifier declSpec = nodeFactory.newCPPSimpleDeclSpecifier();
for(Object token : astStack.closeScope()) for(Object token : astStack.closeScope())
setSpecifier(declSpec, (IToken)token); setSpecifier(declSpec, (IToken)token);
@ -1063,7 +1077,7 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
List<Object> topScope = astStack.closeScope(); List<Object> topScope = astStack.closeScope();
// There's already a composite or elaborated or enum type specifier somewhere on the stack, find it. // There's already a composite or elaborated or enum type specifier somewhere on the stack, find it.
IASTDeclSpecifier declSpec = findFirstAndRemove(topScope, IASTDeclSpecifier.class); ICPPASTDeclSpecifier declSpec = findFirstAndRemove(topScope, ICPPASTDeclSpecifier.class);
// now apply the rest of the specifiers // now apply the rest of the specifiers
for(Object token : topScope) for(Object token : topScope)
@ -1344,14 +1358,15 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
int key = getCompositeTypeSpecifier(parser.getLeftIToken()); int key = getCompositeTypeSpecifier(parser.getLeftIToken());
List<Object> baseSpecifiers = astStack.closeScope(); List<Object> baseSpecifiers = astStack.closeScope();
// may be null, but if it is then hasNestedNameSpecifier == false // may be null, but if it is then hasNestedNameSpecifier == false
IASTName className = (IASTName) astStack.pop(); IASTName className = (IASTName) astStack.pop();
if(hasNestedNameSpecifier) { if(hasNestedNameSpecifier) {
LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop(); LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop();
nestedNames.addFirst(className); nestedNames.addFirst(className);
className = createQualifiedName(nestedNames, false); int startOffset = offset(nestedNames.getLast());
int endOffset = endOffset(className);
className = createQualifiedName(nestedNames, startOffset, endOffset, false);
} }
if(className == null) if(className == null)
@ -1433,10 +1448,21 @@ public class CPPBuildASTParserAction extends BuildASTParserAction {
if(TRACE_ACTIONS) DebugUtil.printMethodTrace(); if(TRACE_ACTIONS) DebugUtil.printMethodTrace();
List<Object> qualifiers = astStack.closeScope(); List<Object> qualifiers = astStack.closeScope();
LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop(); LinkedList<IASTName> nestedNames = (LinkedList<IASTName>) astStack.pop();
boolean hasDColon = astStack.pop() == PLACE_HOLDER; IToken dColon = (IToken) astStack.pop();
IASTName name = createQualifiedName(nestedNames, hasDColon);
int startOffset = dColon == null ? offset(nestedNames.getLast()) : offset(dColon);
int endOffset = endOffset(nestedNames.getFirst()); // temporary
// find the last double colon by searching for it
for(IToken t : reverseIterable(parser.getRuleTokens())) {
if(t.getKind() == TK_ColonColon) {
endOffset = endOffset(t);
break;
}
}
IASTName name = createQualifiedName(nestedNames, startOffset, endOffset, dColon != null, true);
ICPPASTPointerToMember pointer = nodeFactory.newPointerToMember(name); ICPPASTPointerToMember pointer = nodeFactory.newPointerToMember(name);
addCVQualifiersToPointer(pointer, qualifiers); addCVQualifiersToPointer(pointer, qualifiers);

View file

@ -416,7 +416,7 @@ public CPPExpressionStatementParser(String[] mapFrom) { // constructor
// Rule 42: dcolon_opt ::= :: // Rule 42: dcolon_opt ::= ::
// //
case 42: { action.builder. case 42: { action.builder.
consumePlaceHolder(); break; consumeToken(); break;
} }
// //

View file

@ -416,7 +416,7 @@ public CPPNoCastExpressionParser(String[] mapFrom) { // constructor
// Rule 42: dcolon_opt ::= :: // Rule 42: dcolon_opt ::= ::
// //
case 42: { action.builder. case 42: { action.builder.
consumePlaceHolder(); break; consumeToken(); break;
} }
// //

View file

@ -416,7 +416,7 @@ public CPPNoFunctionDeclaratorParser(String[] mapFrom) { // constructor
// Rule 42: dcolon_opt ::= :: // Rule 42: dcolon_opt ::= ::
// //
case 42: { action.builder. case 42: { action.builder.
consumePlaceHolder(); break; consumeToken(); break;
} }
// //

View file

@ -416,7 +416,7 @@ public CPPParser(String[] mapFrom) { // constructor
// Rule 42: dcolon_opt ::= :: // Rule 42: dcolon_opt ::= ::
// //
case 42: { action.builder. case 42: { action.builder.
consumePlaceHolder(); break; consumeToken(); break;
} }
// //

View file

@ -416,7 +416,7 @@ public CPPSizeofExpressionParser(String[] mapFrom) { // constructor
// Rule 42: dcolon_opt ::= :: // Rule 42: dcolon_opt ::= ::
// //
case 42: { action.builder. case 42: { action.builder.
consumePlaceHolder(); break; consumeToken(); break;
} }
// //