mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42: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();
|
||||
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
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue