1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 380498. Fixed few more cases where typedefs were not preserved.

This commit is contained in:
Sergey Prigogin 2012-06-05 10:32:51 -07:00
parent 077c4ed4a1
commit 2bc64f56f3
18 changed files with 160 additions and 110 deletions

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2004, 2010 IBM Corporation and others. * Copyright (c) 2004, 2012 IBM Corporation 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
@ -514,9 +514,13 @@ public class AST2BaseTest extends BaseTestCase {
protected boolean isCPP; protected boolean isCPP;
public BindingAssertionHelper(String contents, boolean isCPP) throws ParserException { 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.contents= contents;
this.isCPP= isCPP; this.isCPP= lang.isCPP();
this.tu= parse(contents, isCPP ? ParserLanguage.CPP : ParserLanguage.C, true, false); this.tu= parse(contents, lang, true, false);
} }
public IASTTranslationUnit getTranslationUnit() { public IASTTranslationUnit getTranslationUnit() {

View file

@ -4706,8 +4706,9 @@ public class AST2CPPTests extends AST2BaseTest {
} }
// template<typename T> // template<typename T>
// class basic_string { // struct basic_string {
// basic_string& operator+=(const T* s); // basic_string& operator+=(const T* s);
// basic_string& append(const T* s);
// }; // };
// //
// template<typename T> // template<typename T>
@ -4721,8 +4722,9 @@ public class AST2CPPTests extends AST2BaseTest {
// void test(const string& s) { // void test(const string& s) {
// auto s1 = "" + s + ""; // auto s1 = "" + s + "";
// auto s2 = s1 += ""; // auto s2 = s1 += "";
// auto s3 = s2.append("foo");
// } // }
public void testTypedefPreservation_380498() throws Exception { public void testTypedefPreservation_380498_1() throws Exception {
BindingAssertionHelper ba= getAssertionHelper(); BindingAssertionHelper ba= getAssertionHelper();
ICPPVariable s1 = ba.assertNonProblem("s1", ICPPVariable.class); ICPPVariable s1 = ba.assertNonProblem("s1", ICPPVariable.class);
assertTrue(s1.getType() instanceof ITypedef); assertTrue(s1.getType() instanceof ITypedef);
@ -4730,6 +4732,25 @@ public class AST2CPPTests extends AST2BaseTest {
ICPPVariable s2 = ba.assertNonProblem("s2", ICPPVariable.class); ICPPVariable s2 = ba.assertNonProblem("s2", ICPPVariable.class);
assertTrue(s2.getType() instanceof ITypedef); assertTrue(s2.getType() instanceof ITypedef);
assertEquals("string", ((ITypedef) s2.getType()).getName()); assertEquals("string", ((ITypedef) s2.getType()).getName());
ICPPVariable s3 = ba.assertNonProblem("s3", ICPPVariable.class);
assertTrue(s3.getType() instanceof ITypedef);
assertEquals("string", ((ITypedef) s3.getType()).getName());
}
// template <typename T>
// struct vector {
// typedef T* const_iterator;
// const_iterator begin() const;
// };
//
// void test(const vector<int>& v) {
// auto it = v.begin();
// }
public void testTypedefPreservation_380498_2() throws Exception {
BindingAssertionHelper ba= getAssertionHelper();
ICPPVariable it = ba.assertNonProblem("it =", "it", ICPPVariable.class);
assertTrue(it.getType() instanceof ITypedef);
assertEquals("vector<int>::const_iterator", ASTTypeUtil.getType(it.getType(), false));
} }
// int f() { // int f() {

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2004, 2011 IBM Corporation and others. * Copyright (c) 2004, 2012 IBM Corporation 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
@ -125,7 +125,7 @@ import org.eclipse.cdt.internal.core.model.ASTStringUtil;
import org.eclipse.cdt.internal.core.parser.ParserException; import org.eclipse.cdt.internal.core.parser.ParserException;
/** /**
* Testcases on the AST. * Test cases on the AST.
*/ */
public class AST2Tests extends AST2BaseTest { public class AST2Tests extends AST2BaseTest {
private static final int NUM_TESTS = 3; private static final int NUM_TESTS = 3;
@ -4866,10 +4866,9 @@ public class AST2Tests extends AST2BaseTest {
// myUnionPointer->bar=4; // myUnionPointer->bar=4;
// } // }
public void testBug228504_nonExistingMembers() throws Exception { public void testBug228504_nonExistingMembers() throws Exception {
boolean[] isCpps= {true, false}; for (ParserLanguage lang: ParserLanguage.values()) {
for (boolean isCpp : isCpps) { BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), lang);
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), isCpp); for (int i= 1; i < 5; i++) {
for (int i=1; i < 5; i++) {
ba.assertNonProblem("foo=" + i, 3); ba.assertNonProblem("foo=" + i, 3);
ba.assertProblem("bar=" + i, 3); ba.assertProblem("bar=" + i, 3);
} }
@ -4912,10 +4911,9 @@ public class AST2Tests extends AST2BaseTest {
// function1(); // ref // function1(); // ref
// } // }
public void testOutOfOrderResolution_Bug232300() throws Exception { public void testOutOfOrderResolution_Bug232300() throws Exception {
final boolean[] isCpps= {false, true};
String code= getAboveComment(); String code= getAboveComment();
for (boolean isCpp : isCpps) { for (ParserLanguage lang: ParserLanguage.values()) {
BindingAssertionHelper ba= new BindingAssertionHelper(code, isCpp); BindingAssertionHelper ba= new BindingAssertionHelper(code, lang);
IBinding b1= ba.assertNonProblem("function1(); // decl", 9); IBinding b1= ba.assertNonProblem("function1(); // decl", 9);
IBinding b2= ba.assertNonProblem("function1() {", 9); IBinding b2= ba.assertNonProblem("function1() {", 9);
IBinding b3= ba.assertNonProblem("function1(); // ref", 9); IBinding b3= ba.assertNonProblem("function1(); // ref", 9);
@ -4927,10 +4925,9 @@ public class AST2Tests extends AST2BaseTest {
// #define foo __typeof__((int*)0 - (int*)0) // #define foo __typeof__((int*)0 - (int*)0)
// typedef foo ptrdiff_t; // typedef foo ptrdiff_t;
public void testRedefinePtrdiff_Bug230895() throws Exception { public void testRedefinePtrdiff_Bug230895() throws Exception {
final boolean[] isCpps= {false, true};
String code= getAboveComment(); String code= getAboveComment();
for (boolean isCpp : isCpps) { for (ParserLanguage lang: ParserLanguage.values()) {
BindingAssertionHelper ba= new BindingAssertionHelper(code, isCpp); BindingAssertionHelper ba= new BindingAssertionHelper(code, lang);
IBinding b1= ba.assertNonProblem("ptrdiff_t", 9); IBinding b1= ba.assertNonProblem("ptrdiff_t", 9);
assertInstance(b1, ITypedef.class); assertInstance(b1, ITypedef.class);
ITypedef td= (ITypedef) b1; ITypedef td= (ITypedef) b1;
@ -4944,10 +4941,9 @@ public class AST2Tests extends AST2BaseTest {
// struct S; // struct S;
// typedef struct S S; // td // typedef struct S S; // td
public void testRedefineStructInScopeThatIsFullyResolved() throws Exception { public void testRedefineStructInScopeThatIsFullyResolved() throws Exception {
final boolean[] isCpps= {false, true};
String code= getAboveComment(); String code= getAboveComment();
for (boolean isCpp : isCpps) { for (ParserLanguage lang: ParserLanguage.values()) {
BindingAssertionHelper ba= new BindingAssertionHelper(code, isCpp); BindingAssertionHelper ba= new BindingAssertionHelper(code, lang);
ba.assertNonProblem("a; // ref", 1); ba.assertNonProblem("a; // ref", 1);
// now scope is fully resolved // now scope is fully resolved
ICompositeType ct= ba.assertNonProblem("S;", 1, ICompositeType.class); ICompositeType ct= ba.assertNonProblem("S;", 1, ICompositeType.class);
@ -4972,10 +4968,9 @@ public class AST2Tests extends AST2BaseTest {
// VOID func(VOID) { // VOID func(VOID) {
// } // }
public void testTypedefVoid_Bug221567() throws Exception { public void testTypedefVoid_Bug221567() throws Exception {
final boolean[] isCpps= { false, true };
String code= getAboveComment(); String code= getAboveComment();
for (boolean isCpp : isCpps) { for (ParserLanguage lang: ParserLanguage.values()) {
BindingAssertionHelper ba= new BindingAssertionHelper(code, isCpp); BindingAssertionHelper ba= new BindingAssertionHelper(code, lang);
ITypedef td= ba.assertNonProblem("VOID;", 4, ITypedef.class); ITypedef td= ba.assertNonProblem("VOID;", 4, ITypedef.class);
IBinding ref= ba.assertNonProblem("VOID)", 4); IBinding ref= ba.assertNonProblem("VOID)", 4);
assertSame(td, ref); assertSame(td, ref);
@ -5021,9 +5016,8 @@ public class AST2Tests extends AST2BaseTest {
// int f5(int *(tint[10])); // int f5(int *(tint[10]));
public void testParamWithFunctionType_Bug84242() throws Exception { public void testParamWithFunctionType_Bug84242() throws Exception {
final String comment= getAboveComment(); final String comment= getAboveComment();
final boolean[] isCpps= {false, true}; for (ParserLanguage lang: ParserLanguage.values()) {
for (boolean isCpp : isCpps) { BindingAssertionHelper ba= new BindingAssertionHelper(comment, lang);
BindingAssertionHelper ba= new BindingAssertionHelper(comment, isCpp);
IFunction f= ba.assertNonProblem("f1", 2, IFunction.class); IFunction f= ba.assertNonProblem("f1", 2, IFunction.class);
isTypeEqual(f.getType(), "int (int (*)(int))"); isTypeEqual(f.getType(), "int (int (*)(int))");
@ -5055,9 +5049,8 @@ public class AST2Tests extends AST2BaseTest {
// int (*f1 (int par))[5]; // int (*f1 (int par))[5];
public void testFunctionReturningPtrToArray_Bug216609() throws Exception { public void testFunctionReturningPtrToArray_Bug216609() throws Exception {
final String comment= getAboveComment(); final String comment= getAboveComment();
final boolean[] isCpps= {false, true}; for (ParserLanguage lang: ParserLanguage.values()) {
for (boolean isCpp : isCpps) { BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), lang);
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), isCpp);
IFunction f= ba.assertNonProblem("f1", 2, IFunction.class); IFunction f= ba.assertNonProblem("f1", 2, IFunction.class);
isTypeEqual(f.getType(), "int (* (int))[5]"); isTypeEqual(f.getType(), "int (* (int))[5]");
@ -5077,7 +5070,6 @@ public class AST2Tests extends AST2BaseTest {
// void ((f4)()); // void ((f4)());
public void testNestedFunctionDeclarators() throws Exception { public void testNestedFunctionDeclarators() throws Exception {
final String comment= getAboveComment(); final String comment= getAboveComment();
final boolean[] isCpps= {false, true};
for (ParserLanguage lang: ParserLanguage.values()) { for (ParserLanguage lang: ParserLanguage.values()) {
IASTTranslationUnit tu= parseAndCheckBindings(comment, lang); IASTTranslationUnit tu= parseAndCheckBindings(comment, lang);
IASTFunctionDefinition fdef= getDeclaration(tu, 0); IASTFunctionDefinition fdef= getDeclaration(tu, 0);
@ -5133,8 +5125,8 @@ public class AST2Tests extends AST2BaseTest {
public void testLocalVariableResolution_Bug235831() throws Exception { public void testLocalVariableResolution_Bug235831() throws Exception {
final String comment= getAboveComment(); final String comment= getAboveComment();
final boolean[] isCpps= {false, true}; final boolean[] isCpps= {false, true};
for (boolean isCpp : isCpps) { for (ParserLanguage lang: ParserLanguage.values()) {
BindingAssertionHelper ba= new BindingAssertionHelper(comment, isCpp); BindingAssertionHelper ba= new BindingAssertionHelper(comment, lang);
ba.assertNonProblem("b; a", 1, IVariable.class); // fill cache of inner block ba.assertNonProblem("b; a", 1, IVariable.class); // fill cache of inner block
IVariable v3= ba.assertNonProblem("a; }", 1, IVariable.class); IVariable v3= ba.assertNonProblem("a; }", 1, IVariable.class);
@ -5148,9 +5140,8 @@ public class AST2Tests extends AST2BaseTest {
// int foo(int (*ptr) (int, int)); // int foo(int (*ptr) (int, int));
public void testComplexParameterBinding_Bug214482() throws Exception { public void testComplexParameterBinding_Bug214482() throws Exception {
final String comment= getAboveComment(); final String comment= getAboveComment();
final boolean[] isCpps= {false, true}; for (ParserLanguage lang: ParserLanguage.values()) {
for (boolean isCpp : isCpps) { BindingAssertionHelper ba= new BindingAssertionHelper(comment, lang);
BindingAssertionHelper ba= new BindingAssertionHelper(comment, isCpp);
IParameter p= ba.assertNonProblem("ptr", 3, IParameter.class); IParameter p= ba.assertNonProblem("ptr", 3, IParameter.class);
assertEquals("ptr", p.getName()); assertEquals("ptr", p.getName());
} }
@ -5519,8 +5510,8 @@ public class AST2Tests extends AST2BaseTest {
// } // }
public void testAnonymousUnionMember() throws Exception { public void testAnonymousUnionMember() throws Exception {
final boolean[] isCpps= {false, true}; final boolean[] isCpps= {false, true};
for (boolean isCpp : isCpps) { for (ParserLanguage lang: ParserLanguage.values()) {
BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), isCpp); BindingAssertionHelper bh= new BindingAssertionHelper(getAboveComment(), lang);
bh.assertNonProblem("a1=", 2); bh.assertNonProblem("a1=", 2);
bh.assertProblem("a2=", 2); bh.assertProblem("a2=", 2);
bh.assertNonProblem("a3=", 2); bh.assertNonProblem("a3=", 2);
@ -5794,9 +5785,8 @@ public class AST2Tests extends AST2BaseTest {
// enum X {e0, e4=4, e5, e2=2, e3}; // enum X {e0, e4=4, e5, e2=2, e3};
public void testValues() throws Exception { public void testValues() throws Exception {
final String code= getAboveComment(); final String code= getAboveComment();
boolean isCpp= false; for (ParserLanguage lang: ParserLanguage.values()) {
do { BindingAssertionHelper bh= new BindingAssertionHelper(code, lang);
BindingAssertionHelper bh= new BindingAssertionHelper(code, false);
IVariable v= (IVariable) bh.assertNonProblem("a=", 1); IVariable v= (IVariable) bh.assertNonProblem("a=", 1);
checkValue(v.getInitialValue(), -4); checkValue(v.getInitialValue(), -4);
v= (IVariable) bh.assertNonProblem("b=", 1); v= (IVariable) bh.assertNonProblem("b=", 1);
@ -5814,8 +5804,7 @@ public class AST2Tests extends AST2BaseTest {
checkValue(e.getValue(), 4); checkValue(e.getValue(), 4);
e= (IEnumerator) bh.assertNonProblem("e5", 2); e= (IEnumerator) bh.assertNonProblem("e5", 2);
checkValue(e.getValue(), 5); checkValue(e.getValue(), 5);
isCpp= !isCpp; }
} while (isCpp);
} }
private void checkValue(IValue initialValue, int i) { private void checkValue(IValue initialValue, int i) {
@ -6088,11 +6077,10 @@ public class AST2Tests extends AST2BaseTest {
// size_t x = a + 5; // size_t x = a + 5;
// size_t y = 2 + a; // size_t y = 2 + a;
// size_t y = a * 2; // size_t y = a * 2;
public void testTypeOfExpressionWithTypedef_380498() throws Exception { public void testTypeOfExpressionWithTypedef_380498_1() throws Exception {
final boolean[] isCpps= { false, true };
String code= getAboveComment(); String code= getAboveComment();
for (boolean isCpp : isCpps) { for (ParserLanguage lang: ParserLanguage.values()) {
BindingAssertionHelper ba= new BindingAssertionHelper(code, isCpp); BindingAssertionHelper ba= new BindingAssertionHelper(code, lang);
IASTExpression exp = ba.assertNode("a + 5", IASTExpression.class); IASTExpression exp = ba.assertNode("a + 5", IASTExpression.class);
assertTrue(exp.getExpressionType() instanceof ITypedef); assertTrue(exp.getExpressionType() instanceof ITypedef);
assertEquals("size_t", ((ITypedef) exp.getExpressionType()).getName()); assertEquals("size_t", ((ITypedef) exp.getExpressionType()).getName());
@ -6105,6 +6093,21 @@ public class AST2Tests extends AST2BaseTest {
} }
} }
// typedef void* VoidPtr;
// typedef VoidPtr (*Func)();
//
// void test(Func f) {
// f();
// }
public void testTypeOfExpressionWithTypedef_380498_2() throws Exception {
String code= getAboveComment();
for (ParserLanguage lang: ParserLanguage.values()) {
BindingAssertionHelper ba= new BindingAssertionHelper(code, lang);
IASTExpression exp = ba.assertNode("f()", IASTExpression.class);
assertTrue(exp.getExpressionType() instanceof ITypedef);
assertEquals("VoidPtr", ((ITypedef) exp.getExpressionType()).getName());
}
}
// typedef int TInt; // typedef int TInt;
// int a= TInt; //ref // int a= TInt; //ref
public void testTypeAsExpressionIsProblem_261175() throws Exception { public void testTypeAsExpressionIsProblem_261175() throws Exception {

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2005, 2010 IBM Corporation and others. * Copyright (c) 2005, 2012 IBM Corporation 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
@ -8,6 +8,7 @@
* Contributors: * Contributors:
* Rational Software - initial implementation * Rational Software - initial implementation
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.core.dom.ast; package org.eclipse.cdt.core.dom.ast;
@ -350,7 +351,8 @@ public class ASTTypeUtil {
result.append(Keywords.ENUM); result.append(Keywords.ENUM);
result.append(SPACE); result.append(SPACE);
} }
appendCppName((ICPPBinding) type, normalize, normalize, result); boolean qualify = normalize || (type instanceof ITypedef && type instanceof ICPPSpecialization);
appendCppName((ICPPBinding) type, normalize, qualify, result);
} else if (type instanceof ICompositeType) { } else if (type instanceof ICompositeType) {
// 101114 fix, do not display class, and for consistency don't display struct/union as well // 101114 fix, do not display class, and for consistency don't display struct/union as well
appendNameCheckAnonymous((ICompositeType) type, result); appendNameCheckAnonymous((ICompositeType) type, result);
@ -469,13 +471,13 @@ public class ASTTypeUtil {
public static void appendType(IType type, boolean normalize, StringBuilder result) { public static void appendType(IType type, boolean normalize, StringBuilder result) {
IType[] types = new IType[DEAULT_ITYPE_SIZE]; IType[] types = new IType[DEAULT_ITYPE_SIZE];
// push all of the types onto the stack // Push all of the types onto the stack
int i = 0; int i = 0;
IQualifierType cvq= null; IQualifierType cvq= null;
ICPPReferenceType ref= null; ICPPReferenceType ref= null;
while (type != null && ++i < 100) { while (type != null && ++i < 100) {
if (type instanceof ITypedef) { if (type instanceof ITypedef) {
if (normalize || type instanceof ICPPSpecialization) { if (normalize) {
// Skip the typedef and proceed with its target type. // Skip the typedef and proceed with its target type.
} else { } else {
// Output reference, qualifier and typedef, then stop. // Output reference, qualifier and typedef, then stop.

View file

@ -9,14 +9,12 @@
* IBM Corp. - Rational Software - initial implementation * IBM Corp. - Rational Software - initial implementation
* Mike Kucera (IBM) - convert to Java 5 enum * Mike Kucera (IBM) - convert to Java 5 enum
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.core.parser; package org.eclipse.cdt.core.parser;
/** /**
* Enumeration of base languages supported by CDT. * Enumeration of base languages supported by CDT.
*/ */
public enum ParserLanguage { public enum ParserLanguage {
C { C {
@Override public boolean isCPP() { return false; } @Override public boolean isCPP() { return false; }
@Override public String toString() { return "C"; } //$NON-NLS-1$ @Override public String toString() { return "C"; } //$NON-NLS-1$
@ -28,5 +26,4 @@ public enum ParserLanguage {
}; };
public abstract boolean isCPP(); public abstract boolean isCPP();
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2009, 2010 Wind River Systems, Inc. and others. * Copyright (c) 2009, 2012 Wind River Systems, 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
@ -10,6 +10,8 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser; package org.eclipse.cdt.internal.core.dom.parser;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
@ -17,6 +19,7 @@ import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
/** /**
* Arithmetic conversions as required to compute the type of unary or binary expressions. * Arithmetic conversions as required to compute the type of unary or binary expressions.
@ -47,6 +50,8 @@ public abstract class ArithmeticConversion {
* or 5.0.9 of C++ standard * or 5.0.9 of C++ standard
*/ */
public final IType convertOperandTypes(int operator, IType op1, IType op2) { public final IType convertOperandTypes(int operator, IType op1, IType op2) {
op1 = SemanticUtil.getNestedType(op1, TDEF);
op2 = SemanticUtil.getNestedType(op2, TDEF);
if (!isArithmeticOrUnscopedEnum(op1) || !isArithmeticOrUnscopedEnum(op2)) { if (!isArithmeticOrUnscopedEnum(op1) || !isArithmeticOrUnscopedEnum(op2)) {
return null; return null;
} }

View file

@ -6,9 +6,9 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* John Camelon (IBM Rational Software) - Initial API and implementation * John Camelon (IBM Rational Software) - Initial API and implementation
* Yuan Zhang / Beth Tibbitts (IBM Research) * Yuan Zhang / Beth Tibbitts (IBM Research)
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.c; package org.eclipse.cdt.internal.core.dom.parser.c;
@ -29,9 +29,8 @@ import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
/** /**
* Function call expression in C. * Function call expression in C.
*/ */
public class CASTFunctionCallExpression extends ASTNode implements public class CASTFunctionCallExpression extends ASTNode
IASTFunctionCallExpression, IASTAmbiguityParent { implements IASTFunctionCallExpression, IASTAmbiguityParent {
private IASTExpression functionName; private IASTExpression functionName;
private IASTInitializerClause[] fArguments; private IASTInitializerClause[] fArguments;
@ -62,11 +61,7 @@ public class CASTFunctionCallExpression extends ASTNode implements
CASTFunctionCallExpression copy = new CASTFunctionCallExpression(null, args); CASTFunctionCallExpression copy = new CASTFunctionCallExpression(null, args);
copy.setFunctionNameExpression(functionName == null ? null : functionName.copy(style)); copy.setFunctionNameExpression(functionName == null ? null : functionName.copy(style));
copy.setOffsetAndLength(this); return copy(copy, style);
if (style == CopyStyle.withLocations) {
copy.setCopyLocation(this);
}
return copy;
} }
@Override @Override
@ -104,12 +99,12 @@ public class CASTFunctionCallExpression extends ASTNode implements
} }
@Override @Override
public boolean accept( ASTVisitor action ){ public boolean accept(ASTVisitor action) {
if( action.shouldVisitExpressions ){ if (action.shouldVisitExpressions) {
switch( action.visit( this ) ){ switch (action.visit(this)) {
case ASTVisitor.PROCESS_ABORT : return false; case ASTVisitor.PROCESS_ABORT: return false;
case ASTVisitor.PROCESS_SKIP : return true; case ASTVisitor.PROCESS_SKIP: return true;
default : break; default: break;
} }
} }

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2004, 2011 IBM Corporation and others. * Copyright (c) 2004, 2012 IBM Corporation 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
@ -203,7 +203,7 @@ public class CPPASTArraySubscriptExpression extends ASTNode
return ExpressionTypes.typeFromFunctionCall(op); return ExpressionTypes.typeFromFunctionCall(op);
} }
IType t1 = getArrayExpression().getExpressionType(); IType t1 = getArrayExpression().getExpressionType();
t1= Conversions.lvalue_to_rvalue(t1); t1= Conversions.lvalue_to_rvalue(t1, true);
if (t1 instanceof IPointerType) { if (t1 instanceof IPointerType) {
t1= ((IPointerType) t1).getType(); t1= ((IPointerType) t1).getType();
return glvalueType(t1); return glvalueType(t1);
@ -212,7 +212,7 @@ public class CPPASTArraySubscriptExpression extends ASTNode
IType t2= null; IType t2= null;
IASTInitializerClause arg = getArgument(); IASTInitializerClause arg = getArgument();
if (arg instanceof IASTExpression) { if (arg instanceof IASTExpression) {
t2= Conversions.lvalue_to_rvalue(t2); t2= Conversions.lvalue_to_rvalue(t2, true);
if (t2 instanceof IPointerType) { if (t2 instanceof IPointerType) {
t2= ((IPointerType) t2).getType(); t2= ((IPointerType) t2).getType();
return glvalueType(t2); return glvalueType(t2);

View file

@ -20,6 +20,7 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionT
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.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.typeFromFunctionCall;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromFunctionCall; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromFunctionCall;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
@ -41,6 +42,7 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
import org.eclipse.cdt.internal.core.dom.parser.ProblemType; 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.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpression, IASTAmbiguityParent { public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpression, IASTAmbiguityParent {
private int op; private int op;
@ -356,20 +358,20 @@ public class CPPASTBinaryExpression extends ASTNode implements ICPPASTBinaryExpr
return CPPBasicType.BOOLEAN; return CPPBasicType.BOOLEAN;
case IASTBinaryExpression.op_plus: case IASTBinaryExpression.op_plus:
if (type1 instanceof IPointerType) { if (SemanticUtil.getNestedType(type1, TDEF) instanceof IPointerType) {
return restoreTypedefs(type1, originalType1); return type1;
} }
if (type2 instanceof IPointerType) { if (SemanticUtil.getNestedType(type2, TDEF) instanceof IPointerType) {
return restoreTypedefs(type2, originalType2); return type2;
} }
break; break;
case IASTBinaryExpression.op_minus: case IASTBinaryExpression.op_minus:
if (type1 instanceof IPointerType) { if (SemanticUtil.getNestedType(type1, TDEF) instanceof IPointerType) {
if (type2 instanceof IPointerType) { if (SemanticUtil.getNestedType(type2, TDEF) instanceof IPointerType) {
return CPPVisitor.getPointerDiffType(this); return CPPVisitor.getPointerDiffType(this);
} }
return restoreTypedefs(type1, originalType1); return type1;
} }
break; break;

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2004, 2011 IBM Corporation and others. * Copyright (c) 2004, 2012 IBM Corporation 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
@ -222,9 +222,9 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
// Void types: Either both are void or one is a throw expression. // Void types: Either both are void or one is a throw expression.
if (void2 || void3) { if (void2 || void3) {
if (isThrowExpression(expr2)) { if (isThrowExpression(expr2)) {
fType= Conversions.lvalue_to_rvalue(t3); fType= Conversions.lvalue_to_rvalue(t3, false);
} else if (isThrowExpression(expr3)) { } else if (isThrowExpression(expr3)) {
fType= Conversions.lvalue_to_rvalue(t2); fType= Conversions.lvalue_to_rvalue(t2, false);
} else if (void2 && void3) { } else if (void2 && void3) {
fType= uqt2; fType= uqt2;
} else { } else {
@ -293,8 +293,8 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
} }
// 5.16-6 // 5.16-6
t2= Conversions.lvalue_to_rvalue(t2); t2= Conversions.lvalue_to_rvalue(t2, false);
t3= Conversions.lvalue_to_rvalue(t3); t3= Conversions.lvalue_to_rvalue(t3, false);
if (t2.isSameType(t3)) { if (t2.isSameType(t3)) {
fType= t2; fType= t2;
} else { } else {
@ -353,7 +353,7 @@ public class CPPASTConditionalExpression extends ASTNode implements IASTConditio
} }
// Unrelated class types or just one class: // Unrelated class types or just one class:
if (vcat2 != PRVALUE) { if (vcat2 != PRVALUE) {
t2= Conversions.lvalue_to_rvalue(t2); t2= Conversions.lvalue_to_rvalue(t2, false);
} }
Cost c= Conversions.checkImplicitConversionSequence(t2, t1, vcat1, UDCMode.ALLOWED, Context.ORDINARY); Cost c= Conversions.checkImplicitConversionSequence(t2, t1, vcat1, UDCMode.ALLOWED, Context.ORDINARY);
if (c.converts()) { if (c.converts()) {

View file

@ -17,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.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.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.prvalueType;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.prvalueTypeWithResolvedTypedefs;
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.typeFromFunctionCall;
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.ALLCVQ;
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.CVTYPE;
@ -386,7 +387,7 @@ public class CPPASTFieldReference extends ASTNode
type= SemanticUtil.mapToAST(type, owner); type= SemanticUtil.mapToAST(type, owner);
} }
IType prValue= prvalueType(type); IType prValue= prvalueTypeWithResolvedTypedefs(type);
if (prValue instanceof IPointerType) { if (prValue instanceof IPointerType) {
return glvalueType(((IPointerType) prValue).getType()); return glvalueType(((IPointerType) prValue).getType());
} }

View file

@ -17,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.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.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.prvalueType;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.prvalueTypeWithResolvedTypedefs;
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.typeFromFunctionCall;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromFunctionCall; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.valueCategoryFromFunctionCall;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateTypeUptoPointers; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateTypeUptoPointers;
@ -254,7 +255,7 @@ public class CPPASTUnaryExpression extends ASTNode implements ICPPASTUnaryExpres
if (op == op_star) { if (op == op_star) {
IType type= operand.getExpressionType(); IType type= operand.getExpressionType();
type = prvalueType(type); type = prvalueTypeWithResolvedTypedefs(type);
if (type instanceof IPointerType) { if (type instanceof IPointerType) {
type= ((ITypeContainer) type).getType(); type= ((ITypeContainer) type).getType();
return glvalueType(type); return glvalueType(type);

View file

@ -152,7 +152,7 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP
IASTExpression expr= rtstmt.getReturnValue(); IASTExpression expr= rtstmt.getReturnValue();
if (expr != null) { if (expr != null) {
IType type= expr.getExpressionType(); IType type= expr.getExpressionType();
type= Conversions.lvalue_to_rvalue(type); type= Conversions.lvalue_to_rvalue(type, false);
if (type != null) { if (type != null) {
return type; return type;
} }

View file

@ -253,14 +253,19 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
@Override @Override
public ICPPFunctionType getType() { public ICPPFunctionType getType() {
if (type == null) { if (type == null) {
final IType t = getNestedType(CPPVisitor.createType((definition != null) ? definition : declarations[0]), TDEF); IType t = CPPVisitor.createType((definition != null) ? definition : declarations[0]);
if (t instanceof ICPPFunctionType) { if (t instanceof ICPPFunctionType) {
type = (ICPPFunctionType) t; type = (ICPPFunctionType) t;
} else if (t instanceof ISemanticProblem){
type= new ProblemFunctionType(((ISemanticProblem) t).getID());
} else { } else {
// This case is unexpected t = getNestedType(t, TDEF);
type = new ProblemFunctionType(ISemanticProblem.TYPE_UNRESOLVED_NAME); if (t instanceof ICPPFunctionType) {
type = (ICPPFunctionType) t;
} else if (t instanceof ISemanticProblem){
type= new ProblemFunctionType(((ISemanticProblem) t).getID());
} else {
// This case is unexpected
type = new ProblemFunctionType(ISemanticProblem.TYPE_UNRESOLVED_NAME);
}
} }
} }
return type; return type;

View file

@ -1155,7 +1155,7 @@ public class Conversions {
/** /**
* 4.1, 4.2, 4.3 * 4.1, 4.2, 4.3
*/ */
public static IType lvalue_to_rvalue(IType type) { public static IType lvalue_to_rvalue(IType type, boolean resolveTypedefs) {
IType t= SemanticUtil.getNestedType(type, TDEF | REF); IType t= SemanticUtil.getNestedType(type, TDEF | REF);
if (t instanceof IArrayType) { if (t instanceof IArrayType) {
return new CPPPointerType(((IArrayType) t).getType()); return new CPPPointerType(((IArrayType) t).getType());
@ -1165,9 +1165,9 @@ public class Conversions {
} }
IType uqType= SemanticUtil.getNestedType(t, TDEF | REF | ALLCVQ); IType uqType= SemanticUtil.getNestedType(t, TDEF | REF | ALLCVQ);
if (uqType instanceof ICPPClassType) { if (uqType instanceof ICPPClassType) {
return SemanticUtil.getNestedType(type, COND_TDEF | REF); return resolveTypedefs ? t : SemanticUtil.getNestedType(type, COND_TDEF | REF);
} }
return SemanticUtil.getNestedType(t, COND_TDEF | REF | ALLCVQ); return resolveTypedefs ? uqType : SemanticUtil.getNestedType(type, COND_TDEF | REF | ALLCVQ);
} }
/** /**

View file

@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2010 Wind River Systems, Inc. and others. * Copyright (c) 2010, 2012 Wind River Systems, 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
@ -39,7 +39,11 @@ public class ExpressionTypes {
} }
public static IType prvalueType(IType type) { public static IType prvalueType(IType type) {
return Conversions.lvalue_to_rvalue(type); return Conversions.lvalue_to_rvalue(type, false);
}
public static IType prvalueTypeWithResolvedTypedefs(IType type) {
return Conversions.lvalue_to_rvalue(type, true);
} }
public static ValueCategory valueCategoryFromFunctionCall(ICPPFunction function) { public static ValueCategory valueCategoryFromFunctionCall(ICPPFunction function) {

View file

@ -235,7 +235,7 @@ public class SemanticUtil {
final boolean ptr= (options & PTR) != 0; final boolean ptr= (options & PTR) != 0;
final boolean mptr= (options & MPTR) != 0; final boolean mptr= (options & MPTR) != 0;
final boolean allcvq= (options & ALLCVQ) != 0; final boolean allcvq= (options & ALLCVQ) != 0;
final boolean cvtype = (options & CVTYPE) != 0; final boolean cvtype= (options & CVTYPE) != 0;
IType beforeTypedefs = null; IType beforeTypedefs = null;
@ -249,10 +249,10 @@ public class SemanticUtil {
t= ((ITypedef) type).getType(); t= ((ITypedef) type).getType();
} }
} else if (type instanceof IPointerType) { } else if (type instanceof IPointerType) {
beforeTypedefs = null;
final boolean isMbrPtr = type instanceof ICPPPointerToMemberType; final boolean isMbrPtr = type instanceof ICPPPointerToMemberType;
if ((ptr && !isMbrPtr) || (mptr && isMbrPtr)) { if ((ptr && !isMbrPtr) || (mptr && isMbrPtr)) {
t= ((IPointerType) type).getType(); t= ((IPointerType) type).getType();
beforeTypedefs = null;
} else if (allcvq) { } else if (allcvq) {
IPointerType pt= (IPointerType) type; IPointerType pt= (IPointerType) type;
if (pt.isConst() || pt.isVolatile() || pt.isRestrict()) { if (pt.isConst() || pt.isVolatile() || pt.isRestrict()) {
@ -263,14 +263,13 @@ public class SemanticUtil {
return new CPPPointerType(pt.getType(), false, false, false); return new CPPPointerType(pt.getType(), false, false, false);
} }
} }
return pt;
} }
} else if (type instanceof IQualifierType) { } else if (type instanceof IQualifierType) {
beforeTypedefs = null;
final IQualifierType qt = (IQualifierType) type; final IQualifierType qt = (IQualifierType) type;
final IType qttgt = qt.getType(); final IType qttgt = qt.getType();
if (allcvq || cvtype) { if (allcvq || cvtype) {
t= qttgt; t= qttgt;
beforeTypedefs = null;
} else if (tdef || cond_tdef) { } else if (tdef || cond_tdef) {
t= getNestedType(qttgt, options); t= getNestedType(qttgt, options);
if (t == qttgt) if (t == qttgt)
@ -278,10 +277,10 @@ public class SemanticUtil {
return addQualifiers(t, qt.isConst(), qt.isVolatile(), false); return addQualifiers(t, qt.isConst(), qt.isVolatile(), false);
} }
} else if (type instanceof IArrayType) { } else if (type instanceof IArrayType) {
beforeTypedefs = null;
final IArrayType atype= (IArrayType) type; final IArrayType atype= (IArrayType) type;
if ((options & ARRAY) != 0) { if ((options & ARRAY) != 0) {
t= atype.getType(); t= atype.getType();
beforeTypedefs = null;
} else if (allcvq) { } else if (allcvq) {
IType nested= atype.getType(); IType nested= atype.getType();
IType newNested= getNestedType(nested, ALLCVQ); IType newNested= getNestedType(nested, ALLCVQ);
@ -290,10 +289,10 @@ public class SemanticUtil {
return replaceNestedType((ITypeContainer) atype, newNested); return replaceNestedType((ITypeContainer) atype, newNested);
} }
} else if (type instanceof ICPPReferenceType) { } else if (type instanceof ICPPReferenceType) {
beforeTypedefs = null;
final ICPPReferenceType rt = (ICPPReferenceType) type; final ICPPReferenceType rt = (ICPPReferenceType) type;
if ((options & REF) != 0) { if ((options & REF) != 0) {
t= rt.getType(); t= rt.getType();
beforeTypedefs = null;
} else if (tdef) { } 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 nested= rt.getType();
@ -404,9 +403,20 @@ public class SemanticUtil {
typedefType = getNestedType(typedefType, REF | ALLCVQ | PTR | ARRAY); typedefType = getNestedType(typedefType, REF | ALLCVQ | PTR | ARRAY);
if (!(typedefType instanceof ITypedef)) if (!(typedefType instanceof ITypedef))
return null; return null;
IType nestedType = getNestedType(type, REF | ALLCVQ | PTR | ARRAY); IType nestedType = type;
if (!nestedType.isSameType(((ITypedef) typedefType).getType())) while (!nestedType.isSameType(((ITypedef) typedefType).getType())) {
return null; if (nestedType instanceof IQualifierType) {
nestedType = ((IQualifierType) nestedType).getType();
} else if (nestedType instanceof IPointerType) {
nestedType = ((IPointerType) nestedType).getType();
} else if (nestedType instanceof IArrayType) {
nestedType = ((IArrayType) nestedType).getType();
} else if (nestedType instanceof ICPPReferenceType) {
nestedType = ((ICPPReferenceType) nestedType).getType();
} else {
return null;
}
}
IType result = null; IType result = null;
ITypeContainer containerType = null; ITypeContainer containerType = null;

View file

@ -1329,7 +1329,7 @@ public class CompletionTests extends AbstractContentAssistTest {
// v.push_back(/*cursor*/); // v.push_back(/*cursor*/);
// } // }
public void testTypedefSpecialization_Bug307818() throws Exception { public void testTypedefSpecialization_Bug307818() throws Exception {
final String[] expected= { "push_back(const int & value) : void" }; final String[] expected= { "push_back(const vector<int>::value_type & value) : void" };
assertParameterHint(expected); assertParameterHint(expected);
} }