r345472 - [AST] Don't store data for GNU range case statement if not needed

Bruno Ricci via cfe-commits cfe-commits at lists.llvm.org
Sun Oct 28 05:30:53 PDT 2018


Author: brunoricci
Date: Sun Oct 28 05:30:53 2018
New Revision: 345472

URL: http://llvm.org/viewvc/llvm-project?rev=345472&view=rev
Log:
[AST] Don't store data for GNU range case statement if not needed

Don't store the data for case statements of the form LHS ... RHS if not
needed. This cuts the size of CaseStmt by 1 pointer + 1 SourceLocation in
the common case.

Also use the newly available space in the bit-fields of Stmt to store the
keyword location of SwitchCase and move the small accessor
SwitchCase::getSubStmt to the header.

Differential Revision: https://reviews.llvm.org/D53609

Reviewed By: rjmccall


Modified:
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/lib/AST/ASTDumper.cpp
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/Stmt.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/test/Import/switch-stmt/test.cpp
    cfe/trunk/test/Misc/ast-dump-color.cpp

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=345472&r1=345471&r2=345472&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Sun Oct 28 05:30:53 2018
@@ -245,6 +245,20 @@ protected:
     SourceLocation RetLoc;
   };
 
+  class SwitchCaseBitfields {
+    friend class SwitchCase;
+    friend class CaseStmt;
+
+    unsigned : NumStmtBits;
+
+    /// Used by CaseStmt to store whether it is a case statement
+    /// of the form case LHS ... RHS (a GNU extension).
+    unsigned CaseStmtIsGNURange : 1;
+
+    /// The location of the "case" or "default" keyword.
+    SourceLocation KeywordLoc;
+  };
+
   //===--- Expression bitfields classes ---===//
 
   class ExprBitfields {
@@ -461,6 +475,7 @@ protected:
     ContinueStmtBitfields ContinueStmtBits;
     BreakStmtBitfields BreakStmtBits;
     ReturnStmtBitfields ReturnStmtBits;
+    SwitchCaseBitfields SwitchCaseBits;
 
     // Expressions
     ExprBitfields ExprBits;
@@ -877,36 +892,40 @@ public:
 // SwitchCase is the base class for CaseStmt and DefaultStmt,
 class SwitchCase : public Stmt {
 protected:
-  // A pointer to the following CaseStmt or DefaultStmt class,
-  // used by SwitchStmt.
-  SwitchCase *NextSwitchCase = nullptr;
-  SourceLocation KeywordLoc;
+  /// The location of the ":".
   SourceLocation ColonLoc;
 
+  // The location of the "case" or "default" keyword. Stored in SwitchCaseBits.
+  // SourceLocation KeywordLoc;
+
+  /// A pointer to the following CaseStmt or DefaultStmt class,
+  /// used by SwitchStmt.
+  SwitchCase *NextSwitchCase = nullptr;
+
   SwitchCase(StmtClass SC, SourceLocation KWLoc, SourceLocation ColonLoc)
-      : Stmt(SC), KeywordLoc(KWLoc), ColonLoc(ColonLoc) {}
+      : Stmt(SC), ColonLoc(ColonLoc) {
+    setKeywordLoc(KWLoc);
+  }
 
   SwitchCase(StmtClass SC, EmptyShell) : Stmt(SC) {}
 
 public:
   const SwitchCase *getNextSwitchCase() const { return NextSwitchCase; }
-
   SwitchCase *getNextSwitchCase() { return NextSwitchCase; }
-
   void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; }
 
-  SourceLocation getKeywordLoc() const { return KeywordLoc; }
-  void setKeywordLoc(SourceLocation L) { KeywordLoc = L; }
+  SourceLocation getKeywordLoc() const { return SwitchCaseBits.KeywordLoc; }
+  void setKeywordLoc(SourceLocation L) { SwitchCaseBits.KeywordLoc = L; }
   SourceLocation getColonLoc() const { return ColonLoc; }
   void setColonLoc(SourceLocation L) { ColonLoc = L; }
 
-  Stmt *getSubStmt();
+  inline Stmt *getSubStmt();
   const Stmt *getSubStmt() const {
-    return const_cast<SwitchCase*>(this)->getSubStmt();
+    return const_cast<SwitchCase *>(this)->getSubStmt();
   }
 
-  SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; }
-  SourceLocation getEndLoc() const LLVM_READONLY;
+  SourceLocation getBeginLoc() const { return getKeywordLoc(); }
+  inline SourceLocation getEndLoc() const LLVM_READONLY;
 
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == CaseStmtClass ||
@@ -914,52 +933,137 @@ public:
   }
 };
 
-class CaseStmt : public SwitchCase {
-  SourceLocation EllipsisLoc;
-  enum { LHS, RHS, SUBSTMT, END_EXPR };
-  Stmt* SubExprs[END_EXPR];  // The expression for the RHS is Non-null for
-                             // GNU "case 1 ... 4" extension
+/// CaseStmt - Represent a case statement. It can optionally be a GNU case
+/// statement of the form LHS ... RHS representing a range of cases.
+class CaseStmt final
+    : public SwitchCase,
+      private llvm::TrailingObjects<CaseStmt, Stmt *, SourceLocation> {
+  friend TrailingObjects;
 
-public:
+  // CaseStmt is followed by several trailing objects, some of which optional.
+  // Note that it would be more convenient to put the optional trailing objects
+  // at the end but this would impact children().
+  // The trailing objects are in order:
+  //
+  // * A "Stmt *" for the LHS of the case statement. Always present.
+  //
+  // * A "Stmt *" for the RHS of the case statement. This is a GNU extension
+  //   which allow ranges in cases statement of the form LHS ... RHS.
+  //   Present if and only if caseStmtIsGNURange() is true.
+  //
+  // * A "Stmt *" for the substatement of the case statement. Always present.
+  //
+  // * A SourceLocation for the location of the ... if this is a case statement
+  //   with a range. Present if and only if caseStmtIsGNURange() is true.
+  enum { LhsOffset = 0, SubStmtOffsetFromRhs = 1 };
+  enum { NumMandatoryStmtPtr = 2 };
+
+  unsigned numTrailingObjects(OverloadToken<Stmt *>) const {
+    return NumMandatoryStmtPtr + caseStmtIsGNURange();
+  }
+
+  unsigned numTrailingObjects(OverloadToken<SourceLocation>) const {
+    return caseStmtIsGNURange();
+  }
+
+  unsigned lhsOffset() const { return LhsOffset; }
+  unsigned rhsOffset() const { return LhsOffset + caseStmtIsGNURange(); }
+  unsigned subStmtOffset() const { return rhsOffset() + SubStmtOffsetFromRhs; }
+
+  /// Build a case statement assuming that the storage for the
+  /// trailing objects has been properly allocated.
   CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
            SourceLocation ellipsisLoc, SourceLocation colonLoc)
-    : SwitchCase(CaseStmtClass, caseLoc, colonLoc) {
-    SubExprs[SUBSTMT] = nullptr;
-    SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs);
-    SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs);
-    EllipsisLoc = ellipsisLoc;
+      : SwitchCase(CaseStmtClass, caseLoc, colonLoc) {
+    setLHS(lhs);
+    setSubStmt(nullptr);
+    // Handle GNU case statements of the form LHS ... RHS.
+    bool IsGNURange = rhs != nullptr;
+    SwitchCaseBits.CaseStmtIsGNURange = IsGNURange;
+    if (IsGNURange) {
+      setRHS(rhs);
+      setEllipsisLoc(ellipsisLoc);
+    }
   }
 
   /// Build an empty switch case statement.
-  explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass, Empty) {}
+  explicit CaseStmt(EmptyShell Empty, bool CaseStmtIsGNURange)
+      : SwitchCase(CaseStmtClass, Empty) {
+    SwitchCaseBits.CaseStmtIsGNURange = CaseStmtIsGNURange;
+  }
 
