Author: rsmith Date: Wed Feb 8 14:39:08 2017 New Revision: 294509 URL: http://llvm.org/viewvc/llvm-project?rev=294509&view=rev Log: More fixes for places where 'decltype(auto)' is permitted in the C++ grammar but makes no sense.
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Parse/ParseExprCXX.cpp cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/lib/Sema/SemaExprCXX.cpp cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=294509&r1=294508&r2=294509&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Feb 8 14:39:08 2017 @@ -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< Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=294509&r1=294508&r2=294509&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Wed Feb 8 14:39:08 2017 @@ -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, Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=294509&r1=294508&r2=294509&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Wed Feb 8 14:39:08 2017 @@ -2580,7 +2580,8 @@ bool Parser::ParseUnqualifiedId(CXXScope 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; } Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=294509&r1=294508&r2=294509&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Feb 8 14:39:08 2017 @@ -3728,6 +3728,9 @@ Sema::BuildMemInitializer(Decl *Construc 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); Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=294509&r1=294508&r2=294509&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Feb 8 14:39:08 2017 @@ -323,20 +323,31 @@ ParsedType Sema::getDestructorName(Sourc 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, Modified: cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp?rev=294509&r1=294508&r2=294509&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp Wed Feb 8 14:39:08 2017 @@ -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 { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits