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:
parent
a028b33c7f
commit
ef2cd8f8c3
|
@ -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<
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue