[clang][ASTImporter] Add import of thread safety attributes.

Attributes of "C/C++ Thread safety attributes" section in Attr.td
are added to ASTImporter. The not added attributes from this section
do not need special import handling.

Reviewed By: martong

Differential Revision: https://reviews.llvm.org/D110528
This commit is contained in:
Balázs Kéri 2021-10-05 12:24:34 +02:00
parent 471b25e217
commit bcefea80a4
2 changed files with 334 additions and 0 deletions

View File

@ -8634,6 +8634,174 @@ Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) {
return ToAttrOrErr.takeError();
break;
}
case attr::AcquireCapability: {
const auto *From = cast<AcquireCapabilityAttr>(FromAttr);
AttrImporter AI(*this);
Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
From, AI.importArrayArg(From->args(), From->args_size()).value(),
From->args_size());
if (ToAttrOrErr)
ToAttr = *ToAttrOrErr;
else
return ToAttrOrErr.takeError();
break;
}
case attr::TryAcquireCapability: {
const auto *From = cast<TryAcquireCapabilityAttr>(FromAttr);
AttrImporter AI(*this);
Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
From, AI.importArg(From->getSuccessValue()).value(),
AI.importArrayArg(From->args(), From->args_size()).value(),
From->args_size());
if (ToAttrOrErr)
ToAttr = *ToAttrOrErr;
else
return ToAttrOrErr.takeError();
break;
}
case attr::ReleaseCapability: {
const auto *From = cast<ReleaseCapabilityAttr>(FromAttr);
AttrImporter AI(*this);
Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
From, AI.importArrayArg(From->args(), From->args_size()).value(),
From->args_size());
if (ToAttrOrErr)
ToAttr = *ToAttrOrErr;
else
return ToAttrOrErr.takeError();
break;
}
case attr::RequiresCapability: {
const auto *From = cast<RequiresCapabilityAttr>(FromAttr);
AttrImporter AI(*this);
Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
From, AI.importArrayArg(From->args(), From->args_size()).value(),
From->args_size());
if (ToAttrOrErr)
ToAttr = *ToAttrOrErr;
else
return ToAttrOrErr.takeError();
break;
}
case attr::GuardedBy: {
const auto *From = cast<GuardedByAttr>(FromAttr);
AttrImporter AI(*this);
Expected<Attr *> ToAttrOrErr =
AI.createImportedAttr(From, AI.importArg(From->getArg()).value());
if (ToAttrOrErr)
ToAttr = *ToAttrOrErr;
else
return ToAttrOrErr.takeError();
break;
}
case attr::PtGuardedBy: {
const auto *From = cast<PtGuardedByAttr>(FromAttr);
AttrImporter AI(*this);
Expected<Attr *> ToAttrOrErr =
AI.createImportedAttr(From, AI.importArg(From->getArg()).value());
if (ToAttrOrErr)
ToAttr = *ToAttrOrErr;
else
return ToAttrOrErr.takeError();
break;
}
case attr::AcquiredAfter: {
const auto *From = cast<AcquiredAfterAttr>(FromAttr);
AttrImporter AI(*this);
Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
From, AI.importArrayArg(From->args(), From->args_size()).value(),
From->args_size());
if (ToAttrOrErr)
ToAttr = *ToAttrOrErr;
else
return ToAttrOrErr.takeError();
break;
}
case attr::AcquiredBefore: {
const auto *From = cast<AcquiredBeforeAttr>(FromAttr);
AttrImporter AI(*this);
Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
From, AI.importArrayArg(From->args(), From->args_size()).value(),
From->args_size());
if (ToAttrOrErr)
ToAttr = *ToAttrOrErr;
else
return ToAttrOrErr.takeError();
break;
}
case attr::AssertExclusiveLock: {
const auto *From = cast<AssertExclusiveLockAttr>(FromAttr);
AttrImporter AI(*this);
Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
From, AI.importArrayArg(From->args(), From->args_size()).value(),
From->args_size());
if (ToAttrOrErr)
ToAttr = *ToAttrOrErr;
else
return ToAttrOrErr.takeError();
break;
}
case attr::AssertSharedLock: {
const auto *From = cast<AssertSharedLockAttr>(FromAttr);
AttrImporter AI(*this);
Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
From, AI.importArrayArg(From->args(), From->args_size()).value(),
From->args_size());
if (ToAttrOrErr)
ToAttr = *ToAttrOrErr;
else
return ToAttrOrErr.takeError();
break;
}
case attr::ExclusiveTrylockFunction: {
const auto *From = cast<ExclusiveTrylockFunctionAttr>(FromAttr);
AttrImporter AI(*this);
Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
From, AI.importArg(From->getSuccessValue()).value(),
AI.importArrayArg(From->args(), From->args_size()).value(),
From->args_size());
if (ToAttrOrErr)
ToAttr = *ToAttrOrErr;
else
return ToAttrOrErr.takeError();
break;
}
case attr::SharedTrylockFunction: {
const auto *From = cast<SharedTrylockFunctionAttr>(FromAttr);
AttrImporter AI(*this);
Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
From, AI.importArg(From->getSuccessValue()).value(),
AI.importArrayArg(From->args(), From->args_size()).value(),
From->args_size());
if (ToAttrOrErr)
ToAttr = *ToAttrOrErr;
else
return ToAttrOrErr.takeError();
break;
}
case attr::LockReturned: {
const auto *From = cast<LockReturnedAttr>(FromAttr);
AttrImporter AI(*this);
Expected<Attr *> ToAttrOrErr =
AI.createImportedAttr(From, AI.importArg(From->getArg()).value());
if (ToAttrOrErr)
ToAttr = *ToAttrOrErr;
else
return ToAttrOrErr.takeError();
break;
}
case attr::LocksExcluded: {
const auto *From = cast<LocksExcludedAttr>(FromAttr);
AttrImporter AI(*this);
Expected<Attr *> ToAttrOrErr = AI.createImportedAttr(
From, AI.importArrayArg(From->args(), From->args_size()).value(),
From->args_size());
if (ToAttrOrErr)
ToAttr = *ToAttrOrErr;
else
return ToAttrOrErr.takeError();
break;
}
default:
// FIXME: 'clone' copies every member but some of them should be imported.

View File

@ -6564,6 +6564,31 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportFormatAttr) {
EXPECT_EQ(FromAttr->getType()->getName(), ToAttr->getType()->getName());
}
TEST_P(ImportAttributes, ImportGuardedVar) {
GuardedVarAttr *FromAttr, *ToAttr;
importAttr<VarDecl>("int test __attribute__((guarded_var));", FromAttr,
ToAttr);
}
TEST_P(ImportAttributes, ImportPtGuardedVar) {
PtGuardedVarAttr *FromAttr, *ToAttr;
importAttr<VarDecl>("int *test __attribute__((pt_guarded_var));", FromAttr,
ToAttr);
}
TEST_P(ImportAttributes, ImportScopedLockable) {
ScopedLockableAttr *FromAttr, *ToAttr;
importAttr<CXXRecordDecl>("struct __attribute__((scoped_lockable)) test {};",
FromAttr, ToAttr);
}
TEST_P(ImportAttributes, ImportCapability) {
CapabilityAttr *FromAttr, *ToAttr;
importAttr<CXXRecordDecl>(
"struct __attribute__((capability(\"cap\"))) test {};", FromAttr, ToAttr);
EXPECT_EQ(FromAttr->getName(), ToAttr->getName());
}
TEST_P(ImportAttributes, ImportAssertCapability) {
AssertCapabilityAttr *FromAttr, *ToAttr;
importAttr<FunctionDecl>(
@ -6572,6 +6597,147 @@ TEST_P(ImportAttributes, ImportAssertCapability) {
checkImportVariadicArg(FromAttr->args(), ToAttr->args());
}
TEST_P(ImportAttributes, ImportAcquireCapability) {
AcquireCapabilityAttr *FromAttr, *ToAttr;
importAttr<FunctionDecl>(
"void test(int A1, int A2) __attribute__((acquire_capability(A1, A2)));",
FromAttr, ToAttr);
checkImportVariadicArg(FromAttr->args(), ToAttr->args());
}
TEST_P(ImportAttributes, ImportTryAcquireCapability) {
TryAcquireCapabilityAttr *FromAttr, *ToAttr;
importAttr<FunctionDecl>(
"void test(int A1, int A2) __attribute__((try_acquire_capability(1, A1, "
"A2)));",
FromAttr, ToAttr);
checkImported(FromAttr->getSuccessValue(), ToAttr->getSuccessValue());
checkImportVariadicArg(FromAttr->args(), ToAttr->args());
}
TEST_P(ImportAttributes, ImportReleaseCapability) {
ReleaseCapabilityAttr *FromAttr, *ToAttr;
importAttr<FunctionDecl>(
"void test(int A1, int A2) __attribute__((release_capability(A1, A2)));",
FromAttr, ToAttr);
checkImportVariadicArg(FromAttr->args(), ToAttr->args());
}
TEST_P(ImportAttributes, ImportRequiresCapability) {
RequiresCapabilityAttr *FromAttr, *ToAttr;
importAttr<FunctionDecl>(
"void test(int A1, int A2) __attribute__((requires_capability(A1, A2)));",
FromAttr, ToAttr);
checkImportVariadicArg(FromAttr->args(), ToAttr->args());
}
TEST_P(ImportAttributes, ImportNoThreadSafetyAnalysis) {
NoThreadSafetyAnalysisAttr *FromAttr, *ToAttr;
importAttr<FunctionDecl>(
"void test() __attribute__((no_thread_safety_analysis));", FromAttr,
ToAttr);
}
TEST_P(ImportAttributes, ImportGuardedBy) {
GuardedByAttr *FromAttr, *ToAttr;
importAttr<VarDecl>(
R"(
int G;
int test __attribute__((guarded_by(G)));
)",
FromAttr, ToAttr);
checkImported(FromAttr->getArg(), ToAttr->getArg());
}
TEST_P(ImportAttributes, ImportPtGuardedBy) {
PtGuardedByAttr *FromAttr, *ToAttr;
importAttr<VarDecl>(
R"(
int G;
int *test __attribute__((pt_guarded_by(G)));
)",
FromAttr, ToAttr);
checkImported(FromAttr->getArg(), ToAttr->getArg());
}
TEST_P(ImportAttributes, ImportAcquiredAfter) {
AcquiredAfterAttr *FromAttr, *ToAttr;
importAttr<VarDecl>(
R"(
struct __attribute__((lockable)) L {};
L A1;
L A2;
L test __attribute__((acquired_after(A1, A2)));
)",
FromAttr, ToAttr);
checkImportVariadicArg(FromAttr->args(), ToAttr->args());
}
TEST_P(ImportAttributes, ImportAcquiredBefore) {
AcquiredBeforeAttr *FromAttr, *ToAttr;
importAttr<VarDecl>(
R"(
struct __attribute__((lockable)) L {};
L A1;
L A2;
L test __attribute__((acquired_before(A1, A2)));
)",
FromAttr, ToAttr);
checkImportVariadicArg(FromAttr->args(), ToAttr->args());
}
TEST_P(ImportAttributes, ImportAssertExclusiveLock) {
AssertExclusiveLockAttr *FromAttr, *ToAttr;
importAttr<FunctionDecl>("void test(int A1, int A2) "
"__attribute__((assert_exclusive_lock(A1, A2)));",
FromAttr, ToAttr);
checkImportVariadicArg(FromAttr->args(), ToAttr->args());
}
TEST_P(ImportAttributes, ImportAssertSharedLock) {
AssertSharedLockAttr *FromAttr, *ToAttr;
importAttr<FunctionDecl>(
"void test(int A1, int A2) __attribute__((assert_shared_lock(A1, A2)));",
FromAttr, ToAttr);
checkImportVariadicArg(FromAttr->args(), ToAttr->args());
}
TEST_P(ImportAttributes, ImportExclusiveTrylockFunction) {
ExclusiveTrylockFunctionAttr *FromAttr, *ToAttr;
importAttr<FunctionDecl>(
"void test(int A1, int A2) __attribute__((exclusive_trylock_function(1, "
"A1, A2)));",
FromAttr, ToAttr);
checkImported(FromAttr->getSuccessValue(), ToAttr->getSuccessValue());
checkImportVariadicArg(FromAttr->args(), ToAttr->args());
}
TEST_P(ImportAttributes, ImportSharedTrylockFunction) {
SharedTrylockFunctionAttr *FromAttr, *ToAttr;
importAttr<FunctionDecl>(
"void test(int A1, int A2) __attribute__((shared_trylock_function(1, A1, "
"A2)));",
FromAttr, ToAttr);
checkImported(FromAttr->getSuccessValue(), ToAttr->getSuccessValue());
checkImportVariadicArg(FromAttr->args(), ToAttr->args());
}
TEST_P(ImportAttributes, ImportLockReturned) {
LockReturnedAttr *FromAttr, *ToAttr;
importAttr<FunctionDecl>(
"void test(int A1) __attribute__((lock_returned(A1)));", FromAttr,
ToAttr);
checkImported(FromAttr->getArg(), ToAttr->getArg());
}
TEST_P(ImportAttributes, ImportLocksExcluded) {
LocksExcludedAttr *FromAttr, *ToAttr;
importAttr<FunctionDecl>(
"void test(int A1, int A2) __attribute__((locks_excluded(A1, A2)));",
FromAttr, ToAttr);
checkImportVariadicArg(FromAttr->args(), ToAttr->args());
}
template <typename T>
auto ExtendWithOptions(const T &Values, const std::vector<std::string> &Args) {
auto Copy = Values;