aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaType.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /clang/lib/Sema/SemaType.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'clang/lib/Sema/SemaType.cpp')
-rw-r--r--clang/lib/Sema/SemaType.cpp701
1 files changed, 512 insertions, 189 deletions
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 3ab5d26a9a75..89d819a77dcb 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -19,9 +19,11 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeLocVisitor.h"
#include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
@@ -33,12 +35,13 @@
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateInstCallback.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include <bitset>
+#include <optional>
using namespace clang;
@@ -430,7 +433,7 @@ static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
if (onlyBlockPointers)
continue;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case DeclaratorChunk::BlockPointer:
result = &ptrChunk;
@@ -759,7 +762,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
/*NumExceptions=*/0,
/*NoexceptExpr=*/nullptr,
/*ExceptionSpecTokens=*/nullptr,
- /*DeclsInPrototype=*/None, loc, loc, declarator));
+ /*DeclsInPrototype=*/std::nullopt, loc, loc, declarator));
// For consistency, make sure the state still has us as processing
// the decl spec.
@@ -827,8 +830,8 @@ static bool checkOmittedBlockReturnType(Sema &S, Declarator &declarator,
/// Apply Objective-C type arguments to the given type.
static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
ArrayRef<TypeSourceInfo *> typeArgs,
- SourceRange typeArgsRange,
- bool failOnError = false) {
+ SourceRange typeArgsRange, bool failOnError,
+ bool rebuilding) {
// We can only apply type arguments to an Objective-C class type.
const auto *objcObjectType = type->getAs<ObjCObjectType>();
if (!objcObjectType || !objcObjectType->getInterface()) {
@@ -892,7 +895,9 @@ static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type,
}
}
- if (!diagnosed) {
+ // When rebuilding, qualifiers might have gotten here through a
+ // final substitution.
+ if (!rebuilding && !diagnosed) {
S.Diag(qual.getBeginLoc(), diag::err_objc_type_arg_qualified)
<< typeArg << typeArg.getQualifiers().getAsString()
<< FixItHint::CreateRemoval(rangeToRemove);
@@ -1054,22 +1059,18 @@ QualType Sema::BuildObjCTypeParamType(const ObjCTypeParamDecl *Decl,
return Result;
}
-QualType Sema::BuildObjCObjectType(QualType BaseType,
- SourceLocation Loc,
- SourceLocation TypeArgsLAngleLoc,
- ArrayRef<TypeSourceInfo *> TypeArgs,
- SourceLocation TypeArgsRAngleLoc,
- SourceLocation ProtocolLAngleLoc,
- ArrayRef<ObjCProtocolDecl *> Protocols,
- ArrayRef<SourceLocation> ProtocolLocs,
- SourceLocation ProtocolRAngleLoc,
- bool FailOnError) {
+QualType Sema::BuildObjCObjectType(
+ QualType BaseType, SourceLocation Loc, SourceLocation TypeArgsLAngleLoc,
+ ArrayRef<TypeSourceInfo *> TypeArgs, SourceLocation TypeArgsRAngleLoc,
+ SourceLocation ProtocolLAngleLoc, ArrayRef<ObjCProtocolDecl *> Protocols,
+ ArrayRef<SourceLocation> ProtocolLocs, SourceLocation ProtocolRAngleLoc,
+ bool FailOnError, bool Rebuilding) {
QualType Result = BaseType;
if (!TypeArgs.empty()) {
- Result = applyObjCTypeArgs(*this, Loc, Result, TypeArgs,
- SourceRange(TypeArgsLAngleLoc,
- TypeArgsRAngleLoc),
- FailOnError);
+ Result =
+ applyObjCTypeArgs(*this, Loc, Result, TypeArgs,
+ SourceRange(TypeArgsLAngleLoc, TypeArgsRAngleLoc),
+ FailOnError, Rebuilding);
if (FailOnError && Result.isNull())
return QualType();
}
@@ -1097,11 +1098,10 @@ TypeResult Sema::actOnObjCProtocolQualifierType(
SourceLocation rAngleLoc) {
// Form id<protocol-list>.
QualType Result = Context.getObjCObjectType(
- Context.ObjCBuiltinIdTy, { },
- llvm::makeArrayRef(
- (ObjCProtocolDecl * const *)protocols.data(),
- protocols.size()),
- false);
+ Context.ObjCBuiltinIdTy, {},
+ llvm::ArrayRef((ObjCProtocolDecl *const *)protocols.data(),
+ protocols.size()),
+ false);
Result = Context.getObjCObjectPointerType(Result);
TypeSourceInfo *ResultTInfo = Context.CreateTypeSourceInfo(Result);
@@ -1168,10 +1168,11 @@ TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers(
T, BaseTypeInfo->getTypeLoc().getSourceRange().getBegin(),
TypeArgsLAngleLoc, ActualTypeArgInfos, TypeArgsRAngleLoc,
ProtocolLAngleLoc,
- llvm::makeArrayRef((ObjCProtocolDecl * const *)Protocols.data(),
- Protocols.size()),
+ llvm::ArrayRef((ObjCProtocolDecl *const *)Protocols.data(),
+ Protocols.size()),
ProtocolLocs, ProtocolRAngleLoc,
- /*FailOnError=*/false);
+ /*FailOnError=*/false,
+ /*Rebuilding=*/false);
if (Result == T)
return BaseType;
@@ -1247,6 +1248,18 @@ getImageAccess(const ParsedAttributesView &Attrs) {
return OpenCLAccessAttr::Keyword_read_only;
}
+static UnaryTransformType::UTTKind
+TSTToUnaryTransformType(DeclSpec::TST SwitchTST) {
+ switch (SwitchTST) {
+#define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait) \
+ case TST_##Trait: \
+ return UnaryTransformType::Enum;
+#include "clang/Basic/TransformTypeTraits.def"
+ default:
+ llvm_unreachable("attempted to parse a non-unary transform builtin");
+ }
+}
+
/// Convert the specified declspec to the appropriate type
/// object.
/// \param state Specifies the declarator containing the declaration specifier
@@ -1369,7 +1382,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
}
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case DeclSpec::TST_int: {
if (DS.getTypeSpecSign() != TypeSpecifierSign::Unsigned) {
switch (DS.getTypeSpecWidth()) {
@@ -1575,6 +1588,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// TypeQuals handled by caller.
Result = Context.getTypeDeclType(D);
+ if (const auto *Using =
+ dyn_cast_or_null<UsingShadowDecl>(DS.getRepAsFoundDecl()))
+ Result = Context.getUsingType(Using, Result);
// In both C and C++, make an ElaboratedType.
ElaboratedTypeKeyword Keyword
@@ -1596,6 +1612,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// TypeQuals handled by caller.
break;
}
+ case DeclSpec::TST_typeof_unqualType:
case DeclSpec::TST_typeofType:
// FIXME: Preserve type source info.
Result = S.GetTypeFromParser(DS.getRepAsType());
@@ -1604,13 +1621,20 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
if (const TagType *TT = Result->getAs<TagType>())
S.DiagnoseUseOfDecl(TT->getDecl(), DS.getTypeSpecTypeLoc());
// TypeQuals handled by caller.
- Result = Context.getTypeOfType(Result);
+ Result = Context.getTypeOfType(
+ Result, DS.getTypeSpecType() == DeclSpec::TST_typeof_unqualType
+ ? TypeOfKind::Unqualified
+ : TypeOfKind::Qualified);
break;
+ case DeclSpec::TST_typeof_unqualExpr:
case DeclSpec::TST_typeofExpr: {
Expr *E = DS.getRepAsExpr();
assert(E && "Didn't get an expression for typeof?");
// TypeQuals handled by caller.
- Result = S.BuildTypeofExprType(E);
+ Result = S.BuildTypeofExprType(E, DS.getTypeSpecType() ==
+ DeclSpec::TST_typeof_unqualExpr
+ ? TypeOfKind::Unqualified
+ : TypeOfKind::Qualified);
if (Result.isNull()) {
Result = Context.IntTy;
declarator.setInvalidType(true);
@@ -1628,12 +1652,13 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
break;
}
- case DeclSpec::TST_underlyingType:
+#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case DeclSpec::TST_##Trait:
+#include "clang/Basic/TransformTypeTraits.def"
Result = S.GetTypeFromParser(DS.getRepAsType());
- assert(!Result.isNull() && "Didn't get a type for __underlying_type?");
- Result = S.BuildUnaryTransformType(Result,
- UnaryTransformType::EnumUnderlyingType,
- DS.getTypeSpecTypeLoc());
+ assert(!Result.isNull() && "Didn't get a type for the transformation?");
+ Result = S.BuildUnaryTransformType(
+ Result, TSTToUnaryTransformType(DS.getTypeSpecType()),
+ DS.getTypeSpecTypeLoc());
if (Result.isNull()) {
Result = Context.IntTy;
declarator.setInvalidType(true);
@@ -2158,7 +2183,7 @@ QualType Sema::BuildPointerType(QualType T,
return QualType();
}
- if (getLangOpts().HLSL) {
+ if (getLangOpts().HLSL && Loc.isValid()) {
Diag(Loc, diag::err_hlsl_pointers_unsupported) << 0;
return QualType();
}
@@ -2228,7 +2253,7 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
return QualType();
}
- if (getLangOpts().HLSL) {
+ if (getLangOpts().HLSL && Loc.isValid()) {
Diag(Loc, diag::err_hlsl_pointers_unsupported) << 1;
return QualType();
}
@@ -2379,6 +2404,23 @@ static ExprResult checkArraySize(Sema &S, Expr *&ArraySize,
return R;
}
+bool Sema::checkArrayElementAlignment(QualType EltTy, SourceLocation Loc) {
+ EltTy = Context.getBaseElementType(EltTy);
+ if (EltTy->isIncompleteType() || EltTy->isDependentType() ||
+ EltTy->isUndeducedType())
+ return true;
+
+ CharUnits Size = Context.getTypeSizeInChars(EltTy);
+ CharUnits Alignment = Context.getTypeAlignInChars(EltTy);
+
+ if (Size.isMultipleOf(Alignment))
+ return true;
+
+ Diag(Loc, diag::err_array_element_alignment)
+ << EltTy << Size.getQuantity() << Alignment.getQuantity();
+ return false;
+}
+
/// Build an array type.
///
/// \param T The type of each element in the array.
@@ -2462,6 +2504,9 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
return QualType();
}
+ if (!checkArrayElementAlignment(T, Loc))
+ return QualType();
+
// Do placeholder conversions on the array size expression.
if (ArraySize && ArraySize->hasPlaceholderType()) {
ExprResult Result = CheckPlaceholderExpr(ArraySize);
@@ -2584,12 +2629,10 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
if (T->isVariableArrayType() && !Context.getTargetInfo().isVLASupported()) {
// CUDA device code and some other targets don't support VLAs.
- targetDiag(Loc, (getLangOpts().CUDA && getLangOpts().CUDAIsDevice)
- ? diag::err_cuda_vla
- : diag::err_vla_unsupported)
- << ((getLangOpts().CUDA && getLangOpts().CUDAIsDevice)
- ? CurrentCUDATarget()
- : CFT_InvalidTarget);
+ bool IsCUDADevice = (getLangOpts().CUDA && getLangOpts().CUDAIsDevice);
+ targetDiag(Loc,
+ IsCUDADevice ? diag::err_cuda_vla : diag::err_vla_unsupported)
+ << (IsCUDADevice ? CurrentCUDATarget() : 0);
}
// If this is not C99, diagnose array size modifiers on non-VLAs.
@@ -2621,17 +2664,28 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr,
// can't already be a vector.
if ((!CurType->isDependentType() &&
(!CurType->isBuiltinType() || CurType->isBooleanType() ||
- (!CurType->isIntegerType() && !CurType->isRealFloatingType()))) ||
+ (!CurType->isIntegerType() && !CurType->isRealFloatingType())) &&
+ !CurType->isBitIntType()) ||
CurType->isArrayType()) {
Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << CurType;
return QualType();
}
+ // Only support _BitInt elements with byte-sized power of 2 NumBits.
+ if (CurType->isBitIntType()) {
+ unsigned NumBits = CurType->getAs<BitIntType>()->getNumBits();
+ if (!llvm::isPowerOf2_32(NumBits) || NumBits < 8) {
+ Diag(AttrLoc, diag::err_attribute_invalid_bitint_vector_type)
+ << (NumBits < 8);
+ return QualType();
+ }
+ }
if (SizeExpr->isTypeDependent() || SizeExpr->isValueDependent())
return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc,
VectorType::GenericVector);
- Optional<llvm::APSInt> VecSize = SizeExpr->getIntegerConstantExpr(Context);
+ std::optional<llvm::APSInt> VecSize =
+ SizeExpr->getIntegerConstantExpr(Context);
if (!VecSize) {
Diag(AttrLoc, diag::err_attribute_argument_type)
<< "vector_size" << AANT_ArgumentIntegerConstant
@@ -2697,8 +2751,19 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
return QualType();
}
+ // Only support _BitInt elements with byte-sized power of 2 NumBits.
+ if (T->isBitIntType()) {
+ unsigned NumBits = T->getAs<BitIntType>()->getNumBits();
+ if (!llvm::isPowerOf2_32(NumBits) || NumBits < 8) {
+ Diag(AttrLoc, diag::err_attribute_invalid_bitint_vector_type)
+ << (NumBits < 8);
+ return QualType();
+ }
+ }
+
if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) {
- Optional<llvm::APSInt> vecSize = ArraySize->getIntegerConstantExpr(Context);
+ std::optional<llvm::APSInt> vecSize =
+ ArraySize->getIntegerConstantExpr(Context);
if (!vecSize) {
Diag(AttrLoc, diag::err_attribute_argument_type)
<< "ext_vector_type" << AANT_ArgumentIntegerConstant
@@ -2744,8 +2809,9 @@ QualType Sema::BuildMatrixType(QualType ElementTy, Expr *NumRows, Expr *NumCols,
return Context.getDependentSizedMatrixType(ElementTy, NumRows, NumCols,
AttrLoc);
- Optional<llvm::APSInt> ValueRows = NumRows->getIntegerConstantExpr(Context);
- Optional<llvm::APSInt> ValueColumns =
+ std::optional<llvm::APSInt> ValueRows =
+ NumRows->getIntegerConstantExpr(Context);
+ std::optional<llvm::APSInt> ValueColumns =
NumCols->getIntegerConstantExpr(Context);
auto const RowRange = NumRows->getSourceRange();
@@ -2810,7 +2876,8 @@ bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) {
}
// Functions cannot return half FP.
- if (T->isHalfType() && !getLangOpts().HalfArgsAndReturns) {
+ if (T->isHalfType() && !getLangOpts().NativeHalfArgsAndReturns &&
+ !Context.getTargetInfo().allowHalfArgsAndReturns()) {
Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 1 <<
FixItHint::CreateInsertion(Loc, "*");
return true;
@@ -2834,6 +2901,8 @@ bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) {
if (T.isVolatileQualified() && getLangOpts().CPlusPlus20)
Diag(Loc, diag::warn_deprecated_volatile_return) << T;
+ if (T.getAddressSpace() != LangAS::Default && getLangOpts().HLSL)
+ return true;
return false;
}
@@ -2916,7 +2985,8 @@ QualType Sema::BuildFunctionType(QualType T,
if (ParamType->isVoidType()) {
Diag(Loc, diag::err_param_with_void_type);
Invalid = true;
- } else if (ParamType->isHalfType() && !getLangOpts().HalfArgsAndReturns) {
+ } else if (ParamType->isHalfType() && !getLangOpts().NativeHalfArgsAndReturns &&
+ !Context.getTargetInfo().allowHalfArgsAndReturns()) {
// Disallow half FP arguments.
Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 0 <<
FixItHint::CreateInsertion(Loc, "*");
@@ -2992,7 +3062,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
return QualType();
}
- if (getLangOpts().HLSL) {
+ if (getLangOpts().HLSL && Loc.isValid()) {
Diag(Loc, diag::err_hlsl_pointers_unsupported) << 0;
return QualType();
}
@@ -3540,7 +3610,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
!D.getNumTypeObjects() &&
D.getDeclSpec().getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier)
break;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case DeclaratorContext::TemplateTypeArg:
Error = 10; // Template type argument
break;
@@ -3565,7 +3635,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
if (SemaRef.getLangOpts().CPlusPlus2b && IsCXXAutoType &&
!Auto->isDecltypeAuto())
break; // auto(x)
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case DeclaratorContext::TypeName:
case DeclaratorContext::Association:
Error = 15; // Generic
@@ -3834,7 +3904,7 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) {
case DeclaratorChunk::Paren:
if (&C == &Paren)
continue;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case DeclaratorChunk::Pointer:
StartsWithDeclaratorId = false;
continue;
@@ -4604,7 +4674,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
// Determine whether we should infer _Nonnull on pointer types.
- Optional<NullabilityKind> inferNullability;
+ std::optional<NullabilityKind> inferNullability;
bool inferNullabilityCS = false;
bool inferNullabilityInnerOnly = false;
bool inferNullabilityInnerOnlyComplete = false;
@@ -4637,8 +4707,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// inner pointers.
complainAboutMissingNullability = CAMN_InnerPointers;
- if (T->canHaveNullability(/*ResultIfUnknown*/false) &&
- !T->getNullability(S.Context)) {
+ if (T->canHaveNullability(/*ResultIfUnknown*/ false) &&
+ !T->getNullability()) {
// Note that we allow but don't require nullability on dependent types.
++NumPointersRemaining;
}
@@ -4674,7 +4744,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case DeclaratorContext::TrailingReturn:
case DeclaratorContext::TrailingReturnVar:
isFunctionOrMethod = true;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case DeclaratorContext::Member:
if (state.getDeclarator().isObjCIvar() && !isFunctionOrMethod) {
@@ -4683,12 +4753,17 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
// Weak properties are inferred to be nullable.
- if (state.getDeclarator().isObjCWeakProperty() && inAssumeNonNullRegion) {
- inferNullability = NullabilityKind::Nullable;
+ if (state.getDeclarator().isObjCWeakProperty()) {
+ // Weak properties cannot be nonnull, and should not complain about
+ // missing nullable attributes during completeness checks.
+ complainAboutMissingNullability = CAMN_No;
+ if (inAssumeNonNullRegion) {
+ inferNullability = NullabilityKind::Nullable;
+ }
break;
}
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case DeclaratorContext::File:
case DeclaratorContext::KNRTypeList: {
@@ -4843,7 +4918,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case CAMN_InnerPointers:
if (NumPointersRemaining == 0)
break;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case CAMN_Yes:
checkNullabilityConsistency(S, pointerKind, pointerLoc, pointerEndLoc);
@@ -4854,8 +4929,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// If the type itself could have nullability but does not, infer pointer
// nullability and perform consistency checking.
if (S.CodeSynthesisContexts.empty()) {
- if (T->canHaveNullability(/*ResultIfUnknown*/false) &&
- !T->getNullability(S.Context)) {
+ if (T->canHaveNullability(/*ResultIfUnknown*/ false) &&
+ !T->getNullability()) {
if (isVaList(T)) {
// Record that we've seen a pointer, but do nothing else.
if (NumPointersRemaining > 0)
@@ -4878,9 +4953,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
- if (complainAboutMissingNullability == CAMN_Yes &&
- T->isArrayType() && !T->getNullability(S.Context) && !isVaList(T) &&
- D.isPrototypeContext() &&
+ if (complainAboutMissingNullability == CAMN_Yes && T->isArrayType() &&
+ !T->getNullability() && !isVaList(T) && D.isPrototypeContext() &&
!hasOuterPointerLikeChunk(D, D.getNumTypeObjects())) {
checkNullabilityConsistency(S, SimplePointerKind::Array,
D.getDeclSpec().getTypeSpecTypeLoc());
@@ -5152,7 +5226,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
<< T << 0 /*pointer hint*/;
D.setInvalidType(true);
}
- } else if (!S.getLangOpts().HalfArgsAndReturns) {
+ } else if (!S.getLangOpts().NativeHalfArgsAndReturns &&
+ !S.Context.getTargetInfo().allowHalfArgsAndReturns()) {
S.Diag(D.getIdentifierLoc(),
diag::err_parameters_retval_cannot_have_fp16_type) << 1;
D.setInvalidType(true);
@@ -5301,14 +5376,19 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
} else {
// We allow a zero-parameter variadic function in C if the
// function is marked with the "overloadable" attribute. Scan
- // for this attribute now.
- if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus)
- if (!D.getDeclarationAttributes().hasAttribute(
- ParsedAttr::AT_Overloadable) &&
- !D.getAttributes().hasAttribute(ParsedAttr::AT_Overloadable) &&
- !D.getDeclSpec().getAttributes().hasAttribute(
- ParsedAttr::AT_Overloadable))
+ // for this attribute now. We also allow it in C2x per WG14 N2975.
+ if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus) {
+ if (LangOpts.C2x)
+ S.Diag(FTI.getEllipsisLoc(),
+ diag::warn_c17_compat_ellipsis_only_parameter);
+ else if (!D.getDeclarationAttributes().hasAttribute(
+ ParsedAttr::AT_Overloadable) &&
+ !D.getAttributes().hasAttribute(
+ ParsedAttr::AT_Overloadable) &&
+ !D.getDeclSpec().getAttributes().hasAttribute(
+ ParsedAttr::AT_Overloadable))
S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_param);
+ }
if (FTI.NumParams && FTI.Params[0].Param == nullptr) {
// C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function
@@ -5384,16 +5464,17 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
D.setInvalidType();
Param->setInvalidDecl();
}
- } else if (!S.getLangOpts().HalfArgsAndReturns) {
+ } else if (!S.getLangOpts().NativeHalfArgsAndReturns &&
+ !S.Context.getTargetInfo().allowHalfArgsAndReturns()) {
S.Diag(Param->getLocation(),
diag::err_parameters_retval_cannot_have_fp16_type) << 0;
D.setInvalidType();
}
} else if (!FTI.hasPrototype) {
- if (ParamTy->isPromotableIntegerType()) {
+ if (Context.isPromotableIntegerType(ParamTy)) {
ParamTy = Context.getPromotedIntegerType(ParamTy);
Param->setKNRPromoted(true);
- } else if (const BuiltinType* BTy = ParamTy->getAs<BuiltinType>()) {
+ } else if (const BuiltinType *BTy = ParamTy->getAs<BuiltinType>()) {
if (BTy->getKind() == BuiltinType::Float) {
ParamTy = Context.DoubleTy;
Param->setKNRPromoted(true);
@@ -5538,7 +5619,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// in ClsType; hence we wrap ClsType into an ElaboratedType.
// NOTE: in particular, no wrap occurs if ClsType already is an
// Elaborated, DependentName, or DependentTemplateSpecialization.
- if (NNSPrefix && isa<TemplateSpecializationType>(NNS->getAsType()))
+ if (isa<TemplateSpecializationType>(NNS->getAsType()))
ClsType = Context.getElaboratedType(ETK_None, NNSPrefix, ClsType);
break;
}
@@ -5775,7 +5856,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
<< T << D.getSourceRange();
D.setEllipsisLoc(SourceLocation());
} else {
- T = Context.getPackExpansionType(T, None, /*ExpectPackInType=*/false);
+ T = Context.getPackExpansionType(T, std::nullopt,
+ /*ExpectPackInType=*/false);
}
break;
case DeclaratorContext::TemplateParam:
@@ -5788,7 +5870,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// parameter packs in the type of the non-type template parameter, then
// it expands those parameter packs.
if (T->containsUnexpandedParameterPack())
- T = Context.getPackExpansionType(T, None);
+ T = Context.getPackExpansionType(T, std::nullopt);
else
S.Diag(D.getEllipsisLoc(),
LangOpts.CPlusPlus11
@@ -5974,6 +6056,21 @@ static void fillAttributedTypeLoc(AttributedTypeLoc TL,
TL.setAttr(State.takeAttrForAttributedType(TL.getTypePtr()));
}
+static void fillMatrixTypeLoc(MatrixTypeLoc MTL,
+ const ParsedAttributesView &Attrs) {
+ for (const ParsedAttr &AL : Attrs) {
+ if (AL.getKind() == ParsedAttr::AT_MatrixType) {
+ MTL.setAttrNameLoc(AL.getLoc());
+ MTL.setAttrRowOperand(AL.getArgAsExpr(0));
+ MTL.setAttrColumnOperand(AL.getArgAsExpr(1));
+ MTL.setAttrOperandParensRange(SourceRange());
+ return;
+ }
+ }
+
+ llvm_unreachable("no matrix_type attribute found at the expected location!");
+}
+
namespace {
class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
Sema &SemaRef;
@@ -6048,18 +6145,20 @@ namespace {
}
void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
- assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
+ assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr ||
+ DS.getTypeSpecType() == DeclSpec::TST_typeof_unqualExpr);
TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
}
void VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
- assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType);
+ assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType ||
+ DS.getTypeSpecType() == DeclSpec::TST_typeof_unqualType);
TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
assert(DS.getRepAsType());
TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- TL.setUnderlyingTInfo(TInfo);
+ TL.setUnmodifiedTInfo(TInfo);
}
void VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
assert(DS.getTypeSpecType() == DeclSpec::TST_decltype);
@@ -6067,8 +6166,7 @@ namespace {
TL.setRParenLoc(DS.getTypeofParensRange().getEnd());
}
void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
- // FIXME: This holds only because we only have one unary transform.
- assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType);
+ assert(DS.isTransformTypeTrait(DS.getTypeSpecType()));
TL.setKWLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
assert(DS.getRepAsType());
@@ -6090,19 +6188,19 @@ namespace {
}
}
void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
- ElaboratedTypeKeyword Keyword
- = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
if (DS.getTypeSpecType() == TST_typename) {
TypeSourceInfo *TInfo = nullptr;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
- if (TInfo) {
- TL.copy(TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>());
- return;
- }
+ if (TInfo)
+ if (auto ETL = TInfo->getTypeLoc().getAs<ElaboratedTypeLoc>()) {
+ TL.copy(ETL);
+ return;
+ }
}
- TL.setElaboratedKeywordLoc(Keyword != ETK_None
- ? DS.getTypeSpecTypeLoc()
- : SourceLocation());
+ const ElaboratedType *T = TL.getTypePtr();
+ TL.setElaboratedKeywordLoc(T->getKeyword() != ETK_None
+ ? DS.getTypeSpecTypeLoc()
+ : SourceLocation());
const CXXScopeSpec& SS = DS.getTypeSpecScope();
TL.setQualifierLoc(SS.getWithLocInContext(Context));
Visit(TL.getNextTypeLoc().getUnqualifiedLoc());
@@ -6158,6 +6256,9 @@ namespace {
void VisitTagTypeLoc(TagTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
}
+ void VisitUsingTypeLoc(UsingTypeLoc TL) {
+ TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
+ }
void VisitAtomicTypeLoc(AtomicTypeLoc TL) {
// An AtomicTypeLoc can come from either an _Atomic(...) type specifier
// or an _Atomic qualifier.
@@ -6339,6 +6440,9 @@ namespace {
VisitDependentSizedExtVectorTypeLoc(DependentSizedExtVectorTypeLoc TL) {
TL.setNameLoc(Chunk.Loc);
}
+ void VisitMatrixTypeLoc(MatrixTypeLoc TL) {
+ fillMatrixTypeLoc(TL, Chunk.getAttrs());
+ }
void VisitTypeLoc(TypeLoc TL) {
llvm_unreachable("unsupported TypeLoc kind in declarator!");
@@ -6386,21 +6490,6 @@ fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL,
"no address_space attribute found at the expected location!");
}
-static void fillMatrixTypeLoc(MatrixTypeLoc MTL,
- const ParsedAttributesView &Attrs) {
- for (const ParsedAttr &AL : Attrs) {
- if (AL.getKind() == ParsedAttr::AT_MatrixType) {
- MTL.setAttrNameLoc(AL.getLoc());
- MTL.setAttrRowOperand(AL.getArgAsExpr(0));
- MTL.setAttrColumnOperand(AL.getArgAsExpr(1));
- MTL.setAttrOperandParensRange(SourceRange());
- return;
- }
- }
-
- llvm_unreachable("no matrix_type attribute found at the expected location!");
-}
-
/// Create and instantiate a TypeSourceInfo with type source information.
///
/// \param T QualType referring to the type as written in source code.
@@ -6432,29 +6521,42 @@ GetTypeSourceInfoForDeclarator(TypeProcessingState &State,
CurrTL = ATL.getValueLoc().getUnqualifiedLoc();
}
- while (MacroQualifiedTypeLoc TL = CurrTL.getAs<MacroQualifiedTypeLoc>()) {
- TL.setExpansionLoc(
- State.getExpansionLocForMacroQualifiedType(TL.getTypePtr()));
- CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
- }
+ bool HasDesugaredTypeLoc = true;
+ while (HasDesugaredTypeLoc) {
+ switch (CurrTL.getTypeLocClass()) {
+ case TypeLoc::MacroQualified: {
+ auto TL = CurrTL.castAs<MacroQualifiedTypeLoc>();
+ TL.setExpansionLoc(
+ State.getExpansionLocForMacroQualifiedType(TL.getTypePtr()));
+ CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
+ break;
+ }
- while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) {
- fillAttributedTypeLoc(TL, State);
- CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
- }
+ case TypeLoc::Attributed: {
+ auto TL = CurrTL.castAs<AttributedTypeLoc>();
+ fillAttributedTypeLoc(TL, State);
+ CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
+ break;
+ }
- while (DependentAddressSpaceTypeLoc TL =
- CurrTL.getAs<DependentAddressSpaceTypeLoc>()) {
- fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs());
- CurrTL = TL.getPointeeTypeLoc().getUnqualifiedLoc();
- }
+ case TypeLoc::Adjusted:
+ case TypeLoc::BTFTagAttributed: {
+ CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
+ break;
+ }
- if (MatrixTypeLoc TL = CurrTL.getAs<MatrixTypeLoc>())
- fillMatrixTypeLoc(TL, D.getTypeObject(i).getAttrs());
+ case TypeLoc::DependentAddressSpace: {
+ auto TL = CurrTL.castAs<DependentAddressSpaceTypeLoc>();
+ fillDependentAddressSpaceTypeLoc(TL, D.getTypeObject(i).getAttrs());
+ CurrTL = TL.getPointeeTypeLoc().getUnqualifiedLoc();
+ break;
+ }
- // FIXME: Ordering here?
- while (AdjustedTypeLoc TL = CurrTL.getAs<AdjustedTypeLoc>())
- CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
+ default:
+ HasDesugaredTypeLoc = false;
+ break;
+ }
+ }
DeclaratorLocFiller(S.Context, State, D.getTypeObject(i)).Visit(CurrTL);
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
@@ -6539,7 +6641,7 @@ static bool BuildAddressSpaceIndex(Sema &S, LangAS &ASIdx,
const Expr *AddrSpace,
SourceLocation AttrLoc) {
if (!AddrSpace->isValueDependent()) {
- Optional<llvm::APSInt> OptAddrSpace =
+ std::optional<llvm::APSInt> OptAddrSpace =
AddrSpace->getIntegerConstantExpr(S.Context);
if (!OptAddrSpace) {
S.Diag(AttrLoc, diag::err_attribute_argument_type)
@@ -6707,6 +6809,8 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
// The keyword-based type attributes imply which address space to use.
ASIdx = S.getLangOpts().SYCLIsDevice ? Attr.asSYCLLangAS()
: Attr.asOpenCLLangAS();
+ if (S.getLangOpts().HLSL)
+ ASIdx = Attr.asHLSLLangAS();
if (ASIdx == LangAS::Default)
llvm_unreachable("Invalid address space");
@@ -7158,17 +7262,25 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
}
std::bitset<attr::LastAttr> Attrs;
- attr::Kind NewAttrKind = A->getKind();
QualType Desugared = Type;
- const AttributedType *AT = dyn_cast<AttributedType>(Type);
- while (AT) {
+ for (;;) {
+ if (const TypedefType *TT = dyn_cast<TypedefType>(Desugared)) {
+ Desugared = TT->desugar();
+ continue;
+ } else if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Desugared)) {
+ Desugared = ET->desugar();
+ continue;
+ }
+ const AttributedType *AT = dyn_cast<AttributedType>(Desugared);
+ if (!AT)
+ break;
Attrs[AT->getAttrKind()] = true;
Desugared = AT->getModifiedType();
- AT = dyn_cast<AttributedType>(Desugared);
}
// You cannot specify duplicate type attributes, so if the attribute has
// already been applied, flag it.
+ attr::Kind NewAttrKind = A->getKind();
if (Attrs[NewAttrKind]) {
S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact) << PAttr;
return true;
@@ -7189,14 +7301,11 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
return true;
}
- // Pointer type qualifiers can only operate on pointer types, but not
- // pointer-to-member types.
- //
- // FIXME: Should we really be disallowing this attribute if there is any
- // type sugar between it and the pointer (other than attributes)? Eg, this
- // disallows the attribute on a parenthesized pointer.
- // And if so, should we really allow *any* type attribute?
+ // Check the raw (i.e., desugared) Canonical type to see if it
+ // is a pointer type.
if (!isa<PointerType>(Desugared)) {
+ // Pointer type qualifiers can only operate on pointer types, but not
+ // pointer-to-member types.
if (Type->isMemberPointerType())
S.Diag(PAttr.getLoc(), diag::err_attribute_no_member_pointers) << PAttr;
else
@@ -7206,7 +7315,8 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
// Add address space to type based on its attributes.
LangAS ASIdx = LangAS::Default;
- uint64_t PtrWidth = S.Context.getTargetInfo().getPointerWidth(0);
+ uint64_t PtrWidth =
+ S.Context.getTargetInfo().getPointerWidth(LangAS::Default);
if (PtrWidth == 32) {
if (Attrs[attr::Ptr64])
ASIdx = LangAS::ptr64;
@@ -7300,7 +7410,7 @@ static bool checkNullabilityTypeSpecifier(TypeProcessingState &state,
// This (unlike the code above) looks through typedefs that might
// have nullability specifiers on them, which means we cannot
// provide a useful Fix-It.
- if (auto existingNullability = desugared->getNullability(S.Context)) {
+ if (auto existingNullability = desugared->getNullability()) {
if (nullability != *existingNullability) {
S.Diag(nullabilityLoc, diag::err_nullability_conflicting)
<< DiagNullabilityKind(nullability, isContextSensitive)
@@ -7399,7 +7509,7 @@ static bool checkObjCKindOfType(TypeProcessingState &state, QualType &type,
// If we started with an object pointer type, rebuild it.
if (ptrType) {
equivType = S.Context.getObjCObjectPointerType(equivType);
- if (auto nullability = type->getNullability(S.Context)) {
+ if (auto nullability = type->getNullability()) {
// We create a nullability attribute from the __kindof attribute.
// Make sure that will make sense.
assert(attr.getAttributeSpellingListIndex() == 0 &&
@@ -7714,7 +7824,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr,
case EST_NoexceptTrue:
case EST_NoThrow:
// Exception spec doesn't conflict with nothrow, so don't warn.
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case EST_Unparsed:
case EST_Uninstantiated:
case EST_DependentNoexcept:
@@ -7853,7 +7963,7 @@ void Sema::adjustMemberFunctionCC(QualType &T, bool IsStatic, bool IsCtorOrDtor,
CallingConv DefaultCC =
Context.getDefaultCallingConvention(IsVariadic, IsStatic);
- if (CurCC != DefaultCC || DefaultCC == ToCC)
+ if (CurCC != DefaultCC)
return;
if (hasExplicitCallingConv(T))
@@ -7960,7 +8070,7 @@ static bool verifyValidIntegerConstantExpr(Sema &S, const ParsedAttr &Attr,
llvm::APSInt &Result) {
const auto *AttrExpr = Attr.getArgAsExpr(0);
if (!AttrExpr->isTypeDependent()) {
- if (Optional<llvm::APSInt> Res =
+ if (std::optional<llvm::APSInt> Res =
AttrExpr->getIntegerConstantExpr(S.Context)) {
Result = *Res;
return true;
@@ -8315,6 +8425,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
case ParsedAttr::AT_OpenCLLocalAddressSpace:
case ParsedAttr::AT_OpenCLConstantAddressSpace:
case ParsedAttr::AT_OpenCLGenericAddressSpace:
+ case ParsedAttr::AT_HLSLGroupSharedAddressSpace:
case ParsedAttr::AT_AddressSpace:
HandleAddressSpaceTypeAttribute(type, attr, state);
attr.setUsedAsTypeAttr();
@@ -8443,7 +8554,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
// clang, so revert to attribute-based handling for C.
if (!state.getSema().getLangOpts().CPlusPlus)
break;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
FUNCTION_TYPE_ATTRS_CASELIST:
attr.setUsedAsTypeAttr();
@@ -9100,29 +9211,23 @@ QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
TagDecl *OwnedTagDecl) {
if (T.isNull())
return T;
- NestedNameSpecifier *NNS;
- if (SS.isValid())
- NNS = SS.getScopeRep();
- else {
- if (Keyword == ETK_None)
- return T;
- NNS = nullptr;
- }
- return Context.getElaboratedType(Keyword, NNS, T, OwnedTagDecl);
+ return Context.getElaboratedType(
+ Keyword, SS.isValid() ? SS.getScopeRep() : nullptr, T, OwnedTagDecl);
}
-QualType Sema::BuildTypeofExprType(Expr *E) {
+QualType Sema::BuildTypeofExprType(Expr *E, TypeOfKind Kind) {
assert(!E->hasPlaceholderType() && "unexpected placeholder");
if (!getLangOpts().CPlusPlus && E->refersToBitField())
- Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield) << 2;
+ Diag(E->getExprLoc(), diag::err_sizeof_alignof_typeof_bitfield)
+ << (Kind == TypeOfKind::Unqualified ? 3 : 2);
if (!E->isTypeDependent()) {
QualType T = E->getType();
if (const TagType *TT = T->getAs<TagType>())
DiagnoseUseOfDecl(TT->getDecl(), E->getExprLoc());
}
- return Context.getTypeOfExprType(E);
+ return Context.getTypeOfExprType(E, Kind);
}
/// getDecltypeForExpr - Given an expr, will return the decltype for
@@ -9207,39 +9312,257 @@ QualType Sema::BuildDecltypeType(Expr *E, bool AsUnevaluated) {
return Context.getDecltypeType(E, getDecltypeForExpr(E));
}
-QualType Sema::BuildUnaryTransformType(QualType BaseType,
- UnaryTransformType::UTTKind UKind,
- SourceLocation Loc) {
- switch (UKind) {
- case UnaryTransformType::EnumUnderlyingType:
- if (!BaseType->isDependentType() && !BaseType->isEnumeralType()) {
- Diag(Loc, diag::err_only_enums_have_underlying_types);
- return QualType();
- } else {
- QualType Underlying = BaseType;
- if (!BaseType->isDependentType()) {
- // The enum could be incomplete if we're parsing its definition or
- // recovering from an error.
- NamedDecl *FwdDecl = nullptr;
- if (BaseType->isIncompleteType(&FwdDecl)) {
- Diag(Loc, diag::err_underlying_type_of_incomplete_enum) << BaseType;
- Diag(FwdDecl->getLocation(), diag::note_forward_declaration) << FwdDecl;
- return QualType();
- }
+static QualType GetEnumUnderlyingType(Sema &S, QualType BaseType,
+ SourceLocation Loc) {
+ assert(BaseType->isEnumeralType());
+ EnumDecl *ED = BaseType->castAs<EnumType>()->getDecl();
+ assert(ED && "EnumType has no EnumDecl");
- EnumDecl *ED = BaseType->castAs<EnumType>()->getDecl();
- assert(ED && "EnumType has no EnumDecl");
+ S.DiagnoseUseOfDecl(ED, Loc);
- DiagnoseUseOfDecl(ED, Loc);
+ QualType Underlying = ED->getIntegerType();
+ assert(!Underlying.isNull());
- Underlying = ED->getIntegerType();
- assert(!Underlying.isNull());
- }
- return Context.getUnaryTransformType(BaseType, Underlying,
- UnaryTransformType::EnumUnderlyingType);
+ return Underlying;
+}
+
+QualType Sema::BuiltinEnumUnderlyingType(QualType BaseType,
+ SourceLocation Loc) {
+ if (!BaseType->isEnumeralType()) {
+ Diag(Loc, diag::err_only_enums_have_underlying_types);
+ return QualType();
+ }
+
+ // The enum could be incomplete if we're parsing its definition or
+ // recovering from an error.
+ NamedDecl *FwdDecl = nullptr;
+ if (BaseType->isIncompleteType(&FwdDecl)) {
+ Diag(Loc, diag::err_underlying_type_of_incomplete_enum) << BaseType;
+ Diag(FwdDecl->getLocation(), diag::note_forward_declaration) << FwdDecl;
+ return QualType();
+ }
+
+ return GetEnumUnderlyingType(*this, BaseType, Loc);
+}
+
+QualType Sema::BuiltinAddPointer(QualType BaseType, SourceLocation Loc) {
+ QualType Pointer = BaseType.isReferenceable() || BaseType->isVoidType()
+ ? BuildPointerType(BaseType.getNonReferenceType(), Loc,
+ DeclarationName())
+ : BaseType;
+
+ return Pointer.isNull() ? QualType() : Pointer;
+}
+
+QualType Sema::BuiltinRemovePointer(QualType BaseType, SourceLocation Loc) {
+ // We don't want block pointers or ObjectiveC's id type.
+ if (!BaseType->isAnyPointerType() || BaseType->isObjCIdType())
+ return BaseType;
+
+ return BaseType->getPointeeType();
+}
+
+QualType Sema::BuiltinDecay(QualType BaseType, SourceLocation Loc) {
+ QualType Underlying = BaseType.getNonReferenceType();
+ if (Underlying->isArrayType())
+ return Context.getDecayedType(Underlying);
+
+ if (Underlying->isFunctionType())
+ return BuiltinAddPointer(BaseType, Loc);
+
+ SplitQualType Split = Underlying.getSplitUnqualifiedType();
+ // std::decay is supposed to produce 'std::remove_cv', but since 'restrict' is
+ // in the same group of qualifiers as 'const' and 'volatile', we're extending
+ // '__decay(T)' so that it removes all qualifiers.
+ Split.Quals.removeCVRQualifiers();
+ return Context.getQualifiedType(Split);
+}
+
+QualType Sema::BuiltinAddReference(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc) {
+ assert(LangOpts.CPlusPlus);
+ QualType Reference =
+ BaseType.isReferenceable()
+ ? BuildReferenceType(BaseType,
+ UKind == UnaryTransformType::AddLvalueReference,
+ Loc, DeclarationName())
+ : BaseType;
+ return Reference.isNull() ? QualType() : Reference;
+}
+
+QualType Sema::BuiltinRemoveExtent(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc) {
+ if (UKind == UnaryTransformType::RemoveAllExtents)
+ return Context.getBaseElementType(BaseType);
+
+ if (const auto *AT = Context.getAsArrayType(BaseType))
+ return AT->getElementType();
+
+ return BaseType;
+}
+
+QualType Sema::BuiltinRemoveReference(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc) {
+ assert(LangOpts.CPlusPlus);
+ QualType T = BaseType.getNonReferenceType();
+ if (UKind == UTTKind::RemoveCVRef &&
+ (T.isConstQualified() || T.isVolatileQualified())) {
+ Qualifiers Quals;
+ QualType Unqual = Context.getUnqualifiedArrayType(T, Quals);
+ Quals.removeConst();
+ Quals.removeVolatile();
+ T = Context.getQualifiedType(Unqual, Quals);
+ }
+ return T;
+}
+
+QualType Sema::BuiltinChangeCVRQualifiers(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc) {
+ if ((BaseType->isReferenceType() && UKind != UTTKind::RemoveRestrict) ||
+ BaseType->isFunctionType())
+ return BaseType;
+
+ Qualifiers Quals;
+ QualType Unqual = Context.getUnqualifiedArrayType(BaseType, Quals);
+
+ if (UKind == UTTKind::RemoveConst || UKind == UTTKind::RemoveCV)
+ Quals.removeConst();
+ if (UKind == UTTKind::RemoveVolatile || UKind == UTTKind::RemoveCV)
+ Quals.removeVolatile();
+ if (UKind == UTTKind::RemoveRestrict)
+ Quals.removeRestrict();
+
+ return Context.getQualifiedType(Unqual, Quals);
+}
+
+static QualType ChangeIntegralSignedness(Sema &S, QualType BaseType,
+ bool IsMakeSigned,
+ SourceLocation Loc) {
+ if (BaseType->isEnumeralType()) {
+ QualType Underlying = GetEnumUnderlyingType(S, BaseType, Loc);
+ if (auto *BitInt = dyn_cast<BitIntType>(Underlying)) {
+ unsigned int Bits = BitInt->getNumBits();
+ if (Bits > 1)
+ return S.Context.getBitIntType(!IsMakeSigned, Bits);
+
+ S.Diag(Loc, diag::err_make_signed_integral_only)
+ << IsMakeSigned << /*_BitInt(1)*/ true << BaseType << 1 << Underlying;
+ return QualType();
+ }
+ if (Underlying->isBooleanType()) {
+ S.Diag(Loc, diag::err_make_signed_integral_only)
+ << IsMakeSigned << /*_BitInt(1)*/ false << BaseType << 1
+ << Underlying;
+ return QualType();
}
}
- llvm_unreachable("unknown unary transform type");
+
+ bool Int128Unsupported = !S.Context.getTargetInfo().hasInt128Type();
+ std::array<CanQualType *, 6> AllSignedIntegers = {
+ &S.Context.SignedCharTy, &S.Context.ShortTy, &S.Context.IntTy,
+ &S.Context.LongTy, &S.Context.LongLongTy, &S.Context.Int128Ty};
+ ArrayRef<CanQualType *> AvailableSignedIntegers(
+ AllSignedIntegers.data(), AllSignedIntegers.size() - Int128Unsupported);
+ std::array<CanQualType *, 6> AllUnsignedIntegers = {
+ &S.Context.UnsignedCharTy, &S.Context.UnsignedShortTy,
+ &S.Context.UnsignedIntTy, &S.Context.UnsignedLongTy,
+ &S.Context.UnsignedLongLongTy, &S.Context.UnsignedInt128Ty};
+ ArrayRef<CanQualType *> AvailableUnsignedIntegers(AllUnsignedIntegers.data(),
+ AllUnsignedIntegers.size() -
+ Int128Unsupported);
+ ArrayRef<CanQualType *> *Consider =
+ IsMakeSigned ? &AvailableSignedIntegers : &AvailableUnsignedIntegers;
+
+ uint64_t BaseSize = S.Context.getTypeSize(BaseType);
+ auto *Result =
+ llvm::find_if(*Consider, [&S, BaseSize](const CanQual<Type> *T) {
+ return BaseSize == S.Context.getTypeSize(T->getTypePtr());
+ });
+
+ assert(Result != Consider->end());
+ return QualType((*Result)->getTypePtr(), 0);
+}
+
+QualType Sema::BuiltinChangeSignedness(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc) {
+ bool IsMakeSigned = UKind == UnaryTransformType::MakeSigned;
+ if ((!BaseType->isIntegerType() && !BaseType->isEnumeralType()) ||
+ BaseType->isBooleanType() ||
+ (BaseType->isBitIntType() &&
+ BaseType->getAs<BitIntType>()->getNumBits() < 2)) {
+ Diag(Loc, diag::err_make_signed_integral_only)
+ << IsMakeSigned << BaseType->isBitIntType() << BaseType << 0;
+ return QualType();
+ }
+
+ bool IsNonIntIntegral =
+ BaseType->isChar16Type() || BaseType->isChar32Type() ||
+ BaseType->isWideCharType() || BaseType->isEnumeralType();
+
+ QualType Underlying =
+ IsNonIntIntegral
+ ? ChangeIntegralSignedness(*this, BaseType, IsMakeSigned, Loc)
+ : IsMakeSigned ? Context.getCorrespondingSignedType(BaseType)
+ : Context.getCorrespondingUnsignedType(BaseType);
+ if (Underlying.isNull())
+ return Underlying;
+ return Context.getQualifiedType(Underlying, BaseType.getQualifiers());
+}
+
+QualType Sema::BuildUnaryTransformType(QualType BaseType, UTTKind UKind,
+ SourceLocation Loc) {
+ if (BaseType->isDependentType())
+ return Context.getUnaryTransformType(BaseType, BaseType, UKind);
+ QualType Result;
+ switch (UKind) {
+ case UnaryTransformType::EnumUnderlyingType: {
+ Result = BuiltinEnumUnderlyingType(BaseType, Loc);
+ break;
+ }
+ case UnaryTransformType::AddPointer: {
+ Result = BuiltinAddPointer(BaseType, Loc);
+ break;
+ }
+ case UnaryTransformType::RemovePointer: {
+ Result = BuiltinRemovePointer(BaseType, Loc);
+ break;
+ }
+ case UnaryTransformType::Decay: {
+ Result = BuiltinDecay(BaseType, Loc);
+ break;
+ }
+ case UnaryTransformType::AddLvalueReference:
+ case UnaryTransformType::AddRvalueReference: {
+ Result = BuiltinAddReference(BaseType, UKind, Loc);
+ break;
+ }
+ case UnaryTransformType::RemoveAllExtents:
+ case UnaryTransformType::RemoveExtent: {
+ Result = BuiltinRemoveExtent(BaseType, UKind, Loc);
+ break;
+ }
+ case UnaryTransformType::RemoveCVRef:
+ case UnaryTransformType::RemoveReference: {
+ Result = BuiltinRemoveReference(BaseType, UKind, Loc);
+ break;
+ }
+ case UnaryTransformType::RemoveConst:
+ case UnaryTransformType::RemoveCV:
+ case UnaryTransformType::RemoveRestrict:
+ case UnaryTransformType::RemoveVolatile: {
+ Result = BuiltinChangeCVRQualifiers(BaseType, UKind, Loc);
+ break;
+ }
+ case UnaryTransformType::MakeSigned:
+ case UnaryTransformType::MakeUnsigned: {
+ Result = BuiltinChangeSignedness(BaseType, UKind, Loc);
+ break;
+ }
+ }
+
+ return !Result.isNull()
+ ? Context.getUnaryTransformType(BaseType, Result, UKind)
+ : Result;
}
QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {