Skip to content

Commit 2aa81a7

Browse files
committed
PR17800: When performing pack expansion, we must always rebuild the AST nodes
to avoid breaking AST invariants by reusing Stmt nodes within the same function. llvm-svn: 194217
1 parent a98da3d commit 2aa81a7

File tree

2 files changed

+18
-1
lines changed

2 files changed

+18
-1
lines changed

clang/lib/Sema/TreeTransform.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,11 @@ class TreeTransform {
142142
///
143143
/// Subclasses may override this function to specify when the transformation
144144
/// should rebuild all AST nodes.
145-
bool AlwaysRebuild() { return false; }
145+
///
146+
/// We must always rebuild all AST nodes when performing variadic template
147+
/// pack expansion, in order to avoid violating the AST invariant that each
148+
/// statement node appears at most once in its containing declaration.
149+
bool AlwaysRebuild() { return SemaRef.ArgumentPackSubstitutionIndex != -1; }
146150

147151
/// \brief Returns the location of the entity being transformed, if that
148152
/// information was not available elsewhere in the AST.

clang/test/SemaCXX/constant-expression-cxx11.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,3 +1811,16 @@ namespace NeverConstantTwoWays {
18111811
1 / 0 : // expected-warning {{division by zero}} expected-note {{division by zero}}
18121812
0;
18131813
}
1814+
1815+
namespace PR17800 {
1816+
struct A {
1817+
constexpr int operator()() const { return 0; }
1818+
};
1819+
template <typename ...T> constexpr int sink(T ...) {
1820+
return 0;
1821+
}
1822+
template <int ...N> constexpr int run() {
1823+
return sink(A()() + N ...);
1824+
}
1825+
constexpr int k = run<1, 2, 3>();
1826+
}

0 commit comments

Comments
 (0)