diff options
Diffstat (limited to 'clang/lib/Parse')
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 49 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 53 |
2 files changed, 79 insertions, 23 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index f414f16af73..e1fbb6dfcab 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1243,7 +1243,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D) { /// ParseDirectDeclarator /// direct-declarator: [C99 6.7.5] -/// identifier +/// [C99] identifier /// '(' declarator ')' /// [GNU] '(' attributes declarator ')' /// [C90] direct-declarator '[' constant-expression[opt] ']' @@ -1258,16 +1258,53 @@ void Parser::ParseDeclaratorInternal(Declarator &D) { /// [C++] direct-declarator '(' parameter-declaration-clause ')' /// cv-qualifier-seq[opt] exception-specification[opt] /// [C++] declarator-id -// -// declarator-id: [C++ 8] -// id-expression -// '::'[opt] nested-name-specifier[opt] type-name +/// +/// declarator-id: [C++ 8] +/// id-expression +/// '::'[opt] nested-name-specifier[opt] type-name +/// +/// id-expression: [C++ 5.1] +/// unqualified-id +/// qualified-id [TODO] +/// +/// unqualified-id: [C++ 5.1] +/// identifier +/// operator-function-id [TODO] +/// conversion-function-id [TODO] +/// '~' class-name +/// template-id [TODO] void Parser::ParseDirectDeclarator(Declarator &D) { // Parse the first direct-declarator seen. if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) { assert(Tok.getIdentifierInfo() && "Not an identifier?"); - D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); + // Determine whether this identifier is a C++ constructor name or + // a normal identifier. + if (getLang().CPlusPlus && + CurScope->isCXXClassScope() && + Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope)) + D.SetConstructor(Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope), + Tok.getIdentifierInfo(), Tok.getLocation()); + else + D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); + } else if (getLang().CPlusPlus && Tok.is(tok::tilde) && + CurScope->isCXXClassScope() && D.mayHaveIdentifier()) { + // This should be a C++ destructor. + SourceLocation TildeLoc = ConsumeToken(); + + // Use the next identifier and "~" to form a name for the + // destructor. This is useful both for diagnostics and for + // correctness of the parser, since we use presence/absence of the + // identifier to determine what we parsed. + // FIXME: We could end up with a template-id here, once we parse + // templates, and will have to do something different to form the + // name of the destructor. + assert(Tok.is(tok::identifier) && "Expected identifier"); + IdentifierInfo *II = Tok.getIdentifierInfo(); + II = &PP.getIdentifierTable().get(std::string("~") + II->getName()); + + if (TypeTy *Type = ParseClassName()) + D.SetDestructor(Type, II, TildeLoc); } else if (Tok.is(tok::l_paren)) { // direct-declarator: '(' declarator ')' // direct-declarator: '(' attributes declarator ')' diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 57fa193e756..f90469acacb 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -128,6 +128,37 @@ Parser::DeclTy *Parser::ParseLinkage(unsigned Context) { return Actions.ActOnLinkageSpec(Loc, LBrace, RBrace, LangBufPtr, StrSize, D); } +/// ParseClassName - Parse a C++ class-name, which names a class. Note +/// that we only check that the result names a type; semantic analysis +/// will need to verify that the type names a class. The result is +/// either a type or NULL, dependending on whether a type name was +/// found. +/// +/// class-name: [C++ 9.1] +/// identifier +/// template-id [TODO] +/// +Parser::TypeTy *Parser::ParseClassName() { + // Parse the class-name. + // FIXME: Alternatively, parse a simple-template-id. + if (Tok.isNot(tok::identifier)) { + Diag(Tok.getLocation(), diag::err_expected_class_name); + return 0; + } + + // We have an identifier; check whether it is actually a type. + TypeTy *Type = Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope); + if (!Type) { + Diag(Tok.getLocation(), diag::err_expected_class_name); + return 0; + } + + // Consume the identifier. + ConsumeToken(); + + return Type; +} + /// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or /// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which /// until we reach the start of a definition or see a token that @@ -325,29 +356,17 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclTy *ClassDecl) // FIXME: Parse optional '::' and optional nested-name-specifier. - // Parse the class-name. - // FIXME: Alternatively, parse a simple-template-id. - if (Tok.isNot(tok::identifier)) { - Diag(Tok.getLocation(), diag::err_expected_class_name); - return true; - } - - // We have an identifier; check whether it is actually a type. - TypeTy *BaseType = Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope); - if (!BaseType) { - Diag(Tok.getLocation(), diag::err_expected_class_name); - return true; - } - // The location of the base class itself. SourceLocation BaseLoc = Tok.getLocation(); + + // Parse the class-name. + TypeTy *BaseType = ParseClassName(); + if (!BaseType) + return true; // Find the complete source range for the base-specifier. SourceRange Range(StartLoc, BaseLoc); - // Consume the identifier token (finally!). - ConsumeToken(); - // Notify semantic analysis that we have parsed a complete // base-specifier. return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access, BaseType, |

