diff options
| author | Leonard Chan <leonardchan@google.com> | 2019-01-24 00:11:35 +0000 |
|---|---|---|
| committer | Leonard Chan <leonardchan@google.com> | 2019-01-24 00:11:35 +0000 |
| commit | 009f9e82319e77c36afe7498f90283d29aa0b2d3 (patch) | |
| tree | 6c9e573750d4b570f3f999edb62bcd6697020c80 /clang/lib | |
| parent | ec0263027811f48b907224ede0dd24c33c1c7507 (diff) | |
| download | bcm5719-llvm-009f9e82319e77c36afe7498f90283d29aa0b2d3.tar.gz bcm5719-llvm-009f9e82319e77c36afe7498f90283d29aa0b2d3.zip | |
[Sema] Fix Modified Type in address_space AttributedType
This is a fix for https://reviews.llvm.org/D51229 where we pass the
address_space qualified type as the modified type of an AttributedType. This
change now instead wraps the AttributedType with either the address_space
qualifier or a DependentAddressSpaceType.
Differential Revision: https://reviews.llvm.org/D55447
llvm-svn: 351997
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/Type.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/AST/TypePrinter.cpp | 13 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaType.cpp | 97 |
3 files changed, 83 insertions, 28 deletions
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index ebbf105d98f..452ff6201a2 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -3205,6 +3205,7 @@ bool AttributedType::isQualifier() const { case attr::TypeNullable: case attr::TypeNullUnspecified: case attr::LifetimeBound: + case attr::AddressSpace: return true; // All other type attributes aren't qualifiers; they rewrite the modified diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 11f9ec33e94..a98b45bebd3 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -257,11 +257,17 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::FunctionProto: case Type::FunctionNoProto: case Type::Paren: - case Type::Attributed: case Type::PackExpansion: case Type::SubstTemplateTypeParm: CanPrefixQualifiers = false; break; + + case Type::Attributed: { + // We still want to print the address_space before the type if it is an + // address_space attribute. + const auto *AttrTy = cast<AttributedType>(T); + CanPrefixQualifiers = AttrTy->getAttrKind() == attr::AddressSpace; + } } return CanPrefixQualifiers; @@ -1377,7 +1383,10 @@ void TypePrinter::printAttributedBefore(const AttributedType *T, if (T->getAttrKind() == attr::ObjCKindOf) OS << "__kindof "; - printBefore(T->getModifiedType(), OS); + if (T->getAttrKind() == attr::AddressSpace) + printBefore(T->getEquivalentType(), OS); + else + printBefore(T->getModifiedType(), OS); if (T->isMSTypeSpec()) { switch (T->getAttrKind()) { diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 93b42829bba..b1aac72ea50 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -5787,28 +5787,27 @@ ParsedType Sema::ActOnObjCInstanceType(SourceLocation Loc) { // Type Attribute Processing //===----------------------------------------------------------------------===// -/// BuildAddressSpaceAttr - Builds a DependentAddressSpaceType if an expression -/// is uninstantiated. If instantiated it will apply the appropriate address space -/// to the type. This function allows dependent template variables to be used in -/// conjunction with the address_space attribute -QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, - SourceLocation AttrLoc) { +/// Build an AddressSpace index from a constant expression and diagnose any +/// errors related to invalid address_spaces. Returns true on successfully +/// building an AddressSpace index. +static bool BuildAddressSpaceIndex(Sema &S, LangAS &ASIdx, + const Expr *AddrSpace, + SourceLocation AttrLoc) { if (!AddrSpace->isValueDependent()) { - llvm::APSInt addrSpace(32); - if (!AddrSpace->isIntegerConstantExpr(addrSpace, Context)) { - Diag(AttrLoc, diag::err_attribute_argument_type) + if (!AddrSpace->isIntegerConstantExpr(addrSpace, S.Context)) { + S.Diag(AttrLoc, diag::err_attribute_argument_type) << "'address_space'" << AANT_ArgumentIntegerConstant << AddrSpace->getSourceRange(); - return QualType(); + return false; } // Bounds checking. if (addrSpace.isSigned()) { if (addrSpace.isNegative()) { - Diag(AttrLoc, diag::err_attribute_address_space_negative) + S.Diag(AttrLoc, diag::err_attribute_address_space_negative) << AddrSpace->getSourceRange(); - return QualType(); + return false; } addrSpace.setIsSigned(false); } @@ -5817,14 +5816,28 @@ QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, max = Qualifiers::MaxAddressSpace - (unsigned)LangAS::FirstTargetAddressSpace; if (addrSpace > max) { - Diag(AttrLoc, diag::err_attribute_address_space_too_high) + S.Diag(AttrLoc, diag::err_attribute_address_space_too_high) << (unsigned)max.getZExtValue() << AddrSpace->getSourceRange(); - return QualType(); + return false; } - LangAS ASIdx = + ASIdx = getLangASFromTargetAS(static_cast<unsigned>(addrSpace.getZExtValue())); + return true; + } + // Default value for DependentAddressSpaceTypes + ASIdx = LangAS::Default; + return true; +} + +/// BuildAddressSpaceAttr - Builds a DependentAddressSpaceType if an expression +/// is uninstantiated. If instantiated it will apply the appropriate address +/// space to the type. This function allows dependent template variables to be +/// used in conjunction with the address_space attribute +QualType Sema::BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace, + SourceLocation AttrLoc) { + if (!AddrSpace->isValueDependent()) { if (DiagnoseMultipleAddrSpaceAttributes(*this, T.getAddressSpace(), ASIdx, AttrLoc)) return QualType(); @@ -5845,6 +5858,14 @@ QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, return Context.getDependentAddressSpaceType(T, AddrSpace, AttrLoc); } +QualType Sema::BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, + SourceLocation AttrLoc) { + LangAS ASIdx; + if (!BuildAddressSpaceIndex(*this, ASIdx, AddrSpace, AttrLoc)) + return QualType(); + return BuildAddressSpaceAttr(T, ASIdx, AddrSpace, AttrLoc); +} + /// HandleAddressSpaceTypeAttribute - Process an address_space attribute on the /// specified type. The attribute contains 1 argument, the id of the address /// space for the type. @@ -5890,19 +5911,41 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, ASArgExpr = static_cast<Expr *>(Attr.getArgAsExpr(0)); } - // Create the DependentAddressSpaceType or append an address space onto - // the type. - QualType T = S.BuildAddressSpaceAttr(Type, ASArgExpr, Attr.getLoc()); + LangAS ASIdx; + if (!BuildAddressSpaceIndex(S, ASIdx, ASArgExpr, Attr.getLoc())) { + Attr.setInvalid(); + return; + } - if (!T.isNull()) { - ASTContext &Ctx = S.Context; - auto *ASAttr = ::new (Ctx) AddressSpaceAttr( - Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex(), - static_cast<unsigned>(T.getQualifiers().getAddressSpace())); - Type = State.getAttributedType(ASAttr, T, T); + ASTContext &Ctx = S.Context; + auto *ASAttr = ::new (Ctx) AddressSpaceAttr( + Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex(), + static_cast<unsigned>(ASIdx)); + + // If the expression is not value dependent (not templated), then we can + // apply the address space qualifiers just to the equivalent type. + // Otherwise, we make an AttributedType with the modified and equivalent + // type the same, and wrap it in a DependentAddressSpaceType. When this + // dependent type is resolved, the qualifier is added to the equivalent type + // later. + QualType T; + if (!ASArgExpr->isValueDependent()) { + QualType EquivType = + S.BuildAddressSpaceAttr(Type, ASIdx, ASArgExpr, Attr.getLoc()); + if (EquivType.isNull()) { + Attr.setInvalid(); + return; + } + T = State.getAttributedType(ASAttr, Type, EquivType); } else { - Attr.setInvalid(); + T = State.getAttributedType(ASAttr, Type, Type); + T = S.BuildAddressSpaceAttr(T, ASIdx, ASArgExpr, Attr.getLoc()); } + + if (!T.isNull()) + Type = T; + else + Attr.setInvalid(); } else { // The keyword-based type attributes imply which address space to use. ASIdx = Attr.asOpenCLLangAS(); @@ -7346,9 +7389,11 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, if (!IsTypeAttr) continue; } - } else if (TAL != TAL_DeclChunk) { + } else if (TAL != TAL_DeclChunk && + attr.getKind() != ParsedAttr::AT_AddressSpace) { // Otherwise, only consider type processing for a C++11 attribute if // it's actually been applied to a type. + // We also allow C++11 address_space attributes to pass through. continue; } } |

