mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-08 09:35:23 +02:00
Bug 397342 - Error calculating size of reference type
Change-Id: I1274da6ebd14f0c1f97dce2699d62018cff57b05 Reviewed-on: https://git.eclipse.org/r/9426 Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com> IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com> Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
This commit is contained in:
parent
9822ba56d8
commit
62b2b932ae
3 changed files with 901 additions and 4 deletions
|
@ -0,0 +1,848 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2004, 2013 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
|
||||||
|
* Markus Schorn (Wind River Systems)
|
||||||
|
* Andrew Ferguson (Symbian)
|
||||||
|
* Mike Kucera (IBM)
|
||||||
|
* Sergey Prigogin (Google)
|
||||||
|
* Nathan Ridge
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.core.parser.tests.ast2;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import junit.framework.AssertionFailedError;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IField;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.c.ICASTTypeIdInitializerExpression;
|
||||||
|
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.c.ANSICParserExtensionConfiguration;
|
||||||
|
import org.eclipse.cdt.core.dom.parser.c.GCCParserExtensionConfiguration;
|
||||||
|
import org.eclipse.cdt.core.dom.parser.c.GCCScannerExtensionConfiguration;
|
||||||
|
import org.eclipse.cdt.core.dom.parser.c.ICParserExtensionConfiguration;
|
||||||
|
import org.eclipse.cdt.core.dom.parser.cpp.ANSICPPParserExtensionConfiguration;
|
||||||
|
import org.eclipse.cdt.core.dom.parser.cpp.GPPParserExtensionConfiguration;
|
||||||
|
import org.eclipse.cdt.core.dom.parser.cpp.GPPScannerExtensionConfiguration;
|
||||||
|
import org.eclipse.cdt.core.dom.parser.cpp.ICPPParserExtensionConfiguration;
|
||||||
|
import org.eclipse.cdt.core.parser.FileContent;
|
||||||
|
import org.eclipse.cdt.core.parser.IParserLogService;
|
||||||
|
import org.eclipse.cdt.core.parser.IScanner;
|
||||||
|
import org.eclipse.cdt.core.parser.IScannerInfo;
|
||||||
|
import org.eclipse.cdt.core.parser.IncludeFileContentProvider;
|
||||||
|
import org.eclipse.cdt.core.parser.NullLogService;
|
||||||
|
import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||||
|
import org.eclipse.cdt.core.parser.ParserMode;
|
||||||
|
import org.eclipse.cdt.core.parser.ScannerInfo;
|
||||||
|
import org.eclipse.cdt.core.parser.tests.ASTComparer;
|
||||||
|
import org.eclipse.cdt.core.testplugin.CTestPlugin;
|
||||||
|
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
|
||||||
|
import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.c.CVisitor;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.c.GNUCSourceParser;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.GNUCPPSourceParser;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||||
|
import org.eclipse.cdt.internal.core.model.ASTStringUtil;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.ParserException;
|
||||||
|
import org.eclipse.cdt.internal.core.parser.scanner.CPreprocessor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author aniefer
|
||||||
|
*/
|
||||||
|
public class AST2BaseTest extends BaseTestCase {
|
||||||
|
public final static String TEST_CODE = "<testcode>";
|
||||||
|
protected static final IParserLogService NULL_LOG = new NullLogService();
|
||||||
|
protected static boolean sValidateCopy;
|
||||||
|
|
||||||
|
private static final ScannerInfo GNU_SCANNER_INFO = new ScannerInfo(getGnuMap());
|
||||||
|
private static final ScannerInfo SCANNER_INFO = new ScannerInfo(getStdMap());
|
||||||
|
|
||||||
|
private static Map<String, String> getGnuMap() {
|
||||||
|
Map<String, String> map= new HashMap<String, String>();
|
||||||
|
map.put("__GNUC__", "4");
|
||||||
|
map.put("__GNUC_MINOR__", "7");
|
||||||
|
map.put("__SIZEOF_SHORT__", "2");
|
||||||
|
map.put("__SIZEOF_INT__", "4");
|
||||||
|
map.put("__SIZEOF_LONG__", "8");
|
||||||
|
map.put("__SIZEOF_POINTER__", "8");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> getStdMap() {
|
||||||
|
Map<String, String> map= new HashMap<String, String>();
|
||||||
|
map.put("__SIZEOF_SHORT__", "2");
|
||||||
|
map.put("__SIZEOF_INT__", "4");
|
||||||
|
map.put("__SIZEOF_LONG__", "8");
|
||||||
|
map.put("__SIZEOF_POINTER__", "8");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AST2BaseTest() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AST2BaseTest(String name) {
|
||||||
|
super(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
sValidateCopy= true;
|
||||||
|
super.setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IASTTranslationUnit parse(String code, ParserLanguage lang) throws ParserException {
|
||||||
|
return parse(code, lang, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IASTTranslationUnit parse(String code, ParserLanguage lang, boolean useGNUExtensions) throws ParserException {
|
||||||
|
return parse(code, lang, useGNUExtensions, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IASTTranslationUnit parse(String code, ParserLanguage lang, boolean useGNUExtensions,
|
||||||
|
boolean expectNoProblems) throws ParserException {
|
||||||
|
return parse(code, lang, useGNUExtensions, expectNoProblems, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IASTTranslationUnit parse(String code, ParserLanguage lang, boolean useGNUExtensions,
|
||||||
|
boolean expectNoProblems, boolean skipTrivialInitializers) throws ParserException {
|
||||||
|
IScanner scanner = createScanner(FileContent.create(TEST_CODE, code.toCharArray()), lang, ParserMode.COMPLETE_PARSE,
|
||||||
|
createScannerInfo(useGNUExtensions));
|
||||||
|
configureScanner(scanner);
|
||||||
|
AbstractGNUSourceCodeParser parser = null;
|
||||||
|
if (lang == ParserLanguage.CPP) {
|
||||||
|
ICPPParserExtensionConfiguration config = null;
|
||||||
|
if (useGNUExtensions) {
|
||||||
|
config = new GPPParserExtensionConfiguration();
|
||||||
|
} else {
|
||||||
|
config = new ANSICPPParserExtensionConfiguration();
|
||||||
|
}
|
||||||
|
parser = new GNUCPPSourceParser(scanner, ParserMode.COMPLETE_PARSE, NULL_LOG,config, null);
|
||||||
|
} else {
|
||||||
|
ICParserExtensionConfiguration config = null;
|
||||||
|
|
||||||
|
if (useGNUExtensions) {
|
||||||
|
config = new GCCParserExtensionConfiguration();
|
||||||
|
} else {
|
||||||
|
config = new ANSICParserExtensionConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
parser = new GNUCSourceParser(scanner, ParserMode.COMPLETE_PARSE, NULL_LOG, config, null);
|
||||||
|
}
|
||||||
|
if (skipTrivialInitializers)
|
||||||
|
parser.setSkipTrivialExpressionsInAggregateInitializers(true);
|
||||||
|
|
||||||
|
IASTTranslationUnit tu = parser.parse();
|
||||||
|
assertTrue(tu.isFrozen());
|
||||||
|
if (sValidateCopy)
|
||||||
|
validateCopy(tu);
|
||||||
|
|
||||||
|
if (parser.encounteredError() && expectNoProblems)
|
||||||
|
throw new ParserException("FAILURE"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
if (lang == ParserLanguage.C && expectNoProblems) {
|
||||||
|
assertEquals(CVisitor.getProblems(tu).length, 0);
|
||||||
|
assertEquals(tu.getPreprocessorProblems().length, 0);
|
||||||
|
} else if (lang == ParserLanguage.CPP && expectNoProblems) {
|
||||||
|
assertEquals(CPPVisitor.getProblems(tu).length, 0);
|
||||||
|
assertEquals(0, tu.getPreprocessorProblems().length);
|
||||||
|
}
|
||||||
|
if (expectNoProblems)
|
||||||
|
assertEquals(0, tu.getPreprocessorProblems().length);
|
||||||
|
|
||||||
|
return tu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScannerInfo createScannerInfo(boolean useGnu) {
|
||||||
|
if (useGnu)
|
||||||
|
return GNU_SCANNER_INFO;
|
||||||
|
return SCANNER_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void configureScanner(IScanner scanner) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IScanner createScanner(FileContent codeReader, ParserLanguage lang, ParserMode mode,
|
||||||
|
IScannerInfo scannerInfo) {
|
||||||
|
IScannerExtensionConfiguration configuration = null;
|
||||||
|
if (lang == ParserLanguage.C) {
|
||||||
|
configuration= GCCScannerExtensionConfiguration.getInstance(scannerInfo);
|
||||||
|
} else {
|
||||||
|
configuration= GPPScannerExtensionConfiguration.getInstance(scannerInfo);
|
||||||
|
}
|
||||||
|
IScanner scanner;
|
||||||
|
scanner= new CPreprocessor(codeReader, scannerInfo, lang, NULL_LOG, configuration,
|
||||||
|
IncludeFileContentProvider.getSavedFilesProvider());
|
||||||
|
return scanner;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validateSimplePostfixInitializerExpressionC(String code) throws ParserException {
|
||||||
|
ICASTTypeIdInitializerExpression e = (ICASTTypeIdInitializerExpression) getExpressionFromStatementInCode(code, ParserLanguage.C);
|
||||||
|
assertNotNull(e);
|
||||||
|
assertNotNull(e.getTypeId());
|
||||||
|
assertNotNull(e.getInitializer());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validateSimpleUnaryTypeIdExpression(String code, int op) throws ParserException {
|
||||||
|
IASTCastExpression e = (IASTCastExpression) getExpressionFromStatementInCode(code, ParserLanguage.C);
|
||||||
|
assertNotNull(e);
|
||||||
|
assertEquals(e.getOperator(), op);
|
||||||
|
assertNotNull(e.getTypeId());
|
||||||
|
IASTIdExpression x = (IASTIdExpression) e.getOperand();
|
||||||
|
assertEquals(x.getName().toString(), "x"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validateSimpleTypeIdExpressionC(String code, int op) throws ParserException {
|
||||||
|
IASTTypeIdExpression e = (IASTTypeIdExpression) getExpressionFromStatementInCode(code, ParserLanguage.C);
|
||||||
|
assertNotNull(e);
|
||||||
|
assertEquals(e.getOperator(), op);
|
||||||
|
assertNotNull(e.getTypeId());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validateSimpleUnaryExpressionC(String code, int operator) throws ParserException {
|
||||||
|
IASTUnaryExpression e = (IASTUnaryExpression) getExpressionFromStatementInCode(code, ParserLanguage.C);
|
||||||
|
assertNotNull(e);
|
||||||
|
assertEquals(e.getOperator(), operator);
|
||||||
|
IASTIdExpression x = (IASTIdExpression) e.getOperand();
|
||||||
|
assertEquals(x.getName().toString(), "x"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validateConditionalExpressionC(String code) throws ParserException {
|
||||||
|
IASTConditionalExpression e = (IASTConditionalExpression) getExpressionFromStatementInCode(code, ParserLanguage.C);
|
||||||
|
assertNotNull(e);
|
||||||
|
IASTIdExpression x = (IASTIdExpression) e.getLogicalConditionExpression();
|
||||||
|
assertEquals(x.getName().toString(), "x"); //$NON-NLS-1$
|
||||||
|
IASTIdExpression y = (IASTIdExpression) e.getPositiveResultExpression();
|
||||||
|
assertEquals(y.getName().toString(), "y"); //$NON-NLS-1$
|
||||||
|
IASTIdExpression x2 = (IASTIdExpression) e.getNegativeResultExpression();
|
||||||
|
assertEquals(x.getName().toString(), x2.getName().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validateSimpleBinaryExpressionC(String code, int operand) throws ParserException {
|
||||||
|
IASTBinaryExpression e = (IASTBinaryExpression) getExpressionFromStatementInCode(code, ParserLanguage.C);
|
||||||
|
assertNotNull(e);
|
||||||
|
assertEquals(e.getOperator(), operand);
|
||||||
|
IASTIdExpression x = (IASTIdExpression) e.getOperand1();
|
||||||
|
assertEquals(x.getName().toString(), "x"); //$NON-NLS-1$
|
||||||
|
IASTIdExpression y = (IASTIdExpression) e.getOperand2();
|
||||||
|
assertEquals(y.getName().toString(), "y"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IASTExpression getExpressionFromStatementInCode(String code, ParserLanguage language) throws ParserException {
|
||||||
|
StringBuffer buffer = new StringBuffer("void f() { "); //$NON-NLS-1$
|
||||||
|
buffer.append("int x, y;\n"); //$NON-NLS-1$
|
||||||
|
buffer.append(code);
|
||||||
|
buffer.append(";\n}"); //$NON-NLS-1$
|
||||||
|
IASTTranslationUnit tu = parse(buffer.toString(), language);
|
||||||
|
IASTFunctionDefinition f = (IASTFunctionDefinition) tu.getDeclarations()[0];
|
||||||
|
IASTCompoundStatement cs = (IASTCompoundStatement) f.getBody();
|
||||||
|
IASTExpressionStatement s = (IASTExpressionStatement) cs.getStatements()[1];
|
||||||
|
return s.getExpression();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T extends IASTNode> T validateCopy(T tu) {
|
||||||
|
IASTNode copy = tu.copy();
|
||||||
|
assertFalse(copy.isFrozen());
|
||||||
|
ASTComparer.assertCopy(tu, copy);
|
||||||
|
return (T) copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static protected class CNameCollector extends ASTVisitor {
|
||||||
|
{
|
||||||
|
shouldVisitNames = true;
|
||||||
|
}
|
||||||
|
public List<IASTName> nameList = new ArrayList<IASTName>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTName name) {
|
||||||
|
nameList.add(name);
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTName getName(int idx) {
|
||||||
|
if (idx < 0 || idx >= nameList.size())
|
||||||
|
return null;
|
||||||
|
return nameList.get(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return nameList.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertInstances(CNameCollector collector, IBinding binding, int num) throws Exception {
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
assertNotNull(binding);
|
||||||
|
|
||||||
|
for (int i = 0; i < collector.size(); i++) {
|
||||||
|
if (collector.getName(i).resolveBinding() == binding)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(count, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected class CPPNameCollector extends ASTVisitor {
|
||||||
|
{
|
||||||
|
shouldVisitNames = true;
|
||||||
|
}
|
||||||
|
public List<IASTName> nameList = new ArrayList<IASTName>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTName name) {
|
||||||
|
nameList.add(name);
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTName getName(int idx) {
|
||||||
|
if (idx < 0 || idx >= nameList.size())
|
||||||
|
return null;
|
||||||
|
return nameList.get(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return nameList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dump() {
|
||||||
|
for (int i= 0; i < size(); i++) {
|
||||||
|
IASTName name= getName(i);
|
||||||
|
String parent= name.getParent() != null ? name.getParent().getRawSignature() : "";
|
||||||
|
System.out.println(i + ": #" + name.getRawSignature() + "# " + parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertInstances(CPPNameCollector collector, IBinding binding, int num) throws Exception {
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < collector.size(); i++) {
|
||||||
|
if (collector.getName(i).resolveBinding() == binding)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(num, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertSameType(IType expected, IType actual) {
|
||||||
|
assertNotNull(expected);
|
||||||
|
assertNotNull(actual);
|
||||||
|
assertTrue("Expected same types, but the types were: '" +
|
||||||
|
ASTTypeUtil.getType(expected, false) + "' and '" + ASTTypeUtil.getType(actual, false) + "'",
|
||||||
|
expected.isSameType(actual));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void isExpressionStringEqual(IASTInitializerClause exp, String str) {
|
||||||
|
String expressionString = ASTStringUtil.getExpressionString((IASTExpression) exp);
|
||||||
|
assertEquals(str, expressionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void isExpressionStringEqual(IASTExpression exp, String str) {
|
||||||
|
String expressionString = ASTStringUtil.getExpressionString(exp);
|
||||||
|
assertEquals(str, expressionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void isParameterSignatureEqual(IASTDeclarator decltor, String str) {
|
||||||
|
assertTrue(decltor instanceof IASTFunctionDeclarator);
|
||||||
|
final String[] sigArray = ASTStringUtil.getParameterSignatureArray((IASTFunctionDeclarator) decltor);
|
||||||
|
assertEquals(str, "(" + ASTStringUtil.join(sigArray, ", ") + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void isSignatureEqual(IASTDeclarator declarator, String expected) {
|
||||||
|
String signature= ASTStringUtil.getSignatureString(declarator);
|
||||||
|
assertEquals(expected, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void isSignatureEqual(IASTDeclSpecifier declSpec, String str) {
|
||||||
|
assertEquals(str, ASTStringUtil.getSignatureString(declSpec, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void isSignatureEqual(IASTTypeId typeId, String str) {
|
||||||
|
assertEquals(str, ASTStringUtil.getSignatureString(typeId.getDeclSpecifier(), typeId.getAbstractDeclarator()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void isTypeEqual(IASTDeclarator decltor, String str) {
|
||||||
|
assertEquals(str, ASTTypeUtil.getType(decltor));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void isTypeEqual(IASTTypeId typeId, String str) {
|
||||||
|
assertEquals(str, ASTTypeUtil.getType(typeId));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void isTypeEqual(IType type, String str) {
|
||||||
|
assertEquals(str, ASTTypeUtil.getType(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void isParameterTypeEqual(IFunctionType fType, String str) {
|
||||||
|
assertEquals(str, ASTTypeUtil.getParameterTypeString(fType));
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected class CNameResolver extends ASTVisitor {
|
||||||
|
{
|
||||||
|
shouldVisitNames = true;
|
||||||
|
}
|
||||||
|
public int numProblemBindings;
|
||||||
|
public int numNullBindings;
|
||||||
|
public List<IASTName> nameList = new ArrayList<IASTName>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTName name) {
|
||||||
|
nameList.add(name);
|
||||||
|
IBinding binding = name.resolveBinding();
|
||||||
|
if (binding instanceof IProblemBinding)
|
||||||
|
numProblemBindings++;
|
||||||
|
if (binding == null)
|
||||||
|
numNullBindings++;
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTName getName(int idx) {
|
||||||
|
if (idx < 0 || idx >= nameList.size())
|
||||||
|
return null;
|
||||||
|
return nameList.get(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return nameList.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected class CPPNameResolver extends ASTVisitor {
|
||||||
|
{
|
||||||
|
shouldVisitNames = true;
|
||||||
|
}
|
||||||
|
public int numProblemBindings;
|
||||||
|
public int numNullBindings;
|
||||||
|
public List<IASTName> nameList = new ArrayList<IASTName>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTName name) {
|
||||||
|
nameList.add(name);
|
||||||
|
IBinding binding = name.resolveBinding();
|
||||||
|
if (binding instanceof IProblemBinding)
|
||||||
|
numProblemBindings++;
|
||||||
|
if (binding == null)
|
||||||
|
numNullBindings++;
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTName getName(int idx) {
|
||||||
|
if (idx < 0 || idx >= nameList.size())
|
||||||
|
return null;
|
||||||
|
return nameList.get(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return nameList.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getAboveComment() throws IOException {
|
||||||
|
return getContents(1)[0].toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CharSequence[] getContents(int sections) throws IOException {
|
||||||
|
CTestPlugin plugin = CTestPlugin.getDefault();
|
||||||
|
if (plugin == null)
|
||||||
|
throw new AssertionFailedError("This test must be run as a JUnit plugin test");
|
||||||
|
return TestSourceReader.getContentsForTest(plugin.getBundle(), "parser", getClass(), getName(), sections);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static <T> T assertInstance(Object o, Class<T> clazz, Class... cs) {
|
||||||
|
assertNotNull("Expected object of " + clazz.getName() + " but got a null value", o);
|
||||||
|
assertTrue("Expected "+clazz.getName()+" but got "+o.getClass().getName(), clazz.isInstance(o));
|
||||||
|
for (Class c : cs) {
|
||||||
|
assertNotNull("Expected object of " + c.getName() + " but got a null value", o);
|
||||||
|
assertTrue("Expected " + c.getName() + " but got " + o.getClass().getName(), c.isInstance(o));
|
||||||
|
}
|
||||||
|
return clazz.cast(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void assertField(IBinding binding, String fieldName, String ownerName) {
|
||||||
|
assertInstance(binding, IField.class);
|
||||||
|
assertEquals(fieldName, binding.getName());
|
||||||
|
ICompositeType struct = ((IField) binding).getCompositeTypeOwner();
|
||||||
|
assertEquals(ownerName, struct.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class BindingAssertionHelper {
|
||||||
|
protected IASTTranslationUnit tu;
|
||||||
|
protected String contents;
|
||||||
|
protected boolean isCPP;
|
||||||
|
|
||||||
|
public BindingAssertionHelper(String contents, boolean isCPP) throws ParserException {
|
||||||
|
this(contents, isCPP ? ParserLanguage.CPP : ParserLanguage.C);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BindingAssertionHelper(String contents, ParserLanguage lang) throws ParserException {
|
||||||
|
this.contents= contents;
|
||||||
|
this.isCPP= lang.isCPP();
|
||||||
|
this.tu= parse(contents, lang, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTTranslationUnit getTranslationUnit() {
|
||||||
|
return tu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IProblemBinding assertProblem(String section, int len) {
|
||||||
|
if (len <= 0)
|
||||||
|
len= section.length() + len;
|
||||||
|
IBinding binding= binding(section, len);
|
||||||
|
assertTrue("Non-ProblemBinding for name: " + section.substring(0, len),
|
||||||
|
binding instanceof IProblemBinding);
|
||||||
|
return (IProblemBinding) binding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IProblemBinding assertProblem(String context, int len, int problemId) {
|
||||||
|
IProblemBinding problemBinding = assertProblem(context, len);
|
||||||
|
assertEquals(problemId, problemBinding.getID());
|
||||||
|
return problemBinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IProblemBinding assertProblem(String context, String name) {
|
||||||
|
IBinding binding= binding(context, name);
|
||||||
|
assertTrue("Non-ProblemBinding for name: " + name, binding instanceof IProblemBinding);
|
||||||
|
return (IProblemBinding) binding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IProblemBinding assertProblem(String context, String name, int problemId) {
|
||||||
|
IProblemBinding problemBinding = assertProblem(context, name);
|
||||||
|
assertEquals(problemId, problemBinding.getID());
|
||||||
|
return problemBinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends IBinding> T assertNonProblem(String section, int len) {
|
||||||
|
if (len <= 0)
|
||||||
|
len= section.length() + len;
|
||||||
|
IBinding binding= binding(section, len);
|
||||||
|
if (binding instanceof IProblemBinding) {
|
||||||
|
IProblemBinding problem= (IProblemBinding) binding;
|
||||||
|
fail("ProblemBinding for name: " + section.substring(0, len) + " (" + renderProblemID(problem.getID()) + ")");
|
||||||
|
}
|
||||||
|
if (binding == null) {
|
||||||
|
fail("Null binding resolved for name: " + section.substring(0, len));
|
||||||
|
}
|
||||||
|
return (T) binding;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getIdentifierLength(String str) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < str.length() && Character.isJavaIdentifierPart(str.charAt(i)); ++i) {
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IProblemBinding assertProblemOnFirstIdentifier(String section) {
|
||||||
|
return assertProblem(section, getIdentifierLength(section));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IProblemBinding assertProblemOnFirstIdentifier(String section, int problemId) {
|
||||||
|
IProblemBinding problemBinding = assertProblemOnFirstIdentifier(section);
|
||||||
|
assertEquals(problemId, problemBinding.getID());
|
||||||
|
return problemBinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends IBinding> T assertNonProblemOnFirstIdentifier(String section, Class... cs) {
|
||||||
|
return assertNonProblem(section, getIdentifierLength(section), cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBinding assertNonProblemOnFirstIdentifier(String section) {
|
||||||
|
return assertNonProblem(section, getIdentifierLength(section), IBinding.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void assertNoName(String section, int len) {
|
||||||
|
IASTName name= findName(section, len);
|
||||||
|
if (name != null) {
|
||||||
|
String selection = section.substring(0, len);
|
||||||
|
fail("Found unexpected \"" + selection + "\": " + name.resolveBinding());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts that there is exactly one name at the given location and that
|
||||||
|
* it resolves to the given type of binding.
|
||||||
|
*/
|
||||||
|
public IASTImplicitName assertImplicitName(String section, int len, Class<?> bindingClass) {
|
||||||
|
IASTName name = findImplicitName(section, len);
|
||||||
|
final String selection = section.substring(0, len);
|
||||||
|
assertNotNull("did not find \"" + selection + "\"", name);
|
||||||
|
|
||||||
|
assertInstance(name, IASTImplicitName.class);
|
||||||
|
IASTImplicitNameOwner owner = (IASTImplicitNameOwner) name.getParent();
|
||||||
|
IASTImplicitName[] implicits = owner.getImplicitNames();
|
||||||
|
assertNotNull(implicits);
|
||||||
|
|
||||||
|
if (implicits.length > 1) {
|
||||||
|
boolean found = false;
|
||||||
|
for (IASTImplicitName n : implicits) {
|
||||||
|
if (((ASTNode) n).getOffset() == ((ASTNode) name).getOffset()) {
|
||||||
|
assertFalse(found);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(selection, name.getRawSignature());
|
||||||
|
IBinding binding = name.resolveBinding();
|
||||||
|
assertNotNull(binding);
|
||||||
|
assertInstance(binding, bindingClass);
|
||||||
|
return (IASTImplicitName) name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void assertNoImplicitName(String section, int len) {
|
||||||
|
IASTName name = findImplicitName(section, len);
|
||||||
|
final String selection = section.substring(0, len);
|
||||||
|
assertNull("found name \"" + selection + "\"", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTImplicitName[] getImplicitNames(String section, int len) {
|
||||||
|
IASTName name = findImplicitName(section, len);
|
||||||
|
IASTImplicitNameOwner owner = (IASTImplicitNameOwner) name.getParent();
|
||||||
|
IASTImplicitName[] implicits = owner.getImplicitNames();
|
||||||
|
return implicits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTName findName(String section, int len) {
|
||||||
|
final int offset = contents.indexOf(section);
|
||||||
|
assertTrue("Section \"" + section + "\" not found", offset >= 0);
|
||||||
|
IASTNodeSelector selector = tu.getNodeSelector(null);
|
||||||
|
return selector.findName(offset, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTName findName(String context, String name) {
|
||||||
|
if (context == null) {
|
||||||
|
context = contents;
|
||||||
|
}
|
||||||
|
int offset = contents.indexOf(context);
|
||||||
|
assertTrue("Context \"" + context + "\" not found", offset >= 0);
|
||||||
|
int nameOffset = context.indexOf(name);
|
||||||
|
assertTrue("Name \"" + name + "\" not found", nameOffset >= 0);
|
||||||
|
IASTNodeSelector selector = tu.getNodeSelector(null);
|
||||||
|
return selector.findName(offset + nameOffset, name.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTName findName(String name) {
|
||||||
|
return findName(contents, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTName findImplicitName(String section, int len) {
|
||||||
|
final int offset = contents.indexOf(section);
|
||||||
|
assertTrue(offset >= 0);
|
||||||
|
IASTNodeSelector selector = tu.getNodeSelector(null);
|
||||||
|
return selector.findImplicitName(offset, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends IASTNode> T assertNode(String context, String nodeText, Class... cs) {
|
||||||
|
if (context == null) {
|
||||||
|
context = contents;
|
||||||
|
}
|
||||||
|
int offset = contents.indexOf(context);
|
||||||
|
assertTrue("Context \"" + context + "\" not found", offset >= 0);
|
||||||
|
int nodeOffset = context.indexOf(nodeText);
|
||||||
|
assertTrue("Node \"" + nodeText + "\" not found", nodeOffset >= 0);
|
||||||
|
IASTNodeSelector selector = tu.getNodeSelector(null);
|
||||||
|
IASTNode node = selector.findNode(offset + nodeOffset, nodeText.length());
|
||||||
|
return assertType(node, cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends IASTNode> T assertNode(String nodeText, Class... cs) {
|
||||||
|
return assertNode(contents, nodeText, cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String renderProblemID(int i) {
|
||||||
|
try {
|
||||||
|
for (Field field : IProblemBinding.class.getDeclaredFields()) {
|
||||||
|
if (field.getName().startsWith("SEMANTIC_")) {
|
||||||
|
if (field.getType() == int.class) {
|
||||||
|
Integer ci= (Integer) field.get(null);
|
||||||
|
if (ci.intValue() == i) {
|
||||||
|
return field.getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return "Unknown problem ID";
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends IBinding> T assertNonProblem(String section, int len, Class... cs) {
|
||||||
|
if (len <= 0)
|
||||||
|
len += section.length();
|
||||||
|
IBinding binding= binding(section, len);
|
||||||
|
assertTrue("ProblemBinding for name: " + section.substring(0, len),
|
||||||
|
!(binding instanceof IProblemBinding));
|
||||||
|
return assertType(binding, cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends IBinding> T assertNonProblem(String section, Class... cs) {
|
||||||
|
return assertNonProblem(section, section.length(), cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends IBinding> T assertNonProblem(String context, String name, Class... cs) {
|
||||||
|
IBinding binding= binding(context, name);
|
||||||
|
assertTrue("ProblemBinding for name: " + name, !(binding instanceof IProblemBinding));
|
||||||
|
return assertType(binding, cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T, U extends T> U assertType(T obj, Class... cs) {
|
||||||
|
for (Class c : cs) {
|
||||||
|
assertInstance(obj, c);
|
||||||
|
}
|
||||||
|
return (U) obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IBinding binding(String section, int len) {
|
||||||
|
IASTName astName = findName(section, len);
|
||||||
|
final String selection = section.substring(0, len);
|
||||||
|
assertNotNull("No AST name for \"" + selection + "\"", astName);
|
||||||
|
assertEquals(selection, astName.getRawSignature());
|
||||||
|
|
||||||
|
IBinding binding = astName.resolveBinding();
|
||||||
|
assertNotNull("No binding for " + astName.getRawSignature(), binding);
|
||||||
|
|
||||||
|
return astName.resolveBinding();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IBinding binding(String context, String name) {
|
||||||
|
IASTName astName = findName(context, name);
|
||||||
|
assertNotNull("No AST name for \"" + name + "\"", astName);
|
||||||
|
assertEquals(name, astName.getRawSignature());
|
||||||
|
|
||||||
|
IBinding binding = astName.resolveBinding();
|
||||||
|
assertNotNull("No binding for " + astName.getRawSignature(), binding);
|
||||||
|
|
||||||
|
return astName.resolveBinding();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected IASTTranslationUnit parseAndCheckBindings(String code, ParserLanguage lang) throws Exception {
|
||||||
|
return parseAndCheckBindings(code, lang, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected IASTTranslationUnit parseAndCheckBindings(String code, ParserLanguage lang, boolean useGnuExtensions) throws Exception {
|
||||||
|
return parseAndCheckBindings(code, lang, useGnuExtensions, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected IASTTranslationUnit parseAndCheckBindings(String code, ParserLanguage lang, boolean useGnuExtensions,
|
||||||
|
boolean skipTrivialInitializers) throws Exception {
|
||||||
|
IASTTranslationUnit tu = parse(code, lang, useGnuExtensions, true, skipTrivialInitializers);
|
||||||
|
CNameCollector col = new CNameCollector();
|
||||||
|
tu.accept(col);
|
||||||
|
assertNoProblemBindings(col);
|
||||||
|
return tu;
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected void assertNoProblemBindings(CNameCollector col) {
|
||||||
|
for (IASTName n : col.nameList) {
|
||||||
|
assertFalse("ProblemBinding for " + n.getRawSignature(), n.resolveBinding() instanceof IProblemBinding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected void assertProblemBindings(CNameCollector col, int count) {
|
||||||
|
int sum = 0;
|
||||||
|
for (IASTName n : col.nameList) {
|
||||||
|
if (n.getBinding() instanceof IProblemBinding)
|
||||||
|
++sum;
|
||||||
|
}
|
||||||
|
assertEquals(count, sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected <T extends IASTDeclaration> T getDeclaration(IASTTranslationUnit tu, int i_decl) {
|
||||||
|
Class<T> tclass;
|
||||||
|
IASTDeclaration[] decls= tu.getDeclarations();
|
||||||
|
assertTrue(decls.length > i_decl);
|
||||||
|
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();
|
||||||
|
assertTrue(decls.length > i_decl);
|
||||||
|
return (T) decls[i_decl];
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected <T extends IASTCompositeTypeSpecifier> T getCompositeType(IASTTranslationUnit tu, int i_decl) {
|
||||||
|
IASTSimpleDeclaration sdecl= getDeclaration(tu, i_decl);
|
||||||
|
return (T) sdecl.getDeclSpecifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected <T extends IASTStatement> T getStatement(IASTFunctionDefinition fdef, int i_stmt) {
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
final protected <T extends IASTExpression> T getExpressionOfStatement(IASTFunctionDefinition fdef, int i) {
|
||||||
|
IASTStatement stmt= getStatement(fdef, i);
|
||||||
|
assertInstance(stmt, IASTExpressionStatement.class);
|
||||||
|
return (T) ((IASTExpressionStatement) stmt).getExpression();
|
||||||
|
}
|
||||||
|
}
|
|
@ -128,6 +128,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
|
||||||
import org.eclipse.cdt.core.parser.ParserLanguage;
|
import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNameBase;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethod;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethod;
|
||||||
|
@ -10116,4 +10117,36 @@ public class AST2CPPTests extends AST2TestBase {
|
||||||
public void testIsBaseOf_399353() throws Exception {
|
public void testIsBaseOf_399353() throws Exception {
|
||||||
parseAndCheckBindings(getAboveComment(), CPP, true);
|
parseAndCheckBindings(getAboveComment(), CPP, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// template <bool> struct B{};
|
||||||
|
// template <>
|
||||||
|
// struct B<true> {
|
||||||
|
// void waldo();
|
||||||
|
// };
|
||||||
|
// typedef char& one;
|
||||||
|
// int main() {
|
||||||
|
// B<sizeof(one) == 1> b;
|
||||||
|
// b.waldo();
|
||||||
|
// }
|
||||||
|
public void testSizeofReference_397342() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct A {
|
||||||
|
// char a[100];
|
||||||
|
// };
|
||||||
|
// struct B {
|
||||||
|
// A& b;
|
||||||
|
// };
|
||||||
|
// A* p;
|
||||||
|
public void testSizeofStructWithReferenceField_397342() throws Exception {
|
||||||
|
BindingAssertionHelper bh = getAssertionHelper();
|
||||||
|
IASTName nameB = bh.findName("B");
|
||||||
|
IASTName namep = bh.findName("p");
|
||||||
|
ICPPClassType B = (ICPPClassType) nameB.resolveBinding();
|
||||||
|
IPointerType ptrToA = (IPointerType) ((ICPPVariable) namep.resolveBinding()).getType();
|
||||||
|
long pointerSize = SizeofCalculator.getSizeAndAlignment(ptrToA, namep).size;
|
||||||
|
long BSize = SizeofCalculator.getSizeAndAlignment(B, nameB).size;
|
||||||
|
assertEquals(pointerSize, BSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2011 Google, Inc and others.
|
* Copyright (c) 2011, 2013 Google, Inc and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -7,6 +7,7 @@
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Sergey Prigogin (Google) - initial API and implementation
|
* Sergey Prigogin (Google) - initial API and implementation
|
||||||
|
* Nathan Ridge
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser;
|
package org.eclipse.cdt.internal.core.dom.parser;
|
||||||
|
|
||||||
|
@ -182,7 +183,12 @@ public class SizeofCalculator {
|
||||||
if (type instanceof IBasicType) {
|
if (type instanceof IBasicType) {
|
||||||
return sizeAndAlignment((IBasicType) type);
|
return sizeAndAlignment((IBasicType) type);
|
||||||
}
|
}
|
||||||
if (type instanceof IPointerType || type instanceof ICPPReferenceType) {
|
// [expr.sizeof]/2: "When applied to a reference or a reference type, the
|
||||||
|
// result is the size of the referenced type."
|
||||||
|
if (type instanceof ICPPReferenceType) {
|
||||||
|
return sizeAndAlignment(((ICPPReferenceType) type).getType());
|
||||||
|
}
|
||||||
|
if (type instanceof IPointerType) {
|
||||||
if (type instanceof ICPPPointerToMemberType)
|
if (type instanceof ICPPPointerToMemberType)
|
||||||
return null;
|
return null;
|
||||||
return sizeof_pointer;
|
return sizeof_pointer;
|
||||||
|
@ -314,14 +320,24 @@ public class SizeofCalculator {
|
||||||
if (field.isStatic())
|
if (field.isStatic())
|
||||||
continue;
|
continue;
|
||||||
IType fieldType = field.getType();
|
IType fieldType = field.getType();
|
||||||
SizeAndAlignment info = sizeAndAlignment(fieldType);
|
SizeAndAlignment info;
|
||||||
|
// sizeof() on a reference type returns the size of the referenced type.
|
||||||
|
// However, a reference field in a structure only occupies as much space
|
||||||
|
// as a pointer.
|
||||||
|
if (fieldType instanceof ICPPReferenceType) {
|
||||||
|
info = sizeof_pointer;
|
||||||
|
} else {
|
||||||
|
info = sizeAndAlignment(fieldType);
|
||||||
|
}
|
||||||
if (info == null)
|
if (info == null)
|
||||||
return null;
|
return null;
|
||||||
if (union) {
|
if (union) {
|
||||||
if (size < info.size)
|
if (size < info.size)
|
||||||
size = info.size;
|
size = info.size;
|
||||||
} else {
|
} else {
|
||||||
size += info.alignment - (size - 1) % info.alignment - 1 + info.size;
|
if (size > 0)
|
||||||
|
size += info.alignment - (size - 1) % info.alignment - 1;
|
||||||
|
size += info.size;
|
||||||
}
|
}
|
||||||
if (maxAlignment < info.alignment)
|
if (maxAlignment < info.alignment)
|
||||||
maxAlignment = info.alignment;
|
maxAlignment = info.alignment;
|
||||||
|
|
Loading…
Add table
Reference in a new issue