<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">I just saw this. Simon Pilgrim already fixed it in r343846. Thanks Simon!<div class=""><br class=""></div><div class="">Louis<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Oct 4, 2018, at 22:02, Galina Kistanova <<a href="mailto:gkistanova@gmail.com" class="">gkistanova@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div dir="ltr" class="">Hello Louis,<br class=""><br class="">This commit broke build step on one of our builders:<br class=""><a href="http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/13042" class="">http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/13042</a></div><div dir="ltr" class=""><br class=""></div><div dir="ltr" class="">. . .<br class="">FAILED: tools/clang/lib/Sema/CMakeFiles/clangSema.dir/SemaExprCXX.cpp.obj <br class="">C:\PROGRA~2\MICROS~1.0\VC\bin\amd64\cl.exe  /nologo /TP -DEXPENSIVE_CHECKS -DGTEST_HAS_RTTI=0 -DUNICODE -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_GLIBCXX_DEBUG -D_GNU_SOURCE -D_HAS_EXCEPTIONS=0 -D_SCL_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Itools\clang\lib\Sema -IC:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\lib\Sema -IC:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\include -Itools\clang\include -Iinclude -IC:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\include /DWIN32 /D_WINDOWS   /Zc:inline /Zc:strictStrings /Oi /Zc:rvalueCast /W4 -wd4141 -wd4146 -wd4180 -wd4244 -wd4258 -wd4267 -wd4291 -wd4345 -wd4351 -wd4355 -wd4456 -wd4457 -wd4458 -wd4459 -wd4503 -wd4624 -wd4722 -wd4800 -wd4100 -wd4127 -wd4512 -wd4505 -wd4610 -wd4510 -wd4702 -wd4245 -wd4706 -wd4310 -wd4701 -wd4703 -wd4389 -wd4611 -wd4805 -wd4204 -wd4577 -wd4091 -wd4592 -wd4319 -wd4324 -w14062 -we4238 /MDd /Zi /Ob0 /Od /RTC1    /EHs-c- /GR- /showIncludes /Fotools\clang\lib\Sema\CMakeFiles\clangSema.dir\SemaExprCXX.cpp.obj /Fdtools\clang\lib\Sema\CMakeFiles\clangSema.dir\clangSema.pdb /FS -c C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\lib\Sema\SemaExprCXX.cpp<br class="">C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\lib\Sema\SemaExprCXX.cpp : fatal error C1128: number of sections exceeded object file format limit: compile with /bigobj<br class=""><br class=""><br class="">Please have a look?<br class="">The builder was already red and did not send notifications on this.<br class=""><br class="">Thanks<br class=""><br class="">Galina<br class=""></div></div><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Thu, Oct 4, 2018 at 8:51 AM Louis Dionne via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" class="">cfe-commits@lists.llvm.org</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: ldionne<br class="">
Date: Thu Oct  4 08:49:42 2018<br class="">
New Revision: 343790<br class="">
<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=343790&view=rev" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project?rev=343790&view=rev</a><br class="">
Log:<br class="">
[clang] Add the exclude_from_explicit_instantiation attribute<br class="">
<br class="">
Summary:<br class="">
This attribute allows excluding a member of a class template from being part<br class="">
of an explicit template instantiation of that class template. This also makes<br class="">
sure that code using such a member will not take for granted that an external<br class="">
instantiation exists in another translation unit. The attribute was discussed<br class="">
on cfe-dev at [1] and is primarily motivated by the removal of always_inline<br class="">
in libc++ to control what's part of the ABI (see links in [1]).<br class="">
<br class="">
[1]: <a href="http://lists.llvm.org/pipermail/cfe-dev/2018-August/059024.html" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/pipermail/cfe-dev/2018-August/059024.html</a><br class="">
<br class="">
<a href="rdar://problem/43428125" class="">rdar://problem/43428125</a><br class="">
<br class="">
Reviewers: rsmith<br class="">
<br class="">
Subscribers: dexonsmith, cfe-commits<br class="">
<br class="">
Differential Revision: <a href="https://reviews.llvm.org/D51789" rel="noreferrer" target="_blank" class="">https://reviews.llvm.org/D51789</a><br class="">
<br class="">
Added:<br class="">
    cfe/trunk/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dont_assume_extern_instantiation.cpp<br class="">
    cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp<br class="">
    cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.explicit_instantiation.cpp<br class="">
    cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.extern_declaration.cpp<br class="">
    cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.merge_redeclarations.cpp<br class="">
