]> granicus.if.org Git - clang/commitdiff
fix a bug handling type attributes in the declspec. declspec processing
authorChris Lattner <sabre@nondot.org>
Thu, 26 Jun 2008 06:27:57 +0000 (06:27 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 26 Jun 2008 06:27:57 +0000 (06:27 +0000)
used to mutate the attribute list for declspecs when the type was
converted, breaking the case where one declspec was shared by multiple
declarators.

This fixes rdar://6032532.

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

lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaType.cpp
test/CodeGen/address-space.c

index 89d0d4011f66857153417216c784dd9d71c618f1..278c8415d6eb913aa5b58532130f67147ab88ed8 100644 (file)
@@ -198,8 +198,8 @@ public:
   //===--------------------------------------------------------------------===//
   // Type Analysis / Processing: SemaType.cpp.
   //
-  QualType ConvertDeclSpecToType(DeclSpec &DS);
-  AttributeList *ProcessTypeAttributes(QualType &Result, AttributeList *AL);
+  QualType ConvertDeclSpecToType(const DeclSpec &DS);
+  void ProcessTypeAttributes(QualType &Result, const AttributeList *AL);
   QualType GetTypeForDeclarator(Declarator &D, Scope *S);
 
   
@@ -305,7 +305,7 @@ private:
   /// The raw attribute contains 1 argument, the id of the address space 
   /// for the type.
   QualType HandleAddressSpaceTypeAttribute(QualType curType, 
-                                           AttributeList *rawAttr);
+                                           const AttributeList *rawAttr);
 
   /// HandleModeTypeAttribute - this attribute modifies the width of a
   /// primitive type.  Note that this is a variable attribute, and not
index c2874106f4e400baacea51fb443c6e16a049b2d5..cdcdebae8171db5204637bb06213ef171b4bb0a7 100644 (file)
@@ -2350,17 +2350,7 @@ void Sema::HandleDeclAttribute(Decl *New, AttributeList *Attr) {
            diag::err_typecheck_ext_vector_not_typedef);
     break;
   case AttributeList::AT_address_space:
