forked from OSchip/llvm-project
Teach clang to instantiate attributes on more declarations. Fixes PR7102.
llvm-svn: 104106
This commit is contained in:
parent
cbfbca14d0
commit
21553f5970
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue