mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Bug 514197 - Organize Includes removes an include necessary for
instantiation of the body of a template function Change-Id: I7a788f5ddcfae039acdec3a7985dcef364c5b8c0
This commit is contained in:
parent
868db5b9b6
commit
4f70ea542a
3 changed files with 122 additions and 14 deletions
|
@ -584,6 +584,28 @@ public class BindingClassifierTest extends OneSourceMultipleHeadersTestCase {
|
||||||
assertDeclared();
|
assertDeclared();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// class A;
|
||||||
|
//
|
||||||
|
// A& f();
|
||||||
|
//
|
||||||
|
// struct A {
|
||||||
|
// void m();
|
||||||
|
// };
|
||||||
|
|
||||||
|
// template <typename T>
|
||||||
|
// void g(T& p) {
|
||||||
|
// p.m();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// void test() {
|
||||||
|
// g(f());
|
||||||
|
// }
|
||||||
|
public void testTemplateParameter_514197() throws Exception {
|
||||||
|
getPreferenceStore().setValue(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS, true);
|
||||||
|
assertDefined("A");
|
||||||
|
assertDeclared("f");
|
||||||
|
}
|
||||||
|
|
||||||
// namespace std {
|
// namespace std {
|
||||||
// template<typename T> class shared_ptr {};
|
// template<typename T> class shared_ptr {};
|
||||||
// template<typename T> class unique_ptr {};
|
// template<typename T> class unique_ptr {};
|
||||||
|
|
|
@ -715,4 +715,42 @@ public class IncludeOrganizerTest extends IncludesTestBase {
|
||||||
preferenceStore.setValue(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS, true);
|
preferenceStore.setValue(PreferenceConstants.FORWARD_DECLARE_FUNCTIONS, true);
|
||||||
assertExpectedResults();
|
assertExpectedResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//h1.h
|
||||||
|
//class A;
|
||||||
|
//
|
||||||
|
//A& f();
|
||||||
|
|
||||||
|
//h2.h
|
||||||
|
//struct A {
|
||||||
|
// void m();
|
||||||
|
//};
|
||||||
|
|
||||||
|
//source.cpp
|
||||||
|
//#include "h1.h"
|
||||||
|
//#include "h2.h"
|
||||||
|
//
|
||||||
|
//template <typename T>
|
||||||
|
//void g(T& p) {
|
||||||
|
// p.m();
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void test() {
|
||||||
|
// g(f());
|
||||||
|
//}
|
||||||
|
//====================
|
||||||
|
//#include "h1.h"
|
||||||
|
//#include "h2.h"
|
||||||
|
//
|
||||||
|
//template <typename T>
|
||||||
|
//void g(T& p) {
|
||||||
|
// p.m();
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void test() {
|
||||||
|
// g(f());
|
||||||
|
//}
|
||||||
|
public void testTemplateParameter_514197() throws Exception {
|
||||||
|
assertExpectedResults();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
@ -115,6 +116,7 @@ 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.ICPPTemplateArgument;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
|
||||||
import org.eclipse.cdt.core.index.IIndexFile;
|
import org.eclipse.cdt.core.index.IIndexFile;
|
||||||
|
@ -132,6 +134,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
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.ClassTypeHelper.MethodKind;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
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.CPPVisitor;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions;
|
||||||
|
@ -908,6 +911,13 @@ public class BindingClassifier {
|
||||||
declareBinding(binding); // Declare the binding of this name.
|
declareBinding(binding); // Declare the binding of this name.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (binding instanceof ICPPTemplateInstance &&
|
||||||
|
!((ICPPTemplateInstance) binding).isExplicitSpecialization() &&
|
||||||
|
isDeclaredLocally(((ICPPTemplateInstance) binding).getSpecializedBinding())) {
|
||||||
|
fInstancesOfLocallyDefinedTemplates.add((ICPPTemplateInstance) binding);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return PROCESS_CONTINUE;
|
return PROCESS_CONTINUE;
|
||||||
}
|
}
|
||||||
|
@ -951,14 +961,15 @@ public class BindingClassifier {
|
||||||
private final IncludeCreationContext fContext;
|
private final IncludeCreationContext fContext;
|
||||||
private final IncludePreferences fPreferences;
|
private final IncludePreferences fPreferences;
|
||||||
/** The bindings which require a full definition. */
|
/** The bindings which require a full definition. */
|
||||||
private final Set<IBinding> fBindingsToDefine;
|
private final Set<IBinding> fBindingsToDefine = new HashSet<>();
|
||||||
/** The bindings which only require a simple forward declaration. */
|
/** The bindings which only require a simple forward declaration. */
|
||||||
private final Set<IBinding> fBindingsToForwardDeclare;
|
private final Set<IBinding> fBindingsToForwardDeclare = new HashSet<>();
|
||||||
/** The AST that the classifier is working on. */
|
/** The AST that the classifier is working on. */
|
||||||
private IASTTranslationUnit fAst;
|
private IASTTranslationUnit fAst;
|
||||||
private final BindingCollector fBindingCollector;
|
private final BindingCollector fBindingCollector = new BindingCollector();
|
||||||
private final Set<IBinding> fProcessedDefinedBindings;
|
private final Set<IBinding> fProcessedDefinedBindings = new HashSet<>();
|
||||||
private final Set<IBinding> fProcessedDeclaredBindings;
|
private final Set<IBinding> fProcessedDeclaredBindings = new HashSet<>();
|
||||||
|
public final Set<ICPPTemplateInstance> fInstancesOfLocallyDefinedTemplates = new HashSet<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param context the context for binding classification
|
* @param context the context for binding classification
|
||||||
|
@ -966,11 +977,6 @@ public class BindingClassifier {
|
||||||
public BindingClassifier(IncludeCreationContext context) {
|
public BindingClassifier(IncludeCreationContext context) {
|
||||||
fContext = context;
|
fContext = context;
|
||||||
fPreferences = context.getPreferences();
|
fPreferences = context.getPreferences();
|
||||||
fBindingsToDefine = new HashSet<>();
|
|
||||||
fBindingsToForwardDeclare = new HashSet<>();
|
|
||||||
fProcessedDefinedBindings = new HashSet<>();
|
|
||||||
fProcessedDeclaredBindings = new HashSet<>();
|
|
||||||
fBindingCollector = new BindingCollector();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void classifyNodeContents(IASTNode node) {
|
public void classifyNodeContents(IASTNode node) {
|
||||||
|
@ -983,11 +989,42 @@ public class BindingClassifier {
|
||||||
// target bindings are in a header not reachable via includes.
|
// target bindings are in a header not reachable via includes.
|
||||||
CPPSemantics.enablePromiscuousBindingResolution();
|
CPPSemantics.enablePromiscuousBindingResolution();
|
||||||
node.accept(fBindingCollector);
|
node.accept(fBindingCollector);
|
||||||
|
postprocessTemplates();
|
||||||
} finally {
|
} finally {
|
||||||
CPPSemantics.disablePromiscuousBindingResolution();
|
CPPSemantics.disablePromiscuousBindingResolution();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void postprocessTemplates() {
|
||||||
|
Set<ICPPTemplateParameter> templatearametersRequiringDefinition = new HashSet<>();
|
||||||
|
for (Iterator<IBinding> it = fBindingsToDefine.iterator(); it.hasNext();) {
|
||||||
|
IBinding binding = it.next();
|
||||||
|
if (binding instanceof ICPPTemplateParameter) {
|
||||||
|
templatearametersRequiringDefinition.add((ICPPTemplateParameter) binding);
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (templatearametersRequiringDefinition.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (ICPPTemplateInstance instance : fInstancesOfLocallyDefinedTemplates) {
|
||||||
|
ICPPTemplateParameterMap parameterMap = instance.getTemplateParameterMap();
|
||||||
|
ICPPTemplateParameter[] params = instance.getTemplateDefinition().getTemplateParameters();
|
||||||
|
for (ICPPTemplateParameter param : params) {
|
||||||
|
if (templatearametersRequiringDefinition.contains(param)) {
|
||||||
|
ICPPTemplateArgument argument = parameterMap.getArgument(param);
|
||||||
|
if (argument != null) {
|
||||||
|
defineTemplateArgument(argument);
|
||||||
|
} else {
|
||||||
|
for (ICPPTemplateArgument arg : parameterMap.getPackExpansion(param)) {
|
||||||
|
defineTemplateArgument(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the bindings which require a full definition.
|
* Returns the bindings which require a full definition.
|
||||||
*/
|
*/
|
||||||
|
@ -1159,8 +1196,9 @@ public class BindingClassifier {
|
||||||
IBinding owner = ((IBinding) type).getOwner();
|
IBinding owner = ((IBinding) type).getOwner();
|
||||||
if (owner instanceof ICPPNamespace &&
|
if (owner instanceof ICPPNamespace &&
|
||||||
(CharArrayUtils.equals(owner.getNameCharArray(), STD) ||
|
(CharArrayUtils.equals(owner.getNameCharArray(), STD) ||
|
||||||
CharArrayUtils.equals(owner.getNameCharArray(), "__gnu_cxx"))) //$NON-NLS-1$
|
CharArrayUtils.equals(owner.getNameCharArray(), "__gnu_cxx"))) { //$NON-NLS-1$
|
||||||
addRequiredBindings((IBinding) type, queue);
|
addRequiredBindings((IBinding) type, queue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1195,10 +1233,14 @@ public class BindingClassifier {
|
||||||
} catch (CoreException e) {
|
} catch (CoreException e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (binding instanceof ICPPTemplateParameter) {
|
||||||
|
newBindings.add(binding);
|
||||||
|
} else if (binding instanceof ICPPUnknownBinding) {
|
||||||
|
newBindings.add(binding.getOwner());
|
||||||
} else if (binding instanceof ICPPMethod) {
|
} else if (binding instanceof ICPPMethod) {
|
||||||
newBindings.add(binding); // Include the method in case we need its inline definition.
|
newBindings.add(binding); // Include the method in case we need its inline definition.
|
||||||
if (binding instanceof ICPPConstructor)
|
if (binding instanceof ICPPConstructor)
|
||||||
newBindings.add(binding.getOwner());
|
newBindings.add(binding.getOwner());
|
||||||
} else if (binding instanceof IType) {
|
} else if (binding instanceof IType) {
|
||||||
// Remove type qualifiers.
|
// Remove type qualifiers.
|
||||||
IBinding b = getTypeBinding((IType) binding);
|
IBinding b = getTypeBinding((IType) binding);
|
||||||
|
@ -1225,10 +1267,10 @@ public class BindingClassifier {
|
||||||
return;
|
return;
|
||||||
if (fProcessedDefinedBindings.contains(binding))
|
if (fProcessedDefinedBindings.contains(binding))
|
||||||
return;
|
return;
|
||||||
if (isDeclaredLocally(binding))
|
|
||||||
return; // Declared locally.
|
|
||||||
if (!fProcessedDeclaredBindings.add(binding))
|
if (!fProcessedDeclaredBindings.add(binding))
|
||||||
return;
|
return;
|
||||||
|
if (isDeclaredLocally(binding))
|
||||||
|
return; // Declared locally.
|
||||||
if (!canForwardDeclare(binding)) {
|
if (!canForwardDeclare(binding)) {
|
||||||
defineBinding(binding);
|
defineBinding(binding);
|
||||||
return;
|
return;
|
||||||
|
@ -1474,6 +1516,12 @@ public class BindingClassifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void defineTemplateArgument(ICPPTemplateArgument argument) {
|
||||||
|
IType type = argument.getOriginalTypeValue();
|
||||||
|
if (type != null)
|
||||||
|
defineTypeExceptTypedefOrNonFixedEnum(type);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isDefined(IBinding binding) {
|
private boolean isDefined(IBinding binding) {
|
||||||
if (fBindingsToDefine.contains(binding))
|
if (fBindingsToDefine.contains(binding))
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Add table
Reference in a new issue