1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-03 23:25:26 +02:00

Bug 417050 - Organize Includes adds includes for template parameters of

unique_ptr.
This commit is contained in:
Sergey Prigogin 2013-09-11 20:29:13 -07:00
parent 7372e983a1
commit 0df9d9c211
4 changed files with 94 additions and 13 deletions

View file

@ -830,7 +830,7 @@ public class ClassTypeHelper {
return null;
}
private static ICPPMethod getMethodInClass(ICPPClassType ct, MethodKind kind, IASTNode point) {
public static ICPPMethod getMethodInClass(ICPPClassType ct, MethodKind kind, IASTNode point) {
switch (kind) {
case DEFAULT_CTOR:
case COPY_CTOR:

View file

@ -22,6 +22,13 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti
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.getUltimateTypeUptoPointers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.cdt.core.dom.ast.ASTGenericVisitor;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
@ -207,13 +214,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
import org.eclipse.cdt.internal.core.index.IIndexScope;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Collection of methods to extract information from a C++ translation unit.
*/
@ -225,7 +225,7 @@ public class CPPVisitor extends ASTQueries {
public static final String BEGIN_STR = "begin"; //$NON-NLS-1$
public static final char[] BEGIN = BEGIN_STR.toCharArray();
public static final char[] END = "end".toCharArray(); //$NON-NLS-1$
static final String STD = "std"; //$NON-NLS-1$
public static final String STD = "std"; //$NON-NLS-1$
private static final char[] SIZE_T = "size_t".toCharArray(); //$NON-NLS-1$
private static final char[] PTRDIFF_T = "ptrdiff_t".toCharArray(); //$NON-NLS-1$
private static final char[] TYPE_INFO = "type_info".toCharArray(); //$NON-NLS-1$

View file

@ -395,6 +395,38 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
assertDeclared();
}
// namespace std {
// template<typename T> class shared_ptr {};
// template<typename T> class unique_ptr {};
// }
// class A {};
// class B {};
// class C {};
// using std::unique_ptr;
// using std::shared_ptr;
//
// struct P {
// ~P();
// shared_ptr<A> x;
// unique_ptr<A> y;
// };
//
// struct Q {
// ~Q() {}
// shared_ptr<B> x;
// unique_ptr<B> y;
// };
//
// void test() {
// shared_ptr<C> x;
// unique_ptr<C> y;
// }
public void testTemplatesAllowingIncompleteParameterType() throws Exception {
assertDefined("B", "C", "shared_ptr", "unique_ptr");
assertDeclared("A");
}
// struct A {};
// struct B {};
// struct C {};

View file

@ -11,6 +11,7 @@
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.includes;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor.STD;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ALLCVQ;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ARRAY;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.PTR;
@ -18,6 +19,8 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -76,14 +79,17 @@ import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
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.ICPPASTTypeId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
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.ICPPEnumeration;
@ -98,12 +104,14 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.index.IIndexMacro;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper.MethodKind;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions;
@ -126,6 +134,15 @@ public class BindingClassifier {
private final BindingCollector fBindingCollector;
private final Set<IBinding> fProcessedDefinedBindings;
private final Set<IBinding> fProcessedDeclaredBindings;
private static final Set<String> templatesAllowingIncompleteArgumentType =
Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(new String[] {
"enable_shared_from_this", // 20.7.2.4 //$NON-NLS-1$
"declval", // 20.2.4 //$NON-NLS-1$
"default_delete", // 20.7.1.1 //$NON-NLS-1$
"shared_ptr", // 20.7.2.2 //$NON-NLS-1$
"unique_ptr", // 20.7.1 //$NON-NLS-1$
"weak_ptr" // 20.7.2.3 //$NON-NLS-1$
})));
/**
* @param context the context for binding classification
@ -1122,7 +1139,7 @@ public class BindingClassifier {
IBinding binding = name.resolveBinding();
if (binding != null) {
if (isInTemplateArgument(name)) {
if (isTemplateArgumentRequiringCompleteType(name)) {
// The name is part of a template argument - define the corresponding binding.
defineBinding(binding);
} else {
@ -1171,9 +1188,41 @@ public class BindingClassifier {
/**
* Checks if the given name is part of a template argument.
*/
public boolean isInTemplateArgument(IASTName name) {
public boolean isTemplateArgumentRequiringCompleteType(IASTName name) {
ICPPASTTypeId typeId = CPPVisitor.findAncestorWithType(name, ICPPASTTypeId.class);
return typeId != null && typeId.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT;
if (typeId == null || typeId.getPropertyInParent() != ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT)
return false;
ICPPASTTemplateId templateId = (ICPPASTTemplateId) typeId.getParent();
IBinding template = templateId.resolveBinding();
if (template instanceof IProblemBinding)
return true;
IBinding owner = template.getOwner();
if (!(owner instanceof ICPPNamespace) ||
!CharArrayUtils.equals(owner.getNameCharArray(), STD) || owner.getOwner() != null) {
return true;
}
String templateName = template.getName();
if (!templatesAllowingIncompleteArgumentType.contains(templateName))
return true;
// For most templates allowing incomplete argument type a full definition of the argument
// type is required if the destructor is called. Since the AST doen't contain all destructor
// calling points, we have to use an indirect approach by examining the containing scope.
IASTNode parent = templateId.getParent();
if (!(parent instanceof ICPPASTNamedTypeSpecifier))
return false;
parent = parent.getParent();
if (!(parent instanceof IASTSimpleDeclaration))
return true;
parent = parent.getParent();
if (!(parent instanceof ICPPASTCompositeTypeSpecifier))
return true;
ICPPClassScope classScope = ((ICPPASTCompositeTypeSpecifier) parent).getScope();
ICPPClassType classType = classScope.getClassType();
ICPPMethod destructor = ClassTypeHelper.getMethodInClass(classType, MethodKind.DTOR, parent);
if (fAst.getDefinitionsInAST(destructor).length != 0)
return true;
return false;
}
private static boolean isEnumerationWithoutFixedUnderlyingType(IBinding typeBinding) {
@ -1197,4 +1246,4 @@ public class BindingClassifier {
}
return true;
}
}
}