diff --git a/clang/Parse/ParseExpr.cpp b/clang/Parse/ParseExpr.cpp index b2d51441db11..ef7b273961d8 100644 --- a/clang/Parse/ParseExpr.cpp +++ b/clang/Parse/ParseExpr.cpp @@ -473,13 +473,7 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) { // constant: integer-constant // constant: floating-constant - // TODO: Validate whether this is an integer or floating-constant or - // neither. - if (1) { - Res = Actions.ParseIntegerLiteral(Tok.getLocation()); - } else { - Res = Actions.ParseFloatingLiteral(Tok.getLocation()); - } + ParseNumericConstant(); ConsumeToken(); // These can be followed by postfix-expr pieces. @@ -931,3 +925,114 @@ Parser::ExprResult Parser::ParseStringLiteralExpression() { // Pass the set of string tokens, ready for concatenation, to the actions. return Actions.ParseStringLiteral(&StringToks[0], StringToks.size()); } + +/// integer-constant: [C99 6.4.4.1] +/// decimal-constant integer-suffix +/// octal-constant integer-suffix +/// hexidecimal-constant integer-suffix +/// decimal-constant: +/// nonzero-digit +/// decimal-constant digit +/// octal-constant: +/// 0 +/// octal-constant octal-digit +/// hexidecimal-constant: +/// hexidecimal-prefix hexidecimal-digit +/// hexidecimal-constant hexidecimal-digit +/// hexidecimal-prefix: one of +/// 0x 0X +/// integer-suffix: +/// unsigned-suffix [long-suffix] +/// unsigned-suffix [long-long-suffix] +/// long-suffix [unsigned-suffix] +/// long-long-suffix [unsigned-sufix] +/// nonzero-digit: +/// 1 2 3 4 5 6 7 8 9 +/// octal-digit: +/// 0 1 2 3 4 5 6 7 +/// hexadecimal-digit: +/// 0 1 2 3 4 5 6 7 8 9 +/// a b c d e f +/// A B C D E F +/// unsigned-suffix: one of +/// u U +/// long-suffix: one of +/// l L +/// long-long-suffix: one of +/// ll LL +/// +/// floating-constant: [C99 6.4.4.2] +/// +Parser::ExprResult Parser::ParseNumericConstant() { + 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). + + unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin); + ExprResult Res; + + if (ActualLength == 1) { + // need to change interface...just a placeholder + Res = Actions.ParseIntegerLiteral(Tok.getLocation()); + } else if (ActualLength > 1) { + const char *ThisTokEnd = ThisTokBegin+ActualLength; + const char *s = ThisTokBegin; + unsigned int radix; + + if (*s == '0') { // parse radix + s++; + if (*s == 'x' || *s == 'X') { + s++; + radix = 16; + while (s < ThisTokEnd && isxdigit(*s)) *s++; + } else { + radix = 8; + while (s < ThisTokEnd && ((*s >= '0') && (*s <= '7'))) *s++; + } + } else { // the first digit is non-zero + radix = 10; + while (s < ThisTokEnd && isdigit(*s)) *s++; + } + + if (*s == '.') { // TODO: Parse Floats... + Res = Actions.ParseFloatingLiteral(Tok.getLocation()); + } else { + int unsigned_cnt = 0, long_cnt = 0, invalid_suffix = 0; + + // if there is no suffix, this loop won't be executed (s == ThisTokEnd) + while (s < ThisTokEnd && !invalid_suffix) { + // parse type suffix - they can appear in any order "ul", "lu", "llu" + if (*s == 'u' || *s == 'U') { + unsigned_cnt++; + if (unsigned_cnt == 2) + invalid_suffix = 1; + else + s++; + } else if (*s == 'l' || *s == 'L') { + long_cnt++; + // l's need to be adjacent and the same case + if ((long_cnt == 2 && (*s != *(s-1))) || long_cnt == 3) + invalid_suffix = 1; + else + s++; + } else { + invalid_suffix = 1; + } + } + if (invalid_suffix) { + Diag(Tok, diag::err_invalid_suffix_integer_constant); + return ExprResult(true); + } else { + // need to change interface...just a placeholder + Res = Actions.ParseIntegerLiteral(Tok.getLocation()); + } + } + } +} diff --git a/clang/clang.xcodeproj/project.pbxproj b/clang/clang.xcodeproj/project.pbxproj index db7e5fd95654..cfbf8fe2290c 100644 --- a/clang/clang.xcodeproj/project.pbxproj +++ b/clang/clang.xcodeproj/project.pbxproj @@ -94,6 +94,23 @@ DED7D9E50A5257F6003AD0FB /* ScratchBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D9E40A5257F6003AD0FB /* ScratchBuffer.cpp */; }; /* End PBXBuildFile section */ +/* Begin PBXBuildStyle section */ + 842065AF0B98D65200CA7A69 /* Development */ = { + isa = PBXBuildStyle; + buildSettings = { + COPY_PHASE_STRIP = NO; + }; + name = Development; + }; + 842065B00B98D65200CA7A69 /* Deployment */ = { + isa = PBXBuildStyle; + buildSettings = { + COPY_PHASE_STRIP = YES; + }; + name = Deployment; + }; +/* End PBXBuildStyle section */ + /* Begin PBXCopyFilesBuildPhase section */ 8DD76F690486A84900D96B5E /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; @@ -476,12 +493,15 @@ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */; - compatibilityVersion = "Xcode 2.4"; + buildSettings = { + }; + buildStyles = ( + 842065AF0B98D65200CA7A69 /* Development */, + 842065B00B98D65200CA7A69 /* Deployment */, + ); hasScannedForEncodings = 1; mainGroup = 08FB7794FE84155DC02AAC07 /* clang */; projectDirPath = ""; - projectRoot = ""; - shouldCheckCompatibility = 1; targets = ( 8DD76F620486A84900D96B5E /* clang */, ); diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index 7d1437d1c798..ea3505bfc8f9 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -470,6 +470,8 @@ DIAG(err_sizeof_incomplete_type, ERROR, "invalid application of 'sizeof' to an incomplete type '%s'") DIAG(err_alignof_incomplete_type, ERROR, "invalid application of '__alignof' to an incomplete type '%s'") +DIAG(err_invalid_suffix_integer_constant, ERROR, + "invalid suffix on integer constant") // Statements. DIAG(err_continue_not_in_loop, ERROR, diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 2e4d654e0ff4..4cdf1ff74b87 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -291,6 +291,7 @@ private: return ParseParenExpression(Op, CastTy, RParenLoc); } ExprResult ParseStringLiteralExpression(); + ExprResult ParseNumericConstant(); //===--------------------------------------------------------------------===// // C++ 5.2p1: C++ Casts