Commit fa808037 authored by Richard Sandiford's avatar Richard Sandiford
Browse files

[AST][SVE] Add new Type queries for sizeless types

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.)

Differential Revision: https://reviews.llvm.org/D75570
parent 7420f969
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -264,6 +264,8 @@ public:
  // 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)
+9 −0
Original line number Diff line number Diff line
@@ -1926,6 +1926,15 @@ public:
  /// 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.

+16 −0
Original line number Diff line number Diff line
@@ -2182,6 +2182,22 @@ bool Type::isIncompleteType(NamedDecl **Def) const {
  }
}

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)
+1 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ add_clang_unittest(ASTTests
  Language.cpp
  NamedDeclPrinterTest.cpp
  RecursiveASTVisitorTest.cpp
  SizelessTypesTest.cpp
  SourceLocationTest.cpp
  StmtPrinterTest.cpp
  StructuralEquivalenceTest.cpp
+82 −0
Original line number Diff line number Diff line
//===- 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());
}