[clang] Add the exclude_from_explicit_instantiation attribute

Summary:
This attribute allows excluding a member of a class template from being part
of an explicit template instantiation of that class template. This also makes
sure that code using such a member will not take for granted that an external
instantiation exists in another translation unit. The attribute was discussed
on cfe-dev at [1] and is primarily motivated by the removal of always_inline
in libc++ to control what's part of the ABI (see links in [1]).

[1]: http://lists.llvm.org/pipermail/cfe-dev/2018-August/059024.html

rdar://problem/43428125

Reviewers: rsmith

Subscribers: dexonsmith, cfe-commits

Differential Revision: https://reviews.llvm.org/D51789

llvm-svn: 343790
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 5666cf0..cfedf0a 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2574,10 +2574,14 @@
   for (auto *D : Instantiation->decls()) {
     bool SuppressNew = false;
     if (auto *Function = dyn_cast<FunctionDecl>(D)) {
-      if (FunctionDecl *Pattern
-            = Function->getInstantiatedFromMemberFunction()) {
-        MemberSpecializationInfo *MSInfo
-          = Function->getMemberSpecializationInfo();
+      if (FunctionDecl *Pattern =
+              Function->getInstantiatedFromMemberFunction()) {
+
+        if (Function->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+          continue;
+
+        MemberSpecializationInfo *MSInfo =
+            Function->getMemberSpecializationInfo();
         assert(MSInfo && "No member specialization information?");
         if (MSInfo->getTemplateSpecializationKind()
                                                  == TSK_ExplicitSpecialization)
@@ -2618,6 +2622,9 @@
         continue;
 
       if (Var->isStaticDataMember()) {
+        if (Var->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+          continue;
+
         MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
         assert(MSInfo && "No member specialization information?");
         if (MSInfo->getTemplateSpecializationKind()
@@ -2649,6 +2656,9 @@
         }
       }
     } else if (auto *Record = dyn_cast<CXXRecordDecl>(D)) {
+      if (Record->hasAttr<ExcludeFromExplicitInstantiationAttr>())
+        continue;
+
       // Always skip the injected-class-name, along with any
       // redeclarations of nested classes, since both would cause us
       // to try to instantiate the members of a class twice.