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 cba231e11ef..884e953e90d 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 @@ -11622,7 +11622,14 @@ public class AST2CPPTests extends AST2TestBase { BindingAssertionHelper bh = getAssertionHelper(); ICPPVariable test = bh.assertNonProblemOnFirstIdentifier("test"); assertTrue(test.getType() instanceof IProblemType); // resolution is ambiguous - } + } + + // char foo() { + // return '*'; + // } + public void testRegression_484618() throws Exception { + parseAndCheckImplicitNameBindings(); + } // constexpr int lambdas_supported = // #if __has_feature(cxx_lambdas) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTLiteralExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTLiteralExpression.java index 367507448b0..512c5845f39 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTLiteralExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTLiteralExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2011 IBM Corporation and others. + * Copyright (c) 2004, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.cdt.core.dom.ast.cpp; +import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner; import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; /** @@ -18,7 +19,8 @@ import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; * @noextend This interface is not intended to be extended by clients. * @noimplement This interface is not intended to be implemented by clients. */ -public interface ICPPASTLiteralExpression extends IASTLiteralExpression, ICPPASTExpression { +public interface ICPPASTLiteralExpression extends IASTLiteralExpression, ICPPASTExpression, + IASTImplicitNameOwner { /** * lk_this represents the 'this' keyword. */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLiteralExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLiteralExpression.java index a7248c763cb..460be69100e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLiteralExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLiteralExpression.java @@ -19,6 +19,7 @@ import static org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory.PRVALUE; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTImplicitDestructorName; +import org.eclipse.cdt.core.dom.ast.IASTImplicitName; import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; import org.eclipse.cdt.core.dom.ast.IBinding; @@ -30,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; +import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; @@ -55,6 +57,9 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx private char[] fSuffix = CharArrayUtils.EMPTY; private boolean fIsCompilerSuffix = true; private ICPPEvaluation fEvaluation; + + private IBinding fUserDefinedLiteralOperator; + private IASTImplicitName[] fImplicitNames; public CPPASTLiteralExpression() { } @@ -64,7 +69,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx this.fValue = value; } - public CPPASTLiteralExpression(int kind, char[] value, char[] suffix) { + public CPPASTLiteralExpression(int kind, char[] value, char[] suffix, boolean isCompilerSuffix) { this(kind, value); this.setSuffix(suffix); } @@ -78,7 +83,8 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx public CPPASTLiteralExpression copy(CopyStyle style) { CPPASTLiteralExpression copy = new CPPASTLiteralExpression(fKind, fValue == null ? null : fValue.clone(), - fSuffix == null ? null : fSuffix.clone()); + fSuffix == null ? null : fSuffix.clone(), + fIsCompilerSuffix); copy.setOffsetAndLength(this); return copy(copy, style); } @@ -158,6 +164,9 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx final int offset = CharArrayUtils.lastIndexOf('"', fValue, CharArrayUtils.indexOf('"', fValue) + 1); if (offset > 0) { setSuffix(CharArrayUtils.subarray(fValue, offset + 1, -1)); + if (fSuffix.length > 0) { + fIsCompilerSuffix = false; + } } } break; @@ -166,6 +175,9 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx final int offset = CharArrayUtils.lastIndexOf('\'', fValue, CharArrayUtils.indexOf('\'', fValue) + 1); if (offset > 0) { setSuffix(CharArrayUtils.subarray(fValue, offset + 1, -1)); + if (fSuffix.length > 0) { + fIsCompilerSuffix = false; + } } } break; @@ -194,6 +206,13 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx default: break; } } + + if (action.shouldVisitImplicitNames) { + for (IASTImplicitName name : getImplicitNames()) { + if (!name.accept(action)) return false; + } + } + if (action.shouldVisitExpressions) { switch (action.leave(this)) { case ASTVisitor.PROCESS_ABORT: return false; @@ -287,16 +306,28 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx return fSuffix.length > 0 ? getUserDefinedLiteralOperatorType() : new CPPBasicType(getBasicCharKind(), 0, this); } + private IBinding getUserDefinedLiteralOperator() { + if (!fIsCompilerSuffix && fUserDefinedLiteralOperator == null) { + try { + fUserDefinedLiteralOperator = CPPSemantics.findUserDefinedLiteralOperator(this); + } catch (DOMException e) { + } + if (fUserDefinedLiteralOperator == null) { + fUserDefinedLiteralOperator = new ProblemBinding(this, ISemanticProblem.BINDING_NOT_FOUND, + fSuffix); + } + } + return fUserDefinedLiteralOperator; + } + // 13.5.8 private IType getUserDefinedLiteralOperatorType() { IType ret = new ProblemType(ISemanticProblem.TYPE_UNRESOLVED_NAME); - try { - IBinding func = CPPSemantics.findUserDefinedLiteralOperator(this); - if (func != null && func instanceof ICPPFunction) { - ret = ((ICPPFunction) func).getType().getReturnType(); - } - } catch (DOMException e) { /* ignore and return the problem type */ } + IBinding func = getUserDefinedLiteralOperator(); + if (func != null && func instanceof ICPPFunction) { + ret = ((ICPPFunction) func).getType().getReturnType(); + } return ret; } @@ -660,4 +691,20 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx public ValueCategory getValueCategory() { return getKind() == lk_string_literal ? LVALUE : PRVALUE; } + + @Override + public IASTImplicitName[] getImplicitNames() { + if (fImplicitNames == null) { + if (fIsCompilerSuffix) { + fImplicitNames = IASTImplicitName.EMPTY_NAME_ARRAY; + } else { + CPPASTImplicitName operatorName = new CPPASTImplicitName(fSuffix, this); + operatorName.setOperator(true); + operatorName.setBinding(getUserDefinedLiteralOperator()); + operatorName.setOffsetAndLength(getOffset() + fValue.length, fSuffix.length); + fImplicitNames = new IASTImplicitName[] { operatorName }; + } + } + return fImplicitNames; + } } 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 29532954bb9..11770af7ffd 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 @@ -440,4 +440,11 @@ public class SemanticHighlightingTest extends TestCase { public void testHighlightingInsideAlignmentSpecifier_451082() throws Exception { makeAssertions(); } + + // struct Duration {}; //$class + // Duration operator "" _d(unsigned long long); //$class,functionDeclaration + // Duration dur = 1000_d; //$class,globalVariable,overloadedOperator + public void testUserDefinedLiteralSuffix_484617() throws Exception { + makeAssertions(); + } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java index 7d32363e8cb..a3578b08f3e 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/selection/CPPSelectionTestsNoIndexer.java @@ -1248,4 +1248,15 @@ public class CPPSelectionTestsNoIndexer extends BaseSelectionTests { offset = code.indexOf("::other->foo") + 9; assertTrue(testF3(file, offset) instanceof IASTName); } + + // struct Duration {}; + // Duration operator "" _d(unsigned long long); + // Duration dur = 42_d; + public void testUserDefinedLiteralSuffix_484618() throws Exception { + String code = getAboveComment(); + IFile file = importFile("testBug484618.cpp", code); + + int offset = code.indexOf("42_d") + 3; + assertTrue(testF3(file, offset) instanceof IASTName); + } }