[cfe-commits] r71916 - in /cfe/trunk: include/clang/AST/Stmt.h lib/Frontend/PCHReaderStmt.cpp lib/Frontend/PCHWriterStmt.cpp lib/Sema/SemaStmt.cpp lib/Sema/SemaTemplateInstantiateStmt.cpp test/SemaTemplate/instantiate-function-1.cpp

Douglas Gregor dgregor at apple.com
Fri May 15 16:57:33 PDT 2009


Author: dgregor
Date: Fri May 15 18:57:33 2009
New Revision: 71916

URL: http://llvm.org/viewvc/llvm-project?rev=71916&view=rev
Log:
Template instantiation for switch statements

Modified:
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/lib/Frontend/PCHReaderStmt.cpp
    cfe/trunk/lib/Frontend/PCHWriterStmt.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateStmt.cpp
    cfe/trunk/test/SemaTemplate/instantiate-function-1.cpp

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=71916&r1=71915&r2=71916&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Fri May 15 18:57:33 2009
@@ -417,14 +417,20 @@
   Stmt* SubExprs[END_EXPR];  // The expression for the RHS is Non-null for 
                              // GNU "case 1 ... 4" extension
   SourceLocation CaseLoc;
+  SourceLocation EllipsisLoc;
+  SourceLocation ColonLoc;
+
   virtual Stmt* v_getSubStmt() { return getSubStmt(); }
 public:
-  CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc) 
+  CaseStmt(Expr *lhs, Expr *rhs, SourceLocation caseLoc,
+           SourceLocation ellipsisLoc, SourceLocation colonLoc) 
     : SwitchCase(CaseStmtClass) {
     SubExprs[SUBSTMT] = 0;
     SubExprs[LHS] = reinterpret_cast<Stmt*>(lhs);
     SubExprs[RHS] = reinterpret_cast<Stmt*>(rhs);
     CaseLoc = caseLoc;
+    EllipsisLoc = ellipsisLoc;
+    ColonLoc = colonLoc;
   }
 
   /// \brief Build an empty switch case statement.
@@ -432,6 +438,10 @@
 
   SourceLocation getCaseLoc() const { return CaseLoc; }
   void setCaseLoc(SourceLocation L) { CaseLoc = L; }
+  SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+  void setEllipsisLoc(SourceLocation L) { EllipsisLoc = L; }
+  SourceLocation getColonLoc() const { return ColonLoc; }
+  void setColonLoc(SourceLocation L) { ColonLoc = L; }
 
   Expr *getLHS() { return reinterpret_cast<Expr*>(SubExprs[LHS]); }
   Expr *getRHS() { return reinterpret_cast<Expr*>(SubExprs[RHS]); }
@@ -471,10 +481,12 @@
 class DefaultStmt : public SwitchCase {
   Stmt* SubStmt;
   SourceLocation DefaultLoc;
+  SourceLocation ColonLoc;
   virtual Stmt* v_getSubStmt() { return getSubStmt(); }
 public:
-  DefaultStmt(SourceLocation DL, Stmt *substmt) : 
-    SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL) {}
+  DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) : 
+    SwitchCase(DefaultStmtClass), SubStmt(substmt), DefaultLoc(DL),
+    ColonLoc(CL) {}
 
   /// \brief Build an empty default statement.
   explicit DefaultStmt(EmptyShell) : SwitchCase(DefaultStmtClass) { }
@@ -485,6 +497,8 @@
 
   SourceLocation getDefaultLoc() const { return DefaultLoc; }
   void setDefaultLoc(SourceLocation L) { DefaultLoc = L; }
+  SourceLocation getColonLoc() const { return ColonLoc; }
+  void setColonLoc(SourceLocation L) { ColonLoc = L; }
 
   virtual SourceRange getSourceRange() const { 
     return SourceRange(DefaultLoc, SubStmt->getLocEnd()); 

Modified: cfe/trunk/lib/Frontend/PCHReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderStmt.cpp?rev=71916&r1=71915&r2=71916&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderStmt.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderStmt.cpp Fri May 15 18:57:33 2009
@@ -147,6 +147,8 @@
   S->setRHS(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2]));
   S->setSubStmt(StmtStack.back());
   S->setCaseLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setEllipsisLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
   return 3;
 }
 
