diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-10-01 18:44:50 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-10-01 18:44:50 +0000 |
commit | 7fb25418ed726c594ee800378538a96c69e84d4b (patch) | |
tree | ebd4b5fca812482aa6686384f20e5d279d6bc695 /clang/lib | |
parent | f14331f5c32c10ddca43ab4d0b3faff2fdfa1367 (diff) | |
download | bcm5719-llvm-7fb25418ed726c594ee800378538a96c69e84d4b.tar.gz bcm5719-llvm-7fb25418ed726c594ee800378538a96c69e84d4b.zip |
Implement the C++0x "trailing return type" feature, e.g.,
auto f(int) -> int
from Daniel Wallin!
(With a few minor bug fixes from me).
llvm-svn: 115322
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Lex/PPMacroExpansion.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 19 | ||||
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 26 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 35 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 1 |
9 files changed, 98 insertions, 17 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index ce76fcd9ba4..5c9530beb24 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1733,6 +1733,7 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray, bool hasAnyExceptionSpec, unsigned NumExs, const QualType *ExArray, const FunctionType::ExtInfo &Info) { + const CallingConv CallConv= Info.getCC(); // Unique functions, to guarantee there is only one function of a particular // structure. diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 46b671da199..ac69595227f 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -518,6 +518,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { .Case("cxx_exceptions", LangOpts.Exceptions) .Case("cxx_rtti", LangOpts.RTTI) .Case("cxx_static_assert", LangOpts.CPlusPlus0x) + .Case("cxx_trailing_return", LangOpts.CPlusPlus0x) .Case("objc_nonfragile_abi", LangOpts.ObjCNonFragileABI) .Case("objc_weak_class", LangOpts.ObjCNonFragileABI) .Case("ownership_holds", true) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 0a48d4d5507..89b41828b06 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3024,6 +3024,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // lparen is already consumed! assert(D.isPastIdentifier() && "Should not call before identifier!"); + ParsedType TrailingReturnType; + // This parameter list may be empty. if (Tok.is(tok::r_paren)) { if (RequiresArg) { @@ -3055,6 +3057,11 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, assert(Exceptions.size() == ExceptionRanges.size() && "Produced different number of exception types and ranges."); } + + // Parse trailing-return-type. + if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) { + TrailingReturnType = ParseTrailingReturnType().get(); + } } // Remember that we parsed a function type, and remember the attributes. @@ -3069,7 +3076,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, Exceptions.data(), ExceptionRanges.data(), Exceptions.size(), - LParenLoc, RParenLoc, D), + LParenLoc, RParenLoc, D, + TrailingReturnType), EndLoc); return; } @@ -3260,9 +3268,6 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, ConsumeToken(); } - // Leave prototype scope. - PrototypeScope.Exit(); - // If we have the closing ')', eat it. SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); SourceLocation EndLoc = RParenLoc; @@ -3289,8 +3294,19 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, assert(Exceptions.size() == ExceptionRanges.size() && "Produced different number of exception types and ranges."); } + + // Parse trailing-return-type. + if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) { + TrailingReturnType = ParseTrailingReturnType().get(); + } } + // FIXME: We should leave the prototype scope before parsing the exception + // specification, and then reenter it when parsing the trailing return type. + + // Leave prototype scope. + PrototypeScope.Exit(); + // Remember that we parsed a function type, and remember the attributes. D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic, EllipsisLoc, @@ -3301,7 +3317,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, Exceptions.data(), ExceptionRanges.data(), Exceptions.size(), - LParenLoc, RParenLoc, D), + LParenLoc, RParenLoc, D, + TrailingReturnType), EndLoc); } diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 092268c8215..59d4f9fad39 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1871,6 +1871,25 @@ bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc, return false; } +/// ParseTrailingReturnType - Parse a trailing return type on a new-style +/// function declaration. +TypeResult Parser::ParseTrailingReturnType() { + assert(Tok.is(tok::arrow) && "expected arrow"); + + ConsumeToken(); + + // FIXME: Need to suppress declarations when parsing this typename. + // Otherwise in this function definition: + // + // auto f() -> struct X {} + // + // struct X is parsed as class definition because of the trailing + // brace. + + SourceRange Range; + return ParseTypeName(&Range); +} + /// \brief We have just started parsing the definition of a new class, /// so push that class onto our stack of classes that is currently /// being parsed. diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index b46e8af9db8..979b76ae984 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -59,7 +59,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, unsigned NumExceptions, SourceLocation LPLoc, SourceLocation RPLoc, - Declarator &TheDeclarator) { + Declarator &TheDeclarator, + ParsedType TrailingReturnType) { DeclaratorChunk I; I.Kind = Function; I.Loc = LPLoc; @@ -76,6 +77,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec; I.Fun.NumExceptions = NumExceptions; I.Fun.Exceptions = 0; + I.Fun.TrailingReturnType = TrailingReturnType.getAsOpaquePtr(); // new[] an argument array if needed. if (NumArgs) { diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 254eb7984dc..542c31abfc4 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -994,7 +994,30 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, &ReturnTypeInfo); break; } - + + // Check for auto functions and trailing return type and adjust the + // return type accordingly. + if (getLangOptions().CPlusPlus0x && D.isFunctionDeclarator()) { + const DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + if (T == Context.UndeducedAutoTy) { + if (FTI.TrailingReturnType) { + T = GetTypeFromParser(ParsedType::getFromOpaquePtr(FTI.TrailingReturnType), + &ReturnTypeInfo); + } + else { + Diag(D.getDeclSpec().getTypeSpecTypeLoc(), + diag::err_auto_missing_trailing_return); + T = Context.IntTy; + D.setInvalidType(true); + } + } + else if (FTI.TrailingReturnType) { + Diag(D.getDeclSpec().getTypeSpecTypeLoc(), + diag::err_trailing_return_without_auto); + D.setInvalidType(true); + } + } + if (T.isNull()) return Context.getNullTypeSourceInfo(); @@ -1635,6 +1658,7 @@ namespace { assert(Chunk.Kind == DeclaratorChunk::Function); TL.setLParenLoc(Chunk.Loc); TL.setRParenLoc(Chunk.EndLoc); + TL.setTrailingReturn(!!Chunk.Fun.TrailingReturnType); const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun; for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) { diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 71492254c6e..135ca46958d 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -2928,20 +2928,33 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB, // the parameters, because users tend to expect this (even if they shouldn't // rely on it!). // - // FIXME: When we implement late-specified return types, we'll need to - // instantiate the return tpe *after* the parameter types in that case, - // since the return type can then refer to the parameters themselves (via - // decltype, sizeof, etc.). + // When the function has a trailing return type, we instantiate the + // parameters before the return type, since the return type can then refer + // to the parameters themselves (via decltype, sizeof, etc.). + // llvm::SmallVector<QualType, 4> ParamTypes; llvm::SmallVector<ParmVarDecl*, 4> ParamDecls; FunctionProtoType *T = TL.getTypePtr(); - QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc()); - if (ResultType.isNull()) - return QualType(); - if (getDerived().TransformFunctionTypeParams(TL, ParamTypes, ParamDecls)) - return QualType(); - + QualType ResultType; + + if (TL.getTrailingReturn()) { + if (getDerived().TransformFunctionTypeParams(TL, ParamTypes, ParamDecls)) + return QualType(); + + ResultType = getDerived().TransformType(TLB, TL.getResultLoc()); + if (ResultType.isNull()) + return QualType(); + } + else { + ResultType = getDerived().TransformType(TLB, TL.getResultLoc()); + if (ResultType.isNull()) + return QualType(); + + if (getDerived().TransformFunctionTypeParams(TL, ParamTypes, ParamDecls)) + return QualType(); + } + QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || ResultType != T->getResultType() || @@ -2959,6 +2972,7 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(Result); NewTL.setLParenLoc(TL.getLParenLoc()); NewTL.setRParenLoc(TL.getRParenLoc()); + NewTL.setTrailingReturn(TL.getTrailingReturn()); for (unsigned i = 0, e = NewTL.getNumArgs(); i != e; ++i) NewTL.setArg(i, ParamDecls[i]); @@ -2983,6 +2997,7 @@ QualType TreeTransform<Derived>::TransformFunctionNoProtoType( FunctionNoProtoTypeLoc NewTL = TLB.push<FunctionNoProtoTypeLoc>(Result); NewTL.setLParenLoc(TL.getLParenLoc()); NewTL.setRParenLoc(TL.getRParenLoc()); + NewTL.setTrailingReturn(false); return Result; } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 7b4264d51c9..ac7385976c0 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2942,6 +2942,7 @@ void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) { TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); + TL.setTrailingReturn(Record[Idx++]); for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) { TL.setArg(i, cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index f5f96ecd24e..ef8c52f4be1 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -412,6 +412,7 @@ void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) { Writer.AddSourceLocation(TL.getLParenLoc(), Record); Writer.AddSourceLocation(TL.getRParenLoc(), Record); + Record.push_back(TL.getTrailingReturn()); for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) Writer.AddDeclRef(TL.getArg(i), Record); } |