-  SourceLocation getCaseLoc() const { return KeywordLoc; }
-  void setCaseLoc(SourceLocation L) { KeywordLoc = L; }
-  SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
-  void setEllipsisLoc(SourceLocation L) { EllipsisLoc = L; }
-  SourceLocation getColonLoc() const { return ColonLoc; }
-  void setColonLoc(SourceLocation L) { ColonLoc = L; }
+public:
+  /// Build a case statement.
+  static CaseStmt *Create(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
+                          SourceLocation caseLoc, SourceLocation ellipsisLoc,
+                          SourceLocation colonLoc);
+
+  /// Build an empty case statement.
+  static CaseStmt *CreateEmpty(const ASTContext &Ctx, bool CaseStmtIsGNURange);
+
+  /// True if this case statement is of the form case LHS ... RHS, which
+  /// is a GNU extension. In this case the RHS can be obtained with getRHS()
+  /// and the location of the ellipsis can be obtained with getEllipsisLoc().
+  bool caseStmtIsGNURange() const { return SwitchCaseBits.CaseStmtIsGNURange; }
+
+  SourceLocation getCaseLoc() const { return getKeywordLoc(); }
+  void setCaseLoc(SourceLocation L) { setKeywordLoc(L); }
+
+  /// Get the location of the ... in a case statement of the form LHS ... RHS.
+  SourceLocation getEllipsisLoc() const {
+    return caseStmtIsGNURange() ? *getTrailingObjects<SourceLocation>()
+                                : SourceLocation();
+  }
+
+  /// Set the location of the ... in a case statement of the form LHS ... RHS.
+  /// Assert that this case statement is of this form.
+  void setEllipsisLoc(SourceLocation L) {
+    assert(
+        caseStmtIsGNURange() &&
+        "setEllipsisLoc but this is not a case stmt of the form LHS ... RHS!");
+    *getTrailingObjects<SourceLocation>() = L;
+  }
 
-  Expr *getLHS() { return reinterpret_cast<Expr*>(SubExprs[LHS]); }
-  Expr *getRHS() { return reinterpret_cast<Expr*>(SubExprs[RHS]); }
-  Stmt *getSubStmt() { return SubExprs[SUBSTMT]; }
+  Expr *getLHS() {
+    return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[lhsOffset()]);
+  }
 
   const Expr *getLHS() const {
-    return reinterpret_cast<const Expr*>(SubExprs[LHS]);
+    return reinterpret_cast<Expr *>(getTrailingObjects<Stmt *>()[lhsOffset()]);
+  }
+
+  void setLHS(Expr *Val) {
+    getTrailingObjects<Stmt *>()[lhsOffset()] = reinterpret_cast<Stmt *>(Val);
+  }
+
+  Expr *getRHS() {
+    return caseStmtIsGNURange() ? reinterpret_cast<Expr *>(
+                                      getTrailingObjects<Stmt *>()[rhsOffset()])
+                                : nullptr;
   }
 
   const Expr *getRHS() const {
-    return reinterpret_cast<const Expr*>(SubExprs[RHS]);
+    return caseStmtIsGNURange() ? reinterpret_cast<Expr *>(
+                                      getTrailingObjects<Stmt *>()[rhsOffset()])
+                                : nullptr;
   }
 
-  const Stmt *getSubStmt() const { return SubExprs[SUBSTMT]; }
+  void setRHS(Expr *Val) {
+    assert(caseStmtIsGNURange() &&
+           "setRHS but this is not a case stmt of the form LHS ... RHS!");
+    getTrailingObjects<Stmt *>()[rhsOffset()] = reinterpret_cast<Stmt *>(Val);
+  }
 
-  void setSubStmt(Stmt *S) { SubExprs[SUBSTMT] = S; }
-  void setLHS(Expr *Val) { SubExprs[LHS] = reinterpret_cast<Stmt*>(Val); }
-  void setRHS(Expr *Val) { SubExprs[RHS] = reinterpret_cast<Stmt*>(Val); }
+  Stmt *getSubStmt() { return getTrailingObjects<Stmt *>()[subStmtOffset()]; }
+  const Stmt *getSubStmt() const {
+    return getTrailingObjects<Stmt *>()[subStmtOffset()];
+  }
 
-  SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; }
+  void setSubStmt(Stmt *S) {
+    getTrailingObjects<Stmt *>()[subStmtOffset()] = S;
+  }
 
+  SourceLocation getBeginLoc() const { return getKeywordLoc(); }
   SourceLocation getEndLoc() const LLVM_READONLY {
     // Handle deeply nested case statements with iteration instead of recursion.
     const CaseStmt *CS = this;
@@ -975,16 +1079,18 @@ public:
 
   // Iterators
   child_range children() {
-    return child_range(&SubExprs[0], &SubExprs[END_EXPR]);
+    return child_range(getTrailingObjects<Stmt *>(),
+                       getTrailingObjects<Stmt *>() +
+                           numTrailingObjects(OverloadToken<Stmt *>()));
   }
 };
 
 class DefaultStmt : public SwitchCase {
-  Stmt* SubStmt;
+  Stmt *SubStmt;
 
 public:
-  DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) :
-    SwitchCase(DefaultStmtClass, DL, CL), SubStmt(substmt) {}
+  DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt)
+      : SwitchCase(DefaultStmtClass, DL, CL), SubStmt(substmt) {}
 
   /// Build an empty default statement.
   explicit DefaultStmt(EmptyShell Empty)
