]> granicus.if.org Git - clang/commitdiff
clang-cl: Handle dll attributes in explicit class template specialization definitions...
authorHans Wennborg <hans@hanshq.net>
Wed, 27 May 2015 00:06:45 +0000 (00:06 +0000)
committerHans Wennborg <hans@hanshq.net>
Wed, 27 May 2015 00:06:45 +0000 (00:06 +0000)
Previously, we wouldn't call checkDLLAttribute() after the class template
specialization definition if the class template was already instantiated
by an explicit class template specialization declaration.

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

include/clang/Sema/Sema.h
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaTemplate.cpp
test/CodeGenCXX/dllexport.cpp
test/CodeGenCXX/dllimport.cpp

index a7020589e85b00256689b3679471029ef6bbb066..39ea3c62a8789a055449a109b1297c4a93e5d061 100644 (file)
@@ -5109,6 +5109,7 @@ public:
                             ArrayRef<CXXCtorInitializer*> MemInits,
                             bool AnyErrors);
 
+  void checkClassLevelDLLAttribute(CXXRecordDecl *Class);
   void CheckCompletedCXXClass(CXXRecordDecl *Record);
   void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
                                          Decl *TagDecl,
index e52d29e45c58f0a226e9513570171a2986717c8c..b1dfe0e95e2d5d2e3a1c39df2a782fe44fc42f54 100644 (file)
@@ -4739,15 +4739,15 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
 }
 
 /// \brief Check class-level dllimport/dllexport attribute.
-static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
+void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
   Attr *ClassAttr = getDLLAttr(Class);
 
   // MSVC inherits DLL attributes to partial class template specializations.
-  if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) {
+  if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) {
     if (auto *Spec = dyn_cast<ClassTemplatePartialSpecializationDecl>(Class)) {
       if (Attr *TemplateAttr =
               getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) {
-        auto *A = cast<InheritableAttr>(TemplateAttr->clone(S.getASTContext()));
+        auto *A = cast<InheritableAttr>(TemplateAttr->clone(getASTContext()));
         A->setInherited(true);
         ClassAttr = A;
       }
@@ -4758,12 +4758,12 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
     return;
 
   if (!Class->isExternallyVisible()) {
-    S.Diag(Class->getLocation(), diag::err_attribute_dll_not_extern)
+    Diag(Class->getLocation(), diag::err_attribute_dll_not_extern)
         << Class << ClassAttr;
     return;
   }
 
-  if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+  if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
       !ClassAttr->isInherited()) {
     // Diagnose dll attributes on members of class with dll attribute.
     for (Decl *Member : Class->decls()) {
@@ -4773,10 +4773,10 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
       if (!MemberAttr || MemberAttr->isInherited() || Member->isInvalidDecl())
         continue;
 
-      S.Diag(MemberAttr->getLocation(),
+      Diag(MemberAttr->getLocation(),
              diag::err_attribute_dll_member_of_dll_class)
           << MemberAttr << ClassAttr;
-      S.Diag(ClassAttr->getLocation(), diag::note_previous_attribute);
+      Diag(ClassAttr->getLocation(), diag::note_previous_attribute);
       Member->setInvalidDecl();
     }
   }
@@ -4798,7 +4798,7 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
   }
 
   // Force declaration of implicit members so they can inherit the attribute.
-  S.ForceDeclarationOfImplicitMembers(Class);
+  ForceDeclarationOfImplicitMembers(Class);
 
   // FIXME: MSVC's docs say all bases must be exportable, but this doesn't
   // seem to be true in practice?
@@ -4818,13 +4818,13 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
 
       if (MD->isInlined()) {
         // MinGW does not import or export inline methods.
-        if (!S.Context.getTargetInfo().getCXXABI().isMicrosoft())
+        if (!Context.getTargetInfo().getCXXABI().isMicrosoft())
           continue;
 
         // MSVC versions before 2015 don't export the move assignment operators,
         // so don't attempt to import them if we have a definition.
         if (ClassImported && MD->isMoveAssignmentOperator() &&
-            !S.getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015))
+            !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015))
           continue;
       }
     }
@@ -4834,7 +4834,7 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
 
     if (!getDLLAttr(Member)) {
       auto *NewAttr =
-          cast<InheritableAttr>(ClassAttr->clone(S.getASTContext()));
+          cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
       NewAttr->setInherited(true);
       Member->addAttr(NewAttr);
     }
@@ -4849,7 +4849,7 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
         if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited())
           continue;
 
-        S.MarkFunctionReferenced(Class->getLocation(), MD);
+        MarkFunctionReferenced(Class->getLocation(), MD);
 
         // The function will be passed to the consumer when its definition is
         // encountered.
@@ -4860,17 +4860,17 @@ static void checkDLLAttribute(Sema &S, CXXRecordDecl *Class) {
         // defaulted methods, and the copy and move assignment operators. The
         // latter are exported even if they are trivial, because the address of
         // an operator can be taken and should compare equal accross libraries.
-        DiagnosticErrorTrap Trap(S.Diags);
-        S.MarkFunctionReferenced(Class->getLocation(), MD);
+        DiagnosticErrorTrap Trap(Diags);
+        MarkFunctionReferenced(Class->getLocation(), MD);
         if (Trap.hasErrorOccurred()) {
-          S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
-              << Class->getName() << !S.getLangOpts().CPlusPlus11;
+          Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
+              << Class->getName() << !getLangOpts().CPlusPlus11;
           break;
         }
 
         // There is no later point when we will see the definition of this
         // function, so pass it to the consumer now.
-        S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD));
+        Consumer.HandleTopLevelDecl(DeclGroupRef(MD));
       }
     }
   }
@@ -5014,7 +5014,7 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
   //   have inheriting constructors.
   DeclareInheritingConstructors(Record);
 
-  checkDLLAttribute(*this, Record);
+  checkClassLevelDLLAttribute(Record);
 }
 
 /// Look up the special member function that would be called by a special
index b5d04cf1a120ed09b5e8ae21464bdf4dffbebfb7..37eeee2f886764afedb49d0e10fb652be205c401 100644 (file)
@@ -7365,10 +7365,19 @@ Sema::ActOnExplicitInstantiation(Scope *S,
     // Fix a TSK_ExplicitInstantiationDeclaration followed by a
     // TSK_ExplicitInstantiationDefinition
     if (Old_TSK == TSK_ExplicitInstantiationDeclaration &&
-        TSK == TSK_ExplicitInstantiationDefinition)
+        TSK == TSK_ExplicitInstantiationDefinition) {
       // FIXME: Need to notify the ASTMutationListener that we did this.
       Def->setTemplateSpecializationKind(TSK);
 
+      if (!getDLLAttr(Def) && getDLLAttr(Specialization)) {
+        auto *A = cast<InheritableAttr>(
+            getDLLAttr(Specialization)->clone(getASTContext()));
+        A->setInherited(true);
+        Def->addAttr(A);
+        checkClassLevelDLLAttribute(Def);
+      }
+    }
+
     InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
   }
 
index bc1486f0d7d28bd293b3ace74f3a01e9634a2690..3a1a3ffd871ec330d97a1589bdf9ebe8e6bc9367 100644 (file)
@@ -691,6 +691,11 @@ extern template struct ExplicitInstantiationDeclExportedTemplate<int>;
 USEMEMFUNC(ExplicitInstantiationDeclExportedTemplate<int>, f);
 // M32-DAG: {{declare|define available_externally}} x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedTemplate@H@@QAEXXZ"
 
+template <typename T> struct ExplicitInstantiationDeclExportedDefTemplate { void f() {} };
+extern template struct ExplicitInstantiationDeclExportedDefTemplate<int>;
+template struct __declspec(dllexport) ExplicitInstantiationDeclExportedDefTemplate<int>;
+// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedDefTemplate@H@@QAEXXZ"
+
 namespace { struct InternalLinkageType {}; }
 struct __declspec(dllexport) PR23308 {
   void f(InternalLinkageType*);
index 639baea5a3dc83a2a607499b5053cb4944568466..6de856017b549d1e7efdeb28d3a9241d57913fce 100644 (file)
@@ -724,6 +724,18 @@ template struct __declspec(dllimport) ExplicitlyInstantiatedWithDifferentAttr<in
 USEMEMFUNC(ExplicitlyInstantiatedWithDifferentAttr<int>, f);
 // M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitlyInstantiatedWithDifferentAttr@H@@QAEXXZ"
 
+template <typename T> struct ExplicitInstantiationDeclImportedDefTemplate { void f() {} };
+extern template struct ExplicitInstantiationDeclImportedDefTemplate<int>;
+template struct __declspec(dllimport) ExplicitInstantiationDeclImportedDefTemplate<int>;
+USEMEMFUNC(ExplicitInstantiationDeclImportedDefTemplate<int>, f);
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclImportedDefTemplate@H@@QAEXXZ"
+
+template <typename T> struct __declspec(dllimport) ExplicitInstantiationDeclExportedDefImportedTemplate { void f() {} };
+extern template struct __declspec(dllimport) ExplicitInstantiationDeclExportedDefImportedTemplate <int>;
+template struct __declspec(dllexport) ExplicitInstantiationDeclExportedDefImportedTemplate<int>;
+USEMEMFUNC(ExplicitInstantiationDeclExportedDefImportedTemplate<int>, f);
+// M32-DAG: {{declare|define available_externally}} dllimport x86_thiscallcc void @"\01?f@?$ExplicitInstantiationDeclExportedDefImportedTemplate@H@@QAEXXZ"
+
 
 //===----------------------------------------------------------------------===//
 // Classes with template base classes