diff options
author | Thomas Preud'homme <thomasp@graphcore.ai> | 2019-05-14 08:43:11 +0000 |
---|---|---|
committer | Thomas Preud'homme <thomasp@graphcore.ai> | 2019-05-14 08:43:11 +0000 |
commit | 004393681c25e34e921adccc69ae6378090dee54 (patch) | |
tree | ed521f05c531892d36ca7237236c3460f2e0638d /llvm/lib/Support/FileCheck.cpp | |
parent | 56f9afaf6b16eacdd497105ef2b34353c269fd83 (diff) | |
download | llvm-004393681c25e34e921adccc69ae6378090dee54.zip llvm-004393681c25e34e921adccc69ae6378090dee54.tar.gz llvm-004393681c25e34e921adccc69ae6378090dee54.tar.bz2 |
Revert "FileCheck [5/12]: Introduce regular numeric variables"
This reverts r360578 (git e47362c1ec1ea31b626336cc05822035601c3e57) to
solve the sphinx build failure on
http://lab.llvm.org:8011/builders/llvm-sphinx-docs buildbot.
llvm-svn: 360653
Diffstat (limited to 'llvm/lib/Support/FileCheck.cpp')
-rw-r--r-- | llvm/lib/Support/FileCheck.cpp | 302 |
1 files changed, 67 insertions, 235 deletions
diff --git a/llvm/lib/Support/FileCheck.cpp b/llvm/lib/Support/FileCheck.cpp index effb643..25ea7e4 100644 --- a/llvm/lib/Support/FileCheck.cpp +++ b/llvm/lib/Support/FileCheck.cpp @@ -24,54 +24,24 @@ using namespace llvm; -bool FileCheckNumericVariable::setValue(uint64_t NewValue) { - if (Value) - return true; - Value = NewValue; - return false; -} - -bool FileCheckNumericVariable::clearValue() { - if (!Value) - return true; - Value = llvm::None; - return false; -} - -llvm::Optional<uint64_t> FileCheckNumExpr::eval() const { - llvm::Optional<uint64_t> LeftOp = this->LeftOp->getValue(); - // Variable is undefined. - if (!LeftOp) - return llvm::None; - return EvalBinop(*LeftOp, RightOp); -} - -StringRef FileCheckNumExpr::getUndefVarName() const { - if (!LeftOp->getValue()) - return LeftOp->getName(); - return StringRef(); -} - llvm::Optional<std::string> FileCheckPatternSubstitution::getResult() const { if (IsNumExpr) { - llvm::Optional<uint64_t> EvaluatedValue = NumExpr->eval(); - if (!EvaluatedValue) + return utostr(NumExpr->getValue()); + } else { + // Look up the value and escape it so that we can put it into the + // regex. + llvm::Optional<StringRef> VarVal = Context->getPatternVarValue(FromStr); + if (!VarVal) return llvm::None; - return utostr(*EvaluatedValue); + return Regex::escape(*VarVal); } - - // Look up the value and escape it so that we can put it into the regex. - llvm::Optional<StringRef> VarVal = Context->getPatternVarValue(FromStr); - if (!VarVal) - return llvm::None; - return Regex::escape(*VarVal); } StringRef FileCheckPatternSubstitution::getUndefVarName() const { + // Parsing guarantees only @LINE is ever referenced and it is not undefined + // by ClearLocalVars. if (IsNumExpr) - // Although a use of an undefined numeric variable is detected at parse - // time, a numeric variable can be undefined later by ClearLocalVariables. - return NumExpr->getUndefVarName(); + return StringRef(); if (!Context->getPatternVarValue(FromStr)) return FromStr; @@ -121,70 +91,31 @@ static char popFront(StringRef &S) { return C; } -static uint64_t add(uint64_t LeftOp, uint64_t RightOp) { - return LeftOp + RightOp; -} -static uint64_t sub(uint64_t LeftOp, uint64_t RightOp) { - return LeftOp - RightOp; -} - FileCheckNumExpr * -FileCheckPattern::parseNumericExpression(StringRef Name, bool IsPseudo, - StringRef Trailer, +FileCheckPattern::parseNumericExpression(StringRef Name, StringRef Trailer, const SourceMgr &SM) const { - if (IsPseudo && !Name.equals("@LINE")) { + if (!Name.equals("@LINE")) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, "invalid pseudo numeric variable '" + Name + "'"); return nullptr; } - // This method is indirectly called from ParsePattern for all numeric - // variable definitions and uses in the order in which they appear in the - // CHECK pattern. For each definition, the pointer to the class instance of - // the corresponding numeric variable definition is stored in - // GlobalNumericVariableTable. Therefore, the pointer we get below is for the - // class instance corresponding to the last definition of this variable use. - auto VarTableIter = Context->GlobalNumericVariableTable.find(Name); - if (VarTableIter == Context->GlobalNumericVariableTable.end()) { - SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, - "using undefined numeric variable '" + Name + "'"); - return nullptr; - } - - FileCheckNumericVariable *LeftOp = VarTableIter->second; - - // Check if this is a supported operation and select a function to perform - // it. + // Check if this is a supported operation and select function to perform it. Trailer = Trailer.ltrim(SpaceChars); - if (Trailer.empty()) { - return Context->makeNumExpr(add, LeftOp, 0); - } + if (Trailer.empty()) + return Context->makeNumExpr(LineNumber); SMLoc OpLoc = SMLoc::getFromPointer(Trailer.data()); char Operator = popFront(Trailer); - binop_eval_t EvalBinop; - switch (Operator) { - case '+': - EvalBinop = add; - break; - case '-': - EvalBinop = sub; - break; - default: - SM.PrintMessage(OpLoc, SourceMgr::DK_Error, - Twine("unsupported numeric operation '") + Twine(Operator) + - "'"); - return nullptr; - } // Parse right operand. Trailer = Trailer.ltrim(SpaceChars); if (Trailer.empty()) { SM.PrintMessage(SMLoc::getFromPointer(Trailer.data()), SourceMgr::DK_Error, - "missing operand in numeric expression"); + "missing operand in numeric expression '" + Trailer + "'"); return nullptr; } - uint64_t RightOp; - if (Trailer.consumeInteger(10, RightOp)) { + uint64_t Offset; + if (Trailer.consumeInteger(10, Offset)) { SM.PrintMessage(SMLoc::getFromPointer(Trailer.data()), SourceMgr::DK_Error, "invalid offset in numeric expression '" + Trailer + "'"); return nullptr; @@ -197,24 +128,31 @@ FileCheckPattern::parseNumericExpression(StringRef Name, bool IsPseudo, return nullptr; } - return Context->makeNumExpr(EvalBinop, LeftOp, RightOp); + uint64_t Value; + switch (Operator) { + case '+': + Value = LineNumber + Offset; + break; + case '-': + Value = LineNumber - Offset; + break; + default: + SM.PrintMessage(OpLoc, SourceMgr::DK_Error, + Twine("unsupported numeric operation '") + Twine(Operator) + + "'"); + return nullptr; + } + return Context->makeNumExpr(Value); } bool FileCheckPattern::ParsePattern(StringRef PatternStr, StringRef Prefix, - SourceMgr &SM, unsigned LineNumber, - const FileCheckRequest &Req) { + SourceMgr &SM, unsigned LineNumber, + const FileCheckRequest &Req) { bool MatchFullLinesHere = Req.MatchFullLines && CheckTy != Check::CheckNot; this->LineNumber = LineNumber; PatternLoc = SMLoc::getFromPointer(PatternStr.data()); - // Create fake @LINE pseudo variable definition. - StringRef LinePseudo = "@LINE"; - uint64_t LineNumber64 = LineNumber; - FileCheckNumericVariable *LinePseudoVar = - Context->makeNumericVariable(LinePseudo, LineNumber64); - Context->GlobalNumericVariableTable[LinePseudo] = LinePseudoVar; - if (!(Req.NoCanonicalizeWhiteSpace && Req.MatchFullLines)) // Ignore trailing whitespace. while (!PatternStr.empty() && @@ -292,10 +230,10 @@ bool FileCheckPattern::ParsePattern(StringRef PatternStr, StringRef Prefix, // forms: [[foo:.*]] and [[foo]]. The former matches .* (or some other // regex) and assigns it to the FileCheck variable 'foo'. The latter // substitutes foo's value. Numeric expressions start with a '#' sign after - // the double brackets and only have the substitution form. Both pattern - // and numeric variables must satisfy the regular expression - // "[a-zA-Z_][0-9a-zA-Z_]*" to be valid, as this helps catch some common - // errors. + // the double brackets and only have the substitution form. Pattern + // variables must satisfy the regular expression "[a-zA-Z_][0-9a-zA-Z_]*" + // to be valid, as this helps catch some common errors. Numeric expressions + // only support the @LINE pseudo numeric variable. if (PatternStr.startswith("[[")) { StringRef UnparsedPatternStr = PatternStr.substr(2); // Find the closing bracket pair ending the match. End is going to be an @@ -345,33 +283,21 @@ bool FileCheckPattern::ParsePattern(StringRef PatternStr, StringRef Prefix, StringRef Trailer = MatchStr.substr(TrailIdx); bool IsVarDef = (VarEndIdx != StringRef::npos); - if (IsVarDef) { - if (IsPseudo || !Trailer.consume_front(":")) { - SM.PrintMessage(SMLoc::getFromPointer(MatchStr.data()), - SourceMgr::DK_Error, - "invalid name in pattern variable definition"); - return true; - } - - // Detect collisions between pattern and numeric variables when the - // former is created later than the latter. - if (Context->GlobalNumericVariableTable.find(Name) != - Context->GlobalNumericVariableTable.end()) { - SM.PrintMessage( - SMLoc::getFromPointer(MatchStr.data()), SourceMgr::DK_Error, - "numeric variable with name '" + Name + "' already exists"); - return true; - } + if (IsVarDef && (IsPseudo || !Trailer.consume_front(":"))) { + SM.PrintMessage(SMLoc::getFromPointer(MatchStr.data()), + SourceMgr::DK_Error, + "invalid name in pattern variable definition"); + return true; } - if (IsNumExpr || (!IsVarDef && IsPseudo)) { - NumExpr = parseNumericExpression(Name, IsPseudo, Trailer, SM); + if (!IsVarDef && IsPseudo) { + NumExpr = parseNumericExpression(Name, Trailer, SM); if (NumExpr == nullptr) return true; IsNumExpr = true; } - // Handle variable use: [[foo]] and [[#<foo expr>]]. + // Handle [[foo]]. if (!IsVarDef) { // Handle use of pattern variables that were defined earlier on the // same line by emitting a backreference. @@ -640,22 +566,12 @@ FileCheckPatternContext::getPatternVarValue(StringRef VarName) { return VarIter->second; } -FileCheckNumExpr * -FileCheckPatternContext::makeNumExpr(binop_eval_t EvalBinop, - FileCheckNumericVariable *OperandLeft, - uint64_t OperandRight) { - NumExprs.push_back(llvm::make_unique<FileCheckNumExpr>(EvalBinop, OperandLeft, - OperandRight)); +template <class... Types> +FileCheckNumExpr *FileCheckPatternContext::makeNumExpr(Types... Args) { + NumExprs.emplace_back(new FileCheckNumExpr(Args...)); return NumExprs.back().get(); } -FileCheckNumericVariable * -FileCheckPatternContext::makeNumericVariable(StringRef Name, uint64_t Value) { - NumericVariables.push_back( - llvm::make_unique<FileCheckNumericVariable>(Name, Value)); - return NumericVariables.back().get(); -} - size_t FileCheckPattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) { // Offset keeps track of the current offset within the input Str size_t Offset = 0; @@ -1529,7 +1445,7 @@ Regex llvm::FileCheck::buildCheckPrefixRegex() { bool FileCheckPatternContext::defineCmdlineVariables( std::vector<std::string> &CmdlineDefines, SourceMgr &SM) { - assert(GlobalVariableTable.empty() && GlobalNumericVariableTable.empty() && + assert(GlobalVariableTable.empty() && "Overriding defined variable with command-line variable definitions"); if (CmdlineDefines.empty()) @@ -1547,9 +1463,6 @@ bool FileCheckPatternContext::defineCmdlineVariables( CmdlineDefsDiag += (Prefix1 + Twine(++I) + Prefix2 + CmdlineDef + "\n").str(); - // Create a buffer with fake command line content in order to display - // parsing diagnostic with location information and point to the - // global definition with invalid syntax. std::unique_ptr<MemoryBuffer> CmdLineDefsDiagBuffer = MemoryBuffer::getMemBufferCopy(CmdlineDefsDiag, "Global defines"); StringRef CmdlineDefsDiagRef = CmdLineDefsDiagBuffer->getBuffer(); @@ -1559,91 +1472,27 @@ bool FileCheckPatternContext::defineCmdlineVariables( CmdlineDefsDiagRef.split(CmdlineDefsDiagVec, '\n', -1 /*MaxSplit*/, false /*KeepEmpty*/); for (StringRef CmdlineDefDiag : CmdlineDefsDiagVec) { - unsigned DefStart = CmdlineDefDiag.find(Prefix2) + Prefix2.size(); - StringRef CmdlineDef = CmdlineDefDiag.substr(DefStart); - if (CmdlineDef.find('=') == StringRef::npos) { - SM.PrintMessage(SMLoc::getFromPointer(CmdlineDef.data()), + unsigned NameStart = CmdlineDefDiag.find(Prefix2) + Prefix2.size(); + if (CmdlineDefDiag.substr(NameStart).find('=') == StringRef::npos) { + SM.PrintMessage(SMLoc::getFromPointer(CmdlineDefDiag.data()), SourceMgr::DK_Error, "Missing equal sign in global definition"); ErrorFound = true; continue; } - - // Numeric variable definition. - if (CmdlineDef[0] == '#') { - bool IsPseudo; - unsigned TrailIdx; - size_t EqIdx = CmdlineDef.find('='); - StringRef CmdlineName = CmdlineDef.substr(1, EqIdx - 1); - if (FileCheckPattern::parseVariable(CmdlineName, IsPseudo, TrailIdx) || - IsPseudo || TrailIdx != CmdlineName.size() || CmdlineName.empty()) { - SM.PrintMessage(SMLoc::getFromPointer(CmdlineName.data()), - SourceMgr::DK_Error, - "invalid name in numeric variable definition '" + - CmdlineName + "'"); - ErrorFound = true; - continue; - } - - // Detect collisions between pattern and numeric variables when the - // latter is created later than the former. - if (DefinedVariableTable.find(CmdlineName) != - DefinedVariableTable.end()) { - SM.PrintMessage( - SMLoc::getFromPointer(CmdlineName.data()), SourceMgr::DK_Error, - "pattern variable with name '" + CmdlineName + "' already exists"); - ErrorFound = true; - continue; - } - - StringRef CmdlineVal = CmdlineDef.substr(EqIdx + 1); - uint64_t Val; - if (CmdlineVal.getAsInteger(10, Val)) { - SM.PrintMessage(SMLoc::getFromPointer(CmdlineVal.data()), - SourceMgr::DK_Error, - "invalid value in numeric variable definition '" + - CmdlineVal + "'"); - ErrorFound = true; - continue; - } - auto DefinedNumericVariable = makeNumericVariable(CmdlineName, Val); - - // Record this variable definition. - GlobalNumericVariableTable[CmdlineName] = DefinedNumericVariable; - } else { - // Pattern variable definition. - std::pair<StringRef, StringRef> CmdlineNameVal = CmdlineDef.split('='); - StringRef Name = CmdlineNameVal.first; - bool IsPseudo; - unsigned TrailIdx; - if (FileCheckPattern::parseVariable(Name, IsPseudo, TrailIdx) || - IsPseudo || TrailIdx != Name.size() || Name.empty()) { - SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, - "invalid name in pattern variable definition '" + Name + - "'"); - ErrorFound = true; - continue; - } - - // Detect collisions between pattern and numeric variables when the - // former is created later than the latter. - if (GlobalNumericVariableTable.find(Name) != - GlobalNumericVariableTable.end()) { - SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, - "numeric variable with name '" + Name + - "' already exists"); - ErrorFound = true; - continue; - } - GlobalVariableTable.insert(CmdlineNameVal); - // Mark the pattern variable as defined to detect collisions between - // pattern and numeric variables in DefineCmdlineVariables when the - // latter is created later than the former. We cannot reuse - // GlobalVariableTable for that by populating it with an empty string - // since we would then lose the ability to detect the use of an undefined - // variable in Match(). - DefinedVariableTable[Name] = true; + std::pair<StringRef, StringRef> CmdlineNameVal = + CmdlineDefDiag.substr(NameStart).split('='); + StringRef Name = CmdlineNameVal.first; + bool IsPseudo; + unsigned TrailIdx; + if (FileCheckPattern::parseVariable(Name, IsPseudo, TrailIdx) || IsPseudo || + TrailIdx != Name.size() || Name.empty()) { + SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, + "invalid name for variable definition '" + Name + "'"); + ErrorFound = true; + continue; } + GlobalVariableTable.insert(CmdlineNameVal); } return ErrorFound; @@ -1655,22 +1504,8 @@ void FileCheckPatternContext::clearLocalVars() { if (Var.first()[0] != '$') LocalPatternVars.push_back(Var.first()); - // Numeric expression substitution reads the value of a variable directly, - // not via GlobalNumericVariableTable. Therefore, we clear local variables by - // clearing their value which will lead to a numeric expression substitution - // failure. We also mark the variable for removal from - // GlobalNumericVariableTable since this is what defineCmdlineVariables - // checks to decide that no global variable has been defined. - for (const auto &Var : GlobalNumericVariableTable) - if (Var.first()[0] != '$') { - Var.getValue()->clearValue(); - LocalNumericVars.push_back(Var.first()); - } - for (const auto &Var : LocalPatternVars) GlobalVariableTable.erase(Var); - for (const auto &Var : LocalNumericVars) - GlobalNumericVariableTable.erase(Var); } bool llvm::FileCheck::CheckInput(SourceMgr &SM, StringRef Buffer, @@ -1703,10 +1538,7 @@ bool llvm::FileCheck::CheckInput(SourceMgr &SM, StringRef Buffer, ++j; } - // Do not clear the first region as it's the one before the first - // CHECK-LABEL and it would clear variables defined on the command-line - // before they get used. - if (i != 0 && Req.EnableVarScope) + if (Req.EnableVarScope) PatternContext.clearLocalVars(); for (; i != j; ++i) { |