]> granicus.if.org Git - clang/commitdiff
Teach clang to instantiate attributes on more declarations. Fixes PR7102.
authorDouglas Gregor <dgregor@apple.com>
Wed, 19 May 2010 03:39:53 +0000 (03:39 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 19 May 2010 03:39:53 +0000 (03:39 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104106 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/attributes.cpp

index 0e4dfcb14cb090cfe79c35315c0e0d0e8f8631fd..e385585a528d018263a20b2561c3dd481dbe88d5 100644 (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();
index 592b474dfb762b5f0cbf80c20a68a492d0c6f6de..2d67d080e862c505310d00edaa444ca9d863e373 100644 (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
index b696c5cd98401ecdc4917e21cae407e668d876fc..c578faba31a91f1b7d566202a37ba6ac48ca1d74 100644 (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];
+}