loladiro updated this revision to Diff 42100.
loladiro added a comment.

Address stylistic concerns brought up by David


http://reviews.llvm.org/D13330

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGVTables.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp
  utils/TableGen/ClangAttrEmitter.cpp

Index: utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2373,6 +2373,8 @@
     case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
     case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
     case Func | Var: return "ExpectedVariableOrFunction";
+    case Func | Class:
+      return "ExpectedFunctionOrClass";
 
     // If not compiling for C++, the class portion does not apply.
     case Func | Var | Class:
Index: test/SemaCXX/unique-instantiations.cpp
===================================================================
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang -cc1 -std=c++14 -fsyntax-only -verify %s
+
+// Correct usage
+template <typename T>
+struct foo {};
+extern template struct __attribute__((unique_instantiation)) foo<int>;
+template struct __attribute__((unique_instantiation)) foo<int>;
+
+template <typename T> T pi = T(3.1415926535897932385);
+extern template __attribute__((unique_instantiation)) float pi<float>;
+template __attribute__((unique_instantiation)) float pi<float>;
+
+// Usages on non-templates
+float __attribute__((unique_instantiation)) notpi(2.71828182845904523536028747135); // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+struct __attribute__((unique_instantiation)) bar{}; // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+void __attribute__((unique_instantiation)) func() {} // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+// Usages that violate one of the conditions required conditions
+template <typename T>
+struct foo1 {};
+template struct __attribute__((unique_instantiation)) foo1<int>; // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template <typename T> T pi1 = T(3.1415926535897932385);
+template __attribute__((unique_instantiation)) float pi1<float>;  // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template <typename T>
+struct foo2 {};
+extern template struct foo2<int>;                                // expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2<int>; // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template <typename T>
+struct foo3 {};
+extern template struct __attribute__((unique_instantiation)) foo3<int>; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3<int>;                                       // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template <typename T>
+struct __attribute__((unique_instantiation)) foo4 {}; // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+template <typename T>
+struct foo5 {};
+extern template struct __attribute__((unique_instantiation)) foo5<int>; // expected-note{{previous explicit instantiation is here}}
+template struct foo5<int>;                                              // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template <typename T>
+struct foo6 {};
+extern template struct  __attribute__((unique_instantiation(16))) foo6<int>;    // expected-error{{'unique_instantiation' attribute takes no arguments}}
Index: test/CodeGenCXX/unique-instantiation.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/unique-instantiation.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang -std=c++14 -emit-llvm -c -S -o - %s | FileCheck %s
+
+// CHECK: @_Z2piIfE = global float
+// CHECK-NOT: @_Z2piIfE = weak_odr global float
+template <typename T> T pi = T(3.1415926535897932385);
+extern template __attribute__((unique_instantiation)) float pi<float>;
+template __attribute__((unique_instantiation)) float pi<float>;
+
+template <typename T>
+struct foo {
+  T x;
+  T getX() { return x; }
+  struct bar {
+    T y;
+    bar(T y) : y(y) {}
+  };
+};
+template <typename T>
+T bar();
+
+// CHECK: define i32 @_ZN3fooIiE4getXEv
+// CHECK: define void @_ZN3fooIiE3barC2Ei
+// CHECK-NOT: define weak_odr i32 @_ZN3fooIiE4getXEv
+// CHECK-NOT: define weak_odr void @_ZN3fooIiE3barC2Ei
+extern template struct __attribute__((unique_instantiation)) foo<int>;
+template struct __attribute__((unique_instantiation)) foo<int>;
+
+extern template __attribute__((unique_instantiation)) int bar<int>();
+
+template <typename T>
+T bar() {
+  return (T)0;
+}
+
+// CHECK: define i32 @_Z3barIiET_v()
+// CHECK-NOT: define weak_odr i32 @_Z3barIiET_v()
+template __attribute__((unique_instantiation)) int bar<int>();
+
+int footest() {
+  auto var = foo<int>{5};
+  auto var2 = foo<int>::bar{5};
+  auto x = bar<int>();
+  return var.getX();
+}
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -86,14 +86,14 @@
   return nullptr;
 }
 
-void Sema::FilterAcceptableTemplateNames(LookupResult &R, 
+void Sema::FilterAcceptableTemplateNames(LookupResult &R,
                                          bool AllowFunctionTemplates) {
   // The set of class templates we've already seen.
   llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates;
   LookupResult::Filter filter = R.makeFilter();
   while (filter.hasNext()) {
     NamedDecl *Orig = filter.next();
-    NamedDecl *Repl = isAcceptableTemplateName(Context, Orig, 
+    NamedDecl *Repl = isAcceptableTemplateName(Context, Orig,
                                                AllowFunctionTemplates);
     if (!Repl)
       filter.erase();
@@ -129,7 +129,7 @@
   for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I)
     if (isAcceptableTemplateName(Context, *I, AllowFunctionTemplates))
       return true;
-  
+
   return false;
 }
 
@@ -263,7 +263,7 @@
     assert((isDependent || !ObjectType->isIncompleteType() ||
             ObjectType->castAs<TagType>()->isBeingDefined()) &&
            "Caller should have completed object type");
-    
+
     // Template names cannot appear inside an Objective-C class or object type.
     if (ObjectType->isObjCObjectOrInterfaceType()) {
       Found.clear();
@@ -310,7 +310,7 @@
   } else {
     // Perform unqualified name lookup in the current scope.
     LookupName(Found, S);
-    
+
     if (!ObjectType.isNull())
       AllowFunctionTemplatesInLookup = false;
   }
@@ -755,7 +755,7 @@
                                      Depth, Position, IsParameterPack,
                                      Name, Params);
   Param->setAccess(AS_public);
-  
+
   // If the template template parameter has a name, then link the identifier
   // into the scope and lookup mechanisms.
   if (Name) {
@@ -882,8 +882,8 @@
     if (RequireCompleteDeclContext(SS, SemanticContext))
       return true;
 
-    // If we're adding a template to a dependent context, we may need to 
-    // rebuilding some of the types used within the template parameter list, 
+    // If we're adding a template to a dependent context, we may need to
+    // rebuilding some of the types used within the template parameter list,
     // now that we know what the current instantiation is.
     if (SemanticContext->isDependentContext()) {
       ContextRAII SavedContext(*this, SemanticContext);
@@ -1040,7 +1040,7 @@
         // definition, as part of error recovery?
         return true;
       }
-    }    
+    }
   } else if (PrevDecl && PrevDecl->isTemplateParameter()) {
     // Maybe we will complain about the shadowed template parameter.
     DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
@@ -1107,10 +1107,10 @@
                                 DeclarationName(Name), TemplateParams,
                                 NewClass, PrevClassTemplate);
   NewClass->setDescribedClassTemplate(NewTemplate);
-  
+
   if (ModulePrivateLoc.isValid())
     NewTemplate->setModulePrivate();
-  
+
   // Build the type for the class template declaration now.
   QualType T = NewTemplate->getInjectedClassNameSpecialization();
   T = Context.getInjectedClassNameType(NewClass, T);
@@ -1201,7 +1201,7 @@
     //   A default template-argument shall not be specified in a
     //   function template declaration or a function template
     //   definition [...]
-    //   If a friend function template declaration specifies a default 
+    //   If a friend function template declaration specifies a default
     //   template-argument, that declaration shall be a definition and shall be
     //   the only declaration of the function template in the translation unit.
     // (C++98/03 doesn't have this wording; see DR226).
@@ -1599,10 +1599,10 @@
         return NNSLoc.getTypeLoc().getSourceRange();
     } else
       break;
-    
+
     NNSLoc = NNSLoc.getPrefix();
   }
-  
+
   return SourceRange();
 }
 
@@ -1645,34 +1645,34 @@
     bool &IsExplicitSpecialization, bool &Invalid) {
   IsExplicitSpecialization = false;
   Invalid = false;
-  
+
   // The sequence of nested types to which we will match up the template
   // parameter lists. We first build this list by starting with the type named
   // by the nested-name-specifier and walking out until we run out of types.
   SmallVector<QualType, 4> NestedTypes;
   QualType T;
   if (SS.getScopeRep()) {
-    if (CXXRecordDecl *Record 
+    if (CXXRecordDecl *Record
               = dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS, true)))
       T = Context.getTypeDeclType(Record);
     else
       T = QualType(SS.getScopeRep()->getAsType(), 0);
   }
