From 984c5eb604d56c3b2abb9abdf5bc39d4ba95025d Mon Sep 17 00:00:00 2001 From: Sergey Prigogin Date: Tue, 4 Dec 2012 12:23:55 -0800 Subject: [PATCH] Bug 395238. Evaluation of constexpr functions. Also few fixes related to alias templates. --- .../parser/tests/ast2/AST2TemplateTests.java | 101 +++++++++ .../tests/IndexCPPTemplateResolutionTest.java | 100 +++++++++ .../cdt/core/dom/ast/cpp/ICPPFunction.java | 9 +- .../cdt/internal/core/dom/parser/Value.java | 7 +- .../core/dom/parser/cpp/CPPAliasTemplate.java | 16 +- .../parser/cpp/CPPClassSpecialization.java | 5 + .../dom/parser/cpp/CPPDeferredFunction.java | 13 +- .../core/dom/parser/cpp/CPPFunction.java | 109 +++++++-- .../parser/cpp/CPPFunctionSpecialization.java | 62 ++++-- .../dom/parser/cpp/CPPFunctionTemplate.java | 32 ++- .../dom/parser/cpp/CPPTemplateParameter.java | 4 +- .../core/dom/parser/cpp/CPPUnknownMethod.java | 5 + .../parser/cpp/ICPPComputableFunction.java | 22 ++ .../core/dom/parser/cpp/ICPPEvaluation.java | 13 ++ .../dom/parser/cpp/ICPPInternalFunction.java | 3 +- .../dom/parser/cpp/ICPPInternalTemplate.java | 12 +- .../cpp/ICPPTemplateParameterOwner.java | 22 ++ .../cpp/semantics/AutoTypeResolver.java | 5 + .../semantics/CPPFunctionParameterMap.java | 102 +++++++++ .../parser/cpp/semantics/CPPTemplates.java | 3 + .../dom/parser/cpp/semantics/EvalBinary.java | 10 + .../cpp/semantics/EvalBinaryTypeId.java | 6 + .../dom/parser/cpp/semantics/EvalBinding.java | 209 ++++++++++++++---- .../dom/parser/cpp/semantics/EvalComma.java | 19 ++ .../parser/cpp/semantics/EvalCompound.java | 9 + .../parser/cpp/semantics/EvalConditional.java | 12 + .../dom/parser/cpp/semantics/EvalFixed.java | 12 + .../cpp/semantics/EvalFunctionCall.java | 74 ++++++- .../parser/cpp/semantics/EvalFunctionSet.java | 6 + .../core/dom/parser/cpp/semantics/EvalID.java | 11 + .../parser/cpp/semantics/EvalInitList.java | 19 ++ .../cpp/semantics/EvalMemberAccess.java | 6 + .../dom/parser/cpp/semantics/EvalTypeId.java | 21 ++ .../dom/parser/cpp/semantics/EvalUnary.java | 10 + .../parser/cpp/semantics/EvalUnaryTypeID.java | 6 + .../composite/cpp/CPPCompositesFactory.java | 26 ++- .../composite/cpp/CompositeCPPFunction.java | 15 +- .../eclipse/cdt/internal/core/pdom/PDOM.java | 7 +- .../cdt/internal/core/pdom/db/Database.java | 1 + .../core/pdom/db/TypeMarshalBuffer.java | 4 +- .../internal/core/pdom/dom/PDOMLinkage.java | 42 +++- .../pdom/dom/cpp/PDOMCPPAliasTemplate.java | 70 ++++-- .../core/pdom/dom/cpp/PDOMCPPConstructor.java | 4 +- .../core/pdom/dom/cpp/PDOMCPPFunction.java | 140 +++++++----- .../cpp/PDOMCPPFunctionSpecialization.java | 56 ++++- .../core/pdom/dom/cpp/PDOMCPPLinkage.java | 75 ++++++- .../core/pdom/dom/cpp/PDOMCPPMethod.java | 2 +- .../dom/cpp/PDOMCPPMethodSpecialization.java | 2 +- 48 files changed, 1292 insertions(+), 227 deletions(-) create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPComputableFunction.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPTemplateParameterOwner.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPFunctionParameterMap.java 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 2a88ba5a8de..c3faee08cc9 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 @@ -6774,4 +6774,105 @@ public class AST2TemplateTests extends AST2BaseTest { public void testAliasTemplate_395026_2() throws Exception { parseAndCheckBindings(); } + + // template + // struct A { + // typedef U type1; + // + // template + // struct rebind { + // typedef A other; + // }; + // }; + // + // template + // struct B { + // template + // static constexpr bool test(typename T2::template rebind::other*) { + // return true; + // } + // + // template + // static constexpr bool test(...) { + // return false; + // } + // + // static const bool value = test(nullptr); + // }; + // + // template::value> + // struct C; + // + // template + // struct C { + // typedef typename T::template rebind::other type2; + // }; + // + // template + // struct D { + // typedef typename T::type1 type3; + // + // template + // using rebind2 = typename C::type2; + // }; + // + // template + // struct E : D { + // typedef D Base; + // typedef typename Base::type3& type4; + // + // template + // struct rebind { + // typedef typename Base::template rebind2 other; + // }; + // }; + // + // template> + // struct F { + // typedef typename E::template rebind::other type5; + // typedef typename E::type4 type6; + // type6 operator[](int n); + // }; + // + // void f(int); + // + // void test() { + // F a; + // f(*a[0]); + // } + public void testConstexprFunction_395238_1() throws Exception { + parseAndCheckBindings(); + } + + // template + // struct A { + // template + // static constexpr U test(U v) { + // return v; + // } + // + // template + // static constexpr bool test(...) { + // return false; + // } + // + // static const bool value = test(true); + // }; + // + // template::value> + // struct B; + // + // template + // struct B { + // typedef T type; + // }; + // + // B::type x; + // B::type y; + public void testConstexprFunction_395238_2() throws Exception { + BindingAssertionHelper ah = getAssertionHelper(); + ITypedef td = ah.assertNonProblem("B::type", "type", ITypedef.class); + assertEquals("bool", ASTTypeUtil.getType(td.getType())); + ah.assertProblem("B::type", "type"); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java index 682f164ebd9..cc4715284cc 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java @@ -2061,4 +2061,104 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa public void testAliasTemplate() throws Exception { checkBindings(); } + + // template + // struct A { + // typedef U type1; + // + // template + // struct rebind { + // typedef A other; + // }; + // }; + // + // template + // struct B { + // template + // static constexpr bool test(typename T2::template rebind::other*) { + // return true; + // } + // + // template + // static constexpr bool test(...) { + // return false; + // } + // + // static const bool value = test(nullptr); + // }; + // + // template::value> + // struct C; + // + // template + // struct C { + // typedef typename T::template rebind::other type2; + // }; + // + // template + // struct D { + // typedef typename T1::type1 type3; + // + // template + // using rebind2 = typename C::type2; + // }; + // + // template + // struct E : D { + // typedef D Base; + // typedef typename Base::type3& type4; + // + // template + // struct rebind { + // typedef typename Base::template rebind2 other; + // }; + // }; + // + // template> + // struct F { + // typedef typename E::template rebind::other type5; + // typedef typename E::type4 type6; + // type6 operator[](int n); + // }; + // + // void f(int); + + // void test() { + // F a; + // f(*a[0]); + // } + public void testConstexprFunction_395238_1() throws Exception { + checkBindings(); + } + + // template + // struct A { + // template + // static constexpr U test(U v) { + // return v; + // } + // + // template + // static constexpr bool test(...) { + // return false; + // } + // + // static const bool value = test(true); + // }; + // + // template::value> + // struct B; + // + // template + // struct B { + // typedef T type; + // }; + + // B::type x; + // B::type y; + public void testConstexprFunction_395238_2() throws Exception { + ITypedef td = getBindingFromASTName("type x", 4, ITypedef.class); + assertEquals("bool", ASTTypeUtil.getType(td.getType())); + getProblemFromASTName("type y", 4); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPFunction.java index b0b38f935a5..76cb6ede4f4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPFunction.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -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.core.dom.ast.cpp; @@ -38,6 +39,12 @@ public interface ICPPFunction extends IFunction, ICPPBinding { */ public boolean isExternC(); + /** + * Returns whether this function is declared constexpr. + * @noreference This method is not intended to be referenced by clients. + */ + public boolean isConstexpr(); + /** * Returns the exception specification for this function or null if there * is no exception specification. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java index 4aea884c140..79fb138efd2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java @@ -55,7 +55,6 @@ import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator.SizeAndAlignment; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; @@ -355,6 +354,7 @@ public class Value implements IValue { return VALUE_CANNOT_BE_DETERMINED; return sizeAndAlignment.size; } + /** * Tests whether the value is a template parameter (or a parameter pack). * @@ -364,10 +364,7 @@ public class Value implements IValue { public static int isTemplateParameter(IValue tval) { ICPPEvaluation eval = tval.getEvaluation(); if (eval instanceof EvalBinding) { - IBinding binding = ((EvalBinding) eval).getBinding(); - if (binding instanceof ICPPTemplateParameter) { - return ((ICPPTemplateParameter) binding).getParameterID(); - } + return ((EvalBinding) eval).getTemplateParameterID(); } return -1; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPAliasTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPAliasTemplate.java index 4d8257a99bf..4bb16be6183 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPAliasTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPAliasTemplate.java @@ -8,6 +8,7 @@ * * Contributors: * Thomas Corbat (IFS) - Initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -28,7 +29,8 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.core.runtime.PlatformObject; -public class CPPAliasTemplate extends PlatformObject implements ICPPAliasTemplate { +public class CPPAliasTemplate extends PlatformObject + implements ICPPAliasTemplate, ICPPTemplateParameterOwner { private final IASTName aliasName; private final IType aliasedType; private ICPPTemplateParameter[] templateParameters; @@ -128,4 +130,16 @@ public class CPPAliasTemplate extends PlatformObject implements ICPPAliasTemplat public String toString() { return ASTTypeUtil.getQualifiedName(this) + " -> " + ASTTypeUtil.getType(aliasedType, true); //$NON-NLS-1$ } + + @Override + public IBinding resolveTemplateParameter(ICPPTemplateParameter templateParameter) { + int pos= templateParameter.getParameterPosition(); + + ICPPASTTemplateParameter[] params = CPPTemplates.getTemplateDeclaration(aliasName).getTemplateParameters(); + if (pos < params.length) { + final IASTName oName = CPPTemplates.getTemplateParameterName(params[pos]); + return oName.resolvePreBinding(); + } + return templateParameter; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java index 468edd02551..6aa3c0be5c7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java @@ -135,6 +135,11 @@ public class CPPClassSpecialization extends CPPSpecialization public boolean isFinal() { return false; } + + @Override + public boolean isConstexpr() { + return false; + } } private ICPPClassSpecializationScope specScope; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java index 1e3fccf39e3..daf282b6106 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPDeferredFunction.java @@ -7,6 +7,7 @@ * * Contributors: * Markus Schorn - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -25,7 +26,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ProblemType; * Represents a reference to a (member) function (instance), which cannot be resolved because * an argument depends on a template parameter. A compiler would resolve it during instantiation. */ -public class CPPDeferredFunction extends CPPUnknownBinding implements ICPPFunction { +public class CPPDeferredFunction extends CPPUnknownBinding implements ICPPFunction, ICPPComputableFunction { private static final ICPPFunctionType FUNCTION_TYPE= new CPPFunctionType(ProblemType.UNKNOWN_FOR_EXPRESSION, IType.EMPTY_TYPE_ARRAY); @@ -69,6 +70,11 @@ public class CPPDeferredFunction extends CPPUnknownBinding implements ICPPFuncti return false; } + @Override + public boolean isConstexpr() { + return false; + } + @Override public IScope getFunctionScope() { return asScope(); @@ -128,4 +134,9 @@ public class CPPDeferredFunction extends CPPUnknownBinding implements ICPPFuncti public IBinding getOwner() { return fOwner; } + + @Override + public ICPPEvaluation getReturnExpression() { + return null; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java index cd8d776018d..acd531befc0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java @@ -18,15 +18,19 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; 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.IASTInitializerClause; 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.IASTReturnStatement; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IBinding; @@ -38,6 +42,7 @@ import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; @@ -52,6 +57,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ProblemFunctionType; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; import org.eclipse.core.runtime.PlatformObject; @@ -230,17 +236,8 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt IASTName n = getASTName(); IScope scope = CPPVisitor.getContainingScope(n); if (scope instanceof ICPPClassScope) { - ICPPASTDeclSpecifier declSpec = null; - if (definition != null) { - IASTNode node = ASTQueries.findOutermostDeclarator(definition).getParent(); - IASTFunctionDefinition def = (IASTFunctionDefinition) node; - declSpec = (ICPPASTDeclSpecifier) def.getDeclSpecifier(); - } else { - IASTNode node = ASTQueries.findOutermostDeclarator(declarations[0]).getParent(); - IASTSimpleDeclaration decl = (IASTSimpleDeclaration)node; - declSpec = (ICPPASTDeclSpecifier) decl.getDeclSpecifier(); - } - if (declSpec.isFriend()) { + ICPPASTDeclSpecifier declSpec = getDeclSpecifier(); + if (declSpec != null && declSpec.isFriend()) { try { while (scope instanceof ICPPClassScope) { scope = scope.getParent(); @@ -252,6 +249,19 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt return scope; } + private ICPPASTDeclSpecifier getDeclSpecifier() { + if (definition != null) { + IASTNode node = ASTQueries.findOutermostDeclarator(definition).getParent(); + IASTFunctionDefinition def = (IASTFunctionDefinition) node; + return (ICPPASTDeclSpecifier) def.getDeclSpecifier(); + } else if (declarations != null && declarations.length != 0) { + IASTNode node = ASTQueries.findOutermostDeclarator(declarations[0]).getParent(); + IASTSimpleDeclaration decl = (IASTSimpleDeclaration) node; + return (ICPPASTDeclSpecifier) decl.getDeclSpecifier(); + } + return null; + } + @Override public ICPPFunctionType getType() { if (type == null) { @@ -420,9 +430,9 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt IASTDeclSpecifier declSpec = null; if (parent instanceof IASTSimpleDeclaration) { - declSpec = ((IASTSimpleDeclaration)parent).getDeclSpecifier(); + declSpec = ((IASTSimpleDeclaration) parent).getDeclSpecifier(); } else if (parent instanceof IASTFunctionDefinition) { - declSpec = ((IASTFunctionDefinition)parent).getDeclSpecifier(); + declSpec = ((IASTFunctionDefinition) parent).getDeclSpecifier(); } if (declSpec != null && declSpec.getStorageClass() == storage) { return true; @@ -437,19 +447,14 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt return false; } - @Override - public boolean isDeleted() { - return isDeletedDefinition(getDefinition()); - } - - public static boolean isDeletedDefinition(IASTNode def) { + static ICPPASTFunctionDefinition getFunctionDefinition(IASTNode def) { while (def != null && !(def instanceof IASTDeclaration)) { def= def.getParent(); } if (def instanceof ICPPASTFunctionDefinition) { - return ((ICPPASTFunctionDefinition) def).isDeleted(); + return (ICPPASTFunctionDefinition) def; } - return false; + return null; } @Override @@ -511,6 +516,26 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt return hasStorageClass(this, IASTDeclSpecifier.sc_auto); } + @Override + public boolean isConstexpr() { + ICPPASTDeclSpecifier declSpec = getDeclSpecifier(); + if (declSpec == null) + return false; + return declSpec.isConstexpr(); + } + + @Override + public boolean isDeleted() { + return isDeletedDefinition(getDefinition()); + } + + static boolean isDeletedDefinition(IASTNode def) { + ICPPASTFunctionDefinition functionDefinition = getFunctionDefinition(def); + if (functionDefinition != null) + return functionDefinition.isDeleted(); + return false; + } + @Override public boolean isRegister() { return hasStorageClass(this, IASTDeclSpecifier.sc_register); @@ -608,4 +633,46 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt ICPPASTFunctionDeclarator dtor = getPreferredDtor(); return dtor != null && AttributeUtil.hasNoreturnAttribute(dtor); } + + @Override + public ICPPEvaluation getReturnExpression() { + if (!isConstexpr()) + return null; + if (definition == null) + return EvalFixed.INCOMPLETE; + + IASTNode node = ASTQueries.findOutermostDeclarator(definition).getParent(); + return getReturnExpression((IASTFunctionDefinition) node); + } + + static ICPPEvaluation getReturnExpression(IASTFunctionDefinition functionDefinition) { + IASTReturnStatement returnStatement = null; + IASTStatement body = functionDefinition.getBody(); + if (body instanceof IASTReturnStatement) { + returnStatement = (IASTReturnStatement) body; + } else if (body instanceof IASTCompoundStatement) { + for (IASTStatement statement : ((IASTCompoundStatement) body).getStatements()) { + if (statement instanceof IASTReturnStatement) { + if (returnStatement != null) + return EvalFixed.INCOMPLETE; + returnStatement = (IASTReturnStatement) statement; + } + } + } + if (returnStatement == null) + return EvalFixed.INCOMPLETE; // constexpr constructors are not supported yet. + + IASTInitializerClause returnExpression = returnStatement.getReturnArgument(); + if (returnExpression instanceof ICPPASTInitializerClause) + return ((ICPPASTInitializerClause) returnExpression).getEvaluation(); + + return EvalFixed.INCOMPLETE; + } + + public static ICPPEvaluation getReturnExpression(ICPPFunction function) { + if (function instanceof ICPPComputableFunction) { + return ((ICPPComputableFunction) function).getReturnExpression(); + } + return null; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java index 6fa49ac16f6..f0d4e6f27aa 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java @@ -24,7 +24,9 @@ import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; 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.ICPPParameter; @@ -43,7 +45,8 @@ public class CPPFunctionSpecialization extends CPPSpecialization implements ICPP private ICPPParameter[] fParams; private final IType[] fExceptionSpecs; - public CPPFunctionSpecialization(ICPPFunction orig, IBinding owner, ICPPTemplateParameterMap argMap, ICPPFunctionType type, IType[] exceptionSpecs) { + public CPPFunctionSpecialization(ICPPFunction orig, IBinding owner, ICPPTemplateParameterMap argMap, + ICPPFunctionType type, IType[] exceptionSpecs) { super(orig, owner, argMap); fType= type; fExceptionSpecs= exceptionSpecs; @@ -103,19 +106,6 @@ public class CPPFunctionSpecialization extends CPPSpecialization implements ICPP return false; } - @Override - public boolean isDeleted() { - IASTNode def = getDefinition(); - if (def != null) - return CPPFunction.isDeletedDefinition(def); - - IBinding f = getSpecializedBinding(); - if (f instanceof ICPPFunction) { - return ((ICPPFunction) f).isDeleted(); - } - return false; - } - @Override public boolean isInline() { if (getDefinition() != null) { @@ -168,6 +158,33 @@ public class CPPFunctionSpecialization extends CPPSpecialization implements ICPP return CPPFunction.hasStorageClass(this, IASTDeclSpecifier.sc_auto); } + @Override + public boolean isConstexpr() { + IASTNode def = getDefinition(); + if (def != null) { + ICPPASTFunctionDefinition functionDefinition = CPPFunction.getFunctionDefinition(def); + return ((ICPPASTDeclSpecifier) functionDefinition.getDeclSpecifier()).isConstexpr(); + } + IBinding f = getSpecializedBinding(); + if (f instanceof ICPPFunction) { + return ((ICPPFunction) f).isConstexpr(); + } + return false; + } + + @Override + public boolean isDeleted() { + IASTNode def = getDefinition(); + if (def != null) + return CPPFunction.isDeletedDefinition(def); + + IBinding f = getSpecializedBinding(); + if (f instanceof ICPPFunction) { + return ((ICPPFunction) f).isDeleted(); + } + return false; + } + @Override public boolean isRegister() { ICPPFunction f = (ICPPFunction) getSpecializedBinding(); @@ -314,4 +331,21 @@ public class CPPFunctionSpecialization extends CPPSpecialization implements ICPP public IType[] getExceptionSpecification() { return fExceptionSpecs; } + + @Override + public ICPPEvaluation getReturnExpression() { + if (!isConstexpr()) + return null; + + IASTNode def = getDefinition(); + if (def != null) { + ICPPASTFunctionDefinition functionDefinition = CPPFunction.getFunctionDefinition(def); + return CPPFunction.getReturnExpression(functionDefinition); + } + IBinding f = getSpecializedBinding(); + if (f instanceof ICPPComputableFunction) { + return ((ICPPComputableFunction) f).getReturnExpression(); + } + return null; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java index fee12ee72c3..3e44f6fca1f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionTemplate.java @@ -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 * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -33,6 +33,7 @@ import org.eclipse.cdt.core.dom.ast.ISemanticProblem; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; @@ -41,6 +42,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ProblemFunctionType; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; /** * Implementation of function templates @@ -316,16 +318,24 @@ public class CPPFunctionTemplate extends CPPTemplateDefinition return hasStorageClass(IASTDeclSpecifier.sc_extern); } - @Override - public boolean isDeleted() { - return CPPFunction.isDeletedDefinition(getDefinition()); - } - @Override public boolean isAuto() { return hasStorageClass(IASTDeclSpecifier.sc_auto); } + @Override + public boolean isConstexpr() { + ICPPASTFunctionDefinition functionDefinition = CPPFunction.getFunctionDefinition(getDefinition()); + if (functionDefinition == null) + return false; + return ((ICPPASTDeclSpecifier) functionDefinition.getDeclSpecifier()).isConstexpr(); + } + + @Override + public boolean isDeleted() { + return CPPFunction.isDeletedDefinition(getDefinition()); + } + @Override public boolean isRegister() { return hasStorageClass(IASTDeclSpecifier.sc_register); @@ -394,4 +404,14 @@ public class CPPFunctionTemplate extends CPPTemplateDefinition } return null; } + + @Override + public ICPPEvaluation getReturnExpression() { + if (!isConstexpr()) + return null; + ICPPASTFunctionDefinition functionDefinition = CPPFunction.getFunctionDefinition(getDefinition()); + if (functionDefinition == null) + return EvalFixed.INCOMPLETE; + return CPPFunction.getReturnExpression(functionDefinition); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateParameter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateParameter.java index 444d85a0316..0ea75eb79d3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateParameter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateParameter.java @@ -255,8 +255,8 @@ public abstract class CPPTemplateParameter extends PlatformObject return current; ICPPTemplateDefinition template= CPPTemplates.getContainingTemplate(getASTTemplateParameter()); - if (template instanceof ICPPInternalTemplate) { - return ((ICPPInternalTemplate) template).resolveTemplateParameter(this); + if (template instanceof ICPPTemplateParameterOwner) { + return ((ICPPTemplateParameterOwner) template).resolveTemplateParameter(this); } // problem finding the containing template diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java index 761461b1881..0219cb9c5b0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownMethod.java @@ -156,4 +156,9 @@ public class CPPUnknownMethod extends CPPUnknownMember implements ICPPMethod { public boolean isFinal() { return false; } + + @Override + public boolean isConstexpr() { + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPComputableFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPComputableFunction.java new file mode 100644 index 00000000000..9d4cef2b01b --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPComputableFunction.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Sergey Prigogin (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +/** + * Represents a function the return value of which may potentially be calculated at parsing time. + */ +public interface ICPPComputableFunction { + /** + * For a constexpr function returns the return statement expression. Otherwise returns + * {@code null}. + */ + public ICPPEvaluation getReturnExpression(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPEvaluation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPEvaluation.java index aed832e59a4..0ed1f673f48 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPEvaluation.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPEvaluation.java @@ -7,6 +7,7 @@ * * Contributors: * Markus Schorn - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -17,6 +18,7 @@ import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPFunctionParameterMap; /** * Assists in evaluating expressions. @@ -70,6 +72,17 @@ public interface ICPPEvaluation extends ISerializableEvaluation { ICPPEvaluation instantiate(ICPPTemplateParameterMap tpMap, int packOffset, ICPPClassSpecialization within, int maxdepth, IASTNode point); + /** + * Computes the evaluation produced by substituting function parameters by their values. + * + * @param parameterMap maps function parameters to their values + * @param maxdepth allowed recursion depth + * @param point determines the scope for name lookups + * @return the computed evaluation + */ + ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, int maxdepth, + IASTNode point); + /** * Determines size of the template parameter pack. * diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPInternalFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPInternalFunction.java index 4f4d4be7701..b5c2d5f40a2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPInternalFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPInternalFunction.java @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Markus Schorn (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -16,7 +17,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding; /** * Interface for ast-internal implementations of function bindings. */ -public interface ICPPInternalFunction extends ICPPInternalBinding { +public interface ICPPInternalFunction extends ICPPInternalBinding, ICPPComputableFunction { /** * Called to resolve the parameter in the second phase. */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPInternalTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPInternalTemplate.java index 68a64cdec60..221e455a9ca 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPInternalTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPInternalTemplate.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,13 +10,9 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; -import org.eclipse.cdt.core.dom.ast.IBinding; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; - /** - * Interface for templates from the ast. + * Interface for templates from the AST. */ -public interface ICPPInternalTemplate extends ICPPInternalBinding, ICPPInstanceCache { - - IBinding resolveTemplateParameter(ICPPTemplateParameter param); +public interface ICPPInternalTemplate + extends ICPPTemplateParameterOwner, ICPPInternalBinding, ICPPInstanceCache { } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPTemplateParameterOwner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPTemplateParameterOwner.java new file mode 100644 index 00000000000..189ae6b3ef2 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/ICPPTemplateParameterOwner.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Sergey Prigogin (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; + +/** + * Interface for templates from the AST. + */ +public interface ICPPTemplateParameterOwner { + + IBinding resolveTemplateParameter(ICPPTemplateParameter param); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AutoTypeResolver.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AutoTypeResolver.java index 1a4a168efef..0114bc9beb3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AutoTypeResolver.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AutoTypeResolver.java @@ -72,6 +72,11 @@ class AutoTypeResolver implements ICPPFunctionTemplate { return false; } + @Override + public boolean isConstexpr() { + return false; + } + @Override public IType[] getExceptionSpecification() { return null; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPFunctionParameterMap.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPFunctionParameterMap.java new file mode 100644 index 00000000000..898ddcdef49 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPFunctionParameterMap.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2012 Google, Inc and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Sergey Prigogin (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; + +import org.eclipse.cdt.core.parser.util.ObjectMap; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; + +/** + * Maps function parameter positions to values. + */ +public class CPPFunctionParameterMap { + public static final CPPFunctionParameterMap EMPTY = new CPPFunctionParameterMap(0); + + private ObjectMap fMap; + + /** + * Constructs an empty parameter map. + */ + public CPPFunctionParameterMap(int initialSize) { + fMap= new ObjectMap(initialSize); + } + + public CPPFunctionParameterMap(CPPFunctionParameterMap other) { + fMap= (ObjectMap) other.fMap.clone(); + } + + /** + * Returns whether the map contains the given parameter + */ + public boolean contains(int parameterPosition) { + return fMap.containsKey(parameterPosition); + } + + /** + * Adds the mapping. + */ + public void put(int parameterPosition, ICPPEvaluation value) { + fMap.put(parameterPosition, value); + } + + /** + * Adds the mapping. + */ + public void put(int parameterPosition, ICPPEvaluation[] packExpansion) { + fMap.put(parameterPosition, packExpansion); + } + + /** + * Returns the value for the given parameter. + */ + public ICPPEvaluation getArgument(int parameterPosition) { + final Object object = fMap.get(parameterPosition); + if (object instanceof ICPPEvaluation) { + return (ICPPEvaluation) object; + } + return null; + } + + /** + * Returns the values for the given function parameter pack. + */ + public ICPPEvaluation[] getPackExpansion(int parameterPosition) { + final Object object = fMap.get(parameterPosition); + if (object instanceof ICPPEvaluation[]) { + return (ICPPEvaluation[]) object; + } + return null; + } + + /** + * Returns the argument at the given position + */ + public ICPPEvaluation getArgument(int parameterPosition, int packOffset) { + final Object object = fMap.get(parameterPosition); + if (object instanceof ICPPEvaluation) + return (ICPPEvaluation) object; + if (object instanceof ICPPEvaluation[]) { + ICPPEvaluation[] args = (ICPPEvaluation[]) object; + if (packOffset < args.length && packOffset >= 0) + return args[packOffset]; + } + return null; + } + + /** + * Puts all mappings from the supplied map into this map. + */ + public void putAll(CPPFunctionParameterMap map) { + final ObjectMap otherMap= map.fMap; + for (int i = 0; i < otherMap.size(); i++) { + fMap.put(otherMap.keyAt(i), otherMap.getAt(i)); + } + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index 0636d2829cb..877e605ba48 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -51,6 +51,7 @@ import org.eclipse.cdt.core.dom.ast.ISemanticProblem; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAliasDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAmbiguousTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; @@ -558,6 +559,8 @@ public class CPPTemplates { IASTDeclarator dtor = ((IASTFunctionDefinition) decl).getDeclarator(); dtor= ASTQueries.findInnermostDeclarator(dtor); name = dtor.getName(); + } else if (decl instanceof ICPPASTAliasDeclaration) { + name = ((ICPPASTAliasDeclaration) decl).getAlias(); } if (name == null) return null; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java index 7eb375ebeb2..b80e21c6f32 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinary.java @@ -347,6 +347,16 @@ public class EvalBinary extends CPPEvaluation { return new EvalBinary(fOperator, arg1, arg2); } + @Override + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + int maxdepth, IASTNode point) { + ICPPEvaluation arg1 = fArg1.computeForFunctionCall(parameterMap, maxdepth, point); + ICPPEvaluation arg2 = fArg2.computeForFunctionCall(parameterMap, maxdepth, point); + if (arg1 == fArg1 && arg2 == fArg2) + return this; + return new EvalBinary(fOperator, arg1, arg2); + } + @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { return CPPTemplates.combinePackSize(fArg1.determinePackSize(tpMap), fArg2.determinePackSize(tpMap)); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java index c9a0aa44f93..98dac57bcd6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinaryTypeId.java @@ -127,6 +127,12 @@ public class EvalBinaryTypeId extends CPPEvaluation { return new EvalBinaryTypeId(fOperator, type1, type2); } + @Override + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + int maxdepth, IASTNode point) { + return this; + } + @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { return CPPTemplates.combinePackSize(CPPTemplates.determinePackSize(fType1, tpMap), diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java index dbd8c1296a8..47a59ec9236 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java @@ -25,7 +25,9 @@ import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition; @@ -42,7 +44,22 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.core.runtime.CoreException; public class EvalBinding extends CPPEvaluation { - private final IBinding fBinding; + /** + * The function owning the parameter if the binding is a function parameter, otherwise + * {@code null}. May be computed lazily and remains {@code null} until computed. + */ + private ICPPFunction fParameterOwner; + /** + * The position of the parameter in the parameter list if the binding is a function parameter, + * otherwise -1. + */ + private int fParameterPosition; + /** + * The binding represented by this evaluation. For a function parameter binding may be computed + * lazily to avoid infinite recursion during unmarshalling of the evaluation. If #fBinding is + * {@code null}, {@link #fParameterOwner} is guaranteed to be not {@code null} and vice versa. + */ + private IBinding fBinding; private final boolean fFixedType; private IType fType; @@ -52,15 +69,79 @@ public class EvalBinding extends CPPEvaluation { private boolean fCheckedIsTypeDependent; public EvalBinding(IBinding binding, IType type) { + fParameterPosition = -1; fBinding= binding; fType= type; fFixedType= type != null; } + public EvalBinding(ICPPFunction parameterOwner, int parameterPosition, IType type) { + fParameterOwner = parameterOwner; + fParameterPosition = parameterPosition; + fType= type; + fFixedType= type != null; + } + public IBinding getBinding() { + if (fBinding == null) { + // fParameterOwner is guaranteed to be not null. + ICPPParameter[] parameters = fParameterOwner.getParameters(); + fBinding = parameters[fParameterPosition]; + } return fBinding; } + /** + * @return if the binding is a function parameter, returns its position in the parameter list, + * otherwise returns -1 + */ + public int getFunctionParameterPosition() { + if (fParameterPosition < 0) { + ICPPFunction parameterOwner = getParameterOwner(); + if (parameterOwner != null) { + ICPPParameter[] parameters = fParameterOwner.getParameters(); + fParameterPosition = findInArray(parameters, fBinding); + } + } + return fParameterPosition; + } + + /** + * @return the function owning the parameter if the binding is a function parameter, + * otherwise {@code null}. + */ + public ICPPFunction getParameterOwner() { + if (fParameterOwner == null && fBinding instanceof ICPPParameter) { + fParameterOwner = (ICPPFunction) ((ICPPParameter) fBinding).getOwner(); + } + return fParameterOwner; + } + + /** + * Finds a given object in an array. + * + * @param array the array to find the object in + * @param obj the object to find + * @return the index of the object in the array, or -1 if the object is not in the array + */ + private static int findInArray(Object[] array, Object obj) { + for (int i = 0; i < array.length; i++) { + if (obj == array[i]) + return i; + } + return -1; + } + + /** + * @return if the binding is a template parameter, returns its ID, otherwise returns -1 + */ + public int getTemplateParameterID() { + // No need to call getBinding method since fBinding cannot be null if the evaluation + // represents a template parameter. + return fBinding instanceof ICPPTemplateParameter ? + ((ICPPTemplateParameter) fBinding).getParameterID() : -1; + } + public IType getFixedType() { return fFixedType ? fType : null; } @@ -88,18 +169,21 @@ public class EvalBinding extends CPPEvaluation { IType t= null; if (fFixedType) { t = fType; - } else if (fBinding instanceof IEnumerator) { - t= ((IEnumerator) fBinding).getType(); - } else if (fBinding instanceof ICPPTemplateNonTypeParameter) { - t= ((ICPPTemplateNonTypeParameter) fBinding).getType(); - } else if (fBinding instanceof IVariable) { - t = ((IVariable) fBinding).getType(); - } else if (fBinding instanceof ICPPUnknownBinding) { - return true; - } else if (fBinding instanceof IFunction) { - t= ((IFunction) fBinding).getType(); - } else { - return false; + } else { + IBinding binding = getBinding(); + if (binding instanceof IEnumerator) { + t= ((IEnumerator) binding).getType(); + } else if (binding instanceof ICPPTemplateNonTypeParameter) { + t= ((ICPPTemplateNonTypeParameter) binding).getType(); + } else if (binding instanceof IVariable) { + t = ((IVariable) binding).getType(); + } else if (binding instanceof ICPPUnknownBinding) { + return true; + } else if (binding instanceof IFunction) { + t= ((IFunction) binding).getType(); + } else { + return false; + } } return CPPTemplates.isDependentType(t); } @@ -114,6 +198,7 @@ public class EvalBinding extends CPPEvaluation { } private boolean computeIsValueDependent() { + // No need to call getBinding() since a function parameter never has an initial value. if (fBinding instanceof IEnumerator) { return Value.isDependentValue(((IEnumerator) fBinding).getValue()); } @@ -141,23 +226,24 @@ public class EvalBinding extends CPPEvaluation { } private IType computeType(IASTNode point) { - if (fBinding instanceof IEnumerator) { - return ((IEnumerator) fBinding).getType(); + IBinding binding = getBinding(); + if (binding instanceof IEnumerator) { + return ((IEnumerator) binding).getType(); } - if (fBinding instanceof ICPPTemplateNonTypeParameter) { - IType type= ((ICPPTemplateNonTypeParameter) fBinding).getType(); + if (binding instanceof ICPPTemplateNonTypeParameter) { + IType type= ((ICPPTemplateNonTypeParameter) binding).getType(); if (CPPTemplates.isDependentType(type)) return new TypeOfDependentExpression(this); return prvalueType(type); } - if (fBinding instanceof IVariable) { - final IType type = ((IVariable) fBinding).getType(); + if (binding instanceof IVariable) { + final IType type = ((IVariable) binding).getType(); if (CPPTemplates.isDependentType(type)) return new TypeOfDependentExpression(this); return SemanticUtil.mapToAST(glvalueType(type), point); } - if (fBinding instanceof IFunction) { - final IFunctionType type = ((IFunction) fBinding).getType(); + if (binding instanceof IFunction) { + final IFunctionType type = ((IFunction) binding).getType(); if (CPPTemplates.isDependentType(type)) return new TypeOfDependentExpression(this); return SemanticUtil.mapToAST(type, point); @@ -171,6 +257,7 @@ public class EvalBinding extends CPPEvaluation { return Value.create(this); IValue value= null; + // No need to call getBinding() since a function parameter never has an initial value. if (fBinding instanceof IInternalVariable) { value= ((IInternalVariable) fBinding).getInitialValue(Value.MAX_RECURSION_DEPTH); } else if (fBinding instanceof IVariable) { @@ -189,7 +276,8 @@ public class EvalBinding extends CPPEvaluation { if (fBinding instanceof ICPPTemplateNonTypeParameter) return ValueCategory.PRVALUE; - if (fBinding instanceof IVariable || fBinding instanceof IFunction) { + // fBinding can be null only when the evaluation represents a function parameter. + if (fBinding instanceof IFunction || fBinding instanceof IVariable || fBinding == null) { return ValueCategory.LVALUE; } return ValueCategory.PRVALUE; @@ -197,22 +285,39 @@ public class EvalBinding extends CPPEvaluation { @Override public void marshal(ITypeMarshalBuffer buffer, boolean includeValue) throws CoreException { - buffer.putByte(ITypeMarshalBuffer.EVAL_BINDING); - buffer.marshalBinding(fBinding); + byte firstByte = ITypeMarshalBuffer.EVAL_BINDING; + ICPPFunction parameterOwner = getParameterOwner(); + if (parameterOwner != null) { + // A function parameter cannot be marshalled directly. We are storing the owning + // function and the parameter position instead. + buffer.putByte((byte) (ITypeMarshalBuffer.EVAL_BINDING | ITypeMarshalBuffer.FLAG1)); + buffer.marshalBinding(parameterOwner); + buffer.putShort((short) getFunctionParameterPosition()); + } else { + buffer.putByte(firstByte); + buffer.marshalBinding(fBinding); + } buffer.marshalType(fFixedType ? fType : null); } public static ISerializableEvaluation unmarshal(int firstByte, ITypeMarshalBuffer buffer) throws CoreException { - IBinding binding= buffer.unmarshalBinding(); - IType type= buffer.unmarshalType(); - return new EvalBinding(binding, type); + if ((firstByte & ITypeMarshalBuffer.FLAG1) != 0) { + ICPPFunction parameterOwner= (ICPPFunction) buffer.unmarshalBinding(); + int parameterPosition= buffer.getShort(); + IType type= buffer.unmarshalType(); + return new EvalBinding(parameterOwner, parameterPosition, type); + } else { + IBinding binding= buffer.unmarshalBinding(); + IType type= buffer.unmarshalType(); + return new EvalBinding(binding, type); + } } @Override public ICPPEvaluation instantiate(ICPPTemplateParameterMap tpMap, int packOffset, ICPPClassSpecialization within, int maxdepth, IASTNode point) { - IBinding binding = fBinding; - if (fBinding instanceof IEnumerator) { + IBinding binding = getBinding(); + if (binding instanceof IEnumerator) { IEnumerator enumerator = (IEnumerator) binding; IType originalType = enumerator.getType(); IType type = CPPTemplates.instantiateType(originalType, tpMap, packOffset, within, point); @@ -221,23 +326,23 @@ public class EvalBinding extends CPPEvaluation { // TODO(sprigogin): Not sure if following condition is correct. if (type != originalType || value != originalValue) return new EvalFixed(type, ValueCategory.PRVALUE, value); - } else if (fBinding instanceof ICPPTemplateNonTypeParameter) { - ICPPTemplateArgument argument = tpMap.getArgument((ICPPTemplateNonTypeParameter) fBinding); + } else if (binding instanceof ICPPTemplateNonTypeParameter) { + ICPPTemplateArgument argument = tpMap.getArgument((ICPPTemplateNonTypeParameter) binding); if (argument != null && argument.isNonTypeValue()) { return argument.getNonTypeEvaluation(); } // TODO(sprigogin): Do we need something similar for pack expansion? - } else if (fBinding instanceof ICPPUnknownBinding) { - binding = resolveUnknown((ICPPUnknownBinding) fBinding, tpMap, packOffset, within, point); - } else if (fBinding instanceof ICPPMethod) { - IBinding owner = fBinding.getOwner(); + } else if (binding instanceof ICPPUnknownBinding) { + binding = resolveUnknown((ICPPUnknownBinding) binding, tpMap, packOffset, within, point); + } else if (binding instanceof ICPPMethod) { + IBinding owner = binding.getOwner(); if (owner instanceof ICPPClassTemplate) { owner = resolveUnknown(CPPTemplates.createDeferredInstance((ICPPClassTemplate) owner), tpMap, packOffset, within, point); } if (owner instanceof ICPPClassSpecialization) { binding = CPPTemplates.createSpecialization((ICPPClassSpecialization) owner, - fBinding, point); + binding, point); } } if (binding == fBinding) @@ -245,21 +350,33 @@ public class EvalBinding extends CPPEvaluation { return new EvalBinding(binding, getFixedType()); } + @Override + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + int maxdepth, IASTNode point) { + int pos = getFunctionParameterPosition(); + if (pos >= 0) { + ICPPEvaluation eval = parameterMap.getArgument(pos); + if (eval != null) + return eval; + } + return this; + } + @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { - if (fBinding instanceof IEnumerator) { - return CPPTemplates.determinePackSize(((IEnumerator) fBinding).getValue(), tpMap); + IBinding binding = getBinding(); + if (binding instanceof IEnumerator) { + return CPPTemplates.determinePackSize(((IEnumerator) binding).getValue(), tpMap); } - if (fBinding instanceof ICPPTemplateNonTypeParameter) { - return CPPTemplates.determinePackSize((ICPPTemplateNonTypeParameter) fBinding, tpMap); + if (binding instanceof ICPPTemplateNonTypeParameter) { + return CPPTemplates.determinePackSize((ICPPTemplateNonTypeParameter) binding, tpMap); } - if (fBinding instanceof ICPPUnknownBinding) { - return CPPTemplates.determinePackSize((ICPPUnknownBinding) fBinding, tpMap); + if (binding instanceof ICPPUnknownBinding) { + return CPPTemplates.determinePackSize((ICPPUnknownBinding) binding, tpMap); } - IBinding binding = fBinding; - if (fBinding instanceof ICPPSpecialization) { - binding = ((ICPPSpecialization) fBinding).getSpecializedBinding(); + if (binding instanceof ICPPSpecialization) { + binding = ((ICPPSpecialization) binding).getSpecializedBinding(); } int r = CPPTemplates.PACK_SIZE_NOT_FOUND; @@ -275,6 +392,8 @@ public class EvalBinding extends CPPEvaluation { @Override public boolean referencesTemplateParameter() { + // No need to call getBinding method since fBinding cannot be null if the evaluation + // represents a template parameter. return fBinding instanceof ICPPTemplateParameter; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java index 9328c13ddcf..ea8d2a1ed97 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalComma.java @@ -189,6 +189,25 @@ public class EvalComma extends CPPEvaluation { return new EvalComma(args); } + @Override + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + int maxdepth, IASTNode point) { + ICPPEvaluation[] args = fArguments; + for (int i = 0; i < fArguments.length; i++) { + ICPPEvaluation arg = fArguments[i].computeForFunctionCall(parameterMap, maxdepth, point); + if (arg != fArguments[i]) { + if (args == fArguments) { + args = new ICPPEvaluation[fArguments.length]; + System.arraycopy(fArguments, 0, args, 0, fArguments.length); + } + args[i] = arg; + } + } + if (args == fArguments) + return this; + return new EvalComma(args); + } + @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { int r = CPPTemplates.PACK_SIZE_NOT_FOUND; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompound.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompound.java index dcc6c627d06..280e0f05d4b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompound.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalCompound.java @@ -94,6 +94,15 @@ public class EvalCompound extends CPPEvaluation { return new EvalCompound(delegate); } + @Override + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + int maxdepth, IASTNode point) { + ICPPEvaluation delegate = fDelegate.computeForFunctionCall(parameterMap, maxdepth, point); + if (delegate == fDelegate) + return this; + return new EvalCompound(delegate); + } + @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { return fDelegate.determinePackSize(tpMap); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java index f2a2370eba3..393c1f7c372 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java @@ -336,6 +336,18 @@ public class EvalConditional extends CPPEvaluation { return new EvalConditional(condition, positive, negative, fPositiveThrows, fNegativeThrows); } + @Override + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + int maxdepth, IASTNode point) { + ICPPEvaluation condition = fCondition.computeForFunctionCall(parameterMap, maxdepth, point); + ICPPEvaluation positive = fPositive == null ? + null : fPositive.computeForFunctionCall(parameterMap, maxdepth, point); + ICPPEvaluation negative = fNegative.computeForFunctionCall(parameterMap, maxdepth, point); + if (condition == fCondition && positive == fPositive && negative == fNegative) + return this; + return new EvalConditional(condition, positive, negative, fPositiveThrows, fNegativeThrows); + } + @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { int r = fCondition.determinePackSize(tpMap); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java index 22d07d9238a..343a7621f18 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java @@ -168,6 +168,18 @@ public class EvalFixed extends CPPEvaluation { return new EvalFixed(type, fValueCategory, value); } + @Override + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + int maxdepth, IASTNode point) { + ICPPEvaluation eval = fValue.getEvaluation(); + if (eval == null) + return this; + eval = eval.computeForFunctionCall(parameterMap, maxdepth, point); + if (eval == fValue.getEvaluation()) + return this; + return new EvalFixed(fType, fValueCategory, Value.create(eval)); + } + @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { return CPPTemplates.determinePackSize(fValue, tpMap); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java index 5ca58c483d2..6218a972870 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionCall.java @@ -11,6 +11,7 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; +import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.typeFromReturnType; 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.valueCategoryFromReturnType; @@ -22,6 +23,7 @@ import java.util.Arrays; import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IType; @@ -29,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; 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.ICPPParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; @@ -139,8 +142,11 @@ public class EvalFunctionCall extends CPPEvaluation { @Override public IValue getValue(IASTNode point) { - // TODO(sprigogin): Simulate execution of a function call if the value is not dependent. - return Value.create(this); + ICPPEvaluation eval = computeForFunctionCall(Value.MAX_RECURSION_DEPTH, point); + if (eval instanceof EvalFixed) + return ((EvalFixed) eval).getValue(); + eval = new EvalFixed(getTypeOrFunctionSet(point), PRVALUE, eval.getValue(point)); + return Value.create(eval); } @Override @@ -201,6 +207,70 @@ public class EvalFunctionCall extends CPPEvaluation { return new EvalFunctionCall(args); } + @Override + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + int maxdepth, IASTNode point) { + if (maxdepth == 0) + return EvalFixed.INCOMPLETE; + + ICPPEvaluation[] args = fArguments; + for (int i = 0; i < fArguments.length; i++) { + ICPPEvaluation arg = fArguments[i].computeForFunctionCall(parameterMap, maxdepth, point); + if (arg != fArguments[i]) { + if (args == fArguments) { + args = new ICPPEvaluation[fArguments.length]; + System.arraycopy(fArguments, 0, args, 0, fArguments.length); + } + args[i] = arg; + } + } + EvalFunctionCall eval = this; + if (args != fArguments) + eval = new EvalFunctionCall(args); + return eval.computeForFunctionCall(maxdepth - 1, point); + } + + private ICPPEvaluation computeForFunctionCall(int maxdepth, IASTNode point) { + if (isValueDependent()) + return this; + ICPPFunction function = getOverload(point); + if (function == null) { + if (fArguments[0] instanceof EvalBinding) { + IBinding binding = ((EvalBinding) fArguments[0]).getBinding(); + if (binding instanceof ICPPFunction) + function = (ICPPFunction) binding; + } + } + if (function == null) + return this; + ICPPEvaluation eval = CPPFunction.getReturnExpression(function); + if (eval == null) + return EvalFixed.INCOMPLETE; + CPPFunctionParameterMap parameterMap = buildParameterMap(function); + return eval.computeForFunctionCall(parameterMap, maxdepth, point); + } + + private CPPFunctionParameterMap buildParameterMap(ICPPFunction function) { + ICPPParameter[] parameters = function.getParameters(); + CPPFunctionParameterMap map = new CPPFunctionParameterMap(parameters.length); + int j = 1; + for (int i = 0; i < parameters.length; i++) { + ICPPParameter param = parameters[i]; + if (param.isParameterPack()) { + // The parameter pack consumes all remaining arguments. + j = fArguments.length; + } else { + if (j < fArguments.length) { + map.put(i, fArguments[j++]); + } else if (param.hasDefaultValue()) { + IValue value = param.getInitialValue(); + map.put(i, value.getEvaluation()); + } + } + } + return map; + } + @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { int r = CPPTemplates.PACK_SIZE_NOT_FOUND; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java index 881db03f857..4e16f5a0751 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFunctionSet.java @@ -170,6 +170,12 @@ public class EvalFunctionSet extends CPPEvaluation { return new EvalFunctionSet(new CPPFunctionSet(functions, arguments, null), fAddressOf); } + @Override + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + int maxdepth, IASTNode point) { + return this; + } + /** * Attempts to resolve the function using the parameters of a function call. * diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java index 4cbea3195e5..501189404f1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java @@ -309,6 +309,17 @@ public class EvalID extends CPPEvaluation { return new EvalID(fieldOwner, nameOwner, fName, fAddressOf, fQualified, templateArgs); } + @Override + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + int maxdepth, IASTNode point) { + if (fFieldOwner == null) + return this; + ICPPEvaluation fieldOwner = fFieldOwner.computeForFunctionCall(parameterMap, maxdepth, point); + if (fieldOwner == fFieldOwner) + return this; + return new EvalID(fieldOwner, fNameOwner, fName, fAddressOf, fQualified, fTemplateArgs); + } + private ICPPEvaluation resolveName(ICPPClassType nameOwner, ICPPTemplateArgument[] templateArgs, IASTNode point) { LookupData data = new LookupData(fName, templateArgs, point); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java index 02eb709506e..996f71a9e62 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalInitList.java @@ -121,6 +121,25 @@ public class EvalInitList extends CPPEvaluation { return new EvalInitList(clauses); } + @Override + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + int maxdepth, IASTNode point) { + ICPPEvaluation[] clauses = fClauses; + for (int i = 0; i < fClauses.length; i++) { + ICPPEvaluation clause = fClauses[i].computeForFunctionCall(parameterMap, maxdepth, point); + if (clause != fClauses[i]) { + if (clauses == fClauses) { + clauses = new ICPPEvaluation[fClauses.length]; + System.arraycopy(fClauses, 0, clauses, 0, fClauses.length); + } + clauses[i] = clause; + } + } + if (clauses == fClauses) + return this; + return new EvalInitList(clauses); + } + @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { int r = CPPTemplates.PACK_SIZE_NOT_FOUND; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java index 61652be2b55..88d935356fb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalMemberAccess.java @@ -334,6 +334,12 @@ public class EvalMemberAccess extends CPPEvaluation { return new EvalMemberAccess(ownerType, fOwnerValueCategory, member, fIsPointerDeref); } + @Override + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + int maxdepth, IASTNode point) { + return this; + } + @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { return CPPTemplates.determinePackSize(fOwnerType, tpMap); 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 41a0fce27aa..62f713dc1b9 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 @@ -165,6 +165,27 @@ public class EvalTypeId extends CPPEvaluation { return new EvalTypeId(type, args); } + @Override + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + int maxdepth, IASTNode point) { + ICPPEvaluation[] args = fArguments; + if (fArguments != null) { + for (int i = 0; i < fArguments.length; i++) { + ICPPEvaluation arg = fArguments[i].computeForFunctionCall(parameterMap, maxdepth, point); + if (arg != fArguments[i]) { + if (args == fArguments) { + args = new ICPPEvaluation[fArguments.length]; + System.arraycopy(fArguments, 0, args, 0, fArguments.length); + } + args[i] = arg; + } + } + } + if (args == fArguments) + return this; + return new EvalTypeId(fInputType, args); + } + @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { int r = CPPTemplates.determinePackSize(fInputType, tpMap); 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 d7b56564e80..a2d61ae8497 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 @@ -324,6 +324,16 @@ public class EvalUnary extends CPPEvaluation { return new EvalUnary(fOperator, argument, aoqn); } + @Override + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + int maxdepth, IASTNode point) { + ICPPEvaluation argument = fArgument.computeForFunctionCall(parameterMap, maxdepth, point); + if (argument == fArgument) + return this; + + return new EvalUnary(fOperator, argument, fAddressOfQualifiedNameBinding); + } + @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { return fArgument.determinePackSize(tpMap); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java index 06eb32de63f..9d2e39b7e52 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java @@ -190,6 +190,12 @@ public class EvalUnaryTypeID extends CPPEvaluation { return new EvalUnaryTypeID(fOperator, type); } + @Override + public ICPPEvaluation computeForFunctionCall(CPPFunctionParameterMap parameterMap, + int maxdepth, IASTNode point) { + return this; + } + @Override public int determinePackSize(ICPPTemplateParameterMap tpMap) { return CPPTemplates.determinePackSize(fOrigType, tpMap); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java index 66d8f36bef8..32d8fe65cdc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CPPCompositesFactory.java @@ -8,6 +8,7 @@ * Contributors: * Andrew Ferguson (Symbian) - Initial implementation * Markus Schorn (Wind River Systems) + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.index.composite.cpp; @@ -255,13 +256,24 @@ public class CPPCompositesFactory extends AbstractCompositeFactory { } if (eval instanceof EvalBinding) { EvalBinding e= (EvalBinding) eval; - IBinding a = e.getBinding(); - IType b = e.getFixedType(); - - IBinding a2 = getCompositeBinding((IIndexFragmentBinding) a); - IType b2 = getCompositeType(b); - if (a != a2 || b != b2) - e= new EvalBinding(a2, b2); + ICPPFunction parameterOwner = e.getParameterOwner(); + if (parameterOwner != null) { + IType b = e.getFixedType(); + IBinding a2 = getCompositeBinding((IIndexFragmentBinding) parameterOwner); + IType b2 = getCompositeType(b); + if (parameterOwner != a2 || b != b2) { + int parameterPosition = e.getFunctionParameterPosition(); + e= new EvalBinding((ICPPFunction) a2, parameterPosition, b2); + } + } else { + IBinding a = e.getBinding(); + IType b = e.getFixedType(); + + IBinding a2 = getCompositeBinding((IIndexFragmentBinding) a); + IType b2 = getCompositeType(b); + if (a != a2 || b != b2) + e= new EvalBinding(a2, b2); + } return e; } if (eval instanceof EvalComma) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunction.java index 2e5a3d68f34..c560bf398e0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/index/composite/cpp/CompositeCPPFunction.java @@ -18,10 +18,13 @@ import org.eclipse.cdt.core.dom.ast.IType; 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.ICPPParameter; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPComputableFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding; import org.eclipse.cdt.internal.core.index.composite.ICompositesFactory; -class CompositeCPPFunction extends CompositeCPPBinding implements ICPPFunction { +class CompositeCPPFunction extends CompositeCPPBinding implements ICPPFunction, ICPPComputableFunction { public CompositeCPPFunction(ICompositesFactory cf, ICPPFunction rbinding) { super(cf, rbinding); @@ -42,6 +45,11 @@ class CompositeCPPFunction extends CompositeCPPBinding implements ICPPFunction { return ((ICPPFunction) rbinding).isMutable(); } + @Override + public boolean isConstexpr() { + return ((ICPPFunction) rbinding).isConstexpr(); + } + @Override public IScope getFunctionScope() { return null; @@ -129,4 +137,9 @@ class CompositeCPPFunction extends CompositeCPPBinding implements ICPPFunction { } return result; } + + @Override + public ICPPEvaluation getReturnExpression() { + return CPPFunction.getReturnExpression((ICPPFunction) rbinding); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java index ce6207bed17..18848bc3c32 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/PDOM.java @@ -221,10 +221,11 @@ public class PDOM extends PlatformObject implements IPDOM { * 127.0 - Explicit virtual overrides, bug 380623. * 128.0 - Preservation of typedefs in template arguments. * 129.0 - Merged several changes affecting index from the master branch. + * 130.0 - Constexpr functions, bug 395238. */ - private static final int MIN_SUPPORTED_VERSION= version(129, 0); - private static final int MAX_SUPPORTED_VERSION= version(129, Short.MAX_VALUE); - private static final int DEFAULT_VERSION = version(129, 0); + private static final int MIN_SUPPORTED_VERSION= version(130, 0); + private static final int MAX_SUPPORTED_VERSION= version(130, Short.MAX_VALUE); + private static final int DEFAULT_VERSION = version(130, 0); private static int version(int major, int minor) { return (major << 16) + minor; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java index 4963a86f84e..86870f1e5cc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/Database.java @@ -78,6 +78,7 @@ public class Database { public static final int PTR_SIZE = 4; // size of a pointer in the database in bytes public static final int TYPE_SIZE = 2 + PTR_SIZE; // size of a type in the database in bytes public static final int VALUE_SIZE = TYPE_SIZE; // size of a value in the database in bytes + public static final int EVALUATION_SIZE = TYPE_SIZE; // size of an evaluation in the database in bytes public static final int ARGUMENT_SIZE = TYPE_SIZE; // size of a template argument in the database in bytes public static final long MAX_DB_SIZE= ((long) 1 << (Integer.SIZE + BLOCK_SIZE_DELTA_BITS)); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/TypeMarshalBuffer.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/TypeMarshalBuffer.java index d5294c33b68..c82ed116aa4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/TypeMarshalBuffer.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/db/TypeMarshalBuffer.java @@ -26,8 +26,8 @@ import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateNonTypeArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeArgument; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; -import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage; +import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; import org.eclipse.core.runtime.CoreException; /** @@ -80,7 +80,7 @@ public class TypeMarshalBuffer implements ITypeMarshalBuffer { } else if (binding == null) { putByte(NULL_TYPE); } else { - PDOMBinding pb= fLinkage.addTypeBinding(binding); + PDOMNode pb= fLinkage.addTypeBinding(binding); if (pb == null) { putByte(UNSTORABLE_TYPE); } else { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java index 2bdfc076faf..7c699dfc9b3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/PDOMLinkage.java @@ -423,7 +423,7 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage return map; } - public abstract PDOMBinding addTypeBinding(IBinding type) throws CoreException; + public abstract PDOMBinding addTypeBinding(IBinding binding) throws CoreException; public abstract IType unmarshalType(ITypeMarshalBuffer buffer) throws CoreException; public abstract IBinding unmarshalBinding(ITypeMarshalBuffer buffer) throws CoreException; public abstract ISerializableEvaluation unmarshalEvaluation(ITypeMarshalBuffer typeMarshalBuffer) throws CoreException; @@ -633,9 +633,41 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage } public IValue loadValue(long offset) throws CoreException { + TypeMarshalBuffer buffer = loadBuffer(offset, Database.VALUE_SIZE); + if (buffer == null) + return null; + return buffer.unmarshalValue(); + } + + public void storeEvaluation(long offset, ISerializableEvaluation eval) throws CoreException { + final Database db= getDB(); + deleteEvaluation(db, offset); + storeEvaluation(db, offset, eval); + } + + private void storeEvaluation(Database db, long offset, ISerializableEvaluation eval) throws CoreException { + if (eval != null) { + TypeMarshalBuffer bc= new TypeMarshalBuffer(this); + bc.marshalEvaluation(eval, true); + storeBuffer(db, offset, bc, Database.EVALUATION_SIZE); + } + } + + private void deleteEvaluation(Database db, long offset) throws CoreException { + deleteSerializedData(db, offset, Database.EVALUATION_SIZE); + } + + public ISerializableEvaluation loadEvaluation(long offset) throws CoreException { + TypeMarshalBuffer buffer = loadBuffer(offset, Database.EVALUATION_SIZE); + if (buffer == null) + return null; + return buffer.unmarshalEvaluation(); + } + + private TypeMarshalBuffer loadBuffer(long offset, int size) throws CoreException { final Database db= getDB(); final byte firstByte= db.getByte(offset); - byte[] data= null; + byte[] data; switch (firstByte) { case TypeMarshalBuffer.INDIRECT_TYPE: data = loadLinkedSerializedData(db, offset + 1); @@ -643,13 +675,13 @@ public abstract class PDOMLinkage extends PDOMNamedNode implements IIndexLinkage case TypeMarshalBuffer.NULL_TYPE: return null; default: - data= new byte[Database.VALUE_SIZE]; + data= new byte[size]; db.getBytes(offset, data); break; } - return new TypeMarshalBuffer(this, data).unmarshalValue(); + return new TypeMarshalBuffer(this, data); } - + public IIndexScope[] getInlineNamespaces() { return IIndexScope.EMPTY_INDEX_SCOPE_ARRAY; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPAliasTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPAliasTemplate.java index 7cf0c3c4971..2383af9629a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPAliasTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPAliasTemplate.java @@ -8,6 +8,7 @@ * * Contributors: * Thomas Corbat (IFS) - Initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; @@ -15,7 +16,10 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplate; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode; @@ -24,39 +28,38 @@ import org.eclipse.core.runtime.CoreException; /** * PDOM binding for alias template. */ -class PDOMCPPAliasTemplate extends PDOMCPPBinding implements ICPPAliasTemplate { +class PDOMCPPAliasTemplate extends PDOMCPPBinding implements ICPPAliasTemplate, IPDOMCPPTemplateParameterOwner { private static final int ALIASED_TYPE_SIZE = Database.TYPE_SIZE; private static final int TEMPLATE_PARAMS_SIZE = PDOMCPPTemplateTemplateParameter.RECORD_SIZE; @SuppressWarnings("hiding") protected static final int RECORD_SIZE = PDOMCPPBinding.RECORD_SIZE + ALIASED_TYPE_SIZE + TEMPLATE_PARAMS_SIZE; - private static final int ALIASED_TYPE_OFFSET = PDOMCPPBinding.RECORD_SIZE + 0; - private static final int TEMPLATE_PARAMS_OFFSET = ALIASED_TYPE_OFFSET + ALIASED_TYPE_SIZE; + private static final int ALIASED_TYPE = PDOMCPPBinding.RECORD_SIZE + 0; + private static final int TEMPLATE_PARAMS = ALIASED_TYPE + ALIASED_TYPE_SIZE; private volatile IPDOMCPPTemplateParameter[] parameters; - public PDOMCPPAliasTemplate(PDOMCPPLinkage linkage, PDOMNode parent, - ICPPAliasTemplate templateAlias) throws CoreException, DOMException { - super(linkage, parent, templateAlias.getNameCharArray()); - setTemplateParameters(linkage, templateAlias.getTemplateParameters()); - setType(linkage, templateAlias.getType()); + public PDOMCPPAliasTemplate(PDOMCPPLinkage linkage, PDOMNode parent, ICPPAliasTemplate template) + throws CoreException, DOMException { + super(linkage, parent, template.getNameCharArray()); + final ICPPTemplateParameter[] origParams= template.getTemplateParameters(); + parameters = PDOMTemplateParameterArray.createPDOMTemplateParameters(linkage, this, origParams); + final Database db = getDB(); + long rec= PDOMTemplateParameterArray.putArray(db, parameters); + db.putRecPtr(record + TEMPLATE_PARAMS, rec); + linkage.new ConfigureAliasTemplate(template, this); } public PDOMCPPAliasTemplate(PDOMCPPLinkage linkage, long record) { super(linkage, record); } - private void setTemplateParameters(PDOMCPPLinkage linkage, - final ICPPTemplateParameter[] origParams) throws CoreException, DOMException { - parameters = PDOMTemplateParameterArray.createPDOMTemplateParameters(linkage, this, origParams); - final Database db = getDB(); - long rec= PDOMTemplateParameterArray.putArray(db, parameters); - db.putRecPtr(record + TEMPLATE_PARAMS_OFFSET, rec); - linkage.new ConfigureTemplateParameters(origParams, parameters); - } - - private void setType(PDOMCPPLinkage linkage, IType aliasedType) throws CoreException { - linkage.storeType(record + ALIASED_TYPE_OFFSET, aliasedType); + public void initData(IType aliasedType) { + try { + getLinkage().storeType(record + ALIASED_TYPE, aliasedType); + } catch (CoreException e) { + CCorePlugin.log(e); + } } @Override @@ -74,11 +77,11 @@ class PDOMCPPAliasTemplate extends PDOMCPPBinding implements ICPPAliasTemplate { } @Override - public ICPPTemplateParameter[] getTemplateParameters() { + public IPDOMCPPTemplateParameter[] getTemplateParameters() { if (parameters == null) { try { Database db = getDB(); - long rec= db.getRecPtr(record + TEMPLATE_PARAMS_OFFSET); + long rec= db.getRecPtr(record + TEMPLATE_PARAMS); if (rec == 0) { parameters= IPDOMCPPTemplateParameter.EMPTY_ARRAY; } else { @@ -95,7 +98,7 @@ class PDOMCPPAliasTemplate extends PDOMCPPBinding implements ICPPAliasTemplate { @Override public IType getType() { try { - return getLinkage().loadType(record + ALIASED_TYPE_OFFSET); + return getLinkage().loadType(record + ALIASED_TYPE); } catch (CoreException e) { CCorePlugin.log(e); return null; @@ -115,4 +118,27 @@ class PDOMCPPAliasTemplate extends PDOMCPPBinding implements ICPPAliasTemplate { } return null; } + + @Override + public ICPPTemplateParameter adaptTemplateParameter(ICPPTemplateParameter param) { + // Template parameters are identified by their position in the parameter list. + int pos = param.getParameterPosition(); + ICPPTemplateParameter[] pars = getTemplateParameters(); + + if (pars == null || pos >= pars.length) + return null; + + ICPPTemplateParameter result= pars[pos]; + if (param instanceof ICPPTemplateTypeParameter) { + if (result instanceof ICPPTemplateTypeParameter) + return result; + } else if (param instanceof ICPPTemplateNonTypeParameter) { + if (result instanceof ICPPTemplateNonTypeParameter) + return result; + } else if (param instanceof ICPPTemplateTemplateParameter) { + if (result instanceof ICPPTemplateTemplateParameter) + return result; + } + return null; + } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructor.java index 5d2712b0bd4..267565bf2b0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPConstructor.java @@ -6,7 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Markus Schorn - initial API and implementation + * Markus Schorn - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; @@ -20,7 +20,7 @@ import org.eclipse.core.runtime.CoreException; class PDOMCPPConstructor extends PDOMCPPMethod implements ICPPConstructor { - public PDOMCPPConstructor(PDOMLinkage linkage, PDOMNode parent, ICPPConstructor method) + public PDOMCPPConstructor(PDOMCPPLinkage linkage, PDOMNode parent, ICPPConstructor method) throws CoreException, DOMException { super(linkage, parent, method); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunction.java index 9edcbf37948..2e87ba1d8b4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunction.java @@ -24,6 +24,9 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.internal.core.dom.parser.ProblemFunctionType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPComputableFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.index.IndexCPPSignatureUtil; import org.eclipse.cdt.internal.core.pdom.db.Database; @@ -37,9 +40,10 @@ import org.eclipse.core.runtime.CoreException; /** * Binding for c++ functions in the index. */ -class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverloader { +class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverloader, ICPPComputableFunction { private static final short ANNOT_PARAMETER_PACK = 8; private static final short ANNOT_IS_DELETED = 9; + private static final short ANNOT_IS_CONSTEXPR = 10; /** * Offset of total number of function parameters (relative to the beginning of the record). @@ -72,28 +76,31 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl */ private static final int ANNOTATION = EXCEPTION_SPEC + Database.PTR_SIZE; // short - private static final int REQUIRED_ARG_COUNT = ANNOTATION + 2; + /** Offset of the number of the required arguments. */ + private static final int REQUIRED_ARG_COUNT = ANNOTATION + 2; // short + /** Offset of the return expression for constexpr functions. */ + private static final int RETURN_EXPRESSION = REQUIRED_ARG_COUNT + 2; // Database.EVALUATION_SIZE /** * The size in bytes of a PDOMCPPFunction record in the database. */ @SuppressWarnings("hiding") - protected static final int RECORD_SIZE = REQUIRED_ARG_COUNT + 4; + protected static final int RECORD_SIZE = RETURN_EXPRESSION + Database.EVALUATION_SIZE; private short fAnnotation = -1; private int fRequiredArgCount = -1; private ICPPFunctionType fType; // No need for volatile, all fields of ICPPFunctionTypes are final. - public PDOMCPPFunction(PDOMLinkage linkage, PDOMNode parent, ICPPFunction function, + public PDOMCPPFunction(PDOMCPPLinkage linkage, PDOMNode parent, ICPPFunction function, boolean setTypes) throws CoreException, DOMException { super(linkage, parent, function.getNameCharArray()); Database db = getDB(); Integer sigHash = IndexCPPSignatureUtil.getSignatureHash(function); getDB().putInt(record + SIGNATURE_HASH, sigHash != null ? sigHash.intValue() : 0); db.putShort(record + ANNOTATION, getAnnotation(function)); - db.putInt(record + REQUIRED_ARG_COUNT, function.getRequiredArgumentCount()); + db.putShort(record + REQUIRED_ARG_COUNT, (short) function.getRequiredArgumentCount()); if (setTypes) { - initData(function.getType(), function.getParameters(), extractExceptionSpec(function)); + linkage.new ConfigureFunction(function, this); } } @@ -105,14 +112,19 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl if (function.isDeleted()) { annot |= (1 << ANNOT_IS_DELETED); } + if (function.isConstexpr()) { + annot |= (1 << ANNOT_IS_CONSTEXPR); + } return (short) annot; } - public void initData(ICPPFunctionType ftype, ICPPParameter[] params, IType[] exceptionSpec) { + public void initData(ICPPFunctionType ftype, ICPPParameter[] params, IType[] exceptionSpec, + ICPPEvaluation returnExpression) { try { setType(ftype); setParameters(params); storeExceptionSpec(exceptionSpec); + getLinkage().storeEvaluation(record + RETURN_EXPRESSION, returnExpression); } catch (CoreException e) { CCorePlugin.log(e); } @@ -120,57 +132,59 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl @Override public void update(final PDOMLinkage linkage, IBinding newBinding) throws CoreException { - if (newBinding instanceof ICPPFunction) { - ICPPFunction func = (ICPPFunction) newBinding; - ICPPFunctionType newType; - ICPPParameter[] newParams; - short newAnnotation; - int newBindingRequiredArgCount; - newType = func.getType(); - newParams = func.getParameters(); - newAnnotation = getAnnotation(func); - newBindingRequiredArgCount = func.getRequiredArgumentCount(); + if (!(newBinding instanceof ICPPFunction)) + return; - fType = null; - linkage.storeType(record + FUNCTION_TYPE, newType); + ICPPFunction func = (ICPPFunction) newBinding; + ICPPFunctionType newType; + ICPPParameter[] newParams; + short newAnnotation; + int newBindingRequiredArgCount; + newType = func.getType(); + newParams = func.getParameters(); + newAnnotation = getAnnotation(func); + newBindingRequiredArgCount = func.getRequiredArgumentCount(); - PDOMCPPParameter oldParams = getFirstParameter(null); - int requiredCount; - if (oldParams != null && hasDeclaration()) { - int parCount = 0; - requiredCount = 0; - for (ICPPParameter newPar : newParams) { - parCount++; - if (parCount <= newBindingRequiredArgCount && !oldParams.hasDefaultValue()) - requiredCount = parCount; - oldParams.update(newPar); - long next = oldParams.getNextPtr(); - if (next == 0) - break; - oldParams = new PDOMCPPParameter(linkage, next, null); - } - if (parCount < newBindingRequiredArgCount) { - requiredCount = newBindingRequiredArgCount; - } - } else { - requiredCount = newBindingRequiredArgCount; - setParameters(newParams); - if (oldParams != null) { - oldParams.delete(linkage); - } + fType = null; + linkage.storeType(record + FUNCTION_TYPE, newType); + + PDOMCPPParameter oldParams = getFirstParameter(null); + int requiredCount; + if (oldParams != null && hasDeclaration()) { + int parCount = 0; + requiredCount = 0; + for (ICPPParameter newPar : newParams) { + parCount++; + if (parCount <= newBindingRequiredArgCount && !oldParams.hasDefaultValue()) + requiredCount = parCount; + oldParams.update(newPar); + long next = oldParams.getNextPtr(); + if (next == 0) + break; + oldParams = new PDOMCPPParameter(linkage, next, null); } - final Database db = getDB(); - db.putShort(record + ANNOTATION, newAnnotation); - fAnnotation = newAnnotation; - db.putInt(record + REQUIRED_ARG_COUNT, requiredCount); - fRequiredArgCount = requiredCount; - - long oldRec = db.getRecPtr(record + EXCEPTION_SPEC); - storeExceptionSpec(extractExceptionSpec(func)); - if (oldRec != 0) { - PDOMCPPTypeList.clearTypes(this, oldRec); + if (parCount < newBindingRequiredArgCount) { + requiredCount = newBindingRequiredArgCount; + } + } else { + requiredCount = newBindingRequiredArgCount; + setParameters(newParams); + if (oldParams != null) { + oldParams.delete(linkage); } } + final Database db = getDB(); + db.putShort(record + ANNOTATION, newAnnotation); + fAnnotation = newAnnotation; + db.putShort(record + REQUIRED_ARG_COUNT, (short) requiredCount); + fRequiredArgCount = requiredCount; + + long oldRec = db.getRecPtr(record + EXCEPTION_SPEC); + storeExceptionSpec(extractExceptionSpec(func)); + if (oldRec != 0) { + PDOMCPPTypeList.clearTypes(this, oldRec); + } + linkage.storeEvaluation(record + RETURN_EXPRESSION, CPPFunction.getReturnExpression(func)); } private void storeExceptionSpec(IType[] exceptionSpec) throws CoreException { @@ -243,7 +257,7 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl public int getRequiredArgumentCount() { if (fRequiredArgCount == -1) { try { - fRequiredArgCount = getDB().getInt(record + REQUIRED_ARG_COUNT); + fRequiredArgCount = getDB().getShort(record + REQUIRED_ARG_COUNT); } catch (CoreException e) { fRequiredArgCount = 0; } @@ -321,6 +335,11 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl return false; } + @Override + public boolean isConstexpr() { + return getBit(getAnnotation(), ANNOT_IS_CONSTEXPR); + } + @Override public boolean isDeleted() { return getBit(getAnnotation(), ANNOT_IS_DELETED); @@ -394,4 +413,17 @@ class PDOMCPPFunction extends PDOMCPPBinding implements ICPPFunction, IPDOMOverl return null; } } + + @Override + public ICPPEvaluation getReturnExpression() { + if (!isConstexpr()) + return null; + + try { + return (ICPPEvaluation) getLinkage().loadEvaluation(record + RETURN_EXPRESSION); + } catch (CoreException e) { + CCorePlugin.log(e); + return null; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionSpecialization.java index 947ed44409d..8698367b01b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPFunctionSpecialization.java @@ -23,6 +23,9 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.internal.core.dom.parser.ProblemFunctionType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPComputableFunction; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.pdom.db.Database; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; @@ -34,7 +37,8 @@ import org.eclipse.core.runtime.CoreException; /** * Binding for function specialization in the index. */ -class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization implements ICPPFunction { +class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization + implements ICPPFunction, ICPPComputableFunction { /** * Offset of total number of function parameters (relative to the beginning of the record). */ @@ -59,24 +63,29 @@ class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization implements ICP /** * Offset of annotation information (relative to the beginning of the record). */ - protected static final int ANNOTATION_OFFSET = EXCEPTION_SPEC + Database.PTR_SIZE; // short - - private static final int REQUIRED_ARG_COUNT_OFFSET= ANNOTATION_OFFSET + 2; + protected static final int ANNOTATION = EXCEPTION_SPEC + Database.PTR_SIZE; // short + /** Offset of the number of the required arguments. */ + private static final int REQUIRED_ARG_COUNT = ANNOTATION + 2; // short + + /** Offset of the return expression for constexpr functions. */ + private static final int RETURN_EXPRESSION = REQUIRED_ARG_COUNT + 2; // Database.EVALUATION_SIZE /** - * The size in bytes of a PDOMCPPFunction record in the database. + * The size in bytes of a PDOMCPPFunctionSpecialization record in the database. */ @SuppressWarnings("hiding") - protected static final int RECORD_SIZE = REQUIRED_ARG_COUNT_OFFSET + 4; + protected static final int RECORD_SIZE = RETURN_EXPRESSION + Database.EVALUATION_SIZE; private static final short ANNOT_PARAMETER_PACK = 8; private static final short ANNOT_IS_DELETED = 9; + private static final short ANNOT_IS_CONSTEXPR = 10; private ICPPFunctionType fType; // No need for volatile, all fields of ICPPFunctionTypes are final. private short fAnnotation= -1; private int fRequiredArgCount= -1; - public PDOMCPPFunctionSpecialization(PDOMLinkage linkage, PDOMNode parent, ICPPFunction astFunction, PDOMBinding specialized) throws CoreException { + public PDOMCPPFunctionSpecialization(PDOMLinkage linkage, PDOMNode parent, ICPPFunction astFunction, + PDOMBinding specialized) throws CoreException { super(linkage, parent, (ICPPSpecialization) astFunction, specialized); Database db = getDB(); @@ -112,8 +121,12 @@ class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization implements ICP db.putRecPtr(record + FIRST_PARAM, next == null ? 0 : next.getRecord()); } fAnnotation = getAnnotation(astFunction); - db.putShort(record + ANNOTATION_OFFSET, fAnnotation); - db.putInt(record + REQUIRED_ARG_COUNT_OFFSET, astFunction.getRequiredArgumentCount()); + db.putShort(record + ANNOTATION, fAnnotation); + db.putShort(record + REQUIRED_ARG_COUNT , (short) astFunction.getRequiredArgumentCount()); + ICPPEvaluation returnExpression = CPPFunction.getReturnExpression(astFunction); + if (returnExpression != null) { + linkage.storeEvaluation(record + RETURN_EXPRESSION, returnExpression); + } long typelist= 0; if (astFunction instanceof ICPPMethod && ((ICPPMethod) astFunction).isImplicit()) { // Don't store the exception specification, it is computed on demand. @@ -131,6 +144,9 @@ class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization implements ICP if (astFunction.isDeleted()) { annot |= (1 << ANNOT_IS_DELETED); } + if (astFunction.isConstexpr()) { + annot |= (1 << ANNOT_IS_CONSTEXPR); + } return (short) annot; } @@ -156,7 +172,7 @@ class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization implements ICP private short readAnnotation() { if (fAnnotation == -1) { try { - fAnnotation= getDB().getShort(record + ANNOTATION_OFFSET); + fAnnotation= getDB().getShort(record + ANNOTATION); } catch (CoreException e) { fAnnotation= 0; } @@ -219,6 +235,11 @@ class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization implements ICP return false; } + @Override + public boolean isConstexpr() { + return getBit(readAnnotation(), ANNOT_IS_CONSTEXPR); + } + @Override public boolean isExtern() { return getBit(readAnnotation(), PDOMCAnnotation.EXTERN_OFFSET); @@ -254,7 +275,7 @@ class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization implements ICP public int getRequiredArgumentCount() { if (fRequiredArgCount == -1) { try { - fRequiredArgCount= getDB().getInt(record + REQUIRED_ARG_COUNT_OFFSET); + fRequiredArgCount= getDB().getShort(record + REQUIRED_ARG_COUNT ); } catch (CoreException e) { fRequiredArgCount= 0; } @@ -300,4 +321,17 @@ class PDOMCPPFunctionSpecialization extends PDOMCPPSpecialization implements ICP return null; } } + + @Override + public ICPPEvaluation getReturnExpression() { + if (!isConstexpr()) + return null; + + try { + return (ICPPEvaluation) getLinkage().loadEvaluation(record + RETURN_EXPRESSION); + } catch (CoreException e) { + CCorePlugin.log(e); + return null; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index 920b06a2789..837a013eaa8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -42,6 +42,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplate; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplateInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; @@ -61,8 +63,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplate; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplateInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; @@ -79,21 +79,23 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPAliasTemplateInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArrayType; 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.CPPDeferredClassInstance; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPParameterPackType; 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.CPPQualifierType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType; -import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPAliasTemplateInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMember; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalBinary; @@ -219,6 +221,29 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { } } + class ConfigureFunction implements Runnable { + private final PDOMCPPFunction fFunction; + private final ICPPFunctionType fOriginalFunctionType; + private final ICPPParameter[] fOriginalParameters; + private final IType[] fOriginalExceptionSpec; + private final ICPPEvaluation fReturnExpression; + + public ConfigureFunction(ICPPFunction original, PDOMCPPFunction function) throws DOMException { + fFunction = function; + fOriginalFunctionType= original.getType(); + fOriginalParameters= original.getParameters(); + fOriginalExceptionSpec= function.extractExceptionSpec(original); + fReturnExpression= CPPFunction.getReturnExpression(original); + postProcesses.add(this); + } + + @Override + public void run() { + fFunction.initData(fOriginalFunctionType, fOriginalParameters, fOriginalExceptionSpec, + fReturnExpression); + } + } + class ConfigureFunctionTemplate implements Runnable { private final PDOMCPPFunctionTemplate fTemplate; private final IPDOMCPPTemplateParameter[] fTemplateParameters; @@ -226,6 +251,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { private final ICPPFunctionType fOriginalFunctionType; private final ICPPParameter[] fOriginalParameters; private final IType[] fOriginalExceptionSpec; + private final ICPPEvaluation fReturnExpression; public ConfigureFunctionTemplate(ICPPFunctionTemplate original, PDOMCPPFunctionTemplate template) throws DOMException { fTemplate = template; @@ -234,6 +260,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { fOriginalFunctionType= original.getType(); fOriginalParameters= original.getParameters(); fOriginalExceptionSpec= template.extractExceptionSpec(original); + fReturnExpression= CPPFunction.getReturnExpression(original); postProcesses.add(this); } @@ -244,7 +271,33 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { if (tp != null) tp.configure(fOriginalTemplateParameters[i]); } - fTemplate.initData(fOriginalFunctionType, fOriginalParameters, fOriginalExceptionSpec); + fTemplate.initData(fOriginalFunctionType, fOriginalParameters, fOriginalExceptionSpec, + fReturnExpression); + } + } + + class ConfigureAliasTemplate implements Runnable { + private final PDOMCPPAliasTemplate fTemplate; + private final IPDOMCPPTemplateParameter[] fTemplateParameters; + private final ICPPTemplateParameter[] fOriginalTemplateParameters; + private final IType fOriginalAliasedType; + + public ConfigureAliasTemplate(ICPPAliasTemplate original, PDOMCPPAliasTemplate template) throws DOMException { + fTemplate = template; + fTemplateParameters= template.getTemplateParameters(); + fOriginalTemplateParameters= original.getTemplateParameters(); + fOriginalAliasedType= original.getType(); + postProcesses.add(this); + } + + @Override + public void run() { + for (int i = 0; i < fOriginalTemplateParameters.length; i++) { + final IPDOMCPPTemplateParameter tp = fTemplateParameters[i]; + if (tp != null) + tp.configure(fOriginalTemplateParameters[i]); + } + fTemplate.initData(fOriginalAliasedType); } } @@ -270,7 +323,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { } /** - * Adds or returns existing binding for the given one. If fromName is not null + * Adds or returns existing binding for the given one. If {@code fromName} is not {@code null}, * then an existing binding is updated with the properties of the name. */ private PDOMBinding addBinding(IBinding inputBinding, IASTName fromName) throws CoreException { @@ -624,8 +677,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { return adaptBinding(null, inputBinding, includeLocal ? FILE_LOCAL_REC_DUMMY : null); } - private final PDOMBinding adaptBinding(final PDOMNode parent, IBinding inputBinding, long[] fileLocalRecHolder) - throws CoreException { + private final PDOMBinding adaptBinding(final PDOMNode parent, IBinding inputBinding, + long[] fileLocalRecHolder) throws CoreException { if (cannotAdapt(inputBinding)) { return null; } @@ -634,8 +687,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { if (result != null) { return result; } - - // assign names to anonymous types. + + // Assign names to anonymous types. IBinding binding= PDOMASTAdapter.getAdapterForAnonymousASTBinding(inputBinding); if (binding == null) { return null; @@ -1022,8 +1075,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { } @Override - public PDOMBinding addTypeBinding(IBinding type) throws CoreException { - return addBinding(type, null); + public PDOMBinding addTypeBinding(IBinding binding) throws CoreException { + return addBinding(binding, null); } @Override diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethod.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethod.java index 697fcfdeab4..600082de250 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethod.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethod.java @@ -64,7 +64,7 @@ class PDOMCPPMethod extends PDOMCPPFunction implements ICPPMethod { private byte annotation1= -1; - public PDOMCPPMethod(PDOMLinkage linkage, PDOMNode parent, ICPPMethod method) throws CoreException, DOMException { + public PDOMCPPMethod(PDOMCPPLinkage linkage, PDOMNode parent, ICPPMethod method) throws CoreException, DOMException { super(linkage, parent, method, true); Database db = getDB(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethodSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethodSpecialization.java index 3262f7a77c3..397fdddfcaa 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethodSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPMethodSpecialization.java @@ -123,7 +123,7 @@ class PDOMCPPMethodSpecialization extends PDOMCPPFunctionSpecialization @Override public int getVisibility() { - return PDOMCPPAnnotation.getVisibility(getByte(record + ANNOTATION_OFFSET)); + return PDOMCPPAnnotation.getVisibility(getByte(record + ANNOTATION)); } @Override