@@ -154,6 +156,7 @@
   VisitSwitchCase(S);
   S->setSubStmt(StmtStack.back());
   S->setDefaultLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  S->setColonLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
   return 1;
 }
 

Modified: cfe/trunk/lib/Frontend/PCHWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterStmt.cpp?rev=71916&r1=71915&r2=71916&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterStmt.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterStmt.cpp Fri May 15 18:57:33 2009
@@ -140,6 +140,8 @@
   Writer.WriteSubStmt(S->getRHS());
   Writer.WriteSubStmt(S->getSubStmt());
   Writer.AddSourceLocation(S->getCaseLoc(), Record);
+  Writer.AddSourceLocation(S->getEllipsisLoc(), Record);
+  Writer.AddSourceLocation(S->getColonLoc(), Record);
   Code = pch::STMT_CASE;
 }
 
@@ -147,6 +149,7 @@
   VisitSwitchCase(S);
   Writer.WriteSubStmt(S->getSubStmt());
   Writer.AddSourceLocation(S->getDefaultLoc(), Record);
+  Writer.AddSourceLocation(S->getColonLoc(), Record);
   Code = pch::STMT_DEFAULT;
 }
 

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=71916&r1=71915&r2=71916&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Fri May 15 18:57:33 2009
@@ -102,13 +102,15 @@
   // C99 6.8.4.2p3: The expression shall be an integer constant.
   // However, GCC allows any evaluatable integer expression. 
   Expr *LHSVal = static_cast<Expr*>(lhsval.get());
-  if (VerifyIntegerConstantExpression(LHSVal))
+  if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent() && 
+      VerifyIntegerConstantExpression(LHSVal))
     return StmtError();
 
   // GCC extension: The expression shall be an integer constant.
 
   Expr *RHSVal = static_cast<Expr*>(rhsval.get());
-  if (RHSVal && VerifyIntegerConstantExpression(RHSVal)) {
+  if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent() &&
+      VerifyIntegerConstantExpression(RHSVal)) {
     RHSVal = 0;  // Recover by just forgetting about it.
     rhsval = 0;
   }
@@ -121,7 +123,8 @@
   // Only now release the smart pointers.
   lhsval.release();
   rhsval.release();
-  CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc);
+  CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc,
+                                        ColonLoc);
   getSwitchStack().back()->addSwitchCase(CS);
   return Owned(CS);
 }
@@ -143,7 +146,7 @@
     return Owned(SubStmt);
   }
 
-  DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, SubStmt);
+  DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt);
   getSwitchStack().back()->addSwitchCase(DS);
   return Owned(DS);
 }
@@ -227,17 +230,18 @@
     // converted by calling that conversion function, and the result of the
     // conversion is used in place of the original condition for the remainder
     // of this section. Integral promotions are performed.
-
-    QualType Ty = Cond->getType();
-
-    // FIXME: Handle class types.
-
-    // If the type is wrong a diagnostic will be emitted later at
-    // ActOnFinishSwitchStmt.
-    if (Ty->isIntegralType() || Ty->isEnumeralType()) {
-      // Integral promotions are performed.
-      // FIXME: Integral promotions for C++ are not complete.
-      UsualUnaryConversions(Cond);
+    if (!Cond->isTypeDependent()) {
+      QualType Ty = Cond->getType();
+      
+      // FIXME: Handle class types.
+      
+      // If the type is wrong a diagnostic will be emitted later at
+      // ActOnFinishSwitchStmt.
+      if (Ty->isIntegralType() || Ty->isEnumeralType()) {
+        // Integral promotions are performed.
+        // FIXME: Integral promotions for C++ are not complete.
+        UsualUnaryConversions(Cond);
+      }
     }
   } else {
     // C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr.
@@ -338,7 +342,8 @@
   Expr *CondExpr = SS->getCond();
   QualType CondType = CondExpr->getType();
 
-  if (!CondType->isIntegerType()) { // C99 6.8.4.2p1
+  if (!CondExpr->isTypeDependent() && 
+      !CondType->isIntegerType()) { // C99 6.8.4.2p1
     Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer)
       << CondType << CondExpr->getSourceRange();
     return StmtError();
@@ -346,7 +351,11 @@
 
   // Get the bitwidth of the switched-on value before promotions.  We must
   // convert the integer case values to this width before comparison.
-  unsigned CondWidth = static_cast<unsigned>(Context.getTypeSize(CondType));
+  bool HasDependentValue 
+    = CondExpr->isTypeDependent() || CondExpr->isValueDependent();
+  unsigned CondWidth 
+    = HasDependentValue? 0
+                       : static_cast<unsigned>(Context.getTypeSize(CondType));
   bool CondIsSigned = CondType->isSignedIntegerType();
   
   // Accumulate all of the case values in a vector so that we can sort them
@@ -362,7 +371,7 @@
   
   bool CaseListIsErroneous = false;
   
-  for (SwitchCase *SC = SS->getSwitchCaseList(); SC;
+  for (SwitchCase *SC = SS->getSwitchCaseList(); SC && !HasDependentValue;
        SC = SC->getNextSwitchCase()) {
     
     if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SC)) {
@@ -384,6 +393,12 @@
       // We already verified that the expression has a i-c-e value (C99
       // 6.8.4.2p3) - get that value now.
       Expr *Lo = CS->getLHS();
+
+      if (Lo->isTypeDependent() || Lo->isValueDependent()) {
+        HasDependentValue = true;
+        break;
+      }
+        
       llvm::APSInt LoVal = Lo->EvaluateAsInt(Context);
       
       // Convert the value to the same width/sign as the condition.
@@ -397,117 +412,127 @@
       CS->setLHS(Lo);
       
       // If this is a case range, remember it in CaseRanges, otherwise CaseVals.
-      if (CS->getRHS())
+      if (CS->getRHS()) {
+        if (CS->getRHS()->isTypeDependent() || 
+            CS->getRHS()->isValueDependent()) {
+          HasDependentValue = true;
+          break;
+        }
         CaseRanges.push_back(std::make_pair(LoVal, CS));
-      else 
+      } else 
         CaseVals.push_back(std::make_pair(LoVal, CS));
     }
   }
-  
-  // Sort all the scalar case values so we can easily detect duplicates.
-  std::stable_sort(CaseVals.begin(), CaseVals.end(), CmpCaseVals);
-  
-  if (!CaseVals.empty()) {
-    for (unsigned i = 0, e = CaseVals.size()-1; i != e; ++i) {
-      if (CaseVals[i].first == CaseVals[i+1].first) {
-        // If we have a duplicate, report it.
-        Diag(CaseVals[i+1].second->getLHS()->getLocStart(),
-             diag::err_duplicate_case) << CaseVals[i].first.toString(10);
-        Diag(CaseVals[i].second->getLHS()->getLocStart(), 
-             diag::note_duplicate_case_prev);
-        // FIXME: We really want to remove the bogus case stmt from the substmt,
-        // but we have no way to do this right now.
-        CaseListIsErroneous = true;
-      }
-    }
-  }
-  
-  // Detect duplicate case ranges, which usually don't exist at all in the first
-  // place.
-  if (!CaseRanges.empty()) {
-    // Sort all the case ranges by their low value so we can easily detect
-    // overlaps between ranges.
-    std::stable_sort(CaseRanges.begin(), CaseRanges.end());
-    
-    // Scan the ranges, computing the high values and removing empty ranges.
-    std::vector<llvm::APSInt> HiVals;
-    for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) {
-      CaseStmt *CR = CaseRanges[i].second;
-      Expr *Hi = CR->getRHS();
-      llvm::APSInt HiVal = Hi->EvaluateAsInt(Context);
 
-      // Convert the value to the same width/sign as the condition.
-      ConvertIntegerToTypeWarnOnOverflow(HiVal, CondWidth, CondIsSigned,
-                                         CR->getRHS()->getLocStart(),
-                                         diag::warn_case_value_overflow);
-      
-      // If the LHS is not the same type as the condition, insert an implicit
-      // cast.
-      ImpCastExprToType(Hi, CondType);
-      CR->setRHS(Hi);
-      
-      // If the low value is bigger than the high value, the case is empty.
-      if (CaseRanges[i].first > HiVal) {
-        Diag(CR->getLHS()->getLocStart(), diag::warn_case_empty_range)
-          << SourceRange(CR->getLHS()->getLocStart(),
-                         CR->getRHS()->getLocEnd());
-        CaseRanges.erase(CaseRanges.begin()+i);
-        --i, --e;
-        continue;
+  if (!HasDependentValue) {
+    // Sort all the scalar case values so we can easily detect duplicates.
+    std::stable_sort(CaseVals.begin(), CaseVals.end(), CmpCaseVals);
+
+    if (!CaseVals.empty()) {
+      for (unsigned i = 0, e = CaseVals.size()-1; i != e; ++i) {
+        if (CaseVals[i].first == CaseVals[i+1].first) {
+          // If we have a duplicate, report it.
+          Diag(CaseVals[i+1].second->getLHS()->getLocStart(),
+               diag::err_duplicate_case) << CaseVals[i].first.toString(10);
+          Diag(CaseVals[i].second->getLHS()->getLocStart(), 
+               diag::note_duplicate_case_prev);
+          // FIXME: We really want to remove the bogus case stmt from
+          // the substmt, but we have no way to do this right now.
+          CaseListIsErroneous = true;
+        }
       }
-      HiVals.push_back(HiVal);
     }
-
-    // Rescan the ranges, looking for overlap with singleton values and other
-    // ranges.  Since the range list is sorted, we only need to compare case
-    // ranges with their neighbors.
-    for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) {
-      llvm::APSInt &CRLo = CaseRanges[i].first;
-      llvm::APSInt &CRHi = HiVals[i];
-      CaseStmt *CR = CaseRanges[i].second;
-      
-      // Check to see whether the case range overlaps with any singleton cases.
-      CaseStmt *OverlapStmt = 0;
-      llvm::APSInt OverlapVal(32);
+  
+    // Detect duplicate case ranges, which usually don't exist at all in
+    // the first place.
+    if (!CaseRanges.empty()) {
+      // Sort all the case ranges by their low value so we can easily detect
+      // overlaps between ranges.
+      std::stable_sort(CaseRanges.begin(), CaseRanges.end());
       
-      // Find the smallest value >= the lower bound.  If I is in the case range,
-      // then we have overlap.
-      CaseValsTy::iterator I = std::lower_bound(CaseVals.begin(),
-                                                CaseVals.end(), CRLo,
-                                                CaseCompareFunctor());
-      if (I != CaseVals.end() && I->first < CRHi) {
-        OverlapVal  = I->first;   // Found overlap with scalar.
-        OverlapStmt = I->second;
-      }
-
-      // Find the smallest value bigger than the upper bound.
-      I = std::upper_bound(I, CaseVals.end(), CRHi, CaseCompareFunctor());
-      if (I != CaseVals.begin() && (I-1)->first >= CRLo) {
-        OverlapVal  = (I-1)->first;      // Found overlap with scalar.
-        OverlapStmt = (I-1)->second;
-      }
-
-      // Check to see if this case stmt overlaps with the subsequent case range.
-      if (i && CRLo <= HiVals[i-1]) {
-        OverlapVal  = HiVals[i-1];       // Found overlap with range.
-        OverlapStmt = CaseRanges[i-1].second;
+      // Scan the ranges, computing the high values and removing empty ranges.
+      std::vector<llvm::APSInt> HiVals;
+      for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) {
+        CaseStmt *CR = CaseRanges[i].second;
+        Expr *Hi = CR->getRHS();
+        llvm::APSInt HiVal = Hi->EvaluateAsInt(Context);
+        
+        // Convert the value to the same width/sign as the condition.
+        ConvertIntegerToTypeWarnOnOverflow(HiVal, CondWidth, CondIsSigned,
+                                           CR->getRHS()->getLocStart(),
+                                           diag::warn_case_value_overflow);
+        
+        // If the LHS is not the same type as the condition, insert an implicit
+        // cast.
+        ImpCastExprToType(Hi, CondType);
+        CR->setRHS(Hi);
+        
+        // If the low value is bigger than the high value, the case is empty.
+        if (CaseRanges[i].first > HiVal) {
+          Diag(CR->getLHS()->getLocStart(), diag::warn_case_empty_range)
+            << SourceRange(CR->getLHS()->getLocStart(),
+                           CR->getRHS()->getLocEnd());
+          CaseRanges.erase(CaseRanges.begin()+i);
+          --i, --e;
+          continue;
+        }
+        HiVals.push_back(HiVal);
       }
       
-      if (OverlapStmt) {
-        // If we have a duplicate, report it.
-        Diag(CR->getLHS()->getLocStart(), diag::err_duplicate_case)
-          << OverlapVal.toString(10);
-        Diag(OverlapStmt->getLHS()->getLocStart(), 
-             diag::note_duplicate_case_prev);
-        // FIXME: We really want to remove the bogus case stmt from the substmt,
-        // but we have no way to do this right now.
-        CaseListIsErroneous = true;
+      // Rescan the ranges, looking for overlap with singleton values and other
+      // ranges.  Since the range list is sorted, we only need to compare case
+      // ranges with their neighbors.
+      for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) {
+        llvm::APSInt &CRLo = CaseRanges[i].first;
+        llvm::APSInt &CRHi = HiVals[i];
+        CaseStmt *CR = CaseRanges[i].second;
+        
+        // Check to see whether the case range overlaps with any
+        // singleton cases.
+        CaseStmt *OverlapStmt = 0;
+        llvm::APSInt OverlapVal(32);
+        
+        // Find the smallest value >= the lower bound.  If I is in the
+        // case range, then we have overlap.
+        CaseValsTy::iterator I = std::lower_bound(CaseVals.begin(),
+                                                  CaseVals.end(), CRLo,
+                                                  CaseCompareFunctor());
+        if (I != CaseVals.end() && I->first < CRHi) {
+          OverlapVal  = I->first;   // Found overlap with scalar.
+          OverlapStmt = I->second;
+        }
+        
+        // Find the smallest value bigger than the upper bound.
+        I = std::upper_bound(I, CaseVals.end(), CRHi, CaseCompareFunctor());
+        if (I != CaseVals.begin() && (I-1)->first >= CRLo) {
+          OverlapVal  = (I-1)->first;      // Found overlap with scalar.
+          OverlapStmt = (I-1)->second;
+        }
+        
+        // Check to see if this case stmt overlaps with the subsequent
+        // case range.
+        if (i && CRLo <= HiVals[i-1]) {
+          OverlapVal  = HiVals[i-1];       // Found overlap with range.
+          OverlapStmt = CaseRanges[i-1].second;
+        }
+        
+        if (OverlapStmt) {
+          // If we have a duplicate, report it.
+          Diag(CR->getLHS()->getLocStart(), diag::err_duplicate_case)
+            << OverlapVal.toString(10);
+          Diag(OverlapStmt->getLHS()->getLocStart(), 
+               diag::note_duplicate_case_prev);
+          // FIXME: We really want to remove the bogus case stmt from
+          // the substmt, but we have no way to do this right now.
+          CaseListIsErroneous = true;
+        }
       }
     }
   }
-  
-  // FIXME: If the case list was broken is some way, we don't have a good system
-  // to patch it up.  Instead, just return the whole substmt as broken.
+
+  // FIXME: If the case list was broken is some way, we don't have a
+  // good system to patch it up.  Instead, just return the whole
+  // substmt as broken.
   if (CaseListIsErroneous)
     return StmtError();
 

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateStmt.cpp?rev=71916&r1=71915&r2=71916&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateStmt.cpp Fri May 15 18:57:33 2009
@@ -39,7 +39,10 @@
     OwningStmtResult VisitDeclStmt(DeclStmt *S);
     OwningStmtResult VisitNullStmt(NullStmt *S);
     OwningStmtResult VisitCompoundStmt(CompoundStmt *S);
+    OwningStmtResult VisitCaseStmt(CaseStmt *S);
+    OwningStmtResult VisitDefaultStmt(DefaultStmt *S);
     OwningStmtResult VisitIfStmt(IfStmt *S);
+    OwningStmtResult VisitSwitchStmt(SwitchStmt *S);
     OwningStmtResult VisitWhileStmt(WhileStmt *S);
     OwningStmtResult VisitDoStmt(DoStmt *S);
     OwningStmtResult VisitForStmt(ForStmt *S);
@@ -150,6 +153,50 @@
                                               S->getRBracLoc()));
 }
 
