Teach clang to instantiate attributes on more declarations. Fixes PR7102.

llvm-svn: 104106
This commit is contained in:
Douglas Gregor 2010-05-19 03:39:53 +00:00
parent cbfbca14d0
commit 21553f5970
3 changed files with 60 additions and 9 deletions

View File

@ -1036,7 +1036,9 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
OldParm->getStorageClassAsWritten());
if (!NewParm)
return 0;
// FIXME: Instantiate attributes
// Mark the (new) default argument as uninstantiated (if any).
if (OldParm->hasUninstantiatedDefaultArg()) {
Expr *Arg = OldParm->getUninstantiatedDefaultArg();

View File

@ -31,7 +31,7 @@ namespace {
DeclContext *Owner;
const MultiLevelTemplateArgumentList &TemplateArgs;
void InstantiateAttrs(Decl *Tmpl, Decl *New);
bool InstantiateAttrs(Decl *Tmpl, Decl *New);
public:
typedef Sema::OwningExprResult OwningExprResult;
@ -143,7 +143,7 @@ bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
}
// FIXME: Is this too simple?
void TemplateDeclInstantiator::InstantiateAttrs(Decl *Tmpl, Decl *New) {
bool TemplateDeclInstantiator::InstantiateAttrs(Decl *Tmpl, Decl *New) {
for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr;
TmplAttr = TmplAttr->getNext()) {
@ -152,6 +152,8 @@ void TemplateDeclInstantiator::InstantiateAttrs(Decl *Tmpl, Decl *New) {
New->addAttr(NewAttr);
}
return false;
}
Decl *
@ -177,7 +179,9 @@ TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) {
D->getQualifier(),
D->getTargetNameLoc(),
D->getNamespace());
InstantiateAttrs(D, Inst);
Owner->addDecl(Inst);
return Inst;
}
@ -353,7 +357,8 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
Var->setAccess(D->getAccess());
Var->setUsed(D->isUsed());
InstantiateAttrs(D, Var);
// FIXME: In theory, we could have a previous declaration for variables that
// are not static data members.
bool Redeclaration = false;
@ -531,6 +536,8 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
FriendDecl *FD =
FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(),
cast<NamedDecl>(NewND), D->getFriendLoc());
InstantiateAttrs(D, FD);
FD->setAccess(AS_public);
Owner->addDecl(FD);
return FD;
@ -564,6 +571,7 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
Enum->setInstantiationOfMemberEnum(D);
Enum->setAccess(D->getAccess());
if (SubstQualifier(D, Enum)) return 0;
InstantiateAttrs(D, Enum);
Owner->addDecl(Enum);
Enum->startDefinition();
@ -763,6 +771,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
PrevClassTemplate);
RecordInst->setDescribedClassTemplate(Inst);
InstantiateAttrs(D, Inst);
if (isFriend) {
if (PrevClassTemplate)
Inst->setAccess(PrevClassTemplate->getAccess());
@ -871,6 +881,8 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
!(isFriend && !D->getTemplatedDecl()->isThisDeclarationADefinition()))
InstTemplate->setInstantiatedFromMemberTemplate(D);
InstantiateAttrs(D, InstTemplate);
// Make declarations visible in the appropriate context.
if (!isFriend)
Owner->addDecl(InstTemplate);
@ -895,6 +907,8 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
D->getLocation(), D->getIdentifier(),
D->getTagKeywordLoc(), PrevDecl);
InstantiateAttrs(D, Record);
// Substitute the nested name specifier, if any.
if (SubstQualifier(D, Record))
return 0;
@ -1422,6 +1436,7 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl(
TTPT->getName(),
D->wasDeclaredWithTypename(),
D->isParameterPack());
InstantiateAttrs(D, Inst);
if (D->hasDefaultArgument())
Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false);
@ -1465,6 +1480,7 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl(
if (Invalid)
Param->setInvalidDecl();
InstantiateAttrs(D, Param);
Param->setDefaultArgument(D->getDefaultArgument());
// Introduce this template parameter's instantiation into the instantiation
@ -1494,7 +1510,8 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl(
D->getDepth() - 1, D->getPosition(),
D->getIdentifier(), InstParams);
Param->setDefaultArgument(D->getDefaultArgument());
InstantiateAttrs(D, Param);
// Introduce this template parameter's instantiation into the instantiation
// scope.
SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param);
@ -1512,6 +1529,8 @@ Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
D->getIdentLocation(),
D->getNominatedNamespace(),
D->getCommonAncestor());
InstantiateAttrs(D, Inst);
Owner->addDecl(Inst);
return Inst;
}
@ -1535,6 +1554,7 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
D->getTargetNestedNameDecl(),
D->getDeclName(),
D->isTypeName());
InstantiateAttrs(D, NewUD);
CXXScopeSpec SS;
SS.setScopeRep(D->getTargetNestedNameDecl());
@ -1615,8 +1635,10 @@ Decl * TemplateDeclInstantiator
D->getDeclName(), 0,
/*instantiation*/ true,
/*typename*/ true, D->getTypenameLoc());
if (UD)
if (UD) {
InstantiateAttrs(D, UD);
SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
}
return UD;
}
@ -1640,8 +1662,10 @@ Decl * TemplateDeclInstantiator
D->getDeclName(), 0,
/*instantiation*/ true,
/*typename*/ false, SourceLocation());
if (UD)
if (UD) {
InstantiateAttrs(D, UD);
SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
}
return UD;
}
@ -1820,8 +1844,9 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
return 0;
InstPartialSpec->setInstantiatedFromMember(PartialSpec);
InstPartialSpec->setTypeAsWritten(WrittenTy);
InstPartialSpec->setTypeAsWritten(WrittenTy);
InstantiateAttrs(PartialSpec, InstPartialSpec);
// Add this partial specialization to the set of class template partial
// specializations.
ClassTemplate->getPartialSpecializations().InsertNode(InstPartialSpec,
@ -1886,6 +1911,9 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
if (Tmpl->isDeleted())
New->setDeleted();
if (InstantiateAttrs(Tmpl, New))
return true;
// If we are performing substituting explicitly-specified template arguments
// or deduced template arguments into a function template and we reach this
// point, we are now past the point where SFINAE applies and have committed

View File

@ -6,3 +6,24 @@ struct X {
int __attribute__((__address_space__(N))) *ptr; // expected-error{{attribute requires 1 argument(s)}}
};
namespace PR7102 {
class NotTpl {
public:
union {
char space[11];
void* ptr;
} __attribute__((packed));
};
template<unsigned N>
class Tpl {
public:
union {
char space[N];
void* ptr;
} __attribute__((packed));
};
int array[sizeof(NotTpl) == sizeof(Tpl<11>)? 1 : -1];
}