1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Add basic support for c++20 three-way comparison operator

This commit is contained in:
Igor V. Kovalenko 2022-12-07 21:56:12 +03:00 committed by Jonah Graham
parent ccf8053680
commit ff8ac10f6e
21 changed files with 96 additions and 10 deletions

View file

@ -29,14 +29,18 @@ public class LexerTests extends BaseTestCase {
private static final LexerOptions DEFAULT_OPTIONS = new LexerOptions();
private static final LexerOptions NO_DOLLAR = new LexerOptions();
private static final LexerOptions NO_MINMAX = new LexerOptions();
private static final LexerOptions NO_MINMAX_CPP = new LexerOptions();
private static final LexerOptions SLASH_PERCENT = new LexerOptions();
private static final LexerOptions CPP_OPTIONS = new LexerOptions();
static {
NO_DOLLAR.fSupportDollarInIdentifiers = false;
NO_MINMAX.fSupportMinAndMax = false;
NO_MINMAX_CPP.fSupportMinAndMax = false;
NO_MINMAX_CPP.fSupportThreeWayComparisonOperator = true;
SLASH_PERCENT.fSupportSlashPercentComments = true;
CPP_OPTIONS.fSupportRawStringLiterals = true;
CPP_OPTIONS.fSupportDigitSeparators = true;
CPP_OPTIONS.fSupportThreeWayComparisonOperator = true;
}
static String TRIGRAPH_REPLACES_CHARS = "#^[]|{}~\\";
@ -716,11 +720,26 @@ public class LexerTests extends BaseTestCase {
IToken.tGTEQUAL, IToken.tAND, IToken.tOR, IToken.tINCR, IToken.tDECR, IToken.tCOMMA, IToken.tARROWSTAR,
IToken.tARROW, IGCCToken.tMIN, IGCCToken.tMAX, Lexer.tOTHER_CHARACTER, };
verifyOperatorAndPunctuators(ops, tokens, DEFAULT_OPTIONS, NO_MINMAX);
}
public void testOperatorAndPunctuatorsCpp20() throws Exception {
final String ops = "<<>><<=>>===!=<=>>=<=&&";
final int[] tokens = new int[] { IToken.tSHIFTL, IToken.tSHIFTR, IToken.tSHIFTLASSIGN, IToken.tSHIFTRASSIGN,
IToken.tEQUAL, IToken.tNOTEQUAL, IToken.tTHREEWAYCOMPARISON, IToken.tGTEQUAL, IToken.tLTEQUAL,
IToken.tAND, };
verifyOperatorAndPunctuators(ops, tokens, CPP_OPTIONS, NO_MINMAX_CPP);
}
private void verifyOperatorAndPunctuators(String ops, int[] tokens, LexerOptions options,
LexerOptions optionsNoMinMax) throws Exception {
for (int splices = 0; splices < 9; splices++) {
for (int trigraphs = 0; trigraphs < 6; trigraphs++) {
StringBuilder buf = new StringBuilder();
String input = useTrigraphs(ops.toCharArray(), trigraphs);
init(instertLineSplices(input, splices));
init(instertLineSplices(input, splices), options);
for (int token2 : tokens) {
Token token = fLexer.currentToken();
buf.append(token.getCharImage());
@ -729,7 +748,7 @@ public class LexerTests extends BaseTestCase {
eof();
assertEquals(ops, buf.toString()); // check token image
init(input, NO_MINMAX);
init(input, optionsNoMinMax);
for (int token : tokens) {
switch (token) {
case IGCCToken.tMIN:

View file

@ -1167,6 +1167,8 @@ public class ASTStringUtil {
return Keywords.cpEQUAL;
case IASTBinaryExpression.op_notequals:
return Keywords.cpNOTEQUAL;
case IASTBinaryExpression.op_threewaycomparison:
return Keywords.cpTHREEWAYCOMPARISON;
case IASTBinaryExpression.op_max:
return Keywords.cpMAX;
case IASTBinaryExpression.op_min:

View file

@ -1311,6 +1311,9 @@ public class ASTSignatureUtil {
case IASTBinaryExpression.op_notequals:
opString = String.valueOf(Keywords.cpNOTEQUAL);
break;
case IASTBinaryExpression.op_threewaycomparison:
opString = String.valueOf(Keywords.cpTHREEWAYCOMPARISON);
break;
case IASTBinaryExpression.op_max:
opString = String.valueOf(Keywords.cpMAX);
break;

View file

@ -226,6 +226,13 @@ public interface IASTBinaryExpression extends IASTExpression {
*/
public static final int op_ellipses = 34;
/**
* For c++, only.
* <code>op_threewaycompare</code> represents <code><=></code> three-way comparison operator.
* @since 8.0
*/
public static final int op_threewaycomparison = 35;
/**
* Get the first operand.
*

View file

@ -85,6 +85,8 @@ public interface IToken {
int tNOTEQUAL = 35;
int tNOT = 36;
int tEQUAL = 37;
/** @since 8.0 */
int tTHREEWAYCOMPARISON = 8001;
int tASSIGN = 38;
int tUNKNOWN_CHAR = 39;
int tSHIFTL = 40;

View file

@ -279,6 +279,7 @@ public class Keywords {
public static final char[] cpNOTEQUAL = "!=".toCharArray();
public static final char[] cpNOT = "!".toCharArray();
public static final char[] cpEQUAL = "==".toCharArray();
public static final char[] cpTHREEWAYCOMPARISON = "<=>".toCharArray();
public static final char[] cpASSIGN = "=".toCharArray();
public static final char[] cpSHIFTL = "<<".toCharArray();
public static final char[] cpLTEQUAL = "<=".toCharArray();

View file

@ -224,19 +224,21 @@ public abstract class ASTAmbiguousBinaryVsCastExpression extends ASTAmbiguousNod
case IASTBinaryExpression.op_max:
case IASTBinaryExpression.op_min:
return 7;
case IASTBinaryExpression.op_threewaycomparison:
return 8;
case IASTBinaryExpression.op_shiftLeft:
case IASTBinaryExpression.op_shiftRight:
return 8;
return 9;
case IASTBinaryExpression.op_plus:
case IASTBinaryExpression.op_minus:
return 9;
return 10;
case IASTBinaryExpression.op_multiply:
case IASTBinaryExpression.op_divide:
case IASTBinaryExpression.op_modulo:
return 10;
return 11;
case IASTBinaryExpression.op_pmarrow:
case IASTBinaryExpression.op_pmdot:
return 11;
return 12;
}
assert false;
return 0;

View file

@ -1123,6 +1123,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
case IToken.tNOTEQUAL:
op = IASTBinaryExpression.op_notequals;
break;
case IToken.tTHREEWAYCOMPARISON:
op = IASTBinaryExpression.op_threewaycomparison;
break;
case IToken.tGT:
op = IASTBinaryExpression.op_greaterThan;
break;
@ -2731,6 +2734,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
case IToken.tDOT:
case IToken.tDOTSTAR:
case IToken.tEQUAL:
case IToken.tTHREEWAYCOMPARISON:
case IToken.tGT:
case IToken.tGT_in_SHIFTR:
case IToken.tGTEQUAL:

View file

@ -224,6 +224,9 @@ public class ValueFactory {
case IASTBinaryExpression.op_greaterEqual:
value = v1 >= v2 ? 1l : 0l;
break;
case IASTBinaryExpression.op_threewaycomparison:
// TODO: implement for <=>
break;
case IASTBinaryExpression.op_binaryAnd:
value = v1 & v2;
break;

View file

@ -439,6 +439,7 @@ public abstract class VariableReadWriteFlags {
case IASTBinaryExpression.op_notequals:
case IASTBinaryExpression.op_shiftLeft:
case IASTBinaryExpression.op_shiftRight:
case IASTBinaryExpression.op_threewaycomparison:
return Optional.of(READ);
case IASTBinaryExpression.op_minus:

View file

@ -234,6 +234,10 @@ public class CASTBinaryExpression extends ASTNode implements IASTBinaryExpressio
case op_notequals:
return new CBasicType(Kind.eInt, 0, this);
case op_threewaycomparison:
// TODO: implement for <=>
break;
case IASTBinaryExpression.op_plus:
if (type1 instanceof IArrayType) {
return Conversions.arrayTypeToPointerType((ICArrayType) type1);

View file

@ -548,6 +548,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
break;
case IToken.tEQUAL:
case IToken.tNOTEQUAL:
case IToken.tTHREEWAYCOMPARISON:
lastOperator = new BinaryOperator(lastOperator, lastExpression, lt1, 80, 81);
break;
case IToken.tGT:

View file

@ -1106,6 +1106,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
break;
case IToken.tEQUAL:
case IToken.tNOTEQUAL:
case IToken.tTHREEWAYCOMPARISON:
lastOperator = new BinaryOperator(lastOperator, expr, lt1, 80, 81);
break;
case IToken.tGT:

View file

@ -34,9 +34,9 @@ public enum OverloadableOperator {
GT(">"), LT("<"), NOT("!"), BITCOMPLEMENT("~"), BITOR("|"), AMPER("&"), XOR("^"), MOD("%"), DIV("/"), STAR("*"),
PLUS("+"), BRACKET("[]"), PAREN("()"), ARROW("->"), ARROWSTAR("->*"), COMMA(","), MINUS("-"), DECR("--"),
INCR("++"), OR("||"), AND("&&"), ASSIGN("="), GTEQUAL(">="), LTEQUAL("<="), NOTEQUAL("!="), EQUAL("=="),
SHIFTR(">>"), SHIFTL("<<"), SHIFTLASSIGN("<<="), SHIFTRASSIGN(">>="), BITORASSIGN("|="), AMPERASSIGN("&="),
XORASSIGN("^="), MODASSIGN("%="), DIVASSIGN("/="), STARASSIGN("*="), MINUSASSIGN("-="), PLUSASSIGN("+="),
NEW("new"), DELETE_ARRAY("delete[]"), DELETE("delete"), NEW_ARRAY("new[]"),
SHIFTR(">>"), SHIFTL("<<"), SHIFTLASSIGN("<<="), SHIFTRASSIGN(">>="), THREEWAYCOMPARISON("<=>"), BITORASSIGN("|="),
AMPERASSIGN("&="), XORASSIGN("^="), MODASSIGN("%="), DIVASSIGN("/="), STARASSIGN("*="), MINUSASSIGN("-="),
PLUSASSIGN("+="), NEW("new"), DELETE_ARRAY("delete[]"), DELETE("delete"), NEW_ARRAY("new[]"),
/**
* Cannot be overloaded by the user, however overload resolution needs to be performed.
@ -155,6 +155,8 @@ public enum OverloadableOperator {
return LT;
case IToken.tLTEQUAL:
return LTEQUAL;
case IToken.tTHREEWAYCOMPARISON:
return THREEWAYCOMPARISON;
// other
case IToken.tASSIGN:
@ -247,6 +249,8 @@ public enum OverloadableOperator {
return LT;
case IASTBinaryExpression.op_lessEqual:
return LTEQUAL;
case IASTBinaryExpression.op_threewaycomparison:
return THREEWAYCOMPARISON;
// other
case IASTBinaryExpression.op_assign:

View file

@ -167,6 +167,10 @@ class BuiltinOperators {
comparison(true);
break;
case THREEWAYCOMPARISON:
// TODO: implement for <=>
break;
case GT:
case GTEQUAL:
case LT:

View file

@ -45,6 +45,7 @@ import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_shiftLeft;
import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_shiftLeftAssign;
import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_shiftRight;
import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_shiftRightAssign;
import static org.eclipse.cdt.core.dom.ast.IASTBinaryExpression.op_threewaycomparison;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.LVALUE;
import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.ExpressionTypes.glvalueType;
@ -388,6 +389,10 @@ public class EvalBinary extends CPPDependentEvaluation {
case op_notequals:
return CPPBasicType.BOOLEAN;
case op_threewaycomparison:
// TODO: implement for <=>
return ProblemType.UNKNOWN_FOR_EXPRESSION;
case op_plus:
if (type1 instanceof IPointerType) {
return ExpressionTypes.restoreTypedefs(type1, originalType1);

View file

@ -91,6 +91,7 @@ public class ExpressionWriter extends NodeWriter {
private static final String ELLIPSES = " ... "; //$NON-NLS-1$
private static final String NOT_EQUALS_OP = " != "; //$NON-NLS-1$
private static final String EQUALS_OP = " == "; //$NON-NLS-1$
private static final String THREEWAYCOMPARISON_OP = " <=> "; //$NON-NLS-1$
private static final String BINARY_OR_ASSIGN = " |= "; //$NON-NLS-1$
private static final String BINARY_XOR_ASSIGN_OP = " ^= "; //$NON-NLS-1$
private static final String BINARY_AND_ASSIGN_OP = " &= "; //$NON-NLS-1$
@ -226,6 +227,8 @@ public class ExpressionWriter extends NodeWriter {
return EQUALS_OP;
case IASTBinaryExpression.op_notequals:
return NOT_EQUALS_OP;
case IASTBinaryExpression.op_threewaycomparison:
return THREEWAYCOMPARISON_OP;
case ICPPASTBinaryExpression.op_pmdot:
return PMDOT_OP;
case ICPPASTBinaryExpression.op_pmarrow:

View file

@ -99,6 +99,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
private static final int ORIGIN_INACTIVE_CODE = OffsetLimitReachedException.ORIGIN_INACTIVE_CODE;
private static final char[] ONE = "1".toCharArray(); //$NON-NLS-1$
private static final char[] CPP_IMPL_THREE_WAY_COMPARISON = "__cpp_impl_three_way_comparison".toCharArray(); //$NON-NLS-1$
// Standard built-ins
private static final ObjectStyleMacro __CDT_PARSER__ = new ObjectStyleMacro("__CDT_PARSER__".toCharArray(), //$NON-NLS-1$
@ -352,6 +353,10 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable {
fIncludeSearchPath = configureIncludeSearchPath(new File(contextPath).getParentFile(), info);
setupMacroDictionary(configuration, info, language);
if (fMacroDictionary.containsKey(CPP_IMPL_THREE_WAY_COMPARISON)) {
fLexOptions.fSupportThreeWayComparisonOperator = true;
}
ILocationCtx ctx = fLocationMap.pushTranslationUnit(fRootContent.getFileLocation(), fRootContent.getSource());
Lexer lexer = new Lexer(fRootContent.getSource(), fLexOptions, this, this);
fRootContext = fCurrentContext = new ScannerContext(ctx, null, lexer);

View file

@ -63,6 +63,7 @@ final public class Lexer implements ITokenSequence {
public boolean fSupportRawStringLiterals = false;
public boolean fSupportUserDefinedLiterals = false;
public boolean fSupportDigitSeparators = false;
public boolean fSupportThreeWayComparisonOperator = false;
public IncludeExportPatterns fIncludeExportPatterns;
@Override
@ -641,7 +642,13 @@ final public class Lexer implements ITokenSequence {
switch (d) {
case '=':
nextCharPhase3();
final int se = nextCharPhase3();
if (fOptions.fSupportThreeWayComparisonOperator) {
if (se == '>') {
nextCharPhase3();
return newToken(IToken.tTHREEWAYCOMPARISON, start);
}
}
return newToken(IToken.tLTEQUAL, start);
case '<':
final int e = nextCharPhase3();

View file

@ -78,6 +78,7 @@ public class TokenUtil {
case IToken.tGTEQUAL:
case IToken.tLT:
case IToken.tLTEQUAL:
case IToken.tTHREEWAYCOMPARISON:
// other
case IToken.tASSIGN:
@ -164,6 +165,8 @@ public class TokenUtil {
return Keywords.cpNOT;
case IToken.tEQUAL:
return Keywords.cpEQUAL;
case IToken.tTHREEWAYCOMPARISON:
return Keywords.cpTHREEWAYCOMPARISON;
case IToken.tASSIGN:
return Keywords.cpASSIGN;
case IToken.tSHIFTL:

View file

@ -650,6 +650,11 @@ public class BindingClassifier {
}
}
if (binaryExpression.getOperator() == IASTBinaryExpression.op_threewaycomparison) {
// TODO: implement for three-way comparison operator x <=> y
return PROCESS_CONTINUE;
}
IType operand1Type = binaryExpression.getOperand1().getExpressionType();
IASTInitializerClause operand2 = binaryExpression.getInitOperand2();
IType operand2Type;