1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 22:52: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:
Sergey Prigogin 2017-03-27 08:24:13 -07:00 committed by Gerrit Code Review @ Eclipse.org
parent 868db5b9b6
commit 4f70ea542a
3 changed files with 122 additions and 14 deletions

View file

@ -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 {};

View file

@ -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();
}
} }

View file

@ -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,11 +1196,12 @@ 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);
} }
} }
} }
}
// Get the specialized binding - e.g. get the binding for X if the current binding // Get the specialized binding - e.g. get the binding for X if the current binding
// is for the template specialization X<Y>. // is for the template specialization X<Y>.
addRequiredBindings(((ICPPSpecialization) binding).getSpecializedBinding(), queue); addRequiredBindings(((ICPPSpecialization) binding).getSpecializedBinding(), queue);
@ -1195,6 +1233,10 @@ 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)
@ -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;