summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaType.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r--lib/Sema/SemaType.cpp118
1 files changed, 91 insertions, 27 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 7169eea..0959f7d 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -793,9 +793,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
// "At least one type specifier shall be given in the declaration
// specifiers in each declaration, and in the specifier-qualifier list in
// each struct declaration and type name."
- // FIXME: Does Microsoft really have the implicit int extension in C++?
- if (S.getLangOpts().CPlusPlus &&
- !S.getLangOpts().MicrosoftExt) {
+ if (S.getLangOpts().CPlusPlus) {
S.Diag(DeclLoc, diag::err_missing_type_specifier)
<< DS.getSourceRange();
@@ -994,11 +992,14 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
}
break;
- case DeclSpec::TST_auto: {
+ case DeclSpec::TST_auto:
// TypeQuals handled by caller.
- Result = Context.getAutoType(QualType());
+ Result = Context.getAutoType(QualType(), /*decltype(auto)*/false);
+ break;
+
+ case DeclSpec::TST_decltype_auto:
+ Result = Context.getAutoType(QualType(), /*decltype(auto)*/true);
break;
- }
case DeclSpec::TST_unknown_anytype:
Result = Context.UnknownAnyTy;
@@ -1457,12 +1458,6 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
return QualType();
}
- if (T->getContainedAutoType()) {
- Diag(Loc, diag::err_illegal_decl_array_of_auto)
- << getPrintableNameForEntity(Entity) << T;
- return QualType();
- }
-
if (const RecordType *EltTy = T->getAs<RecordType>()) {
// If the element type is a struct or union that contains a variadic
// array, accept it as a GNU extension: C99 6.7.2.1p2.
@@ -1572,6 +1567,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
if (!getLangOpts().C99) {
if (T->isVariableArrayType()) {
// Prohibit the use of non-POD types in VLAs.
+ // FIXME: C++1y allows this.
QualType BaseT = Context.getBaseElementType(T);
if (!T->isDependentType() &&
!BaseT.isPODType(Context) &&
@@ -1587,7 +1583,9 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
}
// Just extwarn about VLAs.
else
- Diag(Loc, diag::ext_vla);
+ Diag(Loc, getLangOpts().CPlusPlus1y
+ ? diag::warn_cxx11_compat_array_of_runtime_bound
+ : diag::ext_vla);
} else if (ASM != ArrayType::Normal || Quals != 0)
Diag(Loc,
getLangOpts().CPlusPlus? diag::err_c99_array_usage_cxx
@@ -2020,6 +2018,8 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// The TagDecl owned by the DeclSpec.
TagDecl *OwnedTagDecl = 0;
+ bool ContainsPlaceholderType = false;
+
switch (D.getName().getKind()) {
case UnqualifiedId::IK_ImplicitSelfParam:
case UnqualifiedId::IK_OperatorFunctionId:
@@ -2027,6 +2027,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
case UnqualifiedId::IK_LiteralOperatorId:
case UnqualifiedId::IK_TemplateId:
T = ConvertDeclSpecToType(state);
+ ContainsPlaceholderType = D.getDeclSpec().containsPlaceholderType();
if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
OwnedTagDecl = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
@@ -2050,6 +2051,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// converts to.
T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId,
&ReturnTypeInfo);
+ ContainsPlaceholderType = T->getContainedAutoType();
break;
}
@@ -2060,7 +2062,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
// In C++11, a function declarator using 'auto' must have a trailing return
// type (this is checked later) and we can skip this. In other languages
// using auto, we need to check regardless.
- if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
+ if (ContainsPlaceholderType &&
(!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) {
int Error = -1;
@@ -2103,10 +2105,15 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
Error = 10; // Type alias
break;
case Declarator::TrailingReturnContext:
- Error = 11; // Function return type
+ if (!SemaRef.getLangOpts().CPlusPlus1y)
+ Error = 11; // Function return type
+ break;
+ case Declarator::ConversionIdContext:
+ if (!SemaRef.getLangOpts().CPlusPlus1y)
+ Error = 12; // conversion-type-id
break;
case Declarator::TypeNameContext:
- Error = 12; // Generic
+ Error = 13; // Generic
break;
case Declarator::FileContext:
case Declarator::BlockContext:
@@ -2142,15 +2149,19 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
}
}
+ SourceRange AutoRange = D.getDeclSpec().getTypeSpecTypeLoc();
+ if (D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId)
+ AutoRange = D.getName().getSourceRange();
+
if (Error != -1) {
- SemaRef.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
- diag::err_auto_not_allowed)
- << Error;
+ SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed)
+ << Error << AutoRange;
T = SemaRef.Context.IntTy;
D.setInvalidType(true);
} else
- SemaRef.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
- diag::warn_cxx98_compat_auto_type_specifier);
+ SemaRef.Diag(AutoRange.getBegin(),
+ diag::warn_cxx98_compat_auto_type_specifier)
+ << AutoRange;
}
if (SemaRef.getLangOpts().CPlusPlus &&
@@ -2182,6 +2193,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
D.setInvalidType(true);
break;
case Declarator::TypeNameContext:
+ case Declarator::ConversionIdContext:
case Declarator::TemplateParamContext:
case Declarator::CXXNewContext:
case Declarator::CXXCatchContext:
@@ -2399,6 +2411,46 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
(T->castAs<FunctionProtoType>()->getTypeQuals() != 0 ||
T->castAs<FunctionProtoType>()->getRefQualifier() != RQ_None);
+ // If T is 'decltype(auto)', the only declarators we can have are parens
+ // and at most one function declarator if this is a function declaration.
+ if (const AutoType *AT = T->getAs<AutoType>()) {
+ if (AT->isDecltypeAuto()) {
+ for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) {
+ unsigned Index = E - I - 1;
+ DeclaratorChunk &DeclChunk = D.getTypeObject(Index);
+ unsigned DiagId = diag::err_decltype_auto_compound_type;
+ unsigned DiagKind = 0;
+ switch (DeclChunk.Kind) {
+ case DeclaratorChunk::Paren:
+ continue;
+ case DeclaratorChunk::Function: {
+ unsigned FnIndex;
+ if (D.isFunctionDeclarationContext() &&
+ D.isFunctionDeclarator(FnIndex) && FnIndex == Index)
+ continue;
+ DiagId = diag::err_decltype_auto_function_declarator_not_declaration;
+ break;
+ }
+ case DeclaratorChunk::Pointer:
+ case DeclaratorChunk::BlockPointer:
+ case DeclaratorChunk::MemberPointer:
+ DiagKind = 0;
+ break;
+ case DeclaratorChunk::Reference:
+ DiagKind = 1;
+ break;
+ case DeclaratorChunk::Array:
+ DiagKind = 2;
+ break;
+ }
+
+ S.Diag(DeclChunk.Loc, DiagId) << DiagKind;
+ D.setInvalidType(true);
+ break;
+ }
+ }
+ }
+
// Walk the DeclTypeInfo, building the recursive type as we go.
// DeclTypeInfos are ordered from the identifier out, which is
// opposite of what we want :).
@@ -2527,6 +2579,15 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
}
}
+ if (const AutoType *AT = T->getContainedAutoType()) {
+ // We've already diagnosed this for decltype(auto).
+ if (!AT->isDecltypeAuto())
+ S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto)
+ << getPrintableNameForEntity(Name) << T;
+ T = QualType();
+ break;
+ }
+
T = S.BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals,
SourceRange(DeclType.Loc, DeclType.EndLoc), Name);
break;
@@ -2544,7 +2605,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// trailing-return-type is only required if we're declaring a function,
// and not, for instance, a pointer to a function.
if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
- !FTI.hasTrailingReturnType() && chunkIndex == 0) {
+ !FTI.hasTrailingReturnType() && chunkIndex == 0 &&
+ !S.getLangOpts().CPlusPlus1y) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::err_auto_missing_trailing_return);
T = Context.IntTy;
@@ -2557,7 +2619,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
<< T << D.getDeclSpec().getSourceRange();
D.setInvalidType(true);
} else if (D.getContext() != Declarator::LambdaExprContext &&
- (T.hasQualifiers() || !isa<AutoType>(T))) {
+ (T.hasQualifiers() || !isa<AutoType>(T) ||
+ cast<AutoType>(T)->isDecltypeAuto())) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::err_trailing_return_without_auto)
<< T << D.getDeclSpec().getSourceRange();
@@ -3044,6 +3107,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
case Declarator::ObjCCatchContext:
case Declarator::BlockLiteralContext:
case Declarator::LambdaExprContext:
+ case Declarator::ConversionIdContext:
case Declarator::TrailingReturnContext:
case Declarator::TemplateTypeArgContext:
// FIXME: We may want to allow parameter packs in block-literal contexts
@@ -3781,7 +3845,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
QualType &type) {
bool NonObjCPointer = false;
- if (!type->isDependentType()) {
+ if (!type->isDependentType() && !type->isUndeducedType()) {
if (const PointerType *ptr = type->getAs<PointerType>()) {
QualType pointee = ptr->getPointeeType();
if (pointee->isObjCRetainableType() || pointee->isPointerType())
@@ -4806,7 +4870,7 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
QualType ElemType = Context.getBaseElementType(T);
RequireCompleteType(Loc, ElemType, 0);
- if (T->isLiteralType())
+ if (T->isLiteralType(Context))
return false;
if (Diagnoser.Suppressed)
@@ -4848,7 +4912,7 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
} 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()) {
+ if (!I->getType()->isLiteralType(Context)) {
Diag(I->getLocStart(),
diag::note_non_literal_base_class)
<< RD << I->getType() << I->getSourceRange();
@@ -4857,7 +4921,7 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
}
for (CXXRecordDecl::field_iterator I = RD->field_begin(),
E = RD->field_end(); I != E; ++I) {
- if (!I->getType()->isLiteralType() ||
+ if (!I->getType()->isLiteralType(Context) ||
I->getType().isVolatileQualified()) {
Diag(I->getLocation(), diag::note_non_literal_field)
<< RD << *I << I->getType()
OpenPOWER on IntegriCloud