Skip to content

Commit 5f41173

Browse files
committed
Warn on RequiresCapability attribute mismatch
1 parent 9f3728d commit 5f41173

File tree

4 files changed

+48
-1
lines changed

4 files changed

+48
-1
lines changed

clang/include/clang/Analysis/Analyses/ThreadSafety.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ namespace clang {
2626
class AnalysisDeclContext;
2727
class FunctionDecl;
2828
class NamedDecl;
29+
class Attr;
2930

3031
namespace threadSafety {
3132

@@ -230,6 +231,9 @@ class ThreadSafetyHandler {
230231
/// Warn that there is a cycle in acquired_before/after dependencies.
231232
virtual void handleBeforeAfterCycle(Name L1Name, SourceLocation Loc) {}
232233

234+
virtual void handleAttributeMismatch(const FunctionDecl *FD1,
235+
const FunctionDecl *FD2) {}
236+
233237
/// Called by the analysis when starting analysis of a function.
234238
/// Used to issue suggestions for changes to annotations.
235239
virtual void enterFunction(const FunctionDecl *FD) {}

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4033,7 +4033,9 @@ def warn_acquired_before : Warning<
40334033
def warn_acquired_before_after_cycle : Warning<
40344034
"cycle in acquired_before/after dependencies, starting with '%0'">,
40354035
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
4036-
4036+
def warn_attribute_mismatch : Warning<
4037+
"attribute mismatch between function definition and declaration of %0">,
4038+
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
40374039

40384040
// Thread safety warnings negative capabilities
40394041
def warn_acquire_requires_negative_cap : Warning<

clang/lib/Analysis/ThreadSafety.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2263,6 +2263,37 @@ static bool neverReturns(const CFGBlock *B) {
22632263
return false;
22642264
}
22652265

2266+
template <typename AttrT>
2267+
static SmallVector<const Expr *> collectAttrArgs(const FunctionDecl *FD) {
2268+
SmallVector<const Expr *> Args;
2269+
for (const AttrT *A : FD->specific_attrs<AttrT>()) {
2270+
for (const Expr *E : A->args())
2271+
Args.push_back(E);
2272+
}
2273+
2274+
return Args;
2275+
}
2276+
2277+
static void diagnoseMismatchedFunctionAttrs(const FunctionDecl *FD,
2278+
ThreadSafetyHandler &Handler) {
2279+
assert(FD);
2280+
FD = FD->getDefinition();
2281+
assert(FD);
2282+
auto FDArgs = collectAttrArgs<RequiresCapabilityAttr>(FD);
2283+
2284+
for (const FunctionDecl *D = FD->getPreviousDecl(); D;
2285+
D = D->getPreviousDecl()) {
2286+
auto DArgs = collectAttrArgs<RequiresCapabilityAttr>(D);
2287+
2288+
for (const Expr *E : FDArgs) {
2289+
if (!llvm::is_contained(DArgs, E)) {
2290+
// FD requires E, but D doesn't.
2291+
Handler.handleAttributeMismatch(FD, D);
2292+
}
2293+
}
2294+
}
2295+
}
2296+
22662297
/// Check a function's CFG for thread-safety violations.
22672298
///
22682299
/// We traverse the blocks in the CFG, compute the set of mutexes that are held
@@ -2282,6 +2313,9 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
22822313
const NamedDecl *D = walker.getDecl();
22832314
CurrentFunction = dyn_cast<FunctionDecl>(D);
22842315

2316+
if (CurrentFunction)
2317+
diagnoseMismatchedFunctionAttrs(CurrentFunction, Handler);
2318+
22852319
if (D->hasAttr<NoThreadSafetyAnalysisAttr>())
22862320
return;
22872321

clang/lib/Sema/AnalysisBasedWarnings.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,6 +2073,13 @@ class ThreadSafetyReporter : public clang::threadSafety::ThreadSafetyHandler {
20732073
Warnings.emplace_back(std::move(Warning), getNotes());
20742074
}
20752075

2076+
void handleAttributeMismatch(const FunctionDecl *FD1,
2077+
const FunctionDecl *FD2) override {
2078+
PartialDiagnosticAt Warning(FD2->getLocation(),
2079+
S.PDiag(diag::warn_attribute_mismatch) << FD1);
2080+
Warnings.emplace_back(std::move(Warning), getNotes());
2081+
}
2082+
20762083
void enterFunction(const FunctionDecl* FD) override {
20772084
CurrentFunction = FD;
20782085
}

0 commit comments

Comments
 (0)