diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index dd8987d31eb..62aada47826 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -8736,6 +8736,29 @@ public class AST2TemplateTests extends AST2TestBase { parseAndCheckBindings(); } + // template + // struct enable_if {}; + // + // template + // struct enable_if { + // typedef T type; + // }; + // + // template + // struct A { + // constexpr operator int() const { return false; } + // }; + // + // template + // typename enable_if()>::type waldo(T a); + // + // void test() { + // waldo(0); + // } + public void testDependentConversionOperator_486149() throws Exception { + parseAndCheckBindings(); + } + // template // struct C { // friend bool operator==(C, C); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java index 47aede2b0b6..4286925fa78 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/GCCBuiltinSymbolProvider.java @@ -473,7 +473,7 @@ public class GCCBuiltinSymbolProvider implements IBuiltinBindingsProvider { IBinding b = fCpp ? new CPPImplicitFunction(toCharArray(name), fScope, (ICPPFunctionType) ft, - (ICPPParameter[]) theParms, varargs) : + (ICPPParameter[]) theParms, false, varargs) : new CImplicitFunction(toCharArray(name), fScope, ft, theParms, varargs); fBindingList.add(b); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java index 6ec93159519..d0162013eb3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java @@ -91,12 +91,12 @@ public class CPPASTTranslationUnit extends ASTTranslationUnit implements ICPPAST ICPPFunctionType newFunctionType = new CPPFunctionType(cpp_void_p, newParms); ICPPParameter[] newTheParms = new ICPPParameter[1]; newTheParms[0] = new CPPBuiltinParameter(newParms[0]); - temp = new CPPImplicitFunction(OverloadableOperator.NEW.toCharArray(), theScope, newFunctionType, newTheParms, false); + temp = new CPPImplicitFunction(OverloadableOperator.NEW.toCharArray(), theScope, newFunctionType, newTheParms, false, false); theScope.addBinding(temp); // void* operator new[](std::size_t); temp = null; - temp = new CPPImplicitFunction(OverloadableOperator.NEW_ARRAY.toCharArray(), theScope, newFunctionType, newTheParms, false); + temp = new CPPImplicitFunction(OverloadableOperator.NEW_ARRAY.toCharArray(), theScope, newFunctionType, newTheParms, false, false); theScope.addBinding(temp); // void operator delete(void*); @@ -106,12 +106,14 @@ public class CPPASTTranslationUnit extends ASTTranslationUnit implements ICPPAST ICPPFunctionType deleteFunctionType = new CPPFunctionType(cpp_void, deleteParms); ICPPParameter[] deleteTheParms = new ICPPParameter[1]; deleteTheParms[0] = new CPPBuiltinParameter(deleteParms[0]); - temp = new CPPImplicitFunction(OverloadableOperator.DELETE.toCharArray(), theScope, deleteFunctionType, deleteTheParms, false); + temp = new CPPImplicitFunction(OverloadableOperator.DELETE.toCharArray(), theScope, + deleteFunctionType, deleteTheParms, false, false); theScope.addBinding(temp); // void operator delete[](void*); temp = null; - temp = new CPPImplicitFunction(OverloadableOperator.DELETE_ARRAY.toCharArray(), theScope, deleteFunctionType, deleteTheParms, false); + temp = new CPPImplicitFunction(OverloadableOperator.DELETE_ARRAY.toCharArray(), theScope, + deleteFunctionType, deleteTheParms, false, false); theScope.addBinding(temp); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java index 3da808e5de7..ecd64534509 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java @@ -113,14 +113,15 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { if (!ia.hasUserDeclaredConstructor()) { // Default constructor: A(void) - ICPPMethod m = new CPPImplicitConstructor(this, className, EMPTY_CPPPARAMETER_ARRAY); + boolean isConstexpr = ia.isDefaultConstructorConstexpr(); + ICPPMethod m = new CPPImplicitConstructor(this, className, EMPTY_CPPPARAMETER_ARRAY, isConstexpr); implicits[i++] = m; addBinding(m); } if (!ia.hasUserDeclaredCopyConstructor()) { // Copy constructor: A(const A &) - ICPPMethod m = new CPPImplicitConstructor(this, className, params); + ICPPMethod m = new CPPImplicitConstructor(this, className, params, false); implicits[i++] = m; addBinding(m); } @@ -129,7 +130,8 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { // Copy assignment operator: A& operator = (const A &) IType refType = new CPPReferenceType(classType, false); ICPPFunctionType ft= CPPVisitor.createImplicitFunctionType(refType, params, false, false); - ICPPMethod m = new CPPImplicitMethod(this, OverloadableOperator.ASSIGN.toCharArray(), ft, params); + ICPPMethod m = + new CPPImplicitMethod(this, OverloadableOperator.ASSIGN.toCharArray(), ft, params, false); implicits[i++] = m; addBinding(m); } @@ -137,7 +139,8 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { if (!ia.hasUserDeclaredDestructor()) { // Destructor: ~A() char[] dtorName = CharArrayUtils.concat("~".toCharArray(), className); //$NON-NLS-1$ - ICPPMethod m = new CPPImplicitMethod(this, dtorName, DESTRUCTOR_FUNCTION_TYPE, EMPTY_CPPPARAMETER_ARRAY); + ICPPMethod m = new CPPImplicitMethod(this, dtorName, DESTRUCTOR_FUNCTION_TYPE, EMPTY_CPPPARAMETER_ARRAY, + false); implicits[i++] = m; addBinding(m); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java index cddda41f1ba..e8ce53e481b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java @@ -79,25 +79,26 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP ICPPMethod[] result= new ICPPMethod[needConversionOperator ? 6 : 5]; // Deleted default constructor: A() - CPPImplicitConstructor ctor= new CPPImplicitConstructor(scope, CharArrayUtils.EMPTY, ICPPParameter.EMPTY_CPPPARAMETER_ARRAY); + CPPImplicitConstructor ctor= + new CPPImplicitConstructor(scope, CharArrayUtils.EMPTY, ICPPParameter.EMPTY_CPPPARAMETER_ARRAY, false); ctor.setDeleted(true); result[0]= ctor; // Copy constructor: A(const A &) IType pType = new CPPReferenceType(SemanticUtil.constQualify(this), false); ICPPParameter[] ps = new ICPPParameter[] { new CPPParameter(pType, 0) }; - ctor = new CPPImplicitConstructor(scope, CharArrayUtils.EMPTY, ps); + ctor = new CPPImplicitConstructor(scope, CharArrayUtils.EMPTY, ps, false); result[1]= ctor; // Deleted copy assignment operator: A& operator = (const A &) IType refType = new CPPReferenceType(this, false); ICPPFunctionType ft= CPPVisitor.createImplicitFunctionType(refType, ps, false, false); - ICPPMethod m = new CPPImplicitMethod(scope, OverloadableOperator.ASSIGN.toCharArray(), ft, ps); + ICPPMethod m = new CPPImplicitMethod(scope, OverloadableOperator.ASSIGN.toCharArray(), ft, ps, false); result[2]= m; // Destructor: ~A() ft= CPPVisitor.createImplicitFunctionType(UNSPECIFIED_TYPE, ICPPParameter.EMPTY_CPPPARAMETER_ARRAY, false, false); - m = new CPPImplicitMethod(scope, new char[] {'~'}, ft, ICPPParameter.EMPTY_CPPPARAMETER_ARRAY); + m = new CPPImplicitMethod(scope, new char[] {'~'}, ft, ICPPParameter.EMPTY_CPPPARAMETER_ARRAY, false); result[3]= m; // Function call operator @@ -109,7 +110,7 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP for (int i = 0; i < params.length; i++) { params[i]= new CPPParameter(parameterTypes[i], i); } - m= new CPPImplicitMethod(scope, OverloadableOperator.PAREN.toCharArray(), ft, params) { + m= new CPPImplicitMethod(scope, OverloadableOperator.PAREN.toCharArray(), ft, params, false) { @Override public boolean isImplicit() { return false; } }; @@ -119,7 +120,7 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP if (needConversionOperator) { final CPPFunctionType conversionTarget = new CPPFunctionType(returnType, parameterTypes); ft= new CPPFunctionType(conversionTarget, IType.EMPTY_TYPE_ARRAY, true, false, false, false, false); - m= new CPPImplicitMethod(scope, CPPASTConversionName.createName(conversionTarget, null), ft, params); + m= new CPPImplicitMethod(scope, CPPASTConversionName.createName(conversionTarget, null), ft, params, false); result[5]= m; } return result; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitConstructor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitConstructor.java index 5e95a671a24..7276855a28a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitConstructor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitConstructor.java @@ -8,6 +8,7 @@ * Contributors: * Andrew Niefer (IBM Corporation) - initial API and implementation * Markus Schorn (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -25,8 +26,8 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; */ public class CPPImplicitConstructor extends CPPImplicitMethod implements ICPPConstructor { - public CPPImplicitConstructor(ICPPClassScope scope, char[] name, ICPPParameter[] params) { - super(scope, name, createFunctionType(params), params); + public CPPImplicitConstructor(ICPPClassScope scope, char[] name, ICPPParameter[] params, boolean isConstexpr) { + super(scope, name, createFunctionType(params), params, isConstexpr); } private static ICPPFunctionType createFunctionType(IParameter[] params) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitFunction.java index e0d54095103..1f7102c7565 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitFunction.java @@ -8,6 +8,7 @@ * Contributors: * IBM - Initial API and implementation * Markus Schorn (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -26,18 +27,20 @@ public class CPPImplicitFunction extends CPPFunction { private ICPPParameter[] params; private IScope scope; private ICPPFunctionType functionType; + private final boolean isConstexpr; private final boolean takesVarArgs; private boolean isDeleted; private final char[] name; public CPPImplicitFunction(char[] name, IScope scope, ICPPFunctionType type, - ICPPParameter[] params, boolean takesVarArgs) { + ICPPParameter[] params, boolean isConstexpr, boolean takesVarArgs) { super(null); this.name= name; this.scope= scope; this.functionType= type; this.params= params; this.takesVarArgs= takesVarArgs; + this.isConstexpr = isConstexpr; } @Override @@ -49,7 +52,7 @@ public class CPPImplicitFunction extends CPPFunction { public ICPPFunctionType getType() { return functionType; } - + @Override public String getName() { return String.valueOf(name); @@ -64,27 +67,32 @@ public class CPPImplicitFunction extends CPPFunction { public IScope getScope() { return scope; } - + @Override public IScope getFunctionScope() { return null; } - + + @Override + public boolean isConstexpr() { + return isConstexpr; + } + @Override public boolean takesVarArgs() { return takesVarArgs; } - + @Override public boolean isDeleted() { return isDeleted; } - + @Override public IBinding getOwner() { return null; } - + public void setDeleted(boolean val) { isDeleted= val; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitMethod.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitMethod.java index 2cbbc53cc5c..7c5eebe788f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitMethod.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitMethod.java @@ -9,6 +9,7 @@ * Andrew Niefer (IBM Corporation) - initial API and implementation * Markus Schorn (Wind River Systems) * Thomas Corbat (IFS) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -42,8 +43,9 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; */ public class CPPImplicitMethod extends CPPImplicitFunction implements ICPPMethod { - public CPPImplicitMethod(ICPPClassScope scope, char[] name, ICPPFunctionType type, ICPPParameter[] params) { - super(name, scope, type, params, false); + public CPPImplicitMethod(ICPPClassScope scope, char[] name, ICPPFunctionType type, ICPPParameter[] params, + boolean isConstexpr) { + super(name, scope, type, params, isConstexpr, false); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPInheritedConstructor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPInheritedConstructor.java index 0eff5f79f34..755db52fd3c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPInheritedConstructor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPInheritedConstructor.java @@ -28,7 +28,7 @@ public class CPPInheritedConstructor extends CPPImplicitMethod implements ICPPCo public CPPInheritedConstructor(ICPPClassScope scope, char[] name, ICPPConstructor prototype, ICPPParameter[] params) { - super(scope, name, createFunctionType(params), params); + super(scope, name, createFunctionType(params), params, false); this.prototype = prototype; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ImplicitsAnalysis.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ImplicitsAnalysis.java index 812f88e5c50..b92fde045b2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ImplicitsAnalysis.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ImplicitsAnalysis.java @@ -23,15 +23,19 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; @@ -48,14 +52,17 @@ final class ImplicitsAnalysis { private static final IASTParameterDeclaration[][] EMPTY_ARRAY_OF_PARAMETER_ARRAYS = {}; private final ICPPClassType classType; + private final ICPPASTCompositeTypeSpecifier compositeTypeSpecifier; private boolean hasConstructor; private boolean hasCopyConstructor; private boolean hasCopyAssignmentOperator; private boolean hasDestructor; private IASTParameterDeclaration[][] parametersOfNontrivialConstructors = EMPTY_ARRAY_OF_PARAMETER_ARRAYS; + private boolean hasNonStaticFields; ImplicitsAnalysis(ICPPASTCompositeTypeSpecifier compositeTypeSpecifier, ICPPClassType classType) { this.classType= classType; + this.compositeTypeSpecifier = compositeTypeSpecifier; analyzeMembers(compositeTypeSpecifier); } @@ -124,43 +131,45 @@ final class ImplicitsAnalysis { spec = ((IASTFunctionDefinition) member).getDeclSpecifier(); } - if (!(dcltor instanceof ICPPASTFunctionDeclarator)) - continue; - - IASTName memberName = ASTQueries.findInnermostDeclarator(dcltor).getName(); - char[] declName = memberName.getLookupKey(); - - if (spec instanceof IASTSimpleDeclSpecifier && - ((IASTSimpleDeclSpecifier) spec).getType() == IASTSimpleDeclSpecifier.t_unspecified) { - if (CharArrayUtils.equals(declName, name)) { - hasConstructor = true; + if (dcltor instanceof ICPPASTFunctionDeclarator) { + IASTName memberName = ASTQueries.findInnermostDeclarator(dcltor).getName(); + char[] declName = memberName.getLookupKey(); + + if (spec instanceof IASTSimpleDeclSpecifier && + ((IASTSimpleDeclSpecifier) spec).getType() == IASTSimpleDeclSpecifier.t_unspecified) { + if (CharArrayUtils.equals(declName, name)) { + hasConstructor = true; + IASTParameterDeclaration[] params = ((ICPPASTFunctionDeclarator) dcltor).getParameters(); + if (params.length != 0) { + if (hasTypeReferenceToClassType(params[0])) { + if (parametersHaveInitializers(params, 1)) { + hasCopyConstructor = true; + } + if (params.length > 1) { + parametersOfNontrivialConstructors = + appendAt(parametersOfNontrivialConstructors, numNontrivialConstructors++, params); + } + } else { + parametersOfNontrivialConstructors = + appendAt(parametersOfNontrivialConstructors, numNontrivialConstructors++, params); + } + } + } if (declName.length != 0 && declName[0] == '~' && + CharArrayUtils.equals(declName, 1, name.length, name)) { + hasDestructor = true; + } + } if (CharArrayUtils.equals(declName, OverloadableOperator.ASSIGN.toCharArray())) { IASTParameterDeclaration[] params = ((ICPPASTFunctionDeclarator) dcltor).getParameters(); - if (params.length != 0) { - if (hasTypeReferenceToClassType(params[0])) { - if (parametersHaveInitializers(params, 1)) { - hasCopyConstructor = true; - } - if (params.length > 1) { - parametersOfNontrivialConstructors = - appendAt(parametersOfNontrivialConstructors, numNontrivialConstructors++, params); - } - } else { - parametersOfNontrivialConstructors = - appendAt(parametersOfNontrivialConstructors, numNontrivialConstructors++, params); - } - } - } if (declName.length != 0 && declName[0] == '~' && - CharArrayUtils.equals(declName, 1, name.length, name)) { - hasDestructor = true; + if (params.length == 1 && hasTypeReferenceToClassType(params[0])) + hasCopyAssignmentOperator = true; } - } if (CharArrayUtils.equals(declName, OverloadableOperator.ASSIGN.toCharArray())) { - IASTParameterDeclaration[] params = ((ICPPASTFunctionDeclarator) dcltor).getParameters(); - if (params.length == 1 && hasTypeReferenceToClassType(params[0])) - hasCopyAssignmentOperator = true; - } - - if (hasCopyConstructor && hasDestructor && hasCopyAssignmentOperator && baseSpecifiers.length == 0) { - break; // Nothing else to look for. + + if (hasCopyConstructor && hasDestructor && hasCopyAssignmentOperator && baseSpecifiers.length == 0) { + break; // Nothing else to look for. + } + } else if (dcltor instanceof ICPPASTFieldDeclarator && + spec != null && spec.getStorageClass() != IASTDeclSpecifier.sc_static) { + hasNonStaticFields = true; } } @@ -192,4 +201,38 @@ final class ImplicitsAnalysis { } return true; } + + public boolean isDefaultConstructorConstexpr() { + // The following condition is stronger than necessary. It is sufficient if the class doesn't contain + // non-static fields that don't have constexpr default constructors. + // TODO(sprigogin): Relax the condition in accordance with [dcl.constexpr] 7.1.5-4. + if (hasNonStaticFields) + return false; + + ICPPBase[] bases = ClassTypeHelper.getBases(classType, compositeTypeSpecifier); + for (ICPPBase base : bases) { + if (base.isVirtual()) + return true; + } + + ICPPClassType[] baseClasses = ClassTypeHelper.getAllBases(classType, compositeTypeSpecifier); + for (ICPPClassType baseClass : baseClasses) { + ICPPConstructor ctor = getDefaultConstructor(baseClass, compositeTypeSpecifier); + if (ctor == null || !ctor.isConstexpr()) { + return false; + } + } + return true; + } + + /** + * Returns a user-defined or implicit default constructor for the given class. + */ + private static ICPPConstructor getDefaultConstructor(ICPPClassType classType, IASTNode point) { + for (ICPPConstructor ctor : ClassTypeHelper.getConstructors(classType, point)) { + if (ClassTypeHelper.getMethodKind(classType, ctor) == ClassTypeHelper.MethodKind.DEFAULT_CTOR) + return ctor; + } + return null; + } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java index 1ca94000b91..855c57244af 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/BuiltinOperators.java @@ -566,7 +566,7 @@ class BuiltinOperators { if (fResult == null) { fResult= new ArrayList<>(); } - fResult.add(new CPPImplicitFunction(fOperator.toCharArray(), fFileScope, functionType, parameter, false)); + fResult.add(new CPPImplicitFunction(fOperator.toCharArray(), fFileScope, functionType, parameter, true, false)); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPDependentEvaluation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPDependentEvaluation.java index 6fdac5456fa..61cf1a23542 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPDependentEvaluation.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPDependentEvaluation.java @@ -70,7 +70,7 @@ public abstract class CPPDependentEvaluation extends CPPEvaluation { /** * If the given node is contained in some template declaration, - * return the binding for that template. Otherwise return null. + * returns the binding for that template. Otherwise returns null. */ protected static IBinding findEnclosingTemplate(IASTNode node) { while (node != null) { 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 8fe52e0fd9e..d0b4e6ede08 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 @@ -3794,7 +3794,7 @@ public class CPPSemantics { theParms[i]= new CPPBuiltinParameter(t); } ICPPFunctionType functionType = new CPPFunctionType(returnType, parms); - return new CPPImplicitFunction(CALL_FUNCTION, scope, functionType, theParms, false); + return new CPPImplicitFunction(CALL_FUNCTION, scope, functionType, theParms, false, false); } static boolean isUserDefined(IType type) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java index 5ca2a1fe44a..f05bcfcb78c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java @@ -135,6 +135,8 @@ public class EvalTypeId extends CPPDependentEvaluation { @Override public boolean isValueDependent() { + if (CPPTemplates.isDependentType(fInputType)) + return true; for (ICPPEvaluation arg : fArguments) { if (arg.isValueDependent()) return true; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java index 31f9856a774..e80fc55dc83 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java @@ -37,6 +37,7 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti 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 org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTNode; @@ -46,7 +47,9 @@ import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.ISemanticProblem; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; @@ -61,6 +64,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArithmeticConversion; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; @@ -276,9 +280,34 @@ public class EvalUnary extends CPPDependentEvaluation { if (isValueDependent()) return Value.create(this); - if (getOverload(point) != null) { - // TODO(sprigogin): Simulate execution of a function call. - return Value.create(this); + ICPPEvaluation arg = fArgument; + ICPPFunction overload = getOverload(point); + if (overload != null) { + ICPPFunctionType functionType = overload.getType(); + IType targetType = functionType.getParameterTypes()[0]; + ValueCategory valueCategory = fArgument.getValueCategory(point); + IType type = fArgument.getType(point); + ICPPFunction conversion = null; + try { + Cost cost = Conversions.initializationByConversion(valueCategory, type, (ICPPClassType) type, targetType, false, point); + conversion = cost.getUserDefinedConversion(); + } catch (DOMException e) { + CCorePlugin.log(e); + } + + if (conversion != null) { + if (!conversion.isConstexpr()) + return Value.ERROR; + ICPPEvaluation eval = new EvalBinding(conversion, null, (IBinding) null); + arg = new EvalFunctionCall(new ICPPEvaluation[] {eval, arg}, (IBinding) null); + } + if (!(overload instanceof CPPImplicitFunction)) { + if (!overload.isConstexpr()) + return Value.ERROR; + ICPPEvaluation eval = new EvalBinding(overload, null, (IBinding) null); + arg = new EvalFunctionCall(new ICPPEvaluation[] {eval, arg}, (IBinding) null); + return arg.getValue(point); + } } switch (fOperator) { @@ -302,7 +331,7 @@ public class EvalUnary extends CPPDependentEvaluation { return Value.UNKNOWN; // TODO(sprigogin): Implement } - IValue val = fArgument.getValue(point); + IValue val = arg.getValue(point); if (val == null) return Value.UNKNOWN;