mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-13 19:25:38 +02:00
Bug 527844: ExpressionWriter does not write IASTLiteralExpression suffix
Change-Id: I4dbca527a16c698d7f1a16f2a6a0eca2e6cdc77a Signed-off-by: Hansruedi Patzen <hansruedi.patzen@hsr.ch>
This commit is contained in:
parent
86c3d8eeca
commit
3e66e22aed
8 changed files with 464 additions and 341 deletions
|
@ -12025,6 +12025,39 @@ public class AST2CPPTests extends AST2CPPTestBase {
|
||||||
assertEquals(IProblem.PREPROCESSOR_MULTIPLE_USER_DEFINED_SUFFIXES_IN_CONCATENATION, problems[0].getID());
|
assertEquals(IProblem.PREPROCESSOR_MULTIPLE_USER_DEFINED_SUFFIXES_IN_CONCATENATION, problems[0].getID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// struct basic_string {
|
||||||
|
// basic_string(char const * str, int len);
|
||||||
|
// };
|
||||||
|
// basic_string operator""s(char const * str, int len) {
|
||||||
|
// return basic_string { str, len };
|
||||||
|
// }
|
||||||
|
// auto waldo = "Waldo"s;
|
||||||
|
public void testStringLiterals() throws Exception {
|
||||||
|
checkUserDefinedLiteralIsType(getAboveComment(), "basic_string");
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto waldo = 1i + 1;
|
||||||
|
public void testComplexNumbersCompilerSupport1() throws Exception {
|
||||||
|
checkUserDefinedLiteralIsType(getAboveComment(), "_Complex int");
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto waldo = 1j + 1;
|
||||||
|
public void testComplexNumbersCompilerSupport2() throws Exception {
|
||||||
|
checkUserDefinedLiteralIsType(getAboveComment(), "_Complex int");
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct complex {
|
||||||
|
// complex(unsigned long long real, unsigned long long imag);
|
||||||
|
// complex operator+(unsigned long long);
|
||||||
|
// };
|
||||||
|
// complex operator""i(unsigned long long imag) {
|
||||||
|
// return complex { 0, imag };
|
||||||
|
// }
|
||||||
|
// auto waldo = 1i + 1;
|
||||||
|
public void testComplexNumbersOverriddenCompilerSupport() throws Exception {
|
||||||
|
checkUserDefinedLiteralIsType(getAboveComment(), "complex");
|
||||||
|
}
|
||||||
|
|
||||||
// // Test name lacking a space
|
// // Test name lacking a space
|
||||||
// int operator ""X(const char* s) { return 0; }
|
// int operator ""X(const char* s) { return 0; }
|
||||||
// int operator ""_X(const char* s) { return 0; }
|
// int operator ""_X(const char* s) { return 0; }
|
||||||
|
|
|
@ -198,3 +198,22 @@ TestClass* tc = new TestClass();
|
||||||
//%CPP
|
//%CPP
|
||||||
int i = int(1);
|
int i = int(1);
|
||||||
|
|
||||||
|
//!CPP LiteralExpression with string literal
|
||||||
|
//%CPP
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using namespace std::string_literals;
|
||||||
|
auto str = "foobar"s;
|
||||||
|
}
|
||||||
|
|
||||||
|
//!CPP LiteralExpression with user defined literal
|
||||||
|
//%CPP
|
||||||
|
constexpr long double operator ""_deg(long double deg)
|
||||||
|
{
|
||||||
|
return deg * 3.141592 / 180;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
double x = 90.0_deg;
|
||||||
|
}
|
|
@ -223,6 +223,11 @@ public interface ICPPNodeFactory extends INodeFactory {
|
||||||
@Override
|
@Override
|
||||||
public ICPPASTLiteralExpression newLiteralExpression(int kind, String rep);
|
public ICPPASTLiteralExpression newLiteralExpression(int kind, String rep);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 6.5
|
||||||
|
*/
|
||||||
|
public ICPPASTLiteralExpression newLiteralExpression(int kind, String rep, char[] numericCompilerSuffixes);
|
||||||
|
|
||||||
public ICPPASTNamespaceAlias newNamespaceAlias(IASTName alias, IASTName qualifiedName);
|
public ICPPASTNamespaceAlias newNamespaceAlias(IASTName alias, IASTName qualifiedName);
|
||||||
|
|
||||||
public ICPPASTNamespaceDefinition newNamespaceDefinition(IASTName name);
|
public ICPPASTNamespaceDefinition newNamespaceDefinition(IASTName name);
|
||||||
|
|
|
@ -175,9 +175,9 @@ public class CharArrayUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final char[] concat(char[] first, char[] second) {
|
public static final char[] concat(char[] first, char[] second) {
|
||||||
if (first == null)
|
if (first == null || first.length == 0)
|
||||||
return second;
|
return second;
|
||||||
if (second == null)
|
if (second == null || second.length == 0)
|
||||||
return first;
|
return first;
|
||||||
|
|
||||||
int length1 = first.length;
|
int length1 = first.length;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
* Sergey Prigogin (Google)
|
* Sergey Prigogin (Google)
|
||||||
* Richard Eames
|
* Richard Eames
|
||||||
|
* Hansruedi Patzen (IFS)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
|
@ -24,6 +25,8 @@ import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IProblemType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
|
import org.eclipse.cdt.core.dom.ast.ISemanticProblem;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
|
@ -55,30 +58,48 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
private static final EvalFixed EVAL_FALSE = new EvalFixed(CPPBasicType.BOOLEAN, PRVALUE, IntegralValue.create(false));
|
private static final EvalFixed EVAL_FALSE = new EvalFixed(CPPBasicType.BOOLEAN, PRVALUE, IntegralValue.create(false));
|
||||||
private static final EvalFixed EVAL_NULL_PTR = new EvalFixed(CPPBasicType.NULL_PTR, PRVALUE, IntegralValue.create(0));
|
private static final EvalFixed EVAL_NULL_PTR = new EvalFixed(CPPBasicType.NULL_PTR, PRVALUE, IntegralValue.create(0));
|
||||||
|
|
||||||
public static final CPPASTLiteralExpression INT_ZERO =
|
public static final CPPASTLiteralExpression INT_ZERO = new CPPASTLiteralExpression(lk_integer_constant, new char[] {'0'});
|
||||||
new CPPASTLiteralExpression(lk_integer_constant, new char[] {'0'});
|
|
||||||
|
|
||||||
private int fKind;
|
private int fKind;
|
||||||
private char[] fValue = CharArrayUtils.EMPTY;
|
/**
|
||||||
private int fStringLiteralSize = -1; // Accounting for escape sequences and the null terminator.
|
* The value of a CPPASTLiteralExpression consists of a literal and a suffix.
|
||||||
private char[] fSuffix = CharArrayUtils.EMPTY;
|
*
|
||||||
private boolean fIsCompilerSuffix = true;
|
* E.g. 1f -> literal: 1 suffix: f
|
||||||
private ICPPEvaluation fEvaluation;
|
* 1ull -> literal: 1 suffix: ull
|
||||||
|
* 10.0_udl -> literal: 10.0 suffix: _udl
|
||||||
|
* "waldo"s -> literal: "waldo" suffix: s
|
||||||
|
* 'a'_udl -> literal: 'a' suffix: _udl
|
||||||
|
*/
|
||||||
|
private char[] fLiteral;
|
||||||
|
private char[] fSuffix;
|
||||||
|
private final char[] fNumericCompilerSuffixes;
|
||||||
|
|
||||||
|
private int fStringLiteralSize; // Accounting for escape sequences and the null terminator.
|
||||||
|
private ICPPEvaluation fEvaluation;
|
||||||
private IBinding fUserDefinedLiteralOperator;
|
private IBinding fUserDefinedLiteralOperator;
|
||||||
private IASTImplicitName[] fImplicitNames;
|
private IASTImplicitName[] fImplicitNames;
|
||||||
|
|
||||||
public CPPASTLiteralExpression() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public CPPASTLiteralExpression(int kind, char[] value) {
|
public CPPASTLiteralExpression(int kind, char[] value) {
|
||||||
this.fKind = kind;
|
this(kind, value, CharArrayUtils.EMPTY);
|
||||||
this.fValue = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CPPASTLiteralExpression(int kind, char[] value, char[] suffix, boolean isCompilerSuffix) {
|
public CPPASTLiteralExpression(int kind, char[] value, char[] numericCompilerSuffixes) {
|
||||||
this(kind, value);
|
fKind = kind;
|
||||||
this.setSuffix(suffix);
|
fSuffix = getSuffix(kind, value, CharArrayUtils.EMPTY);
|
||||||
|
fLiteral = getLiteral(value, fSuffix);
|
||||||
|
fNumericCompilerSuffixes = (numericCompilerSuffixes == null) ? CharArrayUtils.EMPTY : numericCompilerSuffixes;
|
||||||
|
fStringLiteralSize = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CPPASTLiteralExpression(CPPASTLiteralExpression other) {
|
||||||
|
fKind = other.fKind;
|
||||||
|
fLiteral = other.fLiteral;
|
||||||
|
fSuffix = other.fSuffix;
|
||||||
|
fNumericCompilerSuffixes = other.fNumericCompilerSuffixes;
|
||||||
|
fStringLiteralSize = other.fStringLiteralSize;
|
||||||
|
fEvaluation = other.fEvaluation;
|
||||||
|
fUserDefinedLiteralOperator = other.fUserDefinedLiteralOperator;
|
||||||
|
fImplicitNames = other.fImplicitNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -88,12 +109,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CPPASTLiteralExpression copy(CopyStyle style) {
|
public CPPASTLiteralExpression copy(CopyStyle style) {
|
||||||
CPPASTLiteralExpression copy = new CPPASTLiteralExpression(fKind,
|
return copy(new CPPASTLiteralExpression(this), style);
|
||||||
fValue == null ? null : fValue.clone(),
|
|
||||||
fSuffix == null ? null : fSuffix.clone(),
|
|
||||||
fIsCompilerSuffix);
|
|
||||||
copy.setOffsetAndLength(this);
|
|
||||||
return copy(copy, style);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -102,107 +118,147 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setKind(int value) {
|
public void setKind(int kind) {
|
||||||
assertNotFrozen();
|
assertNotFrozen();
|
||||||
fKind = value;
|
set(kind, getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public char[] getValue() {
|
public char[] getValue() {
|
||||||
return fValue;
|
return CharArrayUtils.concat(fLiteral, fSuffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setValue(char[] value) {
|
public void setValue(char[] value) {
|
||||||
assertNotFrozen();
|
assertNotFrozen();
|
||||||
this.fValue= value;
|
set(fKind, value);
|
||||||
}
|
|
||||||
|
|
||||||
public char[] getSuffix() {
|
|
||||||
return fSuffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addSuffix(char[] suffix) {
|
|
||||||
setSuffix(suffix);
|
|
||||||
// Make sure fValue reflects the added suffix.
|
|
||||||
fValue = CharArrayUtils.concat(fValue, suffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSuffix(char[] suffix) {
|
|
||||||
this.fSuffix = suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void calculateSuffix() {
|
|
||||||
this.calculateSuffix(CharArrayUtils.EMPTY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the suffix of a user-defined literal integer or float
|
* Sets the kind, suffix and literal fields of this expression.
|
||||||
* @param compilerSuffixes
|
*
|
||||||
|
* @param kind the kind of this literal expression
|
||||||
|
* @param value the value of this literal expression,
|
||||||
|
* this gets split into a literal and a suffix
|
||||||
*/
|
*/
|
||||||
public void calculateSuffix(char[] compilerSuffixes) {
|
private void set(int kind, char[] value) {
|
||||||
try {
|
fKind = kind;
|
||||||
switch (fKind) {
|
fSuffix = getSuffix(kind, value, fSuffix);
|
||||||
|
fLiteral = getLiteral(value, fSuffix);
|
||||||
|
resetLazyFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a suffix to this literal expression.
|
||||||
|
*
|
||||||
|
* @param suffix the suffix to be added.
|
||||||
|
*/
|
||||||
|
public void setSuffix(char[] suffix) {
|
||||||
|
assertNotFrozen();
|
||||||
|
fSuffix = (suffix == null) ? CharArrayUtils.EMPTY : suffix;
|
||||||
|
resetLazyFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the lazy evaluated fields. This is needed if any of the other fields change.
|
||||||
|
*/
|
||||||
|
private void resetLazyFields() {
|
||||||
|
fStringLiteralSize = -1;
|
||||||
|
fEvaluation = null;
|
||||||
|
fUserDefinedLiteralOperator = null;
|
||||||
|
fImplicitNames = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasNumericCompilerSuffix() {
|
||||||
|
if (hasNumericKind() && fSuffix.length == 1) {
|
||||||
|
for (int j = 0; j < fNumericCompilerSuffixes.length; j++) {
|
||||||
|
if (fSuffix[0] == fNumericCompilerSuffixes[j]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasNumericKind() {
|
||||||
|
return fKind == lk_integer_constant || fKind == lk_float_constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static char[] getLiteral(char[] value, char[] suffix) {
|
||||||
|
if (value == null) {
|
||||||
|
return CharArrayUtils.EMPTY;
|
||||||
|
}
|
||||||
|
if (suffix == null || suffix.length == 0) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
final char[] literal = CharArrayUtils.subarray(value, 0, value.length - suffix.length);
|
||||||
|
return (literal == null) ? CharArrayUtils.EMPTY : literal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static char[] getSuffix(int kind, char[] value, char[] suffix) {
|
||||||
|
if (value == null || value.length == 0) {
|
||||||
|
return suffix;
|
||||||
|
}
|
||||||
|
int offset = 0;
|
||||||
|
switch (kind) {
|
||||||
case lk_float_constant:
|
case lk_float_constant:
|
||||||
case lk_integer_constant:
|
case lk_integer_constant:
|
||||||
int udOffset = (fValue[0] == '.' ? afterDecimalPoint(0) : integerLiteral());
|
try {
|
||||||
if (udOffset > 0) {
|
offset = (value[0] == '.') ? afterDecimalPoint(value, 0) : integerLiteral(value);
|
||||||
|
} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case lk_string_literal:
|
||||||
|
offset = CharArrayUtils.lastIndexOf('"', value, CharArrayUtils.indexOf('"', value) + 1) + 1;
|
||||||
|
break;
|
||||||
|
case lk_char_constant:
|
||||||
|
offset = CharArrayUtils.lastIndexOf('\'', value, CharArrayUtils.indexOf('\'', value) + 1) + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
suffix = (offset > 0) ? CharArrayUtils.subarray(value, offset, -1) : suffix;
|
||||||
|
return (suffix == null) ? CharArrayUtils.EMPTY : suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasNumericSuffix() {
|
||||||
|
final int len = fSuffix.length;
|
||||||
|
if (!hasSuffix() || !hasNumericKind() || len > 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* 2.14.8.1
|
* 2.14.8.1
|
||||||
* "If a token matches both user-defined-literal and another literal kind, it is
|
* "If a token matches both user-defined-literal and another literal kind, it is
|
||||||
* treated as the latter"
|
* treated as the latter"
|
||||||
*/
|
*/
|
||||||
setSuffix(CharArrayUtils.subarray(fValue, udOffset, -1));
|
if (len == 1) {
|
||||||
for (int i = 0; i < fSuffix.length; i++) {
|
switch(fSuffix[0]) {
|
||||||
switch (fSuffix[i]) {
|
|
||||||
case 'l': case 'L':
|
|
||||||
case 'u': case 'U':
|
case 'u': case 'U':
|
||||||
case 'f': case 'F':
|
case 'f': case 'F':
|
||||||
continue;
|
case 'l': case 'L':
|
||||||
}
|
return true;
|
||||||
for (int j = 0; j < compilerSuffixes.length; j++) {
|
|
||||||
if (fSuffix[i] == compilerSuffixes[j]) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fIsCompilerSuffix = false;
|
if (len == 2) {
|
||||||
// Remove the suffix from the value if it's a UDL
|
switch(fSuffix[0]) {
|
||||||
setValue(CharArrayUtils.subarray(fValue, 0, udOffset));
|
case 'u': case 'U':
|
||||||
break;
|
return Character.toLowerCase(fSuffix[1]) == 'l';
|
||||||
|
case 'l': case 'L':
|
||||||
|
return Character.toLowerCase(fSuffix[1]) == 'l' || Character.toLowerCase(fSuffix[1]) == 'u';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
if (len == 3) {
|
||||||
case lk_string_literal:
|
switch(fSuffix[0]) {
|
||||||
{
|
case 'u': case 'U':
|
||||||
final int offset = CharArrayUtils.lastIndexOf('"', fValue, CharArrayUtils.indexOf('"', fValue) + 1);
|
return Character.toLowerCase(fSuffix[1]) == 'l' && Character.toLowerCase(fSuffix[2]) == 'l';
|
||||||
if (offset > 0) {
|
case 'l': case 'L':
|
||||||
setSuffix(CharArrayUtils.subarray(fValue, offset + 1, -1));
|
return Character.toLowerCase(fSuffix[1]) == 'l' && Character.toLowerCase(fSuffix[2]) == 'u';
|
||||||
if (fSuffix.length > 0) {
|
|
||||||
fIsCompilerSuffix = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
break;
|
|
||||||
case lk_char_constant:
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
} catch (ArrayIndexOutOfBoundsException e) {
|
|
||||||
// pass
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return new String(fValue);
|
return new String(getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -236,27 +292,30 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasSuffix() {
|
||||||
|
return fSuffix.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
private int computeStringLiteralSize() {
|
private int computeStringLiteralSize() {
|
||||||
int start = 0, end = fValue.length - 1 - getSuffix().length;
|
int start = 0, end = fLiteral.length - 1;
|
||||||
boolean isRaw = false;
|
boolean isRaw = false;
|
||||||
|
|
||||||
// Skip past a prefix affecting the character type.
|
// Skip past a prefix affecting the character type.
|
||||||
if (fValue[0] == 'L' || fValue[0] == 'u' || fValue[0] == 'U') {
|
if (fLiteral[0] == 'L' || fLiteral[0] == 'u' || fLiteral[0] == 'U') {
|
||||||
if(fValue[1] == '8') {
|
if(fLiteral[1] == '8') {
|
||||||
++start;
|
++start;
|
||||||
}
|
}
|
||||||
|
|
||||||
++start;
|
++start;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is an 'R' prefix, skip past it but take note of it.
|
// If there is an 'R' prefix, skip past it but take note of it.
|
||||||
if (fValue[start] == 'R') {
|
if (fLiteral[start] == 'R') {
|
||||||
++start;
|
++start;
|
||||||
isRaw = true;
|
isRaw = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we should have a quote-enclosed string. Skip past the quotes.
|
// Now we should have a quote-enclosed string. Skip past the quotes.
|
||||||
if (!(fValue[start] == '"' && fValue[end] == '"')) {
|
if (!(fLiteral[start] == '"' && fLiteral[end] == '"')) {
|
||||||
// Unexpected!
|
// Unexpected!
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -265,13 +324,13 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
|
|
||||||
// If we have a raw string, skip past the raw prefix.
|
// If we have a raw string, skip past the raw prefix.
|
||||||
if (isRaw) {
|
if (isRaw) {
|
||||||
while (fValue[start] != '(' && start <= end) {
|
while (fLiteral[start] != '(' && start <= end) {
|
||||||
++start;
|
++start;
|
||||||
--end;
|
--end;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we should have a parenthesis-enclosed string.
|
// Now we should have a parenthesis-enclosed string.
|
||||||
if (!(fValue[start] == '(' && fValue[end] == ')')) {
|
if (!(fLiteral[start] == '(' && fLiteral[end] == ')')) {
|
||||||
// Unexpected!
|
// Unexpected!
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -290,7 +349,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
if (escaping) {
|
if (escaping) {
|
||||||
escaping = false;
|
escaping = false;
|
||||||
++length;
|
++length;
|
||||||
} else if (fValue[start] == '\\') {
|
} else if (fLiteral[start] == '\\') {
|
||||||
escaping = true;
|
escaping = true;
|
||||||
} else {
|
} else {
|
||||||
++length;
|
++length;
|
||||||
|
@ -316,18 +375,21 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
}
|
}
|
||||||
|
|
||||||
private IType getCharType() {
|
private IType getCharType() {
|
||||||
return fSuffix.length > 0 ? getUserDefinedLiteralOperatorType() : new CPPBasicType(getBasicCharKind(), 0, this);
|
return hasSuffix() ? getUserDefinedLiteralOperatorType() : new CPPBasicType(getBasicCharKind(), 0, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IBinding getUserDefinedLiteralOperator() {
|
private IBinding getUserDefinedLiteralOperator() {
|
||||||
if (!fIsCompilerSuffix && fUserDefinedLiteralOperator == null) {
|
if (hasSuffix() && !hasNumericSuffix() && fUserDefinedLiteralOperator == null) {
|
||||||
try {
|
try {
|
||||||
fUserDefinedLiteralOperator = CPPSemantics.findUserDefinedLiteralOperator(this);
|
fUserDefinedLiteralOperator = CPPSemantics.findUserDefinedLiteralOperator(this);
|
||||||
|
if (fUserDefinedLiteralOperator instanceof IProblemBinding && hasNumericCompilerSuffix()) {
|
||||||
|
fUserDefinedLiteralOperator = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
} catch (DOMException e) {
|
} catch (DOMException e) {
|
||||||
}
|
}
|
||||||
if (fUserDefinedLiteralOperator == null) {
|
if (fUserDefinedLiteralOperator == null) {
|
||||||
fUserDefinedLiteralOperator = new ProblemBinding(this, ISemanticProblem.BINDING_NOT_FOUND,
|
fUserDefinedLiteralOperator = new ProblemBinding(this, ISemanticProblem.BINDING_NOT_FOUND, fSuffix);
|
||||||
fSuffix);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fUserDefinedLiteralOperator;
|
return fUserDefinedLiteralOperator;
|
||||||
|
@ -335,14 +397,12 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
|
|
||||||
// 13.5.8
|
// 13.5.8
|
||||||
private IType getUserDefinedLiteralOperatorType() {
|
private IType getUserDefinedLiteralOperatorType() {
|
||||||
IType ret = new ProblemType(ISemanticProblem.TYPE_UNRESOLVED_NAME);
|
|
||||||
|
|
||||||
IBinding func = getUserDefinedLiteralOperator();
|
IBinding func = getUserDefinedLiteralOperator();
|
||||||
if (func != null && func instanceof ICPPFunction) {
|
if (func != null && func instanceof ICPPFunction) {
|
||||||
ret = ((ICPPFunction) func).getType().getReturnType();
|
return ((ICPPFunction) func).getType().getReturnType();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return new ProblemType(ISemanticProblem.TYPE_UNRESOLVED_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
public char[] getOperatorName() {
|
public char[] getOperatorName() {
|
||||||
|
@ -350,14 +410,14 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
}
|
}
|
||||||
|
|
||||||
public Kind getBasicCharKind() {
|
public Kind getBasicCharKind() {
|
||||||
switch (fValue[0]) {
|
switch (fLiteral[0]) {
|
||||||
case 'L':
|
case 'L':
|
||||||
return Kind.eWChar;
|
return Kind.eWChar;
|
||||||
case 'U':
|
case 'U':
|
||||||
return Kind.eChar32;
|
return Kind.eChar32;
|
||||||
case 'u':
|
case 'u':
|
||||||
// Bug 526724 u8 should result in Kind.eChar
|
// Bug 526724 u8 should result in Kind.eChar
|
||||||
if (fValue[1] != '8') {
|
if (fLiteral[1] != '8') {
|
||||||
return Kind.eChar16;
|
return Kind.eChar16;
|
||||||
}
|
}
|
||||||
//$FALL-THROUGH$
|
//$FALL-THROUGH$
|
||||||
|
@ -367,117 +427,123 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
}
|
}
|
||||||
|
|
||||||
private IType classifyTypeOfFloatLiteral() {
|
private IType classifyTypeOfFloatLiteral() {
|
||||||
final char[] lit= fSuffix;
|
Kind kind = Kind.eDouble;
|
||||||
final int len= lit.length;
|
int flags = 0;
|
||||||
Kind kind= Kind.eDouble;
|
if (hasSuffix()) {
|
||||||
int flags= 0;
|
if (hasNumericSuffix()) {
|
||||||
if (len > 0) {
|
switch (fSuffix[0]) {
|
||||||
if (fIsCompilerSuffix) {
|
|
||||||
switch (lit[len - 1]) {
|
|
||||||
case 'f': case 'F':
|
case 'f': case 'F':
|
||||||
kind= Kind.eFloat;
|
kind = Kind.eFloat;
|
||||||
break;
|
break;
|
||||||
case 'l': case 'L':
|
case 'l': case 'L':
|
||||||
flags |= IBasicType.IS_LONG;
|
flags |= IBasicType.IS_LONG;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return getUserDefinedLiteralOperatorType();
|
IType type = getUserDefinedLiteralOperatorType();
|
||||||
|
if (type instanceof IProblemType && hasNumericCompilerSuffix()) {
|
||||||
|
switch (fSuffix[0]) {
|
||||||
|
case 'i': case 'j':
|
||||||
|
flags |= IBasicType.IS_IMAGINARY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new CPPBasicType(kind, flags, this);
|
return new CPPBasicType(kind, flags, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IType classifyTypeOfIntLiteral() {
|
private IType classifyTypeOfIntLiteral() {
|
||||||
int makelong= 0;
|
Kind kind = Kind.eInt;
|
||||||
boolean unsigned= false;
|
int flags = 0;
|
||||||
final char[] lit= fSuffix;
|
|
||||||
int flags= 0;
|
|
||||||
|
|
||||||
if (fIsCompilerSuffix) {
|
if (hasSuffix()) {
|
||||||
for (int i= lit.length - 1; i >= 0; i--) {
|
if (hasNumericSuffix()) {
|
||||||
final char c= lit[i];
|
int makelong = 0;
|
||||||
if (!(c > 'f' && c <= 'z') && !(c > 'F' && c <= 'Z')) {
|
for (char c : fSuffix) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'u':
|
case 'u': case 'U':
|
||||||
case 'U':
|
flags |= IBasicType.IS_UNSIGNED;
|
||||||
unsigned = true;
|
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l': case 'L':
|
||||||
case 'L':
|
|
||||||
makelong++;
|
makelong++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unsigned) {
|
|
||||||
flags |= IBasicType.IS_UNSIGNED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (makelong > 1) {
|
if (makelong > 1) {
|
||||||
flags |= IBasicType.IS_LONG_LONG;
|
flags |= IBasicType.IS_LONG_LONG;
|
||||||
} else if (makelong == 1) {
|
} else if (makelong == 1) {
|
||||||
flags |= IBasicType.IS_LONG;
|
flags |= IBasicType.IS_LONG;
|
||||||
}
|
}
|
||||||
} else if (lit.length > 0) {
|
} else {
|
||||||
return getUserDefinedLiteralOperatorType();
|
IType type = getUserDefinedLiteralOperatorType();
|
||||||
|
if (type instanceof IProblemType && hasNumericCompilerSuffix()) {
|
||||||
|
switch (fSuffix[0]) {
|
||||||
|
case 'i': case 'j':
|
||||||
|
flags |= IBasicType.IS_IMAGINARY;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return new CPPBasicType(Kind.eInt, flags, this);
|
} else {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new CPPBasicType(kind, flags, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int integerLiteral() {
|
private static int integerLiteral(char[] value) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
char c = fValue[i++];
|
char c = value[i++];
|
||||||
|
|
||||||
if (c == '0' && i < fValue.length) {
|
if (c == '0' && i < value.length) {
|
||||||
// Probably octal/hex/binary
|
// Probably octal/hex/binary
|
||||||
c = fValue[i];
|
c = value[i];
|
||||||
switch ((c | 0x20)) {
|
switch ((c | 0x20)) {
|
||||||
case 'x':
|
case 'x':
|
||||||
return probablyHex(i);
|
return probablyHex(value, i);
|
||||||
case 'b':
|
case 'b':
|
||||||
return probablyBinary(i);
|
return probablyBinary(value, i);
|
||||||
case '0': case '1': case '2': case '3':
|
case '0': case '1': case '2': case '3':
|
||||||
case '4': case '5': case '6': case '7':
|
case '4': case '5': case '6': case '7':
|
||||||
/* octal-literal:
|
/* octal-literal:
|
||||||
* 0
|
* 0
|
||||||
* octal-literal octal-digit
|
* octal-literal octal-digit
|
||||||
*/
|
*/
|
||||||
while (isOctal(c) && i < fValue.length) {
|
while (isOctal(c) && i < value.length) {
|
||||||
c = fValue[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '.':
|
case '.':
|
||||||
return afterDecimalPoint(i);
|
return afterDecimalPoint(value, i);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If there is an 8 or 9, then we have a malformed octal
|
* If there is an 8 or 9, then we have a malformed octal
|
||||||
*/
|
*/
|
||||||
if (c == '8' || c == '9') {
|
if (c == '8' || c == '9') {
|
||||||
// eat remaining numbers
|
// eat remaining numbers
|
||||||
c = fValue[i];
|
c = value[i];
|
||||||
while (Character.isDigit(c) && i < fValue.length) {
|
while (Character.isDigit(c) && i < value.length) {
|
||||||
c = fValue[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A floating-point constant could also have a leading zero
|
* A floating-point constant could also have a leading zero
|
||||||
*/
|
*/
|
||||||
return handleDecimalOrExponent(c, i);
|
return handleDecimalOrExponent(value, c, i);
|
||||||
} else if (Character.isDigit(c)) {
|
} else if (Character.isDigit(c)) {
|
||||||
/* decimal-literal :
|
/* decimal-literal :
|
||||||
* nonzero-digit (c has to be this to get into this else)
|
* nonzero-digit (c has to be this to get into this else)
|
||||||
* decimal-literal digit
|
* decimal-literal digit
|
||||||
*/
|
*/
|
||||||
c = fValue[i];
|
c = value[i];
|
||||||
while (Character.isDigit(c) && i < fValue.length) {
|
while (Character.isDigit(c) && i < value.length) {
|
||||||
c = fValue[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return handleDecimalOrExponent(c, i);
|
return handleDecimalOrExponent(value, c, i);
|
||||||
} else {
|
} else {
|
||||||
// Somehow we got called and there wasn't a digit
|
// Somehow we got called and there wasn't a digit
|
||||||
// Shouldn't get here
|
// Shouldn't get here
|
||||||
|
@ -490,26 +556,26 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
/*
|
/*
|
||||||
* Consumes a decimal point or exponent, if present.
|
* Consumes a decimal point or exponent, if present.
|
||||||
*/
|
*/
|
||||||
private int handleDecimalOrExponent(char c, int i) {
|
private static int handleDecimalOrExponent(char[] value, char c, int i) {
|
||||||
if (c == '.') {
|
if (c == '.') {
|
||||||
return afterDecimalPoint(i);
|
return afterDecimalPoint(value, i);
|
||||||
} else if ((c | 0x20) == 'e') {
|
} else if ((c | 0x20) == 'e') {
|
||||||
return exponentPart(i);
|
return exponentPart(value, i);
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called with the expectation that fValue[i] == '.'
|
* Called with the expectation that value[i] == '.'
|
||||||
*/
|
*/
|
||||||
private int afterDecimalPoint(int i) {
|
private static int afterDecimalPoint(char[] value, int i) {
|
||||||
char c = fValue[++i];
|
char c = value[++i];
|
||||||
while (Character.isDigit(c) && i < fValue.length) {
|
while (Character.isDigit(c) && i < value.length) {
|
||||||
c = fValue[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((c | 0x20) == 'e') {
|
if ((c | 0x20) == 'e') {
|
||||||
return exponentPart(i);
|
return exponentPart(value, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
|
@ -518,16 +584,16 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
/*
|
/*
|
||||||
* Called with the expectation that c == 'e'
|
* Called with the expectation that c == 'e'
|
||||||
*/
|
*/
|
||||||
private int exponentPart(int i) {
|
private static int exponentPart(char[] value, int i) {
|
||||||
char c = fValue[++i];
|
char c = value[++i];
|
||||||
|
|
||||||
// optional '+' or '-'
|
// optional '+' or '-'
|
||||||
if (c == '+' || c == '-') {
|
if (c == '+' || c == '-') {
|
||||||
c = fValue[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Character.isDigit(c) && i < fValue.length) {
|
while (Character.isDigit(c) && i < value.length) {
|
||||||
c = fValue[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
// If there were no digits following the 'e' then we have
|
// If there were no digits following the 'e' then we have
|
||||||
// D.De or .De which is a UDL on a double
|
// D.De or .De which is a UDL on a double
|
||||||
|
@ -536,21 +602,21 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
}
|
}
|
||||||
|
|
||||||
// GCC's binary constant notation
|
// GCC's binary constant notation
|
||||||
private int probablyBinary(int i) {
|
private static int probablyBinary(char[] value, int i) {
|
||||||
char c = fValue[++i];
|
char c = value[++i];
|
||||||
|
|
||||||
if (c == '1' || c == '0') {
|
if (c == '1' || c == '0') {
|
||||||
while (c == '1' || c == '0' && i < fValue.length) {
|
while (c == '1' || c == '0' && i < value.length) {
|
||||||
c = fValue[i++];
|
c = value[i++];
|
||||||
}
|
}
|
||||||
if (Character.isDigit(c)) {
|
if (Character.isDigit(c)) {
|
||||||
// UDL can't begin with digit, so this is a malformed binary
|
// UDL can't begin with digit, so this is a malformed binary
|
||||||
return -1;
|
return -1;
|
||||||
} else if (c == '.') {
|
} else if (c == '.') {
|
||||||
// no such thing as binary floating point
|
// no such thing as binary floating point
|
||||||
c = fValue[++i];
|
c = value[++i];
|
||||||
while (Character.isDigit(c) && i < fValue.length) {
|
while (Character.isDigit(c) && i < value.length) {
|
||||||
c = fValue[i++];
|
c = value[i++];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -560,22 +626,22 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int probablyHex(int i) {
|
private static int probablyHex(char[] value, int i) {
|
||||||
/* hexadecimal-literal
|
/* hexadecimal-literal
|
||||||
* 0x hexadecimal-digit
|
* 0x hexadecimal-digit
|
||||||
* 0X hexadecimal-digit
|
* 0X hexadecimal-digit
|
||||||
* hexadecimal-literal hexadecimal-digit
|
* hexadecimal-literal hexadecimal-digit
|
||||||
*/
|
*/
|
||||||
char c = fValue[++i];
|
char c = value[++i];
|
||||||
if (isHexDigit(c)) {
|
if (isHexDigit(c)) {
|
||||||
while (isHexDigit(c) && i < fValue.length) {
|
while (isHexDigit(c) && i < value.length) {
|
||||||
c = fValue[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
if (c == '.') {
|
if (c == '.') {
|
||||||
// Could be GCC's hex float
|
// Could be GCC's hex float
|
||||||
return hexFloatAfterDecimal(i);
|
return hexFloatAfterDecimal(value, i);
|
||||||
} else if ((c | 0x20) == 'p') {
|
} else if ((c | 0x20) == 'p') {
|
||||||
return hexFloatExponent(i);
|
return hexFloatExponent(value, i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return i - 1;
|
return i - 1;
|
||||||
|
@ -584,17 +650,17 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assumes fValue[i] == '.'
|
// Assumes value[i] == '.'
|
||||||
private int hexFloatAfterDecimal(int i) {
|
private static int hexFloatAfterDecimal(char[] value, int i) {
|
||||||
// 0xHHH.
|
// 0xHHH.
|
||||||
char c = fValue[++i];
|
char c = value[++i];
|
||||||
if (isHexDigit(c)) {
|
if (isHexDigit(c)) {
|
||||||
while (isHexDigit(c) && i < fValue.length) {
|
while (isHexDigit(c) && i < value.length) {
|
||||||
c = fValue[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((c | 0x20) == 'p') {
|
if ((c | 0x20) == 'p') {
|
||||||
return hexFloatExponent(i);
|
return hexFloatExponent(value, i);
|
||||||
} else {
|
} else {
|
||||||
// The parser is very confused at this point
|
// The parser is very confused at this point
|
||||||
// as the expression is 0x1.f
|
// as the expression is 0x1.f
|
||||||
|
@ -608,17 +674,17 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assumes image[i] == 'p'
|
// Assumes image[i] == 'p'
|
||||||
private int hexFloatExponent(int i) {
|
private static int hexFloatExponent(char[] value, int i) {
|
||||||
// 0xHH.HH[pP][-+]?DDDD
|
// 0xHH.HH[pP][-+]?DDDD
|
||||||
char c = fValue[++i];
|
char c = value[++i];
|
||||||
|
|
||||||
if (c == '-' || c == '+') {
|
if (c == '-' || c == '+') {
|
||||||
c = fValue[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Character.isDigit(c)) {
|
if (Character.isDigit(c)) {
|
||||||
while (Character.isDigit(c) && i < fValue.length) {
|
while (Character.isDigit(c) && i < value.length) {
|
||||||
c = fValue[++i];
|
c = value[++i];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return i - 1;
|
return i - 1;
|
||||||
|
@ -626,12 +692,12 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isHexDigit(char c) {
|
private static boolean isHexDigit(char c) {
|
||||||
c |= 0x20;
|
c |= 0x20;
|
||||||
return ((c <= 'f' && c >= 'a') || (c <= '9' && c >= '0'));
|
return ((c <= 'f' && c >= 'a') || (c <= '9' && c >= '0'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isOctal(final char c) {
|
private static boolean isOctal(final char c) {
|
||||||
return c >= '0' && c <= '7';
|
return c >= '0' && c <= '7';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -642,7 +708,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setValue(String value) {
|
public void setValue(String value) {
|
||||||
assertNotFrozen();
|
assertNotFrozen();
|
||||||
this.fValue = value.toCharArray();
|
set(fKind, value.toCharArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -656,7 +722,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
@Override
|
@Override
|
||||||
public ICPPEvaluation getEvaluation() {
|
public ICPPEvaluation getEvaluation() {
|
||||||
if (fEvaluation == null)
|
if (fEvaluation == null)
|
||||||
fEvaluation= createEvaluation();
|
fEvaluation = createEvaluation();
|
||||||
return fEvaluation;
|
return fEvaluation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,7 +730,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
switch (fKind) {
|
switch (fKind) {
|
||||||
case lk_this: {
|
case lk_this: {
|
||||||
IScope scope = CPPVisitor.getContainingScope(this);
|
IScope scope = CPPVisitor.getContainingScope(this);
|
||||||
IType type= CPPVisitor.getImpliedObjectType(scope);
|
IType type = CPPVisitor.getImpliedObjectType(scope);
|
||||||
if (type == null)
|
if (type == null)
|
||||||
return EvalFixed.INCOMPLETE;
|
return EvalFixed.INCOMPLETE;
|
||||||
return new EvalFixed(new CPPPointerType(type), PRVALUE, IntegralValue.THIS);
|
return new EvalFixed(new CPPPointerType(type), PRVALUE, IntegralValue.THIS);
|
||||||
|
@ -676,11 +742,11 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
case lk_char_constant:
|
case lk_char_constant:
|
||||||
return new EvalFixed(getCharType(), PRVALUE, createCharValue());
|
return new EvalFixed(getCharType(), PRVALUE, createCharValue());
|
||||||
case lk_float_constant:
|
case lk_float_constant:
|
||||||
return new EvalFixed(classifyTypeOfFloatLiteral(), PRVALUE, FloatingPointValue.create(getValue()));
|
return new EvalFixed(classifyTypeOfFloatLiteral(), PRVALUE, FloatingPointValue.create(fLiteral));
|
||||||
case lk_integer_constant:
|
case lk_integer_constant:
|
||||||
return new EvalFixed(classifyTypeOfIntLiteral(), PRVALUE, createIntValue());
|
return new EvalFixed(classifyTypeOfIntLiteral(), PRVALUE, createIntValue());
|
||||||
case lk_string_literal:
|
case lk_string_literal:
|
||||||
return new EvalFixed(getStringType(), LVALUE, CStringValue.create(getValue()));
|
return new EvalFixed(getStringType(), LVALUE, CStringValue.create(fLiteral));
|
||||||
case lk_nullptr:
|
case lk_nullptr:
|
||||||
return EVAL_NULL_PTR;
|
return EVAL_NULL_PTR;
|
||||||
}
|
}
|
||||||
|
@ -705,7 +771,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
} else if (paramCount == 1) {
|
} else if (paramCount == 1) {
|
||||||
//this means that we need to fall back to the raw literal operator
|
//this means that we need to fall back to the raw literal operator
|
||||||
if (params[0].getType() instanceof IPointerType) {
|
if (params[0].getType() instanceof IPointerType) {
|
||||||
char numValue[] = getValue();
|
char numValue[] = fLiteral;
|
||||||
int numLen = numValue.length;
|
int numLen = numValue.length;
|
||||||
char strValue[] = new char[numLen + 2];
|
char strValue[] = new char[numLen + 2];
|
||||||
strValue[0] = '"';
|
strValue[0] = '"';
|
||||||
|
@ -730,7 +796,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
}
|
}
|
||||||
|
|
||||||
//has a user-defined literal suffix but didn't find a udl operator function => error
|
//has a user-defined literal suffix but didn't find a udl operator function => error
|
||||||
if (getSuffix().length > 0 && (getKind() == lk_string_literal || !fIsCompilerSuffix)) {
|
if (hasSuffix() && !hasNumericSuffix() && !hasNumericCompilerSuffix()) {
|
||||||
return EvalFixed.INCOMPLETE;
|
return EvalFixed.INCOMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -739,10 +805,8 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
|
|
||||||
private IValue createCharValue() {
|
private IValue createCharValue() {
|
||||||
try {
|
try {
|
||||||
final char[] image= getValue();
|
final int index = (fLiteral.length > 1 && fLiteral[0] == 'L') ? 2 : 1;
|
||||||
if (image.length > 1 && image[0] == 'L')
|
return IntegralValue.create(ExpressionEvaluator.getChar(fLiteral, index));
|
||||||
return IntegralValue.create(ExpressionEvaluator.getChar(image, 2));
|
|
||||||
return IntegralValue.create(ExpressionEvaluator.getChar(image, 1));
|
|
||||||
} catch (EvalException e) {
|
} catch (EvalException e) {
|
||||||
return IntegralValue.UNKNOWN;
|
return IntegralValue.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
@ -750,7 +814,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
|
|
||||||
private IValue createIntValue() {
|
private IValue createIntValue() {
|
||||||
try {
|
try {
|
||||||
return IntegralValue.create(ExpressionEvaluator.getNumber(getValue()));
|
return IntegralValue.create(ExpressionEvaluator.getNumber(fLiteral));
|
||||||
} catch (EvalException e) {
|
} catch (EvalException e) {
|
||||||
return IntegralValue.UNKNOWN;
|
return IntegralValue.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
@ -768,22 +832,27 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ValueCategory getValueCategory() {
|
public ValueCategory getValueCategory() {
|
||||||
return getKind() == lk_string_literal ? LVALUE : PRVALUE;
|
return (fKind == lk_string_literal) ? LVALUE : PRVALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IASTImplicitName[] getImplicitNames() {
|
public IASTImplicitName[] getImplicitNames() {
|
||||||
if (fImplicitNames == null) {
|
if (fImplicitNames == null) {
|
||||||
if (fIsCompilerSuffix) {
|
if (!hasSuffix() || hasNumericSuffix()) {
|
||||||
|
fImplicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
||||||
|
} else {
|
||||||
|
IBinding userDefinedLiteralOperator = getUserDefinedLiteralOperator();
|
||||||
|
if (userDefinedLiteralOperator == null && hasNumericCompilerSuffix()) {
|
||||||
fImplicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
fImplicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
||||||
} else {
|
} else {
|
||||||
CPPASTImplicitName operatorName = new CPPASTImplicitName(fSuffix, this);
|
CPPASTImplicitName operatorName = new CPPASTImplicitName(fSuffix, this);
|
||||||
operatorName.setOperator(true);
|
operatorName.setOperator(true);
|
||||||
operatorName.setBinding(getUserDefinedLiteralOperator());
|
operatorName.setBinding(userDefinedLiteralOperator);
|
||||||
operatorName.setOffsetAndLength(getOffset() + fValue.length, fSuffix.length);
|
operatorName.setOffsetAndLength(getOffset() + fLiteral.length, fSuffix.length);
|
||||||
fImplicitNames = new IASTImplicitName[] { operatorName };
|
fImplicitNames = new IASTImplicitName[] { operatorName };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return fImplicitNames;
|
return fImplicitNames;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -549,6 +549,11 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory {
|
||||||
return new CPPASTLiteralExpression(kind, rep.toCharArray());
|
return new CPPASTLiteralExpression(kind, rep.toCharArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ICPPASTLiteralExpression newLiteralExpression(int kind, String rep, char[] numericCompilerSuffixes) {
|
||||||
|
return new CPPASTLiteralExpression(kind, rep.toCharArray(), numericCompilerSuffixes);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ICPPASTName newName() {
|
public ICPPASTName newName() {
|
||||||
return new CPPASTName();
|
return new CPPASTName();
|
||||||
|
|
|
@ -1931,15 +1931,13 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
switch (LT(1)) {
|
switch (LT(1)) {
|
||||||
case IToken.tINTEGER:
|
case IToken.tINTEGER:
|
||||||
t = consume();
|
t = consume();
|
||||||
literalExpr = getNodeFactory().newLiteralExpression(IASTLiteralExpression.lk_integer_constant, t.getImage());
|
literalExpr = getNodeFactory().newLiteralExpression(IASTLiteralExpression.lk_integer_constant, t.getImage(), additionalNumericalSuffixes);
|
||||||
literalExprWithRange = setRange(literalExpr, t.getOffset(), t.getEndOffset());
|
literalExprWithRange = setRange(literalExpr, t.getOffset(), t.getEndOffset());
|
||||||
((CPPASTLiteralExpression) literalExpr).calculateSuffix(additionalNumericalSuffixes);
|
|
||||||
break;
|
break;
|
||||||
case IToken.tFLOATINGPT:
|
case IToken.tFLOATINGPT:
|
||||||
t = consume();
|
t = consume();
|
||||||
literalExpr = getNodeFactory().newLiteralExpression(IASTLiteralExpression.lk_float_constant, t.getImage());
|
literalExpr = getNodeFactory().newLiteralExpression(IASTLiteralExpression.lk_float_constant, t.getImage(), additionalNumericalSuffixes);
|
||||||
literalExprWithRange = setRange(literalExpr, t.getOffset(), t.getEndOffset());
|
literalExprWithRange = setRange(literalExpr, t.getOffset(), t.getEndOffset());
|
||||||
((CPPASTLiteralExpression) literalExpr).calculateSuffix(additionalNumericalSuffixes);
|
|
||||||
break;
|
break;
|
||||||
case IToken.tSTRING:
|
case IToken.tSTRING:
|
||||||
case IToken.tLSTRING:
|
case IToken.tLSTRING:
|
||||||
|
@ -1947,9 +1945,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
case IToken.tUTF32STRING:
|
case IToken.tUTF32STRING:
|
||||||
case IToken.tUSER_DEFINED_STRING_LITERAL:
|
case IToken.tUSER_DEFINED_STRING_LITERAL:
|
||||||
literalExprWithRange = stringLiteral();
|
literalExprWithRange = stringLiteral();
|
||||||
if (supportUserDefinedLiterals) {
|
|
||||||
((CPPASTLiteralExpression) literalExprWithRange).calculateSuffix();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case IToken.tCHAR:
|
case IToken.tCHAR:
|
||||||
case IToken.tLCHAR:
|
case IToken.tLCHAR:
|
||||||
|
@ -1960,9 +1955,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
literalExpr = getNodeFactory().newLiteralExpression(
|
literalExpr = getNodeFactory().newLiteralExpression(
|
||||||
IASTLiteralExpression.lk_char_constant, t.getImage());
|
IASTLiteralExpression.lk_char_constant, t.getImage());
|
||||||
literalExprWithRange = setRange(literalExpr, t.getOffset(), t.getEndOffset());
|
literalExprWithRange = setRange(literalExpr, t.getOffset(), t.getEndOffset());
|
||||||
if (supportUserDefinedLiterals) {
|
|
||||||
((CPPASTLiteralExpression) literalExprWithRange).calculateSuffix();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case IToken.t_false:
|
case IToken.t_false:
|
||||||
t = consume();
|
t = consume();
|
||||||
|
@ -2031,7 +2023,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
return literalExprWithRange;
|
return literalExprWithRange;
|
||||||
}
|
}
|
||||||
IToken opName = consume(IToken.tIDENTIFIER);
|
IToken opName = consume(IToken.tIDENTIFIER);
|
||||||
((CPPASTLiteralExpression) literalExprWithRange).addSuffix(opName.getCharImage());
|
((CPPASTLiteralExpression) literalExprWithRange).setSuffix(opName.getCharImage());
|
||||||
setRange(literalExprWithRange, offset, opName.getEndOffset());
|
setRange(literalExprWithRange, offset, opName.getEndOffset());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTArrayDeclarator;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTArrayDeclarator;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression;
|
||||||
import org.eclipse.cdt.core.dom.rewrite.TypeHelper;
|
import org.eclipse.cdt.core.dom.rewrite.TypeHelper;
|
||||||
import org.eclipse.cdt.core.parser.Keywords;
|
import org.eclipse.cdt.core.parser.Keywords;
|
||||||
|
|
||||||
|
@ -220,8 +221,7 @@ public abstract class AccessorFactory {
|
||||||
CPPASTName parameterName = getSetterParameterName();
|
CPPASTName parameterName = getSetterParameterName();
|
||||||
if (Arrays.equals(fieldName.getSimpleID(), parameterName.getSimpleID())) {
|
if (Arrays.equals(fieldName.getSimpleID(), parameterName.getSimpleID())) {
|
||||||
CPPASTFieldReference fieldRef = new CPPASTFieldReference();
|
CPPASTFieldReference fieldRef = new CPPASTFieldReference();
|
||||||
CPPASTLiteralExpression litExpr = new CPPASTLiteralExpression();
|
CPPASTLiteralExpression litExpr = new CPPASTLiteralExpression(ICPPASTLiteralExpression.lk_this, Keywords.cTHIS);
|
||||||
litExpr.setValue(Keywords.cTHIS);
|
|
||||||
fieldRef.setFieldOwner(litExpr);
|
fieldRef.setFieldOwner(litExpr);
|
||||||
fieldRef.setIsPointerDereference(true);
|
fieldRef.setIsPointerDereference(true);
|
||||||
fieldRef.setFieldName(fieldName.copy(CopyStyle.withLocations));
|
fieldRef.setFieldName(fieldName.copy(CopyStyle.withLocations));
|
||||||
|
|
Loading…
Add table
Reference in a new issue