diff options
Diffstat (limited to 'lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 230 |
1 files changed, 227 insertions, 3 deletions
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 694d38b4a1..0f02ed31df 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -27,7 +27,7 @@ using namespace sema; /// These constants match the enumerated choices of /// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type. -enum { +enum AttributeDeclType { ExpectedFunction, ExpectedUnion, ExpectedVariableOrFunction, @@ -42,7 +42,8 @@ enum { ExpectedClassMember, ExpectedVariable, ExpectedMethod, - ExpectedVariableFunctionOrLabel + ExpectedVariableFunctionOrLabel, + ExpectedFieldOrGlobalVar }; //===----------------------------------------------------------------------===// @@ -205,6 +206,34 @@ static bool checkAttributeNumArgs(Sema &S, const AttributeList &Attr, } /// +/// \brief Check the total number of argumenation, whether parsed by clang +/// as arguments or parameters. Outputs a warning. +/// \return false if the number of argumenation units does not match expectation +/// +static bool checkAttributeNumArgsPlusParams(Sema &S, const AttributeList &Attr, + unsigned int Num, + bool moreok = false) { + unsigned int numArgsPlusParams = 0; + + if (Attr.getParameterName()) + numArgsPlusParams++; + + numArgsPlusParams += Attr.getNumArgs(); + + if (moreok && numArgsPlusParams < Num) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_few_arguments) << Num; + return false; + } + + if (!moreok && numArgsPlusParams != Num) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Num; + return false; + } + + return true; +} + +/// /// \brief Check if passed in Decl is a field or potentially shared global var /// \return true if the Decl is a field or potentially shared global variable /// @@ -225,7 +254,7 @@ static bool mayBeSharedVariable(Decl *D) { bool checkIsPointer(Sema & S, Decl * D, const AttributeList & Attr) { if(ValueDecl * vd = dyn_cast <ValueDecl>(D)) { QualType QT = vd->getType(); - if(QT->isAnyPointerType()){ + if(QT->isAnyPointerType()) { return true; } S.Diag(Attr.getLoc(), diag::warn_pointer_attribute_wrong_type) @@ -268,6 +297,30 @@ static void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr, D->addAttr(::new (S.Context) GuardedVarAttr(Attr.getLoc(), S.Context)); } +static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr, + bool pointer = false) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgsPlusParams(S, Attr, 1)) + return; + + // D must be either a member field or global (potentially shared) variable. + if (!mayBeSharedVariable(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << 15; /*fields and global vars*/; + return; + } + + if (pointer && !checkIsPointer(S, D, Attr)) + return; + + if (pointer) + D->addAttr(::new (S.Context) PtGuardedByAttr(Attr.getLoc(), S.Context)); + else + D->addAttr(::new (S.Context) GuardedByAttr(Attr.getLoc(), S.Context)); +} + + static void handleLockableAttr(Sema &S, Decl *D, const AttributeList &Attr, bool scoped = false) { assert(!Attr.isInvalid()); @@ -304,6 +357,138 @@ static void handleNoThreadSafetyAttr(Sema &S, Decl *D, S.Context)); } +static void handleAcquireOrderAttr(Sema &S, Decl *D, const AttributeList &Attr, + bool before) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgsPlusParams(S, Attr, 1, /*moreok=*/true)) + return; + + // D must be either a member field or global (potentially shared) variable. + if (!mayBeSharedVariable(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << 15; /*fields and global vars*/; + return; + } + + if (before) + D->addAttr(::new (S.Context) AcquiredBeforeAttr(Attr.getLoc(), S.Context)); + else + D->addAttr(::new (S.Context) AcquiredAfterAttr(Attr.getLoc(), S.Context)); +} + +static void handleLockFunAttr(Sema &S, Decl *D, const AttributeList &Attr, + bool exclusive = false) { + assert(!Attr.isInvalid()); + + // zero or more arguments ok + + if (!isFunction(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + if (exclusive) + D->addAttr(::new (S.Context) ExclusiveLockFunctionAttr(Attr.getLoc(), + S.Context)); + else + D->addAttr(::new (S.Context) SharedLockFunctionAttr(Attr.getLoc(), + S.Context)); +} + +static void handleTrylockFunAttr(Sema &S, Decl *D, const AttributeList &Attr, + bool exclusive = false) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgsPlusParams(S, Attr, 1, /*moreok=*/true)) + return; + + if (!isFunction(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + if (exclusive) + D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(Attr.getLoc(), + S.Context)); + else + D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(Attr.getLoc(), + S.Context)); + +} + +static void handleLocksRequiredAttr(Sema &S, Decl *D, const AttributeList &Attr, + bool exclusive = false) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgsPlusParams(S, Attr, 1, /*moreok=*/true)) + return; + + if (!isFunction(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + if (exclusive) + D->addAttr(::new (S.Context) ExclusiveLocksRequiredAttr(Attr.getLoc(), + S.Context)); + else + D->addAttr(::new (S.Context) SharedLocksRequiredAttr(Attr.getLoc(), + S.Context)); +} + + +static void handleUnlockFunAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + assert(!Attr.isInvalid()); + + // zero or more arguments ok + + if (!isFunction(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) UnlockFunctionAttr(Attr.getLoc(), S.Context)); +} + +static void handleLockReturnedAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgsPlusParams(S, Attr, 1)) + return; + + if (!isFunction(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) LockReturnedAttr(Attr.getLoc(), S.Context)); +} + +static void handleLocksExcludedAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgsPlusParams(S, Attr, 1, /*moreok=*/true)) + return; + + if (!isFunction(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) LocksExcludedAttr(Attr.getLoc(), S.Context)); +} + + static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D, const AttributeList &Attr) { TypedefNameDecl *tDecl = dyn_cast<TypedefNameDecl>(D); @@ -3180,6 +3365,45 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_lockable: handleLockableAttr(S, D, Attr); break; + case AttributeList::AT_guarded_by: + handleGuardedByAttr(S, D, Attr); + break; + case AttributeList::AT_pt_guarded_by: + handleGuardedByAttr(S, D, Attr, /*pointer = */true); + break; + case AttributeList::AT_exclusive_lock_function: + handleLockFunAttr(S, D, Attr, /*exclusive = */true); + break; + case AttributeList::AT_exclusive_locks_required: + handleLocksRequiredAttr(S, D, Attr, /*exclusive = */true); + break; + case AttributeList::AT_exclusive_trylock_function: + handleTrylockFunAttr(S, D, Attr, /*exclusive = */true); + break; + case AttributeList::AT_lock_returned: + handleLockReturnedAttr(S, D, Attr); + break; + case AttributeList::AT_locks_excluded: + handleLocksExcludedAttr(S, D, Attr); + break; + case AttributeList::AT_shared_lock_function: + handleLockFunAttr(S, D, Attr); + break; + case AttributeList::AT_shared_locks_required: + handleLocksRequiredAttr(S, D, Attr); + break; + case AttributeList::AT_shared_trylock_function: + handleTrylockFunAttr(S, D, Attr); + break; + case AttributeList::AT_unlock_function: + handleUnlockFunAttr(S, D, Attr); + break; + case AttributeList::AT_acquired_before: + handleAcquireOrderAttr(S, D, Attr, /*before = */true); + break; + case AttributeList::AT_acquired_after: + handleAcquireOrderAttr(S, D, Attr, /*before = */false); + break; default: // Ask target about the attribute. |