blob: 1fea9440cd58767491e3f8230e5960cf40f4a502 [file] [log] [blame]
Steve Naroff09ef4742007-03-09 23:16:33 +00001//===--- LiteralSupport.cpp - Code to parse and process literals-*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Steve Naroff and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the NumericLiteralParser interface.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Lex/LiteralSupport.h"
15#include "clang/Lex/Preprocessor.h"
16#include "clang/Basic/TargetInfo.h"
17#include "clang/Basic/Diagnostic.h"
18
19using namespace llvm;
20using namespace clang;
21
22/// integer-constant: [C99 6.4.4.1]
23/// decimal-constant integer-suffix
24/// octal-constant integer-suffix
25/// hexadecimal-constant integer-suffix
26/// decimal-constant:
27/// nonzero-digit
28/// decimal-constant digit
29/// octal-constant:
30/// 0
31/// octal-constant octal-digit
32/// hexadecimal-constant:
33/// hexadecimal-prefix hexadecimal-digit
34/// hexadecimal-constant hexadecimal-digit
35/// hexadecimal-prefix: one of
36/// 0x 0X
37/// integer-suffix:
38/// unsigned-suffix [long-suffix]
39/// unsigned-suffix [long-long-suffix]
40/// long-suffix [unsigned-suffix]
41/// long-long-suffix [unsigned-sufix]
42/// nonzero-digit:
43/// 1 2 3 4 5 6 7 8 9
44/// octal-digit:
45/// 0 1 2 3 4 5 6 7
46/// hexadecimal-digit:
47/// 0 1 2 3 4 5 6 7 8 9
48/// a b c d e f
49/// A B C D E F
50/// unsigned-suffix: one of
51/// u U
52/// long-suffix: one of
53/// l L
54/// long-long-suffix: one of
55/// ll LL
56///
57/// floating-constant: [C99 6.4.4.2]
58/// TODO: add rules...
59///
60
61NumericLiteralParser::
62NumericLiteralParser(const char *begin, const char *end,
Steve Naroff451d8f162007-03-12 23:22:38 +000063 SourceLocation TokLoc, Preprocessor &pp) :
64 PP(pp), ThisTokBegin(begin), ThisTokEnd(end)
Steve Naroff09ef4742007-03-09 23:16:33 +000065{
66 s = DigitsBegin = begin;
67 saw_exponent = false;
68 saw_period = false;
69 saw_float_suffix = false;
70 isLong = false;
71 isUnsigned = false;
72 isLongLong = false;
73 hadError = false;
74
75 if (*s == '0') { // parse radix
76 s++;
77 if ((*s == 'x' || *s == 'X') && (isxdigit(s[1]) || s[1] == '.')) {
78 s++;
79 radix = 16;
80 DigitsBegin = s;
81 s = SkipHexDigits(s);
82 if (s == ThisTokEnd) {
83 } else if (*s == '.') {
84 s++;
85 saw_period = true;
86 s = SkipHexDigits(s);
87 }
88 // A binary exponent can appear with or with a '.'. If dotted, the
89 // binary exponent is required.
90 if (*s == 'p' || *s == 'P') {
91 s++;
92 saw_exponent = true;
93 if (*s == '+' || *s == '-') s++; // sign
94 const char *first_non_digit = SkipDigits(s);
95 if (first_non_digit == s) {
96 Diag(TokLoc, diag::err_exponent_has_no_digits);
97 return;
98 } else {
99 s = first_non_digit;
100 }
101 } else if (saw_period) {
102 Diag(TokLoc, diag::err_hexconstant_requires_exponent);
103 return;
104 }
105 } else {
106 // For now, the radix is set to 8. If we discover that we have a
107 // floating point constant, the radix will change to 10. Octal floating
108 // point constants are not permitted (only decimal and hexadecimal).
109 radix = 8;
110 DigitsBegin = s;
111 s = SkipOctalDigits(s);
112 if (s == ThisTokEnd) {
113 } else if (*s == '.') {
114 s++;
115 radix = 10;
116 saw_period = true;
117 s = SkipDigits(s);
118 }
119 if (*s == 'e' || *s == 'E') { // exponent
120 s++;
121 radix = 10;
122 saw_exponent = true;
123 if (*s == '+' || *s == '-') s++; // sign
124 const char *first_non_digit = SkipDigits(s);
125 if (first_non_digit == s) {
126 Diag(TokLoc, diag::err_exponent_has_no_digits);
127 return;
128 } else {
129 s = first_non_digit;
130 }
131 }
132 }
133 } else { // the first digit is non-zero
134 radix = 10;
135 s = SkipDigits(s);
136 if (s == ThisTokEnd) {
137 } else if (*s == '.') {
138 s++;
139 saw_period = true;
140 s = SkipDigits(s);
141 }
142 if (*s == 'e' || *s == 'E') { // exponent
143 s++;
144 saw_exponent = true;
145 if (*s == '+' || *s == '-') s++; // sign
146 const char *first_non_digit = SkipDigits(s);
147 if (first_non_digit == s) {
148 Diag(TokLoc, diag::err_exponent_has_no_digits);
149 return;
150 } else {
151 s = first_non_digit;
152 }
153 }
154 }
155
156 SuffixBegin = s;
157
158 if (saw_period || saw_exponent) {
159 if (s < ThisTokEnd) { // parse size suffix (float, long double)
160 if (*s == 'f' || *s == 'F') {
161 saw_float_suffix = true;
162 s++;
163 } else if (*s == 'l' || *s == 'L') {
164 isLong = true;
165 s++;
166 }
167 if (s != ThisTokEnd) {
168 Diag(TokLoc, diag::err_invalid_suffix_float_constant,
169 std::string(SuffixBegin, ThisTokEnd));
170 return;
171 }
172 }
173 } else {
174 if (s < ThisTokEnd) {
175 // parse int suffix - they can appear in any order ("ul", "lu", "llu").
176 if (*s == 'u' || *s == 'U') {
177 s++;
178 isUnsigned = true; // unsigned
179
180 if ((s < ThisTokEnd) && (*s == 'l' || *s == 'L')) {
181 s++;
182 // handle "long long" type - l's need to be adjacent and same case.
183 if ((s < ThisTokEnd) && (*s == *(s-1))) {
184 isLongLong = true; // unsigned long long
185 s++;
186 } else {
187 isLong = true; // unsigned long
188 }
189 }
190 } else if (*s == 'l' || *s == 'L') {
191 s++;
192 // handle "long long" types - l's need to be adjacent and same case.
193 if ((s < ThisTokEnd) && (*s == *(s-1))) {
194 s++;
195 if ((s < ThisTokEnd) && (*s == 'u' || *s == 'U')) {
196 isUnsigned = true; // unsigned long long
197 s++;
198 } else {
199 isLongLong = true; // long long
200 }
201 } else { // handle "long" types
202 if ((s < ThisTokEnd) && (*s == 'u' || *s == 'U')) {
203 isUnsigned = true; // unsigned long
204 s++;
205 } else {
206 isLong = true; // long
207 }
208 }
209 }
210 if (s != ThisTokEnd) {
211 Diag(TokLoc, diag::err_invalid_suffix_integer_constant,
212 std::string(SuffixBegin, ThisTokEnd));
213 return;
214 }
215 }
216 }
217}
218
Steve Naroff451d8f162007-03-12 23:22:38 +0000219bool NumericLiteralParser::GetIntegerValue(uintmax_t &val) {
Steve Narofff2fb89e2007-03-13 20:29:44 +0000220 uintmax_t max_value = UINTMAX_MAX / radix;
221 int max_digit = UINTMAX_MAX % radix;
Steve Naroff09ef4742007-03-09 23:16:33 +0000222 char c;
223
224 val = 0;
Steve Naroff451d8f162007-03-12 23:22:38 +0000225 s = DigitsBegin;
226 while (s < SuffixBegin) {
227 c = *s++;
228 if (c >= '0' && c <= '9')
229 c -= '0';
Steve Narofff2fb89e2007-03-13 20:29:44 +0000230 else if (c >= 'A' && c <= 'F')
231 c -= 'A' - 10;
232 else if (c >= 'a' && c <= 'f')
Steve Naroff451d8f162007-03-12 23:22:38 +0000233 c -= 'a' - 10;
234
Steve Narofff2fb89e2007-03-13 20:29:44 +0000235 if (val > max_value || (val == max_value && c > max_digit)) {
Steve Naroff451d8f162007-03-12 23:22:38 +0000236 return false; // Overflow!
237 } else {
238 val *= radix;
239 val += c;
240 }
241 }
242 return true;
243}
244
245bool NumericLiteralParser::GetIntegerValue(int &val) {
Steve Narofff2fb89e2007-03-13 20:29:44 +0000246 intmax_t max_value = INT_MAX / radix;
247 int max_digit = INT_MAX % radix;
Steve Naroff451d8f162007-03-12 23:22:38 +0000248 char c;
249
250 val = 0;
Steve Naroff09ef4742007-03-09 23:16:33 +0000251 s = DigitsBegin;
252 while (s < SuffixBegin) {
253 c = *s++;
254 if (c >= '0' && c <= '9')
255 c -= '0';
Steve Narofff2fb89e2007-03-13 20:29:44 +0000256 else if (c >= 'A' && c <= 'F')
Steve Naroff09ef4742007-03-09 23:16:33 +0000257 c -= 'A' - 10;
Steve Narofff2fb89e2007-03-13 20:29:44 +0000258 else if (c >= 'a' && c <= 'f')
Steve Naroff09ef4742007-03-09 23:16:33 +0000259 c -= 'a' - 10;
260
Steve Narofff2fb89e2007-03-13 20:29:44 +0000261 if (val > max_value || (val == max_value && c > max_digit)) {
Steve Naroff09ef4742007-03-09 23:16:33 +0000262 return false; // Overflow!
263 } else {
264 val *= radix;
265 val += c;
266 }
267 }
268 return true;
269}
Steve Narofff2fb89e2007-03-13 20:29:44 +0000270
271void NumericLiteralParser::Diag(SourceLocation Loc, unsigned DiagID,
272 const std::string &M) {
273 PP.Diag(Loc, DiagID, M);
274 hadError = true;
275}