Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [cdt-dev] Bug in autocomplete with simple templates

Hi,

I tried to fix this issue as my bedtime sweet today. I'm waiting for the bug 
report and add some unit test, then I can push to gerrit. Or someone else 
does, since I don't really have time right now.

bye Michi

On Tuesday, 22 September 2015 11:26:40 CEST Sergey Prigogin wrote:
> Please file a bug.
> 
> -sergey
> 
> On Tue, Sep 22, 2015 at 7:03 AM, Alec Teal <a.teal@xxxxxxxxxxxxx> wrote:
> > Also a problem on
> > 8.7.0.201506070905
> > 
> > How has no one spotted this?
> > 
> > On 22/09/15 11:30, Alec Teal wrote:
> >> I've got sample code (I've distilled the problem to these, I didn't start
> >> naming at C)
> >> 
> >> -----------------------------------------------------
> >> //template<int k>
> >> //any template will do (eg class T)
> >> class D {
> >> 
> >>     struct C {
> >>     
> >>         C* c;
> >>     
> >>     };
> >> 
> >> private:
> >>     C c;
> >> 
> >> public:
> >>     void f() {
> >>     
> >>         //Auto complete on c works great if you keep the template bit
> >> 
> >> commented
> >> 
> >>     }
> >> 
> >> };
> >> ----------------------------------------------------------
> >> 
> >> I've reproduced on two computers using (I think) the same version, can
> >> confirm one of them is:
> >> 8.3.0.201402142303 (whoa, that's old) the other computer is a recent grab
> >> of Eclipse Kepler.... actually I'll look into updating. Was there an easy
> >> fix (and has it been fixed?)
> >> 
> >> Alec
> >> _______________________________________________
> >> cdt-dev mailing list
> >> cdt-dev@xxxxxxxxxxx
> >> To change your delivery options, retrieve your password, or unsubscribe
> >> from this list, visit
> >> https://dev.eclipse.org/mailman/listinfo/cdt-dev
> > 
> > _______________________________________________
> > cdt-dev mailing list
> > cdt-dev@xxxxxxxxxxx
> > To change your delivery options, retrieve your password, or unsubscribe
> > from this list, visit
> > https://dev.eclipse.org/mailman/listinfo/cdt-dev
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/HeuristicResolver.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/HeuristicResolver.java
index e2f4d2a..5943128 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/HeuristicResolver.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/HeuristicResolver.java
@@ -22,10 +22,11 @@
 import org.eclipse.cdt.core.dom.ast.IScope;
 import org.eclipse.cdt.core.dom.ast.IType;
 import org.eclipse.cdt.core.dom.ast.IVariable;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
 import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
 import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
 import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
 import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownMember;
 import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
@@ -40,40 +41,59 @@
 	public static IScope findConcreteScopeForType(IType type, IASTNode point) {
 		if (type instanceof ICPPDeferredClassInstance) {
 			// If this scope is for a deferred-class-instance, use the scope of the primary template.
 			ICPPDeferredClassInstance instance = (ICPPDeferredClassInstance) type;
 			return instance.getClassTemplate().getCompositeScope();
-		} else if (type instanceof TypeOfDependentExpression) {
+		} 
+		
+		while (type instanceof TypeOfDependentExpression) {
 			// If this scope is for the id-expression of a field reference, and the field owner
 			// is a deferred-class-instance, look up the field in the scope of the primary template,
 			// and use the scope of the resulting field type.
 			ICPPEvaluation evaluation = ((TypeOfDependentExpression) type).getEvaluation();
+			while (evaluation instanceof EvalUnary) {
+				evaluation = ((EvalUnary) evaluation).getArgument();
+			}
+			if (evaluation instanceof EvalFixed) {
+				type = ((EvalFixed) evaluation).getType();
+				continue;
+			}
 			if (evaluation instanceof EvalID) {
 				EvalID evalId = (EvalID) evaluation;
 				ICPPEvaluation fieldOwner = evalId.getFieldOwner();
 				if (fieldOwner != null) {
 					IType fieldOwnerType = fieldOwner.getTypeOrFunctionSet(point);
+					IScope scope = null;
+					if (fieldOwnerType instanceof TypeOfDependentExpression) {
+						scope = findConcreteScopeForType(fieldOwnerType, point);
+					}
 					if (fieldOwnerType instanceof ICPPDeferredClassInstance) {
 						ICPPDeferredClassInstance instance = (ICPPDeferredClassInstance) fieldOwnerType;
-						IScope scope = instance.getClassTemplate().getCompositeScope();
+						scope = instance.getClassTemplate().getCompositeScope();
+					} else if (fieldOwnerType instanceof ICPPClassType) {
+						scope = ((ICPPClassType) fieldOwnerType).getCompositeScope();
+					}
+					if (scope != null) {
 						LookupData lookup = new LookupData(evalId.getName(), evalId.getTemplateArgs(), point);
 						lookup.qualified = evalId.isQualified();
 						try {
 							CPPSemantics.lookup(lookup, scope);
 						} catch (DOMException e) {
 							return null;
 						}
 						IBinding[] bindings = lookup.getFoundBindings();
 						if (bindings.length == 1 && bindings[0] instanceof IField) {
 							IType fieldType = ((IField) bindings[0]).getType();
+							fieldType = SemanticUtil.getNestedType(fieldType, SemanticUtil.TDEF|SemanticUtil.PTR);
 							if (fieldType instanceof ICompositeType) {
 								return ((ICompositeType) fieldType).getCompositeScope(); 
 							}
 						}
 					}
 				}
 			}
+			break;
 		}
 		// TODO(nathanridge): Handle more cases.
 		return null;
 	}
 	
@@ -94,13 +114,14 @@
 		ownerType = SemanticUtil.getSimplifiedType(ownerType);
 		if (isPointerDeref && ownerType instanceof IPointerType) {
 			ownerType = ((IPointerType) ownerType).getType();
 			isPointerDeref = false;
 		}
+		IType lookupType = ownerType;
 		if (ownerType instanceof ICPPUnknownType) {
-			IType lookupType = resolveUnknownType((ICPPUnknownType) ownerType, point);
-			// ... or inside the dependent type.
+			lookupType = resolveUnknownType((ICPPUnknownType) ownerType, point);
+		} // ... or inside the dependent type.
 			if (isPointerDeref) {
 				lookupType = SemanticUtil.getSimplifiedType(lookupType);
 				if (lookupType instanceof IPointerType) {
 					lookupType = ((IPointerType) lookupType).getType();
 				} else {
@@ -117,11 +138,10 @@
 						return foundBindings;
 					}
 				} catch (DOMException e) {
 				}
 			}