-  
+
   // If we found an explicit specialization that prevents us from needing
   // 'template<>' headers, this will be set to the location of that
   // explicit specialization.
   SourceLocation ExplicitSpecLoc;
-  
+
   while (!T.isNull()) {
     NestedTypes.push_back(T);
-    
+
     // Retrieve the parent of a record type.
     if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) {
       // If this type is an explicit specialization, we're done.
       if (ClassTemplateSpecializationDecl *Spec
           = dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
-        if (!isa<ClassTemplatePartialSpecializationDecl>(Spec) && 
+        if (!isa<ClassTemplatePartialSpecializationDecl>(Spec) &&
             Spec->getSpecializationKind() == TSK_ExplicitSpecialization) {
           ExplicitSpecLoc = Spec->getLocation();
           break;
@@ -1682,25 +1682,25 @@
         ExplicitSpecLoc = Record->getLocation();
         break;
       }
-      
+
       if (TypeDecl *Parent = dyn_cast<TypeDecl>(Record->getParent()))
         T = Context.getTypeDeclType(Parent);
       else
         T = QualType();
       continue;
-    } 
-    
+    }
+
     if (const TemplateSpecializationType *TST
                                      = T->getAs<TemplateSpecializationType>()) {
       if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) {
         if (TypeDecl *Parent = dyn_cast<TypeDecl>(Template->getDeclContext()))
           T = Context.getTypeDeclType(Parent);
         else
           T = QualType();
-        continue;        
+        continue;
       }
     }
-    
+
     // Look one step prior in a dependent template specialization type.
     if (const DependentTemplateSpecializationType *DependentTST
                           = T->getAs<DependentTemplateSpecializationType>()) {
@@ -1710,27 +1710,27 @@
         T = QualType();
       continue;
     }
-    
+
     // Look one step prior in a dependent name type.
     if (const DependentNameType *DependentName = T->getAs<DependentNameType>()){
       if (NestedNameSpecifier *NNS = DependentName->getQualifier())
         T = QualType(NNS->getAsType(), 0);
       else
         T = QualType();
       continue;
     }
-    
+
     // Retrieve the parent of an enumeration type.
     if (const EnumType *EnumT = T->getAs<EnumType>()) {
       // FIXME: Forward-declared enums require a TSK_ExplicitSpecialization
       // check here.
       EnumDecl *Enum = EnumT->getDecl();
-      
+
       // Get to the parent type.
       if (TypeDecl *Parent = dyn_cast<TypeDecl>(Enum->getParent()))
         T = Context.getTypeDeclType(Parent);
       else
-        T = QualType();      
+        T = QualType();
       continue;
     }
 
@@ -1782,21 +1782,21 @@
   for (unsigned TypeIdx = 0, NumTypes = NestedTypes.size(); TypeIdx != NumTypes;
        ++TypeIdx) {
     T = NestedTypes[TypeIdx];
-    
+
     // Whether we expect a 'template<>' header.
     bool NeedEmptyTemplateHeader = false;
 
     // Whether we expect a template header with parameters.
     bool NeedNonemptyTemplateHeader = false;
-    
+
     // For a dependent type, the set of template parameters that we
     // expect to see.
     TemplateParameterList *ExpectedTemplateParams = nullptr;
 
     // C++0x [temp.expl.spec]p15:
-    //   A member or a member template may be nested within many enclosing 
-    //   class templates. In an explicit specialization for such a member, the 
-    //   member declaration shall be preceded by a template<> for each 
+    //   A member or a member template may be nested within many enclosing
+    //   class templates. In an explicit specialization for such a member, the
+    //   member declaration shall be preceded by a template<> for each
     //   enclosing class template that is explicitly specialized.
     if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) {
       if (ClassTemplatePartialSpecializationDecl *Partial
@@ -1813,38 +1813,38 @@
                      = dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
         // C++0x [temp.expl.spec]p4:
         //   Members of an explicitly specialized class template are defined
-        //   in the same manner as members of normal classes, and not using 
-        //   the template<> syntax. 
+        //   in the same manner as members of normal classes, and not using
+        //   the template<> syntax.
         if (Spec->getSpecializationKind() != TSK_ExplicitSpecialization)
           NeedEmptyTemplateHeader = true;
         else
           continue;
       } else if (Record->getTemplateSpecializationKind()) {
-        if (Record->getTemplateSpecializationKind() 
+        if (Record->getTemplateSpecializationKind()
                                                 != TSK_ExplicitSpecialization &&
             TypeIdx == NumTypes - 1)
           IsExplicitSpecialization = true;
-        
+
         continue;
       }
     } else if (const TemplateSpecializationType *TST
                                      = T->getAs<TemplateSpecializationType>()) {
       if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) {
         ExpectedTemplateParams = Template->getTemplateParameters();
-        NeedNonemptyTemplateHeader = true;        
+        NeedNonemptyTemplateHeader = true;
       }
     } else if (T->getAs<DependentTemplateSpecializationType>()) {
       // FIXME:  We actually could/should check the template arguments here
       // against the corresponding template parameter list.
       NeedNonemptyTemplateHeader = false;
-    } 
-    
+    }
+
     // C++ [temp.expl.spec]p16:
-    //   In an explicit specialization declaration for a member of a class 
-    //   template or a member template that ap- pears in namespace scope, the 
-    //   member template and some of its enclosing class templates may remain 
-    //   unspecialized, except that the declaration shall not explicitly 
-    //   specialize a class member template if its en- closing class templates 
+    //   In an explicit specialization declaration for a member of a class
+    //   template or a member template that ap- pears in namespace scope, the
+    //   member template and some of its enclosing class templates may remain
+    //   unspecialized, except that the declaration shall not explicitly
+    //   specialize a class member template if its en- closing class templates
     //   are not explicitly specialized as well.
     if (ParamIdx < ParamLists.size()) {
       if (ParamLists[ParamIdx]->size() == 0) {
@@ -1854,7 +1854,7 @@
       } else
         SawNonEmptyTemplateParameterList = true;
     }
-    
+
     if (NeedEmptyTemplateHeader) {
       // If we're on the last of the types, and we need a 'template<>' header
       // here, then it's an explicit specialization.
@@ -1864,7 +1864,7 @@
       if (ParamIdx < ParamLists.size()) {
         if (ParamLists[ParamIdx]->size() > 0) {
           // The header has template parameters when it shouldn't. Complain.
-          Diag(ParamLists[ParamIdx]->getTemplateLoc(), 
+          Diag(ParamLists[ParamIdx]->getTemplateLoc(),
                diag::err_template_param_list_matches_nontemplate)
             << T
             << SourceRange(ParamLists[ParamIdx]->getLAngleLoc(),
@@ -1896,7 +1896,7 @@
         if (ParamIdx < ParamLists.size() &&
             DependsOnTemplateParameters(T, ParamLists[ParamIdx]))
           ExpectedTemplateParams = nullptr;
-        else 
+        else
           continue;
       }
 
@@ -1912,11 +1912,11 @@
             CheckTemplateParameterList(ParamLists[ParamIdx], nullptr,
                                        TPC_ClassTemplateMember))
           Invalid = true;
-        
+
         ++ParamIdx;
         continue;
       }
-      
+
       Diag(DeclLoc, diag::err_template_spec_needs_template_parameters)
         << T
         << getRangeOfTypeInNestedNameSpecifier(Context, T, SS);
@@ -1966,23 +1966,23 @@
     // not required, and there were any 'template<>' headers, note where the
     // specialization occurred.
     if (ExplicitSpecLoc.isValid() && HasAnyExplicitSpecHeader)
-      Diag(ExplicitSpecLoc, 
+      Diag(ExplicitSpecLoc,
            diag::note_explicit_template_spec_does_not_need_header)
         << NestedTypes.back();
-    
+
     // We have a template parameter list with no corresponding scope, which
     // means that the resulting template declaration can't be instantiated
     // properly (we'll end up with dependent nodes when we shouldn't).
     if (!AllExplicitSpecHeaders)
       Invalid = true;
   }
 
   // C++ [temp.expl.spec]p16:
-  //   In an explicit specialization declaration for a member of a class 
-  //   template or a member template that ap- pears in namespace scope, the 
-  //   member template and some of its enclosing class templates may remain 
-  //   unspecialized, except that the declaration shall not explicitly 
-  //   specialize a class member template if its en- closing class templates 
+  //   In an explicit specialization declaration for a member of a class
+  //   template or a member template that ap- pears in namespace scope, the
+  //   member template and some of its enclosing class templates may remain
+  //   unspecialized, except that the declaration shall not explicitly
+  //   specialize a class member template if its en- closing class templates
   //   are not explicitly specialized as well.
   if (ParamLists.back()->size() == 0 &&
       CheckExplicitSpecialization(ParamLists[ParamIdx]->getSourceRange(),
@@ -2007,14 +2007,14 @@
         << Template->getDeclName();
     return;
   }
-  
+
   if (OverloadedTemplateStorage *OST = Name.getAsOverloadedTemplate()) {
-    for (OverloadedTemplateStorage::iterator I = OST->begin(), 
+    for (OverloadedTemplateStorage::iterator I = OST->begin(),
                                           IEnd = OST->end();
          I != IEnd; ++I)
       Diag((*I)->getLocation(), diag::note_template_declared_here)
         << 0 << (*I)->getDeclName();
-    
+
     return;
   }
 }
@@ -2272,7 +2272,7 @@
       SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
     return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T));
   }