+Sema::OwningStmtResult TemplateStmtInstantiator::VisitCaseStmt(CaseStmt *S) {
+  // Instantiate left-hand case value.
+  OwningExprResult LHS = SemaRef.InstantiateExpr(S->getLHS(), TemplateArgs);
+  if (LHS.isInvalid())
+    return SemaRef.StmtError();
+
+  // Instantiate right-hand case value (for the GNU case-range extension).
+  OwningExprResult RHS = SemaRef.InstantiateExpr(S->getRHS(), TemplateArgs);
+  if (RHS.isInvalid())
+    return SemaRef.StmtError();
+
+  // Build the case statement.
+  OwningStmtResult Case = SemaRef.ActOnCaseStmt(S->getCaseLoc(),
+                                                move(LHS),
+                                                S->getEllipsisLoc(),
+                                                move(RHS),
+                                                S->getColonLoc());
+  if (Case.isInvalid())
+    return SemaRef.StmtError();
+
+  // Instantiate the statement following the case
+  OwningStmtResult SubStmt = SemaRef.InstantiateStmt(S->getSubStmt(), 
+                                                     TemplateArgs);
+  if (SubStmt.isInvalid())
+    return SemaRef.StmtError();
+
+  SemaRef.ActOnCaseStmtBody(Case.get(), move(SubStmt));
+  return move(Case);
+}
+
+Sema::OwningStmtResult 
+TemplateStmtInstantiator::VisitDefaultStmt(DefaultStmt *S) {
+  // Instantiate the statement following the default case
+  OwningStmtResult SubStmt = SemaRef.InstantiateStmt(S->getSubStmt(), 
+                                                     TemplateArgs);
+  if (SubStmt.isInvalid())
+    return SemaRef.StmtError();
+
+  return SemaRef.ActOnDefaultStmt(S->getDefaultLoc(), 
+                                  S->getColonLoc(),
+                                  move(SubStmt), 
+                                  /*CurScope=*/0);
+}
+
 Sema::OwningStmtResult TemplateStmtInstantiator::VisitIfStmt(IfStmt *S) {
   // Instantiate the condition
   OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
@@ -170,6 +217,28 @@
                              S->getElseLoc(), move(Else));
 }
 
