diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index c20fb763523..d8b931c4842 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -12067,6 +12067,18 @@ public class AST2CPPTests extends AST2CPPTestBase { checkUserDefinedLiteralIsType(getAboveComment(), "complex"); } + // struct complex { + // complex(long double real, long double imag); + // complex operator+(long double long); + // }; + // complex operator""if(long double imag) { + // return complex { 0, imag }; + // } + // auto waldo = 1.0if + 1; + public void testComplexFloatNumbersOverriddenCompilerSupport() throws Exception { + checkUserDefinedLiteralIsType(getAboveComment(), "complex"); + } + // // Test name lacking a space // int operator ""X(const char* s) { return 0; } // int operator ""_X(const char* s) { return 0; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index 54633ceccef..dce940df4d9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -2488,16 +2488,22 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } } + protected boolean isIdentifierOrKeyword(IToken token) { + char[] image = token.getCharImage(); + if (image.length == 0) { + return false; + } + char firstChar = image[0]; + return Character.isLetter(firstChar) || firstChar == '_'; + } + protected IToken identifierOrKeyword() throws EndOfFileException, BacktrackException { - IToken t = LA(1); - char[] image= t.getCharImage(); - if (image.length == 0) - throw backtrack; - char firstChar= image[0]; - if (!Character.isLetter(firstChar) && firstChar != '_') + IToken token = LA(1); + if (!isIdentifierOrKeyword(token)) { throw backtrack; + } consume(); - return t; + return token; } /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index a4614670d45..46cee018422 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -912,14 +912,14 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (strOp.getLength() == 2) { endOffset = strOp.getEndOffset(); - IToken ident = consume(IToken.tIDENTIFIER); + IToken udlOperator = identifierOrKeyword(); char[] operatorName = CharArrayUtils.concat(firstToken.getCharImage(), " ".toCharArray()); //$NON-NLS-1$ operatorName = CharArrayUtils.concat(operatorName, strOp.getCharImage()); - operatorName = CharArrayUtils.concat(operatorName, ident.getCharImage()); + operatorName = CharArrayUtils.concat(operatorName, udlOperator.getCharImage()); IASTName name = getNodeFactory().newOperatorName(operatorName); - setRange(name, firstToken.getOffset(), ident.getEndOffset()); + setRange(name, firstToken.getOffset(), udlOperator.getEndOffset()); return name; } break; @@ -2020,13 +2020,13 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { IToken la = LA(1); int offset = ((ASTNode) literalExprWithRange).getOffset(); int length = ((ASTNode) literalExprWithRange).getLength(); - if (la.getType() == IToken.tIDENTIFIER) { + if (isIdentifierOrKeyword(la)) { if ((offset + length) != la.getOffset()) { return literalExprWithRange; } - IToken opName = consume(IToken.tIDENTIFIER); - ((CPPASTLiteralExpression) literalExprWithRange).setSuffix(opName.getCharImage()); - setRange(literalExprWithRange, offset, opName.getEndOffset()); + consume(); + ((CPPASTLiteralExpression) literalExprWithRange).setSuffix(la.getCharImage()); + setRange(literalExprWithRange, offset, la.getEndOffset()); } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java index e5fbfb4e44a..46abaa0e33b 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java @@ -16,8 +16,10 @@ import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.NullProgressMonitor; @@ -92,18 +94,25 @@ public class SemanticHighlightingTest extends TestCase { return dest; } - private void enableHighlightingsAndAssignColors() { + private void enableHighlightingsAndAssignColors(Set ignoredHighlightings) { fColorToPreferenceKeyMap = new HashMap<>(); IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore(); store.setValue(PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_ENABLED, true); SemanticHighlighting[] semanticHighlightings= SemanticHighlightings.getSemanticHighlightings(); int blue = 0; // for assigning colors to preferences below for (SemanticHighlighting semanticHighlighting : semanticHighlightings) { - // Enable the highlighting. String enabledPreferenceKey = SemanticHighlightings.getEnabledPreferenceKey(semanticHighlighting); - if (!store.getBoolean(enabledPreferenceKey)) + // Make sure ignored highlightings are disabled. + if (ignoredHighlightings.contains(semanticHighlighting.getPreferenceKey())) { + store.setValue(enabledPreferenceKey, false); + continue; + } + + // Enable the highlighting. + if (!store.getBoolean(enabledPreferenceKey)) { store.setValue(enabledPreferenceKey, true); - + } + // Choose a unique color for the highlighting, and save the mapping // from the color to the highlighting's preference key . String colorPreferenceKey = SemanticHighlightings.getColorPreferenceKey(semanticHighlighting); @@ -129,8 +138,8 @@ public class SemanticHighlightingTest extends TestCase { // Note: This is not an override of the TestCase.setUp(), but a method called directly // by the tests, so that they can specify a value for 'isCpp' on a per-test basis. - private void setup(boolean isCpp) throws Exception { - enableHighlightingsAndAssignColors(); + private void setup(boolean isCpp, Set ignoredHighlightings) throws Exception { + enableHighlightingsAndAssignColors(ignoredHighlightings); StringBuilder[] testData = TestSourceReader.getContentsForTest(CTestPlugin.getDefault().getBundle(), "ui", getClass(), getName(), 0); @@ -217,15 +226,23 @@ public class SemanticHighlightingTest extends TestCase { assertEqualMaps(actual, expected); } - private void makeAssertions(boolean isCpp) throws Exception { - setup(isCpp); + private void makeAssertions(boolean isCpp, Set ignoredHighlightings) throws Exception { + setup(isCpp, ignoredHighlightings); try { doMakeAssertions(); } finally { teardown(); } } - + + private void makeAssertions(Set ignoredHighlightings) throws Exception { + makeAssertions(true, ignoredHighlightings); // default to C++ + } + + private void makeAssertions(boolean isCpp) throws Exception { + makeAssertions(isCpp, new HashSet()); + } + private void makeAssertions() throws Exception { makeAssertions(true); // default to C++ } @@ -679,4 +696,48 @@ public class SemanticHighlightingTest extends TestCase { public void testVariablePassedByNonConstRef_529958() throws Exception { makeAssertions(); } + + // float operator""if(long double) { //$functionDeclaration + // return 1.6f; + // } + // int main() { //$functionDeclaration + // auto k = 1.3if; //$localVariableDeclaration,overloadedOperator + // } + public void testOverriddenUDLOperatorIfCall_527954() throws Exception { + makeAssertions(); + } + + // float operator""if(long double) { //$functionDeclaration + // return 1.6f; + // } + // int main() { //$functionDeclaration + // auto k = 1.3if; //$localVariableDeclaration,c_default + // } + public void testUDLOperatorIfCall_527954() throws Exception { + Set ignoredHighlightings = new HashSet<>(); + ignoredHighlightings.add(SemanticHighlightings.OVERLOADED_OPERATOR); + makeAssertions(ignoredHighlightings); + } + + // int operator""int(long double) { //$functionDeclaration + // return -1; + // } + // int main() { //$functionDeclaration + // auto k = 1.3int; //$localVariableDeclaration,overloadedOperator + // } + public void testOverriddenUDLOperatorIntCall_527954() throws Exception { + makeAssertions(); + } + + // int operator""int(long double) { //$functionDeclaration + // return -1; + // } + // int main() { //$functionDeclaration + // auto k = 1.3int; //$localVariableDeclaration,c_default + // } + public void testUDLOperatorIntCall_527954() throws Exception { + Set ignoredHighlightings = new HashSet<>(); + ignoredHighlightings.add(SemanticHighlightings.OVERLOADED_OPERATOR); + makeAssertions(ignoredHighlightings); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java index 1c116510ae8..cf20d4668a8 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java @@ -56,6 +56,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTClassVirtSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNameSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; @@ -1809,7 +1810,36 @@ public class SemanticHighlightings { || token.getNode() instanceof ICPPASTClassVirtSpecifier; } } - + + /** + * Semantic highlighting for context-sensitive UDL like operator""if(...). + * + * This does not get its own color and style; rather, it uses + * the color and style of the 'Default' syntactic highlighting. + */ + private static final class ContextSensitiveUDLHighlighting extends SemanticHighlighting { + @Override + public String getPreferenceKey() { + return ICColorConstants.C_DEFAULT; + } + + @Override + public boolean isEnabledByDefault() { + return true; + } + + @Override + public boolean requiresImplicitNames() { + return true; + } + + @Override + public boolean consumes(ISemanticToken token) { + IASTNode node = token.getNode(); + return node instanceof IASTImplicitName && node.getParent() instanceof ICPPASTLiteralExpression; + } + } + private static boolean heuristicallyResolvesToEnumeration(ICPPUnknownBinding binding) { IBinding[] resolved = HeuristicResolver.resolveUnknownBinding(binding); return resolved.length == 1 && resolved[0] instanceof IEnumeration; @@ -1981,6 +2011,7 @@ public class SemanticHighlightings { highlightings.put(new Key(230), new EnumeratorHighlighting()); highlightings.put(new Key(240), new ContextSensitiveKeywordHighlighting()); highlightings.put(new Key(250), new VariablePassedByNonconstRefHighlighting()); + highlightings.put(new Key(260), new ContextSensitiveUDLHighlighting()); } private static final String ExtensionPoint = "semanticHighlighting"; //$NON-NLS-1$