-  
+
   QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
 
   if (Result.isNull())
@@ -2299,7 +2299,7 @@
     ElabTL.setElaboratedKeywordLoc(SourceLocation());
     ElabTL.setQualifierLoc(SS.getWithLocInContext(Context));
   }
-  
+
   return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result));
 }
 
@@ -2314,23 +2314,23 @@
                                         ASTTemplateArgsPtr TemplateArgsIn,
                                         SourceLocation RAngleLoc) {
   TemplateName Template = TemplateD.get();
-  
+
   // Translate the parser's template argument list in our AST format.
   TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
   translateTemplateArguments(TemplateArgsIn, TemplateArgs);
-  
+
   // Determine the tag kind
   TagTypeKind TagKind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
   ElaboratedTypeKeyword Keyword
     = TypeWithKeyword::getKeywordForTagTypeKind(TagKind);
 
   if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
     QualType T = Context.getDependentTemplateSpecializationType(Keyword,
-                                                          DTN->getQualifier(), 
-                                                          DTN->getIdentifier(), 
+                                                          DTN->getQualifier(),
+                                                          DTN->getIdentifier(),
                                                                 TemplateArgs);
-    
-    // Build type-source information.    
+
+    // Build type-source information.
     TypeLocBuilder TLB;
     DependentTemplateSpecializationTypeLoc SpecTL
       = TLB.push<DependentTemplateSpecializationTypeLoc>(T);
@@ -2354,18 +2354,18 @@
     Diag(TemplateLoc, diag::err_tag_reference_non_tag) << 4;
     Diag(TAT->getLocation(), diag::note_declared_at);
   }
-  
+
   QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs);
   if (Result.isNull())
     return TypeResult(true);
-  
+
   // Check the tag kind
   if (const RecordType *RT = Result->getAs<RecordType>()) {
     RecordDecl *D = RT->getDecl();
-    
+
     IdentifierInfo *Id = D->getIdentifier();
     assert(Id && "templated class must have an identifier");
-    
+
     if (!isAcceptableTagRedeclaration(D, TagKind, TUK == TUK_Definition,
                                       TagLoc, Id)) {
       Diag(TagLoc, diag::err_use_with_wrong_tag)
@@ -3163,7 +3163,7 @@
 
   // Add the converted template type argument.
   ArgType = Context.getCanonicalType(ArgType);
-  
+
   // Objective-C ARC:
   //   If an explicitly-specified template argument type is a lifetime type
   //   with no lifetime qualifier, the __strong lifetime qualifier is inferred.
@@ -3174,7 +3174,7 @@
     Qs.setObjCLifetime(Qualifiers::OCL_Strong);
     ArgType = Context.getQualifiedType(ArgType, Qs);
   }
-  
+
   Converted.push_back(TemplateArgument(ArgType));
   return false;
 }
@@ -3307,7 +3307,7 @@
 /// \param Converted the list of template arguments provided for template
 /// parameters that precede \p Param in the template parameter list.
 ///
-/// \param QualifierLoc Will be set to the nested-name-specifier (with 
+/// \param QualifierLoc Will be set to the nested-name-specifier (with
 /// source-location information) that precedes the template name.
 ///
 /// \returns the substituted template argument, or NULL if an error occurred.
@@ -3659,7 +3659,7 @@
   return false;
 }
 
-/// \brief Diagnose an arity mismatch in the 
+/// \brief Diagnose an arity mismatch in the
 static bool diagnoseArityMismatch(Sema &S, TemplateDecl *Template,
                                   SourceLocation TemplateLoc,
                                   TemplateArgumentListInfo &TemplateArgs) {
@@ -3669,7 +3669,7 @@
 
   SourceRange Range;
   if (NumArgs > NumParams)
-    Range = SourceRange(TemplateArgs[NumParams].getLocation(), 
+    Range = SourceRange(TemplateArgs[NumParams].getLocation(),
                         TemplateArgs.getRAngleLoc());
   S.Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
     << (NumArgs > NumParams)
@@ -4288,43 +4288,43 @@
 
   if (!S.getLangOpts().CPlusPlus11)
     return NPV_NotNullPointer;
-  
+
   // Determine whether we have a constant expression.
   ExprResult ArgRV = S.DefaultFunctionArrayConversion(Arg);
   if (ArgRV.isInvalid())
     return NPV_Error;
   Arg = ArgRV.get();
-  
+
   Expr::EvalResult EvalResult;
   SmallVector<PartialDiagnosticAt, 8> Notes;
   EvalResult.Diag = &Notes;
   if (!Arg->EvaluateAsRValue(EvalResult, S.Context) ||
       EvalResult.HasSideEffects) {
     SourceLocation DiagLoc = Arg->getExprLoc();
-    
+
     // If our only note is the usual "invalid subexpression" note, just point
     // the caret at its location rather than producing an essentially
     // redundant note.
     if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
         diag::note_invalid_subexpr_in_const_expr) {
       DiagLoc = Notes[0].first;
       Notes.clear();
     }
-    
+
     S.Diag(DiagLoc, diag::err_template_arg_not_address_constant)
       << Arg->getType() << Arg->getSourceRange();
     for (unsigned I = 0, N = Notes.size(); I != N; ++I)
       S.Diag(Notes[I].first, Notes[I].second);
-    
+
     S.Diag(Param->getLocation(), diag::note_template_param_here);
     return NPV_Error;
   }
-  
+
   // C++11 [temp.arg.nontype]p1:
   //   - an address constant expression of type std::nullptr_t
   if (Arg->getType()->isNullPtrType())
     return NPV_NullPointer;
-  
+
   //   - a constant expression that evaluates to a null pointer value (4.10); or
   //   - a constant expression that evaluates to a null member pointer value
   //     (4.11); or
@@ -4337,7 +4337,7 @@
         S.IsQualificationConversion(Arg->getType(), ParamType, false,
                                      ObjCLifetimeConversion))
       return NPV_NullPointer;
-    
+
     // The types didn't match, but we know we got a null pointer; complain,
     // then recover as if the types were correct.
     S.Diag(Arg->getExprLoc(), diag::err_template_arg_wrongtype_null_constant)
@@ -4357,7 +4357,7 @@
     S.Diag(Param->getLocation(), diag::note_template_param_here);
     return NPV_NullPointer;
   }
-  
+
   // FIXME: If we ever want to support general, address-constant expressions
   // as non-type template arguments, we should return the ExprResult here to
   // be interpreted by the caller.
@@ -5068,7 +5068,7 @@
     } else if (!Arg->isValueDependent()) {
       class TmplArgICEDiagnoser : public VerifyICEDiagnoser {
         QualType T;
-        
+
       public:
         TmplArgICEDiagnoser(QualType T) : T(T) { }
 
@@ -5130,23 +5130,23 @@
       Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType());
     } else {
       llvm::APSInt OldValue = Value;
-      
+
       // Coerce the template argument's value to the value it will have
       // based on the template parameter's type.
       unsigned AllowedBits = Context.getTypeSize(IntegerType);
       if (Value.getBitWidth() != AllowedBits)
         Value = Value.extOrTrunc(AllowedBits);
       Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType());
