]> granicus.if.org Git - clang/commitdiff
Handle injected class names in the ASTImporter.
authorSean Callanan <scallanan@apple.com>
Sat, 14 May 2016 05:43:57 +0000 (05:43 +0000)
committerSean Callanan <scallanan@apple.com>
Sat, 14 May 2016 05:43:57 +0000 (05:43 +0000)
Every class as parsed by Clang has a forward declaration of itself as a member:

class A {
  class A;
  ...
}

but when the parser generates this it ensures that the RecordTypes for the two
are the same.  This makes (among other things) inheritance work.  This patch
fixes a bug where the ASTImporter generated two separate RecordTypes when
importing the class and the contained forward declaration, and adds a test case.

Thanks to Doug Gregor for advice on this.

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

lib/AST/ASTImporter.cpp
test/ASTMerge/Inputs/inheritance-base.cpp [new file with mode: 0644]
test/ASTMerge/inheritance.cpp [new file with mode: 0644]

index 3598dccf0a18fdbc8b7e6b6ad82b67f00fcfe497..c1dda3fcf65485c581d4dc2421f8c78f255598fa 100644 (file)
@@ -2820,8 +2820,17 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {
         Decl *CDecl = Importer.Import(DCXX->getLambdaContextDecl());
         if (DCXX->getLambdaContextDecl() && !CDecl)
           return nullptr;
-        D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(),
-                                 CDecl);
+        D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), CDecl);
+      } else if (DCXX->isInjectedClassName()) {                                                 
+        // We have to be careful to do a similar dance to the one in                            
+        // Sema::ActOnStartCXXMemberDeclarations                                                
+        CXXRecordDecl *const PrevDecl = nullptr;                                                
+        const bool DelayTypeCreation = true;                                                    
+        D2CXX = CXXRecordDecl::Create(                                                          
+            Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc,                        
+            Name.getAsIdentifierInfo(), PrevDecl, DelayTypeCreation);                           
+        Importer.getToContext().getTypeDeclType(                                                
+            D2CXX, llvm::dyn_cast<CXXRecordDecl>(DC));                                          
       } else {
         D2CXX = CXXRecordDecl::Create(Importer.getToContext(),
                                       D->getTagKind(),
diff --git a/test/ASTMerge/Inputs/inheritance-base.cpp b/test/ASTMerge/Inputs/inheritance-base.cpp
new file mode 100644 (file)
index 0000000..26fe42e
--- /dev/null
@@ -0,0 +1,7 @@
+class A
+{
+public:
+  int x;
+  A(int _x) : x(_x) {
+  }
+};
diff --git a/test/ASTMerge/inheritance.cpp b/test/ASTMerge/inheritance.cpp
new file mode 100644 (file)
index 0000000..7fce82a
--- /dev/null
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -emit-pch -o %t.1.ast %S/Inputs/inheritance-base.cpp
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++1z -ast-merge %t.1.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+class B : public A {
+  B(int _a) : A(_a) {
+  }
+};