aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2013-01-17 23:36:45 +0000
committerDouglas Gregor <dgregor@apple.com>2013-01-17 23:36:45 +0000
commit02dd79830979e6d83d4420377e8f4c9e4a77439b (patch)
treeaa0eee38a0231443297ea3d49a2432834c79a51d /lib
parentfa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4d (diff)
In Objective-C ARC, completely ignore ownership qualifiers on the
return type of a function by canonicalizing them away. They are useless anyway, and conflict with our rules for template argument deduction and __strong. Fixes <rdar://problem/12367446>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172768 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ASTContext.cpp19
-rw-r--r--lib/Sema/SemaType.cpp38
2 files changed, 55 insertions, 2 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index df64237f70..ace9dc0146 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2602,6 +2602,13 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy,
return QualType(New, 0);
}
+/// \brief Determine whether \p T is canonical as the result type of a function.
+static bool isCanonicalResultType(QualType T) {
+ return T.isCanonical() &&
+ (T.getObjCLifetime() == Qualifiers::OCL_None ||
+ T.getObjCLifetime() == Qualifiers::OCL_ExplicitNone);
+}
+
/// getFunctionType - Return a normal function type with a typed argument
/// list. isVariadic indicates whether the argument list includes '...'.
QualType
@@ -2620,7 +2627,7 @@ ASTContext::getFunctionType(QualType ResultTy,
// Determine whether the type being created is already canonical or not.
bool isCanonical =
- EPI.ExceptionSpecType == EST_None && ResultTy.isCanonical() &&
+ EPI.ExceptionSpecType == EST_None && isCanonicalResultType(ResultTy) &&
!EPI.HasTrailingReturn;
for (unsigned i = 0; i != NumArgs && isCanonical; ++i)
if (!ArgArray[i].isCanonicalAsParam())
@@ -2646,7 +2653,15 @@ ASTContext::getFunctionType(QualType ResultTy,
CanonicalEPI.ExtInfo
= CanonicalEPI.ExtInfo.withCallingConv(getCanonicalCallConv(CallConv));
- Canonical = getFunctionType(getCanonicalType(ResultTy),
+ // Result types do not have ARC lifetime qualifiers.
+ QualType CanResultTy = getCanonicalType(ResultTy);
+ if (ResultTy.getQualifiers().hasObjCLifetime()) {
+ Qualifiers Qs = CanResultTy.getQualifiers();
+ Qs.removeObjCLifetime();
+ CanResultTy = getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
+ }
+
+ Canonical = getFunctionType(CanResultTy,
CanonicalArgs.data(), NumArgs,
CanonicalEPI);
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 15aa39b7e4..35816a42f3 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -2471,6 +2471,44 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
S);
}
+ // Objective-C ARC ownership qualifiers are ignored on the function
+ // return type (by type canonicalization). Complain if this attribute
+ // was written here.
+ if (T.getQualifiers().hasObjCLifetime()) {
+ SourceLocation AttrLoc;
+ if (chunkIndex + 1 < D.getNumTypeObjects()) {
+ DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1);
+ for (const AttributeList *Attr = ReturnTypeChunk.getAttrs();
+ Attr; Attr = Attr->getNext()) {
+ if (Attr->getKind() == AttributeList::AT_ObjCOwnership) {
+ AttrLoc = Attr->getLoc();
+ break;
+ }
+ }
+ }
+ if (AttrLoc.isInvalid()) {
+ for (const AttributeList *Attr
+ = D.getDeclSpec().getAttributes().getList();
+ Attr; Attr = Attr->getNext()) {
+ if (Attr->getKind() == AttributeList::AT_ObjCOwnership) {
+ AttrLoc = Attr->getLoc();
+ break;
+ }
+ }
+ }
+
+ if (AttrLoc.isValid()) {
+ // The ownership attributes are almost always written via
+ // the predefined
+ // __strong/__weak/__autoreleasing/__unsafe_unretained.
+ if (AttrLoc.isMacroID())
+ AttrLoc = S.SourceMgr.getImmediateExpansionRange(AttrLoc).first;
+
+ S.Diag(AttrLoc, diag::warn_arc_lifetime_result_type)
+ << T.getQualifiers().getObjCLifetime();
+ }
+ }
+
if (LangOpts.CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.