-      
+
       // Complain if an unsigned parameter received a negative value.
       if (IntegerType->isUnsignedIntegerOrEnumerationType()
                && (OldValue.isSigned() && OldValue.isNegative())) {
         Diag(Arg->getLocStart(), diag::warn_template_arg_negative)
           << OldValue.toString(10) << Value.toString(10) << Param->getType()
           << Arg->getSourceRange();
         Diag(Param->getLocation(), diag::note_template_param_here);
       }
-      
+
       // Complain if we overflowed the template parameter's type.
       unsigned RequiredBits;
       if (IntegerType->isUnsignedIntegerOrEnumerationType())
@@ -5165,7 +5165,7 @@
     }
 
     Converted = TemplateArgument(Context, Value,
-                                 ParamType->isEnumeralType() 
+                                 ParamType->isEnumeralType()
                                    ? Context.getCanonicalType(ParamType)
                                    : IntegerType);
     return Arg;
@@ -5277,17 +5277,17 @@
       Converted = TemplateArgument(Arg);
       return Arg;
     }
-    
+
     switch (isNullPointerValueTemplateArgument(*this, Param, ParamType, Arg)) {
     case NPV_NotNullPointer:
       Diag(Arg->getExprLoc(), diag::err_template_arg_not_convertible)
         << Arg->getType() << ParamType;
       Diag(Param->getLocation(), diag::note_template_param_here);
       return ExprError();
-      
+
     case NPV_Error:
       return ExprError();
-      
+
     case NPV_NullPointer:
       Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null);
       Converted = TemplateArgument(Context.getCanonicalType(ParamType),
@@ -5531,7 +5531,7 @@
                                Context.getTrivialTypeSourceInfo(OrigT, Loc),
                                Loc, Loc);
   }
-  
+
   return E;
 }
 
@@ -5910,7 +5910,7 @@
       << Specialized;
     return true;
   }
-  
+
   // C++ [temp.class.spec]p6:
   //   A class template partial specialization may be declared or redeclared
   //   in any namespace scope in which its definition may be defined (14.5.1
@@ -6489,7 +6489,7 @@
     Diag(Specialization->getLocation(), diag::err_module_private_specialization)
       << (isPartialSpecialization? 1 : 0)
       << FixItHint::CreateRemoval(ModulePrivateLoc);
-  
+
   // Build the fully-sugared type for this class template
   // specialization as the user wrote in the specialization
   // itself. This means that we'll pretty-print the type retrieved
@@ -6950,7 +6950,7 @@
                                          SpecInfo->getPointOfInstantiation(),
                                              HasNoEffect))
     return true;
-  
+
   // Mark the prior declaration as an explicit specialization, so that later
   // clients know that this is an explicit specialization.
   if (!isFriend) {
@@ -7400,20 +7400,22 @@
   Specialization->setExternLoc(ExternLoc);
   Specialization->setTemplateKeywordLoc(TemplateLoc);
   Specialization->setRBraceLoc(SourceLocation());
+  Specialization->setTemplateSpecializationKind(TSK);
 
   if (Attr)
     ProcessDeclAttributeList(S, Specialization, Attr);
 
+  if (PrevDecl)
+    mergeDeclAttributes(Specialization, PrevDecl);
+
   // Add the explicit instantiation into its lexical context. However,
   // since explicit instantiations are never found by name lookup, we
   // just put it into the declaration context directly.
   Specialization->setLexicalDeclContext(CurContext);
   CurContext->addDecl(Specialization);
 
   // Syntax is now OK, so return if it has no other effect on semantics.
   if (HasNoEffect) {
-    // Set the template specialization kind.
-    Specialization->setTemplateSpecializationKind(TSK);
     return Specialization;
   }
 
@@ -7467,14 +7469,7 @@
       }
     }
 
-    // Set the template specialization kind. Make sure it is set before
-    // instantiating the members which will trigger ASTConsumer callbacks.
-    Specialization->setTemplateSpecializationKind(TSK);
     InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
-  } else {
-
-    // Set the template specialization kind.
-    Specialization->setTemplateSpecializationKind(TSK);
   }
 
   return Specialization;
@@ -7604,6 +7599,27 @@
   return TagD;
 }
 
+static void DiagnoseUniqueInstantiation(
+  Sema &S,
+  Declarator &D, TemplateSpecializationKind TSK,
+  bool HadDeclaration,
+  UniqueInstantiationAttr *NewUniqueInstantiation,
+  UniqueInstantiationAttr *OldUniqueInstantiation,
+  clang::SourceLocation OldUniqueInstantiationLoc)
+{
+  if (NewUniqueInstantiation) {
+    if (TSK == TSK_ExplicitInstantiationDefinition && !HadDeclaration)
+      S.Diag(NewUniqueInstantiation->getLocation(),
+           diag::err_unique_instantiation_no_declaration);
+    else if (HadDeclaration && !OldUniqueInstantiation)
+      S.Diag(NewUniqueInstantiation->getLocation(),
+           diag::err_unique_instantiation_not_previous);
+  } else if (OldUniqueInstantiation) {
+    S.Diag(D.getIdentifierLoc(), diag::err_unique_instantiation_not_previous);
+    S.Diag(OldUniqueInstantiationLoc, diag::note_previous_explicit_instantiation);
+  }
+}
+
 DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
                                             SourceLocation ExternLoc,
                                             SourceLocation TemplateLoc,
@@ -7635,18 +7651,18 @@
     return true;
 
   // C++ [dcl.stc]p1:
-  //   A storage-class-specifier shall not be specified in [...] an explicit 
+  //   A storage-class-specifier shall not be specified in [...] an explicit
   //   instantiation (14.7.2) directive.
   if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
     Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_of_typedef)
       << Name;
     return true;
-  } else if (D.getDeclSpec().getStorageClassSpec() 
+  } else if (D.getDeclSpec().getStorageClassSpec()
                                                 != DeclSpec::SCS_unspecified) {
     // Complain about then remove the storage class specifier.
     Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_storage_class)
       << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
-    
+
     D.getMutableDeclSpec().ClearStorageClassSpecs();
   }
 
@@ -7678,6 +7694,11 @@
   LookupResult Previous(*this, NameInfo, LookupOrdinaryName);
   LookupParsedName(Previous, S, &D.getCXXScopeSpec());
 
+  // For diagnosing incorrect uses of unique_instantiation
+  UniqueInstantiationAttr *OldUniqueInstantiation = nullptr;
+  SourceLocation OldUniqueInstantiationLoc;
+  bool HadDeclaration;
+
   if (!R->isFunctionType()) {
     // C++ [temp.explicit]p1:
     //   A [...] static data member of a class template can be explicitly
@@ -7750,6 +7771,15 @@
       // Ignore access control bits, we don't need them for redeclaration
       // checking.
       Prev = cast<VarDecl>(Res.get());
+
+      HadDeclaration = Prev->getTemplateSpecializationKind() ==
+                              TSK_ExplicitInstantiationDeclaration;
+      OldUniqueInstantiation =
+          Prev->getAttr<UniqueInstantiationAttr>();
+      if (OldUniqueInstantiation) {
+        OldUniqueInstantiationLoc = OldUniqueInstantiation->getLocation();
+        Prev->dropAttr<UniqueInstantiationAttr>();
+      }
     }
 
     // C++0x [temp.explicit]p2:
@@ -7782,10 +7812,13 @@
       // Instantiate static data member or variable template.
 
       Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+      // Merge attributes.
+      if (AttributeList *Attr = D.getDeclSpec().getAttributes().getList())
+        ProcessDeclAttributeList(S, Prev, Attr);
       if (PrevTemplate) {
-        // Merge attributes.
-        if (AttributeList *Attr = D.getDeclSpec().getAttributes().getList())
-          ProcessDeclAttributeList(S, Prev, Attr);
+        DiagnoseUniqueInstantiation(*this, D,TSK,HadDeclaration,
+          Prev->getAttr<UniqueInstantiationAttr>(), OldUniqueInstantiation,
+          OldUniqueInstantiationLoc);
       }
       if (TSK == TSK_ExplicitInstantiationDefinition)
         InstantiateVariableDefinition(D.getIdentifierLoc(), Prev);
@@ -7925,11 +7958,23 @@
       return (Decl*) nullptr;
   }
 
