]> granicus.if.org Git - clang/commitdiff
Propagate DLLAttr to friend re-declarations of member functions
authorStephan Bergmann <sbergman@redhat.com>
Thu, 8 Mar 2018 07:34:40 +0000 (07:34 +0000)
committerStephan Bergmann <sbergman@redhat.com>
Thu, 8 Mar 2018 07:34:40 +0000 (07:34 +0000)
...that have already been constructed (e.g., in inner classes) while parsing the
class definition.  They would otherwise lack any DLLAttr inherited from the
class, which are only set here (called from Sema::CheckCompletedClass) after the
class definition has been parsed completely.

Differential revision: https://reviews.llvm.org/D16632

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

lib/Sema/SemaDeclCXX.cpp
test/CodeGenCXX/dllexport.cpp

index 51ba96fb1e809a69acc9497cc81a04005e32ee59..9e3647548be6bd2a3ebd90c4ca4cfb1f045dc6fe 100644 (file)
@@ -5685,6 +5685,21 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
           cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
       NewAttr->setInherited(true);
       Member->addAttr(NewAttr);
+
+      if (MD) {
+        // Propagate DLLAttr to friend re-declarations of MD that have already
+        // been constructed.
+        for (FunctionDecl *FD = MD->getMostRecentDecl(); FD;
+             FD = FD->getPreviousDecl()) {
+          if (FD->getFriendObjectKind() == Decl::FOK_None)
+            continue;
+          assert(!getDLLAttr(FD) &&
+                 "friend re-decl should not already have a DLLAttr");
+          NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
+          NewAttr->setInherited(true);
+          FD->addAttr(NewAttr);
+        }
+      }
     }
   }
 
index 4155940f77e3e19fb4bece278be2eb7605fe027e..82360557ee6ea8d17d968ff63fc230557c238c79 100644 (file)
@@ -290,6 +290,16 @@ struct FuncFriend {
 __declspec(dllexport) void friend1() {}
                       void friend2() {}
 
+// MSC-DAG: define dso_local dllexport void @"\01?func@Befriended@@SAXXZ"()
+// GNU-DAG: define dso_local dllexport void @_ZN10Befriended4funcEv()
+struct __declspec(dllexport) Befriended {
+  static void func();
+  struct Befriending {
+    friend void Befriended::func();
+  };
+};
+void Befriended::func() {}
+
 // Implicit declarations can be redeclared with dllexport.
 // MSC-DAG: define dso_local dllexport noalias i8* @"\01??2@{{YAPAXI|YAPEAX_K}}@Z"(
 // GNU-DAG: define dso_local dllexport noalias i8* @_Znw{{[yj]}}(