diff options
Diffstat (limited to 'clang/lib/Parse')
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 32 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 61 |
2 files changed, 86 insertions, 7 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index d82658825a4..58cc9e2c6b3 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1229,7 +1229,11 @@ void Parser::ParseDeclarator(Declarator &D) { ParseDeclaratorInternal(D); } -/// ParseDeclaratorInternal +/// ParseDeclaratorInternal - Parse a C or C++ declarator. If +/// PtrOperator is true, then this routine won't parse the final +/// direct-declarator; therefore, it effectively parses the C++ +/// ptr-operator production. +/// /// declarator: [C99 6.7.5] /// pointer[opt] direct-declarator /// [C++] '&' declarator [C++ 8p4, dcl.decl] @@ -1239,13 +1243,21 @@ void Parser::ParseDeclarator(Declarator &D) { /// '*' type-qualifier-list[opt] /// '*' type-qualifier-list[opt] pointer /// -void Parser::ParseDeclaratorInternal(Declarator &D) { +/// ptr-operator: +/// '*' cv-qualifier-seq[opt] +/// '&' +/// [GNU] '&' restrict[opt] attributes[opt] +/// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt] [TODO] +void Parser::ParseDeclaratorInternal(Declarator &D, bool PtrOperator) { tok::TokenKind Kind = Tok.getKind(); // Not a pointer, C++ reference, or block. if (Kind != tok::star && (Kind != tok::amp || !getLang().CPlusPlus) && - (Kind != tok::caret || !getLang().Blocks)) - return ParseDirectDeclarator(D); + (Kind != tok::caret || !getLang().Blocks)) { + if (!PtrOperator) + ParseDirectDeclarator(D); + return; + } // Otherwise, '*' -> pointer, '^' -> block, '&' -> reference. SourceLocation Loc = ConsumeToken(); // Eat the * or &. @@ -1257,7 +1269,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D) { ParseTypeQualifierListOpt(DS); // Recursively parse the declarator. - ParseDeclaratorInternal(D); + ParseDeclaratorInternal(D, PtrOperator); if (Kind == tok::star) // Remember that we parsed a pointer type, and remember the type-quals. D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc, @@ -1290,7 +1302,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D) { } // Recursively parse the declarator. - ParseDeclaratorInternal(D); + ParseDeclaratorInternal(D, PtrOperator); if (D.getNumTypeObjects() > 0) { // C++ [dcl.ref]p4: There shall be no references to references. @@ -1382,7 +1394,13 @@ void Parser::ParseDirectDeclarator(Declarator &D) { if (IdentifierInfo *II = MaybeParseOperatorFunctionId()) { D.SetIdentifier(II, OperatorLoc); } else { - // This must be a user-defined conversion. + // This must be a conversion function (C++ [class.conv.fct]). + if (TypeTy *ConvType = ParseConversionFunctionId()) { + IdentifierInfo *II + = &PP.getIdentifierTable().get(std::string("operator ") + + Actions.getTypeAsString(ConvType)); + D.SetConversionFunction(ConvType, II, OperatorLoc); + } } } else if (Tok.is(tok::l_paren)) { // direct-declarator: '(' declarator ')' diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 3134ff87b60..5dc43ed34d2 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -292,6 +292,32 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { DS.Finish(Diags, PP.getSourceManager(), getLang()); } +/// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++ +/// [dcl.name]), which is a non-empty sequence of type-specifiers, +/// e.g., "const short int". Note that the DeclSpec is *not* finished +/// by parsing the type-specifier-seq, because these sequences are +/// typically followed by some form of declarator. Returns true and +/// emits diagnostics if this is not a type-specifier-seq, false +/// otherwise. +/// +/// type-specifier-seq: [C++ 8.1] +/// type-specifier type-specifier-seq[opt] +/// +bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { + DS.SetRangeStart(Tok.getLocation()); + const char *PrevSpec = 0; + int isInvalid = 0; + + // Parse one or more of the type specifiers. + if (!MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) { + Diag(Tok.getLocation(), diag::err_operator_missing_type_specifier); + return true; + } + while (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)); + + return false; +} + /// MaybeParseOperatorFunctionId - Attempts to parse a C++ overloaded /// operator name (C++ [over.oper]). If successful, returns the /// predefined identifier that corresponds to that overloaded @@ -365,3 +391,38 @@ IdentifierInfo *Parser::MaybeParseOperatorFunctionId() { return &PP.getIdentifierTable().getOverloadedOperator(Op); } } + +/// ParseConversionFunctionId - Parse a C++ conversion-function-id, +/// which expresses the name of a user-defined conversion operator +/// (C++ [class.conv.fct]p1). Returns the type that this operator is +/// specifying a conversion for, or NULL if there was an error. +/// +/// conversion-function-id: [C++ 12.3.2] +/// operator conversion-type-id +/// +/// conversion-type-id: +/// type-specifier-seq conversion-declarator[opt] +/// +/// conversion-declarator: +/// ptr-operator conversion-declarator[opt] +Parser::TypeTy *Parser::ParseConversionFunctionId() { + assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword"); + ConsumeToken(); // 'operator' + + // Parse the type-specifier-seq. + DeclSpec DS; + if (ParseCXXTypeSpecifierSeq(DS)) + return 0; + + // Parse the conversion-declarator, which is merely a sequence of + // ptr-operators. + Declarator D(DS, Declarator::TypeNameContext); + ParseDeclaratorInternal(D, /*PtrOperator=*/true); + + // Finish up the type. + Action::TypeResult Result = Actions.ActOnTypeName(CurScope, D); + if (Result.isInvalid) + return 0; + else + return Result.Val; +} |

