aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaType.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r--lib/Sema/SemaType.cpp332
1 files changed, 296 insertions, 36 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index f3e73ec5a723..2b563a50a99f 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -52,18 +52,18 @@ static bool isOmittedBlockReturnType(const Declarator &D) {
/// doesn't apply to the given type.
static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
QualType type) {
- bool useInstantiationLoc = false;
+ bool useExpansionLoc = false;
unsigned diagID = 0;
switch (attr.getKind()) {
case AttributeList::AT_objc_gc:
diagID = diag::warn_pointer_attribute_wrong_type;
- useInstantiationLoc = true;
+ useExpansionLoc = true;
break;
case AttributeList::AT_objc_ownership:
diagID = diag::warn_objc_object_attribute_wrong_type;
- useInstantiationLoc = true;
+ useExpansionLoc = true;
break;
default:
@@ -73,10 +73,10 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
}
SourceLocation loc = attr.getLoc();
- llvm::StringRef name = attr.getName()->getName();
+ StringRef name = attr.getName()->getName();
// The GC attributes are usually written with macros; special-case them.
- if (useInstantiationLoc && loc.isMacroID() && attr.getParameterName()) {
+ if (useExpansionLoc && loc.isMacroID() && attr.getParameterName()) {
if (attr.getParameterName()->isStr("strong")) {
if (S.findMacroSpelling(loc, "__strong")) name = "__strong";
} else if (attr.getParameterName()->isStr("weak")) {
@@ -125,11 +125,11 @@ namespace {
bool hasSavedAttrs;
/// The original set of attributes on the DeclSpec.
- llvm::SmallVector<AttributeList*, 2> savedAttrs;
+ SmallVector<AttributeList*, 2> savedAttrs;
/// A list of attributes to diagnose the uselessness of when the
/// processing is complete.
- llvm::SmallVector<AttributeList*, 2> ignoredTypeAttrs;
+ SmallVector<AttributeList*, 2> ignoredTypeAttrs;
public:
TypeProcessingState(Sema &sema, Declarator &declarator)
@@ -183,7 +183,7 @@ namespace {
/// Diagnose all the ignored type attributes, given that the
/// declarator worked out to the given type.
void diagnoseIgnoredTypeAttrs(QualType type) const {
- for (llvm::SmallVectorImpl<AttributeList*>::const_iterator
+ for (SmallVectorImpl<AttributeList*>::const_iterator
i = ignoredTypeAttrs.begin(), e = ignoredTypeAttrs.end();
i != e; ++i)
diagnoseBadTypeAttribute(getSema(), **i, type);
@@ -664,7 +664,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// each struct declaration and type name."
// FIXME: Does Microsoft really have the implicit int extension in C++?
if (S.getLangOptions().CPlusPlus &&
- !S.getLangOptions().Microsoft) {
+ !S.getLangOptions().MicrosoftExt) {
S.Diag(DeclLoc, diag::err_missing_type_specifier)
<< DS.getSourceRange();
@@ -711,6 +711,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
break;
}
+ case DeclSpec::TST_half: Result = Context.HalfTy; break;
case DeclSpec::TST_float: Result = Context.FloatTy; break;
case DeclSpec::TST_double:
if (DS.getTypeSpecWidth() == DeclSpec::TSW_long)
@@ -856,6 +857,16 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Result = Context.UnknownAnyTy;
break;
+ case DeclSpec::TST_atomic:
+ Result = S.GetTypeFromParser(DS.getRepAsType());
+ assert(!Result.isNull() && "Didn't get a type for _Atomic?");
+ Result = S.BuildAtomicType(Result, DS.getTypeSpecTypeLoc());
+ if (Result.isNull()) {
+ Result = Context.IntTy;
+ declarator.setInvalidType(true);
+ }
+ break;
+
case DeclSpec::TST_error:
Result = Context.IntTy;
declarator.setInvalidType(true);
@@ -1038,6 +1049,11 @@ static QualType inferARCLifetimeForPointee(Sema &S, QualType type,
} else if (type->isObjCARCImplicitlyUnretainedType()) {
implicitLifetime = Qualifiers::OCL_ExplicitNone;
+ // If we are in an unevaluated context, like sizeof, assume ExplicitNone and
+ // don't give error.
+ } else if (S.ExprEvalContexts.back().Context == Sema::Unevaluated) {
+ implicitLifetime = Qualifiers::OCL_ExplicitNone;
+
// If that failed, give an error and recover using __autoreleasing.
} else {
// These types can show up in private ivars in system headers, so
@@ -1419,13 +1435,26 @@ QualType Sema::BuildFunctionType(QualType T,
<< T->isFunctionType() << T;
return QualType();
}
-
+
+ // Functions cannot return half FP.
+ if (T->isHalfType()) {
+ Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 1 <<
+ FixItHint::CreateInsertion(Loc, "*");
+ return QualType();
+ }
+
bool Invalid = false;
for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) {
+ // FIXME: Loc is too inprecise here, should use proper locations for args.
QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]);
if (ParamType->isVoidType()) {
Diag(Loc, diag::err_param_with_void_type);
Invalid = true;
+ } else if (ParamType->isHalfType()) {
+ // Disallow half FP arguments.
+ Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 0 <<
+ FixItHint::CreateInsertion(Loc, "*");
+ Invalid = true;
}
ParamTypes[Idx] = ParamType;
@@ -1492,7 +1521,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
// type. In such cases, the compiler makes a worst-case assumption.
// We make no such assumption right now, so emit an error if the
// class isn't a complete type.
- if (Context.Target.getCXXABI() == CXXABI_Microsoft &&
+ if (Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft &&
RequireCompleteType(Loc, Class, diag::err_incomplete_type))
return QualType();
@@ -1745,9 +1774,10 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
switch (D.getContext()) {
case Declarator::KNRTypeListContext:
- assert(0 && "K&R type lists aren't allowed in C++");
+ llvm_unreachable("K&R type lists aren't allowed in C++");
break;
- case Declarator::ObjCPrototypeContext:
+ case Declarator::ObjCParameterContext:
+ case Declarator::ObjCResultContext:
case Declarator::PrototypeContext:
Error = 0; // Function prototype
break;
@@ -1755,7 +1785,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
break;
switch (cast<TagDecl>(SemaRef.CurContext)->getTagKind()) {
- case TTK_Enum: assert(0 && "unhandled tag kind"); break;
+ case TTK_Enum: llvm_unreachable("unhandled tag kind");
case TTK_Struct: Error = 1; /* Struct member */ break;
case TTK_Union: Error = 2; /* Union member */ break;
case TTK_Class: Error = 3; /* Class member */ break;
@@ -1825,7 +1855,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
}
if (SemaRef.getLangOptions().CPlusPlus &&
- OwnedTagDecl && OwnedTagDecl->isDefinition()) {
+ OwnedTagDecl && OwnedTagDecl->isCompleteDefinition()) {
// Check the contexts where C++ forbids the declaration of a new class
// or enumeration in a type-specifier-seq.
switch (D.getContext()) {
@@ -1856,7 +1886,8 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
<< SemaRef.Context.getTypeDeclType(OwnedTagDecl);
break;
case Declarator::PrototypeContext:
- case Declarator::ObjCPrototypeContext:
+ case Declarator::ObjCParameterContext:
+ case Declarator::ObjCResultContext:
case Declarator::KNRTypeListContext:
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
@@ -1916,7 +1947,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
state.setCurrentChunkIndex(chunkIndex);
DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
switch (DeclType.Kind) {
- default: assert(0 && "Unknown decltype!");
+ default: llvm_unreachable("Unknown decltype!");
case DeclaratorChunk::Paren:
T = S.BuildParenType(T);
break;
@@ -2045,6 +2076,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
D.setInvalidType(true);
}
+ // Do not allow returning half FP value.
+ // FIXME: This really should be in BuildFunctionType.
+ if (T->isHalfType()) {
+ S.Diag(D.getIdentifierLoc(),
+ diag::err_parameters_retval_cannot_have_fp16_type) << 1
+ << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*");
+ D.setInvalidType(true);
+ }
+
// cv-qualifiers on return types are pointless except when the type is a
// class type in C++.
if (isa<PointerType>(T) && T.getLocalCVRQualifiers() &&
@@ -2077,7 +2117,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
TagDecl *Tag = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
- if (Tag->isDefinition())
+ if (Tag->isCompleteDefinition())
S.Diag(Tag->getLocation(), diag::err_type_defined_in_result_type)
<< Context.getTypeDeclType(Tag);
}
@@ -2127,10 +2167,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Otherwise, we have a function with an argument list that is
// potentially variadic.
- llvm::SmallVector<QualType, 16> ArgTys;
+ SmallVector<QualType, 16> ArgTys;
ArgTys.reserve(FTI.NumArgs);
- llvm::SmallVector<bool, 16> ConsumedArguments;
+ SmallVector<bool, 16> ConsumedArguments;
ConsumedArguments.reserve(FTI.NumArgs);
bool HasAnyConsumedArguments = false;
@@ -2168,6 +2208,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// Do not add 'void' to the ArgTys list.
break;
}
+ } else if (ArgTy->isHalfType()) {
+ // Disallow half FP arguments.
+ // FIXME: This really should be in BuildFunctionType.
+ S.Diag(Param->getLocation(),
+ diag::err_parameters_retval_cannot_have_fp16_type) << 0
+ << FixItHint::CreateInsertion(Param->getLocation(), "*");
+ D.setInvalidType();
} else if (!FTI.hasPrototype) {
if (ArgTy->isPromotableIntegerType()) {
ArgTy = Context.getPromotedIntegerType(ArgTy);
@@ -2192,7 +2239,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
if (HasAnyConsumedArguments)
EPI.ConsumedArguments = ConsumedArguments.data();
- llvm::SmallVector<QualType, 4> Exceptions;
+ SmallVector<QualType, 4> Exceptions;
EPI.ExceptionSpecType = FTI.getExceptionSpecType();
if (FTI.getExceptionSpecType() == EST_Dynamic) {
Exceptions.reserve(FTI.NumExceptions);
@@ -2320,6 +2367,20 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
FreeFunction = (DC && !DC->isRecord());
}
+ // C++0x [dcl.constexpr]p8: A constexpr specifier for a non-static member
+ // function that is not a constructor declares that function to be const.
+ if (D.getDeclSpec().isConstexprSpecified() && !FreeFunction &&
+ D.getName().getKind() != UnqualifiedId::IK_ConstructorName &&
+ D.getName().getKind() != UnqualifiedId::IK_ConstructorTemplateId &&
+ !(FnTy->getTypeQuals() & DeclSpec::TQ_const)) {
+ // Rebuild function type adding a 'const' qualifier.
+ FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
+ EPI.TypeQuals |= DeclSpec::TQ_const;
+ T = Context.getFunctionType(FnTy->getResultType(),
+ FnTy->arg_type_begin(),
+ FnTy->getNumArgs(), EPI);
+ }
+
// C++0x [dcl.fct]p6:
// A ref-qualifier shall only be part of the function type for a
// non-static member function, the function type to which a pointer to
@@ -2457,13 +2518,17 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// it expands those parameter packs.
if (T->containsUnexpandedParameterPack())
T = Context.getPackExpansionType(T, llvm::Optional<unsigned>());
- else if (!LangOpts.CPlusPlus0x)
- S.Diag(D.getEllipsisLoc(), diag::ext_variadic_templates);
+ else
+ S.Diag(D.getEllipsisLoc(),
+ LangOpts.CPlusPlus0x
+ ? diag::warn_cxx98_compat_variadic_templates
+ : diag::ext_variadic_templates);
break;
case Declarator::FileContext:
case Declarator::KNRTypeListContext:
- case Declarator::ObjCPrototypeContext: // FIXME: special diagnostic here?
+ case Declarator::ObjCParameterContext: // FIXME: special diagnostic here?
+ case Declarator::ObjCResultContext: // FIXME: special diagnostic here?
case Declarator::TypeNameContext:
case Declarator::CXXNewContext:
case Declarator::AliasDeclContext:
@@ -2850,6 +2915,14 @@ namespace {
void VisitTagTypeLoc(TagTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
}
+ void VisitAtomicTypeLoc(AtomicTypeLoc TL) {
+ TL.setKWLoc(DS.getTypeSpecTypeLoc());
+ TL.setParensRange(DS.getTypeofParensRange());
+
+ TypeSourceInfo *TInfo = 0;
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
+ TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
+ }
void VisitTypeLoc(TypeLoc TL) {
// FIXME: add other typespec types and change this to an assert.
@@ -3030,7 +3103,7 @@ ParsedType Sema::CreateParsedType(QualType T, TypeSourceInfo *TInfo) {
void LocInfoType::getAsStringInternal(std::string &Str,
const PrintingPolicy &Policy) const {
- assert(false && "LocInfoType leaked into the type system; an opaque TypeTy*"
+ llvm_unreachable("LocInfoType leaked into the type system; an opaque TypeTy*"
" was used directly instead of getting the QualType through"
" GetTypeFromParser");
}
@@ -3045,6 +3118,12 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
if (D.isInvalidType())
return true;
+ // Make sure there are no unused decl attributes on the declarator.
+ // We don't want to do this for ObjC parameters because we're going
+ // to apply them to the actual parameter declaration.
+ if (D.getContext() != Declarator::ObjCParameterContext)
+ checkUnusedDeclAttributes(D);
+
if (getLangOptions().CPlusPlus) {
// Check that there are no default arguments (C++ only).
CheckExtraCXXDefaultArguments(D);
@@ -3053,6 +3132,13 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
return CreateParsedType(T, TInfo);
}
+ParsedType Sema::ActOnObjCInstanceType(SourceLocation Loc) {
+ QualType T = Context.getObjCInstanceType();
+ TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(T, Loc);
+ return CreateParsedType(T, TInfo);
+}
+
+
//===----------------------------------------------------------------------===//
// Type Attribute Processing
//===----------------------------------------------------------------------===//
@@ -3064,14 +3150,22 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
const AttributeList &Attr, Sema &S){
// If this type is already address space qualified, reject it.
- // Clause 6.7.3 - Type qualifiers: "No type shall be qualified by qualifiers
- // for two or more different address spaces."
+ // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "No type shall be qualified by
+ // qualifiers for two or more different address spaces."
if (Type.getAddressSpace()) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
Attr.setInvalid();
return;
}
+ // ISO/IEC TR 18037 S5.3 (amending C99 6.7.3): "A function type shall not be
+ // qualified by an address-space qualifier."
+ if (Type->isFunctionType()) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_address_function_type);
+ Attr.setInvalid();
+ return;
+ }
+
// Check the attribute arguments.
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
@@ -3122,15 +3216,18 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
return false;
Sema &S = state.getSema();
+ SourceLocation AttrLoc = attr.getLoc();
+ if (AttrLoc.isMacroID())
+ AttrLoc = S.getSourceManager().getImmediateExpansionRange(AttrLoc).first;
if (type.getQualifiers().getObjCLifetime()) {
- S.Diag(attr.getLoc(), diag::err_attr_objc_ownership_redundant)
+ S.Diag(AttrLoc, diag::err_attr_objc_ownership_redundant)
<< type;
return true;
}
if (!attr.getParameterName()) {
- S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
+ S.Diag(AttrLoc, diag::err_attribute_argument_n_not_string)
<< "objc_ownership" << 1;
attr.setInvalid();
return true;
@@ -3146,7 +3243,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
else if (attr.getParameterName()->isStr("autoreleasing"))
lifetime = Qualifiers::OCL_Autoreleasing;
else {
- S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported)
+ S.Diag(AttrLoc, diag::warn_attribute_type_not_supported)
<< "objc_ownership" << attr.getParameterName();
attr.setInvalid();
return true;
@@ -3164,7 +3261,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
// If we have a valid source location for the attribute, use an
// AttributedType instead.
- if (attr.getLoc().isValid())
+ if (AttrLoc.isValid())
type = S.Context.getAttributedType(AttributedType::attr_objc_ownership,
origType, type);
@@ -3175,10 +3272,11 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
// Actually, delay this until we know what we're parsing.
if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
S.DelayedDiagnostics.add(
- sema::DelayedDiagnostic::makeForbiddenType(attr.getLoc(),
+ sema::DelayedDiagnostic::makeForbiddenType(
+ S.getSourceManager().getExpansionLoc(AttrLoc),
diag::err_arc_weak_no_runtime, type, /*ignored*/ 0));
} else {
- S.Diag(attr.getLoc(), diag::err_arc_weak_no_runtime);
+ S.Diag(AttrLoc, diag::err_arc_weak_no_runtime);
}
attr.setInvalid();
@@ -3194,7 +3292,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) {
ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl();
if (Class->isArcWeakrefUnavailable()) {
- S.Diag(attr.getLoc(), diag::err_arc_unsupported_weak_class);
+ S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
S.Diag(ObjT->getInterfaceDecl()->getLocation(),
diag::note_class_declared);
}
@@ -3283,7 +3381,7 @@ namespace {
QualType Original;
const FunctionType *Fn;
- llvm::SmallVector<unsigned char /*WrapKind*/, 8> Stack;
+ SmallVector<unsigned char /*WrapKind*/, 8> Stack;
FunctionTypeUnwrapper(Sema &S, QualType T) : Original(T) {
while (true) {
@@ -3474,7 +3572,7 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state,
return true;
}
- if (CCOld != CC_Default) {
+ if (CCOld != (S.LangOpts.MRTD ? CC_X86StdCall : CC_Default)) {
// Should we diagnose reapplications of the same convention?
S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
<< FunctionType::getNameForCallConv(CC)
@@ -3718,32 +3816,44 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
switch (attr.getKind()) {
default: break;
+ case AttributeList::AT_may_alias:
+ // FIXME: This attribute needs to actually be handled, but if we ignore
+ // it it breaks large amounts of Linux software.
+ attr.setUsedAsTypeAttr();
+ break;
case AttributeList::AT_address_space:
HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
+ attr.setUsedAsTypeAttr();
break;
OBJC_POINTER_TYPE_ATTRS_CASELIST:
if (!handleObjCPointerTypeAttr(state, attr, type))
distributeObjCPointerTypeAttr(state, attr, type);
+ attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_vector_size:
HandleVectorSizeAttr(type, attr, state.getSema());
+ attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_ext_vector_type:
if (state.getDeclarator().getDeclSpec().getStorageClassSpec()
!= DeclSpec::SCS_typedef)
HandleExtVectorTypeAttr(type, attr, state.getSema());
+ attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_neon_vector_type:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
VectorType::NeonVector, "neon_vector_type");
+ attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_neon_polyvector_type:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
VectorType::NeonPolyVector,
"neon_polyvector_type");
+ attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_opencl_image_access:
HandleOpenCLImageAccessAttribute(type, attr, state.getSema());
+ attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_ns_returns_retained:
@@ -3752,6 +3862,8 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
// fallthrough into the function attrs
FUNCTION_TYPE_ATTRS_CASELIST:
+ attr.setUsedAsTypeAttr();
+
// Never process function type attributes as part of the
// declaration-specifiers.
if (isDeclSpec)
@@ -3954,6 +4066,121 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
std::make_pair(SourceLocation(), PDiag(0)));
}
+/// @brief Ensure that the type T is a literal type.
+///
+/// This routine checks whether the type @p T is a literal type. If @p T is an
+/// incomplete type, an attempt is made to complete it. If @p T is a literal
+/// type, or @p AllowIncompleteType is true and @p T is an incomplete type,
+/// returns false. Otherwise, this routine issues the diagnostic @p PD (giving
+/// it the type @p T), along with notes explaining why the type is not a
+/// literal type, and returns true.
+///
+/// @param Loc The location in the source that the non-literal type
+/// diagnostic should refer to.
+///
+/// @param T The type that this routine is examining for literalness.
+///
+/// @param PD The partial diagnostic that will be printed out if T is not a
+/// literal type.
+///
+/// @param AllowIncompleteType If true, an incomplete type will be considered
+/// acceptable.
+///
+/// @returns @c true if @p T is not a literal type and a diagnostic was emitted,
+/// @c false otherwise.
+bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
+ const PartialDiagnostic &PD,
+ bool AllowIncompleteType) {
+ assert(!T->isDependentType() && "type should not be dependent");
+
+ bool Incomplete = RequireCompleteType(Loc, T, 0);
+ if (T->isLiteralType() || (AllowIncompleteType && Incomplete))
+ return false;
+
+ if (PD.getDiagID() == 0)
+ return true;
+
+ Diag(Loc, PD) << T;
+
+ if (T->isVariableArrayType())
+ return true;
+
+ const RecordType *RT = T->getBaseElementTypeUnsafe()->getAs<RecordType>();
+ if (!RT)
+ return true;
+
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+
+ // If the class has virtual base classes, then it's not an aggregate, and
+ // cannot have any constexpr constructors, so is non-literal. This is better
+ // to diagnose than the resulting absence of constexpr constructors.
+ if (RD->getNumVBases()) {
+ Diag(RD->getLocation(), diag::note_non_literal_virtual_base)
+ << RD->isStruct() << RD->getNumVBases();
+ for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
+ E = RD->vbases_end(); I != E; ++I)
+ Diag(I->getSourceRange().getBegin(),
+ diag::note_constexpr_virtual_base_here) << I->getSourceRange();
+ } else if (!RD->isAggregate() && !RD->hasConstexprNonCopyMoveConstructor()) {
+ Diag(RD->getLocation(), diag::note_non_literal_no_constexpr_ctors) << RD;
+
+ switch (RD->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ExplicitSpecialization:
+ break;
+
+ case TSK_ImplicitInstantiation:
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ // If the base template had constexpr constructors which were
+ // instantiated as non-constexpr constructors, explain why.
+ for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(),
+ E = RD->ctor_end(); I != E; ++I) {
+ if ((*I)->isCopyConstructor() || (*I)->isMoveConstructor())
+ continue;
+
+ FunctionDecl *Base = (*I)->getInstantiatedFromMemberFunction();
+ if (Base && Base->isConstexpr())
+ CheckConstexprFunctionDecl(*I, CCK_NoteNonConstexprInstantiation);
+ }
+ }
+ } else if (RD->hasNonLiteralTypeFieldsOrBases()) {
+ for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+ E = RD->bases_end(); I != E; ++I) {
+ if (!I->getType()->isLiteralType()) {
+ Diag(I->getSourceRange().getBegin(),
+ diag::note_non_literal_base_class)
+ << RD << I->getType() << I->getSourceRange();
+ return true;
+ }
+ }
+ for (CXXRecordDecl::field_iterator I = RD->field_begin(),
+ E = RD->field_end(); I != E; ++I) {
+ if (!(*I)->getType()->isLiteralType()) {
+ Diag((*I)->getLocation(), diag::note_non_literal_field)
+ << RD << (*I) << (*I)->getType();
+ return true;
+ } else if ((*I)->isMutable()) {
+ Diag((*I)->getLocation(), diag::note_non_literal_mutable_field) << RD;
+ 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.
+ 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;
+ }
+
+ return true;
+}
+
/// \brief Retrieve a version of the type 'T' that is elaborated by Keyword
/// and qualified by the nested-name-specifier contained in SS.
QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
@@ -4015,3 +4242,36 @@ QualType Sema::BuildUnaryTransformType(QualType BaseType,
}
llvm_unreachable("unknown unary transform type");
}
+
+QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
+ if (!T->isDependentType()) {
+ int DisallowedKind = -1;
+ if (T->isIncompleteType())
+ // FIXME: It isn't entirely clear whether incomplete atomic types
+ // are allowed or not; for simplicity, ban them for the moment.
+ DisallowedKind = 0;
+ else if (T->isArrayType())
+ DisallowedKind = 1;
+ else if (T->isFunctionType())
+ DisallowedKind = 2;
+ else if (T->isReferenceType())
+ DisallowedKind = 3;
+ else if (T->isAtomicType())
+ DisallowedKind = 4;
+ else if (T.hasQualifiers())
+ DisallowedKind = 5;
+ else if (!T.isTriviallyCopyableType(Context))
+ // Some other non-trivially-copyable type (probably a C++ class)
+ DisallowedKind = 6;
+
+ if (DisallowedKind != -1) {
+ Diag(Loc, diag::err_atomic_specifier_bad_type) << DisallowedKind << T;
+ return QualType();
+ }
+
+ // FIXME: Do we need any handling for ARC here?
+ }
+
+ // Build the pointer type.
+ return Context.getAtomicType(T);
+}