diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 48 |
2 files changed, 55 insertions, 9 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 714e975e42f..c3acd52a1ab 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -736,6 +736,7 @@ static void CheckNonNullArguments(Sema &S, const NamedDecl *FDecl, const Expr * const *ExprArgs, SourceLocation CallSiteLoc) { + // Check the attributes attached to the method/function itself. for (specific_attr_iterator<NonNullAttr> I = FDecl->specific_attr_begin<NonNullAttr>(), E = FDecl->specific_attr_end<NonNullAttr>(); I != E; ++I) { @@ -747,6 +748,21 @@ static void CheckNonNullArguments(Sema &S, CheckNonNullArgument(S, ExprArgs[*i], CallSiteLoc); } } + + // Check the attributes on the parameters. + ArrayRef<ParmVarDecl*> parms; + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FDecl)) + parms = FD->parameters(); + else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(FDecl)) + parms = MD->parameters(); + + unsigned argIndex = 0; + for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end(); + I != E; ++I, ++argIndex) { + const ParmVarDecl *PVD = *I; + if (PVD->hasAttr<NonNullAttr>()) + CheckNonNullArgument(S, ExprArgs[argIndex], CallSiteLoc); + } } /// Handles the checks for format strings, non-POD arguments to vararg diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index b8116a7e8a6..06290672214 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1156,6 +1156,36 @@ static void possibleTransparentUnionPointerType(QualType &T) { } } +static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &Attr, + SourceRange R) { + T = T.getNonReferenceType(); + possibleTransparentUnionPointerType(T); + + if (!T->isAnyPointerType() && !T->isBlockPointerType()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_pointers_only) + << Attr.getName() << R; + return false; + } + return true; +} + +static void handleNonNullAttrParameter(Sema &S, ParmVarDecl *D, + const AttributeList &Attr) { + // Is the argument a pointer type? + if (!attrNonNullArgCheck(S, D->getType(), Attr, D->getSourceRange())) + return; + + if (Attr.getNumArgs() > 0) { + S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_parm_no_args) + << D->getSourceRange(); + return; + } + + D->addAttr(::new (S.Context) + NonNullAttr(Attr.getRange(), S.Context, 0, 0, + Attr.getAttributeSpellingListIndex())); +} + static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { SmallVector<unsigned, 8> NonNullArgs; for (unsigned i = 0; i < Attr.getNumArgs(); ++i) { @@ -1165,15 +1195,10 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; // Is the function argument a pointer type? - QualType T = getFunctionOrMethodArgType(D, Idx).getNonReferenceType(); - possibleTransparentUnionPointerType(T); - - if (!T->isAnyPointerType() && !T->isBlockPointerType()) { - // FIXME: Should also highlight argument in decl. - S.Diag(Attr.getLoc(), diag::warn_attribute_pointers_only) - << Attr.getName() << Ex->getSourceRange(); + // FIXME: Should also highlight argument in decl in the diagnostic. + if (!attrNonNullArgCheck(S, getFunctionOrMethodArgType(D, Idx), + Attr, Ex->getSourceRange())) continue; - } NonNullArgs.push_back(Idx); } @@ -3947,7 +3972,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_Mode: handleModeAttr (S, D, Attr); break; case AttributeList::AT_NoCommon: handleSimpleAttribute<NoCommonAttr>(S, D, Attr); break; - case AttributeList::AT_NonNull: handleNonNullAttr (S, D, Attr); break; + case AttributeList::AT_NonNull: + if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D)) + handleNonNullAttrParameter(S, PVD, Attr); + else + handleNonNullAttr(S, D, Attr); + break; case AttributeList::AT_Overloadable: handleSimpleAttribute<OverloadableAttr>(S, D, Attr); break; case AttributeList::AT_Ownership: handleOwnershipAttr (S, D, Attr); break; |