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 b44e9e88291..0bb7758f146 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 @@ -32,6 +32,9 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; +import org.eclipse.cdt.core.index.IIndexBinding; +import org.eclipse.cdt.core.index.IIndexFileSet; import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.Linkage; @@ -48,13 +51,15 @@ import org.eclipse.cdt.internal.core.parser.scanner.InternalFileContent; public class CPPASTTranslationUnit extends ASTTranslationUnit implements ICPPASTTranslationUnit, IASTAmbiguityParent { private CPPNamespaceScope fScope; private ICPPNamespace fBinding; - private final CPPScopeMapper fScopeMapper= new CPPScopeMapper(this); + private final CPPScopeMapper fScopeMapper; private CPPASTAmbiguityResolver fAmbiguityResolver; // Caches - private Map fFinalOverriderMapCache = new HashMap<>(); + private final Map fFinalOverriderMapCache = new HashMap<>(); + private final Map fBindingReachabilityCache = new HashMap<>(); public CPPASTTranslationUnit() { + fScopeMapper= new CPPScopeMapper(this); } @Override @@ -234,4 +239,43 @@ public class CPPASTTranslationUnit extends ASTTranslationUnit implements ICPPAST public ICPPClassTemplatePartialSpecialization mapToAST(ICPPClassTemplatePartialSpecialization indexSpec) { return fScopeMapper.mapToAST(indexSpec); } + + /** + * Checks if a binding is an AST binding, or is reachable from the AST through includes. + * The binding is assumed to belong to the AST, if it is not an IIndexBinding and not + * a specialization of an IIndexBinding. + * + * @param binding + * @return {@code true} if the {@code binding} is reachable from the AST. + */ + public boolean isReachableFromAst(IBinding binding) { + Boolean cachedValue = fBindingReachabilityCache.get(binding); + if (cachedValue != null) + return cachedValue; + + IIndexBinding indexBinding = null; + if (binding instanceof IIndexBinding) { + indexBinding = (IIndexBinding) binding; + } + if (binding instanceof ICPPSpecialization) { + binding = ((ICPPSpecialization) binding).getSpecializedBinding(); + if (binding instanceof IIndexBinding) { + indexBinding = (IIndexBinding) binding; + } + } + boolean reachable; + if (indexBinding == null) { + // We don't check if the binding really belongs to this AST assuming that + // the caller doesn't deal with two ASTs at a time. + reachable = true; + } else { + IIndexFileSet indexFileSet = getIndexFileSet(); + IIndexFileSet astFileSet = getASTFileSet(); + reachable = indexFileSet != null && + (indexFileSet.containsDeclaration(indexBinding) || + astFileSet.containsDeclaration(indexBinding)); + } + fBindingReachabilityCache.put(binding, reachable); + return reachable; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index b8d90dd96dc..169e1ad4366 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -1104,7 +1104,7 @@ public class CPPSemantics { if (item instanceof IBinding) { IBinding binding = (IBinding) item; CPPASTTranslationUnit tu = data.getTranslationUnit(); - if (!isFromIndex(binding) || tu == null || isReachableFromAst(tu, binding)) { + if (!isFromIndex(binding) || tu == null || tu.isReachableFromAst(binding)) { return true; } } @@ -2257,7 +2257,7 @@ public class CPPSemantics { * the two bindings have the same relevance; -1 if b1 is less relevant than * b2. */ - static int compareByRelevance(IASTTranslationUnit tu, IBinding b1, IBinding b2) { + static int compareByRelevance(CPPASTTranslationUnit tu, IBinding b1, IBinding b2) { boolean b1FromIndex= isFromIndex(b1); boolean b2FromIndex= isFromIndex(b2); if (b1FromIndex != b2FromIndex) { @@ -2265,8 +2265,8 @@ public class CPPSemantics { } else if (b1FromIndex) { // Both are from index. if (tu != null) { - boolean b1Reachable= isReachableFromAst(tu, b1); - boolean b2Reachable= isReachableFromAst(tu, b2); + boolean b1Reachable= tu.isReachableFromAst(b1); + boolean b2Reachable= tu.isReachableFromAst(b2); if (b1Reachable != b2Reachable) { return b1Reachable ? 1 : -1; } @@ -2285,7 +2285,7 @@ public class CPPSemantics { return false; final CPPASTTranslationUnit tu = data.getTranslationUnit(); if (tu != null) { - return !isReachableFromAst(tu, b2) && isReachableFromAst(tu, type); + return !tu.isReachableFromAst(b2) && tu.isReachableFromAst(type); } return false; } @@ -2306,12 +2306,12 @@ public class CPPSemantics { } } - if (!isReachableFromAst(tu, type)) { + if (!tu.isReachableFromAst(type)) { return false; } for (IFunction fn : fns) { - if (isReachableFromAst(tu, fn)) { + if (tu.isReachableFromAst(fn)) { return false; // function from ast } } @@ -2368,12 +2368,12 @@ public class CPPSemantics { } // Everything is from the index final CPPASTTranslationUnit tu = data.getTranslationUnit(); - if (!isReachableFromAst(tu, obj)) { + if (!tu.isReachableFromAst(obj)) { return -1; // obj not reachable } for (IFunction fn : fns) { - if (isReachableFromAst(tu, fn)) { + if (tu.isReachableFromAst(fn)) { return 0; // obj reachable, 1 function reachable } } @@ -2403,40 +2403,10 @@ public class CPPSemantics { * Checks if a binding is an AST binding, or is reachable from the AST through includes. * The binding is assumed to belong to the AST, if it is not an IIndexBinding and not * a specialization of an IIndexBinding. + * * @param ast * @param binding - * @return true if the binding is reachable from ast. - */ - private static boolean isReachableFromAst(IASTTranslationUnit ast, IBinding binding) { - IIndexBinding indexBinding = null; - if (binding instanceof IIndexBinding) { - indexBinding = (IIndexBinding) binding; - } - if (binding instanceof ICPPSpecialization) { - binding = ((ICPPSpecialization) binding).getSpecializedBinding(); - if (binding instanceof IIndexBinding) { - indexBinding = (IIndexBinding) binding; - } - } - if (indexBinding == null) { - // We don't check if the binding really belongs to the AST specified by the ast - // parameter assuming that the caller doesn't deal with two ASTs at a time. - return true; - } - IIndexFileSet indexFileSet = ast.getIndexFileSet(); - IIndexFileSet astFileSet = ast.getASTFileSet(); - return indexFileSet != null && - (indexFileSet.containsDeclaration(indexBinding) || - astFileSet.containsDeclaration(indexBinding)); - } - - /** - * Checks if a binding is an AST binding, or is reachable from the AST through includes. - * The binding is assumed to belong to the AST, if it is not an IIndexBinding and not - * a specialization of an IIndexBinding. - * @param ast - * @param binding - * @return true if the binding is reachable from ast. + * @return {@code true} if the {@code binding}> is reachable from {@code ast}. */ private static boolean isReachableFromAst(IASTTranslationUnit ast, IName name) { if (!(name instanceof IIndexName)) { @@ -2750,7 +2720,7 @@ public class CPPSemantics { } // Try to instantiate a template - IASTTranslationUnit tu= data.getTranslationUnit(); + CPPASTTranslationUnit tu= data.getTranslationUnit(); ICPPTemplateArgument[] tmplArgs= ICPPTemplateArgument.EMPTY_ARGUMENTS; if (templateID instanceof ICPPASTTemplateId) { tmplArgs = CPPTemplates.createTemplateArgumentArray((ICPPASTTemplateId) templateID); @@ -3322,7 +3292,7 @@ public class CPPSemantics { ICPPFunction result= null; ICPPFunctionTemplate resultTemplate= null; boolean isAmbiguous= false; - final IASTTranslationUnit tu= point.getTranslationUnit(); + final CPPASTTranslationUnit tu= (CPPASTTranslationUnit) point.getTranslationUnit(); for (IFunction fn : fns) { try { if (fn instanceof ICPPFunctionTemplate) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java index 22d1c0a4fe9..6dfee36aef6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java @@ -20,7 +20,6 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTNode; -import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IType; @@ -30,6 +29,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates.TypeSelection; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.DeferredUDC; @@ -131,7 +131,7 @@ class FunctionCost { /** * Compares this function call cost to another one. */ - public int compareTo(IASTTranslationUnit tu, FunctionCost other) throws DOMException { + public int compareTo(CPPASTTranslationUnit tu, FunctionCost other) throws DOMException { if (other == null) return -1;