mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-19 15:05:36 +02:00
Bug 459279 - Size of string literals with escape characters
Change-Id: I5fa96ce722db657d5ff4a3557d3add04e991ab88 Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
This commit is contained in:
parent
f7cf56f4c5
commit
34c84eba3c
4 changed files with 90 additions and 35 deletions
|
@ -256,7 +256,7 @@ public class AST2CPPTests extends AST2TestBase {
|
||||||
assertNotNull(second);
|
assertNotNull(second);
|
||||||
assertTrue("Expected types to be the same, but first was: '" + first.toString() + "' and second was: '" + second + "'", first.isSameType(second));
|
assertTrue("Expected types to be the same, but first was: '" + first.toString() + "' and second was: '" + second + "'", first.isSameType(second));
|
||||||
}
|
}
|
||||||
|
|
||||||
// int *zzz1 (char);
|
// int *zzz1 (char);
|
||||||
// int (*zzz2) (char);
|
// int (*zzz2) (char);
|
||||||
// int ((*zzz3)) (char);
|
// int ((*zzz3)) (char);
|
||||||
|
@ -9062,6 +9062,13 @@ public class AST2CPPTests extends AST2TestBase {
|
||||||
public void testSizeofReference_397342() throws Exception {
|
public void testSizeofReference_397342() throws Exception {
|
||||||
parseAndCheckBindings();
|
parseAndCheckBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// constexpr int waldo = sizeof("cat\b\\\n");
|
||||||
|
public void testSizeofStringLiteralWithEscapeCharacters_459279() throws Exception {
|
||||||
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
|
ICPPVariable waldo = helper.assertNonProblem("waldo");
|
||||||
|
assertConstantValue(7, waldo); // "cat" + backspace + slash + newline + null terminator
|
||||||
|
}
|
||||||
|
|
||||||
// struct A {
|
// struct A {
|
||||||
// char a[100];
|
// char a[100];
|
||||||
|
@ -10666,7 +10673,7 @@ public class AST2CPPTests extends AST2TestBase {
|
||||||
public void testIsBaseOf_409100() throws Exception {
|
public void testIsBaseOf_409100() throws Exception {
|
||||||
BindingAssertionHelper b = getAssertionHelper();
|
BindingAssertionHelper b = getAssertionHelper();
|
||||||
IVariable var = b.assertNonProblem("value");
|
IVariable var = b.assertNonProblem("value");
|
||||||
assertEquals(1 /*true */, var.getInitialValue().numericalValue().longValue());
|
assertConstantValue(1 /*true */, var);
|
||||||
}
|
}
|
||||||
|
|
||||||
// namespace NS {
|
// namespace NS {
|
||||||
|
@ -10982,7 +10989,7 @@ public class AST2CPPTests extends AST2TestBase {
|
||||||
public void testConditionalExpressionFolding_429891() throws Exception {
|
public void testConditionalExpressionFolding_429891() throws Exception {
|
||||||
BindingAssertionHelper helper = getAssertionHelper();
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
IVariable waldo = helper.assertNonProblem("waldo");
|
IVariable waldo = helper.assertNonProblem("waldo");
|
||||||
assertEquals(5, waldo.getInitialValue().numericalValue().longValue());
|
assertConstantValue(5, waldo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// constexpr int naive_fibonacci(int x) {
|
// constexpr int naive_fibonacci(int x) {
|
||||||
|
@ -11009,7 +11016,7 @@ public class AST2CPPTests extends AST2TestBase {
|
||||||
public void testNameLookupInDefaultArgument_432701() throws Exception {
|
public void testNameLookupInDefaultArgument_432701() throws Exception {
|
||||||
BindingAssertionHelper helper = getAssertionHelper();
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
IVariable waldo = helper.assertNonProblem("waldo");
|
IVariable waldo = helper.assertNonProblem("waldo");
|
||||||
assertEquals(42, waldo.getInitialValue().numericalValue().longValue());
|
assertConstantValue(42, waldo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct S1 { S1(int); };
|
// struct S1 { S1(int); };
|
||||||
|
|
|
@ -3071,7 +3071,7 @@ public class AST2TemplateTests extends AST2TestBase {
|
||||||
ICPPVariable _256= ba.assertNonProblem("_256=0x100", 4, ICPPVariable.class);
|
ICPPVariable _256= ba.assertNonProblem("_256=0x100", 4, ICPPVariable.class);
|
||||||
IQualifierType qt1= assertInstance(_256.getType(), IQualifierType.class);
|
IQualifierType qt1= assertInstance(_256.getType(), IQualifierType.class);
|
||||||
ICPPBasicType bt1= assertInstance(qt1.getType(), ICPPBasicType.class);
|
ICPPBasicType bt1= assertInstance(qt1.getType(), ICPPBasicType.class);
|
||||||
assertEquals(256, _256.getInitialValue().numericalValue().intValue());
|
assertConstantValue(256, _256);
|
||||||
|
|
||||||
ICPPVariable t= ba.assertNonProblem("t;", 1, ICPPVariable.class);
|
ICPPVariable t= ba.assertNonProblem("t;", 1, ICPPVariable.class);
|
||||||
ICPPTemplateInstance ci1= assertInstance(t.getType(), ICPPTemplateInstance.class, ICPPClassType.class);
|
ICPPTemplateInstance ci1= assertInstance(t.getType(), ICPPTemplateInstance.class, ICPPClassType.class);
|
||||||
|
@ -7390,9 +7390,7 @@ public class AST2TemplateTests extends AST2TestBase {
|
||||||
public void testSfinaeInNestedTypeInTemplateArgument_402257() throws Exception {
|
public void testSfinaeInNestedTypeInTemplateArgument_402257() throws Exception {
|
||||||
BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true);
|
||||||
ICPPVariable B = helper.assertNonProblem("B");
|
ICPPVariable B = helper.assertNonProblem("B");
|
||||||
Long val = B.getInitialValue().numericalValue();
|
assertConstantValue(0 /* false */, B);
|
||||||
assertNotNull(val);
|
|
||||||
assertEquals(0 /* false */, val.longValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct S {
|
// struct S {
|
||||||
|
@ -8038,9 +8036,7 @@ public class AST2TemplateTests extends AST2TestBase {
|
||||||
public void testSizeofParameterPackOnTypeid_401973() throws Exception {
|
public void testSizeofParameterPackOnTypeid_401973() throws Exception {
|
||||||
BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true);
|
BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true);
|
||||||
ICPPVariable bar = helper.assertNonProblem("bar");
|
ICPPVariable bar = helper.assertNonProblem("bar");
|
||||||
Long barValue = bar.getInitialValue().numericalValue();
|
assertConstantValue(2, bar);
|
||||||
assertNotNull(barValue);
|
|
||||||
assertEquals(2, barValue.longValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// template <int...> struct tuple_indices {};
|
// template <int...> struct tuple_indices {};
|
||||||
|
@ -8573,7 +8569,7 @@ public class AST2TemplateTests extends AST2TestBase {
|
||||||
public void testSpecializationOfConstexprFunction_420995() throws Exception {
|
public void testSpecializationOfConstexprFunction_420995() throws Exception {
|
||||||
BindingAssertionHelper helper = getAssertionHelper();
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
ICPPVariable waldo = helper.assertNonProblem("waldo");
|
ICPPVariable waldo = helper.assertNonProblem("waldo");
|
||||||
assertEquals(2, waldo.getInitialValue().numericalValue().longValue());
|
assertConstantValue(2, waldo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// struct Test {
|
// struct Test {
|
||||||
|
|
|
@ -60,6 +60,7 @@ import org.eclipse.cdt.core.dom.ast.IField;
|
||||||
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.IType;
|
import org.eclipse.cdt.core.dom.ast.IType;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||||
import org.eclipse.cdt.core.dom.ast.IVariable;
|
import org.eclipse.cdt.core.dom.ast.IVariable;
|
||||||
import org.eclipse.cdt.core.dom.ast.c.ICASTTypeIdInitializerExpression;
|
import org.eclipse.cdt.core.dom.ast.c.ICASTTypeIdInitializerExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
|
||||||
|
@ -494,6 +495,14 @@ public class AST2TestBase extends BaseTestCase {
|
||||||
assertEquals(ownerName, struct.getName());
|
assertEquals(ownerName, struct.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static void assertConstantValue(long expected, IVariable constant) {
|
||||||
|
IValue value = constant.getInitialValue();
|
||||||
|
assertNotNull(value);
|
||||||
|
Long numericalValue = value.numericalValue();
|
||||||
|
assertNotNull(numericalValue);
|
||||||
|
assertEquals(expected, numericalValue.longValue());
|
||||||
|
}
|
||||||
|
|
||||||
protected class BindingAssertionHelper {
|
protected class BindingAssertionHelper {
|
||||||
protected IASTTranslationUnit tu;
|
protected IASTTranslationUnit tu;
|
||||||
protected String contents;
|
protected String contents;
|
||||||
|
|
|
@ -42,6 +42,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
|
|
||||||
private int kind;
|
private int kind;
|
||||||
private char[] value = CharArrayUtils.EMPTY;
|
private char[] value = CharArrayUtils.EMPTY;
|
||||||
|
private int fStringLiteralSize = -1; // accounting for escape sequences and the null terminator
|
||||||
private ICPPEvaluation fEvaluation;
|
private ICPPEvaluation fEvaluation;
|
||||||
|
|
||||||
public CPPASTLiteralExpression() {
|
public CPPASTLiteralExpression() {
|
||||||
|
@ -110,31 +111,73 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IValue getStringLiteralSize() {
|
private int computeStringLiteralSize() {
|
||||||
char[] value= getValue();
|
int start = 0, end = value.length - 1;
|
||||||
int length= value.length-1;
|
boolean isRaw = false;
|
||||||
boolean isRaw= false;
|
|
||||||
for (int i = 0; i < length; i++) {
|
// Skip past a prefix affecting the character type.
|
||||||
final char c = value[i];
|
if (value[0] == 'L' || value[0] == 'u' || value[0] == 'U') {
|
||||||
if (c == '"') {
|
++start;
|
||||||
if (isRaw) {
|
}
|
||||||
for (int j = i + 1; j < length; j++) {
|
|
||||||
final char d= value[j];
|
// If there is an 'R' prefix, skip past it but take note of it.
|
||||||
if (d == '(') {
|
if (value[start] == 'R') {
|
||||||
length -= 2*(j-i);
|
++start;
|
||||||
break;
|
isRaw = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
// Now we should have a quote-enclosed string. Skip past the quotes.
|
||||||
length -= i;
|
if (!(value[start] == '"' && value[end] == '"')) {
|
||||||
if (length < 0)
|
// Unexpected!
|
||||||
length = 0;
|
return 0;
|
||||||
break;
|
}
|
||||||
} else if (c == 'R') {
|
++start;
|
||||||
isRaw = true;
|
--end;
|
||||||
|
|
||||||
|
// If we have a raw string, skip past the raw prefix.
|
||||||
|
if (isRaw) {
|
||||||
|
while (value[start] != '(' && start <= end) {
|
||||||
|
++start;
|
||||||
|
--end;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we should have a parenthesis-enclosed string.
|
||||||
|
if (!(value[start] == '(' && value[end] == ')')) {
|
||||||
|
// Unexpected!
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since the string is raw, we don't need to process
|
||||||
|
// escape sequences, so the size is just the number
|
||||||
|
// of remaining characters, plus 1 for the null terminator.
|
||||||
|
return (end - start + 1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we have a non-raw string and we need to
|
||||||
|
// process escape sequences.
|
||||||
|
int length = 0;
|
||||||
|
boolean escaping = false;
|
||||||
|
for (; start <= end; ++start) {
|
||||||
|
if (escaping) {
|
||||||
|
escaping = false;
|
||||||
|
++length;
|
||||||
|
} else if (value[start] == '\\') {
|
||||||
|
escaping = true;
|
||||||
|
} else {
|
||||||
|
++length;
|
||||||
}
|
}
|
||||||
|
// TODO: Handle fancier things like octal literals.
|
||||||
|
}
|
||||||
|
|
||||||
|
// + 1 for null terminator.
|
||||||
|
return length + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IValue getStringLiteralSize() {
|
||||||
|
if (fStringLiteralSize == -1) {
|
||||||
|
fStringLiteralSize = computeStringLiteralSize();
|
||||||
}
|
}
|
||||||
return Value.create(length);
|
return Value.create(fStringLiteralSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Kind getCharType() {
|
private Kind getCharType() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue