diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java index ad038861148..eac964f5857 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/scanner/PreprocessorTests.java @@ -1334,4 +1334,30 @@ public class PreprocessorTests extends PreprocessorTestsBase { validateEOF(); validateProblemCount(0); } + + // #define BIN 0b10101010 + // #define HEX 0xAA + // #define OCT 0252 + // #define DEC 170 + // #if (BIN == HEX && HEX == OCT && OCT == DEC) + // int foo = BIN; + // #endif + public void testGCC43BinaryNumbers() throws Exception { + initializeScanner(); + validateToken(IToken.t_int); + validateIdentifier("foo"); + validateToken(IToken.tASSIGN); + validateInteger("0b10101010"); + validateToken(IToken.tSEMI); + validateEOF(); + validateProblemCount(0); + + String badbinary = "{0b012, 0b01b, 0b1111e01, 0b1111p10, 0b10010.10010}"; + initializeScanner(badbinary); + fullyTokenize(); + validateProblemCount(5); + for (int i = 0; i < 5; i++) { + validateProblem(i, IProblem.SCANNER_BAD_BINARY_FORMAT, null); + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java index f2fa958cdac..5d252cef56e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java @@ -640,6 +640,12 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { final char[] image= number.getCharImage(); boolean hasExponent = false; + // Integer constants written in binary are a non-standard extension + // supported by GCC since 4.3 and by some other C compilers + // They consist of a prefix 0b or 0B, followed by a sequence of 0 and 1 digits + // see http://gcc.gnu.org/onlinedocs/gcc/Binary-constants.html + boolean isBin = false; + boolean isHex = false; boolean isOctal = false; boolean hasDot= false; @@ -648,6 +654,11 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { if (image.length > 1) { if (image[0] == '0') { switch (image[++pos]) { + case 'b': + case 'B': + isBin = true; + ++pos; + break; case 'x': case 'X': isHex = true; @@ -665,6 +676,16 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } loop: for (; pos < image.length; pos++) { + if (isBin) { + switch (image[pos]) { + case '0': case'1': + continue; + default: + // 0 and 1 are the only allowed digits for binary integers + // No floating point, exponents etc. are allowed + break loop; + } + } switch (image[pos]) { // octal digits case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': @@ -743,7 +764,12 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { continue loop; } } - if (isFloat) { + if (isBin) { + // The check for bin has to come before float, otherwise binary integers + // with float components get flagged as BAD_FLOATING_POINT + handleProblem(IProblem.SCANNER_BAD_BINARY_FORMAT, image, number.getOffset(), number.getEndOffset()); + } + else if (isFloat) { handleProblem(IProblem.SCANNER_BAD_FLOATING_POINT, image, number.getOffset(), number.getEndOffset()); } else if (isHex) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java index 614c5281f8f..7bf2a887c94 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/ExpressionEvaluator.java @@ -332,6 +332,13 @@ class ExpressionEvaluator { } private long getNumber(char[] image) throws EvalException { + + // Integer constants written in binary are a non-standard extension + // supported by GCC since 4.3 and by some other C compilers + // They consist of a prefix 0b or 0B, followed by a sequence of 0 and 1 digits + // see http://gcc.gnu.org/onlinedocs/gcc/Binary-constants.html + boolean isBin = false; + boolean isHex = false; boolean isOctal = false; @@ -339,6 +346,11 @@ class ExpressionEvaluator { if (image.length > 1) { if (image[0] == '0') { switch (image[++pos]) { + case 'b': + case 'B': + isBin = true; + ++pos; + break; case 'x': case 'X': isHex = true; @@ -351,6 +363,9 @@ class ExpressionEvaluator { } } } + if (isBin) { + return getNumber(image, 2, image.length, 2, IProblem.SCANNER_BAD_BINARY_FORMAT); + } if (isHex) { return getNumber(image, 2, image.length, 16, IProblem.SCANNER_BAD_HEX_FORMAT); }