зеркало из https://github.com/microsoft/clang.git
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:
Родитель
eff98fc356
Коммит
ed9d84a211
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче