diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexMultiFileTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexMultiFileTest.java index f224ed07a3c..580639b635c 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexMultiFileTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexMultiFileTest.java @@ -199,4 +199,28 @@ public class IndexMultiFileTest extends IndexBindingResolutionTestBase { public void testFriendClassDeclaration_508338() throws Exception { checkBindings(); } + + // test.h + // template + // struct atomic; + // + // template + // struct atomic; + + // test1.cpp + // #include "test.h" + + // test2.cpp * + // #include "test.h" + // + // template + // struct atomic {}; + // + // template + // struct atomic { + // void fetch_sub(); + // }; + public void testClassTemplatePartialSpecialization_470726() throws Exception { + checkBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java index 064f0f0fcf4..b44e9e88291 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTTranslationUnit.java @@ -26,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.IMacroBinding; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; @@ -224,4 +225,13 @@ public class CPPASTTranslationUnit extends ASTTranslationUnit implements ICPPAST public Map getFinalOverriderMapCache() { return fFinalOverriderMapCache; } + + public void recordPartialSpecialization(ICPPClassTemplatePartialSpecialization indexSpec, + ICPPClassTemplatePartialSpecialization astSpec) { + fScopeMapper.recordPartialSpecialization(indexSpec, astSpec); + } + + public ICPPClassTemplatePartialSpecialization mapToAST(ICPPClassTemplatePartialSpecialization indexSpec) { + return fScopeMapper.mapToAST(indexSpec); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScopeMapper.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScopeMapper.java index b709416210a..8551d7bce10 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScopeMapper.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScopeMapper.java @@ -33,6 +33,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope; @@ -278,6 +279,9 @@ public class CPPScopeMapper { private final Map> fPerName= new HashMap<>(); private final CPPASTTranslationUnit fTu; protected CharArrayMap fClasses; + + private final Map + fPartialSpecs = new HashMap<>(); public CPPScopeMapper(CPPASTTranslationUnit tu) { fTu= tu; @@ -429,4 +433,17 @@ public class CPPScopeMapper { } return type; } + + public void recordPartialSpecialization(ICPPClassTemplatePartialSpecialization indexSpec, + ICPPClassTemplatePartialSpecialization astSpec) { + fPartialSpecs.put(indexSpec, astSpec); + } + + public ICPPClassTemplatePartialSpecialization mapToAST(ICPPClassTemplatePartialSpecialization indexSpec) { + ICPPClassTemplatePartialSpecialization astSpec = fPartialSpecs.get(indexSpec); + if (astSpec != null) { + return astSpec; + } + return indexSpec; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index 9e9e68b3623..db8b8407ba8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -837,11 +837,20 @@ public class CPPTemplates { return new ProblemBinding(id, IProblemBinding.SEMANTIC_INVALID_TEMPLATE_ARGUMENTS, templateName.toCharArray()); } ICPPPartialSpecialization partialSpec= findPartialSpecialization(classTemplate, args); + ICPPClassTemplatePartialSpecialization indexSpec = null; + if ((isDeclaration || isDefinition) && + (partialSpec instanceof ICPPClassTemplatePartialSpecialization)) { + indexSpec = (ICPPClassTemplatePartialSpecialization) partialSpec; + partialSpec = null; + } if (partialSpec == null) { if (isDeclaration || isDefinition) { if (template instanceof ICPPClassTemplate) { partialSpec = new CPPClassTemplatePartialSpecialization(id, args); - if (template instanceof ICPPInternalClassTemplate) { + if (indexSpec != null) { + SemanticUtil.recordPartialSpecialization(indexSpec, + (ICPPClassTemplatePartialSpecialization) partialSpec, id); + } else if (template instanceof ICPPInternalClassTemplate) { ((ICPPInternalClassTemplate) template).addPartialSpecialization( (ICPPClassTemplatePartialSpecialization) partialSpec); } @@ -2500,9 +2509,9 @@ public class CPPTemplates { return (f instanceof ICPPMethod) && !((ICPPMethod) f).isStatic(); } - private static ICPPPartialSpecialization findPartialSpecialization(ICPPPartiallySpecializable ct, + private static ICPPPartialSpecialization findPartialSpecialization(ICPPPartiallySpecializable template, ICPPTemplateArgument[] args) throws DOMException { - ICPPPartialSpecialization[] pspecs = ct.getPartialSpecializations(); + ICPPPartialSpecialization[] pspecs = template.getPartialSpecializations(); if (pspecs != null && pspecs.length > 0) { final String argStr= ASTTypeUtil.getArgumentListString(args, true); for (ICPPPartialSpecialization pspec : pspecs) { @@ -2554,6 +2563,10 @@ public class CPPTemplates { if (bestMatch == null) return null; + if (bestMatch instanceof ICPPClassTemplatePartialSpecialization) { + bestMatch = SemanticUtil.mapToAST((ICPPClassTemplatePartialSpecialization) bestMatch, point); + } + return instantiatePartialSpecialization(bestMatch, args, isDef, bestMap, point); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java index 0721cbf63e6..a52234c011d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java @@ -54,6 +54,7 @@ import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; @@ -559,6 +560,27 @@ public class SemanticUtil { return scope; } + public static void recordPartialSpecialization(ICPPClassTemplatePartialSpecialization indexSpec, + ICPPClassTemplatePartialSpecialization astSpec, IASTNode point) { + if (point != null) { + IASTTranslationUnit ast = point.getTranslationUnit(); + if (ast instanceof CPPASTTranslationUnit) { + ((CPPASTTranslationUnit) ast).recordPartialSpecialization(indexSpec, astSpec); + } + } + } + + public static ICPPClassTemplatePartialSpecialization mapToAST( + ICPPClassTemplatePartialSpecialization indexSpec, IASTNode point) { + if (point != null) { + IASTTranslationUnit ast = point.getTranslationUnit(); + if (ast instanceof CPPASTTranslationUnit) { + return ((CPPASTTranslationUnit) ast).mapToAST(indexSpec); + } + } + return indexSpec; + } + public static IType[] getSimplifiedTypes(IType[] types) { // Don't create a new array until it's really needed. IType[] result = types;