]> granicus.if.org Git - clang/commitdiff
Mark invalid RecordDecls as completed.
authorErik Verbruggen <erikjv@me.com>
Thu, 27 Oct 2016 08:37:14 +0000 (08:37 +0000)
committerErik Verbruggen <erikjv@me.com>
Thu, 27 Oct 2016 08:37:14 +0000 (08:37 +0000)
Sema::ActOnTag creates TagDecls for records. However, if those record
declarations are invalid, and the parser is in C++ mode, it would
silently drop the TagDecl (and leave it as "beingDefined"). The problem
is that other code (e.g. the ASTWriter) will serialize all types, and
expects them to be complete. So, leaving them open would result in
failing asserts.

Fixes PR20320

Differential Revision: http://reviews.llvm.org/D21176

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

lib/Sema/SemaDecl.cpp
test/Index/pr20320.cpp [new file with mode: 0644]
test/Index/pr20320.h [new file with mode: 0644]
test/SemaCXX/conversion-function.cpp

index e9e0f5e214d28c5580ba7c4be2aaae209ace3da6..c8973ae100e71988d0efc810b4fb966d92ee27b0 100644 (file)
@@ -13386,7 +13386,14 @@ CreateNewDecl:
   OwnedDecl = true;
   // In C++, don't return an invalid declaration. We can't recover well from
   // the cases where we make the type anonymous.
-  return (Invalid && getLangOpts().CPlusPlus) ? nullptr : New;
+  if (Invalid && getLangOpts().CPlusPlus) {
+    if (New->isBeingDefined())
+      if (auto RD = dyn_cast<RecordDecl>(New))
+        RD->completeDefinition();
+    return nullptr;
+  } else {
+    return New;
+  }
 }
 
 void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) {
diff --git a/test/Index/pr20320.cpp b/test/Index/pr20320.cpp
new file mode 100644 (file)
index 0000000..cb54cea
--- /dev/null
@@ -0,0 +1,2 @@
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 local -x c++ %s
+#include "pr20320.h"
diff --git a/test/Index/pr20320.h b/test/Index/pr20320.h
new file mode 100644 (file)
index 0000000..9dbb730
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef pr20320_h
+#define pr20320_h
+
+template<>
+struct S< ::Number::One>
+{
+};
+
+template<>
+struct S< ::Number::Two>
+{
+};
+
+#endif
index 3f494cce8ce3f7958de96002fd6a9c73f59b2b0e..c725a0d5b7c1914f0da07751ee671a42429eefc2 100644 (file)
@@ -434,8 +434,12 @@ namespace PR18234 {
   struct A {
     operator enum E { e } (); // expected-error {{'PR18234::A::E' cannot be defined in a type specifier}}
     operator struct S { int n; } (); // expected-error {{'PR18234::A::S' cannot be defined in a type specifier}}
+    // expected-note@-1 {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'struct A' to 'const PR18234::A::S &' for 1st argument}}
+#if __cplusplus >= 201103L
+  // expected-note@-3 {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'struct A' to 'PR18234::A::S &&' for 1st argument}}
+#endif
   } a;
-  A::S s = a;
+  A::S s = a; // expected-error {{no viable conversion from 'struct A' to 'A::S'}}
   A::E e = a; // expected-note {{here}}
   bool k1 = e == A::e; // expected-error {{no member named 'e'}}
   bool k2 = e.n == 0;