mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 09:25:31 +02:00
Handling problems in declarations, bug 100321, 234085 and 238151.
This commit is contained in:
parent
525c3124a7
commit
53841121fb
14 changed files with 1332 additions and 656 deletions
|
@ -1,26 +1,28 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2006 IBM Corporation and others.
|
||||
* Copyright (c) 2005, 2008 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
/*
|
||||
* Created on Jun 9, 2003
|
||||
* by bnicolle
|
||||
*/
|
||||
package org.eclipse.cdt.core.model.tests;
|
||||
|
||||
import org.eclipse.cdt.core.model.*;
|
||||
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
|
||||
|
||||
import junit.framework.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import org.eclipse.cdt.core.model.CModelException;
|
||||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.IField;
|
||||
import org.eclipse.cdt.core.model.IMethodDeclaration;
|
||||
import org.eclipse.cdt.core.model.IStructure;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.core.parser.ast.ASTAccessVisibility;
|
||||
|
||||
/**
|
||||
* @author bnicolle
|
||||
*
|
||||
|
@ -36,6 +38,7 @@ public class IStructureTests extends IntegratedCModelTest {
|
|||
/**
|
||||
* @see org.eclipse.cdt.internal.core.model.IntegratedCModelTest
|
||||
*/
|
||||
@Override
|
||||
public String getSourcefileSubdir() {
|
||||
return "resources/cmodel/";
|
||||
}
|
||||
|
@ -43,6 +46,7 @@ public class IStructureTests extends IntegratedCModelTest {
|
|||
/**
|
||||
* @see org.eclipse.cdt.internal.core.model.IntegratedCModelTest
|
||||
*/
|
||||
@Override
|
||||
public String getSourcefileResource() {
|
||||
return "IStructure.cpp";
|
||||
}
|
||||
|
@ -83,7 +87,7 @@ public class IStructureTests extends IntegratedCModelTest {
|
|||
ITranslationUnit tu = getTU();
|
||||
List arrayStructs = tu.getChildrenOfType(ICElement.C_STRUCT);
|
||||
String[] myExpectedStructs = {
|
||||
"testStruct1", "testStruct2", "testStruct3",
|
||||
"testStruct1", "testStruct2", "testStruct3", "testStruct4NoSemicolon",
|
||||
/* 2 anonymous structs */ "", "", "testStruct7",
|
||||
"testStruct8"
|
||||
};
|
||||
|
@ -98,8 +102,8 @@ public class IStructureTests extends IntegratedCModelTest {
|
|||
ITranslationUnit tu = getTU();
|
||||
List arrayClasses = tu.getChildrenOfType(ICElement.C_CLASS);
|
||||
String[] myExpectedClasses = {
|
||||
"testClass1", "testClass3", "testClass4Abstract",
|
||||
"testClass5", "testClass6" };
|
||||
"testClass1", "testClass2NoSemicolon", "testClass3", "testClass4Abstract",
|
||||
"testClass5", "testClass6"};
|
||||
assertEquals(myExpectedClasses.length,arrayClasses.size());
|
||||
for(int i=0; i<myExpectedClasses.length; i++) {
|
||||
IStructure myIStruct = (IStructure) arrayClasses.get(i);
|
||||
|
|
|
@ -51,6 +51,8 @@ import org.eclipse.cdt.core.dom.ast.IType;
|
|||
import org.eclipse.cdt.core.dom.ast.c.CASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.c.ICASTTypeIdInitializerExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
|
||||
import org.eclipse.cdt.core.dom.parser.IScannerExtensionConfiguration;
|
||||
import org.eclipse.cdt.core.dom.parser.ISourceCodeParser;
|
||||
import org.eclipse.cdt.core.dom.parser.c.ANSICParserExtensionConfiguration;
|
||||
|
@ -553,6 +555,20 @@ public class AST2BaseTest extends BaseTestCase {
|
|||
return (T) decls[i_decl];
|
||||
}
|
||||
|
||||
final protected <T extends IASTDeclaration> T getDeclaration(ICPPASTNamespaceDefinition ns, int i_decl) {
|
||||
Class<T> tclass;
|
||||
IASTDeclaration[] decls= ns.getDeclarations();
|
||||
assertTrue(decls.length > i_decl);
|
||||
return (T) decls[i_decl];
|
||||
}
|
||||
|
||||
final protected <T extends IASTDeclaration> T getDeclaration(ICPPASTLinkageSpecification ls, int i_decl) {
|
||||
Class<T> tclass;
|
||||
IASTDeclaration[] decls= ls.getDeclarations();
|
||||
assertTrue(decls.length > i_decl);
|
||||
return (T) decls[i_decl];
|
||||
}
|
||||
|
||||
final protected <T extends IASTDeclaration> T getDeclaration(IASTCompositeTypeSpecifier ct, int i_decl) {
|
||||
Class<T> tclass;
|
||||
IASTDeclaration[] decls= ct.getMembers();
|
||||
|
@ -566,7 +582,10 @@ public class AST2BaseTest extends BaseTestCase {
|
|||
}
|
||||
|
||||
final protected <T extends IASTStatement> T getStatement(IASTFunctionDefinition fdef, int i_stmt) {
|
||||
IASTCompoundStatement compound= (IASTCompoundStatement) fdef.getBody();
|
||||
return getStatement((IASTCompoundStatement) fdef.getBody(), i_stmt);
|
||||
}
|
||||
|
||||
final protected <T extends IASTStatement> T getStatement(IASTCompoundStatement compound, int i_stmt) {
|
||||
IASTStatement[] stmts= compound.getStatements();
|
||||
assertTrue(stmts.length > i_stmt);
|
||||
return (T) stmts[i_stmt];
|
||||
|
|
|
@ -76,6 +76,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
|
||||
|
@ -5737,4 +5738,30 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
}
|
||||
isTypeEqual(CPPVisitor.createType(newExpr.getTypeId()), type);
|
||||
}
|
||||
|
||||
// namespace ns {
|
||||
// void test() {}
|
||||
// +error
|
||||
// }
|
||||
public void testTrailingSyntaxErrorInNamespace() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
IASTTranslationUnit tu= parse(comment, ParserLanguage.CPP, false, false);
|
||||
ICPPASTNamespaceDefinition ns= getDeclaration(tu, 0);
|
||||
IASTDeclaration decl= getDeclaration(ns, 0);
|
||||
IASTProblemDeclaration pdecl= getDeclaration(ns, 1);
|
||||
assertEquals("+error", pdecl.getRawSignature());
|
||||
}
|
||||
|
||||
// extern "C" {
|
||||
// void test() {}
|
||||
// +error
|
||||
// }
|
||||
public void testTrailingSyntaxErrorInLinkageSpec() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
IASTTranslationUnit tu= parse(comment, ParserLanguage.CPP, false, false);
|
||||
ICPPASTLinkageSpecification ls= getDeclaration(tu, 0);
|
||||
IASTDeclaration decl= getDeclaration(ls, 0);
|
||||
IASTProblemDeclaration pdecl= getDeclaration(ls, 1);
|
||||
assertEquals("+error", pdecl.getRawSignature());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2007 IBM Corporation and others.
|
||||
* Copyright (c) 2005, 2008 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Rational Software - Initial API and implementation
|
||||
* Anton Leherbauer (Wind River Systems)
|
||||
* IBM Rational Software - Initial API and implementation
|
||||
* Anton Leherbauer (Wind River Systems)
|
||||
* Markus Schorn (Wind River Systems)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.parser.tests.ast2;
|
||||
|
||||
|
@ -17,6 +18,7 @@ import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
|
||||
|
@ -277,8 +279,9 @@ public class AST2KnRTests extends AST2BaseTest {
|
|||
buffer.append( "int f(x) char\n" ); //$NON-NLS-1$
|
||||
buffer.append( "{ return x == 0; }\n" ); //$NON-NLS-1$
|
||||
IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.C, true, false );
|
||||
|
||||
assertTrue( tu.getDeclarations()[0] instanceof IASTProblemDeclaration );
|
||||
IASTDeclaration[] decls= tu.getDeclarations();
|
||||
|
||||
assertTrue(CVisitor.getProblems(tu).length > 0);
|
||||
}
|
||||
|
||||
public void testKRCProblem2() throws Exception {
|
||||
|
@ -288,8 +291,8 @@ public class AST2KnRTests extends AST2BaseTest {
|
|||
buffer.append( "{ return x == 0; }\n" ); //$NON-NLS-1$
|
||||
IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.C, true, false );
|
||||
|
||||
assertTrue( tu.getDeclarations()[1] instanceof IASTProblemDeclaration );
|
||||
assertTrue( tu.getDeclarations()[2] instanceof IASTProblemDeclaration );
|
||||
IASTSimpleDeclaration sd= getDeclaration(tu, 0);
|
||||
assertTrue(CVisitor.getProblems(tu).length > 0);
|
||||
}
|
||||
|
||||
public void testKRCProblem3() throws Exception {
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTProblem;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTProblemStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||
|
@ -4957,4 +4958,65 @@ public class AST2Tests extends AST2BaseTest {
|
|||
assertEquals("ptr", p.getName());
|
||||
}
|
||||
}
|
||||
|
||||
// void test() {}
|
||||
// +error
|
||||
public void testTrailingSyntaxErrorInTU() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
IASTTranslationUnit tu= parse(comment, lang, false, false);
|
||||
IASTDeclaration decl= getDeclaration(tu, 0);
|
||||
IASTProblemDeclaration pdecl= getDeclaration(tu, 1);
|
||||
assertEquals("+error", pdecl.getRawSignature());
|
||||
}
|
||||
}
|
||||
|
||||
// struct X {
|
||||
// int test;
|
||||
// +error
|
||||
// };
|
||||
public void testTrailingSyntaxErrorInCompositeType() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
IASTTranslationUnit tu= parse(comment, lang, false, false);
|
||||
IASTCompositeTypeSpecifier ct= getCompositeType(tu, 0);
|
||||
IASTDeclaration decl= getDeclaration(ct, 0);
|
||||
IASTProblemDeclaration pdecl= getDeclaration(ct, 1);
|
||||
assertEquals("+error", pdecl.getRawSignature());
|
||||
}
|
||||
}
|
||||
|
||||
// void func() {
|
||||
// {
|
||||
// int test;
|
||||
// +error
|
||||
// }
|
||||
// }
|
||||
public void testTrailingSyntaxErrorInCompoundStatements() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
IASTTranslationUnit tu= parse(comment, lang, false, false);
|
||||
IASTFunctionDefinition def= getDeclaration(tu, 0);
|
||||
IASTCompoundStatement compStmt= getStatement(def, 0);
|
||||
IASTDeclarationStatement dstmt= getStatement(compStmt, 0);
|
||||
IASTProblemStatement pstmt= getStatement(compStmt, 1);
|
||||
assertEquals("+error", pstmt.getRawSignature());
|
||||
}
|
||||
}
|
||||
|
||||
// struct X {
|
||||
// ;
|
||||
// };
|
||||
// ;
|
||||
public void testEmptyDeclarations() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
IASTTranslationUnit tu= parse(comment, lang, false, false);
|
||||
IASTCompositeTypeSpecifier ct= getCompositeType(tu, 0);
|
||||
IASTDeclaration empty= getDeclaration(ct, 0);
|
||||
assertEquals(";", empty.getRawSignature());
|
||||
empty= getDeclaration(tu, 1);
|
||||
assertEquals(";", empty.getRawSignature());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -467,7 +467,7 @@ public class DOMLocationTests extends AST2BaseTest {
|
|||
assertSoleLocation(problems[0], code, "xxx(!");
|
||||
assertSoleLocation( decls[0], code, "int x;");
|
||||
assertSoleLocation( problems[1], code, "\\");
|
||||
assertFileLocation( decls[1], code, "int x\\i");
|
||||
assertFileLocation( decls[1], code, "int x\\i;");
|
||||
assertSoleLocation( decls[2], code, "int x2;");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ public class DOMParserTestSuite extends TestCase {
|
|||
suite.addTest(TaskParserTest.suite());
|
||||
suite.addTest(CompletionTestSuite.suite());
|
||||
suite.addTestSuite(CharArrayMapTest.class);
|
||||
suite.addTest(FaultToleranceTests.suite());
|
||||
return suite;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2008 Wind River Systems, Inc. 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Markus Schorn - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.parser.tests.ast2;
|
||||
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTProblemExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTProblemStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
|
||||
import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||
|
||||
/**
|
||||
* Testcases related to recovery from invalid syntax.
|
||||
*/
|
||||
public class FaultToleranceTests extends AST2BaseTest {
|
||||
|
||||
public static TestSuite suite() {
|
||||
return suite(FaultToleranceTests.class);
|
||||
}
|
||||
|
||||
public FaultToleranceTests() {
|
||||
super();
|
||||
}
|
||||
|
||||
public FaultToleranceTests(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
// typedef int tint;
|
||||
// struct X {
|
||||
// int a;
|
||||
// }
|
||||
// tint b;
|
||||
public void testCompositeTypeWithoutSemi() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
IASTTranslationUnit tu= parse(comment, lang, false, false);
|
||||
IASTCompositeTypeSpecifier def= getCompositeType(tu, 1);
|
||||
IASTProblemDeclaration pdecl= getDeclaration(tu, 2);
|
||||
IASTSimpleDeclaration sdecl= getDeclaration(tu, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// typedef int tint;
|
||||
// struct X {
|
||||
// int a;
|
||||
// } c
|
||||
// tint b;
|
||||
public void testCompositeTypeWithDtorWithoutSemi() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
IASTTranslationUnit tu= parse(comment, lang, false, false);
|
||||
IASTSimpleDeclaration sdecl= getDeclaration(tu, 1);
|
||||
assertInstance(sdecl.getDeclSpecifier(), IASTCompositeTypeSpecifier.class);
|
||||
assertEquals(1, sdecl.getDeclarators().length);
|
||||
IASTProblemDeclaration pdecl= getDeclaration(tu, 2);
|
||||
sdecl= getDeclaration(tu, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// typedef int tint;
|
||||
// int a
|
||||
// tint b;
|
||||
public void testVariableWithoutSemi() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
IASTTranslationUnit tu= parse(comment, lang, false, false);
|
||||
IASTSimpleDeclaration sdecl= getDeclaration(tu, 1);
|
||||
assertEquals("int a", sdecl.getRawSignature());
|
||||
IASTProblemDeclaration pdecl= getDeclaration(tu, 2);
|
||||
sdecl= getDeclaration(tu, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// typedef int tint;
|
||||
// int a()
|
||||
// tint b;
|
||||
public void testPrototypeWithoutSemi() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
IASTTranslationUnit tu= parse(comment, lang, false, false);
|
||||
IASTSimpleDeclaration sdecl= getDeclaration(tu, 1);
|
||||
assertEquals("int a()", sdecl.getRawSignature());
|
||||
IASTProblemDeclaration pdecl= getDeclaration(tu, 2);
|
||||
sdecl= getDeclaration(tu, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// struct X {
|
||||
// int a;
|
||||
public void testIncompleteCompositeType() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
IASTTranslationUnit tu= parse(comment, lang, false, false);
|
||||
IASTCompositeTypeSpecifier comp= getCompositeType(tu, 0);
|
||||
IASTProblemDeclaration pdecl= getDeclaration(tu, 1);
|
||||
|
||||
IASTSimpleDeclaration sdecl= getDeclaration(comp, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// void func() {
|
||||
// int a;
|
||||
public void testIncompleteFunctionDefinition() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
IASTTranslationUnit tu= parse(comment, lang, false, false);
|
||||
IASTFunctionDefinition fdef= getDeclaration(tu, 0);
|
||||
IASTProblemDeclaration pdecl= getDeclaration(tu, 1);
|
||||
|
||||
IASTDeclarationStatement sdecl= getStatement(fdef, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// namespace ns {
|
||||
// int a;
|
||||
public void testIncompleteNamespace() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
IASTTranslationUnit tu= parse(comment, ParserLanguage.CPP, false, false);
|
||||
ICPPASTNamespaceDefinition ns= getDeclaration(tu, 0);
|
||||
IASTProblemDeclaration pdecl= getDeclaration(tu, 1);
|
||||
|
||||
IASTSimpleDeclaration sdecl= getDeclaration(ns, 0);
|
||||
}
|
||||
|
||||
// extern "C" {
|
||||
// int a;
|
||||
public void testIncompleteLinkageSpec() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
IASTTranslationUnit tu= parse(comment, ParserLanguage.CPP, false, false);
|
||||
ICPPASTLinkageSpecification ls= getDeclaration(tu, 0);
|
||||
IASTProblemDeclaration pdecl= getDeclaration(tu, 1);
|
||||
|
||||
IASTSimpleDeclaration sdecl= getDeclaration(ls, 0);
|
||||
}
|
||||
|
||||
// void test() {
|
||||
// int a= offsetof(struct mystruct, singlechar);
|
||||
// }
|
||||
public void testRangeOfProblemNode_Bug238151() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
IASTTranslationUnit tu= parse(comment, lang, false, false);
|
||||
IASTFunctionDefinition fdef= getDeclaration(tu, 0);
|
||||
IASTProblemStatement pdecl= getStatement(fdef, 0);
|
||||
assertEquals("int a= offsetof(struct mystruct, singlechar);", pdecl.getRawSignature());
|
||||
}
|
||||
}
|
||||
|
||||
// int f(){
|
||||
// if( 12 A )
|
||||
// return -1;
|
||||
// int v;
|
||||
// }
|
||||
public void testProblemInIfExpression_Bug100321() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
IASTTranslationUnit tu= parse(comment, lang, false, false);
|
||||
IASTFunctionDefinition fdef= getDeclaration(tu, 0);
|
||||
IASTIfStatement ifstmt= getStatement(fdef, 0);
|
||||
assertInstance(ifstmt.getConditionExpression(), IASTProblemExpression.class);
|
||||
assertEquals("12 A", ifstmt.getConditionExpression().getRawSignature());
|
||||
assertInstance(ifstmt.getThenClause(), IASTReturnStatement.class);
|
||||
}
|
||||
}
|
||||
|
||||
// _MYMACRO_ myType foo();
|
||||
// _MYMACRO_ myType foo() {}
|
||||
// extern void foo2() _MYMACRO_;
|
||||
public void testUndefinedMacrosInFunctionDeclarations_Bug234085() throws Exception {
|
||||
final String comment= getAboveComment();
|
||||
for (ParserLanguage lang : ParserLanguage.values()) {
|
||||
IASTTranslationUnit tu= parse(comment, lang, false, false);
|
||||
IASTProblemDeclaration pd= getDeclaration(tu, 0);
|
||||
assertEquals("_MYMACRO_", pd.getRawSignature());
|
||||
IASTSimpleDeclaration sdecl= getDeclaration(tu, 1);
|
||||
assertEquals("myType foo();", sdecl.getRawSignature());
|
||||
|
||||
pd= getDeclaration(tu, 2);
|
||||
assertEquals("_MYMACRO_", pd.getRawSignature());
|
||||
IASTFunctionDefinition fdef= getDeclaration(tu, 3);
|
||||
assertEquals("myType foo() {}", fdef.getRawSignature());
|
||||
|
||||
sdecl= getDeclaration(tu, 4);
|
||||
assertEquals("extern void foo2()", sdecl.getRawSignature());
|
||||
pd= getDeclaration(tu, 5);
|
||||
assertEquals("", pd.getRawSignature()); // the missing semicolon
|
||||
|
||||
if (lang == ParserLanguage.CPP) {
|
||||
pd= getDeclaration(tu, 6);
|
||||
assertEquals("_MYMACRO_;", pd.getRawSignature());
|
||||
} else {
|
||||
sdecl= getDeclaration(tu, 6);
|
||||
assertEquals("_MYMACRO_;", sdecl.getRawSignature());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +1,13 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2004, 2007 IBM Corporation and others.
|
||||
* Copyright (c) 2004, 2008 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Rational Software - Initial API and implementation
|
||||
* IBM Rational Software - Initial API and implementation
|
||||
* Markus Schorn (Wind River Systems)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.parser.tests.ast2;
|
||||
|
||||
|
@ -210,10 +211,11 @@ public class GCCCompleteParseExtensionsTest extends AST2BaseTest {
|
|||
{
|
||||
parseGPP("class B { public: B(); int a;}; B::B() : a(({ 1; })) {}"); //$NON-NLS-1$
|
||||
Writer writer = new StringWriter();
|
||||
writer.write( "int foo(); class B { public: B(); int a;};");
|
||||
writer.write( "B::B() : a(( { int y = foo (); int z;\n" ); //$NON-NLS-1$
|
||||
writer.write( "if (y > 0) z = y;\n" ); //$NON-NLS-1$
|
||||
writer.write( "else z = - y;\n" );//$NON-NLS-1$
|
||||
writer.write( "z; }))\n" );//$NON-NLS-1$
|
||||
writer.write( "z; })) {}\n" );//$NON-NLS-1$
|
||||
parseGPP( writer.toString() );
|
||||
|
||||
writer = new StringWriter();
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Rational Software - Initial API and implementation
|
||||
* IBM Rational Software - Initial API and implementation
|
||||
* Markus Schorn (Wind River Systems)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.parser.tests.ast2;
|
||||
|
||||
|
@ -846,7 +847,7 @@ public class QuickParser2Tests extends TestCase {
|
|||
parse(
|
||||
"class Functor {" +
|
||||
"Functor(const Functor& rhs) : spImpl_(Impl::Clone(rhs.spImpl_.get())){}" +
|
||||
"}"
|
||||
"};"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1524,7 +1525,7 @@ public class QuickParser2Tests extends TestCase {
|
|||
writer.write("B::B() : a(( { int y = foo (); int z;\n");
|
||||
writer.write("if (y > 0) z = y;\n");
|
||||
writer.write("else z = - y;\n");
|
||||
writer.write("z; }))\n");
|
||||
writer.write("z; })) {}\n");
|
||||
parse(writer.toString(), true, ParserLanguage.CPP, true);
|
||||
writer = new StringWriter();
|
||||
writer.write("int x = ({ int y = foo (); int z;\n");
|
||||
|
|
|
@ -36,6 +36,7 @@ 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;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTGotoStatement;
|
||||
|
@ -47,6 +48,7 @@ import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNullStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTProblem;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTProblemDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTProblemExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTProblemStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
|
||||
|
@ -74,6 +76,7 @@ import org.eclipse.cdt.core.parser.IToken;
|
|||
import org.eclipse.cdt.core.parser.OffsetLimitReachedException;
|
||||
import org.eclipse.cdt.core.parser.ParseError;
|
||||
import org.eclipse.cdt.core.parser.ParserMode;
|
||||
import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
|
||||
|
||||
/**
|
||||
* @author jcamelon
|
||||
|
@ -90,6 +93,18 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
protected final boolean supportAttributeSpecifiers;
|
||||
protected final boolean supportDeclspecSpecifiers;
|
||||
protected final IBuiltinBindingsProvider builtinBindingsProvider;
|
||||
|
||||
/**
|
||||
* Marks the beginning of the current declaration. It is important to clear the mark whenever we
|
||||
* enter a nested declaration, in order to avoid holding on to all the tokens.
|
||||
*/
|
||||
protected IToken declarationMark;
|
||||
protected IToken currToken;
|
||||
protected int eofOffset;
|
||||
protected boolean parsePassed = true;
|
||||
protected int backtrackCount = 0;
|
||||
protected BacktrackException backtrack = new BacktrackException();
|
||||
protected ASTCompletionNode completionNode;
|
||||
|
||||
protected AbstractGNUSourceCodeParser(IScanner scanner,
|
||||
IParserLogService logService, ParserMode parserMode,
|
||||
|
@ -110,12 +125,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
this.builtinBindingsProvider= builtinBindingsProvider;
|
||||
}
|
||||
|
||||
protected boolean parsePassed = true;
|
||||
|
||||
protected BacktrackException backtrack = new BacktrackException();
|
||||
|
||||
protected int backtrackCount = 0;
|
||||
|
||||
private AbstractParserLogService wrapLogService(IParserLogService logService) {
|
||||
if (logService instanceof AbstractParserLogService) {
|
||||
return (AbstractParserLogService) logService;
|
||||
|
@ -129,11 +138,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
throw backtrack;
|
||||
}
|
||||
|
||||
protected IToken currToken;
|
||||
|
||||
protected ASTCompletionNode completionNode;
|
||||
|
||||
|
||||
public IASTCompletionNode getCompletionNode() {
|
||||
return completionNode;
|
||||
}
|
||||
|
@ -175,6 +179,17 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
return retToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #LA(int)}, but returns <code>null</code> when eof is reached.
|
||||
*/
|
||||
protected IToken LAcatchEOF(int i) {
|
||||
try {
|
||||
return LA(i);
|
||||
} catch (EndOfFileException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Look ahead in the token list and return the token type.
|
||||
*
|
||||
|
@ -187,6 +202,24 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
protected int LT(int i) throws EndOfFileException {
|
||||
return LA(i).getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #LT(int)}, but returns <code>0</code> when eof is reached.
|
||||
*/
|
||||
protected int LTcatchEOF(int i) {
|
||||
try {
|
||||
return LT(i);
|
||||
} catch (EndOfFileException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isOnSameLine(int offset1, int offset2) {
|
||||
ILocationResolver lr= (ILocationResolver) getTranslationUnit().getAdapter(ILocationResolver.class);
|
||||
IASTFileLocation floc= lr.getMappedFileLocation(offset1, offset2-offset1+1);
|
||||
return floc.getFileName().equals(lr.getContainingFilePath(offset1)) &&
|
||||
floc.getStartingLineNumber() == floc.getEndingLineNumber();
|
||||
}
|
||||
|
||||
protected int calculateEndOffset(IASTNode n) {
|
||||
ASTNode node = (ASTNode) n;
|
||||
|
@ -263,7 +296,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
*/
|
||||
protected IToken fetchToken() throws EndOfFileException {
|
||||
try {
|
||||
return scanner.nextToken();
|
||||
final IToken result= scanner.nextToken();
|
||||
eofOffset= result.getEndOffset();
|
||||
return result;
|
||||
} catch (OffsetLimitReachedException olre) {
|
||||
handleOffsetLimitException(olre);
|
||||
// never returns, to make the java-compiler happy:
|
||||
|
@ -344,24 +379,11 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
return backtrackCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
protected void throwBacktrack(BacktrackException bt) throws BacktrackException {
|
||||
throw bt;
|
||||
}
|
||||
|
||||
protected IASTProblem failParse(BacktrackException bt) {
|
||||
IASTProblem result = null;
|
||||
|
||||
if (bt.getProblem() == null)
|
||||
result = createProblem(IProblem.SYNTAX_ERROR, bt.getOffset(), bt
|
||||
.getLength());
|
||||
else
|
||||
result = bt.getProblem();
|
||||
|
||||
failParse();
|
||||
protected IASTProblem createProblem(BacktrackException bt) {
|
||||
IASTProblem result= bt.getProblem();
|
||||
if (result == null) {
|
||||
result= createProblem(IProblem.SYNTAX_ERROR, bt.getOffset(), bt.getLength());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -413,16 +435,18 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
}
|
||||
|
||||
protected final void throwBacktrack(IASTProblem problem)
|
||||
throws BacktrackException {
|
||||
protected final void throwBacktrack(IASTProblem problem, IASTNode node) throws BacktrackException {
|
||||
++backtrackCount;
|
||||
backtrack.initialize(problem, node);
|
||||
throw backtrack;
|
||||
}
|
||||
|
||||
protected final void throwBacktrack(IASTProblem problem) throws BacktrackException {
|
||||
++backtrackCount;
|
||||
backtrack.initialize(problem);
|
||||
throw backtrack;
|
||||
}
|
||||
|
||||
|
||||
private static final IASTNode[] EMPTY_NODE_ARRAY = new IASTNode[0];
|
||||
|
||||
public IASTTranslationUnit parse() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
translationUnit();
|
||||
|
@ -474,92 +498,189 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws EndOfFileException
|
||||
*/
|
||||
protected void errorHandling() throws EndOfFileException {
|
||||
int depth = (LT(1) == IToken.tLBRACE) ? 1 : 0;
|
||||
int type = consume().getType();
|
||||
if (type == IToken.tSEMI)
|
||||
return;
|
||||
while (!((LT(1) == IToken.tSEMI && depth == 0) || (LT(1) == IToken.tRBRACE && depth == 1))) {
|
||||
switch (LT(1)) {
|
||||
case IToken.tLBRACE:
|
||||
++depth;
|
||||
break;
|
||||
case IToken.tRBRACE:
|
||||
--depth;
|
||||
break;
|
||||
case IToken.tEOC:
|
||||
throw new EndOfFileException();
|
||||
}
|
||||
if (depth < 0)
|
||||
return;
|
||||
|
||||
consume();
|
||||
}
|
||||
|
||||
// eat the SEMI/RBRACE as well
|
||||
consume();
|
||||
protected IASTProblemDeclaration skipProblemDeclaration(int offset) {
|
||||
failParse();
|
||||
declarationMark= null;
|
||||
int endOffset = skipToSemiOrClosingBrace(offset);
|
||||
IASTProblem problem= createProblem(IProblem.SYNTAX_ERROR, offset, endOffset-offset);
|
||||
return createProblemDeclaration(problem);
|
||||
}
|
||||
|
||||
protected IASTProblemStatement skipProblemStatement(int offset) {
|
||||
failParse();
|
||||
declarationMark= null;
|
||||
int endOffset = skipToSemiOrClosingBrace(offset);
|
||||
IASTProblem problem= createProblem(IProblem.SYNTAX_ERROR, offset, endOffset-offset);
|
||||
return createProblemStatement(problem);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called whenever we encounter and error that we cannot
|
||||
* backtrack out of and we still wish to try and continue on with the parse
|
||||
* to do a best-effort parse for our client.
|
||||
*
|
||||
* @throws EndOfFileException
|
||||
* We can potentially hit EndOfFile here as we are skipping
|
||||
* ahead.
|
||||
*/
|
||||
protected void failParseWithErrorHandling() throws EndOfFileException {
|
||||
failParse();
|
||||
errorHandling();
|
||||
}
|
||||
private int skipToSemiOrClosingBrace(int offset) {
|
||||
failParse();
|
||||
declarationMark= null;
|
||||
int depth= 0;
|
||||
int endOffset;
|
||||
loop: try {
|
||||
endOffset= LA(1).getOffset();
|
||||
while(true) {
|
||||
switch (LT(1)) {
|
||||
case IToken.tEOC:
|
||||
endOffset= eofOffset;
|
||||
break loop;
|
||||
case IToken.tSEMI:
|
||||
if (depth == 0) {
|
||||
endOffset= consume().getEndOffset();
|
||||
break loop;
|
||||
}
|
||||
break;
|
||||
case IToken.tLBRACE:
|
||||
++depth;
|
||||
break;
|
||||
case IToken.tRBRACE:
|
||||
if (--depth <= 0) {
|
||||
if (depth == 0 || offset == endOffset) {
|
||||
endOffset= consume().getEndOffset(); // consume closing brace
|
||||
}
|
||||
break loop;
|
||||
}
|
||||
break;
|
||||
}
|
||||
endOffset= consume().getEndOffset();
|
||||
}
|
||||
} catch (EndOfFileException e) {
|
||||
endOffset= eofOffset;
|
||||
}
|
||||
return endOffset;
|
||||
}
|
||||
|
||||
protected IASTProblemExpression skipProblemConditionInParenthesis(int offset) {
|
||||
failParse();
|
||||
int compExpr= 0;
|
||||
int depth= 0;
|
||||
int endOffset= offset;
|
||||
loop: try {
|
||||
while(true) {
|
||||
switch (LT(1)) {
|
||||
case IToken.tEOC:
|
||||
endOffset= eofOffset;
|
||||
break loop;
|
||||
case IToken.tSEMI:
|
||||
case IToken.tLBRACE:
|
||||
if (compExpr == 0) {
|
||||
break loop;
|
||||
}
|
||||
break;
|
||||
case IToken.tLPAREN:
|
||||
depth++;
|
||||
if (LTcatchEOF(2) == IToken.tLBRACE) {
|
||||
if (compExpr == 0) {
|
||||
compExpr= depth;
|
||||
}
|
||||
consume();
|
||||
}
|
||||
break;
|
||||
case IToken.tRPAREN:
|
||||
if (--depth < 0) {
|
||||
break loop;
|
||||
}
|
||||
if (depth < compExpr) {
|
||||
compExpr= 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
endOffset= consume().getEndOffset();
|
||||
}
|
||||
} catch (EndOfFileException e) {
|
||||
endOffset= eofOffset;
|
||||
}
|
||||
IASTProblem problem= createProblem(IProblem.SYNTAX_ERROR, offset, endOffset-offset);
|
||||
return createProblemExpression(problem);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TODO
|
||||
* @throws BacktrackException
|
||||
*/
|
||||
protected IASTCompoundStatement compoundStatement()
|
||||
throws EndOfFileException, BacktrackException {
|
||||
protected IASTCompoundStatement compoundStatement() throws EndOfFileException, BacktrackException {
|
||||
IASTCompoundStatement result = createCompoundStatement();
|
||||
if (LT(1) == IToken.tEOC)
|
||||
return result;
|
||||
|
||||
int startingOffset = consume(IToken.tLBRACE).getOffset();
|
||||
final int offset= LA(1).getOffset();
|
||||
int endOffset= consume(IToken.tLBRACE).getOffset();
|
||||
|
||||
((ASTNode) result).setOffset(startingOffset);
|
||||
//result.setPropertyInParent(IASTFunctionDefinition.FUNCTION_BODY);
|
||||
while (LT(1) != IToken.tRBRACE && LT(1) != IToken.tEOC) {
|
||||
int checkToken = LA(1).hashCode();
|
||||
int stmtOffset= -1;
|
||||
while(true) {
|
||||
IToken next= LAcatchEOF(1);
|
||||
if (next == null) {
|
||||
((ASTNode) result).setOffsetAndLength(offset, endOffset-offset);
|
||||
throwBacktrack(createProblem(IProblem.SYNTAX_ERROR, endOffset, 0), result);
|
||||
return null; // hint for java-compiler
|
||||
}
|
||||
try {
|
||||
IASTStatement s = statement();
|
||||
result.addStatement(s);
|
||||
} catch (BacktrackException b) {
|
||||
IASTProblem p = failParse(b);
|
||||
IASTProblemStatement ps = createProblemStatement();
|
||||
ps.setProblem(p);
|
||||
((ASTNode) ps).setOffsetAndLength(((ASTNode) p).getOffset(),
|
||||
((ASTNode) p).getLength());
|
||||
result.addStatement(ps);
|
||||
if (LA(1).hashCode() == checkToken)
|
||||
failParseWithErrorHandling();
|
||||
if (next.getType() == IToken.tEOC)
|
||||
break;
|
||||
|
||||
if (next.getType() == IToken.tRBRACE) {
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
}
|
||||
|
||||
final int nextOffset = next.getOffset();
|
||||
declarationMark= next;
|
||||
next= null; // don't hold on to the token while parsing namespaces, class bodies, etc.
|
||||
|
||||
IASTStatement stmt;
|
||||
if (stmtOffset == nextOffset) {
|
||||
// no progress
|
||||
stmt= skipProblemStatement(stmtOffset);
|
||||
} else {
|
||||
stmtOffset= nextOffset;
|
||||
stmt= statement();
|
||||
}
|
||||
result.addStatement(stmt);
|
||||
endOffset= calculateEndOffset(stmt);
|
||||
} catch (BacktrackException bt) {
|
||||
IASTStatement stmt= skipProblemStatement(stmtOffset);
|
||||
result.addStatement(stmt);
|
||||
endOffset= calculateEndOffset(stmt);
|
||||
} catch (EndOfFileException e) {
|
||||
IASTStatement stmt= skipProblemStatement(stmtOffset);
|
||||
result.addStatement(stmt);
|
||||
endOffset= calculateEndOffset(stmt);
|
||||
break;
|
||||
} finally {
|
||||
declarationMark= null;
|
||||
}
|
||||
}
|
||||
|
||||
IToken token = consume();
|
||||
int lastOffset = token.getEndOffset();
|
||||
((ASTNode) result).setLength(lastOffset - startingOffset);
|
||||
|
||||
((ASTNode) result).setOffsetAndLength(offset, endOffset-offset);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected abstract IASTProblemStatement createProblemStatement();
|
||||
|
||||
protected abstract IASTProblemDeclaration createProblemDeclaration();
|
||||
protected abstract IASTCompoundStatement createCompoundStatement();
|
||||
|
||||
private IASTProblemDeclaration createProblemDeclaration(IASTProblem problem) {
|
||||
IASTProblemDeclaration pd = createProblemDeclaration();
|
||||
pd.setProblem(problem);
|
||||
((ASTNode) pd).setOffsetAndLength(((ASTNode) problem));
|
||||
return pd;
|
||||
}
|
||||
|
||||
private IASTProblemStatement createProblemStatement(IASTProblem problem) {
|
||||
IASTProblemStatement pstmt = createProblemStatement();
|
||||
pstmt.setProblem(problem);
|
||||
((ASTNode) pstmt).setOffsetAndLength(((ASTNode) problem));
|
||||
return pstmt;
|
||||
}
|
||||
|
||||
private IASTProblemExpression createProblemExpression(IASTProblem problem) {
|
||||
IASTProblemExpression pexpr = createProblemExpression();
|
||||
pexpr.setProblem(problem);
|
||||
((ASTNode) pexpr).setOffsetAndLength(((ASTNode) problem));
|
||||
return pexpr;
|
||||
}
|
||||
|
||||
protected IASTExpression compoundStatementExpression() throws EndOfFileException, BacktrackException {
|
||||
int startingOffset = consume().getOffset(); // tLPAREN always
|
||||
IASTCompoundStatement compoundStatement = null;
|
||||
|
@ -637,10 +758,62 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
protected abstract IASTExpression buildTypeIdExpression(int op,
|
||||
IASTTypeId typeId, int startingOffset, int endingOffset);
|
||||
|
||||
protected abstract void translationUnit();
|
||||
|
||||
protected abstract IASTTranslationUnit getTranslationUnit();
|
||||
|
||||
protected abstract void setupTranslationUnit() throws Exception;
|
||||
|
||||
protected void translationUnit() {
|
||||
try {
|
||||
setupTranslationUnit();
|
||||
} catch (Exception e2) {
|
||||
logException("translationUnit::createCompilationUnit()", e2); //$NON-NLS-1$
|
||||
return;
|
||||
}
|
||||
parseTranslationUnit();
|
||||
}
|
||||
|
||||
protected void parseTranslationUnit() {
|
||||
final IASTTranslationUnit tu= getTranslationUnit();
|
||||
int offset= -1;
|
||||
while (true) {
|
||||
try {
|
||||
IToken next= LAcatchEOF(1);
|
||||
if (next == null || next.getType() == IToken.tEOC)
|
||||
break;
|
||||
|
||||
final int nextOffset = next.getOffset();
|
||||
declarationMark= next;
|
||||
next= null; // don't hold on to the token while parsing namespaces, class bodies, etc.
|
||||
|
||||
if (offset == nextOffset) {
|
||||
// no progress
|
||||
tu.addDeclaration(skipProblemDeclaration(offset));
|
||||
} else {
|
||||
offset= nextOffset;
|
||||
final IASTDeclaration declaration= declaration(DeclarationOptions.GLOBAL);
|
||||
tu.addDeclaration(declaration);
|
||||
}
|
||||
} catch (BacktrackException bt) {
|
||||
IASTDeclaration[] decls= problemDeclaration(offset, bt, DeclarationOptions.GLOBAL);
|
||||
for (IASTDeclaration declaration : decls) {
|
||||
tu.addDeclaration(declaration);
|
||||
}
|
||||
} catch (EndOfFileException e) {
|
||||
tu.addDeclaration(skipProblemDeclaration(offset));
|
||||
break;
|
||||
} catch (OutOfMemoryError oome) {
|
||||
logThrowable("translationUnit", oome); //$NON-NLS-1$
|
||||
throw oome;
|
||||
} catch (Exception e) {
|
||||
logException("translationUnit", e); //$NON-NLS-1$
|
||||
tu.addDeclaration(skipProblemDeclaration(offset));
|
||||
} finally {
|
||||
declarationMark= null;
|
||||
}
|
||||
}
|
||||
((ASTNode) tu).setLength(eofOffset);
|
||||
}
|
||||
|
||||
protected IASTExpression assignmentOperatorExpression(int kind,
|
||||
IASTExpression lhs) throws EndOfFileException, BacktrackException {
|
||||
consume();
|
||||
|
@ -910,6 +1083,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
|
||||
protected IASTStatement handleFunctionBody() throws BacktrackException, EndOfFileException {
|
||||
declarationMark= null;
|
||||
if (mode == ParserMode.QUICK_PARSE || mode == ParserMode.STRUCTURAL_PARSE) {
|
||||
IToken curr = LA(1);
|
||||
IToken last = skipOverCompoundStatement();
|
||||
|
@ -1089,9 +1263,24 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
|
||||
protected abstract IASTName createName(IToken token);
|
||||
|
||||
protected IASTExpression condition() throws BacktrackException, EndOfFileException {
|
||||
IASTExpression cond = expression();
|
||||
return cond;
|
||||
protected IASTExpression condition(boolean followedByParenthesis) throws BacktrackException, EndOfFileException {
|
||||
IToken mark= mark();
|
||||
try {
|
||||
IASTExpression expr= expression();
|
||||
if (!followedByParenthesis)
|
||||
return expr;
|
||||
|
||||
switch (LT(1)) {
|
||||
case IToken.tEOC:
|
||||
case IToken.tRPAREN:
|
||||
return expr;
|
||||
}
|
||||
} catch (BacktrackException b) {
|
||||
if (!followedByParenthesis)
|
||||
throw b;
|
||||
}
|
||||
backup(mark);
|
||||
return skipProblemConditionInParenthesis(mark.getOffset());
|
||||
}
|
||||
|
||||
public boolean encounteredError() {
|
||||
|
@ -1143,8 +1332,67 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
|
||||
protected abstract IASTDeclaration declaration(DeclarationOptions option) throws BacktrackException, EndOfFileException;
|
||||
|
||||
protected IASTDeclaration[] problemDeclaration(int offset, BacktrackException bt, DeclarationOptions option) {
|
||||
failParse();
|
||||
IASTProblem origProblem= createProblem(bt);
|
||||
|
||||
// a node was detected by assuming additional tokens (e.g. missing semicolon)
|
||||
IASTNode n= bt.getNodeBeforeProblem();
|
||||
if (n instanceof IASTDeclaration) {
|
||||
declarationMark= null;
|
||||
return new IASTDeclaration[] {(IASTDeclaration) n, createProblemDeclaration(origProblem)};
|
||||
}
|
||||
|
||||
if (declarationMark != null) {
|
||||
IASTDeclaration trailingProblem= null;
|
||||
offset= declarationMark.getOffset();
|
||||
|
||||
// try to skip identifiers (undefined macros?)
|
||||
IASTDeclaration decl= null;
|
||||
int endOffset= 0;
|
||||
loop: while (declarationMark != null && declarationMark.getType() == IToken.tIDENTIFIER) {
|
||||
endOffset= declarationMark.getEndOffset();
|
||||
declarationMark= declarationMark.getNext();
|
||||
if (declarationMark != null) {
|
||||
backup(declarationMark);
|
||||
// avoid creating an empty declaration
|
||||
switch(LTcatchEOF(1)) {
|
||||
case 0: // eof
|
||||
case IToken.tEOC:
|
||||
case IToken.tSEMI:
|
||||
break loop;
|
||||
}
|
||||
try {
|
||||
decl= declaration(option);
|
||||
break;
|
||||
} catch (BacktrackException bt2) {
|
||||
n= bt.getNodeBeforeProblem();
|
||||
if (n instanceof IASTDeclaration) {
|
||||
decl= (IASTDeclaration) n;
|
||||
trailingProblem= createProblemDeclaration(bt.getProblem());
|
||||
break;
|
||||
}
|
||||
} catch (EndOfFileException e) {
|
||||
endOffset= eofOffset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
declarationMark= null;
|
||||
|
||||
if (decl != null) {
|
||||
IASTProblem problem= createProblem(IProblem.SYNTAX_ERROR, offset, endOffset-offset);
|
||||
IASTDeclaration pd= createProblemDeclaration(problem);
|
||||
if (trailingProblem != null)
|
||||
return new IASTDeclaration[] {pd, decl, trailingProblem};
|
||||
return new IASTDeclaration[] {pd, decl};
|
||||
}
|
||||
}
|
||||
|
||||
protected IASTDeclaration asmDeclaration() throws EndOfFileException,
|
||||
return new IASTDeclaration[] {skipProblemDeclaration(offset)};
|
||||
}
|
||||
|
||||
protected IASTDeclaration asmDeclaration() throws EndOfFileException,
|
||||
BacktrackException {
|
||||
IToken first = consume(); // t_asm
|
||||
IToken next= LA(1);
|
||||
|
@ -1463,7 +1711,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
if (LT(1) != IToken.tEOC) {
|
||||
consume(IToken.t_while);
|
||||
consume(IToken.tLPAREN);
|
||||
do_condition = condition();
|
||||
do_condition = condition(true);
|
||||
}
|
||||
|
||||
int lastOffset;
|
||||
|
@ -1500,7 +1748,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
protected IASTStatement parseWhileStatement() throws EndOfFileException, BacktrackException {
|
||||
int startOffset = consume().getOffset();
|
||||
consume(IToken.tLPAREN);
|
||||
IASTExpression while_condition = condition();
|
||||
IASTExpression while_condition = condition(true);
|
||||
switch (LT(1)) {
|
||||
case IToken.tRPAREN:
|
||||
consume();
|
||||
|
@ -1668,7 +1916,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
return new IASTNode[] {unaryExpression};
|
||||
}
|
||||
return EMPTY_NODE_ARRAY;
|
||||
return IASTNode.EMPTY_NODE_ARRAY;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -6,10 +6,12 @@
|
|||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM - Initial API and implementation
|
||||
* IBM - Initial API and implementation
|
||||
* Markus Schorn (Wind River Systems)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTProblem;
|
||||
|
||||
/**
|
||||
|
@ -17,20 +19,35 @@ import org.eclipse.cdt.core.dom.ast.IASTProblem;
|
|||
*/
|
||||
public class BacktrackException extends Exception {
|
||||
private IASTProblem problem;
|
||||
private IASTNode nodeBeforeProblem; // a node has been created in spite of the problem.
|
||||
private int offset, length;
|
||||
|
||||
public BacktrackException() {
|
||||
}
|
||||
|
||||
public BacktrackException(BacktrackException e) {
|
||||
problem= e.problem;
|
||||
nodeBeforeProblem= e.nodeBeforeProblem;
|
||||
offset= e.offset;
|
||||
length= e.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param p
|
||||
*/
|
||||
public void initialize(IASTProblem p) {
|
||||
reset();
|
||||
problem = p;
|
||||
}
|
||||
|
||||
public void initialize(IASTProblem p, IASTNode node) {
|
||||
reset();
|
||||
problem = p;
|
||||
nodeBeforeProblem= node;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void reset() {
|
||||
nodeBeforeProblem= null;
|
||||
problem = null;
|
||||
offset = 0;
|
||||
length = 0;
|
||||
|
@ -41,6 +58,10 @@ public class BacktrackException extends Exception {
|
|||
public final IASTProblem getProblem() {
|
||||
return problem;
|
||||
}
|
||||
|
||||
public final IASTNode getNodeBeforeProblem() {
|
||||
return nodeBeforeProblem;
|
||||
}
|
||||
|
||||
public void initialize(int start, int l ) {
|
||||
reset();
|
||||
|
|
|
@ -18,6 +18,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTASMDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
|
||||
|
@ -361,27 +362,46 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
switch (LT(1)) {
|
||||
case IToken.t_asm:
|
||||
return asmDeclaration();
|
||||
default:
|
||||
IASTDeclaration d = simpleDeclaration(declOption);
|
||||
return d;
|
||||
case IToken.tSEMI:
|
||||
IToken semi= consume();
|
||||
IASTSimpleDeclaration decl= createSimpleDeclaration();
|
||||
IASTDeclSpecifier declspec= createSimpleTypeSpecifier();
|
||||
decl.setDeclSpecifier(declspec);
|
||||
((ASTNode) declspec).setOffsetAndLength(semi.getOffset(), 0);
|
||||
((ASTNode) decl).setOffsetAndLength(semi.getOffset(), semi.getLength());
|
||||
return decl;
|
||||
}
|
||||
|
||||
return simpleDeclaration(declOption);
|
||||
}
|
||||
|
||||
private IASTDeclaration simpleDeclaration(final DeclarationOptions declOption) throws BacktrackException, EndOfFileException {
|
||||
final IToken firstToken = LA(1);
|
||||
if (firstToken.getType() == IToken.tLBRACE)
|
||||
throwBacktrack(firstToken);
|
||||
private IASTDeclaration simpleDeclaration(final DeclarationOptions declOption)
|
||||
throws BacktrackException, EndOfFileException {
|
||||
if (LT(1) == IToken.tLBRACE)
|
||||
throwBacktrack(LA(1));
|
||||
|
||||
final int firstOffset = firstToken.getOffset();
|
||||
final int firstOffset= LA(1).getOffset();
|
||||
int endOffset= firstOffset;
|
||||
|
||||
IASTDeclSpecifier declSpec;
|
||||
IASTDeclarator dtor= null;
|
||||
IToken markBeforDtor= null;
|
||||
try {
|
||||
declSpec = declSpecifierSeq(declOption);
|
||||
final int lt1= LT(1);
|
||||
if (lt1 != IToken.tSEMI && lt1 != IToken.tEOC) {
|
||||
dtor= initDeclarator(declOption);
|
||||
switch(LTcatchEOF(1)) {
|
||||
case 0: // eof
|
||||
case IToken.tSEMI:
|
||||
case IToken.tEOC:
|
||||
break;
|
||||
default:
|
||||
markBeforDtor= mark();
|
||||
try {
|
||||
dtor= initDeclarator(declOption);
|
||||
} catch (BacktrackException e) {
|
||||
backup(markBeforDtor);
|
||||
} catch (EndOfFileException e) {
|
||||
backup(markBeforDtor);
|
||||
}
|
||||
}
|
||||
} catch (FoundDeclaratorException e) {
|
||||
if (e.altSpec != null) {
|
||||
|
@ -395,13 +415,15 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
|
||||
IASTDeclarator[] declarators= {dtor};
|
||||
while (LT(1) == IToken.tCOMMA) {
|
||||
while (LTcatchEOF(1) == IToken.tCOMMA) {
|
||||
consume();
|
||||
declarators= (IASTDeclarator[]) ArrayUtil.append( IASTDeclarator.class, declarators, initDeclarator(declOption));
|
||||
}
|
||||
declarators= (IASTDeclarator[]) ArrayUtil.removeNulls( IASTDeclarator.class, declarators );
|
||||
|
||||
switch (LT(1)) {
|
||||
boolean insertSemi= false;
|
||||
final int lt1= LTcatchEOF(1);
|
||||
switch (lt1) {
|
||||
case IToken.tLBRACE:
|
||||
return functionDefinition(firstOffset, declSpec, declarators);
|
||||
|
||||
|
@ -412,18 +434,38 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
endOffset= figureEndOffset(declSpec, declarators);
|
||||
break;
|
||||
default:
|
||||
throwBacktrack(firstOffset, LA(1).getEndOffset() - firstOffset);
|
||||
insertSemi= true;
|
||||
if (markBeforDtor == null || !isOnSameLine(calculateEndOffset(declSpec), markBeforDtor.getOffset())) {
|
||||
if (markBeforDtor != null) {
|
||||
backup(markBeforDtor);
|
||||
}
|
||||
declarators= IASTDeclarator.EMPTY_DECLARATOR_ARRAY;
|
||||
endOffset= calculateEndOffset(declSpec);
|
||||
break;
|
||||
}
|
||||
endOffset= figureEndOffset(declSpec, declarators);
|
||||
if (lt1 == 0 || !isOnSameLine(endOffset, LA(1).getOffset())) {
|
||||
break;
|
||||
}
|
||||
if (declarators.length == 1 && declarators[0] instanceof IASTFunctionDeclarator) {
|
||||
break;
|
||||
}
|
||||
throwBacktrack(LA(1));
|
||||
}
|
||||
|
||||
// no function body
|
||||
IASTSimpleDeclaration simpleDeclaration = createSimpleDeclaration();
|
||||
simpleDeclaration.setDeclSpecifier(declSpec);
|
||||
for (int i = 0; i < declarators.length; ++i) {
|
||||
IASTDeclarator declarator = declarators[i];
|
||||
for (IASTDeclarator declarator : declarators) {
|
||||
simpleDeclaration.addDeclarator(declarator);
|
||||
}
|
||||
|
||||
((ASTNode) simpleDeclaration).setOffsetAndLength(firstOffset, endOffset-firstOffset);
|
||||
|
||||
if (insertSemi) {
|
||||
IASTProblem problem= createProblem(IProblem.SYNTAX_ERROR, endOffset, 0);
|
||||
throwBacktrack(problem, simpleDeclaration);
|
||||
}
|
||||
return simpleDeclaration;
|
||||
}
|
||||
|
||||
|
@ -440,12 +482,22 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
IASTFunctionDefinition funcDefinition = createFunctionDefinition();
|
||||
funcDefinition.setDeclSpecifier(declSpec);
|
||||
funcDefinition.setDeclarator((IASTFunctionDeclarator) fdtor);
|
||||
|
||||
try {
|
||||
IASTStatement s= handleFunctionBody();
|
||||
funcDefinition.setBody(s);
|
||||
((ASTNode) funcDefinition).setOffsetAndLength(firstOffset, calculateEndOffset(s) - firstOffset);
|
||||
|
||||
IASTStatement s= handleFunctionBody();
|
||||
funcDefinition.setBody(s);
|
||||
((ASTNode) funcDefinition).setOffsetAndLength(firstOffset, calculateEndOffset(s) - firstOffset);
|
||||
|
||||
return funcDefinition;
|
||||
return funcDefinition;
|
||||
} catch (BacktrackException bt) {
|
||||
final IASTNode n= bt.getNodeBeforeProblem();
|
||||
if (n instanceof IASTCompoundStatement) {
|
||||
funcDefinition.setBody((IASTCompoundStatement) n);
|
||||
((ASTNode) funcDefinition).setOffsetAndLength(firstOffset, calculateEndOffset(n) - firstOffset);
|
||||
throwBacktrack(bt.getProblem(), funcDefinition);
|
||||
}
|
||||
throw bt;
|
||||
}
|
||||
}
|
||||
|
||||
protected IASTFunctionDefinition createFunctionDefinition() {
|
||||
|
@ -463,88 +515,25 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the top-level entry point into the ANSI C++ grammar.
|
||||
*
|
||||
* translationUnit : (declaration)*
|
||||
*/
|
||||
@Override
|
||||
protected void translationUnit() {
|
||||
try {
|
||||
translationUnit = createTranslationUnit();
|
||||
translationUnit.setIndex(index);
|
||||
@Override
|
||||
protected void setupTranslationUnit() throws DOMException {
|
||||
translationUnit = createTranslationUnit();
|
||||
translationUnit.setIndex(index);
|
||||
|
||||
// add built-in names to the scope
|
||||
if (builtinBindingsProvider != null) {
|
||||
IScope tuScope = translationUnit.getScope();
|
||||
|
||||
IBinding[] bindings = builtinBindingsProvider.getBuiltinBindings(tuScope);
|
||||
for (IBinding binding : bindings) {
|
||||
ASTInternal.addBinding(tuScope, binding);
|
||||
}
|
||||
// add built-in names to the scope
|
||||
if (builtinBindingsProvider != null) {
|
||||
IScope tuScope = translationUnit.getScope();
|
||||
|
||||
IBinding[] bindings = builtinBindingsProvider.getBuiltinBindings(tuScope);
|
||||
for (IBinding binding : bindings) {
|
||||
ASTInternal.addBinding(tuScope, binding);
|
||||
}
|
||||
} catch (Exception e2) {
|
||||
logException("translationUnit::createCompilationUnit()", e2); //$NON-NLS-1$
|
||||
return;
|
||||
}
|
||||
}
|
||||
translationUnit.setLocationResolver(scanner.getLocationResolver());
|
||||
}
|
||||
|
||||
translationUnit.setLocationResolver(scanner.getLocationResolver());
|
||||
|
||||
int lastBacktrack = -1;
|
||||
while (true) {
|
||||
try {
|
||||
if (LT(1) == IToken.tEOC)
|
||||
break;
|
||||
int checkOffset = LA(1).hashCode();
|
||||
IASTDeclaration d = declaration(DeclarationOptions.GLOBAL);
|
||||
translationUnit.addDeclaration(d);
|
||||
if (LA(1).hashCode() == checkOffset)
|
||||
failParseWithErrorHandling();
|
||||
} catch (EndOfFileException e) {
|
||||
break;
|
||||
} catch (BacktrackException b) {
|
||||
try {
|
||||
// Mark as failure and try to reach a recovery point
|
||||
IASTProblem p = failParse(b);
|
||||
IASTProblemDeclaration pd = createProblemDeclaration();
|
||||
pd.setProblem(p);
|
||||
((ASTNode) pd).setOffsetAndLength(((ASTNode) p).getOffset(), ((ASTNode) p).getLength());
|
||||
translationUnit.addDeclaration(pd);
|
||||
errorHandling();
|
||||
if (lastBacktrack != -1 && lastBacktrack == LA(1).hashCode()) {
|
||||
// we haven't progressed from the
|
||||
// last backtrack
|
||||
// try and find tne next definition
|
||||
failParseWithErrorHandling();
|
||||
} else {
|
||||
// start again from here
|
||||
lastBacktrack = LA(1).hashCode();
|
||||
}
|
||||
} catch (EndOfFileException e) {
|
||||
break;
|
||||
}
|
||||
} catch (OutOfMemoryError oome) {
|
||||
logThrowable("translationUnit", oome); //$NON-NLS-1$
|
||||
throw oome;
|
||||
} catch (Exception e) {
|
||||
logException("translationUnit", e); //$NON-NLS-1$
|
||||
try {
|
||||
failParseWithErrorHandling();
|
||||
} catch (EndOfFileException e3) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
IASTDeclaration[] declarations = translationUnit.getDeclarations();
|
||||
if (declarations.length != 0) {
|
||||
ASTNode d = (ASTNode) declarations[declarations.length-1];
|
||||
((ASTNode) translationUnit).setLength(d.getOffset() + d.getLength());
|
||||
} else {
|
||||
((ASTNode) translationUnit).setLength(0);
|
||||
}
|
||||
}
|
||||
|
||||
protected IASTProblemDeclaration createProblemDeclaration() {
|
||||
@Override
|
||||
protected IASTProblemDeclaration createProblemDeclaration() {
|
||||
return new CASTProblemDeclaration();
|
||||
}
|
||||
|
||||
|
@ -1092,13 +1081,14 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
boolean encounteredTypename= false;
|
||||
|
||||
declSpecifiers: for (;;) {
|
||||
final IToken token= LA(1);
|
||||
final int lt1= token.getType();
|
||||
final int lt1= LTcatchEOF(1);
|
||||
switch (lt1) {
|
||||
// Storage Class Specifiers
|
||||
case 0: // eof
|
||||
break declSpecifiers;
|
||||
// storage class specifiers
|
||||
case IToken.t_auto:
|
||||
endOffset= consume().getEndOffset();
|
||||
storageClass = IASTDeclSpecifier.sc_auto;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t_register:
|
||||
storageClass = IASTDeclSpecifier.sc_register;
|
||||
|
@ -1139,60 +1129,84 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
|
||||
// Type Specifiers
|
||||
case IToken.t_void:
|
||||
if (encounteredTypename)
|
||||
break declSpecifiers;
|
||||
simpleType = IASTSimpleDeclSpecifier.t_void;
|
||||
encounteredRawType= true;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t_char:
|
||||
simpleType = IASTSimpleDeclSpecifier.t_char;
|
||||
encounteredRawType= true;
|
||||
if (encounteredTypename)
|
||||
break declSpecifiers;
|
||||
simpleType = IASTSimpleDeclSpecifier.t_char;
|
||||
encounteredRawType= true;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t_short:
|
||||
if (encounteredTypename)
|
||||
break declSpecifiers;
|
||||
options |= SHORT;
|
||||
encounteredRawType= true;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t_int:
|
||||
if (encounteredTypename)
|
||||
break declSpecifiers;
|
||||
simpleType = IASTSimpleDeclSpecifier.t_int;
|
||||
encounteredRawType= true;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t_long:
|
||||
if (encounteredTypename)
|
||||
break declSpecifiers;
|
||||
isLong++;
|
||||
encounteredRawType= true;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t_float:
|
||||
if (encounteredTypename)
|
||||
break declSpecifiers;
|
||||
simpleType = IASTSimpleDeclSpecifier.t_float;
|
||||
encounteredRawType= true;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t_double:
|
||||
if (encounteredTypename)
|
||||
break declSpecifiers;
|
||||
simpleType = IASTSimpleDeclSpecifier.t_double;
|
||||
encounteredRawType= true;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t_signed:
|
||||
if (encounteredTypename)
|
||||
break declSpecifiers;
|
||||
options |= SIGNED;
|
||||
encounteredRawType= true;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t_unsigned:
|
||||
if (encounteredTypename)
|
||||
break declSpecifiers;
|
||||
options |= UNSIGNED;
|
||||
encounteredRawType= true;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t__Bool:
|
||||
if (encounteredTypename)
|
||||
break declSpecifiers;
|
||||
simpleType = ICASTSimpleDeclSpecifier.t_Bool;
|
||||
encounteredRawType= true;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t__Complex:
|
||||
if (encounteredTypename)
|
||||
break declSpecifiers;
|
||||
options |= COMPLEX;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
case IToken.t__Imaginary:
|
||||
if (encounteredTypename)
|
||||
break declSpecifiers;
|
||||
options |= IMAGINARY;
|
||||
endOffset= consume().getEndOffset();
|
||||
break;
|
||||
|
@ -1232,7 +1246,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
case IToken.t_struct:
|
||||
case IToken.t_union:
|
||||
if (encounteredTypename || encounteredRawType)
|
||||
throwBacktrack(token);
|
||||
break declSpecifiers;
|
||||
try {
|
||||
result= structOrUnionSpecifier();
|
||||
} catch (BacktrackException bt) {
|
||||
|
@ -1243,7 +1257,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
break;
|
||||
case IToken.t_enum:
|
||||
if (encounteredTypename || encounteredRawType)
|
||||
throwBacktrack(token);
|
||||
break declSpecifiers;
|
||||
try {
|
||||
result= enumSpecifier();
|
||||
} catch (BacktrackException bt) {
|
||||
|
@ -1256,35 +1270,35 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
|
||||
case IGCCToken.t__attribute__: // if __attribute__ is after the declSpec
|
||||
if (!supportAttributeSpecifiers)
|
||||
throwBacktrack(token);
|
||||
throwBacktrack(LA(1));
|
||||
__attribute_decl_seq(true, false);
|
||||
break;
|
||||
case IGCCToken.t__declspec: // __declspec precedes the identifier
|
||||
if (identifier != null || !supportDeclspecSpecifiers)
|
||||
throwBacktrack(token);
|
||||
throwBacktrack(LA(1));
|
||||
__attribute_decl_seq(false, true);
|
||||
break;
|
||||
|
||||
case IGCCToken.t_typeof:
|
||||
if (encounteredRawType || encounteredTypename)
|
||||
throwBacktrack(LA(1));
|
||||
|
||||
typeofExpression = unaryTypeofExpression();
|
||||
encounteredTypename= true;
|
||||
endOffset= calculateEndOffset(typeofExpression);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (lt1 >= IExtensionToken.t__otherDeclSpecModifierFirst && lt1 <= IExtensionToken.t__otherDeclSpecModifierLast) {
|
||||
handleOtherDeclSpecModifier();
|
||||
endOffset= LA(1).getOffset();
|
||||
break;
|
||||
}
|
||||
if (lt1 == IGCCToken.t_typeof) {
|
||||
if (encounteredRawType || encounteredTypename)
|
||||
throwBacktrack(token);
|
||||
|
||||
typeofExpression = unaryTypeofExpression();
|
||||
encounteredTypename= true;
|
||||
endOffset= calculateEndOffset(typeofExpression);
|
||||
break;
|
||||
}
|
||||
break declSpecifiers;
|
||||
}
|
||||
|
||||
if (encounteredRawType && encounteredTypename)
|
||||
throwBacktrack(token);
|
||||
throwBacktrack(LA(1));
|
||||
}
|
||||
|
||||
// check for empty specification
|
||||
|
@ -1402,33 +1416,31 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
*
|
||||
* @throws BacktrackException to request a backtrack
|
||||
*/
|
||||
protected ICASTCompositeTypeSpecifier structOrUnionSpecifier()
|
||||
throws BacktrackException, EndOfFileException {
|
||||
|
||||
protected ICASTCompositeTypeSpecifier structOrUnionSpecifier() throws BacktrackException, EndOfFileException {
|
||||
int classKind = 0;
|
||||
IToken classKey = null;
|
||||
IToken mark = mark();
|
||||
|
||||
IToken mark= mark();
|
||||
final int offset= mark.getOffset();
|
||||
|
||||
// class key
|
||||
switch (LT(1)) {
|
||||
case IToken.t_struct:
|
||||
classKey = consume();
|
||||
consume();
|
||||
classKind = IASTCompositeTypeSpecifier.k_struct;
|
||||
break;
|
||||
case IToken.t_union:
|
||||
classKey = consume();
|
||||
consume();
|
||||
classKind = IASTCompositeTypeSpecifier.k_union;
|
||||
break;
|
||||
default:
|
||||
throwBacktrack(mark.getOffset(), mark.getLength());
|
||||
throwBacktrack(LA(1));
|
||||
return null; // line never reached, hint for the parser.
|
||||
}
|
||||
|
||||
// if __attribute__ or __declspec occurs after struct/union/class and before the identifier
|
||||
__attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers);
|
||||
|
||||
IToken nameToken = null;
|
||||
// class name
|
||||
IToken nameToken = null;
|
||||
if (LT(1) == IToken.tIDENTIFIER) {
|
||||
nameToken = identifier();
|
||||
}
|
||||
|
@ -1439,40 +1451,55 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (LT(1) != IToken.tLBRACE) {
|
||||
IToken errorPoint = LA(1);
|
||||
backup(mark);
|
||||
throwBacktrack(errorPoint.getOffset(), errorPoint.getLength());
|
||||
throwBacktrack(errorPoint);
|
||||
}
|
||||
|
||||
consume();
|
||||
|
||||
IASTName name = (nameToken == null) ? createName() : createName(nameToken);
|
||||
ICASTCompositeTypeSpecifier result = createCompositeTypeSpecifier();
|
||||
|
||||
result.setKey(classKind);
|
||||
((ASTNode) result).setOffset(classKey.getOffset());
|
||||
|
||||
result.setName(name);
|
||||
|
||||
int endOffset;
|
||||
memberDeclarationLoop: while (true) {
|
||||
switch (LT(1)) {
|
||||
case IToken.tRBRACE:
|
||||
case IToken.tEOC:
|
||||
endOffset = consume().getEndOffset();
|
||||
break memberDeclarationLoop;
|
||||
default:
|
||||
int checkToken = LA(1).hashCode();
|
||||
try {
|
||||
IASTDeclaration d = declaration(DeclarationOptions.C_MEMBER);
|
||||
result.addMemberDeclaration(d);
|
||||
} catch (BacktrackException bt) {
|
||||
if (checkToken == LA(1).hashCode())
|
||||
failParseWithErrorHandling();
|
||||
}
|
||||
if (checkToken == LA(1).hashCode())
|
||||
failParseWithErrorHandling();
|
||||
}
|
||||
int endOffset= consume().getEndOffset();
|
||||
int declOffset= -1;
|
||||
loop: while (true) {
|
||||
try {
|
||||
IToken next= LAcatchEOF(1);
|
||||
if (next == null || next.getType() == IToken.tEOC)
|
||||
break loop; // the missing semicolon will cause a problem, just break the loop.
|
||||
|
||||
if (next.getType() == IToken.tRBRACE) {
|
||||
endOffset= consume().getEndOffset();
|
||||
break loop;
|
||||
}
|
||||
|
||||
final int nextOffset = next.getOffset();
|
||||
declarationMark= next;
|
||||
next= null; // don't hold on to the token while parsing namespaces, class bodies, etc.
|
||||
|
||||
IASTDeclaration d;
|
||||
if (declOffset == nextOffset) {
|
||||
// no progress
|
||||
d= skipProblemDeclaration(declOffset);
|
||||
} else {
|
||||
d = declaration(DeclarationOptions.C_MEMBER);
|
||||
}
|
||||
result.addMemberDeclaration(d);
|
||||
endOffset= calculateEndOffset(d);
|
||||
} catch (BacktrackException bt) {
|
||||
IASTDeclaration[] decls= problemDeclaration(declOffset, bt, DeclarationOptions.C_MEMBER);
|
||||
for (IASTDeclaration declaration : decls) {
|
||||
result.addMemberDeclaration(declaration);
|
||||
endOffset= calculateEndOffset(declaration);
|
||||
}
|
||||
} catch (EndOfFileException e) {
|
||||
result.addMemberDeclaration(skipProblemDeclaration(declOffset));
|
||||
endOffset= eofOffset;
|
||||
break loop;
|
||||
} finally {
|
||||
declarationMark= null;
|
||||
}
|
||||
}
|
||||
((ASTNode) result).setLength(endOffset - classKey.getOffset());
|
||||
((ASTNode) result).setOffsetAndLength(offset, endOffset - offset);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -2344,39 +2371,21 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if_loop: while (true) {
|
||||
int so = consume(IToken.t_if).getOffset();
|
||||
consume(IToken.tLPAREN);
|
||||
IASTExpression condition = null;
|
||||
try {
|
||||
condition = condition();
|
||||
if (LT(1) == IToken.tEOC) {
|
||||
// Completing in the condition
|
||||
IASTIfStatement new_if = createIfStatement();
|
||||
new_if.setConditionExpression(condition);
|
||||
|
||||
if (if_statement != null) {
|
||||
if_statement.setElseClause(new_if);
|
||||
}
|
||||
return result != null ? result : new_if;
|
||||
}
|
||||
consume(IToken.tRPAREN);
|
||||
} catch (BacktrackException b) {
|
||||
IASTProblem p = failParse(b);
|
||||
IASTProblemExpression ps = createProblemExpression();
|
||||
ps.setProblem(p);
|
||||
((ASTNode) ps).setOffsetAndLength(((ASTNode) p).getOffset(), ((ASTNode) p).getLength());
|
||||
condition = ps;
|
||||
if( LT(1) == IToken.tRPAREN )
|
||||
consume();
|
||||
else if( LT(2) == IToken.tRPAREN )
|
||||
{
|
||||
consume();
|
||||
consume();
|
||||
}
|
||||
else
|
||||
failParseWithErrorHandling();
|
||||
// condition
|
||||
IASTExpression condition= condition(true);
|
||||
if (LT(1) == IToken.tEOC) {
|
||||
// Completing in the condition
|
||||
IASTIfStatement new_if = createIfStatement();
|
||||
new_if.setConditionExpression(condition);
|
||||
|
||||
if (if_statement != null) {
|
||||
if_statement.setElseClause(new_if);
|
||||
}
|
||||
return result != null ? result : new_if;
|
||||
}
|
||||
consume(IToken.tRPAREN);
|
||||
|
||||
IASTStatement thenClause = statement();
|
||||
|
||||
IASTIfStatement new_if_statement = createIfStatement();
|
||||
((ASTNode) new_if_statement).setOffset(so);
|
||||
if( condition != null ) // shouldn't be possible but failure in condition() makes it so
|
||||
|
@ -2463,7 +2472,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
int startOffset;
|
||||
startOffset = consume().getOffset();
|
||||
consume(IToken.tLPAREN);
|
||||
IASTExpression switch_condition = condition();
|
||||
IASTExpression switch_condition = condition(true);
|
||||
switch (LT(1)) {
|
||||
case IToken.tRPAREN:
|
||||
consume();
|
||||
|
@ -2500,7 +2509,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
case IToken.tEOC:
|
||||
break;
|
||||
default:
|
||||
for_condition = condition();
|
||||
for_condition = condition(false);
|
||||
}
|
||||
switch (LT(1)) {
|
||||
case IToken.tSEMI:
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue