Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Ridge2017-12-17 00:10:14 +0000
committerNathan Ridge2017-12-24 16:38:49 +0000
commit89ec7fe8b8a332ca9f69557ccadd2a4f6dfbaf4f (patch)
tree044211452af47fd2d0fdf00f508c403a772d744b
parent3e66e22aed8e98224c22000bd377a26eff619778 (diff)
downloadorg.eclipse.cdt-89ec7fe8b8a332ca9f69557ccadd2a4f6dfbaf4f.tar.gz
org.eclipse.cdt-89ec7fe8b8a332ca9f69557ccadd2a4f6dfbaf4f.tar.xz
org.eclipse.cdt-89ec7fe8b8a332ca9f69557ccadd2a4f6dfbaf4f.zip
Bug 528846 - Handle id-expression that instantiates to pseudo-destructor name of built-in type
The pseudo-destructor is represented as a CPPImplicitFunction, computed lazily and stored by CPPBasicType. This commit also adds support for alias templates to CPPTemplates.getTemplateName(). Change-Id: I6774556b2493cb68d32c3007d6ce48c7805595f4
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java12
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBasicType.java8
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java17
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java8
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java25
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java21
6 files changed, 80 insertions, 11 deletions
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 1e9b3073fc6..a6cff09c463 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
@@ -10525,4 +10525,16 @@ public class AST2TemplateTests extends AST2CPPTestBase {
BindingAssertionHelper helper = getAssertionHelper();
helper.assertProblem("generate<400>", "generate<400>");
}
+
+ // template <typename T> T declval();
+ //
+ // template <class T>
+ // using destructor_expr_t = decltype(declval<T>().~T());
+ //
+ // typedef destructor_expr_t<int> Waldo;
+ public void testDestructorExpressionType_528846() throws Exception {
+ BindingAssertionHelper helper = getAssertionHelper();
+ IType waldo = helper.assertNonProblem("Waldo");
+ assertSameType(CommonCPPTypes.void_, waldo);
+ }
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBasicType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBasicType.java
index 3093eaab649..3aa121f5bc8 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBasicType.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBasicType.java
@@ -46,4 +46,12 @@ public interface ICPPBasicType extends IBasicType {
*/
@Deprecated
public static final int t_wchar_t = ICPPASTSimpleDeclSpecifier.t_wchar_t;
+
+ /**
+ * Get the built-in type's pseudo-destructor.
+ * The pseudo-destructor is the function named by e.g. an id-expression
+ * of the form "T().~T" when instantiated with T mapped to a built-in type.
+ * @since 6.5
+ */
+ public ICPPFunction getPseudoDestructor();
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java
index 4b16b3731d9..f1a7e8c6e79 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java
@@ -12,19 +12,24 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
+import static org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter.EMPTY_CPPPARAMETER_ARRAY;
+
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IBasicType;
+import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.internal.core.dom.parser.ISerializableType;
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
import org.eclipse.cdt.internal.core.dom.parser.ValueFactory;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.core.runtime.CoreException;
/**
@@ -52,6 +57,7 @@ public class CPPBasicType implements ICPPBasicType, ISerializableType {
private final Kind fKind;
private final int fModifiers;
private Long fAssociatedValue;
+ private ICPPFunction fPseudoDestructor;
public CPPBasicType(Kind kind, int qualifiers, IASTExpression expression) {
if (kind == Kind.eUnspecified) {
@@ -321,4 +327,15 @@ public class CPPBasicType implements ICPPBasicType, ISerializableType {
public IASTExpression getValue() {
return null;
}
+
+ @Override
+ public ICPPFunction getPseudoDestructor() {
+ if (fPseudoDestructor == null) {
+ char[] dtorName = ("~" + toString()).toCharArray(); //$NON-NLS-1$
+ IScope globalScope = CPPSemantics.getCurrentLookupPoint().getTranslationUnit().getScope();
+ fPseudoDestructor = new CPPImplicitFunction(dtorName, globalScope,
+ CPPClassScope.DESTRUCTOR_FUNCTION_TYPE, EMPTY_CPPPARAMETER_ARRAY, true, false);
+ }
+ return fPseudoDestructor;
+ }
}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java
index 573d645a556..5814303663b 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java
@@ -19,7 +19,7 @@ import static org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter.EMPTY_CPPPARAMETER_
import static org.eclipse.cdt.core.parser.util.ArrayUtil.addAll;
import static org.eclipse.cdt.core.parser.util.ArrayUtil.appendAt;
import static org.eclipse.cdt.core.parser.util.ArrayUtil.trim;
-import static org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType.UNSPECIFIED_TYPE;
+import static org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType.VOID;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
import java.util.Arrays;
@@ -69,8 +69,10 @@ import org.eclipse.core.runtime.IStatus;
* Base implementation for C++ scopes.
*/
public class CPPClassScope extends CPPScope implements ICPPClassScope {
- private static final ICPPFunctionType DESTRUCTOR_FUNCTION_TYPE =
- CPPVisitor.createImplicitFunctionType(UNSPECIFIED_TYPE, EMPTY_CPPPARAMETER_ARRAY, false, false);
+ // Destructors don't have a return type, but the type of a destructor call expression
+ // is void, so it's simpler to model them as having a void return type.
+ public static final ICPPFunctionType DESTRUCTOR_FUNCTION_TYPE =
+ CPPVisitor.createImplicitFunctionType(VOID, EMPTY_CPPPARAMETER_ARRAY, false, false);
private ICPPMethod[] implicits;
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 12346969e22..b575b455836 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
@@ -80,6 +80,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter;
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.ICPPBasicType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
@@ -2180,6 +2181,8 @@ public class CPPTemplates {
IASTDeclarator declarator = ((IASTFunctionDefinition) nestedDecl).getDeclarator();
declarator= ASTQueries.findInnermostDeclarator(declarator);
name = declarator.getName();
+ } else if (nestedDecl instanceof ICPPASTAliasDeclaration) {
+ name = ((ICPPASTAliasDeclaration) nestedDecl).getAlias();
}
if (name != null) {
if (name instanceof ICPPASTQualifiedName) {
@@ -3234,6 +3237,17 @@ public class CPPTemplates {
}
return exec;
}
+
+ /**
+ * If 'name' is a destructor-name, return the name of the type (i.e. the
+ * portion following the '~'). Otherwise return null.
+ */
+ public static String unwrapDestructorName(char[] name) {
+ if (name == null || name.length == 0 || name[0] != '~') {
+ return null;
+ }
+ return new String(name).substring(1).trim();
+ }
/**
* Instantiate a plain name (simple-id).
@@ -3251,10 +3265,10 @@ public class CPPTemplates {
* instantiation context's parameter map, the provided name is returned unchanged.
*/
public static char[] instantiateName(char[] name, InstantiationContext context, IBinding enclosingTemplate) {
- if (name == null || name.length == 0 || name[0] != '~') {
+ String typename = unwrapDestructorName(name);
+ if (typename == null) { // not a destructor-name
return name;
}
- String typename = new String(name).substring(1);
ICPPTemplateParameterMap map = context.getParameterMap();
IBinding enclosing = enclosingTemplate;
while (enclosing != null) {
@@ -3267,10 +3281,17 @@ public class CPPTemplates {
IType argType = arg.getTypeValue();
argType = SemanticUtil.getNestedType(argType, CVTYPE | TDEF);
if (argType instanceof ICPPClassType) {
+ // Destructor for class type.
StringBuilder result = new StringBuilder();
result.append('~');
result.append(((ICPPClassType) argType).getName());
return result.toString().toCharArray();
+ } else if (argType instanceof ICPPBasicType) {
+ // Pseudo-destructor for builtin type.
+ StringBuilder result = new StringBuilder();
+ result.append('~');
+ ASTTypeUtil.appendType(argType, true, result);
+ return result.toString().toCharArray();
}
}
}
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 718e96c0d78..4e1f201b7b1 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
@@ -19,6 +19,7 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType;
+import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
@@ -39,6 +40,7 @@ import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
@@ -400,15 +402,22 @@ public class EvalID extends CPPDependentEvaluation {
return EvalFixed.INCOMPLETE;
}
}
- IType fieldOwnerClassTypeCV = SemanticUtil.getNestedType(fieldOwnerType, TDEF | REF);
- IType fieldOwnerClassType = SemanticUtil.getNestedType(fieldOwnerClassTypeCV, CVTYPE);
- if (fieldOwnerClassType instanceof ICPPClassType) {
- ICPPEvaluation eval = resolveName(name, (ICPPClassType) fieldOwnerClassType, fieldOwner,
- templateArgs, fieldOwnerClassTypeCV);
+ IType fieldOwnerTypeSimplifiedCV = SemanticUtil.getNestedType(fieldOwnerType, TDEF | REF);
+ IType fieldOwnerTypeSimplified = SemanticUtil.getNestedType(fieldOwnerTypeSimplifiedCV, CVTYPE);
+ if (fieldOwnerTypeSimplified instanceof ICPPClassType) {
+ ICPPEvaluation eval = resolveName(name, (ICPPClassType) fieldOwnerTypeSimplified, fieldOwner,
+ templateArgs, fieldOwnerTypeSimplifiedCV);
if (eval != null)
return eval;
- if (!CPPTemplates.isDependentType(fieldOwnerClassType))
+ if (!CPPTemplates.isDependentType(fieldOwnerTypeSimplified))
return EvalFixed.INCOMPLETE;
+ } else if (fieldOwnerTypeSimplified instanceof ICPPBasicType) {
+ // Handle pseudo-destructor of basic type, e.g. "T().~T" instantiated with [T = int].
+ String typename = CPPTemplates.unwrapDestructorName(name);
+ if (typename != null && typename.equals(ASTTypeUtil.getType(fieldOwnerTypeSimplified))) {
+ ICPPFunction pseudoDestructor = ((ICPPBasicType) fieldOwnerTypeSimplified).getPseudoDestructor();
+ return new EvalBinding(pseudoDestructor, null, getTemplateDefinition());
+ }
}
}

Back to the top