Mark invalid RecordDecls as completed.

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
This commit is contained in:
Erik Verbruggen 2016-10-27 08:37:14 +00:00
parent 0834a353d3
commit 82e4eed546
4 changed files with 29 additions and 2 deletions

View 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) {

2
test/Index/pr20320.cpp Normal file
View File

@ -0,0 +1,2 @@
// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 local -x c++ %s
#include "pr20320.h"

14
test/Index/pr20320.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef pr20320_h
#define pr20320_h
template<>
struct S< ::Number::One>
{
};
template<>
struct S< ::Number::Two>
{
};
#endif

View 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;