diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 6dd6e1d89c7..46667e57dd4 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -14,6 +14,9 @@ *******************************************************************************/ package org.eclipse.cdt.core.parser.tests.ast2; +import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE; +import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.XVALUE; + import java.io.BufferedReader; import java.io.StringReader; import java.util.Arrays; @@ -8135,11 +8138,13 @@ public class AST2CPPTests extends AST2BaseTest { // struct S { // S(std::initializer_list) {} // S(std::initializer_list) {} + // S() {} // }; // void fs(S){} // void tests() { // fs({1,2,3}); // fs({1.0,2.0,3.0}); + // fs({}); // } public void testListInitialization_302412a() throws Exception { String code= getAboveComment(); @@ -8956,4 +8961,102 @@ public class AST2CPPTests extends AST2BaseTest { ref= bh.assertNonProblem("g(\"abc\")", 1); assertSame(g, ref); } + + // struct A { + // int m; + // }; + // A&& operator+(A, A); + // A&& f(); + // A a; + // A&& ar = static_cast(a); + // void test() { + // f(); // xvalue + // f().m; // xvalue + // static_cast(a); // xvalue + // a+a; // xvalue + // ar; // rvalue + // } + public void testXValueCategories() throws Exception { + String code= getAboveComment(); + IASTTranslationUnit tu= parseAndCheckBindings(code); + ICPPASTFunctionDefinition fdef= getDeclaration(tu, 5); + IASTExpression expr; + + expr= getExpressionOfStatement(fdef, 0); + assertEquals(XVALUE, expr.getValueCategory()); + assertEquals("A", ASTTypeUtil.getType(expr.getExpressionType())); + + expr= getExpressionOfStatement(fdef, 1); + assertEquals(XVALUE, expr.getValueCategory()); + assertEquals("int", ASTTypeUtil.getType(expr.getExpressionType())); + + expr= getExpressionOfStatement(fdef, 2); + assertEquals(XVALUE, expr.getValueCategory()); + assertEquals("A", ASTTypeUtil.getType(expr.getExpressionType())); + + expr= getExpressionOfStatement(fdef, 3); + assertEquals(XVALUE, expr.getValueCategory()); + assertEquals("A", ASTTypeUtil.getType(expr.getExpressionType())); + + // ar; + expr= getExpressionOfStatement(fdef, 4); + assertEquals(LVALUE, expr.getValueCategory()); + assertEquals("A", ASTTypeUtil.getType(expr.getExpressionType())); + } + + // void f() { + // int i; + // int f1(); + // int&& f2(); + // int g(const int&); + // int g(const int&&); + // int j = g(i); // calls g(const int&) + // int k = g(f1()); // calls g(const int&&) + // int l = g(f2()); // calls g(const int&&) + // } + public void testRankingOfReferenceBindings() throws Exception { + String code= getAboveComment(); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + IFunction g1= bh.assertNonProblem("g(const int&)", 1); + IFunction g2= bh.assertNonProblem("g(const int&&)", 1); + + IFunction ref; + ref= bh.assertNonProblem("g(i);", 1); + assertSame(g1, ref); + ref= bh.assertNonProblem("g(f1());", 1); + assertSame(g2, ref); + ref= bh.assertNonProblem("g(f2());", 1); + assertSame(g2, ref); + } + + // namespace std { + // template class initializer_list; + // } + // struct S { + // S(std::initializer_list); // #1 + // S(std::initializer_list); // #2 + // S(); // #3 + // }; + // S s1 = { 1.0, 2.0, 3.0 }; // invoke #1 + // S s2 = { 1, 2, 3 }; // invoke #2 + // S s3 = { }; // invoke #3 + public void testEmptyInitializerList_324096() throws Exception { + String code= getAboveComment(); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + IFunction ctor1= bh.assertNonProblem("S(std::initializer_list);", 1); + IFunction ctor2= bh.assertNonProblem("S(std::initializer_list);", 1); + IFunction ctor3= bh.assertNonProblem("S();", 1); + + IASTName name; + IASTImplicitNameOwner dtor; + name= bh.findName("s1", 2); + dtor= (IASTImplicitNameOwner) name.getParent(); + assertSame(ctor1, dtor.getImplicitNames()[0].resolveBinding()); + name= bh.findName("s2", 2); + dtor= (IASTImplicitNameOwner) name.getParent(); + assertSame(ctor2, dtor.getImplicitNames()[0].resolveBinding()); + name= bh.findName("s3", 2); + dtor= (IASTImplicitNameOwner) name.getParent(); + assertSame(ctor3, dtor.getImplicitNames()[0].resolveBinding()); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index 612e05249cf..7f05a317815 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -1758,13 +1758,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { return funcDefinition; } - protected abstract IASTInitializer optionalInitializer(DeclarationOptions options) + protected abstract IASTInitializer optionalInitializer(IASTDeclarator dtor, DeclarationOptions options) throws EndOfFileException, BacktrackException; protected IASTDeclarator addInitializer(FoundAggregateInitializer e, DeclarationOptions options) throws EndOfFileException, BacktrackException { final IASTDeclarator d = e.fDeclarator; - IASTInitializer i = optionalInitializer(options); + IASTInitializer i = optionalInitializer(d, options); if (i != null) { d.setInitializer(i); ((ASTNode) d).setLength(calculateEndOffset(i) - ((ASTNode) d).getOffset()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java index 75303b006be..39830109248 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java @@ -134,7 +134,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { } @Override - protected IASTInitializer optionalInitializer(DeclarationOptions options) throws EndOfFileException, BacktrackException { + protected IASTInitializer optionalInitializer(IASTDeclarator dtor, DeclarationOptions options) throws EndOfFileException, BacktrackException { if (LTcatchEOF(1) == IToken.tASSIGN) { final int offset= consume().getOffset(); IASTInitializerClause initClause = initClause(false); @@ -1315,7 +1315,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { if (lt1 == IToken.tASSIGN && LT(2) == IToken.tLBRACE) throw new FoundAggregateInitializer(declspec, d); - IASTInitializer i = optionalInitializer(option); + IASTInitializer i = optionalInitializer(d, option); if (i != null) { d.setInitializer(i); ((ASTNode) d).setLength(calculateEndOffset(i) - ((ASTNode) d).getOffset()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index 76cf9fca855..bbb18d56e8f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -2975,7 +2975,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (LTcatchEOF(1) == IToken.tASSIGN && LTcatchEOF(2) == IToken.tLBRACE) throw new FoundAggregateInitializer(declspec, dtor); - IASTInitializer initializer= optionalInitializer(option); + IASTInitializer initializer= optionalInitializer(dtor, option); if (initializer != null) { if (initializer instanceof IASTInitializerList && ((IASTInitializerList) initializer).getSize() == 0) { @@ -3009,7 +3009,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { * braced-init-list */ @Override - protected IASTInitializer optionalInitializer(DeclarationOptions option) throws EndOfFileException, BacktrackException { + protected IASTInitializer optionalInitializer(IASTDeclarator dtor, DeclarationOptions option) throws EndOfFileException, BacktrackException { final int lt1= LTcatchEOF(1); // = initializer-clause @@ -3020,7 +3020,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return null; int offset= consume().getOffset(); - IASTInitializerClause initClause = initClause(LT(1) == IToken.tLBRACE); + final boolean allowSkipping = LT(1) == IToken.tLBRACE && specifiesArray(dtor); + IASTInitializerClause initClause = initClause(allowSkipping); IASTEqualsInitializer initExpr= nodeFactory.newEqualsInitializer(initClause); return setRange(initExpr, offset, calculateEndOffset(initClause)); } @@ -3037,6 +3038,11 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return null; } + private boolean specifiesArray(IASTDeclarator dtor) { + dtor = ASTQueries.findTypeRelevantDeclarator(dtor); + return dtor instanceof IASTArrayDeclarator; + } + private IASTInitializer bracedOrCtorStyleInitializer() throws EndOfFileException, BacktrackException { final int lt1= LT(1); if (lt1 == IToken.tLPAREN) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index d0dc8387057..1a76bac985f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -2970,7 +2970,7 @@ public class CPPSemantics { sourceType= new InitializerListType((ICPPASTInitializerList) initClause); } if (sourceType != null) { - Cost c= Conversions.copyInitializationOfClass(isLValue, sourceType, classType, false); + Cost c= Conversions.checkImplicitConversionSequence(type, sourceType, isLValue, UDCMode.ALLOWED, Context.ORDINARY); if (c.converts()) { IFunction f= c.getUserDefinedConversion(); if (f instanceof ICPPConstructor) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java index 8b38746480d..9746aee7388 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java @@ -571,7 +571,14 @@ public class Conversions { final ICPPConstructor[] constructors = t.getConstructors(); ICPPConstructor[] ctors= constructors; for (ICPPConstructor ctor : ctors) { - if (ctor.getRequiredArgumentCount() <= 1) { + final int minArgCount = ctor.getRequiredArgumentCount(); + if (minArgCount == 0) { + if (arg.getExpressionTypes().length == 0) { + Cost c= new Cost(arg, t, Rank.IDENTITY); + c.setUserDefinedConversion(ctor); + return c; + } + } else if (minArgCount <= 1) { IType[] parTypes= ctor.getType().getParameterTypes(); if (parTypes.length > 0) { final IType target = parTypes[0];