Skip to content

Commit

Permalink
Mark invalid RecordDecls as completed.
Browse files Browse the repository at this point in the history
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

llvm-svn: 285275
  • Loading branch information
erikjv committed Oct 27, 2016
1 parent dd680cc commit 52b2671
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 2 deletions.
9 changes: 8 additions & 1 deletion clang/lib/Sema/SemaDecl.cpp
Expand Up @@ -13386,7 +13386,14 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
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) {
Expand Down
2 changes: 2 additions & 0 deletions clang/test/Index/pr20320.cpp
@@ -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 changes: 14 additions & 0 deletions clang/test/Index/pr20320.h
@@ -0,0 +1,14 @@
#ifndef pr20320_h
#define pr20320_h

template<>
struct S< ::Number::One>
{
};

template<>
struct S< ::Number::Two>
{
};

#endif
6 changes: 5 additions & 1 deletion clang/test/SemaCXX/conversion-function.cpp
Expand Up @@ -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;
Expand Down

0 comments on commit 52b2671

Please sign in to comment.