diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-08 08:45:32 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-08 08:45:32 +0000 |
commit | b453ad3214d00acc51c9aa702c76c58354d84b84 (patch) | |
tree | fbf7b0f3c7bf20b921b60a43a544a87c8968cc05 /lib/Sema/SemaExpr.cpp | |
parent | aae1d8bd6f2482e0bf13a29d5b0cb7639080974d (diff) |
Add support for cooked forms of user-defined-integer-literal and
user-defined-floating-literal. Support for raw forms of these literals
to follow.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152302 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExpr.cpp')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 95 |
1 files changed, 67 insertions, 28 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index f82ff4395d..c1ce02eeea 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2437,6 +2437,38 @@ ExprResult Sema::ActOnIntegerConstant(SourceLocation Loc, uint64_t Val) { Context.IntTy, Loc)); } +static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal, + QualType Ty, SourceLocation Loc) { + const llvm::fltSemantics &Format = S.Context.getFloatTypeSemantics(Ty); + + using llvm::APFloat; + APFloat Val(Format); + + APFloat::opStatus result = Literal.GetFloatValue(Val); + + // Overflow is always an error, but underflow is only an error if + // we underflowed to zero (APFloat reports denormals as underflow). + if ((result & APFloat::opOverflow) || + ((result & APFloat::opUnderflow) && Val.isZero())) { + unsigned diagnostic; + SmallString<20> buffer; + if (result & APFloat::opOverflow) { + diagnostic = diag::warn_float_overflow; + APFloat::getLargest(Format).toString(buffer); + } else { + diagnostic = diag::warn_float_underflow; + APFloat::getSmallest(Format).toString(buffer); + } + + S.Diag(Loc, diagnostic) + << Ty + << StringRef(buffer.data(), buffer.size()); + } + + bool isExact = (result == APFloat::opOK); + return FloatingLiteral::Create(S.Context, Val, isExact, Ty, Loc); +} + ExprResult Sema::ActOnNumericConstant(const Token &Tok) { // Fast path for a single digit (which is quite common). A single digit // cannot have a trigraph, escaped newline, radix prefix, or type suffix. @@ -2461,6 +2493,40 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok) { if (Literal.hadError) return ExprError(); + if (Literal.hasUDSuffix()) { + // We're building a user-defined literal. + IdentifierInfo *UDSuffix = &Context.Idents.get(Literal.getUDSuffix()); + SourceLocation UDSuffixLoc = + getUDSuffixLoc(*this, Tok.getLocation(), Literal.getUDSuffixOffset()); + + // FIXME: Perform literal operator lookup now, and build a raw literal if + // there is no usable operator. + + QualType Ty; + Expr *Lit; + if (Literal.isFloatingLiteral()) { + // C++11 [lex.ext]p4: If S contains a literal operator with parameter type + // long double, the literal is treated as a call of the form + // operator "" X (f L) + Lit = BuildFloatingLiteral(*this, Literal, Context.LongDoubleTy, + Tok.getLocation()); + } else { + // C++11 [lex.ext]p3: If S contains a literal operator with parameter type + // unsigned long long, the literal is treated as a call of the form + // operator "" X (n ULL) + llvm::APInt ResultVal(Context.getTargetInfo().getLongLongWidth(), 0); + if (Literal.GetIntegerValue(ResultVal)) + Diag(Tok.getLocation(), diag::warn_integer_too_large); + + QualType Ty = Context.UnsignedLongLongTy; + Lit = IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation()); + } + + return BuildLiteralOperatorCall(UDSuffix, UDSuffixLoc, + llvm::makeArrayRef(&Lit, 1), + Tok.getLocation()); + } + Expr *Res; if (Literal.isFloatingLiteral()) { @@ -2472,34 +2538,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok) { else Ty = Context.LongDoubleTy; - const llvm::fltSemantics &Format = Context.getFloatTypeSemantics(Ty); - - using llvm::APFloat; - APFloat Val(Format); - - APFloat::opStatus result = Literal.GetFloatValue(Val); - - // Overflow is always an error, but underflow is only an error if - // we underflowed to zero (APFloat reports denormals as underflow). - if ((result & APFloat::opOverflow) || - ((result & APFloat::opUnderflow) && Val.isZero())) { - unsigned diagnostic; - SmallString<20> buffer; - if (result & APFloat::opOverflow) { - diagnostic = diag::warn_float_overflow; - APFloat::getLargest(Format).toString(buffer); - } else { - diagnostic = diag::warn_float_underflow; - APFloat::getSmallest(Format).toString(buffer); - } - - Diag(Tok.getLocation(), diagnostic) - << Ty - << StringRef(buffer.data(), buffer.size()); - } - - bool isExact = (result == APFloat::opOK); - Res = FloatingLiteral::Create(Context, Val, isExact, Ty, Tok.getLocation()); + Res = BuildFloatingLiteral(*this, Literal, Ty, Tok.getLocation()); if (Ty == Context.DoubleTy) { if (getLangOptions().SinglePrecisionConstants) { |