diff options
author | John McCall <rjmccall@apple.com> | 2015-09-23 22:14:21 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2015-09-23 22:14:21 +0000 |
commit | 6997525eaa8fa6ea09e6a8c7a33908e81544ef1f (patch) | |
tree | 1decae494592ba5218d515d64f5d37c14fe5756f /clang/lib/Sema/SemaDeclObjC.cpp | |
parent | d209967a68dc11e255c9794d77340dce080a84e6 (diff) | |
download | bcm5719-llvm-6997525eaa8fa6ea09e6a8c7a33908e81544ef1f.tar.gz bcm5719-llvm-6997525eaa8fa6ea09e6a8c7a33908e81544ef1f.zip |
Forbid qualifiers on ObjC generic parameters and arguments, but
silently ignore them on arguments when they're provided indirectly
(.e.g behind a template argument or typedef).
This is mostly just good language design --- specifying that a
generic argument is __weak doesn't actually do anything --- but
it also prevents assertions when trying to apply a different
ownership qualifier.
rdar://21612439
llvm-svn: 248436
Diffstat (limited to 'clang/lib/Sema/SemaDeclObjC.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index f42c4b7546c..7b9b9c148c1 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -638,20 +638,44 @@ DeclResult Sema::actOnObjCTypeParam(Scope *S, typeBoundInfo = nullptr; } - // Type bounds cannot have explicit nullability. + // Type bounds cannot have qualifiers (even indirectly) or explicit + // nullability. if (typeBoundInfo) { - // Type arguments cannot explicitly specify nullability. - if (auto nullability = AttributedType::stripOuterNullability(typeBound)) { - // Look at the type location information to find the nullability - // specifier so we can zap it. - SourceLocation nullabilityLoc - = typeBoundInfo->getTypeLoc().findNullabilityLoc(); - SourceLocation diagLoc - = nullabilityLoc.isValid()? nullabilityLoc - : typeBoundInfo->getTypeLoc().getLocStart(); - Diag(diagLoc, diag::err_type_param_bound_explicit_nullability) - << paramName << typeBoundInfo->getType() - << FixItHint::CreateRemoval(nullabilityLoc); + QualType typeBound = typeBoundInfo->getType(); + TypeLoc qual = typeBoundInfo->getTypeLoc().findExplicitQualifierLoc(); + if (qual || typeBound.hasQualifiers()) { + bool diagnosed = false; + SourceRange rangeToRemove; + if (qual) { + if (auto attr = qual.getAs<AttributedTypeLoc>()) { + rangeToRemove = attr.getLocalSourceRange(); + if (attr.getTypePtr()->getImmediateNullability()) { + Diag(attr.getLocStart(), + diag::err_objc_type_param_bound_explicit_nullability) + << paramName << typeBound + << FixItHint::CreateRemoval(rangeToRemove); + diagnosed = true; + } + } + } + + if (!diagnosed) { + Diag(qual ? qual.getLocStart() + : typeBoundInfo->getTypeLoc().getLocStart(), + diag::err_objc_type_param_bound_qualified) + << paramName << typeBound << typeBound.getQualifiers().getAsString() + << FixItHint::CreateRemoval(rangeToRemove); + } + + // If the type bound has qualifiers other than CVR, we need to strip + // them or we'll probably assert later when trying to apply new + // qualifiers. + Qualifiers quals = typeBound.getQualifiers(); + quals.removeCVRQualifiers(); + if (!quals.empty()) { + typeBoundInfo = + Context.getTrivialTypeSourceInfo(typeBound.getUnqualifiedType()); + } } } } |