1
0
Fork 0
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:
Hansruedi Patzen 2017-11-28 15:48:19 +01:00 committed by Sergey Prigogin
parent 86c3d8eeca
commit 3e66e22aed
8 changed files with 464 additions and 341 deletions

View file

@ -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; }

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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,13 +427,11 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
} }
private IType classifyTypeOfFloatLiteral() { private IType classifyTypeOfFloatLiteral() {
final char[] lit= fSuffix;
final int len= lit.length;
Kind kind = Kind.eDouble; Kind kind = Kind.eDouble;
int flags = 0; int flags = 0;
if (len > 0) { if (hasSuffix()) {
if (fIsCompilerSuffix) { if (hasNumericSuffix()) {
switch (lit[len - 1]) { switch (fSuffix[0]) {
case 'f': case 'F': case 'f': case 'F':
kind = Kind.eFloat; kind = Kind.eFloat;
break; break;
@ -382,102 +440,110 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
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;
final char[] lit= fSuffix;
int flags = 0; 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());
} }
/** /**
@ -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;
} }
} }

View file

@ -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();

View file

@ -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());
} }
} }

View file

@ -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));