aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-06-15 05:07:49 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-06-15 05:07:49 +0000
commitd2e95d1538ff91fe902464f02f83429f96117af5 (patch)
tree3cfb21b12e22e2576fdb70b1e8a070891344b563
parent0982205bade2fb4fc984c27b2ab401e683963b10 (diff)
PR12717: Clang supports hexadecimal floating-point literals in all language
modes. For languages other than C99/C11, this isn't quite a conforming extension, and for C++11, it breaks some reasonable code containing user-defined literals. In languages which don't officially have hexfloats, pare back this extension to only apply in cases where the token starts 0x and does not contain an underscore. The extension is still not quite conforming, but it's a lot closer now. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158487 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Lex/Lexer.cpp16
-rw-r--r--test/Lexer/c90.c7
-rw-r--r--test/Lexer/hexfloat.cpp8
3 files changed, 29 insertions, 2 deletions
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index 208951faf3..78d58d3a8c 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -1569,8 +1569,20 @@ void Lexer::LexNumericConstant(Token &Result, const char *CurPtr) {
}
// If we have a hex FP constant, continue.
- if ((C == '-' || C == '+') && (PrevCh == 'P' || PrevCh == 'p'))
- return LexNumericConstant(Result, ConsumeChar(CurPtr, Size, Result));
+ if ((C == '-' || C == '+') && (PrevCh == 'P' || PrevCh == 'p')) {
+ // Outside C99, we accept hexadecimal floating point numbers as a
+ // not-quite-conforming extension. Only do so if this looks like it's
+ // actually meant to be a hexfloat, and not if it has a ud-suffix.
+ bool IsHexFloat = true;
+ if (!LangOpts.C99) {
+ if (!isHexaLiteral(BufferPtr, LangOpts))
+ IsHexFloat = false;
+ else if (std::find(BufferPtr, CurPtr, '_') != CurPtr)
+ IsHexFloat = false;
+ }
+ if (IsHexFloat)
+ return LexNumericConstant(Result, ConsumeChar(CurPtr, Size, Result));
+ }
// Update the location of token as well as BufferPtr.
const char *TokStart = BufferPtr;
diff --git a/test/Lexer/c90.c b/test/Lexer/c90.c
index d91057257d..7142c09ac4 100644
--- a/test/Lexer/c90.c
+++ b/test/Lexer/c90.c
@@ -32,3 +32,10 @@ void test3() {
(void)L"\u1234"; // expected-error {{unicode escape sequences are only valid in C99 or C++}}
(void)L'\u1234'; // expected-error {{unicode escape sequences are only valid in C99 or C++}}
}
+
+#define PREFIX(x) foo ## x
+int test4() {
+ int PREFIX(0p) = 0;
+ int *p = &PREFIX(0p+1);
+ return p[-1];
+}
diff --git a/test/Lexer/hexfloat.cpp b/test/Lexer/hexfloat.cpp
index 656693399f..9bd8f830f0 100644
--- a/test/Lexer/hexfloat.cpp
+++ b/test/Lexer/hexfloat.cpp
@@ -5,3 +5,11 @@ double e = 0x.p0; //expected-error{{hexadecimal floating constants require a sig
double d = 0x.2p2; // expected-warning{{hexadecimal floating constants are a C99 feature}}
float g = 0x1.2p2; // expected-warning{{hexadecimal floating constants are a C99 feature}}
double h = 0x1.p2; // expected-warning{{hexadecimal floating constants are a C99 feature}}
+
+// PR12717: In order to minimally diverge from the C++ standard, we do not lex
+// 'p[+-]' as part of a pp-number unless the token starts 0x and doesn't contain
+// an underscore.
+double i = 0p+3; // expected-error{{invalid suffix 'p' on integer constant}}
+#define PREFIX(x) foo ## x
+double foo0p = 1, j = PREFIX(0p+3); // ok
+double k = 0x42_amp+3; // expected-error-re{{invalid suffix '_amp' on integer constant|no matching literal operator for call to 'operator "" _amp'}}