]> granicus.if.org Git - clang/commitdiff
Instantiate attributes from the pattern record when instantiating
authorJohn McCall <rjmccall@apple.com>
Sun, 1 Aug 2010 02:01:53 +0000 (02:01 +0000)
committerJohn McCall <rjmccall@apple.com>
Sun, 1 Aug 2010 02:01:53 +0000 (02:01 +0000)
a class template.  Fixes rdar://problem/8243419.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109967 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/instantiate-attr.cpp

index ecd167d9a0752105825c89d47577ad2a7b7fc1ed..f676304b2fd12e0b1585769ab2e8fff59d3c1a1e 100644 (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,
index 60b8e927fd2891d70c1ddf20ed4ecd864aaf4a88..1a22abb2a1c22f2cfd63b7a6a2a2a1de096e2cf8 100644 (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();
   
index d1503695bc2927bd1bace262d98ffdc4c50b5137..ad96d7ae4e02d08ce3472cf6b280917bdc5b85fb 100644 (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;
 }
index e8291ed00d207cf3bcff5df4522baf647c877092..bbadb6375b5b9ae508598ed61aa9af03176970d6 100644 (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];
+}