Instantiate attributes from the pattern record when instantiating

a class template.  Fixes rdar://problem/8243419.

llvm-svn: 109967
This commit is contained in:
John McCall 2010-08-01 02:01:53 +00:00
parent d9900542a6
commit 6602bb1115
4 changed files with 31 additions and 13 deletions

View File

@ -3905,6 +3905,9 @@ public:
TemplateSpecializationKind TSK,
bool Complain = true);
void InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
Decl *Pattern, Decl *Inst);
bool
InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,

View File

@ -1206,6 +1206,9 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
bool MergeWithParentScope = !Instantiation->isDefinedOutsideFunctionOrMethod();
Sema::LocalInstantiationScope Scope(*this, MergeWithParentScope);
// Pull attributes from the pattern onto the instantiation.
InstantiateAttrs(TemplateArgs, Pattern, Instantiation);
// Start the definition of this instantiation.
Instantiation->startDefinition();

View File

@ -31,8 +31,6 @@ namespace {
DeclContext *Owner;
const MultiLevelTemplateArgumentList &TemplateArgs;
void InstantiateAttrs(Decl *Tmpl, Decl *New);
public:
typedef Sema::OwningExprResult OwningExprResult;
@ -144,28 +142,29 @@ bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
}
// FIXME: Is this still too simple?
void TemplateDeclInstantiator::InstantiateAttrs(Decl *Tmpl, Decl *New) {
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
Decl *Tmpl, Decl *New) {
for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr;
TmplAttr = TmplAttr->getNext()) {
// FIXME: This should be generalized to more than just the AlignedAttr.
if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) {
if (Aligned->isDependent()) {
// The alignment expression is not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(SemaRef,
EnterExpressionEvaluationContext Unevaluated(*this,
Action::Unevaluated);
OwningExprResult Result = SemaRef.SubstExpr(Aligned->getAlignmentExpr(),
TemplateArgs);
OwningExprResult Result = SubstExpr(Aligned->getAlignmentExpr(),
TemplateArgs);
if (!Result.isInvalid())
// FIXME: Is this the correct source location?
SemaRef.AddAlignedAttr(Aligned->getAlignmentExpr()->getExprLoc(),
New, Result.takeAs<Expr>());
AddAlignedAttr(Aligned->getAlignmentExpr()->getExprLoc(),
New, Result.takeAs<Expr>());
continue;
}
}
// FIXME: Is cloning correct for all attributes?
Attr *NewAttr = TmplAttr->clone(SemaRef.Context);
Attr *NewAttr = TmplAttr->clone(Context);
New->addAttr(NewAttr);
}
}
@ -234,7 +233,7 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
Typedef->setPreviousDeclaration(cast<TypedefDecl>(InstPrev));
}
InstantiateAttrs(D, Typedef);
SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef);
Typedef->setAccess(D->getAccess());
Owner->addDecl(Typedef);
@ -399,7 +398,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
if (Owner->isFunctionOrMethod())
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Var);
}
InstantiateAttrs(D, Var);
SemaRef.InstantiateAttrs(TemplateArgs, D, Var);
// Link instantiations of static data members back to the template from
// which they were instantiated.
@ -518,7 +517,7 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
return 0;
}
InstantiateAttrs(D, Field);
SemaRef.InstantiateAttrs(TemplateArgs, D, Field);
if (Invalid)
Field->setInvalidDecl();
@ -1975,7 +1974,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
Proto->getExtInfo()));
}
InstantiateAttrs(Tmpl, New);
SemaRef.InstantiateAttrs(TemplateArgs, Tmpl, New);
return false;
}

View File

@ -11,3 +11,16 @@ struct A {
int a[sizeof(A<int>) == 16 ? 1 : -1];
int a2[sizeof(A<int>::B) == 16 ? 1 : -1];
// rdar://problem/8243419
namespace test1 {
template <typename T> struct A {
int a;
T b[0];
} __attribute__((packed));
typedef A<unsigned long> type;
int test0[sizeof(type) == 4 ? 1 : -1];
int test1[__builtin_offsetof(type, a) == 0 ? 1 : -1];
int test2[__builtin_offsetof(type, b) == 4 ? 1 : -1];
}