]> granicus.if.org Git - clang/commitdiff
[Sema] Add implicit members even for invalid CXXRecordDecls
authorIlya Biryukov <ibiryukov@google.com>
Fri, 2 Feb 2018 08:40:08 +0000 (08:40 +0000)
committerIlya Biryukov <ibiryukov@google.com>
Fri, 2 Feb 2018 08:40:08 +0000 (08:40 +0000)
Summary:
It should be safe, since other code paths are already generating
implicit members even in invalid CXXRecordDecls (e.g. lookup).

If we don't generate implicit members on CXXRecordDecl's completion,
they will be generated by next lookup of constructors. This causes a
crash when the following conditions are met:
  - a CXXRecordDecl is invalid,
  - it is provided via ExternalASTSource (e.g. from PCH),
  - it has inherited constructors (they create ShadowDecls),
  - lookup of its constructors was not run before ASTWriter serialized
    it.

This may require the ShadowDecls created for inherited constructors to
be removed from the class, but that's no longer possible since class is
provided by ExternalASTSource.

See provided lit test for an example.

Reviewers: bkramer

Reviewed By: bkramer

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D42810

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

lib/Sema/SemaDecl.cpp
test/Index/Inputs/crash-preamble-classes.h [new file with mode: 0644]
test/Index/crash-preamble-classes.cpp [new file with mode: 0644]

index 526f6802c330c9f5d9ae17248621f6b51bb942f3..c3975f9f62d9cba9c61754ea706cfb91d2e54433 100644 (file)
@@ -15440,10 +15440,10 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
                                           CXXRecord->getDestructor());
         }
 
-        if (!CXXRecord->isInvalidDecl()) {
-          // Add any implicitly-declared members to this class.
-          AddImplicitlyDeclaredMembersToClass(CXXRecord);
+        // Add any implicitly-declared members to this class.
+        AddImplicitlyDeclaredMembersToClass(CXXRecord);
 
+        if (!CXXRecord->isInvalidDecl()) {
           // If we have virtual base classes, we may end up finding multiple
           // final overriders for a given virtual function. Check for this
           // problem now.
diff --git a/test/Index/Inputs/crash-preamble-classes.h b/test/Index/Inputs/crash-preamble-classes.h
new file mode 100644 (file)
index 0000000..a8fb5ce
--- /dev/null
@@ -0,0 +1,9 @@
+struct Incomplete;
+
+struct X : Incomplete {
+  X();
+};
+
+struct Y : X {
+  using X::X;
+};
diff --git a/test/Index/crash-preamble-classes.cpp b/test/Index/crash-preamble-classes.cpp
new file mode 100644 (file)
index 0000000..e7d4bd7
--- /dev/null
@@ -0,0 +1,8 @@
+#include "crash-preamble-classes.h"
+
+struct Z : Y {
+  Z() {}
+};
+
+// RUN: env CINDEXTEST_EDITING=1 \
+// RUN: c-index-test -test-load-source-reparse 5 local -I %S/Inputs %s