summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaType.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-10-23 17:52:09 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-10-23 17:52:09 +0000
commit519fc96c475680de2cc49e7811dbbfadb912cbcc (patch)
tree310ca684459b7e9ae13c9a3b9abf308b3a634afe /lib/Sema/SemaType.cpp
parent2298981669bf3bd63335a4be179bc0f96823a8f4 (diff)
Notes
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r--lib/Sema/SemaType.cpp214
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;