From: Douglas Gregor Date: Wed, 26 Jan 2011 03:43:54 +0000 (+0000) Subject: Rvalue references for *this: parse ref-qualifiers. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=83f51722ed2b8134810cb178f39e44da811de7cd;p=clang Rvalue references for *this: parse ref-qualifiers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124276 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 65c95dc4c6..59962ae3b7 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -898,6 +898,10 @@ struct DeclaratorChunk { /// contains the location of the ellipsis. unsigned isVariadic : 1; + /// \brief Whether the ref-qualifier (if any) is an lvalue reference. + /// Otherwise, it's an rvalue reference. + unsigned RefQualifierIsLValueRef : 1; + /// The type qualifiers: const/volatile/restrict. /// The qualifier bitmask values are the same as in QualType. unsigned TypeQuals : 3; @@ -922,6 +926,11 @@ struct DeclaratorChunk { /// the function has one. unsigned NumExceptions; + /// \brief The location of the ref-qualifier, if any. + /// + /// If this is an invalid location, there is no ref-qualifier. + unsigned RefQualifierLoc; + /// ThrowLoc - When hasExceptionSpec is true, the location of the throw /// keyword introducing the spec. unsigned ThrowLoc; @@ -970,6 +979,15 @@ struct DeclaratorChunk { SourceLocation getThrowLoc() const { return SourceLocation::getFromRawEncoding(ThrowLoc); } + + /// \brief Retrieve the location of the ref-qualifier, if any. + SourceLocation getRefQualifierLoc() const { + return SourceLocation::getFromRawEncoding(RefQualifierLoc); + } + + /// \brief Determine whether this function declaration contains a + /// ref-qualifier. + bool hasRefQualifier() const { return getRefQualifierLoc().isValid(); } }; struct BlockPointerTypeInfo : TypeInfoCommon { @@ -1084,7 +1102,10 @@ struct DeclaratorChunk { bool hasProto, bool isVariadic, SourceLocation EllipsisLoc, ParamInfo *ArgInfo, unsigned NumArgs, - unsigned TypeQuals, bool hasExceptionSpec, + unsigned TypeQuals, + bool RefQualifierIsLvalueRef, + SourceLocation RefQualifierLoc, + bool hasExceptionSpec, SourceLocation ThrowLoc, bool hasAnyExceptionSpec, ParsedType *Exceptions, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index f4a79077a9..29f9921217 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3064,8 +3064,8 @@ void Parser::ParseParenDeclarator(Declarator &D) { /// '=' assignment-expression /// [GNU] declaration-specifiers abstract-declarator[opt] attributes /// -/// For C++, after the parameter-list, it also parses "cv-qualifier-seq[opt]" -/// and "exception-specification[opt]". +/// For C++, after the parameter-list, it also parses "cv-qualifier-seq[opt]", +/// C++0x "ref-qualifier[opt]" and "exception-specification[opt]". /// void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, ParsedAttributes &attrs, @@ -3085,6 +3085,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // cv-qualifier-seq[opt]. DeclSpec DS; + SourceLocation RefQualifierLoc; + bool RefQualifierIsLValueRef = true; bool hasExceptionSpec = false; SourceLocation ThrowLoc; bool hasAnyExceptionSpec = false; @@ -3097,6 +3099,16 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, if (!DS.getSourceRange().getEnd().isInvalid()) EndLoc = DS.getSourceRange().getEnd(); + // Parse ref-qualifier[opt] + if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) { + if (!getLang().CPlusPlus0x) + Diag(Tok, diag::ext_rvalue_reference); + + RefQualifierIsLValueRef = Tok.is(tok::amp); + RefQualifierLoc = ConsumeToken(); + EndLoc = RefQualifierLoc; + } + // Parse exception-specification[opt]. if (Tok.is(tok::kw_throw)) { hasExceptionSpec = true; @@ -3121,6 +3133,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, SourceLocation(), /*arglist*/ 0, 0, DS.getTypeQualifiers(), + RefQualifierIsLValueRef, + RefQualifierLoc, hasExceptionSpec, ThrowLoc, hasAnyExceptionSpec, Exceptions.data(), @@ -3320,6 +3334,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, SourceLocation EndLoc = RParenLoc; DeclSpec DS; + SourceLocation RefQualifierLoc; + bool RefQualifierIsLValueRef = true; bool hasExceptionSpec = false; SourceLocation ThrowLoc; bool hasAnyExceptionSpec = false; @@ -3334,6 +3350,16 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, if (!DS.getSourceRange().getEnd().isInvalid()) EndLoc = DS.getSourceRange().getEnd(); + // Parse ref-qualifier[opt] + if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) { + if (!getLang().CPlusPlus0x) + Diag(Tok, diag::ext_rvalue_reference); + + RefQualifierIsLValueRef = Tok.is(tok::amp); + RefQualifierLoc = ConsumeToken(); + EndLoc = RefQualifierLoc; + } + // Parse exception-specification[opt]. if (Tok.is(tok::kw_throw)) { hasExceptionSpec = true; @@ -3362,6 +3388,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, EllipsisLoc, ParamInfo.data(), ParamInfo.size(), DS.getTypeQualifiers(), + RefQualifierIsLValueRef, + RefQualifierLoc, hasExceptionSpec, ThrowLoc, hasAnyExceptionSpec, Exceptions.data(), @@ -3443,6 +3471,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, SourceLocation(), &ParamInfo[0], ParamInfo.size(), /*TypeQuals*/0, + true, SourceLocation(), /*exception*/false, SourceLocation(), false, 0, 0, 0, LParenLoc, RLoc, D), diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index acbf3a5a92..67351f7e2f 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1859,6 +1859,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { true, false, SourceLocation(), 0, 0, 0, + true, SourceLocation(), false, SourceLocation(), false, 0, 0, 0, CaretLoc, CaretLoc, diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index 4152c5740a..8a35ab7092 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -52,6 +52,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs, ParamInfo *ArgInfo, unsigned NumArgs, unsigned TypeQuals, + bool RefQualifierIsLvalueRef, + SourceLocation RefQualifierLoc, bool hasExceptionSpec, SourceLocation ThrowLoc, bool hasAnyExceptionSpec, @@ -74,6 +76,8 @@ DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs, I.Fun.TypeQuals = TypeQuals; I.Fun.NumArgs = NumArgs; I.Fun.ArgInfo = 0; + I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef; + I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding(); I.Fun.hasExceptionSpec = hasExceptionSpec; I.Fun.ThrowLoc = ThrowLoc.getRawEncoding(); I.Fun.hasAnyExceptionSpec = hasAnyExceptionSpec; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 39d198be39..1c487b8113 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5539,7 +5539,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, Declarator D(DS, Declarator::BlockContext); D.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(), false, false, SourceLocation(), 0, - 0, 0, false, SourceLocation(), + 0, 0, true, SourceLocation(), + false, SourceLocation(), false, 0,0,0, Loc, Loc, D), SourceLocation()); D.SetIdentifier(&II, Loc); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 8ca1e00823..b663f58f03 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -520,6 +520,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, /*variadic*/ false, SourceLocation(), /*args*/ 0, 0, /*type quals*/ 0, + /*ref-qualifier*/true, SourceLocation(), /*EH*/ false, SourceLocation(), false, 0, 0, 0, /*parens*/ loc, loc, declarator)); diff --git a/test/CXX/dcl.decl/p4-0x.cpp b/test/CXX/dcl.decl/p4-0x.cpp new file mode 100644 index 0000000000..9fa2ea19d4 --- /dev/null +++ b/test/CXX/dcl.decl/p4-0x.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +struct X { + void f() &; + void g() &&; +}; + +void (X::*pmf)() & = &X::f;