summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-06-26 06:27:57 +0000
committerChris Lattner <sabre@nondot.org>2008-06-26 06:27:57 +0000
commit4b413ea3bfa05d915b355298803c07071951c00e (patch)
tree6fc5c29c5ab8c218b00a1b57fc593c43a5725d11
parentdd7c10227b862a3de396a3e4a934cb6de6cfed81 (diff)
downloadbcm5719-llvm-4b413ea3bfa05d915b355298803c07071951c00e.tar.gz
bcm5719-llvm-4b413ea3bfa05d915b355298803c07071951c00e.zip
fix a bug handling type attributes in the declspec. declspec processing
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. llvm-svn: 52769
-rw-r--r--clang/lib/Sema/Sema.h6
-rw-r--r--clang/lib/Sema/SemaDecl.cpp27
-rw-r--r--clang/lib/Sema/SemaType.cpp45
-rw-r--r--clang/test/CodeGen/address-space.c13
4 files changed, 44 insertions, 47 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 89d0d4011f6..278c8415d6e 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -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
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index c2874106f4e..cdcdebae817 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -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();
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index d66b41d8e34..b8e20e45be5 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -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."
diff --git a/clang/test/CodeGen/address-space.c b/clang/test/CodeGen/address-space.c
index 1c295a24570..0edad303ed9 100644
--- a/clang/test/CodeGen/address-space.c
+++ b/clang/test/CodeGen/address-space.c
@@ -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;
+}
+
OpenPOWER on IntegriCloud