[cfe-commits] r39473 - in /cfe/cfe/trunk: AST/SemaExpr.cpp Lex/LiteralSupport.cpp Sema/SemaExpr.cpp clang.xcodeproj/project.pbxproj include/clang/AST/Expr.h include/clang/Lex/LiteralSupport.h
clattner at cs.uiuc.edu
clattner at cs.uiuc.edu
Wed Jul 11 09:44:46 PDT 2007
Author: clattner
Date: Wed Jul 11 11:44:46 2007
New Revision: 39473
URL: http://llvm.org/viewvc/llvm-project?rev=39473&view=rev
Log:
Implement Sema::ParseNumericConstant for integer constants in terms of APInt
and correctly in terms of C99 6.4.4.1p5.
Modified:
cfe/cfe/trunk/AST/SemaExpr.cpp
cfe/cfe/trunk/Lex/LiteralSupport.cpp
cfe/cfe/trunk/Sema/SemaExpr.cpp
cfe/cfe/trunk/clang.xcodeproj/project.pbxproj
cfe/cfe/trunk/include/clang/AST/Expr.h
cfe/cfe/trunk/include/clang/Lex/LiteralSupport.h
Modified: cfe/cfe/trunk/AST/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/SemaExpr.cpp?rev=39473&r1=39472&r2=39473&view=diff
==============================================================================
--- cfe/cfe/trunk/AST/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/AST/SemaExpr.cpp Wed Jul 11 11:44:46 2007
@@ -117,42 +117,98 @@
// 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());
Modified: cfe/cfe/trunk/Lex/LiteralSupport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/LiteralSupport.cpp?rev=39473&r1=39472&r2=39473&view=diff
==============================================================================
--- cfe/cfe/trunk/Lex/LiteralSupport.cpp (original)
+++ cfe/cfe/trunk/Lex/LiteralSupport.cpp Wed Jul 11 11:44:46 2007
@@ -351,44 +351,6 @@
}
}
-bool NumericLiteralParser::GetIntegerValue(uintmax_t &val) {
- uintmax_t max_value = UINTMAX_MAX / radix;
- unsigned max_digit = UINTMAX_MAX % radix;
-
- val = 0;
- s = DigitsBegin;
- while (s < SuffixBegin) {
- unsigned C = HexDigitValue(*s++);
-
- if (val > max_value || (val == max_value && C > max_digit)) {
- return false; // Overflow!
- } else {
- val *= radix;
- val += C;
- }
- }
- return true;
-}
-
-bool NumericLiteralParser::GetIntegerValue(int &val) {
- intmax_t max_value = INT_MAX / radix;
- unsigned max_digit = INT_MAX % radix;
-
- val = 0;
- s = DigitsBegin;
- while (s < SuffixBegin) {
- unsigned C = HexDigitValue(*s++);
-
- if (val > max_value || (val == max_value && C > max_digit)) {
- return false; // Overflow!
- } else {
- val *= radix;
- val += C;
- }
- }
- return true;
-}
-
/// GetIntegerValue - Convert this numeric literal value to an APInt that
/// matches Val's input width. If there is an overflow, set Val to the low bits
/// of the result and return true. Otherwise, return false.
Modified: cfe/cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaExpr.cpp?rev=39473&r1=39472&r2=39473&view=diff
==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:44:46 2007
@@ -117,42 +117,98 @@
// 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());
Modified: cfe/cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=39473&r1=39472&r2=39473&view=diff
==============================================================================
--- cfe/cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/cfe/trunk/clang.xcodeproj/project.pbxproj Wed Jul 11 11:44:46 2007
@@ -94,23 +94,6 @@
DED7D9E50A5257F6003AD0FB /* ScratchBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D9E40A5257F6003AD0FB /* ScratchBuffer.cpp */; };
/* End PBXBuildFile section */
-/* Begin PBXBuildStyle section */
- 84DE4C220BFFB2D9009E9268 /* Development */ = {
- isa = PBXBuildStyle;
- buildSettings = {
- COPY_PHASE_STRIP = NO;
- };
- name = Development;
- };
- 84DE4C230BFFB2D9009E9268 /* Deployment */ = {
- isa = PBXBuildStyle;
- buildSettings = {
- COPY_PHASE_STRIP = YES;
- };
- name = Deployment;
- };
-/* End PBXBuildStyle section */
-
/* Begin PBXCopyFilesBuildPhase section */
8DD76F690486A84900D96B5E /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
@@ -493,12 +476,6 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
- buildSettings = {
- };
- buildStyles = (
- 84DE4C220BFFB2D9009E9268 /* Development */,
- 84DE4C230BFFB2D9009E9268 /* Deployment */,
- );
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
projectDirPath = "";
Modified: cfe/cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Expr.h?rev=39473&r1=39472&r2=39473&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Expr.h Wed Jul 11 11:44:46 2007
@@ -17,6 +17,7 @@
#include "clang/AST/Stmt.h"
#include "clang/AST/Type.h"
#include "clang/AST/Decl.h"
+#include "llvm/ADT/APInt.h"
namespace llvm {
namespace clang {
@@ -102,16 +103,16 @@
};
class IntegerLiteral : public Expr {
- intmax_t Value;
+ APInt Value;
SourceLocation Loc;
public:
// type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy,
// or UnsignedLongLongTy
- IntegerLiteral(intmax_t value, QualType type, SourceLocation l)
- : Expr(IntegerLiteralClass, type), Value(value), Loc(l) {
+ IntegerLiteral(const APInt &V, QualType type, SourceLocation l)
+ : Expr(IntegerLiteralClass, type), Value(V), Loc(l) {
assert(type->isIntegerType() && "Illegal type in IntegerLiteral");
}
- intmax_t getValue() const { return Value; }
+ const APInt &getValue() const { return Value; }
virtual SourceRange getSourceRange() const { return SourceRange(Loc); }
virtual void visit(StmtVisitor &Visitor);
Modified: cfe/cfe/trunk/include/clang/Lex/LiteralSupport.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Lex/LiteralSupport.h?rev=39473&r1=39472&r2=39473&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/LiteralSupport.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/LiteralSupport.h Wed Jul 11 11:44:46 2007
@@ -39,7 +39,7 @@
const char *DigitsBegin, *SuffixBegin; // markers
const char *s; // cursor
- unsigned int radix;
+ unsigned radix;
bool saw_exponent, saw_period;
bool saw_float_suffix;
@@ -49,7 +49,7 @@
SourceLocation Loc, Preprocessor &PP);
bool hadError;
bool isUnsigned;
- bool isLong;
+ bool isLong; // This is also set for long long.
bool isLongLong;
bool isIntegerLiteral() const {
@@ -61,19 +61,12 @@
bool hasSuffix() const {
return SuffixBegin != ThisTokEnd;
}
- /// getIntegerValue - Convert the string into a number. At this point, we
- /// know the digit characters are valid (0...9, a...f, A...F). We don't know
- /// how many bits are needed to store the number. Sizing of the integer
- /// type (int, unsigned, long, unsigned long, long long, unsigned long long)
- /// will be done elsewhere - the size computation is target dependent. We
- /// return true if the value fit into "val", false otherwise.
- /// NOTE: The api of these returns an inverted value for 'overflow' than the
- /// version below does.
- bool GetIntegerValue(uintmax_t &val);
- bool GetIntegerValue(int &val);
+
+ unsigned getRadix() const { return radix; }
/// GetIntegerValue - Convert this numeric literal value to an APInt that
- /// matches Val's input width. If there is an overflow, set Val to the low
+ /// matches Val's input width. If there is an overflow (i.e., if the unsigned
+ /// value read is larger than the APInt's bits will hold), set Val to the low
/// bits of the result and return true. Otherwise, return false.
bool GetIntegerValue(APInt &Val);
More information about the cfe-commits
mailing list