-		}
 		return IBinding.EMPTY_BINDING_ARRAY;
 	}
 	
 	/**
 	 * Helper function for resolveUnknownType(). 
@@ -146,11 +166,11 @@
 	 * 
 	 * Returns null if no heuristic resolution could be performed.
 
 	 * @param point the point of instantiation for lookups
 	 */
-	private static IType resolveUnknownType(ICPPUnknownType type, IASTNode point) {
+	public static IType resolveUnknownType(ICPPUnknownType type, IASTNode point) {
 		if (type instanceof ICPPDeferredClassInstance) {
 			return ((ICPPDeferredClassInstance) type).getClassTemplate();
 		} else if (type instanceof TypeOfDependentExpression) {
 			ICPPEvaluation evaluation = ((TypeOfDependentExpression) type).getEvaluation();
 			if (evaluation instanceof EvalUnary) {
@@ -192,11 +212,11 @@
 	 * @param point the point of instantiation for lookups
 	 */
 	public static IBinding[] resolveUnknownBinding(ICPPUnknownBinding binding, IASTNode point) {
 		if (binding instanceof ICPPDeferredClassInstance) {
 			return new IBinding[] { ((ICPPDeferredClassInstance) binding).getClassTemplate() };
-		} else if (binding instanceof ICPPUnknownMember) {
+		} else if (binding instanceof ICPPUnknownMember && !(binding instanceof ICPPTemplateParameter)) {
 			return lookInside(((ICPPUnknownMember) binding).getOwnerType(), false,
 					binding.getNameCharArray(), null, point);
 		}
 		return IBinding.EMPTY_BINDING_ARRAY;
 	}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistProcessor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistProcessor.java
index ad6df3d..077e937 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistProcessor.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/CContentAssistProcessor.java
@@ -42,10 +42,12 @@
 import org.eclipse.cdt.ui.CUIPlugin;
 import org.eclipse.cdt.ui.text.ICCompletionProposal;
 import org.eclipse.cdt.ui.text.contentassist.ContentAssistInvocationContext;
 import org.eclipse.cdt.ui.text.contentassist.IProposalFilter;
 
+import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
+import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.HeuristicResolver;
 import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
 
 import org.eclipse.cdt.internal.ui.preferences.ProposalFilterPreferencesUtil;
 import org.eclipse.cdt.internal.ui.text.CHeuristicScanner;
 import org.eclipse.cdt.internal.ui.text.CParameterListValidator;
@@ -271,10 +273,13 @@
 				IASTName[] names = node.getNames();
 				if (names.length > 0 && names[0].getParent() instanceof IASTFieldReference) {
 					IASTFieldReference ref = (IASTFieldReference) names[0].getParent();
 					IASTExpression ownerExpr = ref.getFieldOwner();
 					IType ownerExprType = SemanticUtil.getNestedType(ownerExpr.getExpressionType(), SemanticUtil.TDEF);
+					if (ownerExprType instanceof ICPPUnknownType) {
+						ownerExprType = HeuristicResolver.resolveUnknownType((ICPPUnknownType) ownerExprType,names[0]);
+					}
 					if (ownerExprType instanceof IPointerType) {
 						context = replaceDotWithArrow(viewer, offset, isCompletion, context, activationChar);
 					}
 				}
 			}

Back to the top