+  HadDeclaration = Specialization->getTemplateSpecializationKind() ==
+                        TSK_ExplicitInstantiationDeclaration;
+  OldUniqueInstantiation = Specialization->getAttr<UniqueInstantiationAttr>();
+  if (OldUniqueInstantiation) {
+    OldUniqueInstantiationLoc = OldUniqueInstantiation->getLocation();
+    Specialization->dropAttr<UniqueInstantiationAttr>();
+  }
+
   Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
   AttributeList *Attr = D.getDeclSpec().getAttributes().getList();
   if (Attr)
     ProcessDeclAttributeList(S, Specialization, Attr);
 
+  DiagnoseUniqueInstantiation(*this, D,TSK,HadDeclaration,
+    Specialization->getAttr<UniqueInstantiationAttr>(), OldUniqueInstantiation,
+    OldUniqueInstantiationLoc);
+
   if (Specialization->isDefined()) {
     // Let the ASTConsumer know that this function has been explicitly
     // instantiated now, and its linkage might have changed.
@@ -7984,7 +8029,7 @@
   // Create the resulting type.
   ElaboratedTypeKeyword Kwd = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
   QualType Result = Context.getDependentNameType(Kwd, NNS, Name);
-  
+
   // Create type-source location information for this type.
   TypeLocBuilder TLB;
   DependentNameTypeLoc TL = TLB.push<DependentNameTypeLoc>(Result);
@@ -8000,7 +8045,7 @@
                         SourceLocation IdLoc) {
   if (SS.isInvalid())
     return true;
-  
+
   if (TypenameLoc.isValid() && S && !S->getTemplateParamParent())
     Diag(TypenameLoc,
          getLangOpts().CPlusPlus11 ?
@@ -8046,11 +8091,11 @@
            diag::warn_cxx98_compat_typename_outside_of_template :
            diag::ext_typename_outside_of_template)
       << FixItHint::CreateRemoval(TypenameLoc);
-  
+
   // Translate the parser's template argument list in our AST format.
   TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc);
   translateTemplateArguments(TemplateArgsIn, TemplateArgs);
-  
+
   TemplateName Template = TemplateIn.get();
   if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) {
     // Construct a dependent template specialization type.
@@ -8060,10 +8105,10 @@
                                                           DTN->getQualifier(),
                                                           DTN->getIdentifier(),
                                                                 TemplateArgs);
-    
+
     // Create source-location information for this type.
     TypeLocBuilder Builder;
-    DependentTemplateSpecializationTypeLoc SpecTL 
+    DependentTemplateSpecializationTypeLoc SpecTL
     = Builder.push<DependentTemplateSpecializationTypeLoc>(T);
     SpecTL.setElaboratedKeywordLoc(TypenameLoc);
     SpecTL.setQualifierLoc(SS.getWithLocInContext(Context));
@@ -8075,11 +8120,11 @@
       SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
     return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
   }
-  
+
   QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs);
   if (T.isNull())
     return true;
-  
+
   // Provide source-location information for the template specialization type.
   TypeLocBuilder Builder;
   TemplateSpecializationTypeLoc SpecTL
@@ -8090,12 +8135,12 @@
   SpecTL.setRAngleLoc(RAngleLoc);
   for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
     SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo());
-  
+
   T = Context.getElaboratedType(ETK_Typename, SS.getScopeRep(), T);
   ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T);
   TL.setElaboratedKeywordLoc(TypenameLoc);
   TL.setQualifierLoc(SS.getWithLocInContext(Context));
-  
+
   TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T);
   return CreateParsedType(T, TSI);
 }
@@ -8140,9 +8185,9 @@
 /// \brief Build the type that describes a C++ typename specifier,
 /// e.g., "typename T::type".
 QualType
-Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, 
+Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
                         SourceLocation KeywordLoc,
-                        NestedNameSpecifierLoc QualifierLoc, 
+                        NestedNameSpecifierLoc QualifierLoc,
                         const IdentifierInfo &II,
                         SourceLocation IILoc) {
   CXXScopeSpec SS;
@@ -8153,8 +8198,8 @@
     // If the nested-name-specifier is dependent and couldn't be
     // resolved to a type, build a typename type.
     assert(QualifierLoc.getNestedNameSpecifier()->isDependent());
-    return Context.getDependentNameType(Keyword, 
-                                        QualifierLoc.getNestedNameSpecifier(), 
+    return Context.getDependentNameType(Keyword,
+                                        QualifierLoc.getNestedNameSpecifier(),
                                         &II);
   }
 
@@ -8206,16 +8251,16 @@
 
   case LookupResult::NotFoundInCurrentInstantiation:
     // Okay, it's a member of an unknown instantiation.
-    return Context.getDependentNameType(Keyword, 
-                                        QualifierLoc.getNestedNameSpecifier(), 
+    return Context.getDependentNameType(Keyword,
+                                        QualifierLoc.getNestedNameSpecifier(),
                                         &II);
 
   case LookupResult::Found:
     if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) {
       // We found a type. Build an ElaboratedType, since the
       // typename-specifier was just sugar.
       MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false);
-      return Context.getElaboratedType(ETK_Typename, 
+      return Context.getElaboratedType(ETK_Typename,
                                        QualifierLoc.getNestedNameSpecifier(),
                                        Context.getTypeDeclType(Type));
     }
@@ -8282,7 +8327,7 @@
       this->Loc = Loc;
       this->Entity = Entity;
     }
