diff --git a/llvm/lib/Support/FileCheck.cpp b/llvm/lib/Support/FileCheck.cpp --- a/llvm/lib/Support/FileCheck.cpp +++ b/llvm/lib/Support/FileCheck.cpp @@ -60,27 +60,49 @@ Expected ExpressionFormat::getMatchingString(ExpressionValue IntegerValue) const { + uint64_t AbsoluteValue; + StringRef SignPrefix = IntegerValue.isNegative() ? "-" : ""; + if (Value == Kind::Signed) { Expected SignedValue = IntegerValue.getSignedValue(); if (!SignedValue) return SignedValue.takeError(); - return itostr(*SignedValue); + if (*SignedValue < 0) + AbsoluteValue = cantFail(IntegerValue.getAbsolute().getUnsignedValue()); + else + AbsoluteValue = cantFail(IntegerValue.getSignedValue()); + } else { + Expected UnsignedValue = IntegerValue.getUnsignedValue(); + if (!UnsignedValue) + return UnsignedValue.takeError(); + AbsoluteValue = *UnsignedValue; } - Expected UnsignedValue = IntegerValue.getUnsignedValue(); - if (!UnsignedValue) - return UnsignedValue.takeError(); + std::string AbsoluteValueStr; switch (Value) { case Kind::Unsigned: - return utostr(*UnsignedValue); + case Kind::Signed: + AbsoluteValueStr = utostr(AbsoluteValue); + break; case Kind::HexUpper: - return utohexstr(*UnsignedValue, /*LowerCase=*/false); + AbsoluteValueStr = utohexstr(AbsoluteValue, /*LowerCase=*/false); + break; case Kind::HexLower: - return utohexstr(*UnsignedValue, /*LowerCase=*/true); + AbsoluteValueStr = utohexstr(AbsoluteValue, /*LowerCase=*/true); + break; default: return createStringError(std::errc::invalid_argument, "trying to match value with invalid format"); } + + if (Precision > AbsoluteValueStr.size()) { + unsigned LeadingZeros = Precision - AbsoluteValueStr.size(); + return (Twine(SignPrefix) + std::string(LeadingZeros, '0') + + AbsoluteValueStr) + .str(); + } + + return (Twine(SignPrefix) + AbsoluteValueStr).str(); } Expected @@ -675,21 +697,33 @@ return ErrorDiagnostic::get( SM, Expr, "invalid matching format specification in expression"); + // Parse precision. + unsigned Precision = 0; + if (Expr.consume_front(".")) { + if (Expr.consumeInteger(10, Precision)) + return ErrorDiagnostic::get(SM, Expr, + "invalid precision in format specifier"); + } + // Check for unknown matching format specifier and set matching format in // class instance representing this expression. SMLoc fmtloc = SMLoc::getFromPointer(Expr.data()); switch (popFront(Expr)) { case 'u': - ExplicitFormat = ExpressionFormat(ExpressionFormat::Kind::Unsigned); + ExplicitFormat = + ExpressionFormat(ExpressionFormat::Kind::Unsigned, Precision); break; case 'd': - ExplicitFormat = ExpressionFormat(ExpressionFormat::Kind::Signed); + ExplicitFormat = + ExpressionFormat(ExpressionFormat::Kind::Signed, Precision); break; case 'x': - ExplicitFormat = ExpressionFormat(ExpressionFormat::Kind::HexLower); + ExplicitFormat = + ExpressionFormat(ExpressionFormat::Kind::HexLower, Precision); break; case 'X': - ExplicitFormat = ExpressionFormat(ExpressionFormat::Kind::HexUpper); + ExplicitFormat = + ExpressionFormat(ExpressionFormat::Kind::HexUpper, Precision); break; default: return ErrorDiagnostic::get(SM, fmtloc, diff --git a/llvm/lib/Support/FileCheckImpl.h b/llvm/lib/Support/FileCheckImpl.h --- a/llvm/lib/Support/FileCheckImpl.h +++ b/llvm/lib/Support/FileCheckImpl.h @@ -53,15 +53,17 @@ private: Kind Value; + unsigned Precision; public: /// Evaluates a format to true if it can be used in a match. explicit operator bool() const { return Value != Kind::NoFormat; } /// Define format equality: formats are equal if neither is NoFormat and - /// their kinds are the same. + /// their kinds and precision are the same. bool operator==(const ExpressionFormat &Other) const { - return Value != Kind::NoFormat && Value == Other.Value; + return Value != Kind::NoFormat && Value == Other.Value && + Precision == Other.Precision; } bool operator!=(const ExpressionFormat &Other) const { @@ -75,8 +77,10 @@ /// \returns the format specifier corresponding to this format as a string. StringRef toString() const; - ExpressionFormat() : Value(Kind::NoFormat){}; - explicit ExpressionFormat(Kind Value) : Value(Value){}; + ExpressionFormat() : Value(Kind::NoFormat), Precision(0){}; + explicit ExpressionFormat(Kind Value) : Value(Value), Precision(0){}; + explicit ExpressionFormat(Kind Value, unsigned Precision) + : Value(Value), Precision(Precision){}; /// \returns a wildcard regular expression StringRef that matches any value /// in the format represented by this instance, or an error if the format is