Modified:<br class="">
    cfe/trunk/include/clang/Basic/Attr.td<br class="">
    cfe/trunk/include/clang/Basic/AttrDocs.td<br class="">
    cfe/trunk/lib/Sema/Sema.cpp<br class="">
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp<br class="">
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp<br class="">
    cfe/trunk/test/Misc/pragma-attribute-supported-attributes-list.test<br class="">
<br class="">
Modified: cfe/trunk/include/clang/Basic/Attr.td<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=343790&r1=343789&r2=343790&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=343790&r1=343789&r2=343790&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/include/clang/Basic/Attr.td (original)<br class="">
+++ cfe/trunk/include/clang/Basic/Attr.td Thu Oct  4 08:49:42 2018<br class="">
@@ -3042,6 +3042,13 @@ def InternalLinkage : InheritableAttr {<br class="">
   let Documentation = [InternalLinkageDocs];<br class="">
 }<br class="">
<br class="">
+def ExcludeFromExplicitInstantiation : InheritableAttr {<br class="">
+  let Spellings = [Clang<"exclude_from_explicit_instantiation">];<br class="">
+  let Subjects = SubjectList<[Var, Function, CXXRecord]>;<br class="">
+  let Documentation = [ExcludeFromExplicitInstantiationDocs];<br class="">
+  let MeaningfulToClassTemplateDefinition = 1;<br class="">
+}<br class="">
+<br class="">
 def Reinitializes : InheritableAttr {<br class="">
   let Spellings = [Clang<"reinitializes", 0>];<br class="">
   let Subjects = SubjectList<[NonStaticNonConstCXXMethod], ErrorDiag>;<br class="">
<br class="">
Modified: cfe/trunk/include/clang/Basic/AttrDocs.td<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=343790&r1=343789&r2=343790&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=343790&r1=343789&r2=343790&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/include/clang/Basic/AttrDocs.td (original)<br class="">
+++ cfe/trunk/include/clang/Basic/AttrDocs.td Thu Oct  4 08:49:42 2018<br class="">
@@ -2975,6 +2975,68 @@ This can be used to contain the ABI of a<br class="">
   }];<br class="">
 }<br class="">
<br class="">
+def ExcludeFromExplicitInstantiationDocs : Documentation {<br class="">
+  let Category = DocCatFunction;<br class="">
+  let Content = [{<br class="">
+The ``exclude_from_explicit_instantiation`` attribute opts-out a member of a<br class="">
+class template from being part of explicit template instantiations of that<br class="">
+class template. This means that an explicit instantiation will not instantiate<br class="">
+members of the class template marked with the attribute, but also that code<br class="">
+where an extern template declaration of the enclosing class template is visible<br class="">
+will not take for granted that an external instantiation of the class template<br class="">
+would provide those members (which would otherwise be a link error, since the<br class="">
+explicit instantiation won't provide those members). For example, let's say we<br class="">
+don't want the ``data()`` method to be part of libc++'s ABI. To make sure it<br class="">
+is not exported from the dylib, we give it hidden visibility:<br class="">
+<br class="">
+  .. code-block:: c++<br class="">
+<br class="">
+    // in <string><br class="">
+    template <class CharT><br class="">
+    class basic_string {<br class="">
+    public:<br class="">
+      __attribute__((__visibility__("hidden")))<br class="">
+      const value_type* data() const noexcept { ... }<br class="">
+    };<br class="">
+<br class="">
+    template class basic_string<char>;<br class="">
+<br class="">
+Since an explicit template instantiation declaration for ``basic_string<char>``<br class="">
+is provided, the compiler is free to assume that ``basic_string<char>::data()``<br class="">
+will be provided by another translation unit, and it is free to produce an<br class="">
+external call to this function. However, since ``data()`` has hidden visibility<br class="">
+and the explicit template instantiation is provided in a shared library (as<br class="">
+opposed to simply another translation unit), ``basic_string<char>::data()``<br class="">
+won't be found and a link error will ensue. This happens because the compiler<br class="">
+assumes that ``basic_string<char>::data()`` is part of the explicit template<br class="">
+instantiation declaration, when it really isn't. To tell the compiler that<br class="">
+``data()`` is not part of the explicit template instantiation declaration, the<br class="">
+``exclude_from_explicit_instantiation`` attribute can be used:<br class="">
+<br class="">
+  .. code-block:: c++<br class="">
+<br class="">
+    // in <string><br class="">
+    template <class CharT><br class="">
+    class basic_string {<br class="">
+    public:<br class="">
+      __attribute__((__visibility__("hidden")))<br class="">
+      __attribute__((exclude_from_explicit_instantiation))<br class="">
+      const value_type* data() const noexcept { ... }<br class="">
+    };<br class="">
+<br class="">
+    template class basic_string<char>;<br class="">
+<br class="">
+Now, the compiler won't assume that ``basic_string<char>::data()`` is provided<br class="">
+externally despite there being an explicit template instantiation declaration:<br class="">
+the compiler will implicitly instantiate ``basic_string<char>::data()`` in the<br class="">
+TUs where it is used.<br class="">
+<br class="">
+This attribute can be used on static and non-static member functions of class<br class="">
+templates, static data members of class templates and member classes of class<br class="">
+templates.<br class="">
+  }];<br class="">
+}<br class="">
+<br class="">
 def DisableTailCallsDocs : Documentation {<br class="">
   let Category = DocCatFunction;<br class="">
   let Content = [{<br class="">
<br class="">
Modified: cfe/trunk/lib/Sema/Sema.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=343790&r1=343789&r2=343790&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=343790&r1=343789&r2=343790&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/Sema/Sema.cpp (original)<br class="">
+++ cfe/trunk/lib/Sema/Sema.cpp Thu Oct  4 08:49:42 2018<br class="">
@@ -644,7 +644,8 @@ void Sema::getUndefinedButUsed(<br class="">
         continue;<br class="">
       if (FD->isExternallyVisible() &&<br class="">
           !isExternalWithNoLinkageType(FD) &&<br class="">
-          !FD->getMostRecentDecl()->isInlined())<br class="">
+          !FD->getMostRecentDecl()->isInlined() &&<br class="">
+          !FD->hasAttr<ExcludeFromExplicitInstantiationAttr>())<br class="">
         continue;<br class="">
       if (FD->getBuiltinID())<br class="">
         continue;<br class="">
@@ -654,7 +655,8 @@ void Sema::getUndefinedButUsed(<br class="">
         continue;<br class="">
       if (VD->isExternallyVisible() &&<br class="">
           !isExternalWithNoLinkageType(VD) &&<br class="">
-          !VD->getMostRecentDecl()->isInline())<br class="">
+          !VD->getMostRecentDecl()->isInline() &&<br class="">
+          !VD->hasAttr<ExcludeFromExplicitInstantiationAttr>())<br class="">
         continue;<br class="">
<br class="">
       // Skip VarDecls that lack formal definitions but which we know are in<br class="">
<br class="">
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=343790&r1=343789&r2=343790&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=343790&r1=343789&r2=343790&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)<br class="">
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Thu Oct  4 08:49:42 2018<br class="">
@@ -6512,6 +6512,9 @@ static void ProcessDeclAttribute(Sema &S<br class="">
   case ParsedAttr::AT_InternalLinkage:<br class="">
     handleInternalLinkageAttr(S, D, AL);<br class="">
     break;<br class="">
+  case ParsedAttr::AT_ExcludeFromExplicitInstantiation:<br class="">
+    handleSimpleAttribute<ExcludeFromExplicitInstantiationAttr>(S, D, AL);<br class="">
+    break;<br class="">
   case ParsedAttr::AT_LTOVisibilityPublic:<br class="">
     handleSimpleAttribute<LTOVisibilityPublicAttr>(S, D, AL);<br class="">
     break;<br class="">
<br class="">
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=343790&r1=343789&r2=343790&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=343790&r1=343789&r2=343790&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)<br class="">
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Oct  4 08:49:42 2018<br class="">
@@ -2574,10 +2574,14 @@ Sema::InstantiateClassMembers(SourceLoca<br class="">
   for (auto *D : Instantiation->decls()) {<br class="">
     bool SuppressNew = false;<br class="">
     if (auto *Function = dyn_cast<FunctionDecl>(D)) {<br class="">
-      if (FunctionDecl *Pattern<br class="">
-            = Function->getInstantiatedFromMemberFunction()) {<br class="">
-        MemberSpecializationInfo *MSInfo<br class="">
-          = Function->getMemberSpecializationInfo();<br class="">
+      if (FunctionDecl *Pattern =<br class="">
+              Function->getInstantiatedFromMemberFunction()) {<br class="">
+<br class="">
+        if (Function->hasAttr<ExcludeFromExplicitInstantiationAttr>())<br class="">
+          continue;<br class="">
+<br class="">
+        MemberSpecializationInfo *MSInfo =<br class="">
+            Function->getMemberSpecializationInfo();<br class="">
         assert(MSInfo && "No member specialization information?");<br class="">
         if (MSInfo->getTemplateSpecializationKind()<br class="">
                                                  == TSK_ExplicitSpecialization)<br class="">
@@ -2618,6 +2622,9 @@ Sema::InstantiateClassMembers(SourceLoca<br class="">
         continue;<br class="">
<br class="">
       if (Var->isStaticDataMember()) {<br class="">
+        if (Var->hasAttr<ExcludeFromExplicitInstantiationAttr>())<br class="">
+          continue;<br class="">
+<br class="">
         MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();<br class="">
         assert(MSInfo && "No member specialization information?");<br class="">
         if (MSInfo->getTemplateSpecializationKind()<br class="">
@@ -2649,6 +2656,9 @@ Sema::InstantiateClassMembers(SourceLoca<br class="">
         }<br class="">
       }<br class="">
     } else if (auto *Record = dyn_cast<CXXRecordDecl>(D)) {<br class="">
+      if (Record->hasAttr<ExcludeFromExplicitInstantiationAttr>())<br class="">
+        continue;<br class="">
+<br class="">
       // Always skip the injected-class-name, along with any<br class="">
       // redeclarations of nested classes, since both would cause us<br class="">
       // to try to instantiate the members of a class twice.<br class="">
<br class="">
Added: cfe/trunk/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dont_assume_extern_instantiation.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dont_assume_extern_instantiation.cpp?rev=343790&view=auto" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dont_assume_extern_instantiation.cpp?rev=343790&view=auto</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dont_assume_extern_instantiation.cpp (added)<br class="">
+++ cfe/trunk/test/CodeGenCXX/attr-exclude_from_explicit_instantiation.dont_assume_extern_instantiation.cpp Thu Oct  4 08:49:42 2018<br class="">
@@ -0,0 +1,84 @@<br class="">
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -O0 -o - %s | FileCheck %s<br class="">
+<br class="">
+// Test that we do not assume that entities marked with the<br class="">
+// exclude_from_explicit_instantiation attribute are instantiated<br class="">
+// in another TU when an extern template instantiation declaration<br class="">
+// is present. We test that by making sure that definitions are<br class="">
+// generated in this TU despite there being an extern template<br class="">
+// instantiation declaration, which is normally not the case.<br class="">
+<br class="">
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))<br class="">
+<br class="">
+template <class T><br class="">
+struct Foo {<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION        inline void non_static_member_function1();<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION               void non_static_member_function2();<br class="">
+<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION static inline void static_member_function1();<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION static        void static_member_function2();<br class="">
+<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION static        int static_data_member;<br class="">
+<br class="">
+  struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION member_class1 {<br class="">
+    static void static_member_function() { }<br class="">
+  };<br class="">
+<br class="">
+  struct member_class2 {<br class="">
+    EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function() { }<br class="">
+  };<br class="">
+};<br class="">
+<br class="">
+template <class T> inline void Foo<T>::non_static_member_function1() { }<br class="">
+template <class T>        void Foo<T>::non_static_member_function2() { }<br class="">
+<br class="">
+template <class T> inline void Foo<T>::static_member_function1() { }<br class="">
+template <class T>        void Foo<T>::static_member_function2() { }<br class="">
+<br class="">
+template <class T>        int Foo<T>::static_data_member = 0;<br class="">
+<br class="">
+extern template struct Foo<int>;<br class="">
+<br class="">
+void use() {<br class="">
+  Foo<int> f;<br class="">
+<br class="">
+  // An inline non-static member function marked with the attribute is not<br class="">
+  // part of the extern template declaration, so a definition must be emitted<br class="">
+  // in this TU.<br class="">
+  // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE27non_static_member_function1Ev<br class="">
+  f.non_static_member_function1();<br class="">
+<br class="">
+  // A non-inline non-static member function marked with the attribute is<br class="">
+  // not part of the extern template declaration, so a definition must be<br class="">
+  // emitted in this TU.<br class="">
+  // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE27non_static_member_function2Ev<br class="">
+  f.non_static_member_function2();<br class="">
+<br class="">
+  // An inline static member function marked with the attribute is not<br class="">
+  // part of the extern template declaration, so a definition must be<br class="">
+  // emitted in this TU.<br class="">
+  // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE23static_member_function1Ev<br class="">
+  Foo<int>::static_member_function1();<br class="">
+<br class="">
+  // A non-inline static member function marked with the attribute is not<br class="">
+  // part of the extern template declaration, so a definition must be<br class="">
+  // emitted in this TU.<br class="">
+  // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE23static_member_function2Ev<br class="">
+  Foo<int>::static_member_function2();<br class="">
+<br class="">
+  // A static data member marked with the attribute is not part of the<br class="">
+  // extern template declaration, so a definition must be emitted in this TU.<br class="">
+  // CHECK-DAG: @_ZN3FooIiE18static_data_memberE = linkonce_odr global<br class="">
+  int& odr_use = Foo<int>::static_data_member;<br class="">
+<br class="">
+  // A member class marked with the attribute is not part of the extern<br class="">
+  // template declaration (it is not recursively instantiated), so its member<br class="">
+  // functions must be emitted in this TU.<br class="">
+  // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE13member_class122static_member_functionEv<br class="">
+  Foo<int>::member_class1::static_member_function();<br class="">
+<br class="">
+  // A member function marked with the attribute in a member class is not<br class="">
+  // part of the extern template declaration of the parent class template, so<br class="">
+  // it must be emitted in this TU.<br class="">
+  // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE13member_class222static_member_functionEv<br class="">
+  Foo<int>::member_class2::static_member_function();<br class="">
+}<br class="">
<br class="">
Modified: cfe/trunk/test/Misc/pragma-attribute-supported-attributes-list.test<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/pragma-attribute-supported-attributes-list.test?rev=343790&r1=343789&r2=343790&view=diff" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/pragma-attribute-supported-attributes-list.test?rev=343790&r1=343789&r2=343790&view=diff</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/test/Misc/pragma-attribute-supported-attributes-list.test (original)<br class="">
+++ cfe/trunk/test/Misc/pragma-attribute-supported-attributes-list.test Thu Oct  4 08:49:42 2018<br class="">
@@ -2,7 +2,7 @@<br class="">
<br class="">
 // The number of supported attributes should never go down!<br class="">
<br class="">
-// CHECK: #pragma clang attribute supports 128 attributes:<br class="">
+// CHECK: #pragma clang attribute supports 129 attributes:<br class="">
 // CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function)<br class="">
 // CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function)<br class="">
 // CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function)<br class="">
@@ -47,6 +47,7 @@<br class="">
 // CHECK-NEXT: DisableTailCalls (SubjectMatchRule_function, SubjectMatchRule_objc_method)<br class="">
 // CHECK-NEXT: EnableIf (SubjectMatchRule_function)<br class="">
 // CHECK-NEXT: EnumExtensibility (SubjectMatchRule_enum)<br class="">
+// CHECK-NEXT: ExcludeFromExplicitInstantiation (SubjectMatchRule_variable, SubjectMatchRule_function, SubjectMatchRule_record)<br class="">
 // CHECK-NEXT: ExternalSourceSymbol ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable))<br class="">
 // CHECK-NEXT: FlagEnum (SubjectMatchRule_enum)<br class="">
 // CHECK-NEXT: Flatten (SubjectMatchRule_function)<br class="">
<br class="">
Added: cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp?rev=343790&view=auto" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp?rev=343790&view=auto</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp (added)<br class="">
+++ cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp Thu Oct  4 08:49:42 2018<br class="">
@@ -0,0 +1,36 @@<br class="">
+// RUN: %clang_cc1 -fsyntax-only -Wundefined-func-template -Wundefined-var-template -verify %s<br class="">
+<br class="">
+// Test that a diagnostic is emitted when an entity marked with the<br class="">
+// exclude_from_explicit_instantiation attribute is not defined in<br class="">
+// the current TU but it is used (and it is hence implicitly<br class="">
+// instantiated).<br class="">
+<br class="">
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))<br class="">
+<br class="">
+template <class T><br class="">
+struct Foo {<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void non_static_member_function(); // expected-note{{forward declaration of template entity is here}}<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function(); // expected-note{{forward declaration of template entity is here}}<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION static int static_data_member; // expected-note{{forward declaration of template entity is here}}<br class="">
+  struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION nested {<br class="">
+    static int static_member_function(); // expected-note{{forward declaration of template entity is here}}<br class="">
+  };<br class="">
+};<br class="">
+<br class="">
+extern template struct Foo<int>;<br class="">
+<br class="">
+void use() {<br class="">
+  Foo<int> foo;<br class="">
+<br class="">
+  foo.non_static_member_function(); // expected-warning{{instantiation of function 'Foo<int>::non_static_member_function' required here, but no definition is available}}<br class="">
+  // expected-note@-1 {{add an explicit instantiation}}<br class="">
+<br class="">
+  Foo<int>::static_member_function(); // expected-warning{{instantiation of function 'Foo<int>::static_member_function' required here, but no definition is available}}<br class="">
+  // expected-note@-1 {{add an explicit instantiation}}<br class="">
+<br class="">
+  (void)Foo<int>::static_data_member; // expected-warning{{instantiation of variable 'Foo<int>::static_data_member' required here, but no definition is available}}<br class="">
+  // expected-note@-1 {{add an explicit instantiation}}<br class="">
+<br class="">
+  Foo<int>::nested::static_member_function(); // expected-warning{{instantiation of function 'Foo<int>::nested::static_member_function' required here, but no definition is available}}<br class="">
+  // expected-note@-1 {{add an explicit instantiation}}<br class="">
+}<br class="">
<br class="">
Added: cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.explicit_instantiation.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.explicit_instantiation.cpp?rev=343790&view=auto" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.explicit_instantiation.cpp?rev=343790&view=auto</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.explicit_instantiation.cpp (added)<br class="">
+++ cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.explicit_instantiation.cpp Thu Oct  4 08:49:42 2018<br class="">
@@ -0,0 +1,45 @@<br class="">
+// RUN: %clang_cc1 -fsyntax-only -verify %s<br class="">
+<br class="">
+// Test that explicit instantiations do not instantiate entities<br class="">
+// marked with the exclude_from_explicit_instantiation attribute.<br class="">
+<br class="">
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))<br class="">
+<br class="">
+template <class T><br class="">
+struct Foo {<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION inline void non_static_member_function1();<br class="">
+<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void non_static_member_function2();<br class="">
+<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION static inline void static_member_function1();<br class="">
+<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function2();<br class="">
+<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION static int static_data_member;<br class="">
+<br class="">
+  struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION member_class1 {<br class="">
+    static void non_static_member_function() { using Fail = typename T::fail; }<br class="">
+  };<br class="">
+<br class="">
+  struct member_class2 {<br class="">
+    EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void non_static_member_function() { using Fail = typename T::fail; }<br class="">
+  };<br class="">
+};<br class="">
+<br class="">
+template <class T><br class="">
+inline void Foo<T>::non_static_member_function1() { using Fail = typename T::fail; }<br class="">
+<br class="">
+template <class T><br class="">
+void Foo<T>::non_static_member_function2() { using Fail = typename T::fail; }<br class="">
+<br class="">
+template <class T><br class="">
+inline void Foo<T>::static_member_function1() { using Fail = typename T::fail; }<br class="">
+<br class="">
+template <class T><br class="">
+void Foo<T>::static_member_function2() { using Fail = typename T::fail; }<br class="">
+<br class="">
+template <class T><br class="">
+int Foo<T>::static_data_member = T::fail;<br class="">
+<br class="">
+// expected-no-diagnostics<br class="">
+template struct Foo<int>;<br class="">
<br class="">
Added: cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.extern_declaration.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.extern_declaration.cpp?rev=343790&view=auto" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.extern_declaration.cpp?rev=343790&view=auto</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.extern_declaration.cpp (added)<br class="">
+++ cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.extern_declaration.cpp Thu Oct  4 08:49:42 2018<br class="">
@@ -0,0 +1,69 @@<br class="">
+// RUN: %clang_cc1 -Wno-unused-local-typedef -fsyntax-only -verify %s<br class="">
+<br class="">
+// Test that extern instantiation declarations cause members marked with<br class="">
+// the exclude_from_explicit_instantiation attribute to be instantiated in<br class="">
+// the current TU.<br class="">
+<br class="">
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))<br class="">
+<br class="">
+template <class T><br class="">
+struct Foo {<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION inline void non_static_member_function1();<br class="">
+<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void non_static_member_function2();<br class="">
+<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION static inline void static_member_function1();<br class="">
+<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function2();<br class="">
+<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION static int static_data_member;<br class="">
+<br class="">
+  struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION member_class1 {<br class="">
+    static void static_member_function() {<br class="">
+      using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}<br class="">
+    }<br class="">
+  };<br class="">
+<br class="">
+  struct member_class2 {<br class="">
+    EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function() {<br class="">
+      using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}<br class="">
+    }<br class="">
+  };<br class="">
+};<br class="">
+<br class="">
+template <class T><br class="">
+inline void Foo<T>::non_static_member_function1() {<br class="">
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}<br class="">
+}<br class="">
+<br class="">
+template <class T><br class="">
+void Foo<T>::non_static_member_function2() {<br class="">
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}<br class="">
+}<br class="">
+<br class="">
+template <class T><br class="">
+inline void Foo<T>::static_member_function1() {<br class="">
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}<br class="">
+}<br class="">
+<br class="">
+template <class T><br class="">
+void Foo<T>::static_member_function2() {<br class="">
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}<br class="">
+}<br class="">
+<br class="">
+template <class T><br class="">
+int Foo<T>::static_data_member = T::invalid; // expected-error{{no member named 'invalid' in 'Empty'}}<br class="">
+<br class="">
+struct Empty { };<br class="">
+extern template struct Foo<Empty>;<br class="">
+<br class="">
+int main() {<br class="">
+  Foo<Empty> foo;<br class="">
+  foo.non_static_member_function1();                   // expected-note{{in instantiation of}}<br class="">
+  foo.non_static_member_function2();                   // expected-note{{in instantiation of}}<br class="">
+  Foo<Empty>::static_member_function1();               // expected-note{{in instantiation of}}<br class="">
+  Foo<Empty>::static_member_function2();               // expected-note{{in instantiation of}}<br class="">
+  (void)foo.static_data_member;                        // expected-note{{in instantiation of}}<br class="">
+  Foo<Empty>::member_class1::static_member_function(); // expected-note{{in instantiation of}}<br class="">
+  Foo<Empty>::member_class2::static_member_function(); // expected-note{{in instantiation of}}<br class="">
+}<br class="">
<br class="">
Added: cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.merge_redeclarations.cpp<br class="">
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.merge_redeclarations.cpp?rev=343790&view=auto" rel="noreferrer" target="_blank" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.merge_redeclarations.cpp?rev=343790&view=auto</a><br class="">
==============================================================================<br class="">
--- cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.merge_redeclarations.cpp (added)<br class="">
+++ cfe/trunk/test/SemaCXX/attr-exclude_from_explicit_instantiation.merge_redeclarations.cpp Thu Oct  4 08:49:42 2018<br class="">
@@ -0,0 +1,43 @@<br class="">
+// RUN: %clang_cc1 -fsyntax-only -verify %s<br class="">
+<br class="">
+// Test that we properly merge the exclude_from_explicit_instantiation<br class="">
+// attribute on redeclarations.<br class="">
+<br class="">
+#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))<br class="">
+<br class="">
+template <class T><br class="">
+struct Foo {<br class="">
+  // Declaration without the attribute, definition with the attribute.<br class="">
+  void func1();<br class="">
+<br class="">
+  // Declaration with the attribute, definition without the attribute.<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void func2();<br class="">
+<br class="">
+  // Declaration with the attribute, definition with the attribute.<br class="">
+  EXCLUDE_FROM_EXPLICIT_INSTANTIATION void func3();<br class="">
+};<br class="">
+<br class="">
+template <class T><br class="">
+EXCLUDE_FROM_EXPLICIT_INSTANTIATION void Foo<T>::func1() {<br class="">
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}<br class="">
+}<br class="">
+<br class="">
+template <class T><br class="">
+void Foo<T>::func2() {<br class="">
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}<br class="">
+}<br class="">
+<br class="">
+template <class T><br class="">
+EXCLUDE_FROM_EXPLICIT_INSTANTIATION void Foo<T>::func3() {<br class="">
+  using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}<br class="">
+}<br class="">
+<br class="">
+struct Empty { };<br class="">
+extern template struct Foo<Empty>;<br class="">
+<br class="">
+int main() {<br class="">
+  Foo<Empty> foo;<br class="">
+  foo.func1(); // expected-note{{in instantiation of}}<br class="">
+  foo.func2(); // expected-note{{in instantiation of}}<br class="">
+  foo.func3(); // expected-note{{in instantiation of}}<br class="">
+}<br class="">
<br class="">
<br class="">
_______________________________________________<br class="">
cfe-commits mailing list<br class="">
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" class="">cfe-commits@lists.llvm.org</a><br class="">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br class="">
</blockquote></div>
</div></blockquote></div><br class=""></div></body></html>