1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 364226: Invalid redeclaration of class-template.

This commit is contained in:
Markus Schorn 2011-11-30 11:02:58 +01:00
parent d4ea43f6c8
commit 6e0560d4f5
3 changed files with 111 additions and 56 deletions

View file

@ -6393,6 +6393,24 @@ public class AST2CPPTests extends AST2BaseTest {
assertProblemBinding(IProblemBinding.SEMANTIC_INVALID_REDEFINITION, nc.getName(8).resolveBinding()); assertProblemBinding(IProblemBinding.SEMANTIC_INVALID_REDEFINITION, nc.getName(8).resolveBinding());
} }
// template <typename T> class A;
// template <template<typename> class T> class A {};
// template <template<typename> class T> class A;
// template <template<typename> class T> class B {};
// template <typename T> class B;
// template <typename T> class B {};
public void testInvalidClassRedeclaration_364226() throws Exception {
final String code = getAboveComment();
IASTTranslationUnit tu= parse(code, ParserLanguage.CPP, true, false);
CPPNameCollector nc= new CPPNameCollector();
tu.accept(nc);
assertProblemBindings(nc, 4);
assertProblemBinding(IProblemBinding.SEMANTIC_INVALID_REDEFINITION, nc.getName(4).resolveBinding());
assertProblemBinding(IProblemBinding.SEMANTIC_INVALID_REDECLARATION, nc.getName(7).resolveBinding());
assertProblemBinding(IProblemBinding.SEMANTIC_INVALID_REDECLARATION, nc.getName(12).resolveBinding());
assertProblemBinding(IProblemBinding.SEMANTIC_INVALID_REDEFINITION, nc.getName(14).resolveBinding());
}
// struct Foo { // struct Foo {
// void foo(); // void foo();
// }; // };

View file

