rsandifo-arm created this revision. rsandifo-arm added reviewers: sdesmalen, efriedma, rovka, rjmccall. Herald added subscribers: cfe-commits, psnobl, rkruppe, kristof.beyls, tschuett, mgorny. Herald added a reviewer: rengolin. Herald added a project: clang. rsandifo-arm added a comment. rsandifo-arm added a child revision: D75572: [Sema][SVE] Reject sizeof and alignof for sizeless types.
At the moment the queries just return true for SVE types, so an obvious alternative would be to check specifically for SVE types. The sizeless type concept is more general than that though. E.g. my understanding from: https://gcc.gnu.org/ml/gcc/2019-11/msg00092.html is that the RVV folks intend to use this too (both for clang and gcc). One of the defining features of the SVE ACLE types is that they are "sizeless"; see the SVE ACLE spec: https://developer.arm.com/docs/100987/0000/arm-c-language-extensions-for-sve or the email message: http://lists.llvm.org/pipermail/cfe-dev/2019-June/062523.html for a fuller definition of what that means. This patch adds two associated type queries: - isSizelessBuiltinType asks specifically about types that are built into clang. It is effectively an enum range check. - isSizelessType instead tests for any type that has the "sizeless" type property. At the moment it only returns true for the built-in types, but it seems better not to hard-code that assumption throughout the codebase. (E.g. we could in principle support some form of user-defined sizeless types in future. Even if that seems unlikely and never actually happens, the possibility at least exists.) Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D75570 Files: clang/include/clang/AST/CanonicalType.h clang/include/clang/AST/Type.h clang/lib/AST/Type.cpp clang/unittests/AST/CMakeLists.txt clang/unittests/AST/SizelessTypesTest.cpp
Index: clang/unittests/AST/SizelessTypesTest.cpp =================================================================== --- /dev/null +++ clang/unittests/AST/SizelessTypesTest.cpp @@ -0,0 +1,83 @@ +//===- unittests/AST/SizelessTypesTest.cpp --- Sizeless type tests --------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file contains tests for clang::Type queries related to sizeless types. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Type.h" +#include "clang/Tooling/Tooling.h" +#include "gtest/gtest.h" + +using namespace clang; + +struct SizelessTypeTester : public ::testing::Test { + // Declare an incomplete structure type. + std::unique_ptr<ASTUnit> AST = + tooling::buildASTFromCodeWithArgs("struct foo;", + {"-target", "aarch64-linux-gnu"}); + ASTContext &Ctx = AST->getASTContext(); + TranslationUnitDecl &TU = *Ctx.getTranslationUnitDecl(); + TypeDecl *Foo = cast<TypeDecl>(TU.lookup(&Ctx.Idents.get("foo")).front()); + const Type *FooTy = Foo->getTypeForDecl(); +}; + +TEST_F(SizelessTypeTester, TestSizelessBuiltin) { + ASSERT_TRUE(Ctx.SveInt8Ty->isSizelessBuiltinType()); + ASSERT_TRUE(Ctx.SveInt16Ty->isSizelessBuiltinType()); + ASSERT_TRUE(Ctx.SveInt32Ty->isSizelessBuiltinType()); + ASSERT_TRUE(Ctx.SveInt64Ty->isSizelessBuiltinType()); + + ASSERT_TRUE(Ctx.SveUint8Ty->isSizelessBuiltinType()); + ASSERT_TRUE(Ctx.SveUint16Ty->isSizelessBuiltinType()); + ASSERT_TRUE(Ctx.SveUint32Ty->isSizelessBuiltinType()); + ASSERT_TRUE(Ctx.SveUint64Ty->isSizelessBuiltinType()); + + ASSERT_TRUE(Ctx.SveFloat16Ty->isSizelessBuiltinType()); + ASSERT_TRUE(Ctx.SveFloat32Ty->isSizelessBuiltinType()); + ASSERT_TRUE(Ctx.SveFloat64Ty->isSizelessBuiltinType()); + + ASSERT_TRUE(Ctx.SveBoolTy->isSizelessBuiltinType()); + + ASSERT_FALSE(Ctx.VoidTy->isSizelessBuiltinType()); + ASSERT_FALSE(Ctx.PseudoObjectTy->isSizelessBuiltinType()); + ASSERT_FALSE(FooTy->isSizelessBuiltinType()); + + ASSERT_FALSE(Ctx.getPointerType(Ctx.SveBoolTy)->isSizelessBuiltinType()); + ASSERT_FALSE(Ctx.getLValueReferenceType(Ctx.SveBoolTy)-> + isSizelessBuiltinType()); + ASSERT_FALSE(Ctx.getRValueReferenceType(Ctx.SveBoolTy)-> + isSizelessBuiltinType()); +} + +TEST_F(SizelessTypeTester, TestSizeless) { + ASSERT_TRUE(Ctx.SveInt8Ty->isSizelessType()); + ASSERT_TRUE(Ctx.SveInt16Ty->isSizelessType()); + ASSERT_TRUE(Ctx.SveInt32Ty->isSizelessType()); + ASSERT_TRUE(Ctx.SveInt64Ty->isSizelessType()); + + ASSERT_TRUE(Ctx.SveUint8Ty->isSizelessType()); + ASSERT_TRUE(Ctx.SveUint16Ty->isSizelessType()); + ASSERT_TRUE(Ctx.SveUint32Ty->isSizelessType()); + ASSERT_TRUE(Ctx.SveUint64Ty->isSizelessType()); + + ASSERT_TRUE(Ctx.SveFloat16Ty->isSizelessType()); + ASSERT_TRUE(Ctx.SveFloat32Ty->isSizelessType()); + ASSERT_TRUE(Ctx.SveFloat64Ty->isSizelessType()); + + ASSERT_TRUE(Ctx.SveBoolTy->isSizelessType()); + + ASSERT_FALSE(Ctx.VoidTy->isSizelessType()); + ASSERT_FALSE(Ctx.PseudoObjectTy->isSizelessType()); + ASSERT_FALSE(FooTy->isSizelessType()); + + ASSERT_FALSE(Ctx.getPointerType(Ctx.SveBoolTy)->isSizelessType()); + ASSERT_FALSE(Ctx.getLValueReferenceType(Ctx.SveBoolTy)->isSizelessType()); + ASSERT_FALSE(Ctx.getRValueReferenceType(Ctx.SveBoolTy)->isSizelessType()); +} Index: clang/unittests/AST/CMakeLists.txt =================================================================== --- clang/unittests/AST/CMakeLists.txt +++ clang/unittests/AST/CMakeLists.txt @@ -29,6 +29,7 @@ NamedDeclPrinterTest.cpp OMPStructuredBlockTest.cpp RecursiveASTVisitorTest.cpp + SizelessTypesTest.cpp SourceLocationTest.cpp StmtPrinterTest.cpp StructuralEquivalenceTest.cpp Index: clang/lib/AST/Type.cpp =================================================================== --- clang/lib/AST/Type.cpp +++ clang/lib/AST/Type.cpp @@ -2182,6 +2182,24 @@ } } +bool Type::isSizelessBuiltinType() const { + if (const BuiltinType *BT = getAs<BuiltinType>()) { + switch (BT->getKind()) { + // SVE Types +#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id: +#include "clang/Basic/AArch64SVEACLETypes.def" + return true; + default: + return false; + } + } + return false; +} + +bool Type::isSizelessType() const { + return isSizelessBuiltinType(); +} + bool QualType::isPODType(const ASTContext &Context) const { // C++11 has a more relaxed definition of POD. if (Context.getLangOpts().CPlusPlus11) Index: clang/include/clang/AST/Type.h =================================================================== --- clang/include/clang/AST/Type.h +++ clang/include/clang/AST/Type.h @@ -1908,6 +1908,15 @@ /// or QualType::getSingleStepDesugaredType(const ASTContext&). QualType getLocallyUnqualifiedSingleStepDesugaredType() const; + /// As an extension, we classify types as one of "sized" or "sizeless"; + /// every type is one or the other. Standard types are all sized; + /// sizeless types are purely an extension. + /// + /// Sizeless types contain data with no specified size, alignment, + /// or layout. + bool isSizelessType() const; + bool isSizelessBuiltinType() const; + /// Types are partitioned into 3 broad categories (C99 6.2.5p1): /// object types, function types, and incomplete types. Index: clang/include/clang/AST/CanonicalType.h =================================================================== --- clang/include/clang/AST/CanonicalType.h +++ clang/include/clang/AST/CanonicalType.h @@ -264,6 +264,8 @@ // Type predicates LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isObjectType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSizelessType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSizelessBuiltinType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIncompleteOrObjectType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isVariablyModifiedType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegerType)
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits