mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 22:52:11 +02:00
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
This commit is contained in:
parent
3e66e22aed
commit
89ec7fe8b8
6 changed files with 80 additions and 11 deletions
|
@ -10525,4 +10525,16 @@ public class AST2TemplateTests extends AST2CPPTestBase {
|
||||||
BindingAssertionHelper helper = getAssertionHelper();
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
helper.assertProblem("generate<400>", "generate<400>");
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,4 +46,12 @@ public interface ICPPBasicType extends IBasicType {
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static final int t_wchar_t = ICPPASTSimpleDeclSpecifier.t_wchar_t;
|
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,19 +12,24 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
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.ASTTypeUtil;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
|
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
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.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
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.ICPPASTInitializerClause;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier;
|
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.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.ISerializableType;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
|
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.ValueFactory;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,6 +57,7 @@ public class CPPBasicType implements ICPPBasicType, ISerializableType {
|
||||||
private final Kind fKind;
|
private final Kind fKind;
|
||||||
private final int fModifiers;
|
private final int fModifiers;
|
||||||
private Long fAssociatedValue;
|
private Long fAssociatedValue;
|
||||||
|
private ICPPFunction fPseudoDestructor;
|
||||||
|
|
||||||
public CPPBasicType(Kind kind, int qualifiers, IASTExpression expression) {
|
public CPPBasicType(Kind kind, int qualifiers, IASTExpression expression) {
|
||||||
if (kind == Kind.eUnspecified) {
|
if (kind == Kind.eUnspecified) {
|
||||||
|
@ -321,4 +327,15 @@ public class CPPBasicType implements ICPPBasicType, ISerializableType {
|
||||||
public IASTExpression getValue() {
|
public IASTExpression getValue() {
|
||||||
return null;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.addAll;
|
||||||
import static org.eclipse.cdt.core.parser.util.ArrayUtil.appendAt;
|
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.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 static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -69,8 +69,10 @@ import org.eclipse.core.runtime.IStatus;
|
||||||
* Base implementation for C++ scopes.
|
* Base implementation for C++ scopes.
|
||||||
*/
|
*/
|
||||||
public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
||||||
private static final ICPPFunctionType DESTRUCTOR_FUNCTION_TYPE =
|
// Destructors don't have a return type, but the type of a destructor call expression
|
||||||
CPPVisitor.createImplicitFunctionType(UNSPECIFIED_TYPE, EMPTY_CPPPARAMETER_ARRAY, false, false);
|
// 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;
|
private ICPPMethod[] implicits;
|
||||||
|
|
||||||
|
|
|
@ -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.ICPPASTTemplatedTypeTemplateParameter;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPAliasTemplate;
|
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.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.ICPPClassScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
|
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.ICPPClassTemplate;
|
||||||
|
@ -2180,6 +2181,8 @@ public class CPPTemplates {
|
||||||
IASTDeclarator declarator = ((IASTFunctionDefinition) nestedDecl).getDeclarator();
|
IASTDeclarator declarator = ((IASTFunctionDefinition) nestedDecl).getDeclarator();
|
||||||
declarator= ASTQueries.findInnermostDeclarator(declarator);
|
declarator= ASTQueries.findInnermostDeclarator(declarator);
|
||||||
name = declarator.getName();
|
name = declarator.getName();
|
||||||
|
} else if (nestedDecl instanceof ICPPASTAliasDeclaration) {
|
||||||
|
name = ((ICPPASTAliasDeclaration) nestedDecl).getAlias();
|
||||||
}
|
}
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
if (name instanceof ICPPASTQualifiedName) {
|
if (name instanceof ICPPASTQualifiedName) {
|
||||||
|
@ -3235,6 +3238,17 @@ public class CPPTemplates {
|
||||||
return exec;
|
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).
|
* Instantiate a plain name (simple-id).
|
||||||
* Only destructor names require instantiation, e.g. the name "~T", when instantiated
|
* Only destructor names require instantiation, e.g. the name "~T", when instantiated
|
||||||
|
@ -3251,10 +3265,10 @@ public class CPPTemplates {
|
||||||
* instantiation context's parameter map, the provided name is returned unchanged.
|
* instantiation context's parameter map, the provided name is returned unchanged.
|
||||||
*/
|
*/
|
||||||
public static char[] instantiateName(char[] name, InstantiationContext context, IBinding enclosingTemplate) {
|
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;
|
return name;
|
||||||
}
|
}
|
||||||
String typename = new String(name).substring(1);
|
|
||||||
ICPPTemplateParameterMap map = context.getParameterMap();
|
ICPPTemplateParameterMap map = context.getParameterMap();
|
||||||
IBinding enclosing = enclosingTemplate;
|
IBinding enclosing = enclosingTemplate;
|
||||||
while (enclosing != null) {
|
while (enclosing != null) {
|
||||||
|
@ -3267,10 +3281,17 @@ public class CPPTemplates {
|
||||||
IType argType = arg.getTypeValue();
|
IType argType = arg.getTypeValue();
|
||||||
argType = SemanticUtil.getNestedType(argType, CVTYPE | TDEF);
|
argType = SemanticUtil.getNestedType(argType, CVTYPE | TDEF);
|
||||||
if (argType instanceof ICPPClassType) {
|
if (argType instanceof ICPPClassType) {
|
||||||
|
// Destructor for class type.
|
||||||
StringBuilder result = new StringBuilder();
|
StringBuilder result = new StringBuilder();
|
||||||
result.append('~');
|
result.append('~');
|
||||||
result.append(((ICPPClassType) argType).getName());
|
result.append(((ICPPClassType) argType).getName());
|
||||||
return result.toString().toCharArray();
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.TDEF;
|
||||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType;
|
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.DOMException;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
|
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
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.ICPPASTFunctionDefinition;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
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.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.ICPPClassTemplate;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||||
|
@ -400,15 +402,22 @@ public class EvalID extends CPPDependentEvaluation {
|
||||||
return EvalFixed.INCOMPLETE;
|
return EvalFixed.INCOMPLETE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IType fieldOwnerClassTypeCV = SemanticUtil.getNestedType(fieldOwnerType, TDEF | REF);
|
IType fieldOwnerTypeSimplifiedCV = SemanticUtil.getNestedType(fieldOwnerType, TDEF | REF);
|
||||||
IType fieldOwnerClassType = SemanticUtil.getNestedType(fieldOwnerClassTypeCV, CVTYPE);
|
IType fieldOwnerTypeSimplified = SemanticUtil.getNestedType(fieldOwnerTypeSimplifiedCV, CVTYPE);
|
||||||
if (fieldOwnerClassType instanceof ICPPClassType) {
|
if (fieldOwnerTypeSimplified instanceof ICPPClassType) {
|
||||||
ICPPEvaluation eval = resolveName(name, (ICPPClassType) fieldOwnerClassType, fieldOwner,
|
ICPPEvaluation eval = resolveName(name, (ICPPClassType) fieldOwnerTypeSimplified, fieldOwner,
|
||||||
templateArgs, fieldOwnerClassTypeCV);
|
templateArgs, fieldOwnerTypeSimplifiedCV);
|
||||||
if (eval != null)
|
if (eval != null)
|
||||||
return eval;
|
return eval;
|
||||||
if (!CPPTemplates.isDependentType(fieldOwnerClassType))
|
if (!CPPTemplates.isDependentType(fieldOwnerTypeSimplified))
|
||||||
return EvalFixed.INCOMPLETE;
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue