]> granicus.if.org Git - clang/commitdiff
Fix a pretty nasty bug in noreturn destructors that cascaded into lots
authorChandler Carruth <chandlerc@gmail.com>
Tue, 20 Sep 2011 04:55:26 +0000 (04:55 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Tue, 20 Sep 2011 04:55:26 +0000 (04:55 +0000)
of false positive warnings that depend on noreturn destructors pruning
the CFGs, but only in C++0x mode!

This was really surprising as the debugger quickly reveals that the
attributes are parsed correctly (and using the same code) in both modes.
The warning fires in the same way in both modes. But between parsing and
building the destructor declaration with the noreturn attribute and the
warning, it magically disappears. The key? The 'noexcept' appears!

When we were rebuilding the destructor type with the computed implicit
noexcept we completely dropped the old type on the floor. This almost
makes sense (as the arguments and return type to a destructor aren't
exactly unpredictable), but lost any function type attributes as well.
The fix is simple, we build the new type off of the old one rather than
starting fresh.

Testing this is a bit awkward. I've done it by running the
noreturn-sensitive tests in both modes, which previous failed and now
passes, but if anyone has ideas about how to more specifically and
thoroughly test that the extended info on a destructor is preserved when
adding noexcept, I'm all ears.

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

lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/return-noreturn.cpp

index 37a4026b5817a8294f8a7bc820e9b93eea882e0b..67b1274c2cc1653be6414d286baccf1ed485bab0 100644 (file)
@@ -6964,8 +6964,10 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *classDecl,
   ImplicitExceptionSpecification exceptSpec =
       ComputeDefaultedDtorExceptionSpec(classDecl);
 
-  // Replace the destructor's type.
-  FunctionProtoType::ExtProtoInfo epi;
+  // Replace the destructor's type, building off the existing one. Fortunately,
+  // the only thing of interest in the destructor type is its extended info.
+  // The return and arguments are fixed.
+  FunctionProtoType::ExtProtoInfo epi = dtorType->getExtProtoInfo();
   epi.ExceptionSpecType = exceptSpec.getExceptionSpecType();
   epi.NumExceptions = exceptSpec.size();
   epi.Exceptions = exceptSpec.data();
index 2109efc19eb8d12dbc19b1af95a44cadc9be5aef..1fcccd49459cceb0fb1b474d19d5f8e072972bf8 100644 (file)
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 %s -fsyntax-only -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code
+// RUN: %clang_cc1 %s -fsyntax-only -std=c++0x -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code
 
 // A destructor may be marked noreturn and should still influence the CFG.
 void pr6884_abort() __attribute__((noreturn));