-      
+
     ExprResult TransformLambdaExpr(LambdaExpr *E) {
       // Lambdas never need to be transformed.
       return E;
@@ -8333,15 +8378,15 @@
 }
 
 bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) {
-  if (SS.isInvalid()) 
+  if (SS.isInvalid())
     return true;
 
   NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
   CurrentInstantiationRebuilder Rebuilder(*this, SS.getRange().getBegin(),
                                           DeclarationName());
-  NestedNameSpecifierLoc Rebuilt 
+  NestedNameSpecifierLoc Rebuilt
     = Rebuilder.TransformNestedNameSpecifierLoc(QualifierLoc);
-  if (!Rebuilt) 
+  if (!Rebuilt)
     return true;
 
   SS.Adopt(Rebuilt);
@@ -8354,36 +8399,36 @@
                                                TemplateParameterList *Params) {
   for (unsigned I = 0, N = Params->size(); I != N; ++I) {
     Decl *Param = Params->getParam(I);
-    
+
     // There is nothing to rebuild in a type parameter.
     if (isa<TemplateTypeParmDecl>(Param))
       continue;
-    
+
     // Rebuild the template parameter list of a template template parameter.
-    if (TemplateTemplateParmDecl *TTP 
+    if (TemplateTemplateParmDecl *TTP
         = dyn_cast<TemplateTemplateParmDecl>(Param)) {
       if (RebuildTemplateParamsInCurrentInstantiation(
             TTP->getTemplateParameters()))
         return true;
-      
+
       continue;
     }
-    
+
     // Rebuild the type of a non-type template parameter.
     NonTypeTemplateParmDecl *NTTP = cast<NonTypeTemplateParmDecl>(Param);
-    TypeSourceInfo *NewTSI 
-      = RebuildTypeInCurrentInstantiation(NTTP->getTypeSourceInfo(), 
-                                          NTTP->getLocation(), 
+    TypeSourceInfo *NewTSI
+      = RebuildTypeInCurrentInstantiation(NTTP->getTypeSourceInfo(),
+                                          NTTP->getLocation(),
                                           NTTP->getDeclName());
     if (!NewTSI)
       return true;
-    
+
     if (NewTSI != NTTP->getTypeSourceInfo()) {
       NTTP->setTypeSourceInfo(NewTSI);
       NTTP->setType(NewTSI->getType());
     }
   }
-  
+
   return false;
 }
 
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -862,7 +862,7 @@
         << Attr.getName() << AANT_ArgumentIdentifier;
     return;
   }
-  
+
   D->addAttr(::new (S.Context)
              ConsumableAttr(Attr.getRange(), S.Context, DefaultState,
                             Attr.getAttributeSpellingListIndex()));
@@ -873,32 +873,32 @@
                                         const AttributeList &Attr) {
   ASTContext &CurrContext = S.getASTContext();
   QualType ThisType = MD->getThisType(CurrContext)->getPointeeType();
-  
+
   if (const CXXRecordDecl *RD = ThisType->getAsCXXRecordDecl()) {
     if (!RD->hasAttr<ConsumableAttr>()) {
       S.Diag(Attr.getLoc(), diag::warn_attr_on_unconsumable_class) <<
         RD->getNameAsString();
-      
+
       return false;
     }
   }
-  
+
   return true;
 }
 
 
 static void handleCallableWhenAttr(Sema &S, Decl *D,
                                    const AttributeList &Attr) {
   if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
     return;
-  
+
   if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
     return;
-  
+
   SmallVector<CallableWhenAttr::ConsumedState, 3> States;
   for (unsigned ArgIndex = 0; ArgIndex < Attr.getNumArgs(); ++ArgIndex) {
     CallableWhenAttr::ConsumedState CallableState;
-    
+
     StringRef StateString;
     SourceLocation Loc;
     if (Attr.isArgIdent(ArgIndex)) {
@@ -916,10 +916,10 @@
         << Attr.getName() << StateString;
       return;
     }
-      
+
     States.push_back(CallableState);
   }
-  
+
   D->addAttr(::new (S.Context)
              CallableWhenAttr(Attr.getRange(), S.Context, States.data(),
                States.size(), Attr.getAttributeSpellingListIndex()));
@@ -929,7 +929,7 @@
 static void handleParamTypestateAttr(Sema &S, Decl *D,
                                     const AttributeList &Attr) {
   ParamTypestateAttr::ConsumedState ParamState;
-  
+
   if (Attr.isArgIdent(0)) {
     IdentifierLoc *Ident = Attr.getArgAsIdent(0);
     StringRef StateString = Ident->Ident->getName();
@@ -945,7 +945,7 @@
       Attr.getName() << AANT_ArgumentIdentifier;
     return;
   }
-  
+
   // FIXME: This check is currently being done in the analysis.  It can be
   //        enabled here only after the parser propagates attributes at
   //        template specialization definition, not declaration.
@@ -957,7 +957,7 @@
   //      ReturnType.getAsString();
   //    return;
   //}
-  
+
   D->addAttr(::new (S.Context)
              ParamTypestateAttr(Attr.getRange(), S.Context, ParamState,
                                 Attr.getAttributeSpellingListIndex()));
@@ -967,7 +967,7 @@
 static void handleReturnTypestateAttr(Sema &S, Decl *D,
                                       const AttributeList &Attr) {
   ReturnTypestateAttr::ConsumedState ReturnState;
-  
+
   if (Attr.isArgIdent(0)) {
     IdentifierLoc *IL = Attr.getArgAsIdent(0);
     if (!ReturnTypestateAttr::ConvertStrToConsumedState(IL->Ident->getName(),
@@ -981,7 +981,7 @@
       Attr.getName() << AANT_ArgumentIdentifier;
     return;
   }
-  
+
   // FIXME: This check is currently being done in the analysis.  It can be
   //        enabled here only after the parser propagates attributes at
   //        template specialization definition, not declaration.
@@ -993,9 +993,9 @@
   //} else if (const CXXConstructorDecl *Constructor =
   //             dyn_cast<CXXConstructorDecl>(D)) {
   //  ReturnType = Constructor->getThisType(S.getASTContext())->getPointeeType();
-  //  
+  //
   //} else {
-  //  
+  //
   //  ReturnType = cast<FunctionDecl>(D)->getCallResultType();
   //}
   //
@@ -1006,7 +1006,7 @@
   //      ReturnType.getAsString();
   //    return;
   //}
-  
+
   D->addAttr(::new (S.Context)
              ReturnTypestateAttr(Attr.getRange(), S.Context, ReturnState,
                                  Attr.getAttributeSpellingListIndex()));
@@ -1016,7 +1016,7 @@
 static void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
   if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
     return;
-  
+
   SetTypestateAttr::ConsumedState NewState;
   if (Attr.isArgIdent(0)) {
     IdentifierLoc *Ident = Attr.getArgAsIdent(0);
@@ -1031,7 +1031,7 @@
       Attr.getName() << AANT_ArgumentIdentifier;
     return;
   }
-  
+
   D->addAttr(::new (S.Context)
              SetTypestateAttr(Attr.getRange(), S.Context, NewState,
                               Attr.getAttributeSpellingListIndex()));
@@ -1041,8 +1041,8 @@
                                     const AttributeList &Attr) {
   if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
     return;
-  
-  TestTypestateAttr::ConsumedState TestState;  
+
+  TestTypestateAttr::ConsumedState TestState;
   if (Attr.isArgIdent(0)) {
     IdentifierLoc *Ident = Attr.getArgAsIdent(0);
     StringRef Param = Ident->Ident->getName();
@@ -1056,7 +1056,7 @@
       Attr.getName() << AANT_ArgumentIdentifier;
     return;
   }
-  
+
   D->addAttr(::new (S.Context)
              TestTypestateAttr(Attr.getRange(), S.Context, TestState,
                                 Attr.getAttributeSpellingListIndex()));
@@ -1655,7 +1655,7 @@
 
 static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D,
                                        const AttributeList &Attr) {
-  
+
   // The checking path for 'noreturn' and 'analyzer_noreturn' are different
   // because 'analyzer_noreturn' does not impact the type.
   if (!isFunctionOrMethodOrBlock(D)) {
@@ -1669,7 +1669,7 @@
       return;
     }
   }
-  
+
   D->addAttr(::new (S.Context)
              AnalyzerNoReturnAttr(Attr.getRange(), S.Context,
                                   Attr.getAttributeSpellingListIndex()));
@@ -1679,20 +1679,20 @@
 static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) {
 /*
   Returning a Vector Class in Registers
-  
-  According to the PPU ABI specifications, a class with a single member of 
+
+  According to the PPU ABI specifications, a class with a single member of
   vector type is returned in memory when used as the return value of a function.
   This results in inefficient code when implementing vector classes. To return
   the value in a single vector register, add the vecreturn attribute to the
   class definition. This attribute is also applicable to struct types.
-  
+
   Example:
-  
+
   struct Vector
   {
     __vector float xyzw;
   } __attribute__((vecreturn));
-  
+
   Vector Add(Vector lhs, Vector rhs)
   {
     Vector result;
@@ -2053,7 +2053,7 @@
     return;
   IdentifierLoc *Platform = Attr.getArgAsIdent(0);
   unsigned Index = Attr.getAttributeSpellingListIndex();
-  
+
   IdentifierInfo *II = Platform->Ident;
   if (AvailabilityAttr::getPrettyPlatformName(II->getName()).empty())
     S.Diag(Platform->Loc, diag::warn_availability_unknown_platform)
@@ -2214,7 +2214,7 @@
       << Attr.getName() << TypeStr;
     return;
   }
-  
+
   // Complain about attempts to use protected visibility on targets
   // (like Darwin) that don't support it.
   if (type == VisibilityAttr::Protected &&
@@ -2287,7 +2287,7 @@
     //  @property (retain, nonatomic) struct Bork *Q __attribute__((NSObject));
     //
     // In this case it follows tradition and suppresses an error in the above
-    // case.    
+    // case.
     S.Diag(D->getLocation(), diag::warn_nsobject_attribute);
   }
   D->addAttr(::new (S.Context)
@@ -2435,8 +2435,8 @@
       << Attr.getName() << 1;
       return;
     }
-  
-  D->addAttr(::new (S.Context) 
+
+  D->addAttr(::new (S.Context)
              WarnUnusedResultAttr(Attr.getRange(), S.Context,
                                   Attr.getAttributeSpellingListIndex()));
 }
@@ -2736,7 +2736,7 @@
     S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
     return;
   }
-  
+
   if (S.getCurFunctionOrMethodDecl()) {
     S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr);
     Attr.setInvalid();
@@ -2814,10 +2814,10 @@
 
   // Check for supported formats.
   FormatAttrKind Kind = getFormatAttrKind(Format);
-  
+
   if (Kind == IgnoredFormat)
     return;
-  
+
   if (Kind == InvalidFormat) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)
       << Attr.getName() << II->getName();
@@ -2995,7 +2995,7 @@
     if (I->getAnnotation() == Str)
       return;
   }
-  
+
   D->addAttr(::new (S.Context)
              AnnotateAttr(Attr.getRange(), S.Context, Str,
                           Attr.getAttributeSpellingListIndex()));
@@ -3701,7 +3701,7 @@
   }
 }
 
-bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, 
+bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC,
                                 const FunctionDecl *FD) {
   if (attr.isInvalid())
     return true;
@@ -3760,7 +3760,7 @@
     // method calling convention.
     TargetInfo::CallingConvMethodType MT = TargetInfo::CCMT_Unknown;
     if (FD)
-      MT = FD->isCXXInstanceMember() ? TargetInfo::CCMT_Member : 
+      MT = FD->isCXXInstanceMember() ? TargetInfo::CCMT_Member :
                                     TargetInfo::CCMT_NonMember;
     CC = TI.getDefaultCallingConv(MT);
   }
@@ -3870,7 +3870,7 @@
       << Attr.getName() << /* arg num = */ 1 << AANT_ArgumentIdentifier;
     return;
   }
-  
+
   if (!checkAttributeNumArgs(S, Attr, 3))
     return;
 
@@ -3915,7 +3915,7 @@
       << Attr.getName() << 1 << AANT_ArgumentIdentifier;
     return;
   }
-  
+
   if (!checkAttributeNumArgs(S, Attr, 1))
     return;
 
@@ -3948,13 +3948,13 @@
 }
 
 static bool isValidSubjectOfNSAttribute(Sema &S, QualType type) {
-  return type->isDependentType() || 
-         type->isObjCObjectPointerType() || 
+  return type->isDependentType() ||
+         type->isObjCObjectPointerType() ||
          S.Context.isObjCNSObjectType(type);
 }
 static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) {
-  return type->isDependentType() || 
-         type->isPointerType() || 
+  return type->isDependentType() ||
+         type->isPointerType() ||
          isValidSubjectOfNSAttribute(S, type);
 }
 
