diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:52:09 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:52:09 +0000 |
commit | 519fc96c475680de2cc49e7811dbbfadb912cbcc (patch) | |
tree | 310ca684459b7e9ae13c9a3b9abf308b3a634afe /lib/Sema/SemaType.cpp | |
parent | 2298981669bf3bd63335a4be179bc0f96823a8f4 (diff) |
Notes
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r-- | lib/Sema/SemaType.cpp | 214 |
1 files changed, 121 insertions, 93 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 29acf6177eb9c..fccdb2bc2e2c3 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -82,7 +82,7 @@ static void diagnoseBadTypeAttribute(Sema &S, const ParsedAttr &attr, } SourceLocation loc = attr.getLoc(); - StringRef name = attr.getName()->getName(); + StringRef name = attr.getAttrName()->getName(); // The GC attributes are usually written with macros; special-case them. IdentifierInfo *II = attr.isArgIdent(0) ? attr.getArgAsIdent(0)->Ident @@ -811,7 +811,7 @@ static bool checkOmittedBlockReturnType(Sema &S, Declarator &declarator, continue; S.Diag(AL.getLoc(), diag::warn_block_literal_attributes_on_omitted_return_type) - << AL.getName(); + << AL; ToBeRemoved.push_back(&AL); } // Remove bad attributes from the list. @@ -1290,14 +1290,14 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified) Result = Context.WCharTy; else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) { - S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec) + S.Diag(DS.getTypeSpecSignLoc(), diag::ext_wchar_t_sign_spec) << DS.getSpecifierName(DS.getTypeSpecType(), Context.getPrintingPolicy()); Result = Context.getSignedWCharType(); } else { assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned && "Unknown TSS value"); - S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec) + S.Diag(DS.getTypeSpecSignLoc(), diag::ext_wchar_t_sign_spec) << DS.getSpecifierName(DS.getTypeSpecType(), Context.getPrintingPolicy()); Result = Context.getUnsignedWCharType(); @@ -1633,6 +1633,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { case OpenCLAccessAttr::Keyword_read_only: \ Result = Context.Id##ROTy; \ break; \ + case OpenCLAccessAttr::SpellingNotCalculated: \ + llvm_unreachable("Spelling not yet calculated"); \ } \ break; #include "clang/Basic/OpenCLImageTypes.def" @@ -1953,7 +1955,8 @@ static bool checkQualifiedFunction(Sema &S, QualType T, SourceLocation Loc, QualifiedFunctionKind QFK) { // Does T refer to a function type with a cv-qualifier or a ref-qualifier? const FunctionProtoType *FPT = T->getAs<FunctionProtoType>(); - if (!FPT || (FPT->getMethodQuals().empty() && FPT->getRefQualifier() == RQ_None)) + if (!FPT || + (FPT->getMethodQuals().empty() && FPT->getRefQualifier() == RQ_None)) return false; S.Diag(Loc, diag::err_compound_qualified_function_type) @@ -1962,6 +1965,17 @@ static bool checkQualifiedFunction(Sema &S, QualType T, SourceLocation Loc, return true; } +bool Sema::CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc) { + const FunctionProtoType *FPT = T->getAs<FunctionProtoType>(); + if (!FPT || + (FPT->getMethodQuals().empty() && FPT->getRefQualifier() == RQ_None)) + return false; + + Diag(Loc, diag::err_qualified_function_typeid) + << T << getFunctionQualifiersAsString(FPT); + return true; +} + /// Build a pointer type. /// /// \param T The type to which we'll be building a pointer. @@ -2276,7 +2290,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, } } - T = Context.getConstantArrayType(T, ConstVal, ASM, Quals); + T = Context.getConstantArrayType(T, ConstVal, ArraySize, ASM, Quals); } // OpenCL v1.2 s6.9.d: variable length arrays are not supported. @@ -2461,6 +2475,11 @@ bool Sema::CheckFunctionReturnType(QualType T, SourceLocation Loc) { checkNonTrivialCUnion(T, Loc, NTCUC_FunctionReturn, NTCUK_Destruct|NTCUK_Copy); + // C++2a [dcl.fct]p12: + // A volatile-qualified return type is deprecated + if (T.isVolatileQualified() && getLangOpts().CPlusPlus2a) + Diag(Loc, diag::warn_deprecated_volatile_return) << T; + return false; } @@ -2541,6 +2560,11 @@ QualType Sema::BuildFunctionType(QualType T, Invalid = true; } + // C++2a [dcl.fct]p4: + // A parameter with volatile-qualified type is deprecated + if (ParamType.isVolatileQualified() && getLangOpts().CPlusPlus2a) + Diag(Loc, diag::warn_deprecated_volatile_param) << ParamType; + ParamTypes[Idx] = ParamType; } @@ -3942,10 +3966,9 @@ static bool IsNoDerefableChunk(DeclaratorChunk Chunk) { } template<typename AttrT> -static AttrT *createSimpleAttr(ASTContext &Ctx, ParsedAttr &Attr) { - Attr.setUsedAsTypeAttr(); - return ::new (Ctx) - AttrT(Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex()); +static AttrT *createSimpleAttr(ASTContext &Ctx, ParsedAttr &AL) { + AL.setUsedAsTypeAttr(); + return ::new (Ctx) AttrT(Ctx, AL); } static Attr *createNullabilityAttr(ASTContext &Ctx, ParsedAttr &Attr, @@ -4672,6 +4695,11 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, S.Diag(DeclType.Loc, diag::err_func_returning_qualified_void) << T; } else diagnoseRedundantReturnTypeQualifiers(S, T, D, chunkIndex); + + // C++2a [dcl.fct]p12: + // A volatile-qualified return type is deprecated + if (T.isVolatileQualified() && S.getLangOpts().CPlusPlus2a) + S.Diag(DeclType.Loc, diag::warn_deprecated_volatile_return) << T; } // Objective-C ARC ownership qualifiers are ignored on the function @@ -5151,9 +5179,16 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // C++0x [dcl.constexpr]p9: // A constexpr specifier used in an object declaration declares the object // as const. - if (D.getDeclSpec().hasConstexprSpecifier() && T->isObjectType()) { + if (D.getDeclSpec().getConstexprSpecifier() == CSK_constexpr && + T->isObjectType()) T.addConst(); - } + + // C++2a [dcl.fct]p4: + // A parameter with volatile-qualified type is deprecated + if (T.isVolatileQualified() && S.getLangOpts().CPlusPlus2a && + (D.getContext() == DeclaratorContext::PrototypeContext || + D.getContext() == DeclaratorContext::LambdaExprParameterContext)) + S.Diag(D.getIdentifierLoc(), diag::warn_deprecated_volatile_param) << T; // If there was an ellipsis in the declarator, the declaration declares a // parameter pack whose type may be a pack expansion type. @@ -5983,9 +6018,8 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, } ASTContext &Ctx = S.Context; - auto *ASAttr = ::new (Ctx) AddressSpaceAttr( - Attr.getRange(), Ctx, Attr.getAttributeSpellingListIndex(), - static_cast<unsigned>(ASIdx)); + auto *ASAttr = + ::new (Ctx) AddressSpaceAttr(Ctx, Attr, static_cast<unsigned>(ASIdx)); // If the expression is not value dependent (not templated), then we can // apply the address space qualifiers just to the equivalent type. @@ -6027,36 +6061,6 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, } } -/// Does this type have a "direct" ownership qualifier? That is, -/// is it written like "__strong id", as opposed to something like -/// "typeof(foo)", where that happens to be strong? -static bool hasDirectOwnershipQualifier(QualType type) { - // Fast path: no qualifier at all. - assert(type.getQualifiers().hasObjCLifetime()); - - while (true) { - // __strong id - if (const AttributedType *attr = dyn_cast<AttributedType>(type)) { - if (attr->getAttrKind() == attr::ObjCOwnership) - return true; - - type = attr->getModifiedType(); - - // X *__strong (...) - } else if (const ParenType *paren = dyn_cast<ParenType>(type)) { - type = paren->getInnerType(); - - // That's it for things we want to complain about. In particular, - // we do not want to look through typedefs, typeof(expr), - // typeof(type), or any other way that the type is somehow - // abstracted. - } else { - - return false; - } - } -} - /// handleObjCOwnershipTypeAttr - Process an objc_ownership /// attribute on the specified type. /// @@ -6112,8 +6116,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, else if (II->isStr("autoreleasing")) lifetime = Qualifiers::OCL_Autoreleasing; else { - S.Diag(AttrLoc, diag::warn_attribute_type_not_supported) - << attr.getName() << II; + S.Diag(AttrLoc, diag::warn_attribute_type_not_supported) << attr << II; attr.setInvalid(); return true; } @@ -6132,7 +6135,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, if (Qualifiers::ObjCLifetime previousLifetime = type.getQualifiers().getObjCLifetime()) { // If it's written directly, that's an error. - if (hasDirectOwnershipQualifier(type)) { + if (S.Context.hasDirectOwnershipQualifier(type)) { S.Diag(AttrLoc, diag::err_attr_objc_ownership_redundant) << type; return true; @@ -6155,7 +6158,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, underlyingType.Quals.addObjCLifetime(lifetime); if (NonObjCPointer) { - StringRef name = attr.getName()->getName(); + StringRef name = attr.getAttrName()->getName(); switch (lifetime) { case Qualifiers::OCL_None: case Qualifiers::OCL_ExplicitNone: @@ -6194,9 +6197,8 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, // If we have a valid source location for the attribute, use an // AttributedType instead. if (AttrLoc.isValid()) { - type = state.getAttributedType(::new (S.Context) ObjCOwnershipAttr( - attr.getRange(), S.Context, II, - attr.getAttributeSpellingListIndex()), + type = state.getAttributedType(::new (S.Context) + ObjCOwnershipAttr(S.Context, attr, II), origType, type); } @@ -6288,7 +6290,7 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr, GCAttr = Qualifiers::Strong; else { S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported) - << attr.getName() << II; + << attr << II; attr.setInvalid(); return true; } @@ -6299,9 +6301,7 @@ static bool handleObjCGCTypeAttr(TypeProcessingState &state, ParsedAttr &attr, // Make an attributed type to preserve the source information. if (attr.getLoc().isValid()) type = state.getAttributedType( - ::new (S.Context) ObjCGCAttr(attr.getRange(), S.Context, II, - attr.getAttributeSpellingListIndex()), - origType, type); + ::new (S.Context) ObjCGCAttr(S.Context, attr, II), origType, type); return true; } @@ -6473,8 +6473,7 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State, // You cannot specify duplicate type attributes, so if the attribute has // already been applied, flag it. if (NewAttrKind == CurAttrKind) { - S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact) - << PAttr.getName(); + S.Diag(PAttr.getLoc(), diag::warn_duplicate_attribute_exact) << PAttr; return true; } @@ -6743,9 +6742,9 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state, if (chunk.Kind != DeclaratorChunk::MemberPointer) { diag << FixItHint::CreateRemoval(attr.getLoc()) << FixItHint::CreateInsertion( - state.getSema().getPreprocessor() - .getLocForEndOfToken(chunk.Loc), - " " + attr.getName()->getName().str() + " "); + state.getSema().getPreprocessor().getLocForEndOfToken( + chunk.Loc), + " " + attr.getAttrName()->getName().str() + " "); } moveAttrFromListToList(attr, state.getCurrentAttributes(), @@ -6823,8 +6822,7 @@ static Attr *getCCTypeAttr(ASTContext &Ctx, ParsedAttr &Attr) { PcsAttr::PCSType Type; if (!PcsAttr::ConvertStrToPCSType(Str, Type)) llvm_unreachable("already validated the attribute"); - return ::new (Ctx) PcsAttr(Attr.getRange(), Ctx, Type, - Attr.getAttributeSpellingListIndex()); + return ::new (Ctx) PcsAttr(Ctx, Attr, Type); } case ParsedAttr::AT_IntelOclBicc: return createSimpleAttr<IntelOclBiccAttr>(Ctx, Attr); @@ -7343,7 +7341,7 @@ static void HandleOpenCLAccessAttr(QualType &CurType, const ParsedAttr &Attr, } else { llvm_unreachable("unexpected type"); } - StringRef AttrName = Attr.getName()->getName(); + StringRef AttrName = Attr.getAttrName()->getName(); if (PrevAccessQual == AttrName.ltrim("_")) { // Duplicated qualifiers S.Diag(Attr.getLoc(), diag::warn_duplicate_declspec) @@ -7390,8 +7388,22 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State, bool IsPointee = ChunkIndex > 0 && (D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Pointer || - D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer || - D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Reference); + D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Reference || + D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer); + // For pointers/references to arrays the next chunk is always an array + // followed by any number of parentheses. + if (!IsPointee && ChunkIndex > 1) { + auto AdjustedCI = ChunkIndex - 1; + if (D.getTypeObject(AdjustedCI).Kind == DeclaratorChunk::Array) + AdjustedCI--; + // Skip over all parentheses. + while (AdjustedCI > 0 && + D.getTypeObject(AdjustedCI).Kind == DeclaratorChunk::Paren) + AdjustedCI--; + if (D.getTypeObject(AdjustedCI).Kind == DeclaratorChunk::Pointer || + D.getTypeObject(AdjustedCI).Kind == DeclaratorChunk::Reference) + IsPointee = true; + } bool IsFuncReturnType = ChunkIndex > 0 && D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Function; @@ -7526,7 +7538,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, IsTypeAttr ? diag::warn_gcc_ignores_type_attr : diag::warn_cxx11_gnu_attribute_on_type) - << attr.getName(); + << attr; if (!IsTypeAttr) continue; } @@ -7555,7 +7567,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk) state.getSema().Diag(attr.getLoc(), diag::warn_unknown_attribute_ignored) - << attr.getName(); + << attr; break; case ParsedAttr::IgnoredAttribute: @@ -7720,7 +7732,9 @@ void Sema::completeExprArrayBound(Expr *E) { auto *Def = Var->getDefinition(); if (!Def) { SourceLocation PointOfInstantiation = E->getExprLoc(); - InstantiateVariableDefinition(PointOfInstantiation, Var); + runWithSufficientStackSpace(PointOfInstantiation, [&] { + InstantiateVariableDefinition(PointOfInstantiation, Var); + }); Def = Var->getDefinition(); // If we don't already have a point of instantiation, and we managed @@ -7947,14 +7961,16 @@ static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) { break; } - RD->addAttr(MSInheritanceAttr::CreateImplicit( - S.getASTContext(), IM, - /*BestCase=*/S.MSPointerToMemberRepresentationMethod == - LangOptions::PPTMK_BestCase, - S.ImplicitMSInheritanceAttrLoc.isValid() - ? S.ImplicitMSInheritanceAttrLoc - : RD->getSourceRange())); - S.Consumer.AssignInheritanceModel(RD); + SourceRange Loc = + S.ImplicitMSInheritanceAttrLoc.isValid() + ? S.ImplicitMSInheritanceAttrLoc + : RD->getSourceRange(); + RD->addAttr(MSInheritanceAttr::CreateImplicit( + S.getASTContext(), + /*BestCase=*/S.MSPointerToMemberRepresentationMethod == + LangOptions::PPTMK_BestCase, + Loc, AttributeCommonInfo::AS_Microsoft, IM)); + S.Consumer.AssignInheritanceModel(RD); } } @@ -8058,9 +8074,11 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, } else if (auto *ClassTemplateSpec = dyn_cast<ClassTemplateSpecializationDecl>(RD)) { if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) { - Diagnosed = InstantiateClassTemplateSpecialization( - Loc, ClassTemplateSpec, TSK_ImplicitInstantiation, - /*Complain=*/Diagnoser); + runWithSufficientStackSpace(Loc, [&] { + Diagnosed = InstantiateClassTemplateSpecialization( + Loc, ClassTemplateSpec, TSK_ImplicitInstantiation, + /*Complain=*/Diagnoser); + }); Instantiated = true; } } else { @@ -8071,10 +8089,12 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, // This record was instantiated from a class within a template. if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) { - Diagnosed = InstantiateClass(Loc, RD, Pattern, - getTemplateInstantiationArgs(RD), - TSK_ImplicitInstantiation, - /*Complain=*/Diagnoser); + runWithSufficientStackSpace(Loc, [&] { + Diagnosed = InstantiateClass(Loc, RD, Pattern, + getTemplateInstantiationArgs(RD), + TSK_ImplicitInstantiation, + /*Complain=*/Diagnoser); + }); Instantiated = true; } } @@ -8222,20 +8242,28 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, return true; } } - } else if (!RD->hasTrivialDestructor()) { - // All fields and bases are of literal types, so have trivial destructors. - // If this class's destructor is non-trivial it must be user-declared. + } else if (getLangOpts().CPlusPlus2a ? !RD->hasConstexprDestructor() + : !RD->hasTrivialDestructor()) { + // All fields and bases are of literal types, so have trivial or constexpr + // destructors. If this class's destructor is non-trivial / non-constexpr, + // it must be user-declared. CXXDestructorDecl *Dtor = RD->getDestructor(); assert(Dtor && "class has literal fields and bases but no dtor?"); if (!Dtor) return true; - Diag(Dtor->getLocation(), Dtor->isUserProvided() ? - diag::note_non_literal_user_provided_dtor : - diag::note_non_literal_nontrivial_dtor) << RD; - if (!Dtor->isUserProvided()) - SpecialMemberIsTrivial(Dtor, CXXDestructor, TAH_IgnoreTrivialABI, - /*Diagnose*/true); + if (getLangOpts().CPlusPlus2a) { + Diag(Dtor->getLocation(), diag::note_non_literal_non_constexpr_dtor) + << RD; + } else { + Diag(Dtor->getLocation(), Dtor->isUserProvided() + ? diag::note_non_literal_user_provided_dtor + : diag::note_non_literal_nontrivial_dtor) + << RD; + if (!Dtor->isUserProvided()) + SpecialMemberIsTrivial(Dtor, CXXDestructor, TAH_IgnoreTrivialABI, + /*Diagnose*/ true); + } } return true; |