aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Sema/AttributeList.cpp1
-rw-r--r--lib/Sema/SemaDeclAttr.cpp20
-rw-r--r--lib/Sema/SemaExprCXX.cpp5
3 files changed, 25 insertions, 1 deletions
diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp
index 77d962542b..c3efda9a7a 100644
--- a/lib/Sema/AttributeList.cpp
+++ b/lib/Sema/AttributeList.cpp
@@ -85,6 +85,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("deprecated", AT_deprecated)
.Case("visibility", AT_visibility)
.Case("destructor", AT_destructor)
+ .Case("forbid_temporaries", AT_forbid_temporaries)
.Case("format_arg", AT_format_arg)
.Case("gnu_inline", AT_gnu_inline)
.Case("weak_import", AT_weak_import)
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 474c7cb82f..21d0f46528 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -885,6 +885,24 @@ static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr,
d->addAttr(::new (S.Context) VecReturnAttr(Attr.getLoc(), S.Context));
}
+static void HandleForbidTemporariesAttr(Decl *d, const AttributeList &Attr,
+ Sema &S) {
+ assert(Attr.isInvalid() == false);
+
+ if (Attr.getNumArgs() != 0) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+ return;
+ }
+
+ if (!isa<TypeDecl>(d)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 9 /*class*/;
+ return;
+ }
+
+ d->addAttr(::new (S.Context) ForbidTemporariesAttr(Attr.getLoc(), S.Context));
+}
+
static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) {
if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
@@ -2674,6 +2692,8 @@ static void ProcessInheritableDeclAttr(Scope *scope, Decl *D,
case AttributeList::AT_ext_vector_type:
HandleExtVectorTypeAttr(scope, D, Attr, S);
break;
+ case AttributeList::AT_forbid_temporaries:
+ HandleForbidTemporariesAttr(D, Attr, S); break;
case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break;
case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break;
case AttributeList::AT_global: HandleGlobalAttr (D, Attr, S); break;
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 0b7a051365..cb02be546e 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -3188,9 +3188,12 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) {
}
}
+ CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ if (RD->getAttr<ForbidTemporariesAttr>())
+ Diag(E->getExprLoc(), diag::warn_temporaries_forbidden) << E->getType();
+
// That should be enough to guarantee that this type is complete.
// If it has a trivial destructor, we can avoid the extra copy.
- CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
if (RD->isInvalidDecl() || RD->hasTrivialDestructor())
return Owned(E);