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

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

View file

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

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

View file

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