More fixes for places where 'decltype(auto)' is permitted in the C++ grammar but makes no sense.

llvm-svn: 294509
This commit is contained in:
Richard Smith 2017-02-08 20:39:08 +00:00
parent a028b33c7f
commit ef2cd8f8c3
6 changed files with 55 additions and 22 deletions

View File

@ -1944,6 +1944,8 @@ def err_auto_bitfield : Error<
"cannot pass bit-field as __auto_type initializer in C">;
// C++1y decltype(auto) type
def err_decltype_auto_invalid : Error<
"'decltype(auto)' not allowed here">;
def err_decltype_auto_cannot_be_combined : Error<
"'decltype(auto)' cannot be combined with other type specifiers">;
def err_decltype_auto_function_declarator_not_declaration : Error<

View File

@ -4749,7 +4749,8 @@ public:
ParsedType ObjectType,
bool EnteringContext);
ParsedType getDestructorType(const DeclSpec& DS, ParsedType ObjectType);
ParsedType getDestructorTypeForDecltype(const DeclSpec &DS,
ParsedType ObjectType);
// Checks that reinterpret casts don't have undefined behavior.
void CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,

View File

@ -2580,7 +2580,8 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
if (SS.isEmpty() && Tok.is(tok::kw_decltype)) {
DeclSpec DS(AttrFactory);
SourceLocation EndLoc = ParseDecltypeSpecifier(DS);
if (ParsedType Type = Actions.getDestructorType(DS, ObjectType)) {
if (ParsedType Type =
Actions.getDestructorTypeForDecltype(DS, ObjectType)) {
Result.setDestructorName(TildeLoc, Type, EndLoc);
return false;
}

View File

@ -3728,6 +3728,9 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo);
} else if (DS.getTypeSpecType() == TST_decltype) {
BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
} else if (DS.getTypeSpecType() == TST_decltype_auto) {
Diag(DS.getTypeSpecTypeLoc(), diag::err_decltype_auto_invalid);
return true;
} else {
LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName);
LookupParsedName(R, S, &SS);

View File

@ -323,20 +323,31 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc,
return nullptr;
}
ParsedType Sema::getDestructorType(const DeclSpec& DS, ParsedType ObjectType) {
if (DS.getTypeSpecType() == DeclSpec::TST_error || !ObjectType)
return nullptr;
assert(DS.getTypeSpecType() == DeclSpec::TST_decltype
&& "only get destructor types from declspecs");
QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
QualType SearchType = GetTypeFromParser(ObjectType);
if (SearchType->isDependentType() || Context.hasSameUnqualifiedType(SearchType, T)) {
return ParsedType::make(T);
}
ParsedType Sema::getDestructorTypeForDecltype(const DeclSpec &DS,
ParsedType ObjectType) {
if (DS.getTypeSpecType() == DeclSpec::TST_error)
return nullptr;
if (DS.getTypeSpecType() == DeclSpec::TST_decltype_auto) {
Diag(DS.getTypeSpecTypeLoc(), diag::err_decltype_auto_invalid);
return nullptr;
}
assert(DS.getTypeSpecType() == DeclSpec::TST_decltype &&
"unexpected type in getDestructorType");
QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
// If we know the type of the object, check that the correct destructor
// type was named now; we can give better diagnostics this way.
QualType SearchType = GetTypeFromParser(ObjectType);
if (!SearchType.isNull() && !SearchType->isDependentType() &&
!Context.hasSameUnqualifiedType(T, SearchType)) {
Diag(DS.getTypeSpecTypeLoc(), diag::err_destructor_expr_type_mismatch)
<< T << SearchType;
return nullptr;
}
return ParsedType::make(T);
}
bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS,

View File

@ -385,16 +385,31 @@ namespace MemberTemplatesWithDeduction {
}
}
namespace NNS {
int n;
decltype(auto) i();
decltype(n) j();
struct X {
// We resolve a wording bug here: 'decltype(auto)::' should not be parsed
// as a nested-name-specifier.
friend decltype(auto) ::NNS::i();
friend decltype(n) ::NNS::j(); // expected-error {{not a class}}
};
// We resolve a wording bug here: 'decltype(auto)' should not be modeled as a
// decltype-specifier, just as a simple-type-specifier. All the extra places
// where a decltype-specifier can appear make no sense for 'decltype(auto)'.
namespace DecltypeAutoShouldNotBeADecltypeSpecifier {
namespace NNS {
int n;
decltype(auto) i();
decltype(n) j();
struct X {
friend decltype(auto) ::DecltypeAutoShouldNotBeADecltypeSpecifier::NNS::i();
friend decltype(n) ::DecltypeAutoShouldNotBeADecltypeSpecifier::NNS::j(); // expected-error {{not a class}}
};
}
namespace Dtor {
struct A {};
void f(A a) { a.~decltype(auto)(); } // expected-error {{'decltype(auto)' not allowed here}}
}
namespace BaseClass {
struct A : decltype(auto) {}; // expected-error {{'decltype(auto)' not allowed here}}
struct B {
B() : decltype(auto)() {} // expected-error {{'decltype(auto)' not allowed here}}
};
}
}
namespace CurrentInstantiation {