diff --git a/llvm/include/llvm/Support/FileCheck.h b/llvm/include/llvm/Support/FileCheck.h
--- a/llvm/include/llvm/Support/FileCheck.h
+++ b/llvm/include/llvm/Support/FileCheck.h
@@ -155,6 +155,7 @@
   /// Returns the pointer to the global state for all patterns in this
   /// FileCheck instance.
   FileCheckPatternContext *getContext() const { return Context; }
+
   /// Return whether \p is a valid first character for a variable name.
   static bool isValidVarNameStart(char C);
   /// Verify that the string at the start of \p Str is a well formed variable.
@@ -162,6 +163,11 @@
   /// variable and \p TrailIdx to the position of the last character that is
   /// part of the variable name. Otherwise, only return true.
   static bool parseVariable(StringRef Str, bool &IsPseudo, unsigned &TrailIdx);
+  /// Parse a numeric expression involving pseudo variable \p Name with the
+  /// string corresponding to the operation being performed in \p Trailer.
+  /// Return whether parsing failed in which case errors are reported on \p SM.
+  bool parseExpression(StringRef Name, StringRef Trailer,
+                       const SourceMgr &SM) const;
   bool ParsePattern(StringRef PatternStr, StringRef Prefix, SourceMgr &SM,
                     unsigned LineNumber, const FileCheckRequest &Req);
   size_t match(StringRef Buffer, size_t &MatchLen) const;
@@ -184,7 +190,7 @@
   bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM);
   void AddBackrefToRegEx(unsigned BackrefNum);
   unsigned computeMatchDistance(StringRef Buffer) const;
-  bool EvaluateExpression(StringRef Expr, std::string &Value) const;
+  void evaluateExpression(StringRef Expr, std::string &Value) const;
   size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM);
 };
 
diff --git a/llvm/lib/Support/FileCheck.cpp b/llvm/lib/Support/FileCheck.cpp
--- a/llvm/lib/Support/FileCheck.cpp
+++ b/llvm/lib/Support/FileCheck.cpp
@@ -56,6 +56,58 @@
   return false;
 }
 
+// Parsing helper function that strips the first character in S and returns it.
+static char next(StringRef &S) {
+  char C = S.front();
+  S = S.drop_front();
+  return C;
+}
+
+bool FileCheckPattern::parseExpression(StringRef Name, StringRef Trailer,
+                                       const SourceMgr &SM) const {
+  if (!Name.equals("@LINE")) {
+    SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error,
+                    "invalid pseudo variable '" + Name + "'");
+    return true;
+  }
+
+  // Check if this is a supported operation and select function to perform it.
+  if (Trailer.empty())
+    return false;
+  SMLoc OpLoc = SMLoc::getFromPointer(Trailer.data());
+  char Operator = next(Trailer);
+  switch (Operator) {
+  case '+':
+  case '-':
+    break;
+  default:
+    SM.PrintMessage(OpLoc, SourceMgr::DK_Error,
+                    StringRef("unsupported numeric operation '") +
+                        Twine(Operator) + "'");
+    return true;
+  }
+
+  // Parse right operand.
+  if (Trailer.empty()) {
+    SM.PrintMessage(SMLoc::getFromPointer(Trailer.data()), SourceMgr::DK_Error,
+                    "missing operand in numeric expression '" + Trailer + "'");
+    return true;
+  }
+  uint64_t Offset;
+  if (Trailer.consumeInteger(10, Offset)) {
+    SM.PrintMessage(SMLoc::getFromPointer(Trailer.data()), SourceMgr::DK_Error,
+                    "invalid offset in numeric expression '" + Trailer + "'");
+    return true;
+  }
+  if (!Trailer.empty()) {
+    SM.PrintMessage(SMLoc::getFromPointer(Trailer.data()), SourceMgr::DK_Error,
+                    "unexpected characters at end of numeric expression '" +
+                        Trailer + "'");
+    return true;
+  }
+  return false;
+}
+
 /// Parses the given string into the Pattern.
 ///
 /// \p Prefix provides which prefix is being matched, \p SM provides the
@@ -164,6 +216,14 @@
       MatchStr = MatchStr.substr(0, End);
       PatternStr = PatternStr.substr(End + 4);
 
+      size_t VarEndIdx = MatchStr.find(":");
+      size_t SpacePos = MatchStr.substr(0, VarEndIdx).find_first_of(" \t");
+      if (SpacePos != StringRef::npos) {
+        SM.PrintMessage(SMLoc::getFromPointer(MatchStr.data() + SpacePos),
+                        SourceMgr::DK_Error, "unexpected whitespace");
+        return true;
+      }
+
       // Get the regex name (e.g. "foo") and verify it is well formed.
       bool IsPseudo;
       unsigned TrailIdx;
@@ -175,7 +235,7 @@
 
       StringRef Name = MatchStr.substr(0, TrailIdx);
       StringRef Trailer = MatchStr.substr(TrailIdx);
-      bool IsVarDef = (Trailer.find(":") != StringRef::npos);
+      bool IsVarDef = (VarEndIdx != StringRef::npos);
 
       if (IsVarDef && (IsPseudo || !Trailer.consume_front(":"))) {
         SM.PrintMessage(SMLoc::getFromPointer(MatchStr.data()),
@@ -184,17 +244,9 @@
         return true;
       }
 
-      // Verify that the name/expression is well formed. FileCheck currently
-      // supports @LINE, @LINE+number, @LINE-number expressions. The check here
-      // is relaxed. A stricter check is performed in \c EvaluateExpression.
-      if (IsPseudo) {
-        for (unsigned I = 0, E = Trailer.size(); I != E; ++I) {
-          if (!isalnum(Trailer[I]) && Trailer[I] != '+' && Trailer[I] != '-') {
-            SM.PrintMessage(SMLoc::getFromPointer(Name.data() + I),
-                            SourceMgr::DK_Error, "invalid name in named regex");
-            return true;
-          }
-        }
+      if (!IsVarDef && IsPseudo) {
+        if (parseExpression(Name, Trailer, SM))
+          return true;
       }
 
       // Handle [[foo]].
@@ -265,24 +317,16 @@
 }
 
 /// Evaluates expression and stores the result to \p Value.
-///
-/// Returns true on success and false when the expression has invalid syntax.
-bool FileCheckPattern::EvaluateExpression(StringRef Expr, std::string &Value) const {
-  // The only supported expression is @LINE([\+-]\d+)?
-  if (!Expr.startswith("@LINE"))
-    return false;
+void FileCheckPattern::evaluateExpression(StringRef Expr,
+                                          std::string &Value) const {
   Expr = Expr.substr(StringRef("@LINE").size());
   int Offset = 0;
   if (!Expr.empty()) {
     if (Expr[0] == '+')
       Expr = Expr.substr(1);
-    else if (Expr[0] != '-')
-      return false;
-    if (Expr.getAsInteger(10, Offset))
-      return false;
+    Expr.getAsInteger(10, Offset);
   }
   Value = llvm::itostr(LineNumber + Offset);
-  return true;
 }
 
 /// Matches the pattern string against the input buffer \p Buffer
@@ -321,8 +365,7 @@
       std::string Value;
 
       if (VariableUse.first[0] == '@') {
-        if (!EvaluateExpression(VariableUse.first, Value))
-          return StringRef::npos;
+        evaluateExpression(VariableUse.first, Value);
       } else {
         llvm::Optional<StringRef> ValueRef =
             Context->getVarValue(VariableUse.first);
@@ -398,14 +441,10 @@
       StringRef Var = VariableUse.first;
       if (Var[0] == '@') {
         std::string Value;
-        if (EvaluateExpression(Var, Value)) {
-          OS << "with expression \"";
-          OS.write_escaped(Var) << "\" equal to \"";
-          OS.write_escaped(Value) << "\"";
-        } else {
-          OS << "uses incorrect expression \"";
-          OS.write_escaped(Var) << "\"";
-        }
+        evaluateExpression(Var, Value);
+        OS << "with expression \"";
+        OS.write_escaped(Var) << "\" equal to \"";
+        OS.write_escaped(Value) << "\"";
       } else {
         llvm::Optional<StringRef> VarValue = Context->getVarValue(Var);
 
diff --git a/llvm/test/FileCheck/defines.txt b/llvm/test/FileCheck/defines.txt
--- a/llvm/test/FileCheck/defines.txt
+++ b/llvm/test/FileCheck/defines.txt
@@ -8,9 +8,9 @@
 ; RUN: not FileCheck -D= -input-file %s %s 2>&1 | FileCheck %s -check-prefix ERRCLIVAR2
 ; RUN: FileCheck -DVALUE= -check-prefix EMPTY -input-file %s %s 2>&1
 
-; RUN: not FileCheck -D10VALUE=10 -input-file %s %s 2>&1 | FileCheck %s -check-prefix ERRCLIFMT
-; RUN: not FileCheck -D@VALUE=10 -input-file %s %s 2>&1 | FileCheck %s -check-prefix ERRCLIPSEUDO
-; RUN: not FileCheck -D'VALUE + 2=10' -input-file %s %s 2>&1 | FileCheck %s -check-prefix ERRCLITRAIL
+; RUN: not FileCheck -D10VALUE=10 -input-file %s %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix ERRCLIFMT
+; RUN: not FileCheck -D@VALUE=10 -input-file %s %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix ERRCLIPSEUDO
+; RUN: not FileCheck -D'VALUE + 2=10' -input-file %s %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix ERRCLITRAIL
 Value = 10
 ; CHECK: Value = [[VALUE]]
 ; NOT-NOT: Value = [[VALUE]]
diff --git a/llvm/test/FileCheck/line-count.txt b/llvm/test/FileCheck/line-count.txt
--- a/llvm/test/FileCheck/line-count.txt
+++ b/llvm/test/FileCheck/line-count.txt
@@ -1,15 +1,56 @@
 ; RUN: FileCheck  -input-file %s %s
-; RUN: not FileCheck -check-prefix BAD -input-file %s %s
-3
-4 aaa
-5 bbb
-6 ccc
-7 CHECK: [[@LINE-3]] {{a}}aa
-8 CHECK: [[@LINE-3]] {{b}}bb
-9 CHECK: [[@LINE-3]] {{c}}cc
-10 foobar
-11 CHECK: [[@LINE-1]] {{foo}}bar
-12
-13 arst CHECK: [[@LINE]] {{a}}rst
-14
-15 BAD: [[@LINE:cant-have-regex]]
+; RUN: not FileCheck -check-prefix BAD1 -input-file %s %s 2>&1 | FileCheck -check-prefix ERR1 %s
+; RUN: not FileCheck -check-prefix BAD2 -input-file %s %s 2>&1 | FileCheck -check-prefix ERR2 %s
+; RUN: not FileCheck -check-prefix BAD3 -input-file %s %s 2>&1 | FileCheck -check-prefix ERR3 %s
+; RUN: not FileCheck -check-prefix BAD4 -input-file %s %s 2>&1 | FileCheck -check-prefix ERR4 %s
+; RUN: not FileCheck -check-prefix BAD5 -input-file %s %s 2>&1 | FileCheck -check-prefix ERR5 %s
+; RUN: not FileCheck -check-prefix BAD6 -input-file %s %s 2>&1 | FileCheck -check-prefix ERR6 %s
+; RUN: not FileCheck -check-prefix BAD7 -input-file %s %s 2>&1 | FileCheck -check-prefix ERR7 %s
+; RUN: not FileCheck -check-prefix BAD8 -input-file %s %s 2>&1 | FileCheck -check-prefix ERR8 %s
+; RUN: not FileCheck -check-prefix BAD9 -input-file %s %s 2>&1 | FileCheck -check-prefix ERR9 %s
+; RUN: not FileCheck -check-prefix BAD10 -input-file %s %s 2>&1 | FileCheck -check-prefix ERR10 %s
+; RUN: not FileCheck -check-prefix BAD10 -input-file %s %s 2>&1 | FileCheck -check-prefix ERR10 %s
+13
+14 aaa
+15 bbb
+16 ccc
+17 CHECK: [[@LINE-3]] {{a}}aa
+18 CHECK: [[@LINE-3]] {{b}}bb
+19 CHECK: [[@LINE-3]] {{c}}cc
+20 foobar
+21 CHECK: [[@LINE-1]] {{foo}}bar
+22
+23 arst CHECK: [[@LINE]] {{a}}rst
+24
+25 BAD1: [[@LINE:cant-have-regex]]
+26 ERR1: line-count.txt:[[@LINE-1]]:12: error: invalid name in named regex definition
+27
+28 BAD2: [[ @LINE]]
+29 ERR2: line-count.txt:[[@LINE-1]]:12: error: unexpected whitespace
+30
+31 BAD3: [[@LINE ]]
+32 ERR3: line-count.txt:[[@LINE-1]]:17: error: unexpected whitespace
+33
+34 BAD4: [[ @LINE-1]]
+35 ERR4: line-count.txt:[[@LINE-1]]:12: error: unexpected whitespace
+36
+37 BAD5: [[@LINE -1]]
+38 ERR5: line-count.txt:[[@LINE-1]]:17: error: unexpected whitespace
+39
+40 BAD6: [[@LINE- 1]]
+41 ERR6: line-count.txt:[[@LINE-1]]:18: error: unexpected whitespace
+42
+43 BAD7: [[@LINE-1 ]]
+44 ERR7: line-count.txt:[[@LINE-1]]:19: error: unexpected whitespace
+45
+46 BAD8: [[@LIN]]
+47 ERR8: line-count.txt:[[@LINE-1]]:12: error: invalid  pseudo variable '@LIN'
+48
+49 BAD9: [[@LINE*2]]
+50 ERR9: line-count.txt:[[@LINE-1]]:17: error: unsupported numeric operation '*'
+51
+52 BAD10: [[@LINE-x]]
+53 ERR10: line-count.txt:[[@LINE-1]]:19: error: invalid offset in numeric expression 'x'
+54
+55 BAD11: [[@LINE-1x]]
+56 ERR11: line-count.txt:[[@LINE-1]]:19: error: unexpected characters at end of numeric expression 'x'
diff --git a/llvm/unittests/Support/FileCheckTest.cpp b/llvm/unittests/Support/FileCheckTest.cpp
--- a/llvm/unittests/Support/FileCheckTest.cpp
+++ b/llvm/unittests/Support/FileCheckTest.cpp
@@ -126,4 +126,60 @@
   EXPECT_FALSE(IsPseudo);
   EXPECT_EQ(TrailIdx, VarName.size() - 1);
 }
+
+class ExprTester {
+private:
+  SourceMgr SM;
+  FileCheckPatternContext Context;
+  FileCheckPattern P = FileCheckPattern(Check::CheckPlain, &Context);
+
+public:
+  bool parse_expect(std::string &VarName, std::string &Trailer) {
+    StringRef NameTrailer = StringRef(VarName + Trailer);
+    std::unique_ptr<MemoryBuffer> Buffer =
+        MemoryBuffer::getMemBufferCopy(NameTrailer, "TestBuffer");
+    StringRef NameTrailerRef = Buffer->getBuffer();
+    SM.AddNewSourceBuffer(std::move(Buffer), SMLoc());
+    StringRef VarNameRef = NameTrailerRef.substr(0, VarName.size());
+    StringRef TrailerRef = NameTrailerRef.substr(VarName.size());
+    return P.parseExpression(VarNameRef, TrailerRef, SM);
+  }
+};
+
+TEST_F(FileCheckTest, ParseExpr) {
+  ExprTester Tester;
+
+  // @LINE with offset.
+  std::string VarName = "@LINE";
+  std::string Trailer = "+3";
+  EXPECT_FALSE(Tester.parse_expect(VarName, Trailer));
+
+  // @LINE only.
+  Trailer = "";
+  EXPECT_FALSE(Tester.parse_expect(VarName, Trailer));
+
+  // Wrong Pseudovar.
+  VarName = "@FOO";
+  EXPECT_TRUE(Tester.parse_expect(VarName, Trailer));
+
+  // Unsupported operator.
+  VarName = "@LINE";
+  Trailer = "/2";
+  EXPECT_TRUE(Tester.parse_expect(VarName, Trailer));
+
+  // Missing offset operand.
+  VarName = "@LINE";
+  Trailer = "+";
+  EXPECT_TRUE(Tester.parse_expect(VarName, Trailer));
+
+  // Cannot parse offset operand.
+  VarName = "@LINE";
+  Trailer = "+x";
+  EXPECT_TRUE(Tester.parse_expect(VarName, Trailer));
+
+  // Unexpected string at end of numeric expression.
+  VarName = "@LINE";
+  Trailer = "+5x";
+  EXPECT_TRUE(Tester.parse_expect(VarName, Trailer));
+}
 } // namespace