summaryrefslogtreecommitdiffstats
path: root/clang/AST/SemaExpr.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2007-05-21 01:08:44 +0000
committerChris Lattner <sabre@nondot.org>2007-05-21 01:08:44 +0000
commit67ca9252f80339a8875eebb2fb8ef6ca94df8ecc (patch)
treeb8ba76289353b04559fe09ab5fe88e0c2a946b28 /clang/AST/SemaExpr.cpp
parent4dc8a6f1e7329af0df3a77cf58376bdc8b6018de (diff)
downloadbcm5719-llvm-67ca9252f80339a8875eebb2fb8ef6ca94df8ecc.tar.gz
bcm5719-llvm-67ca9252f80339a8875eebb2fb8ef6ca94df8ecc.zip
Implement Sema::ParseNumericConstant for integer constants in terms of APInt
and correctly in terms of C99 6.4.4.1p5. llvm-svn: 39473
Diffstat (limited to 'clang/AST/SemaExpr.cpp')
-rw-r--r--clang/AST/SemaExpr.cpp98
1 files changed, 77 insertions, 21 deletions
diff --git a/clang/AST/SemaExpr.cpp b/clang/AST/SemaExpr.cpp
index 67aa839c122..fc05189d23d 100644
--- a/clang/AST/SemaExpr.cpp
+++ b/clang/AST/SemaExpr.cpp
@@ -117,42 +117,98 @@ Action::ExprResult Sema::ParseNumericConstant(const LexerToken &Tok) {
// cannot have a trigraph, escaped newline, radix prefix, or type suffix.
if (Tok.getLength() == 1) {
const char *t = PP.getSourceManager().getCharacterData(Tok.getLocation());
- return ExprResult(new IntegerLiteral(*t-'0', Context.IntTy,
+
+ unsigned IntSize = Context.Target.getIntWidth(Tok.getLocation());
+ return ExprResult(new IntegerLiteral(APInt(IntSize, *t-'0'), Context.IntTy,
Tok.getLocation()));
}
SmallString<512> IntegerBuffer;
IntegerBuffer.resize(Tok.getLength());
const char *ThisTokBegin = &IntegerBuffer[0];
- // Get the spelling of the token, which eliminates trigraphs, etc. Notes:
- // - We know that ThisTokBuf points to a buffer that is big enough for the
- // whole token and 'spelled' tokens can only shrink.
- // - In practice, the local buffer is only used when the spelling doesn't
- // match the original token (which is rare). The common case simply returns
- // a pointer to a *constant* buffer (avoiding a copy).
-
+ // Get the spelling of the token, which eliminates trigraphs, etc.
unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
Tok.getLocation(), PP);
if (Literal.hadError)
return ExprResult(true);
-
+
if (Literal.isIntegerLiteral()) {
QualType t;
- if (Literal.hasSuffix()) {
- if (Literal.isLong)
- t = Literal.isUnsigned ? Context.UnsignedLongTy : Context.LongTy;
- else if (Literal.isLongLong)
- t = Literal.isUnsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
- else
- t = Context.UnsignedIntTy;
+
+ // Get the value in the widest-possible width.
+ APInt ResultVal(Context.Target.getIntMaxTWidth(Tok.getLocation()), 0);
+
+ if (Literal.GetIntegerValue(ResultVal)) {
+ // If this value didn't fit into uintmax_t, warn and force to ull.
+ Diag(Tok.getLocation(), diag::warn_integer_too_large);
+ t = Context.UnsignedLongLongTy;
+ assert(Context.getIntegerBitwidth(t, Tok.getLocation()) ==
+ ResultVal.getBitWidth() && "long long is not intmax_t?");
} else {
- t = Context.IntTy; // implicit type is "int"
+ // If this value fits into a ULL, try to figure out what else it fits into
+ // according to the rules of C99 6.4.4.1p5.
+
+ // Octal, Hexadecimal, and integers with a U suffix are allowed to
+ // be an unsigned int.
+ bool AllowUnsigned = Literal.isUnsigned || Literal.getRadix() != 10;
+
+ // Check from smallest to largest, picking the smallest type we can.
+ if (!Literal.isLong) { // Are int/unsigned possibilities?
+ unsigned IntSize = Context.Target.getIntWidth(Tok.getLocation());
+ // Does it fit in a unsigned int?
+ if (ResultVal.isIntN(IntSize)) {
+ // Does it fit in a signed int?
+ if (!Literal.isUnsigned && ResultVal[IntSize-1] == 0)
+ t = Context.IntTy;
+ else if (AllowUnsigned)
+ t = Context.UnsignedIntTy;
+ }
+
+ if (!t.isNull())
+ ResultVal.trunc(IntSize);
+ }
+
+ // Are long/unsigned long possibilities?
+ if (t.isNull() && !Literal.isLongLong) {
+ unsigned LongSize = Context.Target.getLongWidth(Tok.getLocation());
+
+ // Does it fit in a unsigned long?
+ if (ResultVal.isIntN(LongSize)) {
+ // Does it fit in a signed long?
+ if (!Literal.isUnsigned && ResultVal[LongSize-1] == 0)
+ t = Context.LongTy;
+ else if (AllowUnsigned)
+ t = Context.UnsignedLongTy;
+ }
+ if (!t.isNull())
+ ResultVal.trunc(LongSize);
+ }
+
+ // Finally, check long long if needed.
+ if (t.isNull()) {
+ unsigned LongLongSize =
+ Context.Target.getLongLongWidth(Tok.getLocation());
+
+ // Does it fit in a unsigned long long?
+ if (ResultVal.isIntN(LongLongSize)) {
+ // Does it fit in a signed long long?
+ if (!Literal.isUnsigned && ResultVal[LongLongSize-1] == 0)
+ t = Context.LongLongTy;
+ else if (AllowUnsigned)
+ t = Context.UnsignedLongLongTy;
+ }
+ }
+
+ // If we still couldn't decide a type, we probably have something that
+ // does not fit in a signed long long, but has no U suffix.
+ if (t.isNull()) {
+ Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed);
+ t = Context.UnsignedLongLongTy;
+ }
}
- uintmax_t val;
- if (Literal.GetIntegerValue(val)) {
- return new IntegerLiteral(val, t, Tok.getLocation());
- }
+
+ return new IntegerLiteral(ResultVal, t, Tok.getLocation());
} else if (Literal.isFloatingLiteral()) {
// FIXME: fill in the value and compute the real type...
return new FloatingLiteral(7.7, Context.FloatTy, Tok.getLocation());
OpenPOWER on IntegriCloud