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.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52769 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2008-06-26 06:27:57 +00:00
Родитель 65e4af90e6
Коммит fca0ddd429
4 изменённых файлов: 44 добавлений и 47 удалений

Просмотреть файл

@ -198,8 +198,8 @@ public:
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// Type Analysis / Processing: SemaType.cpp. // Type Analysis / Processing: SemaType.cpp.
// //
QualType ConvertDeclSpecToType(DeclSpec &DS); QualType ConvertDeclSpecToType(const DeclSpec &DS);
AttributeList *ProcessTypeAttributes(QualType &Result, AttributeList *AL); void ProcessTypeAttributes(QualType &Result, const AttributeList *AL);
QualType GetTypeForDeclarator(Declarator &D, Scope *S); QualType GetTypeForDeclarator(Declarator &D, Scope *S);
@ -305,7 +305,7 @@ private:
/// The raw attribute contains 1 argument, the id of the address space /// The raw attribute contains 1 argument, the id of the address space
/// for the type. /// for the type.
QualType HandleAddressSpaceTypeAttribute(QualType curType, QualType HandleAddressSpaceTypeAttribute(QualType curType,
AttributeList *rawAttr); const AttributeList *rawAttr);
/// HandleModeTypeAttribute - this attribute modifies the width of a /// HandleModeTypeAttribute - this attribute modifies the width of a
/// primitive type. Note that this is a variable attribute, and not /// primitive type. Note that this is a variable attribute, and not

Просмотреть файл

@ -2350,17 +2350,7 @@ void Sema::HandleDeclAttribute(Decl *New, AttributeList *Attr) {
diag::err_typecheck_ext_vector_not_typedef); diag::err_typecheck_ext_vector_not_typedef);
break; break;
case AttributeList::AT_address_space: case AttributeList::AT_address_space:
if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) { // Ignore this, this is a type attribute, handled by ProcessTypeAttributes.
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);
}
break; break;
case AttributeList::AT_mode: case AttributeList::AT_mode:
if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) { 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, void Sema::HandleDeclAttributes(Decl *New, AttributeList *declspec_prefix,
AttributeList *declarator_postfix) { AttributeList *declarator_postfix) {
if (declspec_prefix == 0 && declarator_postfix == 0) return;
while (declspec_prefix) { while (declspec_prefix) {
HandleDeclAttribute(New, declspec_prefix); HandleDeclAttribute(New, declspec_prefix);
declspec_prefix = declspec_prefix->getNext(); 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) { while (declarator_postfix) {
HandleDeclAttribute(New, declarator_postfix); HandleDeclAttribute(New, declarator_postfix);
declarator_postfix = declarator_postfix->getNext(); declarator_postfix = declarator_postfix->getNext();

Просмотреть файл

@ -21,7 +21,7 @@ using namespace clang;
/// ConvertDeclSpecToType - Convert the specified declspec to the appropriate /// ConvertDeclSpecToType - Convert the specified declspec to the appropriate
/// type object. This returns null on error. /// 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 // FIXME: Should move the logic from DeclSpec::Finish to here for validity
// checking. // checking.
QualType Result; 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 // See if there are any attributes on the declspec that apply to the type (as
// opposed to the decl). // opposed to the decl).
if (AttributeList *AL = DS.getAttributes()) if (const AttributeList *AL = DS.getAttributes())
DS.SetAttributes(ProcessTypeAttributes(Result, AL)); ProcessTypeAttributes(Result, AL);
// Apply const/volatile/restrict qualifiers to T. // Apply const/volatile/restrict qualifiers to T.
if (unsigned TypeQuals = DS.getTypeQualifiers()) { if (unsigned TypeQuals = DS.getTypeQualifiers()) {
@ -258,8 +258,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
T = Context.getPointerType(T).getQualifiedType(DeclType.Ptr.TypeQuals); T = Context.getPointerType(T).getQualifiedType(DeclType.Ptr.TypeQuals);
// See if there are any attributes on the pointer that apply to it. // See if there are any attributes on the pointer that apply to it.
if (AttributeList *AL = DeclType.Ptr.AttrList) if (const AttributeList *AL = DeclType.Ptr.AttrList)
DeclType.Ptr.AttrList = ProcessTypeAttributes(T, AL); ProcessTypeAttributes(T, AL);
break; break;
case DeclaratorChunk::Reference: case DeclaratorChunk::Reference:
@ -288,8 +288,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
T.addRestrict(); T.addRestrict();
// See if there are any attributes on the pointer that apply to it. // See if there are any attributes on the pointer that apply to it.
if (AttributeList *AL = DeclType.Ref.AttrList) if (const AttributeList *AL = DeclType.Ref.AttrList)
DeclType.Ref.AttrList = ProcessTypeAttributes(T, AL); ProcessTypeAttributes(T, AL);
break; break;
case DeclaratorChunk::Array: { case DeclaratorChunk::Array: {
DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr; DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
@ -513,46 +513,27 @@ Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
return T.getAsOpaquePtr(); 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 // Scan through and apply attributes to this type where it makes sense. Some
// attributes (such as __address_space__, __vector_size__, etc) apply to the // attributes (such as __address_space__, __vector_size__, etc) apply to the
// type, but others can be present in the type specifiers even though they // 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 // apply to the decl. Here we apply type attributes and ignore the rest.
// type and leave the others alone. for (; AL; AL = AL->getNext()) {
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);
// If this is an attribute we can handle, do so now, otherwise, add it to // If this is an attribute we can handle, do so now, otherwise, add it to
// the LeftOverAttrs list for rechaining. // the LeftOverAttrs list for rechaining.
switch (ThisAttr->getKind()) { switch (AL->getKind()) {
default: break; default: break;
case AttributeList::AT_address_space: case AttributeList::AT_address_space:
Result = HandleAddressSpaceTypeAttribute(Result, ThisAttr); Result = HandleAddressSpaceTypeAttribute(Result, AL);
delete ThisAttr; // Consume the attribute.
continue; 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 /// HandleAddressSpaceTypeAttribute - Process an address_space attribute on the
/// specified type. /// specified type.
QualType Sema::HandleAddressSpaceTypeAttribute(QualType Type, QualType Sema::HandleAddressSpaceTypeAttribute(QualType Type,
AttributeList *Attr) { const AttributeList *Attr) {
// If this type is already address space qualified, reject it. // If this type is already address space qualified, reject it.
// Clause 6.7.3 - Type qualifiers: "No type shall be qualified by qualifiers // Clause 6.7.3 - Type qualifiers: "No type shall be qualified by qualifiers
// for two or more different address spaces." // for two or more different address spaces."

Просмотреть файл

@ -1,9 +1,20 @@
// RUN: clang -emit-llvm < %s 2>&1 | grep '@foo.*global.*addrspace(1)' && // 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 '@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 foo __attribute__((address_space(1)));
int ban[10] __attribute__((address_space(1))); int ban[10] __attribute__((address_space(1)));
int bar() { return foo; } int bar() { return foo; }
int baz(int i) { return ban[i]; } 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;
}