@@ -994,12 +1100,10 @@ public:
   const Stmt *getSubStmt() const { return SubStmt; }
   void setSubStmt(Stmt *S) { SubStmt = S; }
 
-  SourceLocation getDefaultLoc() const { return KeywordLoc; }
-  void setDefaultLoc(SourceLocation L) { KeywordLoc = L; }
-  SourceLocation getColonLoc() const { return ColonLoc; }
-  void setColonLoc(SourceLocation L) { ColonLoc = L; }
+  SourceLocation getDefaultLoc() const { return getKeywordLoc(); }
+  void setDefaultLoc(SourceLocation L) { setKeywordLoc(L); }
 
-  SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; }
+  SourceLocation getBeginLoc() const { return getKeywordLoc(); }
   SourceLocation getEndLoc() const LLVM_READONLY {
     return SubStmt->getEndLoc();
   }
@@ -1009,13 +1113,23 @@ public:
   }
 
   // Iterators
-  child_range children() { return child_range(&SubStmt, &SubStmt+1); }
+  child_range children() { return child_range(&SubStmt, &SubStmt + 1); }
 };
 
-inline SourceLocation SwitchCase::getEndLoc() const {
+SourceLocation SwitchCase::getEndLoc() const {
   if (const auto *CS = dyn_cast<CaseStmt>(this))
     return CS->getEndLoc();
-  return cast<DefaultStmt>(this)->getEndLoc();
+  else if (const auto *DS = dyn_cast<DefaultStmt>(this))
+    return DS->getEndLoc();
+  llvm_unreachable("SwitchCase is neither a CaseStmt nor a DefaultStmt!");
+}
+
+Stmt *SwitchCase::getSubStmt() {
+  if (auto *CS = dyn_cast<CaseStmt>(this))
+    return CS->getSubStmt();
+  else if (auto *DS = dyn_cast<DefaultStmt>(this))
+    return DS->getSubStmt();
+  llvm_unreachable("SwitchCase is neither a CaseStmt nor a DefaultStmt!");
 }
 
 /// LabelStmt - Represents a label, which has a substatement.  For example:

Modified: cfe/trunk/lib/AST/ASTDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=345472&r1=345471&r2=345472&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDumper.cpp (original)
+++ cfe/trunk/lib/AST/ASTDumper.cpp Sun Oct 28 05:30:53 2018
@@ -515,6 +515,7 @@ namespace  {
     void VisitLabelStmt(const LabelStmt *Node);
     void VisitGotoStmt(const GotoStmt *Node);
     void VisitCXXCatchStmt(const CXXCatchStmt *Node);
+    void VisitCaseStmt(const CaseStmt *Node);
     void VisitCapturedStmt(const CapturedStmt *Node);
 
     // OpenMP
@@ -2047,6 +2048,12 @@ void ASTDumper::VisitCXXCatchStmt(const
   dumpDecl(Node->getExceptionDecl());
 }
 
+void ASTDumper::VisitCaseStmt(const CaseStmt *Node) {
+  VisitStmt(Node);
+  if (Node->caseStmtIsGNURange())
+    OS << " gnu_range";
+}
+
 void ASTDumper::VisitCapturedStmt(const CapturedStmt *Node) {
   VisitStmt(Node);
   dumpDecl(Node->getCapturedDecl());

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=345472&r1=345471&r2=345472&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Sun Oct 28 05:30:53 2018
@@ -5707,8 +5707,8 @@ ExpectedStmt ASTNodeImporter::VisitCaseS
   std::tie(ToLHS, ToRHS, ToSubStmt, ToCaseLoc, ToEllipsisLoc, ToColonLoc) =
       *Imp;
 
-  auto *ToStmt = new (Importer.getToContext()) CaseStmt(
-      ToLHS, ToRHS, ToCaseLoc, ToEllipsisLoc, ToColonLoc);
+  auto *ToStmt = CaseStmt::Create(Importer.getToContext(), ToLHS, ToRHS,
+                                  ToCaseLoc, ToEllipsisLoc, ToColonLoc);
   ToStmt->setSubStmt(ToSubStmt);
 
   return ToStmt;

Modified: cfe/trunk/lib/AST/Stmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=345472&r1=345471&r2=345472&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Stmt.cpp (original)
+++ cfe/trunk/lib/AST/Stmt.cpp Sun Oct 28 05:30:53 2018
@@ -942,12 +942,6 @@ void SwitchStmt::setConditionVariable(co
                                    VarRange.getEnd());
 }
 
-Stmt *SwitchCase::getSubStmt() {
-  if (isa<CaseStmt>(this))
-    return cast<CaseStmt>(this)->getSubStmt();
-  return cast<DefaultStmt>(this)->getSubStmt();
-}
-
 WhileStmt::WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
                      SourceLocation WL)
   : Stmt(WhileStmtClass) {
@@ -991,6 +985,27 @@ Expr* ReturnStmt::getRetValue() {
   return cast_or_null<Expr>(RetExpr);
 }
 
+// CaseStmt
+CaseStmt *CaseStmt::Create(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
+                           SourceLocation caseLoc, SourceLocation ellipsisLoc,
+                           SourceLocation colonLoc) {
+  bool CaseStmtIsGNURange = rhs != nullptr;
+  void *Mem = Ctx.Allocate(
+      totalSizeToAlloc<Stmt *, SourceLocation>(
+          NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange),
+      alignof(CaseStmt));
+  return new (Mem) CaseStmt(lhs, rhs, caseLoc, ellipsisLoc, colonLoc);
+}
+
+CaseStmt *CaseStmt::CreateEmpty(const ASTContext &Ctx,
+                                bool CaseStmtIsGNURange) {
+  void *Mem = Ctx.Allocate(
+      totalSizeToAlloc<Stmt *, SourceLocation>(
+          NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange),
+      alignof(CaseStmt));
+  return new (Mem) CaseStmt(EmptyShell(), CaseStmtIsGNURange);
+}
+
 SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock,
                        Stmt *Handler)
     : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc) {

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=345472&r1=345471&r2=345472&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Sun Oct 28 05:30:53 2018
@@ -462,8 +462,8 @@ Sema::ActOnCaseStmt(SourceLocation CaseL
     return StmtError();
   }
 
-  CaseStmt *CS = new (Context)
-      CaseStmt(LHSVal.get(), RHSVal.get(), CaseLoc, DotDotDotLoc, ColonLoc);
+  auto *CS = CaseStmt::Create(Context, LHSVal.get(), RHSVal.get(),
+                              CaseLoc, DotDotDotLoc, ColonLoc);
   getCurFunction()->SwitchStack.back().getPointer()->addSwitchCase(CS);
   return CS;
 }
