Thread safety analysis: the NO_THREAD_SAFETY_ANALYSIS attribute will now

disable checking of arguments to the function, which is done by
-Wthread-safety-reference.

llvm-svn: 246806
This commit is contained in:
DeLesley Hutchins 2015-09-03 21:14:22 +00:00
parent 99d95328d6
commit 445a31cd4b
2 changed files with 86 additions and 23 deletions

View File

@ -1926,34 +1926,42 @@ void BuildLockset::VisitCallExpr(CallExpr *Exp) {
}
}
if (ExamineArgs) {
if (FunctionDecl *FD = Exp->getDirectCallee()) {
unsigned Fn = FD->getNumParams();
unsigned Cn = Exp->getNumArgs();
unsigned Skip = 0;
unsigned i = 0;
if (OperatorFun) {
if (isa<CXXMethodDecl>(FD)) {
// First arg in operator call is implicit self argument,
// and doesn't appear in the FunctionDecl.
Skip = 1;
Cn--;
} else {
// Ignore the first argument of operators; it's been checked above.
i = 1;
// NO_THREAD_SAFETY_ANALYSIS does double duty here. Normally it
// only turns off checking within the body of a function, but we also
// use it to turn off checking in arguments to the function. This
// could result in some false negatives, but the alternative is to
// create yet another attribute.
//
if (!FD->hasAttr<NoThreadSafetyAnalysisAttr>()) {
unsigned Fn = FD->getNumParams();
unsigned Cn = Exp->getNumArgs();
unsigned Skip = 0;
unsigned i = 0;
if (OperatorFun) {
if (isa<CXXMethodDecl>(FD)) {
// First arg in operator call is implicit self argument,
// and doesn't appear in the FunctionDecl.
Skip = 1;
Cn--;
} else {
// Ignore the first argument of operators; it's been checked above.
i = 1;
}
}
}
// Ignore default arguments
unsigned n = (Fn < Cn) ? Fn : Cn;
// Ignore default arguments
unsigned n = (Fn < Cn) ? Fn : Cn;
for (; i < n; ++i) {
ParmVarDecl* Pvd = FD->getParamDecl(i);
Expr* Arg = Exp->getArg(i+Skip);
QualType Qt = Pvd->getType();
if (Qt->isReferenceType())
checkAccess(Arg, AK_Read, POK_PassByRef);
for (; i < n; ++i) {
ParmVarDecl* Pvd = FD->getParamDecl(i);
Expr* Arg = Exp->getArg(i+Skip);
QualType Qt = Pvd->getType();
if (Qt->isReferenceType())
checkAccess(Arg, AK_Read, POK_PassByRef);
}
}
}
}

View File

@ -5091,3 +5091,58 @@ class Foo {
} // end namespace ScopedAdoptTest
namespace TestReferenceNoThreadSafetyAnalysis {
#define TS_UNCHECKED_READ(x) ts_unchecked_read(x)
// Takes a reference to a guarded data member, and returns an unguarded
// reference.
template <class T>
inline const T& ts_unchecked_read(const T& v) NO_THREAD_SAFETY_ANALYSIS {
return v;
}
template <class T>
inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS {
return v;
}
class Foo {
public:
Foo(): a(0) { }
int a;
};
class Bar {
public:
Bar() : a(0) { }
Mutex mu;
int a GUARDED_BY(mu);
Foo foo GUARDED_BY(mu);
};
void test() {
Bar bar;
const Bar cbar;
int a = TS_UNCHECKED_READ(bar.a); // nowarn
TS_UNCHECKED_READ(bar.a) = 1; // nowarn
int b = TS_UNCHECKED_READ(bar.foo).a; // nowarn
TS_UNCHECKED_READ(bar.foo).a = 1; // nowarn
int c = TS_UNCHECKED_READ(cbar.a); // nowarn
}
#undef TS_UNCHECKED_READ
} // end namespace TestReferenceNoThreadSafetyAnalysis