mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-07 09:46:02 +02:00
Unnecessary ambiguity in sizeof expression, bug 252243.
This commit is contained in:
parent
a3765fa703
commit
4e20a3afa8
4 changed files with 60 additions and 94 deletions
|
@ -5993,4 +5993,18 @@ public class AST2Tests extends AST2BaseTest {
|
|||
bh= new BindingAssertionHelper(code, false);
|
||||
bh.assertProblem("TInt; //ref", 4);
|
||||
}
|
||||
|
||||
// typedef int x, y;
|
||||
// void func(int c) {
|
||||
// c= sizeof(x(y));
|
||||
// x(y);
|
||||
// }
|
||||
public void testSizeofFunctionType_252243() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(code, lang == ParserLanguage.CPP);
|
||||
ba.assertProblem("y));", 1);
|
||||
IVariable v= ba.assertNonProblem("y);", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ import org.eclipse.cdt.core.dom.ast.ASTCompletionNode;
|
|||
import org.eclipse.cdt.core.dom.ast.ASTGenericVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTASMDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTBreakStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCaseStatement;
|
||||
|
@ -38,7 +37,6 @@ import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFieldDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
|
||||
|
@ -1776,23 +1774,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
backup(lastTokenOfExpression); consume();
|
||||
return expressionStatement;
|
||||
}
|
||||
|
||||
// a function call interpreted as declaration: 'func(x);' --> 'func x;'
|
||||
if (declarators.length == 1) {
|
||||
IASTName name= ((IASTNamedTypeSpecifier) declspec).getName();
|
||||
final IASTDeclarator dtor= declarators[0];
|
||||
if (name.contains(declspec)) {
|
||||
if (dtor.getNestedDeclarator() != null) {
|
||||
if (dtor instanceof IASTAmbiguousDeclarator == false
|
||||
&& dtor instanceof IASTArrayDeclarator == false
|
||||
&& dtor instanceof IASTFieldDeclarator == false
|
||||
&& dtor instanceof IASTFunctionDeclarator == false) {
|
||||
backup(lastTokenOfExpression); consume();
|
||||
return expressionStatement;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2090,7 +2071,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
consume(IToken.tLPAREN);
|
||||
int typeidOffset= LA(1).getOffset();
|
||||
typeid= typeId(DeclarationOptions.TYPEID);
|
||||
if (typeid != null) {
|
||||
if (!isValidTypeIDForUnaryExpression(unaryExprKind, typeid)) {
|
||||
typeid= null;
|
||||
} else {
|
||||
switch(LT(1)) {
|
||||
case IToken.tRPAREN:
|
||||
case IToken.tEOC:
|
||||
|
@ -2167,7 +2150,18 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
return ambExpr;
|
||||
}
|
||||
|
||||
protected abstract IASTAmbiguousExpression createAmbiguousExpression();
|
||||
private boolean isValidTypeIDForUnaryExpression(int unaryExprKind, IASTTypeId typeid) {
|
||||
if (typeid == null)
|
||||
return false;
|
||||
if (unaryExprKind == IASTUnaryExpression.op_sizeof) {
|
||||
// 5.3.3.1
|
||||
if (ASTQueries.findTypeRelevantDeclarator(typeid.getAbstractDeclarator()) instanceof IASTFunctionDeclarator)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract IASTAmbiguousExpression createAmbiguousExpression();
|
||||
protected abstract IASTAmbiguousExpression createAmbiguousBinaryVsCastExpression(IASTBinaryExpression binary, IASTCastExpression castExpr);
|
||||
protected abstract IASTAmbiguousExpression createAmbiguousCastVsFunctionCallExpression(IASTCastExpression castExpr, IASTFunctionCallExpression funcCall);
|
||||
|
||||
|
|
|
@ -10,10 +10,8 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||
|
@ -25,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
|
||||
|
@ -36,22 +35,10 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
|||
* Visitor to resolve ast ambiguities in the right order
|
||||
*/
|
||||
final class CPPASTAmbiguityResolver extends ASTVisitor {
|
||||
private static class ClassContext {
|
||||
ArrayList<IASTNode> fDeferredNodes;
|
||||
final IASTNode fNode;
|
||||
public ClassContext(IASTNode node) {
|
||||
fNode= node;
|
||||
}
|
||||
public void deferNode(IASTNode node) {
|
||||
if (fDeferredNodes == null)
|
||||
fDeferredNodes= new ArrayList<IASTNode>();
|
||||
fDeferredNodes.add(node);
|
||||
}
|
||||
}
|
||||
private LinkedList<ClassContext> fContextStack;
|
||||
private ClassContext fCurrentContext;
|
||||
private int fSkipInitializers= 0;
|
||||
private int fDeferFunctions= 1;
|
||||
private HashSet<IASTDeclaration> fRepopulate= new HashSet<IASTDeclaration>();
|
||||
private LinkedList<IASTNode> fDeferredNodes= new LinkedList<IASTNode>();
|
||||
|
||||
public CPPASTAmbiguityResolver() {
|
||||
super(false);
|
||||
|
@ -60,6 +47,7 @@ final class CPPASTAmbiguityResolver extends ASTVisitor {
|
|||
shouldVisitDeclarations= true;
|
||||
shouldVisitDeclSpecifiers= true;
|
||||
shouldVisitInitializers= true;
|
||||
shouldVisitTranslationUnit= true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,13 +79,7 @@ final class CPPASTAmbiguityResolver extends ASTVisitor {
|
|||
@Override
|
||||
public int visit(IASTDeclSpecifier declSpec) {
|
||||
if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
|
||||
if (fCurrentContext != null) {
|
||||
// defer visiting nested classes until the outer class body has been visited.
|
||||
fCurrentContext.deferNode(declSpec);
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
pushContext();
|
||||
fCurrentContext= new ClassContext(declSpec);
|
||||
fDeferFunctions++;
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
@ -105,46 +87,14 @@ final class CPPASTAmbiguityResolver extends ASTVisitor {
|
|||
@Override
|
||||
public int leave(IASTDeclSpecifier declSpec) {
|
||||
if (declSpec instanceof ICPPASTCompositeTypeSpecifier) {
|
||||
assert fCurrentContext != null;
|
||||
assert fCurrentContext.fNode == declSpec;
|
||||
if (fCurrentContext != null) {
|
||||
final List<IASTNode> deferredNodes = fCurrentContext.fDeferredNodes;
|
||||
fCurrentContext= null;
|
||||
if (deferredNodes != null) {
|
||||
for (IASTNode node : deferredNodes) {
|
||||
node.accept(this);
|
||||
}
|
||||
}
|
||||
popContext();
|
||||
}
|
||||
fDeferFunctions--;
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
||||
private void pushContext() {
|
||||
if (fCurrentContext==null) {
|
||||
if (fContextStack != null && !fContextStack.isEmpty()) {
|
||||
fContextStack.addLast(null);
|
||||
}
|
||||
} else {
|
||||
if (fContextStack == null) {
|
||||
fContextStack= new LinkedList<ClassContext>();
|
||||
}
|
||||
fContextStack.addLast(fCurrentContext);
|
||||
}
|
||||
}
|
||||
|
||||
private void popContext() {
|
||||
if (fContextStack == null || fContextStack.isEmpty()) {
|
||||
fCurrentContext= null;
|
||||
} else {
|
||||
fCurrentContext= fContextStack.removeLast();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTDeclaration decl) {
|
||||
if (decl instanceof IASTFunctionDefinition) {
|
||||
if (fDeferFunctions > 0 && decl instanceof IASTFunctionDefinition) {
|
||||
final IASTFunctionDefinition fdef= (IASTFunctionDefinition) decl;
|
||||
|
||||
// visit the declarator first, it may contain ambiguous template arguments needed
|
||||
|
@ -152,13 +102,10 @@ final class CPPASTAmbiguityResolver extends ASTVisitor {
|
|||
fSkipInitializers++;
|
||||
ASTQueries.findOutermostDeclarator(fdef.getDeclarator()).accept(this);
|
||||
fSkipInitializers--;
|
||||
|
||||
if (fCurrentContext != null) {
|
||||
// defer visiting the body of the function until the class body has been visited.
|
||||
fdef.getDeclSpecifier().accept(this);
|
||||
fCurrentContext.deferNode(decl);
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
fdef.getDeclSpecifier().accept(this);
|
||||
// defer visiting the body of the function until the class body has been visited.
|
||||
fDeferredNodes.add(decl);
|
||||
return PROCESS_SKIP;
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
@ -171,6 +118,23 @@ final class CPPASTAmbiguityResolver extends ASTVisitor {
|
|||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTInitializer initializer) {
|
||||
if (fSkipInitializers > 0)
|
||||
return PROCESS_SKIP;
|
||||
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int leave(IASTTranslationUnit tu) {
|
||||
while (!fDeferredNodes.isEmpty()) {
|
||||
fDeferFunctions= 0;
|
||||
fDeferredNodes.removeFirst().accept(this);
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
||||
private void repopulateScope(IASTDeclaration declaration) {
|
||||
IScope scope= CPPVisitor.getContainingNonTemplateScope(declaration);
|
||||
if (scope instanceof ICPPASTInternalScope) {
|
||||
|
@ -183,12 +147,4 @@ final class CPPASTAmbiguityResolver extends ASTVisitor {
|
|||
CPPSemantics.populateCache((ICPPASTInternalScope) scope, declaration);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int visit(IASTInitializer initializer) {
|
||||
if (fSkipInitializers > 0)
|
||||
return PROCESS_SKIP;
|
||||
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -271,13 +271,15 @@ public class LookupData {
|
|||
return true;
|
||||
}
|
||||
if (p1 instanceof IASTExpression) {
|
||||
ASTNodeProperty prop = p1.getPropertyInParent();
|
||||
if (p1 instanceof IASTIdExpression) {
|
||||
p1= p1.getParent();
|
||||
}
|
||||
while (p1 instanceof IASTUnaryExpression && ((IASTUnaryExpression) p1).getOperator() == IASTUnaryExpression.op_bracketedPrimary) {
|
||||
prop = p1.getPropertyInParent();
|
||||
p1= p1.getParent();
|
||||
}
|
||||
if (p1 instanceof IASTFunctionCallExpression) {
|
||||
if (p1 instanceof IASTFunctionCallExpression && prop == IASTFunctionCallExpression.FUNCTION_NAME) {
|
||||
return true;
|
||||
}
|
||||
} else if (p1 instanceof ICPPASTNamedTypeSpecifier && p2 instanceof IASTTypeId) {
|
||||
|
|
Loading…
Add table
Reference in a new issue