1*e8d8bef9SDimitry Andric //===- FileCheck.cpp - Check that File's Contents match what is expected --===// 2*e8d8bef9SDimitry Andric // 3*e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*e8d8bef9SDimitry Andric // 7*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8*e8d8bef9SDimitry Andric // 9*e8d8bef9SDimitry Andric // FileCheck does a line-by line check of a file that validates whether it 10*e8d8bef9SDimitry Andric // contains the expected content. This is useful for regression tests etc. 11*e8d8bef9SDimitry Andric // 12*e8d8bef9SDimitry Andric // This file implements most of the API that will be used by the FileCheck utility 13*e8d8bef9SDimitry Andric // as well as various unittests. 14*e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 15*e8d8bef9SDimitry Andric 16*e8d8bef9SDimitry Andric #include "llvm/FileCheck/FileCheck.h" 17*e8d8bef9SDimitry Andric #include "FileCheckImpl.h" 18*e8d8bef9SDimitry Andric #include "llvm/ADT/STLExtras.h" 19*e8d8bef9SDimitry Andric #include "llvm/ADT/StringSet.h" 20*e8d8bef9SDimitry Andric #include "llvm/ADT/Twine.h" 21*e8d8bef9SDimitry Andric #include "llvm/Support/CheckedArithmetic.h" 22*e8d8bef9SDimitry Andric #include "llvm/Support/FormatVariadic.h" 23*e8d8bef9SDimitry Andric #include <cstdint> 24*e8d8bef9SDimitry Andric #include <list> 25*e8d8bef9SDimitry Andric #include <set> 26*e8d8bef9SDimitry Andric #include <tuple> 27*e8d8bef9SDimitry Andric #include <utility> 28*e8d8bef9SDimitry Andric 29*e8d8bef9SDimitry Andric using namespace llvm; 30*e8d8bef9SDimitry Andric 31*e8d8bef9SDimitry Andric StringRef ExpressionFormat::toString() const { 32*e8d8bef9SDimitry Andric switch (Value) { 33*e8d8bef9SDimitry Andric case Kind::NoFormat: 34*e8d8bef9SDimitry Andric return StringRef("<none>"); 35*e8d8bef9SDimitry Andric case Kind::Unsigned: 36*e8d8bef9SDimitry Andric return StringRef("%u"); 37*e8d8bef9SDimitry Andric case Kind::Signed: 38*e8d8bef9SDimitry Andric return StringRef("%d"); 39*e8d8bef9SDimitry Andric case Kind::HexUpper: 40*e8d8bef9SDimitry Andric return StringRef("%X"); 41*e8d8bef9SDimitry Andric case Kind::HexLower: 42*e8d8bef9SDimitry Andric return StringRef("%x"); 43*e8d8bef9SDimitry Andric } 44*e8d8bef9SDimitry Andric llvm_unreachable("unknown expression format"); 45*e8d8bef9SDimitry Andric } 46*e8d8bef9SDimitry Andric 47*e8d8bef9SDimitry Andric Expected<std::string> ExpressionFormat::getWildcardRegex() const { 48*e8d8bef9SDimitry Andric auto CreatePrecisionRegex = [this](StringRef S) { 49*e8d8bef9SDimitry Andric return (S + Twine('{') + Twine(Precision) + "}").str(); 50*e8d8bef9SDimitry Andric }; 51*e8d8bef9SDimitry Andric 52*e8d8bef9SDimitry Andric switch (Value) { 53*e8d8bef9SDimitry Andric case Kind::Unsigned: 54*e8d8bef9SDimitry Andric if (Precision) 55*e8d8bef9SDimitry Andric return CreatePrecisionRegex("([1-9][0-9]*)?[0-9]"); 56*e8d8bef9SDimitry Andric return std::string("[0-9]+"); 57*e8d8bef9SDimitry Andric case Kind::Signed: 58*e8d8bef9SDimitry Andric if (Precision) 59*e8d8bef9SDimitry Andric return CreatePrecisionRegex("-?([1-9][0-9]*)?[0-9]"); 60*e8d8bef9SDimitry Andric return std::string("-?[0-9]+"); 61*e8d8bef9SDimitry Andric case Kind::HexUpper: 62*e8d8bef9SDimitry Andric if (Precision) 63*e8d8bef9SDimitry Andric return CreatePrecisionRegex("([1-9A-F][0-9A-F]*)?[0-9A-F]"); 64*e8d8bef9SDimitry Andric return std::string("[0-9A-F]+"); 65*e8d8bef9SDimitry Andric case Kind::HexLower: 66*e8d8bef9SDimitry Andric if (Precision) 67*e8d8bef9SDimitry Andric return CreatePrecisionRegex("([1-9a-f][0-9a-f]*)?[0-9a-f]"); 68*e8d8bef9SDimitry Andric return std::string("[0-9a-f]+"); 69*e8d8bef9SDimitry Andric default: 70*e8d8bef9SDimitry Andric return createStringError(std::errc::invalid_argument, 71*e8d8bef9SDimitry Andric "trying to match value with invalid format"); 72*e8d8bef9SDimitry Andric } 73*e8d8bef9SDimitry Andric } 74*e8d8bef9SDimitry Andric 75*e8d8bef9SDimitry Andric Expected<std::string> 76*e8d8bef9SDimitry Andric ExpressionFormat::getMatchingString(ExpressionValue IntegerValue) const { 77*e8d8bef9SDimitry Andric uint64_t AbsoluteValue; 78*e8d8bef9SDimitry Andric StringRef SignPrefix = IntegerValue.isNegative() ? "-" : ""; 79*e8d8bef9SDimitry Andric 80*e8d8bef9SDimitry Andric if (Value == Kind::Signed) { 81*e8d8bef9SDimitry Andric Expected<int64_t> SignedValue = IntegerValue.getSignedValue(); 82*e8d8bef9SDimitry Andric if (!SignedValue) 83*e8d8bef9SDimitry Andric return SignedValue.takeError(); 84*e8d8bef9SDimitry Andric if (*SignedValue < 0) 85*e8d8bef9SDimitry Andric AbsoluteValue = cantFail(IntegerValue.getAbsolute().getUnsignedValue()); 86*e8d8bef9SDimitry Andric else 87*e8d8bef9SDimitry Andric AbsoluteValue = *SignedValue; 88*e8d8bef9SDimitry Andric } else { 89*e8d8bef9SDimitry Andric Expected<uint64_t> UnsignedValue = IntegerValue.getUnsignedValue(); 90*e8d8bef9SDimitry Andric if (!UnsignedValue) 91*e8d8bef9SDimitry Andric return UnsignedValue.takeError(); 92*e8d8bef9SDimitry Andric AbsoluteValue = *UnsignedValue; 93*e8d8bef9SDimitry Andric } 94*e8d8bef9SDimitry Andric 95*e8d8bef9SDimitry Andric std::string AbsoluteValueStr; 96*e8d8bef9SDimitry Andric switch (Value) { 97*e8d8bef9SDimitry Andric case Kind::Unsigned: 98*e8d8bef9SDimitry Andric case Kind::Signed: 99*e8d8bef9SDimitry Andric AbsoluteValueStr = utostr(AbsoluteValue); 100*e8d8bef9SDimitry Andric break; 101*e8d8bef9SDimitry Andric case Kind::HexUpper: 102*e8d8bef9SDimitry Andric case Kind::HexLower: 103*e8d8bef9SDimitry Andric AbsoluteValueStr = utohexstr(AbsoluteValue, Value == Kind::HexLower); 104*e8d8bef9SDimitry Andric break; 105*e8d8bef9SDimitry Andric default: 106*e8d8bef9SDimitry Andric return createStringError(std::errc::invalid_argument, 107*e8d8bef9SDimitry Andric "trying to match value with invalid format"); 108*e8d8bef9SDimitry Andric } 109*e8d8bef9SDimitry Andric 110*e8d8bef9SDimitry Andric if (Precision > AbsoluteValueStr.size()) { 111*e8d8bef9SDimitry Andric unsigned LeadingZeros = Precision - AbsoluteValueStr.size(); 112*e8d8bef9SDimitry Andric return (Twine(SignPrefix) + std::string(LeadingZeros, '0') + 113*e8d8bef9SDimitry Andric AbsoluteValueStr) 114*e8d8bef9SDimitry Andric .str(); 115*e8d8bef9SDimitry Andric } 116*e8d8bef9SDimitry Andric 117*e8d8bef9SDimitry Andric return (Twine(SignPrefix) + AbsoluteValueStr).str(); 118*e8d8bef9SDimitry Andric } 119*e8d8bef9SDimitry Andric 120*e8d8bef9SDimitry Andric Expected<ExpressionValue> 121*e8d8bef9SDimitry Andric ExpressionFormat::valueFromStringRepr(StringRef StrVal, 122*e8d8bef9SDimitry Andric const SourceMgr &SM) const { 123*e8d8bef9SDimitry Andric bool ValueIsSigned = Value == Kind::Signed; 124*e8d8bef9SDimitry Andric StringRef OverflowErrorStr = "unable to represent numeric value"; 125*e8d8bef9SDimitry Andric if (ValueIsSigned) { 126*e8d8bef9SDimitry Andric int64_t SignedValue; 127*e8d8bef9SDimitry Andric 128*e8d8bef9SDimitry Andric if (StrVal.getAsInteger(10, SignedValue)) 129*e8d8bef9SDimitry Andric return ErrorDiagnostic::get(SM, StrVal, OverflowErrorStr); 130*e8d8bef9SDimitry Andric 131*e8d8bef9SDimitry Andric return ExpressionValue(SignedValue); 132*e8d8bef9SDimitry Andric } 133*e8d8bef9SDimitry Andric 134*e8d8bef9SDimitry Andric bool Hex = Value == Kind::HexUpper || Value == Kind::HexLower; 135*e8d8bef9SDimitry Andric uint64_t UnsignedValue; 136*e8d8bef9SDimitry Andric if (StrVal.getAsInteger(Hex ? 16 : 10, UnsignedValue)) 137*e8d8bef9SDimitry Andric return ErrorDiagnostic::get(SM, StrVal, OverflowErrorStr); 138*e8d8bef9SDimitry Andric 139*e8d8bef9SDimitry Andric return ExpressionValue(UnsignedValue); 140*e8d8bef9SDimitry Andric } 141*e8d8bef9SDimitry Andric 142*e8d8bef9SDimitry Andric static int64_t getAsSigned(uint64_t UnsignedValue) { 143*e8d8bef9SDimitry Andric // Use memcpy to reinterpret the bitpattern in Value since casting to 144*e8d8bef9SDimitry Andric // signed is implementation-defined if the unsigned value is too big to be 145*e8d8bef9SDimitry Andric // represented in the signed type and using an union violates type aliasing 146*e8d8bef9SDimitry Andric // rules. 147*e8d8bef9SDimitry Andric int64_t SignedValue; 148*e8d8bef9SDimitry Andric memcpy(&SignedValue, &UnsignedValue, sizeof(SignedValue)); 149*e8d8bef9SDimitry Andric return SignedValue; 150*e8d8bef9SDimitry Andric } 151*e8d8bef9SDimitry Andric 152*e8d8bef9SDimitry Andric Expected<int64_t> ExpressionValue::getSignedValue() const { 153*e8d8bef9SDimitry Andric if (Negative) 154*e8d8bef9SDimitry Andric return getAsSigned(Value); 155*e8d8bef9SDimitry Andric 156*e8d8bef9SDimitry Andric if (Value > (uint64_t)std::numeric_limits<int64_t>::max()) 157*e8d8bef9SDimitry Andric return make_error<OverflowError>(); 158*e8d8bef9SDimitry Andric 159*e8d8bef9SDimitry Andric // Value is in the representable range of int64_t so we can use cast. 160*e8d8bef9SDimitry Andric return static_cast<int64_t>(Value); 161*e8d8bef9SDimitry Andric } 162*e8d8bef9SDimitry Andric 163*e8d8bef9SDimitry Andric Expected<uint64_t> ExpressionValue::getUnsignedValue() const { 164*e8d8bef9SDimitry Andric if (Negative) 165*e8d8bef9SDimitry Andric return make_error<OverflowError>(); 166*e8d8bef9SDimitry Andric 167*e8d8bef9SDimitry Andric return Value; 168*e8d8bef9SDimitry Andric } 169*e8d8bef9SDimitry Andric 170*e8d8bef9SDimitry Andric ExpressionValue ExpressionValue::getAbsolute() const { 171*e8d8bef9SDimitry Andric if (!Negative) 172*e8d8bef9SDimitry Andric return *this; 173*e8d8bef9SDimitry Andric 174*e8d8bef9SDimitry Andric int64_t SignedValue = getAsSigned(Value); 175*e8d8bef9SDimitry Andric int64_t MaxInt64 = std::numeric_limits<int64_t>::max(); 176*e8d8bef9SDimitry Andric // Absolute value can be represented as int64_t. 177*e8d8bef9SDimitry Andric if (SignedValue >= -MaxInt64) 178*e8d8bef9SDimitry Andric return ExpressionValue(-getAsSigned(Value)); 179*e8d8bef9SDimitry Andric 180*e8d8bef9SDimitry Andric // -X == -(max int64_t + Rem), negate each component independently. 181*e8d8bef9SDimitry Andric SignedValue += MaxInt64; 182*e8d8bef9SDimitry Andric uint64_t RemainingValueAbsolute = -SignedValue; 183*e8d8bef9SDimitry Andric return ExpressionValue(MaxInt64 + RemainingValueAbsolute); 184*e8d8bef9SDimitry Andric } 185*e8d8bef9SDimitry Andric 186*e8d8bef9SDimitry Andric Expected<ExpressionValue> llvm::operator+(const ExpressionValue &LeftOperand, 187*e8d8bef9SDimitry Andric const ExpressionValue &RightOperand) { 188*e8d8bef9SDimitry Andric if (LeftOperand.isNegative() && RightOperand.isNegative()) { 189*e8d8bef9SDimitry Andric int64_t LeftValue = cantFail(LeftOperand.getSignedValue()); 190*e8d8bef9SDimitry Andric int64_t RightValue = cantFail(RightOperand.getSignedValue()); 191*e8d8bef9SDimitry Andric Optional<int64_t> Result = checkedAdd<int64_t>(LeftValue, RightValue); 192*e8d8bef9SDimitry Andric if (!Result) 193*e8d8bef9SDimitry Andric return make_error<OverflowError>(); 194*e8d8bef9SDimitry Andric 195*e8d8bef9SDimitry Andric return ExpressionValue(*Result); 196*e8d8bef9SDimitry Andric } 197*e8d8bef9SDimitry Andric 198*e8d8bef9SDimitry Andric // (-A) + B == B - A. 199*e8d8bef9SDimitry Andric if (LeftOperand.isNegative()) 200*e8d8bef9SDimitry Andric return RightOperand - LeftOperand.getAbsolute(); 201*e8d8bef9SDimitry Andric 202*e8d8bef9SDimitry Andric // A + (-B) == A - B. 203*e8d8bef9SDimitry Andric if (RightOperand.isNegative()) 204*e8d8bef9SDimitry Andric return LeftOperand - RightOperand.getAbsolute(); 205*e8d8bef9SDimitry Andric 206*e8d8bef9SDimitry Andric // Both values are positive at this point. 207*e8d8bef9SDimitry Andric uint64_t LeftValue = cantFail(LeftOperand.getUnsignedValue()); 208*e8d8bef9SDimitry Andric uint64_t RightValue = cantFail(RightOperand.getUnsignedValue()); 209*e8d8bef9SDimitry Andric Optional<uint64_t> Result = 210*e8d8bef9SDimitry Andric checkedAddUnsigned<uint64_t>(LeftValue, RightValue); 211*e8d8bef9SDimitry Andric if (!Result) 212*e8d8bef9SDimitry Andric return make_error<OverflowError>(); 213*e8d8bef9SDimitry Andric 214*e8d8bef9SDimitry Andric return ExpressionValue(*Result); 215*e8d8bef9SDimitry Andric } 216*e8d8bef9SDimitry Andric 217*e8d8bef9SDimitry Andric Expected<ExpressionValue> llvm::operator-(const ExpressionValue &LeftOperand, 218*e8d8bef9SDimitry Andric const ExpressionValue &RightOperand) { 219*e8d8bef9SDimitry Andric // Result will be negative and thus might underflow. 220*e8d8bef9SDimitry Andric if (LeftOperand.isNegative() && !RightOperand.isNegative()) { 221*e8d8bef9SDimitry Andric int64_t LeftValue = cantFail(LeftOperand.getSignedValue()); 222*e8d8bef9SDimitry Andric uint64_t RightValue = cantFail(RightOperand.getUnsignedValue()); 223*e8d8bef9SDimitry Andric // Result <= -1 - (max int64_t) which overflows on 1- and 2-complement. 224*e8d8bef9SDimitry Andric if (RightValue > (uint64_t)std::numeric_limits<int64_t>::max()) 225*e8d8bef9SDimitry Andric return make_error<OverflowError>(); 226*e8d8bef9SDimitry Andric Optional<int64_t> Result = 227*e8d8bef9SDimitry Andric checkedSub(LeftValue, static_cast<int64_t>(RightValue)); 228*e8d8bef9SDimitry Andric if (!Result) 229*e8d8bef9SDimitry Andric return make_error<OverflowError>(); 230*e8d8bef9SDimitry Andric 231*e8d8bef9SDimitry Andric return ExpressionValue(*Result); 232*e8d8bef9SDimitry Andric } 233*e8d8bef9SDimitry Andric 234*e8d8bef9SDimitry Andric // (-A) - (-B) == B - A. 235*e8d8bef9SDimitry Andric if (LeftOperand.isNegative()) 236*e8d8bef9SDimitry Andric return RightOperand.getAbsolute() - LeftOperand.getAbsolute(); 237*e8d8bef9SDimitry Andric 238*e8d8bef9SDimitry Andric // A - (-B) == A + B. 239*e8d8bef9SDimitry Andric if (RightOperand.isNegative()) 240*e8d8bef9SDimitry Andric return LeftOperand + RightOperand.getAbsolute(); 241*e8d8bef9SDimitry Andric 242*e8d8bef9SDimitry Andric // Both values are positive at this point. 243*e8d8bef9SDimitry Andric uint64_t LeftValue = cantFail(LeftOperand.getUnsignedValue()); 244*e8d8bef9SDimitry Andric uint64_t RightValue = cantFail(RightOperand.getUnsignedValue()); 245*e8d8bef9SDimitry Andric if (LeftValue >= RightValue) 246*e8d8bef9SDimitry Andric return ExpressionValue(LeftValue - RightValue); 247*e8d8bef9SDimitry Andric else { 248*e8d8bef9SDimitry Andric uint64_t AbsoluteDifference = RightValue - LeftValue; 249*e8d8bef9SDimitry Andric uint64_t MaxInt64 = std::numeric_limits<int64_t>::max(); 250*e8d8bef9SDimitry Andric // Value might underflow. 251*e8d8bef9SDimitry Andric if (AbsoluteDifference > MaxInt64) { 252*e8d8bef9SDimitry Andric AbsoluteDifference -= MaxInt64; 253*e8d8bef9SDimitry Andric int64_t Result = -MaxInt64; 254*e8d8bef9SDimitry Andric int64_t MinInt64 = std::numeric_limits<int64_t>::min(); 255*e8d8bef9SDimitry Andric // Underflow, tested by: 256*e8d8bef9SDimitry Andric // abs(Result + (max int64_t)) > abs((min int64_t) + (max int64_t)) 257*e8d8bef9SDimitry Andric if (AbsoluteDifference > static_cast<uint64_t>(-(MinInt64 - Result))) 258*e8d8bef9SDimitry Andric return make_error<OverflowError>(); 259*e8d8bef9SDimitry Andric Result -= static_cast<int64_t>(AbsoluteDifference); 260*e8d8bef9SDimitry Andric return ExpressionValue(Result); 261*e8d8bef9SDimitry Andric } 262*e8d8bef9SDimitry Andric 263*e8d8bef9SDimitry Andric return ExpressionValue(-static_cast<int64_t>(AbsoluteDifference)); 264*e8d8bef9SDimitry Andric } 265*e8d8bef9SDimitry Andric } 266*e8d8bef9SDimitry Andric 267*e8d8bef9SDimitry Andric Expected<ExpressionValue> llvm::operator*(const ExpressionValue &LeftOperand, 268*e8d8bef9SDimitry Andric const ExpressionValue &RightOperand) { 269*e8d8bef9SDimitry Andric // -A * -B == A * B 270*e8d8bef9SDimitry Andric if (LeftOperand.isNegative() && RightOperand.isNegative()) 271*e8d8bef9SDimitry Andric return LeftOperand.getAbsolute() * RightOperand.getAbsolute(); 272*e8d8bef9SDimitry Andric 273*e8d8bef9SDimitry Andric // A * -B == -B * A 274*e8d8bef9SDimitry Andric if (RightOperand.isNegative()) 275*e8d8bef9SDimitry Andric return RightOperand * LeftOperand; 276*e8d8bef9SDimitry Andric 277*e8d8bef9SDimitry Andric assert(!RightOperand.isNegative() && "Unexpected negative operand!"); 278*e8d8bef9SDimitry Andric 279*e8d8bef9SDimitry Andric // Result will be negative and can underflow. 280*e8d8bef9SDimitry Andric if (LeftOperand.isNegative()) { 281*e8d8bef9SDimitry Andric auto Result = LeftOperand.getAbsolute() * RightOperand.getAbsolute(); 282*e8d8bef9SDimitry Andric if (!Result) 283*e8d8bef9SDimitry Andric return Result; 284*e8d8bef9SDimitry Andric 285*e8d8bef9SDimitry Andric return ExpressionValue(0) - *Result; 286*e8d8bef9SDimitry Andric } 287*e8d8bef9SDimitry Andric 288*e8d8bef9SDimitry Andric // Result will be positive and can overflow. 289*e8d8bef9SDimitry Andric uint64_t LeftValue = cantFail(LeftOperand.getUnsignedValue()); 290*e8d8bef9SDimitry Andric uint64_t RightValue = cantFail(RightOperand.getUnsignedValue()); 291*e8d8bef9SDimitry Andric Optional<uint64_t> Result = 292*e8d8bef9SDimitry Andric checkedMulUnsigned<uint64_t>(LeftValue, RightValue); 293*e8d8bef9SDimitry Andric if (!Result) 294*e8d8bef9SDimitry Andric return make_error<OverflowError>(); 295*e8d8bef9SDimitry Andric 296*e8d8bef9SDimitry Andric return ExpressionValue(*Result); 297*e8d8bef9SDimitry Andric } 298*e8d8bef9SDimitry Andric 299*e8d8bef9SDimitry Andric Expected<ExpressionValue> llvm::operator/(const ExpressionValue &LeftOperand, 300*e8d8bef9SDimitry Andric const ExpressionValue &RightOperand) { 301*e8d8bef9SDimitry Andric // -A / -B == A / B 302*e8d8bef9SDimitry Andric if (LeftOperand.isNegative() && RightOperand.isNegative()) 303*e8d8bef9SDimitry Andric return LeftOperand.getAbsolute() / RightOperand.getAbsolute(); 304*e8d8bef9SDimitry Andric 305*e8d8bef9SDimitry Andric // Check for divide by zero. 306*e8d8bef9SDimitry Andric if (RightOperand == ExpressionValue(0)) 307*e8d8bef9SDimitry Andric return make_error<OverflowError>(); 308*e8d8bef9SDimitry Andric 309*e8d8bef9SDimitry Andric // Result will be negative and can underflow. 310*e8d8bef9SDimitry Andric if (LeftOperand.isNegative() || RightOperand.isNegative()) 311*e8d8bef9SDimitry Andric return ExpressionValue(0) - 312*e8d8bef9SDimitry Andric cantFail(LeftOperand.getAbsolute() / RightOperand.getAbsolute()); 313*e8d8bef9SDimitry Andric 314*e8d8bef9SDimitry Andric uint64_t LeftValue = cantFail(LeftOperand.getUnsignedValue()); 315*e8d8bef9SDimitry Andric uint64_t RightValue = cantFail(RightOperand.getUnsignedValue()); 316*e8d8bef9SDimitry Andric return ExpressionValue(LeftValue / RightValue); 317*e8d8bef9SDimitry Andric } 318*e8d8bef9SDimitry Andric 319*e8d8bef9SDimitry Andric Expected<ExpressionValue> llvm::max(const ExpressionValue &LeftOperand, 320*e8d8bef9SDimitry Andric const ExpressionValue &RightOperand) { 321*e8d8bef9SDimitry Andric if (LeftOperand.isNegative() && RightOperand.isNegative()) { 322*e8d8bef9SDimitry Andric int64_t LeftValue = cantFail(LeftOperand.getSignedValue()); 323*e8d8bef9SDimitry Andric int64_t RightValue = cantFail(RightOperand.getSignedValue()); 324*e8d8bef9SDimitry Andric return ExpressionValue(std::max(LeftValue, RightValue)); 325*e8d8bef9SDimitry Andric } 326*e8d8bef9SDimitry Andric 327*e8d8bef9SDimitry Andric if (!LeftOperand.isNegative() && !RightOperand.isNegative()) { 328*e8d8bef9SDimitry Andric uint64_t LeftValue = cantFail(LeftOperand.getUnsignedValue()); 329*e8d8bef9SDimitry Andric uint64_t RightValue = cantFail(RightOperand.getUnsignedValue()); 330*e8d8bef9SDimitry Andric return ExpressionValue(std::max(LeftValue, RightValue)); 331*e8d8bef9SDimitry Andric } 332*e8d8bef9SDimitry Andric 333*e8d8bef9SDimitry Andric if (LeftOperand.isNegative()) 334*e8d8bef9SDimitry Andric return RightOperand; 335*e8d8bef9SDimitry Andric 336*e8d8bef9SDimitry Andric return LeftOperand; 337*e8d8bef9SDimitry Andric } 338*e8d8bef9SDimitry Andric 339*e8d8bef9SDimitry Andric Expected<ExpressionValue> llvm::min(const ExpressionValue &LeftOperand, 340*e8d8bef9SDimitry Andric const ExpressionValue &RightOperand) { 341*e8d8bef9SDimitry Andric if (cantFail(max(LeftOperand, RightOperand)) == LeftOperand) 342*e8d8bef9SDimitry Andric return RightOperand; 343*e8d8bef9SDimitry Andric 344*e8d8bef9SDimitry Andric return LeftOperand; 345*e8d8bef9SDimitry Andric } 346*e8d8bef9SDimitry Andric 347*e8d8bef9SDimitry Andric Expected<ExpressionValue> NumericVariableUse::eval() const { 348*e8d8bef9SDimitry Andric Optional<ExpressionValue> Value = Variable->getValue(); 349*e8d8bef9SDimitry Andric if (Value) 350*e8d8bef9SDimitry Andric return *Value; 351*e8d8bef9SDimitry Andric 352*e8d8bef9SDimitry Andric return make_error<UndefVarError>(getExpressionStr()); 353*e8d8bef9SDimitry Andric } 354*e8d8bef9SDimitry Andric 355*e8d8bef9SDimitry Andric Expected<ExpressionValue> BinaryOperation::eval() const { 356*e8d8bef9SDimitry Andric Expected<ExpressionValue> LeftOp = LeftOperand->eval(); 357*e8d8bef9SDimitry Andric Expected<ExpressionValue> RightOp = RightOperand->eval(); 358*e8d8bef9SDimitry Andric 359*e8d8bef9SDimitry Andric // Bubble up any error (e.g. undefined variables) in the recursive 360*e8d8bef9SDimitry Andric // evaluation. 361*e8d8bef9SDimitry Andric if (!LeftOp || !RightOp) { 362*e8d8bef9SDimitry Andric Error Err = Error::success(); 363*e8d8bef9SDimitry Andric if (!LeftOp) 364*e8d8bef9SDimitry Andric Err = joinErrors(std::move(Err), LeftOp.takeError()); 365*e8d8bef9SDimitry Andric if (!RightOp) 366*e8d8bef9SDimitry Andric Err = joinErrors(std::move(Err), RightOp.takeError()); 367*e8d8bef9SDimitry Andric return std::move(Err); 368*e8d8bef9SDimitry Andric } 369*e8d8bef9SDimitry Andric 370*e8d8bef9SDimitry Andric return EvalBinop(*LeftOp, *RightOp); 371*e8d8bef9SDimitry Andric } 372*e8d8bef9SDimitry Andric 373*e8d8bef9SDimitry Andric Expected<ExpressionFormat> 374*e8d8bef9SDimitry Andric BinaryOperation::getImplicitFormat(const SourceMgr &SM) const { 375*e8d8bef9SDimitry Andric Expected<ExpressionFormat> LeftFormat = LeftOperand->getImplicitFormat(SM); 376*e8d8bef9SDimitry Andric Expected<ExpressionFormat> RightFormat = RightOperand->getImplicitFormat(SM); 377*e8d8bef9SDimitry Andric if (!LeftFormat || !RightFormat) { 378*e8d8bef9SDimitry Andric Error Err = Error::success(); 379*e8d8bef9SDimitry Andric if (!LeftFormat) 380*e8d8bef9SDimitry Andric Err = joinErrors(std::move(Err), LeftFormat.takeError()); 381*e8d8bef9SDimitry Andric if (!RightFormat) 382*e8d8bef9SDimitry Andric Err = joinErrors(std::move(Err), RightFormat.takeError()); 383*e8d8bef9SDimitry Andric return std::move(Err); 384*e8d8bef9SDimitry Andric } 385*e8d8bef9SDimitry Andric 386*e8d8bef9SDimitry Andric if (*LeftFormat != ExpressionFormat::Kind::NoFormat && 387*e8d8bef9SDimitry Andric *RightFormat != ExpressionFormat::Kind::NoFormat && 388*e8d8bef9SDimitry Andric *LeftFormat != *RightFormat) 389*e8d8bef9SDimitry Andric return ErrorDiagnostic::get( 390*e8d8bef9SDimitry Andric SM, getExpressionStr(), 391*e8d8bef9SDimitry Andric "implicit format conflict between '" + LeftOperand->getExpressionStr() + 392*e8d8bef9SDimitry Andric "' (" + LeftFormat->toString() + ") and '" + 393*e8d8bef9SDimitry Andric RightOperand->getExpressionStr() + "' (" + RightFormat->toString() + 394*e8d8bef9SDimitry Andric "), need an explicit format specifier"); 395*e8d8bef9SDimitry Andric 396*e8d8bef9SDimitry Andric return *LeftFormat != ExpressionFormat::Kind::NoFormat ? *LeftFormat 397*e8d8bef9SDimitry Andric : *RightFormat; 398*e8d8bef9SDimitry Andric } 399*e8d8bef9SDimitry Andric 400*e8d8bef9SDimitry Andric Expected<std::string> NumericSubstitution::getResult() const { 401*e8d8bef9SDimitry Andric assert(ExpressionPointer->getAST() != nullptr && 402*e8d8bef9SDimitry Andric "Substituting empty expression"); 403*e8d8bef9SDimitry Andric Expected<ExpressionValue> EvaluatedValue = 404*e8d8bef9SDimitry Andric ExpressionPointer->getAST()->eval(); 405*e8d8bef9SDimitry Andric if (!EvaluatedValue) 406*e8d8bef9SDimitry Andric return EvaluatedValue.takeError(); 407*e8d8bef9SDimitry Andric ExpressionFormat Format = ExpressionPointer->getFormat(); 408*e8d8bef9SDimitry Andric return Format.getMatchingString(*EvaluatedValue); 409*e8d8bef9SDimitry Andric } 410*e8d8bef9SDimitry Andric 411*e8d8bef9SDimitry Andric Expected<std::string> StringSubstitution::getResult() const { 412*e8d8bef9SDimitry Andric // Look up the value and escape it so that we can put it into the regex. 413*e8d8bef9SDimitry Andric Expected<StringRef> VarVal = Context->getPatternVarValue(FromStr); 414*e8d8bef9SDimitry Andric if (!VarVal) 415*e8d8bef9SDimitry Andric return VarVal.takeError(); 416*e8d8bef9SDimitry Andric return Regex::escape(*VarVal); 417*e8d8bef9SDimitry Andric } 418*e8d8bef9SDimitry Andric 419*e8d8bef9SDimitry Andric bool Pattern::isValidVarNameStart(char C) { return C == '_' || isAlpha(C); } 420*e8d8bef9SDimitry Andric 421*e8d8bef9SDimitry Andric Expected<Pattern::VariableProperties> 422*e8d8bef9SDimitry Andric Pattern::parseVariable(StringRef &Str, const SourceMgr &SM) { 423*e8d8bef9SDimitry Andric if (Str.empty()) 424*e8d8bef9SDimitry Andric return ErrorDiagnostic::get(SM, Str, "empty variable name"); 425*e8d8bef9SDimitry Andric 426*e8d8bef9SDimitry Andric size_t I = 0; 427*e8d8bef9SDimitry Andric bool IsPseudo = Str[0] == '@'; 428*e8d8bef9SDimitry Andric 429*e8d8bef9SDimitry Andric // Global vars start with '$'. 430*e8d8bef9SDimitry Andric if (Str[0] == '$' || IsPseudo) 431*e8d8bef9SDimitry Andric ++I; 432*e8d8bef9SDimitry Andric 433*e8d8bef9SDimitry Andric if (!isValidVarNameStart(Str[I++])) 434*e8d8bef9SDimitry Andric return ErrorDiagnostic::get(SM, Str, "invalid variable name"); 435*e8d8bef9SDimitry Andric 436*e8d8bef9SDimitry Andric for (size_t E = Str.size(); I != E; ++I) 437*e8d8bef9SDimitry Andric // Variable names are composed of alphanumeric characters and underscores. 438*e8d8bef9SDimitry Andric if (Str[I] != '_' && !isAlnum(Str[I])) 439*e8d8bef9SDimitry Andric break; 440*e8d8bef9SDimitry Andric 441*e8d8bef9SDimitry Andric StringRef Name = Str.take_front(I); 442*e8d8bef9SDimitry Andric Str = Str.substr(I); 443*e8d8bef9SDimitry Andric return VariableProperties {Name, IsPseudo}; 444*e8d8bef9SDimitry Andric } 445*e8d8bef9SDimitry Andric 446*e8d8bef9SDimitry Andric // StringRef holding all characters considered as horizontal whitespaces by 447*e8d8bef9SDimitry Andric // FileCheck input canonicalization. 448*e8d8bef9SDimitry Andric constexpr StringLiteral SpaceChars = " \t"; 449*e8d8bef9SDimitry Andric 450*e8d8bef9SDimitry Andric // Parsing helper function that strips the first character in S and returns it. 451*e8d8bef9SDimitry Andric static char popFront(StringRef &S) { 452*e8d8bef9SDimitry Andric char C = S.front(); 453*e8d8bef9SDimitry Andric S = S.drop_front(); 454*e8d8bef9SDimitry Andric return C; 455*e8d8bef9SDimitry Andric } 456*e8d8bef9SDimitry Andric 457*e8d8bef9SDimitry Andric char OverflowError::ID = 0; 458*e8d8bef9SDimitry Andric char UndefVarError::ID = 0; 459*e8d8bef9SDimitry Andric char ErrorDiagnostic::ID = 0; 460*e8d8bef9SDimitry Andric char NotFoundError::ID = 0; 461*e8d8bef9SDimitry Andric 462*e8d8bef9SDimitry Andric Expected<NumericVariable *> Pattern::parseNumericVariableDefinition( 463*e8d8bef9SDimitry Andric StringRef &Expr, FileCheckPatternContext *Context, 464*e8d8bef9SDimitry Andric Optional<size_t> LineNumber, ExpressionFormat ImplicitFormat, 465*e8d8bef9SDimitry Andric const SourceMgr &SM) { 466*e8d8bef9SDimitry Andric Expected<VariableProperties> ParseVarResult = parseVariable(Expr, SM); 467*e8d8bef9SDimitry Andric if (!ParseVarResult) 468*e8d8bef9SDimitry Andric return ParseVarResult.takeError(); 469*e8d8bef9SDimitry Andric StringRef Name = ParseVarResult->Name; 470*e8d8bef9SDimitry Andric 471*e8d8bef9SDimitry Andric if (ParseVarResult->IsPseudo) 472*e8d8bef9SDimitry Andric return ErrorDiagnostic::get( 473*e8d8bef9SDimitry Andric SM, Name, "definition of pseudo numeric variable unsupported"); 474*e8d8bef9SDimitry Andric 475*e8d8bef9SDimitry Andric // Detect collisions between string and numeric variables when the latter 476*e8d8bef9SDimitry Andric // is created later than the former. 477*e8d8bef9SDimitry Andric if (Context->DefinedVariableTable.find(Name) != 478*e8d8bef9SDimitry Andric Context->DefinedVariableTable.end()) 479*e8d8bef9SDimitry Andric return ErrorDiagnostic::get( 480*e8d8bef9SDimitry Andric SM, Name, "string variable with name '" + Name + "' already exists"); 481*e8d8bef9SDimitry Andric 482*e8d8bef9SDimitry Andric Expr = Expr.ltrim(SpaceChars); 483*e8d8bef9SDimitry Andric if (!Expr.empty()) 484*e8d8bef9SDimitry Andric return ErrorDiagnostic::get( 485*e8d8bef9SDimitry Andric SM, Expr, "unexpected characters after numeric variable name"); 486*e8d8bef9SDimitry Andric 487*e8d8bef9SDimitry Andric NumericVariable *DefinedNumericVariable; 488*e8d8bef9SDimitry Andric auto VarTableIter = Context->GlobalNumericVariableTable.find(Name); 489*e8d8bef9SDimitry Andric if (VarTableIter != Context->GlobalNumericVariableTable.end()) { 490*e8d8bef9SDimitry Andric DefinedNumericVariable = VarTableIter->second; 491*e8d8bef9SDimitry Andric if (DefinedNumericVariable->getImplicitFormat() != ImplicitFormat) 492*e8d8bef9SDimitry Andric return ErrorDiagnostic::get( 493*e8d8bef9SDimitry Andric SM, Expr, "format different from previous variable definition"); 494*e8d8bef9SDimitry Andric } else 495*e8d8bef9SDimitry Andric DefinedNumericVariable = 496*e8d8bef9SDimitry Andric Context->makeNumericVariable(Name, ImplicitFormat, LineNumber); 497*e8d8bef9SDimitry Andric 498*e8d8bef9SDimitry Andric return DefinedNumericVariable; 499*e8d8bef9SDimitry Andric } 500*e8d8bef9SDimitry Andric 501*e8d8bef9SDimitry Andric Expected<std::unique_ptr<NumericVariableUse>> Pattern::parseNumericVariableUse( 502*e8d8bef9SDimitry Andric StringRef Name, bool IsPseudo, Optional<size_t> LineNumber, 503*e8d8bef9SDimitry Andric FileCheckPatternContext *Context, const SourceMgr &SM) { 504*e8d8bef9SDimitry Andric if (IsPseudo && !Name.equals("@LINE")) 505*e8d8bef9SDimitry Andric return ErrorDiagnostic::get( 506*e8d8bef9SDimitry Andric SM, Name, "invalid pseudo numeric variable '" + Name + "'"); 507*e8d8bef9SDimitry Andric 508*e8d8bef9SDimitry Andric // Numeric variable definitions and uses are parsed in the order in which 509*e8d8bef9SDimitry Andric // they appear in the CHECK patterns. For each definition, the pointer to the 510*e8d8bef9SDimitry Andric // class instance of the corresponding numeric variable definition is stored 511*e8d8bef9SDimitry Andric // in GlobalNumericVariableTable in parsePattern. Therefore, if the pointer 512*e8d8bef9SDimitry Andric // we get below is null, it means no such variable was defined before. When 513*e8d8bef9SDimitry Andric // that happens, we create a dummy variable so that parsing can continue. All 514*e8d8bef9SDimitry Andric // uses of undefined variables, whether string or numeric, are then diagnosed 515*e8d8bef9SDimitry Andric // in printSubstitutions() after failing to match. 516*e8d8bef9SDimitry Andric auto VarTableIter = Context->GlobalNumericVariableTable.find(Name); 517*e8d8bef9SDimitry Andric NumericVariable *NumericVariable; 518*e8d8bef9SDimitry Andric if (VarTableIter != Context->GlobalNumericVariableTable.end()) 519*e8d8bef9SDimitry Andric NumericVariable = VarTableIter->second; 520*e8d8bef9SDimitry Andric else { 521*e8d8bef9SDimitry Andric NumericVariable = Context->makeNumericVariable( 522*e8d8bef9SDimitry Andric Name, ExpressionFormat(ExpressionFormat::Kind::Unsigned)); 523*e8d8bef9SDimitry Andric Context->GlobalNumericVariableTable[Name] = NumericVariable; 524*e8d8bef9SDimitry Andric } 525*e8d8bef9SDimitry Andric 526*e8d8bef9SDimitry Andric Optional<size_t> DefLineNumber = NumericVariable->getDefLineNumber(); 527*e8d8bef9SDimitry Andric if (DefLineNumber && LineNumber && *DefLineNumber == *LineNumber) 528*e8d8bef9SDimitry Andric return ErrorDiagnostic::get( 529*e8d8bef9SDimitry Andric SM, Name, 530*e8d8bef9SDimitry Andric "numeric variable '" + Name + 531*e8d8bef9SDimitry Andric "' defined earlier in the same CHECK directive"); 532*e8d8bef9SDimitry Andric 533*e8d8bef9SDimitry Andric return std::make_unique<NumericVariableUse>(Name, NumericVariable); 534*e8d8bef9SDimitry Andric } 535*e8d8bef9SDimitry Andric 536*e8d8bef9SDimitry Andric Expected<std::unique_ptr<ExpressionAST>> Pattern::parseNumericOperand( 537*e8d8bef9SDimitry Andric StringRef &Expr, AllowedOperand AO, bool MaybeInvalidConstraint, 538*e8d8bef9SDimitry Andric Optional<size_t> LineNumber, FileCheckPatternContext *Context, 539*e8d8bef9SDimitry Andric const SourceMgr &SM) { 540*e8d8bef9SDimitry Andric if (Expr.startswith("(")) { 541*e8d8bef9SDimitry Andric if (AO != AllowedOperand::Any) 542*e8d8bef9SDimitry Andric return ErrorDiagnostic::get( 543*e8d8bef9SDimitry Andric SM, Expr, "parenthesized expression not permitted here"); 544*e8d8bef9SDimitry Andric return parseParenExpr(Expr, LineNumber, Context, SM); 545*e8d8bef9SDimitry Andric } 546*e8d8bef9SDimitry Andric 547*e8d8bef9SDimitry Andric if (AO == AllowedOperand::LineVar || AO == AllowedOperand::Any) { 548*e8d8bef9SDimitry Andric // Try to parse as a numeric variable use. 549*e8d8bef9SDimitry Andric Expected<Pattern::VariableProperties> ParseVarResult = 550*e8d8bef9SDimitry Andric parseVariable(Expr, SM); 551*e8d8bef9SDimitry Andric if (ParseVarResult) { 552*e8d8bef9SDimitry Andric // Try to parse a function call. 553*e8d8bef9SDimitry Andric if (Expr.ltrim(SpaceChars).startswith("(")) { 554*e8d8bef9SDimitry Andric if (AO != AllowedOperand::Any) 555*e8d8bef9SDimitry Andric return ErrorDiagnostic::get(SM, ParseVarResult->Name, 556*e8d8bef9SDimitry Andric "unexpected function call"); 557*e8d8bef9SDimitry Andric 558*e8d8bef9SDimitry Andric return parseCallExpr(Expr, ParseVarResult->Name, LineNumber, Context, 559*e8d8bef9SDimitry Andric SM); 560*e8d8bef9SDimitry Andric } 561*e8d8bef9SDimitry Andric 562*e8d8bef9SDimitry Andric return parseNumericVariableUse(ParseVarResult->Name, 563*e8d8bef9SDimitry Andric ParseVarResult->IsPseudo, LineNumber, 564*e8d8bef9SDimitry Andric Context, SM); 565*e8d8bef9SDimitry Andric } 566*e8d8bef9SDimitry Andric 567*e8d8bef9SDimitry Andric if (AO == AllowedOperand::LineVar) 568*e8d8bef9SDimitry Andric return ParseVarResult.takeError(); 569*e8d8bef9SDimitry Andric // Ignore the error and retry parsing as a literal. 570*e8d8bef9SDimitry Andric consumeError(ParseVarResult.takeError()); 571*e8d8bef9SDimitry Andric } 572*e8d8bef9SDimitry Andric 573*e8d8bef9SDimitry Andric // Otherwise, parse it as a literal. 574*e8d8bef9SDimitry Andric int64_t SignedLiteralValue; 575*e8d8bef9SDimitry Andric uint64_t UnsignedLiteralValue; 576*e8d8bef9SDimitry Andric StringRef SaveExpr = Expr; 577*e8d8bef9SDimitry Andric // Accept both signed and unsigned literal, default to signed literal. 578*e8d8bef9SDimitry Andric if (!Expr.consumeInteger((AO == AllowedOperand::LegacyLiteral) ? 10 : 0, 579*e8d8bef9SDimitry Andric UnsignedLiteralValue)) 580*e8d8bef9SDimitry Andric return std::make_unique<ExpressionLiteral>(SaveExpr.drop_back(Expr.size()), 581*e8d8bef9SDimitry Andric UnsignedLiteralValue); 582*e8d8bef9SDimitry Andric Expr = SaveExpr; 583*e8d8bef9SDimitry Andric if (AO == AllowedOperand::Any && !Expr.consumeInteger(0, SignedLiteralValue)) 584*e8d8bef9SDimitry Andric return std::make_unique<ExpressionLiteral>(SaveExpr.drop_back(Expr.size()), 585*e8d8bef9SDimitry Andric SignedLiteralValue); 586*e8d8bef9SDimitry Andric 587*e8d8bef9SDimitry Andric return ErrorDiagnostic::get( 588*e8d8bef9SDimitry Andric SM, Expr, 589*e8d8bef9SDimitry Andric Twine("invalid ") + 590*e8d8bef9SDimitry Andric (MaybeInvalidConstraint ? "matching constraint or " : "") + 591*e8d8bef9SDimitry Andric "operand format"); 592*e8d8bef9SDimitry Andric } 593*e8d8bef9SDimitry Andric 594*e8d8bef9SDimitry Andric Expected<std::unique_ptr<ExpressionAST>> 595*e8d8bef9SDimitry Andric Pattern::parseParenExpr(StringRef &Expr, Optional<size_t> LineNumber, 596*e8d8bef9SDimitry Andric FileCheckPatternContext *Context, const SourceMgr &SM) { 597*e8d8bef9SDimitry Andric Expr = Expr.ltrim(SpaceChars); 598*e8d8bef9SDimitry Andric assert(Expr.startswith("(")); 599*e8d8bef9SDimitry Andric 600*e8d8bef9SDimitry Andric // Parse right operand. 601*e8d8bef9SDimitry Andric Expr.consume_front("("); 602*e8d8bef9SDimitry Andric Expr = Expr.ltrim(SpaceChars); 603*e8d8bef9SDimitry Andric if (Expr.empty()) 604*e8d8bef9SDimitry Andric return ErrorDiagnostic::get(SM, Expr, "missing operand in expression"); 605*e8d8bef9SDimitry Andric 606*e8d8bef9SDimitry Andric // Note: parseNumericOperand handles nested opening parentheses. 607*e8d8bef9SDimitry Andric Expected<std::unique_ptr<ExpressionAST>> SubExprResult = parseNumericOperand( 608*e8d8bef9SDimitry Andric Expr, AllowedOperand::Any, /*MaybeInvalidConstraint=*/false, LineNumber, 609*e8d8bef9SDimitry Andric Context, SM); 610*e8d8bef9SDimitry Andric Expr = Expr.ltrim(SpaceChars); 611*e8d8bef9SDimitry Andric while (SubExprResult && !Expr.empty() && !Expr.startswith(")")) { 612*e8d8bef9SDimitry Andric StringRef OrigExpr = Expr; 613*e8d8bef9SDimitry Andric SubExprResult = parseBinop(OrigExpr, Expr, std::move(*SubExprResult), false, 614*e8d8bef9SDimitry Andric LineNumber, Context, SM); 615*e8d8bef9SDimitry Andric Expr = Expr.ltrim(SpaceChars); 616*e8d8bef9SDimitry Andric } 617*e8d8bef9SDimitry Andric if (!SubExprResult) 618*e8d8bef9SDimitry Andric return SubExprResult; 619*e8d8bef9SDimitry Andric 620*e8d8bef9SDimitry Andric if (!Expr.consume_front(")")) { 621*e8d8bef9SDimitry Andric return ErrorDiagnostic::get(SM, Expr, 622*e8d8bef9SDimitry Andric "missing ')' at end of nested expression"); 623*e8d8bef9SDimitry Andric } 624*e8d8bef9SDimitry Andric return SubExprResult; 625*e8d8bef9SDimitry Andric } 626*e8d8bef9SDimitry Andric 627*e8d8bef9SDimitry Andric Expected<std::unique_ptr<ExpressionAST>> 628*e8d8bef9SDimitry Andric Pattern::parseBinop(StringRef Expr, StringRef &RemainingExpr, 629*e8d8bef9SDimitry Andric std::unique_ptr<ExpressionAST> LeftOp, 630*e8d8bef9SDimitry Andric bool IsLegacyLineExpr, Optional<size_t> LineNumber, 631*e8d8bef9SDimitry Andric FileCheckPatternContext *Context, const SourceMgr &SM) { 632*e8d8bef9SDimitry Andric RemainingExpr = RemainingExpr.ltrim(SpaceChars); 633*e8d8bef9SDimitry Andric if (RemainingExpr.empty()) 634*e8d8bef9SDimitry Andric return std::move(LeftOp); 635*e8d8bef9SDimitry Andric 636*e8d8bef9SDimitry Andric // Check if this is a supported operation and select a function to perform 637*e8d8bef9SDimitry Andric // it. 638*e8d8bef9SDimitry Andric SMLoc OpLoc = SMLoc::getFromPointer(RemainingExpr.data()); 639*e8d8bef9SDimitry Andric char Operator = popFront(RemainingExpr); 640*e8d8bef9SDimitry Andric binop_eval_t EvalBinop; 641*e8d8bef9SDimitry Andric switch (Operator) { 642*e8d8bef9SDimitry Andric case '+': 643*e8d8bef9SDimitry Andric EvalBinop = operator+; 644*e8d8bef9SDimitry Andric break; 645*e8d8bef9SDimitry Andric case '-': 646*e8d8bef9SDimitry Andric EvalBinop = operator-; 647*e8d8bef9SDimitry Andric break; 648*e8d8bef9SDimitry Andric default: 649*e8d8bef9SDimitry Andric return ErrorDiagnostic::get( 650*e8d8bef9SDimitry Andric SM, OpLoc, Twine("unsupported operation '") + Twine(Operator) + "'"); 651*e8d8bef9SDimitry Andric } 652*e8d8bef9SDimitry Andric 653*e8d8bef9SDimitry Andric // Parse right operand. 654*e8d8bef9SDimitry Andric RemainingExpr = RemainingExpr.ltrim(SpaceChars); 655*e8d8bef9SDimitry Andric if (RemainingExpr.empty()) 656*e8d8bef9SDimitry Andric return ErrorDiagnostic::get(SM, RemainingExpr, 657*e8d8bef9SDimitry Andric "missing operand in expression"); 658*e8d8bef9SDimitry Andric // The second operand in a legacy @LINE expression is always a literal. 659*e8d8bef9SDimitry Andric AllowedOperand AO = 660*e8d8bef9SDimitry Andric IsLegacyLineExpr ? AllowedOperand::LegacyLiteral : AllowedOperand::Any; 661*e8d8bef9SDimitry Andric Expected<std::unique_ptr<ExpressionAST>> RightOpResult = 662*e8d8bef9SDimitry Andric parseNumericOperand(RemainingExpr, AO, /*MaybeInvalidConstraint=*/false, 663*e8d8bef9SDimitry Andric LineNumber, Context, SM); 664*e8d8bef9SDimitry Andric if (!RightOpResult) 665*e8d8bef9SDimitry Andric return RightOpResult; 666*e8d8bef9SDimitry Andric 667*e8d8bef9SDimitry Andric Expr = Expr.drop_back(RemainingExpr.size()); 668*e8d8bef9SDimitry Andric return std::make_unique<BinaryOperation>(Expr, EvalBinop, std::move(LeftOp), 669*e8d8bef9SDimitry Andric std::move(*RightOpResult)); 670*e8d8bef9SDimitry Andric } 671*e8d8bef9SDimitry Andric 672*e8d8bef9SDimitry Andric Expected<std::unique_ptr<ExpressionAST>> 673*e8d8bef9SDimitry Andric Pattern::parseCallExpr(StringRef &Expr, StringRef FuncName, 674*e8d8bef9SDimitry Andric Optional<size_t> LineNumber, 675*e8d8bef9SDimitry Andric FileCheckPatternContext *Context, const SourceMgr &SM) { 676*e8d8bef9SDimitry Andric Expr = Expr.ltrim(SpaceChars); 677*e8d8bef9SDimitry Andric assert(Expr.startswith("(")); 678*e8d8bef9SDimitry Andric 679*e8d8bef9SDimitry Andric auto OptFunc = StringSwitch<Optional<binop_eval_t>>(FuncName) 680*e8d8bef9SDimitry Andric .Case("add", operator+) 681*e8d8bef9SDimitry Andric .Case("div", operator/) 682*e8d8bef9SDimitry Andric .Case("max", max) 683*e8d8bef9SDimitry Andric .Case("min", min) 684*e8d8bef9SDimitry Andric .Case("mul", operator*) 685*e8d8bef9SDimitry Andric .Case("sub", operator-) 686*e8d8bef9SDimitry Andric .Default(None); 687*e8d8bef9SDimitry Andric 688*e8d8bef9SDimitry Andric if (!OptFunc) 689*e8d8bef9SDimitry Andric return ErrorDiagnostic::get( 690*e8d8bef9SDimitry Andric SM, FuncName, Twine("call to undefined function '") + FuncName + "'"); 691*e8d8bef9SDimitry Andric 692*e8d8bef9SDimitry Andric Expr.consume_front("("); 693*e8d8bef9SDimitry Andric Expr = Expr.ltrim(SpaceChars); 694*e8d8bef9SDimitry Andric 695*e8d8bef9SDimitry Andric // Parse call arguments, which are comma separated. 696*e8d8bef9SDimitry Andric SmallVector<std::unique_ptr<ExpressionAST>, 4> Args; 697*e8d8bef9SDimitry Andric while (!Expr.empty() && !Expr.startswith(")")) { 698*e8d8bef9SDimitry Andric if (Expr.startswith(",")) 699*e8d8bef9SDimitry Andric return ErrorDiagnostic::get(SM, Expr, "missing argument"); 700*e8d8bef9SDimitry Andric 701*e8d8bef9SDimitry Andric // Parse the argument, which is an arbitary expression. 702*e8d8bef9SDimitry Andric StringRef OuterBinOpExpr = Expr; 703*e8d8bef9SDimitry Andric Expected<std::unique_ptr<ExpressionAST>> Arg = parseNumericOperand( 704*e8d8bef9SDimitry Andric Expr, AllowedOperand::Any, /*MaybeInvalidConstraint=*/false, LineNumber, 705*e8d8bef9SDimitry Andric Context, SM); 706*e8d8bef9SDimitry Andric while (Arg && !Expr.empty()) { 707*e8d8bef9SDimitry Andric Expr = Expr.ltrim(SpaceChars); 708*e8d8bef9SDimitry Andric // Have we reached an argument terminator? 709*e8d8bef9SDimitry Andric if (Expr.startswith(",") || Expr.startswith(")")) 710*e8d8bef9SDimitry Andric break; 711*e8d8bef9SDimitry Andric 712*e8d8bef9SDimitry Andric // Arg = Arg <op> <expr> 713*e8d8bef9SDimitry Andric Arg = parseBinop(OuterBinOpExpr, Expr, std::move(*Arg), false, LineNumber, 714*e8d8bef9SDimitry Andric Context, SM); 715*e8d8bef9SDimitry Andric } 716*e8d8bef9SDimitry Andric 717*e8d8bef9SDimitry Andric // Prefer an expression error over a generic invalid argument message. 718*e8d8bef9SDimitry Andric if (!Arg) 719*e8d8bef9SDimitry Andric return Arg.takeError(); 720*e8d8bef9SDimitry Andric Args.push_back(std::move(*Arg)); 721*e8d8bef9SDimitry Andric 722*e8d8bef9SDimitry Andric // Have we parsed all available arguments? 723*e8d8bef9SDimitry Andric Expr = Expr.ltrim(SpaceChars); 724*e8d8bef9SDimitry Andric if (!Expr.consume_front(",")) 725*e8d8bef9SDimitry Andric break; 726*e8d8bef9SDimitry Andric 727*e8d8bef9SDimitry Andric Expr = Expr.ltrim(SpaceChars); 728*e8d8bef9SDimitry Andric if (Expr.startswith(")")) 729*e8d8bef9SDimitry Andric return ErrorDiagnostic::get(SM, Expr, "missing argument"); 730*e8d8bef9SDimitry Andric } 731*e8d8bef9SDimitry Andric 732*e8d8bef9SDimitry Andric if (!Expr.consume_front(")")) 733*e8d8bef9SDimitry Andric return ErrorDiagnostic::get(SM, Expr, 734*e8d8bef9SDimitry Andric "missing ')' at end of call expression"); 735*e8d8bef9SDimitry Andric 736*e8d8bef9SDimitry Andric const unsigned NumArgs = Args.size(); 737*e8d8bef9SDimitry Andric if (NumArgs == 2) 738*e8d8bef9SDimitry Andric return std::make_unique<BinaryOperation>(Expr, *OptFunc, std::move(Args[0]), 739*e8d8bef9SDimitry Andric std::move(Args[1])); 740*e8d8bef9SDimitry Andric 741*e8d8bef9SDimitry Andric // TODO: Support more than binop_eval_t. 742*e8d8bef9SDimitry Andric return ErrorDiagnostic::get(SM, FuncName, 743*e8d8bef9SDimitry Andric Twine("function '") + FuncName + 744*e8d8bef9SDimitry Andric Twine("' takes 2 arguments but ") + 745*e8d8bef9SDimitry Andric Twine(NumArgs) + " given"); 746*e8d8bef9SDimitry Andric } 747*e8d8bef9SDimitry Andric 748*e8d8bef9SDimitry Andric Expected<std::unique_ptr<Expression>> Pattern::parseNumericSubstitutionBlock( 749*e8d8bef9SDimitry Andric StringRef Expr, Optional<NumericVariable *> &DefinedNumericVariable, 750*e8d8bef9SDimitry Andric bool IsLegacyLineExpr, Optional<size_t> LineNumber, 751*e8d8bef9SDimitry Andric FileCheckPatternContext *Context, const SourceMgr &SM) { 752*e8d8bef9SDimitry Andric std::unique_ptr<ExpressionAST> ExpressionASTPointer = nullptr; 753*e8d8bef9SDimitry Andric StringRef DefExpr = StringRef(); 754*e8d8bef9SDimitry Andric DefinedNumericVariable = None; 755*e8d8bef9SDimitry Andric ExpressionFormat ExplicitFormat = ExpressionFormat(); 756*e8d8bef9SDimitry Andric unsigned Precision = 0; 757*e8d8bef9SDimitry Andric 758*e8d8bef9SDimitry Andric // Parse format specifier (NOTE: ',' is also an argument seperator). 759*e8d8bef9SDimitry Andric size_t FormatSpecEnd = Expr.find(','); 760*e8d8bef9SDimitry Andric size_t FunctionStart = Expr.find('('); 761*e8d8bef9SDimitry Andric if (FormatSpecEnd != StringRef::npos && FormatSpecEnd < FunctionStart) { 762*e8d8bef9SDimitry Andric StringRef FormatExpr = Expr.take_front(FormatSpecEnd); 763*e8d8bef9SDimitry Andric Expr = Expr.drop_front(FormatSpecEnd + 1); 764*e8d8bef9SDimitry Andric FormatExpr = FormatExpr.trim(SpaceChars); 765*e8d8bef9SDimitry Andric if (!FormatExpr.consume_front("%")) 766*e8d8bef9SDimitry Andric return ErrorDiagnostic::get( 767*e8d8bef9SDimitry Andric SM, FormatExpr, 768*e8d8bef9SDimitry Andric "invalid matching format specification in expression"); 769*e8d8bef9SDimitry Andric 770*e8d8bef9SDimitry Andric // Parse precision. 771*e8d8bef9SDimitry Andric if (FormatExpr.consume_front(".")) { 772*e8d8bef9SDimitry Andric if (FormatExpr.consumeInteger(10, Precision)) 773*e8d8bef9SDimitry Andric return ErrorDiagnostic::get(SM, FormatExpr, 774*e8d8bef9SDimitry Andric "invalid precision in format specifier"); 775*e8d8bef9SDimitry Andric } 776*e8d8bef9SDimitry Andric 777*e8d8bef9SDimitry Andric if (!FormatExpr.empty()) { 778*e8d8bef9SDimitry Andric // Check for unknown matching format specifier and set matching format in 779*e8d8bef9SDimitry Andric // class instance representing this expression. 780*e8d8bef9SDimitry Andric SMLoc FmtLoc = SMLoc::getFromPointer(FormatExpr.data()); 781*e8d8bef9SDimitry Andric switch (popFront(FormatExpr)) { 782*e8d8bef9SDimitry Andric case 'u': 783*e8d8bef9SDimitry Andric ExplicitFormat = 784*e8d8bef9SDimitry Andric ExpressionFormat(ExpressionFormat::Kind::Unsigned, Precision); 785*e8d8bef9SDimitry Andric break; 786*e8d8bef9SDimitry Andric case 'd': 787*e8d8bef9SDimitry Andric ExplicitFormat = 788*e8d8bef9SDimitry Andric ExpressionFormat(ExpressionFormat::Kind::Signed, Precision); 789*e8d8bef9SDimitry Andric break; 790*e8d8bef9SDimitry Andric case 'x': 791*e8d8bef9SDimitry Andric ExplicitFormat = 792*e8d8bef9SDimitry Andric ExpressionFormat(ExpressionFormat::Kind::HexLower, Precision); 793*e8d8bef9SDimitry Andric break; 794*e8d8bef9SDimitry Andric case 'X': 795*e8d8bef9SDimitry Andric ExplicitFormat = 796*e8d8bef9SDimitry Andric ExpressionFormat(ExpressionFormat::Kind::HexUpper, Precision); 797*e8d8bef9SDimitry Andric break; 798*e8d8bef9SDimitry Andric default: 799*e8d8bef9SDimitry Andric return ErrorDiagnostic::get(SM, FmtLoc, 800*e8d8bef9SDimitry Andric "invalid format specifier in expression"); 801*e8d8bef9SDimitry Andric } 802*e8d8bef9SDimitry Andric } 803*e8d8bef9SDimitry Andric 804*e8d8bef9SDimitry Andric FormatExpr = FormatExpr.ltrim(SpaceChars); 805*e8d8bef9SDimitry Andric if (!FormatExpr.empty()) 806*e8d8bef9SDimitry Andric return ErrorDiagnostic::get( 807*e8d8bef9SDimitry Andric SM, FormatExpr, 808*e8d8bef9SDimitry Andric "invalid matching format specification in expression"); 809*e8d8bef9SDimitry Andric } 810*e8d8bef9SDimitry Andric 811*e8d8bef9SDimitry Andric // Save variable definition expression if any. 812*e8d8bef9SDimitry Andric size_t DefEnd = Expr.find(':'); 813*e8d8bef9SDimitry Andric if (DefEnd != StringRef::npos) { 814*e8d8bef9SDimitry Andric DefExpr = Expr.substr(0, DefEnd); 815*e8d8bef9SDimitry Andric Expr = Expr.substr(DefEnd + 1); 816*e8d8bef9SDimitry Andric } 817*e8d8bef9SDimitry Andric 818*e8d8bef9SDimitry Andric // Parse matching constraint. 819*e8d8bef9SDimitry Andric Expr = Expr.ltrim(SpaceChars); 820*e8d8bef9SDimitry Andric bool HasParsedValidConstraint = false; 821*e8d8bef9SDimitry Andric if (Expr.consume_front("==")) 822*e8d8bef9SDimitry Andric HasParsedValidConstraint = true; 823*e8d8bef9SDimitry Andric 824*e8d8bef9SDimitry Andric // Parse the expression itself. 825*e8d8bef9SDimitry Andric Expr = Expr.ltrim(SpaceChars); 826*e8d8bef9SDimitry Andric if (Expr.empty()) { 827*e8d8bef9SDimitry Andric if (HasParsedValidConstraint) 828*e8d8bef9SDimitry Andric return ErrorDiagnostic::get( 829*e8d8bef9SDimitry Andric SM, Expr, "empty numeric expression should not have a constraint"); 830*e8d8bef9SDimitry Andric } else { 831*e8d8bef9SDimitry Andric Expr = Expr.rtrim(SpaceChars); 832*e8d8bef9SDimitry Andric StringRef OuterBinOpExpr = Expr; 833*e8d8bef9SDimitry Andric // The first operand in a legacy @LINE expression is always the @LINE 834*e8d8bef9SDimitry Andric // pseudo variable. 835*e8d8bef9SDimitry Andric AllowedOperand AO = 836*e8d8bef9SDimitry Andric IsLegacyLineExpr ? AllowedOperand::LineVar : AllowedOperand::Any; 837*e8d8bef9SDimitry Andric Expected<std::unique_ptr<ExpressionAST>> ParseResult = parseNumericOperand( 838*e8d8bef9SDimitry Andric Expr, AO, !HasParsedValidConstraint, LineNumber, Context, SM); 839*e8d8bef9SDimitry Andric while (ParseResult && !Expr.empty()) { 840*e8d8bef9SDimitry Andric ParseResult = parseBinop(OuterBinOpExpr, Expr, std::move(*ParseResult), 841*e8d8bef9SDimitry Andric IsLegacyLineExpr, LineNumber, Context, SM); 842*e8d8bef9SDimitry Andric // Legacy @LINE expressions only allow 2 operands. 843*e8d8bef9SDimitry Andric if (ParseResult && IsLegacyLineExpr && !Expr.empty()) 844*e8d8bef9SDimitry Andric return ErrorDiagnostic::get( 845*e8d8bef9SDimitry Andric SM, Expr, 846*e8d8bef9SDimitry Andric "unexpected characters at end of expression '" + Expr + "'"); 847*e8d8bef9SDimitry Andric } 848*e8d8bef9SDimitry Andric if (!ParseResult) 849*e8d8bef9SDimitry Andric return ParseResult.takeError(); 850*e8d8bef9SDimitry Andric ExpressionASTPointer = std::move(*ParseResult); 851*e8d8bef9SDimitry Andric } 852*e8d8bef9SDimitry Andric 853*e8d8bef9SDimitry Andric // Select format of the expression, i.e. (i) its explicit format, if any, 854*e8d8bef9SDimitry Andric // otherwise (ii) its implicit format, if any, otherwise (iii) the default 855*e8d8bef9SDimitry Andric // format (unsigned). Error out in case of conflicting implicit format 856*e8d8bef9SDimitry Andric // without explicit format. 857*e8d8bef9SDimitry Andric ExpressionFormat Format; 858*e8d8bef9SDimitry Andric if (ExplicitFormat) 859*e8d8bef9SDimitry Andric Format = ExplicitFormat; 860*e8d8bef9SDimitry Andric else if (ExpressionASTPointer) { 861*e8d8bef9SDimitry Andric Expected<ExpressionFormat> ImplicitFormat = 862*e8d8bef9SDimitry Andric ExpressionASTPointer->getImplicitFormat(SM); 863*e8d8bef9SDimitry Andric if (!ImplicitFormat) 864*e8d8bef9SDimitry Andric return ImplicitFormat.takeError(); 865*e8d8bef9SDimitry Andric Format = *ImplicitFormat; 866*e8d8bef9SDimitry Andric } 867*e8d8bef9SDimitry Andric if (!Format) 868*e8d8bef9SDimitry Andric Format = ExpressionFormat(ExpressionFormat::Kind::Unsigned, Precision); 869*e8d8bef9SDimitry Andric 870*e8d8bef9SDimitry Andric std::unique_ptr<Expression> ExpressionPointer = 871*e8d8bef9SDimitry Andric std::make_unique<Expression>(std::move(ExpressionASTPointer), Format); 872*e8d8bef9SDimitry Andric 873*e8d8bef9SDimitry Andric // Parse the numeric variable definition. 874*e8d8bef9SDimitry Andric if (DefEnd != StringRef::npos) { 875*e8d8bef9SDimitry Andric DefExpr = DefExpr.ltrim(SpaceChars); 876*e8d8bef9SDimitry Andric Expected<NumericVariable *> ParseResult = parseNumericVariableDefinition( 877*e8d8bef9SDimitry Andric DefExpr, Context, LineNumber, ExpressionPointer->getFormat(), SM); 878*e8d8bef9SDimitry Andric 879*e8d8bef9SDimitry Andric if (!ParseResult) 880*e8d8bef9SDimitry Andric return ParseResult.takeError(); 881*e8d8bef9SDimitry Andric DefinedNumericVariable = *ParseResult; 882*e8d8bef9SDimitry Andric } 883*e8d8bef9SDimitry Andric 884*e8d8bef9SDimitry Andric return std::move(ExpressionPointer); 885*e8d8bef9SDimitry Andric } 886*e8d8bef9SDimitry Andric 887*e8d8bef9SDimitry Andric bool Pattern::parsePattern(StringRef PatternStr, StringRef Prefix, 888*e8d8bef9SDimitry Andric SourceMgr &SM, const FileCheckRequest &Req) { 889*e8d8bef9SDimitry Andric bool MatchFullLinesHere = Req.MatchFullLines && CheckTy != Check::CheckNot; 890*e8d8bef9SDimitry Andric IgnoreCase = Req.IgnoreCase; 891*e8d8bef9SDimitry Andric 892*e8d8bef9SDimitry Andric PatternLoc = SMLoc::getFromPointer(PatternStr.data()); 893*e8d8bef9SDimitry Andric 894*e8d8bef9SDimitry Andric if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines)) 895*e8d8bef9SDimitry Andric // Ignore trailing whitespace. 896*e8d8bef9SDimitry Andric while (!PatternStr.empty() && 897*e8d8bef9SDimitry Andric (PatternStr.back() == ' ' || PatternStr.back() == '\t')) 898*e8d8bef9SDimitry Andric PatternStr = PatternStr.substr(0, PatternStr.size() - 1); 899*e8d8bef9SDimitry Andric 900*e8d8bef9SDimitry Andric // Check that there is something on the line. 901*e8d8bef9SDimitry Andric if (PatternStr.empty() && CheckTy != Check::CheckEmpty) { 902*e8d8bef9SDimitry Andric SM.PrintMessage(PatternLoc, SourceMgr::DK_Error, 903*e8d8bef9SDimitry Andric "found empty check string with prefix '" + Prefix + ":'"); 904*e8d8bef9SDimitry Andric return true; 905*e8d8bef9SDimitry Andric } 906*e8d8bef9SDimitry Andric 907*e8d8bef9SDimitry Andric if (!PatternStr.empty() && CheckTy == Check::CheckEmpty) { 908*e8d8bef9SDimitry Andric SM.PrintMessage( 909*e8d8bef9SDimitry Andric PatternLoc, SourceMgr::DK_Error, 910*e8d8bef9SDimitry Andric "found non-empty check string for empty check with prefix '" + Prefix + 911*e8d8bef9SDimitry Andric ":'"); 912*e8d8bef9SDimitry Andric return true; 913*e8d8bef9SDimitry Andric } 914*e8d8bef9SDimitry Andric 915*e8d8bef9SDimitry Andric if (CheckTy == Check::CheckEmpty) { 916*e8d8bef9SDimitry Andric RegExStr = "(\n$)"; 917*e8d8bef9SDimitry Andric return false; 918*e8d8bef9SDimitry Andric } 919*e8d8bef9SDimitry Andric 920*e8d8bef9SDimitry Andric // If literal check, set fixed string. 921*e8d8bef9SDimitry Andric if (CheckTy.isLiteralMatch()) { 922*e8d8bef9SDimitry Andric FixedStr = PatternStr; 923*e8d8bef9SDimitry Andric return false; 924*e8d8bef9SDimitry Andric } 925*e8d8bef9SDimitry Andric 926*e8d8bef9SDimitry Andric // Check to see if this is a fixed string, or if it has regex pieces. 927*e8d8bef9SDimitry Andric if (!MatchFullLinesHere && 928*e8d8bef9SDimitry Andric (PatternStr.size() < 2 || (PatternStr.find("{{") == StringRef::npos && 929*e8d8bef9SDimitry Andric PatternStr.find("[[") == StringRef::npos))) { 930*e8d8bef9SDimitry Andric FixedStr = PatternStr; 931*e8d8bef9SDimitry Andric return false; 932*e8d8bef9SDimitry Andric } 933*e8d8bef9SDimitry Andric 934*e8d8bef9SDimitry Andric if (MatchFullLinesHere) { 935*e8d8bef9SDimitry Andric RegExStr += '^'; 936*e8d8bef9SDimitry Andric if (!Req.NoCanonicalizeWhiteSpace) 937*e8d8bef9SDimitry Andric RegExStr += " *"; 938*e8d8bef9SDimitry Andric } 939*e8d8bef9SDimitry Andric 940*e8d8bef9SDimitry Andric // Paren value #0 is for the fully matched string. Any new parenthesized 941*e8d8bef9SDimitry Andric // values add from there. 942*e8d8bef9SDimitry Andric unsigned CurParen = 1; 943*e8d8bef9SDimitry Andric 944*e8d8bef9SDimitry Andric // Otherwise, there is at least one regex piece. Build up the regex pattern 945*e8d8bef9SDimitry Andric // by escaping scary characters in fixed strings, building up one big regex. 946*e8d8bef9SDimitry Andric while (!PatternStr.empty()) { 947*e8d8bef9SDimitry Andric // RegEx matches. 948*e8d8bef9SDimitry Andric if (PatternStr.startswith("{{")) { 949*e8d8bef9SDimitry Andric // This is the start of a regex match. Scan for the }}. 950*e8d8bef9SDimitry Andric size_t End = PatternStr.find("}}"); 951*e8d8bef9SDimitry Andric if (End == StringRef::npos) { 952*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), 953*e8d8bef9SDimitry Andric SourceMgr::DK_Error, 954*e8d8bef9SDimitry Andric "found start of regex string with no end '}}'"); 955*e8d8bef9SDimitry Andric return true; 956*e8d8bef9SDimitry Andric } 957*e8d8bef9SDimitry Andric 958*e8d8bef9SDimitry Andric // Enclose {{}} patterns in parens just like [[]] even though we're not 959*e8d8bef9SDimitry Andric // capturing the result for any purpose. This is required in case the 960*e8d8bef9SDimitry Andric // expression contains an alternation like: CHECK: abc{{x|z}}def. We 961*e8d8bef9SDimitry Andric // want this to turn into: "abc(x|z)def" not "abcx|zdef". 962*e8d8bef9SDimitry Andric RegExStr += '('; 963*e8d8bef9SDimitry Andric ++CurParen; 964*e8d8bef9SDimitry Andric 965*e8d8bef9SDimitry Andric if (AddRegExToRegEx(PatternStr.substr(2, End - 2), CurParen, SM)) 966*e8d8bef9SDimitry Andric return true; 967*e8d8bef9SDimitry Andric RegExStr += ')'; 968*e8d8bef9SDimitry Andric 969*e8d8bef9SDimitry Andric PatternStr = PatternStr.substr(End + 2); 970*e8d8bef9SDimitry Andric continue; 971*e8d8bef9SDimitry Andric } 972*e8d8bef9SDimitry Andric 973*e8d8bef9SDimitry Andric // String and numeric substitution blocks. Pattern substitution blocks come 974*e8d8bef9SDimitry Andric // in two forms: [[foo:.*]] and [[foo]]. The former matches .* (or some 975*e8d8bef9SDimitry Andric // other regex) and assigns it to the string variable 'foo'. The latter 976*e8d8bef9SDimitry Andric // substitutes foo's value. Numeric substitution blocks recognize the same 977*e8d8bef9SDimitry Andric // form as string ones, but start with a '#' sign after the double 978*e8d8bef9SDimitry Andric // brackets. They also accept a combined form which sets a numeric variable 979*e8d8bef9SDimitry Andric // to the evaluation of an expression. Both string and numeric variable 980*e8d8bef9SDimitry Andric // names must satisfy the regular expression "[a-zA-Z_][0-9a-zA-Z_]*" to be 981*e8d8bef9SDimitry Andric // valid, as this helps catch some common errors. 982*e8d8bef9SDimitry Andric if (PatternStr.startswith("[[")) { 983*e8d8bef9SDimitry Andric StringRef UnparsedPatternStr = PatternStr.substr(2); 984*e8d8bef9SDimitry Andric // Find the closing bracket pair ending the match. End is going to be an 985*e8d8bef9SDimitry Andric // offset relative to the beginning of the match string. 986*e8d8bef9SDimitry Andric size_t End = FindRegexVarEnd(UnparsedPatternStr, SM); 987*e8d8bef9SDimitry Andric StringRef MatchStr = UnparsedPatternStr.substr(0, End); 988*e8d8bef9SDimitry Andric bool IsNumBlock = MatchStr.consume_front("#"); 989*e8d8bef9SDimitry Andric 990*e8d8bef9SDimitry Andric if (End == StringRef::npos) { 991*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), 992*e8d8bef9SDimitry Andric SourceMgr::DK_Error, 993*e8d8bef9SDimitry Andric "Invalid substitution block, no ]] found"); 994*e8d8bef9SDimitry Andric return true; 995*e8d8bef9SDimitry Andric } 996*e8d8bef9SDimitry Andric // Strip the substitution block we are parsing. End points to the start 997*e8d8bef9SDimitry Andric // of the "]]" closing the expression so account for it in computing the 998*e8d8bef9SDimitry Andric // index of the first unparsed character. 999*e8d8bef9SDimitry Andric PatternStr = UnparsedPatternStr.substr(End + 2); 1000*e8d8bef9SDimitry Andric 1001*e8d8bef9SDimitry Andric bool IsDefinition = false; 1002*e8d8bef9SDimitry Andric bool SubstNeeded = false; 1003*e8d8bef9SDimitry Andric // Whether the substitution block is a legacy use of @LINE with string 1004*e8d8bef9SDimitry Andric // substitution block syntax. 1005*e8d8bef9SDimitry Andric bool IsLegacyLineExpr = false; 1006*e8d8bef9SDimitry Andric StringRef DefName; 1007*e8d8bef9SDimitry Andric StringRef SubstStr; 1008*e8d8bef9SDimitry Andric std::string MatchRegexp; 1009*e8d8bef9SDimitry Andric size_t SubstInsertIdx = RegExStr.size(); 1010*e8d8bef9SDimitry Andric 1011*e8d8bef9SDimitry Andric // Parse string variable or legacy @LINE expression. 1012*e8d8bef9SDimitry Andric if (!IsNumBlock) { 1013*e8d8bef9SDimitry Andric size_t VarEndIdx = MatchStr.find(':'); 1014*e8d8bef9SDimitry Andric size_t SpacePos = MatchStr.substr(0, VarEndIdx).find_first_of(" \t"); 1015*e8d8bef9SDimitry Andric if (SpacePos != StringRef::npos) { 1016*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(MatchStr.data() + SpacePos), 1017*e8d8bef9SDimitry Andric SourceMgr::DK_Error, "unexpected whitespace"); 1018*e8d8bef9SDimitry Andric return true; 1019*e8d8bef9SDimitry Andric } 1020*e8d8bef9SDimitry Andric 1021*e8d8bef9SDimitry Andric // Get the name (e.g. "foo") and verify it is well formed. 1022*e8d8bef9SDimitry Andric StringRef OrigMatchStr = MatchStr; 1023*e8d8bef9SDimitry Andric Expected<Pattern::VariableProperties> ParseVarResult = 1024*e8d8bef9SDimitry Andric parseVariable(MatchStr, SM); 1025*e8d8bef9SDimitry Andric if (!ParseVarResult) { 1026*e8d8bef9SDimitry Andric logAllUnhandledErrors(ParseVarResult.takeError(), errs()); 1027*e8d8bef9SDimitry Andric return true; 1028*e8d8bef9SDimitry Andric } 1029*e8d8bef9SDimitry Andric StringRef Name = ParseVarResult->Name; 1030*e8d8bef9SDimitry Andric bool IsPseudo = ParseVarResult->IsPseudo; 1031*e8d8bef9SDimitry Andric 1032*e8d8bef9SDimitry Andric IsDefinition = (VarEndIdx != StringRef::npos); 1033*e8d8bef9SDimitry Andric SubstNeeded = !IsDefinition; 1034*e8d8bef9SDimitry Andric if (IsDefinition) { 1035*e8d8bef9SDimitry Andric if ((IsPseudo || !MatchStr.consume_front(":"))) { 1036*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(Name.data()), 1037*e8d8bef9SDimitry Andric SourceMgr::DK_Error, 1038*e8d8bef9SDimitry Andric "invalid name in string variable definition"); 1039*e8d8bef9SDimitry Andric return true; 1040*e8d8bef9SDimitry Andric } 1041*e8d8bef9SDimitry Andric 1042*e8d8bef9SDimitry Andric // Detect collisions between string and numeric variables when the 1043*e8d8bef9SDimitry Andric // former is created later than the latter. 1044*e8d8bef9SDimitry Andric if (Context->GlobalNumericVariableTable.find(Name) != 1045*e8d8bef9SDimitry Andric Context->GlobalNumericVariableTable.end()) { 1046*e8d8bef9SDimitry Andric SM.PrintMessage( 1047*e8d8bef9SDimitry Andric SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, 1048*e8d8bef9SDimitry Andric "numeric variable with name '" + Name + "' already exists"); 1049*e8d8bef9SDimitry Andric return true; 1050*e8d8bef9SDimitry Andric } 1051*e8d8bef9SDimitry Andric DefName = Name; 1052*e8d8bef9SDimitry Andric MatchRegexp = MatchStr.str(); 1053*e8d8bef9SDimitry Andric } else { 1054*e8d8bef9SDimitry Andric if (IsPseudo) { 1055*e8d8bef9SDimitry Andric MatchStr = OrigMatchStr; 1056*e8d8bef9SDimitry Andric IsLegacyLineExpr = IsNumBlock = true; 1057*e8d8bef9SDimitry Andric } else 1058*e8d8bef9SDimitry Andric SubstStr = Name; 1059*e8d8bef9SDimitry Andric } 1060*e8d8bef9SDimitry Andric } 1061*e8d8bef9SDimitry Andric 1062*e8d8bef9SDimitry Andric // Parse numeric substitution block. 1063*e8d8bef9SDimitry Andric std::unique_ptr<Expression> ExpressionPointer; 1064*e8d8bef9SDimitry Andric Optional<NumericVariable *> DefinedNumericVariable; 1065*e8d8bef9SDimitry Andric if (IsNumBlock) { 1066*e8d8bef9SDimitry Andric Expected<std::unique_ptr<Expression>> ParseResult = 1067*e8d8bef9SDimitry Andric parseNumericSubstitutionBlock(MatchStr, DefinedNumericVariable, 1068*e8d8bef9SDimitry Andric IsLegacyLineExpr, LineNumber, Context, 1069*e8d8bef9SDimitry Andric SM); 1070*e8d8bef9SDimitry Andric if (!ParseResult) { 1071*e8d8bef9SDimitry Andric logAllUnhandledErrors(ParseResult.takeError(), errs()); 1072*e8d8bef9SDimitry Andric return true; 1073*e8d8bef9SDimitry Andric } 1074*e8d8bef9SDimitry Andric ExpressionPointer = std::move(*ParseResult); 1075*e8d8bef9SDimitry Andric SubstNeeded = ExpressionPointer->getAST() != nullptr; 1076*e8d8bef9SDimitry Andric if (DefinedNumericVariable) { 1077*e8d8bef9SDimitry Andric IsDefinition = true; 1078*e8d8bef9SDimitry Andric DefName = (*DefinedNumericVariable)->getName(); 1079*e8d8bef9SDimitry Andric } 1080*e8d8bef9SDimitry Andric if (SubstNeeded) 1081*e8d8bef9SDimitry Andric SubstStr = MatchStr; 1082*e8d8bef9SDimitry Andric else { 1083*e8d8bef9SDimitry Andric ExpressionFormat Format = ExpressionPointer->getFormat(); 1084*e8d8bef9SDimitry Andric MatchRegexp = cantFail(Format.getWildcardRegex()); 1085*e8d8bef9SDimitry Andric } 1086*e8d8bef9SDimitry Andric } 1087*e8d8bef9SDimitry Andric 1088*e8d8bef9SDimitry Andric // Handle variable definition: [[<def>:(...)]] and [[#(...)<def>:(...)]]. 1089*e8d8bef9SDimitry Andric if (IsDefinition) { 1090*e8d8bef9SDimitry Andric RegExStr += '('; 1091*e8d8bef9SDimitry Andric ++SubstInsertIdx; 1092*e8d8bef9SDimitry Andric 1093*e8d8bef9SDimitry Andric if (IsNumBlock) { 1094*e8d8bef9SDimitry Andric NumericVariableMatch NumericVariableDefinition = { 1095*e8d8bef9SDimitry Andric *DefinedNumericVariable, CurParen}; 1096*e8d8bef9SDimitry Andric NumericVariableDefs[DefName] = NumericVariableDefinition; 1097*e8d8bef9SDimitry Andric // This store is done here rather than in match() to allow 1098*e8d8bef9SDimitry Andric // parseNumericVariableUse() to get the pointer to the class instance 1099*e8d8bef9SDimitry Andric // of the right variable definition corresponding to a given numeric 1100*e8d8bef9SDimitry Andric // variable use. 1101*e8d8bef9SDimitry Andric Context->GlobalNumericVariableTable[DefName] = 1102*e8d8bef9SDimitry Andric *DefinedNumericVariable; 1103*e8d8bef9SDimitry Andric } else { 1104*e8d8bef9SDimitry Andric VariableDefs[DefName] = CurParen; 1105*e8d8bef9SDimitry Andric // Mark string variable as defined to detect collisions between 1106*e8d8bef9SDimitry Andric // string and numeric variables in parseNumericVariableUse() and 1107*e8d8bef9SDimitry Andric // defineCmdlineVariables() when the latter is created later than the 1108*e8d8bef9SDimitry Andric // former. We cannot reuse GlobalVariableTable for this by populating 1109*e8d8bef9SDimitry Andric // it with an empty string since we would then lose the ability to 1110*e8d8bef9SDimitry Andric // detect the use of an undefined variable in match(). 1111*e8d8bef9SDimitry Andric Context->DefinedVariableTable[DefName] = true; 1112*e8d8bef9SDimitry Andric } 1113*e8d8bef9SDimitry Andric 1114*e8d8bef9SDimitry Andric ++CurParen; 1115*e8d8bef9SDimitry Andric } 1116*e8d8bef9SDimitry Andric 1117*e8d8bef9SDimitry Andric if (!MatchRegexp.empty() && AddRegExToRegEx(MatchRegexp, CurParen, SM)) 1118*e8d8bef9SDimitry Andric return true; 1119*e8d8bef9SDimitry Andric 1120*e8d8bef9SDimitry Andric if (IsDefinition) 1121*e8d8bef9SDimitry Andric RegExStr += ')'; 1122*e8d8bef9SDimitry Andric 1123*e8d8bef9SDimitry Andric // Handle substitutions: [[foo]] and [[#<foo expr>]]. 1124*e8d8bef9SDimitry Andric if (SubstNeeded) { 1125*e8d8bef9SDimitry Andric // Handle substitution of string variables that were defined earlier on 1126*e8d8bef9SDimitry Andric // the same line by emitting a backreference. Expressions do not 1127*e8d8bef9SDimitry Andric // support substituting a numeric variable defined on the same line. 1128*e8d8bef9SDimitry Andric if (!IsNumBlock && VariableDefs.find(SubstStr) != VariableDefs.end()) { 1129*e8d8bef9SDimitry Andric unsigned CaptureParenGroup = VariableDefs[SubstStr]; 1130*e8d8bef9SDimitry Andric if (CaptureParenGroup < 1 || CaptureParenGroup > 9) { 1131*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(SubstStr.data()), 1132*e8d8bef9SDimitry Andric SourceMgr::DK_Error, 1133*e8d8bef9SDimitry Andric "Can't back-reference more than 9 variables"); 1134*e8d8bef9SDimitry Andric return true; 1135*e8d8bef9SDimitry Andric } 1136*e8d8bef9SDimitry Andric AddBackrefToRegEx(CaptureParenGroup); 1137*e8d8bef9SDimitry Andric } else { 1138*e8d8bef9SDimitry Andric // Handle substitution of string variables ([[<var>]]) defined in 1139*e8d8bef9SDimitry Andric // previous CHECK patterns, and substitution of expressions. 1140*e8d8bef9SDimitry Andric Substitution *Substitution = 1141*e8d8bef9SDimitry Andric IsNumBlock 1142*e8d8bef9SDimitry Andric ? Context->makeNumericSubstitution( 1143*e8d8bef9SDimitry Andric SubstStr, std::move(ExpressionPointer), SubstInsertIdx) 1144*e8d8bef9SDimitry Andric : Context->makeStringSubstitution(SubstStr, SubstInsertIdx); 1145*e8d8bef9SDimitry Andric Substitutions.push_back(Substitution); 1146*e8d8bef9SDimitry Andric } 1147*e8d8bef9SDimitry Andric } 1148*e8d8bef9SDimitry Andric } 1149*e8d8bef9SDimitry Andric 1150*e8d8bef9SDimitry Andric // Handle fixed string matches. 1151*e8d8bef9SDimitry Andric // Find the end, which is the start of the next regex. 1152*e8d8bef9SDimitry Andric size_t FixedMatchEnd = PatternStr.find("{{"); 1153*e8d8bef9SDimitry Andric FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[[")); 1154*e8d8bef9SDimitry Andric RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd)); 1155*e8d8bef9SDimitry Andric PatternStr = PatternStr.substr(FixedMatchEnd); 1156*e8d8bef9SDimitry Andric } 1157*e8d8bef9SDimitry Andric 1158*e8d8bef9SDimitry Andric if (MatchFullLinesHere) { 1159*e8d8bef9SDimitry Andric if (!Req.NoCanonicalizeWhiteSpace) 1160*e8d8bef9SDimitry Andric RegExStr += " *"; 1161*e8d8bef9SDimitry Andric RegExStr += '$'; 1162*e8d8bef9SDimitry Andric } 1163*e8d8bef9SDimitry Andric 1164*e8d8bef9SDimitry Andric return false; 1165*e8d8bef9SDimitry Andric } 1166*e8d8bef9SDimitry Andric 1167*e8d8bef9SDimitry Andric bool Pattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) { 1168*e8d8bef9SDimitry Andric Regex R(RS); 1169*e8d8bef9SDimitry Andric std::string Error; 1170*e8d8bef9SDimitry Andric if (!R.isValid(Error)) { 1171*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(RS.data()), SourceMgr::DK_Error, 1172*e8d8bef9SDimitry Andric "invalid regex: " + Error); 1173*e8d8bef9SDimitry Andric return true; 1174*e8d8bef9SDimitry Andric } 1175*e8d8bef9SDimitry Andric 1176*e8d8bef9SDimitry Andric RegExStr += RS.str(); 1177*e8d8bef9SDimitry Andric CurParen += R.getNumMatches(); 1178*e8d8bef9SDimitry Andric return false; 1179*e8d8bef9SDimitry Andric } 1180*e8d8bef9SDimitry Andric 1181*e8d8bef9SDimitry Andric void Pattern::AddBackrefToRegEx(unsigned BackrefNum) { 1182*e8d8bef9SDimitry Andric assert(BackrefNum >= 1 && BackrefNum <= 9 && "Invalid backref number"); 1183*e8d8bef9SDimitry Andric std::string Backref = std::string("\\") + std::string(1, '0' + BackrefNum); 1184*e8d8bef9SDimitry Andric RegExStr += Backref; 1185*e8d8bef9SDimitry Andric } 1186*e8d8bef9SDimitry Andric 1187*e8d8bef9SDimitry Andric Expected<size_t> Pattern::match(StringRef Buffer, size_t &MatchLen, 1188*e8d8bef9SDimitry Andric const SourceMgr &SM) const { 1189*e8d8bef9SDimitry Andric // If this is the EOF pattern, match it immediately. 1190*e8d8bef9SDimitry Andric if (CheckTy == Check::CheckEOF) { 1191*e8d8bef9SDimitry Andric MatchLen = 0; 1192*e8d8bef9SDimitry Andric return Buffer.size(); 1193*e8d8bef9SDimitry Andric } 1194*e8d8bef9SDimitry Andric 1195*e8d8bef9SDimitry Andric // If this is a fixed string pattern, just match it now. 1196*e8d8bef9SDimitry Andric if (!FixedStr.empty()) { 1197*e8d8bef9SDimitry Andric MatchLen = FixedStr.size(); 1198*e8d8bef9SDimitry Andric size_t Pos = 1199*e8d8bef9SDimitry Andric IgnoreCase ? Buffer.find_lower(FixedStr) : Buffer.find(FixedStr); 1200*e8d8bef9SDimitry Andric if (Pos == StringRef::npos) 1201*e8d8bef9SDimitry Andric return make_error<NotFoundError>(); 1202*e8d8bef9SDimitry Andric return Pos; 1203*e8d8bef9SDimitry Andric } 1204*e8d8bef9SDimitry Andric 1205*e8d8bef9SDimitry Andric // Regex match. 1206*e8d8bef9SDimitry Andric 1207*e8d8bef9SDimitry Andric // If there are substitutions, we need to create a temporary string with the 1208*e8d8bef9SDimitry Andric // actual value. 1209*e8d8bef9SDimitry Andric StringRef RegExToMatch = RegExStr; 1210*e8d8bef9SDimitry Andric std::string TmpStr; 1211*e8d8bef9SDimitry Andric if (!Substitutions.empty()) { 1212*e8d8bef9SDimitry Andric TmpStr = RegExStr; 1213*e8d8bef9SDimitry Andric if (LineNumber) 1214*e8d8bef9SDimitry Andric Context->LineVariable->setValue(ExpressionValue(*LineNumber)); 1215*e8d8bef9SDimitry Andric 1216*e8d8bef9SDimitry Andric size_t InsertOffset = 0; 1217*e8d8bef9SDimitry Andric // Substitute all string variables and expressions whose values are only 1218*e8d8bef9SDimitry Andric // now known. Use of string variables defined on the same line are handled 1219*e8d8bef9SDimitry Andric // by back-references. 1220*e8d8bef9SDimitry Andric for (const auto &Substitution : Substitutions) { 1221*e8d8bef9SDimitry Andric // Substitute and check for failure (e.g. use of undefined variable). 1222*e8d8bef9SDimitry Andric Expected<std::string> Value = Substitution->getResult(); 1223*e8d8bef9SDimitry Andric if (!Value) { 1224*e8d8bef9SDimitry Andric // Convert to an ErrorDiagnostic to get location information. This is 1225*e8d8bef9SDimitry Andric // done here rather than PrintNoMatch since now we know which 1226*e8d8bef9SDimitry Andric // substitution block caused the overflow. 1227*e8d8bef9SDimitry Andric Error Err = 1228*e8d8bef9SDimitry Andric handleErrors(Value.takeError(), [&](const OverflowError &E) { 1229*e8d8bef9SDimitry Andric return ErrorDiagnostic::get(SM, Substitution->getFromString(), 1230*e8d8bef9SDimitry Andric "unable to substitute variable or " 1231*e8d8bef9SDimitry Andric "numeric expression: overflow error"); 1232*e8d8bef9SDimitry Andric }); 1233*e8d8bef9SDimitry Andric return std::move(Err); 1234*e8d8bef9SDimitry Andric } 1235*e8d8bef9SDimitry Andric 1236*e8d8bef9SDimitry Andric // Plop it into the regex at the adjusted offset. 1237*e8d8bef9SDimitry Andric TmpStr.insert(TmpStr.begin() + Substitution->getIndex() + InsertOffset, 1238*e8d8bef9SDimitry Andric Value->begin(), Value->end()); 1239*e8d8bef9SDimitry Andric InsertOffset += Value->size(); 1240*e8d8bef9SDimitry Andric } 1241*e8d8bef9SDimitry Andric 1242*e8d8bef9SDimitry Andric // Match the newly constructed regex. 1243*e8d8bef9SDimitry Andric RegExToMatch = TmpStr; 1244*e8d8bef9SDimitry Andric } 1245*e8d8bef9SDimitry Andric 1246*e8d8bef9SDimitry Andric SmallVector<StringRef, 4> MatchInfo; 1247*e8d8bef9SDimitry Andric unsigned int Flags = Regex::Newline; 1248*e8d8bef9SDimitry Andric if (IgnoreCase) 1249*e8d8bef9SDimitry Andric Flags |= Regex::IgnoreCase; 1250*e8d8bef9SDimitry Andric if (!Regex(RegExToMatch, Flags).match(Buffer, &MatchInfo)) 1251*e8d8bef9SDimitry Andric return make_error<NotFoundError>(); 1252*e8d8bef9SDimitry Andric 1253*e8d8bef9SDimitry Andric // Successful regex match. 1254*e8d8bef9SDimitry Andric assert(!MatchInfo.empty() && "Didn't get any match"); 1255*e8d8bef9SDimitry Andric StringRef FullMatch = MatchInfo[0]; 1256*e8d8bef9SDimitry Andric 1257*e8d8bef9SDimitry Andric // If this defines any string variables, remember their values. 1258*e8d8bef9SDimitry Andric for (const auto &VariableDef : VariableDefs) { 1259*e8d8bef9SDimitry Andric assert(VariableDef.second < MatchInfo.size() && "Internal paren error"); 1260*e8d8bef9SDimitry Andric Context->GlobalVariableTable[VariableDef.first] = 1261*e8d8bef9SDimitry Andric MatchInfo[VariableDef.second]; 1262*e8d8bef9SDimitry Andric } 1263*e8d8bef9SDimitry Andric 1264*e8d8bef9SDimitry Andric // If this defines any numeric variables, remember their values. 1265*e8d8bef9SDimitry Andric for (const auto &NumericVariableDef : NumericVariableDefs) { 1266*e8d8bef9SDimitry Andric const NumericVariableMatch &NumericVariableMatch = 1267*e8d8bef9SDimitry Andric NumericVariableDef.getValue(); 1268*e8d8bef9SDimitry Andric unsigned CaptureParenGroup = NumericVariableMatch.CaptureParenGroup; 1269*e8d8bef9SDimitry Andric assert(CaptureParenGroup < MatchInfo.size() && "Internal paren error"); 1270*e8d8bef9SDimitry Andric NumericVariable *DefinedNumericVariable = 1271*e8d8bef9SDimitry Andric NumericVariableMatch.DefinedNumericVariable; 1272*e8d8bef9SDimitry Andric 1273*e8d8bef9SDimitry Andric StringRef MatchedValue = MatchInfo[CaptureParenGroup]; 1274*e8d8bef9SDimitry Andric ExpressionFormat Format = DefinedNumericVariable->getImplicitFormat(); 1275*e8d8bef9SDimitry Andric Expected<ExpressionValue> Value = 1276*e8d8bef9SDimitry Andric Format.valueFromStringRepr(MatchedValue, SM); 1277*e8d8bef9SDimitry Andric if (!Value) 1278*e8d8bef9SDimitry Andric return Value.takeError(); 1279*e8d8bef9SDimitry Andric DefinedNumericVariable->setValue(*Value, MatchedValue); 1280*e8d8bef9SDimitry Andric } 1281*e8d8bef9SDimitry Andric 1282*e8d8bef9SDimitry Andric // Like CHECK-NEXT, CHECK-EMPTY's match range is considered to start after 1283*e8d8bef9SDimitry Andric // the required preceding newline, which is consumed by the pattern in the 1284*e8d8bef9SDimitry Andric // case of CHECK-EMPTY but not CHECK-NEXT. 1285*e8d8bef9SDimitry Andric size_t MatchStartSkip = CheckTy == Check::CheckEmpty; 1286*e8d8bef9SDimitry Andric MatchLen = FullMatch.size() - MatchStartSkip; 1287*e8d8bef9SDimitry Andric return FullMatch.data() - Buffer.data() + MatchStartSkip; 1288*e8d8bef9SDimitry Andric } 1289*e8d8bef9SDimitry Andric 1290*e8d8bef9SDimitry Andric unsigned Pattern::computeMatchDistance(StringRef Buffer) const { 1291*e8d8bef9SDimitry Andric // Just compute the number of matching characters. For regular expressions, we 1292*e8d8bef9SDimitry Andric // just compare against the regex itself and hope for the best. 1293*e8d8bef9SDimitry Andric // 1294*e8d8bef9SDimitry Andric // FIXME: One easy improvement here is have the regex lib generate a single 1295*e8d8bef9SDimitry Andric // example regular expression which matches, and use that as the example 1296*e8d8bef9SDimitry Andric // string. 1297*e8d8bef9SDimitry Andric StringRef ExampleString(FixedStr); 1298*e8d8bef9SDimitry Andric if (ExampleString.empty()) 1299*e8d8bef9SDimitry Andric ExampleString = RegExStr; 1300*e8d8bef9SDimitry Andric 1301*e8d8bef9SDimitry Andric // Only compare up to the first line in the buffer, or the string size. 1302*e8d8bef9SDimitry Andric StringRef BufferPrefix = Buffer.substr(0, ExampleString.size()); 1303*e8d8bef9SDimitry Andric BufferPrefix = BufferPrefix.split('\n').first; 1304*e8d8bef9SDimitry Andric return BufferPrefix.edit_distance(ExampleString); 1305*e8d8bef9SDimitry Andric } 1306*e8d8bef9SDimitry Andric 1307*e8d8bef9SDimitry Andric void Pattern::printSubstitutions(const SourceMgr &SM, StringRef Buffer, 1308*e8d8bef9SDimitry Andric SMRange Range, 1309*e8d8bef9SDimitry Andric FileCheckDiag::MatchType MatchTy, 1310*e8d8bef9SDimitry Andric std::vector<FileCheckDiag> *Diags) const { 1311*e8d8bef9SDimitry Andric // Print what we know about substitutions. 1312*e8d8bef9SDimitry Andric if (!Substitutions.empty()) { 1313*e8d8bef9SDimitry Andric for (const auto &Substitution : Substitutions) { 1314*e8d8bef9SDimitry Andric SmallString<256> Msg; 1315*e8d8bef9SDimitry Andric raw_svector_ostream OS(Msg); 1316*e8d8bef9SDimitry Andric Expected<std::string> MatchedValue = Substitution->getResult(); 1317*e8d8bef9SDimitry Andric 1318*e8d8bef9SDimitry Andric // Substitution failed or is not known at match time, print the undefined 1319*e8d8bef9SDimitry Andric // variables it uses. 1320*e8d8bef9SDimitry Andric if (!MatchedValue) { 1321*e8d8bef9SDimitry Andric bool UndefSeen = false; 1322*e8d8bef9SDimitry Andric handleAllErrors( 1323*e8d8bef9SDimitry Andric MatchedValue.takeError(), [](const NotFoundError &E) {}, 1324*e8d8bef9SDimitry Andric // Handled in PrintNoMatch(). 1325*e8d8bef9SDimitry Andric [](const ErrorDiagnostic &E) {}, 1326*e8d8bef9SDimitry Andric // Handled in match(). 1327*e8d8bef9SDimitry Andric [](const OverflowError &E) {}, 1328*e8d8bef9SDimitry Andric [&](const UndefVarError &E) { 1329*e8d8bef9SDimitry Andric if (!UndefSeen) { 1330*e8d8bef9SDimitry Andric OS << "uses undefined variable(s):"; 1331*e8d8bef9SDimitry Andric UndefSeen = true; 1332*e8d8bef9SDimitry Andric } 1333*e8d8bef9SDimitry Andric OS << " "; 1334*e8d8bef9SDimitry Andric E.log(OS); 1335*e8d8bef9SDimitry Andric }); 1336*e8d8bef9SDimitry Andric } else { 1337*e8d8bef9SDimitry Andric // Substitution succeeded. Print substituted value. 1338*e8d8bef9SDimitry Andric OS << "with \""; 1339*e8d8bef9SDimitry Andric OS.write_escaped(Substitution->getFromString()) << "\" equal to \""; 1340*e8d8bef9SDimitry Andric OS.write_escaped(*MatchedValue) << "\""; 1341*e8d8bef9SDimitry Andric } 1342*e8d8bef9SDimitry Andric 1343*e8d8bef9SDimitry Andric // We report only the start of the match/search range to suggest we are 1344*e8d8bef9SDimitry Andric // reporting the substitutions as set at the start of the match/search. 1345*e8d8bef9SDimitry Andric // Indicating a non-zero-length range might instead seem to imply that the 1346*e8d8bef9SDimitry Andric // substitution matches or was captured from exactly that range. 1347*e8d8bef9SDimitry Andric if (Diags) 1348*e8d8bef9SDimitry Andric Diags->emplace_back(SM, CheckTy, getLoc(), MatchTy, 1349*e8d8bef9SDimitry Andric SMRange(Range.Start, Range.Start), OS.str()); 1350*e8d8bef9SDimitry Andric else 1351*e8d8bef9SDimitry Andric SM.PrintMessage(Range.Start, SourceMgr::DK_Note, OS.str()); 1352*e8d8bef9SDimitry Andric } 1353*e8d8bef9SDimitry Andric } 1354*e8d8bef9SDimitry Andric } 1355*e8d8bef9SDimitry Andric 1356*e8d8bef9SDimitry Andric void Pattern::printVariableDefs(const SourceMgr &SM, 1357*e8d8bef9SDimitry Andric FileCheckDiag::MatchType MatchTy, 1358*e8d8bef9SDimitry Andric std::vector<FileCheckDiag> *Diags) const { 1359*e8d8bef9SDimitry Andric if (VariableDefs.empty() && NumericVariableDefs.empty()) 1360*e8d8bef9SDimitry Andric return; 1361*e8d8bef9SDimitry Andric // Build list of variable captures. 1362*e8d8bef9SDimitry Andric struct VarCapture { 1363*e8d8bef9SDimitry Andric StringRef Name; 1364*e8d8bef9SDimitry Andric SMRange Range; 1365*e8d8bef9SDimitry Andric }; 1366*e8d8bef9SDimitry Andric SmallVector<VarCapture, 2> VarCaptures; 1367*e8d8bef9SDimitry Andric for (const auto &VariableDef : VariableDefs) { 1368*e8d8bef9SDimitry Andric VarCapture VC; 1369*e8d8bef9SDimitry Andric VC.Name = VariableDef.first; 1370*e8d8bef9SDimitry Andric StringRef Value = Context->GlobalVariableTable[VC.Name]; 1371*e8d8bef9SDimitry Andric SMLoc Start = SMLoc::getFromPointer(Value.data()); 1372*e8d8bef9SDimitry Andric SMLoc End = SMLoc::getFromPointer(Value.data() + Value.size()); 1373*e8d8bef9SDimitry Andric VC.Range = SMRange(Start, End); 1374*e8d8bef9SDimitry Andric VarCaptures.push_back(VC); 1375*e8d8bef9SDimitry Andric } 1376*e8d8bef9SDimitry Andric for (const auto &VariableDef : NumericVariableDefs) { 1377*e8d8bef9SDimitry Andric VarCapture VC; 1378*e8d8bef9SDimitry Andric VC.Name = VariableDef.getKey(); 1379*e8d8bef9SDimitry Andric StringRef StrValue = VariableDef.getValue() 1380*e8d8bef9SDimitry Andric .DefinedNumericVariable->getStringValue() 1381*e8d8bef9SDimitry Andric .getValue(); 1382*e8d8bef9SDimitry Andric SMLoc Start = SMLoc::getFromPointer(StrValue.data()); 1383*e8d8bef9SDimitry Andric SMLoc End = SMLoc::getFromPointer(StrValue.data() + StrValue.size()); 1384*e8d8bef9SDimitry Andric VC.Range = SMRange(Start, End); 1385*e8d8bef9SDimitry Andric VarCaptures.push_back(VC); 1386*e8d8bef9SDimitry Andric } 1387*e8d8bef9SDimitry Andric // Sort variable captures by the order in which they matched the input. 1388*e8d8bef9SDimitry Andric // Ranges shouldn't be overlapping, so we can just compare the start. 1389*e8d8bef9SDimitry Andric llvm::sort(VarCaptures, [](const VarCapture &A, const VarCapture &B) { 1390*e8d8bef9SDimitry Andric assert(A.Range.Start != B.Range.Start && 1391*e8d8bef9SDimitry Andric "unexpected overlapping variable captures"); 1392*e8d8bef9SDimitry Andric return A.Range.Start.getPointer() < B.Range.Start.getPointer(); 1393*e8d8bef9SDimitry Andric }); 1394*e8d8bef9SDimitry Andric // Create notes for the sorted captures. 1395*e8d8bef9SDimitry Andric for (const VarCapture &VC : VarCaptures) { 1396*e8d8bef9SDimitry Andric SmallString<256> Msg; 1397*e8d8bef9SDimitry Andric raw_svector_ostream OS(Msg); 1398*e8d8bef9SDimitry Andric OS << "captured var \"" << VC.Name << "\""; 1399*e8d8bef9SDimitry Andric if (Diags) 1400*e8d8bef9SDimitry Andric Diags->emplace_back(SM, CheckTy, getLoc(), MatchTy, VC.Range, OS.str()); 1401*e8d8bef9SDimitry Andric else 1402*e8d8bef9SDimitry Andric SM.PrintMessage(VC.Range.Start, SourceMgr::DK_Note, OS.str(), VC.Range); 1403*e8d8bef9SDimitry Andric } 1404*e8d8bef9SDimitry Andric } 1405*e8d8bef9SDimitry Andric 1406*e8d8bef9SDimitry Andric static SMRange ProcessMatchResult(FileCheckDiag::MatchType MatchTy, 1407*e8d8bef9SDimitry Andric const SourceMgr &SM, SMLoc Loc, 1408*e8d8bef9SDimitry Andric Check::FileCheckType CheckTy, 1409*e8d8bef9SDimitry Andric StringRef Buffer, size_t Pos, size_t Len, 1410*e8d8bef9SDimitry Andric std::vector<FileCheckDiag> *Diags, 1411*e8d8bef9SDimitry Andric bool AdjustPrevDiags = false) { 1412*e8d8bef9SDimitry Andric SMLoc Start = SMLoc::getFromPointer(Buffer.data() + Pos); 1413*e8d8bef9SDimitry Andric SMLoc End = SMLoc::getFromPointer(Buffer.data() + Pos + Len); 1414*e8d8bef9SDimitry Andric SMRange Range(Start, End); 1415*e8d8bef9SDimitry Andric if (Diags) { 1416*e8d8bef9SDimitry Andric if (AdjustPrevDiags) { 1417*e8d8bef9SDimitry Andric SMLoc CheckLoc = Diags->rbegin()->CheckLoc; 1418*e8d8bef9SDimitry Andric for (auto I = Diags->rbegin(), E = Diags->rend(); 1419*e8d8bef9SDimitry Andric I != E && I->CheckLoc == CheckLoc; ++I) 1420*e8d8bef9SDimitry Andric I->MatchTy = MatchTy; 1421*e8d8bef9SDimitry Andric } else 1422*e8d8bef9SDimitry Andric Diags->emplace_back(SM, CheckTy, Loc, MatchTy, Range); 1423*e8d8bef9SDimitry Andric } 1424*e8d8bef9SDimitry Andric return Range; 1425*e8d8bef9SDimitry Andric } 1426*e8d8bef9SDimitry Andric 1427*e8d8bef9SDimitry Andric void Pattern::printFuzzyMatch(const SourceMgr &SM, StringRef Buffer, 1428*e8d8bef9SDimitry Andric std::vector<FileCheckDiag> *Diags) const { 1429*e8d8bef9SDimitry Andric // Attempt to find the closest/best fuzzy match. Usually an error happens 1430*e8d8bef9SDimitry Andric // because some string in the output didn't exactly match. In these cases, we 1431*e8d8bef9SDimitry Andric // would like to show the user a best guess at what "should have" matched, to 1432*e8d8bef9SDimitry Andric // save them having to actually check the input manually. 1433*e8d8bef9SDimitry Andric size_t NumLinesForward = 0; 1434*e8d8bef9SDimitry Andric size_t Best = StringRef::npos; 1435*e8d8bef9SDimitry Andric double BestQuality = 0; 1436*e8d8bef9SDimitry Andric 1437*e8d8bef9SDimitry Andric // Use an arbitrary 4k limit on how far we will search. 1438*e8d8bef9SDimitry Andric for (size_t i = 0, e = std::min(size_t(4096), Buffer.size()); i != e; ++i) { 1439*e8d8bef9SDimitry Andric if (Buffer[i] == '\n') 1440*e8d8bef9SDimitry Andric ++NumLinesForward; 1441*e8d8bef9SDimitry Andric 1442*e8d8bef9SDimitry Andric // Patterns have leading whitespace stripped, so skip whitespace when 1443*e8d8bef9SDimitry Andric // looking for something which looks like a pattern. 1444*e8d8bef9SDimitry Andric if (Buffer[i] == ' ' || Buffer[i] == '\t') 1445*e8d8bef9SDimitry Andric continue; 1446*e8d8bef9SDimitry Andric 1447*e8d8bef9SDimitry Andric // Compute the "quality" of this match as an arbitrary combination of the 1448*e8d8bef9SDimitry Andric // match distance and the number of lines skipped to get to this match. 1449*e8d8bef9SDimitry Andric unsigned Distance = computeMatchDistance(Buffer.substr(i)); 1450*e8d8bef9SDimitry Andric double Quality = Distance + (NumLinesForward / 100.); 1451*e8d8bef9SDimitry Andric 1452*e8d8bef9SDimitry Andric if (Quality < BestQuality || Best == StringRef::npos) { 1453*e8d8bef9SDimitry Andric Best = i; 1454*e8d8bef9SDimitry Andric BestQuality = Quality; 1455*e8d8bef9SDimitry Andric } 1456*e8d8bef9SDimitry Andric } 1457*e8d8bef9SDimitry Andric 1458*e8d8bef9SDimitry Andric // Print the "possible intended match here" line if we found something 1459*e8d8bef9SDimitry Andric // reasonable and not equal to what we showed in the "scanning from here" 1460*e8d8bef9SDimitry Andric // line. 1461*e8d8bef9SDimitry Andric if (Best && Best != StringRef::npos && BestQuality < 50) { 1462*e8d8bef9SDimitry Andric SMRange MatchRange = 1463*e8d8bef9SDimitry Andric ProcessMatchResult(FileCheckDiag::MatchFuzzy, SM, getLoc(), 1464*e8d8bef9SDimitry Andric getCheckTy(), Buffer, Best, 0, Diags); 1465*e8d8bef9SDimitry Andric SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, 1466*e8d8bef9SDimitry Andric "possible intended match here"); 1467*e8d8bef9SDimitry Andric 1468*e8d8bef9SDimitry Andric // FIXME: If we wanted to be really friendly we would show why the match 1469*e8d8bef9SDimitry Andric // failed, as it can be hard to spot simple one character differences. 1470*e8d8bef9SDimitry Andric } 1471*e8d8bef9SDimitry Andric } 1472*e8d8bef9SDimitry Andric 1473*e8d8bef9SDimitry Andric Expected<StringRef> 1474*e8d8bef9SDimitry Andric FileCheckPatternContext::getPatternVarValue(StringRef VarName) { 1475*e8d8bef9SDimitry Andric auto VarIter = GlobalVariableTable.find(VarName); 1476*e8d8bef9SDimitry Andric if (VarIter == GlobalVariableTable.end()) 1477*e8d8bef9SDimitry Andric return make_error<UndefVarError>(VarName); 1478*e8d8bef9SDimitry Andric 1479*e8d8bef9SDimitry Andric return VarIter->second; 1480*e8d8bef9SDimitry Andric } 1481*e8d8bef9SDimitry Andric 1482*e8d8bef9SDimitry Andric template <class... Types> 1483*e8d8bef9SDimitry Andric NumericVariable *FileCheckPatternContext::makeNumericVariable(Types... args) { 1484*e8d8bef9SDimitry Andric NumericVariables.push_back(std::make_unique<NumericVariable>(args...)); 1485*e8d8bef9SDimitry Andric return NumericVariables.back().get(); 1486*e8d8bef9SDimitry Andric } 1487*e8d8bef9SDimitry Andric 1488*e8d8bef9SDimitry Andric Substitution * 1489*e8d8bef9SDimitry Andric FileCheckPatternContext::makeStringSubstitution(StringRef VarName, 1490*e8d8bef9SDimitry Andric size_t InsertIdx) { 1491*e8d8bef9SDimitry Andric Substitutions.push_back( 1492*e8d8bef9SDimitry Andric std::make_unique<StringSubstitution>(this, VarName, InsertIdx)); 1493*e8d8bef9SDimitry Andric return Substitutions.back().get(); 1494*e8d8bef9SDimitry Andric } 1495*e8d8bef9SDimitry Andric 1496*e8d8bef9SDimitry Andric Substitution *FileCheckPatternContext::makeNumericSubstitution( 1497*e8d8bef9SDimitry Andric StringRef ExpressionStr, std::unique_ptr<Expression> Expression, 1498*e8d8bef9SDimitry Andric size_t InsertIdx) { 1499*e8d8bef9SDimitry Andric Substitutions.push_back(std::make_unique<NumericSubstitution>( 1500*e8d8bef9SDimitry Andric this, ExpressionStr, std::move(Expression), InsertIdx)); 1501*e8d8bef9SDimitry Andric return Substitutions.back().get(); 1502*e8d8bef9SDimitry Andric } 1503*e8d8bef9SDimitry Andric 1504*e8d8bef9SDimitry Andric size_t Pattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) { 1505*e8d8bef9SDimitry Andric // Offset keeps track of the current offset within the input Str 1506*e8d8bef9SDimitry Andric size_t Offset = 0; 1507*e8d8bef9SDimitry Andric // [...] Nesting depth 1508*e8d8bef9SDimitry Andric size_t BracketDepth = 0; 1509*e8d8bef9SDimitry Andric 1510*e8d8bef9SDimitry Andric while (!Str.empty()) { 1511*e8d8bef9SDimitry Andric if (Str.startswith("]]") && BracketDepth == 0) 1512*e8d8bef9SDimitry Andric return Offset; 1513*e8d8bef9SDimitry Andric if (Str[0] == '\\') { 1514*e8d8bef9SDimitry Andric // Backslash escapes the next char within regexes, so skip them both. 1515*e8d8bef9SDimitry Andric Str = Str.substr(2); 1516*e8d8bef9SDimitry Andric Offset += 2; 1517*e8d8bef9SDimitry Andric } else { 1518*e8d8bef9SDimitry Andric switch (Str[0]) { 1519*e8d8bef9SDimitry Andric default: 1520*e8d8bef9SDimitry Andric break; 1521*e8d8bef9SDimitry Andric case '[': 1522*e8d8bef9SDimitry Andric BracketDepth++; 1523*e8d8bef9SDimitry Andric break; 1524*e8d8bef9SDimitry Andric case ']': 1525*e8d8bef9SDimitry Andric if (BracketDepth == 0) { 1526*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(Str.data()), 1527*e8d8bef9SDimitry Andric SourceMgr::DK_Error, 1528*e8d8bef9SDimitry Andric "missing closing \"]\" for regex variable"); 1529*e8d8bef9SDimitry Andric exit(1); 1530*e8d8bef9SDimitry Andric } 1531*e8d8bef9SDimitry Andric BracketDepth--; 1532*e8d8bef9SDimitry Andric break; 1533*e8d8bef9SDimitry Andric } 1534*e8d8bef9SDimitry Andric Str = Str.substr(1); 1535*e8d8bef9SDimitry Andric Offset++; 1536*e8d8bef9SDimitry Andric } 1537*e8d8bef9SDimitry Andric } 1538*e8d8bef9SDimitry Andric 1539*e8d8bef9SDimitry Andric return StringRef::npos; 1540*e8d8bef9SDimitry Andric } 1541*e8d8bef9SDimitry Andric 1542*e8d8bef9SDimitry Andric StringRef FileCheck::CanonicalizeFile(MemoryBuffer &MB, 1543*e8d8bef9SDimitry Andric SmallVectorImpl<char> &OutputBuffer) { 1544*e8d8bef9SDimitry Andric OutputBuffer.reserve(MB.getBufferSize()); 1545*e8d8bef9SDimitry Andric 1546*e8d8bef9SDimitry Andric for (const char *Ptr = MB.getBufferStart(), *End = MB.getBufferEnd(); 1547*e8d8bef9SDimitry Andric Ptr != End; ++Ptr) { 1548*e8d8bef9SDimitry Andric // Eliminate trailing dosish \r. 1549*e8d8bef9SDimitry Andric if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') { 1550*e8d8bef9SDimitry Andric continue; 1551*e8d8bef9SDimitry Andric } 1552*e8d8bef9SDimitry Andric 1553*e8d8bef9SDimitry Andric // If current char is not a horizontal whitespace or if horizontal 1554*e8d8bef9SDimitry Andric // whitespace canonicalization is disabled, dump it to output as is. 1555*e8d8bef9SDimitry Andric if (Req.NoCanonicalizeWhiteSpace || (*Ptr != ' ' && *Ptr != '\t')) { 1556*e8d8bef9SDimitry Andric OutputBuffer.push_back(*Ptr); 1557*e8d8bef9SDimitry Andric continue; 1558*e8d8bef9SDimitry Andric } 1559*e8d8bef9SDimitry Andric 1560*e8d8bef9SDimitry Andric // Otherwise, add one space and advance over neighboring space. 1561*e8d8bef9SDimitry Andric OutputBuffer.push_back(' '); 1562*e8d8bef9SDimitry Andric while (Ptr + 1 != End && (Ptr[1] == ' ' || Ptr[1] == '\t')) 1563*e8d8bef9SDimitry Andric ++Ptr; 1564*e8d8bef9SDimitry Andric } 1565*e8d8bef9SDimitry Andric 1566*e8d8bef9SDimitry Andric // Add a null byte and then return all but that byte. 1567*e8d8bef9SDimitry Andric OutputBuffer.push_back('\0'); 1568*e8d8bef9SDimitry Andric return StringRef(OutputBuffer.data(), OutputBuffer.size() - 1); 1569*e8d8bef9SDimitry Andric } 1570*e8d8bef9SDimitry Andric 1571*e8d8bef9SDimitry Andric FileCheckDiag::FileCheckDiag(const SourceMgr &SM, 1572*e8d8bef9SDimitry Andric const Check::FileCheckType &CheckTy, 1573*e8d8bef9SDimitry Andric SMLoc CheckLoc, MatchType MatchTy, 1574*e8d8bef9SDimitry Andric SMRange InputRange, StringRef Note) 1575*e8d8bef9SDimitry Andric : CheckTy(CheckTy), CheckLoc(CheckLoc), MatchTy(MatchTy), Note(Note) { 1576*e8d8bef9SDimitry Andric auto Start = SM.getLineAndColumn(InputRange.Start); 1577*e8d8bef9SDimitry Andric auto End = SM.getLineAndColumn(InputRange.End); 1578*e8d8bef9SDimitry Andric InputStartLine = Start.first; 1579*e8d8bef9SDimitry Andric InputStartCol = Start.second; 1580*e8d8bef9SDimitry Andric InputEndLine = End.first; 1581*e8d8bef9SDimitry Andric InputEndCol = End.second; 1582*e8d8bef9SDimitry Andric } 1583*e8d8bef9SDimitry Andric 1584*e8d8bef9SDimitry Andric static bool IsPartOfWord(char c) { 1585*e8d8bef9SDimitry Andric return (isAlnum(c) || c == '-' || c == '_'); 1586*e8d8bef9SDimitry Andric } 1587*e8d8bef9SDimitry Andric 1588*e8d8bef9SDimitry Andric Check::FileCheckType &Check::FileCheckType::setCount(int C) { 1589*e8d8bef9SDimitry Andric assert(Count > 0 && "zero and negative counts are not supported"); 1590*e8d8bef9SDimitry Andric assert((C == 1 || Kind == CheckPlain) && 1591*e8d8bef9SDimitry Andric "count supported only for plain CHECK directives"); 1592*e8d8bef9SDimitry Andric Count = C; 1593*e8d8bef9SDimitry Andric return *this; 1594*e8d8bef9SDimitry Andric } 1595*e8d8bef9SDimitry Andric 1596*e8d8bef9SDimitry Andric std::string Check::FileCheckType::getModifiersDescription() const { 1597*e8d8bef9SDimitry Andric if (Modifiers.none()) 1598*e8d8bef9SDimitry Andric return ""; 1599*e8d8bef9SDimitry Andric std::string Ret; 1600*e8d8bef9SDimitry Andric raw_string_ostream OS(Ret); 1601*e8d8bef9SDimitry Andric OS << '{'; 1602*e8d8bef9SDimitry Andric if (isLiteralMatch()) 1603*e8d8bef9SDimitry Andric OS << "LITERAL"; 1604*e8d8bef9SDimitry Andric OS << '}'; 1605*e8d8bef9SDimitry Andric return OS.str(); 1606*e8d8bef9SDimitry Andric } 1607*e8d8bef9SDimitry Andric 1608*e8d8bef9SDimitry Andric std::string Check::FileCheckType::getDescription(StringRef Prefix) const { 1609*e8d8bef9SDimitry Andric // Append directive modifiers. 1610*e8d8bef9SDimitry Andric auto WithModifiers = [this, Prefix](StringRef Str) -> std::string { 1611*e8d8bef9SDimitry Andric return (Prefix + Str + getModifiersDescription()).str(); 1612*e8d8bef9SDimitry Andric }; 1613*e8d8bef9SDimitry Andric 1614*e8d8bef9SDimitry Andric switch (Kind) { 1615*e8d8bef9SDimitry Andric case Check::CheckNone: 1616*e8d8bef9SDimitry Andric return "invalid"; 1617*e8d8bef9SDimitry Andric case Check::CheckPlain: 1618*e8d8bef9SDimitry Andric if (Count > 1) 1619*e8d8bef9SDimitry Andric return WithModifiers("-COUNT"); 1620*e8d8bef9SDimitry Andric return WithModifiers(""); 1621*e8d8bef9SDimitry Andric case Check::CheckNext: 1622*e8d8bef9SDimitry Andric return WithModifiers("-NEXT"); 1623*e8d8bef9SDimitry Andric case Check::CheckSame: 1624*e8d8bef9SDimitry Andric return WithModifiers("-SAME"); 1625*e8d8bef9SDimitry Andric case Check::CheckNot: 1626*e8d8bef9SDimitry Andric return WithModifiers("-NOT"); 1627*e8d8bef9SDimitry Andric case Check::CheckDAG: 1628*e8d8bef9SDimitry Andric return WithModifiers("-DAG"); 1629*e8d8bef9SDimitry Andric case Check::CheckLabel: 1630*e8d8bef9SDimitry Andric return WithModifiers("-LABEL"); 1631*e8d8bef9SDimitry Andric case Check::CheckEmpty: 1632*e8d8bef9SDimitry Andric return WithModifiers("-EMPTY"); 1633*e8d8bef9SDimitry Andric case Check::CheckComment: 1634*e8d8bef9SDimitry Andric return std::string(Prefix); 1635*e8d8bef9SDimitry Andric case Check::CheckEOF: 1636*e8d8bef9SDimitry Andric return "implicit EOF"; 1637*e8d8bef9SDimitry Andric case Check::CheckBadNot: 1638*e8d8bef9SDimitry Andric return "bad NOT"; 1639*e8d8bef9SDimitry Andric case Check::CheckBadCount: 1640*e8d8bef9SDimitry Andric return "bad COUNT"; 1641*e8d8bef9SDimitry Andric } 1642*e8d8bef9SDimitry Andric llvm_unreachable("unknown FileCheckType"); 1643*e8d8bef9SDimitry Andric } 1644*e8d8bef9SDimitry Andric 1645*e8d8bef9SDimitry Andric static std::pair<Check::FileCheckType, StringRef> 1646*e8d8bef9SDimitry Andric FindCheckType(const FileCheckRequest &Req, StringRef Buffer, StringRef Prefix) { 1647*e8d8bef9SDimitry Andric if (Buffer.size() <= Prefix.size()) 1648*e8d8bef9SDimitry Andric return {Check::CheckNone, StringRef()}; 1649*e8d8bef9SDimitry Andric 1650*e8d8bef9SDimitry Andric StringRef Rest = Buffer.drop_front(Prefix.size()); 1651*e8d8bef9SDimitry Andric // Check for comment. 1652*e8d8bef9SDimitry Andric if (llvm::is_contained(Req.CommentPrefixes, Prefix)) { 1653*e8d8bef9SDimitry Andric if (Rest.consume_front(":")) 1654*e8d8bef9SDimitry Andric return {Check::CheckComment, Rest}; 1655*e8d8bef9SDimitry Andric // Ignore a comment prefix if it has a suffix like "-NOT". 1656*e8d8bef9SDimitry Andric return {Check::CheckNone, StringRef()}; 1657*e8d8bef9SDimitry Andric } 1658*e8d8bef9SDimitry Andric 1659*e8d8bef9SDimitry Andric auto ConsumeModifiers = [&](Check::FileCheckType Ret) 1660*e8d8bef9SDimitry Andric -> std::pair<Check::FileCheckType, StringRef> { 1661*e8d8bef9SDimitry Andric if (Rest.consume_front(":")) 1662*e8d8bef9SDimitry Andric return {Ret, Rest}; 1663*e8d8bef9SDimitry Andric if (!Rest.consume_front("{")) 1664*e8d8bef9SDimitry Andric return {Check::CheckNone, StringRef()}; 1665*e8d8bef9SDimitry Andric 1666*e8d8bef9SDimitry Andric // Parse the modifiers, speparated by commas. 1667*e8d8bef9SDimitry Andric do { 1668*e8d8bef9SDimitry Andric // Allow whitespace in modifiers list. 1669*e8d8bef9SDimitry Andric Rest = Rest.ltrim(); 1670*e8d8bef9SDimitry Andric if (Rest.consume_front("LITERAL")) 1671*e8d8bef9SDimitry Andric Ret.setLiteralMatch(); 1672*e8d8bef9SDimitry Andric else 1673*e8d8bef9SDimitry Andric return {Check::CheckNone, Rest}; 1674*e8d8bef9SDimitry Andric // Allow whitespace in modifiers list. 1675*e8d8bef9SDimitry Andric Rest = Rest.ltrim(); 1676*e8d8bef9SDimitry Andric } while (Rest.consume_front(",")); 1677*e8d8bef9SDimitry Andric if (!Rest.consume_front("}:")) 1678*e8d8bef9SDimitry Andric return {Check::CheckNone, Rest}; 1679*e8d8bef9SDimitry Andric return {Ret, Rest}; 1680*e8d8bef9SDimitry Andric }; 1681*e8d8bef9SDimitry Andric 1682*e8d8bef9SDimitry Andric // Verify that the prefix is followed by directive modifiers or a colon. 1683*e8d8bef9SDimitry Andric if (Rest.consume_front(":")) 1684*e8d8bef9SDimitry Andric return {Check::CheckPlain, Rest}; 1685*e8d8bef9SDimitry Andric if (Rest.front() == '{') 1686*e8d8bef9SDimitry Andric return ConsumeModifiers(Check::CheckPlain); 1687*e8d8bef9SDimitry Andric 1688*e8d8bef9SDimitry Andric if (!Rest.consume_front("-")) 1689*e8d8bef9SDimitry Andric return {Check::CheckNone, StringRef()}; 1690*e8d8bef9SDimitry Andric 1691*e8d8bef9SDimitry Andric if (Rest.consume_front("COUNT-")) { 1692*e8d8bef9SDimitry Andric int64_t Count; 1693*e8d8bef9SDimitry Andric if (Rest.consumeInteger(10, Count)) 1694*e8d8bef9SDimitry Andric // Error happened in parsing integer. 1695*e8d8bef9SDimitry Andric return {Check::CheckBadCount, Rest}; 1696*e8d8bef9SDimitry Andric if (Count <= 0 || Count > INT32_MAX) 1697*e8d8bef9SDimitry Andric return {Check::CheckBadCount, Rest}; 1698*e8d8bef9SDimitry Andric if (Rest.front() != ':' && Rest.front() != '{') 1699*e8d8bef9SDimitry Andric return {Check::CheckBadCount, Rest}; 1700*e8d8bef9SDimitry Andric return ConsumeModifiers( 1701*e8d8bef9SDimitry Andric Check::FileCheckType(Check::CheckPlain).setCount(Count)); 1702*e8d8bef9SDimitry Andric } 1703*e8d8bef9SDimitry Andric 1704*e8d8bef9SDimitry Andric // You can't combine -NOT with another suffix. 1705*e8d8bef9SDimitry Andric if (Rest.startswith("DAG-NOT:") || Rest.startswith("NOT-DAG:") || 1706*e8d8bef9SDimitry Andric Rest.startswith("NEXT-NOT:") || Rest.startswith("NOT-NEXT:") || 1707*e8d8bef9SDimitry Andric Rest.startswith("SAME-NOT:") || Rest.startswith("NOT-SAME:") || 1708*e8d8bef9SDimitry Andric Rest.startswith("EMPTY-NOT:") || Rest.startswith("NOT-EMPTY:")) 1709*e8d8bef9SDimitry Andric return {Check::CheckBadNot, Rest}; 1710*e8d8bef9SDimitry Andric 1711*e8d8bef9SDimitry Andric if (Rest.consume_front("NEXT")) 1712*e8d8bef9SDimitry Andric return ConsumeModifiers(Check::CheckNext); 1713*e8d8bef9SDimitry Andric 1714*e8d8bef9SDimitry Andric if (Rest.consume_front("SAME")) 1715*e8d8bef9SDimitry Andric return ConsumeModifiers(Check::CheckSame); 1716*e8d8bef9SDimitry Andric 1717*e8d8bef9SDimitry Andric if (Rest.consume_front("NOT")) 1718*e8d8bef9SDimitry Andric return ConsumeModifiers(Check::CheckNot); 1719*e8d8bef9SDimitry Andric 1720*e8d8bef9SDimitry Andric if (Rest.consume_front("DAG")) 1721*e8d8bef9SDimitry Andric return ConsumeModifiers(Check::CheckDAG); 1722*e8d8bef9SDimitry Andric 1723*e8d8bef9SDimitry Andric if (Rest.consume_front("LABEL")) 1724*e8d8bef9SDimitry Andric return ConsumeModifiers(Check::CheckLabel); 1725*e8d8bef9SDimitry Andric 1726*e8d8bef9SDimitry Andric if (Rest.consume_front("EMPTY")) 1727*e8d8bef9SDimitry Andric return ConsumeModifiers(Check::CheckEmpty); 1728*e8d8bef9SDimitry Andric 1729*e8d8bef9SDimitry Andric return {Check::CheckNone, Rest}; 1730*e8d8bef9SDimitry Andric } 1731*e8d8bef9SDimitry Andric 1732*e8d8bef9SDimitry Andric // From the given position, find the next character after the word. 1733*e8d8bef9SDimitry Andric static size_t SkipWord(StringRef Str, size_t Loc) { 1734*e8d8bef9SDimitry Andric while (Loc < Str.size() && IsPartOfWord(Str[Loc])) 1735*e8d8bef9SDimitry Andric ++Loc; 1736*e8d8bef9SDimitry Andric return Loc; 1737*e8d8bef9SDimitry Andric } 1738*e8d8bef9SDimitry Andric 1739*e8d8bef9SDimitry Andric /// Searches the buffer for the first prefix in the prefix regular expression. 1740*e8d8bef9SDimitry Andric /// 1741*e8d8bef9SDimitry Andric /// This searches the buffer using the provided regular expression, however it 1742*e8d8bef9SDimitry Andric /// enforces constraints beyond that: 1743*e8d8bef9SDimitry Andric /// 1) The found prefix must not be a suffix of something that looks like 1744*e8d8bef9SDimitry Andric /// a valid prefix. 1745*e8d8bef9SDimitry Andric /// 2) The found prefix must be followed by a valid check type suffix using \c 1746*e8d8bef9SDimitry Andric /// FindCheckType above. 1747*e8d8bef9SDimitry Andric /// 1748*e8d8bef9SDimitry Andric /// \returns a pair of StringRefs into the Buffer, which combines: 1749*e8d8bef9SDimitry Andric /// - the first match of the regular expression to satisfy these two is 1750*e8d8bef9SDimitry Andric /// returned, 1751*e8d8bef9SDimitry Andric /// otherwise an empty StringRef is returned to indicate failure. 1752*e8d8bef9SDimitry Andric /// - buffer rewound to the location right after parsed suffix, for parsing 1753*e8d8bef9SDimitry Andric /// to continue from 1754*e8d8bef9SDimitry Andric /// 1755*e8d8bef9SDimitry Andric /// If this routine returns a valid prefix, it will also shrink \p Buffer to 1756*e8d8bef9SDimitry Andric /// start at the beginning of the returned prefix, increment \p LineNumber for 1757*e8d8bef9SDimitry Andric /// each new line consumed from \p Buffer, and set \p CheckTy to the type of 1758*e8d8bef9SDimitry Andric /// check found by examining the suffix. 1759*e8d8bef9SDimitry Andric /// 1760*e8d8bef9SDimitry Andric /// If no valid prefix is found, the state of Buffer, LineNumber, and CheckTy 1761*e8d8bef9SDimitry Andric /// is unspecified. 1762*e8d8bef9SDimitry Andric static std::pair<StringRef, StringRef> 1763*e8d8bef9SDimitry Andric FindFirstMatchingPrefix(const FileCheckRequest &Req, Regex &PrefixRE, 1764*e8d8bef9SDimitry Andric StringRef &Buffer, unsigned &LineNumber, 1765*e8d8bef9SDimitry Andric Check::FileCheckType &CheckTy) { 1766*e8d8bef9SDimitry Andric SmallVector<StringRef, 2> Matches; 1767*e8d8bef9SDimitry Andric 1768*e8d8bef9SDimitry Andric while (!Buffer.empty()) { 1769*e8d8bef9SDimitry Andric // Find the first (longest) match using the RE. 1770*e8d8bef9SDimitry Andric if (!PrefixRE.match(Buffer, &Matches)) 1771*e8d8bef9SDimitry Andric // No match at all, bail. 1772*e8d8bef9SDimitry Andric return {StringRef(), StringRef()}; 1773*e8d8bef9SDimitry Andric 1774*e8d8bef9SDimitry Andric StringRef Prefix = Matches[0]; 1775*e8d8bef9SDimitry Andric Matches.clear(); 1776*e8d8bef9SDimitry Andric 1777*e8d8bef9SDimitry Andric assert(Prefix.data() >= Buffer.data() && 1778*e8d8bef9SDimitry Andric Prefix.data() < Buffer.data() + Buffer.size() && 1779*e8d8bef9SDimitry Andric "Prefix doesn't start inside of buffer!"); 1780*e8d8bef9SDimitry Andric size_t Loc = Prefix.data() - Buffer.data(); 1781*e8d8bef9SDimitry Andric StringRef Skipped = Buffer.substr(0, Loc); 1782*e8d8bef9SDimitry Andric Buffer = Buffer.drop_front(Loc); 1783*e8d8bef9SDimitry Andric LineNumber += Skipped.count('\n'); 1784*e8d8bef9SDimitry Andric 1785*e8d8bef9SDimitry Andric // Check that the matched prefix isn't a suffix of some other check-like 1786*e8d8bef9SDimitry Andric // word. 1787*e8d8bef9SDimitry Andric // FIXME: This is a very ad-hoc check. it would be better handled in some 1788*e8d8bef9SDimitry Andric // other way. Among other things it seems hard to distinguish between 1789*e8d8bef9SDimitry Andric // intentional and unintentional uses of this feature. 1790*e8d8bef9SDimitry Andric if (Skipped.empty() || !IsPartOfWord(Skipped.back())) { 1791*e8d8bef9SDimitry Andric // Now extract the type. 1792*e8d8bef9SDimitry Andric StringRef AfterSuffix; 1793*e8d8bef9SDimitry Andric std::tie(CheckTy, AfterSuffix) = FindCheckType(Req, Buffer, Prefix); 1794*e8d8bef9SDimitry Andric 1795*e8d8bef9SDimitry Andric // If we've found a valid check type for this prefix, we're done. 1796*e8d8bef9SDimitry Andric if (CheckTy != Check::CheckNone) 1797*e8d8bef9SDimitry Andric return {Prefix, AfterSuffix}; 1798*e8d8bef9SDimitry Andric } 1799*e8d8bef9SDimitry Andric 1800*e8d8bef9SDimitry Andric // If we didn't successfully find a prefix, we need to skip this invalid 1801*e8d8bef9SDimitry Andric // prefix and continue scanning. We directly skip the prefix that was 1802*e8d8bef9SDimitry Andric // matched and any additional parts of that check-like word. 1803*e8d8bef9SDimitry Andric Buffer = Buffer.drop_front(SkipWord(Buffer, Prefix.size())); 1804*e8d8bef9SDimitry Andric } 1805*e8d8bef9SDimitry Andric 1806*e8d8bef9SDimitry Andric // We ran out of buffer while skipping partial matches so give up. 1807*e8d8bef9SDimitry Andric return {StringRef(), StringRef()}; 1808*e8d8bef9SDimitry Andric } 1809*e8d8bef9SDimitry Andric 1810*e8d8bef9SDimitry Andric void FileCheckPatternContext::createLineVariable() { 1811*e8d8bef9SDimitry Andric assert(!LineVariable && "@LINE pseudo numeric variable already created"); 1812*e8d8bef9SDimitry Andric StringRef LineName = "@LINE"; 1813*e8d8bef9SDimitry Andric LineVariable = makeNumericVariable( 1814*e8d8bef9SDimitry Andric LineName, ExpressionFormat(ExpressionFormat::Kind::Unsigned)); 1815*e8d8bef9SDimitry Andric GlobalNumericVariableTable[LineName] = LineVariable; 1816*e8d8bef9SDimitry Andric } 1817*e8d8bef9SDimitry Andric 1818*e8d8bef9SDimitry Andric FileCheck::FileCheck(FileCheckRequest Req) 1819*e8d8bef9SDimitry Andric : Req(Req), PatternContext(std::make_unique<FileCheckPatternContext>()), 1820*e8d8bef9SDimitry Andric CheckStrings(std::make_unique<std::vector<FileCheckString>>()) {} 1821*e8d8bef9SDimitry Andric 1822*e8d8bef9SDimitry Andric FileCheck::~FileCheck() = default; 1823*e8d8bef9SDimitry Andric 1824*e8d8bef9SDimitry Andric bool FileCheck::readCheckFile( 1825*e8d8bef9SDimitry Andric SourceMgr &SM, StringRef Buffer, Regex &PrefixRE, 1826*e8d8bef9SDimitry Andric std::pair<unsigned, unsigned> *ImpPatBufferIDRange) { 1827*e8d8bef9SDimitry Andric if (ImpPatBufferIDRange) 1828*e8d8bef9SDimitry Andric ImpPatBufferIDRange->first = ImpPatBufferIDRange->second = 0; 1829*e8d8bef9SDimitry Andric 1830*e8d8bef9SDimitry Andric Error DefineError = 1831*e8d8bef9SDimitry Andric PatternContext->defineCmdlineVariables(Req.GlobalDefines, SM); 1832*e8d8bef9SDimitry Andric if (DefineError) { 1833*e8d8bef9SDimitry Andric logAllUnhandledErrors(std::move(DefineError), errs()); 1834*e8d8bef9SDimitry Andric return true; 1835*e8d8bef9SDimitry Andric } 1836*e8d8bef9SDimitry Andric 1837*e8d8bef9SDimitry Andric PatternContext->createLineVariable(); 1838*e8d8bef9SDimitry Andric 1839*e8d8bef9SDimitry Andric std::vector<Pattern> ImplicitNegativeChecks; 1840*e8d8bef9SDimitry Andric for (StringRef PatternString : Req.ImplicitCheckNot) { 1841*e8d8bef9SDimitry Andric // Create a buffer with fake command line content in order to display the 1842*e8d8bef9SDimitry Andric // command line option responsible for the specific implicit CHECK-NOT. 1843*e8d8bef9SDimitry Andric std::string Prefix = "-implicit-check-not='"; 1844*e8d8bef9SDimitry Andric std::string Suffix = "'"; 1845*e8d8bef9SDimitry Andric std::unique_ptr<MemoryBuffer> CmdLine = MemoryBuffer::getMemBufferCopy( 1846*e8d8bef9SDimitry Andric (Prefix + PatternString + Suffix).str(), "command line"); 1847*e8d8bef9SDimitry Andric 1848*e8d8bef9SDimitry Andric StringRef PatternInBuffer = 1849*e8d8bef9SDimitry Andric CmdLine->getBuffer().substr(Prefix.size(), PatternString.size()); 1850*e8d8bef9SDimitry Andric unsigned BufferID = SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc()); 1851*e8d8bef9SDimitry Andric if (ImpPatBufferIDRange) { 1852*e8d8bef9SDimitry Andric if (ImpPatBufferIDRange->first == ImpPatBufferIDRange->second) { 1853*e8d8bef9SDimitry Andric ImpPatBufferIDRange->first = BufferID; 1854*e8d8bef9SDimitry Andric ImpPatBufferIDRange->second = BufferID + 1; 1855*e8d8bef9SDimitry Andric } else { 1856*e8d8bef9SDimitry Andric assert(BufferID == ImpPatBufferIDRange->second && 1857*e8d8bef9SDimitry Andric "expected consecutive source buffer IDs"); 1858*e8d8bef9SDimitry Andric ++ImpPatBufferIDRange->second; 1859*e8d8bef9SDimitry Andric } 1860*e8d8bef9SDimitry Andric } 1861*e8d8bef9SDimitry Andric 1862*e8d8bef9SDimitry Andric ImplicitNegativeChecks.push_back( 1863*e8d8bef9SDimitry Andric Pattern(Check::CheckNot, PatternContext.get())); 1864*e8d8bef9SDimitry Andric ImplicitNegativeChecks.back().parsePattern(PatternInBuffer, 1865*e8d8bef9SDimitry Andric "IMPLICIT-CHECK", SM, Req); 1866*e8d8bef9SDimitry Andric } 1867*e8d8bef9SDimitry Andric 1868*e8d8bef9SDimitry Andric std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks; 1869*e8d8bef9SDimitry Andric 1870*e8d8bef9SDimitry Andric // LineNumber keeps track of the line on which CheckPrefix instances are 1871*e8d8bef9SDimitry Andric // found. 1872*e8d8bef9SDimitry Andric unsigned LineNumber = 1; 1873*e8d8bef9SDimitry Andric 1874*e8d8bef9SDimitry Andric std::set<StringRef> PrefixesNotFound(Req.CheckPrefixes.begin(), 1875*e8d8bef9SDimitry Andric Req.CheckPrefixes.end()); 1876*e8d8bef9SDimitry Andric const size_t DistinctPrefixes = PrefixesNotFound.size(); 1877*e8d8bef9SDimitry Andric while (true) { 1878*e8d8bef9SDimitry Andric Check::FileCheckType CheckTy; 1879*e8d8bef9SDimitry Andric 1880*e8d8bef9SDimitry Andric // See if a prefix occurs in the memory buffer. 1881*e8d8bef9SDimitry Andric StringRef UsedPrefix; 1882*e8d8bef9SDimitry Andric StringRef AfterSuffix; 1883*e8d8bef9SDimitry Andric std::tie(UsedPrefix, AfterSuffix) = 1884*e8d8bef9SDimitry Andric FindFirstMatchingPrefix(Req, PrefixRE, Buffer, LineNumber, CheckTy); 1885*e8d8bef9SDimitry Andric if (UsedPrefix.empty()) 1886*e8d8bef9SDimitry Andric break; 1887*e8d8bef9SDimitry Andric if (CheckTy != Check::CheckComment) 1888*e8d8bef9SDimitry Andric PrefixesNotFound.erase(UsedPrefix); 1889*e8d8bef9SDimitry Andric 1890*e8d8bef9SDimitry Andric assert(UsedPrefix.data() == Buffer.data() && 1891*e8d8bef9SDimitry Andric "Failed to move Buffer's start forward, or pointed prefix outside " 1892*e8d8bef9SDimitry Andric "of the buffer!"); 1893*e8d8bef9SDimitry Andric assert(AfterSuffix.data() >= Buffer.data() && 1894*e8d8bef9SDimitry Andric AfterSuffix.data() < Buffer.data() + Buffer.size() && 1895*e8d8bef9SDimitry Andric "Parsing after suffix doesn't start inside of buffer!"); 1896*e8d8bef9SDimitry Andric 1897*e8d8bef9SDimitry Andric // Location to use for error messages. 1898*e8d8bef9SDimitry Andric const char *UsedPrefixStart = UsedPrefix.data(); 1899*e8d8bef9SDimitry Andric 1900*e8d8bef9SDimitry Andric // Skip the buffer to the end of parsed suffix (or just prefix, if no good 1901*e8d8bef9SDimitry Andric // suffix was processed). 1902*e8d8bef9SDimitry Andric Buffer = AfterSuffix.empty() ? Buffer.drop_front(UsedPrefix.size()) 1903*e8d8bef9SDimitry Andric : AfterSuffix; 1904*e8d8bef9SDimitry Andric 1905*e8d8bef9SDimitry Andric // Complain about useful-looking but unsupported suffixes. 1906*e8d8bef9SDimitry Andric if (CheckTy == Check::CheckBadNot) { 1907*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error, 1908*e8d8bef9SDimitry Andric "unsupported -NOT combo on prefix '" + UsedPrefix + "'"); 1909*e8d8bef9SDimitry Andric return true; 1910*e8d8bef9SDimitry Andric } 1911*e8d8bef9SDimitry Andric 1912*e8d8bef9SDimitry Andric // Complain about invalid count specification. 1913*e8d8bef9SDimitry Andric if (CheckTy == Check::CheckBadCount) { 1914*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Error, 1915*e8d8bef9SDimitry Andric "invalid count in -COUNT specification on prefix '" + 1916*e8d8bef9SDimitry Andric UsedPrefix + "'"); 1917*e8d8bef9SDimitry Andric return true; 1918*e8d8bef9SDimitry Andric } 1919*e8d8bef9SDimitry Andric 1920*e8d8bef9SDimitry Andric // Okay, we found the prefix, yay. Remember the rest of the line, but ignore 1921*e8d8bef9SDimitry Andric // leading whitespace. 1922*e8d8bef9SDimitry Andric if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines)) 1923*e8d8bef9SDimitry Andric Buffer = Buffer.substr(Buffer.find_first_not_of(" \t")); 1924*e8d8bef9SDimitry Andric 1925*e8d8bef9SDimitry Andric // Scan ahead to the end of line. 1926*e8d8bef9SDimitry Andric size_t EOL = Buffer.find_first_of("\n\r"); 1927*e8d8bef9SDimitry Andric 1928*e8d8bef9SDimitry Andric // Remember the location of the start of the pattern, for diagnostics. 1929*e8d8bef9SDimitry Andric SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data()); 1930*e8d8bef9SDimitry Andric 1931*e8d8bef9SDimitry Andric // Extract the pattern from the buffer. 1932*e8d8bef9SDimitry Andric StringRef PatternBuffer = Buffer.substr(0, EOL); 1933*e8d8bef9SDimitry Andric Buffer = Buffer.substr(EOL); 1934*e8d8bef9SDimitry Andric 1935*e8d8bef9SDimitry Andric // If this is a comment, we're done. 1936*e8d8bef9SDimitry Andric if (CheckTy == Check::CheckComment) 1937*e8d8bef9SDimitry Andric continue; 1938*e8d8bef9SDimitry Andric 1939*e8d8bef9SDimitry Andric // Parse the pattern. 1940*e8d8bef9SDimitry Andric Pattern P(CheckTy, PatternContext.get(), LineNumber); 1941*e8d8bef9SDimitry Andric if (P.parsePattern(PatternBuffer, UsedPrefix, SM, Req)) 1942*e8d8bef9SDimitry Andric return true; 1943*e8d8bef9SDimitry Andric 1944*e8d8bef9SDimitry Andric // Verify that CHECK-LABEL lines do not define or use variables 1945*e8d8bef9SDimitry Andric if ((CheckTy == Check::CheckLabel) && P.hasVariable()) { 1946*e8d8bef9SDimitry Andric SM.PrintMessage( 1947*e8d8bef9SDimitry Andric SMLoc::getFromPointer(UsedPrefixStart), SourceMgr::DK_Error, 1948*e8d8bef9SDimitry Andric "found '" + UsedPrefix + "-LABEL:'" 1949*e8d8bef9SDimitry Andric " with variable definition or use"); 1950*e8d8bef9SDimitry Andric return true; 1951*e8d8bef9SDimitry Andric } 1952*e8d8bef9SDimitry Andric 1953*e8d8bef9SDimitry Andric // Verify that CHECK-NEXT/SAME/EMPTY lines have at least one CHECK line before them. 1954*e8d8bef9SDimitry Andric if ((CheckTy == Check::CheckNext || CheckTy == Check::CheckSame || 1955*e8d8bef9SDimitry Andric CheckTy == Check::CheckEmpty) && 1956*e8d8bef9SDimitry Andric CheckStrings->empty()) { 1957*e8d8bef9SDimitry Andric StringRef Type = CheckTy == Check::CheckNext 1958*e8d8bef9SDimitry Andric ? "NEXT" 1959*e8d8bef9SDimitry Andric : CheckTy == Check::CheckEmpty ? "EMPTY" : "SAME"; 1960*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(UsedPrefixStart), 1961*e8d8bef9SDimitry Andric SourceMgr::DK_Error, 1962*e8d8bef9SDimitry Andric "found '" + UsedPrefix + "-" + Type + 1963*e8d8bef9SDimitry Andric "' without previous '" + UsedPrefix + ": line"); 1964*e8d8bef9SDimitry Andric return true; 1965*e8d8bef9SDimitry Andric } 1966*e8d8bef9SDimitry Andric 1967*e8d8bef9SDimitry Andric // Handle CHECK-DAG/-NOT. 1968*e8d8bef9SDimitry Andric if (CheckTy == Check::CheckDAG || CheckTy == Check::CheckNot) { 1969*e8d8bef9SDimitry Andric DagNotMatches.push_back(P); 1970*e8d8bef9SDimitry Andric continue; 1971*e8d8bef9SDimitry Andric } 1972*e8d8bef9SDimitry Andric 1973*e8d8bef9SDimitry Andric // Okay, add the string we captured to the output vector and move on. 1974*e8d8bef9SDimitry Andric CheckStrings->emplace_back(P, UsedPrefix, PatternLoc); 1975*e8d8bef9SDimitry Andric std::swap(DagNotMatches, CheckStrings->back().DagNotStrings); 1976*e8d8bef9SDimitry Andric DagNotMatches = ImplicitNegativeChecks; 1977*e8d8bef9SDimitry Andric } 1978*e8d8bef9SDimitry Andric 1979*e8d8bef9SDimitry Andric // When there are no used prefixes we report an error except in the case that 1980*e8d8bef9SDimitry Andric // no prefix is specified explicitly but -implicit-check-not is specified. 1981*e8d8bef9SDimitry Andric const bool NoPrefixesFound = PrefixesNotFound.size() == DistinctPrefixes; 1982*e8d8bef9SDimitry Andric const bool SomePrefixesUnexpectedlyNotUsed = 1983*e8d8bef9SDimitry Andric !Req.AllowUnusedPrefixes && !PrefixesNotFound.empty(); 1984*e8d8bef9SDimitry Andric if ((NoPrefixesFound || SomePrefixesUnexpectedlyNotUsed) && 1985*e8d8bef9SDimitry Andric (ImplicitNegativeChecks.empty() || !Req.IsDefaultCheckPrefix)) { 1986*e8d8bef9SDimitry Andric errs() << "error: no check strings found with prefix" 1987*e8d8bef9SDimitry Andric << (PrefixesNotFound.size() > 1 ? "es " : " "); 1988*e8d8bef9SDimitry Andric bool First = true; 1989*e8d8bef9SDimitry Andric for (StringRef MissingPrefix : PrefixesNotFound) { 1990*e8d8bef9SDimitry Andric if (!First) 1991*e8d8bef9SDimitry Andric errs() << ", "; 1992*e8d8bef9SDimitry Andric errs() << "\'" << MissingPrefix << ":'"; 1993*e8d8bef9SDimitry Andric First = false; 1994*e8d8bef9SDimitry Andric } 1995*e8d8bef9SDimitry Andric errs() << '\n'; 1996*e8d8bef9SDimitry Andric return true; 1997*e8d8bef9SDimitry Andric } 1998*e8d8bef9SDimitry Andric 1999*e8d8bef9SDimitry Andric // Add an EOF pattern for any trailing --implicit-check-not/CHECK-DAG/-NOTs, 2000*e8d8bef9SDimitry Andric // and use the first prefix as a filler for the error message. 2001*e8d8bef9SDimitry Andric if (!DagNotMatches.empty()) { 2002*e8d8bef9SDimitry Andric CheckStrings->emplace_back( 2003*e8d8bef9SDimitry Andric Pattern(Check::CheckEOF, PatternContext.get(), LineNumber + 1), 2004*e8d8bef9SDimitry Andric *Req.CheckPrefixes.begin(), SMLoc::getFromPointer(Buffer.data())); 2005*e8d8bef9SDimitry Andric std::swap(DagNotMatches, CheckStrings->back().DagNotStrings); 2006*e8d8bef9SDimitry Andric } 2007*e8d8bef9SDimitry Andric 2008*e8d8bef9SDimitry Andric return false; 2009*e8d8bef9SDimitry Andric } 2010*e8d8bef9SDimitry Andric 2011*e8d8bef9SDimitry Andric static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM, 2012*e8d8bef9SDimitry Andric StringRef Prefix, SMLoc Loc, const Pattern &Pat, 2013*e8d8bef9SDimitry Andric int MatchedCount, StringRef Buffer, size_t MatchPos, 2014*e8d8bef9SDimitry Andric size_t MatchLen, const FileCheckRequest &Req, 2015*e8d8bef9SDimitry Andric std::vector<FileCheckDiag> *Diags) { 2016*e8d8bef9SDimitry Andric bool PrintDiag = true; 2017*e8d8bef9SDimitry Andric if (ExpectedMatch) { 2018*e8d8bef9SDimitry Andric if (!Req.Verbose) 2019*e8d8bef9SDimitry Andric return; 2020*e8d8bef9SDimitry Andric if (!Req.VerboseVerbose && Pat.getCheckTy() == Check::CheckEOF) 2021*e8d8bef9SDimitry Andric return; 2022*e8d8bef9SDimitry Andric // Due to their verbosity, we don't print verbose diagnostics here if we're 2023*e8d8bef9SDimitry Andric // gathering them for a different rendering, but we always print other 2024*e8d8bef9SDimitry Andric // diagnostics. 2025*e8d8bef9SDimitry Andric PrintDiag = !Diags; 2026*e8d8bef9SDimitry Andric } 2027*e8d8bef9SDimitry Andric FileCheckDiag::MatchType MatchTy = ExpectedMatch 2028*e8d8bef9SDimitry Andric ? FileCheckDiag::MatchFoundAndExpected 2029*e8d8bef9SDimitry Andric : FileCheckDiag::MatchFoundButExcluded; 2030*e8d8bef9SDimitry Andric SMRange MatchRange = ProcessMatchResult(MatchTy, SM, Loc, Pat.getCheckTy(), 2031*e8d8bef9SDimitry Andric Buffer, MatchPos, MatchLen, Diags); 2032*e8d8bef9SDimitry Andric if (Diags) { 2033*e8d8bef9SDimitry Andric Pat.printSubstitutions(SM, Buffer, MatchRange, MatchTy, Diags); 2034*e8d8bef9SDimitry Andric Pat.printVariableDefs(SM, MatchTy, Diags); 2035*e8d8bef9SDimitry Andric } 2036*e8d8bef9SDimitry Andric if (!PrintDiag) 2037*e8d8bef9SDimitry Andric return; 2038*e8d8bef9SDimitry Andric 2039*e8d8bef9SDimitry Andric std::string Message = formatv("{0}: {1} string found in input", 2040*e8d8bef9SDimitry Andric Pat.getCheckTy().getDescription(Prefix), 2041*e8d8bef9SDimitry Andric (ExpectedMatch ? "expected" : "excluded")) 2042*e8d8bef9SDimitry Andric .str(); 2043*e8d8bef9SDimitry Andric if (Pat.getCount() > 1) 2044*e8d8bef9SDimitry Andric Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str(); 2045*e8d8bef9SDimitry Andric 2046*e8d8bef9SDimitry Andric SM.PrintMessage( 2047*e8d8bef9SDimitry Andric Loc, ExpectedMatch ? SourceMgr::DK_Remark : SourceMgr::DK_Error, Message); 2048*e8d8bef9SDimitry Andric SM.PrintMessage(MatchRange.Start, SourceMgr::DK_Note, "found here", 2049*e8d8bef9SDimitry Andric {MatchRange}); 2050*e8d8bef9SDimitry Andric Pat.printSubstitutions(SM, Buffer, MatchRange, MatchTy, nullptr); 2051*e8d8bef9SDimitry Andric Pat.printVariableDefs(SM, MatchTy, nullptr); 2052*e8d8bef9SDimitry Andric } 2053*e8d8bef9SDimitry Andric 2054*e8d8bef9SDimitry Andric static void PrintMatch(bool ExpectedMatch, const SourceMgr &SM, 2055*e8d8bef9SDimitry Andric const FileCheckString &CheckStr, int MatchedCount, 2056*e8d8bef9SDimitry Andric StringRef Buffer, size_t MatchPos, size_t MatchLen, 2057*e8d8bef9SDimitry Andric FileCheckRequest &Req, 2058*e8d8bef9SDimitry Andric std::vector<FileCheckDiag> *Diags) { 2059*e8d8bef9SDimitry Andric PrintMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat, 2060*e8d8bef9SDimitry Andric MatchedCount, Buffer, MatchPos, MatchLen, Req, Diags); 2061*e8d8bef9SDimitry Andric } 2062*e8d8bef9SDimitry Andric 2063*e8d8bef9SDimitry Andric static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM, 2064*e8d8bef9SDimitry Andric StringRef Prefix, SMLoc Loc, const Pattern &Pat, 2065*e8d8bef9SDimitry Andric int MatchedCount, StringRef Buffer, 2066*e8d8bef9SDimitry Andric bool VerboseVerbose, std::vector<FileCheckDiag> *Diags, 2067*e8d8bef9SDimitry Andric Error MatchErrors) { 2068*e8d8bef9SDimitry Andric assert(MatchErrors && "Called on successful match"); 2069*e8d8bef9SDimitry Andric bool PrintDiag = true; 2070*e8d8bef9SDimitry Andric if (!ExpectedMatch) { 2071*e8d8bef9SDimitry Andric if (!VerboseVerbose) { 2072*e8d8bef9SDimitry Andric consumeError(std::move(MatchErrors)); 2073*e8d8bef9SDimitry Andric return; 2074*e8d8bef9SDimitry Andric } 2075*e8d8bef9SDimitry Andric // Due to their verbosity, we don't print verbose diagnostics here if we're 2076*e8d8bef9SDimitry Andric // gathering them for a different rendering, but we always print other 2077*e8d8bef9SDimitry Andric // diagnostics. 2078*e8d8bef9SDimitry Andric PrintDiag = !Diags; 2079*e8d8bef9SDimitry Andric } 2080*e8d8bef9SDimitry Andric 2081*e8d8bef9SDimitry Andric // If the current position is at the end of a line, advance to the start of 2082*e8d8bef9SDimitry Andric // the next line. 2083*e8d8bef9SDimitry Andric Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r")); 2084*e8d8bef9SDimitry Andric FileCheckDiag::MatchType MatchTy = ExpectedMatch 2085*e8d8bef9SDimitry Andric ? FileCheckDiag::MatchNoneButExpected 2086*e8d8bef9SDimitry Andric : FileCheckDiag::MatchNoneAndExcluded; 2087*e8d8bef9SDimitry Andric SMRange SearchRange = ProcessMatchResult(MatchTy, SM, Loc, Pat.getCheckTy(), 2088*e8d8bef9SDimitry Andric Buffer, 0, Buffer.size(), Diags); 2089*e8d8bef9SDimitry Andric if (Diags) 2090*e8d8bef9SDimitry Andric Pat.printSubstitutions(SM, Buffer, SearchRange, MatchTy, Diags); 2091*e8d8bef9SDimitry Andric if (!PrintDiag) { 2092*e8d8bef9SDimitry Andric consumeError(std::move(MatchErrors)); 2093*e8d8bef9SDimitry Andric return; 2094*e8d8bef9SDimitry Andric } 2095*e8d8bef9SDimitry Andric 2096*e8d8bef9SDimitry Andric MatchErrors = handleErrors(std::move(MatchErrors), 2097*e8d8bef9SDimitry Andric [](const ErrorDiagnostic &E) { E.log(errs()); }); 2098*e8d8bef9SDimitry Andric 2099*e8d8bef9SDimitry Andric // No problem matching the string per se. 2100*e8d8bef9SDimitry Andric if (!MatchErrors) 2101*e8d8bef9SDimitry Andric return; 2102*e8d8bef9SDimitry Andric consumeError(std::move(MatchErrors)); 2103*e8d8bef9SDimitry Andric 2104*e8d8bef9SDimitry Andric // Print "not found" diagnostic. 2105*e8d8bef9SDimitry Andric std::string Message = formatv("{0}: {1} string not found in input", 2106*e8d8bef9SDimitry Andric Pat.getCheckTy().getDescription(Prefix), 2107*e8d8bef9SDimitry Andric (ExpectedMatch ? "expected" : "excluded")) 2108*e8d8bef9SDimitry Andric .str(); 2109*e8d8bef9SDimitry Andric if (Pat.getCount() > 1) 2110*e8d8bef9SDimitry Andric Message += formatv(" ({0} out of {1})", MatchedCount, Pat.getCount()).str(); 2111*e8d8bef9SDimitry Andric SM.PrintMessage( 2112*e8d8bef9SDimitry Andric Loc, ExpectedMatch ? SourceMgr::DK_Error : SourceMgr::DK_Remark, Message); 2113*e8d8bef9SDimitry Andric 2114*e8d8bef9SDimitry Andric // Print the "scanning from here" line. 2115*e8d8bef9SDimitry Andric SM.PrintMessage(SearchRange.Start, SourceMgr::DK_Note, "scanning from here"); 2116*e8d8bef9SDimitry Andric 2117*e8d8bef9SDimitry Andric // Allow the pattern to print additional information if desired. 2118*e8d8bef9SDimitry Andric Pat.printSubstitutions(SM, Buffer, SearchRange, MatchTy, nullptr); 2119*e8d8bef9SDimitry Andric 2120*e8d8bef9SDimitry Andric if (ExpectedMatch) 2121*e8d8bef9SDimitry Andric Pat.printFuzzyMatch(SM, Buffer, Diags); 2122*e8d8bef9SDimitry Andric } 2123*e8d8bef9SDimitry Andric 2124*e8d8bef9SDimitry Andric static void PrintNoMatch(bool ExpectedMatch, const SourceMgr &SM, 2125*e8d8bef9SDimitry Andric const FileCheckString &CheckStr, int MatchedCount, 2126*e8d8bef9SDimitry Andric StringRef Buffer, bool VerboseVerbose, 2127*e8d8bef9SDimitry Andric std::vector<FileCheckDiag> *Diags, Error MatchErrors) { 2128*e8d8bef9SDimitry Andric PrintNoMatch(ExpectedMatch, SM, CheckStr.Prefix, CheckStr.Loc, CheckStr.Pat, 2129*e8d8bef9SDimitry Andric MatchedCount, Buffer, VerboseVerbose, Diags, 2130*e8d8bef9SDimitry Andric std::move(MatchErrors)); 2131*e8d8bef9SDimitry Andric } 2132*e8d8bef9SDimitry Andric 2133*e8d8bef9SDimitry Andric /// Counts the number of newlines in the specified range. 2134*e8d8bef9SDimitry Andric static unsigned CountNumNewlinesBetween(StringRef Range, 2135*e8d8bef9SDimitry Andric const char *&FirstNewLine) { 2136*e8d8bef9SDimitry Andric unsigned NumNewLines = 0; 2137*e8d8bef9SDimitry Andric while (1) { 2138*e8d8bef9SDimitry Andric // Scan for newline. 2139*e8d8bef9SDimitry Andric Range = Range.substr(Range.find_first_of("\n\r")); 2140*e8d8bef9SDimitry Andric if (Range.empty()) 2141*e8d8bef9SDimitry Andric return NumNewLines; 2142*e8d8bef9SDimitry Andric 2143*e8d8bef9SDimitry Andric ++NumNewLines; 2144*e8d8bef9SDimitry Andric 2145*e8d8bef9SDimitry Andric // Handle \n\r and \r\n as a single newline. 2146*e8d8bef9SDimitry Andric if (Range.size() > 1 && (Range[1] == '\n' || Range[1] == '\r') && 2147*e8d8bef9SDimitry Andric (Range[0] != Range[1])) 2148*e8d8bef9SDimitry Andric Range = Range.substr(1); 2149*e8d8bef9SDimitry Andric Range = Range.substr(1); 2150*e8d8bef9SDimitry Andric 2151*e8d8bef9SDimitry Andric if (NumNewLines == 1) 2152*e8d8bef9SDimitry Andric FirstNewLine = Range.begin(); 2153*e8d8bef9SDimitry Andric } 2154*e8d8bef9SDimitry Andric } 2155*e8d8bef9SDimitry Andric 2156*e8d8bef9SDimitry Andric size_t FileCheckString::Check(const SourceMgr &SM, StringRef Buffer, 2157*e8d8bef9SDimitry Andric bool IsLabelScanMode, size_t &MatchLen, 2158*e8d8bef9SDimitry Andric FileCheckRequest &Req, 2159*e8d8bef9SDimitry Andric std::vector<FileCheckDiag> *Diags) const { 2160*e8d8bef9SDimitry Andric size_t LastPos = 0; 2161*e8d8bef9SDimitry Andric std::vector<const Pattern *> NotStrings; 2162*e8d8bef9SDimitry Andric 2163*e8d8bef9SDimitry Andric // IsLabelScanMode is true when we are scanning forward to find CHECK-LABEL 2164*e8d8bef9SDimitry Andric // bounds; we have not processed variable definitions within the bounded block 2165*e8d8bef9SDimitry Andric // yet so cannot handle any final CHECK-DAG yet; this is handled when going 2166*e8d8bef9SDimitry Andric // over the block again (including the last CHECK-LABEL) in normal mode. 2167*e8d8bef9SDimitry Andric if (!IsLabelScanMode) { 2168*e8d8bef9SDimitry Andric // Match "dag strings" (with mixed "not strings" if any). 2169*e8d8bef9SDimitry Andric LastPos = CheckDag(SM, Buffer, NotStrings, Req, Diags); 2170*e8d8bef9SDimitry Andric if (LastPos == StringRef::npos) 2171*e8d8bef9SDimitry Andric return StringRef::npos; 2172*e8d8bef9SDimitry Andric } 2173*e8d8bef9SDimitry Andric 2174*e8d8bef9SDimitry Andric // Match itself from the last position after matching CHECK-DAG. 2175*e8d8bef9SDimitry Andric size_t LastMatchEnd = LastPos; 2176*e8d8bef9SDimitry Andric size_t FirstMatchPos = 0; 2177*e8d8bef9SDimitry Andric // Go match the pattern Count times. Majority of patterns only match with 2178*e8d8bef9SDimitry Andric // count 1 though. 2179*e8d8bef9SDimitry Andric assert(Pat.getCount() != 0 && "pattern count can not be zero"); 2180*e8d8bef9SDimitry Andric for (int i = 1; i <= Pat.getCount(); i++) { 2181*e8d8bef9SDimitry Andric StringRef MatchBuffer = Buffer.substr(LastMatchEnd); 2182*e8d8bef9SDimitry Andric size_t CurrentMatchLen; 2183*e8d8bef9SDimitry Andric // get a match at current start point 2184*e8d8bef9SDimitry Andric Expected<size_t> MatchResult = Pat.match(MatchBuffer, CurrentMatchLen, SM); 2185*e8d8bef9SDimitry Andric 2186*e8d8bef9SDimitry Andric // report 2187*e8d8bef9SDimitry Andric if (!MatchResult) { 2188*e8d8bef9SDimitry Andric PrintNoMatch(true, SM, *this, i, MatchBuffer, Req.VerboseVerbose, Diags, 2189*e8d8bef9SDimitry Andric MatchResult.takeError()); 2190*e8d8bef9SDimitry Andric return StringRef::npos; 2191*e8d8bef9SDimitry Andric } 2192*e8d8bef9SDimitry Andric size_t MatchPos = *MatchResult; 2193*e8d8bef9SDimitry Andric PrintMatch(true, SM, *this, i, MatchBuffer, MatchPos, CurrentMatchLen, Req, 2194*e8d8bef9SDimitry Andric Diags); 2195*e8d8bef9SDimitry Andric if (i == 1) 2196*e8d8bef9SDimitry Andric FirstMatchPos = LastPos + MatchPos; 2197*e8d8bef9SDimitry Andric 2198*e8d8bef9SDimitry Andric // move start point after the match 2199*e8d8bef9SDimitry Andric LastMatchEnd += MatchPos + CurrentMatchLen; 2200*e8d8bef9SDimitry Andric } 2201*e8d8bef9SDimitry Andric // Full match len counts from first match pos. 2202*e8d8bef9SDimitry Andric MatchLen = LastMatchEnd - FirstMatchPos; 2203*e8d8bef9SDimitry Andric 2204*e8d8bef9SDimitry Andric // Similar to the above, in "label-scan mode" we can't yet handle CHECK-NEXT 2205*e8d8bef9SDimitry Andric // or CHECK-NOT 2206*e8d8bef9SDimitry Andric if (!IsLabelScanMode) { 2207*e8d8bef9SDimitry Andric size_t MatchPos = FirstMatchPos - LastPos; 2208*e8d8bef9SDimitry Andric StringRef MatchBuffer = Buffer.substr(LastPos); 2209*e8d8bef9SDimitry Andric StringRef SkippedRegion = Buffer.substr(LastPos, MatchPos); 2210*e8d8bef9SDimitry Andric 2211*e8d8bef9SDimitry Andric // If this check is a "CHECK-NEXT", verify that the previous match was on 2212*e8d8bef9SDimitry Andric // the previous line (i.e. that there is one newline between them). 2213*e8d8bef9SDimitry Andric if (CheckNext(SM, SkippedRegion)) { 2214*e8d8bef9SDimitry Andric ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine, SM, Loc, 2215*e8d8bef9SDimitry Andric Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen, 2216*e8d8bef9SDimitry Andric Diags, Req.Verbose); 2217*e8d8bef9SDimitry Andric return StringRef::npos; 2218*e8d8bef9SDimitry Andric } 2219*e8d8bef9SDimitry Andric 2220*e8d8bef9SDimitry Andric // If this check is a "CHECK-SAME", verify that the previous match was on 2221*e8d8bef9SDimitry Andric // the same line (i.e. that there is no newline between them). 2222*e8d8bef9SDimitry Andric if (CheckSame(SM, SkippedRegion)) { 2223*e8d8bef9SDimitry Andric ProcessMatchResult(FileCheckDiag::MatchFoundButWrongLine, SM, Loc, 2224*e8d8bef9SDimitry Andric Pat.getCheckTy(), MatchBuffer, MatchPos, MatchLen, 2225*e8d8bef9SDimitry Andric Diags, Req.Verbose); 2226*e8d8bef9SDimitry Andric return StringRef::npos; 2227*e8d8bef9SDimitry Andric } 2228*e8d8bef9SDimitry Andric 2229*e8d8bef9SDimitry Andric // If this match had "not strings", verify that they don't exist in the 2230*e8d8bef9SDimitry Andric // skipped region. 2231*e8d8bef9SDimitry Andric if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags)) 2232*e8d8bef9SDimitry Andric return StringRef::npos; 2233*e8d8bef9SDimitry Andric } 2234*e8d8bef9SDimitry Andric 2235*e8d8bef9SDimitry Andric return FirstMatchPos; 2236*e8d8bef9SDimitry Andric } 2237*e8d8bef9SDimitry Andric 2238*e8d8bef9SDimitry Andric bool FileCheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const { 2239*e8d8bef9SDimitry Andric if (Pat.getCheckTy() != Check::CheckNext && 2240*e8d8bef9SDimitry Andric Pat.getCheckTy() != Check::CheckEmpty) 2241*e8d8bef9SDimitry Andric return false; 2242*e8d8bef9SDimitry Andric 2243*e8d8bef9SDimitry Andric Twine CheckName = 2244*e8d8bef9SDimitry Andric Prefix + 2245*e8d8bef9SDimitry Andric Twine(Pat.getCheckTy() == Check::CheckEmpty ? "-EMPTY" : "-NEXT"); 2246*e8d8bef9SDimitry Andric 2247*e8d8bef9SDimitry Andric // Count the number of newlines between the previous match and this one. 2248*e8d8bef9SDimitry Andric const char *FirstNewLine = nullptr; 2249*e8d8bef9SDimitry Andric unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine); 2250*e8d8bef9SDimitry Andric 2251*e8d8bef9SDimitry Andric if (NumNewLines == 0) { 2252*e8d8bef9SDimitry Andric SM.PrintMessage(Loc, SourceMgr::DK_Error, 2253*e8d8bef9SDimitry Andric CheckName + ": is on the same line as previous match"); 2254*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note, 2255*e8d8bef9SDimitry Andric "'next' match was here"); 2256*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 2257*e8d8bef9SDimitry Andric "previous match ended here"); 2258*e8d8bef9SDimitry Andric return true; 2259*e8d8bef9SDimitry Andric } 2260*e8d8bef9SDimitry Andric 2261*e8d8bef9SDimitry Andric if (NumNewLines != 1) { 2262*e8d8bef9SDimitry Andric SM.PrintMessage(Loc, SourceMgr::DK_Error, 2263*e8d8bef9SDimitry Andric CheckName + 2264*e8d8bef9SDimitry Andric ": is not on the line after the previous match"); 2265*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note, 2266*e8d8bef9SDimitry Andric "'next' match was here"); 2267*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 2268*e8d8bef9SDimitry Andric "previous match ended here"); 2269*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note, 2270*e8d8bef9SDimitry Andric "non-matching line after previous match is here"); 2271*e8d8bef9SDimitry Andric return true; 2272*e8d8bef9SDimitry Andric } 2273*e8d8bef9SDimitry Andric 2274*e8d8bef9SDimitry Andric return false; 2275*e8d8bef9SDimitry Andric } 2276*e8d8bef9SDimitry Andric 2277*e8d8bef9SDimitry Andric bool FileCheckString::CheckSame(const SourceMgr &SM, StringRef Buffer) const { 2278*e8d8bef9SDimitry Andric if (Pat.getCheckTy() != Check::CheckSame) 2279*e8d8bef9SDimitry Andric return false; 2280*e8d8bef9SDimitry Andric 2281*e8d8bef9SDimitry Andric // Count the number of newlines between the previous match and this one. 2282*e8d8bef9SDimitry Andric const char *FirstNewLine = nullptr; 2283*e8d8bef9SDimitry Andric unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine); 2284*e8d8bef9SDimitry Andric 2285*e8d8bef9SDimitry Andric if (NumNewLines != 0) { 2286*e8d8bef9SDimitry Andric SM.PrintMessage(Loc, SourceMgr::DK_Error, 2287*e8d8bef9SDimitry Andric Prefix + 2288*e8d8bef9SDimitry Andric "-SAME: is not on the same line as the previous match"); 2289*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(Buffer.end()), SourceMgr::DK_Note, 2290*e8d8bef9SDimitry Andric "'next' match was here"); 2291*e8d8bef9SDimitry Andric SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, 2292*e8d8bef9SDimitry Andric "previous match ended here"); 2293*e8d8bef9SDimitry Andric return true; 2294*e8d8bef9SDimitry Andric } 2295*e8d8bef9SDimitry Andric 2296*e8d8bef9SDimitry Andric return false; 2297*e8d8bef9SDimitry Andric } 2298*e8d8bef9SDimitry Andric 2299*e8d8bef9SDimitry Andric bool FileCheckString::CheckNot(const SourceMgr &SM, StringRef Buffer, 2300*e8d8bef9SDimitry Andric const std::vector<const Pattern *> &NotStrings, 2301*e8d8bef9SDimitry Andric const FileCheckRequest &Req, 2302*e8d8bef9SDimitry Andric std::vector<FileCheckDiag> *Diags) const { 2303*e8d8bef9SDimitry Andric bool DirectiveFail = false; 2304*e8d8bef9SDimitry Andric for (const Pattern *Pat : NotStrings) { 2305*e8d8bef9SDimitry Andric assert((Pat->getCheckTy() == Check::CheckNot) && "Expect CHECK-NOT!"); 2306*e8d8bef9SDimitry Andric 2307*e8d8bef9SDimitry Andric size_t MatchLen = 0; 2308*e8d8bef9SDimitry Andric Expected<size_t> MatchResult = Pat->match(Buffer, MatchLen, SM); 2309*e8d8bef9SDimitry Andric 2310*e8d8bef9SDimitry Andric if (!MatchResult) { 2311*e8d8bef9SDimitry Andric PrintNoMatch(false, SM, Prefix, Pat->getLoc(), *Pat, 1, Buffer, 2312*e8d8bef9SDimitry Andric Req.VerboseVerbose, Diags, MatchResult.takeError()); 2313*e8d8bef9SDimitry Andric continue; 2314*e8d8bef9SDimitry Andric } 2315*e8d8bef9SDimitry Andric size_t Pos = *MatchResult; 2316*e8d8bef9SDimitry Andric 2317*e8d8bef9SDimitry Andric PrintMatch(false, SM, Prefix, Pat->getLoc(), *Pat, 1, Buffer, Pos, MatchLen, 2318*e8d8bef9SDimitry Andric Req, Diags); 2319*e8d8bef9SDimitry Andric DirectiveFail = true; 2320*e8d8bef9SDimitry Andric } 2321*e8d8bef9SDimitry Andric 2322*e8d8bef9SDimitry Andric return DirectiveFail; 2323*e8d8bef9SDimitry Andric } 2324*e8d8bef9SDimitry Andric 2325*e8d8bef9SDimitry Andric size_t FileCheckString::CheckDag(const SourceMgr &SM, StringRef Buffer, 2326*e8d8bef9SDimitry Andric std::vector<const Pattern *> &NotStrings, 2327*e8d8bef9SDimitry Andric const FileCheckRequest &Req, 2328*e8d8bef9SDimitry Andric std::vector<FileCheckDiag> *Diags) const { 2329*e8d8bef9SDimitry Andric if (DagNotStrings.empty()) 2330*e8d8bef9SDimitry Andric return 0; 2331*e8d8bef9SDimitry Andric 2332*e8d8bef9SDimitry Andric // The start of the search range. 2333*e8d8bef9SDimitry Andric size_t StartPos = 0; 2334*e8d8bef9SDimitry Andric 2335*e8d8bef9SDimitry Andric struct MatchRange { 2336*e8d8bef9SDimitry Andric size_t Pos; 2337*e8d8bef9SDimitry Andric size_t End; 2338*e8d8bef9SDimitry Andric }; 2339*e8d8bef9SDimitry Andric // A sorted list of ranges for non-overlapping CHECK-DAG matches. Match 2340*e8d8bef9SDimitry Andric // ranges are erased from this list once they are no longer in the search 2341*e8d8bef9SDimitry Andric // range. 2342*e8d8bef9SDimitry Andric std::list<MatchRange> MatchRanges; 2343*e8d8bef9SDimitry Andric 2344*e8d8bef9SDimitry Andric // We need PatItr and PatEnd later for detecting the end of a CHECK-DAG 2345*e8d8bef9SDimitry Andric // group, so we don't use a range-based for loop here. 2346*e8d8bef9SDimitry Andric for (auto PatItr = DagNotStrings.begin(), PatEnd = DagNotStrings.end(); 2347*e8d8bef9SDimitry Andric PatItr != PatEnd; ++PatItr) { 2348*e8d8bef9SDimitry Andric const Pattern &Pat = *PatItr; 2349*e8d8bef9SDimitry Andric assert((Pat.getCheckTy() == Check::CheckDAG || 2350*e8d8bef9SDimitry Andric Pat.getCheckTy() == Check::CheckNot) && 2351*e8d8bef9SDimitry Andric "Invalid CHECK-DAG or CHECK-NOT!"); 2352*e8d8bef9SDimitry Andric 2353*e8d8bef9SDimitry Andric if (Pat.getCheckTy() == Check::CheckNot) { 2354*e8d8bef9SDimitry Andric NotStrings.push_back(&Pat); 2355*e8d8bef9SDimitry Andric continue; 2356*e8d8bef9SDimitry Andric } 2357*e8d8bef9SDimitry Andric 2358*e8d8bef9SDimitry Andric assert((Pat.getCheckTy() == Check::CheckDAG) && "Expect CHECK-DAG!"); 2359*e8d8bef9SDimitry Andric 2360*e8d8bef9SDimitry Andric // CHECK-DAG always matches from the start. 2361*e8d8bef9SDimitry Andric size_t MatchLen = 0, MatchPos = StartPos; 2362*e8d8bef9SDimitry Andric 2363*e8d8bef9SDimitry Andric // Search for a match that doesn't overlap a previous match in this 2364*e8d8bef9SDimitry Andric // CHECK-DAG group. 2365*e8d8bef9SDimitry Andric for (auto MI = MatchRanges.begin(), ME = MatchRanges.end(); true; ++MI) { 2366*e8d8bef9SDimitry Andric StringRef MatchBuffer = Buffer.substr(MatchPos); 2367*e8d8bef9SDimitry Andric Expected<size_t> MatchResult = Pat.match(MatchBuffer, MatchLen, SM); 2368*e8d8bef9SDimitry Andric // With a group of CHECK-DAGs, a single mismatching means the match on 2369*e8d8bef9SDimitry Andric // that group of CHECK-DAGs fails immediately. 2370*e8d8bef9SDimitry Andric if (!MatchResult) { 2371*e8d8bef9SDimitry Andric PrintNoMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, MatchBuffer, 2372*e8d8bef9SDimitry Andric Req.VerboseVerbose, Diags, MatchResult.takeError()); 2373*e8d8bef9SDimitry Andric return StringRef::npos; 2374*e8d8bef9SDimitry Andric } 2375*e8d8bef9SDimitry Andric size_t MatchPosBuf = *MatchResult; 2376*e8d8bef9SDimitry Andric // Re-calc it as the offset relative to the start of the original string. 2377*e8d8bef9SDimitry Andric MatchPos += MatchPosBuf; 2378*e8d8bef9SDimitry Andric if (Req.VerboseVerbose) 2379*e8d8bef9SDimitry Andric PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer, MatchPos, 2380*e8d8bef9SDimitry Andric MatchLen, Req, Diags); 2381*e8d8bef9SDimitry Andric MatchRange M{MatchPos, MatchPos + MatchLen}; 2382*e8d8bef9SDimitry Andric if (Req.AllowDeprecatedDagOverlap) { 2383*e8d8bef9SDimitry Andric // We don't need to track all matches in this mode, so we just maintain 2384*e8d8bef9SDimitry Andric // one match range that encompasses the current CHECK-DAG group's 2385*e8d8bef9SDimitry Andric // matches. 2386*e8d8bef9SDimitry Andric if (MatchRanges.empty()) 2387*e8d8bef9SDimitry Andric MatchRanges.insert(MatchRanges.end(), M); 2388*e8d8bef9SDimitry Andric else { 2389*e8d8bef9SDimitry Andric auto Block = MatchRanges.begin(); 2390*e8d8bef9SDimitry Andric Block->Pos = std::min(Block->Pos, M.Pos); 2391*e8d8bef9SDimitry Andric Block->End = std::max(Block->End, M.End); 2392*e8d8bef9SDimitry Andric } 2393*e8d8bef9SDimitry Andric break; 2394*e8d8bef9SDimitry Andric } 2395*e8d8bef9SDimitry Andric // Iterate previous matches until overlapping match or insertion point. 2396*e8d8bef9SDimitry Andric bool Overlap = false; 2397*e8d8bef9SDimitry Andric for (; MI != ME; ++MI) { 2398*e8d8bef9SDimitry Andric if (M.Pos < MI->End) { 2399*e8d8bef9SDimitry Andric // !Overlap => New match has no overlap and is before this old match. 2400*e8d8bef9SDimitry Andric // Overlap => New match overlaps this old match. 2401*e8d8bef9SDimitry Andric Overlap = MI->Pos < M.End; 2402*e8d8bef9SDimitry Andric break; 2403*e8d8bef9SDimitry Andric } 2404*e8d8bef9SDimitry Andric } 2405*e8d8bef9SDimitry Andric if (!Overlap) { 2406*e8d8bef9SDimitry Andric // Insert non-overlapping match into list. 2407*e8d8bef9SDimitry Andric MatchRanges.insert(MI, M); 2408*e8d8bef9SDimitry Andric break; 2409*e8d8bef9SDimitry Andric } 2410*e8d8bef9SDimitry Andric if (Req.VerboseVerbose) { 2411*e8d8bef9SDimitry Andric // Due to their verbosity, we don't print verbose diagnostics here if 2412*e8d8bef9SDimitry Andric // we're gathering them for a different rendering, but we always print 2413*e8d8bef9SDimitry Andric // other diagnostics. 2414*e8d8bef9SDimitry Andric if (!Diags) { 2415*e8d8bef9SDimitry Andric SMLoc OldStart = SMLoc::getFromPointer(Buffer.data() + MI->Pos); 2416*e8d8bef9SDimitry Andric SMLoc OldEnd = SMLoc::getFromPointer(Buffer.data() + MI->End); 2417*e8d8bef9SDimitry Andric SMRange OldRange(OldStart, OldEnd); 2418*e8d8bef9SDimitry Andric SM.PrintMessage(OldStart, SourceMgr::DK_Note, 2419*e8d8bef9SDimitry Andric "match discarded, overlaps earlier DAG match here", 2420*e8d8bef9SDimitry Andric {OldRange}); 2421*e8d8bef9SDimitry Andric } else { 2422*e8d8bef9SDimitry Andric SMLoc CheckLoc = Diags->rbegin()->CheckLoc; 2423*e8d8bef9SDimitry Andric for (auto I = Diags->rbegin(), E = Diags->rend(); 2424*e8d8bef9SDimitry Andric I != E && I->CheckLoc == CheckLoc; ++I) 2425*e8d8bef9SDimitry Andric I->MatchTy = FileCheckDiag::MatchFoundButDiscarded; 2426*e8d8bef9SDimitry Andric } 2427*e8d8bef9SDimitry Andric } 2428*e8d8bef9SDimitry Andric MatchPos = MI->End; 2429*e8d8bef9SDimitry Andric } 2430*e8d8bef9SDimitry Andric if (!Req.VerboseVerbose) 2431*e8d8bef9SDimitry Andric PrintMatch(true, SM, Prefix, Pat.getLoc(), Pat, 1, Buffer, MatchPos, 2432*e8d8bef9SDimitry Andric MatchLen, Req, Diags); 2433*e8d8bef9SDimitry Andric 2434*e8d8bef9SDimitry Andric // Handle the end of a CHECK-DAG group. 2435*e8d8bef9SDimitry Andric if (std::next(PatItr) == PatEnd || 2436*e8d8bef9SDimitry Andric std::next(PatItr)->getCheckTy() == Check::CheckNot) { 2437*e8d8bef9SDimitry Andric if (!NotStrings.empty()) { 2438*e8d8bef9SDimitry Andric // If there are CHECK-NOTs between two CHECK-DAGs or from CHECK to 2439*e8d8bef9SDimitry Andric // CHECK-DAG, verify that there are no 'not' strings occurred in that 2440*e8d8bef9SDimitry Andric // region. 2441*e8d8bef9SDimitry Andric StringRef SkippedRegion = 2442*e8d8bef9SDimitry Andric Buffer.slice(StartPos, MatchRanges.begin()->Pos); 2443*e8d8bef9SDimitry Andric if (CheckNot(SM, SkippedRegion, NotStrings, Req, Diags)) 2444*e8d8bef9SDimitry Andric return StringRef::npos; 2445*e8d8bef9SDimitry Andric // Clear "not strings". 2446*e8d8bef9SDimitry Andric NotStrings.clear(); 2447*e8d8bef9SDimitry Andric } 2448*e8d8bef9SDimitry Andric // All subsequent CHECK-DAGs and CHECK-NOTs should be matched from the 2449*e8d8bef9SDimitry Andric // end of this CHECK-DAG group's match range. 2450*e8d8bef9SDimitry Andric StartPos = MatchRanges.rbegin()->End; 2451*e8d8bef9SDimitry Andric // Don't waste time checking for (impossible) overlaps before that. 2452*e8d8bef9SDimitry Andric MatchRanges.clear(); 2453*e8d8bef9SDimitry Andric } 2454*e8d8bef9SDimitry Andric } 2455*e8d8bef9SDimitry Andric 2456*e8d8bef9SDimitry Andric return StartPos; 2457*e8d8bef9SDimitry Andric } 2458*e8d8bef9SDimitry Andric 2459*e8d8bef9SDimitry Andric static bool ValidatePrefixes(StringRef Kind, StringSet<> &UniquePrefixes, 2460*e8d8bef9SDimitry Andric ArrayRef<StringRef> SuppliedPrefixes) { 2461*e8d8bef9SDimitry Andric for (StringRef Prefix : SuppliedPrefixes) { 2462*e8d8bef9SDimitry Andric if (Prefix.empty()) { 2463*e8d8bef9SDimitry Andric errs() << "error: supplied " << Kind << " prefix must not be the empty " 2464*e8d8bef9SDimitry Andric << "string\n"; 2465*e8d8bef9SDimitry Andric return false; 2466*e8d8bef9SDimitry Andric } 2467*e8d8bef9SDimitry Andric static const Regex Validator("^[a-zA-Z0-9_-]*$"); 2468*e8d8bef9SDimitry Andric if (!Validator.match(Prefix)) { 2469*e8d8bef9SDimitry Andric errs() << "error: supplied " << Kind << " prefix must start with a " 2470*e8d8bef9SDimitry Andric << "letter and contain only alphanumeric characters, hyphens, and " 2471*e8d8bef9SDimitry Andric << "underscores: '" << Prefix << "'\n"; 2472*e8d8bef9SDimitry Andric return false; 2473*e8d8bef9SDimitry Andric } 2474*e8d8bef9SDimitry Andric if (!UniquePrefixes.insert(Prefix).second) { 2475*e8d8bef9SDimitry Andric errs() << "error: supplied " << Kind << " prefix must be unique among " 2476*e8d8bef9SDimitry Andric << "check and comment prefixes: '" << Prefix << "'\n"; 2477*e8d8bef9SDimitry Andric return false; 2478*e8d8bef9SDimitry Andric } 2479*e8d8bef9SDimitry Andric } 2480*e8d8bef9SDimitry Andric return true; 2481*e8d8bef9SDimitry Andric } 2482*e8d8bef9SDimitry Andric 2483*e8d8bef9SDimitry Andric static const char *DefaultCheckPrefixes[] = {"CHECK"}; 2484*e8d8bef9SDimitry Andric static const char *DefaultCommentPrefixes[] = {"COM", "RUN"}; 2485*e8d8bef9SDimitry Andric 2486*e8d8bef9SDimitry Andric bool FileCheck::ValidateCheckPrefixes() { 2487*e8d8bef9SDimitry Andric StringSet<> UniquePrefixes; 2488*e8d8bef9SDimitry Andric // Add default prefixes to catch user-supplied duplicates of them below. 2489*e8d8bef9SDimitry Andric if (Req.CheckPrefixes.empty()) { 2490*e8d8bef9SDimitry Andric for (const char *Prefix : DefaultCheckPrefixes) 2491*e8d8bef9SDimitry Andric UniquePrefixes.insert(Prefix); 2492*e8d8bef9SDimitry Andric } 2493*e8d8bef9SDimitry Andric if (Req.CommentPrefixes.empty()) { 2494*e8d8bef9SDimitry Andric for (const char *Prefix : DefaultCommentPrefixes) 2495*e8d8bef9SDimitry Andric UniquePrefixes.insert(Prefix); 2496*e8d8bef9SDimitry Andric } 2497*e8d8bef9SDimitry Andric // Do not validate the default prefixes, or diagnostics about duplicates might 2498*e8d8bef9SDimitry Andric // incorrectly indicate that they were supplied by the user. 2499*e8d8bef9SDimitry Andric if (!ValidatePrefixes("check", UniquePrefixes, Req.CheckPrefixes)) 2500*e8d8bef9SDimitry Andric return false; 2501*e8d8bef9SDimitry Andric if (!ValidatePrefixes("comment", UniquePrefixes, Req.CommentPrefixes)) 2502*e8d8bef9SDimitry Andric return false; 2503*e8d8bef9SDimitry Andric return true; 2504*e8d8bef9SDimitry Andric } 2505*e8d8bef9SDimitry Andric 2506*e8d8bef9SDimitry Andric Regex FileCheck::buildCheckPrefixRegex() { 2507*e8d8bef9SDimitry Andric if (Req.CheckPrefixes.empty()) { 2508*e8d8bef9SDimitry Andric for (const char *Prefix : DefaultCheckPrefixes) 2509*e8d8bef9SDimitry Andric Req.CheckPrefixes.push_back(Prefix); 2510*e8d8bef9SDimitry Andric Req.IsDefaultCheckPrefix = true; 2511*e8d8bef9SDimitry Andric } 2512*e8d8bef9SDimitry Andric if (Req.CommentPrefixes.empty()) { 2513*e8d8bef9SDimitry Andric for (const char *Prefix : DefaultCommentPrefixes) 2514*e8d8bef9SDimitry Andric Req.CommentPrefixes.push_back(Prefix); 2515*e8d8bef9SDimitry Andric } 2516*e8d8bef9SDimitry Andric 2517*e8d8bef9SDimitry Andric // We already validated the contents of CheckPrefixes and CommentPrefixes so 2518*e8d8bef9SDimitry Andric // just concatenate them as alternatives. 2519*e8d8bef9SDimitry Andric SmallString<32> PrefixRegexStr; 2520*e8d8bef9SDimitry Andric for (size_t I = 0, E = Req.CheckPrefixes.size(); I != E; ++I) { 2521*e8d8bef9SDimitry Andric if (I != 0) 2522*e8d8bef9SDimitry Andric PrefixRegexStr.push_back('|'); 2523*e8d8bef9SDimitry Andric PrefixRegexStr.append(Req.CheckPrefixes[I]); 2524*e8d8bef9SDimitry Andric } 2525*e8d8bef9SDimitry Andric for (StringRef Prefix : Req.CommentPrefixes) { 2526*e8d8bef9SDimitry Andric PrefixRegexStr.push_back('|'); 2527*e8d8bef9SDimitry Andric PrefixRegexStr.append(Prefix); 2528*e8d8bef9SDimitry Andric } 2529*e8d8bef9SDimitry Andric 2530*e8d8bef9SDimitry Andric return Regex(PrefixRegexStr); 2531*e8d8bef9SDimitry Andric } 2532*e8d8bef9SDimitry Andric 2533*e8d8bef9SDimitry Andric Error FileCheckPatternContext::defineCmdlineVariables( 2534*e8d8bef9SDimitry Andric ArrayRef<StringRef> CmdlineDefines, SourceMgr &SM) { 2535*e8d8bef9SDimitry Andric assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() && 2536*e8d8bef9SDimitry Andric "Overriding defined variable with command-line variable definitions"); 2537*e8d8bef9SDimitry Andric 2538*e8d8bef9SDimitry Andric if (CmdlineDefines.empty()) 2539*e8d8bef9SDimitry Andric return Error::success(); 2540*e8d8bef9SDimitry Andric 2541*e8d8bef9SDimitry Andric // Create a string representing the vector of command-line definitions. Each 2542*e8d8bef9SDimitry Andric // definition is on its own line and prefixed with a definition number to 2543*e8d8bef9SDimitry Andric // clarify which definition a given diagnostic corresponds to. 2544*e8d8bef9SDimitry Andric unsigned I = 0; 2545*e8d8bef9SDimitry Andric Error Errs = Error::success(); 2546*e8d8bef9SDimitry Andric std::string CmdlineDefsDiag; 2547*e8d8bef9SDimitry Andric SmallVector<std::pair<size_t, size_t>, 4> CmdlineDefsIndices; 2548*e8d8bef9SDimitry Andric for (StringRef CmdlineDef : CmdlineDefines) { 2549*e8d8bef9SDimitry Andric std::string DefPrefix = ("Global define #" + Twine(++I) + ": ").str(); 2550*e8d8bef9SDimitry Andric size_t EqIdx = CmdlineDef.find('='); 2551*e8d8bef9SDimitry Andric if (EqIdx == StringRef::npos) { 2552*e8d8bef9SDimitry Andric CmdlineDefsIndices.push_back(std::make_pair(CmdlineDefsDiag.size(), 0)); 2553*e8d8bef9SDimitry Andric continue; 2554*e8d8bef9SDimitry Andric } 2555*e8d8bef9SDimitry Andric // Numeric variable definition. 2556*e8d8bef9SDimitry Andric if (CmdlineDef[0] == '#') { 2557*e8d8bef9SDimitry Andric // Append a copy of the command-line definition adapted to use the same 2558*e8d8bef9SDimitry Andric // format as in the input file to be able to reuse 2559*e8d8bef9SDimitry Andric // parseNumericSubstitutionBlock. 2560*e8d8bef9SDimitry Andric CmdlineDefsDiag += (DefPrefix + CmdlineDef + " (parsed as: [[").str(); 2561*e8d8bef9SDimitry Andric std::string SubstitutionStr = std::string(CmdlineDef); 2562*e8d8bef9SDimitry Andric SubstitutionStr[EqIdx] = ':'; 2563*e8d8bef9SDimitry Andric CmdlineDefsIndices.push_back( 2564*e8d8bef9SDimitry Andric std::make_pair(CmdlineDefsDiag.size(), SubstitutionStr.size())); 2565*e8d8bef9SDimitry Andric CmdlineDefsDiag += (SubstitutionStr + Twine("]])\n")).str(); 2566*e8d8bef9SDimitry Andric } else { 2567*e8d8bef9SDimitry Andric CmdlineDefsDiag += DefPrefix; 2568*e8d8bef9SDimitry Andric CmdlineDefsIndices.push_back( 2569*e8d8bef9SDimitry Andric std::make_pair(CmdlineDefsDiag.size(), CmdlineDef.size())); 2570*e8d8bef9SDimitry Andric CmdlineDefsDiag += (CmdlineDef + "\n").str(); 2571*e8d8bef9SDimitry Andric } 2572*e8d8bef9SDimitry Andric } 2573*e8d8bef9SDimitry Andric 2574*e8d8bef9SDimitry Andric // Create a buffer with fake command line content in order to display 2575*e8d8bef9SDimitry Andric // parsing diagnostic with location information and point to the 2576*e8d8bef9SDimitry Andric // global definition with invalid syntax. 2577*e8d8bef9SDimitry Andric std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer = 2578*e8d8bef9SDimitry Andric MemoryBuffer::getMemBufferCopy(CmdlineDefsDiag, "Global defines"); 2579*e8d8bef9SDimitry Andric StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer(); 2580*e8d8bef9SDimitry Andric SM.AddNewSourceBuffer(std::move(CmdLineDefsDiagBuffer), SMLoc()); 2581*e8d8bef9SDimitry Andric 2582*e8d8bef9SDimitry Andric for (std::pair<size_t, size_t> CmdlineDefIndices : CmdlineDefsIndices) { 2583*e8d8bef9SDimitry Andric StringRef CmdlineDef = CmdlineDefsDiagRef.substr(CmdlineDefIndices.first, 2584*e8d8bef9SDimitry Andric CmdlineDefIndices.second); 2585*e8d8bef9SDimitry Andric if (CmdlineDef.empty()) { 2586*e8d8bef9SDimitry Andric Errs = joinErrors( 2587*e8d8bef9SDimitry Andric std::move(Errs), 2588*e8d8bef9SDimitry Andric ErrorDiagnostic::get(SM, CmdlineDef, 2589*e8d8bef9SDimitry Andric "missing equal sign in global definition")); 2590*e8d8bef9SDimitry Andric continue; 2591*e8d8bef9SDimitry Andric } 2592*e8d8bef9SDimitry Andric 2593*e8d8bef9SDimitry Andric // Numeric variable definition. 2594*e8d8bef9SDimitry Andric if (CmdlineDef[0] == '#') { 2595*e8d8bef9SDimitry Andric // Now parse the definition both to check that the syntax is correct and 2596*e8d8bef9SDimitry Andric // to create the necessary class instance. 2597*e8d8bef9SDimitry Andric StringRef CmdlineDefExpr = CmdlineDef.substr(1); 2598*e8d8bef9SDimitry Andric Optional<NumericVariable *> DefinedNumericVariable; 2599*e8d8bef9SDimitry Andric Expected<std::unique_ptr<Expression>> ExpressionResult = 2600*e8d8bef9SDimitry Andric Pattern::parseNumericSubstitutionBlock( 2601*e8d8bef9SDimitry Andric CmdlineDefExpr, DefinedNumericVariable, false, None, this, SM); 2602*e8d8bef9SDimitry Andric if (!ExpressionResult) { 2603*e8d8bef9SDimitry Andric Errs = joinErrors(std::move(Errs), ExpressionResult.takeError()); 2604*e8d8bef9SDimitry Andric continue; 2605*e8d8bef9SDimitry Andric } 2606*e8d8bef9SDimitry Andric std::unique_ptr<Expression> Expression = std::move(*ExpressionResult); 2607*e8d8bef9SDimitry Andric // Now evaluate the expression whose value this variable should be set 2608*e8d8bef9SDimitry Andric // to, since the expression of a command-line variable definition should 2609*e8d8bef9SDimitry Andric // only use variables defined earlier on the command-line. If not, this 2610*e8d8bef9SDimitry Andric // is an error and we report it. 2611*e8d8bef9SDimitry Andric Expected<ExpressionValue> Value = Expression->getAST()->eval(); 2612*e8d8bef9SDimitry Andric if (!Value) { 2613*e8d8bef9SDimitry Andric Errs = joinErrors(std::move(Errs), Value.takeError()); 2614*e8d8bef9SDimitry Andric continue; 2615*e8d8bef9SDimitry Andric } 2616*e8d8bef9SDimitry Andric 2617*e8d8bef9SDimitry Andric assert(DefinedNumericVariable && "No variable defined"); 2618*e8d8bef9SDimitry Andric (*DefinedNumericVariable)->setValue(*Value); 2619*e8d8bef9SDimitry Andric 2620*e8d8bef9SDimitry Andric // Record this variable definition. 2621*e8d8bef9SDimitry Andric GlobalNumericVariableTable[(*DefinedNumericVariable)->getName()] = 2622*e8d8bef9SDimitry Andric *DefinedNumericVariable; 2623*e8d8bef9SDimitry Andric } else { 2624*e8d8bef9SDimitry Andric // String variable definition. 2625*e8d8bef9SDimitry Andric std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.split('='); 2626*e8d8bef9SDimitry Andric StringRef CmdlineName = CmdlineNameVal.first; 2627*e8d8bef9SDimitry Andric StringRef OrigCmdlineName = CmdlineName; 2628*e8d8bef9SDimitry Andric Expected<Pattern::VariableProperties> ParseVarResult = 2629*e8d8bef9SDimitry Andric Pattern::parseVariable(CmdlineName, SM); 2630*e8d8bef9SDimitry Andric if (!ParseVarResult) { 2631*e8d8bef9SDimitry Andric Errs = joinErrors(std::move(Errs), ParseVarResult.takeError()); 2632*e8d8bef9SDimitry Andric continue; 2633*e8d8bef9SDimitry Andric } 2634*e8d8bef9SDimitry Andric // Check that CmdlineName does not denote a pseudo variable is only 2635*e8d8bef9SDimitry Andric // composed of the parsed numeric variable. This catches cases like 2636*e8d8bef9SDimitry Andric // "FOO+2" in a "FOO+2=10" definition. 2637*e8d8bef9SDimitry Andric if (ParseVarResult->IsPseudo || !CmdlineName.empty()) { 2638*e8d8bef9SDimitry Andric Errs = joinErrors(std::move(Errs), 2639*e8d8bef9SDimitry Andric ErrorDiagnostic::get( 2640*e8d8bef9SDimitry Andric SM, OrigCmdlineName, 2641*e8d8bef9SDimitry Andric "invalid name in string variable definition '" + 2642*e8d8bef9SDimitry Andric OrigCmdlineName + "'")); 2643*e8d8bef9SDimitry Andric continue; 2644*e8d8bef9SDimitry Andric } 2645*e8d8bef9SDimitry Andric StringRef Name = ParseVarResult->Name; 2646*e8d8bef9SDimitry Andric 2647*e8d8bef9SDimitry Andric // Detect collisions between string and numeric variables when the former 2648*e8d8bef9SDimitry Andric // is created later than the latter. 2649*e8d8bef9SDimitry Andric if (GlobalNumericVariableTable.find(Name) != 2650*e8d8bef9SDimitry Andric GlobalNumericVariableTable.end()) { 2651*e8d8bef9SDimitry Andric Errs = joinErrors(std::move(Errs), 2652*e8d8bef9SDimitry Andric ErrorDiagnostic::get(SM, Name, 2653*e8d8bef9SDimitry Andric "numeric variable with name '" + 2654*e8d8bef9SDimitry Andric Name + "' already exists")); 2655*e8d8bef9SDimitry Andric continue; 2656*e8d8bef9SDimitry Andric } 2657*e8d8bef9SDimitry Andric GlobalVariableTable.insert(CmdlineNameVal); 2658*e8d8bef9SDimitry Andric // Mark the string variable as defined to detect collisions between 2659*e8d8bef9SDimitry Andric // string and numeric variables in defineCmdlineVariables when the latter 2660*e8d8bef9SDimitry Andric // is created later than the former. We cannot reuse GlobalVariableTable 2661*e8d8bef9SDimitry Andric // for this by populating it with an empty string since we would then 2662*e8d8bef9SDimitry Andric // lose the ability to detect the use of an undefined variable in 2663*e8d8bef9SDimitry Andric // match(). 2664*e8d8bef9SDimitry Andric DefinedVariableTable[Name] = true; 2665*e8d8bef9SDimitry Andric } 2666*e8d8bef9SDimitry Andric } 2667*e8d8bef9SDimitry Andric 2668*e8d8bef9SDimitry Andric return Errs; 2669*e8d8bef9SDimitry Andric } 2670*e8d8bef9SDimitry Andric 2671*e8d8bef9SDimitry Andric void FileCheckPatternContext::clearLocalVars() { 2672*e8d8bef9SDimitry Andric SmallVector<StringRef, 16> LocalPatternVars, LocalNumericVars; 2673*e8d8bef9SDimitry Andric for (const StringMapEntry<StringRef> &Var : GlobalVariableTable) 2674*e8d8bef9SDimitry Andric if (Var.first()[0] != '$') 2675*e8d8bef9SDimitry Andric LocalPatternVars.push_back(Var.first()); 2676*e8d8bef9SDimitry Andric 2677*e8d8bef9SDimitry Andric // Numeric substitution reads the value of a variable directly, not via 2678*e8d8bef9SDimitry Andric // GlobalNumericVariableTable. Therefore, we clear local variables by 2679*e8d8bef9SDimitry Andric // clearing their value which will lead to a numeric substitution failure. We 2680*e8d8bef9SDimitry Andric // also mark the variable for removal from GlobalNumericVariableTable since 2681*e8d8bef9SDimitry Andric // this is what defineCmdlineVariables checks to decide that no global 2682*e8d8bef9SDimitry Andric // variable has been defined. 2683*e8d8bef9SDimitry Andric for (const auto &Var : GlobalNumericVariableTable) 2684*e8d8bef9SDimitry Andric if (Var.first()[0] != '$') { 2685*e8d8bef9SDimitry Andric Var.getValue()->clearValue(); 2686*e8d8bef9SDimitry Andric LocalNumericVars.push_back(Var.first()); 2687*e8d8bef9SDimitry Andric } 2688*e8d8bef9SDimitry Andric 2689*e8d8bef9SDimitry Andric for (const auto &Var : LocalPatternVars) 2690*e8d8bef9SDimitry Andric GlobalVariableTable.erase(Var); 2691*e8d8bef9SDimitry Andric for (const auto &Var : LocalNumericVars) 2692*e8d8bef9SDimitry Andric GlobalNumericVariableTable.erase(Var); 2693*e8d8bef9SDimitry Andric } 2694*e8d8bef9SDimitry Andric 2695*e8d8bef9SDimitry Andric bool FileCheck::checkInput(SourceMgr &SM, StringRef Buffer, 2696*e8d8bef9SDimitry Andric std::vector<FileCheckDiag> *Diags) { 2697*e8d8bef9SDimitry Andric bool ChecksFailed = false; 2698*e8d8bef9SDimitry Andric 2699*e8d8bef9SDimitry Andric unsigned i = 0, j = 0, e = CheckStrings->size(); 2700*e8d8bef9SDimitry Andric while (true) { 2701*e8d8bef9SDimitry Andric StringRef CheckRegion; 2702*e8d8bef9SDimitry Andric if (j == e) { 2703*e8d8bef9SDimitry Andric CheckRegion = Buffer; 2704*e8d8bef9SDimitry Andric } else { 2705*e8d8bef9SDimitry Andric const FileCheckString &CheckLabelStr = (*CheckStrings)[j]; 2706*e8d8bef9SDimitry Andric if (CheckLabelStr.Pat.getCheckTy() != Check::CheckLabel) { 2707*e8d8bef9SDimitry Andric ++j; 2708*e8d8bef9SDimitry Andric continue; 2709*e8d8bef9SDimitry Andric } 2710*e8d8bef9SDimitry Andric 2711*e8d8bef9SDimitry Andric // Scan to next CHECK-LABEL match, ignoring CHECK-NOT and CHECK-DAG 2712*e8d8bef9SDimitry Andric size_t MatchLabelLen = 0; 2713*e8d8bef9SDimitry Andric size_t MatchLabelPos = 2714*e8d8bef9SDimitry Andric CheckLabelStr.Check(SM, Buffer, true, MatchLabelLen, Req, Diags); 2715*e8d8bef9SDimitry Andric if (MatchLabelPos == StringRef::npos) 2716*e8d8bef9SDimitry Andric // Immediately bail if CHECK-LABEL fails, nothing else we can do. 2717*e8d8bef9SDimitry Andric return false; 2718*e8d8bef9SDimitry Andric 2719*e8d8bef9SDimitry Andric CheckRegion = Buffer.substr(0, MatchLabelPos + MatchLabelLen); 2720*e8d8bef9SDimitry Andric Buffer = Buffer.substr(MatchLabelPos + MatchLabelLen); 2721*e8d8bef9SDimitry Andric ++j; 2722*e8d8bef9SDimitry Andric } 2723*e8d8bef9SDimitry Andric 2724*e8d8bef9SDimitry Andric // Do not clear the first region as it's the one before the first 2725*e8d8bef9SDimitry Andric // CHECK-LABEL and it would clear variables defined on the command-line 2726*e8d8bef9SDimitry Andric // before they get used. 2727*e8d8bef9SDimitry Andric if (i != 0 && Req.EnableVarScope) 2728*e8d8bef9SDimitry Andric PatternContext->clearLocalVars(); 2729*e8d8bef9SDimitry Andric 2730*e8d8bef9SDimitry Andric for (; i != j; ++i) { 2731*e8d8bef9SDimitry Andric const FileCheckString &CheckStr = (*CheckStrings)[i]; 2732*e8d8bef9SDimitry Andric 2733*e8d8bef9SDimitry Andric // Check each string within the scanned region, including a second check 2734*e8d8bef9SDimitry Andric // of any final CHECK-LABEL (to verify CHECK-NOT and CHECK-DAG) 2735*e8d8bef9SDimitry Andric size_t MatchLen = 0; 2736*e8d8bef9SDimitry Andric size_t MatchPos = 2737*e8d8bef9SDimitry Andric CheckStr.Check(SM, CheckRegion, false, MatchLen, Req, Diags); 2738*e8d8bef9SDimitry Andric 2739*e8d8bef9SDimitry Andric if (MatchPos == StringRef::npos) { 2740*e8d8bef9SDimitry Andric ChecksFailed = true; 2741*e8d8bef9SDimitry Andric i = j; 2742*e8d8bef9SDimitry Andric break; 2743*e8d8bef9SDimitry Andric } 2744*e8d8bef9SDimitry Andric 2745*e8d8bef9SDimitry Andric CheckRegion = CheckRegion.substr(MatchPos + MatchLen); 2746*e8d8bef9SDimitry Andric } 2747*e8d8bef9SDimitry Andric 2748*e8d8bef9SDimitry Andric if (j == e) 2749*e8d8bef9SDimitry Andric break; 2750*e8d8bef9SDimitry Andric } 2751*e8d8bef9SDimitry Andric 2752*e8d8bef9SDimitry Andric // Success if no checks failed. 2753*e8d8bef9SDimitry Andric return !ChecksFailed; 2754*e8d8bef9SDimitry Andric } 2755