1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-09 01:05:38 +02:00

Bug 297457: Instantiation of std::endl.

This commit is contained in:
Markus Schorn 2010-09-16 12:52:19 +00:00
parent 83aed16ff8
commit baee7308fe
5 changed files with 70 additions and 14 deletions

View file

@ -26,8 +26,10 @@ import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement; import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
import org.eclipse.cdt.core.dom.ast.IASTProblemStatement; import org.eclipse.cdt.core.dom.ast.IASTProblemStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IASTTypeId;
@ -5116,4 +5118,26 @@ public class AST2TemplateTests extends AST2BaseTest {
final String code= getAboveComment(); final String code= getAboveComment();
parseAndCheckBindings(code); parseAndCheckBindings(code);
} }
// template<typename _CharT> struct OutStream {
// OutStream& operator<<(OutStream& (*__pf)(OutStream&));
// };
// template<typename _CharT> OutStream<_CharT>& endl(OutStream<_CharT>& __os);
//
// void test() {
// OutStream<char> out;
// out << endl;
// }
public void testInstantiationOfEndl_297457() throws Exception {
final String code= getAboveComment();
IASTTranslationUnit tu= parseAndCheckBindings(code);
final IASTNodeSelector nodeSelector = tu.getNodeSelector(null);
IASTName methodName= nodeSelector.findEnclosingName(code.indexOf("operator<<"), 1);
IASTImplicitName name = nodeSelector.findImplicitName(code.indexOf("<< endl"), 2);
final IBinding method = methodName.resolveBinding();
final IBinding reference = name.resolveBinding();
assertSame(method, ((ICPPSpecialization) reference).getSpecializedBinding());
}
} }

View file

