]> granicus.if.org Git - clang/commitdiff
Port r163224 to C++.
authorNico Weber <nicolasweber@gmx.de>
Wed, 18 Feb 2015 05:19:40 +0000 (05:19 +0000)
committerNico Weber <nicolasweber@gmx.de>
Wed, 18 Feb 2015 05:19:40 +0000 (05:19 +0000)
The motivation is to fix a crash on

  struct S {} s;
  Foo S::~S() { s.~S(); }

What was happening here was that S::~S() was marked as invalid since its
return type is invalid, and as a consequence CheckFunctionDeclaration() wasn't
called and S::~S() didn't get merged into S's implicit destructor.  This way,
the class ended up with two destructors, which confused the overload printer
when it suddenly had to print two possible destructors for `s.~S()`.

In addition to fixing the crash, this change also seems to improve diagnostics
in a few other places, see test changes.

Crash found by SLi's bot.

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

lib/Sema/SemaDecl.cpp
test/SemaCXX/PR9461.cpp
test/SemaCXX/crashes.cpp
test/SemaCXX/destructor.cpp

index ae18d9cbdb41a79d41728ad7cc50aefcc780daed..d351b4841f8576b7030a4443b4ae8780def892a7 100644 (file)
@@ -7418,7 +7418,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
       D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
                                                   isExplicitSpecialization));
     else if (!Previous.empty())
-      // Make graceful recovery from an invalid redeclaration.
+      // Recover gracefully from an invalid redeclaration.
       D.setRedeclaration(true);
     assert((NewFD->isInvalidDecl() || !D.isRedeclaration() ||
             Previous.getResultKind() != LookupResult::FoundOverloaded) &&
@@ -7559,6 +7559,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
       if (!NewFD->isInvalidDecl())
         D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
                                                     isExplicitSpecialization));
+      else if (!Previous.empty())
+        // Recover gracefully from an invalid redeclaration.
+        D.setRedeclaration(true);
     }
 
     assert((NewFD->isInvalidDecl() || !D.isRedeclaration() ||
index beed348abb7510cc9f55fb1f17290c4596312cf7..f97a208192b60ce0a1a5608b171284ca79d6d132 100644 (file)
@@ -22,9 +22,9 @@ _S_construct(); // expected-error {{requires}}
 };
 
 template<typename _CharT,typename _Traits,typename _Alloc>
-basic_string<_CharT,_Traits,_Alloc>::basic_string(const _CharT*,const _Alloc&)
+basic_string<_CharT,_Traits,_Alloc>::basic_string(const _CharT* c,const _Alloc&)
 :us(_S_construct)
-{string a;}
+{string a(c);}
 
 struct runtime_error{runtime_error(string);};
 
index 6ae476f7080c561a12f72fbb55f3b385c9340ec9..12251bba95a43c99103fcced4f798c72a3971771 100644 (file)
@@ -175,16 +175,16 @@ namespace test3 {
 namespace pr16964 {
   template<typename> struct bs {
     bs();
-    static int* member();
+    static int* member(); // expected-note{{possible target}}
     member();  // expected-error{{C++ requires a type specifier for all declarations}}
     static member();  // expected-error{{C++ requires a type specifier for all declarations}}
-    static int* member(int);
+    static int* member(int); // expected-note{{possible target}}
   };
 
-  template<typename T> bs<T>::bs() { member; }
+  template<typename T> bs<T>::bs() { member; }  // expected-error{{did you mean to call it}}
 
   bs<int> test() {
-    return bs<int>();
+    return bs<int>(); // expected-note{{in instantiation}}
   }
 }
 
@@ -195,7 +195,7 @@ namespace pr12791 {
   struct forward_iterator_tag : public input_iterator_tag {};
 
   template<typename _CharT, typename _Traits, typename _Alloc> struct basic_string {
-    struct _Alloc_hider : _Alloc {};
+    struct _Alloc_hider : _Alloc { _Alloc_hider(_CharT*, const _Alloc&); };
     mutable _Alloc_hider _M_dataplus;
     template<class _InputIterator> basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a = _Alloc());
     template<class _InIterator> static _CharT* _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a, input_iterator_tag);
@@ -206,12 +206,11 @@ namespace pr12791 {
   template<typename _CharT, typename _Traits, typename _Alloc>
   template<typename _InputIterator>
   basic_string<_CharT, _Traits, _Alloc>:: basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a)
-  : _M_dataplus(_S_construct(__beg, __end, __a), __a) {}
+  : _M_dataplus(_S_construct(__beg, __end, __a, input_iterator_tag()), __a) {}
 
   template<typename _CharT, typename _Traits = char_traits<_CharT>, typename _Alloc = allocator<_CharT> > struct basic_stringbuf {
     typedef _CharT char_type;
     typedef basic_string<char_type, _Traits, _Alloc> __string_type;
-    typedef typename __string_type::size_type __size_type;
     __string_type str() const {__string_type((char_type*)0,(char_type*)0);}
   };
 
index 5305ff5f7ca65180a6347acbaaa4c580a975c6e2..c66ec9f2c757eb4b560237dfbbb5ef7740dbe5c2 100644 (file)
@@ -173,6 +173,12 @@ protected:
   ~S7();
 };
 
+struct S8 {} s8;
+
+UnknownType S8::~S8() { // expected-error {{unknown type name 'UnknownType'}}
+  s8.~S8();
+}
+
 template<class T> class TS : public B {
   virtual void m();
 };