mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-05 08:46:02 +02:00
Do not allow structured binding initializer referencing introduced name (#241)
If name lookup ends up with a variable, additionally check if node being resolved is part of the structured binding initializer introducing found variable. If this is the case, produce problem binding and report structured binding declaration error via codan. This change also prevents infinite recursion trying to resolve auto type of introduced variable while evaluating such problematic initializer.
This commit is contained in:
parent
2776d17014
commit
fe7a9d7856
10 changed files with 62 additions and 1 deletions
|
@ -2,7 +2,7 @@ Manifest-Version: 1.0
|
|||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: %Bundle-Name
|
||||
Bundle-SymbolicName: org.eclipse.cdt.codan.checkers;singleton:=true
|
||||
Bundle-Version: 3.5.0.qualifier
|
||||
Bundle-Version: 3.5.100.qualifier
|
||||
Bundle-Activator: org.eclipse.cdt.codan.checkers.CodanCheckersActivator
|
||||
Require-Bundle: org.eclipse.core.runtime,
|
||||
org.eclipse.core.resources,
|
||||
|
|
|
@ -113,6 +113,9 @@ problem.name.11 = Method cannot be resolved
|
|||
problem.description.12 = Name resolution problem found by the indexer
|
||||
problem.messagePattern.12 = Field ''{0}'' could not be resolved
|
||||
problem.name.12 = Field cannot be resolved
|
||||
problem.description.13 = Name resolution problem found by the indexer
|
||||
problem.messagePattern.13 = Structured binding initializer expression refers to introduced name ''{0}''
|
||||
problem.name.13 = Invalid structured binding declaration
|
||||
checker.name.AbstractClassCreation = Abstract class cannot be instantiated
|
||||
problem.name.AbstractClassCreation = Abstract class cannot be instantiated
|
||||
problem.messagePattern.AbstractClassCreation = The type ''{0}'' must implement the inherited pure virtual method ''{1}''\u0020
|
||||
|
|
|
@ -273,6 +273,16 @@
|
|||
messagePattern="%problem.messagePattern.12"
|
||||
name="%problem.name.12">
|
||||
</problem>
|
||||
<problem
|
||||
category="org.eclipse.cdt.codan.core.categories.CompilerErrors"
|
||||
defaultEnabled="true"
|
||||
defaultSeverity="Error"
|
||||
description="%problem.description.13"
|
||||
id="org.eclipse.cdt.codan.internal.checkers.StructuredBindingDeclarationProblem"
|
||||
markerType="org.eclipse.cdt.codan.core.codanSemanticProblem"
|
||||
messagePattern="%problem.messagePattern.13"
|
||||
name="%problem.name.13">
|
||||
</problem>
|
||||
</checker>
|
||||
<checker
|
||||
class="org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfChecker"
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTStructuredBindingDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
|
@ -64,6 +65,7 @@ public class ProblemBindingChecker extends AbstractIndexAstChecker {
|
|||
public static String ERR_ID_FieldResolutionProblem = "org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem"; //$NON-NLS-1$
|
||||
public static String ERR_ID_VariableResolutionProblem = "org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem"; //$NON-NLS-1$
|
||||
public static String ERR_ID_Candidates = "org.eclipse.cdt.codan.internal.checkers.Candidates"; //$NON-NLS-1$
|
||||
public static String ERR_ID_StructuredBindingDeclarationProblem = "org.eclipse.cdt.codan.internal.checkers.StructuredBindingDeclarationProblem"; //$NON-NLS-1$
|
||||
|
||||
@Override
|
||||
public boolean runInEditor() {
|
||||
|
@ -126,6 +128,22 @@ public class ProblemBindingChecker extends AbstractIndexAstChecker {
|
|||
contextFlagsString);
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
if (id == IProblemBinding.SEMANTIC_INVALID_STRUCTURED_BINDING_INITIALIZER) {
|
||||
IASTNode problemNode = parentNode;
|
||||
while (problemNode != null) {
|
||||
if (problemNode instanceof ICPPASTStructuredBindingDeclaration) {
|
||||
break;
|
||||
}
|
||||
problemNode = problemNode.getParent();
|
||||
}
|
||||
if (problemNode == null) {
|
||||
// this should not happen because problem binding should be inside structured binding initializer subtree
|
||||
problemNode = parentNode;
|
||||
}
|
||||
reportProblem(ERR_ID_StructuredBindingDeclarationProblem, problemNode,
|
||||
parentNode.getRawSignature(), contextFlagsString);
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
if (id == IProblemBinding.SEMANTIC_INVALID_REDECLARATION) {
|
||||
reportProblem(ERR_ID_RedeclarationProblem, name, name.getRawSignature(),
|
||||
contextFlagsString);
|
||||
|
|
|
@ -415,4 +415,12 @@ public class StructuredBindingTests extends AST2CPPTestBase {
|
|||
assertEquals(IntegralValue.create(1), subvalues[0].getValue());
|
||||
assertEquals(FloatingPointValue.create(2.0), subvalues[1].getValue());
|
||||
}
|
||||
|
||||
//void f() {
|
||||
// auto& [x] = x.y;
|
||||
//}
|
||||
public void testInvalidReferenceToIntroducedName() throws Exception {
|
||||
BindingAssertionHelper ba = getAssertionHelper();
|
||||
ba.assertProblem("x.y;", 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,8 @@ public interface IProblemBinding extends IBinding, IScope, IType, ISemanticProbl
|
|||
public static final int SEMANTIC_RECURSION_IN_LOOKUP = BINDING_RECURSION_IN_LOOKUP;
|
||||
/** @since 5.1 */
|
||||
public static final int SEMANTIC_INVALID_TEMPLATE_ARGUMENTS = BINDING_INVALID_TEMPLATE_ARGUMENTS;
|
||||
/** @since 8.1 */
|
||||
public static final int SEMANTIC_INVALID_STRUCTURED_BINDING_INITIALIZER = BINDING_INVALID_STRUCTURED_BINDING_INITIALIZER;
|
||||
|
||||
/**
|
||||
* @deprecated There may be additional problems.
|
||||
|
|
|
@ -37,6 +37,8 @@ public interface ISemanticProblem {
|
|||
int BINDING_RECURSION_IN_LOOKUP = 14;
|
||||
int BINDING_INVALID_TEMPLATE_ARGUMENTS = 15;
|
||||
int BINDING_NO_CLASS = 16;
|
||||
/** @since 8.1 */
|
||||
int BINDING_INVALID_STRUCTURED_BINDING_INITIALIZER = 17;
|
||||
|
||||
int TYPE_NO_NAME = 10000;
|
||||
int TYPE_UNRESOLVED_NAME = 10001;
|
||||
|
|
|
@ -409,6 +409,21 @@ public class CPPSemantics {
|
|||
}
|
||||
}
|
||||
|
||||
// If any name in the initializer refers to introduced names then declaration is ill-formed.
|
||||
if (binding instanceof ICPPInternalBinding internalBinding && internalBinding.getDefinition() != null
|
||||
&& internalBinding.getDefinition()
|
||||
.getParent() instanceof ICPPASTStructuredBindingDeclaration declaration) {
|
||||
IASTNode parent = lookupName.getParent();
|
||||
while (parent != null) {
|
||||
if (parent == declaration) {
|
||||
binding = new ProblemBinding(lookupName, data.getLookupPoint(),
|
||||
IProblemBinding.SEMANTIC_INVALID_STRUCTURED_BINDING_INITIALIZER, data.getFoundBindings());
|
||||
break;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
}
|
||||
}
|
||||
|
||||
if (binding instanceof IProblemBinding)
|
||||
return binding;
|
||||
|
||||
|
|
|
@ -93,6 +93,8 @@ public class ParserMessages {
|
|||
return "ISemanticProblem.BINDING_INVALID_REDECLARATION";
|
||||
case ISemanticProblem.BINDING_INVALID_REDEFINITION:
|
||||
return "ISemanticProblem.BINDING_INVALID_REDEFINITION";
|
||||
case ISemanticProblem.BINDING_INVALID_STRUCTURED_BINDING_INITIALIZER:
|
||||
return "ISemanticProblem.BINDING_INVALID_STRUCTURED_BINDING_INITIALIZER";
|
||||
case ISemanticProblem.BINDING_INVALID_TEMPLATE_ARGUMENTS:
|
||||
return "ISemanticProblem.BINDING_INVALID_TEMPLATE_ARGUMENTS";
|
||||
case ISemanticProblem.BINDING_INVALID_TYPE:
|
||||
|
|
|
@ -71,6 +71,7 @@ ISemanticProblem.BINDING_INVALID_REDECLARATION=Invalid redeclaration of the name
|
|||
ISemanticProblem.BINDING_RECURSION_IN_LOOKUP=Recursion while looking up ''{0}''
|
||||
ISemanticProblem.BINDING_MEMBER_DECLARATION_NOT_FOUND=A declaration could not be found for this member definition: {0}
|
||||
ISemanticProblem.BINDING_INVALID_TEMPLATE_ARGUMENTS=A template id provides illegal arguments for the instantiation: {0}
|
||||
ISemanticProblem.BINDING_INVALID_STRUCTURED_BINDING_INITIALIZER=Invalid structured binding initializer referencing introduced name ''{0}''
|
||||
|
||||
ISemanticProblem.TYPE_NO_NAME=Type specification lacks a name
|
||||
ISemanticProblem.TYPE_UNRESOLVED_NAME=Type depends on an unresolved name
|
||||
|
|
Loading…
Add table
Reference in a new issue