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 edd950758da..adb24e96363 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 @@ -362,4 +362,24 @@ public class IndexMultiFileTest extends IndexBindingResolutionTestBase { public void testAliasTemplateReferencingSameName_518937() throws Exception { checkBindings(); } + + //h1.h + // class A { + // friend class B1; + // }; + + //s1.cpp + // #include "h1.h" + + //h2.h + // class B1 {}; + // class B2 {}; + + //s2.cpp * + // #include "h2.h" + // B1 b1; + // B2 b2; + public void testClassFirstDeclaredAsFriend_530430() throws Exception { + checkBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IName.java index 69d4eb07b79..199e36c2b72 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/IName.java @@ -56,7 +56,7 @@ public interface IName { public boolean isReference(); /** - * Is this name being used in the AST as a reference rather than a declaration? + * Is this name being used in the AST as a definition rather than a declaration? * @return boolean */ public boolean isDefinition(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/IPDOMCPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/IPDOMCPPClassType.java index 9efb5691307..03561e12613 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/IPDOMCPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/IPDOMCPPClassType.java @@ -46,5 +46,11 @@ public interface IPDOMCPPClassType extends ICPPClassType, IPDOMBinding, IIndexTy * A class type is visible to ADL only if it's only declaration so far * is a friend declaration inside another class. */ - default boolean isVisibleToAdlOnly() { return false; } + boolean isVisibleToAdlOnly(); + + /** + * Set whether this class type is visible to ADL only. + * See isVisibleToAdlOnly(). + */ + void setVisibleToAdlOnly(boolean visibleToAdlOnly) throws CoreException; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java index 7883148bc8b..6bee6866b49 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassSpecialization.java @@ -558,4 +558,15 @@ class PDOMCPPClassSpecialization extends PDOMCPPSpecialization return v_private; // Fallback visibility } } + + // Class specializations do not need to be marked "visible to ADL only" + // independent of their specialized class types, so they do not need + // to implement these methods. + @Override + public boolean isVisibleToAdlOnly() { + return false; + } + @Override + public void setVisibleToAdlOnly(boolean visibleToAdlOnly) throws CoreException { + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java index a8f4cad182d..333d3214079 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPClassType.java @@ -110,7 +110,8 @@ class PDOMCPPClassType extends PDOMCPPBinding implements IPDOMCPPClassType, IPDO getDB().putByte(record + FINAL, (byte) (ct.isFinal() ? 1 : 0)); } - private void setVisibleToAdlOnly(boolean visibleToAdlOnly) throws CoreException { + @Override + public void setVisibleToAdlOnly(boolean visibleToAdlOnly) throws CoreException { getDB().putByte(record + VISIBLE_TO_ADL_ONLY, (byte) (visibleToAdlOnly ? 1 : 0)); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index 5a6ec404f77..0a63d117761 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -635,6 +635,26 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { addImplicitMethods(pdomBinding, (ICPPClassType) binding); } } + + // If we have a non-friend declaration of a class type, mark the class type + // as being fully visible (not just visible to ADL only). This is important + // in case the first declaration of the class type was a friend declaration, + // in which case it was initially marked as visible to ADL only. + if (pdomBinding instanceof IPDOMCPPClassType && (name.isDeclaration() || name.isDefinition())) { + boolean declaresFriend = false; + IASTNode parent = name.getParent(); + if (parent instanceof ICPPASTQualifiedName) { + parent = parent.getParent(); + } + if (parent instanceof ICPPASTElaboratedTypeSpecifier) { + if (((ICPPASTElaboratedTypeSpecifier) parent).isFriend()) { + declaresFriend = true; + } + } + if (!declaresFriend) { + ((IPDOMCPPClassType) pdomBinding).setVisibleToAdlOnly(false); + } + } // Some of the nodes created during addImplicitMethods() can // also schedule post-processes, so we need to run through