зеркало из https://github.com/microsoft/clang-1.git
Fix a few auto-related issues:
* 'auto' was being rejected on abstract-declarators with trailing return types and on typedefs with trailing return types. 'auto' is always allowed in these cases. This was found while testing the fix for PR 9278. * A very poor diagnostic was being issued for auto (f() -> int): "return type must be 'auto', not 'auto'". This is closely related to PR 9060. * Trailing return type handling was happening slightly too late, resulting in the checks for functions returning arrays and functions returning functions being missed. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126166 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
24d44eddfc
Коммит
e7397c6a1b
|
@ -918,6 +918,8 @@ def err_auto_missing_trailing_return : Error<
|
|||
"'auto' return without trailing return type">;
|
||||
def err_trailing_return_without_auto : Error<
|
||||
"function with trailing return type must specify return type 'auto', not %0">;
|
||||
def err_trailing_return_in_parens : Error<
|
||||
"trailing return type may not be nested within parentheses">;
|
||||
def err_auto_var_deduction_failure : Error<
|
||||
"variable %0 with type %1 has incompatible initializer of type %2">;
|
||||
def err_auto_new_deduction_failure : Error<
|
||||
|
|
|
@ -1450,6 +1450,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
if (D.getAttributes())
|
||||
distributeTypeAttrsFromDeclarator(state, T);
|
||||
|
||||
// C++0x [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context.
|
||||
if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
|
||||
!D.isFunctionDeclarator()) {
|
||||
int Error = -1;
|
||||
|
@ -1495,6 +1496,25 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
|
||||
Error = 8;
|
||||
|
||||
// C++0x [dcl.spec.auto]p2: 'auto' is always fine if the declarator
|
||||
// contains a trailing return type. That is only legal at the outermost
|
||||
// level. Check all declarator chunks (outermost first) anyway, to give
|
||||
// better diagnostics.
|
||||
if (Error != -1) {
|
||||
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
|
||||
unsigned chunkIndex = e - i - 1;
|
||||
state.setCurrentChunkIndex(chunkIndex);
|
||||
DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
|
||||
if (DeclType.Kind == DeclaratorChunk::Function) {
|
||||
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
|
||||
if (FTI.TrailingReturnType) {
|
||||
Error = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Error != -1) {
|
||||
Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_auto_not_allowed)
|
||||
<< Error;
|
||||
|
@ -1502,7 +1522,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
D.setInvalidType(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (T.isNull())
|
||||
return Context.getNullTypeSourceInfo();
|
||||
|
||||
|
@ -1603,6 +1623,37 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
// of the type, otherwise the argument list is ().
|
||||
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
|
||||
|
||||
// Check for auto functions and trailing return type and adjust the
|
||||
// return type accordingly.
|
||||
if (!D.isInvalidType()) {
|
||||
// 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.TrailingReturnType && chunkIndex == 0) {
|
||||
Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
|
||||
diag::err_auto_missing_trailing_return);
|
||||
T = Context.IntTy;
|
||||
D.setInvalidType(true);
|
||||
} else if (FTI.TrailingReturnType) {
|
||||
// T must be exactly 'auto' at this point. See CWG issue 681.
|
||||
if (isa<ParenType>(T)) {
|
||||
Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
|
||||
diag::err_trailing_return_in_parens)
|
||||
<< T << D.getDeclSpec().getSourceRange();
|
||||
D.setInvalidType(true);
|
||||
} else if (T.hasQualifiers() || !isa<AutoType>(T)) {
|
||||
Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
|
||||
diag::err_trailing_return_without_auto)
|
||||
<< T << D.getDeclSpec().getSourceRange();
|
||||
D.setInvalidType(true);
|
||||
}
|
||||
|
||||
T = GetTypeFromParser(
|
||||
ParsedType::getFromOpaquePtr(FTI.TrailingReturnType),
|
||||
&ReturnTypeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// C99 6.7.5.3p1: The return type may not be a function or array type.
|
||||
// For conversion functions, we'll diagnose this particular error later.
|
||||
if ((T->isArrayType() || T->isFunctionType()) &&
|
||||
|
@ -1618,32 +1669,6 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
D.setInvalidType(true);
|
||||
}
|
||||
|
||||
// Check for auto functions and trailing return type and adjust the
|
||||
// return type accordingly.
|
||||
if (!D.isInvalidType()) {
|
||||
// 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.TrailingReturnType && chunkIndex == 0) {
|
||||
Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
|
||||
diag::err_auto_missing_trailing_return);
|
||||
T = Context.IntTy;
|
||||
D.setInvalidType(true);
|
||||
} else if (FTI.TrailingReturnType) {
|
||||
if (T.hasQualifiers() || !isa<AutoType>(T)) {
|
||||
// T must be exactly 'auto' at this point. See CWG issue 681.
|
||||
Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
|
||||
diag::err_trailing_return_without_auto)
|
||||
<< T << D.getDeclSpec().getSourceRange();
|
||||
D.setInvalidType(true);
|
||||
}
|
||||
|
||||
T = GetTypeFromParser(
|
||||
ParsedType::getFromOpaquePtr(FTI.TrailingReturnType),
|
||||
&ReturnTypeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// cv-qualifiers on return types are pointless except when the type is a
|
||||
// class type in C++.
|
||||
if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() &&
|
||||
|
@ -2050,7 +2075,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (T.isNull())
|
||||
return Context.getNullTypeSourceInfo();
|
||||
else if (D.isInvalidType())
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
// RUN: %clang_cc1 -fexceptions -fsyntax-only -verify %s -std=c++0x
|
||||
|
||||
struct S {
|
||||
virtual ~S();
|
||||
|
||||
void g() throw (auto(*)()->int);
|
||||
|
||||
// Note, this is not permitted: conversion-declarator cannot have a trailing return type.
|
||||
// FIXME: don't issue the second diagnostic for this.
|
||||
operator auto(*)()->int(); // expected-error{{'auto' not allowed here}} expected-error {{C++ requires a type specifier}}
|
||||
};
|
||||
|
||||
typedef auto Fun(int a) -> decltype(a + a);
|
||||
typedef auto (*PFun)(int a) -> decltype(a + a);
|
||||
|
||||
void g(auto (*f)() -> int) {
|
||||
try { }
|
||||
catch (auto (&f)() -> int) { }
|
||||
catch (auto (*const f[10])() -> int) { }
|
||||
}
|
||||
|
||||
namespace std {
|
||||
class type_info;
|
||||
}
|
||||
|
||||
template<typename T> struct U {};
|
||||
|
||||
void j() {
|
||||
(void)typeid(auto(*)()->void);
|
||||
(void)sizeof(auto(*)()->void);
|
||||
(void)__alignof(auto(*)()->void);
|
||||
|
||||
U<auto(*)()->void> v;
|
||||
|
||||
int n;
|
||||
(void)static_cast<auto(*)()->void>(&j);
|
||||
auto p = reinterpret_cast<auto(*)()->int>(&j);
|
||||
(void)const_cast<auto(**)()->int>(&p);
|
||||
(void)(auto(*)()->void)(&j);
|
||||
}
|
||||
|
||||
template <auto (*f)() -> void = &j> class C { };
|
||||
struct F : auto(*)()->int {}; // expected-error{{expected class name}}
|
||||
template<typename T = auto(*)()->int> struct G { };
|
||||
|
||||
int g();
|
||||
auto (*h)() -> auto = &g; // expected-error{{'auto' not allowed here}}
|
||||
auto (*i)() = &g; // ok; auto deduced as int.
|
||||
auto (*k)() -> int = i; // ok; no deduction.
|
|
@ -16,6 +16,7 @@ struct S {
|
|||
|
||||
// PR 9278: auto is not allowed in typedefs, except with a trailing return type.
|
||||
typedef auto *AutoPtr; // expected-error{{'auto' not allowed in typedef}}
|
||||
typedef auto (*PFun)(int a); // expected-error{{'auto' not allowed in typedef}}
|
||||
typedef auto Fun(int a) -> decltype(a + a);
|
||||
|
||||
void g(auto a) { // expected-error{{'auto' not allowed in function prototype}}
|
||||
|
@ -64,13 +65,5 @@ template<typename T = auto> struct G { }; // expected-error{{'auto' not allowed
|
|||
|
||||
using A = auto; // expected-error{{expected ';'}} expected-error{{requires a qualified name}}
|
||||
|
||||
// Whether this is illegal depends on the interpretation of [decl.spec.auto]p2 and p3,
|
||||
// and in particular the "Otherwise, ..." at the start of p3.
|
||||
namespace TrailingReturnType {
|
||||
// FIXME: don't issue the second diagnostic for this error.
|
||||
auto f() -> auto; // expected-error{{'auto' not allowed here}} unexpected-error{{without trailing return type}}
|
||||
int g();
|
||||
auto (*h)() -> auto = &g; // expected-error{{'auto' not allowed here}}
|
||||
auto (*i)() = &g; // ok; auto deduced as int.
|
||||
auto (*j)() -> int = i; // ok; no deduction.
|
||||
}
|
||||
// FIXME: don't issue the second diagnostic for this error.
|
||||
auto k() -> auto; // expected-error{{'auto' not allowed here}} unexpected-error{{without trailing return type}}
|
||||
|
|
|
@ -3,3 +3,5 @@
|
|||
auto a() -> int; // ok
|
||||
const auto b() -> int; // expected-error {{function with trailing return type must specify return type 'auto', not 'auto const'}}
|
||||
auto *c() -> int; // expected-error {{function with trailing return type must specify return type 'auto', not 'auto *'}}
|
||||
auto (d() -> int); // expected-error {{trailing return type may not be nested within parentheses}}
|
||||
auto e() -> auto (*)() -> auto (*)() -> void; // ok: same as void (*(*e())())();
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
|
||||
|
||||
auto f() -> int[32]; // expected-error{{function cannot return array}}
|
||||
auto g() -> int(int); // expected-error{{function cannot return function}}
|
||||
auto h() -> auto() -> int; // expected-error{{function cannot return function}}
|
||||
auto i() -> auto(*)() -> int;
|
|
@ -0,0 +1,3 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s
|
||||
|
||||
auto j() -> enum { e3 }; // expected-error{{can not be defined in a type specifier}}
|
Загрузка…
Ссылка в новой задаче