1
0
Fork 0
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:
Nathan Ridge 2015-02-06 02:52:31 -05:00
parent f7cf56f4c5
commit 34c84eba3c
4 changed files with 90 additions and 35 deletions

View file

@ -9063,6 +9063,13 @@ public class AST2CPPTests extends AST2TestBase {
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 {
// char a[100];
// };
@ -10666,7 +10673,7 @@ public class AST2CPPTests extends AST2TestBase {
public void testIsBaseOf_409100() throws Exception {
BindingAssertionHelper b = getAssertionHelper();
IVariable var = b.assertNonProblem("value");
assertEquals(1 /*true */, var.getInitialValue().numericalValue().longValue());
assertConstantValue(1 /*true */, var);
}
// namespace NS {
@ -10982,7 +10989,7 @@ public class AST2CPPTests extends AST2TestBase {
public void testConditionalExpressionFolding_429891() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();
IVariable waldo = helper.assertNonProblem("waldo");
assertEquals(5, waldo.getInitialValue().numericalValue().longValue());
assertConstantValue(5, waldo);
}
// constexpr int naive_fibonacci(int x) {
@ -11009,7 +11016,7 @@ public class AST2CPPTests extends AST2TestBase {
public void testNameLookupInDefaultArgument_432701() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();
IVariable waldo = helper.assertNonProblem("waldo");
assertEquals(42, waldo.getInitialValue().numericalValue().longValue());
assertConstantValue(42, waldo);
}
// struct S1 { S1(int); };

View file

@ -3071,7 +3071,7 @@ public class AST2TemplateTests extends AST2TestBase {
ICPPVariable _256= ba.assertNonProblem("_256=0x100", 4, ICPPVariable.class);
IQualifierType qt1= assertInstance(_256.getType(), IQualifierType.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);
ICPPTemplateInstance ci1= assertInstance(t.getType(), ICPPTemplateInstance.class, ICPPClassType.class);
@ -7390,9 +7390,7 @@ public class AST2TemplateTests extends AST2TestBase {
public void testSfinaeInNestedTypeInTemplateArgument_402257() throws Exception {
BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true);
ICPPVariable B = helper.assertNonProblem("B");
Long val = B.getInitialValue().numericalValue();
assertNotNull(val);
assertEquals(0 /* false */, val.longValue());
assertConstantValue(0 /* false */, B);
}
// struct S {
@ -8038,9 +8036,7 @@ public class AST2TemplateTests extends AST2TestBase {
public void testSizeofParameterPackOnTypeid_401973() throws Exception {
BindingAssertionHelper helper = new BindingAssertionHelper(getAboveComment(), true);
ICPPVariable bar = helper.assertNonProblem("bar");
Long barValue = bar.getInitialValue().numericalValue();
assertNotNull(barValue);
assertEquals(2, barValue.longValue());
assertConstantValue(2, bar);
}
// template <int...> struct tuple_indices {};
@ -8573,7 +8569,7 @@ public class AST2TemplateTests extends AST2TestBase {
public void testSpecializationOfConstexprFunction_420995() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();
ICPPVariable waldo = helper.assertNonProblem("waldo");
assertEquals(2, waldo.getInitialValue().numericalValue().longValue());
assertConstantValue(2, waldo);
}
// struct Test {

View file

@ -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.IProblemBinding;
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.c.ICASTTypeIdInitializerExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
@ -494,6 +495,14 @@ public class AST2TestBase extends BaseTestCase {
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 IASTTranslationUnit tu;
protected String contents;

View file

@ -42,6 +42,7 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
private int kind;
private char[] value = CharArrayUtils.EMPTY;
private int fStringLiteralSize = -1; // accounting for escape sequences and the null terminator
private ICPPEvaluation fEvaluation;
public CPPASTLiteralExpression() {
@ -110,31 +111,73 @@ public class CPPASTLiteralExpression extends ASTNode implements ICPPASTLiteralEx
return true;
}
private IValue getStringLiteralSize() {
char[] value= getValue();
int length= value.length-1;
private int computeStringLiteralSize() {
int start = 0, end = value.length - 1;
boolean isRaw = false;
for (int i = 0; i < length; i++) {
final char c = value[i];
if (c == '"') {
if (isRaw) {
for (int j = i + 1; j < length; j++) {
final char d= value[j];
if (d == '(') {
length -= 2*(j-i);
break;
// Skip past a prefix affecting the character type.
if (value[0] == 'L' || value[0] == 'u' || value[0] == 'U') {
++start;
}
}
}
length -= i;
if (length < 0)
length = 0;
break;
} else if (c == 'R') {
// If there is an 'R' prefix, skip past it but take note of it.
if (value[start] == 'R') {
++start;
isRaw = true;
}
// Now we should have a quote-enclosed string. Skip past the quotes.
if (!(value[start] == '"' && value[end] == '"')) {
// Unexpected!
return 0;
}
return Value.create(length);
++start;
--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(fStringLiteralSize);
}
private Kind getCharType() {