mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 14:12:10 +02:00
Bug 536986 - Add support for string literal operator templates
This was proposed for standardization in N3599. The proposal was not accepted, but it's supported by gcc and clang as an extension. Change-Id: I0c4a6e532f3a9172a8cb26218f0a608a1ca6be7d
This commit is contained in:
parent
c29769823c
commit
fac1ba39e6
2 changed files with 52 additions and 5 deletions
|
@ -11373,4 +11373,16 @@ public class AST2TemplateTests extends AST2CPPTestBase {
|
||||||
public void testGlobalConstWorksAsConstExpression_545756() throws Exception {
|
public void testGlobalConstWorksAsConstExpression_545756() throws Exception {
|
||||||
parseAndCheckBindings();
|
parseAndCheckBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// template <class C, C... Chars>
|
||||||
|
// unsigned int operator""_test() {
|
||||||
|
// return sizeof...(Chars);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// void foo() {
|
||||||
|
// auto len = "test"_test;
|
||||||
|
// }
|
||||||
|
public void testStringLiteralOperatorTemplate_536986() throws Exception {
|
||||||
|
parseAndCheckImplicitNameBindings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,6 +231,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPReferenceType;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateNonTypeArgument;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateNonTypeArgument;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateParameterMap;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeArgument;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownField;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownField;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMemberClass;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMemberClass;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMethod;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownMethod;
|
||||||
|
@ -3453,11 +3454,10 @@ public class CPPSemantics {
|
||||||
data.setFunctionArguments(false, createArgForType(exp, charArray));
|
data.setFunctionArguments(false, createArgForType(exp, charArray));
|
||||||
ret = resolveFunction(data, funcs, true, false);
|
ret = resolveFunction(data, funcs, true, false);
|
||||||
|
|
||||||
//
|
|
||||||
char[] stringLiteral = exp.getValue(); // The string literal that was passed to the operator
|
char[] stringLiteral = exp.getValue(); // The string literal that was passed to the operator
|
||||||
|
|
||||||
// The string literal is passed to the operator as chars:
|
// The string literal is passed to the operator as chars:
|
||||||
// "literal"_op -> operator "" _op<'l', 'i', 't', 'e', 'r', 'a', 'l'>();
|
// 12345_op -> operator "" _op<'1', '2', '3', '4', '5'>();
|
||||||
ICPPTemplateArgument args[] = new ICPPTemplateArgument[stringLiteral.length];
|
ICPPTemplateArgument args[] = new ICPPTemplateArgument[stringLiteral.length];
|
||||||
for (int k = 0; k < stringLiteral.length; k++) {
|
for (int k = 0; k < stringLiteral.length; k++) {
|
||||||
args[k] = new CPPTemplateNonTypeArgument(
|
args[k] = new CPPTemplateNonTypeArgument(
|
||||||
|
@ -3492,13 +3492,48 @@ public class CPPSemantics {
|
||||||
* str (i.e., its length excluding the terminating null character).
|
* str (i.e., its length excluding the terminating null character).
|
||||||
* L is treated as operator "" X(str, len)
|
* L is treated as operator "" X(str, len)
|
||||||
*/
|
*/
|
||||||
CPPPointerType strType = new CPPPointerType(
|
IType charType = new CPPBasicType(((CPPASTLiteralExpression) exp).getBasicCharKind(), 0, null);
|
||||||
new CPPBasicType(((CPPASTLiteralExpression) exp).getBasicCharKind(), 0, null), true, false,
|
CPPPointerType strType = new CPPPointerType(charType, true, false, false);
|
||||||
false);
|
|
||||||
IASTInitializerClause[] initializer = new IASTInitializerClause[] { createArgForType(exp, strType),
|
IASTInitializerClause[] initializer = new IASTInitializerClause[] { createArgForType(exp, strType),
|
||||||
createArgForType(null, CPPBasicType.UNSIGNED_INT) };
|
createArgForType(null, CPPBasicType.UNSIGNED_INT) };
|
||||||
data.setFunctionArguments(false, initializer);
|
data.setFunctionArguments(false, initializer);
|
||||||
ret = resolveFunction(data, funcs, true, false);
|
ret = resolveFunction(data, funcs, true, false);
|
||||||
|
|
||||||
|
// GNU extension: allow literal operator templates for string literals.
|
||||||
|
// The implementation follows the proposed spec in
|
||||||
|
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3599.html.
|
||||||
|
char[] stringLiteral = exp.getValue(); // The string literal that was passed to the operator
|
||||||
|
|
||||||
|
// The operator template is expected to take the character type as its first argument,
|
||||||
|
// followed by the characters as non-type arguments.
|
||||||
|
// "literal"_op -> operator "" _op<char, 'l', 'i', 't', 'e', 'r', 'a', 'l'>();
|
||||||
|
ICPPTemplateArgument args[] = new ICPPTemplateArgument[stringLiteral.length + 1];
|
||||||
|
args[0] = new CPPTemplateTypeArgument(charType);
|
||||||
|
for (int k = 0; k < stringLiteral.length; k++) {
|
||||||
|
args[k + 1] = new CPPTemplateNonTypeArgument(
|
||||||
|
new EvalFixed(CPPBasicType.CHAR, PRVALUE, IntegralValue.create(stringLiteral[k])));
|
||||||
|
}
|
||||||
|
|
||||||
|
data = new LookupData(((CPPASTLiteralExpression) exp).getOperatorName(), args, exp);
|
||||||
|
IBinding litTpl = resolveFunction(data, tplFunctions, true, false);
|
||||||
|
|
||||||
|
// Do we have valid template and non-template bindings?
|
||||||
|
if (ret != null && !(ret instanceof IProblemBinding)) {
|
||||||
|
// Do we have valid template and non-template bindings?
|
||||||
|
if (litTpl instanceof ICPPFunctionInstance) {
|
||||||
|
// Ambiguity? It has two valid options, and the spec says it shouldn't
|
||||||
|
return new ProblemBinding(data.getLookupName(), exp, IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP,
|
||||||
|
tplFunctions);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (litTpl instanceof ICPPFunctionInstance) {
|
||||||
|
// Only the template binding is valid
|
||||||
|
ret = litTpl;
|
||||||
|
} else {
|
||||||
|
// Couldn't find a valid operator
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (kind == IASTLiteralExpression.lk_char_constant) {
|
} else if (kind == IASTLiteralExpression.lk_char_constant) {
|
||||||
/*
|
/*
|
||||||
* 2.14.8.6
|
* 2.14.8.6
|
||||||
|
|
Loading…
Add table
Reference in a new issue