@@ -472,7 +472,7 @@ Sema::ActOnCaseStmt(SourceLocation CaseL
 void Sema::ActOnCaseStmtBody(Stmt *caseStmt, Stmt *SubStmt) {
   DiagnoseUnusedExprResult(SubStmt);
 
-  CaseStmt *CS = static_cast<CaseStmt*>(caseStmt);
+  auto *CS = static_cast<CaseStmt *>(caseStmt);
   CS->setSubStmt(SubStmt);
 }
 

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=345472&r1=345471&r2=345472&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Sun Oct 28 05:30:53 2018
@@ -177,10 +177,13 @@ void ASTStmtReader::VisitSwitchCase(Swit
 
 void ASTStmtReader::VisitCaseStmt(CaseStmt *S) {
   VisitSwitchCase(S);
+  bool CaseStmtIsGNURange = Record.readInt();
   S->setLHS(Record.readSubExpr());
-  S->setRHS(Record.readSubExpr());
   S->setSubStmt(Record.readSubStmt());
-  S->setEllipsisLoc(ReadSourceLocation());
+  if (CaseStmtIsGNURange) {
+    S->setRHS(Record.readSubExpr());
+    S->setEllipsisLoc(ReadSourceLocation());
+  }
 }
 
 void ASTStmtReader::VisitDefaultStmt(DefaultStmt *S) {
@@ -2277,7 +2280,9 @@ Stmt *ASTReader::ReadStmtFromStream(Modu
       break;
 
     case STMT_CASE:
-      S = new (Context) CaseStmt(Empty);
+      S = CaseStmt::CreateEmpty(
+          Context,
+          /*CaseStmtIsGNURange*/ Record[ASTStmtReader::NumStmtFields + 3]);
       break;
 
     case STMT_DEFAULT:

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=345472&r1=345471&r2=345472&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Sun Oct 28 05:30:53 2018
@@ -96,10 +96,13 @@ void ASTStmtWriter::VisitSwitchCase(Swit
 
 void ASTStmtWriter::VisitCaseStmt(CaseStmt *S) {
   VisitSwitchCase(S);
+  Record.push_back(S->caseStmtIsGNURange());
   Record.AddStmt(S->getLHS());
-  Record.AddStmt(S->getRHS());
   Record.AddStmt(S->getSubStmt());
-  Record.AddSourceLocation(S->getEllipsisLoc());
+  if (S->caseStmtIsGNURange()) {
+    Record.AddStmt(S->getRHS());
+    Record.AddSourceLocation(S->getEllipsisLoc());
+  }
   Code = serialization::STMT_CASE;
 }
 

Modified: cfe/trunk/test/Import/switch-stmt/test.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Import/switch-stmt/test.cpp?rev=345472&r1=345471&r2=345472&view=diff
==============================================================================
--- cfe/trunk/test/Import/switch-stmt/test.cpp (original)
+++ cfe/trunk/test/Import/switch-stmt/test.cpp Sun Oct 28 05:30:53 2018
@@ -7,10 +7,8 @@
 // CHECK-NEXT: CompoundStmt
 // CHECK-NEXT: CaseStmt
 // CHECK-NEXT: IntegerLiteral
-// CHECK-NEXT: <<NULL>>
 // CHECK-NEXT: CaseStmt
 // CHECK-NEXT: IntegerLiteral
-// CHECK-NEXT: <<NULL>>
 // CHECK-NEXT: BreakStmt
 
 // CHECK: SwitchStmt
@@ -22,11 +20,9 @@
 // CHECK-NEXT: CompoundStmt
 // CHECK-NEXT: CaseStmt
 // CHECK-NEXT: IntegerLiteral
-// CHECK-NEXT: <<NULL>>
 // CHECK-NEXT: BreakStmt
 // CHECK-NEXT: CaseStmt
 // CHECK-NEXT: IntegerLiteral
-// CHECK-NEXT: <<NULL>>
 // CHECK-NEXT: BreakStmt
 
 // CHECK: SwitchStmt

Modified: cfe/trunk/test/Misc/ast-dump-color.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/ast-dump-color.cpp?rev=345472&r1=345471&r2=345472&view=diff
==============================================================================
--- cfe/trunk/test/Misc/ast-dump-color.cpp (original)
+++ cfe/trunk/test/Misc/ast-dump-color.cpp Sun Oct 28 05:30:53 2018
@@ -51,13 +51,11 @@ struct Invalid {
 //CHECK: {{^}}[[Blue]]| |   `-[[RESET]][[MAGENTA]]CompoundStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:14[[RESET]], [[Yellow]]line:15:3[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| |     |-[[RESET]][[MAGENTA]]CaseStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:11:3[[RESET]], [[Yellow]]line:12:27[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| |     | |-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:11:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 1[[RESET]]{{$}}
-//CHECK: {{^}}[[Blue]]| |     | |-[[RESET]][[Blue]]<<<NULL>>>[[RESET]]{{$}}
 //CHECK: {{^}}[[Blue]]| |     | `-[[RESET]][[MAGENTA]]AttributedStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:12:5[[RESET]], [[Yellow]]col:27[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| |     |   |-[[RESET]][[BLUE]]FallThroughAttr[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:7[[RESET]], [[Yellow]]col:14[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| |     |   `-[[RESET]][[MAGENTA]]NullStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:27[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| |     `-[[RESET]][[MAGENTA]]CaseStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:13:3[[RESET]], [[Yellow]]line:14:5[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| |       |-[[RESET]][[MAGENTA]]IntegerLiteral[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:13:8[[RESET]]> [[Green]]'int'[[RESET]][[Cyan]][[RESET]][[Cyan]][[RESET]][[CYAN]] 2[[RESET]]{{$}}
-//CHECK: {{^}}[[Blue]]| |       |-[[RESET]][[Blue]]<<<NULL>>>[[RESET]]{{$}}
 //CHECK: {{^}}[[Blue]]| |       `-[[RESET]][[MAGENTA]]NullStmt[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:14:5[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]| `-[[RESET]][[Blue]]FullComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]line:8:4[[RESET]], [[Yellow]]col:11[[RESET]]>{{$}}
 //CHECK: {{^}}[[Blue]]|   `-[[RESET]][[Blue]]ParagraphComment[[RESET]][[Yellow]] 0x{{[0-9a-fA-F]*}}[[RESET]] <[[Yellow]]col:4[[RESET]], [[Yellow]]col:11[[RESET]]>{{$}}




More information about the cfe-commits mailing list