From: Chris Lattner Date: Thu, 21 Feb 2008 00:48:22 +0000 (+0000) Subject: Correctly handle address space qualifiers in declspecs. This X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=74788ba1dc1dd836edd1956c1a4b071b2bb71574;p=clang Correctly handle address space qualifiers in declspecs. This allows us to correctly handle stuff like: _AS1 float *B; and to reject stuff like: _AS1 _AS2* x; git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47417 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index 69058ef1aa..9db0e0145e 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -1735,48 +1735,47 @@ Sema::DeclTy* Sema::ActOnLinkageSpec(SourceLocation Loc, return new LinkageSpecDecl(Loc, Language, dcl); } -void Sema::HandleDeclAttribute(Decl *New, AttributeList *rawAttr) { +void Sema::HandleDeclAttribute(Decl *New, AttributeList *Attr) { - switch (rawAttr->getKind()) { + switch (Attr->getKind()) { case AttributeList::AT_vector_size: if (ValueDecl *vDecl = dyn_cast(New)) { - QualType newType = HandleVectorTypeAttribute(vDecl->getType(), rawAttr); + QualType newType = HandleVectorTypeAttribute(vDecl->getType(), Attr); if (!newType.isNull()) // install the new vector type into the decl vDecl->setType(newType); } if (TypedefDecl *tDecl = dyn_cast(New)) { QualType newType = HandleVectorTypeAttribute(tDecl->getUnderlyingType(), - rawAttr); + Attr); if (!newType.isNull()) // install the new vector type into the decl tDecl->setUnderlyingType(newType); } break; case AttributeList::AT_ocu_vector_type: if (TypedefDecl *tDecl = dyn_cast(New)) - HandleOCUVectorTypeAttribute(tDecl, rawAttr); + HandleOCUVectorTypeAttribute(tDecl, Attr); else - Diag(rawAttr->getLoc(), + Diag(Attr->getLoc(), diag::err_typecheck_ocu_vector_not_typedef); break; case AttributeList::AT_address_space: if (TypedefDecl *tDecl = dyn_cast(New)) { QualType newType = HandleAddressSpaceTypeAttribute( tDecl->getUnderlyingType(), - rawAttr); - if (!newType.isNull()) // install the new addr spaced type into the decl - tDecl->setUnderlyingType(newType); + Attr); + tDecl->setUnderlyingType(newType); } else if (ValueDecl *vDecl = dyn_cast(New)) { QualType newType = HandleAddressSpaceTypeAttribute(vDecl->getType(), - rawAttr); - if (!newType.isNull()) // install the new addr spaced type into the decl - vDecl->setType(newType); + Attr); + // install the new addr spaced type into the decl + vDecl->setType(newType); } break; case AttributeList::AT_aligned: - HandleAlignedAttribute(New, rawAttr); + HandleAlignedAttribute(New, Attr); break; case AttributeList::AT_packed: - HandlePackedAttribute(New, rawAttr); + HandlePackedAttribute(New, Attr); break; default: // FIXME: add other attributes... @@ -1796,33 +1795,6 @@ void Sema::HandleDeclAttributes(Decl *New, AttributeList *declspec_prefix, } } -QualType Sema::HandleAddressSpaceTypeAttribute(QualType curType, - AttributeList *rawAttr) { - // check the attribute arguments. - if (rawAttr->getNumArgs() != 1) { - Diag(rawAttr->getLoc(), diag::err_attribute_wrong_number_arguments, - std::string("1")); - return QualType(); - } - Expr *addrSpaceExpr = static_cast(rawAttr->getArg(0)); - llvm::APSInt addrSpace(32); - if (!addrSpaceExpr->isIntegerConstantExpr(addrSpace, Context)) { - Diag(rawAttr->getLoc(), diag::err_attribute_address_space_not_int, - addrSpaceExpr->getSourceRange()); - return QualType(); - } - unsigned addressSpace = static_cast(addrSpace.getZExtValue()); - - // Zero is the default memory space, so no qualification is needed - if (addressSpace == 0) - return curType; - - // TODO: Should we convert contained types of address space - // qualified types here or or where they directly participate in conversions - // (i.e. elsewhere) - return Context.getASQualType(curType, addressSpace); -} - void Sema::HandleOCUVectorTypeAttribute(TypedefDecl *tDecl, AttributeList *rawAttr) { QualType curType = tDecl->getUnderlyingType(); diff --git a/Sema/SemaType.cpp b/Sema/SemaType.cpp index f17afd466d..2002bd3719 100644 --- a/Sema/SemaType.cpp +++ b/Sema/SemaType.cpp @@ -153,8 +153,20 @@ QualType Sema::ConvertDeclSpecToType(DeclSpec &DS) { llvm::SmallVector LeftOverAttrs; AttributeList *AL = DS.getAttributes(); 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 + // the LeftOverAttrs list for rechaining. + switch (ThisAttr->getKind()) { + default: break; + case AttributeList::AT_address_space: + Result = HandleAddressSpaceTypeAttribute(Result, ThisAttr); + delete ThisAttr; // Consume the attribute. + continue; + } LeftOverAttrs.push_back(ThisAttr); } @@ -172,6 +184,37 @@ QualType Sema::ConvertDeclSpecToType(DeclSpec &DS) { return Result; } +/// HandleAddressSpaceTypeAttribute - Process an address_space attribute on the +/// specified type. +QualType Sema::HandleAddressSpaceTypeAttribute(QualType Type, + 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." + if (Type.getAddressSpace()) { + Diag(Attr->getLoc(), diag::err_attribute_address_multiple_qualifiers); + return Type; + } + + // Check the attribute arguments. + if (Attr->getNumArgs() != 1) { + Diag(Attr->getLoc(), diag::err_attribute_wrong_number_arguments, + std::string("1")); + return Type; + } + Expr *ASArgExpr = static_cast(Attr->getArg(0)); + llvm::APSInt addrSpace(32); + if (!ASArgExpr->isIntegerConstantExpr(addrSpace, Context)) { + Diag(Attr->getLoc(), diag::err_attribute_address_space_not_int, + ASArgExpr->getSourceRange()); + return Type; + } + + unsigned ASIdx = static_cast(addrSpace.getZExtValue()); + return Context.getASQualType(Type, ASIdx); +} + + /// GetTypeForDeclarator - Convert the type for the specified declarator to Type /// instances. QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) { diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index b380b76d4c..882ca92e51 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -579,6 +579,8 @@ DIAG(err_ocuvector_component_access, ERROR, "vector component access limited to variables") DIAG(err_attribute_address_space_not_int, ERROR, "address space attribute requires an integer constant") +DIAG(err_attribute_address_multiple_qualifiers, ERROR, + "multiple address spaces specified for type") DIAG(warn_attribute_ignored, WARNING, "'%0' attribute ignored") DIAG(warn_attribute_ignored_for_field_of_type, WARNING,