@ -18,6 +18,7 @@ import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager; import org.eclipse.cdt.core.dom.IPDOMManager;
import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IFunctionType;
@ -81,7 +82,13 @@ public abstract class IndexBindingResolutionTestBase extends BaseTestCase {
protected IASTName findName(String section, int len) { protected IASTName findName(String section, int len) {
IASTTranslationUnit ast = strategy.getAst(); IASTTranslationUnit ast = strategy.getAst();
return ast.getNodeSelector(null).findName(strategy.getTestData()[1].indexOf(section), len); final IASTNodeSelector nodeSelector = ast.getNodeSelector(null);
final int offset = strategy.getTestData()[1].indexOf(section);
IASTName name= nodeSelector.findName(offset, len);
if (name == null)
name= nodeSelector.findImplicitName(offset, len);
return name;
} }
/** /**

View file

@ -1780,4 +1780,19 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
inst = getBindingFromASTName("g(1)", 1); inst = getBindingFromASTName("g(1)", 1);
assertTrue(inst.isExplicitSpecialization()); assertTrue(inst.isExplicitSpecialization());
} }
// template<typename _CharT> struct OutStream {
// OutStream& operator<<(OutStream& (*__pf)(OutStream&));
// };
// template<typename _CharT> OutStream<_CharT>& endl(OutStream<_CharT>& __os);
// void test() {
// OutStream<char> out;
// out << endl;
// }
public void testInstantiationOfEndl_297457() throws Exception {
final IBinding reference = getBindingFromASTName("<< endl", 2);
assertTrue(reference instanceof ICPPSpecialization);
}
} }

View file

@ -1906,7 +1906,7 @@ public class CPPSemantics {
if (type == null) { if (type == null) {
type = temp; type = temp;
} else if (!type.equals(temp)) { } else if (!type.equals(temp)) {
int c = compareByRelevance(data, type, temp); int c = compareByRelevance(data.tu, type, temp);
if (c < 0) { if (c < 0) {
type= temp; type= temp;
} else if (c == 0) { } else if (c == 0) {
@ -1927,7 +1927,7 @@ public class CPPSemantics {
} else if (obj == temp) { } else if (obj == temp) {
// Ok, delegates are synonyms. // Ok, delegates are synonyms.
} else { } else {
int c = compareByRelevance(data, obj, temp); int c = compareByRelevance(data.tu, obj, temp);
if (c < 0) { if (c < 0) {
obj= temp; obj= temp;
} else if (c == 0) { } else if (c == 0) {
@ -1966,7 +1966,7 @@ public class CPPSemantics {
if (obj != null && type != null) { if (obj != null && type != null) {
if (obj instanceof ICPPNamespace) { if (obj instanceof ICPPNamespace) {
if (compareByRelevance(data, type, obj) >= 0) { if (compareByRelevance(data.tu, type, obj) >= 0) {
obj= null; obj= null;
} }
} else if (!data.typesOnly && overrulesByRelevance(data, type, obj)) { } else if (!data.typesOnly && overrulesByRelevance(data, type, obj)) {
@ -2019,16 +2019,16 @@ public class CPPSemantics {
* the two bindings have the same relevance; -1 if <code>b1</code> is less relevant than * the two bindings have the same relevance; -1 if <code>b1</code> is less relevant than
* <code>b2</code>. * <code>b2</code>.
*/ */
static int compareByRelevance(LookupData data, IBinding b1, IBinding b2) { static int compareByRelevance(IASTTranslationUnit tu, IBinding b1, IBinding b2) {
boolean b1FromIndex= isFromIndex(b1); boolean b1FromIndex= isFromIndex(b1);
boolean b2FromIndex= isFromIndex(b2); boolean b2FromIndex= isFromIndex(b2);
if (b1FromIndex != b2FromIndex) { if (b1FromIndex != b2FromIndex) {
return !b1FromIndex ? 1 : -1; return !b1FromIndex ? 1 : -1;
} else if (b1FromIndex) { } else if (b1FromIndex) {
// Both are from index. // Both are from index.
if (data != null && data.tu != null) { if (tu != null) {
boolean b1Reachable= isReachableFromAst(data.tu, b1); boolean b1Reachable= isReachableFromAst(tu, b1);
boolean b2Reachable= isReachableFromAst(data.tu, b2); boolean b2Reachable= isReachableFromAst(tu, b2);
if (b1Reachable != b2Reachable) { if (b1Reachable != b2Reachable) {
return b1Reachable ? 1 : -1; return b1Reachable ? 1 : -1;
} }
@ -2357,7 +2357,7 @@ public class CPPSemantics {
potentialCosts.add(fnCost); potentialCosts.add(fnCost);
continue; continue;
} }
int cmp= fnCost.compareTo(data, bestFnCost); int cmp= fnCost.compareTo(data.tu, bestFnCost);
if (cmp < 0) { if (cmp < 0) {
bestFnCost= fnCost; bestFnCost= fnCost;
ambiguousFunctions= null; ambiguousFunctions= null;
@ -2369,7 +2369,7 @@ public class CPPSemantics {
if (potentialCosts != null) { if (potentialCosts != null) {
for (FunctionCost fnCost : potentialCosts) { for (FunctionCost fnCost : potentialCosts) {
if (!fnCost.mustBeWorse(bestFnCost) && fnCost.performUDC()) { if (!fnCost.mustBeWorse(bestFnCost) && fnCost.performUDC()) {
int cmp= fnCost.compareTo(data, bestFnCost); int cmp= fnCost.compareTo(data.tu, bestFnCost);
if (cmp < 0) { if (cmp < 0) {
bestFnCost= fnCost; bestFnCost= fnCost;
ambiguousFunctions= null; ambiguousFunctions= null;
@ -2765,6 +2765,8 @@ public class CPPSemantics {
// Second pass, consider templates // Second pass, consider templates
ICPPFunction result= null; ICPPFunction result= null;
ICPPFunctionTemplate resultTemplate= null; ICPPFunctionTemplate resultTemplate= null;
boolean isAmbiguous= false;
final IASTTranslationUnit tu= name.getTranslationUnit();
for (IFunction fn : fns) { for (IFunction fn : fns) {
try { try {
if (fn instanceof ICPPFunctionTemplate) { if (fn instanceof ICPPFunctionTemplate) {
@ -2775,9 +2777,13 @@ public class CPPSemantics {
if (result != null) { if (result != null) {
cmp= CPPTemplates.orderTemplateFunctions(resultTemplate, template); cmp= CPPTemplates.orderTemplateFunctions(resultTemplate, template);
if (cmp == 0) if (cmp == 0)
return null; cmp= compareByRelevance(tu, resultTemplate, template);
} }
if (cmp == 0)
isAmbiguous= true;
if (cmp < 0) { if (cmp < 0) {
isAmbiguous= false;
resultTemplate= template; resultTemplate= template;
result= inst; result= inst;
} }
@ -2786,6 +2792,9 @@ public class CPPSemantics {
} catch (DOMException e) { } catch (DOMException e) {
} }
} }
if (isAmbiguous)
return null;
return result; return result;
} }

View file

@ -14,6 +14,7 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti
import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
@ -115,7 +116,7 @@ class FunctionCost {
/** /**
* Compares this function call cost to another one. * Compares this function call cost to another one.
*/ */
public int compareTo(LookupData data, FunctionCost other) throws DOMException { public int compareTo(IASTTranslationUnit tu, FunctionCost other) throws DOMException {
if (other == null) if (other == null)
return -1; return -1;
@ -163,7 +164,7 @@ class FunctionCost {
// if we are ambiguous at this point prefer non-index bindings // if we are ambiguous at this point prefer non-index bindings
if (haveBetter == haveWorse) { if (haveBetter == haveWorse) {
return -CPPSemantics.compareByRelevance(data, getFunction(), other.getFunction()); return -CPPSemantics.compareByRelevance(tu, getFunction(), other.getFunction());
} }
if (haveBetter) if (haveBetter)