forked from OSchip/llvm-project
Delayed template instantiation of late-parsed attributes.
llvm-svn: 148595
This commit is contained in:
parent
52ee45d64a
commit
30398dd410
|
@ -104,6 +104,8 @@ public:
|
|||
// Clone this attribute.
|
||||
virtual Attr* clone(ASTContext &C) const = 0;
|
||||
|
||||
virtual bool isLateParsed() const { return false; }
|
||||
|
||||
// Pretty print this attribute.
|
||||
virtual void printPretty(llvm::raw_ostream &OS, ASTContext &C) const = 0;
|
||||
|
||||
|
|
|
@ -5131,8 +5131,22 @@ public:
|
|||
TemplateSpecializationKind TSK,
|
||||
bool Complain = true);
|
||||
|
||||
struct LateInstantiatedAttribute {
|
||||
const Attr *TmplAttr;
|
||||
LocalInstantiationScope *Scope;
|
||||
Decl *NewDecl;
|
||||
|
||||
LateInstantiatedAttribute(const Attr *A, LocalInstantiationScope *S,
|
||||
Decl *D)
|
||||
: TmplAttr(A), Scope(S), NewDecl(D)
|
||||
{ }
|
||||
};
|
||||
typedef SmallVector<LateInstantiatedAttribute, 16> LateInstantiatedAttrVec;
|
||||
|
||||
void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||
const Decl *Pattern, Decl *Inst);
|
||||
const Decl *Pattern, Decl *Inst,
|
||||
LateInstantiatedAttrVec *LateAttrs = 0,
|
||||
LocalInstantiationScope *OuterMostScope = 0);
|
||||
|
||||
bool
|
||||
InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
|
||||
|
|
|
@ -268,6 +268,50 @@ namespace clang {
|
|||
Exited = true;
|
||||
}
|
||||
|
||||
/// \brief Clone this scope, and all outer scopes, down to the given
|
||||
/// outermost scope.
|
||||
LocalInstantiationScope *cloneScopes(LocalInstantiationScope *Outermost) {
|
||||
if (this == Outermost) return this;
|
||||
LocalInstantiationScope *newScope =
|
||||
new LocalInstantiationScope(SemaRef, CombineWithOuterScope);
|
||||
|
||||
newScope->Outer = 0;
|
||||
if (Outer)
|
||||
newScope->Outer = Outer->cloneScopes(Outermost);
|
||||
|
||||
newScope->PartiallySubstitutedPack = PartiallySubstitutedPack;
|
||||
newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack;
|
||||
newScope->NumArgsInPartiallySubstitutedPack =
|
||||
NumArgsInPartiallySubstitutedPack;
|
||||
|
||||
for (LocalDeclsMap::iterator I = LocalDecls.begin(), E = LocalDecls.end();
|
||||
I != E; ++I) {
|
||||
const Decl *D = I->first;
|
||||
llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored =
|
||||
newScope->LocalDecls[D];
|
||||
if (I->second.is<Decl *>()) {
|
||||
Stored = I->second.get<Decl *>();
|
||||
} else {
|
||||
DeclArgumentPack *OldPack = I->second.get<DeclArgumentPack *>();
|
||||
DeclArgumentPack *NewPack = new DeclArgumentPack(*OldPack);
|
||||
Stored = NewPack;
|
||||
newScope->ArgumentPacks.push_back(NewPack);
|
||||
}
|
||||
}
|
||||
return newScope;
|
||||
}
|
||||
|
||||
/// \brief deletes the given scope, and all otuer scopes, down to the
|
||||
/// given outermost scope.
|
||||
static void deleteScopes(LocalInstantiationScope *Scope,
|
||||
LocalInstantiationScope *Outermost) {
|
||||
while (Scope && Scope != Outermost) {
|
||||
LocalInstantiationScope *Out = Scope->Outer;
|
||||
delete Scope;
|
||||
Scope = Out;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Find the instantiation of the declaration D within the current
|
||||
/// instantiation scope.
|
||||
///
|
||||
|
@ -314,6 +358,8 @@ namespace clang {
|
|||
Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
|
||||
DeclContext *Owner;
|
||||
const MultiLevelTemplateArgumentList &TemplateArgs;
|
||||
Sema::LateInstantiatedAttrVec* LateAttrs;
|
||||
LocalInstantiationScope *StartingScope;
|
||||
|
||||
/// \brief A list of out-of-line class template partial
|
||||
/// specializations that will need to be instantiated after the
|
||||
|
@ -326,7 +372,7 @@ namespace clang {
|
|||
TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
|
||||
const MultiLevelTemplateArgumentList &TemplateArgs)
|
||||
: SemaRef(SemaRef), SubstIndex(SemaRef, -1), Owner(Owner),
|
||||
TemplateArgs(TemplateArgs) { }
|
||||
TemplateArgs(TemplateArgs), LateAttrs(0), StartingScope(0) { }
|
||||
|
||||
// FIXME: Once we get closer to completion, replace these manually-written
|
||||
// declarations with automatically-generated ones from
|
||||
|
@ -382,6 +428,21 @@ namespace clang {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Enable late instantiation of attributes. Late instantiated attributes
|
||||
// will be stored in LA.
|
||||
void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA) {
|
||||
LateAttrs = LA;
|
||||
StartingScope = SemaRef.CurrentInstantiationScope;
|
||||
}
|
||||
|
||||
// Disable late instantiation of attributes.
|
||||
void disableLateAttributeInstantiation() {
|
||||
LateAttrs = 0;
|
||||
StartingScope = 0;
|
||||
}
|
||||
|
||||
LocalInstantiationScope *getStartingScope() const { return StartingScope; }
|
||||
|
||||
typedef
|
||||
SmallVectorImpl<std::pair<ClassTemplateDecl *,
|
||||
ClassTemplatePartialSpecializationDecl *> >
|
||||
|
|
|
@ -857,7 +857,7 @@ void Parser::ParseThreadSafetyAttribute(IdentifierInfo &AttrName,
|
|||
ConsumeToken(); // Eat the comma, move to the next argument
|
||||
}
|
||||
// Match the ')'.
|
||||
if (ArgExprsOk && !T.consumeClose() && ArgExprs.size() > 0) {
|
||||
if (ArgExprsOk && !T.consumeClose()) {
|
||||
Attrs.addNew(&AttrName, AttrNameLoc, 0, AttrNameLoc, 0, SourceLocation(),
|
||||
ArgExprs.take(), ArgExprs.size());
|
||||
}
|
||||
|
|
|
@ -1654,6 +1654,10 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
|
|||
return Invalid;
|
||||
}
|
||||
|
||||
// Defined via #include from SemaTemplateInstantiateDecl.cpp
|
||||
Attr* instantiateTemplateAttribute(const Attr *At, ASTContext &C, Sema &S,
|
||||
const MultiLevelTemplateArgumentList &TemplateArgs);
|
||||
|
||||
/// \brief Instantiate the definition of a class from a given pattern.
|
||||
///
|
||||
/// \param PointOfInstantiation The point of instantiation within the
|
||||
|
@ -1763,6 +1767,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
|
|||
SmallVector<Decl*, 4> Fields;
|
||||
SmallVector<std::pair<FieldDecl*, FieldDecl*>, 4>
|
||||
FieldsWithMemberInitializers;
|
||||
// Delay instantiation of late parsed attributes.
|
||||
LateInstantiatedAttrVec LateAttrs;
|
||||
Instantiator.enableLateAttributeInstantiation(&LateAttrs);
|
||||
|
||||
for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
|
||||
MemberEnd = Pattern->decls_end();
|
||||
Member != MemberEnd; ++Member) {
|
||||
|
@ -1822,6 +1830,21 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
|
|||
}
|
||||
}
|
||||
|
||||
// Instantiate late parsed attributes, and attach them to their decls.
|
||||
// See Sema::InstantiateAttrs
|
||||
for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
|
||||
E = LateAttrs.end(); I != E; ++I) {
|
||||
assert(CurrentInstantiationScope == Instantiator.getStartingScope());
|
||||
CurrentInstantiationScope = I->Scope;
|
||||
Attr *NewAttr =
|
||||
instantiateTemplateAttribute(I->TmplAttr, Context, *this, TemplateArgs);
|
||||
I->NewDecl->addAttr(NewAttr);
|
||||
LocalInstantiationScope::deleteScopes(I->Scope,
|
||||
Instantiator.getStartingScope());
|
||||
}
|
||||
Instantiator.disableLateAttributeInstantiation();
|
||||
LateAttrs.clear();
|
||||
|
||||
if (!FieldsWithMemberInitializers.empty())
|
||||
ActOnFinishDelayedMemberInitializers(Instantiation);
|
||||
|
||||
|
|
|
@ -61,10 +61,13 @@ bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
|
|||
#include "clang/Sema/AttrTemplateInstantiate.inc"
|
||||
|
||||
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||
const Decl *Tmpl, Decl *New) {
|
||||
const Decl *Tmpl, Decl *New,
|
||||
LateInstantiatedAttrVec *LateAttrs,
|
||||
LocalInstantiationScope *OuterMostScope) {
|
||||
for (AttrVec::const_iterator i = Tmpl->attr_begin(), e = Tmpl->attr_end();
|
||||
i != e; ++i) {
|
||||
const Attr *TmplAttr = *i;
|
||||
|
||||
// FIXME: This should be generalized to more than just the AlignedAttr.
|
||||
if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) {
|
||||
if (Aligned->isAlignmentDependent()) {
|
||||
|
@ -89,9 +92,18 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
|
|||
}
|
||||
}
|
||||
|
||||
Attr *NewAttr =
|
||||
instantiateTemplateAttribute(TmplAttr, Context, *this, TemplateArgs);
|
||||
New->addAttr(NewAttr);
|
||||
if (TmplAttr->isLateParsed() && LateAttrs) {
|
||||
// Late parsed attributes must be instantiated and attached after the
|
||||
// enclosing class has been instantiated. See Sema::InstantiateClass.
|
||||
LocalInstantiationScope *Saved = 0;
|
||||
if (CurrentInstantiationScope)
|
||||
Saved = CurrentInstantiationScope->cloneScopes(OuterMostScope);
|
||||
LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New));
|
||||
} else {
|
||||
Attr *NewAttr =
|
||||
instantiateTemplateAttribute(TmplAttr, Context, *this, TemplateArgs);
|
||||
New->addAttr(NewAttr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -495,7 +507,7 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
SemaRef.InstantiateAttrs(TemplateArgs, D, Field);
|
||||
SemaRef.InstantiateAttrs(TemplateArgs, D, Field, LateAttrs, StartingScope);
|
||||
|
||||
if (Invalid)
|
||||
Field->setInvalidDecl();
|
||||
|
@ -2378,7 +2390,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
|
|||
// Get the definition. Leaves the variable unchanged if undefined.
|
||||
Tmpl->isDefined(Definition);
|
||||
|
||||
SemaRef.InstantiateAttrs(TemplateArgs, Definition, New);
|
||||
SemaRef.InstantiateAttrs(TemplateArgs, Definition, New,
|
||||
LateAttrs, StartingScope);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1051,14 +1051,12 @@ class Foo {
|
|||
public:
|
||||
void func(T x) {
|
||||
mu_.Lock();
|
||||
// count_ = x;
|
||||
count_ = x;
|
||||
mu_.Unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
// FIXME: This test passed earlier only because thread safety was turned
|
||||
// off for templates.
|
||||
// T count_ GUARDED_BY(mu_);
|
||||
T count_ GUARDED_BY(mu_);
|
||||
Bar<T> bar_;
|
||||
Mutex mu_;
|
||||
};
|
||||
|
@ -1790,27 +1788,15 @@ public:
|
|||
// Test dependent guarded_by
|
||||
T data GUARDED_BY(mu_);
|
||||
|
||||
void foo() {
|
||||
mu_.Lock();
|
||||
void fooEx() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
|
||||
data = 0;
|
||||
mu_.Unlock();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
class CellDelayed {
|
||||
public:
|
||||
// Test dependent guarded_by
|
||||
T data GUARDED_BY(mu_);
|
||||
|
||||
void foo() {
|
||||
mu_.Lock();
|
||||
data = 0;
|
||||
mu_.Unlock();
|
||||
}
|
||||
|
||||
Mutex mu_;
|
||||
};
|
||||
|
||||
void test() {
|
||||
|
@ -1842,13 +1828,50 @@ void test() {
|
|||
cell.data = 0; // \
|
||||
// expected-warning {{writing variable 'data' requires locking 'mu_' exclusively}}
|
||||
cell.foo();
|
||||
cell.mu_.Lock();
|
||||
cell.fooEx();
|
||||
cell.mu_.Unlock();
|
||||
}
|
||||
|
||||
// FIXME: This doesn't work yet
|
||||
// CellDelayed<int> celld;
|
||||
// celld.foo();
|
||||
|
||||
template <class T>
|
||||
class CellDelayed {
|
||||
public:
|
||||
// Test dependent guarded_by
|
||||
T data GUARDED_BY(mu_);
|
||||
|
||||
void fooEx(CellDelayed<T> *other) EXCLUSIVE_LOCKS_REQUIRED(mu_, other->mu_) {
|
||||
this->data = other->data;
|
||||
}
|
||||
|
||||
template <class T2>
|
||||
void fooExT(CellDelayed<T2> *otherT) EXCLUSIVE_LOCKS_REQUIRED(mu_, otherT->mu_) {
|
||||
this->data = otherT->data;
|
||||
}
|
||||
|
||||
void foo() {
|
||||
mu_.Lock();
|
||||
data = 0;
|
||||
mu_.Unlock();
|
||||
}
|
||||
|
||||
Mutex mu_;
|
||||
};
|
||||
|
||||
void testDelayed() {
|
||||
CellDelayed<int> celld;
|
||||
CellDelayed<int> celld2;
|
||||
celld.foo();
|
||||
celld.mu_.Lock();
|
||||
celld2.mu_.Lock();
|
||||
|
||||
celld.fooEx(&celld2);
|
||||
celld.fooExT(&celld2);
|
||||
|
||||
celld2.mu_.Unlock();
|
||||
celld.mu_.Unlock();
|
||||
}
|
||||
|
||||
}; // end namespace TestTemplateAttributeInstantiation
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -349,7 +349,7 @@ namespace {
|
|||
<< "Size;\n";
|
||||
OS << " }\n";
|
||||
OS << " unsigned " << getLowerName() << "_size() const {\n"
|
||||
<< " return " << getLowerName() << "Size;\n;";
|
||||
<< " return " << getLowerName() << "Size;\n";
|
||||
OS << " }";
|
||||
}
|
||||
void writeCloneArgs(raw_ostream &OS) const {
|
||||
|
@ -709,6 +709,11 @@ void ClangAttrClassEmitter::run(raw_ostream &OS) {
|
|||
<< "attr::" << R.getName() << "; }\n";
|
||||
OS << " static bool classof(const " << R.getName()
|
||||
<< "Attr *) { return true; }\n";
|
||||
|
||||
bool LateParsed = R.getValueAsBit("LateParsed");
|
||||
OS << " virtual bool isLateParsed() const { return "
|
||||
<< LateParsed << "; }\n";
|
||||
|
||||
OS << "};\n\n";
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue