diff options
Diffstat (limited to 'lib/Sema/SemaType.cpp')
| -rw-r--r-- | lib/Sema/SemaType.cpp | 504 |
1 files changed, 408 insertions, 96 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index f6ad132cde83..f3747eaa5cb5 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/Sema/SemaInternal.h" #include "TypeLocBuilder.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" @@ -22,7 +21,6 @@ #include "clang/AST/Expr.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeLocVisitor.h" -#include "clang/Lex/Preprocessor.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" @@ -30,9 +28,11 @@ #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -100,20 +100,27 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, case AttributeList::AT_ObjCGC: \ case AttributeList::AT_ObjCOwnership -// Function type attributes. -#define FUNCTION_TYPE_ATTRS_CASELIST \ - case AttributeList::AT_NoReturn: \ +// Calling convention attributes. +#define CALLING_CONV_ATTRS_CASELIST \ case AttributeList::AT_CDecl: \ case AttributeList::AT_FastCall: \ case AttributeList::AT_StdCall: \ case AttributeList::AT_ThisCall: \ case AttributeList::AT_Pascal: \ + case AttributeList::AT_SwiftCall: \ case AttributeList::AT_VectorCall: \ case AttributeList::AT_MSABI: \ case AttributeList::AT_SysVABI: \ - case AttributeList::AT_Regparm: \ case AttributeList::AT_Pcs: \ - case AttributeList::AT_IntelOclBicc + case AttributeList::AT_IntelOclBicc: \ + case AttributeList::AT_PreserveMost: \ + case AttributeList::AT_PreserveAll + +// Function type attributes. +#define FUNCTION_TYPE_ATTRS_CASELIST \ + case AttributeList::AT_NoReturn: \ + case AttributeList::AT_Regparm: \ + CALLING_CONV_ATTRS_CASELIST // Microsoft-specific type qualifiers. #define MS_TYPE_ATTRS_CASELIST \ @@ -239,7 +246,7 @@ namespace { savedAttrs.back()->setNext(nullptr); } }; -} +} // end anonymous namespace static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) { attr.setNext(head); @@ -727,6 +734,7 @@ static void diagnoseAndRemoveTypeQualifiers(Sema &S, const DeclSpec &DS, // it; they probably didn't mean to specify a redundant qualifier. typedef std::pair<DeclSpec::TQ, SourceLocation> QualLoc; for (QualLoc Qual : {QualLoc(DeclSpec::TQ_const, DS.getConstSpecLoc()), + QualLoc(DeclSpec::TQ_restrict, DS.getRestrictSpecLoc()), QualLoc(DeclSpec::TQ_volatile, DS.getVolatileSpecLoc()), QualLoc(DeclSpec::TQ_atomic, DS.getAtomicSpecLoc())}) { if (!(RemoveTQs & Qual.first)) @@ -743,6 +751,47 @@ static void diagnoseAndRemoveTypeQualifiers(Sema &S, const DeclSpec &DS, } } +/// Return true if this is omitted block return type. Also check type +/// attributes and type qualifiers when returning true. +static bool checkOmittedBlockReturnType(Sema &S, Declarator &declarator, + QualType Result) { + if (!isOmittedBlockReturnType(declarator)) + return false; + + // Warn if we see type attributes for omitted return type on a block literal. + AttributeList *&attrs = + declarator.getMutableDeclSpec().getAttributes().getListRef(); + AttributeList *prev = nullptr; + for (AttributeList *cur = attrs; cur; cur = cur->getNext()) { + AttributeList &attr = *cur; + // Skip attributes that were marked to be invalid or non-type + // attributes. + if (attr.isInvalid() || !attr.isTypeAttr()) { + prev = cur; + continue; + } + S.Diag(attr.getLoc(), + diag::warn_block_literal_attributes_on_omitted_return_type) + << attr.getName(); + // Remove cur from the list. + if (prev) { + prev->setNext(cur->getNext()); + prev = cur; + } else { + attrs = cur->getNext(); + } + } + + // Warn if we see type qualifiers for omitted return type on a block literal. + const DeclSpec &DS = declarator.getDeclSpec(); + unsigned TypeQuals = DS.getTypeQualifiers(); + diagnoseAndRemoveTypeQualifiers(S, DS, TypeQuals, Result, (unsigned)-1, + diag::warn_block_literal_qualifiers_on_omitted_return_type); + declarator.getMutableDeclSpec().ClearTypeQualifiers(); + + return true; +} + /// Apply Objective-C type arguments to the given type. static QualType applyObjCTypeArgs(Sema &S, SourceLocation loc, QualType type, ArrayRef<TypeSourceInfo *> typeArgs, @@ -1171,6 +1220,21 @@ TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers( return CreateParsedType(Result, ResultTInfo); } +static StringRef getImageAccessAttrStr(AttributeList *attrs) { + if (attrs) { + + AttributeList *Next; + do { + AttributeList &Attr = *attrs; + Next = Attr.getNext(); + if (Attr.getKind() == AttributeList::AT_OpenCLAccess) { + return Attr.getName()->getName(); + } + } while (Next); + } + return ""; +} + /// \brief Convert the specified declspec to the appropriate type /// object. /// \param state Specifies the declarator containing the declaration specifier @@ -1244,7 +1308,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { Result = Context.getAutoDeductType(); break; } else if (declarator.getContext() == Declarator::LambdaExprContext || - isOmittedBlockReturnType(declarator)) { + checkOmittedBlockReturnType(S, declarator, + Context.DependentTy)) { Result = Context.DependentTy; break; } @@ -1332,7 +1397,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { } case DeclSpec::TST_int128: if (!S.Context.getTargetInfo().hasInt128Type()) - S.Diag(DS.getTypeSpecTypeLoc(), diag::err_int128_unsupported); + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) + << "__int128"; if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned) Result = Context.UnsignedInt128Ty; else @@ -1354,7 +1420,14 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { declarator.setInvalidType(true); } break; + case DeclSpec::TST_float128: + if (!S.Context.getTargetInfo().hasFloat128Type()) + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_unsupported) + << "__float128"; + Result = Context.Float128Ty; + break; case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool + break; case DeclSpec::TST_decimal32: // _Decimal32 case DeclSpec::TST_decimal64: // _Decimal64 case DeclSpec::TST_decimal128: // _Decimal128 @@ -1423,9 +1496,18 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { declarator.setInvalidType(true); } } else if (!S.getOpenCLOptions().cl_khr_gl_msaa_sharing && - (Result->isImage2dMSAAT() || Result->isImage2dArrayMSAAT() || - Result->isImage2dArrayMSAATDepth() || - Result->isImage2dMSAATDepth())) { + (Result->isOCLImage2dArrayMSAADepthROType() || + Result->isOCLImage2dArrayMSAADepthWOType() || + Result->isOCLImage2dArrayMSAADepthRWType() || + Result->isOCLImage2dArrayMSAAROType() || + Result->isOCLImage2dArrayMSAARWType() || + Result->isOCLImage2dArrayMSAAWOType() || + Result->isOCLImage2dMSAADepthROType() || + Result->isOCLImage2dMSAADepthRWType() || + Result->isOCLImage2dMSAADepthWOType() || + Result->isOCLImage2dMSAAROType() || + Result->isOCLImage2dMSAARWType() || + Result->isOCLImage2dMSAAWOType())) { S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension) << Result << "cl_khr_gl_msaa_sharing"; declarator.setInvalidType(true); @@ -1539,6 +1621,16 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { } break; +#define GENERIC_IMAGE_TYPE(ImgType, Id) \ + case DeclSpec::TST_##ImgType##_t: \ + Result = llvm::StringSwitch<QualType>( \ + getImageAccessAttrStr(DS.getAttributes().getList())) \ + .Cases("write_only", "__write_only", Context.Id##WOTy) \ + .Cases("read_write", "__read_write", Context.Id##RWTy) \ + .Default(Context.Id##ROTy); \ + break; +#include "clang/Basic/OpenCLImageTypes.def" + case DeclSpec::TST_error: Result = Context.IntTy; declarator.setInvalidType(true); @@ -1693,12 +1785,13 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, } QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, - unsigned CVRA, const DeclSpec *DS) { + unsigned CVRAU, const DeclSpec *DS) { if (T.isNull()) return QualType(); - // Convert from DeclSpec::TQ to Qualifiers::TQ by just dropping TQ_atomic. - unsigned CVR = CVRA & ~DeclSpec::TQ_atomic; + // Convert from DeclSpec::TQ to Qualifiers::TQ by just dropping TQ_atomic and + // TQ_unaligned; + unsigned CVR = CVRAU & ~(DeclSpec::TQ_atomic | DeclSpec::TQ_unaligned); // C11 6.7.3/5: // If the same qualifier appears more than once in the same @@ -1708,7 +1801,7 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, // It's not specified what happens when the _Atomic qualifier is applied to // a type specified with the _Atomic specifier, but we assume that this // should be treated as if the _Atomic qualifier appeared multiple times. - if (CVRA & DeclSpec::TQ_atomic && !T->isAtomicType()) { + if (CVRAU & DeclSpec::TQ_atomic && !T->isAtomicType()) { // C11 6.7.3/5: // If other qualifiers appear along with the _Atomic qualifier in a // specifier-qualifier-list, the resulting type is the so-qualified @@ -1725,7 +1818,9 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, return BuildQualifiedType(T, Loc, Split.Quals); } - return BuildQualifiedType(T, Loc, Qualifiers::fromCVRMask(CVR), DS); + Qualifiers Q = Qualifiers::fromCVRMask(CVR); + Q.setUnaligned(CVRAU & DeclSpec::TQ_unaligned); + return BuildQualifiedType(T, Loc, Q, DS); } /// \brief Build a paren type including \p T. @@ -1821,7 +1916,7 @@ namespace { /// /// The values of this enum are used in diagnostics. enum QualifiedFunctionKind { QFK_BlockPointer, QFK_Pointer, QFK_Reference }; -} +} // end anonymous namespace /// Check whether the type T is a qualified function type, and if it is, /// diagnose that it cannot be contained within the given kind of declarator. @@ -1968,10 +2063,10 @@ static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) { } Diagnoser; return S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser, - S.LangOpts.GNUMode).isInvalid(); + S.LangOpts.GNUMode || + S.LangOpts.OpenCL).isInvalid(); } - /// \brief Build an array type. /// /// \param T The type of each element in the array. @@ -2150,15 +2245,8 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, // If this is not C99, extwarn about VLA's and C99 array size modifiers. if (!getLangOpts().C99) { if (T->isVariableArrayType()) { - // Prohibit the use of non-POD types in VLAs. - QualType BaseT = Context.getBaseElementType(T); - if (!T->isDependentType() && isCompleteType(Loc, BaseT) && - !BaseT.isPODType(Context) && !BaseT->isObjCLifetimeType()) { - Diag(Loc, diag::err_vla_non_pod) << BaseT; - return QualType(); - } // Prohibit the use of VLAs during template argument deduction. - else if (isSFINAEContext()) { + if (isSFINAEContext()) { Diag(Loc, diag::err_vla_in_sfinae); return QualType(); } @@ -2176,6 +2264,18 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, Diag(Loc, diag::warn_vla_used); } + // OpenCL v2.0 s6.12.5 - Arrays of blocks are not supported. + // OpenCL v2.0 s6.16.13.1 - Arrays of pipe type are not supported. + // OpenCL v2.0 s6.9.b - Arrays of image/sampler type are not supported. + if (getLangOpts().OpenCL) { + const QualType ArrType = Context.getBaseElementType(T); + if (ArrType->isBlockPointerType() || ArrType->isPipeType() || + ArrType->isSamplerT() || ArrType->isImageType()) { + Diag(Loc, diag::err_opencl_invalid_type_array) << ArrType; + return QualType(); + } + } + return T; } @@ -2184,10 +2284,16 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, /// Run the required checks for the extended vector type. QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, SourceLocation AttrLoc) { - // unlike gcc's vector_size attribute, we do not allow vectors to be defined + // Unlike gcc's vector_size attribute, we do not allow vectors to be defined // in conjunction with complex types (pointers, arrays, functions, etc.). - if (!T->isDependentType() && - !T->isIntegerType() && !T->isRealFloatingType()) { + // + // Additionally, OpenCL prohibits vectors of booleans (they're considered a + // reserved data type under OpenCL v2.0 s6.1.4), we don't support selects + // on bitvectors, and we have no well-defined ABI for bitvectors, so vectors + // of bool aren't allowed. + if ((!T->isDependentType() && !T->isIntegerType() && + !T->isRealFloatingType()) || + T->isBooleanType()) { Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << T; return QualType(); } @@ -2201,7 +2307,7 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, return QualType(); } - // unlike gcc's vector_size attribute, the size is specified as the + // Unlike gcc's vector_size attribute, the size is specified as the // number of elements, not the number of bytes. unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue()); @@ -2247,6 +2353,74 @@ bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) { return false; } +/// Check the extended parameter information. Most of the necessary +/// checking should occur when applying the parameter attribute; the +/// only other checks required are positional restrictions. +static void checkExtParameterInfos(Sema &S, ArrayRef<QualType> paramTypes, + const FunctionProtoType::ExtProtoInfo &EPI, + llvm::function_ref<SourceLocation(unsigned)> getParamLoc) { + assert(EPI.ExtParameterInfos && "shouldn't get here without param infos"); + + bool hasCheckedSwiftCall = false; + auto checkForSwiftCC = [&](unsigned paramIndex) { + // Only do this once. + if (hasCheckedSwiftCall) return; + hasCheckedSwiftCall = true; + if (EPI.ExtInfo.getCC() == CC_Swift) return; + S.Diag(getParamLoc(paramIndex), diag::err_swift_param_attr_not_swiftcall) + << getParameterABISpelling(EPI.ExtParameterInfos[paramIndex].getABI()); + }; + + for (size_t paramIndex = 0, numParams = paramTypes.size(); + paramIndex != numParams; ++paramIndex) { + switch (EPI.ExtParameterInfos[paramIndex].getABI()) { + // Nothing interesting to check for orindary-ABI parameters. + case ParameterABI::Ordinary: + continue; + + // swift_indirect_result parameters must be a prefix of the function + // arguments. + case ParameterABI::SwiftIndirectResult: + checkForSwiftCC(paramIndex); + if (paramIndex != 0 && + EPI.ExtParameterInfos[paramIndex - 1].getABI() + != ParameterABI::SwiftIndirectResult) { + S.Diag(getParamLoc(paramIndex), + diag::err_swift_indirect_result_not_first); + } + continue; + + // swift_context parameters must be the last parameter except for + // a possible swift_error parameter. + case ParameterABI::SwiftContext: + checkForSwiftCC(paramIndex); + if (!(paramIndex == numParams - 1 || + (paramIndex == numParams - 2 && + EPI.ExtParameterInfos[numParams - 1].getABI() + == ParameterABI::SwiftErrorResult))) { + S.Diag(getParamLoc(paramIndex), + diag::err_swift_context_not_before_swift_error_result); + } + continue; + + // swift_error parameters must be the last parameter. + case ParameterABI::SwiftErrorResult: + checkForSwiftCC(paramIndex); + if (paramIndex != numParams - 1) { + S.Diag(getParamLoc(paramIndex), + diag::err_swift_error_result_not_last); + } else if (paramIndex == 0 || + EPI.ExtParameterInfos[paramIndex - 1].getABI() + != ParameterABI::SwiftContext) { + S.Diag(getParamLoc(paramIndex), + diag::err_swift_error_result_not_after_swift_context); + } + continue; + } + llvm_unreachable("bad ABI kind"); + } +} + QualType Sema::BuildFunctionType(QualType T, MutableArrayRef<QualType> ParamTypes, SourceLocation Loc, DeclarationName Entity, @@ -2271,6 +2445,11 @@ QualType Sema::BuildFunctionType(QualType T, ParamTypes[Idx] = ParamType; } + if (EPI.ExtParameterInfos) { + checkExtParameterInfos(*this, ParamTypes, EPI, + [=](unsigned i) { return Loc; }); + } + if (Invalid) return QualType(); @@ -2477,7 +2656,8 @@ void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals, SourceLocation ConstQualLoc, SourceLocation VolatileQualLoc, SourceLocation RestrictQualLoc, - SourceLocation AtomicQualLoc) { + SourceLocation AtomicQualLoc, + SourceLocation UnalignedQualLoc) { if (!Quals) return; @@ -2485,26 +2665,27 @@ void Sema::diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals, const char *Name; unsigned Mask; SourceLocation Loc; - } const QualKinds[4] = { + } const QualKinds[5] = { { "const", DeclSpec::TQ_const, ConstQualLoc }, { "volatile", DeclSpec::TQ_volatile, VolatileQualLoc }, { "restrict", DeclSpec::TQ_restrict, RestrictQualLoc }, + { "__unaligned", DeclSpec::TQ_unaligned, UnalignedQualLoc }, { "_Atomic", DeclSpec::TQ_atomic, AtomicQualLoc } }; SmallString<32> QualStr; unsigned NumQuals = 0; SourceLocation Loc; - FixItHint FixIts[4]; + FixItHint FixIts[5]; // Build a string naming the redundant qualifiers. - for (unsigned I = 0; I != 4; ++I) { - if (Quals & QualKinds[I].Mask) { + for (auto &E : QualKinds) { + if (Quals & E.Mask) { if (!QualStr.empty()) QualStr += ' '; - QualStr += QualKinds[I].Name; + QualStr += E.Name; // If we have a location for the qualifier, offer a fixit. - SourceLocation QualLoc = QualKinds[I].Loc; + SourceLocation QualLoc = E.Loc; if (QualLoc.isValid()) { FixIts[NumQuals] = FixItHint::CreateRemoval(QualLoc); if (Loc.isInvalid() || @@ -2550,7 +2731,8 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy, SourceLocation::getFromRawEncoding(PTI.ConstQualLoc), SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc), SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc), - SourceLocation::getFromRawEncoding(PTI.AtomicQualLoc)); + SourceLocation::getFromRawEncoding(PTI.AtomicQualLoc), + SourceLocation::getFromRawEncoding(PTI.UnalignedQualLoc)); return; } @@ -2586,7 +2768,8 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy, D.getDeclSpec().getConstSpecLoc(), D.getDeclSpec().getVolatileSpecLoc(), D.getDeclSpec().getRestrictSpecLoc(), - D.getDeclSpec().getAtomicSpecLoc()); + D.getDeclSpec().getAtomicSpecLoc(), + D.getDeclSpec().getUnalignedSpecLoc()); } static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, @@ -2700,6 +2883,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case Declarator::FileContext: case Declarator::BlockContext: case Declarator::ForContext: + case Declarator::InitStmtContext: case Declarator::ConditionContext: break; case Declarator::CXXNewContext: @@ -2785,6 +2969,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case Declarator::MemberContext: case Declarator::BlockContext: case Declarator::ForContext: + case Declarator::InitStmtContext: case Declarator::BlockLiteralContext: case Declarator::LambdaExprContext: // C++11 [dcl.type]p3: @@ -2940,6 +3125,26 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D, unsigned ChunkIndex) { assert(D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function); + // Check for an explicit CC attribute. + for (auto Attr = FTI.AttrList; Attr; Attr = Attr->getNext()) { + switch (Attr->getKind()) { + CALLING_CONV_ATTRS_CASELIST: { + // Ignore attributes that don't validate or can't apply to the + // function type. We'll diagnose the failure to apply them in + // handleFunctionTypeAttr. + CallingConv CC; + if (!S.CheckCallingConvAttr(*Attr, CC) && + (!FTI.isVariadic || supportsVariadicCall(CC))) { + return CC; + } + break; + } + + default: + break; + } + } + bool IsCXXInstanceMethod = false; if (S.getLangOpts().CPlusPlus) { @@ -2979,15 +3184,19 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D, CallingConv CC = S.Context.getDefaultCallingConvention(FTI.isVariadic, IsCXXInstanceMethod); - // Attribute AT_OpenCLKernel affects the calling convention only on - // the SPIR target, hence it cannot be treated as a calling + // Attribute AT_OpenCLKernel affects the calling convention for SPIR + // and AMDGPU targets, hence it cannot be treated as a calling // convention attribute. This is the simplest place to infer - // "spir_kernel" for OpenCL kernels on SPIR. - if (CC == CC_SpirFunction) { + // calling convention for OpenCL kernels. + if (S.getLangOpts().OpenCL) { for (const AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); Attr; Attr = Attr->getNext()) { if (Attr->getKind() == AttributeList::AT_OpenCLKernel) { - CC = CC_SpirKernel; + llvm::Triple::ArchType arch = S.Context.getTargetInfo().getTriple().getArch(); + if (arch == llvm::Triple::spir || arch == llvm::Triple::spir64 || + arch == llvm::Triple::amdgcn) { + CC = CC_OpenCLKernel; + } break; } } @@ -3004,7 +3213,7 @@ namespace { BlockPointer, MemberPointer, }; -} +} // end anonymous namespace IdentifierInfo *Sema::getNullabilityKeyword(NullabilityKind nullability) { switch (nullability) { @@ -3064,7 +3273,7 @@ namespace { // NSError** NSErrorPointerPointer, }; -} +} // end anonymous namespace /// Classify the given declarator, whose type-specified is \c type, based on /// what kind of pointer it refers to. @@ -3192,7 +3401,6 @@ static PointerDeclaratorKind classifyPointerDeclarator(Sema &S, break; } while (true); - switch (numNormalPointers) { case 0: return PointerDeclaratorKind::NonPointer; @@ -3509,6 +3717,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case Declarator::CXXCatchContext: case Declarator::CXXNewContext: case Declarator::ForContext: + case Declarator::InitStmtContext: case Declarator::LambdaExprContext: case Declarator::LambdaExprParameterContext: case Declarator::ObjCCatchContext: @@ -3609,15 +3818,20 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case DeclaratorChunk::BlockPointer: // If blocks are disabled, emit an error. if (!LangOpts.Blocks) - S.Diag(DeclType.Loc, diag::err_blocks_disable); + S.Diag(DeclType.Loc, diag::err_blocks_disable) << LangOpts.OpenCL; // Handle pointer nullability. inferPointerNullability(SimplePointerKind::BlockPointer, DeclType.Loc, DeclType.getAttrListRef()); T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name); - if (DeclType.Cls.TypeQuals) + if (DeclType.Cls.TypeQuals || LangOpts.OpenCL) { + // OpenCL v2.0, s6.12.5 - Block variable declarations are implicitly + // qualified with const. + if (LangOpts.OpenCL) + DeclType.Cls.TypeQuals |= DeclSpec::TQ_const; T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Cls.TypeQuals); + } break; case DeclaratorChunk::Pointer: // Verify that we're not building a pointer to pointer to function with @@ -3638,10 +3852,21 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals); break; } + + // OpenCL v2.0 s6.9b - Pointer to image/sampler cannot be used. + // OpenCL v2.0 s6.13.16.1 - Pointer to pipe cannot be used. + // OpenCL v2.0 s6.12.5 - Pointers to Blocks are not allowed. + if (LangOpts.OpenCL) { + if (T->isImageType() || T->isSamplerT() || T->isPipeType() || + T->isBlockPointerType()) { + S.Diag(D.getIdentifierLoc(), diag::err_opencl_pointer_to_type) << T; + D.setInvalidType(true); + } + } + T = S.BuildPointerType(T, DeclType.Loc, Name); if (DeclType.Ptr.TypeQuals) T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals); - break; case DeclaratorChunk::Reference: { // Verify that we're not building a reference to pointer to function with @@ -3808,7 +4033,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (T->isHalfType()) { if (S.getLangOpts().OpenCL) { if (!S.getOpenCLOptions().cl_khr_fp16) { - S.Diag(D.getIdentifierLoc(), diag::err_opencl_half_return) << T; + S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return) + << T << 0 /*pointer hint*/; D.setInvalidType(true); } } else if (!S.getLangOpts().HalfArgsAndReturns) { @@ -3818,6 +4044,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } } + // OpenCL v2.0 s6.12.5 - A block cannot be the return value of a + // function. + if (LangOpts.OpenCL && (T->isBlockPointerType() || T->isImageType() || + T->isSamplerT() || T->isPipeType())) { + S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return) + << T << 1 /*hint off*/; + D.setInvalidType(true); + } + // Methods cannot return interface types. All ObjC objects are // passed by reference. if (T->isObjCObjectType()) { @@ -3967,9 +4202,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, SmallVector<QualType, 16> ParamTys; ParamTys.reserve(FTI.NumParams); - SmallVector<bool, 16> ConsumedParameters; - ConsumedParameters.reserve(FTI.NumParams); - bool HasAnyConsumedParameters = false; + SmallVector<FunctionProtoType::ExtParameterInfo, 16> + ExtParameterInfos(FTI.NumParams); + bool HasAnyInterestingExtParameterInfos = false; for (unsigned i = 0, e = FTI.NumParams; i != e; ++i) { ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param); @@ -4027,17 +4262,25 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } } - if (LangOpts.ObjCAutoRefCount) { - bool Consumed = Param->hasAttr<NSConsumedAttr>(); - ConsumedParameters.push_back(Consumed); - HasAnyConsumedParameters |= Consumed; + if (LangOpts.ObjCAutoRefCount && Param->hasAttr<NSConsumedAttr>()) { + ExtParameterInfos[i] = ExtParameterInfos[i].withIsConsumed(true); + HasAnyInterestingExtParameterInfos = true; + } + + if (auto attr = Param->getAttr<ParameterABIAttr>()) { + ExtParameterInfos[i] = + ExtParameterInfos[i].withABI(attr->getABI()); + HasAnyInterestingExtParameterInfos = true; } ParamTys.push_back(ParamTy); } - if (HasAnyConsumedParameters) - EPI.ConsumedParameters = ConsumedParameters.data(); + if (HasAnyInterestingExtParameterInfos) { + EPI.ExtParameterInfos = ExtParameterInfos.data(); + checkExtParameterInfos(S, ParamTys, EPI, + [&](unsigned i) { return FTI.Params[i].Param->getLocation(); }); + } SmallVector<QualType, 4> Exceptions; SmallVector<ParsedType, 2> DynamicExceptions; @@ -4068,7 +4311,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, T = Context.getFunctionType(T, ParamTys, EPI); } - break; } case DeclaratorChunk::MemberPointer: { @@ -4306,6 +4548,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case Declarator::MemberContext: case Declarator::BlockContext: case Declarator::ForContext: + case Declarator::InitStmtContext: case Declarator::ConditionContext: case Declarator::CXXCatchContext: case Declarator::ObjCCatchContext: @@ -4497,6 +4740,8 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { return AttributeList::AT_ThisCall; case AttributedType::attr_pascal: return AttributeList::AT_Pascal; + case AttributedType::attr_swiftcall: + return AttributeList::AT_SwiftCall; case AttributedType::attr_vectorcall: return AttributeList::AT_VectorCall; case AttributedType::attr_pcs: @@ -4508,6 +4753,10 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { return AttributeList::AT_MSABI; case AttributedType::attr_sysv_abi: return AttributeList::AT_SysVABI; + case AttributedType::attr_preserve_most: + return AttributeList::AT_PreserveMost; + case AttributedType::attr_preserve_all: + return AttributeList::AT_PreserveAll; case AttributedType::attr_ptr32: return AttributeList::AT_Ptr32; case AttributedType::attr_ptr64: @@ -4725,7 +4974,7 @@ namespace { void VisitPipeTypeLoc(PipeTypeLoc TL) { TL.setKWLoc(DS.getTypeSpecTypeLoc()); - TypeSourceInfo *TInfo = 0; + TypeSourceInfo *TInfo = nullptr; Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc()); } @@ -4859,7 +5108,7 @@ namespace { llvm_unreachable("unsupported TypeLoc kind in declarator!"); } }; -} +} // end anonymous namespace static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) { SourceLocation Loc; @@ -4995,7 +5244,6 @@ ParsedType Sema::ActOnObjCInstanceType(SourceLocation Loc) { return CreateParsedType(T, TInfo); } - //===----------------------------------------------------------------------===// // Type Attribute Processing //===----------------------------------------------------------------------===// @@ -5194,11 +5442,13 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, } // Otherwise, if the qualifiers actually conflict, pull sugar off - // until we reach a type that is directly qualified. + // and remove the ObjCLifetime qualifiers. if (previousLifetime != lifetime) { - // This should always terminate: the canonical type is - // qualified, so some bit of sugar must be hiding it. - while (!underlyingType.Quals.hasObjCLifetime()) { + // It's possible to have multiple local ObjCLifetime qualifiers. We + // can't stop after we reach a type that is directly qualified. + const Type *prevTy = nullptr; + while (!prevTy || prevTy != underlyingType.Ty) { + prevTy = underlyingType.Ty; underlyingType = underlyingType.getSingleStepDesugaredType(); } underlyingType.Quals.removeObjCLifetime(); @@ -5369,6 +5619,7 @@ namespace { struct FunctionTypeUnwrapper { enum WrapKind { Desugar, + Attributed, Parens, Pointer, BlockPointer, @@ -5401,6 +5652,9 @@ namespace { } else if (isa<ReferenceType>(Ty)) { T = cast<ReferenceType>(Ty)->getPointeeType(); Stack.push_back(Reference); + } else if (isa<AttributedType>(Ty)) { + T = cast<AttributedType>(Ty)->getEquivalentType(); + Stack.push_back(Attributed); } else { const Type *DTy = Ty->getUnqualifiedDesugaredType(); if (Ty == DTy) { @@ -5449,6 +5703,9 @@ namespace { // information. return wrap(C, Old->getUnqualifiedDesugaredType(), I); + case Attributed: + return wrap(C, cast<AttributedType>(Old)->getEquivalentType(), I); + case Parens: { QualType New = wrap(C, cast<ParenType>(Old)->getInnerType(), I); return C.getParenType(New); @@ -5483,7 +5740,7 @@ namespace { llvm_unreachable("unknown wrapping kind"); } }; -} +} // end anonymous namespace static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, AttributeList &Attr, @@ -5672,10 +5929,11 @@ bool Sema::checkObjCKindOfType(QualType &type, SourceLocation loc) { // Rebuild the "equivalent" type, which pushes __kindof down into // the object type. - QualType equivType = Context.getObjCObjectType(objType->getBaseType(), - objType->getTypeArgsAsWritten(), - objType->getProtocols(), - /*isKindOf=*/true); + // There is no need to apply kindof on an unqualified id type. + QualType equivType = Context.getObjCObjectType( + objType->getBaseType(), objType->getTypeArgsAsWritten(), + objType->getProtocols(), + /*isKindOf=*/objType->isObjCUnqualifiedId() ? false : true); // If we started with an object pointer type, rebuild it. if (ptrType) { @@ -5814,6 +6072,8 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) { return AttributedType::attr_thiscall; case AttributeList::AT_Pascal: return AttributedType::attr_pascal; + case AttributeList::AT_SwiftCall: + return AttributedType::attr_swiftcall; case AttributeList::AT_VectorCall: return AttributedType::attr_vectorcall; case AttributeList::AT_Pcs: { @@ -5835,6 +6095,10 @@ static AttributedType::Kind getCCTypeAttrKind(AttributeList &Attr) { return AttributedType::attr_ms_abi; case AttributeList::AT_SysVABI: return AttributedType::attr_sysv_abi; + case AttributeList::AT_PreserveMost: + return AttributedType::attr_preserve_most; + case AttributeList::AT_PreserveAll: + return AttributedType::attr_preserve_all; } llvm_unreachable("unexpected attribute kind!"); } @@ -5930,18 +6194,28 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, } } - // Diagnose use of callee-cleanup calling convention on variadic functions. + // Diagnose use of variadic functions with calling conventions that + // don't support them (e.g. because they're callee-cleanup). + // We delay warning about this on unprototyped function declarations + // until after redeclaration checking, just in case we pick up a + // prototype that way. And apparently we also "delay" warning about + // unprototyped function types in general, despite not necessarily having + // much ability to diagnose it later. if (!supportsVariadicCall(CC)) { const FunctionProtoType *FnP = dyn_cast<FunctionProtoType>(fn); if (FnP && FnP->isVariadic()) { unsigned DiagID = diag::err_cconv_varargs; + // stdcall and fastcall are ignored with a warning for GCC and MS // compatibility. - if (CC == CC_X86StdCall || CC == CC_X86FastCall) + bool IsInvalid = true; + if (CC == CC_X86StdCall || CC == CC_X86FastCall) { DiagID = diag::warn_cconv_varargs; + IsInvalid = false; + } S.Diag(attr.getLoc(), DiagID) << FunctionType::getNameForCallConv(CC); - attr.setInvalid(); + if (IsInvalid) attr.setInvalid(); return true; } } @@ -5957,9 +6231,14 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, // Modify the CC from the wrapped function type, wrap it all back, and then // wrap the whole thing in an AttributedType as written. The modified type // might have a different CC if we ignored the attribute. - FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withCallingConv(CC); - QualType Equivalent = + QualType Equivalent; + if (CCOld == CC) { + Equivalent = type; + } else { + auto EI = unwrapped.get()->getExtInfo().withCallingConv(CC); + Equivalent = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); + } type = S.Context.getAttributedType(CCAttrKind, type, Equivalent); return true; } @@ -6217,6 +6496,36 @@ static void HandleNeonVectorTypeAttr(QualType& CurType, CurType = S.Context.getVectorType(CurType, numElts, VecKind); } +/// Handle OpenCL Access Qualifier Attribute. +static void HandleOpenCLAccessAttr(QualType &CurType, const AttributeList &Attr, + Sema &S) { + // OpenCL v2.0 s6.6 - Access qualifier can be used only for image and pipe type. + if (!(CurType->isImageType() || CurType->isPipeType())) { + S.Diag(Attr.getLoc(), diag::err_opencl_invalid_access_qualifier); + Attr.setInvalid(); + return; + } + + if (const TypedefType* TypedefTy = CurType->getAs<TypedefType>()) { + QualType PointeeTy = TypedefTy->desugar(); + S.Diag(Attr.getLoc(), diag::err_opencl_multiple_access_qualifiers); + + std::string PrevAccessQual; + switch (cast<BuiltinType>(PointeeTy.getTypePtr())->getKind()) { + #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + case BuiltinType::Id: \ + PrevAccessQual = #Access; \ + break; + #include "clang/Basic/OpenCLImageTypes.def" + default: + assert(0 && "Unable to find corresponding image type."); + } + + S.Diag(TypedefTy->getDecl()->getLocStart(), + diag::note_opencl_typedef_access_qualifier) << PrevAccessQual; + } +} + static void processTypeAttrs(TypeProcessingState &state, QualType &type, TypeAttrLocation TAL, AttributeList *attrs) { // Scan through and apply attributes to this type where it makes sense. Some @@ -6312,9 +6621,8 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, VectorType::NeonPolyVector); attr.setUsedAsTypeAttr(); break; - case AttributeList::AT_OpenCLImageAccess: - // FIXME: there should be some type checking happening here, I would - // imagine, but the original handler's checking was entirely superfluous. + case AttributeList::AT_OpenCLAccess: + HandleOpenCLAccessAttr(type, attr, state.getSema()); attr.setUsedAsTypeAttr(); break; @@ -6554,8 +6862,8 @@ bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested, RD = Pattern; D = RD->getDefinition(); } else if (auto *ED = dyn_cast<EnumDecl>(D)) { - while (auto *NewED = ED->getInstantiatedFromMemberEnum()) - ED = NewED; + if (auto *Pattern = ED->getTemplateInstantiationPattern()) + ED = Pattern; if (OnlyNeedComplete && ED->isFixed()) { // If the enum has a fixed underlying type, and we're only looking for a // complete type (not a definition), any visible declaration of it will @@ -6616,6 +6924,7 @@ static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) { S.ImplicitMSInheritanceAttrLoc.isValid() ? S.ImplicitMSInheritanceAttrLoc : RD->getSourceRange())); + S.Consumer.AssignInheritanceModel(RD); } } @@ -6641,9 +6950,16 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, } } - // If we have a complete type, we're done. NamedDecl *Def = nullptr; - if (!T->isIncompleteType(&Def)) { + bool Incomplete = T->isIncompleteType(&Def); + + // Check that any necessary explicit specializations are visible. For an + // enum, we just need the declaration, so don't check this. + if (Def && !isa<EnumDecl>(Def)) + checkSpecializationVisibility(Loc, Def); + + // If we have a complete type, we're done. + if (!Incomplete) { // If we know about the definition but it is not visible, complain. NamedDecl *SuggestedDef = nullptr; if (Def && @@ -6652,7 +6968,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, // definition visible. bool TreatAsComplete = Diagnoser && !isSFINAEContext(); if (Diagnoser) - diagnoseMissingImport(Loc, SuggestedDef, /*NeedDefinition*/true, + diagnoseMissingImport(Loc, SuggestedDef, MissingImportKind::Definition, /*Recover*/TreatAsComplete); return !TreatAsComplete; } @@ -6745,15 +7061,11 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, } } - if (!Diagnoser) - return true; + // FIXME: If we didn't instantiate a definition because of an explicit + // specialization declaration, check that it's visible. - // We have an incomplete type. Produce a diagnostic. - if (Ident___float128 && - T == Context.getTypeDeclType(Context.getFloat128StubType())) { - Diag(Loc, diag::err_typecheck_decl_incomplete_type___float128); + if (!Diagnoser) return true; - } Diagnoser->diagnose(*this, Loc, T); |