@@ -4036,7 +4036,7 @@
     typeOK = isValidSubjectOfNSReturnsRetainedAttribute(returnType);
     cf = false;
     break;
-      
+
   case AttributeList::AT_NSReturnsAutoreleased:
   case AttributeList::AT_NSReturnsNotRetained:
     typeOK = isValidSubjectOfNSAttribute(S, returnType);
@@ -4103,7 +4103,7 @@
                                               const AttributeList &attr) {
   const int EP_ObjCMethod = 1;
   const int EP_ObjCProperty = 2;
-  
+
   SourceLocation loc = attr.getLoc();
   QualType resultType;
   if (isa<ObjCMethodDecl>(D))
@@ -4130,7 +4130,7 @@
 static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
                                         const AttributeList &attr) {
   ObjCMethodDecl *method = cast<ObjCMethodDecl>(D);
-  
+
   DeclContext *DC = method->getDeclContext();
   if (const ObjCProtocolDecl *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
     S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
@@ -4143,7 +4143,7 @@
     << attr.getName() << 1;
     return;
   }
-  
+
   method->addAttr(::new (S.Context)
                   ObjCRequiresSuperAttr(attr.getRange(), S.Context,
                                         attr.getAttributeSpellingListIndex()));
@@ -4195,7 +4195,7 @@
       return;
     }
   }
-  
+
   D->addAttr(::new (S.Context)
              ObjCBridgeAttr(Attr.getRange(), S.Context, Parm->Ident,
                            Attr.getAttributeSpellingListIndex()));
@@ -4209,7 +4209,7 @@
     S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
     return;
   }
-  
+
   D->addAttr(::new (S.Context)
              ObjCBridgeMutableAttr(Attr.getRange(), S.Context, Parm->Ident,
                             Attr.getAttributeSpellingListIndex()));
@@ -4458,7 +4458,7 @@
   if (!Attr.isArgExpr(0)) {
     S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
       << AANT_ArgumentIntegerConstant;
-    return;    
+    return;
   }
 
   // FIXME: Check for decl - it should be void ()(void).
@@ -4865,6 +4865,38 @@
     D->addAttr(Internal);
 }
 
+static void handleUniqueInstantiation(Sema &S, Decl *D,
+                                      const AttributeList &Attr) {
+  if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+    // If this is an explicit instantiation definition. Check that it was
+    // preceeded by an ExplicitInstantiationDeclaration. Note, this
+    // requirement encourages a programming style that uses unique explicit
+    // instantiation declarations (typically in a header) to suppress
+    // implicit instantiations of a template or its members, so that the
+    // unique explicit instantiation definition of that template or its members
+    // is unique.
+    if (CTSD->getSpecializationKind() == TSK_ExplicitInstantiationDefinition) {
+      if (!CTSD->getPreviousDecl())
+        S.Diag(Attr.getLoc(), diag::err_unique_instantiation_no_declaration);
+    }
+    return handleSimpleAttribute<UniqueInstantiationAttr>(S, D, Attr);
+  } else if (auto *FD = dyn_cast<FunctionDecl>(D)) {
+    if (FD->getTemplateSpecializationKind() ==
+            TSK_ExplicitInstantiationDefinition ||
+        FD->getTemplateSpecializationKind() ==
+            TSK_ExplicitInstantiationDeclaration)
+      return handleSimpleAttribute<UniqueInstantiationAttr>(S, D, Attr);
+  } else if (auto *VD = dyn_cast<VarDecl>(D)) {
+    if (VD->getTemplateSpecializationKind() ==
+            TSK_ExplicitInstantiationDefinition ||
+        VD->getTemplateSpecializationKind() ==
+            TSK_ExplicitInstantiationDeclaration)
+      return handleSimpleAttribute<UniqueInstantiationAttr>(S, D, Attr);
+  }
+  S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
+      << Attr.getName() << ExpectedExplicitInstantiation;
+}
+
 /// Handles semantic checking for features that are common to all attributes,
 /// such as checking whether a parameter was properly specified, or the correct
 /// number of arguments were passed, etc.
@@ -5158,7 +5190,7 @@
   case AttributeList::AT_ObjCBoxable:
     handleObjCBoxable(S, D, Attr);
     break;
-          
+
   case AttributeList::AT_CFAuditedTransfer:
     handleCFAuditedTransferAttr(S, D, Attr);
     break;
@@ -5249,6 +5281,9 @@
   case AttributeList::AT_Weak:
     handleSimpleAttribute<WeakAttr>(S, D, Attr);
     break;
+  case AttributeList::AT_UniqueInstantiation:
+    handleUniqueInstantiation(S, D, Attr);
+    break;
   case AttributeList::AT_WeakRef:
     handleWeakRefAttr(S, D, Attr);
     break;
@@ -5708,9 +5743,9 @@
   if (S.getLangOpts().ObjCAutoRefCount)
     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(decl)) {
       // FIXME: we may want to suppress diagnostics for all
-      // kind of forbidden type messages on unavailable functions. 
+      // kind of forbidden type messages on unavailable functions.
       if (FD->hasAttr<UnavailableAttr>() &&
-          diag.getForbiddenTypeDiagnostic() == 
+          diag.getForbiddenTypeDiagnostic() ==
           diag::err_arc_array_param_no_ownership) {
         diag.Triggered = true;
         return;
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -2188,6 +2188,19 @@
   return AnyAdded;
 }
 
+static void checkUniqueInstantiationAttrs(Sema &S, const Decl *New,
+                                          const Decl *Old) {
+  Attr *NewAttr = New->getAttr<UniqueInstantiationAttr>();
+
+  // Check that any previous definitions also had this attribute set.
+  if (Old->hasAttr<UniqueInstantiationAttr>() == (NewAttr != nullptr))
+    return;
+
+  SourceLocation NewLoc = NewAttr ? NewAttr->getLocation() : New->getLocStart();
+  S.Diag(NewLoc, diag::err_unique_instantiation_not_previous);
+  S.Diag(Old->getLocStart(), diag::note_previous_explicit_instantiation);
+}
+
 static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
                                const InheritableAttr *Attr,
                                Sema::AvailabilityMergeKind AMK) {
@@ -2289,6 +2302,18 @@
   if (!New->hasAttrs())
     return;
 
+  // Explicit template instantiations need special handling because in certain
+  // ABIs explicit template definitions may add attributes over explicit
+  // template declarations. In clang getDefinition() will get the
+  // ClassTemplateSpecializationDecl associated with the class template
+  // declaration, so we'd give incorrect warnings here.
+  if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(New)) {
+    TemplateSpecializationKind Kind = CTSD->getSpecializationKind();
+    if (Kind == TSK_ExplicitInstantiationDeclaration ||
+        Kind == TSK_ExplicitInstantiationDefinition)
+      return;
+  }
+
   const Decl *Def = getDefinition(Old);
   if (!Def || Def == New)
     return;
