summaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/Sema.cpp6
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp3
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp18
3 files changed, 21 insertions, 6 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index ccbbe50093b..a9c5f7d58bf 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -644,7 +644,8 @@ void Sema::getUndefinedButUsed(
continue;
if (FD->isExternallyVisible() &&
!isExternalWithNoLinkageType(FD) &&
- !FD->getMostRecentDecl()->isInlined())
+ !FD->getMostRecentDecl()->isInlined() &&
+ !FD->hasAttr<ExcludeFromExplicitInstantiationAttr>())
continue;
if (FD->getBuiltinID())
continue;
@@ -654,7 +655,8 @@ void Sema::getUndefinedButUsed(
continue;
if (VD->isExternallyVisible() &&
!isExternalWithNoLinkageType(VD) &&
- !VD->getMostRecentDecl()->isInline())
+ !VD->getMostRecentDecl()->isInline() &&
+ !VD->hasAttr<ExcludeFromExplicitInstantiationAttr>())
continue;
// Skip VarDecls that lack formal definitions but which we know are in
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index a437f159968..c0fb3356bae 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6512,6 +6512,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_InternalLinkage:
handleInternalLinkageAttr(S, D, AL);
break;
+ case ParsedAttr::AT_ExcludeFromExplicitInstantiation:
+ handleSimpleAttribute<ExcludeFromExplicitInstantiationAttr>(S, D, AL);
+ break;
case ParsedAttr::AT_LTOVisibilityPublic:
handleSimpleAttribute<LTOVisibilityPublicAttr>(S, D, AL);
break;
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 5666cf04a24..cfedf0a0994 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2574,10 +2574,14 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
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 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
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 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
}
}
} 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.