From: Michael Han Date: Mon, 23 Jul 2012 18:48:41 +0000 (+0000) Subject: Refactor handler functions for thread safety attributes. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dc69157f9bfa538e2bf62a01fa46df22ce45ce3c;p=clang Refactor handler functions for thread safety attributes. Make handler functions for thread safety attributes consistent with other attributes handler functions by removing the bool parameter from some of the thread safety attributes handler functions and extracting common checks out of different handler functions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160635 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 65fceaa93a..8f3b00f8c9 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -430,80 +430,119 @@ enum ThreadAttributeDeclKind { ThreadExpectedClassOrStruct }; -static void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr, - bool pointer = false) { +static bool checkGuardedVarAttrCommon(Sema &S, Decl *D, + const AttributeList &Attr) { assert(!Attr.isInvalid()); if (!checkAttributeNumArgs(S, Attr, 0)) - return; + return false; // D must be either a member field or global (potentially shared) variable. if (!mayBeSharedVariable(D)) { S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) << Attr.getName() << ThreadExpectedFieldOrGlobalVar; - return; + return false; } - if (pointer && !threadSafetyCheckIsPointer(S, D, Attr)) + return true; +} + +static void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!checkGuardedVarAttrCommon(S, D, Attr)) return; + + D->addAttr(::new (S.Context) GuardedVarAttr(Attr.getRange(), S.Context)); +} - if (pointer) - D->addAttr(::new (S.Context) PtGuardedVarAttr(Attr.getRange(), S.Context)); - else - D->addAttr(::new (S.Context) GuardedVarAttr(Attr.getRange(), S.Context)); +static void handlePtGuardedVarAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!checkGuardedVarAttrCommon(S, D, Attr)) + return; + + if (!threadSafetyCheckIsPointer(S, D, Attr)) + return; + + D->addAttr(::new (S.Context) PtGuardedVarAttr(Attr.getRange(), S.Context)); } -static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr, - bool pointer = false) { +static bool checkGuardedByAttrCommon(Sema &S, Decl *D, + const AttributeList &Attr, + Expr* &Arg) { assert(!Attr.isInvalid()); if (!checkAttributeNumArgs(S, Attr, 1)) - return; + return false; // D must be either a member field or global (potentially shared) variable. if (!mayBeSharedVariable(D)) { S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) << Attr.getName() << ThreadExpectedFieldOrGlobalVar; - return; + return false; } - if (pointer && !threadSafetyCheckIsPointer(S, D, Attr)) - return; - SmallVector Args; // check that all arguments are lockable objects checkAttrArgsAreLockableObjs(S, D, Attr, Args); unsigned Size = Args.size(); if (Size != 1) + return false; + + Arg = Args[0]; + + return true; +} + +static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr) { + Expr *Arg = 0; + if (!checkGuardedByAttrCommon(S, D, Attr, Arg)) return; - Expr *Arg = Args[0]; - if (pointer) - D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(), - S.Context, Arg)); - else - D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg)); + D->addAttr(::new (S.Context) GuardedByAttr(Attr.getRange(), S.Context, Arg)); } +static void handlePtGuardedByAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + Expr *Arg = 0; + if (!checkGuardedByAttrCommon(S, D, Attr, Arg)) + return; + + if (!threadSafetyCheckIsPointer(S, D, Attr)) + return; + + D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getRange(), + S.Context, Arg)); +} -static void handleLockableAttr(Sema &S, Decl *D, const AttributeList &Attr, - bool scoped = false) { +static bool checkLockableAttrCommon(Sema &S, Decl *D, + const AttributeList &Attr) { assert(!Attr.isInvalid()); if (!checkAttributeNumArgs(S, Attr, 0)) - return; + return false; // FIXME: Lockable structs for C code. if (!isa(D)) { S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) << Attr.getName() << ThreadExpectedClassOrStruct; - return; + return false; } - if (scoped) - D->addAttr(::new (S.Context) ScopedLockableAttr(Attr.getRange(), S.Context)); - else - D->addAttr(::new (S.Context) LockableAttr(Attr.getRange(), S.Context)); + return true; +} + +static void handleLockableAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!checkLockableAttrCommon(S, D, Attr)) + return; + + D->addAttr(::new (S.Context) LockableAttr(Attr.getRange(), S.Context)); +} + +static void handleScopedLockableAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (!checkLockableAttrCommon(S, D, Attr)) + return; + + D->addAttr(::new (S.Context) ScopedLockableAttr(Attr.getRange(), S.Context)); } static void handleNoThreadSafetyAttr(Sema &S, Decl *D, @@ -540,19 +579,20 @@ static void handleNoAddressSafetyAttr(Sema &S, Decl *D, S.Context)); } -static void handleAcquireOrderAttr(Sema &S, Decl *D, const AttributeList &Attr, - bool before) { +static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, + const AttributeList &Attr, + SmallVector &Args) { assert(!Attr.isInvalid()); if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) - return; + return false; // D must be either a member field or global (potentially shared) variable. ValueDecl *VD = dyn_cast(D); if (!VD || !mayBeSharedVariable(D)) { S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) << Attr.getName() << ThreadExpectedFieldOrGlobalVar; - return; + return false; } // Check that this attribute only applies to lockable types. @@ -561,29 +601,44 @@ static void handleAcquireOrderAttr(Sema &S, Decl *D, const AttributeList &Attr, const RecordType *RT = getRecordType(QT); if (!RT || !RT->getDecl()->getAttr()) { S.Diag(Attr.getLoc(), diag::warn_thread_attribute_decl_not_lockable) - << Attr.getName(); - return; + << Attr.getName(); + return false; } } - SmallVector Args; // Check that all arguments are lockable objects. checkAttrArgsAreLockableObjs(S, D, Attr, Args); - unsigned Size = Args.size(); - if (Size == 0) + if (Args.size() == 0) + return false; + + return true; +} + +static void handleAcquiredAfterAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + SmallVector Args; + if (!checkAcquireOrderAttrCommon(S, D, Attr, Args)) return; + Expr **StartArg = &Args[0]; + D->addAttr(::new (S.Context) AcquiredAfterAttr(Attr.getRange(), S.Context, + StartArg, Args.size())); +} - if (before) - D->addAttr(::new (S.Context) AcquiredBeforeAttr(Attr.getRange(), S.Context, - StartArg, Size)); - else - D->addAttr(::new (S.Context) AcquiredAfterAttr(Attr.getRange(), S.Context, - StartArg, Size)); +static void handleAcquiredBeforeAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + SmallVector Args; + if (!checkAcquireOrderAttrCommon(S, D, Attr, Args)) + return; + + Expr **StartArg = &Args[0]; + D->addAttr(::new (S.Context) AcquiredBeforeAttr(Attr.getRange(), S.Context, + StartArg, Args.size())); } -static void handleLockFunAttr(Sema &S, Decl *D, const AttributeList &Attr, - bool exclusive = false) { +static bool checkLockFunAttrCommon(Sema &S, Decl *D, + const AttributeList &Attr, + SmallVector &Args) { assert(!Attr.isInvalid()); // zero or more arguments ok @@ -592,91 +647,141 @@ static void handleLockFunAttr(Sema &S, Decl *D, const AttributeList &Attr, if (!isa(D) && !isa(D)) { S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) << Attr.getName() << ThreadExpectedFunctionOrMethod; - return; + return false; } // check that all arguments are lockable objects - SmallVector Args; checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true); + + return true; +} + +static void handleSharedLockFunctionAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + SmallVector Args; + if (!checkLockFunAttrCommon(S, D, Attr, Args)) + return; + unsigned Size = Args.size(); Expr **StartArg = Size == 0 ? 0 : &Args[0]; + D->addAttr(::new (S.Context) SharedLockFunctionAttr(Attr.getRange(), + S.Context, + StartArg, Size)); +} - if (exclusive) - D->addAttr(::new (S.Context) ExclusiveLockFunctionAttr(Attr.getRange(), - S.Context, StartArg, - Size)); - else - D->addAttr(::new (S.Context) SharedLockFunctionAttr(Attr.getRange(), - S.Context, StartArg, - Size)); +static void handleExclusiveLockFunctionAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + SmallVector Args; + if (!checkLockFunAttrCommon(S, D, Attr, Args)) + return; + + unsigned Size = Args.size(); + Expr **StartArg = Size == 0 ? 0 : &Args[0]; + D->addAttr(::new (S.Context) ExclusiveLockFunctionAttr(Attr.getRange(), + S.Context, + StartArg, Size)); } -static void handleTrylockFunAttr(Sema &S, Decl *D, const AttributeList &Attr, - bool exclusive = false) { +static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, + const AttributeList &Attr, + SmallVector &Args) { assert(!Attr.isInvalid()); if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) - return; + return false; if (!isa(D) && !isa(D)) { S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) << Attr.getName() << ThreadExpectedFunctionOrMethod; - return; + return false; } if (!isIntOrBool(Attr.getArg(0))) { S.Diag(Attr.getLoc(), diag::err_attribute_first_argument_not_int_or_bool) - << Attr.getName(); - return; + << Attr.getName(); + return false; } - SmallVector Args; // check that all arguments are lockable objects checkAttrArgsAreLockableObjs(S, D, Attr, Args, 1); + + return true; +} + +static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + SmallVector Args; + if (!checkTryLockFunAttrCommon(S, D, Attr, Args)) + return; + unsigned Size = Args.size(); Expr **StartArg = Size == 0 ? 0 : &Args[0]; + D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(Attr.getRange(), + S.Context, + Attr.getArg(0), + StartArg, Size)); +} - if (exclusive) - D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(Attr.getRange(), - S.Context, - Attr.getArg(0), - StartArg, Size)); - else - D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(Attr.getRange(), - S.Context, - Attr.getArg(0), - StartArg, Size)); +static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + SmallVector Args; + if (!checkTryLockFunAttrCommon(S, D, Attr, Args)) + return; + + unsigned Size = Args.size(); + Expr **StartArg = Size == 0 ? 0 : &Args[0]; + D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(Attr.getRange(), + S.Context, + Attr.getArg(0), + StartArg, Size)); } -static void handleLocksRequiredAttr(Sema &S, Decl *D, const AttributeList &Attr, - bool exclusive = false) { +static bool checkLocksRequiredCommon(Sema &S, Decl *D, + const AttributeList &Attr, + SmallVector &Args) { assert(!Attr.isInvalid()); if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) - return; + return false; if (!isa(D) && !isa(D)) { S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) << Attr.getName() << ThreadExpectedFunctionOrMethod; - return; + return false; } // check that all arguments are lockable objects - SmallVector Args; checkAttrArgsAreLockableObjs(S, D, Attr, Args); - unsigned Size = Args.size(); - if (Size == 0) + if (Args.size() == 0) + return false; + + return true; +} + +static void handleExclusiveLocksRequiredAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + SmallVector Args; + if (!checkLocksRequiredCommon(S, D, Attr, Args)) return; + Expr **StartArg = &Args[0]; + D->addAttr(::new (S.Context) ExclusiveLocksRequiredAttr(Attr.getRange(), + S.Context, + StartArg, + Args.size())); +} - if (exclusive) - D->addAttr(::new (S.Context) ExclusiveLocksRequiredAttr(Attr.getRange(), - S.Context, StartArg, - Size)); - else - D->addAttr(::new (S.Context) SharedLocksRequiredAttr(Attr.getRange(), - S.Context, StartArg, - Size)); +static void handleSharedLocksRequiredAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + SmallVector Args; + if (!checkLocksRequiredCommon(S, D, Attr, Args)) + return; + + Expr **StartArg = &Args[0]; + D->addAttr(::new (S.Context) SharedLocksRequiredAttr(Attr.getRange(), + S.Context, + StartArg, + Args.size())); } static void handleUnlockFunAttr(Sema &S, Decl *D, @@ -4168,10 +4273,10 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, handleGuardedVarAttr(S, D, Attr); break; case AttributeList::AT_PtGuardedVar: - handleGuardedVarAttr(S, D, Attr, /*pointer = */true); + handlePtGuardedVarAttr(S, D, Attr); break; case AttributeList::AT_ScopedLockable: - handleLockableAttr(S, D, Attr, /*scoped = */true); + handleScopedLockableAttr(S, D, Attr); break; case AttributeList::AT_NoAddressSafetyAnalysis: handleNoAddressSafetyAttr(S, D, Attr); @@ -4186,16 +4291,16 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, handleGuardedByAttr(S, D, Attr); break; case AttributeList::AT_PtGuardedBy: - handleGuardedByAttr(S, D, Attr, /*pointer = */true); + handlePtGuardedByAttr(S, D, Attr); break; case AttributeList::AT_ExclusiveLockFunction: - handleLockFunAttr(S, D, Attr, /*exclusive = */true); + handleExclusiveLockFunctionAttr(S, D, Attr); break; case AttributeList::AT_ExclusiveLocksRequired: - handleLocksRequiredAttr(S, D, Attr, /*exclusive = */true); + handleExclusiveLocksRequiredAttr(S, D, Attr); break; case AttributeList::AT_ExclusiveTrylockFunction: - handleTrylockFunAttr(S, D, Attr, /*exclusive = */true); + handleExclusiveTrylockFunctionAttr(S, D, Attr); break; case AttributeList::AT_LockReturned: handleLockReturnedAttr(S, D, Attr); @@ -4204,22 +4309,22 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, handleLocksExcludedAttr(S, D, Attr); break; case AttributeList::AT_SharedLockFunction: - handleLockFunAttr(S, D, Attr); + handleSharedLockFunctionAttr(S, D, Attr); break; case AttributeList::AT_SharedLocksRequired: - handleLocksRequiredAttr(S, D, Attr); + handleSharedLocksRequiredAttr(S, D, Attr); break; case AttributeList::AT_SharedTrylockFunction: - handleTrylockFunAttr(S, D, Attr); + handleSharedTrylockFunctionAttr(S, D, Attr); break; case AttributeList::AT_UnlockFunction: handleUnlockFunAttr(S, D, Attr); break; case AttributeList::AT_AcquiredBefore: - handleAcquireOrderAttr(S, D, Attr, /*before = */true); + handleAcquiredBeforeAttr(S, D, Attr); break; case AttributeList::AT_AcquiredAfter: - handleAcquireOrderAttr(S, D, Attr, /*before = */false); + handleAcquiredAfterAttr(S, D, Attr); break; default: