summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp21
1 files changed, 21 insertions, 0 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index ccdb4d288e..50ea98e7f6 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -6008,6 +6008,27 @@ static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) {
<< Attr;
ND.dropAttr<NotTailCalledAttr>();
}
+
+ // Check the attributes on the function type, if any.
+ if (const auto *FD = dyn_cast<FunctionDecl>(&ND)) {
+ for (TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc();
+ auto ATL = TL.getAsAdjusted<AttributedTypeLoc>();
+ TL = ATL.getModifiedLoc()) {
+ // The [[lifetimebound]] attribute can be applied to the implicit object
+ // parameter of a non-static member function (other than a ctor or dtor)
+ // by applying it to the function type.
+ if (ATL.getAttrKind() == AttributedType::attr_lifetimebound) {
+ const auto *MD = dyn_cast<CXXMethodDecl>(FD);
+ if (!MD || MD->isStatic()) {
+ S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_no_object_param)
+ << !MD << ATL.getLocalSourceRange();
+ } else if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD)) {
+ S.Diag(ATL.getAttrNameLoc(), diag::err_lifetimebound_ctor_dtor)
+ << isa<CXXDestructorDecl>(MD) << ATL.getLocalSourceRange();
+ }
+ }
+ }
+ }
}
static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,