diff options
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 44 | ||||
-rw-r--r-- | test/SemaTemplate/attributes.cpp | 21 |
3 files changed, 60 insertions, 9 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 0e4dfcb14c..e385585a52 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -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(); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 592b474dfb..2d67d080e8 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -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 diff --git a/test/SemaTemplate/attributes.cpp b/test/SemaTemplate/attributes.cpp index b696c5cd98..c578faba31 100644 --- a/test/SemaTemplate/attributes.cpp +++ b/test/SemaTemplate/attributes.cpp @@ -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]; +} |