@@ -2382,6 +2407,8 @@
   // attributes declared post-definition are currently ignored
   checkNewAttributesAfterDef(*this, New, Old);
 
+  checkUniqueInstantiationAttrs(*this, New, Old);
+
   if (!Old->hasAttrs())
     return;
 
Index: lib/CodeGen/CGVTables.cpp
===================================================================
--- lib/CodeGen/CGVTables.cpp
+++ lib/CodeGen/CGVTables.cpp
@@ -741,6 +741,10 @@
                  llvm::Function::InternalLinkage;
 
       case TSK_ExplicitInstantiationDefinition:
+        // If the key function has strong linkage (say due to
+        // UniqueInstantiationAttr), the VTable should too.
+        if (Context.containedInUniqueInstantiation(keyFunction))
+          return llvm::GlobalVariable::ExternalLinkage;
         return !Context.getLangOpts().AppleKext ?
                  llvm::GlobalVariable::WeakODRLinkage :
                  llvm::Function::InternalLinkage;
@@ -759,7 +763,10 @@
       llvm::GlobalValue::LinkOnceODRLinkage;
   llvm::GlobalVariable::LinkageTypes NonDiscardableODRLinkage =
       llvm::GlobalValue::WeakODRLinkage;
-  if (RD->hasAttr<DLLExportAttr>()) {
+  if (RD->hasAttr<UniqueInstantiationAttr>() ||
+      Context.containedInUniqueInstantiation(RD)) {
+    NonDiscardableODRLinkage = llvm::GlobalVariable::ExternalLinkage;
+  } else if (RD->hasAttr<DLLExportAttr>()) {
     // Cannot discard exported vtables.
     DiscardableODRLinkage = NonDiscardableODRLinkage;
   } else if (RD->hasAttr<DLLImportAttr>()) {
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -8254,6 +8254,17 @@
   return getFunctionType(ResType, ArgTypes, EPI);
 }
 
+bool ASTContext::containedInUniqueInstantiation(const Decl *D) {
+  const RecordDecl *RD;
+  while ((RD = dyn_cast<RecordDecl>(D->getDeclContext()))) {
+    auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD);
+    if (CTSD && CTSD->hasAttr<UniqueInstantiationAttr>())
+      return true;
+    D = RD;
+  }
+  return false;
+}
+
 static GVALinkage basicGVALinkageForFunction(const ASTContext &Context,
                                              const FunctionDecl *FD) {
   if (!FD->isExternallyVisible())
@@ -8267,6 +8278,13 @@
     break;
 
   case TSK_ExplicitInstantiationDefinition:
+    if (FD->hasAttr<UniqueInstantiationAttr>() ||
+        Context.containedInUniqueInstantiation(FD)) {
+      // This translation unit is responsible for emitting a unique
+      // instantiation of this function regardless of whether or not
+      // the function is marked inline, so the processing below is irrelevant.
+      return GVA_StrongExternal;
+    }
     return GVA_StrongODR;
 
   // C++11 [temp.explicit]p10:
@@ -8369,6 +8387,9 @@
                : GVA_StrongExternal;
 
   case TSK_ExplicitInstantiationDefinition:
+    if (VD->hasAttr<UniqueInstantiationAttr>() ||
+        Context.containedInUniqueInstantiation(VD))
+      return GVA_StrongExternal;
     return GVA_StrongODR;
 
   case TSK_ExplicitInstantiationDeclaration:
Index: include/clang/Sema/AttributeList.h
===================================================================
--- include/clang/Sema/AttributeList.h
+++ include/clang/Sema/AttributeList.h
@@ -855,7 +855,9 @@
   ExpectedStructOrTypedef,
   ExpectedObjectiveCInterfaceOrProtocol,
   ExpectedKernelFunction,
-  ExpectedFunctionWithProtoType
+  ExpectedFunctionWithProtoType,
+  ExpectedExplicitInstantiation,
+  ExpectedFunctionOrClass
 };
 
 }  // end namespace clang
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -2428,7 +2428,8 @@
   "Objective-C instance methods|init methods of interface or class extension declarations|"
   "variables, functions and classes|Objective-C protocols|"
   "functions and global variables|structs, unions, and typedefs|structs and typedefs|"
-  "interface or protocol declarations|kernel functions|non-K&R-style functions}1">,
+  "interface or protocol declarations|kernel functions|non-K&R-style functions|"
+  "explicit template declarations or definitions|functions and classes}1">,
   InGroup<IgnoredAttributes>;
 def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>;
 def warn_type_attribute_wrong_type : Warning<
@@ -2533,8 +2534,14 @@
   "%plural{0:no parameters to index into|"
   "1:can only be 1, since there is one parameter|"
   ":must be between 1 and %2}2">;
-
-// Thread Safety Analysis   
+def err_unique_instantiation_no_declaration : Error<
+  "'unique_instantiation' attribute on an explicit instantiation requires"
+  " a previous explicit instantiation declaration">;
+def err_unique_instantiation_not_previous : Error<
+  "'unique_instantiation' attribute must be specified for all declarations and"
+  " definitions of this explicit template instantiation">;
+
+// Thread Safety Analysis
 def warn_unlock_but_no_lock : Warning<"releasing %0 '%1' that was not held">,
   InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
 def warn_unlock_kind_mismatch : Warning<
Index: include/clang/Basic/AttrDocs.td
===================================================================
--- include/clang/Basic/AttrDocs.td
+++ include/clang/Basic/AttrDocs.td
@@ -1856,6 +1856,39 @@
         return callee(); // This call is tail-call optimized.
       }
     };
+  }];
+}
+
+def UniqueInstantiationDocs : Documentation {
+  let Category = DocCatFunction;
+  let Content = [{
+The ``unique_instantiation`` attribute may only be applied to explicit template
+declarations and definitions, i.e. expressions of the form:
+
+  .. code-block:: c++
+
+    // Explicit template declaration (usually found in a .h file)
+    extern template struct __attribute__((unique_instantiation)) my_template<int>;
+
+    // Explicit template definition (in exactly **ONE** .cpp file)
+    template struct __attribute__((unique_instantiation)) my_template<int>;
+
+
+When the unique_instantiation attribute is specified on an explicit template
+instantiation, the compiler is given license to emit strong symbols for
+this specific explicit template instantiation.
+
+If the attribute is present on one such definition or declaration for a given
+entity, it must be present on all.
+
+Note that to ensure correct execution the user **MUST** make certain that no
+other translation unit has an implicit instantiation of the same entity. In
+particular this means that any usage of the entity has to be preceeded by an
+appropriate explicit template declaration or definition.
 
+It is thus recommended that explicit template declarations are placed in headers
+to suppress any potential implicit instantiation of the entity. In order to
+encourage this programming style, any explicit template definition with this
+attribute **MUST** be preceeded by an appropriate declaration.
   }];
 }
Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td
+++ include/clang/Basic/Attr.td
@@ -1220,7 +1220,7 @@
   let Documentation = [OverloadableDocs];
 }
 
-def Override : InheritableAttr { 
+def Override : InheritableAttr {
   let Spellings = [Keyword<"override">];
   let SemaHandler = 0;
   let Documentation = [Undocumented];
@@ -1288,7 +1288,7 @@
 
 def WorkGroupSizeHint :  InheritableAttr {
   let Spellings = [GNU<"work_group_size_hint">];
-  let Args = [UnsignedArgument<"XDim">, 
+  let Args = [UnsignedArgument<"XDim">,
               UnsignedArgument<"YDim">,
               UnsignedArgument<"ZDim">];
   let Subjects = SubjectList<[Function], ErrorDiag>;
@@ -1514,6 +1514,12 @@
   let Documentation = [Undocumented];
 }
 
+def UniqueInstantiation : InheritableAttr {
+  let Spellings = [GNU<"unique_instantiation">];
+  let Subjects = SubjectList<[Var, Function, CXXRecord], ErrorDiag>;
+  let Documentation = [UniqueInstantiationDocs];
+}
+
 def WeakImport : InheritableAttr {
   let Spellings = [GNU<"weak_import">];
   let Documentation = [Undocumented];
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -2360,6 +2360,7 @@
   /// when it is called.
   void AddDeallocation(void (*Callback)(void*), void *Data);
 
+  static bool containedInUniqueInstantiation(const Decl *D);
   GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const;
   GVALinkage GetGVALinkageForVariable(const VarDecl *VD);
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to