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

@ -6392,7 +6392,25 @@ public class AST2CPPTests extends AST2BaseTest {
assertProblemBinding(IProblemBinding.SEMANTIC_INVALID_REDECLARATION, nc.getName(6).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 {
// void foo();
// };

View file

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

View file

@ -460,10 +460,9 @@ public class CPPVisitor extends ASTQueries {
}
try {
boolean template = false;
ICPPASTTemplateDeclaration templateDecl = CPPTemplates.getTemplateDeclaration(name);
ICPPScope scope = (ICPPScope) getContainingScope(name);
while (scope instanceof ICPPTemplateScope) {
template = true;
scope= (ICPPScope) scope.getParent();
}
@ -493,35 +492,21 @@ public class CPPVisitor extends ASTQueries {
if (binding instanceof ICPPClassType) {
final ICPPInternalBinding ib = (ICPPInternalBinding) binding;
if ((binding instanceof ICPPClassTemplate) == template) {
if (templateParametersMatch((ICPPClassType) binding, templateDecl)) {
ib.addDeclaration(elabType);
return binding;
}
if (CPPSemantics.declaredBefore(binding, name, false)) {
if (CPPSemantics.declaredBefore(ib, name, false)) {
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION);
}
// Mark the other declarations as problem and create the binding
final IASTNode[] decls = ib.getDeclarations();
if (decls != null) {
for (IASTNode decl : decls) {
if (decl instanceof IASTName) {
final IASTName n = (IASTName) decl;
n.setBinding(new ProblemBinding(n, IProblemBinding.SEMANTIC_INVALID_REDECLARATION));
}
}
}
IASTNode decl= ib.getDefinition();
if (decl instanceof IASTName) {
final IASTName n = (IASTName) decl;
n.setBinding(new ProblemBinding(n, IProblemBinding.SEMANTIC_INVALID_REDEFINITION));
}
markRedeclaration(ib);
}
}
// Create a binding
if (elabType.getKind() != IASTElaboratedTypeSpecifier.k_enum) {
if (template)
if (templateDecl != null)
binding = new CPPClassTemplate(name);
else
binding = new CPPClassType(name, binding);
@ -535,44 +520,91 @@ public class CPPVisitor extends ASTQueries {
return binding;
}
public static void markRedeclaration(final ICPPInternalBinding ib) {
// Mark the other declarations as problem and create the binding
final IASTNode[] decls = ib.getDeclarations();
if (decls != null) {
for (IASTNode decl : decls) {
if (decl instanceof IASTName) {
final IASTName n = (IASTName) decl;
n.setBinding(new ProblemBinding(n, IProblemBinding.SEMANTIC_INVALID_REDECLARATION));
}
}
}
IASTNode decl= ib.getDefinition();
if (decl instanceof IASTName) {
final IASTName n = (IASTName) decl;
n.setBinding(new ProblemBinding(n, IProblemBinding.SEMANTIC_INVALID_REDEFINITION));
}
}
/**
* Tests whether a class binding matches the template parameters of another declaration
*/
private static boolean templateParametersMatch(ICPPClassType binding,
ICPPASTTemplateDeclaration templateDecl) {
final boolean isTemplate= binding instanceof ICPPClassTemplate;
if (templateDecl == null)
return !isTemplate;
if (!isTemplate)
return false;
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) {
IASTName name = compType.getName();
if (name instanceof ICPPASTQualifiedName) {
IASTName[] ns = ((ICPPASTQualifiedName) name).getNames();
name = ns[ns.length - 1];
}
IBinding binding = null;
if (name instanceof ICPPASTTemplateId)
return CPPTemplates.createBinding((ICPPASTTemplateId) name);
ICPPScope scope = (ICPPScope) getContainingScope(name);
try {
boolean template = false;
try {
while (scope instanceof ICPPTemplateScope) {
template = true;
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) {
binding = e.getProblem();
return e.getProblem();
}
return binding;
// 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;
}
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) {