1
0
Fork 0
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:
Sergey Prigogin 2012-05-30 18:25:21 -07:00
parent 3604f812ce
commit 2776e06605
11 changed files with 288 additions and 92 deletions

View file

@ -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 assertType(binding, type, cs);
}
return type.cast(binding);
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,6 +702,16 @@ 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 {

View file

@ -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;
// }

View file

@ -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 {

View file

@ -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) {

View file

@ -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

View file

@ -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);
}
}

View file

@ -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

View file

@ -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) });

View file

@ -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);
}
/**

View file

@ -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;
}
}

View file

@ -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);
// Resolve typedefs.
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, 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;