@ -781,7 +781,9 @@ public class CPPSemantics {
data.foundItems = ArrayUtil.addAll(Object.class, (Object[]) data.foundItems, (Object[]) results); data.foundItems = ArrayUtil.addAll(Object.class, (Object[]) data.foundItems, (Object[]) results);
} }
} else { } else {
data.foundItems = mergePrefixResults((CharArrayObjectMap) data.foundItems, results, scoped); @SuppressWarnings("unchecked")
final CharArrayObjectMap<Object> oldItems = (CharArrayObjectMap<Object>) data.foundItems;
data.foundItems = mergePrefixResults(oldItems, results, scoped);
} }
} }
@ -791,15 +793,17 @@ public class CPPSemantics {
* @param scoped * @param scoped
* @return * @return
*/ */
static CharArrayObjectMap mergePrefixResults(CharArrayObjectMap dest, Object source, boolean scoped) { static CharArrayObjectMap<Object> mergePrefixResults(CharArrayObjectMap<Object> dest, Object source, boolean scoped) {
if (source == null) return dest; if (source == null) return dest;
CharArrayObjectMap resultMap = (dest != null) ? dest : new CharArrayObjectMap(2); CharArrayObjectMap<Object> resultMap = (dest != null) ? dest : new CharArrayObjectMap<Object>(2);
CharArrayObjectMap map = null; CharArrayObjectMap<Object> map = null;
Object[] objs = null; Object[] objs = null;
int size; int size;
if (source instanceof CharArrayObjectMap) { if (source instanceof CharArrayObjectMap) {
map = (CharArrayObjectMap) source; @SuppressWarnings("unchecked")
final CharArrayObjectMap<Object> sourceMap = (CharArrayObjectMap<Object>) source;
map = sourceMap;
size= map.size(); size= map.size();
} else { } else {
if (source instanceof Object[]) if (source instanceof Object[])
@ -3499,7 +3503,7 @@ public class CPPSemantics {
LookupData data = createLookupData(name); LookupData data = createLookupData(name);
data.contentAssist = true; data.contentAssist = true;
data.prefixLookup = prefixLookup; data.prefixLookup = prefixLookup;
data.foundItems = new CharArrayObjectMap(2); data.foundItems = new CharArrayObjectMap<Object>(2);
// Convert namespaces to scopes. // Convert namespaces to scopes.
List<ICPPScope> nsScopes= new ArrayList<ICPPScope>(); List<ICPPScope> nsScopes= new ArrayList<ICPPScope>();
@ -3567,7 +3571,8 @@ public class CPPSemantics {
} }
} catch (DOMException e) { } catch (DOMException e) {
} }
CharArrayObjectMap map = (CharArrayObjectMap) data.foundItems; @SuppressWarnings("unchecked")
CharArrayObjectMap<Object> map = (CharArrayObjectMap<Object>) data.foundItems;
IBinding[] result = IBinding.EMPTY_BINDING_ARRAY; IBinding[] result = IBinding.EMPTY_BINDING_ARRAY;
if (!map.isEmpty()) { if (!map.isEmpty()) {
char[] key = null; char[] key = null;
@ -3686,7 +3691,7 @@ public class CPPSemantics {
return true; return true;
} }
private static boolean isSameTemplateParameter(ICPPTemplateParameter tp1, ICPPASTTemplateParameter tp2) { static boolean isSameTemplateParameter(ICPPTemplateParameter tp1, ICPPASTTemplateParameter tp2) {
if (tp1.isParameterPack() != tp2.isParameterPack()) if (tp1.isParameterPack() != tp2.isParameterPack())
return false; return false;

View file

@ -460,10 +460,9 @@ public class CPPVisitor extends ASTQueries {
} }
try { try {
boolean template = false; ICPPASTTemplateDeclaration templateDecl = CPPTemplates.getTemplateDeclaration(name);
ICPPScope scope = (ICPPScope) getContainingScope(name); ICPPScope scope = (ICPPScope) getContainingScope(name);
while (scope instanceof ICPPTemplateScope) { while (scope instanceof ICPPTemplateScope) {
template = true;
scope= (ICPPScope) scope.getParent(); scope= (ICPPScope) scope.getParent();
} }
@ -493,14 +492,35 @@ public class CPPVisitor extends ASTQueries {
if (binding instanceof ICPPClassType) { if (binding instanceof ICPPClassType) {
final ICPPInternalBinding ib = (ICPPInternalBinding) binding; final ICPPInternalBinding ib = (ICPPInternalBinding) binding;
if ((binding instanceof ICPPClassTemplate) == template) { if (templateParametersMatch((ICPPClassType) binding, templateDecl)) {
ib.addDeclaration(elabType); ib.addDeclaration(elabType);
return binding; return binding;
} }
if (CPPSemantics.declaredBefore(binding, name, false)) {
if (CPPSemantics.declaredBefore(ib, name, false)) {
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION); return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION);
} }
markRedeclaration(ib);
}
}
// Create a binding
if (elabType.getKind() != IASTElaboratedTypeSpecifier.k_enum) {
if (templateDecl != null)
binding = new CPPClassTemplate(name);
else
binding = new CPPClassType(name, binding);
// name may live in a different scope, so make sure to add it to the owner scope, as well.
ASTInternal.addName(scope, elabType.getName());
}
} catch (DOMException e) {
binding = e.getProblem();
}
return binding;
}
public static void markRedeclaration(final ICPPInternalBinding ib) {
// Mark the other declarations as problem and create the binding // Mark the other declarations as problem and create the binding
final IASTNode[] decls = ib.getDeclarations(); final IASTNode[] decls = ib.getDeclarations();
if (decls != null) { if (decls != null) {
@ -517,22 +537,30 @@ public class CPPVisitor extends ASTQueries {
n.setBinding(new ProblemBinding(n, IProblemBinding.SEMANTIC_INVALID_REDEFINITION)); n.setBinding(new ProblemBinding(n, IProblemBinding.SEMANTIC_INVALID_REDEFINITION));
} }
} }
}
// Create a binding /**
if (elabType.getKind() != IASTElaboratedTypeSpecifier.k_enum) { * Tests whether a class binding matches the template parameters of another declaration
if (template) */
binding = new CPPClassTemplate(name); private static boolean templateParametersMatch(ICPPClassType binding,
else ICPPASTTemplateDeclaration templateDecl) {
binding = new CPPClassType(name, binding); final boolean isTemplate= binding instanceof ICPPClassTemplate;
// name may live in a different scope, so make sure to add it to the owner scope, as well. if (templateDecl == null)
ASTInternal.addName(scope, elabType.getName()); return !isTemplate;
} if (!isTemplate)
} catch (DOMException e) { return false;
binding = e.getProblem();
}
return binding; ICPPTemplateParameter[] pars1 = ((ICPPClassTemplate) binding).getTemplateParameters();
ICPPASTTemplateParameter[] pars2 = templateDecl.getTemplateParameters();
int i=0;
for (ICPPASTTemplateParameter p2 : pars2) {
if (i >= pars1.length)
return true;
if (!CPPSemantics.isSameTemplateParameter(pars1[i++], p2))
return false;
}
return true;
} }
private static IBinding createBinding(ICPPASTCompositeTypeSpecifier compType) { private static IBinding createBinding(ICPPASTCompositeTypeSpecifier compType) {
@ -541,39 +569,43 @@ public class CPPVisitor extends ASTQueries {
IASTName[] ns = ((ICPPASTQualifiedName) name).getNames(); IASTName[] ns = ((ICPPASTQualifiedName) name).getNames();
name = ns[ns.length - 1]; name = ns[ns.length - 1];
} }
if (name instanceof ICPPASTTemplateId)
return CPPTemplates.createBinding((ICPPASTTemplateId) name);
IBinding binding = null;
ICPPScope scope = (ICPPScope) getContainingScope(name); ICPPScope scope = (ICPPScope) getContainingScope(name);
try { try {
boolean template = false;
while (scope instanceof ICPPTemplateScope) { while (scope instanceof ICPPTemplateScope) {
template = true;
scope= (ICPPScope) scope.getParent(); scope= (ICPPScope) scope.getParent();
} }
if (name instanceof ICPPASTTemplateId) {
return CPPTemplates.createBinding((ICPPASTTemplateId) name);
}
if (name.getLookupKey().length > 0 && scope != null) // can't lookup anonymous things
binding = scope.getBinding(name, false);
if (binding instanceof ICPPInternalBinding && binding instanceof ICPPClassType && name.isActive()) {
ICPPInternalBinding internal = (ICPPInternalBinding) binding;
if (internal.getDefinition() == null && (binding instanceof ICPPClassTemplate) == template) {
ASTInternal.addDefinition(internal, compType);
} else {
binding = new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDEFINITION);
}
} else {
if (template) {
binding = new CPPClassTemplate(name);
} else {
binding = new CPPClassType(name, binding);
}
}
} catch (DOMException e) { } catch (DOMException e) {
binding = e.getProblem(); return e.getProblem();
} }
// Can't lookup anonymous names
IBinding binding= null;
ICPPASTTemplateDeclaration templateDecl = CPPTemplates.getTemplateDeclaration(name);
if (name.getLookupKey().length > 0 && scope != null) {
binding = scope.getBinding(name, false);
if (binding instanceof ICPPInternalBinding
&& binding instanceof ICPPClassType && name.isActive()) {
ICPPInternalBinding ib = (ICPPInternalBinding) binding;
if (ib.getDefinition() == null
&& templateParametersMatch((ICPPClassType) binding, templateDecl)) {
ASTInternal.addDefinition(ib, compType);
return binding; return binding;
} }
if (CPPSemantics.declaredBefore(ib, name, false)) {
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDEFINITION);
}
markRedeclaration(ib);
}
}
if (templateDecl != null)
return new CPPClassTemplate(name);
return new CPPClassType(name, binding);
}
private static IBinding createBinding(IASTDeclaration declaration) { private static IBinding createBinding(IASTDeclaration declaration) {
if (declaration instanceof ICPPASTNamespaceDefinition) { if (declaration instanceof ICPPASTNamespaceDefinition) {