]> granicus.if.org Git - clang/commitdiff
PR17800: When performing pack expansion, we must always rebuild the AST nodes
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 7 Nov 2013 20:07:17 +0000 (20:07 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 7 Nov 2013 20:07:17 +0000 (20:07 +0000)
to avoid breaking AST invariants by reusing Stmt nodes within the same
function.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194217 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/TreeTransform.h
test/SemaCXX/constant-expression-cxx11.cpp

index 2d22e4ca6473a808f444e64372d81dda4aa9a85c..52f647083a24f3a66859436739f9e24667e0b953 100644 (file)
@@ -142,7 +142,11 @@ public:
   ///
   /// Subclasses may override this function to specify when the transformation
   /// should rebuild all AST nodes.
-  bool AlwaysRebuild() { return false; }
+  ///
+  /// We must always rebuild all AST nodes when performing variadic template
+  /// pack expansion, in order to avoid violating the AST invariant that each
+  /// statement node appears at most once in its containing declaration.
+  bool AlwaysRebuild() { return SemaRef.ArgumentPackSubstitutionIndex != -1; }
 
   /// \brief Returns the location of the entity being transformed, if that
   /// information was not available elsewhere in the AST.
index c721d7e33cc4dafe31eebe792361a80fd8666fa0..664daf081bda1ffda765f3a091097ed68f70b6a9 100644 (file)
@@ -1811,3 +1811,16 @@ namespace NeverConstantTwoWays {
         1 / 0 : // expected-warning {{division by zero}} expected-note {{division by zero}}
         0;
 }
+
+namespace PR17800 {
+  struct A {
+    constexpr int operator()() const { return 0; }
+  };
+  template <typename ...T> constexpr int sink(T ...) {
+    return 0;
+  }
+  template <int ...N> constexpr int run() {
+    return sink(A()() + N ...);
+  }
+  constexpr int k = run<1, 2, 3>();
+}