[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