+Sema::OwningStmtResult 
+TemplateStmtInstantiator::VisitSwitchStmt(SwitchStmt *S) {
+  // Instantiate the condition.
+  OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);
+  if (Cond.isInvalid())
+    return SemaRef.StmtError();
+
+  // Start the switch statement itself.
+  OwningStmtResult Switch = SemaRef.ActOnStartOfSwitchStmt(move(Cond));
+  if (Switch.isInvalid())
+    return SemaRef.StmtError();
+
+  // Instantiate the body of the switch statement.
+  OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs);
+  if (Body.isInvalid())
+    return SemaRef.StmtError();
+
+  // Complete the switch statement.
+  return SemaRef.ActOnFinishSwitchStmt(S->getSwitchLoc(), move(Switch),
+                                       move(Body));
+}
+
 Sema::OwningStmtResult TemplateStmtInstantiator::VisitWhileStmt(WhileStmt *S) {
   // Instantiate the condition
   OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs);

Modified: cfe/trunk/test/SemaTemplate/instantiate-function-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-function-1.cpp?rev=71916&r1=71915&r2=71916&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-function-1.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-function-1.cpp Fri May 15 18:57:33 2009
@@ -140,3 +140,33 @@
     this.f; // expected-error{{member reference base type 'struct Member0 *const' is not a structure or union}}
   }
 };
+
+template<typename T, typename U> struct Switch0 {
+  U f(T value, U v0, U v1, U v2) {
+    switch (value) {
+    case 0: return v0;
+
+    case 1: return v1;
+
+    case 2: // fall through
+
+    default:
+      return  v2;
+    }
+  }
+};
+
+template struct Switch0<int, float>;
+
+template<typename T, int I1, int I2> struct Switch1 {
+  T f(T x, T y, T z) {
+    switch (x) {
+    case I1: return y; // expected-note{{previous}}
+    case I2: return z; // expected-error{{duplicate}}
+    default: return x;
+    }
+  }
+};
+
+template struct Switch1<int, 1, 2>;
+template struct Switch1<int, 2, 2>; // expected-note{{instantiation}}





More information about the cfe-commits mailing list