diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-11-07 20:07:17 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-11-07 20:07:17 +0000 |
commit | 2aa81a718e64fb4ca651ea12ab7afaeffc11e463 (patch) | |
tree | f1939cc5f74847f640d2c97c3ad061e9dc1b292a | |
parent | a98da3d236ac9cf8cf1e818069245fcdf307b783 (diff) | |
download | bcm5719-llvm-2aa81a718e64fb4ca651ea12ab7afaeffc11e463.tar.gz bcm5719-llvm-2aa81a718e64fb4ca651ea12ab7afaeffc11e463.zip |
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
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 6 | ||||
-rw-r--r-- | clang/test/SemaCXX/constant-expression-cxx11.cpp | 13 |
2 files changed, 18 insertions, 1 deletions
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 2d22e4ca647..52f647083a2 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -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. diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index c721d7e33cc..664daf081bd 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -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>(); +} |