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 | |
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')
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 50 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 35 |
2 files changed, 62 insertions, 23 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()); + } } } } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 73da718a813..96c51a94ebb 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -790,18 +790,33 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, TypeSourceInfo *typeArgInfo = typeArgs[i]; QualType typeArg = typeArgInfo->getType(); - // Type arguments cannot explicitly specify nullability. - if (auto nullability = AttributedType::stripOuterNullability(typeArg)) { - SourceLocation nullabilityLoc - = typeArgInfo->getTypeLoc().findNullabilityLoc(); - SourceLocation diagLoc = nullabilityLoc.isValid()? nullabilityLoc - : typeArgInfo->getTypeLoc().getLocStart(); - S.Diag(diagLoc, - diag::err_type_arg_explicit_nullability) - << typeArg - << FixItHint::CreateRemoval(nullabilityLoc); + // Type arguments cannot have explicit qualifiers or nullability. + // We ignore indirect sources of these, e.g. behind typedefs or + // template arguments. + if (TypeLoc qual = typeArgInfo->getTypeLoc().findExplicitQualifierLoc()) { + bool diagnosed = false; + SourceRange rangeToRemove; + if (auto attr = qual.getAs<AttributedTypeLoc>()) { + rangeToRemove = attr.getLocalSourceRange(); + if (attr.getTypePtr()->getImmediateNullability()) { + typeArg = attr.getTypePtr()->getModifiedType(); + S.Diag(attr.getLocStart(), + diag::err_objc_type_arg_explicit_nullability) + << typeArg << FixItHint::CreateRemoval(rangeToRemove); + diagnosed = true; + } + } + + if (!diagnosed) { + S.Diag(qual.getLocStart(), diag::err_objc_type_arg_qualified) + << typeArg << typeArg.getQualifiers().getAsString() + << FixItHint::CreateRemoval(rangeToRemove); + } } + // Remove qualifiers even if they're non-local. + typeArg = typeArg.getUnqualifiedType(); + finalTypeArgs.push_back(typeArg); if (typeArg->getAs<PackExpansionType>()) |