r342516 - [MS] Defer dllexport inline friend functions like other inline methods

Reid Kleckner via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 18 16:16:31 PDT 2018


Author: rnk
Date: Tue Sep 18 16:16:30 2018
New Revision: 342516

URL: http://llvm.org/viewvc/llvm-project?rev=342516&view=rev
Log:
[MS] Defer dllexport inline friend functions like other inline methods

This special case was added in r264841, but the code breaks our
invariants by calling EmitTopLevelDecl without first creating a
HandlingTopLevelDeclRAII scope.

This fixes the PCH crash in https://crbug.com/884427. I was never able
to make a satisfactory reduction, unfortunately. I'm not very worried
about this regressing since this change makes the code simpler while
passing the existing test that shows we do emit dllexported friend
function definitions. Now we just defer their emission until the tag is
fully complete, which is generally good.

Modified:
    cfe/trunk/lib/CodeGen/ModuleBuilder.cpp

Modified: cfe/trunk/lib/CodeGen/ModuleBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ModuleBuilder.cpp?rev=342516&r1=342515&r2=342516&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/ModuleBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/ModuleBuilder.cpp Tue Sep 18 16:16:30 2018
@@ -64,7 +64,7 @@ namespace {
     std::unique_ptr<CodeGen::CodeGenModule> Builder;
 
   private:
-    SmallVector<CXXMethodDecl *, 8> DeferredInlineMethodDefinitions;
+    SmallVector<FunctionDecl *, 8> DeferredInlineMemberFuncDefs;
 
   public:
     CodeGeneratorImpl(DiagnosticsEngine &diags, llvm::StringRef ModuleName,
@@ -80,7 +80,7 @@ namespace {
 
     ~CodeGeneratorImpl() override {
       // There should normally not be any leftover inline method definitions.
-      assert(DeferredInlineMethodDefinitions.empty() ||
+      assert(DeferredInlineMemberFuncDefs.empty() ||
              Diags.hasErrorOccurred());
     }
 
@@ -163,16 +163,16 @@ namespace {
     }
 
     void EmitDeferredDecls() {
-      if (DeferredInlineMethodDefinitions.empty())
+      if (DeferredInlineMemberFuncDefs.empty())
         return;
 
       // Emit any deferred inline method definitions. Note that more deferred
       // methods may be added during this loop, since ASTConsumer callbacks
       // can be invoked if AST inspection results in declarations being added.
       HandlingTopLevelDeclRAII HandlingDecl(*this);
-      for (unsigned I = 0; I != DeferredInlineMethodDefinitions.size(); ++I)
-        Builder->EmitTopLevelDecl(DeferredInlineMethodDefinitions[I]);
-      DeferredInlineMethodDefinitions.clear();
+      for (unsigned I = 0; I != DeferredInlineMemberFuncDefs.size(); ++I)
+        Builder->EmitTopLevelDecl(DeferredInlineMemberFuncDefs[I]);
+      DeferredInlineMemberFuncDefs.clear();
     }
 
     void HandleInlineFunctionDefinition(FunctionDecl *D) override {
@@ -181,17 +181,6 @@ namespace {
 
       assert(D->doesThisDeclarationHaveABody());
 
-      // Handle friend functions.
-      if (D->isInIdentifierNamespace(Decl::IDNS_OrdinaryFriend)) {
-        if (Ctx->getTargetInfo().getCXXABI().isMicrosoft()
-            && !D->getLexicalDeclContext()->isDependentContext())
-          Builder->EmitTopLevelDecl(D);
-        return;
-      }
-
-      // Otherwise, must be a method.
-      auto MD = cast<CXXMethodDecl>(D);
-
       // We may want to emit this definition. However, that decision might be
       // based on computing the linkage, and we have to defer that in case we
       // are inside of something that will change the method's final linkage,
@@ -200,13 +189,13 @@ namespace {
       //     void bar();
       //     void foo() { bar(); }
       //   } A;
-      DeferredInlineMethodDefinitions.push_back(MD);
+      DeferredInlineMemberFuncDefs.push_back(D);
 
       // Provide some coverage mapping even for methods that aren't emitted.
       // Don't do this for templated classes though, as they may not be
       // instantiable.
-      if (!MD->getParent()->isDependentContext())
-        Builder->AddDeferredUnusedCoverageMapping(MD);
+      if (!D->getLexicalDeclContext()->isDependentContext())
+        Builder->AddDeferredUnusedCoverageMapping(D);
     }
 
     /// HandleTagDeclDefinition - This callback is invoked each time a TagDecl




More information about the cfe-commits mailing list