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
|
@ -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); };
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Add table
Reference in a new issue