-    if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) {
-      QualType newType = HandleAddressSpaceTypeAttribute(
-                                                  tDecl->getUnderlyingType(), 
-                                                  Attr);
-      tDecl->setUnderlyingType(newType);
-    } else if (ValueDecl *vDecl = dyn_cast<ValueDecl>(New)) {
-      QualType newType = HandleAddressSpaceTypeAttribute(vDecl->getType(), 
-                                                         Attr);
-      // install the new addr spaced type into the decl
-      vDecl->setType(newType);
-    }
+    // Ignore this, this is a type attribute, handled by ProcessTypeAttributes.
     break;
   case AttributeList::AT_mode:
     if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) {
@@ -2430,10 +2420,25 @@ void Sema::HandleDeclAttribute(Decl *New, AttributeList *Attr) {
 
 void Sema::HandleDeclAttributes(Decl *New, AttributeList *declspec_prefix,
                                 AttributeList *declarator_postfix) {
+  if (declspec_prefix == 0 && declarator_postfix == 0) return;
+  
   while (declspec_prefix) {
     HandleDeclAttribute(New, declspec_prefix);
     declspec_prefix = declspec_prefix->getNext();
   }
+  
+  // If there are any type attributes that were in the declarator, apply them to
+  // its top level type.
+  if (ValueDecl *VD = dyn_cast<ValueDecl>(New)) {
+    QualType DT = VD->getType();
+    ProcessTypeAttributes(DT, declarator_postfix);
+    VD->setType(DT);
+  } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(New)) {
+    QualType DT = TD->getUnderlyingType();
+    ProcessTypeAttributes(DT, declarator_postfix);
+    TD->setUnderlyingType(DT);
+  }
+  
   while (declarator_postfix) {
     HandleDeclAttribute(New, declarator_postfix);
     declarator_postfix = declarator_postfix->getNext();
index d66b41d8e349c99ad46e3d028838964e41374fa3..b8e20e45be577f2fb5191aa74517771ec6db49c5 100644 (file)
@@ -21,7 +21,7 @@ using namespace clang;
 
 /// ConvertDeclSpecToType - Convert the specified declspec to the appropriate
 /// type object.  This returns null on error.
-QualType Sema::ConvertDeclSpecToType(DeclSpec &DS) {
+QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) {
   // FIXME: Should move the logic from DeclSpec::Finish to here for validity
   // checking.
   QualType Result;
@@ -168,8 +168,8 @@ QualType Sema::ConvertDeclSpecToType(DeclSpec &DS) {
   
   // See if there are any attributes on the declspec that apply to the type (as
   // opposed to the decl).
-  if (AttributeList *AL = DS.getAttributes())
-    DS.SetAttributes(ProcessTypeAttributes(Result, AL));
+  if (const AttributeList *AL = DS.getAttributes())
+    ProcessTypeAttributes(Result, AL);
     
   // Apply const/volatile/restrict qualifiers to T.
   if (unsigned TypeQuals = DS.getTypeQualifiers()) {
@@ -258,8 +258,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
       T = Context.getPointerType(T).getQualifiedType(DeclType.Ptr.TypeQuals);
         
       // See if there are any attributes on the pointer that apply to it.
-      if (AttributeList *AL = DeclType.Ptr.AttrList)
-        DeclType.Ptr.AttrList = ProcessTypeAttributes(T, AL);
+      if (const AttributeList *AL = DeclType.Ptr.AttrList)
+        ProcessTypeAttributes(T, AL);
         
       break;
     case DeclaratorChunk::Reference:
@@ -288,8 +288,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
         T.addRestrict();
         
       // See if there are any attributes on the pointer that apply to it.
-      if (AttributeList *AL = DeclType.Ref.AttrList)
-        DeclType.Ref.AttrList = ProcessTypeAttributes(T, AL);
+      if (const AttributeList *AL = DeclType.Ref.AttrList)
+        ProcessTypeAttributes(T, AL);
       break;
     case DeclaratorChunk::Array: {
       DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
@@ -513,46 +513,27 @@ Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
   return T.getAsOpaquePtr();
 }
 
-AttributeList *Sema::ProcessTypeAttributes(QualType &Result, AttributeList *AL){
+void Sema::ProcessTypeAttributes(QualType &Result, const AttributeList *AL) {
   // Scan through and apply attributes to this type where it makes sense.  Some
   // attributes (such as __address_space__, __vector_size__, etc) apply to the
   // type, but others can be present in the type specifiers even though they
-  // apply to the decl.  Here we apply and delete attributes that apply to the
-  // type and leave the others alone.
-  llvm::SmallVector<AttributeList *, 8> LeftOverAttrs;
-  while (AL) {
-    // Unlink this attribute from the chain, so we can process it independently.
-    AttributeList *ThisAttr = AL;
-    AL = AL->getNext();
-    ThisAttr->setNext(0);
-    
+  // apply to the decl.  Here we apply type attributes and ignore the rest.
+  for (; AL; AL = AL->getNext()) {
     // If this is an attribute we can handle, do so now, otherwise, add it to
     // the LeftOverAttrs list for rechaining.
-    switch (ThisAttr->getKind()) {
+    switch (AL->getKind()) {
     default: break;
     case AttributeList::AT_address_space:
-      Result = HandleAddressSpaceTypeAttribute(Result, ThisAttr);
-      delete ThisAttr;  // Consume the attribute.
+      Result = HandleAddressSpaceTypeAttribute(Result, AL);
       continue;
     }
-    
-    LeftOverAttrs.push_back(ThisAttr);
   }
-  
-  // Rechain any attributes that haven't been deleted to the DeclSpec.
-  AttributeList *List = 0;
-  for (unsigned i = 0, e = LeftOverAttrs.size(); i != e; ++i) {
-    LeftOverAttrs[i]->setNext(List);
-    List = LeftOverAttrs[i];
-  }
-  
-  return List;
 }
 
 /// HandleAddressSpaceTypeAttribute - Process an address_space attribute on the
 /// specified type.
 QualType Sema::HandleAddressSpaceTypeAttribute(QualType Type, 
-                                               AttributeList *Attr) {
+                                               const AttributeList *Attr) {
   // If this type is already address space qualified, reject it.
   // Clause 6.7.3 - Type qualifiers: "No type shall be qualified by qualifiers
   // for two or more different address spaces."
index 1c295a24570f9b1e7fcb5dda453ae8c0b48df869..0edad303ed98d15a4dc1426f714330d728555001 100644 (file)
@@ -1,9 +1,20 @@
 // RUN: clang -emit-llvm < %s 2>&1 | grep '@foo.*global.*addrspace(1)' &&
 // RUN: clang -emit-llvm < %s 2>&1 | grep '@ban.*global.*addrspace(1)' &&
-// RUN: clang -emit-llvm < %s 2>&1 | grep 'load.*addrspace(1)' | count 2
+// RUN: clang -emit-llvm < %s 2>&1 | grep 'load.*addrspace(1)' | count 2 &&
+// RUN: clang -emit-llvm < %s 2>&1 | grep 'load.*addrspace(2).. @A' &&
+// RUN: clang -emit-llvm < %s 2>&1 | grep 'load.*addrspace(2).. @B'
+
 int foo __attribute__((address_space(1)));
 int ban[10] __attribute__((address_space(1)));
 
 int bar() { return foo; }
 
 int baz(int i) { return ban[i]; }
+
+// Both A and B point into addrspace(2).
+__attribute__((address_space(2))) int *A, *B;
+
+void test3() {
+  *A = *B;
+}
+