Thread safety: added support for function scopes in attribute arguments.

This patch was written by DeLesley Hutchins.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139302 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Caitlin Sadowski 2011-09-08 17:42:31 +00:00
Родитель eff98fc356
Коммит ed9d84a211
7 изменённых файлов: 94 добавлений и 2 удалений

Просмотреть файл

@ -671,6 +671,9 @@ public:
/// \brief Whether this declaration is a parameter pack.
bool isParameterPack() const;
/// \brief returns true if this declaration is a template
bool isTemplateDecl() const;
/// \brief Whether this declaration is a function or function template.
bool isFunctionOrFunctionTemplate() const;

Просмотреть файл

@ -1244,6 +1244,10 @@ public:
void EnterDeclaratorContext(Scope *S, DeclContext *DC);
void ExitDeclaratorContext(Scope *S);
/// Push the parameters of D, which must be a function, into scope.
void ActOnReenterFunctionContext(Scope* S, Decl* D);
void ActOnExitFunctionContext() { PopDeclContext(); }
DeclContext *getFunctionLevelDeclContext();
/// getCurFunctionDecl - If inside of a function body, this returns a pointer

Просмотреть файл

@ -133,6 +133,10 @@ bool Decl::isFunctionOrFunctionTemplate() const {
return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this);
}
bool Decl::isTemplateDecl() const {
return isa<TemplateDecl>(this);
}
bool Decl::isDefinedOutsideFunctionOrMethod() const {
for (const DeclContext *DC = getDeclContext();
DC && !DC->isTranslationUnit();

Просмотреть файл

@ -759,8 +759,28 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA) {
ParsedAttributes Attrs(AttrFactory);
SourceLocation endLoc;
// If the Decl is templatized, add template parameters to scope.
bool HasTemplateScope = LA.D && LA.D->isTemplateDecl();
ParseScope TempScope(this, Scope::TemplateParamScope, HasTemplateScope);
if (HasTemplateScope)
Actions.ActOnReenterTemplateScope(Actions.CurScope, LA.D);
// If the Decl is on a function, add function parameters to the scope.
bool HasFunctionScope = LA.D && LA.D->isFunctionOrFunctionTemplate();
ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope, HasFunctionScope);
if (HasFunctionScope)
Actions.ActOnReenterFunctionContext(Actions.CurScope, LA.D);
ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc);
if (HasFunctionScope) {
Actions.ActOnExitFunctionContext();
FnScope.Exit(); // Pop scope, and remove Decls from IdResolver
}
if (HasTemplateScope) {
TempScope.Exit();
}
// Late parsed attributes must be attached to Decls by hand. If the
// LA.D is not set, then this was not done properly.
assert(LA.D && "No decl attached to late parsed attribute");

Просмотреть файл

@ -782,6 +782,29 @@ void Sema::ExitDeclaratorContext(Scope *S) {
// disappear.
}
void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) {
FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
if (FunctionTemplateDecl *TFD = dyn_cast_or_null<FunctionTemplateDecl>(D)) {
// We assume that the caller has already called
// ActOnReenterTemplateScope
FD = TFD->getTemplatedDecl();
}
if (!FD)
return;
PushDeclContext(S, FD);
for (unsigned P = 0, NumParams = FD->getNumParams(); P < NumParams; ++P) {
ParmVarDecl *Param = FD->getParamDecl(P);
// If the parameter has an identifier, then add it to the scope
if (Param->getIdentifier()) {
S->AddDecl(Param);
IdResolver.AddDecl(Param);
}
}
}
/// \brief Determine whether we allow overloading of the function
/// PrevDecl with another declaration.
///

Просмотреть файл

@ -304,8 +304,11 @@ static bool checkAttrArgsAreLockableObjs(Sema &S, Decl *D,
for(unsigned Idx = Sidx; Idx < Attr.getNumArgs(); ++Idx) {
Expr *ArgExp = Attr.getArg(Idx);
if (ArgExp->isTypeDependent())
continue;
if (ArgExp->isTypeDependent()) {
// FIXME -- need to processs this again on template instantiation
Args.push_back(ArgExp);
continue;
}
QualType ArgTy = ArgExp->getType();
@ -390,6 +393,7 @@ static void handleGuardedByAttr(Sema &S, Decl *D, const AttributeList &Attr,
return;
if (Arg->isTypeDependent())
// FIXME: handle attributes with dependent types
return;
// check that the argument is lockable object

Просмотреть файл

@ -1219,3 +1219,37 @@ struct Foomgoper {
};
//-----------------------------------------------------
// Parsing of member variables and function parameters
//------------------------------------------------------
Mu gmu;
class StaticMu {
static Mu statmu;
};
class FooLate {
public:
void foo1() __attribute__((exclusive_locks_required(gmu))) { }
void foo2() __attribute__((exclusive_locks_required(mu))) { }
void foo3(Mu *m) __attribute__((exclusive_locks_required(m))) { }
void foo3(FooLate *f) __attribute__((exclusive_locks_required(f->mu))) { }
void foo4(FooLate *f) __attribute__((exclusive_locks_required(f->mu)));
static void foo5() __attribute__((exclusive_locks_required(mu))); // \
expected-error {{invalid use of member 'mu' in static member function}}
template <class T>
void foo6() __attribute__((exclusive_locks_required(T::statmu))) { }
template <class T>
void foo7(T* f) __attribute__((exclusive_locks_required(f->mu))) { }
int a __attribute__((guarded_by(gmu)));
int b __attribute__((guarded_by(mu)));
int c __attribute__((guarded_by(this->mu)));
Mu mu;
};