r194217 - PR17800: When performing pack expansion, we must always rebuild the AST nodes

Richard Smith richard-llvm at metafoo.co.uk
Thu Nov 7 12:07:17 PST 2013


Author: rsmith
Date: Thu Nov  7 14:07:17 2013
New Revision: 194217

URL: http://llvm.org/viewvc/llvm-project?rev=194217&view=rev
Log:
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.

Modified:
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=194217&r1=194216&r2=194217&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Nov  7 14:07:17 2013
@@ -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.

Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=194217&r1=194216&r2=194217&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Thu Nov  7 14:07:17 2013
@@ -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>();
+}





More information about the cfe-commits mailing list