[cfe-commits] r123316 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaTemplateVariadic.cpp lib/Sema/TreeTransform.h test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp
Douglas Gregor
dgregor at apple.com
Wed Jan 12 09:07:58 PST 2011
Author: dgregor
Date: Wed Jan 12 11:07:58 2011
New Revision: 123316
URL: http://llvm.org/viewvc/llvm-project?rev=123316&view=rev
Log:
Teach TreeTransform how to transform a pack expansion type into
another pack expansion type. This can happen when rebuilding types in
the current instantiation.
Fixes <rdar://problem/8848837> (Clang crashing on libc++ <functional>).
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=123316&r1=123315&r2=123316&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Jan 12 11:07:58 2011
@@ -3331,7 +3331,13 @@
/// expansion.
TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern,
SourceLocation EllipsisLoc);
-
+
+ /// \brief Construct a pack expansion type from the pattern of the pack
+ /// expansion.
+ QualType CheckPackExpansion(QualType Pattern,
+ SourceRange PatternRange,
+ SourceLocation EllipsisLoc);
+
/// \brief Invoked when parsing an expression followed by an ellipsis, which
/// creates a pack expansion.
///
Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=123316&r1=123315&r2=123316&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Wed Jan 12 11:07:58 2011
@@ -377,18 +377,13 @@
TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern,
SourceLocation EllipsisLoc) {
- // C++0x [temp.variadic]p5:
- // The pattern of a pack expansion shall name one or more
- // parameter packs that are not expanded by a nested pack
- // expansion.
- if (!Pattern->getType()->containsUnexpandedParameterPack()) {
- Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
- << Pattern->getTypeLoc().getSourceRange();
+ // Create the pack expansion type and source-location information.
+ QualType Result = CheckPackExpansion(Pattern->getType(),
+ Pattern->getTypeLoc().getSourceRange(),
+ EllipsisLoc);
+ if (Result.isNull())
return 0;
- }
- // Create the pack expansion type and source-location information.
- QualType Result = Context.getPackExpansionType(Pattern->getType());
TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);
PackExpansionTypeLoc TL = cast<PackExpansionTypeLoc>(TSResult->getTypeLoc());
TL.setEllipsisLoc(EllipsisLoc);
@@ -400,6 +395,22 @@
return TSResult;
}
+QualType Sema::CheckPackExpansion(QualType Pattern,
+ SourceRange PatternRange,
+ SourceLocation EllipsisLoc) {
+ // C++0x [temp.variadic]p5:
+ // The pattern of a pack expansion shall name one or more
+ // parameter packs that are not expanded by a nested pack
+ // expansion.
+ if (!Pattern->containsUnexpandedParameterPack()) {
+ Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+ << PatternRange;
+ return QualType();
+ }
+
+ return Context.getPackExpansionType(Pattern);
+}
+
ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) {
if (!Pattern)
return ExprError();
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=123316&r1=123315&r2=123316&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Jan 12 11:07:58 2011
@@ -808,6 +808,16 @@
return SemaRef.Context.getElaboratedType(Keyword, NNS, T);
}
+ /// \brief Build a new pack expansion type.
+ ///
+ /// By default, builds a new PackExpansionType type from the given pattern.
+ /// Subclasses may override this routine to provide different behavior.
+ QualType RebuildPackExpansionType(QualType Pattern,
+ SourceRange PatternRange,
+ SourceLocation EllipsisLoc) {
+ return getSema().CheckPackExpansion(Pattern, PatternRange, EllipsisLoc);
+ }
+
/// \brief Build a new nested-name-specifier given the prefix and an
/// identifier that names the next step in the nested-name-specifier.
///
@@ -4232,8 +4242,24 @@
template<typename Derived>
QualType TreeTransform<Derived>::TransformPackExpansionType(TypeLocBuilder &TLB,
PackExpansionTypeLoc TL) {
- llvm_unreachable("Caller must expansion pack expansion types");
- return QualType();
+ QualType Pattern
+ = getDerived().TransformType(TLB, TL.getPatternLoc());
+ if (Pattern.isNull())
+ return QualType();
+
+ QualType Result = TL.getType();
+ if (getDerived().AlwaysRebuild() ||
+ Pattern != TL.getPatternLoc().getType()) {
+ Result = getDerived().RebuildPackExpansionType(Pattern,
+ TL.getPatternLoc().getSourceRange(),
+ TL.getEllipsisLoc());
+ if (Result.isNull())
+ return QualType();
+ }
+
+ PackExpansionTypeLoc NewT = TLB.push<PackExpansionTypeLoc>(Result);
+ NewT.setEllipsisLoc(TL.getEllipsisLoc());
+ return Result;
}
template<typename Derived>
Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp?rev=123316&r1=123315&r2=123316&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/injected-class-name.cpp Wed Jan 12 11:07:58 2011
@@ -39,3 +39,21 @@
template<typename ...InnerTypes>
template<typename ...ReallyInner>
void X0<T, T, Types...>::Inner<InnerTypes...>::f4() { }
+
+namespace rdar8848837 {
+ // Out-of-line definitions that cause rebuilding in the current
+ // instantiation.
+ template<typename F> struct X;
+
+ template<typename R, typename ...ArgTypes>
+ struct X<R(ArgTypes...)> {
+ X<R(ArgTypes...)> f();
+ };
+
+ template<typename R, typename ...ArgTypes>
+ X<R(ArgTypes...)> X<R(ArgTypes...)>::f() { return *this; }
+
+
+ X<int(float, double)> xif;
+
+}
More information about the cfe-commits
mailing list