Skip to content

Commit 800ce47

Browse files
committed
Warn on RequiresCapability attribute mismatch
1 parent ac02bf7 commit 800ce47

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
@@ -3978,7 +3978,9 @@ def warn_acquired_before : Warning<
39783978
def warn_acquired_before_after_cycle : Warning<
39793979
"cycle in acquired_before/after dependencies, starting with '%0'">,
39803980
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
3981-
3981+
def warn_attribute_mismatch : Warning<
3982+
"attribute mismatch between function definition and declaration of %0">,
3983+
InGroup<ThreadSafetyAnalysis>, DefaultIgnore;
39823984

39833985
// Thread safety warnings negative capabilities
39843986
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
@@ -2260,6 +2260,37 @@ static bool neverReturns(const CFGBlock *B) {
22602260
return false;
22612261
}
22622262

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

2313+
if (CurrentFunction)
2314+
diagnoseMismatchedFunctionAttrs(CurrentFunction, Handler);
2315+
22822316
if (D->hasAttr<NoThreadSafetyAnalysisAttr>())
22832317
return;
22842318

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)