aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaType.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-04-26 16:15:35 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-04-26 16:15:35 +0000
commita2c3646c35dd09d21b74826240aa916545b1873f (patch)
treee2a57dcc3d41734ea9734c76a9d759c8951392f4 /lib/Sema/SemaType.cpp
parentbebf5b1bcfbf591dd3cd80c4aebd6486bb34f41c (diff)
Implement C++1y decltype(auto).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180610 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r--lib/Sema/SemaType.cpp69
1 files changed, 58 insertions, 11 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 5289d15c34..8bf5143bed 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -994,11 +994,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 +1460,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.
@@ -2063,7 +2060,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 (D.getDeclSpec().containsPlaceholderType() &&
(!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) {
int Error = -1;
@@ -2402,6 +2399,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 :).
@@ -2530,6 +2567,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;
+ D.setInvalidType(true);
+ }
+ }
+
T = S.BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals,
SourceRange(DeclType.Loc, DeclType.EndLoc), Name);
break;
@@ -2560,7 +2606,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();