From: Richard Smith Date: Tue, 12 Jun 2012 01:51:59 +0000 (+0000) Subject: If parsing a trailing-return-type fails, don't pretend we didn't have one at X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=54655be65585ed6618fdd7a19fa6c70efc321d3a;p=clang If parsing a trailing-return-type fails, don't pretend we didn't have one at all. Suppresses follow-on errors mentioned in PR13074. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158348 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 422a17cc25..6b52cd5e91 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -1104,6 +1104,10 @@ struct DeclaratorChunk { /// DeleteArgInfo - If this is true, we need to delete[] ArgInfo. unsigned DeleteArgInfo : 1; + /// HasTrailingReturnType - If this is true, a trailing return type was + /// specified. + unsigned HasTrailingReturnType : 1; + /// When isVariadic is true, the location of the ellipsis in the source. unsigned EllipsisLoc; @@ -1154,10 +1158,9 @@ struct DeclaratorChunk { Expr *NoexceptExpr; }; - /// TrailingReturnType - If this isn't null, it's the trailing return type - /// specified. This is actually a ParsedType, but stored as void* to - /// allow union storage. - void *TrailingReturnType; + /// TrailingReturnType - If HasTrailingReturnType is true, this is the + /// trailing return type specified. + UnionParsedType TrailingReturnType; /// freeArgs - reset the argument list to having zero arguments. This is /// used in various places for error recovery. @@ -1222,6 +1225,13 @@ struct DeclaratorChunk { ExceptionSpecificationType getExceptionSpecType() const { return static_cast(ExceptionSpecType); } + + /// \brief Determine whether this function declarator had a + /// trailing-return-type. + bool hasTrailingReturnType() const { return HasTrailingReturnType; } + + /// \brief Get the trailing-return-type for this function declarator. + ParsedType getTrailingReturnType() const { return TrailingReturnType; } }; struct BlockPointerTypeInfo : TypeInfoCommon { @@ -1352,8 +1362,8 @@ struct DeclaratorChunk { SourceLocation LocalRangeBegin, SourceLocation LocalRangeEnd, Declarator &TheDeclarator, - ParsedType TrailingReturnType = - ParsedType()); + TypeResult TrailingReturnType = + TypeResult()); /// getBlockPointer - Return a DeclaratorChunk for a block. /// diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index ac6378035c..3eeef7bff3 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -4276,7 +4276,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, SmallVector DynamicExceptionRanges; ExprResult NoexceptExpr; ParsedAttributes FnAttrs(AttrFactory); - ParsedType TrailingReturnType; + TypeResult TrailingReturnType; Actions.ActOnStartFunctionDeclarator(); @@ -4358,7 +4358,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, if (getLangOpts().CPlusPlus0x && Tok.is(tok::arrow)) { Diag(Tok, diag::warn_cxx98_compat_trailing_return_type); SourceRange Range; - TrailingReturnType = ParseTrailingReturnType(Range).get(); + TrailingReturnType = ParseTrailingReturnType(Range); if (Range.getEnd().isValid()) EndLoc = Range.getEnd(); } diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 68eff7cf5f..1c7b56fd4d 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -792,10 +792,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( MaybeParseCXX0XAttributes(Attr, &DeclEndLoc); // Parse trailing-return-type[opt]. - ParsedType TrailingReturnType; + TypeResult TrailingReturnType; if (Tok.is(tok::arrow)) { SourceRange Range; - TrailingReturnType = ParseTrailingReturnType(Range).get(); + TrailingReturnType = ParseTrailingReturnType(Range); if (Range.getEnd().isValid()) DeclEndLoc = Range.getEnd(); } @@ -838,10 +838,10 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( } // Parse the return type, if there is one. - ParsedType TrailingReturnType; + TypeResult TrailingReturnType; if (Tok.is(tok::arrow)) { SourceRange Range; - TrailingReturnType = ParseTrailingReturnType(Range).get(); + TrailingReturnType = ParseTrailingReturnType(Range); if (Range.getEnd().isValid()) DeclEndLoc = Range.getEnd(); } diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index 8ea72ca79c..f6764c2999 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -165,7 +165,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, SourceLocation LocalRangeBegin, SourceLocation LocalRangeEnd, Declarator &TheDeclarator, - ParsedType TrailingReturnType) { + TypeResult TrailingReturnType) { DeclaratorChunk I; I.Kind = Function; I.Loc = LocalRangeBegin; @@ -188,7 +188,9 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, I.Fun.NumExceptions = 0; I.Fun.Exceptions = 0; I.Fun.NoexceptExpr = 0; - I.Fun.TrailingReturnType = TrailingReturnType.getAsOpaquePtr(); + I.Fun.HasTrailingReturnType = TrailingReturnType.isUsable() || + TrailingReturnType.isInvalid(); + I.Fun.TrailingReturnType = TrailingReturnType.get(); // new[] an argument array if needed. if (NumArgs) { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 9ad8c30505..924b0f73d6 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5158,7 +5158,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, QualType T = R->getAs()->getResultType(); DeclaratorChunk &C = D.getTypeObject(0); if (!T->isVoidType() && C.Fun.NumArgs == 0 && !C.Fun.isVariadic && - !C.Fun.TrailingReturnType && + !C.Fun.hasTrailingReturnType() && C.Fun.getExceptionSpecType() == EST_None) { SourceRange ParenRange(C.Loc, C.EndLoc); Diag(C.Loc, diag::warn_empty_parens_are_function_decl) << ParenRange; diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 209c020fff..21af5f4f2e 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1901,7 +1901,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex); if (DeclType.Kind == DeclaratorChunk::Function) { const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; - if (FTI.TrailingReturnType) { + if (FTI.hasTrailingReturnType()) { Error = -1; break; } @@ -2176,12 +2176,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // 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) { + !FTI.hasTrailingReturnType() && chunkIndex == 0) { S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_auto_missing_trailing_return); T = Context.IntTy; D.setInvalidType(true); - } else if (FTI.TrailingReturnType) { + } else if (FTI.hasTrailingReturnType()) { // T must be exactly 'auto' at this point. See CWG issue 681. if (isa(T)) { S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(), @@ -2195,10 +2195,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, << T << D.getDeclSpec().getSourceRange(); D.setInvalidType(true); } - - T = S.GetTypeFromParser( - ParsedType::getFromOpaquePtr(FTI.TrailingReturnType), - &TInfo); + T = S.GetTypeFromParser(FTI.getTrailingReturnType(), &TInfo); + if (T.isNull()) { + // An error occurred parsing the trailing return type. + T = Context.IntTy; + D.setInvalidType(true); + } } } @@ -2301,7 +2303,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, FunctionProtoType::ExtProtoInfo EPI; EPI.Variadic = FTI.isVariadic; - EPI.HasTrailingReturn = FTI.TrailingReturnType; + EPI.HasTrailingReturn = FTI.hasTrailingReturnType(); EPI.TypeQuals = FTI.TypeQuals; EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None : FTI.RefQualifierIsLValueRef? RQ_LValue @@ -3119,7 +3121,7 @@ namespace { assert(Chunk.Kind == DeclaratorChunk::Function); TL.setLocalRangeBegin(Chunk.Loc); TL.setLocalRangeEnd(Chunk.EndLoc); - TL.setTrailingReturn(!!Chunk.Fun.TrailingReturnType); + TL.setTrailingReturn(Chunk.Fun.hasTrailingReturnType()); const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun; for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) { diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp index 71f57dcc66..7499829185 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp @@ -64,5 +64,4 @@ template struct G { }; // expected-error{{'auto' not allowed using A = auto; // expected-error{{'auto' not allowed in type alias}} -// FIXME: don't issue the second diagnostic for this error. -auto k() -> auto; // expected-error{{'auto' not allowed in function return type}} unexpected-error{{without trailing return type}} +auto k() -> auto; // expected-error{{'auto' not allowed in function return type}} diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp index 680e9124cb..719aeeddeb 100644 --- a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp +++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p9-0x.cpp @@ -4,4 +4,4 @@ // will necessarily be ill-formed as a trailing return type for a function // definition), and recover with a "type cannot be defined in a trailing return // type" error. -auto j() -> enum { e3 }; // expected-error{{unnamed enumeration must be a definition}} expected-error {{expected a type}} expected-error {{without trailing return type}} +auto j() -> enum { e3 }; // expected-error{{unnamed enumeration must be a definition}} expected-error {{expected a type}} diff --git a/test/Parser/cxx11-type-specifier.cpp b/test/Parser/cxx11-type-specifier.cpp index 212ffb407b..c66462a84f 100644 --- a/test/Parser/cxx11-type-specifier.cpp +++ b/test/Parser/cxx11-type-specifier.cpp @@ -21,7 +21,4 @@ void f() { // And for trailing-type-specifier-seq -// FIXME: Don't treat an ill-formed trailing-return-type the same as no -// trailing-return-type, and avoid the second diagnostic. -auto f() -> unknown; // expected-error{{unknown type name 'unknown'}} \ - expected-error{{'auto' return without trailing return type}} +auto f() -> unknown; // expected-error{{unknown type name 'unknown'}}