mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 380498 - typedef is expanded during refactoring
This commit is contained in:
parent
3604f812ce
commit
2776e06605
11 changed files with 288 additions and 92 deletions
|
@ -10,6 +10,7 @@
|
|||
* Markus Schorn (Wind River Systems)
|
||||
* Andrew Ferguson (Symbian)
|
||||
* Mike Kucera (IBM)
|
||||
* Sergey Prigogin (Google)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.parser.tests.ast2;
|
||||
|
||||
|
@ -628,6 +629,23 @@ public class AST2BaseTest extends BaseTestCase {
|
|||
return selector.findImplicitName(offset, len);
|
||||
}
|
||||
|
||||
public <T extends IASTNode> T assertNode(String context, String nodeText, Class<T> type, 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, type, cs);
|
||||
}
|
||||
|
||||
public <T extends IASTNode> T assertNode(String nodeText, Class<T> type, Class... cs) {
|
||||
return assertNode(contents, nodeText, type, cs);
|
||||
}
|
||||
|
||||
private String renderProblemID(int i) {
|
||||
try {
|
||||
for (Field field : IProblemBinding.class.getDeclaredFields()) {
|
||||
|
@ -652,17 +670,31 @@ public class AST2BaseTest extends BaseTestCase {
|
|||
IBinding binding= binding(section, len);
|
||||
assertTrue("ProblemBinding for name: " + section.substring(0, len),
|
||||
!(binding instanceof IProblemBinding));
|
||||
assertInstance(binding, type);
|
||||
for (Class c : cs) {
|
||||
assertInstance(binding, c);
|
||||
}
|
||||
return type.cast(binding);
|
||||
return assertType(binding, type, cs);
|
||||
}
|
||||
|
||||
public <T extends IBinding> T assertNonProblem(String section, Class<T> type, Class... cs) {
|
||||
return assertNonProblem(section, section.length(), type, cs);
|
||||
}
|
||||
|
||||
public <T extends IBinding> T assertNonProblem(String context, String name, Class<T> type, Class... cs) {
|
||||
IBinding binding= binding(context, name);
|
||||
assertTrue("ProblemBinding for name: " + name, !(binding instanceof IProblemBinding));
|
||||
return assertType(binding, type, cs);
|
||||
}
|
||||
|
||||
public <T, U extends T> U assertType(T obj, Class<U> type, Class... cs) {
|
||||
assertInstance(obj, type);
|
||||
for (Class c : cs) {
|
||||
assertInstance(obj, c);
|
||||
}
|
||||
return type.cast(obj);
|
||||
}
|
||||
|
||||
private IBinding binding(String section, int len) {
|
||||
IASTName name = findName(section, len);
|
||||
final String selection = section.substring(0, len);
|
||||
assertNotNull("did not find \"" + selection + "\"", name);
|
||||
assertNotNull("Did not find \"" + selection + "\"", name);
|
||||
assertEquals(selection, name.getRawSignature());
|
||||
|
||||
IBinding binding = name.resolveBinding();
|
||||
|
@ -670,7 +702,17 @@ public class AST2BaseTest extends BaseTestCase {
|
|||
|
||||
return name.resolveBinding();
|
||||
}
|
||||
}
|
||||
|
||||
private IBinding binding(String context, String name) {
|
||||
IASTName astName = findName(context, name);
|
||||
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);
|
||||
|
|
|
@ -4705,6 +4705,33 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
assertSame(i, col.getName(7).resolveBinding());
|
||||
}
|
||||
|
||||
// template<typename T>
|
||||
// class basic_string {
|
||||
// basic_string& operator+=(const T* s);
|
||||
// };
|
||||
//
|
||||
// template<typename T>
|
||||
// basic_string<T> operator+(const T* cs, const basic_string<T>& s);
|
||||
//
|
||||
// template<typename T>
|
||||
// basic_string<T> operator+(const basic_string<T>& s, const T* cs);
|
||||
//
|
||||
// typedef basic_string<char> string;
|
||||
//
|
||||
// void test(const string& s) {
|
||||
// auto s1 = "" + s + "";
|
||||
// auto s2 = s1 += "";
|
||||
// }
|
||||
public void testTypedefPreservation_380498() throws Exception {
|
||||
BindingAssertionHelper ba= getAssertionHelper();
|
||||
ICPPVariable s1 = ba.assertNonProblem("s1", ICPPVariable.class);
|
||||
assertTrue(s1.getType() instanceof ITypedef);
|
||||
assertEquals("string", ((ITypedef) s1.getType()).getName());
|
||||
ICPPVariable s2 = ba.assertNonProblem("s2", ICPPVariable.class);
|
||||
assertTrue(s2.getType() instanceof ITypedef);
|
||||
assertEquals("string", ((ITypedef) s2.getType()).getName());
|
||||
}
|
||||
|
||||
// int f() {
|
||||
// return 5;
|
||||
// }
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* Doug Schaefer (IBM) - Initial API and implementation
|
||||
* Markus Schorn (Wind River Systems)
|
||||
* Andrew Ferguson (Symbian)
|
||||
* Sergey Prigogin (Google)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.core.parser.tests.ast2;
|
||||
|
||||
|
@ -6081,6 +6082,29 @@ public class AST2Tests extends AST2BaseTest {
|
|||
}
|
||||
}
|
||||
|
||||
// typedef long unsigned int size_t;
|
||||
//
|
||||
// size_t a = 0;
|
||||
// size_t x = a + 5;
|
||||
// size_t y = 2 + a;
|
||||
// size_t y = a * 2;
|
||||
public void testTypeOfExpressionWithTypedef_380498() throws Exception {
|
||||
final boolean[] isCpps= { false, true };
|
||||
String code= getAboveComment();
|
||||
for (boolean isCpp : isCpps) {
|
||||
BindingAssertionHelper ba= new BindingAssertionHelper(code, isCpp);
|
||||
IASTExpression exp = ba.assertNode("a + 5", IASTExpression.class);
|
||||
assertTrue(exp.getExpressionType() instanceof ITypedef);
|
||||
assertEquals("size_t", ((ITypedef) exp.getExpressionType()).getName());
|
||||
exp = ba.assertNode("2 + a", IASTExpression.class);
|
||||
assertTrue(exp.getExpressionType() instanceof ITypedef);
|
||||
assertEquals("size_t", ((ITypedef) exp.getExpressionType()).getName());
|
||||
exp = ba.assertNode("a * 2", IASTExpression.class);
|
||||
assertTrue(exp.getExpressionType() instanceof ITypedef);
|
||||
assertEquals("size_t", ((ITypedef) exp.getExpressionType()).getName());
|
||||
}
|
||||
}
|
||||
|
||||
// typedef int TInt;
|
||||
// int a= TInt; //ref
|
||||
public void testTypeAsExpressionIsProblem_261175() throws Exception {
|
||||
|
|
|
@ -9,9 +9,12 @@
|
|||
* John Camelon (IBM Rational Software) - Initial API and implementation
|
||||
* Yuan Zhang / Beth Tibbitts (IBM Research)
|
||||
* Markus Schorn (Wind River Systems)
|
||||
* Sergey Prigogin (Google)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.c;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.restoreTypedefs;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
|
@ -207,11 +210,13 @@ public class CASTBinaryExpression extends ASTNode
|
|||
@Override
|
||||
public IType getExpressionType() {
|
||||
final int op = getOperator();
|
||||
final IType t1= CVisitor.unwrapTypedefs(getOperand1().getExpressionType());
|
||||
final IType t2= CVisitor.unwrapTypedefs(getOperand2().getExpressionType());
|
||||
IType type= CArithmeticConversion.convertCOperandTypes(op, t1, t2);
|
||||
IType originalType1 = getOperand1().getExpressionType();
|
||||
IType originalType2 = getOperand2().getExpressionType();
|
||||
final IType type1= CVisitor.unwrapTypedefs(originalType1);
|
||||
final IType type2= CVisitor.unwrapTypedefs(originalType2);
|
||||
IType type= CArithmeticConversion.convertCOperandTypes(op, type1, type2);
|
||||
if (type != null) {
|
||||
return type;
|
||||
return restoreTypedefs(type, originalType1, originalType2);
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
|
@ -226,25 +231,25 @@ public class CASTBinaryExpression extends ASTNode
|
|||
return new CBasicType(Kind.eInt, 0, this);
|
||||
|
||||
case IASTBinaryExpression.op_plus:
|
||||
if (t1 instanceof IArrayType) {
|
||||
return arrayTypeToPointerType((ICArrayType) t1);
|
||||
} else if (t2 instanceof IPointerType) {
|
||||
return t2;
|
||||
} else if (t2 instanceof IArrayType) {
|
||||
return arrayTypeToPointerType((ICArrayType) t2);
|
||||
if (type1 instanceof IArrayType) {
|
||||
return arrayTypeToPointerType((ICArrayType) type1);
|
||||
} else if (type2 instanceof IPointerType) {
|
||||
return restoreTypedefs(type2, originalType2);
|
||||
} else if (type2 instanceof IArrayType) {
|
||||
return arrayTypeToPointerType((ICArrayType) type2);
|
||||
}
|
||||
break;
|
||||
|
||||
case IASTBinaryExpression.op_minus:
|
||||
if (t2 instanceof IPointerType || t2 instanceof IArrayType) {
|
||||
if (t1 instanceof IPointerType || t1 instanceof IArrayType) {
|
||||
if (type2 instanceof IPointerType || type2 instanceof IArrayType) {
|
||||
if (type1 instanceof IPointerType || type1 instanceof IArrayType) {
|
||||
return CVisitor.getPtrDiffType(this);
|
||||
}
|
||||
return t1;
|
||||
return restoreTypedefs(type1, originalType1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return t1;
|
||||
return restoreTypedefs(type1, originalType1);
|
||||
}
|
||||
|
||||
private IType arrayTypeToPointerType(ICArrayType type) {
|
||||
|
|
|
@ -9,9 +9,12 @@
|
|||
* John Camelon (IBM Rational Software) - Initial API and implementation
|
||||
* Yuan Zhang / Beth Tibbitts (IBM Research)
|
||||
* Markus Schorn (Wind River Systems)
|
||||
* Sergey Prigogin (Google)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.c;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.restoreTypedefs;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
|
@ -122,17 +125,17 @@ public class CASTUnaryExpression extends ASTNode implements IASTUnaryExpression,
|
|||
}
|
||||
break;
|
||||
case op_amper:
|
||||
return new CPointerType(type, 0);
|
||||
return new CPointerType(exprType, 0);
|
||||
case op_minus:
|
||||
case op_plus:
|
||||
case op_tilde:
|
||||
IType t= CArithmeticConversion.promoteCType(type);
|
||||
if (t != null) {
|
||||
return t;
|
||||
return restoreTypedefs(t, exprType);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return exprType; // return the original
|
||||
return exprType; // Return the original.
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* John Camelon (IBM) - Initial API and implementation
|
||||
* Mike Kucera (IBM)
|
||||
* Markus Schorn (Wind River Systems)
|
||||
* Sergey Prigogin (Google)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
|
@ -16,6 +17,7 @@ import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
|
|||
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.glvalueType;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.prvalueType;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.restoreTypedefs;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeFromFunctionCall;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromFunctionCall;
|
||||
|
||||
|
@ -40,7 +42,6 @@ import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||
|
||||
|
||||
public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpression, IASTAmbiguityParent {
|
||||
private int op;
|
||||
private IASTExpression operand1;
|
||||
|
@ -313,21 +314,26 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
|
|||
}
|
||||
|
||||
private IType createExpressionType() {
|
||||
IType originalType1 = operand1.getExpressionType();
|
||||
IType originalType2 = operand2 instanceof IASTExpression ?
|
||||
((IASTExpression) operand2).getExpressionType() : null;
|
||||
|
||||
// Check for overloaded operator.
|
||||
ICPPFunction o= getOverload();
|
||||
if (o != null) {
|
||||
return typeFromFunctionCall(o);
|
||||
IType type = typeFromFunctionCall(o);
|
||||
return restoreTypedefs(type, originalType1, originalType2);
|
||||
}
|
||||
|
||||
final int op = getOperator();
|
||||
IType type1 = prvalueType(operand1.getExpressionType());
|
||||
IType type1 = prvalueType(originalType1);
|
||||
if (type1 instanceof ISemanticProblem) {
|
||||
return type1;
|
||||
}
|
||||
|
||||
IType type2 = null;
|
||||
if (operand2 instanceof IASTExpression) {
|
||||
type2= prvalueType(((IASTExpression) operand2).getExpressionType());
|
||||
if (originalType2 != null) {
|
||||
type2= prvalueType(originalType2);
|
||||
if (type2 instanceof ISemanticProblem) {
|
||||
return type2;
|
||||
}
|
||||
|
@ -335,7 +341,7 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
|
|||
|
||||
IType type= CPPArithmeticConversion.convertCppOperandTypes(op, type1, type2);
|
||||
if (type != null) {
|
||||
return type;
|
||||
return restoreTypedefs(type, originalType1, originalType2);
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
|
@ -351,10 +357,10 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
|
|||
|
||||
case IASTBinaryExpression.op_plus:
|
||||
if (type1 instanceof IPointerType) {
|
||||
return type1;
|
||||
return restoreTypedefs(type1, originalType1);
|
||||
}
|
||||
if (type2 instanceof IPointerType) {
|
||||
return type2;
|
||||
return restoreTypedefs(type2, originalType2);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -363,7 +369,7 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
|
|||
if (type2 instanceof IPointerType) {
|
||||
return CPPVisitor.getPointerDiffType(this);
|
||||
}
|
||||
return type1;
|
||||
return restoreTypedefs(type1, originalType1);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -380,6 +386,6 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
|
|||
}
|
||||
return new ProblemType(ISemanticProblem.TYPE_UNKNOWN_FOR_EXPRESSION);
|
||||
}
|
||||
return type1;
|
||||
return restoreTypedefs(type1, originalType1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,13 +72,9 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
|
|||
|
||||
@Override
|
||||
public CPPASTUnaryExpression copy(CopyStyle style) {
|
||||
CPPASTUnaryExpression copy = new CPPASTUnaryExpression(op, operand == null ? null
|
||||
: operand.copy(style));
|
||||
copy.setOffsetAndLength(this);
|
||||
if (style == CopyStyle.withLocations) {
|
||||
copy.setCopyLocation(this);
|
||||
}
|
||||
return copy;
|
||||
CPPASTUnaryExpression copy =
|
||||
new CPPASTUnaryExpression(op, operand == null ? null : operand.copy(style));
|
||||
return copy(copy, style);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2065,6 +2065,9 @@ public class CPPVisitor extends ASTQueries {
|
|||
return new ProblemType(ISemanticProblem.TYPE_CANNOT_DEDUCE_AUTO_TYPE);
|
||||
}
|
||||
type = argument.getTypeValue();
|
||||
IType t = SemanticUtil.substituteTypedef(type, initType);
|
||||
if (t != null)
|
||||
type = t;
|
||||
if (initClause instanceof ICPPASTInitializerList) {
|
||||
type = (IType) CPPTemplates.instantiate(initializer_list_template,
|
||||
new ICPPTemplateArgument[] { new CPPTemplateArgument(type) });
|
||||
|
|
|
@ -16,7 +16,16 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
|||
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromReturnType;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ALLCVQ;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.COND_TDEF;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.addQualifiers;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.calculateInheritanceDepth;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getCVQualifier;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.isVoidType;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
|
@ -179,7 +188,7 @@ public class Conversions {
|
|||
return cost;
|
||||
}
|
||||
}
|
||||
// — otherwise, the program is ill-formed.
|
||||
// � otherwise, the program is ill-formed.
|
||||
return Cost.NO_CONVERSION;
|
||||
}
|
||||
|
||||
|
@ -1147,18 +1156,18 @@ public class Conversions {
|
|||
* 4.1, 4.2, 4.3
|
||||
*/
|
||||
public static IType lvalue_to_rvalue(IType type) {
|
||||
type= SemanticUtil.getNestedType(type, TDEF | REF);
|
||||
if (type instanceof IArrayType) {
|
||||
return new CPPPointerType(((IArrayType) type).getType());
|
||||
IType t= SemanticUtil.getNestedType(type, TDEF | REF);
|
||||
if (t instanceof IArrayType) {
|
||||
return new CPPPointerType(((IArrayType) t).getType());
|
||||
}
|
||||
if (type instanceof IFunctionType) {
|
||||
return new CPPPointerType(type);
|
||||
if (t instanceof IFunctionType) {
|
||||
return new CPPPointerType(t);
|
||||
}
|
||||
IType uqType= SemanticUtil.getNestedType(type, TDEF | REF | ALLCVQ);
|
||||
IType uqType= SemanticUtil.getNestedType(t, TDEF | REF | ALLCVQ);
|
||||
if (uqType instanceof ICPPClassType) {
|
||||
return type;
|
||||
return SemanticUtil.getNestedType(type, COND_TDEF | REF);
|
||||
}
|
||||
return uqType;
|
||||
return SemanticUtil.getNestedType(t, COND_TDEF | REF | ALLCVQ);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,9 +7,11 @@
|
|||
*
|
||||
* Contributors:
|
||||
* Markus Schorn - initial API and implementation
|
||||
* Sergey Prigogin (Google)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.COND_TDEF;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
||||
|
@ -27,13 +29,13 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||
|
||||
/**
|
||||
* Methods for computing the type of an expression
|
||||
* Methods for computing the type of an expression.
|
||||
*/
|
||||
public class ExpressionTypes {
|
||||
|
||||
public static IType glvalueType(IType type) {
|
||||
// Reference types are removed.
|
||||
return SemanticUtil.getNestedType(type, TDEF | REF);
|
||||
return SemanticUtil.getNestedType(type, COND_TDEF | REF);
|
||||
}
|
||||
|
||||
public static IType prvalueType(IType type) {
|
||||
|
@ -65,46 +67,46 @@ public class ExpressionTypes {
|
|||
return typeFromReturnType(ft.getReturnType());
|
||||
}
|
||||
|
||||
public static IType typeFromReturnType(IType r) {
|
||||
r= SemanticUtil.getNestedType(r, TDEF);
|
||||
if (r instanceof ICPPReferenceType) {
|
||||
return glvalueType(r);
|
||||
public static IType typeFromReturnType(IType type) {
|
||||
IType t= SemanticUtil.getNestedType(type, TDEF);
|
||||
if (t instanceof ICPPReferenceType) {
|
||||
return glvalueType(type);
|
||||
}
|
||||
return prvalueType(r);
|
||||
return prvalueType(type);
|
||||
}
|
||||
|
||||
public static IType typeOrFunctionSet(IASTExpression e) {
|
||||
FunctionSetType fs= getFunctionSetType(e);
|
||||
public static IType typeOrFunctionSet(IASTExpression exp) {
|
||||
FunctionSetType fs= getFunctionSetType(exp);
|
||||
if (fs != null) {
|
||||
return fs;
|
||||
}
|
||||
return e.getExpressionType();
|
||||
return exp.getExpressionType();
|
||||
}
|
||||
|
||||
public static ValueCategory valueCat(IASTExpression e) {
|
||||
FunctionSetType fs= getFunctionSetType(e);
|
||||
public static ValueCategory valueCat(IASTExpression exp) {
|
||||
FunctionSetType fs= getFunctionSetType(exp);
|
||||
if (fs != null)
|
||||
return fs.getValueCategory();
|
||||
return e.getValueCategory();
|
||||
return exp.getValueCategory();
|
||||
}
|
||||
|
||||
private static FunctionSetType getFunctionSetType(IASTExpression e) {
|
||||
private static FunctionSetType getFunctionSetType(IASTExpression exp) {
|
||||
boolean addressOf= false;
|
||||
while (e instanceof IASTUnaryExpression) {
|
||||
final IASTUnaryExpression unary = (IASTUnaryExpression) e;
|
||||
while (exp instanceof IASTUnaryExpression) {
|
||||
final IASTUnaryExpression unary = (IASTUnaryExpression) exp;
|
||||
final int op= unary.getOperator();
|
||||
if (op == IASTUnaryExpression.op_bracketedPrimary) {
|
||||
e= unary.getOperand();
|
||||
exp= unary.getOperand();
|
||||
} else if (!addressOf && op == IASTUnaryExpression.op_amper) {
|
||||
addressOf= true;
|
||||
e= unary.getOperand();
|
||||
exp= unary.getOperand();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (e instanceof IASTIdExpression) {
|
||||
IASTIdExpression idexpr= (IASTIdExpression) e;
|
||||
if (exp instanceof IASTIdExpression) {
|
||||
IASTIdExpression idexpr= (IASTIdExpression) exp;
|
||||
final IASTName name = idexpr.getName();
|
||||
IBinding b= name.resolvePreBinding();
|
||||
if (b instanceof CPPFunctionSet) {
|
||||
|
@ -113,4 +115,23 @@ public class ExpressionTypes {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IType restoreTypedefs(IType type, IType originalType) {
|
||||
IType t = SemanticUtil.substituteTypedef(type, originalType);
|
||||
if (t != null)
|
||||
return t;
|
||||
return type;
|
||||
}
|
||||
|
||||
public static IType restoreTypedefs(IType type, IType originalType1, IType originalType2) {
|
||||
IType t = SemanticUtil.substituteTypedef(type, originalType1);
|
||||
if (t != null)
|
||||
return t;
|
||||
if (originalType2 != null) {
|
||||
t = SemanticUtil.substituteTypedef(type, originalType2);
|
||||
if (t != null)
|
||||
return t;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,14 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CVQualifier.*;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CVQualifier.CONST;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CVQualifier.CONST_RESTRICT;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CVQualifier.CONST_VOLATILE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CVQualifier.CONST_VOLATILE_RESTRICT;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CVQualifier.NONE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CVQualifier.RESTRICT;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CVQualifier.VOLATILE;
|
||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CVQualifier.VOLATILE_RESTRICT;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
@ -60,20 +67,23 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
|
||||
|
||||
/**
|
||||
*
|
||||
* Collection of static methods operating on C++ bindings.
|
||||
*/
|
||||
public class SemanticUtil {
|
||||
private static final char[] OPERATOR_CHARS = Keywords.OPERATOR.toCharArray();
|
||||
// Cache of overloadable operator names for fast lookup. Used by isConversionOperator.
|
||||
private static final CharArraySet cas= new CharArraySet(OverloadableOperator.values().length);
|
||||
|
||||
public static final int TDEF = 0x01;
|
||||
public static final int REF = 0x02;
|
||||
public static final int CVTYPE = 0x04;
|
||||
public static final int ALLCVQ= 0x08;
|
||||
public static final int PTR= 0x10;
|
||||
public static final int MPTR= 0x20;
|
||||
public static final int ARRAY= 0x40;
|
||||
// Resolve typedefs.
|
||||
public static final int TDEF = 0x01;
|
||||
// Resolve typedefs, but only if necessary for a nested type transformation.
|
||||
public static final int COND_TDEF = 0x02;
|
||||
public static final int REF = 0x04;
|
||||
public static final int CVTYPE = 0x08;
|
||||
public static final int ALLCVQ = 0x10;
|
||||
public static final int PTR = 0x20;
|
||||
public static final int MPTR = 0x40;
|
||||
public static final int ARRAY = 0x80;
|
||||
|
||||
static {
|
||||
final int OPERATOR_SPC= OPERATOR_CHARS.length + 1;
|
||||
|
@ -221,14 +231,25 @@ public class SemanticUtil {
|
|||
*/
|
||||
public static IType getNestedType(IType type, int options) {
|
||||
final boolean tdef= (options & TDEF) != 0;
|
||||
final boolean cond_tdef= (options & COND_TDEF) != 0;
|
||||
final boolean ptr= (options & PTR) != 0;
|
||||
final boolean mptr= (options & MPTR) != 0;
|
||||
final boolean allcvq= (options & ALLCVQ) != 0;
|
||||
final boolean cvtype = (options & CVTYPE) != 0;
|
||||
|
||||
IType beforeTypedefs = null;
|
||||
|
||||
while (true) {
|
||||
IType t= null;
|
||||
if (type instanceof IPointerType) {
|
||||
if (type instanceof ITypedef) {
|
||||
if (tdef || cond_tdef) {
|
||||
if (beforeTypedefs == null && cond_tdef) {
|
||||
beforeTypedefs = type;
|
||||
}
|
||||
t= ((ITypedef) type).getType();
|
||||
}
|
||||
} else if (type instanceof IPointerType) {
|
||||
beforeTypedefs = null;
|
||||
final boolean isMbrPtr = type instanceof ICPPPointerToMemberType;
|
||||
if ((ptr && !isMbrPtr) || (mptr && isMbrPtr)) {
|
||||
t= ((IPointerType) type).getType();
|
||||
|
@ -244,20 +265,20 @@ public class SemanticUtil {
|
|||
}
|
||||
return pt;
|
||||
}
|
||||
} else if (tdef && type instanceof ITypedef) {
|
||||
t= ((ITypedef) type).getType();
|
||||
} else if (type instanceof IQualifierType) {
|
||||
beforeTypedefs = null;
|
||||
final IQualifierType qt = (IQualifierType) type;
|
||||
final IType qttgt = qt.getType();
|
||||
if (allcvq || cvtype) {
|
||||
t= qttgt;
|
||||
} else if (tdef) {
|
||||
} else if (tdef || cond_tdef) {
|
||||
t= getNestedType(qttgt, options);
|
||||
if (t == qttgt)
|
||||
return qt;
|
||||
return addQualifiers(t, qt.isConst(), qt.isVolatile(), false);
|
||||
}
|
||||
} else if (type instanceof IArrayType) {
|
||||
beforeTypedefs = null;
|
||||
final IArrayType atype= (IArrayType) type;
|
||||
if ((options & ARRAY) != 0) {
|
||||
t= atype.getType();
|
||||
|
@ -269,11 +290,12 @@ public class SemanticUtil {
|
|||
return replaceNestedType((ITypeContainer) atype, newNested);
|
||||
}
|
||||
} else if (type instanceof ICPPReferenceType) {
|
||||
beforeTypedefs = null;
|
||||
final ICPPReferenceType rt = (ICPPReferenceType) type;
|
||||
if ((options & REF) != 0) {
|
||||
t= rt.getType();
|
||||
} else if (tdef) {
|
||||
// a typedef within the reference type can influence whether the reference is lvalue or rvalue
|
||||
// A typedef within the reference type can influence whether the reference is lvalue or rvalue
|
||||
IType nested= rt.getType();
|
||||
IType newNested = getNestedType(nested, TDEF);
|
||||
if (nested == newNested)
|
||||
|
@ -282,8 +304,12 @@ public class SemanticUtil {
|
|||
}
|
||||
}
|
||||
// Pack expansion types are dependent types, there is no need to descend into those.
|
||||
if (t == null)
|
||||
if (t == null) {
|
||||
if (beforeTypedefs != null) {
|
||||
return beforeTypedefs;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
type= t;
|
||||
}
|
||||
|
@ -354,7 +380,7 @@ public class SemanticUtil {
|
|||
if (newNestedType == null)
|
||||
return type;
|
||||
|
||||
// bug 249085 make sure not to add unnecessary qualifications
|
||||
// Bug 249085 make sure not to add unnecessary qualifications
|
||||
if (type instanceof IQualifierType) {
|
||||
IQualifierType qt= (IQualifierType) type;
|
||||
return addQualifiers(newNestedType, qt.isConst(), qt.isVolatile(), false);
|
||||
|
@ -365,6 +391,40 @@ public class SemanticUtil {
|
|||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the given type or its nested type with a typedef if that type is the same as
|
||||
* the type the typedef resolves to.
|
||||
*
|
||||
* @param type the type subject to substitution
|
||||
* @param typedefType the type possibly containing the typedef as its nested type.
|
||||
* @return the given type with the nested type replaced by the typedef, or {@code null} if
|
||||
* the typedefType doesn't contain a typedef or the nested type doesn't match the typedef.
|
||||
*/
|
||||
public static IType substituteTypedef(IType type, IType typedefType) {
|
||||
typedefType = getNestedType(typedefType, REF | ALLCVQ | PTR | ARRAY);
|
||||
if (!(typedefType instanceof ITypedef))
|
||||
return null;
|
||||
IType nestedType = getNestedType(type, REF | ALLCVQ | PTR | ARRAY);
|
||||
if (!nestedType.isSameType(((ITypedef) typedefType).getType()))
|
||||
return null;
|
||||
|
||||
IType result = null;
|
||||
ITypeContainer containerType = null;
|
||||
for (IType t = type; ; t = containerType.getType()) {
|
||||
IType newType = t == nestedType ? typedefType : (IType) t.clone();
|
||||
if (result == null)
|
||||
result = newType;
|
||||
if (containerType != null) {
|
||||
containerType.setType(newType);
|
||||
}
|
||||
if (t == nestedType)
|
||||
return result;
|
||||
if (!(t instanceof ITypeContainer))
|
||||
return null;
|
||||
containerType = (ITypeContainer) t;
|
||||
}
|
||||
}
|
||||
|
||||
public static IType mapToAST(IType type, IASTNode node) {
|
||||
if (type instanceof IFunctionType) {
|
||||
final ICPPFunctionType ft = (ICPPFunctionType) type;
|
||||
|
|
Loading…
Add table
Reference in a new issue